From 13bf2f19acd5f60d107491156473bf05e25cb7bc Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sun, 13 Jan 2013 14:54:12 -0500 Subject: [PATCH] Internals: Have V3Unknown/Const use only dtypes for selects. --- src/V3Const.cpp | 68 +++++++++++++++++++++++++++++------------------ src/V3Unknown.cpp | 29 ++++++++++---------- 2 files changed, 57 insertions(+), 40 deletions(-) diff --git a/src/V3Const.cpp b/src/V3Const.cpp index a0ccf761d..4e2be9fa4 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -370,37 +370,53 @@ private: // Extraction checks bool warnSelect(AstSel* nodep) { - AstNode* basefromp = AstArraySel::baseFromp(nodep); if (m_doGenerate) { // Never checked yet V3Width::widthParamsEdit(nodep); nodep->iterateChildren(*this); // May need "constifying" } - if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) { - AstVar* varp = varrefp->varp(); - if (!varp->dtypep()) varp->v3fatalSrc("Data type lost"); - AstBasicDType* bdtypep = varp->basicp(); if (!bdtypep) varp->v3fatalSrc("Select of non-selectable type"); - if (m_warn - && nodep->lsbp()->castConst() - && nodep->widthp()->castConst() - && (!bdtypep->isRanged() || bdtypep->msb())) { // else it's non-resolvable parameterized - if (nodep->lsbp()->castConst()->num().isFourState() - || nodep->widthp()->castConst()->num().isFourState()) { - nodep->v3error("Selection index is constantly unknown or tristated: " - "lsb="<lsbp()->name()<<" width="<widthp()->name()); - // Replacing nodep will make a mess above, so we replace the offender - replaceZero(nodep->lsbp()); - } - else if ((nodep->msbConst() > bdtypep->msbMaxSelect()) - || (nodep->lsbConst() > bdtypep->msbMaxSelect())) { - // See also warning in V3Width - nodep->v3warn(SELRANGE, "Selection index out of range: " - <msbConst()<<":"<lsbConst() - <<" outside "<msbMaxSelect()<<":0" - <<(bdtypep->lsb()>=0 ? "" - :" (adjusted +"+cvtToStr(-bdtypep->lsb())+" to account for negative lsb)")); - // Don't replace with zero, we'll do it later - } + // Find range of dtype we are selecting from + // Similar code in V3Unknown::AstSel + int declMsbMaxSelect = -1; + int declLsb = -1; + bool doit = false; + AstNodeDType* dtypep = nodep->fromp()->dtypep()->skipRefp(); + if (!dtypep) nodep->v3fatalSrc("Select of non-selectable type"); + if (AstNodeArrayDType* adtypep = dtypep->castNodeArrayDType()) { + declMsbMaxSelect = adtypep->msbMaxSelect(); + declLsb = adtypep->lsb(); + doit = true; + } else if (AstBasicDType* adtypep = dtypep->castBasicDType()) { + declMsbMaxSelect = adtypep->msbMaxSelect(); + declLsb = adtypep->lsb(); + doit = (!adtypep->isRanged() || adtypep->msb()); // else it's non-resolvable parameterized + } else if (AstNodeClassDType* adtypep = dtypep->castNodeClassDType()) { + declMsbMaxSelect = adtypep->msbMaxSelect(); + declLsb = adtypep->lsb(); + doit = true; + } else { + nodep->v3error("Select from non-selectable "<prettyTypeName()); + } + if (m_warn + && nodep->lsbp()->castConst() + && nodep->widthp()->castConst() + && doit) { + if (nodep->lsbp()->castConst()->num().isFourState() + || nodep->widthp()->castConst()->num().isFourState()) { + nodep->v3error("Selection index is constantly unknown or tristated: " + "lsb="<lsbp()->name()<<" width="<widthp()->name()); + // Replacing nodep will make a mess above, so we replace the offender + replaceZero(nodep->lsbp()); + } + else if ((nodep->msbConst() > declMsbMaxSelect) + || (nodep->lsbConst() > declMsbMaxSelect)) { + // See also warning in V3Width + nodep->v3warn(SELRANGE, "Selection index out of range: " + <msbConst()<<":"<lsbConst() + <<" outside "<=0 ? "" + :" (adjusted +"+cvtToStr(-declLsb)+" to account for negative lsb)")); + // Don't replace with zero, we'll do it later } } return false; // Not a transform, so NOP diff --git a/src/V3Unknown.cpp b/src/V3Unknown.cpp index 85b95d42e..b5239a88c 100644 --- a/src/V3Unknown.cpp +++ b/src/V3Unknown.cpp @@ -323,16 +323,14 @@ private: nodep->iterateChildren(*this); if (!nodep->user1SetOnce()) { // Guard against reading/writing past end of bit vector array - int maxmsb = 0; - bool lvalue = false; AstNode* basefromp = AstArraySel::baseFromp(nodep); + bool lvalue = false; if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) { lvalue = varrefp->lvalue(); - maxmsb = (varrefp->varp()->width()-1); - } else { - // If it's a PARAMETER[bit], then basefromp may be a constant instead of a varrefp - maxmsb = basefromp->width()-1; } + // Find range of dtype we are selecting from + // Similar code in V3Const::warnSelect + int maxmsb = nodep->fromp()->dtypep()->width()-1; int maxlsb = maxmsb - nodep->width() + 1; if (debug()>=9) nodep->dumpTree(cout,"sel_old: "); V3Number maxlsbnum (nodep->fileline(), nodep->lsbp()->width(), maxlsb); @@ -375,22 +373,25 @@ private: if (debug()==9) nodep->dumpTree(cout,"-in: "); // Guard against reading/writing past end of arrays AstNode* basefromp = AstArraySel::baseFromp(nodep->fromp()); - int dimension = AstArraySel::dimension(nodep->fromp()); - int maxmsb = 0; bool lvalue = false; if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) { - AstNodeArrayDType* adtypep = varrefp->varp()->dtypep()->dtypeDimensionp(dimension)->castNodeArrayDType(); - if (!adtypep) nodep->v3fatalSrc("ArraySel to type without array at same depth"); lvalue = varrefp->lvalue(); - maxmsb = adtypep->elementsConst()-1; - } else if (AstConst* lhconstp = basefromp->castConst()) { + } else if (basefromp->castConst()) { // If it's a PARAMETER[bit], then basefromp may be a constant instead of a varrefp - maxmsb = lhconstp->width(); } else { nodep->v3fatalSrc("No VarRef or Const under ArraySel\n"); } + // Find range of dtype we are selecting from + int declElements = -1; + AstNodeDType* dtypep = nodep->fromp()->dtypep()->skipRefp(); + if (!dtypep) nodep->v3fatalSrc("Select of non-selectable type"); + if (AstNodeArrayDType* adtypep = dtypep->castNodeArrayDType()) { + declElements = adtypep->elementsConst(); + } else { + nodep->v3error("Select from non-array "<prettyTypeName()); + } if (debug()>=9) nodep->dumpTree(cout,"arraysel_old: "); - V3Number widthnum (nodep->fileline(), nodep->bitp()->width(), maxmsb); + V3Number widthnum (nodep->fileline(), nodep->bitp()->width(), declElements-1); // See if the condition is constant true AstNode* condp = new AstLte (nodep->fileline(),