aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG4
-rw-r--r--frontends/ast/simplify.cc12
-rw-r--r--tests/verilog/always_comb_nolatch_5.ys15
-rw-r--r--tests/verilog/always_comb_nolatch_6.ys15
4 files changed, 45 insertions, 1 deletions
diff --git a/CHANGELOG b/CHANGELOG
index bec9f8321..a27adc5bf 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -5,6 +5,10 @@ List of major changes and improvements between releases
Yosys 0.16 .. Yosys 0.16-dev
--------------------------
+ * SystemVerilog
+ - Fixed automatic `nosync` inference for local variables in `always_comb`
+ procedures not applying to nested blocks and blocks in functions
+
Yosys 0.15 .. Yosys 0.16
--------------------------
* Various
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index 565025d3a..bd3e09c4b 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -744,6 +744,16 @@ static void mark_auto_nosync(AstNode *block, const AstNode *wire)
false);
}
+// block names can be prefixed with an explicit scope during elaboration
+static bool is_autonamed_block(const std::string &str) {
+ size_t last_dot = str.rfind('.');
+ // unprefixed names: autonamed if the first char is a dollar sign
+ if (last_dot == std::string::npos)
+ return str.at(0) == '$'; // e.g., `$fordecl_block$1`
+ // prefixed names: autonamed if the final chunk begins with a dollar sign
+ return str.rfind(".$") == last_dot; // e.g., `\foo.bar.$fordecl_block$1`
+}
+
// check a procedural block for auto-nosync markings, remove them, and add
// nosync to local variables as necessary
static void check_auto_nosync(AstNode *node)
@@ -2355,7 +2365,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
// if this is an autonamed block is in an always_comb
if (current_always && current_always->attributes.count(ID::always_comb)
- && str.at(0) == '$')
+ && is_autonamed_block(str))
// track local variables in this block so we can consider adding
// nosync once the block has been fully elaborated
for (AstNode *child : children)
diff --git a/tests/verilog/always_comb_nolatch_5.ys b/tests/verilog/always_comb_nolatch_5.ys
new file mode 100644
index 000000000..132878626
--- /dev/null
+++ b/tests/verilog/always_comb_nolatch_5.ys
@@ -0,0 +1,15 @@
+read_verilog -sv <<EOF
+module top;
+logic [4:0] x;
+logic z;
+assign z = 1'b1;
+always_comb begin : foo
+ x = '0;
+ if (z) begin : bar
+ for (int i = 0; i < 5; i++)
+ x[i] = 1'b1;
+ end
+end
+endmodule
+EOF
+proc
diff --git a/tests/verilog/always_comb_nolatch_6.ys b/tests/verilog/always_comb_nolatch_6.ys
new file mode 100644
index 000000000..90ee78a68
--- /dev/null
+++ b/tests/verilog/always_comb_nolatch_6.ys
@@ -0,0 +1,15 @@
+read_verilog -sv <<EOF
+module top(input wire x, y, output reg z);
+function automatic f;
+ input inp;
+ for (int i = 0; i < 1; i++)
+ f = inp + 0;
+endfunction
+always_comb
+ if (y)
+ z = f(x);
+ else
+ z = 0;
+endmodule
+EOF
+proc