sv: fix always_comb auto nosync for nested and function blocks

This commit is contained in:
Zachary Snow 2022-02-22 16:57:08 +01:00 committed by Zachary Snow
parent 957fdb328a
commit bf15dbd0f7
4 changed files with 45 additions and 1 deletions

View File

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

View File

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

View File

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

View File

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