Blame | Last modification | View Log | Download | RSS feed
/*
* hdl.y parser for verilog net lists
* by Frank Bennett
*
* i.e. hdl s.g
* products two files: s.nam, s.seq - 1 net per line
* s.seq is sorted by reference designator
* s.nam is sorted by netname
*
* - primarily handles "flat" verilog HDL netlists.
* - parses hierarchical netlist but currently doesn't flatten them.
* - concatenated signal names need to be expanded. currently the whole
* netname bundle is given the name : "concatenation"
* - not included :
* Behavioral Statements
* Specify blocks
*
* PD yacc :
* byacc, Bob Corbett. Berkely yacc adapted for MINIX by Peter Housel
* COLOGNE:commands/lex-yacc/byacc.tar.Z
*
* DOS extender - 386 to avoid malloc problems
* djgpp.zip
* wuarchive.wustl.edu (128.252.135.4): /mirrors3/garbo.uwasa.fi/programming
*/
%{
#define YYDEBUG 1
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#define out(c) putc(c,yyout)
#define NCOM 300
int bug=0, ind ;
FILE *fopen(), *freopen(), *fi, *ft, *fo, *fr ;
static int i, comment=0;
char *cp, *st, refd[20], part[20] ;
char ln[80] ;
extern char *strsave(), *malloc();
extern int yyleng, lexval ;
extern char yytext[];
extern char yysbuf[];
typedef struct YYS_TYPE { /* use instead of %union below */
int i;
char s[50];
} yys_type ;
#define YYSTYPE yys_type
# define YYLMAX 132
int yylineno =0;
int yyleng ;
char yytext[YYLMAX];
char yysbuf[YYLMAX];
char modnam[YYLMAX];
int yysptr = -1, yylast, toklast;
FILE *yyout;
#define YYNL 10
%}
/* HP-UX yacc seems to be fussy about :
%union {
int i;
char s[50];
}
*/
%token NL NAME NUMBER MODULE ENDMODULE WIRE INPUT OUTPUT INOUT
%token NETTYPE ASSIGN STRENGTH0 STRENGTH1 GATETYPE INITIAL
%token PARAMETER REG TIME INTEGER REAL EVENT DEFPARAM
%token BIN_OP UNARY_OP PRIMITIVE ENDPRIM TABLE ENDTABLE
%token OUT_SYM LEV_SYM EDGE_SYM
%left BIN_OP
%start modules
%%
modules : modules mod_prim
| modules error
| mod_prim
;
mod_prim : module
| primitive
;
primitive : PRIMITIVE NAME '(' list_of_vars ')' ';' prim_body ENDPRIM
;
list_of_vars : list_of_vars ',' NAME
| NAME
;
prim_body : UDP_decl UDP_init table_def
| UDP_decl table_def
;
UDP_decl : output_decl
| input_decl
| reg_decl
;
UDP_init : INITIAL NAME '=' init_val
;
init_val : '1' '\'' 'b' '0'
| '1' '\'' 'b' '1'
| '1' '\'' 'b' 'x'
| '1'
| '0'
;
table_def : TABLE table_entries ENDTABLE
;
table_entries : table_entries combin_entry
| combin_entry
| table_entries seq_entry
| seq_entry
;
combin_entry : level_in_list ':' OUT_SYM ';'
;
seq_entry : level_in_list ':' state ':' next_state ';'
| edge_in_list ':' state ':' next_state ';'
;
level_in_list : LEV_SYM
;
edge_in_list : LEV_SYM edge LEV_SYM
| edge
;
edge : '(' LEV_SYM LEV_SYM ')'
| EDGE_SYM
;
state : LEV_SYM
;
next_state : OUT_SYM
;
module : MODULE NAME ';' mod_body ENDMODULE
| MODULE NAME '('list_of_ports')' ';' mod_body ENDMODULE
;
list_of_ports : list_of_ports ',' port
| port
;
port : NAME
| NAME '[' const_exp ']'
| NAME '[' const_exp ':' const_exp ']'
;
mod_body : mod_body module_item
| module_item
;
module_item : param_decl
| input_decl
| output_decl
| inout_decl
| net_decl
| reg_decl
| time_decl
| integer_decl
| real_decl
| event_decl
| gate_decl
| module_instant
| defparm_decl
| cont_assign
;
param_decl : PARAMETER
;
reg_decl : REG
;
time_decl : TIME
;
integer_decl : INTEGER
;
real_decl : REAL
;
event_decl : EVENT
;
defparm_decl : DEFPARAM
;
gate_decl : GATETYPE gate_instant
| GATETYPE dr_strength gate_instant
| GATETYPE delay gate_instant
| GATETYPE dr_strength delay gate_instant
;
gate_instant : NAME '(' exp ')'
;
input_decl : INPUT list_vars ';'
| INPUT range list_vars ';'
;
output_decl : OUTPUT list_vars ';'
| OUTPUT range list_vars ';'
;
inout_decl : INOUT list_vars ';'
| INOUT range list_vars ';'
;
net_decl : NETTYPE list_vars ';'
| NETTYPE range list_vars ';'
| NETTYPE delay list_vars ';'
| NETTYPE range delay list_vars ';'
;
range : '[' const_exp ':' const_exp ']'
;
delay : '#' number
| '#' NAME
;
dr_strength : '(' STRENGTH0 ',' STRENGTH1 ')'
| '(' STRENGTH1 ',' STRENGTH0 ')'
;
list_vars : list_vars ',' NAME
| NAME
;
module_instant : name_mod mod_inst_list ';'
| name_mod par_val mod_inst_list ';'
;
name_mod : NAME
{ strcpy( part, yytext); }
;
mod_inst_list : mod_inst_list ',' mod_inst
| mod_inst
;
mod_inst : reference '(' list_mod_conn ')'
| reference '(' list_nam_conn ')'
;
reference : NAME
{ strcpy( refd, yytext); }
;
list_mod_conn : list_mod_conn ',' exp
| exp
;
list_nam_conn : list_nam_conn ',' nam_conn
| nam_conn
;
nam_conn : '.' NAME '(' sig_nam ')'
{
fprintf(fo,"%-18s %-22s %-10s %10s %s\n",
$4.s, refd, $2.s, part, modnam);
}
;
sig_nam : NAME
| NAME '[' exp ']'
{ strcpy($$.s, $1.s);
strcat($$.s, "[");
strcat($$.s, $3.s);
strcat($$.s, "]");
}
| NAME '[' exp ':' exp ']'
{ strcpy($$.s, $1.s);
strcat($$.s, "[");
strcat($$.s, $3.s);
strcat($$.s, ":");
strcat($$.s, $5.s);
strcat($$.s, "]");
}
| concatenation
{ strcpy($$.s, "concatenation");}
;
par_val : '#' '(' exp ')'
;
cont_assign : ASSIGN list_assigns ';'
| ASSIGN dr_strength list_assigns ';'
| ASSIGN delay list_assigns ';'
| ASSIGN dr_strength delay list_assigns ';'
;
list_assigns : list_assigns ',' assignment
| assignment
;
assignment : lvalue '=' exp
| lvalue '=' '(' exp ')'
;
lvalue : NAME
| NAME '[' exp ']'
| concatenation
;
const_exp : exp
;
concatenation : '{' exp_list '}'
;
exp_list : exp_list ',' exp
| exp
;
exp : primary
| UNARY_OP primary
| UNARY_OP '(' exp ')'
| exp BIN_OP exp
;
primary : number
| NAME '[' exp ']'
| NAME
| concatenation
;
number : NUMBER
| NUMBER '\'' 'b' NUMBER
| NUMBER '\'' 'd' NUMBER
| NUMBER '\'' 'o' NUMBER
;
%% /* start of main */
main(argc,argv)
int argc;
char *argv[];
{
int i,p;
char frnam[60], fsnam[60];
yyout =stderr;
if(argc == 1) {
fprintf(stderr,"use:hdl [-ds] file\n"); exit(1);
}
for(i=1; i<argc; i++)
if(argv[i][0] == '-'){
bug = ((argv[i][1] == 'd') || (argv[i][2] == 'd'));
}
else break;
if(freopen( argv[i],"r",stdin) == NULL){
fprintf(stderr,"can't open %s\n", argv[i]);exit(1);
} else {
/* open output */
for( cp=argv[i], st=fsnam ; *cp && *cp != '.' ; )*st++ = *cp++;
*st = 0;
strcpy( frnam, fsnam );
strcat( frnam, ".nam"); strcat( fsnam, ".seq");
if((fo = fopen(fsnam, "w")) == NULL) err("can't open %s",fsnam);
fprintf(stderr,"reading nets from %s\n", argv[i]);
}
yyparse() ;
fclose(fo);
fprintf(stderr,"sorting...\n");
sprintf(ln, "sort <%s >%s", fsnam, frnam); system(ln);
}
int
yylex() /* Gets the next token from the input stream */
{
int c, i, j ;
static int eline ;
extern int bug;
start:
if(yysptr == -1){
i = 0; eline =1; yylineno++;
/* get line to yysbuf */
while( ((c=getchar()) != EOF) && (c != YYNL)){
if(c == '\t'){ c=' ';do yysbuf[i++] = c; while(i & 7);}
else {
if (c != ' ')eline =0;
yysbuf[i++] = c;
}
}
yysptr = 0;
yysbuf[i] = '\0';
yylast = toklast = 0;
}
if(c == EOF)
return(EOF);
while( (c = yysbuf[yysptr]) == ' ') yysptr++;
if(bug){
fprintf(yyout,"%03d:%s\n",yylineno,yysbuf);
for( i=yysptr ; i>0 ; i-- )out(' ');
}
if ( c == YYNL || c== 0 ){
yysptr= -1;
if(bug)fprintf(yyout,"\n");
goto start;
}
if( comment ){
while( (c = yysbuf[yysptr++]) != '*' && c != '/'&& c );
if( c == '*' && yysbuf[yysptr]=='/' )
comment-- ;
if( c == '/' && yysbuf[yysptr]=='*' )
comment++ ;
if( c == 0 )
yysptr = -1;
if( comment )
goto start;
yysptr++;
goto start;
}
if( c == '/' ) { /* comment // ? */
if( yysbuf[yysptr+1] == '/') {
yysptr= -1;
goto start;
}
if( yysbuf[yysptr+1] == '*') {
comment++; yysptr +=2;
goto start;
}
}
if( c == '\\'){ /* escaped name */
yyleng=0;
while( (c=yysbuf[++yysptr]) != ' ' )
yytext[yyleng++] = c;
yytext[yyleng] = '\0';
if(bug)fprintf(yyout," ^tok:NAME\n");
if( toklast==MODULE ){
toklast = 0;
strcpy(modnam, yytext);
fprintf(stderr,"module %s\n", modnam);
}
if( toklast==PRIMITIVE ){
toklast = 0;
strcpy(modnam, yytext);
fprintf(stderr,"primitive %s\n", modnam);
}
strcpy(yylval.s, yytext);
return(NAME);
}
if( isalpha(c) ) {
if( yylast == '\'' ){ /* number base - 1'b0 */
yysptr++;
if(bug)
if(c < ' ') fprintf(yyout," ^CHAR:%d\n",c);
else fprintf(yyout," ^CHAR:%c\n",c);
yylast = c;
return(c);
}
if( (j=chktok()) != 0){
toklast = j;
return(j);
}
name:
yyleng=0;
while( isalpha(c) || isdigit(c) || c=='_' ) {
yytext[yyleng++] = c; c = yysbuf[++yysptr];
}
yytext[yyleng] = '\0';
if(bug)fprintf(yyout," ^tok:NAME\n");
if( toklast==MODULE ){
toklast = 0;
strcpy(modnam, yytext);
fprintf(stderr,"module %s\n", modnam);
}
if( toklast==PRIMITIVE ){
toklast = 0;
strcpy(modnam, yytext);
fprintf(stderr,"primitive %s\n", modnam);
}
strcpy(yylval.s, yytext);
return(NAME);
}
if( isdigit(c) ) {
yyleng=0;
while( isdigit(c) ) {
yytext[yyleng++] = c; c = yysbuf[++yysptr];
}
yytext[yyleng] = '\0';
if(bug)fprintf(yyout," ^tok:NUMBER\n");
strcpy(yylval.s, yytext);
return(NUMBER);
}
yysptr++; yylast = c;
if( c=='+' || c=='-' || c=='&' || c=='|' || c=='^' ){
if(bug) fprintf(yyout," ^BIN_OP:%c\n",c);
return(BIN_OP);
}
if( c=='!' || c=='~' ){
if(bug) fprintf(yyout," ^UNARY_OP:%c\n",c);
return(UNARY_OP);
}
if(bug)
if(c < ' ')
fprintf(yyout," ^CHAR:%d\n",c);
else
fprintf(yyout," ^CHAR:%c\n",c);
return(c);
} /* nexttoken */
int chktok()
{
static struct { char *keyword; int val, tok; } key [] = {
"module " , 0, MODULE,
"endmodule" , 0, ENDMODULE,
"primitive ", 0, PRIMITIVE,
"endprimitive",0,ENDPRIM,
"input " , 0, INPUT,
"output " , 0, OUTPUT,
"inout " , 0, INOUT,
"assign " , 0, ASSIGN,
"wire " , 0, NETTYPE,
"triand " , 1, NETTYPE,
"trior " , 2, NETTYPE,
"tri1 " , 3, NETTYPE,
"tri " , 4, NETTYPE,
"supply0 " , 5, NETTYPE,
"supply1 " , 6, NETTYPE,
"wor " , 7, NETTYPE,
"trireg " , 8, NETTYPE,
"supply0 " , 0, STRENGTH0,
"strong0 " , 1, STRENGTH0,
"pull0 " , 2, STRENGTH0,
"weak0 " , 3, STRENGTH0,
"highz0 " , 4, STRENGTH0,
"supply1 " , 0, STRENGTH1,
"strong1 " , 1, STRENGTH1,
"pull1 " , 2, STRENGTH1,
"weak1 " , 3, STRENGTH1,
"highz1 " , 4, STRENGTH1,
"parameter ", 0, PARAMETER,
"reg " , 0, REG,
"time " , 0, TIME,
"integer " , 0, INTEGER,
"real " , 0, REAL,
"event " , 0, EVENT,
"defparam " , 0, DEFPARAM,
"and " , 0, GATETYPE,
"nand " , 1, GATETYPE,
"or " , 2, GATETYPE,
"nor " , 3, GATETYPE,
"xor " , 4, GATETYPE,
"xnor " , 5, GATETYPE,
"buf " , 6, GATETYPE,
"tran " , 7, GATETYPE,
"table " , 0, TABLE,
"endtable" , 0, ENDTABLE,
"initial " , 0, INITIAL,
NULL, 0, 0
};
int save, i, j ;
char *s;
for( j=0 ; (s=key[j].keyword) != NULL ; j++) {
save = yysptr; yyleng = 0;
while( *s == yysbuf[yysptr++] && *s )
yytext[yyleng++] = *s++;
if(*s == '\0'){
yytext[yyleng] = '\0';
yysptr--;
if(bug){
for( i=yysptr-1 ; i>0 ; i-- )out(' ');
fprintf(yyout," ^tok:%s\n",yytext);
}
yylval.i = key[j].val;
return(key[j].tok);
}
yysptr = save;
}
return(0);
}
yyerror(s)
char *s;
{
int i;
fprintf(stderr,"%s error on line %d\n",s,yylineno);
fprintf(stderr,"%s\n", yysbuf);
for( i=yysptr ; i>0 ; i-- )out(' ');
fprintf(stderr,"^\n");
}
char *strsave(s)
char *s;
{
char *p, *malloc();
if((p = malloc(strlen(s)+1)) != NULL) strcpy(p,s);
if( p==NULL)err("out of malloc space");
return(p);
}
err(s,t)
char *s,*t;
{
fprintf(stderr,s,t); fprintf(stderr,"\n");
exit(1);
}