mirror of https://github.com/YosysHQ/yosys.git
sv: improve support for wire and var with user-defined types
- User-defined types must be data types. Using a net type (e.g. wire) is a syntax error. - User-defined types without a net type are always variables (i.e. logic). - Nets and variables can now be explicitly declared using user-defined types: typedef logic [1:0] W; wire W w; typedef logic [1:0] V; var V v; Fixes #2846
This commit is contained in:
parent
c8023e37d8
commit
979053855c
|
@ -127,6 +127,15 @@ struct specify_rise_fall {
|
||||||
specify_triple fall;
|
specify_triple fall;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void addWiretypeNode(std::string *name, AstNode *node)
|
||||||
|
{
|
||||||
|
log_assert(node);
|
||||||
|
node->is_custom_type = true;
|
||||||
|
node->children.push_back(new AstNode(AST_WIRETYPE));
|
||||||
|
node->children.back()->str = *name;
|
||||||
|
delete name;
|
||||||
|
}
|
||||||
|
|
||||||
static void addTypedefNode(std::string *name, AstNode *node)
|
static void addTypedefNode(std::string *name, AstNode *node)
|
||||||
{
|
{
|
||||||
log_assert(node);
|
log_assert(node);
|
||||||
|
@ -305,10 +314,10 @@ static void checkLabelsMatch(const char *element, const std::string *before, con
|
||||||
%type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list non_io_wire_type io_wire_type
|
%type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list non_io_wire_type io_wire_type
|
||||||
%type <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id hierarchical_type_id integral_number
|
%type <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id hierarchical_type_id integral_number
|
||||||
%type <string> type_name
|
%type <string> type_name
|
||||||
%type <ast> opt_enum_init enum_type struct_type non_wire_data_type func_return_type
|
%type <ast> opt_enum_init enum_type struct_type enum_struct_type func_return_type typedef_base_type
|
||||||
%type <boolean> opt_property always_comb_or_latch always_or_always_ff
|
%type <boolean> opt_property always_comb_or_latch always_or_always_ff
|
||||||
%type <boolean> opt_signedness_default_signed opt_signedness_default_unsigned
|
%type <boolean> opt_signedness_default_signed opt_signedness_default_unsigned
|
||||||
%type <integer> integer_atom_type
|
%type <integer> integer_atom_type integer_vector_type
|
||||||
%type <al> attr case_attr
|
%type <al> attr case_attr
|
||||||
%type <ast> struct_union
|
%type <ast> struct_union
|
||||||
%type <ast_node_type> asgn_binop
|
%type <ast_node_type> asgn_binop
|
||||||
|
@ -763,12 +772,6 @@ opt_wire_type_token:
|
||||||
wire_type_token | %empty;
|
wire_type_token | %empty;
|
||||||
|
|
||||||
wire_type_token:
|
wire_type_token:
|
||||||
hierarchical_type_id {
|
|
||||||
astbuf3->is_custom_type = true;
|
|
||||||
astbuf3->children.push_back(new AstNode(AST_WIRETYPE));
|
|
||||||
astbuf3->children.back()->str = *$1;
|
|
||||||
delete $1;
|
|
||||||
} |
|
|
||||||
TOK_WOR {
|
TOK_WOR {
|
||||||
astbuf3->is_wor = true;
|
astbuf3->is_wor = true;
|
||||||
} |
|
} |
|
||||||
|
@ -812,6 +815,9 @@ logic_type:
|
||||||
astbuf3->range_left = $1 - 1;
|
astbuf3->range_left = $1 - 1;
|
||||||
astbuf3->range_right = 0;
|
astbuf3->range_right = 0;
|
||||||
astbuf3->is_signed = true;
|
astbuf3->is_signed = true;
|
||||||
|
} |
|
||||||
|
hierarchical_type_id {
|
||||||
|
addWiretypeNode($1, astbuf3);
|
||||||
};
|
};
|
||||||
|
|
||||||
integer_atom_type:
|
integer_atom_type:
|
||||||
|
@ -821,6 +827,10 @@ integer_atom_type:
|
||||||
TOK_LONGINT { $$ = 64; } |
|
TOK_LONGINT { $$ = 64; } |
|
||||||
TOK_BYTE { $$ = 8; } ;
|
TOK_BYTE { $$ = 8; } ;
|
||||||
|
|
||||||
|
integer_vector_type:
|
||||||
|
TOK_LOGIC { $$ = TOK_LOGIC; } |
|
||||||
|
TOK_REG { $$ = TOK_REG; } ;
|
||||||
|
|
||||||
non_opt_range:
|
non_opt_range:
|
||||||
'[' expr ':' expr ']' {
|
'[' expr ':' expr ']' {
|
||||||
$$ = new AstNode(AST_RANGE);
|
$$ = new AstNode(AST_RANGE);
|
||||||
|
@ -1985,7 +1995,7 @@ type_name: TOK_ID // first time seen
|
||||||
;
|
;
|
||||||
|
|
||||||
typedef_decl:
|
typedef_decl:
|
||||||
TOK_TYPEDEF non_io_wire_type range type_name range_or_multirange ';' {
|
TOK_TYPEDEF typedef_base_type range type_name range_or_multirange ';' {
|
||||||
astbuf1 = $2;
|
astbuf1 = $2;
|
||||||
astbuf2 = checkRange(astbuf1, $3);
|
astbuf2 = checkRange(astbuf1, $3);
|
||||||
if (astbuf2)
|
if (astbuf2)
|
||||||
|
@ -1998,10 +2008,33 @@ typedef_decl:
|
||||||
rewriteAsMemoryNode(astbuf1, $5);
|
rewriteAsMemoryNode(astbuf1, $5);
|
||||||
}
|
}
|
||||||
addTypedefNode($4, astbuf1); }
|
addTypedefNode($4, astbuf1); }
|
||||||
| TOK_TYPEDEF non_wire_data_type type_name ';' { addTypedefNode($3, $2); }
|
| TOK_TYPEDEF enum_struct_type type_name ';' { addTypedefNode($3, $2); }
|
||||||
;
|
;
|
||||||
|
|
||||||
non_wire_data_type:
|
typedef_base_type:
|
||||||
|
hierarchical_type_id {
|
||||||
|
$$ = new AstNode(AST_WIRE);
|
||||||
|
$$->is_logic = true;
|
||||||
|
addWiretypeNode($1, $$);
|
||||||
|
} |
|
||||||
|
integer_vector_type opt_signedness_default_unsigned {
|
||||||
|
$$ = new AstNode(AST_WIRE);
|
||||||
|
if ($1 == TOK_REG) {
|
||||||
|
$$->is_reg = true;
|
||||||
|
} else {
|
||||||
|
$$->is_logic = true;
|
||||||
|
}
|
||||||
|
$$->is_signed = $2;
|
||||||
|
} |
|
||||||
|
integer_atom_type opt_signedness_default_signed {
|
||||||
|
$$ = new AstNode(AST_WIRE);
|
||||||
|
$$->is_logic = true;
|
||||||
|
$$->is_signed = $2;
|
||||||
|
$$->range_left = $1 - 1;
|
||||||
|
$$->range_right = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum_struct_type:
|
||||||
enum_type
|
enum_type
|
||||||
| struct_type
|
| struct_type
|
||||||
;
|
;
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
package pkg;
|
||||||
|
typedef logic pkg_user_t;
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
module top;
|
||||||
|
typedef logic user_t;
|
||||||
|
|
||||||
|
// Continuous assignment to a variable is legal
|
||||||
|
user_t var_1;
|
||||||
|
assign var_1 = 0;
|
||||||
|
assert property (var_1 == 0);
|
||||||
|
|
||||||
|
var user_t var_2;
|
||||||
|
assign var_2 = 0;
|
||||||
|
assert property (var_2 == 0);
|
||||||
|
|
||||||
|
var pkg::pkg_user_t var_3;
|
||||||
|
assign var_3 = 0;
|
||||||
|
assert property (var_3 == 0);
|
||||||
|
|
||||||
|
// Procedural assignment to a variable is legal
|
||||||
|
user_t var_4 = 0;
|
||||||
|
assert property (var_4 == 0);
|
||||||
|
|
||||||
|
user_t var_5;
|
||||||
|
initial var_5 = 0;
|
||||||
|
assert property (var_5 == 0);
|
||||||
|
|
||||||
|
var user_t var_6 = 0;
|
||||||
|
assert property (var_6 == 0);
|
||||||
|
|
||||||
|
var user_t var_7;
|
||||||
|
initial var_7 = 0;
|
||||||
|
assert property (var_7 == 0);
|
||||||
|
|
||||||
|
pkg::pkg_user_t var_8 = 0;
|
||||||
|
assert property (var_8 == 0);
|
||||||
|
|
||||||
|
pkg::pkg_user_t var_9;
|
||||||
|
initial var_9 = 0;
|
||||||
|
assert property (var_9 == 0);
|
||||||
|
|
||||||
|
var pkg::pkg_user_t var_10 = 0;
|
||||||
|
assert property (var_10 == 0);
|
||||||
|
|
||||||
|
var pkg::pkg_user_t var_11;
|
||||||
|
initial var_11 = 0;
|
||||||
|
assert property (var_11 == 0);
|
||||||
|
|
||||||
|
// Continuous assignment to a net is legal
|
||||||
|
wire user_t wire_1 = 0;
|
||||||
|
assert property (wire_3 == 0);
|
||||||
|
|
||||||
|
wire user_t wire_2;
|
||||||
|
assign wire_2 = 0;
|
||||||
|
assert property (wire_2 == 0);
|
||||||
|
|
||||||
|
wire pkg::pkg_user_t wire_3 = 0;
|
||||||
|
assert property (wire_3 == 0);
|
||||||
|
|
||||||
|
wire pkg::pkg_user_t wire_4;
|
||||||
|
assign wire_4 = 0;
|
||||||
|
assert property (wire_4 == 0);
|
||||||
|
|
||||||
|
// Mixing continuous and procedural assignments is illegal
|
||||||
|
user_t var_12 = 0;
|
||||||
|
assign var_12 = 1; // warning: reg assigned in a continuous assignment
|
||||||
|
|
||||||
|
user_t var_13;
|
||||||
|
initial var_13 = 0;
|
||||||
|
assign var_13 = 1; // warning: reg assigned in a continuous assignment
|
||||||
|
|
||||||
|
var user_t var_14 = 0;
|
||||||
|
assign var_14 = 1; // warning: reg assigned in a continuous assignment
|
||||||
|
|
||||||
|
var user_t var_15;
|
||||||
|
initial var_15 = 0;
|
||||||
|
assign var_15 = 1; // warning: reg assigned in a continuous assignment
|
||||||
|
|
||||||
|
pkg::pkg_user_t var_16 = 0;
|
||||||
|
assign var_16 = 1; // warning: reg assigned in a continuous assignment
|
||||||
|
|
||||||
|
pkg::pkg_user_t var_17;
|
||||||
|
initial var_17 = 0;
|
||||||
|
assign var_17 = 1; // warning: reg assigned in a continuous assignment
|
||||||
|
|
||||||
|
var pkg::pkg_user_t var_18 = 0;
|
||||||
|
assign var_18 = 1; // warning: reg assigned in a continuous assignment
|
||||||
|
|
||||||
|
var pkg::pkg_user_t var_19;
|
||||||
|
initial var_19 = 0;
|
||||||
|
assign var_19 = 1; // warning: reg assigned in a continuous assignment
|
||||||
|
|
||||||
|
endmodule
|
|
@ -0,0 +1,14 @@
|
||||||
|
logger -expect-no-warnings
|
||||||
|
logger -expect warning "reg '\\var_12' is assigned in a continuous assignment" 1
|
||||||
|
logger -expect warning "reg '\\var_13' is assigned in a continuous assignment" 1
|
||||||
|
logger -expect warning "reg '\\var_14' is assigned in a continuous assignment" 1
|
||||||
|
logger -expect warning "reg '\\var_15' is assigned in a continuous assignment" 1
|
||||||
|
logger -expect warning "reg '\\var_16' is assigned in a continuous assignment" 1
|
||||||
|
logger -expect warning "reg '\\var_17' is assigned in a continuous assignment" 1
|
||||||
|
logger -expect warning "reg '\\var_18' is assigned in a continuous assignment" 1
|
||||||
|
logger -expect warning "reg '\\var_19' is assigned in a continuous assignment" 1
|
||||||
|
|
||||||
|
read_verilog -sv typedef_initial_and_assign.sv
|
||||||
|
hierarchy; proc; opt
|
||||||
|
select -module top
|
||||||
|
sat -verify -seq 1 -tempinduct -prove-asserts -show-all
|
Loading…
Reference in New Issue