/* 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. Author: Szu-Tsung Cheng, stcheng@ic.Berkeley.EDU 10/92 10/93 $Header: /projects/development/hsv/CVSRepository/vl2mv/src/parser/verilog.y,v 1.7 2009/03/16 20:57:20 fabio Exp $ */ %{ #include #include "util.h" #include "list.h" #include "st.h" #include "array.h" #include "set.h" #include "stack.h" #include "vl_defs.h" #include "vl_types.h" #include "vlr_int.h" #include "vl_create.h" #include "vl_write.h" #include "vl_create.h" #include "verilog.h" #define NOND_SET "NDset" extern vl_descPtr mod_list; extern char yyid[]; extern char brep[]; extern int bexp0, bexp1; extern char last_macro[]; extern st_table *macros; extern int compatibleChecking; extern char yytypetoken[]; extern int instantiateAll; int YYTrace=0; char *vl_filename = ""; struct vl_desc *vl_description = NIL(struct vl_desc); struct vl_module *vl_currentModule=NIL(vl_module); struct vl_primitive *vl_currentPrimitive=NIL(vl_primitive); struct vl_function *vl_currentFunction=NIL(vl_function); lsList vl_module_stack; lsList vl_cur_type_stack; st_table *aux_st=NIL(st_table); char modName[MAXSTRLEN]; char *cp; short eventType; int enum_val=0; int reserve_type_name=1; int task_mode=0; int timed_statement = 0; static int c_assign=0; EXTERN int yylex ARGS(()); %} %union { int ival; char *charp; typestructPtr type; lsList lstp; vl_bassign_stmtPtr basgn; vl_begin_end_stmtPtr seqstmt; vl_case_itemPtr caseitem; vl_cont_assignPtr casgn; vl_declPtr bascdcl; vl_delayPtr dlay; vl_descPtr desc; vl_event_exprPtr evnt; vl_exprPtr expr; vl_fork_join_stmtPtr parstmt; vl_functionPtr func; vl_gate_instPtr gtinst; vl_gate_inst_listPtr gtlist; vl_id_rangePtr idrng; vl_lvalPtr lval; vl_mod_prim_inst_listPtr modlist; vl_modulePtr modu; vl_netdeclPtr netdcl; vl_paramdeclPtr paradcl; vl_portPtr port; vl_port_connectPtr connect; vl_prim_entryPtr ntry; vl_primitivePtr prim; vl_procstmtPtr prcstmt; vl_rangePtr rang; vl_range_or_typePtr rngtyp; vl_rangedeclPtr rangdcl; vl_taskPtr task; vl_task_enable_stmtPtr taskenablestmt; vl_typePtr typedcl; vl_type_specifierPtr typespc; vl_enumeratorPtr enumtr; vl_enum_typePtr enumtp; multi_concatPtr mconcat; } %start source_text %token YYIDE %token YYINUMBER %token YYRNUMBER %token YYSTRING %token YYALLPATH %token YYALWAYS %token YYAND %token YYASSIGN %token YYBEGIN %token YYBUF %token YYBUFIF0 %token YYBUFIF1 %token YYCASE %token YYCASEX %token YYCASEZ %token YYCMOS %token YYCONDITIONAL %token YYDEASSIGN %token YYDEFAULT %token YYDEFPARAM %token YYDISABLE %token YYELSE %token YYEDGE %token YYEND %token YYENDCASE %token YYENDMODULE %token YYENDFUNCTION %token YYENDPRIMITIVE %token YYENDSPECIFY %token YYENDTABLE %token YYENDTASK %token YYENUM %token YYEVENT %token YYFOR %token YYFOREVER %token YYFORK %token YYFUNCTION %token YYGEQ %token YYHIGHZ0 %token YYHIGHZ1 %token YYIF %token YYINITIAL %token YYINOUT %token YYINPUT %token YYINTEGER %token YYJOIN %token YYLARGE %token YYLEADTO %token YYLEQ %token YYLOGAND %token YYCASEEQUALITY %token YYCASEINEQUALITY %token YYLOGNAND %token YYLOGNOR %token YYLOGOR %token YYLOGXNOR %token YYLOGEQUALITY %token YYLOGINEQUALITY %token YYLSHIFT %token YYMACROMODULE %token YYMEDIUM %token YYMODULE %token YYMREG %token YYNAND %token YYNBASSIGN %token YYNEGEDGE %token YYNMOS %token YYNOR %token YYNOT %token YYNOTIF0 %token YYNOTIF1 %token YYOR %token YYOUTPUT %token YYPARAMETER %token YYPMOS %token YYPOSEDGE %token YYPRIMITIVE %token YYPULL0 %token YYPULL1 %token YYPULLUP %token YYPULLDOWN %token YYRCMOS %token YYREAL %token YYREG %token YYREPEAT %token YYRIGHTARROW %token YYRNMOS %token YYRPMOS %token YYRSHIFT %token YYRTRAN %token YYRTRANIF0 %token YYRTRANIF1 %token YYSCALARED %token YYSMALL %token YYSPECIFY %token YYSPECPARAM %token YYSTRONG0 %token YYSTRONG1 %token YYSUPPLY0 %token YYSUPPLY1 %token YYSWIRE %token YYTABLE %token YYTASK %token YYTESLATIMER %token YYTIME %token YYTRAN %token YYTRANIF0 %token YYTRANIF1 %token YYTRI %token YYTRI0 %token YYTRI1 %token YYTRIAND %token YYTRIOR %token YYTRIREG %token YYuTYPE %token YYTYPEDEF %token YYVECTORED %token YYWAIT %token YYWAND %token YYWEAK0 %token YYWEAK1 %token YYWHILE %token YYWIRE %token YYWOR %token YYXNOR %token YYXOR %token YYsysSETUP %token YYsysID %token YYsysND %right YYCONDITIONAL %right '?' ':' %left YYOR %left YYLOGOR %left YYLOGAND %left '|' %left '^' YYLOGXNOR %left '&' %left YYLOGEQUALITY YYLOGINEQUALITY YYCASEEQUALITY YYCASEINEQUALITY %left '<' YYLEQ '>' YYGEQ YYNBASSIGN %left YYLSHIFT YYRSHIFT %left '+' '-' %left '*' '/' '%' %right '~' '!' YYUNARYOPERATOR %type source_text %type description %type module %type primitive %type port_list_opt port_list %type port %type port_expression_opt port_expression %type port_ref_list %type port_reference %type port_reference_arg %type module_item %type module_item_clr %type parameter_declaration %type input_declaration output_declaration inout_declaration %type reg_declaration %type net_declaration %type time_declaration event_declaration %type integer_declaration real_declaration %type gate_instantiation %type module_or_primitive_instantiation %type parameter_override %type continuous_assign %type initial_statement always_statement %type task %type function %type variable_list primitive_declaration_eclr %type table_definition %type table_entries combinational_entry_eclr sequential_entry_eclr %type combinational_entry sequential_entry %type input_list level_symbol_or_edge_eclr %type output_symbol state next_state %type level_symbol edge level_symbol_or_edge edge_symbol %type primitive_declaration %type tf_declaration_clr tf_declaration_eclr %type statement_opt %type range_or_type_opt range_or_type %type range %type tf_declaration %type assignment_list %type range_opt %type expression %type drive_strength_opt drive_strength %type charge_strength_opt charge_strength %type nettype %type expandrange_opt expandrange %type delay_opt delay %type register_variable_list %type name_of_event_list %type identifier %type register_variable %type name_of_register %type name_of_event %type strength0 strength1 %type assignment %type drive_delay_clr gate_instance_list %type gatetype drive_delay %type gate_instance %type terminal_list %type name_of_gate_instance name_of_module_or_primitive %type terminal %type module_or_primitive_option_clr %type module_or_primitive_option %type module_or_primitive_instance_list %type delay_or_parameter_value_assignment %type module_or_primitive_instance %type module_connection_list module_port_connection_list %type named_port_connection_list %type module_port_connection named_port_connection %type statement %type statement_clr case_item_eclr %type case_item %type delay_control %type event_control %type lvalue %type expression_list %type seq_block %type par_block %type name_of_block %type block_declaration_clr %type block_declaration %type task_enable %type concatenation %type mintypmax_expression_list %type mintypmax_expression %type primary %type function_call %type event_expression ored_event_expression %type type_declaration type_decorator_opt %type type_name enum_name %type type_specifier %type enum_lst_opt enumerator_list %type enum_specifier %type enumerator %type nondeterminism_list %type multiple_concatenation /* The rules for if-then-else statements produce one harmless * shift-reduce conflict. */ %expect 1 %% source_text : { YYTRACE("source_text:"); if (vl_description == NIL(struct vl_desc)) { $$ = vl_description = mod_list = vl_create_desc("stdin"); } } | source_text description { YYTRACE("source_text: source_text description"); } ; description : module { YYTRACE("description: module"); } | primitive { YYTRACE("description: primitive"); } | type_declaration { YYTRACE("module_item: type_declaration"); } ; type_declaration : YYTYPEDEF type_specifier type_name ';' { YYTRACE("type_declaration: YYTYPEDEF typesepcifier type_name ';'"); vl_create_typedecl($3, $2); if (compatibleChecking) yyerror("type mechanism is not allowed"); } ; module : YYMODULE YYIDE { vl_id_rangePtr idptr; if (!empty_file_stack() && !instantiateAll && mod_list) st_insert(mod_list->mod_holes,vlStrdup(yyid),0); idptr = vl_create_id_range(vlStrdup(yyid), NIL(vl_range)); vl_currentModule = vl_create_module(idptr, LS_NIL, LS_NIL); (void)push_stack(vl_module_stack, (void*)vl_currentModule); set_eliminate(idptr->name, mod_list->mp_undefined); } port_list_opt ';' { vl_currentModule->ports = $4; } module_item_clr YYENDMODULE { YYTRACE("module: YYMODULE YYIDE port_list_opt ';' module_item_clr YYENDMODULE"); vl_currentModule->mod_items = $7; $$ = vl_currentModule; (void**)pop_stack(vl_module_stack, (void**)&vl_currentModule); vl_currentModule = (vl_module*)(void*)top_stack(vl_module_stack); assert(vl_currentModule == NIL(vl_module)); } | YYMACROMODULE YYIDE port_list_opt ';' module_item_clr YYENDMODULE { YYTRACE("module: YYMACROMODULE YYIDE port_list_opt ';' module_item_clr YYENDMODULE"); TODO("module: YYMACROMODULE YYIDE port_list_opt ';' module_item_clr YYENDMODULE"); } ; port_list_opt : { YYTRACE("port_list_opt:"); $$ = LS_NIL; } | '(' port_list ')' { YYTRACE("port_list_opt: '(' port_list ')'"); $$ = $2; } ; port_list : port { lsHandle handle; YYTRACE("port_list: port"); $$ = lsCreate(); lsNewEnd($$, (lsGeneric)$1, &handle); } | port_list ',' port { lsHandle handle; YYTRACE("port_list: port_list ',' port"); lsNewEnd($1, (lsGeneric)$3, &handle); $$ = $1; } ; port : port_expression_opt { YYTRACE("port: port_expression_opt"); $$ = vl_create_port(ModulePort, NIL(vl_id_range), $1); } | '.' YYIDE { $$ = vl_create_id_range(vlStrdup(yyid), NIL(vl_range)); } '(' port_expression_opt ')' { YYTRACE("port: ',' YYIDE '(' port_expression_opt ')'"); $$ = vl_create_port(NamedPort, $3, $5); } ; port_expression_opt : { YYTRACE("port_expression_opt:"); $$ = LS_NIL; } | port_expression { YYTRACE("port_expression_opt: port_expression"); } ; port_expression : port_reference { lsHandle handle; YYTRACE("port_expression: port_reference"); $$ = lsCreate(); lsNewEnd($$, (lsGeneric)$1, &handle); } | '{' port_ref_list '}' { YYTRACE("port_expression: '{' port_ref_list '}'"); $$ = $2; } ; port_ref_list : port_reference { lsHandle handle; YYTRACE("port_ref_list: port_reference"); $$ = lsCreate(); lsNewEnd($$, (lsGeneric)$1, &handle); } | port_ref_list ',' port_reference { lsHandle handle; YYTRACE("port_ref_list: port_ref_list ',' port_reference"); lsNewEnd($1, (lsGeneric)$3, &handle); $$ = $1; } ; port_reference : YYIDE { $$ = vl_create_id_range(vlStrdup(yyid), NIL(vl_range)); } port_reference_arg { YYTRACE("port_reference: YYIDE port_reference_arg"); $$ = vl_create_id_range($2->name, $3); } ; port_reference_arg : { YYTRACE("port_reference_arg:"); $$ = vl_create_range(NIL(vl_expr), NIL(vl_expr)); } | '[' expression ']' { YYTRACE("port_reference_arg: '[' expression ']'"); $$ = vl_create_range($2, NIL(vl_expr)); } | '[' expression ':' expression ']' { YYTRACE("port_reference_arg: '[' expression ':' expression ']'"); $$ = vl_create_range($2, $4); } ; module_item_clr : { YYTRACE("module_item_clr:"); $$ = lsCreate(); } | module_item_clr module_item { lsHandle handle; int decomposed_assign = 0; lsHandle assignHandle; lsGen assignGen; vl_cont_assign *cont_assign, *new_cont_assign; lsList new_assigns; vl_bassign_stmt *assign; YYTRACE("module_item_clr: module_item_clr module_item"); if (((vl_decl*)$2)->type == ContAssign) if (lsLength(((vl_cont_assign*)$2)->assigns) > 1) { decomposed_assign = 1; cont_assign = (vl_cont_assign*)$2; for (assignGen=lsStart(((vl_cont_assign*)$2)->assigns); lsNext(assignGen,(lsGeneric*)&assign,&assignHandle) != LS_NOMORE; ) { new_assigns = lsCreate(); lsNewEnd(new_assigns, (lsGeneric)assign, 0); new_cont_assign = vl_create_cont_assign_stmt(cont_assign->strength, cont_assign->delay, new_assigns); lsNewEnd($1, (lsGeneric)new_cont_assign, 0); } lsFinish(assignGen); lsDestroy(cont_assign->assigns, 0); vl_chk_free((char*)$2); } if (!decomposed_assign) lsNewEnd($1, (lsGeneric)$2, &handle); $$ = $1; } ; module_item : parameter_declaration { YYTRACE("module_item: parameter_declaration"); $$ = (typestructPtr)$1; } | input_declaration { YYTRACE("module_item: input_declaration"); $$ = (typestructPtr)$1; } | output_declaration { YYTRACE("module_item: output_declaration"); $$ = (typestructPtr)$1; } | inout_declaration { YYTRACE("module_item: inout_declaration"); $$ = (typestructPtr)$1; } | net_declaration { YYTRACE("module_item: net_declaration"); $$ = (typestructPtr)$1; } | reg_declaration { YYTRACE("module_item: reg_declaration"); $$ = (typestructPtr)$1; } | time_declaration { YYTRACE("module_item: time_declaration"); $$ = (typestructPtr)$1; } | integer_declaration { YYTRACE("module_item: integer_declaration"); $$ = (typestructPtr)$1; } | real_declaration { YYTRACE("module_item: real_declaration"); $$ = (typestructPtr)$1; } | event_declaration { YYTRACE("module_item: event_declaration"); $$ = (typestructPtr)$1; } | gate_instantiation { YYTRACE("module_item: gate_instantiation"); $$ = (typestructPtr)$1; } | module_or_primitive_instantiation { YYTRACE("module_item: module_or_primitive_instantiation"); $$ = (typestructPtr)$1; } | parameter_override { YYTRACE("module_item: parameter_override"); $$ = (typestructPtr)$1; } | continuous_assign { YYTRACE("module_item: continous_assign"); $$ = (typestructPtr)$1; } | specify_block { YYTRACE("module_item: specify_block"); $$ = $1; } | initial_statement { YYTRACE("module_item: initial_statement"); $$ = (typestructPtr)$1; } | always_statement { YYTRACE("module_item: always_statement"); $$ = (typestructPtr)$1; } | task { YYTRACE("module_item: task"); $$ = (typestructPtr)$1; } | function { YYTRACE("module_item: function"); $$ = (typestructPtr)$1; } ; primitive : YYPRIMITIVE YYIDE { vl_id_rangePtr idptr; idptr = vl_create_id_range(vlStrdup(yyid), NIL(vl_range)); vl_currentPrimitive = vl_create_primitive(idptr, LS_NIL, LS_NIL, LS_NIL); set_eliminate(idptr->name, mod_list->mp_undefined); } '(' port_list ')' ';' primitive_declaration_eclr table_definition YYENDPRIMITIVE { YYTRACE("primitive: YYPRMITIVE YYIDE '(' variable_list ')' ';' primitive_declaration_eclr table_definition YYENDPRIMITIVE"); vl_currentPrimitive->ports = $5; vl_currentPrimitive->decls = $8; vl_currentPrimitive->entries = $9; $$ = vl_currentPrimitive; vl_currentPrimitive = NIL(vl_primitive); } ; primitive_declaration_eclr : primitive_declaration { lsHandle handle; YYTRACE("primitive_declaration_eclr: primitive_declaration"); $$ = lsCreate(); lsNewEnd($$, (lsGeneric)$1, &handle); } | primitive_declaration_eclr primitive_declaration { lsHandle handle; YYTRACE("primitive_declaration_eclr: primitive_declaration_eclr primitive_declaration"); lsNewEnd($1, (lsGeneric)$2, &handle); $$ = $1; } ; primitive_declaration : output_declaration { YYTRACE("primitive_declaration: output_declaration"); $$ = (typestructPtr)$1; } | reg_declaration { YYTRACE("primitive_decalration: reg_declaration"); $$ = (typestructPtr)$1; } | input_declaration { YYTRACE("primitive_decalration: input_declaration"); $$ = (typestructPtr)$1; } ; table_definition : YYTABLE table_entries YYENDTABLE { YYTRACE("table_definition: YYTABLE table_entries YYENDTABLE"); $$ = $2; } ; table_entries : combinational_entry_eclr { YYTRACE("table_definition: combinational_entry_eclr"); vl_currentPrimitive->type = CombPrimDecl; } | sequential_entry_eclr { YYTRACE("table_definition: sequential_entry_eclr"); vl_currentPrimitive->type = SeqPrimDecl; } ; combinational_entry_eclr : combinational_entry { YYTRACE("combinational_entry_eclr: combinational_entry"); $$ = lsCreate(); lsNewEnd($$, (lsGeneric)$1, LS_NH); } | combinational_entry_eclr combinational_entry { YYTRACE("combinational_entry_eclr: combinational_entry_eclr combinational_entry"); lsNewEnd($1, (lsGeneric)$2, LS_NH); $$ = $1; } ; combinational_entry : input_list ':' output_symbol ';' { YYTRACE("combinational_entry: input_list ':' output_symbol ';'"); $$ = vl_create_prim_entry($1, PrimNone, $3); } ; sequential_entry_eclr : sequential_entry { YYTRACE("sequential_entry_eclr: sequential_entry"); $$ = lsCreate(); lsNewEnd($$, (lsGeneric)$1, LS_NH); } | sequential_entry_eclr sequential_entry { YYTRACE("sequential_entry_eclr: sequential_entry_eclr sequential_entry"); lsNewEnd($1, (lsGeneric)$2, LS_NH); $$ = $1; } ; sequential_entry : input_list ':' state ':' next_state ';' { YYTRACE("sequential_entry: input_list ':' state ':' next_state ';'"); $$ = vl_create_prim_entry($1, $3, $5); } ; input_list : level_symbol_or_edge_eclr { YYTRACE("input_list: level_symbol_or_edge_eclr"); } ; level_symbol_or_edge_eclr : level_symbol_or_edge { YYTRACE("level_symbol_or_edge_eclr: level_symbol_or_edge"); $$ = lsCreate(); lsNewEnd($$, (lsGeneric)$1, LS_NH); } | level_symbol_or_edge_eclr level_symbol_or_edge { YYTRACE("level_symbol_or_edge_eclr: level_symbol_or_edge_eclr level_symbol_or_edge"); lsNewEnd($1, (lsGeneric)$2, LS_NH); $$ = $1; } ; level_symbol_or_edge : level_symbol { YYTRACE("level_symbol_or_edge: level_symbol"); } | edge { YYTRACE("level_symbol_or_edge: edge"); } ; edge : '(' level_symbol level_symbol ')' { YYTRACE("edge: '(' level_symbol level_symbol ')'"); switch ($2) { case Prim0: $$ = ($3==PrimX) ? Prim0X : PrimR; break; case Prim1: $$ = ($3==PrimX) ? Prim1X : PrimF; break; case PrimX: $$ = ($3==Prim1) ? PrimX1 : ($3==Prim0) ? PrimX0 : PrimXB; break; case PrimB: $$ = ($3==PrimX) ? PrimBX : PrimBB; break; case PrimQ: $$ = ($3==Prim1) ? PrimQ1 : ($3==Prim0) ? PrimQ0 : PrimQB; break; default: { char mesg[MAXSTRLEN]; sprintf(mesg, "Unknown edge symbol (%d,%d)", $2, $3); compile_error(mesg); } } } | edge_symbol { YYTRACE("edge: edge_symbol"); } ; state : level_symbol { YYTRACE("state: level_symbol"); } ; next_state : output_symbol { YYTRACE("next_state: output_symbol"); } | '-' { YYTRACE("next_state: '_'"); $$ = PrimM; } ; output_symbol : '0' { YYTRACE("output_symbol: '0'"); $$ = Prim0; } | '1' { YYTRACE("output_symbol: '1'"); $$ = Prim1; } | 'x' { YYTRACE("output_symbol: 'x'"); $$ = PrimX; } | 'X' { YYTRACE("output_symbol: 'X'"); $$ = PrimX; } ; level_symbol : '0' { YYTRACE("level_symbol: '0'"); $$ = Prim0; } | '1' { YYTRACE("level_symbol: '1'"); $$ = Prim1; } | 'x' { YYTRACE("level_symbol: 'x'"); $$ = PrimX; } | 'X' { YYTRACE("level_symbol: 'X'"); $$ = PrimX; } | '?' { YYTRACE("level_symbol: '?'"); $$ = PrimQ; } | 'b' { YYTRACE("level_symbol: 'b'"); $$ = PrimB; } | 'B' { YYTRACE("level_symbol: 'B'"); $$ = PrimB; } ; edge_symbol : 'r' { YYTRACE("edge_symbol: 'r'"); $$ = PrimR; } | 'R' { YYTRACE("edge_symbol: 'R'"); $$ = PrimR; } | 'f' { YYTRACE("edge_symbol: 'f'"); $$ = PrimF; } | 'F' { YYTRACE("edge_symbol: 'F'"); $$ = PrimF; } | 'p' { YYTRACE("edge_symbol: 'p'"); $$ = PrimP; } | 'P' { YYTRACE("edge_symbol: 'P'"); $$ = PrimP; } | 'n' { YYTRACE("edge_symbol: 'n'"); $$ = PrimN; } | 'N' { YYTRACE("edge_symbol: 'N'"); $$ = PrimN; } | '*' { YYTRACE("edge_symbol: '*'"); $$ = PrimS; } ; task : YYTASK YYIDE { $$ = vl_create_id_range(vlStrdup(yyid), NIL(vl_range)); task_mode = 1; } ';' tf_declaration_clr statement_opt YYENDTASK { YYTRACE("YYTASK YYIDE ';' tf_declaration_clr statement_opt YYENDTASK"); $$ = vl_create_task($3, $5, $6); task_mode = 0; } ; function : YYFUNCTION range_or_type_opt YYIDE { int bad_type=0; $$ = vl_create_id_range(vlStrdup(yyid), NIL(vl_range)); if (!$2) { vl_expr *zero; zero = vl_create_expr(IntExpr, 0, (double)0.0, NIL(void), NIL(void), NIL(void)); $2 = vl_create_range_or_type(Range_Dcl, vl_create_range(zero,zero)); } else if (!$2->range) { bad_type = 1; } if (bad_type) { char buf[MAXSTRLEN]; sprintf(buf, "bit width of function '%s' is not known",yyid); compile_error(buf); } vl_currentFunction = vl_create_function(0, $2->range, $$, lsCreate(), lsCreate()); vl_currentModule = (vl_module*)vl_currentFunction; push_stack(vl_module_stack, vl_currentModule); } ';' tf_declaration_eclr statement_opt YYENDFUNCTION { vl_id_range *func_out; short func_type=0; lsList out_ids; YYTRACE("YYFUNCTION range_or_type_opt YYIDE ';' tf_declaration_eclr statement_opt YYENDFUNCTION"); if ($2 == NIL(vl_range_or_type)) { func_type = IntFuncDecl; } else { switch ($2->type) { case Range_Dcl: func_type = RangeFuncDecl; break; case Integer_Dcl: func_type = IntFuncDecl; break; case Real_Dcl: func_type = RealFuncDecl; break; default: internal_error("unknown function type"); } } func_out = vl_create_id_range($4->name, NIL(vl_range)); func_out->flags |= OutPort; out_ids = lsCreate(); lsNewEnd(out_ids, (lsGeneric)func_out, 0); if ($2->type == Range_Dcl) lsNewEnd($6, (lsGeneric)vl_create_rangedecl(NIL(vl_type), RegDecl, $2->range, out_ids, 0), 0); else lsNewEnd($6, (lsGeneric)vl_create_rangedecl(NIL(vl_type), RegDecl, NIL(vl_range), out_ids, 0), 0); ((vl_function*)vl_currentModule)->type = func_type; ((vl_function*)vl_currentModule)->decls = $6; ((vl_function*)vl_currentModule)->stmts = $7; $$ = (vl_function*)vl_currentModule; (void*)pop_stack(vl_module_stack, (void**)&vl_currentModule); vl_currentModule = (vl_module*)(void*)top_stack(vl_module_stack); lsNewBegin($$->ports, (lsGeneric)func_out, 0); vl_currentFunction = NIL(vl_function); assert(vl_currentModule != NIL(vl_module)); } ; range_or_type_opt : { YYTRACE("range_or_type_opt:"); $$ = NIL(vl_range_or_type); } | range_or_type { YYTRACE("range_or_type_opt: range_or_type"); $$ = $1; } ; range_or_type : range { YYTRACE("range_or_type: range"); $$ = vl_create_range_or_type(Range_Dcl, $1); } | YYINTEGER { YYTRACE("range_or_type: YYINTEGER"); $$ = vl_create_range_or_type(Integer_Dcl, NIL(vl_range)); } | YYREAL { YYTRACE("range_or_type: YYREAL"); $$ = vl_create_range_or_type(Real_Dcl, NIL(vl_range)); } ; tf_declaration_clr : { YYTRACE("tf_declaration_clr:"); $$ = lsCreate(); } | tf_declaration_clr tf_declaration { lsHandle handle; YYTRACE("tf_declaration_clr: tf_declaration_clr tf_declaration"); lsNewEnd($1, (lsGeneric)$2, &handle); $$ = $1; } ; tf_declaration_eclr : tf_declaration { lsHandle handle; YYTRACE("tf_declaration_eclr: tf_declaration"); $$ = lsCreate(); lsNewEnd($$, (lsGeneric)$1, &handle); } | tf_declaration_eclr tf_declaration { lsHandle handle; YYTRACE("tf_declaration_eclr: tf_decalration_eclr tf_declaration"); lsNewEnd($1, (lsGeneric)$2, &handle); $$ = $1; } ; tf_declaration : parameter_declaration { YYTRACE("tf_declaration: parameter_decalration"); $$ = (typestructPtr)$1; } | input_declaration { YYTRACE("tf_declaration: input_declaration"); $$ = (typestructPtr)$1; } | output_declaration { YYTRACE("tf_declaration: output_declaration"); $$ = (typestructPtr)$1; } | inout_declaration { YYTRACE("tf_declaration: inout_declaration"); $$ = (typestructPtr)$1; } | reg_declaration { YYTRACE("tf_declaration: reg_declaration"); $$ = (typestructPtr)$1; } | time_declaration { YYTRACE("tf_declaration: time_declaration"); $$ = (typestructPtr)$1; } | integer_declaration { YYTRACE("tf_declaration: integer_declaration"); $$ = (typestructPtr)$1; } | real_declaration { YYTRACE("tf_declaration: real_declaration"); $$ = (typestructPtr)$1; } | event_declaration { YYTRACE("tf_declaration: event_declaration"); $$ = (typestructPtr)$1; } ; type_name : YYIDE { YYTRACE("type_name: YYIDE"); $$ = vlStrdup(yyid); } ; type_specifier : enum_specifier { YYTRACE("type_specifier: enum_specifier ';'"); $$ = vl_create_type_specifier(EnumType, $1); } ; enum_specifier : YYENUM {enum_val=0;} enum_name enum_lst_opt { YYTRACE("enum_specifier: YYENUM enum_name enum_lst_opt"); $$ = vl_create_enum_type($3, $4); } | YYENUM {enum_val=0;} '{' enumerator_list '}' { YYTRACE("enum_specifier: YYENUM '{' enumerator_list '}'"); $$ = vl_create_enum_type(NIL(char), $4); } ; enum_name : YYIDE { YYTRACE("enum_name: YYIDE"); $$ = vlStrdup(yyid); } ; enum_lst_opt : '{' enumerator_list '}' { YYTRACE("enum_lst_opt: '{' enumerator_list '}'"); $$ = $2; } | { YYTRACE("enum_lst_opt: "); $$ = (lsList)0; } ; enumerator_list : enumerator { YYTRACE("enumerator_list: enumerator"); $$ = lsCreate(); lsNewEnd($$, (lsGeneric)$1, 0); } | enumerator_list ',' enumerator { YYTRACE("enumerator_list: enumerator_list ',' enumerator"); lsNewEnd($$, (lsGeneric)$3, 0); } ; enumerator : YYIDE { YYTRACE("enumerator: YYIDE"); $$ = vl_create_enumerator(vlStrdup(yyid), enum_val++); } | YYIDE {cp=vlStrdup(yyid);} '=' expression { YYTRACE("enumerator: YYIDE '=' expression"); enum_val = vl_eval_expr($4); $$ = vl_create_enumerator(cp, enum_val++); } ; type_decorator_opt : YYuTYPE { vl_type *var_type; int mustBe1; YYTRACE("type_decorator_opt: YYuTYPE"); mustBe1 = st_lookup(mod_list->type_st, yyid, (char**)&var_type); assert(mustBe1); $$ = var_type; } | { YYTRACE("type_decorator_opt: "); $$ = NIL(vl_type); } ; parameter_declaration : YYPARAMETER assignment_list ';' { YYTRACE("parameter_declaration: YYPARAMETER assignment_list ';'"); $$ = vl_create_paramdecl(ParamDecl, $2); } ; input_declaration : YYINPUT range_opt variable_list ';' { YYTRACE("input_declaration: YYINPUT range_opt variable_list ';'"); $$ = vl_create_rangedecl(NIL(vl_type), InputDecl, $2, $3, 0); } ; output_declaration : YYOUTPUT range_opt variable_list ';' { YYTRACE("output_declaration: YYOUTPUT range_opt variable_list ';'"); $$ = vl_create_rangedecl(NIL(vl_type), OutputDecl, $2, $3, 0); } ; inout_declaration : YYINOUT range_opt variable_list ';' { YYTRACE("inout_declaration: YYINOUT range_opt variable_list ';'"); $$ = vl_create_rangedecl(NIL(vl_type), InoutDecl, $2, $3, 0); } ; net_declaration : type_decorator_opt nettype drive_strength_opt expandrange_opt delay_opt assignment_list ';' { YYTRACE("net_declaration: type_decorator_opt nettype drive_strength_opt expandrange_opt delay_opt assignment_list ';'"); $$ = vl_create_netdecl_assigned($1, $2, $3, $4, $5, $6); } | type_decorator_opt nettype drive_strength_opt expandrange_opt delay_opt variable_list ';' { YYTRACE("net_declaration: type_decorator_opt nettype drive_strength_opt expandrange_opt delay_opt variable_list ';'"); $$ = vl_create_netdecl($1, $2, $3, $4, $5, $6); } | type_decorator_opt YYTRIREG charge_strength_opt expandrange_opt delay_opt variable_list ';' { YYTRACE("net_declaration: type_decorator_opt YYTRIREG charge_strength_opt expandrange_opt delay_opt variable_list ';'"); $$ = vl_create_netdecl($1, TriregDecl, $3, $4, $5, $6); } ; nettype : YYSWIRE { YYTRACE("nettype: YYSWIRE"); $$ = SWireDecl; } | YYWIRE { YYTRACE("nettype: YYWIRE"); $$ = WireDecl; } | YYTRI { YYTRACE("nettype: YYTRI"); $$ = TriDecl; } | YYTRI1 { YYTRACE("nettype: YYTRI1"); $$ = Tri1Decl; } | YYSUPPLY0 { YYTRACE("nettype: YYSUPPLY0"); $$ = Supply0Decl; } | YYWAND { YYTRACE("nettype: YYWAND"); $$ = WandDecl; } | YYTRIAND { YYTRACE("nettype: YYTRIAND"); $$ = TriandDecl; } | YYTRI0 { YYTRACE("nettype: YYTRI0"); $$ = Tri0Decl; } | YYSUPPLY1 { YYTRACE("nettype: YYSUPPLY1"); $$ = Supply1Decl; } | YYWOR { YYTRACE("nettype: YYWOR"); $$ = WorDecl; } | YYTRIOR { YYTRACE("nettype: YYTRIOR"); $$ = TriorDecl; } ; expandrange_opt : { YYTRACE("expandrange_opt:"); $$ = NIL(vl_range); } | expandrange { YYTRACE("expandrange_opt: expandrange"); $$ = $1; } ; expandrange : range { YYTRACE("expandrange: range"); } | YYSCALARED range { YYTRACE("expandrange: YYSCALARED range"); $$ = $2; } | YYVECTORED range { YYTRACE("expandrange: YYVECTORED range"); $$ = $2; } ; reg_declaration : type_decorator_opt YYREG range_opt register_variable_list ';' { YYTRACE("reg_declaration: type_decorator_opt YYREG range_opt register_variable_list ';'"); $$ = vl_create_rangedecl($1, RegDecl, $3, $4, 0); } | type_decorator_opt YYMREG range_opt register_variable_list ';' { YYTRACE("reg_declaration: type_decorator_opt YYMREG range_opt register_variable_list ';'"); $$ = vl_create_rangedecl($1, RegDecl, $3, $4, MVar); } ; time_declaration : YYTIME register_variable_list ';' { YYTRACE("time_declaration: YYTIME register_variable_list ';'"); $$ = vl_create_basicdecl(TimeDecl, $2); } ; integer_declaration : YYINTEGER register_variable_list ';' { YYTRACE("integer_declaration: YYINTEGER register_variable_list ';'"); $$ = vl_create_basicdecl(IntDecl, $2); } ; real_declaration : YYREAL variable_list ';' { YYTRACE("real_declaration: YYREAL variable_list ';'"); $$ = vl_create_basicdecl(RealDecl, $2); } ; event_declaration : YYEVENT name_of_event_list ';' { YYTRACE("event_declaration: YYEVENT name_of_event_list ';'"); $$ = vl_create_basicdecl(EventDecl, $2); } ; continuous_assign : YYASSIGN {reserve_type_name=0; c_assign=1;} drive_strength_opt delay_opt assignment_list ';' { YYTRACE("continuous_assign: YYASSIGN drive_strength_opt delay_opt assignment_list ';'"); $$ = vl_create_cont_assign_stmt($3, $4, $5); reserve_type_name=1; c_assign=0; } ; parameter_override : YYDEFPARAM assignment_list ';' { YYTRACE("parameter_override: YYDEFPARAM assign_list ';'"); $$ = vl_create_paramdecl(DefparamDecl, $2); } ; variable_list : identifier { lsHandle handle; YYTRACE("variable_list: identifier"); $$ = lsCreate(); lsNewEnd($$, (lsGeneric)$1, &handle); } | variable_list ',' identifier { lsHandle handle; YYTRACE("variable_list: variable_list ',' identifier"); lsNewEnd($1, (lsGeneric)$3, &handle); $$ = $1; } ; register_variable_list : register_variable { lsHandle handle; YYTRACE("register_variable_list: register_variable"); $$ = lsCreate(); lsNewEnd($$, (lsGeneric)$1, &handle); } | register_variable_list ',' register_variable { lsHandle handle; YYTRACE("register_variable_list: register_variable_list ',' register_variable"); lsNewEnd($1, (lsGeneric)$3, &handle); $$ = $1; } ; register_variable : name_of_register { YYTRACE("register_variable: name_of_register"); $$ = vl_create_id_range($1, NIL(vl_range)); } | name_of_register '[' expression ':' expression ']' { int lo, hi; YYTRACE("register_variable: name_of_register '[' expression ':' expression ']'"); lo = vl_eval_expr($3); hi = vl_eval_expr($5); if (lo > hi) $$ = vl_create_id_range($1, vl_create_range($5, $3)); else $$ = vl_create_id_range($1, vl_create_range($3, $5)); } ; name_of_register : YYIDE { YYTRACE("name_of_register: YYIDE"); $$ = vlStrdup(yyid); } ; name_of_event_list : name_of_event { lsHandle handle; YYTRACE("name_of_event_list: name_of_event"); $$ = lsCreate(); lsNewEnd($$, (lsGeneric)$1, &handle); } | name_of_event_list ',' name_of_event { lsHandle handle; YYTRACE("name_of_event_list: name_of_event_list ',' name_of_event"); lsNewEnd($1, (lsGeneric)$3, &handle); $$ = $1; } ; name_of_event : YYIDE { YYTRACE("name_of_event: YYIDE"); $$ = vl_create_id_range(vlStrdup(yyid), NIL(vl_range)); } ; charge_strength_opt : { YYTRACE("charge_strength_opt:"); $$ = 0; } | charge_strength { YYTRACE("charge_strength_opt: charge_strength"); } ; charge_strength : '(' YYSMALL ')' { YYTRACE("charge_strength: '(' YYSMALL ')'"); $$ = Small; } | '(' YYMEDIUM ')' { YYTRACE("charge_strength: '(' YYMEDIUM ')'"); $$ = Medium; } | '(' YYLARGE ')' { YYTRACE("charge_strength: '(' YYLARGE ')'"); $$ = Large; } ; drive_strength_opt : { YYTRACE("drive_strength_opt:"); $$ = 0; } | drive_strength { YYTRACE("drive_strength_opt: drive_strength"); $$ = $1; } ; drive_strength : '(' strength0 ',' strength1 ')' { YYTRACE("drive_strength: '(' strength0 ',' strength1 ')'"); $$ = drive_strength($2, $4); } | '(' strength1 ',' strength0 ')' { YYTRACE("drive_strength: '(' strength1 ',' strength0 ')'"); $$ = drive_strength($4, $2); } ; strength0 : YYSUPPLY0 { YYTRACE("strength0: YYSUPPLY0"); $$ = YYSUPPLY0; } | YYSTRONG0 { YYTRACE("strength0: YYSTRONG0"); $$ = YYSTRONG0; } | YYPULL0 { YYTRACE("strength0: YYPULL0"); $$ = YYPULL0; } | YYWEAK0 { YYTRACE("strength0: YYWEAK0"); $$ = YYWEAK0; } | YYHIGHZ0 { YYTRACE("strength0: YYHIGHZ0"); $$ = YYHIGHZ0; } ; strength1 : YYSUPPLY1 { YYTRACE("strength1: YYSUPPLY1"); $$ = YYSUPPLY1; } | YYSTRONG1 { YYTRACE("strength1: YYSTRONG1"); $$ = YYSTRONG1; } | YYPULL1 { YYTRACE("strength1: YYPULL1"); $$ = YYPULL1; } | YYWEAK1 { YYTRACE("strength1: YYWEAK1"); $$ = YYWEAK1; } | YYHIGHZ1 { YYTRACE("strength1: YYHIGHZ1"); $$ = YYHIGHZ1; } ; range_opt : { YYTRACE("range_opt:"); $$ = NIL(vl_range); } | range { YYTRACE("range_opt: range"); $$ = $1; } ; range : '[' expression ':' expression ']' { YYTRACE("range: '[' expression ':' expression ']'"); $$ = vl_create_range($2, $4); } ; assignment_list : assignment { lsHandle handle; YYTRACE("assignment_list: assignment"); $$ = lsCreate(); lsNewEnd($$, (lsGeneric)$1, &handle); } | assignment_list ',' assignment { lsHandle handle; YYTRACE("assignment_list: assignment_list ',' assignment"); lsNewEnd($1, (lsGeneric)$3, &handle); $$ = $1; } ; gate_instantiation : gatetype drive_delay_clr gate_instance_list ';' { int strength=0; vl_delay *delay=NIL(vl_delay); YYTRACE("gate_instantiation: gatetype drive_delay_clr gate_instance_list ';'"); extract_delay_strength($2, &delay, &strength); lsDestroy($2, NULL); $$ = vl_create_gate_inst_list($1, strength, delay, $3); insert_instances($3, $$); } ; drive_delay_clr : { YYTRACE("drive_delay_clr:"); $$ = lsCreate(); } | drive_delay_clr drive_delay { lsHandle handle; YYTRACE("drive_delay_clr: drive_delay_clr drive_delay"); lsNewEnd($1, (lsGeneric)$2, &handle); $$ = $1; } ; drive_delay : drive_strength { YYTRACE("drive_delay: drive_strength"); $$ = $1 << 2; } | delay { YYTRACE("drive_delay: delay"); $$ = (int)($1) | LEAST_SB; } ; gatetype : YYAND { YYTRACE("gatetype: YYAND"); $$ = AndGate; } | YYNAND { YYTRACE("gatetype: YYNAND"); $$ = NandGate; } | YYOR { YYTRACE("gatetype: YYOR"); $$ = OrGate; } | YYNOR { YYTRACE("gatetype: YYNOR"); $$ = NorGate; } | YYXOR { YYTRACE("gatetype: YYXOR"); $$ = XorGate; } | YYXNOR { YYTRACE("gatetype: YYXNOR"); $$ = XnorGate; } | YYBUF { YYTRACE("gatetype: YYBUF"); $$ = BufGate; } | YYBUFIF0 { YYTRACE("gatetype: YYBIFIF0"); $$ = Bufif0Gate; } | YYBUFIF1 { YYTRACE("gatetype: YYBIFIF1"); $$ = Bufif1Gate; } | YYNOT { YYTRACE("gatetype: YYNOT"); $$ = NotGate; } | YYNOTIF0 { YYTRACE("gatetype: YYNOTIF0"); $$ = Notif0Gate; } | YYNOTIF1 { YYTRACE("gatetype: YYNOTIF1"); $$ = Notif1Gate; } | YYPULLDOWN { YYTRACE("gatetype: YYPULLDOWN"); $$ = PulldownGate; } | YYPULLUP { YYTRACE("gatetype: YYPULLUP"); $$ = PullupGate; } | YYNMOS { YYTRACE("gatetype: YYNMOS"); $$ = NmosGate; } | YYPMOS { YYTRACE("gatetype: YYPMOS"); $$ = PmosGate; } | YYRNMOS { YYTRACE("gatetype: YYRNMOS"); $$ = RnmosGate; } | YYRPMOS { YYTRACE("gatetype: YYRPMOS"); $$ = RpmosGate; } | YYCMOS { YYTRACE("gatetype: YYCMOS"); $$ = CmosGate; } | YYRCMOS { YYTRACE("gatetype: YYRCMOS"); $$ = RcmosGate; } | YYTRAN { YYTRACE("gatetype: YYTRAN"); $$ = TranGate; } | YYRTRAN { YYTRACE("gatetype: YYRTRAN"); $$ = RtranGate; } | YYTRANIF0 { YYTRACE("gatetype: YYTRANIF0"); $$ = Tranif0Gate; } | YYRTRANIF0 { YYTRACE("gatetype: YYRTRANIF0"); $$ = Rtranif0Gate; } | YYTRANIF1 { YYTRACE("gatetype: YYTRANIF1"); $$ = Tranif1Gate; } | YYRTRANIF1 { YYTRACE("gatetype: YYRTRANIF1"); $$ = Rtranif1Gate; } | YYTESLATIMER { YYTRACE("gatetype: YYTESLATIMER"); $$ = TeslaTimerGate; } ; gate_instance_list : gate_instance { lsHandle handle; YYTRACE("gate_instance_list: gate_instance"); $$ = lsCreate(); lsNewEnd($$, (lsGeneric)$1, &handle); } | gate_instance_list ',' gate_instance { lsHandle handle; YYTRACE("gate_instance_list: gate_instance_list ',' gate_instance"); lsNewEnd($1, (lsGeneric)$3, &handle); $$ = $1; } ; gate_instance : '(' terminal_list ')' { YYTRACE("gate_instance: '(' terminal_list ')'"); $$ = vl_create_gate_inst(NIL(vl_id_range), $2); } | name_of_gate_instance '(' terminal_list ')' { YYTRACE("gate_instance: name_of_gate_instance '(' terminal_list ')'"); $$ = vl_create_gate_inst($1, $3); } ; name_of_gate_instance : YYIDE { YYTRACE("name_of_gate_instance: YYIDE"); $$ = vl_create_id_range(vlStrdup(yyid), NIL(vl_range)); } ; terminal_list : terminal { lsHandle handle; YYTRACE("terminal_list: terminal"); $$ = lsCreate(); lsNewEnd($$, (lsGeneric)$1, &handle); } | terminal_list ',' terminal { lsHandle handle; YYTRACE("terminal_list: terminal_list ',' terminal"); lsNewEnd($1, (lsGeneric)$3, &handle); $$ = $1; } ; terminal : expression { YYTRACE("terminal: expression"); } ; module_or_primitive_instantiation : name_of_module_or_primitive module_or_primitive_option_clr module_or_primitive_instance_list ';' { int strength=0; vl_delay *delay=NIL(vl_delay); YYTRACE("module_or_primitive_instantiation: name_of_module_or_primitive module_or_primitive_option_clr module_or_primitive_instance_list ';'"); extract_delay_strength($2, &delay, &strength); lsDestroy($2, NULL); $$ = vl_add_find_mod_prim_instances($1, delay, strength, $3); insert_instances($3, $$); } ; name_of_module_or_primitive : YYIDE { YYTRACE("name_of_module_or_primitive: YYIDE"); $$ = vl_create_id_range(vlStrdup(yyid), NIL(vl_range)); } ; module_or_primitive_option_clr : { YYTRACE("module_or_primitive_option_clr:"); $$ = lsCreate(); } | module_or_primitive_option_clr module_or_primitive_option { lsHandle handle; YYTRACE("module_or_primitive_option_clr: module_or_primitive_option_clr module_or_primitive_option"); lsNewEnd($1, (lsGeneric)$2, &handle); $$ = $1; } ; module_or_primitive_option : drive_strength { YYTRACE("module_or_primitive_option:"); $$ = $1 << 2; } | delay_or_parameter_value_assignment { YYTRACE("module_or_primitive_option: delay"); $$ = (int)($1) | LEAST_SB; } ; delay_or_parameter_value_assignment : '#' YYINUMBER { vl_expr *expr; YYTRACE("delay_or_parameter_value_assignment: '#' YYINUMBER"); expr = vl_create_expr(IntExpr, atoi(yytext), (double)0.0, NIL(void), NIL(void), NIL(void)); $$ = vl_create_delay(expr, NIL(vl_expr), NIL(vl_expr)); } | '#' YYRNUMBER { vl_expr *expr; YYTRACE("delay_or_parameter_value_assignment: '#' YYRNUMBER"); expr = vl_create_expr(IntExpr, 0, atof(yytext), NIL(void), NIL(void), NIL(void)); $$ = vl_create_delay(expr, NIL(vl_expr), NIL(vl_expr)); } | '#' identifier { vl_expr *expr; YYTRACE("delay_or_parameter_value_assignment: '#' identifier"); expr = vl_create_expr(IDExpr, 0, (double)0.0, $2, NIL(void), NIL(void)); $$ = vl_create_delay(expr, NIL(vl_expr), NIL(vl_expr)); } | '#' '(' mintypmax_expression_list ')' { YYTRACE("delay_or_parameter_value_assignment: '#' '(' mintypmax_expression_list ')'"); $$ = vl_create_delay(NIL(vl_expr), NIL(vl_expr), (vl_expr*)$3); } ; module_or_primitive_instance_list : module_or_primitive_instance { lsHandle handle; YYTRACE("module_or_primitive_instance_list: module_or_primitive_instance"); $$ = lsCreate(); lsNewEnd($$, (lsGeneric)$1, &handle); } | module_or_primitive_instance_list ',' module_or_primitive_instance { lsHandle handle; YYTRACE("module_or_primitive_instance_list: module_or_primitive_instance_list ',' module_or_primitive_instance"); lsNewEnd($1, (lsGeneric)$3, &handle); $$ = $1; } ; module_or_primitive_instance : '(' module_connection_list ')' { YYTRACE("module_or_primitive_instance: '(' module_connection_list ')'"); $$ = (typestructPtr)vl_create_mod_prim_inst(NIL(vl_id_range), $2); } | identifier '(' module_connection_list ')' { YYTRACE("module_or_primitive_instance: '(' module_connection_list ')'"); $$ = (typestructPtr)vl_create_mod_prim_inst($1, $3); } ; module_connection_list : module_port_connection_list { YYTRACE("module_connection_list: module_port_connection_list"); } | named_port_connection_list { YYTRACE("module_connection_list: named_port_connection_list"); } ; module_port_connection_list : module_port_connection { lsHandle handle; YYTRACE("module_port_connection_list: module_port_connection"); $$ = lsCreate(); lsNewEnd($$, (lsGeneric)$1, &handle); } | module_port_connection_list ',' module_port_connection { lsHandle handle; YYTRACE("module_port_connection_list: module_port_connection_list ',' module_port_connection"); lsNewEnd($1, (lsGeneric)$3, &handle); $$ = $1; } ; named_port_connection_list : named_port_connection { lsHandle handle; YYTRACE("named_port_connection_list: named_port_connection"); $$ = lsCreate(); lsNewEnd($$, (lsGeneric)$1, &handle); } | named_port_connection_list ',' named_port_connection { lsHandle handle; YYTRACE("named_port_connection_list: named_port_connection_list ',' name_port_connection"); lsNewEnd($1, (lsGeneric)$3, &handle); $$ = $1; } ; module_port_connection : { YYTRACE("module_port_connection:"); $$ = vl_create_port_connect(ModuleConnect, NIL(vl_id_range), NIL(vl_expr)); } | expression { YYTRACE("module_port_connection: expression"); $$ = vl_create_port_connect(ModuleConnect, NIL(vl_id_range), $1); } ; named_port_connection : '.' identifier '(' expression ')' { YYTRACE("named_port_connection: '.' identifier '(' expression ')'"); $$ = vl_create_port_connect(NamedConnect, $2, $4); } ; initial_statement : YYINITIAL {reserve_type_name=0; timed_statement=0;} statement { YYTRACE("initial_statement: YYINITIAL statement"); $$ = vl_create_procstmt(InitialStmt, $3); reserve_type_name=1; if (timed_statement) $$->flags |= TimedInitStmt; } ; always_statement : YYALWAYS {reserve_type_name=0;} statement { YYTRACE("always_statement: YYALWAYS statement"); $$ = vl_create_procstmt(AlwaysStmt, $3); reserve_type_name=1; } ; statement_opt : { YYTRACE("statement_opt:"); $$ = lsCreate(); } | statement { lsHandle handle; YYTRACE("statement_opt: statement"); $$ = lsCreate(); lsNewEnd($$, (lsGeneric)$1, &handle); } ; statement_clr : { YYTRACE("statement_clr:"); $$ = lsCreate(); } | statement_clr statement { lsHandle handle; YYTRACE("statement_clr: statement_clr statement"); lsNewEnd($1, (lsGeneric)$2, &handle); $$ = $1; } ; statement : ';' { YYTRACE("statement: ';'"); $$ = NIL(typestruct); } | assignment ';' { YYTRACE("statement: assignment ';'"); } | YYIF '(' expression ')' statement { YYTRACE("statement: YYIF '(' expression ')' statement"); $$ = (typestructPtr)vl_create_if_else_stmt($3, $5, NIL(typestruct)); } | YYIF '(' expression ')' statement YYELSE statement { YYTRACE("statement: YYIF '(' expression ')' statement YYELSE statement"); $$ = (typestructPtr)vl_create_if_else_stmt($3, $5, $7); } | YYCASE '(' expression ')' case_item_eclr YYENDCASE { YYTRACE("statement: YYCASE '(' expression ')' case_item_eclr YYENDCASE"); $$ = (typestructPtr)vl_create_case_stmt(CaseStmt, $3, $5); } | YYCASEZ '(' expression ')' case_item_eclr YYENDCASE { YYTRACE("statement: YYCASEZ '(' expression ')' case_item_eclr YYENDCASE"); $$ = (typestructPtr)vl_create_case_stmt(CasezStmt, $3, $5); } | YYCASEX '(' expression ')' case_item_eclr YYENDCASE { YYTRACE("statement: YYCASEX '(' expression ')' case_item_eclr YYENDCASE"); $$ = (typestructPtr)vl_create_case_stmt(CasexStmt, $3, $5); } | YYFOREVER statement { YYTRACE("statement: YYFOREVER statement"); $$ = (typestructPtr)vl_create_forever_stmt($2); } | YYREPEAT '(' expression ')' statement { YYTRACE("statement: YYREPEAT '(' expression ')' statement"); $$ = (typestructPtr)vl_create_repeat_stmt($3, $5); } | YYWHILE '(' expression ')' statement { YYTRACE("statement: YYWHILE '(' expression ')' statement"); $$ = (typestructPtr)vl_create_while_stmt($3, $5); } | YYFOR '(' assignment ';' expression ';' assignment ')' statement { YYTRACE("statement: YYFOR '(' assignment ';' expression ';' assignment ')' statement"); $$ = (typestructPtr)vl_create_for_stmt($3, $5, $7, $9); } | delay_control statement { YYTRACE("statement: delay_control statement"); $$ = (typestructPtr)vl_create_delay_control_stmt($1, $2); } | event_control statement { YYTRACE("statement: event_control statement"); $$ = (typestructPtr)vl_create_event_control_stmt($1, $2); } | lvalue type_action '=' delay_control expression ';' { YYTRACE("statement: lvalue '=' delay_control expression ';'"); $$ = (typestructPtr)vl_create_bassign_stmt(DelayBassignStmt, $1, $4, $5); } | lvalue type_action '=' event_control expression ';' { YYTRACE("statement: lvalue '=' event_control expression ';'"); $$ = (typestructPtr)vl_create_bassign_stmt(EventBassignStmt, $1, $4, $5); } | lvalue type_action YYNBASSIGN delay_control expression ';' { YYTRACE("statement: lvalue YYNBASSIGN delay_control expression ';'"); $$ = (typestructPtr)vl_create_bassign_stmt(DelayNbassignStmt, $1, $4, $5); } | lvalue type_action YYNBASSIGN event_control expression ';' { YYTRACE("statement: lvalue YYNBASSIGN event_control expression ';'"); $$ = (typestructPtr)vl_create_bassign_stmt(EventNbassignStmt, $1, $4, $5); } | YYWAIT '(' expression ')' statement { YYTRACE("statement: YYWAIT '(' expression ')' statement"); $$ = (typestructPtr)vl_create_wait_stmt($3, $5); } | YYRIGHTARROW name_of_event ';' { YYTRACE("statement: YYRIGHTARROW name_of_event ';'"); $$ = (typestructPtr)vl_create_send_event_stmt($2); } | seq_block { YYTRACE("statement: seq_block"); } | par_block { YYTRACE("statement: par_block"); } | task_enable { YYTRACE("statement: task_enable"); } | system_task_enable { YYTRACE("statement: system_task_enable"); TODO("statement: system_task_enable"); $$ = NIL(typestruct); } | YYDISABLE YYIDE { $$ = vl_create_id_range(vlStrdup(yyid), NIL(vl_range)); } ';' { YYTRACE("statement: YYDISABLE YYIDE ';'"); $$ = (typestructPtr)vl_create_disable_stmt($3); } | YYASSIGN assignment ';' { YYTRACE("statement: YYASSIGN assignment ';'"); $2->type = AssignStmt; $$ = (typestructPtr)$2; } | YYDEASSIGN lvalue ';' { YYTRACE("statement: YYDEASSIGN lvalue ';'"); $$ = (typestructPtr)vl_create_deassign_stmt($2); } ; assignment : lvalue type_action '=' expression { YYTRACE("assignment: lvalue '=' expression"); associate_symbolic_value($1, $4); $$ = vl_create_bassign_stmt(BassignStmt, $1, NIL(void), $4); if (c_assign && $1->type != ConcatExpr) { vl_id_range *id_sym; if (!st_lookup(vl_currentModule->sig_st, $1->name->name, (char**)&id_sym)) compile_error("continuous assignment to undeclared var"); id_sym->flags |= WireVar; } pop_stack(vl_cur_type_stack, (void **) &aux_st); } | lvalue type_action YYNBASSIGN expression { YYTRACE("assignment: lvalue YYNBASSIGN expression"); associate_symbolic_value($1, $4); $$ = vl_create_bassign_stmt(NbassignStmt, $1, NIL(void), $4); if (c_assign && $1->type != ConcatExpr) { vl_id_range *id_sym; if (!st_lookup(vl_currentModule->sig_st, $1->name->name, (char**)&id_sym)) compile_error("non-blocking assignment to undeclared var"); id_sym->flags |= WireVar; } pop_stack(vl_cur_type_stack, (void **) &aux_st); } ; type_action : { vl_id_range *id_sym; if ($0->type != ConcatExpr) { push_stack(vl_cur_type_stack, aux_st); if (st_lookup(vl_currentModule->sig_st, $0->name->name, &id_sym)) if (id_sym->id_type) aux_st = id_sym->id_type->specifier->u.enum_type->domain_st; else aux_st = NIL(st_table); else aux_st = NIL(st_table); } } ; type_action_expr : { /* Partial patch: b = (v1 == a) ? v1 : v2, where v1 and v2 * are enumerated values still compiled incorrectly. */ vl_id_range *id_sym; if ($-1->type != ConcatExpr) { push_stack(vl_cur_type_stack, aux_st); if ($-1->type == IDExpr) { if (st_lookup(vl_currentModule->sig_st, $-1->u.name->name, &id_sym)) if (id_sym->id_type) aux_st = id_sym->id_type->specifier->u.enum_type->domain_st; else aux_st = NIL(st_table); else aux_st = NIL(st_table); } else aux_st = NIL(st_table); } } ; case_item_eclr : case_item { lsHandle handle; YYTRACE("case_item_eclr: case_item"); $$ = lsCreate(); lsNewEnd($$, (lsGeneric)$1, &handle); } | case_item_eclr case_item { lsHandle handle; YYTRACE("case_item_eclr: case_item_eclr case_item"); lsNewEnd($1, (lsGeneric)$2, &handle); $$ = $1; } ; case_item : expression_list ':' statement { YYTRACE("case_item: expression_list ':' statement"); $$ = vl_create_case_item(CaseItem, $1, $3); } | YYDEFAULT ':' statement { YYTRACE("case_item: YYDEFAULT ':' statement"); $$ = vl_create_case_item(DefaultItem, (lsList)0, $3); } | YYDEFAULT statement { YYTRACE("case_item: YYDEFAULT statement"); $$ = vl_create_case_item(DefaultItem, (lsList)0, $2); } ; seq_block : YYBEGIN statement_clr YYEND { YYTRACE("seq_block: YYBEGIN statement_clr YYEND"); $$ = vl_create_begin_end_stmt(NIL(vl_id_range), LS_NH, $2); } | YYBEGIN ':' name_of_block block_declaration_clr statement_clr YYEND { YYTRACE("seq_block: YYBEGIN ':' name_of_block block_declaration_clr statement_clr YYEND"); $$ = vl_create_begin_end_stmt($3, $4, $5); } ; par_block : YYFORK statement_clr YYJOIN { YYTRACE("par_block: YYFORK statement_clr YYJOIN"); $$ = vl_create_fork_join_stmt(NIL(vl_id_range), LS_NH, $2); TODO("fork/join : dynamic process control"); } | YYFORK ':' name_of_block block_declaration_clr statement_clr YYJOIN { YYTRACE("par_block: YYFORK ':' name_of_block block_declaration_clr statement_clr YYJOIN"); $$ = vl_create_fork_join_stmt($3, $4, $5); TODO("fork/join : dynamic process control"); } ; name_of_block : YYIDE { YYTRACE("name_of_block: YYIDE"); $$ = vl_create_id_range(vlStrdup(yyid), NIL(vl_range)); } ; block_declaration_clr : { YYTRACE("block_declaration_clr:"); $$ = lsCreate(); } | block_declaration_clr block_declaration { lsHandle handle; YYTRACE("block_declaration_clr: block_declaration_clr block_declaration"); lsNewEnd($1, (lsGeneric)$2, &handle); $$ = $1; } ; block_declaration : parameter_declaration { YYTRACE("block_declaration: parameter_declaration"); $$ = (typestructPtr)$1; } | reg_declaration { YYTRACE("block_declaration: reg_declaration"); $$ = (typestructPtr)$1; } | integer_declaration { YYTRACE("block_declaration: integer_declaration"); $$ = (typestructPtr)$1; } | real_declaration { YYTRACE("block_declaration: real_declaration"); $$ = (typestructPtr)$1; } | time_declaration { YYTRACE("block_delcaration: time_declaration"); $$ = (typestructPtr)$1; } | event_declaration { YYTRACE("block_declaration: event_declaration"); $$ = (typestructPtr)$1; } ; task_enable : YYIDE { $$ = vl_create_id_range(vlStrdup(yyid), NIL(vl_range)); } ';' { YYTRACE("task_enable: YYIDE ';'"); $$ = vl_create_task_enable_stmt(TaskEnableStmt, $2, (lsList)0); } | YYIDE { $$ = vl_create_id_range(vlStrdup(yyid), NIL(vl_range)); } '(' expression_list ')' ';' { YYTRACE("task_enable: YYIDE '(' expression_list ')' ';'"); $$ = vl_create_task_enable_stmt(TaskEnableStmt, $2, $4); } ; system_task_enable : name_of_system_task ';' { YYTRACE("system_task_enable: name_of_system_task ';'"); } | name_of_system_task '(' expression_list ')' ';' { YYTRACE("system_task_enable: name_of_system_task '(' expression_list ')'"); } ; name_of_system_task : system_identifier { YYTRACE("name_of_system_task: system_identifier"); } ; specify_block : YYSPECIFY specify_item_clr YYENDSPECIFY { YYTRACE("specify_block: YYSPECIFY specify_item_clr YYENDSPECIFY"); TODO("specify_block: YYSPECIFY specify_item_clr YYENDSPECIFY"); } ; specify_item_clr : | specify_item_clr specify_item ; specify_item : specparam_declaration | path_declaration | level_sensitive_path_declaration | edge_sensitive_path_declaration | system_timing_check ; specparam_declaration : YYSPECPARAM assignment_list ';' ; path_declaration : path_description '=' path_delay_value ';' ; path_description : '(' specify_terminal_descriptor YYLEADTO specify_terminal_descriptor ')' | '(' path_list YYALLPATH path_list_or_edge_sensitive_path_list ')' ; path_list : specify_terminal_descriptor | path_list ',' specify_terminal_descriptor ; specify_terminal_descriptor : YYIDE | YYIDE '[' expression ']' | YYIDE '[' expression ';' expression ']' ; path_list_or_edge_sensitive_path_list : path_list | '(' path_list ',' specify_terminal_descriptor polarity_operator YYCONDITIONAL expression ')' ; path_delay_value : path_delay_expression | '(' path_delay_expression ',' path_delay_expression ')' | '(' path_delay_expression ',' path_delay_expression ',' path_delay_expression ')' | '(' path_delay_expression ',' path_delay_expression ',' path_delay_expression ',' path_delay_expression ',' path_delay_expression ',' path_delay_expression ')' ; path_delay_expression : expression { } ; system_timing_check : YYsysSETUP '(' ')' ';' ; level_sensitive_path_declaration : YYIF '(' expression ')' '(' specify_terminal_descriptor polarity_operator_opt YYLEADTO spec_terminal_desptr_or_edge_sensitive_spec_terminal_desptr | YYIF '(' expression ')' '(' path_list ',' specify_terminal_descriptor polarity_operator_opt YYALLPATH path_list ')' path_list '=' path_delay_value ';' ; spec_terminal_desptr_or_edge_sensitive_spec_terminal_desptr : specify_terminal_descriptor ')' path_list '=' path_delay_value ';' | '(' specify_terminal_descriptor polarity_operator YYCONDITIONAL expression ')' ')' '=' path_delay_value ';' ; polarity_operator_opt : | polarity_operator ; polarity_operator : '+' | '-' ; edge_sensitive_path_declaration : '(' specify_terminal_descriptor YYLEADTO '(' specify_terminal_descriptor polarity_operator YYCONDITIONAL expression ')' ')' '=' path_delay_value ';' | '(' edge_identifier specify_terminal_descriptor YYLEADTO '(' specify_terminal_descriptor polarity_operator YYCONDITIONAL expression ')' ')' '=' path_delay_value ';' | '(' edge_identifier specify_terminal_descriptor YYALLPATH '(' path_list ',' specify_terminal_descriptor polarity_operator YYCONDITIONAL expression ')' ')' '=' path_delay_value ';' | YYIF '(' expression ')' '(' specify_terminal_descriptor YYALLPATH '(' path_list ',' specify_terminal_descriptor polarity_operator YYCONDITIONAL expression ')' ')' '=' path_delay_value ';' | YYIF '(' expression ')' '(' edge_identifier specify_terminal_descriptor YYLEADTO '(' specify_terminal_descriptor polarity_operator YYCONDITIONAL expression ')' ')' '=' path_delay_value ';' | YYIF '(' expression ')' '(' edge_identifier specify_terminal_descriptor YYALLPATH '(' path_list ',' specify_terminal_descriptor polarity_operator YYCONDITIONAL expression ')' ')' '=' path_delay_value ';' ; edge_identifier : YYPOSEDGE | YYNEGEDGE ; lvalue : identifier { YYTRACE("lvalue: YYIDE"); $$ = vl_create_lval(IDExpr, $1, NIL(vl_range), (lsList)0); } | identifier '[' expression ']' { YYTRACE("lvalue: YYIDE '[' expression ']'"); $$ = vl_create_lval(BitSelExpr, $1, vl_create_range($3, NIL(vl_expr)), (lsList)0); } | identifier '[' expression ':' expression ']' { YYTRACE("lvalue: YYIDE'[' expression ':' expression ']'"); $$ = vl_create_lval(PartSelExpr, $1, vl_create_range($3, $5), (lsList)0); } | concatenation { YYTRACE("lvalue: concatenation"); $$ = vl_create_lval(ConcatExpr, NIL(vl_id_range), NIL(vl_range), $1); } ; mintypmax_expression_list : mintypmax_expression { lsHandle handle; YYTRACE("mintypmax_expression_list: mintypmax_expression"); $$ = lsCreate(); lsNewEnd($$, (lsGeneric)$1, &handle); } | mintypmax_expression_list ',' mintypmax_expression { lsHandle handle; YYTRACE("mintypmax_expression_list: mintypmax_expression_list ',' mintypmax_expression"); lsNewEnd($1, (lsGeneric)$3, &handle); $$ = $1; } ; mintypmax_expression : expression { YYTRACE("mintypmax_expression: expression"); $$ = vl_create_expr(MinTypMaxExpr, 0, (double)0.0, $1, NIL(vl_expr), NIL(vl_expr)); } | expression ':' expression { YYTRACE("mintypmax_expression: expression ':' expression"); $$ = vl_create_expr(MinTypMaxExpr, 0, (double)0.0, $1, $3, NIL(vl_expr)); } | expression ':' expression ':' expression { YYTRACE("mintypmax_expression: expression ':' expression ':' expression"); $$ = vl_create_expr(MinTypMaxExpr, 0, (double)0.0, $1, $3, $5); } ; expression_list : expression { lsHandle handle; YYTRACE("expression_list: expression"); $$ = lsCreate(); lsNewEnd($$, (lsGeneric)$1, &handle); } | expression_list ',' expression { lsHandle handle; YYTRACE("expression_list: expression_list ',' expression"); $$ = lsCreate(); lsNewEnd($1, (lsGeneric)$3, &handle); $$ = $1; } ; expression : primary { YYTRACE("expression: primary"); } | '+' primary %prec YYUNARYOPERATOR { YYTRACE("expression: '+' primary %prec YYUNARYOPERATOR"); $$ = vl_create_expr(UplusExpr, 0, (double)0.0, $2, NIL(vl_expr), NIL(vl_expr)); } | '-' primary %prec YYUNARYOPERATOR { YYTRACE("expression: '-' primary %prec YYUNARYOPERATOR"); $$ = vl_create_expr(UminusExpr, 0, (double)0.0, $2, NIL(vl_expr), NIL(vl_expr)); } | '!' primary %prec YYUNARYOPERATOR { YYTRACE("expression: '!' primary %prec YYUNARYOPERATOR"); $$ = vl_create_expr(UnotExpr, 0, (double)0.0, $2, NIL(vl_expr), NIL(vl_expr)); } | '~' primary %prec YYUNARYOPERATOR { YYTRACE("expression: '~' primary %prec YYUNARYOPERATOR"); $$ = vl_create_expr(UcomplExpr, 0, (double)0.0, $2, NIL(vl_expr), NIL(vl_expr)); } | '&' primary %prec YYUNARYOPERATOR { YYTRACE("expression: '&' primary %prec YYUNARYOPERATOR"); $$ = vl_create_expr(UandExpr, 0, (double)0.0, $2, NIL(vl_expr), NIL(vl_expr)); } | '|' primary %prec YYUNARYOPERATOR { YYTRACE("expression: '|' primary %prec YYUNARYOPERATOR"); $$ = vl_create_expr(UorExpr, 0, (double)0.0, $2, NIL(vl_expr), NIL(vl_expr)); } | '^' primary %prec YYUNARYOPERATOR { YYTRACE("expression: '^' primary %prec YYUNARYOPERATOR"); $$ = vl_create_expr(UxorExpr, 0, (double)0.0, $2, NIL(vl_expr), NIL(vl_expr)); } | YYLOGNAND primary %prec YYUNARYOPERATOR { YYTRACE("expression: YYLOGNAND primary %prec YYUNARYOPERATOR"); $$ = vl_create_expr(UnandExpr, 0, (double)0.0, $2, NIL(vl_expr), NIL(vl_expr)); } | YYLOGNOR primary %prec YYUNARYOPERATOR { YYTRACE("expression: YYLOGNOR primary %prec YYUNARYOPERATOR"); $$ = vl_create_expr(UnorExpr, 0, (double)0.0, $2, NIL(vl_expr), NIL(vl_expr)); } | YYLOGXNOR primary %prec YYUNARYOPERATOR { YYTRACE("expression: YYLOGXNOR primary %prec YYUNARYOPERATOR"); $$ = vl_create_expr(UxnorExpr, 0, (double)0.0, $2, NIL(vl_expr), NIL(vl_expr)); } | expression '+' expression { YYTRACE("expression: expression '+' expression"); $$ = vl_create_expr(BplusExpr, 0, (double)0.0, $1, $3, NIL(vl_expr)); } | expression '-' expression { YYTRACE("expression: expressio '-' expression"); $$ = vl_create_expr(BminusExpr, 0, (double)0.0, $1, $3, NIL(vl_expr)); } | expression '*' expression { YYTRACE("expression: expression '*' expression"); $$ = vl_create_expr(BtimesExpr, 0, (double)0.0, $1, $3, NIL(vl_expr)); } | expression '/' expression { YYTRACE("expression: expression '/' expression"); $$ = vl_create_expr(BdivExpr, 0, (double)0.0, $1, $3, NIL(vl_expr)); } | expression '%' expression { YYTRACE("expression: expression '%' expression"); $$ = vl_create_expr(BremExpr, 0, (double)0.0, $1, $3, NIL(vl_expr)); } | expression YYLOGEQUALITY type_action_expr expression { YYTRACE("expression: expression YYLOGEQUALITY expression"); $$ = vl_create_expr(Beq2Expr, 0, (double)0.0, $1, $4, NIL(vl_expr)); pop_stack(vl_cur_type_stack, (void **) &aux_st); } | expression YYLOGINEQUALITY type_action_expr expression { YYTRACE("expression: expression YYLOGINEQUALITY expression"); $$ = vl_create_expr(Bneq2Expr, 0, (double)0.0, $1, $4, NIL(vl_expr)); pop_stack(vl_cur_type_stack, (void **) &aux_st); } | expression YYCASEEQUALITY type_action_expr expression { YYTRACE("expression: expression YYCASEEQUALITY expression"); $$ = vl_create_expr(Beq3Expr, 0, (double)0.0, $1, $4, NIL(vl_expr)); pop_stack(vl_cur_type_stack, (void **) &aux_st); } | expression YYCASEINEQUALITY type_action_expr expression { YYTRACE("expression: expression YYCASEINEQUALITY expression"); $$ = vl_create_expr(Bneq3Expr, 0, (double)0.0, $1, $4, NIL(vl_expr)); pop_stack(vl_cur_type_stack, (void **) &aux_st); } | expression YYLOGAND expression { YYTRACE("expression: expression YYLOGAND expression"); $$ = vl_create_expr(BlandExpr, 0, (double)0.0, $1, $3, NIL(vl_expr)); } | expression YYLOGOR expression { YYTRACE("expression: expression YYLOGOR expression"); $$ = vl_create_expr(BlorExpr, 0, (double)0.0, $1, $3, NIL(vl_expr)); } | expression '<' expression { YYTRACE("expression: expression '<' expression"); $$ = vl_create_expr(BltExpr, 0, (double)0.0, $1, $3, NIL(vl_expr)); } | expression '>' expression { YYTRACE("expression: expression '>' expression"); $$ = vl_create_expr(BgtExpr, 0, (double)0.0, $1, $3, NIL(vl_expr)); } | expression '&' expression { YYTRACE("expression: expression '&' expression"); $$ = vl_create_expr(BandExpr, 0, (double)0.0, $1, $3, NIL(vl_expr)); } | expression '|' expression { YYTRACE("expression: expression '|' expression"); $$ = vl_create_expr(BorExpr, 0, (double)0.0, $1, $3, NIL(vl_expr)); } | expression '^' expression { YYTRACE("expression: expression '^' expression"); $$ = vl_create_expr(BxorExpr, 0, (double)0.0, $1, $3, NIL(vl_expr)); } | expression YYLEQ expression { YYTRACE("expression: expression YYLEQ expression"); $$ = vl_create_expr(BleExpr, 0, (double)0.0, $1, $3, NIL(vl_expr)); } | expression YYNBASSIGN expression { YYTRACE("expression: expression YYLEQ expression"); $$ = vl_create_expr(BleExpr, 0, (double)0.0, $1, $3, NIL(vl_expr)); } | expression YYGEQ expression { YYTRACE("expression: expression YYGEQ expression"); $$ = vl_create_expr(BgeExpr, 0, (double)0.0, $1, $3, NIL(vl_expr)); } | expression YYLSHIFT expression { YYTRACE("expression: expression YYLSHIFT expression"); $$ = vl_create_expr(BlshiftExpr, 0, (double)0.0, $1, $3, NIL(vl_expr)); } | expression YYRSHIFT expression { YYTRACE("expression: expression YYRSHIFT expression"); $$ = vl_create_expr(BrshiftExpr, 0, (double)0.0, $1, $3, NIL(vl_expr)); } | expression YYLOGXNOR expression { YYTRACE("expression: expression YYLOGXNOR expression"); $$ = vl_create_expr(BxnorExpr, 0, (double)0.0, $1, $3, NIL(vl_expr)); } | expression '?' expression ':' expression { YYTRACE("expression: expression '?' expression ':' expression"); $$ = vl_create_expr(TcondExpr, 0, (double)0.0, $1, $3, $5); } | YYSTRING { YYTRACE("expression: YYSTRING"); $$ = vl_create_expr(StringExpr, 0, (double)0.0, vlStrdup(yytext), NIL(vl_expr), NIL(vl_expr)); TODO(" is not supported in generated FSMs"); } ; primary : YYINUMBER { YYTRACE("primary: YYINUMBER"); if (strchr(yytext, '\'')) { $$ = vl_create_expr(BitExpr, 0, (double)0.0, (void*)bexp1, (void*)bexp0, (void*)vlStrdup(brep)); } else { $$ = vl_create_expr(IntExpr, atoi(yytext), (double)0.0, NIL(vl_expr), NIL(vl_expr), NIL(vl_expr)); } } | YYRNUMBER { YYTRACE("primary: YYRNUMBER"); $$ = vl_create_expr(RealExpr, 0, atof(yytext), NIL(vl_expr), NIL(vl_expr), NIL(vl_expr)); } | identifier { YYTRACE("primary: identifier"); $$ = vl_create_expr(IDExpr, 0, (double)0.0, $1, NIL(vl_expr), NIL(vl_expr)); } | identifier '[' expression ']' { YYTRACE("primary: identifier '[' expression ']'"); $$ = vl_create_expr(BitSelExpr, 0, (double)0.0, vl_create_id_range($1->name, vl_create_range($3, NIL(vl_expr))), NIL(vl_expr), NIL(vl_expr)); } | identifier '[' expression ':' expression ']' { YYTRACE("primary: identifier '[' expression ':' expression ']'"); $$ = vl_create_expr(BitSelExpr, 0, (double)0.0, vl_create_id_range($1->name, vl_create_range($3, $5)), NIL(vl_expr), NIL(vl_expr)); } | concatenation { YYTRACE("primary: concatenation"); $$ = vl_create_expr(ConcatExpr, 0, (double)0.0, $1, NIL(vl_expr), NIL(vl_expr)); } | multiple_concatenation { YYTRACE("primary: multiple_concatenatin"); $$ = vl_create_expr(ConcatExpr, 0, (double)0.0, $1->concat, $1->rep, NIL(vl_expr)); vl_chk_free((char*)$1); } | function_call { YYTRACE("primary: function_call"); } | '(' mintypmax_expression ')' { YYTRACE("primary: '(' mintypmax_expression ')'"); $$ = $2; } | YYsysID '(' nondeterminism_list ')' { YYTRACE("primary: YYsysID '(' nondeterminism_list ')'"); TODO("System task (\"$sys-task(...)\")"); } | YYsysND '(' nondeterminism_list ')' { $$ = vl_create_expr(NondExpr, 0, (double)0.0, $3, NIL(vl_expr), NIL(vl_expr)); if ($$ == NIL(vl_expr)) yyerror("unsynchronized nondeterministic wire"); } ; nondeterminism_list : event_control { YYTRACE("nondeterminism_list : event_control"); $$ = lsCreate(); lsNewEnd($$, (lsGeneric)$1, 0); } | expression { YYTRACE("nondeterminism_list : expression"); $$ = lsCreate(); lsNewEnd($$, (lsGeneric)$1, 0); } | nondeterminism_list ',' event_control { YYTRACE("nondeterminism_list : nondeterminism_list ',' event_control"); lsNewEnd($$, (lsGeneric)$3, 0); } | nondeterminism_list ',' expression { YYTRACE("nondeterminism_list : nondeterminism_list ',' expression"); lsNewEnd($$, (lsGeneric)$3, 0); } ; concatenation : '{' expression_list '}' { YYTRACE("concatenation: '{' expression_list '}'"); $$ = $2; } ; multiple_concatenation : '{' expression '{' expression_list '}' '}' { YYTRACE("multiple_concatenation: '{' expression '{' expression_list '}' '}'"); $$ = vl_create_mconcat($2,$4); } ; function_call : identifier '(' expression_list ')' { YYTRACE("function_call: identifier '(' expression_list ')'"); $$ = vl_create_expr(FuncExpr, 0, (double)0.0, $1, $3, NIL(void)); } ; system_identifier : YYsysID ; identifier : YYIDE { YYTRACE("identifier: YYIDE"); $$ = vl_create_id_range(vlStrdup(yyid), NIL(vl_range)); } | identifier '.' YYIDE { YYTRACE("identifier: identifier '.' YYIDE"); TODO("identifier: identifier '.' YYIDE --> cross hierarchy access"); } ; delay_opt : { YYTRACE("delay_opt:"); $$ = NIL(vl_delay); } | delay { YYTRACE("delay_opt: delay"); } ; delay : '#' YYINUMBER { vl_expr *expr; YYTRACE("delay: '#' YYINUMBER"); expr = vl_create_expr(IntExpr, atoi(yytext), (double)0.0, NIL(void), NIL(void), NIL(void)); $$ = vl_create_delay(expr, NIL(vl_expr), NIL(vl_expr)); } | '#' YYRNUMBER { vl_expr *expr; YYTRACE("delay: '#' YYRNUMBER"); expr = vl_create_expr(IntExpr, 0, atof(yytext), NIL(void), NIL(void), NIL(void)); $$ = vl_create_delay(expr, NIL(vl_expr), NIL(vl_expr)); } | '#' identifier { vl_expr *expr; YYTRACE("delay: '#' identifier"); expr = vl_create_expr(IDExpr, 0, (double)0.0, $2, NIL(void), NIL(void)); $$ = vl_create_delay(expr, NIL(vl_expr), NIL(vl_expr)); } | '#' '(' mintypmax_expression ')' { YYTRACE("delay: '#' '(' mintypmax_expression ')'"); $$ = vl_create_delay($3, NIL(vl_expr), NIL(vl_expr)); } | '#' '(' mintypmax_expression ',' mintypmax_expression ')' { YYTRACE("delay: '#' '(' mintypmax_expression ',' mintypmax_expression ')'"); $$ = vl_create_delay($3, $5, NIL(vl_expr)); } | '#' '(' mintypmax_expression ',' mintypmax_expression ',' mintypmax_expression ')' { YYTRACE("delay: '#' '(' mintypmax_expression ',' mintypmax_expression ',' mintypmax_expression ')'"); $$ = vl_create_delay($3, $5, $7); } ; delay_control : '#' YYINUMBER { vl_expr *expr; YYTRACE("delay_control: '#' YYINUMBER"); expr = vl_create_expr(IntExpr, atoi(yytext), (double)0.0, NIL(void), NIL(void), NIL(void)); $$ = vl_create_delay(expr, NIL(vl_expr), NIL(vl_expr)); timed_statement = 1; } | '#' YYRNUMBER { vl_expr *expr; YYTRACE("delay_control: '#' YYRNUMBER"); expr = vl_create_expr(RealExpr, 0, atof(yytext), NIL(void), NIL(void), NIL(void)); $$ = vl_create_delay(expr, NIL(vl_expr), NIL(vl_expr)); timed_statement = 1; } | '#' identifier { vl_expr *expr; YYTRACE("delay_control: '#' identifier"); expr = vl_create_expr(IDExpr, 0, (double)0.0, $2, NIL(void), NIL(void)); $$ = vl_create_delay(expr, NIL(vl_expr), NIL(vl_expr)); timed_statement = 1; } | '#' '(' mintypmax_expression_list ')' { YYTRACE("delay_control: '#' '(' mintypmax_expression ')'"); $$ = vl_create_delay((vl_expr*)$3, NIL(vl_expr), (vl_expr*)$3); timed_statement = 1; } ; event_control : '@' identifier { vl_exprPtr expr; YYTRACE("event_control: '@' identifier"); expr = vl_create_expr(IDExpr, 0, (double)0.0, $2, NIL(vl_expr), NIL(vl_expr)); $$ = vl_create_event_expr(EventExpr, expr); timed_statement = 1; } | '@' '(' event_expression ')' { YYTRACE("event_control: '@' '(' event_expression ')'"); $$ = $3; timed_statement = 1; } | '@' '(' ored_event_expression ')' { YYTRACE("event_control: '@' '(' ored_event_expression ')'"); $$ = $3; timed_statement = 1; } ; event_expression : expression { YYTRACE("event_expression: expression"); $$ = vl_create_event_expr(EventExpr, $1); } | YYPOSEDGE expression { YYTRACE("event_expression: YYPOSEDGE expression"); $$ = vl_create_event_expr(PosedgeEventExpr, $2); } | YYNEGEDGE expression { YYTRACE("event_expression: YYNEGEDGE expression"); $$ = vl_create_event_expr(NegedgeEventExpr, $2); } | YYEDGE expression { YYTRACE("event_expression: YYEDGE expression"); $$ = vl_create_event_expr(EdgeEventExpr, $2); } ; ored_event_expression : event_expression YYOR event_expression { lsList event_list; YYTRACE("ored_event_expression: event_expression YYOR event_expression"); event_list = lsCreate(); lsNewEnd(event_list, (lsGeneric)$1, LS_NH); lsNewEnd(event_list, (lsGeneric)$3, LS_NH); $$ = vl_create_event_expr(OrEventExpr, NIL(vl_expr)); $$->list = event_list; } | ored_event_expression YYOR event_expression { YYTRACE("ored_event_expression: ored_event_expression YYOR event_expression"); lsNewEnd($1->list, (lsGeneric)$3, LS_NH); $$ = $1; } ; %% void yyerror(str) char *str; { fprintf(stderr, "%s : (line:%d;file:%s) token :'%s', ", str, yylineno, vl_filename, #ifndef _snake (yytypetoken[0])?yytypetoken:yytext #else (yytypetoken[0])?yytypetoken:(char*)yytext #endif ); fprintf(stderr, "yacc token : '%s'\n", yytext); if (vl_currentModule) fprintf(stderr, "unexpected token '%s' seen in module '%s'\n", #ifndef _snake (yytypetoken[0])?yytypetoken:yytext, #else (yytypetoken[0])?yytypetoken:(char*)yytext, #endif vl_currentModule->name->name); exit (1); }