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
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="<<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() > bdtypep->msbMaxSelect())
|| (nodep->lsbConst() > bdtypep->msbMaxSelect())) {
// See also warning in V3Width
nodep->v3warn(SELRANGE, "Selection index out of range: "
<<nodep->msbConst()<<":"<<nodep->lsbConst()
<<" outside "<<bdtypep->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 "<<dtypep->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="<<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

View File

@ -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 "<<dtypep->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(),