Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect inlining of continuous assignment #881

Closed
veripoolbot opened this issue Feb 6, 2015 · 5 comments
Closed

Incorrect inlining of continuous assignment #881

veripoolbot opened this issue Feb 6, 2015 · 5 comments
Assignees
Labels
area: wrong runtime result Issue involves an incorrect runtine result from Verilated model resolution: fixed Closed; fixed

Comments

@veripoolbot
Copy link
Contributor


Author Name: Mike Thyer
Original Redmine Issue: 881 from https://www.veripool.org
Original Date: 2015-02-05
Original Assignee: Wilson Snyder (@wsnyder)


I've distilled an issue with the inlining of continuous assignments into a tiny test case.
I've attached a regression test demonstrating this, the important bits are here:

assign a_w = a_r;
always @(*) begin
  a_r = 0;
  b_r = a_w;
  a_r = c_q_r;
  c_d_r = c_q_r; // a counter
end

In some circumstances Verilator inlines the assign into the always block. This results in b_r taking on the value 0 instead of being the same as a_r.

In the full code, this problem occurred using -O1 but went away using -O0. It also occurred when using -O0 -OG, but not when using -O1 -Og.
In this reduced case, the problem only occurs when using -O0 -OG. Curiously there are no UNOPTFLAT warnings, just incorrect simulation results.

I realize the -O options are for developers rather than users. I'm hoping that diagnosing this smaller problem will help get the full code compiling with the -O1 setting.
I've started looking through the Verilator source code, but I'm not fully up to speed with it yet. I can see where the inlining is done, I don't yet fully understand how Verilator decides if this is valid or not.

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Jie Xu (@jiexu)
Original Date: 2015-02-06T21:54:08Z


IMHO Verilator is giving the correct simulation result with @-O1@ which actually enables @-OG@. The "problem" occurs whenever you disable Gate optimization with either @-O0@ or @-Og@.

Basically Verilator sees @a_w@ and @a_r@ are exactly the same signal when you have an assignment like that. And inside the combinational block the @a_r = 0@ is executed first and the value of @a_r@ is assigned to @b_r@ afterwards which is 0.

If you look the Verilator source code src/Verilator.cpp:390 where the Gate optimisation is called, you will see the other info

Command Line disabled gate optimization with -Og/-O0. This may cause ordering problems.

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Mike Thyer
Original Date: 2015-02-10T20:28:45Z


Using the -O0 setting, Verilator consistently has the same behaviour as ModelSim, NCSim and a Xilinx FPGA. Turning gate optimizations on seems to be causing the differences. Curiously, in an attempt to use one less language construct, I converted the assign into an always block, and the same differences still occur (with a_w now defined as a reg).

always @() begin
a_w = a_r;
end
always @(
) begin
a_r = 0;
b_r = a_w;
a_r = c_q_r;
c_d_r = c_q_r; // a counter
end

I don't think the inlining is valid as it changes the behaviour of the code. Substituting a_r for a_w changes the evaluation of "a_w = a_r" from occurring whenever a_r changes, to when a_w is read. This means that "a_w = a_r" is no longer being reevaluated after the second assignment to a_r, when it should be.

If we consider the larger always block in isolation as a hardware block, it looks like this, with inputs at the top, outputs below:

    C       A
  -----------
    |\      |
    | \     |
    |  \    |
  -----------
    C   A   B

If we then connect the output A back up to the input A, the result should be B taking on the value of C.

I'm still working my way through the Verilator source code as and when I can find the time. So far Verilator has been very reliable, and we can easily work-around this issue, but I'd like to try and help get this fixed so as to reduce the likelihood of encountering similar issues in the future.

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Wilson Snyder (@wsnyder)
Original Date: 2015-02-12T00:39:14Z


I claim that the optimization problem can only occur when the substitution assignment has on its right-hand-side (a_r) a variable that the target always block also has on its left-hand-side (a_r).

Committed a fix that disables under this case to git. Please give it a try.

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Mike Thyer
Original Date: 2015-02-12T18:55:48Z


Thanks very much for the fix. I can confirm it works. I tried it in our full system where we originally encountered the issue, and it works, without needing the work-around now. I also tried adding a few more assigns and loops through the always block to the tiny test case, so as to make the overall loop less immediately obvious, and Verilator keeps behaving correctly. Thanks again.

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Wilson Snyder (@wsnyder)
Original Date: 2015-02-13T01:41:45Z


In 3.870.

@veripoolbot veripoolbot added area: wrong runtime result Issue involves an incorrect runtine result from Verilated model resolution: fixed Closed; fixed labels Dec 22, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: wrong runtime result Issue involves an incorrect runtine result from Verilated model resolution: fixed Closed; fixed
Projects
None yet
Development

No branches or pull requests

2 participants