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

Gate optimizer: Can't replace lvalue assignments with const var #831

Closed
veripoolbot opened this issue Oct 19, 2014 · 11 comments
Closed

Gate optimizer: Can't replace lvalue assignments with const var #831

veripoolbot opened this issue Oct 19, 2014 · 11 comments
Assignees

Comments

@veripoolbot
Copy link
Contributor

@veripoolbot veripoolbot commented Oct 19, 2014


Author Name: Jonathon Donaldson
Original Redmine Issue: 831 from https://www.veripool.org

Original Assignee: Wilson Snyder (@wsnyder)


I'm getting this extremely annoying internal error when verilating my code:

%Error: Internal Error: ../design/cpu/cpu_reg_file.sv:413: ../V3Gate.cpp:762: Can't replace lvalue assignments with const var
%Error: Internal Error: See the manual and http://www.veripool.org/verilator for more assistance.

The code that's causing the error is as follows.

logic [7:0] timer_T1;

always_ff @(posedge i_clk)
begin
  if (i_rst || i_ls_en) begin
     timer_T1 <= {$bits(timer_T1){1'b0}}; /////////// THIS IS LINE 413 ///////////
  end else if (i_clk_en) begin

     if (tick_T1)
       timer_T1 <= {$bits(timer_T1){1'b0}};
     else if (tick_8kHz)
       timer_T1 <= timer_T1 + 1'b1;

  end
end

I can't figure out what the problem is. The first issue is that it's not clear to me what "Can't replace lvalue assignments with const var" means. But the most annoying part is that if I verilate the file standalone separate from the rest of the project source files with no source changes whatsoever then the module builds fine. That's a pain because I've been trying to create a very small example to reproduce the error that I can send you but I can't get the error to happen outside of this large project.

Another annoying part is that verilator seems to be totally arbitrary in what it chooses to report this error on. For example, I have the following always block immediately below the above code which is identical except the register name is different, and verilator does not report the internal error:

logic [7:0] timer_T2;

always_ff @(posedge i_clk)
begin
  if (i_rst || i_ls_en) begin
     timer_T2 <= {$bits(timer_T2){1'b0}};
  end else if (i_clk_en) begin

     if (tick_T2)
       timer_T2 <= {$bits(timer_T2){1'b0}};
     else if (tick_8kHz)
       timer_T2 <= timer_T2 + 1'b1;

  end
end

There are other always blocks in the file that are all very similar. Some I get the error on some I don't. The only way I have been able to get rid of the error (just temporarily) is to delete the offending line completely. Obviously that breaks my design but it at least let's me get the rest of the project built - which did build without any additional errors.

Any ideas? I'll keep trying to reproduce the error in a smaller example but I honestly don't think it's going to be possible. I've tried everything I can think of...

@veripoolbot
Copy link
Contributor Author

@veripoolbot veripoolbot commented Oct 19, 2014


Original Redmine Comment
Author Name: Jonathon Donaldson
Original Date: 2014-10-19T04:01:52Z


Couple hours later and still trying to figure this out. The last new thing I tried was to enable the --debug options on the verilator command line. Every option I tried, including various debug levels, resulted in verilator core dumping. Not sure why that's happening.

Also, I tried using "--debugi- " on the cpu_reg_file.sv and I could never get verilator to output anything at all. Is it possible there is a bug in that switch? For <src_file> I tried specifying just "cpu_reg_file.sv" by itself, then I tried "../design/cpu/cpu_reg_file.sv" for the full path, then I tried just "cpu_reg_file" for the module name. None of those options work for me. Am I getting the syntax right? I'm using it like this:


--debugi-../design/cpu/cpu_reg_file.sv 10

@veripoolbot
Copy link
Contributor Author

@veripoolbot veripoolbot commented Oct 19, 2014


Original Redmine Comment
Author Name: Wilson Snyder (@wsnyder)
Original Date: 2014-10-19T14:13:47Z


Internal errors as you guessed shouldn't happen, which is why the message is non-obvious.

That the problem is hard to pin down and moves suggests it is an optimizer issue. Indeed, V3Gate is an optimization step.

debugi takes a verilator source filename:

--debugi-V3Gate 9

For the crash with --debug, run with --gdbbt and it should say where the problem is.

As to the bug I would guess it thinks timer_T1 is constant, and somehow it's getting confused substituting in that constant. Maybe tick_T1 is always set, so that is why the tick_T2 version doesn't show the same bug? Anywhow with --debugi-V3Gate 5 you should get a lot of output, and see some printout "elimUsePre" just before the crash which will be helpful in fixing this.

@veripoolbot
Copy link
Contributor Author

@veripoolbot veripoolbot commented Oct 19, 2014


Original Redmine Comment
Author Name: Jonathon Donaldson
Original Date: 2014-10-19T19:58:47Z


Okay, so I figured out what the issue was. W00t! Unfortunately the "--debugi-V3Gate 5" wasn't very useful since it was hard to decipher, but your comments about optimizing along with verilator possibly thinking a signal was constant/unchanging helped me to track it down.

As I continued through incrementally getting the rest of the source files together and getting everything verilated, I went back and un-deleted the few lines that had been causing the internal error and tried to rebuild. When I built this time verilator no longer reported the error. Success!! But the obvious question is, "So what changed?". I had to figure out what the original source of the problem was or it would have bothered me from now until the end of time.

Fortunately I have the project under revision control so I simply diff'd all of my changes until I saw something that looked like it might have fixed the problem. The one change that I found was that I was previously tying the clock-enable (clk_en) signal in my clock generator module to 1'b0 because I was eventually going to pull that clock-enable line out to the top-level and drive it with my SystemC code. But at the time I didn't want to deal with it right away so I just tied it to a constant.

So I undid all my latest changes, got verilator to report the internal error again, and then tried the following:

  • Tied clk_en to 1'b1 instead of 1'b0. FIXED!
  • Left clk_en tied to 1'b0, but deleted "if (i_clk_en)" from the offending always block. FIXED!
  • Pulled clk_en out to top-level pin (which was my original plan in the first place). FIXED!

Unfortunately, I still can't get the internal error to occur outside of this one project. I tried creating an entirely separate smaller project with an identical hierarchy, module names, and signal names, but no matter what I did I couldn't get verilator to report the error. I was hoping I'd be able to send you something but I guess not. At least I was able to tell you the exact source of the problem. :)

Thanks for your insight it really helped. My entire design now builds and runs fine. We'll chalk this one up to user error. :)

Also, I tried using --gdbbt to figure out why --debug was causing a core-dump (seg fault) but there was no additional output from verilator. I compared one log file without --gdbbt and another log file with --gdbbt and the only thing that changed was the hexadecimal values. Am I doing something wrong? What am I supposed to see if I enable --gdbbt?

@veripoolbot
Copy link
Contributor Author

@veripoolbot veripoolbot commented Oct 20, 2014


Original Redmine Comment
Author Name: Wilson Snyder (@wsnyder)
Original Date: 2014-10-20T23:33:18Z


I tried a few simple tests and also couldn't make this. Now that you're not blocked I'll mark it closed without enough info, if you get a test case, please reopen, thanks.

@veripoolbot
Copy link
Contributor Author

@veripoolbot veripoolbot commented Feb 2, 2016


Original Redmine Comment
Author Name: Johan Bjork
Original Date: 2016-02-02T19:42:36Z


We just ran into the same issue.
As with the original reporter, I've had no luck reproducing this in a smaller design.

Couple of insights:

  1. Removing the check makes things compile and seemingly work as expected
  2. It does not happen during optimizeSignals, but later in the dedupe stage.
  3. The GateVarVertex in GateDedupeGraphVisitor::visit that triggers the issue has one node "in" and vvertexp->inBeginp->fromp() points to an always block that looks something like this
ALWAYS
  IF
     VARREF clk
     ASSIGNDLY
       CONST
       VARREF (this is the varref that matches the vvertexp varscope)

  1. vvertexp contains an out edge to the same always block, and when calling GateElimVisitor on above block it fails as the varref is an lvalue.
    (likely invalid, but since I don't really understand the code yet, removing the m_graph.removeRedundantEdgesSum(&V3GraphEdge::followAlwaysTrue) also makes the problem go away)

Any ideas?

@veripoolbot
Copy link
Contributor Author

@veripoolbot veripoolbot commented Nov 14, 2016


Original Redmine Comment
Author Name: Richard Swetz
Original Date: 2016-11-14T15:15:06Z


I have run into this error periodically. It definitely comes and goes so to speak. My observation is that it is related to having two blocks of nearly identical logic as the original reporter.

Note that Timer_T1 and Timer_T2 produce the exact same value on if tick_t1 and tick_t2 are driven by the same logic.

In my case, they were two identical blocks ... whose output drove two different things ... the purpose for this was physical placement due to one block's output crossing a clock boundary and one not. (I used synthesis directive that made the two block place differently.)

It seems to me that what verilator is getting hung up on is that it probably identified the two blocks as identical and created a single model rather than one. It has trouble assigning a constant to something that is already a constant (unlike assigning the same RHS which becomes an OR).

I hope this helps those familiar with Verilator code.

My "solution" was to modular to the blocks and instantiate twice. It seems to avoid the internal error ... at least for today.

@veripoolbot
Copy link
Contributor Author

@veripoolbot veripoolbot commented Nov 14, 2016


Original Redmine Comment
Author Name: Wilson Snyder (@wsnyder)
Original Date: 2016-11-14T17:49:35Z


Sorry you're still seeing this. The error specifically is that the optimizer sees duplicate logic and is basically attempting to make code like "1'b0 <= ..." that is assigning something to a constant rather than a variable, which is obviously illegal. I had several examples looking for simple duplicates but couldn't make a test case; if anyone can create one it'll probably be straight forward to fix.

Or, if ideally if someone wants to debug further, use "--debug --debugi-V3Gate 5" (or higher), and trace the node number that the error message prints out backwards through the log files to identify where it went wrong.

@veripoolbot
Copy link
Contributor Author

@veripoolbot veripoolbot commented Dec 6, 2019


Original Redmine Comment
Author Name: Driss Hafdi
Original Date: 2019-12-06T15:14:29Z


We've recently come across this issue and have managed to reproduce it in a small testbench. You can find it in the last commit here: https://github.com/drissos/verilator/tree/lvalue-const-issue
It is very unclear to me what's actually causing the issue and don't know enough about the codebase to attempt a fix.

@veripoolbot
Copy link
Contributor Author

@veripoolbot veripoolbot commented Dec 6, 2019


Original Redmine Comment
Author Name: Wilson Snyder (@wsnyder)
Original Date: 2019-12-06T22:22:48Z


Thanks for tracking it down, and to a small case no less, will take a look.

@veripoolbot
Copy link
Contributor Author

@veripoolbot veripoolbot commented Dec 7, 2019


Original Redmine Comment
Author Name: Wilson Snyder (@wsnyder)
Original Date: 2019-12-07T21:53:30Z


If there was two logic blocks that constant propagated to be identical, they cross connected, and one had a recirculation term back to itself, then when Verilator attempted to remove the duplicate logic it may result in this error.

Fixed in git towards 4.024.

@veripoolbot
Copy link
Contributor Author

@veripoolbot veripoolbot commented Dec 8, 2019


Original Redmine Comment
Author Name: Wilson Snyder (@wsnyder)
Original Date: 2019-12-08T13:11:04Z


In 4.024.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.