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
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);

View File

@ -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

View File

@ -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 "<<nodep<<endl);
UINFO(9," Flip-to-RValue "<<nodep<<endl);
nodep->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 "<<newp<<endl);
if (!m_modp) { invarp->v3error("Unsupported: Creating tristate signal not underneath a module: "<<invarp->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 "<<newp<<endl);
if (!m_modp) { invarp->v3error("Unsupported: Creating tristate signal not underneath a module: "<<invarp->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 "<<newp<<endl);
if (!m_modp) { newp->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 "<<outvarp);
if (invarp->user3p()) UINFO(9, "propagate pull to "<<outvarp<<endl);
} else if (invarp->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 "<<newlhsp);
UINFO(9," newout "<<newlhsp<<endl);
nodep->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 "<<enassp<<endl);
nodep->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 "<<enp<<endl);
nodep->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 "<<enp<<endl);
nodep->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":"")<<" "<<nodep<<endl);
UINFO(9,dbgState()<<nodep<<endl);
{
if (m_alhs && nodep->user1p()) { nodep->v3error("Unsupported LHS tristate construct: "<<nodep->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 "<<newp<<endl);
if (debug()>=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 "<<enrefp<<endl);
if (debug()>=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: "<<nodep->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 "<<refp->varp());
UINFO(9, "propagate pull on "<<outrefp);
//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: ");
}
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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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