Internals: Misc tristate merges. Pins renamed but... No functional change intended.

This commit is contained in:
Wilson Snyder 2012-05-07 23:42:58 -04:00
parent ff69bdbc6f
commit e498b73933
7 changed files with 55 additions and 34 deletions

View File

@ -236,7 +236,8 @@ public:
//###################################################################### //######################################################################
// Inst class functions // 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 // If a pin connection is "simple" leave it as-is
// Else create a intermediate wire to perform the interconnect // Else create a intermediate wire to perform the interconnect
// Return the new assignment, if one was made // Return the new assignment, if one was made
@ -248,11 +249,13 @@ AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModu
AstAssignW* assignp = NULL; AstAssignW* assignp = NULL;
if (connectRefp) connBasicp = connectRefp->varp()->dtypep()->basicp(); if (connectRefp) connBasicp = connectRefp->varp()->dtypep()->basicp();
// //
if (connectRefp if (!alwaysCvt
&& connectRefp
&& connectRefp->varp()->dtypep()->sameTree(pinVarp->dtypep()) && connectRefp->varp()->dtypep()->sameTree(pinVarp->dtypep())
&& !connectRefp->varp()->isSc()) { // Need the signal as a 'shell' to convert types && !connectRefp->varp()->isSc()) { // Need the signal as a 'shell' to convert types
// Done. Same data type // Done. Same data type
} else if (connBasicp } else if (!alwaysCvt
&& connBasicp
&& pinBasicp && pinBasicp
&& connBasicp->width() == pinBasicp->width() && connBasicp->width() == pinBasicp->width()
&& connBasicp->lsb() == pinBasicp->lsb() && connBasicp->lsb() == pinBasicp->lsb()
@ -260,13 +263,14 @@ AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModu
&& connBasicp->width() == pinVarp->width() && connBasicp->width() == pinVarp->width()
&& 1) { && 1) {
// Done. One to one interconnect won't need a temporary variable. // 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. // Done. Constant.
} else { } else {
// Make a new temp wire // Make a new temp wire
//if (1||debug()>=9) { pinp->dumpTree(cout,"in_pin:"); } //if (1||debug()>=9) { pinp->dumpTree(cout,"in_pin:"); }
AstNode* pinexprp = pinp->exprp()->unlinkFrBack(); 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); 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 // Important to add statement next to cell, in case there is a generate with same named cell
cellp->addNextHere(newvarp); cellp->addNextHere(newvarp);

View File

@ -34,7 +34,7 @@ public:
static void instAll(AstNetlist* nodep); static void instAll(AstNetlist* nodep);
static void dearrayAll(AstNetlist* nodep); static void dearrayAll(AstNetlist* nodep);
static AstAssignW* pinReconnectSimple(AstPin* nodep, AstCell* cellp, AstNodeModule* modp, static AstAssignW* pinReconnectSimple(AstPin* nodep, AstCell* cellp, AstNodeModule* modp,
bool forTristate); bool forTristate, bool alwaysCvt=false);
}; };
#endif // Guard #endif // Guard

View File

@ -69,7 +69,7 @@ public:
// Given a node, flip any VarRef from LValue to RValue (i.e. make it an input) // Given a node, flip any VarRef from LValue to RValue (i.e. make it an input)
// See also V3LinkLValue::linkLValueSet // See also V3LinkLValue::linkLValueSet
class TristateInPinVisitor : public TristateBaseVisitor { class TristatePinVisitor : public TristateBaseVisitor {
// VISITORS // VISITORS
virtual void visit(AstVarRef* nodep, AstNUser*) { virtual void visit(AstVarRef* nodep, AstNUser*) {
if (nodep->lvalue()) { if (nodep->lvalue()) {
@ -82,10 +82,10 @@ class TristateInPinVisitor : public TristateBaseVisitor {
} }
public: public:
// CONSTUCTORS // CONSTUCTORS
TristateInPinVisitor(AstNode* nodep) { TristatePinVisitor(AstNode* nodep) {
nodep->accept(*this); nodep->accept(*this);
} }
virtual ~TristateInPinVisitor() {} virtual ~TristatePinVisitor() {}
}; };
//###################################################################### //######################################################################
@ -144,6 +144,7 @@ class TristateVisitor : public TristateBaseVisitor {
AstVarType::MODULETEMP, AstVarType::MODULETEMP,
invarp->name()+"__en", invarp->name()+"__en",
invarp); invarp);
UINFO(9," newenv "<<newp<<endl);
if (!m_modp) { invarp->v3error("Unsupported: Creating tristate signal not underneath a module: "<<invarp->prettyName()); } if (!m_modp) { invarp->v3error("Unsupported: Creating tristate signal not underneath a module: "<<invarp->prettyName()); }
else m_modp->addStmtp(newp); else m_modp->addStmtp(newp);
invarp->user1p(newp); // find envar given invarp invarp->user1p(newp); // find envar given invarp
@ -158,6 +159,7 @@ class TristateVisitor : public TristateBaseVisitor {
AstVarType::MODULETEMP, AstVarType::MODULETEMP,
invarp->name()+"__out", invarp->name()+"__out",
invarp); invarp);
UINFO(9," newout "<<newp<<endl);
if (!m_modp) { invarp->v3error("Unsupported: Creating tristate signal not underneath a module: "<<invarp->prettyName()); } if (!m_modp) { invarp->v3error("Unsupported: Creating tristate signal not underneath a module: "<<invarp->prettyName()); }
else m_modp->addStmtp(newp); else m_modp->addStmtp(newp);
invarp->user4p(newp); // find outvar given invarp invarp->user4p(newp); // find outvar given invarp
@ -170,6 +172,7 @@ class TristateVisitor : public TristateBaseVisitor {
AstVarType::MODULETEMP, AstVarType::MODULETEMP,
"__Vtriunconn"+cvtToStr(m_unique++), "__Vtriunconn"+cvtToStr(m_unique++),
dtypep); dtypep);
UINFO(9," newunc "<<newp<<endl);
if (!m_modp) { newp->v3error("Unsupported: Creating tristate signal not underneath a module"); } if (!m_modp) { newp->v3error("Unsupported: Creating tristate signal not underneath a module"); }
else m_modp->addStmtp(newp); else m_modp->addStmtp(newp);
return newp; return newp;
@ -291,7 +294,7 @@ class TristateVisitor : public TristateBaseVisitor {
// //
outvarp->user1p(envarp); outvarp->user1p(envarp);
outvarp->user3p(invarp->user3p()); // AstPull* propagation outvarp->user3p(invarp->user3p()); // AstPull* propagation
if (invarp->user3p()) UINFO(9, "propagate pull to "<<outvarp); if (invarp->user3p()) UINFO(9, "propagate pull to "<<outvarp<<endl);
} else if (invarp->user1p()) { } else if (invarp->user1p()) {
envarp = invarp->user1p()->castNode()->castVar(); // From CASEEQ, foo === 1'bz envarp = invarp->user1p()->castNode()->castVar(); // From CASEEQ, foo === 1'bz
} }
@ -311,7 +314,7 @@ class TristateVisitor : public TristateBaseVisitor {
AstVarType::MODULETEMP, AstVarType::MODULETEMP,
lhsp->name()+"__out"+cvtToStr(m_unique), lhsp->name()+"__out"+cvtToStr(m_unique),
VFlagBitPacked(), w); // 2-state ok; sep enable VFlagBitPacked(), w); // 2-state ok; sep enable
UINFO(9," newout "<<newlhsp); UINFO(9," newout "<<newlhsp<<endl);
nodep->addStmtp(newlhsp); nodep->addStmtp(newlhsp);
refp->varp(newlhsp); // assign the new var to the varref refp->varp(newlhsp); // assign the new var to the varref
refp->name(newlhsp->name()); refp->name(newlhsp->name());
@ -326,6 +329,7 @@ class TristateVisitor : public TristateBaseVisitor {
AstNode* enassp = new AstAssignW(refp->fileline(), AstNode* enassp = new AstAssignW(refp->fileline(),
new AstVarRef(refp->fileline(), newenp, true), new AstVarRef(refp->fileline(), newenp, true),
getEnp(refp)); getEnp(refp));
UINFO(9," newass "<<enassp<<endl);
nodep->addStmtp(enassp); nodep->addStmtp(enassp);
// now append this driver to the driver logic. // 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 // The output enable of a cond is a cond of the output enable of the
// two expressions with the same conditional. // two expressions with the same conditional.
AstNode* enp = new AstCond(nodep->fileline(), condp->cloneTree(false), en1p, en2p); AstNode* enp = new AstCond(nodep->fileline(), condp->cloneTree(false), en1p, en2p);
UINFO(9," newcond "<<enp<<endl);
nodep->user1p(enp); nodep->user1p(enp);
expr1p->user1p(NULL); expr1p->user1p(NULL);
expr2p->user1p(NULL); expr2p->user1p(NULL);
@ -483,6 +488,7 @@ class TristateVisitor : public TristateBaseVisitor {
AstNode* en1p = getEnp(expr1p); AstNode* en1p = getEnp(expr1p);
AstNode* en2p = getEnp(expr2p); AstNode* en2p = getEnp(expr2p);
AstNode* enp = new AstConcat(nodep->fileline(), en1p, en2p); AstNode* enp = new AstConcat(nodep->fileline(), en1p, en2p);
UINFO(9," newconc "<<enp<<endl);
nodep->user1p(enp); nodep->user1p(enp);
expr1p->user1p(NULL); expr1p->user1p(NULL);
expr2p->user1p(NULL); expr2p->user1p(NULL);
@ -515,7 +521,7 @@ class TristateVisitor : public TristateBaseVisitor {
void visitAndOr(AstNodeBiop* nodep, bool isAnd) { void visitAndOr(AstNodeBiop* nodep, bool isAnd) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
UINFO(9,(m_alhs?"alhs":"")<<" "<<nodep<<endl); UINFO(9,dbgState()<<nodep<<endl);
{ {
if (m_alhs && nodep->user1p()) { nodep->v3error("Unsupported LHS tristate construct: "<<nodep->prettyTypeName()); return; } if (m_alhs && nodep->user1p()) { nodep->v3error("Unsupported LHS tristate construct: "<<nodep->prettyTypeName()); return; }
// ANDs and Z's have issues. Earlier optimizations convert // ANDs and Z's have issues. Earlier optimizations convert
@ -612,6 +618,7 @@ class TristateVisitor : public TristateBaseVisitor {
new AstEqCase(fl, new AstConst(fl, oneIfEnOne), new AstEqCase(fl, new AstConst(fl, oneIfEnOne),
varrefp)); varrefp));
if (neq) newp = new AstLogNot(fl, newp); if (neq) newp = new AstLogNot(fl, newp);
UINFO(9," newceq "<<newp<<endl);
if (debug()>=9) nodep->dumpTree(cout,"-caseeq-old: "); if (debug()>=9) nodep->dumpTree(cout,"-caseeq-old: ");
if (debug()>=9) newp->dumpTree(cout,"-caseeq-new: "); if (debug()>=9) newp->dumpTree(cout,"-caseeq-new: ");
nodep->replaceWith(newp); nodep->replaceWith(newp);
@ -660,8 +667,9 @@ class TristateVisitor : public TristateBaseVisitor {
// INPUT: -> (VARREF(trisig__pinin)), // INPUT: -> (VARREF(trisig__pinin)),
// trisig__pinin = SEL(trisig,x) // via pinReconnectSimple // trisig__pinin = SEL(trisig,x) // via pinReconnectSimple
// OUTPUT: -> (VARREF(trisig__pinout)) // OUTPUT: -> (VARREF(trisig__pinout))
// SEL(trisig,x) = trisig__pinout
// ^-- ->user1p() == trisig__pinen
// ENABLE: -> (VARREF(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 // 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 // PIN PORT NEW PORTS AND CONNECTIONS
// N/C input in(from-resolver), __out(to-resolver-only), __en(to-resolver-only) // 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(), AstVar* enVarp = new AstVar(nodep->fileline(),
AstVarType::MODULETEMP, AstVarType::MODULETEMP,
nodep->name() + "__en" + cvtToStr(m_unique), nodep->name() + "__en" + cvtToStr(m_unique++),
VFlagLogicPacked(), enModVarp->width()); VFlagLogicPacked(), enModVarp->width());
AstPin* enpinp = new AstPin(nodep->fileline(), AstPin* enpinp = new AstPin(nodep->fileline(),
nodep->pinNum(), nodep->pinNum(),
nodep->name() + "__en" + cvtToStr(m_unique++), enModVarp->name(), // should be {var}"__en"
new AstVarRef(nodep->fileline(), enVarp, true)); new AstVarRef(nodep->fileline(), enVarp, true));
enpinp->modVarp(enModVarp); enpinp->modVarp(enModVarp);
enpinp->user2(true); // mark this visited enpinp->user2(true); // mark this visited
m_cellp->addPinsp(enpinp); m_cellp->addPinsp(enpinp);
m_modp->addStmtp(enVarp); m_modp->addStmtp(enVarp);
enrefp = new AstVarRef(nodep->fileline(), enVarp, false); enrefp = new AstVarRef(nodep->fileline(), enVarp, false);
UINFO(9," newvrf "<<enrefp<<endl);
if (debug()>=9) enpinp->dumpTree(cout,"-pin-ena: "); if (debug()>=9) enpinp->dumpTree(cout,"-pin-ena: ");
} }
// Create new output pin // Create new output pin
@ -723,7 +732,7 @@ class TristateVisitor : public TristateBaseVisitor {
AstNode* outexprp = nodep->exprp()->cloneTree(false); // Note has lvalue() set AstNode* outexprp = nodep->exprp()->cloneTree(false); // Note has lvalue() set
outpinp = new AstPin(nodep->fileline(), outpinp = new AstPin(nodep->fileline(),
nodep->pinNum(), nodep->pinNum(),
nodep->name() + "__out"+cvtToStr(m_unique), outModVarp->name(), // should be {var}"__out"
outexprp); outexprp);
outpinp->modVarp(outModVarp); outpinp->modVarp(outModVarp);
outpinp->user2(true); // mark this visited outpinp->user2(true); // mark this visited
@ -736,30 +745,30 @@ class TristateVisitor : public TristateBaseVisitor {
} }
// Existing pin becomes an input // 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() V3Inst::pinReconnectSimple(nodep, m_cellp, m_modp, true); // Note may change nodep->exprp()
if (debug()>=9) nodep->dumpTree(cout,"-pin-in: "); if (debug()>=9) nodep->dumpTree(cout,"-pin-in: ");
// Connect enable to output signal // Connect enable to output signal
AstVarRef* refp; AstVarRef* outrefp;
if (!outAssignp) { if (!outAssignp) {
refp = outpinp->exprp()->castVarRef(); outrefp = outpinp->exprp()->castVarRef();
} else { } 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: "<<nodep->exprp()->prettyTypeName()); nodep->v3error("Unsupported tristate port expression: "<<nodep->exprp()->prettyTypeName());
} else { } else {
refp->user1p(enrefp); // Mark as now tristated; iteration will pick it up from there outrefp->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 visit(outrefp, NULL); // visit this var ref to get it in the varmap
} }
// Propagate any pullups/pulldowns upwards if necessary // Propagate any pullups/pulldowns upwards if necessary
if (refp) { if (outrefp) {
if (AstPull* pullp = (AstPull*) nodep->modVarp()->user3p()) { if (AstPull* pullp = (AstPull*) nodep->modVarp()->user3p()) {
UINFO(9, "propagate pull to "<<refp->varp()); UINFO(9, "propagate pull on "<<outrefp);
//selp: Note we don't currently obey selects; all bits must be consistently pulled //selp: Note we don't currently obey selects; all bits must be consistently pulled
setPullDirection(refp->varp(), pullp); setPullDirection(outrefp->varp(), pullp);
} }
} }

View File

@ -45,7 +45,8 @@ bool check() {
printf("%%E-FAIL: "); printf("%%E-FAIL: ");
} }
if (verbose) { 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; return pass;
} }

View File

@ -24,7 +24,7 @@ bool check() {
int W = (((tb->OE2) ? (tb->A2 & 0x1) : 0) << tb->A1) int W = (((tb->OE2) ? (tb->A2 & 0x1) : 0) << tb->A1)
| (((tb->OE1) ? (tb->A2 >> 1)&0x1 : 0) << tb->A2); | (((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; pass = true;
if (verbose) printf("- pass: "); if (verbose) printf("- pass: ");
} else { } else {
@ -33,7 +33,8 @@ bool check() {
printf("%%E-Fail: "); 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; return pass;
} }

View File

@ -10,6 +10,7 @@ module top (
input [`WIDTH-1:0] A2, input [`WIDTH-1:0] A2,
output [`WIDTH-1:0] Y1, output [`WIDTH-1:0] Y1,
output [`WIDTH-1:0] Y2, output [`WIDTH-1:0] Y2,
output [`WIDTH-1:0] Y3,
output [`WIDTH**2-1:0] W); output [`WIDTH**2-1:0] W);
assign W[A1] = (OE2) ? A2[0] : 1'bz; 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 // have 2 different 'chips' drive the PAD to act like a bi-directional bus
wire [`WIDTH-1:0] PAD; wire [`WIDTH-1:0] PAD;
io_ring io_ring1 (.OE(OE1), .A(A1), .Y(Y1), .PAD(PAD)); io_ring io_ring1 (.OE(OE1), .A(A1), .O(Y1), .PAD(PAD));
io_ring io_ring2 (.OE(OE2), .A(A2), .Y(Y2), .PAD(PAD)); io_ring io_ring2 (.OE(OE2), .A(A2), .O(Y2), .PAD(PAD));
assign Y3 = PAD;
pullup p1(PAD); pullup p1(PAD);
// pulldown p1(PAD); // pulldown p1(PAD);
@ -28,8 +31,8 @@ module top (
endmodule endmodule
module io_ring (input OE, input [`WIDTH-1:0] A, output [`WIDTH-1:0] Y, inout [`WIDTH-1:0] 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(Y), .PAD(PAD)); io io[`WIDTH-1:0] (.OE(OE), .I(A), .O(O), .PAD(PAD));
endmodule endmodule
module io (input OE, input I, output O, inout PAD); module io (input OE, input I, output O, inout PAD);

View File

@ -162,6 +162,9 @@ endmodule
// floating output and inout // 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); module Test4(output Z4, inout Z5);
endmodule endmodule