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
Detect and warn appropriately on intentional latches #1609
Comments
Original Redmine Comment Not sure I'm interpreting the question correctly, but... Verilator doesn't presently identify self-identify latches (unless always_latch is used). If you'd like to contribute something to do this, and e.g. issue a LATCH warning and suppress the COMBDLY warning, I think that would be valuable. You would of course still need to disable the LATCH warning at the appropriate spots. |
Original Redmine Comment To ignore intentional standalone latches I think I need to update class ActiveDlyVisitor to supress the warning if the following conditions are met:
Exactly how to determine each of this things will be a bit of a learning exercise for me, (the first 2 look easy enough to figure out) but i'm keen to give it a go to understand the internals :) |
Original Redmine Comment Great, would be awesome to get this in. The sensitivity list will at that point have some elements with combo on it. We should support arbitrary latches, it's fine to e.g. have reset or multiple assignments e.g.
First step would be to make a test file with a bunch of examples in it, run with debug and look at the *_delayed.tree file. Logic would then build a V3Graph consisting of:
Now you can dump the graph (.dot) and see if it's what you expect for your example. Then to report, traverse the graph making sure every path from input lands at every output. Note V3Split has a lot of similar concepts, though more complicated. Search for V3Graph there's a lot of examples. What really makes a latch is some output is not set in all control flow paths. Then do the following: if always && latch_detected => suppress COMBDLY, add a new LATCH warning suggesting fixing terms or use of always_latch. |
Original Redmine Comment Work in progress, but I have this basically working. I still need to generate more test cases and to also run a full regression. I have implemented as a new pass called V3Latch, which may be a bit heavy weight (its only ~200 LOC) but it seemed the cleanest way to isolate the changes. |
Original Redmine Comment Great, let me know when you have something for review. I'd also suggest running it on SweRV to see if it flags anything. Leaving it V3Latch while you work on it is fine, we'll see what it looks like in the end as to if it should be wedged elsewhere. |
Original Redmine Comment Hi Julien, I would like to help you out on this task. Is there anything that you would like to get off your plate? Best Regards |
Original Redmine Comment This is pretty much complete I think, and seems to work well on the examples I have tried it on. PS: I'm sure this could be combined with the V3Active pass very easily if required, as most of the work is done in the new V3LatchGraph class |
Original Redmine Comment Wow, great stuff, I was expecting a LOT of questions before you had a fix!
Had one minor issue, you need to add the .cpp file to src/Makefile_obj.in, I suspect you edited src/Makefile_obj but that's generated. Please add some test cases that you believe test every non-internal-error branch in the code, see for example t_const_bad.*.
Yes, please do that, as otherwise it is runtime-harmful.
Nit, please insert in sorted order. Think you also want a LATCH warning (when any latch NOT in always_latch)?
I pushed this.
Need e.g. V3LATCH_ prefix on these (or renamed appropriately for whatever CPP file lands in), but it's probably cleaner to make an enum.
Likewise, need a prefix. Space indent "# define". Use // comment. However, where this is used the only expensive one is "OUTPUT "+name, so perhaps just always do it and change that one not to have the "OUTPUT " prefix. Another alternative is to hold the AstNode* in the vertex, which has the upside of making debug show the node information if needed.
m_ on all members. p suffix on pointers. Comment on members. "*" goes next to type. (Note clang-format will fix it for you, but it makes some things ugly). e.g.:
Move into the for initializer.
Probably faster to have a clear() method and avoid re-new'ing.
If you use vertexp->user() instead of color you can then use m_graph.userClearVertices();
const string& name
Yes, once you have AstUser1InUse, or call user1ClearTree()
Yes.
if (debug() >= 9). Then run with "--debugi-V3Latch 9"
m_graph.dumpDotFilePrefixed("latch");
Please use an iterator instead.
Use new LATCH warning.
clear()?
Please rename m_graphp to match other places.
Please add m_enable = false here, as might be false-set from some earlier SenItem.
This leaks (I think) for SenItem not under Always. Perhaps make once in constructor (don't need a pointer then), then m_graph.clear() on entry to AstAlways?
Need m_graphp = NULL, but by earlier comments perhaps not a pointer any longer. |
Only just got back to this, sorry. Thanks for the review. I am tidying this up now. A few comments/questions first:
I did originally do this, but found removeRedundantEdges also uses the user field so currupted the graph in "debug" mode. color() seemed the next most logical field to use.
My reason for using EC_INFO here, instead of a new warning, was that I wanted an informational message which did not need to be supressed in order to successfully verilate the file in question. Because always_latch is SystemVerilog it cannot always be used. In my case, the file in question is third party IP, which cannot be modified, and must be compiled as pure Verilog. Is there a better way to issue a non-fatal warning? |
Also, when merging into V3Active, shall I keep V3LatchGraph in it's own source file, or move the whole lot into V3Active.cpp? |
Use LATCH, and mark it as a lintError() . If the user doesn't want it they can use -Wno-LATCH on the command line. Please merge it into V3Active.cpp. |
Getting there. Now 24 regression tests fail due to detected latches :) Need to review these and make sure they are expected. |
Am I able to push my branch? |
Let me review again and run on some private designs. |
Sorry, I've lost where your branch was, can you ideally rebase to master, then do a github pull request with it? |
It's just local at the moment, I was hoping to push to remote but I lack permissions, or I am using the wrong credentials. I branched from master on Monday BTW. |
I can't create a branch so posting another patch file: |
Compile issues:
Code review:
Suggest rename m_curVertexp;
Need comments on all member variables please.
Please use latchCheckInternal style naming instead.
Start a new if/else tracking vertex.
s/t/outVertexp/
s/out/outVertexp/
LatchDetectGraphVertex* branchp = m_graph.add_path_vertex(parentp, "BRANCH", true);
Given the var itself isn't a latch, I suggest renaming to m_isLatched,
vrp->prettyNameQ() and remove the quotes in your string.
To all fail tests, please add expect_filename => $Self->{golden_filename}, I get a lot of "make test_regress" failures. I think most all are false |
Thanks. I'll get those done. I do not see the compilation errors, could this be down to GCC version? I am using a pretty old GCC (4.8.5) on RedHat7. I was still expecting the failures as I am yet to review them all. I think they are all due to bombing out with latch warnings, so just need to check they are genuine. About 25 to go through in my run. Would the prefered solution be to add -Wno-LATCH to the .pl files for tests which are known to create latches, or /* verilator lint_off LATCH */ to the .v files? |
It might be the new gcc, but make sure you have VERILATOR_AUTHOR_SITE in your ~/bashrc/.cshrc so when you configure you get warnings. There's probably only one or two tests that really have latches, for those please surround the lines that get warnings with the lint_off metacomments. |
Looks like this has been stalled for a while, any interest on getting it dusted off and merged in? |
Yes, very little spare bandwidth lately, but I will try ... |
So having another look at this, and it is flagging latches here in regression (one of many examples):
Looking at the code, this is a genuine latch detection since tmp_cout is not assigned in all control paths. Would you agree? |
I think that this warning is appropriate. The module here is modeling code and not meant to be RTL as I understand it. (Totally looking forward to see this Linting rule in Verilator by the way). |
@PeterMonsson, Thanks for the feedback. I am working through the regression failures. Many of them are similar to the above, and just require // verilator lint_off LATCH, which I am adding where appropriate. I have other genuine false positives which I need to look into. Many of them are due to what appear to be internally generated signals (names starting __V) which my code is not distinguishing from genuine design signals. Is there a simple AstVar attribute I should query to filter these out? I could just ignore anything with the __V prefix, but this would be a bit naff. |
I think I have answered my own question. AstVar::isSignal() seems to be what I want |
Only 2 types of false positive left in test_regress now, and one of them is this:
Is there an easy way (during the V3Active pass) to tell that the implicit else node above is an un-reachable control path? |
This isn't unreachable, it should give a LATCH warning as it is a latch if i=='x. The code should be changed to have either an else instead of elseif at the end, or to have "else o = 'x" at the end. |
Ok, it's not unreachable, but for synthesis it effectively is. I'm not sure we should emit the warning here. Synthesis (DC) does not generate a latch here, or with the equivalent (fully defined) case statement:
Verilator will currently warn with the if/else variant, but not the case variant, which doesn't feel like the right thing to do? |
Yes, we should have if/case operate the same and it's probably more intuitive to follow the synthesis rules. |
It is going to be problematic eliminating the false positives in the remaining 2 failing test cases:
Consider the following:
Even though this covers all possible (2-state) combinations of 'in' and hence always assigns 'out', Verilator converts it to a series of if/else nodes with a dangling implicit else with no asignment. Latch detection just searches for control paths without an assignment, and in this case finds one, even though no value of 'in' could ever get to it. To illustrate, here is the output C++
Can I add // verilator lint_off LATCH to these last 2 test cases and raise a PR for review anyway? |
Is your code after V3Case? V3Case does the analysis of full case, and could simply set v3warnOff LATCH on the file lines involved after analyzing them. |
I have taken the above adivce, thanks. |
Author Name: Julien Margetts
Original Redmine Issue: 1609 from https://www.veripool.org
Original Assignee: Julien Margetts
According to Cummings:
"Guideline #2: When modeling latches, use nonblocking assignments."
However, as I'm sure you are aware, Verilating the following code results in Warning-COMBDLY
/* verilator lint_off COMBDLY */ does work (as does using always_latch) but we are not permitted to modify this source
-Wno-COMBDLY also works but I don't want to turn this warning off globally
The following config file also works:
I'm happy to use the config file as it allows me to re-enable to warning, but is this the recommended aproach?
The reason I ask is that in the warning text:
"%Warning-COMBDLY: test.v:9: Delayed assignments (<=) in non-clocked (non flop or latch) block: ... Suggest blocking assignments (=)"
"non flop or latch" Implies verilator did not recognise this was an intentional latch.
The text was updated successfully, but these errors were encountered: