forked from github/verilator
Fix pattern assignment to arrayed basic type, bug769.
This commit is contained in:
parent
0eb5a0a539
commit
a428e7f618
2
Changes
2
Changes
@ -15,6 +15,8 @@ indicates the contributor was also the author of the fix; Thanks!
|
||||
|
||||
**** Fix seg-fault with variable of parameterized interface, bug692. [Jie Xu]
|
||||
|
||||
**** Fix pattern assignment to arrayed basic type, bug769. [Jie Xu]
|
||||
|
||||
**** Fix shift corner-cases, bug765, bug766, bug768, bug772, bug776. [Clifford Wolf]
|
||||
|
||||
**** Fix C compiler interpreting signing, bug773. [Clifford Wolf]
|
||||
|
116
src/V3Width.cpp
116
src/V3Width.cpp
@ -163,6 +163,9 @@ private:
|
||||
bool m_doGenerate; // Do errors later inside generate statement
|
||||
int m_dtTables; // Number of created data type tables
|
||||
|
||||
// TYPES
|
||||
typedef map<int,AstPatMember*> PatVecMap;
|
||||
|
||||
// ENUMS
|
||||
enum ExtendRule {
|
||||
EXTEND_EXP, // Extend if expect sign and node signed, e.g. node=y in ADD(x,y), "x + y"
|
||||
@ -1398,34 +1401,16 @@ private:
|
||||
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);
|
||||
else if (vdtypep->castNodeArrayDType()) {
|
||||
AstNodeArrayDType* arrayp = vdtypep->castNodeArrayDType();
|
||||
VNumRange range = arrayp->declRange();
|
||||
PatVecMap patmap = patVectorMap(nodep, range);
|
||||
UINFO(9,"ent "<<range.hi()<<" to "<<range.lo()<<endl);
|
||||
AstNode* newp = NULL;
|
||||
for (int ent=arrayp->declRange().hi(); ent>=arrayp->declRange().lo(); --ent) {
|
||||
for (int ent=range.hi(); ent>=range.lo(); --ent) {
|
||||
AstPatMember* newpatp = NULL;
|
||||
AstPatMember* patp = NULL;
|
||||
PatMap::iterator it=patmap.find(ent);
|
||||
PatVecMap::iterator it=patmap.find(ent);
|
||||
if (it == patmap.end()) {
|
||||
if (defaultp) {
|
||||
newpatp = defaultp->cloneTree(false);
|
||||
@ -1442,7 +1427,7 @@ private:
|
||||
// Determine initial values
|
||||
vdtypep = arrayp->subDTypep();
|
||||
// Don't want the RHS an array
|
||||
patp->dtypep(arrayp->subDTypep());
|
||||
patp->dtypep(vdtypep);
|
||||
// Determine values - might be another InitArray
|
||||
patp->accept(*this,WidthVP(patp->dtypep(),BOTH).p());
|
||||
// Convert to InitArray or constify immediately
|
||||
@ -1479,6 +1464,62 @@ private:
|
||||
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 if (vdtypep->castBasicDType()
|
||||
&& vdtypep->castBasicDType()->isRanged()) {
|
||||
AstBasicDType* bdtypep = vdtypep->castBasicDType();
|
||||
VNumRange range = bdtypep->declRange();
|
||||
PatVecMap patmap = patVectorMap(nodep, range);
|
||||
UINFO(9,"ent "<<range.hi()<<" to "<<range.lo()<<endl);
|
||||
AstNode* newp = NULL;
|
||||
for (int ent=range.hi(); ent>=range.lo(); --ent) {
|
||||
AstPatMember* newpatp = NULL;
|
||||
AstPatMember* patp = NULL;
|
||||
PatVecMap::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 = nodep->findLogicBoolDType();
|
||||
// Don't want the RHS an array
|
||||
patp->dtypep(vdtypep);
|
||||
// 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 (valuep->castConst()) {
|
||||
// Forming a AstConcat will cause problems with unsized (uncommitted sized) constants
|
||||
if (AstNode* newp = WidthCommitVisitor::newIfConstCommitSize(valuep->castConst())) {
|
||||
pushDeletep(valuep); valuep=NULL;
|
||||
valuep = newp;
|
||||
}
|
||||
}
|
||||
{ // 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.empty()) 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());
|
||||
}
|
||||
@ -2995,6 +3036,29 @@ private:
|
||||
return varp;
|
||||
}
|
||||
|
||||
PatVecMap patVectorMap(AstPattern* nodep, const VNumRange& range) {
|
||||
PatVecMap patmap;
|
||||
int element = range.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 += range.leftToRightInc();
|
||||
}
|
||||
return patmap;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// METHODS - special type detection
|
||||
void assertAtStatement(AstNode* nodep, AstNUser* vup) {
|
||||
|
@ -12,7 +12,12 @@ module t (/*AUTOARG*/
|
||||
|
||||
logic [1:0] [3:0] [3:0] array_simp; // big endian array
|
||||
|
||||
logic [3:0] array_oned;
|
||||
|
||||
initial begin
|
||||
array_oned = '{2:1'b1, 0:1'b1, default:1'b0};
|
||||
if (array_oned != 4'b0101) $stop;
|
||||
|
||||
array_simp[0] = '{ 4'd3, 4'd2, 4'd1, 4'd0};
|
||||
if (array_simp[0] !== 16'h3210) $stop;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user