Fix pattern assignment to arrayed basic type, bug769.

This commit is contained in:
Wilson Snyder 2014-06-06 21:14:44 -04:00
parent 0eb5a0a539
commit a428e7f618
3 changed files with 97 additions and 26 deletions

View File

@ -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]

View File

@ -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) {

View File

@ -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;