diff --git a/ivtest/ivltests/sv_class_new_init.v b/ivtest/ivltests/sv_class_new_init.v new file mode 100644 index 000000000..7ff5cbb0f --- /dev/null +++ b/ivtest/ivltests/sv_class_new_init.v @@ -0,0 +1,29 @@ +// Check that the class new initializer can be used for all sorts for variable +// declarations + +package P; + class C; + endclass + C c = new; +endpackage + +module test; + + class C; + task check; + $display("PASSED"); + endtask + endclass + + class D; + C c = new; + endclass + + C c = new; + + initial begin + static C c = new; + c.check(); + end + +endmodule diff --git a/ivtest/regress-sv.list b/ivtest/regress-sv.list index 716582999..c4b8b163c 100644 --- a/ivtest/regress-sv.list +++ b/ivtest/regress-sv.list @@ -436,6 +436,7 @@ sv_class22 normal,-g2009 ivltests sv_class23 normal,-g2009 ivltests sv_class24 normal,-g2009 ivltests sv_class_extends_scoped normal,-g2009 ivltests +sv_class_new_init normal,-g2009 ivltests sv_darray1 normal,-g2009 ivltests sv_darray2 normal,-g2009 ivltests sv_darray3 normal,-g2009 ivltests diff --git a/ivtest/regress-vlog95.list b/ivtest/regress-vlog95.list index 069831104..1c66d40f6 100644 --- a/ivtest/regress-vlog95.list +++ b/ivtest/regress-vlog95.list @@ -364,6 +364,7 @@ sv_class22 CE,-g2009 ivltests sv_class23 CE,-g2009 ivltests sv_class24 CE,-g2009 ivltests sv_class_extends_scoped CE,-g2009 ivltests +sv_class_new_init CE,-g2009 ivltests sv_end_label CE,-g2009 ivltests # Also generate sv_foreach2 CE,-g2009,-pallowsigned=1 ivltests sv_foreach3 CE,-g2009 ivltests diff --git a/parse.y b/parse.y index 8af33f0b9..4ddf96132 100644 --- a/parse.y +++ b/parse.y @@ -439,7 +439,6 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vector*statement_list; - net_decl_assign_t*net_decl_assign; enum_type_t*enum_type; decl_assignment_t*decl_assignment; @@ -604,13 +603,14 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vector udp_initial udp_init_opt %type udp_initial_expr_opt -%type register_variable net_variable event_variable label_opt class_declaration_endlabel_opt +%type net_variable event_variable label_opt class_declaration_endlabel_opt %type block_identifier_opt -%type register_variable_list net_variable_list event_variable_list +%type net_variable_list event_variable_list %type list_of_identifiers loop_variables %type list_of_port_identifiers list_of_variable_port_identifiers -%type net_decl_assign net_decl_assigns +%type net_decl_assigns +%type net_decl_assign %type port port_opt port_reference port_reference_list %type port_declaration @@ -645,6 +645,7 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vector assignment_pattern expression expr_mintypmax %type expr_primary_or_typename expr_primary %type class_new dynamic_array_new let_default_opt +%type var_decl_initializer_opt %type inc_or_dec_expression inside_expression lpvalue %type branch_probe_expression streaming_concatenation %type delay_value delay_value_simple @@ -1182,7 +1183,7 @@ data_declaration /* IEEE1800-2005: A.2.1.3 */ data_type = new vector_type_t(IVL_VT_LOGIC, false, 0); FILE_NAME(data_type, @2); } - pform_makewire(@2, 0, str_strength, $3, NetNet::IMPLICIT_REG, data_type); + pform_makewire(@2, 0, str_strength, $3, NetNet::IMPLICIT_REG, data_type, $1); } | attribute_list_opt K_event event_variable_list ';' { if ($3) pform_make_events($3, @2.text, @2.first_line); @@ -1660,7 +1661,7 @@ loop_statement /* IEEE1800-2005: A.6.8 */ decl_assignment_t*tmp_assign = new decl_assignment_t; tmp_assign->name = lex_strings.make($4); assign_list.push_back(tmp_assign); - pform_makewire(@4, 0, str_strength, &assign_list, NetNet::REG, $3); + pform_make_var(@4, &assign_list, $3); } statement_or_null { pform_name_t tmp_hident; @@ -1767,7 +1768,6 @@ loop_statement /* IEEE1800-2005: A.6.8 */ ; -/* TODO: Replace register_variable_list with list_of_variable_decl_assignments. */ list_of_variable_decl_assignments /* IEEE1800-2005 A.2.3 */ : variable_decl_assignment { std::list*tmp = new std::list; @@ -1781,37 +1781,29 @@ list_of_variable_decl_assignments /* IEEE1800-2005 A.2.3 */ } ; +var_decl_initializer_opt + : '=' expression { $$ = $2; } + | '=' class_new { $$ = $2; } + | '=' dynamic_array_new { $$ = $2; } + | { $$ = 0; } + ; + variable_decl_assignment /* IEEE1800-2005 A.2.3 */ - : IDENTIFIER dimensions_opt - { decl_assignment_t*tmp = new decl_assignment_t; + : IDENTIFIER dimensions_opt var_decl_initializer_opt + { if ($3 && pform_peek_scope()->var_init_needs_explicit_lifetime() + && (var_lifetime == LexicalScope::INHERITED)) { + cerr << @1 << ": warning: Static variable initialization requires " + "explicit lifetime in this context." << endl; + warn_count += 1; + } + + decl_assignment_t*tmp = new decl_assignment_t; tmp->name = lex_strings.make($1); if ($2) { tmp->index = *$2; delete $2; } - delete[]$1; - $$ = tmp; - } - | IDENTIFIER '=' expression - { decl_assignment_t*tmp = new decl_assignment_t; - tmp->name = lex_strings.make($1); - tmp->expr .reset($3); - delete[]$1; - $$ = tmp; - } - | IDENTIFIER '=' class_new - { decl_assignment_t*tmp = new decl_assignment_t; - tmp->name = lex_strings.make($1); - tmp->expr .reset($3); - delete[]$1; - $$ = tmp; - } - | IDENTIFIER dimensions '=' dynamic_array_new - { decl_assignment_t*tmp = new decl_assignment_t; - tmp->name = lex_strings.make($1); - tmp->index = *$2; - tmp->expr .reset($4); - delete $2; + tmp->expr.reset($3); delete[]$1; $$ = tmp; } @@ -2682,21 +2674,22 @@ block_item_decl /* variable declarations. Note that data_type can be 0 if we are recovering from an error. */ - : data_type register_variable_list ';' - { if ($1) pform_set_data_type(@1, $1, $2, NetNet::REG, attributes_in_context); + : data_type list_of_variable_decl_assignments ';' + { if ($1) pform_make_var(@1, $2, $1, attributes_in_context); } - | variable_lifetime data_type register_variable_list ';' - { if ($2) pform_set_data_type(@2, $2, $3, NetNet::REG, attributes_in_context); + | variable_lifetime data_type list_of_variable_decl_assignments ';' + { if ($2) pform_make_var(@2, $3, $2, attributes_in_context); var_lifetime = LexicalScope::INHERITED; } - | K_reg data_type register_variable_list ';' - { if ($2) pform_set_data_type(@2, $2, $3, NetNet::REG, attributes_in_context); + /* The extra `reg` is not valid (System)Verilog, this is a iverilog extension. */ + | K_reg data_type list_of_variable_decl_assignments ';' + { if ($2) pform_make_var(@2, $3, $2, attributes_in_context); } - | variable_lifetime K_reg data_type register_variable_list ';' - { if ($3) pform_set_data_type(@3, $3, $4, NetNet::REG, attributes_in_context); + | variable_lifetime K_reg data_type list_of_variable_decl_assignments ';' + { if ($3) pform_make_var(@3, $4, $3, attributes_in_context); var_lifetime = LexicalScope::INHERITED; } @@ -4999,12 +4992,8 @@ module_item data_type = new vector_type_t(IVL_VT_LOGIC, false, 0); FILE_NAME(data_type, @2); } - pform_makewire(@2, $4, str_strength, $5, $2, data_type); - if ($1) { - yywarn(@2, "Attributes are not supported on net declaration " - "assignments and will be discarded."); - delete $1; - } + pform_makewire(@2, $4, str_strength, $5, $2, data_type, $1); + delete $1; } /* This form doesn't have the range, but does have strengths. This @@ -5016,22 +5005,14 @@ module_item data_type = new vector_type_t(IVL_VT_LOGIC, false, 0); FILE_NAME(data_type, @2); } - pform_makewire(@2, 0, $4, $5, $2, data_type); - if ($1) { - yywarn(@2, "Attributes are not supported on net declaration " - "assignments and will be discarded."); - delete $1; - } + pform_makewire(@2, 0, $4, $5, $2, data_type, $1); + delete $1; } | attribute_list_opt K_wreal net_decl_assigns ';' { real_type_t*data_type = new real_type_t(real_type_t::REAL); - pform_makewire(@2, 0, str_strength, $3, NetNet::WIRE, data_type); - if ($1) { - yywarn(@2, "Attributes are not supported on net declaration " - "assignments and will be discarded."); - delete $1; - } + pform_makewire(@2, 0, str_strength, $3, NetNet::WIRE, data_type, $1); + delete $1; } | K_trireg charge_strength_opt dimensions_opt delay3_opt list_of_identifiers ';' @@ -5539,10 +5520,9 @@ generate_block net_decl_assign : IDENTIFIER '=' expression - { net_decl_assign_t*tmp = new net_decl_assign_t; - tmp->next = tmp; + { decl_assignment_t*tmp = new decl_assignment_t; tmp->name = lex_strings.make($1); - tmp->expr = $3; + tmp->expr.reset($3); delete[]$1; $$ = tmp; } @@ -5550,14 +5530,15 @@ net_decl_assign net_decl_assigns : net_decl_assigns ',' net_decl_assign - { net_decl_assign_t*tmp = $1; - $3->next = tmp->next; - tmp->next = $3; - $$ = tmp; - } + { std::list*tmp = $1; + tmp->push_back($3); + $$ = tmp; + } | net_decl_assign - { $$ = $1; - } + { std::list*tmp = new std::list; + tmp->push_back($1); + $$ = tmp; + } ; net_type @@ -5996,64 +5977,6 @@ dimensions } ; - /* The register_variable rule is matched only when I am parsing - variables in a "reg" definition. I therefore know that I am - creating registers and I do not need to let the containing rule - handle it. The register variable list simply packs them together - so that bit ranges can be assigned. */ -register_variable - : IDENTIFIER dimensions_opt - { perm_string name = lex_strings.make($1); - pform_makewire(@1, name, NetNet::REG, - NetNet::NOT_A_PORT, IVL_VT_NO_TYPE, 0); - pform_set_reg_idx(name, $2); - $$ = $1; - } - | IDENTIFIER dimensions_opt '=' expression - { if (pform_peek_scope()->var_init_needs_explicit_lifetime() - && (var_lifetime == LexicalScope::INHERITED)) { - cerr << @3 << ": warning: Static variable initialization requires " - "explicit lifetime in this context." << endl; - warn_count += 1; - } - perm_string name = lex_strings.make($1); - pform_makewire(@1, name, NetNet::REG, - NetNet::NOT_A_PORT, IVL_VT_NO_TYPE, 0); - pform_set_reg_idx(name, $2); - pform_make_var_init(@1, name, $4); - $$ = $1; - } - | IDENTIFIER dimensions_opt '=' dynamic_array_new - { if (pform_peek_scope()->var_init_needs_explicit_lifetime() - && (var_lifetime == LexicalScope::INHERITED)) { - cerr << @3 << ": warning: Static variable initialization requires " - "explicit lifetime in this context." << endl; - warn_count += 1; - } - perm_string name = lex_strings.make($1); - pform_makewire(@1, name, NetNet::REG, - NetNet::NOT_A_PORT, IVL_VT_NO_TYPE, 0); - pform_set_reg_idx(name, $2); - pform_make_var_init(@1, name, $4); - $$ = $1; - } - ; - -register_variable_list - : register_variable - { std::list*tmp = new std::list; - tmp->push_back(lex_strings.make($1)); - $$ = tmp; - delete[]$1; - } - | register_variable_list ',' register_variable - { std::list*tmp = $1; - tmp->push_back(lex_strings.make($3)); - $$ = tmp; - delete[]$3; - } - ; - net_variable : IDENTIFIER dimensions_opt { perm_string name = lex_strings.make($1); diff --git a/pform.cc b/pform.cc index 4ee97ccda..f9f7a3237 100644 --- a/pform.cc +++ b/pform.cc @@ -998,11 +998,18 @@ PCallTask* pform_make_call_task(const struct vlltype&loc, return tmp; } -void pform_make_foreach_declarations(const struct vlltype&loc, - std::list*loop_vars) +void pform_make_var(const struct vlltype&loc, + std::list*assign_list, + data_type_t*data_type, std::list*attr) { static const struct str_pair_t str = { IVL_DR_STRONG, IVL_DR_STRONG }; + pform_makewire(loc, 0, str, assign_list, NetNet::REG, data_type, attr); +} + +void pform_make_foreach_declarations(const struct vlltype&loc, + std::list*loop_vars) +{ listassign_list; for (list::const_iterator cur = loop_vars->begin() ; cur != loop_vars->end() ; ++ cur) { @@ -1011,7 +1018,7 @@ void pform_make_foreach_declarations(const struct vlltype&loc, assign_list.push_back(tmp_assign); } - pform_makewire(loc, 0, str, &assign_list, NetNet::REG, &size_type); + pform_make_var(loc, &assign_list, &size_type); } PForeach* pform_make_foreach(const struct vlltype&loc, @@ -2835,90 +2842,13 @@ void pform_makewire(const vlltype&li, perm_string name, } } -/* - * This form takes a list of names and some type information, and - * generates a bunch of variables/nets. We use the basic - * pform_makewire above. - */ -void pform_makewire(const vlltype&li, - list*range, - bool signed_flag, - list*names, - NetNet::Type type, - NetNet::PortType pt, - ivl_variable_type_t dt, - list*attr, - PWSRType rt) -{ - for (list::iterator cur = names->begin() - ; cur != names->end() ; ++ cur ) { - perm_string txt = *cur; - pform_makewire(li, txt, type, pt, dt, attr); - /* This has already been done for real variables. */ - if (dt != IVL_VT_REAL) { - pform_set_net_range(txt, type, range, signed_flag, dt, rt, 0); - } - } - - delete names; - delete range; - delete attr; -} - -/* - * This form makes nets with delays and continuous assignments. - */ -void pform_makewire(const vlltype&li, - list*delay, - str_pair_t str, - net_decl_assign_t*decls, - NetNet::Type type, - data_type_t*data_type) -{ - // The decls pointer is a circularly linked list. - net_decl_assign_t*first = decls->next; - - list*names = new list; - - // Go through the circularly linked list non-destructively. - do { - pform_makewire(li, first->name, type, NetNet::NOT_A_PORT, IVL_VT_NO_TYPE, 0); - names->push_back(first->name); - first = first->next; - } while (first != decls->next); - - // The pform_set_data_type function will delete the names list. - pform_set_data_type(li, data_type, names, type, 0); - - // This time, go through the list, deleting cells as I'm done. - first = decls->next; - decls->next = 0; - while (first) { - net_decl_assign_t*next = first->next; - PWire*cur = pform_get_wire_in_scope(first->name); - if (cur != 0) { - PEIdent*lval = new PEIdent(first->name); - FILE_NAME(lval, li.text, li.first_line); - PGAssign*ass = pform_make_pgassign(lval, first->expr, - delay, str); - FILE_NAME(ass, li.text, li.first_line); - } - - delete first; - first = next; - } -} - -/* - * This should eventually replace the form above that takes a - * net_decl_assign_t argument. - */ void pform_makewire(const struct vlltype&li, std::list*delay, str_pair_t str, std::list*assign_list, NetNet::Type type, - data_type_t*data_type) + data_type_t*data_type, + list*attr) { if (is_compilation_unit(lexical_scope) && !gn_system_verilog()) { VLerror(li, "error: variable declarations must be contained within a module."); @@ -2935,7 +2865,7 @@ void pform_makewire(const struct vlltype&li, names->push_back(curp->name); } - pform_set_data_type(li, data_type, names, type, 0); + pform_set_data_type(li, data_type, names, type, attr); while (! assign_list->empty()) { decl_assignment_t*first = assign_list->front(); diff --git a/pform.h b/pform.h index 861d59e67..687dee9bd 100644 --- a/pform.h +++ b/pform.h @@ -96,12 +96,6 @@ struct parmvalue_t { struct str_pair_t { ivl_drive_t str0, str1; }; -struct net_decl_assign_t { - perm_string name; - PExpr*expr; - struct net_decl_assign_t*next; -}; - /* The lgate is gate instantiation information. */ struct lgate { explicit inline lgate(int =0) @@ -361,38 +355,20 @@ extern void pform_makewire(const struct vlltype&li, perm_string name, ivl_variable_type_t, std::list*attr); -/* This form handles simple declarations */ -extern void pform_makewire(const struct vlltype&li, - std::list*range, - bool signed_flag, - std::list*names, - NetNet::Type type, - NetNet::PortType, - ivl_variable_type_t, - std::list*attr, - PWSRType rt = SR_NET); - /* This form handles assignment declarations. */ -extern void pform_makewire(const struct vlltype&li, - std::list*delay, - str_pair_t str, - net_decl_assign_t*assign_list, - NetNet::Type type, - data_type_t*data_type); extern void pform_makewire(const struct vlltype&li, std::list*delay, str_pair_t str, std::list*assign_list, NetNet::Type type, - data_type_t*data_type); + data_type_t*data_type, + std::list*attr = 0); -/* This form handles nets declared as structures. (See pform_struct_type.cc) */ -extern void pform_makewire(const struct vlltype&li, - struct_type_t*struct_type, - NetNet::PortType, - std::list*names, - std::list*attr); +extern void pform_make_var(const struct vlltype&loc, + std::list*assign_list, + data_type_t*data_type, + std::list*attr = 0); extern void pform_make_var_init(const struct vlltype&li, perm_string name, PExpr*expr); diff --git a/pform_struct_type.cc b/pform_struct_type.cc index 108b197b6..221722c43 100644 --- a/pform_struct_type.cc +++ b/pform_struct_type.cc @@ -91,32 +91,3 @@ void pform_set_struct_type(const struct vlltype&li, struct_type_t*struct_type, l pform_set_struct_type(li, struct_type, *cur, net_type, attr); } } - -static void pform_makewire(const struct vlltype&li, - struct_type_t*struct_type, - NetNet::PortType ptype, - perm_string name, - list*) -{ - ivl_variable_type_t base_type = struct_type->figure_packed_base_type(); - - PWire*cur = pform_get_make_wire_in_scope(li, name, NetNet::WIRE, ptype, base_type); - assert(cur); - FILE_NAME(cur, li); - cur->set_data_type(struct_type); -} - -void pform_makewire(const struct vlltype&li, - struct_type_t*struct_type, - NetNet::PortType ptype, - list*names, - list*attr) -{ - for (list::iterator cur = names->begin() - ; cur != names->end() ; ++ cur ) { - perm_string txt = *cur; - pform_makewire(li, struct_type, ptype, txt, attr); - } - - delete names; -}