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
generate-conditional with short-circuited local expression #413
Comments
Original Redmine Comment I knew about the side effect part related to ++ and --, but this is an interesting case. I'm surprised that & also short circuits. What Verilator is seeing is the MASK[CONSTANT] and throwing the warning on that in isolation. It performs this check before it processes the block as part of the data type resolution, so doesn't (yet) know it won't be executed. The fix isn't obvious, it has to process the expression before evaluating it due to Verilog's nasty width resolution rules. Maybe it needs to remember the error and only throw it later, or in the case of generates check later, but not too late as all of the constants will soon be folded in. This'll need some thought. |
Original Redmine Comment A little more digging in the standards by a colleague found exactly how this should behave. If is section 4.2.1 in IEEE 1354-2001 (Verilog) and section 11.5.1 in IEEE 1800-2009 (SystemVerilog) "Vector bit-select and part-select addressing":
Thus, it would seem to be fully legal to access a vector out-of-bounds as in this case in either Verilog or SystemVerilog, and the result from this look-up must be considered x. |
Original Redmine Comment I'm looking further into this bug. For convenience, I have created a rather simpler patch, which I attach as a diff against git HEAD (commit 0ae00fc). |
Original Redmine Comment I also extended the initial test cases back when this was filed and can make them ready when/if you'd like to work on this. |
Original Redmine Comment Here is a patch to deal with this. It only affects generated @if@, since the test in generated @for@ loops is restricted to simple comparisons at present in Verilator, while in generated @case@ blocks, the dependency is on a constant expression, with much less scope for short-circuiting. We set a flag (@m_generate@) in @WidthVisitor@ to indicate that we are inside a generate block for which selection width errors should be ignored. We don't print the error and we don't reduce the width in this case. When constifying the condition of a generated if, we set a flag for @ConstVisitor@ to indicate we are in the generate block. This has two effects.
To make this work, I had to modify astgen. I added an optional third argument to TREEOP, which I used to indicate the visit function should not be generated automatically. I could then substitute hand-written versions for @AstLogAnd@, @astand@, @AstLogOr@ and @Astor@ to do short-circuiting. I'm not a PERL expert, but ultimately it would be good to provide this automatically through a third argument. I've extended the test case to check all the possible short-circuiting operations. Supplied as a git patch against current HEAD (commit 4a5e775). |
Original Redmine Comment Great, I'm still digesting! I need to think about how to get what you want with the astgen visitors without actually overriding the function as I don't want to maintain a hand written visitor. |
Original Redmine Comment I added to git a t_dpi_shortcircuit test. It's currently disabled. I also added a patch to do the emacs indentation part of this patch. I'd like your thoughts on the overall approach, since ideally the solution wouldn't care about parameters, because we'll want short circuiting to apply to everything not just parmameters eventually. One alternative might be to use V3Simulate.h to determine what to execute. I'll email some general thoughts on the patch itself. |
Original Redmine Comment Updated patch, which has a modified TREEOP to generate short-circuited visitors. Various improvements to the C++ code as suggested by email. For general short-circuiting, the C compiler will presumably do this, even if we do not. However we may be able to generate smaller programs if we can short-circuit constants within Verilator to prune unused code. Potentially that opens up other optimizations (pruning code often does). I haven't tried the DPI short-circuit test yet. |
Original Redmine Comment Some more changes, following email discussion. This is now strictly IEEE 1800-2009. Short-circuiting is used only for && || -> and ?:, and is applied both to generate IF statements and expressions in general. I've added a new set of tests to check that this fails when it should. For example with bitwise & and | and where there are selection width errors remaining after short-circuiting. Attached as a tar and bzipped git format-patch against current HEAD (commit 7eb407f) |
Original Redmine Comment I ran "make test" and it showed two failures t_lint_unused_bad and t_lint_syncasyncnet_bad, related to short circuiting suppressing variable unused warnings. To match what GCC and other tools do, "0 && a" should still consider "a" as a used variable. I realized though this was broken related to my last set of suggestions, and just needed to include m_doVConst in astgen. Everything is merged in, so please "git pull" and start from the mainline before sending other patches, thanks. (BTW your using a github account would be useful.) Fixed in git towards 3.840. |
Original Redmine Comment In 3.840. |
Author Name: Jeremy Bennett (@jeremybennett)
Original Redmine Issue: 413 from https://www.veripool.org
Original Date: 2011-11-04
Original Assignee: Jeremy Bennett (@jeremybennett)
In C, conditional expressions are "short-circuited". For example @((i < MAX) && (a[i] == 0))@ will not evaluate @A[i]@ if @i@ is not less than @max@.
The same is not true of Verilog, which leaves it to the implementation to decide whether to carry out such short-circuiting. SystemVerilog removes the ambiguity to follow the same rule as C.
This means that in SystemVerilog at least the following should not cause a problem:
Even though @ACTSIZE@ is less than @maxsize@, @Mask[g]@ will only be evaluated when @g@ is less than ACTSIZE. However Verilator gets this wrong, and throws an error trying to access @Mask[4]@ through @Mask[7]@. Other tools accept this (with Verilog of SystemVerilog).
A variant is where the boolean AND (@&&@) is replaced by a bitwise AND (@&@). This would seem to be wrong by any standard, but other tools all accept it. The problem was only found in the source when Verilator threw an error.
The attached test exercises the first case in module @foobar@, and the second in module @BarFoo@.
The following web page provides some helpful discussion of the language standard issue: http://stackoverflow.com/questions/3224553/does-verilog-support-short-circuit-evaluation.
The text was updated successfully, but these errors were encountered: