/* PROGRAM: translate.c ** PURPOSE: Front end parser for AIM (Adaptive Image Manager) Model of Computn ** - translates Aim Server Call descriptions (ASCs) into ** assembly (ASM) level and bit vector (BVC) level calls ** - performs allocation of operands per translation table ** FILES: translate.h : C language header file ** *_MOC_trn.tbl : translation table for ASC->ASM->BVC for device * ** AUTHOR: Yue Yin, University of Florida, 15 Jun 2000 ** LANG: ANSI standard C ** REVS: v0.* : Prototypes ** v1.* : Alpha test, inclusion of nested loops, simple expression ** v2.0 : Upgraded to include MOCSET construct, complex expression **/ #include "translate.h" int I,T; // I,T: img,tpl sizes (pixels) int nst,sst,pst; // stackptrs: number,symbol,nesting int numstk[10],symstk[10]; // number and symbol stacks char var[MAX_VAR_NUM][MAX_LENGTH_NAME]; // variable array for MOCSET cmd // MAX_VAR_NUM: max no. var's for MOCSET int val[MAX_VAR_NUM]; // value array for MOCSET variables int varnum=0; // first coord.of var[] & val[] arr void scanASM(istream&); // scanner for ASMs in transln.tbl. void scanBVC(istream&); // scanner for BVCs in transln.tbl. char nextchar(istream&); // get next character from i/o strm int expr(istream&); // recognize and eval. an expressn. void ASC_ASM(istream&); // convert ASC to ASM void ASM_BVC(const char[MAX_LENGTH_INSTRLINE],int); // convert ASM to BVC void lookuptbl(char[MAX_LENGTH_NAME], int); // transln.tbl. LUT void setTypeNo(const char[MAX_LENGTH_NAME], const char[MAX_LENGTH_NAME],int&); // sets the type of an opcode void readstr(istream&, char[MAX_LENGTH_NAME]); // get string from input void SyntErr(); // syntax error handler void Expr_err(); // error handler for expression eval /*****************************************************************************/ /****** STEP 1: SCANNING INPUT (ASC FILE) ******/ /*****************************************************************************/ void scanASC(istream& istrm) // SCAN THE ASC FILE FROM istrm { char next_char; // lookahead character char ch; // character buffer (general purp.) /* Note: ASC counter "Nasc" is global var, init. in */ next_char=0; // zero lookahead next_char=nextchar(istrm); // initialize lookahead buffer while (eof[0]==0) { // read until EOF on input stream switch(next_char) { // branch on lookahead character case '{': // OPEN BRACE ({) starts ASC-loop ASCBrace[++ascbrc]=Nasc+1; // increment brace level in ASC call ch=istrm.get(); // get current char from istream next_char=nextchar(istrm); // lookahead: next useful character break; // exit the case statement case '}': // CLOSED BRACE (}) ends ASC-loop (unroll) int b,e,loop,i,j,k; // local variables ch=istrm.get(); // get current char from istream b=ASCBrace[ascbrc--]; // decrement brace level in ASC call next_char=nextchar(istrm); // lookahead: next useful character if (next_char=='*'){ // if a "*", then ASC loop construct ch=istrm.get(); // get current char from istream e=Nasc; // e: number of ASC calls w/in loop nst=0;sst=0;pst=0; // set stackptrs to zero loop=expr(istrm); // evaluate ASC loop repetition factor for(i=1;i>unroll ASC stream "loop" times for (j=b;j<=e;j++) { // copy ASCs (indexed from #b to #e) int p; // p: local index of character in ASC Nasc++; // increment ASC count as we unroll loop ASCcall[Nasc]=ASCcall[j]; // copy current ASC call to unrolled strm ASMcall[Nasc]=ASMcall[j]; // ASC_ASM has produced ASM call, copy it BVCcall[Nasc]=BVCcall[j]; // ASM_BVC has produced ASM call, copy it p=0; // initialize index of character in ASC while (ASCcall[Nasc][p]!=' '){ // copy all nonblank ASC characters asc[Nasc][p]=ASCcall[Nasc][p]; // to array to be passed to MOC p++; // increment character pointer } // end-while asc[Nasc][p]='\0'; // put in the end-of-string character for (k=1;k<=TPN;k++){ // copy array of Data-size param's for ASC if (Dat[k][1][j]>0) // copy param #1 if > 0, else default 0 Dat[k][1][Nasc]=Dat[k][1][j]; // (initialized in ) if (Dat[k][2][j]>0) // copy param #2 if > 0, else default 0 Dat[k][2][Nasc]=Dat[k][2][j]; if (Dat[k][3][j]>0) // copy param #3 if > 0, else default 0 Dat[k][3][Nasc]=Dat[k][3][j]; } // end Data-parameter loop } // end j-loop for ASC stream within-{}loop } // end unrolling of {} loop next_char=nextchar(istrm); // lookahead: next useful character } // end if-stmt [next_char=='*'] break; // exit case stmt case ',': // SKIP OVER COMMAS that delimit ASC calls ch=istrm.get(); // get current char from istream next_char=nextchar(istrm); // lookahead: next useful character break; // exit case stmt default: // ALL OTHER CASES - translate ASC call ASC_ASM(istrm); // ASC->ASM translation routine next_char=nextchar(istrm); // lookahead: next useful character } // end of case stmt if (next_char==EOF) eof[0]=1; // END OF ASC FILE } // end of while loop for ASC file } // end of scanASC() procedure /*****************************************************************************/ /****** STEP 2: SCANNING ASM TRANSLATION TABLE FILE ******/ /*****************************************************************************/ void scanASM(istream& istrm) // scan ASM opcode in translation table { char next_char; // lookahead character char ch; // current character buffer /* Note: "asmi" [global var] is the index of current ASM in translation table */ next_char=0; // initialize lookahead character next_char=nextchar(istrm); // lookahead: next useful character while (eof[1]==0) { // while not end of ASC to be translated switch(next_char) { // CASE stmt on lookahead character case '{': // OPEN BRACE starts ASM loop spec. ASMBrace[++asmbrc]=asmi+1; // increment no. of ASM loop levels ch=istrm.get(); // get current ASM char from istream next_char=nextchar(istrm); // lookahead: next useful ASM character break; // exit case stmt case '}': // CLOSED BRACE ends ASM loop spec. int b,e,loop,i,j; // loop unrolling limits and indices ch=istrm.get(); // get current ASM char from istream b=ASMBrace[asmbrc--]; // decrement ASM loop level next_char=nextchar(istrm); // lookahead: next useful ASM character if (next_char=='*'){ // IF LOOP REPETITION CHAR detected, ch=istrm.get(); // get current ASM char from istream e=asmi; // get index of current ASM in trn.table nst=0;sst=0;pst=0; // initialize stack pointers loop=expr(istrm); // determine ASM loop unrolling rep factor for(i=1;i>temp; // get ASM opcode from xlation table istrm>>t; // get no. BVCs for ASM from xlation tbl l=strlen(temp); // get length of opcode in characters Trn[asctp].callNop[asmi]=t; // put t in translation table array Trn[asctp].calls[asmi] = (char*)malloc((l+1)*sizeof(char)); // allocate mem for current ASM strcpy(Trn[asctp].calls[asmi],temp); // copy current ASM to memory if (asmi==Trn[asctp].callNo) eof[1]=1; // end of ASM opcode sequence next_char=nextchar(istrm); // lookahead: next useful ASM character } // end case stmt } // ending while loop for ASMs } // end scanASM procedure /*****************************************************************************/ /****** STEP 3: SCANNING BVC TRANSLATION TABLE FILE ******/ /*****************************************************************************/ void scanBVC(istream& istrm) // Scan BVC translation table { char next_char; // BVC lookahead character char ch; // current BVC character buffer /* Note: BVCs are indexed by global variable "bvci" */ next_char=0; // initialize BVC lookahead character next_char=nextchar(istrm); // lookahead: next useful BVC character while (eof[2]==0) { // while BVC stream is non-null switch(next_char) { // CASE stmt on BVC ahead character case '{': // OPEN BRACE: new BVC repetition level BVCBrace[++bvcbrc]=bvci+1; // increment BVC level ch=istrm.get(); // get current BVC char from istream next_char=nextchar(istrm); // lookahead: next useful BVC character break; // exit case stmt case '}': // CLOSED BRACE: end of BVC loop int b,e,loop,i,j; // BVC loop unrolling buffers ch=istrm.get(); // get current BVC char from istream b=BVCBrace[bvcbrc--]; // decrement BVC processing level next_char=nextchar(istrm); // lookahead: next useful BVC character if (next_char=='*'){ // ASTERISK: process BVC rep factor ch=istrm.get(); // get current BVC char from istream e=bvci; // store current BVC pointer in xlatn tbl nst=0;sst=0;pst=0; // initialize translation stack pointers loop=expr(istrm); // determine BVC loop repetition factor for(i=1;i>temp; // copy BVC xlatn tbl entry to trn.array istrm>>t; // copy no. BVCs to translation tbl array l=strlen(temp); // get no. of characters in BVC opcode Trn[asmtp].callNop[bvci]=t; // put size of BVCs in translation tbl arr Trn[asmtp].calls[bvci] = /* allocate memory for one BVC */ (char*)malloc((l+1)*sizeof(char)); strcpy(Trn[asmtp].calls[bvci],temp); // copy BVC opcodes to trn array if (bvci==Trn[asmtp].callNo) eof[2]=1; // no more BVC opcodes in stream next_char=nextchar(istrm); // lookahead: next useful BVC character } // end case stmt } // end while loop } // end scanBVC /*****************************************************************************/ /****** THREE UTILITY ROUTINES: nextchar(), comptmd(), comptas() ******/ /*****************************************************************************/ char nextchar(istream& istrm) // get the next meaningful char from stream { char temp[MAX_LENGTH_LINE]; char next_char; char ch; int e; next_char = istrm.peek(); do { while (next_char=='\t' || next_char==' ') { // ignore tab and space ch=istrm.get(); next_char = istrm.peek(); } e=0; while (next_char=='#'||next_char=='\n') { // ignore comment and '\n' istrm.getline(temp,MAX_LENGTH_LINE); next_char=istrm.peek(); e=1; } }while(e==1); return next_char; } /* Note: We need to compute some simple arithmetic expressions in loop repetition factors, such as {...}*(K/L) or {...}(K*L). Also some addition expressions such as {...}*(K-1) or {...}*(K+1). We can also evaluate expressions such as {...}*(K+L*M/N...), where K,L,M,N are defined in the MOCSET statement. Note: "\" denotes the ceiling of a quotient, e.g., K\L denotes CEILING(K/L). */ int comptmd(int i) // compute * , / and \ in expression { if (symstk[sst-1]=='*') { // multiplication op detected on symbol stack sst--;nst--; // pop asterisk off of symbol stack return numstk[nst]*i; // return value after multiplication performed } else if (symstk[sst-1]=='/'){ // division op detected on symbol stack sst--;nst--; // pop asterisk off of symbol stack return numstk[nst]/i; // return value after multiplication performed } else if (symstk[sst-1]=='\\'){ // ceiling op detected on symbol stack int q; // buffer for doing the ceiling function sst--;nst--; // pop reverse slash off symbol stack q=numstk[nst]/i; // compute ceiling function if (q*i='0') { // if next character is a digit istrm>>i; // put the digit in "i" i=comptmd(i); // then call the mult/div eval proc numstk[nst]=i; // push i onto the stack nst++; // increment stack pointer loop=expr(istrm); // recursively evaluate expression } else if ((next_char>'A'&&next_char<'Z')|| (next_char>'a'&&next_char<'z')) { // nextchar is a letter int vi=0; // initialize posn of char in varnm do{ // build variable name istrm>>ch; // get a character from istrm varname[vi++]=ch; // push character on array ch=istrm.peek(); // peek at next character } /* Note: while ch is not an end-of-variable character, build var-name */ while (ch!='\n'&&ch!=' '&&ch!='\t'&&ch!='('&&ch!=')'&&ch!='{'&&ch!='}' &&ch!='+'&&ch!='-'&&ch!='*'&&ch!='/'&&ch!='\\'&&ch!=','); varname[vi]='\0'; // terminate the variable name /* Note: here we check for special variable names such as image, */ /* template, or mesh size definitions */ if (strcmp(varname,"I")==0) i=comptmd(I); // I: image size else if (strcmp(varname,"T")==0) i=comptmd(T); // T: template size else if (strcmp(varname,"MESH")==0) i=comptmd(MESH);// MESH: mesh size else { // search for variable name for (int j=1;j<=varnum;j++) { // loop through variable name tbl if (strcmp(var[j],varname)==0){ // if it is in the table varval=val[j]; // then assign value to variable break; // exit the loop } // end-if check variable name } // end-loop check variable name i=comptmd(varval); // compute mult/div assoc w/varbl } // end strcmp "if" stmt numstk[nst]=i; // push result of mul/div onto stk nst++; // incr. stack pointer loop=expr(istrm); // recursively evaluate expression } // end processing for char=A-Z,a-z else if (next_char=='+') { // plus sign encountered istrm>>ch; // get current character comptas(); // invoke add/subtr compute routine symstk[sst]='+'; // push + on symbol stack sst++; // increment stack pointer loop=expr(istrm); // recursively evaluate expression } else if (next_char=='-') { // minus sign encountered istrm>>ch; // get current character comptas(); // invoke add/subtr compute routine symstk[sst]='-'; // push - on symbol stack sst++; // increment stack pointer if (nst==0) { // check for unary minus numstk[0]=0; // set flag on the number stack nst++; // increment number stack pointer } // endif loop=expr(istrm); // recursively evaluate expression } else if (next_char=='*') { // multiplication sign encountered istrm>>ch; // get current character symstk[sst]='*'; // push symbol onto symbol stack sst++; // increment symbol stack pointer loop=expr(istrm); // recursively evaluate expression } else if (next_char=='/') { // division sign encountered istrm>>ch; // get current character symstk[sst]='/'; // push symbol onto symbol stack sst++; // increment symbol stack pointer loop=expr(istrm); // recursively evaluate expression } else if (next_char=='\\') { // ceiling on division encountered istrm>>ch; // get current character symstk[sst]='\\'; // push symbol onto symbol stack sst++; // increment symbol stack pointer loop=expr(istrm); // recursively evaluate expression } else if (next_char=='(') { // open parenthesis encountered istrm>>ch; // get current character symstk[sst]='('; // push symbol onto symbol stack sst++;pst++; // increment stack pointers loop=expr(istrm); // recursively evaluate expression } else if (next_char==')'&&pst>0) { // closed parenthesis encountered istrm>>ch; // get current character comptas(); // invoke add/subtr expr eval sst--;nst--;pst--; // pop symbol,num,paren stacks i=comptmd(numstk[nst]); // call mul/div expr eval routine numstk[nst]=i; // push result on number stack nst++; // increment stack pointer loop=expr(istrm); // recursively evaluate expression } else { // some other character comptas(); // eval add/sub expression if (nst==1 && sst==0) loop = numstk[0]; // if end of expression, loop<-val else Expr_err(); // otherwise emit error message } return loop; // return the computed expr value } /*****************************************************************************/ /****** BIG UTILITY ROUTINE: TRANSLATE ASC TO ASM ******/ /*****************************************************************************/ void ASC_ASM(istream& istrm) // parse ASC call and translate ASC to ASM { char tp[MAX_LENGTH_NAME]; // temporary buffer int input_size[2],resbits,rs[3],pim,tsize; // char ch; // current character istrm>>ASC.opcode; // get ASC opcode from ASC file /* PROCESS MOCSET CONSTRUCT (MOCSET sets value of variable, MOCSETMESH */ /* sets the mesh size */ if ((strcmp(ASC.opcode, "MOCSET")==0) // MOCSET ||(strcmp(ASC.opcode, "MOCSETMESH")==0)){ // MOCSETMESH do { // parse "MOCSET K=,L=,..." int vi=0; // character pointer in varble name varnum++; // increment number of variables ch=nextchar(istrm); // lookahead at current character if (ch<'A'||ch>'z' || (ch>'Z'&&ch<'a')) SyntErr(); // if not a letter -> SyntaxErr istrm>>ch; // get current character while (ch!=' '&&ch!='\t'&&ch!='='){ // while not end-of-name do var[varnum][vi++]=ch; // build variable name array istrm>>ch; // get another character } // endwhile var[varnum][vi]='\0'; // insert string terminator if (ch!='=') { // parse an equal sign (end varnam) ch=nextchar(istrm); // lookahead at current character istrm>>ch; // get current character } if (ch!='=') SyntErr(); // if not "=", then SyntaxError istrm>>val[varnum]; // get variable value if (strcmp(ASC.opcode, "MOCSETMESH")==0) MESH*=val[varnum]; // build mesh size via mult of dims ch=istrm.peek(); // peek at current character if (ch==' '||ch=='\t'||ch==',') { if (ch!=',') ch=nextchar(istrm); // terminate exprn: = istrm>>ch; // get the current character } }while (ch==','); // end of assignment to one variable return; // end of MOCSET processing } /* This is where the ASC call is actually parsed */ Nasc++; // increment # of ASC calls ostrstream ostrasc(ASCcall[Nasc],MAX_LENGTH_LINE); // C++ lib: buildstr strcpy(asc[Nasc],ASC.opcode); // put opcode in "asc" table istrm>>ch; // get current character if (ch!='(') SyntErr(); // if NOT "(" then SyntaxError ostrasc<>ch; // expect ",", get current char if (ch!=',') SyntErr(); // if not a comma, then SyntaxError input_size[i]=1; // initialize input size for(int j=1;j<=max(ASC.D[0],ASC.D[i]);j++) { // operand dim loop nst=0;sst=0;pst=0; // zero stack pointers ASC.Md[i][j]=expr(istrm); // get M11,...,M1D1,M21,...,M2D2 nextchar(istrm);istrm>>ch; // expect "," if (ch!=',') SyntErr(); // if not a comma, then SyntaxError input_size[i]*=ASC.Md[i][j]; // compute input size ostrasc<>ch; // expect "," if (ch!=',') SyntErr(); // if not a comma, then SyntaxError input_size[i]*=ASC.Sig[i]; // compute input size nst=0;sst=0;pst=0; // zero out stack ASC.Noi[i]=expr(istrm); // get N1,N2 (noise bits) opn1&2 nextchar(istrm);istrm>>ch; // expect "," if (ch!=',') SyntErr(); // if not a comma, then SyntaxError ostrasc<>ch; // expect "," if (ch!=',') SyntErr(); // if not a comma, then SyntaxError ostrasc<>ch; // expect "," if (ch!=',') SyntErr(); // if not a comma, then SyntaxError readstr(istrm,ASC.o); // get the O operation symbol nst=0;sst=0;pst=0; // zero out the stack ASC.Po=expr(istrm); // get precision of O operation ostrasc<>ch; // expect ")" if (ch!=')') SyntErr(); // if not a ")", then SyntaxError ostrasc<<")"<>ASM.opcode; // get op name if (nop>0) { // if more than 0 registers istrasm>>ASM.regid1; // get reg-id1 istrasm>>ASM.regsize1; // get reg-size1 if (nop>1) { // if more than 1 registers istrasm>>ASM.regid2; // get reg-id2 istrasm>>ASM.regsize2; // get reg-size2 if (nop>2) { // if 3 registers istrasm>>ASM.regid3; // get reg-id3 istrasm>>ASM.regsize3; // get reg-size3 } } } type(ASM.opcode,tp,asmtp); // get type of opcode if it exists if (asmtp==-1) lookuptbl(ASM.opcode,2); // lookup translation table if opcode doesn't exist // copmute data, result, and instruction bits Dat[asmtp][1][Nasc] = ASM.regsize1+ASM.regsize2; resbits = ASM.regsize3; Ins[asmtp][1] = 116; // compute register sizes for BVC rs[0]=0; rs[1]=0; rs[2]=0; if (nop>0) { rs[0]=ASC.Sig[0]; rs[1]=ASC.Sig[1]; if (strcmp(ASC.o,"x")==0) rs[2]=rs[0]+rs[1]; // regsize for mul op else if (strcmp(ASC.o,"+")==0) rs[2]=1+max(rs[0],rs[1]); // for addop else rs[2]=max(rs[0]+rs[1],1+max(rs[0],rs[1])); // for all other ops } // build the list of BVC calls Nbvc=0; BVCcall[Nasc][Nasm]=(char**)malloc((Trn[asmtp].callNo+1)*sizeof(char[MAX_LENGTH_INSTRLINE])); for(int i=1;i<=Trn[asmtp].callNo;i++) { char temp[MAX_LENGTH_INSTRLINE]; ostrstream ostrbvc(temp,MAX_LENGTH_INSTRLINE); ostrbvc<>opc; // get opcode from trntable if (strcmp(opc,opcode)==0) { // if opcode found int n, ncyc; // n: # of ASMs or BVCs found=1; // set opcode flag = found /* Note: The next two statements process the maps-to "->" symbol */ trntbl>>ch; // get character for "-" trntbl>>ch; // get character for ">" nst=0;sst=0;pst=0; // Zero stack pointers n=expr(trntbl); // get n, # of opcodes translated into nextchar(trntbl);trntbl>>ch; // update character buffers if (ch!=',') SyntErr(); // if not comma, SyntaxError nst=0;sst=0;pst=0; // Zero stack pointers ncyc=expr(trntbl); // get no. cycles for ASM,BVC nextchar(trntbl);trntbl>>ch; // update character buffers if (ch!=',') SyntErr(); // if not comma, SyntaxError trntbl>>tp; // get type of opcode // set Trn table values setTypeNo(opcode,tp,tpno); Trn[tpno].Ncyc = ncyc; Trn[tpno].callNo = n; Trn[tpno].callNop=(int*)malloc((n+1)*sizeof(int)); Trn[tpno].calls=(char**)malloc((n+1)*sizeof(char*)); eof[mb]=0; // flag to set end-of-sequence if (mb==1) // for ASM { asmi=0; asctp=tpno;asmbrc=0;scanASM(trntbl);} else // for BVC { bvci=0; asmtp=tpno;bvcbrc=0;scanBVC(trntbl);} } //end of if (strcmp(opc,opcode)==0) } //end of if ((nch!=' ')&&(nch!='\t')&&(nch!='#')&&(nch!=0)) if (found==0) { // if opcode absent, next line trntbl.getline(temp, MAX_LENGTH_LINE); nch=trntbl.peek(); // look ahead in trn tbl } } while (found==0 && nch!=EOF); // until found or EOF trntbl.close(); // close trn tbl file if (found==0) { // ERROR HANDLER: opcode not found cout<>ch; while (ch!=',') { s[i++]=ch; istrm>>ch; if (i>=MAX_LENGTH_NAME-1) SyntErr(); } if (i==0) SyntErr(); s[i]='\0'; } void SyntErr() // syntax error { cout<<"Syntax Error!"<