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
|
// 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);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue