mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 01:54:01 +02:00
Fix part-select in constant function, bug916.
This commit is contained in:
@@ -1569,6 +1569,24 @@ V3Number& V3Number::opSel (const V3Number& lhs, uint32_t msbval, uint32_t lsbval
|
||||
return *this;
|
||||
}
|
||||
|
||||
V3Number& V3Number::opSelInto (const V3Number& lhs, const V3Number& lsb, int width) {
|
||||
return opSelInto(lhs, lsb.toSInt(), width);
|
||||
}
|
||||
|
||||
V3Number& V3Number::opSelInto (const V3Number& lhs, int lsbval, int width) {
|
||||
// this[lsbval+width-1 : lsbval] = lhs; Other bits of this are not affected
|
||||
int ibit=0;
|
||||
for(int bit=lsbval; bit<lsbval+width; bit++) {
|
||||
if (ibit>=0 && ibit<(uint32_t)lhs.width()) {
|
||||
setBit(bit,lhs.bitIs(ibit));
|
||||
} else {
|
||||
setBit(bit,'x');
|
||||
}
|
||||
ibit++;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
V3Number& V3Number::opCond (const V3Number& lhs, const V3Number& if1s, const V3Number& if0s) {
|
||||
V3Number lhstrue (lhs.m_fileline); lhstrue.opRedOr(lhs);
|
||||
if (lhstrue.bitIs0(0)) {
|
||||
|
||||
@@ -235,6 +235,8 @@ public:
|
||||
V3Number& opStreamL (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opSel (const V3Number& lhs, const V3Number& rhs, const V3Number& ths);
|
||||
V3Number& opSel (const V3Number& lhs, uint32_t rhs, uint32_t ths);
|
||||
V3Number& opSelInto (const V3Number& lhs, const V3Number& lsb, int width);
|
||||
V3Number& opSelInto (const V3Number& lhs, int lsb, int width);
|
||||
V3Number& opCond (const V3Number& lhs, const V3Number& rhs, const V3Number& ths);
|
||||
V3Number& opCaseEq (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opCaseNeq (const V3Number& lhs, const V3Number& rhs);
|
||||
|
||||
+48
-11
@@ -224,16 +224,24 @@ private:
|
||||
if (!vscp) nodep->v3fatalSrc("Not linked");
|
||||
return vscp;
|
||||
}
|
||||
|
||||
int unrollCount() {
|
||||
return m_params ? v3Global.opt.unrollCount()*16
|
||||
: v3Global.opt.unrollCount();
|
||||
}
|
||||
|
||||
bool jumpingOver(AstNode* nodep) {
|
||||
// True to jump over this node - all visitors must call this up front
|
||||
return (m_jumpp && m_jumpp->labelp()!=nodep);
|
||||
}
|
||||
void assignOutNumber(AstNodeAssign* nodep, AstNode* vscp, const V3Number* nump) {
|
||||
// Don't do setNumber, as value isn't yet visible to following statements
|
||||
if (nodep->castAssignDly()) {
|
||||
// Don't do setNumber, as value isn't yet visible to following statements
|
||||
newOutNumber(vscp)->opAssign(*nump);
|
||||
} else {
|
||||
newNumber(vscp)->opAssign(*nump);
|
||||
newOutNumber(vscp)->opAssign(*nump);
|
||||
}
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstAlways* nodep, AstNUser*) {
|
||||
@@ -438,7 +446,43 @@ private:
|
||||
if (m_anyAssignDly) clearOptimizable(nodep, "Mix of dly/non-dly assigns");
|
||||
m_anyAssignComb = true;
|
||||
}
|
||||
if (!nodep->lhsp()->castVarRef()) {
|
||||
if (AstSel* selp = nodep->lhsp()->castSel()) {
|
||||
if (!m_params) { clearOptimizable(nodep, "LHS has select"); return; }
|
||||
checkNodeInfo(selp);
|
||||
AstVarRef* varrefp = selp->fromp()->castVarRef();
|
||||
if (!varrefp) {
|
||||
clearOptimizable(nodep, "Select LHS isn't simple variable");
|
||||
return;
|
||||
}
|
||||
if (m_checkOnly) {
|
||||
nodep->iterateChildren(*this);
|
||||
} else {
|
||||
selp->lsbp()->iterateAndNext(*this);
|
||||
nodep->rhsp()->iterateAndNext(*this);
|
||||
if (optimizable()) {
|
||||
AstNode* vscp = varOrScope(varrefp);
|
||||
if (optimizable()) {
|
||||
V3Number outnum (nodep->fileline(), varrefp->varp()->widthMin());
|
||||
if (V3Number* outnump = fetchOutNumberNull(vscp)) {
|
||||
outnum = *outnump;
|
||||
} else if (V3Number* outnump = fetchNumberNull(vscp)) {
|
||||
outnum = *outnump;
|
||||
} else { // Assignment to unassigned variable, all bits are X or 0
|
||||
if (varrefp->varp()->basicp() && varrefp->varp()->basicp()->isZeroInit()) {
|
||||
outnum.setAllBits0();
|
||||
} else {
|
||||
outnum.setAllBitsX();
|
||||
}
|
||||
}
|
||||
outnum.opSelInto(*fetchNumber(nodep->rhsp()),
|
||||
*fetchNumber(selp->lsbp()),
|
||||
selp->widthConst());
|
||||
assignOutNumber(nodep, vscp, &outnum);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!nodep->lhsp()->castVarRef()) {
|
||||
clearOptimizable(nodep, "LHS isn't simple variable");
|
||||
}
|
||||
else if (m_checkOnly) {
|
||||
@@ -448,14 +492,7 @@ private:
|
||||
nodep->rhsp()->iterateAndNext(*this);
|
||||
if (optimizable()) {
|
||||
AstNode* vscp = varOrScope(nodep->lhsp()->castVarRef());
|
||||
// Copy by value, not reference, as we don't want a=a+1 to get right results
|
||||
if (nodep->castAssignDly()) {
|
||||
// Don't do setNumber, as value isn't yet visible to following statements
|
||||
newOutNumber(vscp)->opAssign(*fetchNumber(nodep->rhsp()));
|
||||
} else {
|
||||
newNumber(vscp)->opAssign(*fetchNumber(nodep->rhsp()));
|
||||
newOutNumber(vscp)->opAssign(*fetchNumber(nodep->rhsp()));
|
||||
}
|
||||
assignOutNumber(nodep, vscp, fetchNumber(nodep->rhsp()));
|
||||
}
|
||||
}
|
||||
m_inDlyAssign = false;
|
||||
|
||||
Reference in New Issue
Block a user