Internals: Make V3Width dimensionValue more generic. No functional change.

This commit is contained in:
Wilson Snyder 2014-11-28 15:51:35 -05:00
parent 7c588c2e30
commit 2e5f5010f7
1 changed files with 50 additions and 34 deletions

View File

@ -818,45 +818,55 @@ private:
m_attrp = nodep;
nodep->fromp()->iterateAndNext(*this,WidthVP(SELF,BOTH).p());
// Don't iterate children, don't want to lose VarRef.
if (nodep->attrType()==AstAttrType::VAR_BASE) {
switch (nodep->attrType()) {
case AstAttrType::VAR_BASE:
// Soon to be handled in V3LinkWidth SEL generation, under attrp() and newSubLsbOf
} else if (nodep->attrType()==AstAttrType::MEMBER_BASE) {
break;
case AstAttrType::MEMBER_BASE:
// Soon to be handled in V3LinkWidth SEL generation, under attrp() and newSubLsbOf
} else if (nodep->attrType()==AstAttrType::DIM_DIMENSIONS
|| nodep->attrType()==AstAttrType::DIM_UNPK_DIMENSIONS) {
break;
case AstAttrType::DIM_DIMENSIONS:
case AstAttrType::DIM_UNPK_DIMENSIONS: {
if (!nodep->fromp() || !nodep->fromp()->dtypep()) nodep->v3fatalSrc("Unsized expression");
pair<uint32_t,uint32_t> dim = nodep->fromp()->dtypep()->dimensions(true);
int val = (nodep->attrType()==AstAttrType::DIM_UNPK_DIMENSIONS
? dim.second : (dim.first+dim.second));
nodep->replaceWith(new AstConst(nodep->fileline(), AstConst::Signed32(), val)); nodep->deleteTree(); nodep=NULL;
} else if (nodep->attrType()==AstAttrType::DIM_BITS
|| nodep->attrType()==AstAttrType::DIM_HIGH
|| nodep->attrType()==AstAttrType::DIM_INCREMENT
|| nodep->attrType()==AstAttrType::DIM_LEFT
|| nodep->attrType()==AstAttrType::DIM_LOW
|| nodep->attrType()==AstAttrType::DIM_RIGHT
|| nodep->attrType()==AstAttrType::DIM_SIZE) {
break;
}
case AstAttrType::DIM_BITS:
case AstAttrType::DIM_HIGH:
case AstAttrType::DIM_INCREMENT:
case AstAttrType::DIM_LEFT:
case AstAttrType::DIM_LOW:
case AstAttrType::DIM_RIGHT:
case AstAttrType::DIM_SIZE: {
if (!nodep->fromp() || !nodep->fromp()->dtypep()) nodep->v3fatalSrc("Unsized expression");
pair<uint32_t,uint32_t> dim = nodep->fromp()->dtypep()->skipRefp()->dimensions(true);
uint32_t maxdim = dim.first+dim.second;
if (!nodep->dimp() || nodep->dimp()->castConst() || maxdim<1) {
int dim = !nodep->dimp() ? 1 : nodep->dimp()->castConst()->toSInt();
int val = dimensionValue(nodep->fromp()->dtypep(), nodep->attrType(), dim);
nodep->replaceWith(new AstConst(nodep->fileline(), AstConst::Signed32(), val)); nodep->deleteTree(); nodep=NULL;
AstConst* newp = dimensionValue(nodep->fromp()->dtypep(), nodep->attrType(), dim);
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
}
else { // Need a runtime lookup table. Yuk.
if (!nodep->fromp() || !nodep->fromp()->dtypep()) nodep->v3fatalSrc("Unsized expression");
AstVar* varp = dimensionVarp(nodep->fromp()->dtypep(), nodep->attrType());
AstVar* varp = dimensionVarp(nodep->fromp()->dtypep(), nodep->attrType(), maxdim);
AstNode* dimp = nodep->dimp()->unlinkFrBack();
AstVarRef* varrefp = new AstVarRef(nodep->fileline(), varp, false);
varrefp->packagep(v3Global.rootp()->dollarUnitPkgAddp());
AstNode* newp = new AstArraySel(nodep->fileline(), varrefp, dimp);
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
}
} else { // Everything else resolved earlier
break;
}
default: {
// Everything else resolved earlier
nodep->dtypeSetLogicSized(32,1,AstNumeric::UNSIGNED); // Approximation, unsized 32
UINFO(1,"Missing ATTR type case node: "<<nodep<<endl);
nodep->v3fatalSrc("Missing ATTR type case");
break;
}
}
m_attrp = oldAttr;
}
@ -3090,7 +3100,7 @@ private:
return nodep;
}
int dimensionValue(AstNodeDType* nodep, AstAttrType attrType, int dim) {
AstConst* dimensionValue(AstNodeDType* nodep, AstAttrType attrType, int dim) {
// Return the dimension value for the specified attribute and constant dimension
AstNodeDType* dtypep = nodep->skipRefp();
VNumRange declRange; // ranged() set false
@ -3111,8 +3121,10 @@ private:
}
break;
}
AstConst* valp = NULL; // If NULL, construct from val
int val = 0;
if (attrType==AstAttrType::DIM_BITS) {
switch (attrType) {
case AstAttrType::DIM_BITS: {
int bits = 1;
while (dtypep) {
//UINFO(9, " bits at "<<bits<<" "<<dtypep<<endl);
@ -3136,29 +3148,35 @@ private:
} else {
val = bits;
}
} else if (attrType==AstAttrType::DIM_HIGH) {
break; }
case AstAttrType::DIM_HIGH:
val = !declRange.ranged() ? 0 : declRange.hi();
} else if (attrType==AstAttrType::DIM_LEFT) {
break;
case AstAttrType::DIM_LEFT:
val = !declRange.ranged() ? 0 : declRange.left();
} else if (attrType==AstAttrType::DIM_LOW) {
break;
case AstAttrType::DIM_LOW:
val = !declRange.ranged() ? 0 : declRange.lo();
} else if (attrType==AstAttrType::DIM_RIGHT) {
break;
case AstAttrType::DIM_RIGHT:
val = !declRange.ranged() ? 0 : declRange.right();
} else if (attrType==AstAttrType::DIM_INCREMENT) {
break;
case AstAttrType::DIM_INCREMENT:
val = (declRange.ranged() && declRange.littleEndian()) ? -1 : 1;
} else if (attrType==AstAttrType::DIM_SIZE) {
break;
case AstAttrType::DIM_SIZE:
val = !declRange.ranged() ? 0 : declRange.elements();
} else {
break;
default:
nodep->v3fatalSrc("Missing DIM ATTR type case");
break;
}
UINFO(9," $dimension "<<attrType.ascii()<<"("<<((void*)dtypep)<<","<<dim<<")="<<val<<endl);
return val;
if (!valp) valp = new AstConst(nodep->fileline(), AstConst::Signed32(), val);
UINFO(9," $dimension "<<attrType.ascii()<<"("<<((void*)dtypep)<<","<<dim<<")="<<valp<<endl);
return valp;
}
AstVar* dimensionVarp(AstNodeDType* nodep, AstAttrType attrType) {
AstVar* dimensionVarp(AstNodeDType* nodep, AstAttrType attrType, uint32_t maxdim) {
// Return a variable table which has specified dimension properties for this variable
pair<uint32_t,uint32_t> dim = nodep->skipRefp()->dimensions(true);
uint32_t maxdim = dim.first+dim.second;
//
AstNodeArrayDType* vardtypep = new AstUnpackArrayDType(nodep->fileline(),
nodep->findSigned32DType(),
new AstRange(nodep->fileline(), maxdim, 0));
@ -3173,11 +3191,9 @@ private:
// Add to root, as don't know module we are in, and aids later structure sharing
v3Global.rootp()->dollarUnitPkgAddp()->addStmtp(varp);
// Element 0 is a non-index and has speced values
initp->addInitsp(new AstConst(nodep->fileline(), AstConst::Signed32(),
dimensionValue(nodep, attrType, 0)));
initp->addInitsp(dimensionValue(nodep, attrType, 0));
for (unsigned i=1; i<maxdim+1; ++i) {
initp->addInitsp(new AstConst(nodep->fileline(), AstConst::Signed32(),
dimensionValue(nodep, attrType, i)));
initp->addInitsp(dimensionValue(nodep, attrType, i));
}
varp->iterate(*this); // May have already done $unit so must do this var
return varp;