Verilator handling of combo always block
When investigating to improve the performance of Verilator-based simulator model, I found the following handling of combo blocks in Verilator:
1) The sense list in always combo block is actually not really used. When forming AstActive, the sense list of combo always block is deleted.
2) Instead Verilator will kind of take in all the AstVarRef on RHS as the sense item. This is reflected in V3Order.cpp when forming the graph. This in some cases will make the signal as Circular.
We have some cases where the above of handling will make Verilator generating at least inefficient(not know if incorrect) code. For example:
module test (a, b, result); input wire a; input wire b; output wire [31:0] result; logic [2:0] c; always @(a,b) // By doing this, the designer knows c is not a problem. begin // c = 3'b0; // by uncomenting this line, Verilator will not take c into sense list. c = c | (a << 1); c = c | (b << 2); end assign result[2:0] = c; endmodule
Verilator will take the
c into the
change_request list in this example. However here
c is an output and don't really need another loop to settle.
The big question here is which should we depends on, either the designer's list (
always(a,b))) or all the VAR used as condition. IMHO, I believe we should respect the designer as he has the option
always* if he really want to take later case.
#1 Updated by Wilson Snyder almost 5 years ago
- Status changed from New to Feature
Verilator follows the synthesis rules which you described - basically treat all combos as an "always @*".
Obviously Verilator is cycle based, so will not do what the sensitivity list strictly requires; though it could be told to use only the list for doing ordering (V3Order). The main catch is there are things that need to be sensitive to for proper scheduling that are not legally or traditionally listed in the sensitivity list, for example memories or the variables that a function call inside the block needs.
#2 Updated by Jie Xu almost 5 years ago
Agree with your points. But it would be nice to have an option to Verilator which determines how the sense list should be constructed. The default process can still be "always @*". Then when user uses that option, he should be responsible for what is he doing.
#3 Updated by Wilson Snyder almost 5 years ago
I'm fine with adding an option like that. My caution is that you will need to solve the problems of those items which cannot be legally put into the sensitivity list.
It would require changing the verilog code, but one option would be to add a meta comment (that becomes an attribute after parsing):
always @(a,b) // By doing this, the designer knows c is not a problem. begin // verilator strict_sense_list // c = 3'b0; // by uncomenting this line, Verilator will not take c into sense list. c = c | (a << 1); c = c | (b << 2); end
#4 Updated by Wilson Snyder almost 5 years ago
I didn't mention the point of the meta comment is you would use it only when there are no function calls or other stuff that might get you in trouble, then you don't need to solve that issue.
Both methods are also probably reasonable, add the switch and it would have the same effect as setting that meta comment on all combo always'.
#5 Updated by Jie Xu almost 5 years ago
The reason I want a switch is that it is quite difficult to find all the cases in a relative large design. And this is really important one as it may affect both the simulator performance and accuracy.
I actually have tried another solution as well. I add meta info
/*verilator clock_enable*/ to "c". That also works in the sense eliminate the extra loop. However, when I tried this trick in our larger design, then the simulator behaved not correct any more.
So for the meta info method, my concern is the design will not simulate correctly if we only change some of the always blocks.
Also available in: Atom