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.
|
** PSL is no longer supported, please use System Verilog assertions.
|
||||||
|
|
||||||
|
** Support '{} assignment pattern on arrays, bug355.
|
||||||
|
|
||||||
*** Add --no-trace-params.
|
*** Add --no-trace-params.
|
||||||
|
|
||||||
*** Add assertions on 'unique if', bug725. [Jeff Bush]
|
*** Add assertions on 'unique if', bug725. [Jeff Bush]
|
||||||
|
|
|
||||||
|
|
@ -408,6 +408,22 @@ class SliceVisitor : public AstNVisitor {
|
||||||
|
|
||||||
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
|
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
|
||||||
if (!nodep->user1()) {
|
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
|
// Hasn't been searched for implicit slices yet
|
||||||
findImplicit(nodep);
|
findImplicit(nodep);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -911,7 +911,7 @@ private:
|
||||||
}
|
}
|
||||||
if (nodep->valuep()) {
|
if (nodep->valuep()) {
|
||||||
//if (debug()) nodep->dumpTree(cout," final: ");
|
//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
|
if (!nodep->valuep()->castInitArray()) { // No dtype at present, perhaps TODO
|
||||||
widthCheck(nodep,"Initial value",nodep->valuep(),nodep->width(),nodep->widthMin());
|
widthCheck(nodep,"Initial value",nodep->valuep(),nodep->width(),nodep->widthMin());
|
||||||
}
|
}
|
||||||
|
|
@ -1020,8 +1020,15 @@ private:
|
||||||
nodep->dtypeFrom(nodep->itemp());
|
nodep->dtypeFrom(nodep->itemp());
|
||||||
}
|
}
|
||||||
virtual void visit(AstInitArray* nodep, AstNUser* vup) {
|
virtual void visit(AstInitArray* nodep, AstNUser* vup) {
|
||||||
// Should be correct by construction, so we'll just loop through all types
|
// InitArray has type of the array; children are array values
|
||||||
nodep->iterateChildren(*this, vup);
|
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) {
|
virtual void visit(AstInside* nodep, AstNUser* vup) {
|
||||||
nodep->exprp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,PRELIM).p());
|
nodep->exprp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,PRELIM).p());
|
||||||
|
|
@ -1269,19 +1276,95 @@ private:
|
||||||
patp->dtypep(memp);
|
patp->dtypep(memp);
|
||||||
patp->accept(*this,WidthVP(memp,BOTH).p());
|
patp->accept(*this,WidthVP(memp,BOTH).p());
|
||||||
// Convert to concat for now
|
// Convert to concat for now
|
||||||
if (!newp) newp = patp->lhssp()->unlinkFrBack();
|
AstNode* valuep = patp->lhssp()->unlinkFrBack();
|
||||||
|
if (!newp) newp = valuep;
|
||||||
else {
|
else {
|
||||||
AstConcat* concatp = new AstConcat(patp->fileline(), newp, patp->lhssp()->unlinkFrBack());
|
AstConcat* concatp = new AstConcat(patp->fileline(), newp, valuep);
|
||||||
newp = concatp;
|
newp = concatp;
|
||||||
newp->dtypeSetLogicSized(concatp->lhsp()->width()+concatp->rhsp()->width(),
|
newp->dtypeSetLogicSized(concatp->lhsp()->width()+concatp->rhsp()->width(),
|
||||||
concatp->lhsp()->width()+concatp->rhsp()->width(),
|
concatp->lhsp()->width()+concatp->rhsp()->width(),
|
||||||
nodep->dtypep()->numeric());
|
nodep->dtypep()->numeric());
|
||||||
}
|
}
|
||||||
if (newpatp) pushDeletep(newpatp);
|
if (newpatp) { pushDeletep(newpatp); newpatp=NULL; }
|
||||||
}
|
}
|
||||||
if (newp) nodep->replaceWith(newp);
|
if (newp) nodep->replaceWith(newp);
|
||||||
else nodep->v3error("Assignment pattern with no members");
|
else nodep->v3error("Assignment pattern with no members");
|
||||||
pushDeletep(nodep); nodep = NULL; // Deletes defaultp also, if present
|
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 {
|
} else {
|
||||||
nodep->v3error("Unsupported: Assignment pattern applies against non struct/union: "<<vdtypep->prettyTypeName());
|
nodep->v3error("Unsupported: Assignment pattern applies against non struct/union: "<<vdtypep->prettyTypeName());
|
||||||
}
|
}
|
||||||
|
|
@ -1291,10 +1374,11 @@ private:
|
||||||
AstNodeDType* vdtypep = vup->c()->dtypep();
|
AstNodeDType* vdtypep = vup->c()->dtypep();
|
||||||
if (!vdtypep) nodep->v3fatalSrc("Pattern member type not assigned by AstPattern visitor");
|
if (!vdtypep) nodep->v3fatalSrc("Pattern member type not assigned by AstPattern visitor");
|
||||||
nodep->dtypep(vdtypep);
|
nodep->dtypep(vdtypep);
|
||||||
|
UINFO(9," PATMEMBER "<<nodep<<endl);
|
||||||
if (nodep->lhssp()->nextp()) nodep->v3fatalSrc("PatMember value should be singular w/replicates removed");
|
if (nodep->lhssp()->nextp()) nodep->v3fatalSrc("PatMember value should be singular w/replicates removed");
|
||||||
nodep->lhssp()->dtypeFrom(nodep);
|
nodep->lhssp()->dtypeFrom(nodep);
|
||||||
nodep->iterateChildren(*this,WidthVP(nodep->dtypep(),BOTH).p());
|
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) {
|
int visitPatMemberRep(AstPatMember* nodep) {
|
||||||
uint32_t times = 1;
|
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
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
# Version 2.0.
|
# Version 2.0.
|
||||||
|
|
||||||
$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug355");
|
|
||||||
|
|
||||||
compile (
|
compile (
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,18 @@ module t (/*AUTOARG*/
|
||||||
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;
|
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
|
// 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");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$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
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
# Version 2.0.
|
# Version 2.0.
|
||||||
|
|
||||||
$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug355");
|
|
||||||
|
|
||||||
compile (
|
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;
|
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
|
// 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");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue