Subversion Repositories Vertical

Rev

Rev 2 | Blame | Compare with Previous | 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);
}