aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--frontends/verilog/verilog_parser.y55
-rw-r--r--passes/memory/memory_share.cc45
-rw-r--r--tests/svtypes/typedef_initial_and_assign.sv94
-rw-r--r--tests/svtypes/typedef_initial_and_assign.ys14
5 files changed, 178 insertions, 32 deletions
diff --git a/Makefile b/Makefile
index 9a714e94e..6b64b0e35 100644
--- a/Makefile
+++ b/Makefile
@@ -126,7 +126,7 @@ LDFLAGS += -rdynamic
LDLIBS += -lrt
endif
-YOSYS_VER := 0.9+4259
+YOSYS_VER := 0.9+4261
GIT_REV := $(shell git -C $(YOSYS_SRC) rev-parse --short HEAD 2> /dev/null || echo UNKNOWN)
OBJS = kernel/version_$(GIT_REV).o
diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y
index a5227cb09..b0c16c0f4 100644
--- a/frontends/verilog/verilog_parser.y
+++ b/frontends/verilog/verilog_parser.y
@@ -127,6 +127,15 @@ struct specify_rise_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)
{
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 <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id hierarchical_type_id integral_number
%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_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 <ast> struct_union
%type <ast_node_type> asgn_binop
@@ -763,12 +772,6 @@ opt_wire_type_token:
wire_type_token | %empty;
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 {
astbuf3->is_wor = true;
} |
@@ -812,6 +815,9 @@ logic_type:
astbuf3->range_left = $1 - 1;
astbuf3->range_right = 0;
astbuf3->is_signed = true;
+ } |
+ hierarchical_type_id {
+ addWiretypeNode($1, astbuf3);
};
integer_atom_type:
@@ -821,6 +827,10 @@ integer_atom_type:
TOK_LONGINT { $$ = 64; } |
TOK_BYTE { $$ = 8; } ;
+integer_vector_type:
+ TOK_LOGIC { $$ = TOK_LOGIC; } |
+ TOK_REG { $$ = TOK_REG; } ;
+
non_opt_range:
'[' expr ':' expr ']' {
$$ = new AstNode(AST_RANGE);
@@ -1985,7 +1995,7 @@ type_name: TOK_ID // first time seen
;
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;
astbuf2 = checkRange(astbuf1, $3);
if (astbuf2)
@@ -1998,10 +2008,33 @@ typedef_decl:
rewriteAsMemoryNode(astbuf1, $5);
}
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
| struct_type
;
diff --git a/passes/memory/memory_share.cc b/passes/memory/memory_share.cc
index 8499b46d8..1951b5400 100644
--- a/passes/memory/memory_share.cc
+++ b/passes/memory/memory_share.cc
@@ -112,25 +112,27 @@ struct MemoryShareWorker
// merged by widening the narrow one. Check if the conditions
// hold for that.
int wide_log2 = std::max(port1.wide_log2, port2.wide_log2);
- if (GetSize(port1.addr) <= wide_log2)
+ SigSpec addr1 = sigmap_xmux(port1.addr);
+ SigSpec addr2 = sigmap_xmux(port2.addr);
+ if (GetSize(addr1) <= wide_log2)
continue;
- if (GetSize(port2.addr) <= wide_log2)
+ if (GetSize(addr2) <= wide_log2)
continue;
- if (!port1.addr.extract(0, wide_log2).is_fully_const())
+ if (!addr1.extract(0, wide_log2).is_fully_const())
continue;
- if (!port2.addr.extract(0, wide_log2).is_fully_const())
+ if (!addr2.extract(0, wide_log2).is_fully_const())
continue;
- if (sigmap_xmux(port1.addr.extract_end(wide_log2)) != sigmap_xmux(port2.addr.extract_end(wide_log2))) {
+ if (addr1.extract_end(wide_log2) != addr2.extract_end(wide_log2)) {
// Incompatible addresses after widening. Last chance — widen both
// ports by one more bit to merge them.
if (!flag_widen)
continue;
wide_log2++;
- if (sigmap_xmux(port1.addr.extract_end(wide_log2)) != sigmap_xmux(port2.addr.extract_end(wide_log2)))
+ if (addr1.extract_end(wide_log2) != addr2.extract_end(wide_log2))
continue;
- if (!port1.addr.extract(0, wide_log2).is_fully_const())
+ if (!addr1.extract(0, wide_log2).is_fully_const())
continue;
- if (!port2.addr.extract(0, wide_log2).is_fully_const())
+ if (!addr2.extract(0, wide_log2).is_fully_const())
continue;
}
// Combine init/reset values.
@@ -150,12 +152,13 @@ struct MemoryShareWorker
// At this point we are committed to the merge.
{
log(" Merging ports %d, %d (address %s).\n", i, j, log_signal(port1.addr));
+ port1.addr = addr1;
+ port2.addr = addr2;
mem.prepare_rd_merge(i, j, &initvals);
mem.widen_prep(wide_log2);
SigSpec new_data = module->addWire(NEW_ID, mem.width << wide_log2);
module->connect(port1.data, new_data.extract(sub1 * mem.width, mem.width << port1.wide_log2));
module->connect(port2.data, new_data.extract(sub2 * mem.width, mem.width << port2.wide_log2));
- port1.addr = sigmap_xmux(port1.addr);
for (int k = 0; k < wide_log2; k++)
port1.addr[k] = State::S0;
port1.init_value = init_value;
@@ -211,31 +214,33 @@ struct MemoryShareWorker
// merged by widening the narrow one. Check if the conditions
// hold for that.
int wide_log2 = std::max(port1.wide_log2, port2.wide_log2);
- if (GetSize(port1.addr) <= wide_log2)
+ SigSpec addr1 = sigmap_xmux(port1.addr);
+ SigSpec addr2 = sigmap_xmux(port2.addr);
+ if (GetSize(addr1) <= wide_log2)
continue;
- if (GetSize(port2.addr) <= wide_log2)
+ if (GetSize(addr2) <= wide_log2)
continue;
- if (!port1.addr.extract(0, wide_log2).is_fully_const())
+ if (!addr1.extract(0, wide_log2).is_fully_const())
continue;
- if (!port2.addr.extract(0, wide_log2).is_fully_const())
+ if (!addr2.extract(0, wide_log2).is_fully_const())
continue;
- if (sigmap_xmux(port1.addr.extract_end(wide_log2)) != sigmap_xmux(port2.addr.extract_end(wide_log2))) {
+ if (addr1.extract_end(wide_log2) != addr2.extract_end(wide_log2)) {
// Incompatible addresses after widening. Last chance — widen both
// ports by one more bit to merge them.
if (!flag_widen)
continue;
wide_log2++;
- if (sigmap_xmux(port1.addr.extract_end(wide_log2)) != sigmap_xmux(port2.addr.extract_end(wide_log2)))
+ if (addr1.extract_end(wide_log2) != addr2.extract_end(wide_log2))
continue;
- if (!port1.addr.extract(0, wide_log2).is_fully_const())
+ if (!addr1.extract(0, wide_log2).is_fully_const())
continue;
- if (!port2.addr.extract(0, wide_log2).is_fully_const())
+ if (!addr2.extract(0, wide_log2).is_fully_const())
continue;
}
- log(" Merging ports %d, %d (address %s).\n", i, j, log_signal(port1.addr));
+ log(" Merging ports %d, %d (address %s).\n", i, j, log_signal(addr1));
+ port1.addr = addr1;
+ port2.addr = addr2;
mem.prepare_wr_merge(i, j, &initvals);
- port1.addr = sigmap_xmux(port1.addr);
- port2.addr = sigmap_xmux(port2.addr);
mem.widen_wr_port(i, wide_log2);
mem.widen_wr_port(j, wide_log2);
int pos = 0;
diff --git a/tests/svtypes/typedef_initial_and_assign.sv b/tests/svtypes/typedef_initial_and_assign.sv
new file mode 100644
index 000000000..05579947d
--- /dev/null
+++ b/tests/svtypes/typedef_initial_and_assign.sv
@@ -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
diff --git a/tests/svtypes/typedef_initial_and_assign.ys b/tests/svtypes/typedef_initial_and_assign.ys
new file mode 100644
index 000000000..de456bb82
--- /dev/null
+++ b/tests/svtypes/typedef_initial_and_assign.ys
@@ -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 \ No newline at end of file