From a428e7f618341a125a8378c1c9cb641d59a1cc3a Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Fri, 6 Jun 2014 21:14:44 -0400 Subject: [PATCH] Fix pattern assignment to arrayed basic type, bug769. --- Changes | 2 + src/V3Width.cpp | 116 ++++++++++++++++++------ test_regress/t/t_array_pattern_packed.v | 5 + 3 files changed, 97 insertions(+), 26 deletions(-) diff --git a/Changes b/Changes index 028b719c6..9cf9b0365 100644 --- a/Changes +++ b/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] diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 590fe2220..92091f8b4 100644 --- a/src/V3Width.cpp +++ b/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 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 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: "<keyp()->prettyTypeName()); - } - } - if (patmap.find(element) != patmap.end()) { - patp->v3error("Assignment pattern key used multiple times: "<declRange().leftToRightInc(); - } - } - UINFO(9,"ent "<declRange().hi()<<" to "<declRange().lo()<castNodeArrayDType()) { + AstNodeArrayDType* arrayp = vdtypep->castNodeArrayDType(); + VNumRange range = arrayp->declRange(); + PatVecMap patmap = patVectorMap(nodep, range); + UINFO(9,"ent "<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.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: "<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: "<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: "<keyp()->prettyTypeName()); + } + } + if (patmap.find(element) != patmap.end()) { + patp->v3error("Assignment pattern key used multiple times: "<