From e498b739333a92d3f99e1d524c665c49d83e7493 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Mon, 7 May 2012 23:42:58 -0400 Subject: [PATCH] Internals: Misc tristate merges. Pins renamed but... No functional change intended. --- src/V3Inst.cpp | 14 +++++---- src/V3Inst.h | 2 +- src/V3Tristate.cpp | 51 +++++++++++++++++++-------------- test_regress/t/t_tri_gate.cpp | 3 +- test_regress/t/t_tri_select.cpp | 5 ++-- test_regress/t/t_tri_select.v | 11 ++++--- test_regress/t/t_tri_various.v | 3 ++ 7 files changed, 55 insertions(+), 34 deletions(-) diff --git a/src/V3Inst.cpp b/src/V3Inst.cpp index 272a9a494..18d689cb1 100644 --- a/src/V3Inst.cpp +++ b/src/V3Inst.cpp @@ -236,7 +236,8 @@ public: //###################################################################### // Inst class functions -AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModule*, bool forTristate) { +AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModule*, + bool forTristate, bool alwaysCvt) { // If a pin connection is "simple" leave it as-is // Else create a intermediate wire to perform the interconnect // Return the new assignment, if one was made @@ -248,11 +249,13 @@ AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModu AstAssignW* assignp = NULL; if (connectRefp) connBasicp = connectRefp->varp()->dtypep()->basicp(); // - if (connectRefp + if (!alwaysCvt + && connectRefp && connectRefp->varp()->dtypep()->sameTree(pinVarp->dtypep()) && !connectRefp->varp()->isSc()) { // Need the signal as a 'shell' to convert types // Done. Same data type - } else if (connBasicp + } else if (!alwaysCvt + && connBasicp && pinBasicp && connBasicp->width() == pinBasicp->width() && connBasicp->lsb() == pinBasicp->lsb() @@ -260,13 +263,14 @@ AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModu && connBasicp->width() == pinVarp->width() && 1) { // Done. One to one interconnect won't need a temporary variable. - } else if (!forTristate && pinp->exprp()->castConst()) { + } else if (!alwaysCvt && !forTristate && pinp->exprp()->castConst()) { // Done. Constant. } else { // Make a new temp wire //if (1||debug()>=9) { pinp->dumpTree(cout,"in_pin:"); } AstNode* pinexprp = pinp->exprp()->unlinkFrBack(); - string newvarname = "__Vcellinp__"+cellp->name()+"__"+pinp->name(); + string newvarname = ((pinVarp->isOutput() ? "__Vcellout__" : "__Vcellinp__") + +cellp->name()+"__"+pinp->name()); AstVar* newvarp = new AstVar (pinVarp->fileline(), AstVarType::MODULETEMP, newvarname, pinVarp); // Important to add statement next to cell, in case there is a generate with same named cell cellp->addNextHere(newvarp); diff --git a/src/V3Inst.h b/src/V3Inst.h index 710c76057..16d6553b6 100644 --- a/src/V3Inst.h +++ b/src/V3Inst.h @@ -34,7 +34,7 @@ public: static void instAll(AstNetlist* nodep); static void dearrayAll(AstNetlist* nodep); static AstAssignW* pinReconnectSimple(AstPin* nodep, AstCell* cellp, AstNodeModule* modp, - bool forTristate); + bool forTristate, bool alwaysCvt=false); }; #endif // Guard diff --git a/src/V3Tristate.cpp b/src/V3Tristate.cpp index 1be80b5d4..a8cf39939 100644 --- a/src/V3Tristate.cpp +++ b/src/V3Tristate.cpp @@ -69,11 +69,11 @@ public: // Given a node, flip any VarRef from LValue to RValue (i.e. make it an input) // See also V3LinkLValue::linkLValueSet -class TristateInPinVisitor : public TristateBaseVisitor { +class TristatePinVisitor : public TristateBaseVisitor { // VISITORS virtual void visit(AstVarRef* nodep, AstNUser*) { if (nodep->lvalue()) { - UINFO(9," Flip-to-RValue "<lvalue(false); } } @@ -82,10 +82,10 @@ class TristateInPinVisitor : public TristateBaseVisitor { } public: // CONSTUCTORS - TristateInPinVisitor(AstNode* nodep) { + TristatePinVisitor(AstNode* nodep) { nodep->accept(*this); } - virtual ~TristateInPinVisitor() {} + virtual ~TristatePinVisitor() {} }; //###################################################################### @@ -144,6 +144,7 @@ class TristateVisitor : public TristateBaseVisitor { AstVarType::MODULETEMP, invarp->name()+"__en", invarp); + UINFO(9," newenv "<v3error("Unsupported: Creating tristate signal not underneath a module: "<prettyName()); } else m_modp->addStmtp(newp); invarp->user1p(newp); // find envar given invarp @@ -158,6 +159,7 @@ class TristateVisitor : public TristateBaseVisitor { AstVarType::MODULETEMP, invarp->name()+"__out", invarp); + UINFO(9," newout "<v3error("Unsupported: Creating tristate signal not underneath a module: "<prettyName()); } else m_modp->addStmtp(newp); invarp->user4p(newp); // find outvar given invarp @@ -170,6 +172,7 @@ class TristateVisitor : public TristateBaseVisitor { AstVarType::MODULETEMP, "__Vtriunconn"+cvtToStr(m_unique++), dtypep); + UINFO(9," newunc "<v3error("Unsupported: Creating tristate signal not underneath a module"); } else m_modp->addStmtp(newp); return newp; @@ -291,7 +294,7 @@ class TristateVisitor : public TristateBaseVisitor { // outvarp->user1p(envarp); outvarp->user3p(invarp->user3p()); // AstPull* propagation - if (invarp->user3p()) UINFO(9, "propagate pull to "<user3p()) UINFO(9, "propagate pull to "<user1p()) { envarp = invarp->user1p()->castNode()->castVar(); // From CASEEQ, foo === 1'bz } @@ -311,7 +314,7 @@ class TristateVisitor : public TristateBaseVisitor { AstVarType::MODULETEMP, lhsp->name()+"__out"+cvtToStr(m_unique), VFlagBitPacked(), w); // 2-state ok; sep enable - UINFO(9," newout "<addStmtp(newlhsp); refp->varp(newlhsp); // assign the new var to the varref refp->name(newlhsp->name()); @@ -326,6 +329,7 @@ class TristateVisitor : public TristateBaseVisitor { AstNode* enassp = new AstAssignW(refp->fileline(), new AstVarRef(refp->fileline(), newenp, true), getEnp(refp)); + UINFO(9," newass "<addStmtp(enassp); // now append this driver to the driver logic. @@ -432,6 +436,7 @@ class TristateVisitor : public TristateBaseVisitor { // The output enable of a cond is a cond of the output enable of the // two expressions with the same conditional. AstNode* enp = new AstCond(nodep->fileline(), condp->cloneTree(false), en1p, en2p); + UINFO(9," newcond "<user1p(enp); expr1p->user1p(NULL); expr2p->user1p(NULL); @@ -483,6 +488,7 @@ class TristateVisitor : public TristateBaseVisitor { AstNode* en1p = getEnp(expr1p); AstNode* en2p = getEnp(expr2p); AstNode* enp = new AstConcat(nodep->fileline(), en1p, en2p); + UINFO(9," newconc "<user1p(enp); expr1p->user1p(NULL); expr2p->user1p(NULL); @@ -515,7 +521,7 @@ class TristateVisitor : public TristateBaseVisitor { void visitAndOr(AstNodeBiop* nodep, bool isAnd) { nodep->iterateChildren(*this); - UINFO(9,(m_alhs?"alhs":"")<<" "<user1p()) { nodep->v3error("Unsupported LHS tristate construct: "<prettyTypeName()); return; } // ANDs and Z's have issues. Earlier optimizations convert @@ -612,6 +618,7 @@ class TristateVisitor : public TristateBaseVisitor { new AstEqCase(fl, new AstConst(fl, oneIfEnOne), varrefp)); if (neq) newp = new AstLogNot(fl, newp); + UINFO(9," newceq "<=9) nodep->dumpTree(cout,"-caseeq-old: "); if (debug()>=9) newp->dumpTree(cout,"-caseeq-new: "); nodep->replaceWith(newp); @@ -660,8 +667,9 @@ class TristateVisitor : public TristateBaseVisitor { // INPUT: -> (VARREF(trisig__pinin)), // trisig__pinin = SEL(trisig,x) // via pinReconnectSimple // OUTPUT: -> (VARREF(trisig__pinout)) + // SEL(trisig,x) = trisig__pinout + // ^-- ->user1p() == trisig__pinen // ENABLE: -> (VARREF(trisig__pinen) - // SEL(trisig,x) = BUFIF1(enable__temp, trisig__pinen) // Added complication is the signal may be an output/inout or just input with tie off (or not) up top // PIN PORT NEW PORTS AND CONNECTIONS // N/C input in(from-resolver), __out(to-resolver-only), __en(to-resolver-only) @@ -702,17 +710,18 @@ class TristateVisitor : public TristateBaseVisitor { { AstVar* enVarp = new AstVar(nodep->fileline(), AstVarType::MODULETEMP, - nodep->name() + "__en" + cvtToStr(m_unique), + nodep->name() + "__en" + cvtToStr(m_unique++), VFlagLogicPacked(), enModVarp->width()); AstPin* enpinp = new AstPin(nodep->fileline(), nodep->pinNum(), - nodep->name() + "__en" + cvtToStr(m_unique++), + enModVarp->name(), // should be {var}"__en" new AstVarRef(nodep->fileline(), enVarp, true)); enpinp->modVarp(enModVarp); enpinp->user2(true); // mark this visited m_cellp->addPinsp(enpinp); m_modp->addStmtp(enVarp); enrefp = new AstVarRef(nodep->fileline(), enVarp, false); + UINFO(9," newvrf "<=9) enpinp->dumpTree(cout,"-pin-ena: "); } // Create new output pin @@ -723,7 +732,7 @@ class TristateVisitor : public TristateBaseVisitor { AstNode* outexprp = nodep->exprp()->cloneTree(false); // Note has lvalue() set outpinp = new AstPin(nodep->fileline(), nodep->pinNum(), - nodep->name() + "__out"+cvtToStr(m_unique), + outModVarp->name(), // should be {var}"__out" outexprp); outpinp->modVarp(outModVarp); outpinp->user2(true); // mark this visited @@ -736,30 +745,30 @@ class TristateVisitor : public TristateBaseVisitor { } // Existing pin becomes an input - TristateInPinVisitor visitor (nodep->exprp()); + TristatePinVisitor visitor (nodep->exprp()); V3Inst::pinReconnectSimple(nodep, m_cellp, m_modp, true); // Note may change nodep->exprp() if (debug()>=9) nodep->dumpTree(cout,"-pin-in: "); // Connect enable to output signal - AstVarRef* refp; + AstVarRef* outrefp; if (!outAssignp) { - refp = outpinp->exprp()->castVarRef(); + outrefp = outpinp->exprp()->castVarRef(); } else { - refp = outAssignp->rhsp()->castVarRef(); // This should be the same var as the output pin + outrefp = outAssignp->rhsp()->castVarRef(); // This should be the same var as the output pin } - if (!refp) { // deal with simple varref port + if (!outrefp) { // deal with simple varref port nodep->v3error("Unsupported tristate port expression: "<exprp()->prettyTypeName()); } else { - refp->user1p(enrefp); // Mark as now tristated; iteration will pick it up from there - visit(refp, NULL); // visit this var ref to get it in the varmap + outrefp->user1p(enrefp); // Mark as now tristated; iteration will pick it up from there + visit(outrefp, NULL); // visit this var ref to get it in the varmap } // Propagate any pullups/pulldowns upwards if necessary - if (refp) { + if (outrefp) { if (AstPull* pullp = (AstPull*) nodep->modVarp()->user3p()) { - UINFO(9, "propagate pull to "<varp()); + UINFO(9, "propagate pull on "<varp(), pullp); + setPullDirection(outrefp->varp(), pullp); } } diff --git a/test_regress/t/t_tri_gate.cpp b/test_regress/t/t_tri_gate.cpp index b52fc202b..1960985f7 100644 --- a/test_regress/t/t_tri_gate.cpp +++ b/test_regress/t/t_tri_gate.cpp @@ -45,7 +45,8 @@ bool check() { printf("%%E-FAIL: "); } if (verbose) { - printf("SEL=%d A=%d W=%d X=%d Y=%d Z=%d c=%d\n", tb->SEL, tb->A, tb->W, tb->X, tb->Y, tb->Z, c); + printf("SEL=%d A=%d got: W=%d X=%d Y=%d Z=%d exp: WXYZ=%d\n", + tb->SEL, tb->A, tb->W, tb->X, tb->Y, tb->Z, c); } return pass; } diff --git a/test_regress/t/t_tri_select.cpp b/test_regress/t/t_tri_select.cpp index 29d52cf0b..9e7793361 100644 --- a/test_regress/t/t_tri_select.cpp +++ b/test_regress/t/t_tri_select.cpp @@ -24,7 +24,7 @@ bool check() { int W = (((tb->OE2) ? (tb->A2 & 0x1) : 0) << tb->A1) | (((tb->OE1) ? (tb->A2 >> 1)&0x1 : 0) << tb->A2); - if(tb->Y1 == tb->Y2 && tb->Y1 == Y && tb->W == W) { + if(tb->Y1 == Y && tb->Y2 == Y && tb->Y3 == Y && tb->W == W) { pass = true; if (verbose) printf("- pass: "); } else { @@ -33,7 +33,8 @@ bool check() { printf("%%E-Fail: "); } - if (verbose) printf("Read: OE1=%d OE2=%d A1=0x%x A2=0x%x Y1=0x%x Y2=0x%x W=0x%x Expected: Y1=Y2=%d and W=0x%x\n", tb->OE1, tb->OE2, tb->A1, tb->A2, tb->Y1, tb->Y2, tb->W, Y,W); + if (verbose) printf("Read: OE1=%d OE2=%d A1=0x%x A2=0x%x Y1=0x%x Y2=0x%x Y3=0x%x W=0x%x Expected: Y1=Y2=Y3=%d and W=0x%x\n", + tb->OE1, tb->OE2, tb->A1, tb->A2, tb->Y1, tb->Y2, tb->Y3, tb->W, Y,W); return pass; } diff --git a/test_regress/t/t_tri_select.v b/test_regress/t/t_tri_select.v index 0545c8879..260471882 100644 --- a/test_regress/t/t_tri_select.v +++ b/test_regress/t/t_tri_select.v @@ -10,6 +10,7 @@ module top ( input [`WIDTH-1:0] A2, output [`WIDTH-1:0] Y1, output [`WIDTH-1:0] Y2, + output [`WIDTH-1:0] Y3, output [`WIDTH**2-1:0] W); assign W[A1] = (OE2) ? A2[0] : 1'bz; @@ -17,8 +18,10 @@ module top ( // have 2 different 'chips' drive the PAD to act like a bi-directional bus wire [`WIDTH-1:0] PAD; - io_ring io_ring1 (.OE(OE1), .A(A1), .Y(Y1), .PAD(PAD)); - io_ring io_ring2 (.OE(OE2), .A(A2), .Y(Y2), .PAD(PAD)); + io_ring io_ring1 (.OE(OE1), .A(A1), .O(Y1), .PAD(PAD)); + io_ring io_ring2 (.OE(OE2), .A(A2), .O(Y2), .PAD(PAD)); + + assign Y3 = PAD; pullup p1(PAD); // pulldown p1(PAD); @@ -28,8 +31,8 @@ module top ( endmodule -module io_ring (input OE, input [`WIDTH-1:0] A, output [`WIDTH-1:0] Y, inout [`WIDTH-1:0] PAD); - io io[`WIDTH-1:0] (.OE(OE), .I(A), .O(Y), .PAD(PAD)); +module io_ring (input OE, input [`WIDTH-1:0] A, output [`WIDTH-1:0] O, inout [`WIDTH-1:0] PAD); + io io[`WIDTH-1:0] (.OE(OE), .I(A), .O(O), .PAD(PAD)); endmodule module io (input OE, input I, output O, inout PAD); diff --git a/test_regress/t/t_tri_various.v b/test_regress/t/t_tri_various.v index 2bbf56076..8a3367298 100644 --- a/test_regress/t/t_tri_various.v +++ b/test_regress/t/t_tri_various.v @@ -162,6 +162,9 @@ endmodule // floating output and inout +`ifndef VERILATOR +// Note verilator doesn't know to make Z4 a tristate unless marked an inout +`endif module Test4(output Z4, inout Z5); endmodule