%{ /* * vl2mv: Verilog to BLIF-MV Translator Distribution * * Copyright (c) 1992, 1993 * Regents of the University of California * All rights reserved. * * Use and copying of this software and preparation of derivative works * based upon this software are permitted. However, any distribution of * this software or derivative works must include the above copyright * notice. * * This software is made available AS IS, and neither the Electronics * Research Laboratory or the Universify of California make any * warranty about the software, its performance or its conformity to * any specification. * * * $Header: /projects/development/hsv/CVSRepository/vl2mv/src/parser/verilog.l,v 1.4 2009/03/09 20:25:57 fabio Exp $ * * Lexical Scanner for Verilog * * Author: Szu-Tsung Cheng, stcheng@ic.berkeley.edu * * Date: September 18, 1992 */ #include #include "util.h" #include "st.h" #include "list.h" #include "array.h" #include "set.h" #include "stack.h" #include "vl_defs.h" #include "vl_types.h" #include "vlr_int.h" #include "verilog_yacc.h" #include "verilog.h" #ifdef FLEX_SCANNER #ifndef YY_FLEX_LEX_COMPAT #define YYLMAX YY_BUF_SIZE #else #define MAX_INCLUDE_DEPTH 20 YY_BUFFER_STATE buffer_stack[MAX_INCLUDE_DEPTH]; int buffer_stack_ptr = 0; #endif #endif extern vl_descPtr mod_list; extern char *vl_filename; extern st_table *aux_st; extern int reserve_type_name; extern int Loop_Unrolling; static int scan_table = 0; char yyid[MAXSTRLEN]; char brep[MAXSTRLEN]; int bexp0, bexp1; char last_macro[MAXSTRLEN]; /* last macro name get expanded */ char curr_macro[MAXSTRLEN]; char yytypetoken[MAXSTRLEN]; st_table *macros; char ifelse_stack[MAXSTRLEN]; int ifelseSP=0; %} %option yylineno %a 3000 %e 1700 %k 1000 %n 700 %o 4000 %p 5000 %Start Snormal Stable Sskip Space [\f\n\r\t\b ] Alpha [a-zA-Z] AlphaU [a-zA-Z_] AlphaNum [a-zA-Z0-9] AlphaNumU [a-zA-Z0-9_] Digit [0-9] DigitU [0-9_] Number {Digit}{DigitU}* Decimal ({Number})?'[dD][ ]*{Number} Octal ({Number})?'[oO][ ]*[0-7xXzZ?][0-7xXzZ?_]* Hexdecimal ({Number})?'[hH][ ]*[0-9a-fA-FxXzZ?][0-9a-fA-FxXzZ?_]* Binary ({Number})?'[bB][ ]*[01xXzZ?][01xXzZ?_]* %% strcpy(last_macro, curr_macro); curr_macro[0]='\0'; if (ifelseSP==0) { if (scan_table) BEGIN Stable; else BEGIN Snormal; } {Space}+ { #ifdef FLEX_SCANNER int i; for (i=0; i`ifdef[^\n]*\n { if (find_macro(yytext)) { ifelse_stack[ifelseSP++] = 1; } else { ifelse_stack[ifelseSP++] = 0; BEGIN Sskip; } if (ifelseSP == MAXSTRLEN) lex_panic("nested `if/`else too deep"); } `ifndef[^\n]*\n { if (find_not_macro(yytext)) { ifelse_stack[ifelseSP++] = 1; } else { ifelse_stack[ifelseSP++] = 0; BEGIN Sskip; } if (ifelseSP == MAXSTRLEN) lex_panic("nested `if/`else too deep"); } `else { if (ifelse_stack[ifelseSP-1]) { ifelse_stack[ifelseSP-1] = 0; BEGIN Sskip; } else { if (scan_table) BEGIN Stable; else BEGIN Snormal; } } `endif { if (!ifelse_stack[--ifelseSP]) { if (scan_table) BEGIN Stable; else BEGIN Snormal; } } [^\f\n\r\t\b ]+ { continue; } "/*" { skipcommentblock(); continue; } "//" { skipcommentline(); continue; } `timescale[^\n]*\n { continue; } `define[^\n]*\n { #ifdef FLEX_SCANNER yylineno++; #endif memorize_macro(yytext, macros); continue; } `include[^\n]*\n { char *cp; #ifdef FLEX_SCANNER yylineno++; #endif yytext[strlen(yytext)-1] = '\0'; cp = strstr(yytext, "`include"); cp += strlen("`include"); while (*cp==' ' || *cp=='\t' || *cp=='\r') cp++; push_open_file(cp); } `VL2MVDataVar[^\n]*\n { char *cp; char varname[MAXSTRLEN], vartype[MAXSTRLEN]; int i; vl_id_range *id_sym; #ifdef FLEX_SCANNER yylineno++; #endif cp = strstr(yytext, "`VL2MVDataVar"); cp += strlen("`Vl2MVDataVar"); while (*cp==' '||*cp=='\t'||*cp=='\r') cp++; i =0; while (*cp!=' '&&*cp!='\t'&&*cp!='\r'&& *cp!='\0') { varname[i++] = *cp; cp++; } varname[i] = '\0'; while (*cp==' '||*cp=='\t'||*cp=='\r') cp++; i =0; while (*cp!=' '&&*cp!='\t'&&*cp!='\r'&& *cp!='\0'&&*cp!='\n') { vartype[i++] = *cp; cp++; } vartype[i] = '\0'; if (vl_currentModule) { if (st_lookup(vl_currentModule->sig_st, varname, (char**)&id_sym)) { if (id_sym->unintType) vl_chk_free(id_sym->unintType); id_sym->unintType = vlStrdup(vartype); } } } `VL2MVClock[^\n]*\n { char *cp, cname[MAXSTRLEN], buf[MAXSTRLEN]; int i; int edge, pi; float rho; /* VL2MVClock 1:0:-1 0 0.0 */ #ifdef FLEX_SCANNER yylineno++; #endif yytext[strlen(yytext)-1] = '\0'; cp = strstr(yytext, "`VL2MVClock"); cp += strlen("`VL2MVClock"); /* name */ while (*cp==' '||*cp=='\t'||*cp=='\r') cp++; i=0; while (*cp!=' ' && *cp!='\t' && *cp!='\r' && *cp!='\0') { cname[i++] = *cp; cp++; } cname[i] = '\0'; /* pi */ while (*cp==' '||*cp=='\t'||*cp=='\r') cp++; i=0; while (*cp!=' ' && *cp!='\t' && *cp!='\r' && *cp!='\0') { buf[i++] = *cp; cp++; } pi = atoi(buf); /* edge */ while (*cp==' '||*cp=='\t'||*cp=='\r') cp++; i=0; while (*cp!=' ' && *cp!='\t' && *cp!='\r' && *cp!='\0') { buf[i++] = *cp; cp++; } edge = atoi(buf); /* rho */ while (*cp==' '||*cp=='\t'||*cp=='\r') cp++; i=0; while (*cp!=' ' && *cp!='\t' && *cp!='\r' && *cp!='\0') { buf[i++] = *cp; cp++; } rho = atof(buf); register_vl2mv_synClock(cname, edge, pi, rho); continue; } `VL2MVundefMod[^\n]*\n { char *cp, modname[MAXSTRLEN]; int i; #ifdef FLEX_SCANNER yylineno++; #endif i=0; yytext[strlen(yytext)-1] = '\0'; cp = strstr(yytext, "`VL2MVundefMod"); cp += strlen("`VL2MVundefMod"); while (*cp==' ' || *cp=='\t' || *cp=='\r') cp++; while (*cp!=' ' && *cp!='\t' && *cp!='\r' && *cp!='\0') { modname[i++] = *cp; cp++; } modname[i] = '\0'; if (mod_list) st_insert(mod_list->mod_holes, vlStrdup(modname), 0); continue; } ">=" { return YYGEQ; } "=<" { return YYLEQ; } "&&" { return YYLOGAND; } "||" { return YYLOGOR; } "===" { return YYCASEEQUALITY; } "==" { return YYLOGEQUALITY; } "!==" { return YYCASEINEQUALITY; } "!=" { return YYLOGINEQUALITY; } "^~" { return YYLOGXNOR; } "~^" { return YYLOGXNOR; } "~&" { return YYLOGNAND; } "~|" { return YYLOGNOR; } "<<" { return YYLSHIFT; } ">>" { return YYRSHIFT; } "?:" { return YYCONDITIONAL; } \"[^"]*\" { return YYSTRING; } always { return YYALWAYS; } "*>" { return YYALLPATH; } and { return YYAND; } assign { return YYASSIGN; } begin { return YYBEGIN; } buf { return YYBUF; } bufif0 { return YYBUFIF0; } bufif1 { return YYBUFIF1; } case { return YYCASE; } casex { return YYCASEX; } casez { return YYCASEZ; } cmos { return YYCMOS; } deassign { return YYDEASSIGN; } default { return YYDEFAULT; } defparam { return YYDEFPARAM; } disable { return YYDISABLE; } edge { return YYEDGE; } else { return YYELSE; } end { return YYEND; } endcase { return YYENDCASE; } endfunction { return YYENDFUNCTION; } endmodule { return YYENDMODULE; } endprimitive { return YYENDPRIMITIVE; } endspecify { return YYENDSPECIFY; } endtable { scan_table = 0; return YYENDTABLE; } endtask { return YYENDTASK; } enum { return YYENUM; } event { return YYEVENT; } for { return YYFOR; } forever { return YYFOREVER; } fork { return YYFORK; } function { return YYFUNCTION; } highz0 { return YYHIGHZ0; } highz1 { return YYHIGHZ1; } if { return YYIF; } initial { return YYINITIAL; } inout { return YYINOUT; } input { return YYINPUT; } integer { return YYINTEGER; } join { return YYJOIN; } large { return YYLARGE; } "=>" { return YYLEADTO; } macromodule { return YYMACROMODULE; } medium { return YYMEDIUM; } module { return YYMODULE; } mREG { return YYMREG; } "<=" { return YYNBASSIGN; } nand { return YYNAND; } negedge { return YYNEGEDGE; } nmos { return YYNMOS; } nor { return YYNOR; } not { return YYNOT; } notif0 { return YYNOTIF0; } notif1 { return YYNOTIF1; } or { return YYOR; } output { return YYOUTPUT; } parameter { return YYPARAMETER; } pmos { return YYPMOS; } posedge { return YYPOSEDGE; } primitive { return YYPRIMITIVE; } pull0 { return YYPULL0; } pull1 { return YYPULL1; } pulldown { return YYPULLDOWN; } pullup { return YYPULLUP; } rcmos { return YYRCMOS; } real { return YYREAL; } reg { return YYREG; } repeat { return YYREPEAT; } "->" { return YYRIGHTARROW; } rnmos { return YYRNMOS; } rpmos { return YYRPMOS; } rtran { return YYRTRAN; } rtranif0 { return YYRTRANIF0; } rtranif1 { return YYRTRANIF1; } scalered { return YYSCALARED; } small { return YYSMALL; } specify { return YYSPECIFY; } specparam { return YYSPECPARAM; } strong0 { return YYSTRONG0; } strong1 { return YYSTRONG1; } supply0 { return YYSUPPLY0; } supply1 { return YYSUPPLY1; } swire { return YYSWIRE; } table { scan_table = 1; return YYTABLE; } task { return YYTASK; } teslaTimer { return YYTESLATIMER; } time { return YYTIME; } tran { return YYTRAN; } tranif0 { return YYTRANIF0; } tranif1 { return YYTRANIF1; } tri { return YYTRI; } tri0 { return YYTRI0; } tri1 { return YYTRI1; } triand { return YYTRIAND; } trior { return YYTRIOR; } trireg { return YYTRIREG; } typedef { return YYTYPEDEF; } vectored { return YYVECTORED; } wait { return YYWAIT; } wand { return YYWAND; } weak0 { return YYWEAK0; } weak1 { return YYWEAK1; } while { return YYWHILE; } wire { return YYWIRE; } wor { return YYWOR; } xnor { return YYXNOR; } xor { return YYXOR; } \$setup { return YYsysSETUP; } \$NDset { return YYsysND; } \$ND { return YYsysND; } \${AlphaU}{AlphaNumU}* { return YYsysID; } `{AlphaU}{AlphaNumU}* { char *macro; strcpy(yyid, yytext); /* macro expansion */ if (st_lookup(macros, yyid+1, ¯o)) { expand_macro(yyid+1, macros); continue; } return YYIDE; } {AlphaU}{AlphaNumU}* { vl_type *var_type; yytypetoken[0] = '\0'; strcpy(yyid, yytext); /* type name checking */ if (reserve_type_name) if (st_lookup(mod_list->type_st, yytext, (char**)&var_type)) return YYuTYPE; /* enum name */ if (aux_st) { vl_enumerator *enum_elt; if (st_lookup(aux_st, yytext, (char**)&enum_elt)){ sprintf(yytypetoken, yytext); sprintf(yytext, "%d", enum_elt->val); return YYINUMBER; } } return YYIDE; } \\[^\n\t\b\r\f ]* { strcpy(yyid, yytext); return YYIDE; } {Number}*\.{Number}+ { return YYRNUMBER; } {Number}+\.{Number}* { return YYRNUMBER; } {Number} { return YYINUMBER; } {Binary} { binbin(yytext, brep); encodebit(brep, &bexp1, &bexp0); return YYINUMBER; } {Octal} { octbin(yytext, brep); encodebit(brep, &bexp1, &bexp0); return YYINUMBER; } {Decimal} { decbin(yytext, brep); encodebit(brep, &bexp1, &bexp0); return YYINUMBER; } {Hexdecimal} { hexbin(yytext, brep); encodebit(brep, &bexp1, &bexp0); return YYINUMBER; } \(\?\?\) { return '*'; } \(01\) { return 'r'; } \(10\) { return 'f'; } . { return yytext[0]; } %% int yywrap() { if (!empty_file_stack()) { pop_close_file(); return 0; } else { return 1; } } void skipcommentblock() { int done, level = 0; char c; for (done=0; !done; yyleng = (yyleng > YYLMAX-2) ? YYLMAX-2 : yyleng) { if ((c = input()) == '*') { yytext[yyleng++] = c; if ((c = input()) == '/') { done = (level-- == 0); } else { unput(c); } } else if (c == '/') { yytext[yyleng++] = c; if ((c = input()) == '*') { level++; } else { unput(c); } } else if (c == 0) { char buf[MAXSTRLEN]; sprintf(buf, "incomplete comment (%d)\n", yylineno); fail(buf); } else { #ifdef FLEX_SCANNER if (c == '\n') yylineno++; #endif yytext[yyleng++] = c; } } } void skipcommentline() { int done; char c; for (done=0; !done; yyleng = (yyleng > YYLMAX-2) ? YYLMAX-2 : yyleng) { if ((c = input()) == '\n') { done = 1; } else { yytext[yyleng++] = c; } } yytext[yyleng] = '\0'; #ifdef FLEX_SCANNER yylineno++; #endif } void binbin(instr, outstr) char *instr; char *outstr; { char *cp, *firstcp; int blen = 0, bpos=0; blen = atoi(instr); blen = (blen==0) ? MAXBITNUM : blen; firstcp = strpbrk(instr, "bB")+1; cp = instr + strlen(instr) - 1; outstr[blen] = '\0'; for (bpos = blen-1; bpos >=0 && cp >= firstcp; cp--) { if (*cp != '_' && *cp != ' ') { outstr[bpos] = *cp; bpos--; } } for (; bpos >=0; bpos--) { outstr[bpos] = '0'; } } char *hexnum[16] = {"0000","0001","0010","0011", "0100","0101","0110","0111", "1000","1001","1010","1011", "1100","1101","1110","1111"}; void decbin(instr, outstr) char *instr; char *outstr; { char *firstcp, buf[MAXSTRLEN]; int num, blen = 0; utol(instr); blen = atoi(instr); blen = (blen==0) ? MAXBITNUM : blen; firstcp = strpbrk(instr, "dD")+1; while (*firstcp==' ') firstcp++; num = atoi(firstcp); /* don't put x, z, ? in decimal string */ sprintf(buf, "%d'h%x", blen, num); hexbin(buf, outstr); } void octbin(instr, outstr) char *instr; char *outstr; { char *cp, *firstcp; int blen = 0, bpos=0, i; utol(instr); blen = atoi(instr); blen = (blen==0) ? MAXBITNUM : blen; firstcp = strpbrk(instr, "oO")+1; cp = instr + strlen(instr) - 1; outstr[blen] = '\0'; for (bpos = blen-1; bpos >=0 && cp >= firstcp; cp--) { if (*cp != '_' && *cp != ' ') { for (i = 3; i >= 1; i--) { if (bpos >= 0) { if (*cp=='x' || *cp=='z' || *cp=='?') { outstr[bpos] = *cp; bpos--; } else if (isdigit(*cp)) { outstr[bpos] = hexnum[*cp-'0'][i]; bpos--; } } } } } for (; bpos >=0; bpos--) { outstr[bpos] = '0'; } } void hexbin(instr, outstr) char *instr; char *outstr; { char *cp, *firstcp; int blen = 0, bpos=0, i; utol(instr); blen = atoi(instr); blen = (blen==0) ? MAXBITNUM : blen; firstcp = strpbrk(instr, "hH")+1; cp = instr + strlen(instr) - 1; outstr[blen] = '\0'; for (bpos = blen-1; bpos >=0 && cp >= firstcp; cp--) { if (*cp != '_' && *cp != ' ') { for (i = 3; i >= 0; i--) { if (bpos >= 0) { if (*cp=='x' || *cp=='z' || *cp=='?') { outstr[bpos] = *cp; bpos--; } else if (isdigit(*cp)) { outstr[bpos] = hexnum[*cp-'0'][i]; bpos--; } else if (isxdigit(*cp)) { outstr[bpos] = hexnum[*cp-'a'+10][i]; bpos--; } } } } } for (; bpos >=0; bpos--) { outstr[bpos] = '0'; } } char *utol(str) char *str; { char *cp; for (cp = str; *cp!='\0'; cp++) { if (isupper(*cp)) *cp = tolower(*cp); } return str; } void encodebit(char *instr, int *part1, int *part0) { int i, bmask; *part1 = *part0 = 0; i = strlen(instr); i = (i > MAXBITNUM) ? MAXBITNUM-1 : i-1; for (bmask = 1; i>=0; bmask <<= 1, i--) { switch (instr[i]) { case '1': *part1 |= bmask; break; case '0': *part0 |= bmask; break; case 'x': case '?': *part1 |= bmask; *part0 |= bmask; break; case 'z': break; } } } /* * memorize_macro * * insert a argumentless macro into macro table */ void memorize_macro(instr, macros) char *instr; st_table *macros; { char *cp, *cp1, *cp2; char mname[MAXSTRLEN]; cp = strstr(instr,MACRO_DEFINE) + strlen(MACRO_DEFINE); sscanf(cp, "%s", mname); cp = strstr(cp, mname) + strlen(mname); cp1 = strstr(cp, "//"); cp2 = strstr(cp, "/*"); if (cp1 || cp2) { if (cp1) *cp1='\0'; if (cp2) *cp2='\0'; } st_insert(macros, vlStrdup(mname), vlStrdup(cp)); } /* * expand_macro * * expand an argumentless macro into input stream (using unput) */ void expand_macro(mname, macros) char *mname; st_table *macros; { char *mbody; int i; if (st_lookup(macros, mname, &mbody)) { for (i=strlen(mbody)-1; i>=0; i--) { unput(mbody[i]); } strcpy(curr_macro, mname); } } stack_t file_stack; stack_t fname_stack; stack_t lineno_stack; stack_t buffer_stack; void push_open_file(char *fname) { FILE *infile; char *filename; char buf[MAXSTRLEN]; filename = vlStrdup(fname); if (*filename == '"') { unsigned int i, j; j = strlen(filename)-1; while (filename[j] == ' ' || filename[j] == '\t' || filename[j] == '\r') j--; if (filename[j] != '"') { sprintf(buf, "unbalanced \"\n"); yyerror(buf); } filename[j] = '\0'; for(i=0; i=0; i--) if (filename[i] == '/') break; strcpy(cwd, filename); if (i==-1) { cwd[0]='.'; cwd[1]='\0'; } else { cwd[i]='\0'; } push_stack(dir_stack, vlStrdup(pwd)); chdir(cwd); } void popd() { char *cwd; pop_stack(dir_stack, (void**)&cwd); chdir(cwd); free(cwd); }