forked from github/verilator
Support '{} assignment pattern on arrays, bug355.
This commit is contained in:
parent
6e3e8318d0
commit
446b0e4e5e
2
Changes
2
Changes
@ -7,6 +7,8 @@ indicates the contributor was also the author of the fix; Thanks!
|
||||
|
||||
** PSL is no longer supported, please use System Verilog assertions.
|
||||
|
||||
** Support '{} assignment pattern on arrays, bug355.
|
||||
|
||||
*** Add --no-trace-params.
|
||||
|
||||
*** Add assertions on 'unique if', bug725. [Jeff Bush]
|
||||
|
@ -408,6 +408,22 @@ class SliceVisitor : public AstNVisitor {
|
||||
|
||||
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
|
||||
if (!nodep->user1()) {
|
||||
// Cleanup initArrays
|
||||
if (AstInitArray* initp = nodep->rhsp()->castInitArray()) {
|
||||
//if (debug()>=9) nodep->dumpTree(cout, "-InitArrayIn: ");
|
||||
AstNode* newp = NULL;
|
||||
int index = 0;
|
||||
while (AstNode* subp=initp->initsp()) {
|
||||
AstNode* lhsp = new AstArraySel(nodep->fileline(),
|
||||
nodep->lhsp()->cloneTree(false),
|
||||
index++);
|
||||
newp = newp->addNext(nodep->cloneType(lhsp, subp->unlinkFrBack()));
|
||||
}
|
||||
//if (debug()>=9) newp->dumpTreeAndNext(cout, "-InitArrayOut: ");
|
||||
nodep->replaceWith(newp);
|
||||
pushDeletep(nodep); nodep=NULL;
|
||||
return; // WIll iterate in a moment
|
||||
}
|
||||
// Hasn't been searched for implicit slices yet
|
||||
findImplicit(nodep);
|
||||
}
|
||||
|
@ -911,7 +911,7 @@ private:
|
||||
}
|
||||
if (nodep->valuep()) {
|
||||
//if (debug()) nodep->dumpTree(cout," final: ");
|
||||
if (!didchk) nodep->valuep()->iterateAndNext(*this,WidthVP(nodep->dtypep()->width(),0,BOTH).p());
|
||||
if (!didchk) nodep->valuep()->iterateAndNext(*this,WidthVP(nodep->dtypep(),BOTH).p());
|
||||
if (!nodep->valuep()->castInitArray()) { // No dtype at present, perhaps TODO
|
||||
widthCheck(nodep,"Initial value",nodep->valuep(),nodep->width(),nodep->widthMin());
|
||||
}
|
||||
@ -1020,8 +1020,15 @@ private:
|
||||
nodep->dtypeFrom(nodep->itemp());
|
||||
}
|
||||
virtual void visit(AstInitArray* nodep, AstNUser* vup) {
|
||||
// Should be correct by construction, so we'll just loop through all types
|
||||
nodep->iterateChildren(*this, vup);
|
||||
// InitArray has type of the array; children are array values
|
||||
AstNodeDType* vdtypep = vup->c()->dtypep();
|
||||
if (!vdtypep) nodep->v3fatalSrc("InitArray type not assigned by AstPattern visitor");
|
||||
nodep->dtypep(vdtypep);
|
||||
if (AstNodeArrayDType* arrayp = vdtypep->castNodeArrayDType()) {
|
||||
nodep->iterateChildren(*this,WidthVP(arrayp->subDTypep(),BOTH).p());
|
||||
} else {
|
||||
nodep->v3fatalSrc("InitArray on non-array");
|
||||
}
|
||||
}
|
||||
virtual void visit(AstInside* nodep, AstNUser* vup) {
|
||||
nodep->exprp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,PRELIM).p());
|
||||
@ -1269,19 +1276,95 @@ private:
|
||||
patp->dtypep(memp);
|
||||
patp->accept(*this,WidthVP(memp,BOTH).p());
|
||||
// Convert to concat for now
|
||||
if (!newp) newp = patp->lhssp()->unlinkFrBack();
|
||||
AstNode* valuep = patp->lhssp()->unlinkFrBack();
|
||||
if (!newp) newp = valuep;
|
||||
else {
|
||||
AstConcat* concatp = new AstConcat(patp->fileline(), newp, patp->lhssp()->unlinkFrBack());
|
||||
AstConcat* concatp = new AstConcat(patp->fileline(), newp, valuep);
|
||||
newp = concatp;
|
||||
newp->dtypeSetLogicSized(concatp->lhsp()->width()+concatp->rhsp()->width(),
|
||||
concatp->lhsp()->width()+concatp->rhsp()->width(),
|
||||
nodep->dtypep()->numeric());
|
||||
}
|
||||
if (newpatp) pushDeletep(newpatp);
|
||||
if (newpatp) { pushDeletep(newpatp); newpatp=NULL; }
|
||||
}
|
||||
if (newp) nodep->replaceWith(newp);
|
||||
else nodep->v3error("Assignment pattern with no members");
|
||||
pushDeletep(nodep); nodep = NULL; // Deletes defaultp also, if present
|
||||
}
|
||||
else if (AstNodeArrayDType* arrayp = vdtypep->castNodeArrayDType()) {
|
||||
typedef map<int,AstPatMember*> PatMap;
|
||||
PatMap patmap;
|
||||
{
|
||||
int element = arrayp->declRange().left();
|
||||
for (AstPatMember* patp = nodep->itemsp()->castPatMember();
|
||||
patp; patp = patp->nextp()->castPatMember()) {
|
||||
if (patp->keyp()) {
|
||||
if (AstConst* constp = patp->keyp()->castConst()) {
|
||||
element = constp->toSInt();
|
||||
} else {
|
||||
patp->keyp()->v3error("Assignment pattern key not supported/understood: "<<patp->keyp()->prettyTypeName());
|
||||
}
|
||||
}
|
||||
if (patmap.find(element) != patmap.end()) {
|
||||
patp->v3error("Assignment pattern key used multiple times: "<<element);
|
||||
} else {
|
||||
patmap.insert(make_pair(element, patp));
|
||||
}
|
||||
element += arrayp->declRange().leftToRightInc();
|
||||
}
|
||||
}
|
||||
UINFO(9,"ent "<<arrayp->declRange().hi()<<" to "<<arrayp->declRange().lo()<<endl);
|
||||
AstNode* newp = NULL;
|
||||
for (int ent=arrayp->declRange().hi(); ent>=arrayp->declRange().lo(); --ent) {
|
||||
AstPatMember* newpatp = NULL;
|
||||
AstPatMember* patp = NULL;
|
||||
PatMap::iterator it=patmap.find(ent);
|
||||
if (it == patmap.end()) {
|
||||
if (defaultp) {
|
||||
newpatp = defaultp->cloneTree(false);
|
||||
patp = newpatp;
|
||||
}
|
||||
else {
|
||||
nodep->v3error("Assignment pattern missed initializing elements: "<<ent);
|
||||
}
|
||||
} else {
|
||||
patp = it->second;
|
||||
patmap.erase(it);
|
||||
}
|
||||
|
||||
// Determine initial values
|
||||
vdtypep = arrayp->subDTypep();
|
||||
// Don't want the RHS an array
|
||||
patp->dtypep(arrayp->subDTypep());
|
||||
// Determine values - might be another InitArray
|
||||
patp->accept(*this,WidthVP(patp->dtypep(),BOTH).p());
|
||||
// Convert to InitArray or constify immediately
|
||||
AstNode* valuep = patp->lhssp()->unlinkFrBack();
|
||||
if (arrayp->castUnpackArrayDType()) {
|
||||
if (!newp) {
|
||||
newp = new AstInitArray(nodep->fileline(), arrayp, valuep);
|
||||
} else {
|
||||
// We iterate hi()..lo() as that is what packed needs,
|
||||
// but INITARRAY needs lo() first
|
||||
newp->castInitArray()->initsp()->addHereThisAsNext(valuep);
|
||||
}
|
||||
} else { // Packed. Convert to concat for now.
|
||||
if (!newp) newp = valuep;
|
||||
else {
|
||||
AstConcat* concatp = new AstConcat(patp->fileline(), newp, valuep);
|
||||
newp = concatp;
|
||||
newp->dtypeSetLogicSized(concatp->lhsp()->width()+concatp->rhsp()->width(),
|
||||
concatp->lhsp()->width()+concatp->rhsp()->width(),
|
||||
nodep->dtypep()->numeric());
|
||||
}
|
||||
}
|
||||
if (newpatp) { pushDeletep(newpatp); newpatp=NULL; }
|
||||
}
|
||||
if (patmap.size()) nodep->v3error("Assignment pattern with too many elements");
|
||||
if (newp) nodep->replaceWith(newp);
|
||||
else nodep->v3error("Assignment pattern with no members");
|
||||
//if (debug()>=9) newp->dumpTree("-apat-out: ");
|
||||
pushDeletep(nodep); nodep = NULL; // Deletes defaultp also, if present
|
||||
} else {
|
||||
nodep->v3error("Unsupported: Assignment pattern applies against non struct/union: "<<vdtypep->prettyTypeName());
|
||||
}
|
||||
@ -1291,10 +1374,11 @@ private:
|
||||
AstNodeDType* vdtypep = vup->c()->dtypep();
|
||||
if (!vdtypep) nodep->v3fatalSrc("Pattern member type not assigned by AstPattern visitor");
|
||||
nodep->dtypep(vdtypep);
|
||||
UINFO(9," PATMEMBER "<<nodep<<endl);
|
||||
if (nodep->lhssp()->nextp()) nodep->v3fatalSrc("PatMember value should be singular w/replicates removed");
|
||||
nodep->lhssp()->dtypeFrom(nodep);
|
||||
nodep->iterateChildren(*this,WidthVP(nodep->dtypep(),BOTH).p());
|
||||
widthCheck(nodep,"LHS",nodep->lhssp(),nodep->width(),nodep->width());
|
||||
widthCheck(nodep,"Value",nodep->lhssp(),vdtypep);
|
||||
}
|
||||
int visitPatMemberRep(AstPatMember* nodep) {
|
||||
uint32_t times = 1;
|
||||
|
@ -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, bug355");
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
|
@ -26,11 +26,21 @@ module t (/*AUTOARG*/
|
||||
//array_simp[0] = '{ 1:4'd3, default:13};
|
||||
//if (array_simp[0] !== 16'hDD3D) $stop;
|
||||
|
||||
array_simp = '{ '{ 4'd3, 4'd2, 4'd1, 4'd0 }, '{ 4'd1, 4'd2, 4'd3, 4'd4 }};
|
||||
array_simp = '{ '{ 4'd3, 4'd2, 4'd1, 4'd0 }, '{ 4'd1, 4'd2, 4'd3, 4'd4 }};
|
||||
if (array_simp !== 32'h3210_1234) $stop;
|
||||
|
||||
// IEEE says '{} allowed only on assignments, not !=, ==.
|
||||
|
||||
// Doesn't seem to work for unpacked arrays in other simulators
|
||||
array_simp = '{2 { '{4 { 4'd3, 4'd2, 4'd1, 4'd0 }} } };
|
||||
array_simp = '{2{ '{4'd3, 4'd2, 4'd1, 4'd0 } }};
|
||||
if (array_simp !== 32'h3210_3210) $stop;
|
||||
|
||||
array_simp = '{2{ '{4{ 4'd3 }} }};
|
||||
if (array_simp !== 32'h3333_3333) $stop;
|
||||
|
||||
// Not legal in other simulators - replication doesn't match
|
||||
// However IEEE suggests this is legal.
|
||||
//array_simp = '{2{ '{2{ 4'd3, 4'd2 }} }}; // Note it's not '{3,2}
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
|
@ -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, bug355");
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
|
@ -25,7 +25,17 @@ module t (/*AUTOARG*/);
|
||||
array_simp[0][3],array_simp[0][2],array_simp[0][1],array_simp[0][0]} !== 32'h3210_1234) $stop;
|
||||
|
||||
// Doesn't seem to work for unpacked arrays in other simulators
|
||||
array_simp = '{2 { '{4 { 4'd3, 4'd2, 4'd1, 4'd0 }} } };
|
||||
array_simp = '{2{ '{4'd3, 4'd2, 4'd1, 4'd0 } }};
|
||||
if ({array_simp[1][3],array_simp[1][2],array_simp[1][1],array_simp[1][0],
|
||||
array_simp[0][3],array_simp[0][2],array_simp[0][1],array_simp[0][0]} !== 32'h3210_3210) $stop;
|
||||
|
||||
array_simp = '{2{ '{4{ 4'd3 }} }};
|
||||
if ({array_simp[1][3],array_simp[1][2],array_simp[1][1],array_simp[1][0],
|
||||
array_simp[0][3],array_simp[0][2],array_simp[0][1],array_simp[0][0]} !== 32'h3333_3333) $stop;
|
||||
|
||||
// Not legal in other simulators - replication doesn't match
|
||||
// However IEEE suggests this is legal.
|
||||
//array_simp = '{2{ '{2{ 4'd3, 4'd2 }} }}; // Note it's not '{3,2}
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
|
Loading…
Reference in New Issue
Block a user