Merge pull request #618 from larsclausen/signal-decl-consolidation

Consolidate signal declaration
This commit is contained in:
Stephen Williams 2022-02-18 08:27:52 -08:00 committed by GitHub
commit cc0a8c8dd2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 99 additions and 268 deletions

View File

@ -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

View File

@ -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

View File

@ -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

175
parse.y
View File

@ -439,7 +439,6 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vector<Statem
Statement*statement;
std::vector<Statement*>*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<Statem
%type <statement> udp_initial udp_init_opt
%type <expr> udp_initial_expr_opt
%type <text> register_variable net_variable event_variable label_opt class_declaration_endlabel_opt
%type <text> net_variable event_variable label_opt class_declaration_endlabel_opt
%type <text> block_identifier_opt
%type <perm_strings> register_variable_list net_variable_list event_variable_list
%type <perm_strings> net_variable_list event_variable_list
%type <perm_strings> list_of_identifiers loop_variables
%type <port_list> list_of_port_identifiers list_of_variable_port_identifiers
%type <net_decl_assign> net_decl_assign net_decl_assigns
%type <decl_assignments> net_decl_assigns
%type <decl_assignment> net_decl_assign
%type <mport> port port_opt port_reference port_reference_list
%type <mport> port_declaration
@ -645,6 +645,7 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vector<Statem
%type <expr> assignment_pattern expression expr_mintypmax
%type <expr> expr_primary_or_typename expr_primary
%type <expr> class_new dynamic_array_new let_default_opt
%type <expr> var_decl_initializer_opt
%type <expr> inc_or_dec_expression inside_expression lpvalue
%type <expr> branch_probe_expression streaming_concatenation
%type <expr> 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<decl_assignment_t*>*tmp = new std::list<decl_assignment_t*>;
@ -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<decl_assignment_t*>*tmp = $1;
tmp->push_back($3);
$$ = tmp;
}
| net_decl_assign
{ $$ = $1;
}
{ std::list<decl_assignment_t*>*tmp = new std::list<decl_assignment_t*>;
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<perm_string>*tmp = new std::list<perm_string>;
tmp->push_back(lex_strings.make($1));
$$ = tmp;
delete[]$1;
}
| register_variable_list ',' register_variable
{ std::list<perm_string>*tmp = $1;
tmp->push_back(lex_strings.make($3));
$$ = tmp;
delete[]$3;
}
;
net_variable
: IDENTIFIER dimensions_opt
{ perm_string name = lex_strings.make($1);

View File

@ -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<perm_string>*loop_vars)
void pform_make_var(const struct vlltype&loc,
std::list<decl_assignment_t*>*assign_list,
data_type_t*data_type, std::list<named_pexpr_t>*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<perm_string>*loop_vars)
{
list<decl_assignment_t*>assign_list;
for (list<perm_string>::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<pform_range_t>*range,
bool signed_flag,
list<perm_string>*names,
NetNet::Type type,
NetNet::PortType pt,
ivl_variable_type_t dt,
list<named_pexpr_t>*attr,
PWSRType rt)
{
for (list<perm_string>::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<PExpr*>*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<perm_string>*names = new list<perm_string>;
// 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<PExpr*>*delay,
str_pair_t str,
std::list<decl_assignment_t*>*assign_list,
NetNet::Type type,
data_type_t*data_type)
data_type_t*data_type,
list<named_pexpr_t>*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();

36
pform.h
View File

@ -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<named_pexpr_t>*attr);
/* This form handles simple declarations */
extern void pform_makewire(const struct vlltype&li,
std::list<pform_range_t>*range,
bool signed_flag,
std::list<perm_string>*names,
NetNet::Type type,
NetNet::PortType,
ivl_variable_type_t,
std::list<named_pexpr_t>*attr,
PWSRType rt = SR_NET);
/* This form handles assignment declarations. */
extern void pform_makewire(const struct vlltype&li,
std::list<PExpr*>*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<PExpr*>*delay,
str_pair_t str,
std::list<decl_assignment_t*>*assign_list,
NetNet::Type type,
data_type_t*data_type);
data_type_t*data_type,
std::list<named_pexpr_t>*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<perm_string>*names,
std::list<named_pexpr_t>*attr);
extern void pform_make_var(const struct vlltype&loc,
std::list<decl_assignment_t*>*assign_list,
data_type_t*data_type,
std::list<named_pexpr_t>*attr = 0);
extern void pform_make_var_init(const struct vlltype&li,
perm_string name, PExpr*expr);

View File

@ -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<named_pexpr_t>*)
{
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<perm_string>*names,
list<named_pexpr_t>*attr)
{
for (list<perm_string>::iterator cur = names->begin()
; cur != names->end() ; ++ cur ) {
perm_string txt = *cur;
pform_makewire(li, struct_type, ptype, txt, attr);
}
delete names;
}