Fix dot indexing into arrayed inferfaces, bug978.

This commit is contained in:
Wilson Snyder 2015-10-23 23:06:24 -04:00
parent 215d5f68b0
commit 4464b13163
7 changed files with 137 additions and 33 deletions

View File

@ -31,6 +31,8 @@ indicates the contributor was also the author of the fix; Thanks!
**** Fix struct.enum.name method calls, bug855. [Jonathon Donaldson]
**** Fix dot indexing into arrayed inferfaces, bug978. [Johan Bjork]
* Verilator 3.876 2015-08-12

View File

@ -109,8 +109,9 @@ private:
// Create an AstAssignVarScope for Vars to Cells so we can link with their scope later
AstNode* lhsp = new AstVarXRef (exprp->fileline(), nodep->modVarp(), m_cellp->name(), false);
AstVarRef* refp = exprp->castVarRef();
if (!refp) exprp->v3fatalSrc("Interfaces: Pin is not connected to a VarRef");
AstAssignVarScope* assp = new AstAssignVarScope(exprp->fileline(), lhsp, refp);
AstVarXRef* xrefp = exprp->castVarXRef();
if (!refp && !xrefp) exprp->v3fatalSrc("Interfaces: Pin is not connected to a VarRef or VarXRef");
AstAssignVarScope* assp = new AstAssignVarScope(exprp->fileline(), lhsp, exprp);
m_modp->addStmtp(assp);
} else {
nodep->v3error("Assigned pin is neither input nor output");
@ -169,6 +170,12 @@ private:
if (nodep->rangep()) {
m_cellRangep = nodep->rangep();
UINFO(4," CELL "<<nodep<<endl);
AstVar *ifaceVarp = nodep->nextp()->castVar();
bool isIface = ifaceVarp
&& ifaceVarp->dtypep()->castUnpackArrayDType()
&& ifaceVarp->dtypep()->castUnpackArrayDType()->subDTypep()->castIfaceRefDType();
// Make all of the required clones
m_instLsb = m_cellRangep->lsbConst();
for (m_instNum = m_instLsb; m_instNum<=m_cellRangep->msbConst(); m_instNum++) {
@ -181,6 +188,22 @@ private:
// The spec says we add [x], but that won't work in C...
newp->name(newp->name()+"__BRA__"+cvtToStr(m_instNum)+"__KET__");
newp->origName(newp->origName()+"__BRA__"+cvtToStr(m_instNum)+"__KET__");
// If this AstCell is actually an interface instantiation, let's ensure we also clone
// the IfaceRef.
if (isIface) {
AstUnpackArrayDType *arrdtype = ifaceVarp->dtypep()->castUnpackArrayDType();
AstVar* varNewp = ifaceVarp->cloneTree(false);
AstIfaceRefDType *ifaceRefp = arrdtype->subDTypep()->castIfaceRefDType()->cloneTree(false);
arrdtype->addNextHere(ifaceRefp);
ifaceRefp->cellp(newp);
ifaceRefp->cellName(newp->name());
varNewp->name(varNewp->name() + "__BRA__" + cvtToStr(m_instNum) + "__KET__");
varNewp->origName(varNewp->origName() + "__BRA__" + cvtToStr(m_instNum) + "__KET__");
varNewp->dtypep(ifaceRefp);
newp->addNextHere(varNewp);
if (debug()==9) { varNewp->dumpTree(cout, "newintf: "); cout << endl; }
}
// Fixup pins
newp->pinsp()->iterateAndNext(*this);
if (debug()==9) { newp->dumpTree(cout,"newcell: "); cout<<endl; }
@ -188,9 +211,14 @@ private:
// Done. Delete original
m_cellRangep=NULL;
if (isIface) {
ifaceVarp->unlinkFrBack(); pushDeletep(ifaceVarp); VL_DANGLING(ifaceVarp);
}
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
}
nodep->iterateChildren(*this);
}
virtual void visit(AstPin* nodep, AstNUser*) {
// Any non-direct pins need reconnection with a part-select
if (!nodep->exprp()) return; // No-connect
@ -217,6 +245,29 @@ private:
} else {
nodep->v3fatalSrc("Width mismatch; V3Width should have errored out.");
}
} else if(AstArraySel *arrselp = nodep->exprp()->castArraySel()) {
if (AstUnpackArrayDType *arrp = arrselp->lhsp()->dtypep()->castUnpackArrayDType()) {
if (!arrp->subDTypep()->castIfaceRefDType())
return;
AstConst *constp = arrselp->rhsp()->castConst();
if (!constp) {
nodep->v3error("Unsupported: Non-constant index when passing interface to module");
return;
}
string index = AstNode::encodeNumber(constp->toSInt());
AstVarRef *varrefp = arrselp->lhsp()->castVarRef();
AstVarXRef *newp = new AstVarXRef(nodep->fileline(),varrefp->name () + "__BRA__" + index + "__KET__", "", true);
AstVar *varp = varrefp->varp()->cloneTree(true);
varp->name(varp->name() + "__TMP__" + "__BRA__" + index + "__KET__");
varp->dtypep(arrp->subDTypep()->backp()->castIfaceRefDType());
newp->addNextHere(varp);
newp->varp(varp);
newp->dtypep(arrp->subDTypep()->castIfaceRefDType());
newp->packagep(varrefp->packagep());
arrselp->addNextHere(newp);
arrselp->unlinkFrBack()->deleteTree();
}
}
}
@ -272,8 +323,10 @@ public:
// Else create a intermediate wire to perform the interconnect
// Return the new assignment, if one was made
// Note this module calles cloneTree() via new AstVar
AstVar* pinVarp = pinp->modVarp();
AstVarRef* connectRefp = pinp->exprp()->castVarRef();
AstVarXRef* connectXRefp = pinp->exprp()->castVarXRef();
AstBasicDType* pinBasicp = pinVarp->dtypep()->basicp(); // Maybe NULL
AstBasicDType* connBasicp = NULL;
AstAssignW* assignp = NULL;
@ -288,6 +341,9 @@ public:
&& connectRefp
&& connectRefp->varp()->isIfaceRef()) {
// Done. Interface
} else if (!alwaysCvt
&& connectXRefp
&& connectXRefp->varp()->isIfaceRef()) {
} else if (!alwaysCvt
&& connBasicp
&& pinBasicp

View File

@ -348,18 +348,23 @@ private:
// This is quite similar to how classes work; when unpacked classes are better supported
// may remap interfaces to be more like a class.
if (!nodep->hasIfaceVar()) {
if (!nodep->rangep()) {
string varName = nodep->name() + "__Viftop"; // V3LinkDot looks for this naming
AstIfaceRefDType *idtypep = new AstIfaceRefDType(nodep->fileline(), nodep->name(),
nodep->modp()->name());
string varName = nodep->name() + "__Viftop"; // V3LinkDot looks for this naming
AstIfaceRefDType *idtypep = new AstIfaceRefDType(nodep->fileline(), nodep->name(),
nodep->modp()->name());
idtypep->ifacep(NULL); // cellp overrides
AstVar *varp;
if (nodep->rangep()) {
AstNodeArrayDType *arrp = new AstUnpackArrayDType(nodep->fileline(),VFlagChildDType(), idtypep, nodep->rangep()->cloneTree(true));
varp = new AstVar(nodep->fileline(), AstVarType::IFACEREF, varName,
VFlagChildDType(), arrp);
} else {
idtypep->cellp(nodep); // Only set when real parent cell known
idtypep->ifacep(NULL); // cellp overrides
AstVar *varp = new AstVar(nodep->fileline(), AstVarType::IFACEREF, varName,
VFlagChildDType(), idtypep);
varp->isIfaceParent(true);
nodep->addNextHere(varp);
nodep->hasIfaceVar(true);
varp = new AstVar(nodep->fileline(), AstVarType::IFACEREF, varName,
VFlagChildDType(), idtypep);
}
varp->isIfaceParent(true);
nodep->addNextHere(varp);
nodep->hasIfaceVar(true);
}
}
if (nodep->modp()) {

View File

@ -1145,8 +1145,9 @@ class LinkDotScopeVisitor : public AstNVisitor {
VSymEnt* rhsSymp;
{
AstVarRef* refp = nodep->rhsp()->castVarRef();
if (!refp) nodep->v3fatalSrc("Unsupported: Non VarRef attached to interface pin");
string scopename = refp->name();
AstVarXRef* xrefp = nodep->rhsp()->castVarXRef();
if (!refp && !xrefp) nodep->v3fatalSrc("Unsupported: Non Var(X)Ref attached to interface pin");
string scopename = refp ? refp->name() : xrefp->name();
string baddot; VSymEnt* okSymp;
VSymEnt* symp = m_statep->findDotted(m_modSymp, scopename, baddot, okSymp);
if (!symp) nodep->v3fatalSrc("No symbol for interface alias rhs");

View File

@ -481,15 +481,28 @@ void ParamVisitor::visitCell(AstCell* nodep) {
AstVar* modvarp = pinp->modVarp();
if (modvarp->isIfaceRef()) {
AstIfaceRefDType* portIrefp = modvarp->subDTypep()->castIfaceRefDType();
AstIfaceRefDType* pinIrefp = NULL;
AstNode *exprp = pinp->exprp();
if (exprp
&& exprp->castVarRef()
&& exprp->castVarRef()->varp()
&& exprp->castVarRef()->varp()->subDTypep()
&& exprp->castVarRef()->varp()->subDTypep()->castIfaceRefDType())
pinIrefp = exprp->castVarRef()->varp()->subDTypep()->castIfaceRefDType();
else if (exprp
&& exprp->op1p()
&& exprp->op1p()->castVarRef()
&& exprp->op1p()->castVarRef()->varp()
&& exprp->op1p()->castVarRef()->varp()->subDTypep()
&& exprp->op1p()->castVarRef()->varp()->subDTypep()->castUnpackArrayDType()
&& exprp->op1p()->castVarRef()->varp()->subDTypep()->castUnpackArrayDType()->subDTypep()
&& exprp->op1p()->castVarRef()->varp()->subDTypep()->castUnpackArrayDType()->subDTypep()->castIfaceRefDType())
pinIrefp = exprp->op1p()->castVarRef()->varp()->subDTypep()->castUnpackArrayDType()->subDTypep()->castIfaceRefDType();
//UINFO(9," portIfaceRef "<<portIrefp<<endl);
if (!pinp->exprp()
|| !pinp->exprp()->castVarRef()
|| !pinp->exprp()->castVarRef()->varp()
|| !pinp->exprp()->castVarRef()->varp()->subDTypep()
|| !pinp->exprp()->castVarRef()->varp()->subDTypep()->castIfaceRefDType()) {
if (!pinIrefp) {
pinp->v3error("Interface port '"<<modvarp->prettyName()<<"' is not connected to interface/modport pin expression");
} else {
AstIfaceRefDType* pinIrefp = pinp->exprp()->castVarRef()->varp()->subDTypep()->castIfaceRefDType();
//UINFO(9," pinIfaceRef "<<pinIrefp<<endl);
if (portIrefp->ifaceViaCellp() != pinIrefp->ifaceViaCellp()) {
UINFO(9," IfaceRefDType needs reconnect "<<pinIrefp<<endl);

View File

@ -7,8 +7,6 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug978");
compile (
);

View File

@ -4,24 +4,53 @@
// without warranty, 2015 by Johan Bjork.
interface intf;
logic a;
modport source(output a);
modport sink(input a);
logic logic_in_intf;
modport source(output logic_in_intf);
modport sink(input logic_in_intf);
endinterface
module modify_interface
(
input logic value,
intf.source intf_inst
);
assign intf_inst.logic_in_intf = value;
endmodule
module t
#(
parameter N = 1
)
( input [N-1:0] a_in,
output[N-1:0] a_out
);
parameter N = 6
)();
intf ifs[N-1:0] ();
logic [N-1:0] a_q;
logic [N-1:0] data;
assign data = {1'b0, 1'b1, 1'b0, 1'b1, 1'b0, 1'b1};
generate
genvar i;
for (i = 0;i < 4; i++) begin
assign ifs[i].logic_in_intf = data[i];
end
endgenerate
modify_interface m (
.value(data[4]),
.intf_inst(ifs[4]));
modify_interface m1 (
.value(~ifs[4].logic_in_intf),
.intf_inst(ifs[5]));
generate
genvar j;
for (j = 0;j < N-1; j++) begin
initial begin
if (ifs[j].logic_in_intf != data[j]) $stop;
end
end
endgenerate
assign a_out = a_q;
assign ifs[0].a = a_in[0];
initial begin
if (ifs[5].logic_in_intf != ~ifs[4].logic_in_intf) $stop;
$write("*-* All Finished *-*\n");
$finish;
end