Internals: Have V3Unknown/Const use only dtypes for selects.

This commit is contained in:
Wilson Snyder 2013-01-13 14:54:12 -05:00
parent 1d5ebfd0b1
commit 13bf2f19ac
2 changed files with 57 additions and 40 deletions

View File

@ -370,37 +370,53 @@ private:
// Extraction checks // Extraction checks
bool warnSelect(AstSel* nodep) { bool warnSelect(AstSel* nodep) {
AstNode* basefromp = AstArraySel::baseFromp(nodep);
if (m_doGenerate) { if (m_doGenerate) {
// Never checked yet // Never checked yet
V3Width::widthParamsEdit(nodep); V3Width::widthParamsEdit(nodep);
nodep->iterateChildren(*this); // May need "constifying" nodep->iterateChildren(*this); // May need "constifying"
} }
if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) { // Find range of dtype we are selecting from
AstVar* varp = varrefp->varp(); // Similar code in V3Unknown::AstSel
if (!varp->dtypep()) varp->v3fatalSrc("Data type lost"); int declMsbMaxSelect = -1;
AstBasicDType* bdtypep = varp->basicp(); if (!bdtypep) varp->v3fatalSrc("Select of non-selectable type"); int declLsb = -1;
if (m_warn bool doit = false;
&& nodep->lsbp()->castConst() AstNodeDType* dtypep = nodep->fromp()->dtypep()->skipRefp();
&& nodep->widthp()->castConst() if (!dtypep) nodep->v3fatalSrc("Select of non-selectable type");
&& (!bdtypep->isRanged() || bdtypep->msb())) { // else it's non-resolvable parameterized if (AstNodeArrayDType* adtypep = dtypep->castNodeArrayDType()) {
if (nodep->lsbp()->castConst()->num().isFourState() declMsbMaxSelect = adtypep->msbMaxSelect();
|| nodep->widthp()->castConst()->num().isFourState()) { declLsb = adtypep->lsb();
nodep->v3error("Selection index is constantly unknown or tristated: " doit = true;
"lsb="<<nodep->lsbp()->name()<<" width="<<nodep->widthp()->name()); } else if (AstBasicDType* adtypep = dtypep->castBasicDType()) {
// Replacing nodep will make a mess above, so we replace the offender declMsbMaxSelect = adtypep->msbMaxSelect();
replaceZero(nodep->lsbp()); declLsb = adtypep->lsb();
} doit = (!adtypep->isRanged() || adtypep->msb()); // else it's non-resolvable parameterized
else if ((nodep->msbConst() > bdtypep->msbMaxSelect()) } else if (AstNodeClassDType* adtypep = dtypep->castNodeClassDType()) {
|| (nodep->lsbConst() > bdtypep->msbMaxSelect())) { declMsbMaxSelect = adtypep->msbMaxSelect();
// See also warning in V3Width declLsb = adtypep->lsb();
nodep->v3warn(SELRANGE, "Selection index out of range: " doit = true;
<<nodep->msbConst()<<":"<<nodep->lsbConst() } else {
<<" outside "<<bdtypep->msbMaxSelect()<<":0" nodep->v3error("Select from non-selectable "<<dtypep->prettyTypeName());
<<(bdtypep->lsb()>=0 ? "" }
:" (adjusted +"+cvtToStr(-bdtypep->lsb())+" to account for negative lsb)")); if (m_warn
// Don't replace with zero, we'll do it later && 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="<<nodep->lsbp()->name()<<" width="<<nodep->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: "
<<nodep->msbConst()<<":"<<nodep->lsbConst()
<<" outside "<<declMsbMaxSelect<<":0"
<<(declLsb>=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 return false; // Not a transform, so NOP

View File

@ -323,16 +323,14 @@ private:
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (!nodep->user1SetOnce()) { if (!nodep->user1SetOnce()) {
// Guard against reading/writing past end of bit vector array // Guard against reading/writing past end of bit vector array
int maxmsb = 0;
bool lvalue = false;
AstNode* basefromp = AstArraySel::baseFromp(nodep); AstNode* basefromp = AstArraySel::baseFromp(nodep);
bool lvalue = false;
if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) { if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) {
lvalue = varrefp->lvalue(); 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; int maxlsb = maxmsb - nodep->width() + 1;
if (debug()>=9) nodep->dumpTree(cout,"sel_old: "); if (debug()>=9) nodep->dumpTree(cout,"sel_old: ");
V3Number maxlsbnum (nodep->fileline(), nodep->lsbp()->width(), maxlsb); V3Number maxlsbnum (nodep->fileline(), nodep->lsbp()->width(), maxlsb);
@ -375,22 +373,25 @@ private:
if (debug()==9) nodep->dumpTree(cout,"-in: "); if (debug()==9) nodep->dumpTree(cout,"-in: ");
// Guard against reading/writing past end of arrays // Guard against reading/writing past end of arrays
AstNode* basefromp = AstArraySel::baseFromp(nodep->fromp()); AstNode* basefromp = AstArraySel::baseFromp(nodep->fromp());
int dimension = AstArraySel::dimension(nodep->fromp());
int maxmsb = 0;
bool lvalue = false; bool lvalue = false;
if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) { 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(); lvalue = varrefp->lvalue();
maxmsb = adtypep->elementsConst()-1; } else if (basefromp->castConst()) {
} else if (AstConst* lhconstp = basefromp->castConst()) {
// If it's a PARAMETER[bit], then basefromp may be a constant instead of a varrefp // If it's a PARAMETER[bit], then basefromp may be a constant instead of a varrefp
maxmsb = lhconstp->width();
} else { } else {
nodep->v3fatalSrc("No VarRef or Const under ArraySel\n"); 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 "<<dtypep->prettyTypeName());
}
if (debug()>=9) nodep->dumpTree(cout,"arraysel_old: "); 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 // See if the condition is constant true
AstNode* condp = new AstLte (nodep->fileline(), AstNode* condp = new AstLte (nodep->fileline(),