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

Don't crash when attempting to dot index into an interface array #978

Closed
veripoolbot opened this issue Oct 4, 2015 · 13 comments
Closed
Labels
resolution: fixed Closed; fixed

Comments

@veripoolbot
Copy link
Contributor


Author Name: Johan Bjork
Original Redmine Issue: 978 from https://www.veripool.org
Original Date: 2015-10-03
Original Assignee: Johan Bjork


Verilator crashes with an internal error when trying to index with a constant into an interface. See #� for more details on the simple (and the more complicated case). This patch fixes the internal error for the simple case where you use a constant index into an interface array.

This does not attempt to address either #� or the array'ed interfaces issue in 879.

Previously the testcase would fail with:

%Error: Internal Error: t/t_array_interface.v:19: ../V3Broken.cpp:220: Broken link in node (or something without maybePointedTo): m_cellp && !m_cellp->brokeExists()
%Error: Internal Error: See the manual and http://www.veripool.org/verilator for more assistance.
%Error: Command Failed /Users/phb/DEV/verilator//verilator_bin --prefix Vt_array_interface --x-assign unique -cc -Mdir obj_dir/t_array_interface -OD --debug-check --clk clk -f input.vc t/t_array_interfa

Patch can be accessed at https://github.com/phb/verilator-asserts/tree/ifracerefdtype

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Wilson Snyder (@wsnyder)
Original Date: 2015-10-04T15:08:24Z


Thanks, the logical part of the patch makes sense but the test case needs to pass to commit.

V4$ test_regress/t/t_array_interface.pl --vlt
%Error: t/t_array_interface.v:6: syntax error, unexpected if, expecting IDENTIFIER or PACKAGE-IDENTIFIER or TYPE-IDENTIFIER
%Error: t/t_array_interface.v:8: syntax error, unexpected modport
%Error: t/t_array_interface.v:19: syntax error, unexpected IDENTIFIER, expecting '('

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Johan Bjork
Original Date: 2015-10-04T15:09:40Z


Hm, sounds like I messed up my push, that should have been fixed already. Give me a few minutes to clean that up.

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Johan Bjork
Original Date: 2015-10-04T15:11:27Z


https://github.com/phb/verilator-asserts/tree/ifacerefdtype -- seems I had a typo in the branch name for the first push that contained the testcase bug)

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Wilson Snyder (@wsnyder)
Original Date: 2015-10-04T15:19:22Z


Great! Pushed to git towards 3.877.

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Johan Bjork
Original Date: 2015-10-10T00:44:12Z


Unfortunately I've come to realize that this patch is actually fundamentally broken. Sorry for the inconvenience, but can you please back out the change? (Couple of issues with the patch, fundamentally it's doing this at the wrong stage, the constant values has not been calculated yet and alas it was just a pure coincidence that the tests passed.)

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Wilson Snyder (@wsnyder)
Original Date: 2015-10-10T11:55:13Z


Ok, thanks for the notice. I backed it out, but kept the test with it marked as broken - remove the one line in the test's .pl file when fixing it please.

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Johan Bjork
Original Date: 2015-10-20T23:39:55Z


Wilson,

This turned out to be a lot harder then I initially expected.

I'm sort of happy with my latest attempt, however, there are two potential deal breakers.
I'd love some feedback if you think this approach makes any sense, and specifically feedback on two comments I've left in V3Param.cpp (Ensuring parameterized interfaces get relinked) and V3Inst.cpp (Creating a AstVar w/o using V3LinkDot)

https://github.com/phb/verilator-dev/tree/#�

I've expanded the test in question to try and ensure that this is actually working as expected. All prior tests are also passing with this version.

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Wilson Snyder (@wsnyder)
Original Date: 2015-10-21T11:01:08Z


+++ b/src/V3Inst.cpp
+    std::map<string,AstVar*> m_seenInterfaceVarp;

A later comment will get rid of this, but next time please add and use something like:

typedef std::map<string,AstVar*> SeenIfNameMap;


+++ b/src/V3Inst.cpp
@@ -217,6 +244,29 @@ private:
+       } else if(AstArraySel *arrselp = nodep->exprp()->castArraySel()) {
+           if (AstUnpackArrayDType *arrp = arrselp->lhsp()->dtypep()->castUnpackArrayDType()) {
+               if (!arrp->subDTypep()->castIfaceRefDType())
+                   return;
+
+               AstConst *constp = arrselp->rhsp()->castConst();
+               if (!constp) {
+                   nodep->v3error("Unsupported: Non-constant index when passing interface to module");

Need a return or something here, otherwise the next line is going to core dump.

+               }
+               string index = AstNode::encodeNumber(constp->toSInt());
+               AstVarRef *varrefp = arrselp->lhsp()->castVarRef();
+
+               AstVarRef *newp = new AstVarRef(nodep->fileline(),varrefp->name () + "__BRA__" + index  + "__KET__", false);
+               newp->dtypep(arrp->subDTypep());
+               //Wilson: I'm looking for a way to do this in a better way. My original attempt was to call V3LinkDot again after the V3Inst stage
+               //But the Ast has progressed too far and V3LinkDot messes it up (notably the t_lint_ifdepth_bad.pl test fails
+               //because it thinks the variable is defined twice.
+               // Also, this is not setting newp->packagep(). I hope you can give advice on how to do this properly.

Right, in general outside LinkDot code can't ever connect using a name
lookup. LinkDot also can't be called elsewhere. I think however you could
make a VarXRef, which requires a link to any element of the interface
"newp->varp(varrefp->varp())", then the name will get resolved by V3LinkDot
later.

For newp, the variable you're referencing is in the same scope as varrefp,
right, so just "newp->packagep(verrefp->packagep())".  Otherwise you'd need
to find the package to which the variable you reference lives, perhaps by
storing that information in a earlier visitor pass.



+++ b/src/V3LinkCells.cpp
+               if (nodep->rangep()) {
+                   string varName = nodep->name() + "__Viftop";  // V3LinkDot looks for this naming
+                   AstIfaceRefDType *idtypep = new AstIfaceRefDType(nodep->fileline(), nodep->name(),
+                                                                    nodep->modp()->name());
+                   idtypep->ifacep(NULL);  // cellp overrides
+
+                   AstNodeArrayDType *newp = new AstUnpackArrayDType(nodep->fileline(),VFlagChildDType(),
+                   AstVar *varp = new AstVar(nodep->fileline(), AstVarType::IFACEREF, varName,
+                                             VFlagChildDType(), newp);
+                   varp->isIfaceParent(true);
+                   nodep->addNextHere(varp);
+                   nodep->hasIfaceVar(true);
+               } else {
+                   string varName = nodep->name() + "__Viftop";  // V3LinkDot looks for this naming
+                   AstIfaceRefDType *idtypep = new AstIfaceRefDType(nodep->fileline(), nodep->name(),
+                                                                    nodep->modp()->name());
+                   idtypep->cellp(nodep);  // Only set when real parent cell known
+                   idtypep->ifacep(NULL);  // cellp overrides
+                   AstVar *varp = new AstVar(nodep->fileline(), AstVarType::IFACEREF, varName,
+                                             VFlagChildDType(), idtypep);
+                   varp->isIfaceParent(true);
+                   nodep->addNextHere(varp);
+                   nodep->hasIfaceVar(true);
+               }

Please move the common code inside the if/else to above/below the if.


+++ b/src/V3Param.cpp
             AstVar* modvarp = pinp->modVarp();
             if (modvarp->isIfaceRef()) {
                 AstIfaceRefDType* portIrefp = modvarp->subDTypep()->castIfaceRefDType();
+               AstIfaceRefDType* pinIrefp = NULL;
+               AstNode *exprp = pinp->exprp();
+               // Wilson: So eh, this is pretty awkward and awfully specific, will likely not work the minute we're not dealing with constants
+               // This can likely be sort of cleaned up with some helpers, but it's really ugly.
+               // Any advice is appreciated
+               if (exprp
+                       && exprp->castVarRef()
+                       && exprp->castVarRef()->varp()
+                       && exprp->castVarRef()->varp()->subDTypep()
+                       && exprp->castVarRef()->varp()->subDTypep()->castIfaceRefDType())
+                       pinIrefp = exprp->castVarRef()->varp()->subDTypep()->castIfaceRefDType();
+               else if (exprp
+                               && exprp->op1p()
+                               && exprp->op1p()->castVarRef()
+                               && exprp->op1p()->castVarRef()->varp()
+                               && exprp->op1p()->castVarRef()->varp()->subDTypep()
+                               && exprp->op1p()->castVarRef()->varp()->subDTypep()->castUnpackArrayDType()
+                               && exprp->op1p()->castVarRef()->varp()->subDTypep()->castUnpackArrayDType()->subDTypep()
+                               && exprp->op1p()->castVarRef()->varp()->subDTypep()->castUnpackArrayDType()->subDTypep()->castIfaceRefDType())

I think this may be ok.  V3Param will already have constants for the sizes,
so that's ok, and there's only a couple of legal formats for connecting to
the interface.

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Johan Bjork
Original Date: 2015-10-22T04:31:44Z


Thanks for the quick feedback. I've spent some time trying to change the V3Inst code to create an AstVarXRef instead without much luck. The stages following V3Inst seems to be pretty strict about the Pin being connected to an AstVarRef.

There is a function/stage pinReconnectSimple which I don't quite understand yet -- however, it seems to wrap a pin expression in a temporary Var to ensure the Pin is only directly connected to an AstVarRef. Is that the code you had in mind that would deal with the AstVarXRef ?

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Johan Bjork
Original Date: 2015-10-22T22:37:08Z


Got it working. I'll clean up the changes and send a new patch later tonight.

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Johan Bjork
Original Date: 2015-10-23T01:25:16Z


rebased, updated version here: https://github.com/phb/verilator-dev/tree/#�

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Wilson Snyder (@wsnyder)
Original Date: 2015-10-24T03:06:31Z


Thanks, pushed to git towards 3.878.

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Wilson Snyder (@wsnyder)
Original Date: 2015-11-01T13:23:34Z


In 3.878.

@veripoolbot veripoolbot added the resolution: fixed Closed; fixed label Dec 22, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
resolution: fixed Closed; fixed
Projects
None yet
Development

No branches or pull requests

1 participant