Fix showing reference locations for BLKANDNBLK (#2170).

This commit is contained in:
Wilson Snyder 2020-12-09 23:07:11 -05:00
parent a1322635fd
commit 53ce708294
3 changed files with 34 additions and 12 deletions

View File

@ -17,6 +17,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
**** Fix DPI open array handling issues.
**** Fix showing reference locations for BLKANDNBLK (#2170). [Yuri Victorovich]
* Verilator 4.106 2020-12-02

View File

@ -71,9 +71,10 @@ private:
// AstVarScope::user2p() -> AstActive*. Points to activity block of signal
// (valid when AstVarScope::user1p is valid)
// AstVarScope::user4p() -> AstAlwaysPost*. Post block for this variable
// AstVarScope::user5() -> VarUsage. Tracks delayed vs non-delayed usage
// AstVarScope::user5p() -> AstVarRef*. Last blocking or non-blocking reference
// AstVar::user2() -> bool. Set true if already made warning
// AstVarRef::user2() -> bool. Set true if already processed
// AstVarRef::user5() -> bool. Set true if was blocking reference
// AstAlwaysPost::user2() -> ActActive*. Points to activity block of signal
// (valid when AstAlwaysPost::user4p is valid)
// AstAlwaysPost::user4() -> AstIf*. Last IF (__Vdlyvset__) created under this AlwaysPost
@ -86,8 +87,6 @@ private:
AstUser4InUse m_inuser4;
AstUser5InUse m_inuser5;
enum VarUsage : uint8_t { VU_NONE = 0, VU_DLY = 1, VU_NONDLY = 2 };
// STATE
AstActive* m_activep = nullptr; // Current activate
AstCFunc* m_cfuncp = nullptr; // Current public C Function
@ -104,13 +103,28 @@ private:
// METHODS
VL_DEBUG_FUNC; // Declare debug()
void markVarUsage(AstVarScope* nodep, uint32_t flags) {
// UINFO(4, " MVU " << flags << " " << nodep << endl);
nodep->user5(nodep->user5() | flags);
if ((nodep->user5() & VU_DLY) && (nodep->user5() & VU_NONDLY)) {
nodep->v3warn(BLKANDNBLK,
"Unsupported: Blocked and non-blocking assignments to same variable: "
<< nodep->varp()->prettyNameQ());
void markVarUsage(AstNodeVarRef* nodep, bool blocking) {
if (blocking) nodep->user5(true);
AstVarScope* vscp = nodep->varScopep();
// UINFO(4, " MVU " << blocking << " " << nodep << endl);
if (!vscp->user5p()) {
vscp->user5p(nodep);
} else {
AstNode* lastrefp = vscp->user5p();
bool last_was_blocking = lastrefp->user5();
if (last_was_blocking != blocking) {
AstNode* nonblockingp = blocking ? nodep : lastrefp;
AstNode* blockingp = blocking ? lastrefp : nodep;
vscp->v3warn(
BLKANDNBLK,
"Unsupported: Blocked and non-blocking assignments to same variable: "
<< vscp->varp()->prettyNameQ() << '\n'
<< vscp->warnContextPrimary() << '\n'
<< blockingp->warnOther() << "... Location of blocking assignment\n"
<< blockingp->warnContextSecondary() << '\n'
<< nonblockingp->warnOther() << "... Location of nonblocking assignment\n"
<< nonblockingp->warnContextSecondary());
}
}
}
AstVarScope* createVarSc(AstVarScope* oldvarscp, const string& name,
@ -412,7 +426,7 @@ private:
if (!nodep->user2Inc()) { // Not done yet
if (m_inDly && nodep->access().isWriteOrRW()) {
UINFO(4, "AssignDlyVar: " << nodep << endl);
markVarUsage(nodep->varScopep(), VU_DLY);
markVarUsage(nodep, true);
UASSERT_OBJ(m_activep, nodep, "<= not under sensitivity block");
UASSERT_OBJ(!nodep->access().isRW(), nodep, "<= on read+write method");
if (!m_activep->hasClocked()) {
@ -463,7 +477,7 @@ private:
// UINFO(9, "NBA " << nodep << endl);
if (!m_inInitial) {
UINFO(4, "AssignNDlyVar: " << nodep << endl);
markVarUsage(nodep->varScopep(), VU_NONDLY);
markVarUsage(nodep, false);
}
}
}

View File

@ -1,4 +1,10 @@
%Error-BLKANDNBLK: t/t_order_blkandnblk_bad.v:17:21: Unsupported: Blocked and non-blocking assignments to same variable: 't.array'
17 | logic [1:0][3:0] array;
| ^~~~~
t/t_order_blkandnblk_bad.v:19:16: ... Location of blocking assignment
19 | always_comb array[0] = i;
| ^~~~~
t/t_order_blkandnblk_bad.v:22:6: ... Location of nonblocking assignment
22 | array[1] <= array[0];
| ^~~~~
%Error: Exiting due to