forked from github/verilator
Internals: Misc tristate merges. Pins renamed but... No functional change intended.
This commit is contained in:
parent
ff69bdbc6f
commit
e498b73933
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user