Internals: V3Number tracks node information, part of bug1305.

Signed-off-by: Wilson Snyder <wsnyder@wsnyder.org>
This commit is contained in:
Todd Strader 2019-05-09 20:03:19 -04:00 committed by Wilson Snyder
parent 00efa05b50
commit eac3458647
27 changed files with 469 additions and 382 deletions

View File

@ -1628,19 +1628,19 @@ public:
else if (expr2p) dtypeFrom(expr2p);
}
ASTNODE_BASE_FUNCS(NodeCond)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, const V3Number& ths) {
if (lhs.isNeqZero()) out.opAssign(rhs); else out.opAssign(ths); }
AstNode* condp() const { return op1p(); } // op1 = Condition
AstNode* expr1p() const { return op2p(); } // op2 = If true...
AstNode* expr2p() const { return op3p(); } // op3 = If false...
virtual void numberOperate(V3Number& out, const V3Number& lhs,
const V3Number& rhs, const V3Number& ths);
AstNode* condp() const { return op1p(); } // op1 = Condition
AstNode* expr1p() const { return op2p(); } // op2 = If true...
AstNode* expr2p() const { return op3p(); } // op3 = If false...
virtual string emitVerilog() { return "%k(%l %f? %r %k: %t)"; }
virtual string emitC() { return "VL_COND_%nq%lq%rq%tq(%nw,%lw,%rw,%tw, %P, %li, %ri, %ti)"; }
virtual bool cleanOut() { return false; } // clean if e1 & e2 clean
virtual bool cleanOut() { return false; } // clean if e1 & e2 clean
virtual bool cleanLhs() { return true; }
virtual bool cleanRhs() { return false; } virtual bool cleanThs() { return false; } // Propagates up
virtual bool sizeMattersLhs() { return false; } virtual bool sizeMattersRhs() { return false; }
virtual bool sizeMattersThs() { return false; }
virtual int instrCount() const { return instrCountBranch(); }
virtual int instrCount() const { return instrCountBranch(); }
virtual AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) = 0;
};

View File

@ -84,6 +84,11 @@ const char* AstNodeClassDType::broken() const {
return NULL;
}
void AstNodeCond::numberOperate(V3Number& out, const V3Number& lhs,
const V3Number& rhs, const V3Number& ths) {
if (lhs.isNeqZero()) out.opAssign(rhs); else out.opAssign(ths);
}
int AstBasicDType::widthAlignBytes() const {
if (width()<=8) return 1;
else if (width()<=16) return 2;

View File

@ -48,56 +48,82 @@
class AstConst : public AstNodeMath {
// A constant
private:
V3Number m_num; // Constant value
public:
AstConst(FileLine* fl, const V3Number& num)
:AstNodeMath(fl)
,m_num(num) {
if (m_num.isDouble()) {
dtypeSetDouble();
V3Number m_num; // Constant value
void initWithNumber() {
if (m_num.isDouble()) {
dtypeSetDouble();
} else if (m_num.isString()) {
dtypeSetString();
} else {
dtypeSetLogicSized(m_num.width(), m_num.sized()?0:m_num.widthMin(),
dtypeSetString();
} else {
dtypeSetLogicSized(m_num.width(), (m_num.sized() ? 0 : m_num.widthMin()),
m_num.isSigned() ? AstNumeric::SIGNED
: AstNumeric::UNSIGNED);
: AstNumeric::UNSIGNED);
}
}
public:
AstConst(FileLine* fl, const V3Number& num)
: AstNodeMath(fl)
, m_num(num) {
initWithNumber();
}
class WidthedValue {}; // for creator type-overload selection
AstConst(FileLine* fl, WidthedValue, int width, uint32_t value)
: AstNodeMath(fl)
, m_num(this, width, value) {
initWithNumber();
}
class StringToParse {}; // for creator type-overload selection
AstConst(FileLine* fl, StringToParse, const char* sourcep)
: AstNodeMath(fl)
, m_num(this, sourcep) {
initWithNumber();
}
class VerilogStringLiteral {}; // for creator type-overload selection
AstConst(FileLine* fl, VerilogStringLiteral, const string& str)
: AstNodeMath(fl)
, m_num(V3Number::VerilogStringLiteral(), this, str) {
initWithNumber();
}
AstConst(FileLine* fl, uint32_t num)
:AstNodeMath(fl)
,m_num(V3Number(fl,32,num)) { dtypeSetLogicSized(m_num.width(),
m_num.sized()?0:m_num.widthMin(),
AstNumeric::UNSIGNED); }
: AstNodeMath(fl)
, m_num(V3Number(this, 32, num)) {
dtypeSetLogicSized(m_num.width(),
m_num.sized() ? 0 : m_num.widthMin(),
AstNumeric::UNSIGNED);
}
class Unsized32 {}; // for creator type-overload selection
AstConst(FileLine* fl, Unsized32, uint32_t num) // Unsized 32-bit integer of specified value
:AstNodeMath(fl)
,m_num(V3Number(fl,32,num)) { m_num.width(32,false); dtypeSetLogicSized(32,m_num.widthMin(),
AstNumeric::UNSIGNED); }
class Signed32 {}; // for creator type-overload selection
: AstNodeMath(fl)
, m_num(V3Number(this, 32, num)) {
m_num.width(32,false);
dtypeSetLogicSized(32, m_num.widthMin(), AstNumeric::UNSIGNED);
}
class Signed32 {}; // for creator type-overload selection
AstConst(FileLine* fl, Signed32, int32_t num) // Signed 32-bit integer of specified value
:AstNodeMath(fl)
,m_num(V3Number(fl,32,num)) { m_num.width(32,32); dtypeSetLogicSized(32,m_num.widthMin(),
AstNumeric::SIGNED); }
class RealDouble {}; // for creator type-overload selection
: AstNodeMath(fl)
, m_num(V3Number(this, 32, num)) {
m_num.width(32,32);
dtypeSetLogicSized(32, m_num.widthMin(), AstNumeric::SIGNED);
}
class RealDouble {}; // for creator type-overload selection
AstConst(FileLine* fl, RealDouble, double num)
:AstNodeMath(fl)
,m_num(V3Number(fl,64)) { m_num.setDouble(num); dtypeSetDouble(); }
class String {}; // for creator type-overload selection
: AstNodeMath(fl)
, m_num(V3Number(this, 64)) { m_num.setDouble(num); dtypeSetDouble(); }
class String {}; // for creator type-overload selection
AstConst(FileLine* fl, String, const string& num)
:AstNodeMath(fl)
,m_num(V3Number(V3Number::String(), fl, num)) { dtypeSetString(); }
: AstNodeMath(fl)
, m_num(V3Number(V3Number::String(), this, num)) { dtypeSetString(); }
class LogicFalse {};
AstConst(FileLine* fl, LogicFalse) // Shorthand const 0, know the dtype should be a logic of size 1
:AstNodeMath(fl)
,m_num(V3Number(fl,1,0)) { dtypeSetLogicBool(); }
AstConst(FileLine* fl, LogicFalse) // Shorthand const 0, dtype should be a logic of size 1
: AstNodeMath(fl)
, m_num(V3Number(this, 1, 0)) { dtypeSetLogicBool(); }
class LogicTrue {};
AstConst(FileLine* fl, LogicTrue) // Shorthand const 1, know the dtype should be a logic of size 1
:AstNodeMath(fl)
,m_num(V3Number(fl,1,1)) { dtypeSetLogicBool(); }
AstConst(FileLine* fl, LogicTrue) // Shorthand const 1, dtype should be a logic of size 1
: AstNodeMath(fl)
, m_num(V3Number(this, 1, 1)) { dtypeSetLogicBool(); }
ASTNODE_NODE_FUNCS(Const)
virtual string name() const { return num().ascii(); } // * = Value
virtual const V3Number& num() const { return m_num; } // * = Value
virtual string name() const { return num().ascii(); } // * = Value
virtual const V3Number& num() const { return m_num; } // * = Value
uint32_t toUInt() const { return num().toUInt(); }
vlsint32_t toSInt() const { return num().toSInt(); }
vluint64_t toUQuad() const { return num().toUQuad(); }

View File

@ -125,9 +125,9 @@ void V3CCtors::evalAsserts() {
newp = new AstWordSel(varp->fileline(), newp,
new AstConst(varp->fileline(), varp->widthWords()-1));
}
uint64_t value = VL_MASK_Q(storedWidth) & ~VL_MASK_Q(lastWordWidth);
V3Number num (varp->fileline(), storedWidth, value);
newp = new AstAnd(varp->fileline(), newp,
uint64_t value = VL_MASK_Q(storedWidth) & ~VL_MASK_Q(lastWordWidth);
V3Number num (varp, storedWidth, value);
newp = new AstAnd(varp->fileline(), newp,
new AstConst(varp->fileline(), num));
AstNodeIf* ifp = new AstIf(varp->fileline(), newp,
new AstCStmt(varp->fileline(),

View File

@ -170,10 +170,10 @@ private:
if (neverItem(nodep, iconstp)) {
// X in casez can't ever be executed
} else {
V3Number nummask (itemp->fileline(), iconstp->width());
nummask.opBitsNonX(iconstp->num());
uint32_t mask = nummask.toUInt();
V3Number numval (itemp->fileline(), iconstp->width());
V3Number nummask (itemp, iconstp->width());
nummask.opBitsNonX(iconstp->num());
uint32_t mask = nummask.toUInt();
V3Number numval (itemp, iconstp->width());
numval.opBitsOne(iconstp->num());
uint32_t val = numval.toUInt();
for (uint32_t i=0; i<(1UL<<m_caseWidth); ++i) {
@ -248,9 +248,9 @@ private:
if (tree0p && !tree0p->user3()) tree0p = tree0p->cloneTree(true);
if (tree1p && !tree1p->user3()) tree1p = tree1p->cloneTree(true);
// Alternate scheme if we ever do multiple bits at a time:
//V3Number nummask (cexprp->fileline(), cexprp->width(), (1UL<<msb));
//AstNode* and1p = new AstAnd(cexprp->fileline(), cexprp->cloneTree(false),
// Alternate scheme if we ever do multiple bits at a time:
//V3Number nummask (cexprp, cexprp->width(), (1UL<<msb));
//AstNode* and1p = new AstAnd(cexprp->fileline(), cexprp->cloneTree(false),
// new AstConst(cexprp->fileline(), nummask));
AstNode* and1p = new AstSel(cexprp->fileline(), cexprp->cloneTree(false),
msb, 1);
@ -334,9 +334,9 @@ private:
condp = new AstAnd(itemp->fileline(), ap, bp);
} else if (iconstp && iconstp->num().isFourState()
&& (nodep->casex() || nodep->casez() || nodep->caseInside())) {
V3Number nummask (itemp->fileline(), iconstp->width());
nummask.opBitsNonX(iconstp->num());
V3Number numval (itemp->fileline(), iconstp->width());
V3Number nummask (itemp, iconstp->width());
nummask.opBitsNonX(iconstp->num());
V3Number numval (itemp, iconstp->width());
numval.opBitsOne(iconstp->num());
AstNode* and1p = new AstAnd(itemp->fileline(), cexprp->cloneTree(false),
new AstConst(itemp->fileline(), nummask));

View File

@ -119,9 +119,9 @@ private:
AstNRelinker relinkHandle;
nodep->unlinkFrBack(&relinkHandle);
//
computeCppWidth(nodep);
V3Number mask (nodep->fileline(), cppWidth(nodep));
mask.setMask(nodep->widthMin());
computeCppWidth(nodep);
V3Number mask (nodep, cppWidth(nodep));
mask.setMask(nodep->widthMin());
AstNode* cleanp = new AstAnd(nodep->fileline(),
new AstConst(nodep->fileline(), mask),
nodep);

View File

@ -385,9 +385,9 @@ private:
extendp->unlinkFrBack()->deleteTree(); // aka nodep->lhsp.
nodep->rhsp(smallerp);
constp->unlinkFrBack();
V3Number num (constp->fileline(), subsize);
num.opAssign(constp->num());
constp->unlinkFrBack();
V3Number num (constp, subsize);
num.opAssign(constp->num());
nodep->lhsp(new AstConst(constp->fileline(), num));
constp->deleteTree(); VL_DANGLING(constp);
if (debug()>=9) nodep->dumpTree(cout,"BI(EXTEND)-ou:");
@ -597,8 +597,8 @@ private:
oldp->deleteTree(); VL_DANGLING(oldp);
}
void replaceNum(AstNode* nodep, uint32_t val) {
V3Number num (nodep->fileline(), nodep->width(), val);
replaceNum(nodep, num); VL_DANGLING(nodep);
V3Number num (nodep, nodep->width(), val);
replaceNum(nodep, num); VL_DANGLING(nodep);
}
void replaceNumSigned(AstNodeBiop* nodep, uint32_t val) {
// We allow both sides to be constant, as one may have come from parameter propagation, etc.
@ -631,24 +631,24 @@ private:
}
}
void replaceAllOnes(AstNode* nodep) {
V3Number ones (nodep->fileline(), nodep->width(), 0);
ones.setMask(nodep->width());
replaceNum(nodep, ones); VL_DANGLING(nodep);
V3Number ones (nodep, nodep->width(), 0);
ones.setMask(nodep->width());
replaceNum(nodep, ones); VL_DANGLING(nodep);
}
void replaceConst(AstNodeUniop* nodep) {
V3Number num (nodep->fileline(), nodep->width());
V3Number num (nodep, nodep->width());
nodep->numberOperate(num, VN_CAST(nodep->lhsp(), Const)->num());
UINFO(4,"UNICONST -> "<<num<<endl);
replaceNum(nodep, num); VL_DANGLING(nodep);
UINFO(4,"UNICONST -> "<<num<<endl);
replaceNum(nodep, num); VL_DANGLING(nodep);
}
void replaceConst(AstNodeBiop* nodep) {
V3Number num (nodep->fileline(), nodep->width());
V3Number num (nodep, nodep->width());
nodep->numberOperate(num, VN_CAST(nodep->lhsp(), Const)->num(), VN_CAST(nodep->rhsp(), Const)->num());
UINFO(4,"BICONST -> "<<num<<endl);
replaceNum(nodep, num); VL_DANGLING(nodep);
UINFO(4,"BICONST -> "<<num<<endl);
replaceNum(nodep, num); VL_DANGLING(nodep);
}
void replaceConst(AstNodeTriop* nodep) {
V3Number num (nodep->fileline(), nodep->width());
V3Number num (nodep, nodep->width());
nodep->numberOperate(num, VN_CAST(nodep->lhsp(), Const)->num(),
VN_CAST(nodep->rhsp(), Const)->num(),
VN_CAST(nodep->thsp(), Const)->num());
@ -915,20 +915,20 @@ private:
shift1p->deleteTree(); VL_DANGLING(shift1p);
shift2p->deleteTree(); VL_DANGLING(shift2p);
AstNode* newp;
V3Number mask1 (nodep->fileline(), nodep->width());
V3Number ones (nodep->fileline(), nodep->width());
ones.setMask(nodep->width());
if (shift1<0) {
mask1.opShiftR(ones,V3Number(nodep->fileline(),VL_WORDSIZE,-shift1));
} else {
mask1.opShiftL(ones,V3Number(nodep->fileline(),VL_WORDSIZE,shift1));
}
V3Number mask (nodep->fileline(), nodep->width());
if (shift2<0) {
mask.opShiftR(mask1,V3Number(nodep->fileline(),VL_WORDSIZE,-shift2));
} else {
mask.opShiftL(mask1,V3Number(nodep->fileline(),VL_WORDSIZE,shift2));
}
V3Number mask1 (nodep, nodep->width());
V3Number ones (nodep, nodep->width());
ones.setMask(nodep->width());
if (shift1<0) {
mask1.opShiftR(ones, V3Number(nodep, VL_WORDSIZE, -shift1));
} else {
mask1.opShiftL(ones, V3Number(nodep, VL_WORDSIZE, shift1));
}
V3Number mask (nodep, nodep->width());
if (shift2<0) {
mask.opShiftR(mask1, V3Number(nodep, VL_WORDSIZE, -shift2));
} else {
mask.opShiftL(mask1, V3Number(nodep, VL_WORDSIZE, shift2));
}
if (newshift<0) {
newp = new AstShiftR(nodep->fileline(), ap,
new AstConst(nodep->fileline(), -newshift));
@ -1194,9 +1194,9 @@ private:
AstConst* andConstp = VN_CAST(VN_CAST(nodep, And)->lhsp(), Const);
AstNode* fromp = VN_CAST(VN_CAST(nodep, And)->rhsp(), ShiftR)->lhsp()->unlinkFrBack();
AstConst* shiftConstp = VN_CAST(VN_CAST(VN_CAST(nodep, And)->rhsp(), ShiftR)->rhsp(), Const);
V3Number val (andConstp->fileline(), andConstp->width());
val.opShiftL(andConstp->num(), shiftConstp->num());
AstAnd* newp = new AstAnd(nodep->fileline(),
V3Number val (andConstp, andConstp->width());
val.opShiftL(andConstp->num(), shiftConstp->num());
AstAnd* newp = new AstAnd(nodep->fileline(),
new AstConst(nodep->fileline(), val),
fromp);
// widthMin no longer applicable if different C-expanded width
@ -2002,9 +2002,10 @@ private:
if (argp) {
AstNode* nextp=argp->nextp();
if (argp && VN_IS(argp, Const)) { // Convert it
string out = VN_CAST(argp, Const)->num().displayed(nodep->fileline(), fmt);
UINFO(9," DispConst: "<<fmt<<" -> "<<out<<" for "<<argp<<endl);
// fmt = out w/ replace % with %% as it must be literal.
string out = VN_CAST(argp, Const)->num().displayed(nodep, fmt);
UINFO(9," DispConst: "<<fmt<<" -> "<<out
<<" for "<<argp<<endl);
// fmt = out w/ replace % with %% as it must be literal.
fmt = VString::quotePercent(out);
argp->unlinkFrBack()->deleteTree(); VL_DANGLING(argp);
}

View File

@ -280,9 +280,9 @@ private:
= new AstAssign(nodep->fileline(),
new AstVarRef(nodep->fileline(), setvscp, true),
new AstConst(nodep->fileline(),
V3Number(nodep->fileline(),1,true)));
nodep->addNextHere(setassignp);
}
V3Number(nodep, 1, true)));
nodep->addNextHere(setassignp);
}
if (m_nextDlyp) { // Tell next assigndly it can share the variable
m_nextDlyp->user3p(setvscp);
}

View File

@ -2979,7 +2979,7 @@ class EmitCTrace : EmitCStmts {
itemp=VN_CAST(itemp->nextp(), EnumItem)) {
AstConst* constp = VN_CAST(itemp->valuep(), Const);
if (++nvals > 1) puts(", ");
putbs("\""+constp->num().displayed(nodep->fileline(), "%0b")+"\"");
putbs("\""+constp->num().displayed(nodep, "%0b")+"\"");
}
puts("};\n");
puts("vcdp->declDTypeEnum("+cvtToStr(enumNum)

View File

@ -59,13 +59,13 @@ private:
return (nodep->width()+(VL_WORDSIZE-1)) & ~(VL_WORDSIZE-1);
}
V3Number notWideMask(AstNode* nodep) {
return V3Number(nodep->fileline(), VL_WORDSIZE, ~VL_MASK_I(nodep->widthMin()));
return V3Number(nodep, VL_WORDSIZE, ~VL_MASK_I(nodep->widthMin()));
}
V3Number wordMask(AstNode* nodep) {
if (nodep->isWide()) {
return V3Number(nodep->fileline(), VL_WORDSIZE, VL_MASK_I(nodep->widthMin()));
} else {
V3Number mask (nodep->fileline(), longOrQuadWidth(nodep));
if (nodep->isWide()) {
return V3Number(nodep, VL_WORDSIZE, VL_MASK_I(nodep->widthMin()));
} else {
V3Number mask (nodep, longOrQuadWidth(nodep));
mask.setMask(nodep->widthMin());
return mask;
}
@ -222,8 +222,8 @@ private:
if (rhsp->num().isFourState()) {
rhsp->v3error("Unsupported: 4-state numbers in this context");
}
for (int w=0; w<nodep->widthWords(); w++) {
V3Number num (nodep->fileline(), VL_WORDSIZE, rhsp->num().dataWord(w));
for (int w=0; w<nodep->widthWords(); w++) {
V3Number num (nodep, VL_WORDSIZE, rhsp->num().dataWord(w));
addWordAssign(nodep, w, new AstConst(nodep->fileline(), num));
}
return true;
@ -368,9 +368,9 @@ private:
newSelBitBit(nodep->lsbp()),
nodep->width());
// If > 1 bit, we might be crossing the word boundary
AstNode* midp=NULL;
V3Number zero (nodep->fileline(), longOrQuadWidth(nodep));
if (nodep->widthConst() > 1) {
AstNode* midp=NULL;
V3Number zero (nodep, longOrQuadWidth(nodep));
if (nodep->widthConst() > 1) {
AstNode* midwordp = // SEL(from,[1+wordnum])
new AstWordSel(nodep->fromp()->fileline(),
nodep->fromp()->cloneTree(true),
@ -475,9 +475,9 @@ private:
lowwordp,
newSelBitBit(rhsp->lsbp()),
VL_WORDSIZE);
// Upper bits
V3Number zero (nodep->fileline(), VL_WORDSIZE, 0);
AstNode* midwordp = // SEL(from,[1+wordnum])
// Upper bits
V3Number zero (nodep, VL_WORDSIZE, 0);
AstNode* midwordp = // SEL(from,[1+wordnum])
new AstWordSel(rhsp->fromp()->fileline(),
rhsp->fromp()->cloneTree(true),
newSelBitWord(rhsp->lsbp(), w+1));
@ -517,9 +517,9 @@ private:
AstNode* destp = lhsp->fromp()->unlinkFrBack();
int lsb = lhsp->lsbConst();
int msb = lhsp->msbConst();
V3Number maskset (nodep->fileline(), destp->widthMin());
for (int bit=lsb; bit<(msb+1); bit++) maskset.setBit(bit,1);
V3Number maskold (nodep->fileline(), destp->widthMin()); maskold.opNot(maskset);
V3Number maskset (nodep, destp->widthMin());
for (int bit=lsb; bit<(msb+1); bit++) maskset.setBit(bit, 1);
V3Number maskold (nodep, destp->widthMin()); maskold.opNot(maskset);
if (destwide) {
UINFO(8," ASSIGNSEL(const,wide) "<<nodep<<endl);
for (int w=0; w<destp->widthWords(); w++) {
@ -624,7 +624,7 @@ private:
AstNode* oldvalp = destp->cloneTree(true);
fixCloneLvalue(oldvalp);
V3Number maskwidth (nodep->fileline(), destp->widthMin());
V3Number maskwidth (nodep, destp->widthMin());
for (int bit=0; bit < lhsp->widthConst(); bit++) maskwidth.setBit(bit,1);
if (destp->isQuad() && !rhsp->isQuad()) rhsp = new AstCCast(nodep->fileline(), rhsp, nodep);
@ -811,8 +811,8 @@ private:
replaceWithDelete(nodep,newp); VL_DANGLING(nodep);
} else {
UINFO(8," REDOR->EQ "<<nodep<<endl);
AstNode* lhsp = nodep->lhsp()->unlinkFrBack();
V3Number zero (nodep->fileline(), longOrQuadWidth(nodep));
AstNode* lhsp = nodep->lhsp()->unlinkFrBack();
V3Number zero (nodep, longOrQuadWidth(nodep));
AstNode* newp = new AstNeq(nodep->fileline(),
new AstConst(nodep->fileline(), zero),
lhsp);

View File

@ -609,8 +609,7 @@ class LinkDotFindVisitor : public AstNVisitor {
if (literal[0] == '"') {
// This is a string
string v = literal.substr(1, literal.find('"', 1) - 1);
V3Number n(V3Number::VerilogStringLiteral(), fl, v);
return new AstConst(fl,n);
return new AstConst(fl, AstConst::VerilogStringLiteral(), v);
} else if ((literal.find('.') != string::npos)
|| (literal.find('e') != string::npos)) {
// This may be a real
@ -629,12 +628,10 @@ class LinkDotFindVisitor : public AstNVisitor {
// the Verilog literal parser.
char* endp;
int v = strtol(literal.c_str(), &endp, 0);
if ((v != 0) && (endp[0] == 0)) { // C literal
V3Number n(fl, 32, v);
return new AstConst(fl, n);
} else { // Try a Verilog literal (fatals if not)
V3Number n(fl, literal.c_str());
return new AstConst(fl, n);
if ((v != 0) && (endp[0] == 0)) { // C literal
return new AstConst(fl, AstConst::WidthedValue(), 32, v);
} else { // Try a Verilog literal (fatals if not)
return new AstConst(fl, AstConst::StringToParse(), literal.c_str());
}
}
return NULL;

View File

@ -141,9 +141,9 @@ private:
countp);
AstNode* decp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true),
new AstSub(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false),
new AstConst(nodep->fileline(), 1)));
V3Number zero (nodep->fileline(), 32, 0); zero.isSigned(true);
AstNode* zerosp = new AstConst(nodep->fileline(), zero);
new AstConst(nodep->fileline(), 1)));
V3Number zero (nodep, 32, 0); zero.isSigned(true);
AstNode* zerosp = new AstConst(nodep->fileline(), zero);
AstNode* condp = new AstGtS(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false),
zerosp);
AstNode* bodysp = nodep->bodysp(); if (bodysp) bodysp->unlinkFrBackWithNext();

View File

@ -23,6 +23,7 @@
#include "V3Global.h"
#include "V3Number.h"
#include "V3Ast.h"
#include <algorithm>
#include <cmath>
@ -31,15 +32,24 @@
#define MAX_SPRINTF_DOUBLE_SIZE 100 // Maximum characters with a sprintf %e/%f/%g (probably < 30)
//######################################################################
//======================================================================
// Errors
void V3Number::v3errorEnd(std::ostringstream& str) {
std::ostringstream nsstr;
nsstr<<str.str();
m_fileline->v3errorEnd(nsstr);
}
//======================================================================
// Read class functions
// CREATION
V3Number::V3Number(VerilogStringLiteral, FileLine* fileline, const string& str) {
V3Number::V3Number(VerilogStringLiteral, AstNode* nodep, const string& str) {
// Create a number using a verilog string as the value, thus 8 bits per character.
// cppcheck bug - doesn't see init() resets these
// cppcheck: Member variable 'm_sized/m_width' is not initialized in the constructor
init(fileline, str.length()*8);
init(nodep, str.length()*8);
m_fromString = true;
for (unsigned pos=0; pos<str.length(); ++pos) {
int topos = str.length()-1-pos;
@ -52,8 +62,9 @@ V3Number::V3Number(VerilogStringLiteral, FileLine* fileline, const string& str)
opCleanThis(true);
}
V3Number::V3Number(FileLine* fileline, const char* sourcep) {
init(fileline, 0);
void V3Number::V3NumberCreate(AstNode* nodep, const char* sourcep, FileLine* fl) {
init(nodep, 0);
m_fileline = fl;
const char* value_startp = sourcep;
for (const char* cp=sourcep; *cp; cp++) {
if (*cp == '\'') {
@ -133,19 +144,20 @@ V3Number::V3Number(FileLine* fileline, const char* sourcep) {
} else { // Wide; all previous digits are already in m_value[0]
// this = (this * 10)/*product*/ + (*cp-'0')/*addend*/
// Assumed rare; lots of optimizations are possible here
V3Number product (fileline, width()+4); // +4 for overflow detection
V3Number ten (fileline, width()+4, 10);
V3Number addend (fileline, width(), (*cp-'0'));
product.opMul(*this,ten);
this->opAdd(product,addend);
if (product.bitsValue(width(), 4)) { // Overflowed
m_fileline->v3error("Too many digits for "<<width()<<" bit number: "<<sourcep);
if (!m_sized) {
static int warned = false;
if (!warned++) {
m_fileline->v3error("As that number was unsized ('d...) it is limited to 32 bits (IEEE 2017 5.7.1)");
}
}
V3Number product (this, width()+4); // +4 for overflow detection
V3Number ten (this, width()+4, 10);
V3Number addend (this, width(), (*cp-'0'));
product.opMul(*this,ten);
this->opAdd(product, addend);
if (product.bitsValue(width(), 4)) { // Overflowed
v3error("Too many digits for "<<width()<<" bit number: "<<sourcep);
if (!m_sized) {
static int warned = false;
if (!warned++) {
v3error("As that number was unsized ('d...)"
" it is limited to 32 bits (IEEE 2017 5.7.1)");
}
}
while (*(cp+1)) cp++; // Skip ahead so don't get multiple warnings
}
}
@ -165,23 +177,25 @@ V3Number::V3Number(FileLine* fileline, const char* sourcep) {
}
case '_': break;
default: {
m_fileline->v3error("Illegal character in decimal constant: "<<*cp);
break;
}
}
}
obit = width();
if ((got_01+got_x+got_z)>1) m_fileline->v3error("Mixing X/Z/? with digits not legal in decimal constant: "<<value_startp);
v3error("Illegal character in decimal constant: "<<*cp);
break;
}
}
}
obit = width();
if ((got_01+got_x+got_z) > 1) {
v3error("Mixing X/Z/? with digits not legal in decimal constant: "<<value_startp);
}
}
else {
// Convert bin/octal number to hex
// Convert bin/octal number to hex
for (const char* cp=value_startp+strlen(value_startp)-1;
cp >= value_startp;
cp--) {
if (*cp!='_' && *cp!='0' && obit>=width()) {
m_fileline->v3error("Too many digits for "<<width()<<" bit number: "<<sourcep);
break;
}
if (*cp!='_' && *cp!='0' && obit>=width()) {
v3error("Too many digits for "<<width()<<" bit number: "<<sourcep);
break;
}
switch(tolower(base)) {
case 'b': {
switch(tolower(*cp)) {
@ -191,10 +205,10 @@ V3Number::V3Number(FileLine* fileline, const char* sourcep) {
case 'x': setBit(obit++, 'x'); break;
case '_': break;
default:
m_fileline->v3error("Illegal character in binary constant: "<<*cp);
}
break;
}
v3error("Illegal character in binary constant: "<<*cp);
}
break;
}
case 'o':
case 'c': {
@ -213,10 +227,10 @@ V3Number::V3Number(FileLine* fileline, const char* sourcep) {
setBit(obit++, 'x'); setBit(obit++, 'x'); setBit(obit++, 'x'); break;
case '_': break;
default:
m_fileline->v3error("Illegal character in octal constant");
}
break;
}
v3error("Illegal character in octal constant");
}
break;
}
case 'h': {
switch(tolower(*cp)) {
@ -242,14 +256,14 @@ V3Number::V3Number(FileLine* fileline, const char* sourcep) {
setBit(obit++,'x'); setBit(obit++,'x'); setBit(obit++,'x'); setBit(obit++,'x'); break;
case '_': break;
default:
m_fileline->v3error("Illegal character in hex constant: "<<*cp);
}
break;
}
default:
m_fileline->v3error("Illegal base character: "<<base);
}
}
v3error("Illegal character in hex constant: "<<*cp);
}
break;
}
default:
v3error("Illegal base character: "<<base);
}
}
}
// Z or X extend specific width values. Spec says we don't 1 extend.
@ -263,6 +277,11 @@ V3Number::V3Number(FileLine* fileline, const char* sourcep) {
//printf("Dump \"%s\" CP \"%s\" B '%c' %d W %d\n", sourcep, value_startp, base, width(), m_value[0]);
}
void V3Number::setNames(AstNode* nodep) {
if (!nodep) return;
m_fileline = nodep->fileline();
}
//======================================================================
// Global
@ -302,7 +321,7 @@ V3Number& V3Number::setLongS(vlsint32_t value) {
}
V3Number& V3Number::setDouble(double value) {
if (VL_UNLIKELY(width()!=64)) {
m_fileline->v3fatalSrc("Real operation on wrong sized number");
v3fatalSrc("Real operation on wrong sized number");
}
m_double = true;
union { double d; uint32_t u[2]; } u;
@ -400,12 +419,12 @@ string V3Number::ascii(bool prefixed, bool cleanVerilog) const {
if (binary) {
out<<"b";
out<<displayed(m_fileline, "%0b");
out<<displayed("%0b");
}
else {
if (prefixed) out<<"h";
// Always deal with 4 bits at once. Note no 4-state, it's above.
out<<displayed(m_fileline, "%0h");
if (prefixed) out<<"h";
// Always deal with 4 bits at once. Note no 4-state, it's above.
out<<displayed("%0h");
}
return out.str();
}
@ -458,6 +477,9 @@ bool V3Number::displayedFmtLegal(char format) {
default: return false;
}
}
string V3Number::displayed(AstNode* nodep, const string& vformat) const {
return displayed(nodep->fileline(), vformat);
}
string V3Number::displayed(FileLine*fl, const string& vformat) const {
string::const_iterator pos = vformat.begin();
@ -504,9 +526,9 @@ string V3Number::displayed(FileLine*fl, const string& vformat) const {
return str;
}
case 'c': {
if (this->width()>8) fl->v3warn(WIDTH,"$display-like format of %c format of > 8 bit value");
unsigned int v = bitsValue(0, 8);
char strc[2]; strc[0] = v&0xff; strc[1] = '\0';
if (width()>8) fl->v3warn(WIDTH, "$display-like format of %c format of > 8 bit value");
unsigned int v = bitsValue(0, 8);
char strc[2]; strc[0] = v&0xff; strc[1] = '\0';
str = strc;
return str;
}
@ -603,8 +625,8 @@ string V3Number::displayed(FileLine*fl, const string& vformat) const {
return toString();
}
default:
fl->v3fatalSrc("Unknown $display-like format code for number: %"<<pos[0]);
return "ERR";
fl->v3fatalSrc("Unknown $display-like format code for number: %"<<pos[0]);
return "ERR";
}
}
@ -622,9 +644,9 @@ string V3Number::toDecimalU() const {
int maxdecwidth = (width()+3)*4/3;
// Or (maxdecwidth+7)/8], but can't have more than 4 BCD bits per word
V3Number bcd (fileline(), maxdecwidth+4);
V3Number tmp (fileline(), maxdecwidth+4);
V3Number tmp2 (fileline(), maxdecwidth+4);
V3Number bcd (this, maxdecwidth+4);
V3Number tmp (this, maxdecwidth+4);
V3Number tmp2 (this, maxdecwidth+4);
int from_bit = width()-1;
// Skip all leading zeros
@ -643,7 +665,7 @@ string V3Number::toDecimalU() const {
}
// Shift; bcd = bcd << 1
tmp.opAssign(bcd);
bcd.opShiftL(tmp, V3Number(fileline(), 32, 1));
bcd.opShiftL(tmp, V3Number(this, 32, 1));
// bcd[0] = this[from_bit]
if (bitIs1(from_bit)) bcd.setBit(0, 1);
}
@ -673,10 +695,10 @@ uint32_t V3Number::toUInt() const {
double V3Number::toDouble() const {
if (VL_UNLIKELY(!isDouble())) {
m_fileline->v3fatalSrc("Real conversion on non-real number");
v3fatalSrc("Real conversion on non-real number");
}
if (VL_UNLIKELY(width()!=64)) {
m_fileline->v3fatalSrc("Real operation on wrong sized number");
v3fatalSrc("Real operation on wrong sized number");
}
union { double d; uint32_t u[2]; } u;
u.u[0] = m_value[0]; u.u[1] = m_value[1];
@ -1020,7 +1042,7 @@ V3Number& V3Number::opConcat(const V3Number& lhs, const V3Number& rhs) {
setZero();
// See also error in V3Width
if (!lhs.sized() || !rhs.sized()) {
m_fileline->v3warn(WIDTHCONCAT,"Unsized numbers/parameters not allowed in concatenations.");
v3warn(WIDTHCONCAT,"Unsized numbers/parameters not allowed in concatenations.");
}
int obit = 0;
for(int bit=0; bit<rhs.width(); bit++) {
@ -1042,14 +1064,18 @@ V3Number& V3Number::opLenN(const V3Number& lhs) {
V3Number& V3Number::opRepl(const V3Number& lhs, const V3Number& rhs) { // rhs is # of times to replicate
// Hopefully the using routine has a error check too.
// See also error in V3Width
if (!lhs.sized()) m_fileline->v3warn(WIDTHCONCAT,"Unsized numbers/parameters not allowed in replications.");
if (!lhs.sized()) {
v3warn(WIDTHCONCAT,"Unsized numbers/parameters not allowed in replications.");
}
return opRepl(lhs, rhs.toUInt());
}
V3Number& V3Number::opRepl(const V3Number& lhs, uint32_t rhsval) { // rhs is # of times to replicate
// i op repl, L(i)*value(rhs) bit return
setZero();
if (rhsval>8192) m_fileline->v3warn(WIDTHCONCAT,"More than a 8k bit replication is probably wrong: "<<rhsval);
if (rhsval > 8192) {
v3warn(WIDTHCONCAT,"More than a 8k bit replication is probably wrong: "<<rhsval);
}
int obit = 0;
for (unsigned times=0; times<rhsval; times++) {
for(int bit=0; bit<lhs.width(); bit++) {
@ -1064,7 +1090,7 @@ V3Number& V3Number::opStreamL(const V3Number& lhs, const V3Number& rhs) {
setZero();
// See also error in V3Width
if (!lhs.sized()) {
m_fileline->v3warn(WIDTHCONCAT,"Unsized numbers/parameters not allowed in streams.");
v3warn(WIDTHCONCAT,"Unsized numbers/parameters not allowed in streams.");
}
// Slice size should never exceed the lhs width
int ssize = std::min(rhs.toUInt(), static_cast<unsigned>(lhs.width()));
@ -1351,9 +1377,9 @@ V3Number& V3Number::opAbsS(const V3Number& lhs) {
V3Number& V3Number::opNegate(const V3Number& lhs) {
// op i, L(lhs) bit return
if (lhs.isFourState()) return setAllBitsX();
V3Number notlhs (lhs.m_fileline, width());
V3Number notlhs (&lhs, width());
notlhs.opNot(lhs);
V3Number one (lhs.m_fileline, width(), 1);
V3Number one (&lhs, width(), 1);
opAdd(notlhs,one);
return *this;
}
@ -1375,7 +1401,7 @@ V3Number& V3Number::opAdd(const V3Number& lhs, const V3Number& rhs) {
V3Number& V3Number::opSub(const V3Number& lhs, const V3Number& rhs) {
// i op j, max(L(lhs),L(rhs)) bit return, if any 4-state, 4-state return
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
V3Number negrhs (rhs.m_fileline, rhs.width());
V3Number negrhs (&rhs, rhs.width());
negrhs.opNegate(rhs);
return opAdd(lhs, negrhs);
}
@ -1611,14 +1637,14 @@ V3Number& V3Number::opPow(const V3Number& lhs, const V3Number& rhs, bool lsign,
if (lhs.isEqZero()) return setZero();
setZero();
m_value[0] = 1;
V3Number power (lhs.m_fileline, width()); power.opAssign(lhs);
V3Number power (&lhs, width()); power.opAssign(lhs);
for (int bit=0; bit<rhs.width(); bit++) {
if (bit>0) { // power = power*power
V3Number lastPower (lhs.m_fileline, width()); lastPower.opAssign(power);
power.opMul(lastPower, lastPower);
}
if (rhs.bitIs1(bit)) { // out *= power
V3Number lastOut (lhs.m_fileline, width()); lastOut.opAssign(*this);
if (bit>0) { // power = power*power
V3Number lastPower (&lhs, width()); lastPower.opAssign(power);
power.opMul(lastPower, lastPower);
}
if (rhs.bitIs1(bit)) { // out *= power
V3Number lastOut (&lhs, width()); lastOut.opAssign(*this);
this->opMul(lastOut, power);
//UINFO(0, "pow "<<lhs<<" "<<rhs<<" b"<<bit<<" pow="<<power<<" now="<<*this<<endl);
}
@ -1684,7 +1710,7 @@ void V3Number::opCleanThis(bool warnOnTruncation) {
uint32_t newValueXMsb = m_valueX[words()-1] & hiWordMask();
if (warnOnTruncation && (newValueMsb != m_value[words()-1] || newValueXMsb != m_valueX[words()-1])) {
// Displaying in decimal avoids hiWordMask truncation
m_fileline->v3warn(WIDTH,"Value too large for "<<width()<<" bit number: "<<displayed(m_fileline, "%d"));
v3warn(WIDTH,"Value too large for "<<width()<<" bit number: "<<displayed("%d"));
}
m_value[words()-1] = newValueMsb;
m_valueX[words()-1] = newValueXMsb;
@ -1730,7 +1756,7 @@ V3Number& V3Number::opSelInto(const V3Number& lhs, int lsbval, int width) {
}
V3Number& V3Number::opCond(const V3Number& lhs, const V3Number& if1s, const V3Number& if0s) {
V3Number lhstrue (lhs.m_fileline); lhstrue.opRedOr(lhs);
V3Number lhstrue (&lhs); lhstrue.opRedOr(lhs);
if (lhstrue.bitIs0(0)) {
this->opAssign(if0s);
}
@ -1767,7 +1793,7 @@ V3Number& V3Number::opRToIRoundS(const V3Number& lhs) {
V3Number& V3Number::opRealToBits(const V3Number& lhs) {
// Conveniently our internal format is identical so we can copy bits...
if (lhs.width()!=64 || this->width()!=64) {
m_fileline->v3fatalSrc("Real operation on wrong sized number");
v3fatalSrc("Real operation on wrong sized number");
}
opAssign(lhs);
m_double = false;
@ -1776,7 +1802,7 @@ V3Number& V3Number::opRealToBits(const V3Number& lhs) {
V3Number& V3Number::opBitsToRealD(const V3Number& lhs) {
// Conveniently our internal format is identical so we can copy bits...
if (lhs.width()!=64 || this->width()!=64) {
m_fileline->v3fatalSrc("Real operation on wrong sized number");
v3fatalSrc("Real operation on wrong sized number");
}
opAssign(lhs);
m_double = true;

View File

@ -25,12 +25,13 @@
#include "verilatedos.h"
#include "V3Error.h"
#include "V3FileLine.h"
#include <vector>
//============================================================================
class AstNode;
class V3Number {
// Large 4-state number handling
int m_width; // Width as specified/calculated.
@ -39,8 +40,8 @@ class V3Number {
bool m_double:1; // True if double real value
bool m_isString:1; // True if string
bool m_fromString:1; // True if from string literal
bool m_autoExtend:1; // True if SystemVerilog extend-to-any-width
FileLine* m_fileline;
bool m_autoExtend:1; // True if SystemVerilog extend-to-any-width
FileLine* m_fileline;
std::vector<uint32_t> m_value; // The Value, with bit 0 being in bit 0 of this vector (unless X/Z)
std::vector<uint32_t> m_valueX; // Each bit is true if it's X or Z, 10=z, 11=x
string m_stringVal; // If isString, the value of the string
@ -49,8 +50,8 @@ class V3Number {
V3Number& setString(const string& str) { m_isString=true; m_stringVal=str; return *this; }
void opCleanThis(bool warnOnTruncation = false);
public:
FileLine* fileline() const { return m_fileline; }
void fileline(FileLine* fl) { m_fileline=fl; }
void nodep(AstNode* nodep) { setNames(nodep); }
FileLine* fileline() const { return m_fileline; };
V3Number& setZero();
V3Number& setQuad(vluint64_t value);
V3Number& setLong(uint32_t value);
@ -131,18 +132,34 @@ private:
public:
// CONSTRUCTORS
explicit V3Number(FileLine* fileline) { init(fileline, 1); }
V3Number(FileLine* fileline, int width) { init(fileline, width); } // 0=unsized
V3Number(FileLine* fileline, int width, uint32_t value) { init(fileline, width); m_value[0]=value; opCleanThis(); }
V3Number(FileLine* fileline, const char* sourcep); // Create from a verilog 32'hxxxx number.
explicit V3Number(AstNode* nodep) { init(nodep, 1); }
V3Number(AstNode* nodep, int width) { init(nodep, width); } // 0=unsized
V3Number(AstNode* nodep, int width, uint32_t value) {
init(nodep, width); m_value[0]=value; opCleanThis();
}
// Create from a verilog 32'hxxxx number.
V3Number(AstNode* nodep, const char* sourcep) { V3NumberCreate(nodep, sourcep, NULL); }
class FileLined {}; // Fileline based errors, for parsing only, otherwise pass nodep
V3Number(FileLined, FileLine* fl, const char* sourcep) { V3NumberCreate(NULL, sourcep, fl); }
class VerilogStringLiteral {}; // For creator type-overload selection
V3Number(VerilogStringLiteral, FileLine* fileline, const string& str);
V3Number(VerilogStringLiteral, AstNode* nodep, const string& str);
class String {};
V3Number(String, FileLine* fileline, const string& value) { init(fileline, 0); setString(value); }
V3Number(String, AstNode* nodep, const string& value) { init(nodep, 0); setString(value); }
V3Number(const V3Number* nump, int width = 1) {
init(NULL, width);
m_fileline = nump->fileline();
}
V3Number(const V3Number* nump, int width, uint32_t value) {
init(NULL, width);
m_value[0]=value;
opCleanThis();
m_fileline = nump->fileline();
}
private:
void init(FileLine* fileline, int swidth) {
m_fileline = fileline;
void V3NumberCreate(AstNode* nodep, const char* sourcep, FileLine* fl);
void init(AstNode* nodep, int swidth) {
setNames(nodep);
m_signed = false;
m_double = false;
m_isString = false;
@ -151,7 +168,13 @@ private:
width(swidth);
for (int i=0; i<words(); i++) m_value[i]=m_valueX[i] = 0;
}
void setNames(AstNode* nodep);
string displayed(FileLine* fl, const string& vformat) const;
string displayed(const string& vformat) const {
return displayed(m_fileline, vformat);
}
public:
void v3errorEnd(std::ostringstream& sstr);
void width(int width, bool sized=true) {
// Set width. Only set m_width here, as we need to tweak vector size
if (width) { m_sized = sized; m_width=width; }
@ -173,10 +196,10 @@ public:
// ACCESSORS
string ascii(bool prefixed=true, bool cleanVerilog=false) const;
static string quoteNameControls(const string& namein); // Add backslash quotes to strings
string displayed(FileLine* fl, const string& vformat) const;
string displayed(AstNode* nodep, const string& vformat) const;
static bool displayedFmtLegal(char format); // Is this a valid format letter?
int width() const { return m_width; }
int widthMin() const; // Minimum width that can represent this number (~== log2(num)+1)
int widthMin() const; // Minimum width that can represent this number (~== log2(num)+1)
bool sized() const { return m_sized; }
bool autoExtend() const { return m_autoExtend; }
bool isFromString() const { return m_fromString; }

View File

@ -494,9 +494,9 @@ private:
if (!itemp->isDefault()) {
for (AstNode* ep = itemp->condsp(); ep; ep=ep->nextp()) {
if (const AstConst* ccondp = VN_CAST(ep, Const)) {
V3Number match (nodep->fileline(), 1);
match.opEq(ccondp->num(), exprp->num());
if (!keepp && match.isNeqZero()) {
V3Number match (nodep, 1);
match.opEq(ccondp->num(), exprp->num());
if (!keepp && match.isNeqZero()) {
keepp = itemp->bodysp();
}
} else {
@ -575,11 +575,13 @@ void ParamVisitor::visitCell(AstCell* nodep) {
} else {
AstConst* exprp = VN_CAST(pinp->exprp(), Const);
AstConst* origp = VN_CAST(modvarp->valuep(), Const);
if (!exprp) {
//if (debug()) pinp->dumpTree(cout,"error:");
pinp->v3error("Can't convert defparam value to constant: Param "<<pinp->name()<<" of "<<nodep->prettyName());
pinp->exprp()->replaceWith(new AstConst(pinp->fileline(), V3Number(pinp->fileline(), modvarp->width(), 0)));
} else if (origp && exprp->sameTree(origp)) {
if (!exprp) {
//if (debug()) pinp->dumpTree(cout,"error:");
pinp->v3error("Can't convert defparam value to constant: Param "
<<pinp->name()<<" of "<<nodep->prettyName());
pinp->exprp()->replaceWith(
new AstConst(pinp->fileline(), V3Number(pinp, modvarp->width(), 0)));
} else if (origp && exprp->sameTree(origp)) {
// Setting parameter to its default value. Just ignore it.
// This prevents making additional modules, and makes coverage more
// obvious as it won't show up under a unique module page name.

View File

@ -183,9 +183,9 @@ public:
return strp;
}
V3Number* newNumber(FileLine* fl, const char* text) {
V3Number* nump = new V3Number(fl, text);
m_numberps.push_back(nump);
return nump;
V3Number* nump = new V3Number(V3Number::FileLined(), fl, text);
m_numberps.push_back(nump);
return nump;
}
// Return next token, for bison, since bison isn't class based, use a global THIS

View File

@ -284,12 +284,12 @@ private:
m1value),
nodep->width()));
} else {
V3Number zeronum (nodep->fileline(), nodep->width(), 0);
constzerop = new AstConst(nodep->fileline(), zeronum);
}
V3Number zeronum (nodep, nodep->width(), 0);
constzerop = new AstConst(nodep->fileline(), zeronum);
}
constzerop->dtypeFrom(nodep); // unsigned
V3Number widthnum (nodep->fileline(), nodep->rhsp()->widthMin(), m1value);
V3Number widthnum (nodep, nodep->rhsp()->widthMin(), m1value);
AstNode* constwidthp = new AstConst(nodep->fileline(), widthnum);
constwidthp->dtypeFrom(nodep->rhsp()); // unsigned
AstCond* newp =

View File

@ -127,9 +127,9 @@ private:
for (AstMemberDType* itemp = stp->membersp(); itemp; itemp=VN_CAST(itemp->nextp(), MemberDType)) {
int width = itemp->width();
int lsb = itemp->lsb();
int msb = lsb + width - 1;
V3Number fieldNum = V3Number(nump->fileline(), width);
fieldNum.opSel(*nump, msb, lsb);
int msb = lsb + width - 1;
V3Number fieldNum = V3Number(nump, width);
fieldNum.opSel(*nump, msb, lsb);
out<<itemp->name()<<": ";
if (AstNodeDType * childTypep = itemp->subDTypep()) {
out<<prettyNumber(&fieldNum, childTypep);
@ -149,9 +149,9 @@ private:
for (int element = 0; element < arrayElements; ++element) {
int width = childTypep->width();
int lsb = width * element;
int msb = lsb + width - 1;
V3Number fieldNum = V3Number(nump->fileline(), width);
fieldNum.opSel(*nump, msb, lsb);
int msb = lsb + width - 1;
V3Number fieldNum = V3Number(nump, width);
fieldNum.opSel(*nump, msb, lsb);
int arrayElem = arrayp->lsb() + element;
out<<arrayElem<<" = "<<prettyNumber(&fieldNum, childTypep);
if (element < arrayElements - 1) out<<", ";
@ -213,11 +213,11 @@ private:
//UINFO(7,"Num Reuse "<<nodep->width()<<endl);
nump = m_numFreeps.back(); m_numFreeps.pop_back();
nump->width(nodep->width());
nump->fileline(nodep->fileline());
nump->setLong(value); // We do support more than 32 bit numbers, just valuep=0 in that case
} else {
//UINFO(7,"Num New "<<nodep->width()<<endl);
nump = new V3Number(nodep->fileline(), nodep->width(), value);
nump->nodep(nodep);
nump->setLong(value);
} else {
//UINFO(7,"Num New "<<nodep->width()<<endl);
nump = new V3Number(nodep, nodep->width(), value);
m_numAllps.push_back(nump);
}
nump->isDouble(nodep->isDouble());
@ -520,9 +520,9 @@ private:
} else {
iterate(nodep->lhsp());
if (optimizable()) {
if (fetchNumber(nodep->lhsp())->isEqZero()) {
newNumber(nodep, V3Number(nodep->fileline(), 1, 1)); // a one
} else {
if (fetchNumber(nodep->lhsp())->isEqZero()) {
newNumber(nodep, V3Number(nodep, 1, 1)); // a one
} else {
iterate(nodep->rhsp());
newNumber(nodep, *fetchNumber(nodep->rhsp()));
}
@ -552,19 +552,21 @@ private:
void handleAssignSel(AstNodeAssign* nodep, AstSel* selp) {
AstVarRef* varrefp = NULL;
V3Number lsb = V3Number(nodep->fileline());
V3Number lsb = V3Number(nodep);
iterateAndNextNull(nodep->rhsp()); // Value to assign
handleAssignSelRecurse(nodep, selp, varrefp/*ref*/, lsb/*ref*/, 0);
if (!m_checkOnly && optimizable()) {
if (!varrefp) nodep->v3fatalSrc("Indicated optimizable, but no variable found on RHS of select");
AstNode* vscp = varOrScope(varrefp);
V3Number outnum = V3Number(nodep->fileline());
if (V3Number* vscpnump = fetchOutNumberNull(vscp)) {
outnum = *vscpnump;
} else if (V3Number* vscpnump = fetchNumberNull(vscp)) {
outnum = *vscpnump;
} else { // Assignment to unassigned variable, all bits are X or 0
outnum = V3Number(nodep->fileline(), varrefp->varp()->widthMin());
handleAssignSelRecurse(nodep, selp, varrefp/*ref*/, lsb/*ref*/, 0);
if (!m_checkOnly && optimizable()) {
if (!varrefp) {
nodep->v3fatalSrc("Indicated optimizable, but no variable found on RHS of select");
}
AstNode* vscp = varOrScope(varrefp);
V3Number outnum = V3Number(nodep);
if (V3Number* vscpnump = fetchOutNumberNull(vscp)) {
outnum = *vscpnump;
} else if (V3Number* vscpnump = fetchNumberNull(vscp)) {
outnum = *vscpnump;
} else { // Assignment to unassigned variable, all bits are X or 0
outnum = V3Number(nodep, varrefp->varp()->widthMin());
if (varrefp->varp()->basicp() && varrefp->varp()->basicp()->isZeroInit()) {
outnum.setAllBits0();
} else {
@ -588,9 +590,9 @@ private:
lsbRef = *fetchNumber(selp->lsbp());
return; // And presumably still optimizable()
} else if (AstSel* subselp = VN_CAST(selp->lhsp(), Sel)) {
V3Number sublsb = V3Number(nodep->fileline());
handleAssignSelRecurse(nodep, subselp, outVarrefpRef, sublsb/*ref*/, depth+1);
if (optimizable()) {
V3Number sublsb = V3Number(nodep);
handleAssignSelRecurse(nodep, subselp, outVarrefpRef, sublsb/*ref*/, depth+1);
if (optimizable()) {
lsbRef = sublsb;
lsbRef.opAdd(sublsb, *fetchNumber(selp->lsbp()));
}
@ -648,9 +650,9 @@ private:
for (AstNode* ep = itemp->condsp(); ep; ep=ep->nextp()) {
if (hit) break;
iterateAndNextNull(ep);
if (optimizable()) {
V3Number match (nodep->fileline(), 1);
match.opEq(*fetchNumber(nodep->exprp()), *fetchNumber(ep));
if (optimizable()) {
V3Number match (nodep, 1);
match.opEq(*fetchNumber(nodep->exprp()), *fetchNumber(ep));
if (match.isNeqZero()) {
iterateAndNextNull(itemp->bodysp());
hit = true;
@ -853,9 +855,9 @@ private:
clearOptimizable(nodep, "Argument for $display like statement is not constant");
break;
}
string format = string("%") + pos[0];
result += nump->displayed(nodep->fileline(), format);
} else {
string format = string("%") + pos[0];
result += nump->displayed(nodep, format);
} else {
switch (tolower(pos[0])) {
case '%':
result += "%";
@ -872,9 +874,9 @@ private:
}
}
V3Number* resultNump = new V3Number(V3Number::String(), nodep->fileline(), result);
setNumber(nodep, resultNump);
m_stringNumbersp.push_back(resultNump);
V3Number* resultNump = new V3Number(V3Number::String(), nodep, result);
setNumber(nodep, resultNump);
m_stringNumbersp.push_back(resultNump);
}
}

View File

@ -300,7 +300,7 @@ private:
AstVarScope* invscp = *it;
// LSB is first variable, so extract it that way
simvis.newNumber(invscp,
V3Number(invscp->fileline(), invscp->width(),
V3Number(invscp, invscp->width(),
VL_MASK_I(invscp->width()) & (inValue>>shift)));
shift += invscp->width();
// We're just using32 bit arithmetic, because there's no way the input table can be 2^32 bytes!
@ -316,8 +316,8 @@ private:
}
// If a output changed, add it to table
int outnum = 0;
V3Number outputChgMask (nodep->fileline(), m_outVarps.size(), 0);
int outnum = 0;
V3Number outputChgMask (nodep, m_outVarps.size(), 0);
for (std::deque<AstVarScope*>::iterator it = m_outVarps.begin(); it!=m_outVarps.end(); ++it) {
AstVarScope* outvscp = *it;
V3Number* outnump = simvis.fetchOutNumberNull(outvscp);
@ -327,9 +327,9 @@ private:
m_outNotSet[outnum] = true;
// Value in table is arbitrary, but we need something
setp = new AstConst(outvscp->fileline(),
V3Number(outvscp->fileline(), outvscp->width(), 0));
} else {
UINFO(8," Output "<<outvscp->name()<<" = "<<*outnump<<endl);
V3Number(outvscp, outvscp->width(), 0));
} else {
UINFO(8," Output "<<outvscp->name()<<" = "<<*outnump<<endl);
// m_tableVarps[inValue] = num;
// Mark changed bit, too
outputChgMask.setBit(outnum, 1);
@ -392,9 +392,9 @@ private:
AstNode* outsetp = outasnp;
// Is the value set in only some branches of the table?
if (m_outNotSet[outnum]) {
V3Number outputChgMask (nodep->fileline(), m_outVarps.size(), 0);
outputChgMask.setBit(outnum,1);
if (m_outNotSet[outnum]) {
V3Number outputChgMask (nodep, m_outVarps.size(), 0);
outputChgMask.setBit(outnum, 1);
outsetp = new AstIf(nodep->fileline(),
new AstAnd(nodep->fileline(),
new AstArraySel(nodep->fileline(),

View File

@ -511,7 +511,8 @@ private:
}
} else {
AstNode* clrp = new AstAssign(fl, new AstVarRef(fl, m_activityVscp, true),
new AstConst(fl, V3Number(fl, m_activityVscp->width(), 0)));
new AstConst(fl, AstConst::WidthedValue(),
m_activityVscp->width(), 0));
m_fullFuncp->addFinalsp(clrp->cloneTree(true));
m_chgFuncp->addFinalsp(clrp);
}

View File

@ -365,9 +365,9 @@ class TristateVisitor : public TristateBaseVisitor {
AstNode* getEnp(AstNode* nodep) {
// checks if user1p() is null, and if so, adds a constant output
// enable driver of all 1's. Otherwise returns the user1p() data.
if (!nodep->user1p()) {
V3Number num(nodep->fileline(), nodep->width());
num.setAllBits1();
if (!nodep->user1p()) {
V3Number num(nodep, nodep->width());
num.setAllBits1();
AstNode* enp = new AstConst(nodep->fileline(), num);
nodep->user1p(enp);
}
@ -479,9 +479,9 @@ class TristateVisitor : public TristateBaseVisitor {
VarMap::iterator it = m_lhsmap.find(varp);
if (it == m_lhsmap.end()) {
// set output enable to always be off on this assign statement so that this var is floating
UINFO(8," Adding driver to var "<<varp<<endl);
V3Number zeros (varp->fileline(), varp->width());
zeros.setAllBits0();
UINFO(8," Adding driver to var "<<varp<<endl);
V3Number zeros (varp, varp->width());
zeros.setAllBits0();
AstConst* constp = new AstConst(varp->fileline(), zeros);
AstVarRef* varrefp = new AstVarRef(varp->fileline(), varp, true);
AstNode* newp = new AstAssignW(varp->fileline(), varrefp, constp);
@ -592,13 +592,13 @@ class TristateVisitor : public TristateBaseVisitor {
: new AstAnd(refp->fileline(), tmp, undrivenp));
}
if (!undrivenp) { // No drivers on the bus
V3Number ones(invarp->fileline(), lhsp->width()); ones.setAllBits1();
undrivenp = new AstConst(invarp->fileline(), ones);
}
if (!outvarp) {
// This is the final resolution of the tristate, so we apply
// the pull direction to any undriven pins.
V3Number pull(invarp->fileline(), lhsp->width());
V3Number ones(invarp, lhsp->width()); ones.setAllBits1();
undrivenp = new AstConst(invarp->fileline(), ones);
}
if (!outvarp) {
// This is the final resolution of the tristate, so we apply
// the pull direction to any undriven pins.
V3Number pull(invarp, lhsp->width());
AstPull* pullp = static_cast<AstPull*>(lhsp->user3p());
if (pullp && pullp->direction() == 1) {
pull.setAllBits1();
@ -654,9 +654,12 @@ class TristateVisitor : public TristateBaseVisitor {
else if (m_tgraph.isTristate(nodep)) {
m_tgraph.didProcess(nodep);
FileLine* fl = nodep->fileline();
V3Number numz (fl,nodep->width()); numz.opBitsZ(nodep->num()); //Z->1, else 0
V3Number numz0(fl,nodep->width()); numz0.opNot(numz); // Z->0, else 1
V3Number num1 (fl,nodep->width()); num1.opAnd(nodep->num(),numz0); // 01X->01X, Z->0
V3Number numz (nodep, nodep->width());
numz.opBitsZ(nodep->num()); // Z->1, else 0
V3Number numz0(nodep, nodep->width());
numz0.opNot(numz); // Z->0, else 1
V3Number num1 (nodep, nodep->width());
num1.opAnd(nodep->num(), numz0); // 01X->01X, Z->0
AstConst* newconstp = new AstConst(fl, num1);
AstConst* enp = new AstConst(fl, numz0);
nodep->replaceWith(newconstp);

View File

@ -185,7 +185,7 @@ private:
// If we got ==1'bx it can never be true (but 1'bx==1'bx can be!)
if (((VN_IS(lhsp, Const) && VN_CAST(lhsp, Const)->num().isFourState())
|| (VN_IS(rhsp, Const) && VN_CAST(rhsp, Const)->num().isFourState()))) {
V3Number num(nodep->fileline(), 1, (VN_IS(nodep, EqCase) ? 0:1));
V3Number num(nodep, 1, (VN_IS(nodep, EqCase) ? 0:1));
newp = new AstConst(nodep->fileline(), num);
lhsp->deleteTree(); VL_DANGLING(lhsp);
rhsp->deleteTree(); VL_DANGLING(rhsp);
@ -218,9 +218,9 @@ private:
newp = new AstEq(nodep->fileline(), lhsp, rhsp);
} else {
// X or Z's become mask, ala case statements.
V3Number nummask (rhsp->fileline(), rhsp->width());
V3Number nummask (rhsp, rhsp->width());
nummask.opBitsNonX(VN_CAST(rhsp, Const)->num());
V3Number numval (rhsp->fileline(), rhsp->width());
V3Number numval (rhsp, rhsp->width());
numval.opBitsOne(VN_CAST(rhsp, Const)->num());
AstNode* and1p = new AstAnd(nodep->fileline(), lhsp,
new AstConst(nodep->fileline(), nummask));
@ -252,8 +252,8 @@ private:
virtual void visit(AstIsUnknown* nodep) {
iterateChildren(nodep);
// Ahh, we're two state, so this is easy
UINFO(4," ISUNKNOWN->0 "<<nodep<<endl);
V3Number zero (nodep->fileline(), 1, 0);
UINFO(4," ISUNKNOWN->0 "<<nodep<<endl);
V3Number zero (nodep, 1, 0);
AstConst* newp = new AstConst(nodep->fileline(), zero);
nodep->replaceWith(newp);
nodep->deleteTree(); VL_DANGLING(nodep);
@ -266,13 +266,13 @@ private:
// CONST(num) -> VARREF(newvarp)
// -> VAR(newvarp)
// -> INITIAL(VARREF(newvarp, OR(num_No_Xs,AND(random,num_1s_Where_X))
V3Number numb1 (nodep->fileline(), nodep->width());
numb1.opBitsOne(nodep->num());
V3Number numbx (nodep->fileline(), nodep->width());
numbx.opBitsXZ(nodep->num());
if (v3Global.opt.xAssign()!="unique") {
// All X bits just become 0; fastest simulation, but not nice
V3Number numnew (nodep->fileline(), numb1.width());
V3Number numb1 (nodep, nodep->width());
numb1.opBitsOne(nodep->num());
V3Number numbx (nodep, nodep->width());
numbx.opBitsXZ(nodep->num());
if (v3Global.opt.xAssign()!="unique") {
// All X bits just become 0; fastest simulation, but not nice
V3Number numnew (nodep, numb1.width());
if (v3Global.opt.xAssign()=="1") {
numnew.opOr(numb1, numbx);
} else {
@ -334,8 +334,8 @@ private:
// Find range of dtype we are selecting from
// Similar code in V3Const::warnSelect
int maxmsb = nodep->fromp()->dtypep()->width()-1;
if (debug()>=9) nodep->dumpTree(cout,"sel_old: ");
V3Number maxmsbnum (nodep->fileline(), nodep->lsbp()->width(), maxmsb);
if (debug()>=9) nodep->dumpTree(cout,"sel_old: ");
V3Number maxmsbnum (nodep, nodep->lsbp()->width(), maxmsb);
// If (maxmsb >= selected), we're in bound
AstNode* condp = new AstGte(nodep->fileline(),
@ -351,9 +351,9 @@ private:
else if (!lvalue) {
// SEL(...) -> COND(LTE(bit<=maxmsb), ARRAYSEL(...), {width{1'bx}})
AstNRelinker replaceHandle;
nodep->unlinkFrBack(&replaceHandle);
V3Number xnum (nodep->fileline(), nodep->width());
xnum.setAllBitsX();
nodep->unlinkFrBack(&replaceHandle);
V3Number xnum (nodep, nodep->width());
xnum.setAllBitsX();
AstNode* newp = new AstCondBound(nodep->fileline(),
condp,
nodep,
@ -396,8 +396,8 @@ private:
} else {
nodep->v3error("Select from non-array "<<dtypep->prettyTypeName());
}
if (debug()>=9) nodep->dumpTree(cout,"arraysel_old: ");
V3Number widthnum (nodep->fileline(), nodep->bitp()->width(), declElements-1);
if (debug()>=9) nodep->dumpTree(cout,"arraysel_old: ");
V3Number widthnum (nodep, nodep->bitp()->width(), declElements-1);
// See if the condition is constant true
AstNode* condp = new AstGte(nodep->fileline(),
@ -414,9 +414,9 @@ private:
// ARRAYSEL(...) -> COND(LT(bit<maxbit), ARRAYSEL(...), {width{1'bx}})
AstNRelinker replaceHandle;
nodep->unlinkFrBack(&replaceHandle);
V3Number xnum (nodep->fileline(), nodep->width());
if (nodep->isString()) {
xnum = V3Number(V3Number::String(), nodep->fileline(), "");
V3Number xnum (nodep, nodep->width());
if (nodep->isString()) {
xnum = V3Number(V3Number::String(), nodep, "");
} else {
xnum.setAllBitsX();
}
@ -432,8 +432,8 @@ private:
else if (!lvalue) { // Mid-multidimension read, just use zero
// ARRAYSEL(...) -> ARRAYSEL(COND(LT(bit<maxbit), bit, 0))
AstNRelinker replaceHandle;
AstNode* bitp = nodep->bitp()->unlinkFrBack(&replaceHandle);
V3Number zeronum (nodep->fileline(), bitp->width(), 0);
AstNode* bitp = nodep->bitp()->unlinkFrBack(&replaceHandle);
V3Number zeronum (nodep, bitp->width(), 0);
AstNode* newp = new AstCondBound(bitp->fileline(),
condp, bitp,
new AstConst(bitp->fileline(), zeronum));

View File

@ -231,12 +231,12 @@ private:
bool countLoops(AstAssign *initp, AstNode *condp, AstNode *incp, int max, int &outLoopsr) {
outLoopsr = 0;
V3Number loopValue = V3Number(initp->fileline());
if (!simulateTree(initp->rhsp(), NULL, initp, loopValue)) {
return false;
}
while (1) {
V3Number res = V3Number(initp->fileline());
V3Number loopValue = V3Number(initp);
if (!simulateTree(initp->rhsp(), NULL, initp, loopValue)) {
return false;
}
while (1) {
V3Number res = V3Number(initp);
if (!simulateTree(condp, &loopValue, NULL, res)) {
return false;
}
@ -248,10 +248,10 @@ private:
// Run inc
AstAssign* incpass = VN_CAST(incp, Assign);
V3Number newLoopValue = V3Number(initp->fileline());
if (!simulateTree(incpass->rhsp(), &loopValue, incpass, newLoopValue)) {
return false;
}
V3Number newLoopValue = V3Number(initp);
if (!simulateTree(incpass->rhsp(), &loopValue, incpass, newLoopValue)) {
return false;
}
loopValue.opAssign(newLoopValue);
if (outLoopsr > max) {
return false;
@ -265,9 +265,9 @@ private:
AstNode* condp,
AstNode* precondsp,
AstNode* incp, AstNode* bodysp) {
UINFO(9, "forUnroller "<<nodep<<endl);
V3Number loopValue = V3Number(nodep->fileline());
if (!simulateTree(initp->rhsp(), NULL, initp, loopValue)) {
UINFO(9, "forUnroller "<<nodep<<endl);
V3Number loopValue = V3Number(nodep);
if (!simulateTree(initp->rhsp(), NULL, initp, loopValue)) {
return false;
}
AstNode* stmtsp = NULL;
@ -295,9 +295,9 @@ private:
if (stmtsp) {
int times = 0;
while (1) {
UINFO(8," Looping "<<loopValue<<endl);
V3Number res = V3Number(nodep->fileline());
if (!simulateTree(condp, &loopValue, NULL, res)) {
UINFO(8," Looping "<<loopValue<<endl);
V3Number res = V3Number(nodep);
if (!simulateTree(condp, &loopValue, NULL, res)) {
nodep->v3error("Loop unrolling failed.");
return false;
}
@ -337,9 +337,9 @@ private:
// loopValue += valInc
AstAssign *incpass = VN_CAST(incp, Assign);
V3Number newLoopValue = V3Number(nodep->fileline());
if (!simulateTree(incpass->rhsp(), &loopValue, incpass, newLoopValue)) {
nodep->v3error("Loop unrolling failed");
V3Number newLoopValue = V3Number(nodep);
if (!simulateTree(incpass->rhsp(), &loopValue, incpass, newLoopValue)) {
nodep->v3error("Loop unrolling failed");
return false;
}
loopValue.opAssign(newLoopValue);

View File

@ -1321,8 +1321,8 @@ private:
// Assign widths
userIterateAndNext(nodep->itemsp(), WidthVP(nodep->dtypep(),BOTH).p());
// Assign missing values
V3Number num (nodep->fileline(), nodep->width(), 0);
V3Number one (nodep->fileline(), nodep->width(), 1);
V3Number num (nodep, nodep->width(), 0);
V3Number one (nodep, nodep->width(), 1);
std::map<V3Number,AstEnumItem*> inits;
for (AstEnumItem* itemp = nodep->itemsp(); itemp; itemp=VN_CAST(itemp->nextp(), EnumItem)) {
if (itemp->valuep()) {
@ -2923,9 +2923,9 @@ private:
if (nodep->rhsp()->width()>32) {
AstConst* shiftp = VN_CAST(nodep->rhsp(), Const);
if (shiftp && shiftp->num().mostSetBitP1() <= 32) {
// If (number)<<96'h1, then make it into (number)<<32'h1
V3Number num (shiftp->fileline(), 32, 0); num.opAssign(shiftp->num());
AstNode* shiftp = nodep->rhsp();
// If (number)<<96'h1, then make it into (number)<<32'h1
V3Number num (shiftp, 32, 0); num.opAssign(shiftp->num());
AstNode* shiftp = nodep->rhsp();
nodep->rhsp()->replaceWith(new AstConst(shiftp->fileline(), num));
shiftp->deleteTree(); VL_DANGLING(shiftp);
}
@ -3082,9 +3082,9 @@ private:
AstConst* constp = VN_CAST(nodep, Const);
int expWidth = expDTypep->width();
if (constp && !constp->num().isNegative()) {
// Save later constant propagation work, just right-size it.
V3Number num (nodep->fileline(), expWidth);
num.opAssign(constp->num());
// Save later constant propagation work, just right-size it.
V3Number num (nodep, expWidth);
num.opAssign(constp->num());
num.isSigned(false);
AstNode* newp = new AstConst(nodep->fileline(), num);
constp->replaceWith(newp);
@ -3134,9 +3134,9 @@ private:
int expSigned = false;
UINFO(4," widthReduce_old: "<<nodep<<endl);
AstConst* constp = VN_CAST(nodep, Const);
if (constp) {
V3Number num (nodep->fileline(), expWidth);
num.opRedOr(constp->num());
if (constp) {
V3Number num (nodep, expWidth);
num.opRedOr(constp->num());
num.isSigned(expSigned);
AstNode* newp = new AstConst(nodep->fileline(), num);
constp->replaceWith(newp);
@ -3157,9 +3157,9 @@ private:
// For SystemVerilog '0,'1,'x,'z, autoextend and don't warn
if (AstConst* constp = VN_CAST(nodepr, Const)) {
if (constp->num().autoExtend() && !constp->num().sized() && constp->width()==1) {
// Make it the proper size. Careful of proper extension of 0's/1's
V3Number num (constp->fileline(), expWidth);
num.opRepl(constp->num(), expWidth); // {width{'1}}
// Make it the proper size. Careful of proper extension of 0's/1's
V3Number num (constp, expWidth);
num.opRepl(constp->num(), expWidth); // {width{'1}}
AstNode* newp = new AstConst(constp->fileline(), num);
// Spec says always unsigned with proper width
if (debug()>4) constp->dumpTree(cout," fixAutoExtend_old: ");
@ -3176,7 +3176,7 @@ private:
&& expWidth > 32 && constp->num().isMsbXZ()) {
constp->v3warn(WIDTH, "Unsized constant being X/Z extended to "
<<expWidth<<" bits: "<<constp->prettyName());
V3Number num (constp->fileline(), expWidth);
V3Number num (constp, expWidth);
num.opExtendXZ(constp->num(), constp->width());
AstNode* newp = new AstConst(constp->fileline(), num);
// Spec says always unsigned with proper width
@ -3802,9 +3802,9 @@ private:
if (attrType == AstAttrType::ENUM_NAME) {
initp->defaultp(new AstConst(nodep->fileline(), AstConst::String(), ""));
} else if (attrType == AstAttrType::ENUM_NEXT
|| attrType == AstAttrType::ENUM_PREV) {
initp->defaultp(new AstConst(nodep->fileline(), V3Number(nodep->fileline(), nodep->width(), 0)));
} else {
|| attrType == AstAttrType::ENUM_PREV) {
initp->defaultp(new AstConst(nodep->fileline(), V3Number(nodep, nodep->width(), 0)));
} else {
nodep->v3fatalSrc("Bad case");
}

View File

@ -77,9 +77,9 @@ public:
static AstConst* newIfConstCommitSize(AstConst* nodep) {
if (((nodep->dtypep()->width() != nodep->num().width())
|| !nodep->num().sized())
&& !nodep->num().isString()) { // Need to force the number from unsized to sized
V3Number num (nodep->fileline(), nodep->dtypep()->width());
num.opAssign(nodep->num());
&& !nodep->num().isString()) { // Need to force the number from unsized to sized
V3Number num (nodep, nodep->dtypep()->width());
num.opAssign(nodep->num());
num.isSigned(nodep->isSigned());
AstConst* newp = new AstConst(nodep->fileline(), num);
newp->dtypeFrom(nodep);

View File

@ -120,9 +120,9 @@ private:
return lhsp;
} else if (VN_IS(lhsp, Const)) {
// Optional vs just making add/sub below, but saves constification some work
V3Number num (lhsp->fileline(), lhsp->width());
num.opSub(VN_CAST(lhsp, Const)->num(), V3Number(lhsp->fileline(), 32, rhs));
num.isSigned(lhsp->isSigned());
V3Number num (lhsp, lhsp->width());
num.opSub(VN_CAST(lhsp, Const)->num(), V3Number(lhsp, 32, rhs));
num.isSigned(lhsp->isSigned());
AstNode* newp = new AstConst(lhsp->fileline(), num);
return newp;
} else if (rhs > 0) {

View File

@ -1936,10 +1936,10 @@ genvar_iteration<nodep>: // ==IEEE: genvar_iteration
| varRefBase yP_SSRIGHTEQ expr { $$ = new AstAssign($2,$1,new AstShiftRS($2,$1->cloneTree(true),$3)); }
// // inc_or_dec_operator
// When support ++ as a real AST type, maybe AstWhile::precondsp() becomes generic AstNodeMathStmt?
| yP_PLUSPLUS varRefBase { $$ = new AstAssign($1,$2,new AstAdd ($1,$2->cloneTree(true),new AstConst($1,V3Number($1,"'b1")))); }
| yP_MINUSMINUS varRefBase { $$ = new AstAssign($1,$2,new AstSub ($1,$2->cloneTree(true),new AstConst($1,V3Number($1,"'b1")))); }
| varRefBase yP_PLUSPLUS { $$ = new AstAssign($2,$1,new AstAdd ($2,$1->cloneTree(true),new AstConst($2,V3Number($2,"'b1")))); }
| varRefBase yP_MINUSMINUS { $$ = new AstAssign($2,$1,new AstSub ($2,$1->cloneTree(true),new AstConst($2,V3Number($2,"'b1")))); }
| yP_PLUSPLUS varRefBase { $$ = new AstAssign($1,$2,new AstAdd ($1,$2->cloneTree(true), new AstConst($1, AstConst::StringToParse(), "'b1"))); }
| yP_MINUSMINUS varRefBase { $$ = new AstAssign($1,$2,new AstSub ($1,$2->cloneTree(true), new AstConst($1, AstConst::StringToParse(), "'b1"))); }
| varRefBase yP_PLUSPLUS { $$ = new AstAssign($2,$1,new AstAdd ($2,$1->cloneTree(true), new AstConst($2, AstConst::StringToParse(), "'b1"))); }
| varRefBase yP_MINUSMINUS { $$ = new AstAssign($2,$1,new AstSub ($2,$1->cloneTree(true), new AstConst($2, AstConst::StringToParse(), "'b1"))); }
;
case_generate_itemListE<nodep>: // IEEE: [{ case_generate_itemList }]
@ -2520,10 +2520,10 @@ foperator_assignment<nodep>: // IEEE: operator_assignment (for first part of exp
finc_or_dec_expression<nodep>: // ==IEEE: inc_or_dec_expression
//UNSUP: Generic scopes in incrementes
fexprLvalue yP_PLUSPLUS { $$ = new AstAssign($2,$1,new AstAdd ($2,$1->cloneTree(true),new AstConst($2,V3Number($2,"'b1")))); }
| fexprLvalue yP_MINUSMINUS { $$ = new AstAssign($2,$1,new AstSub ($2,$1->cloneTree(true),new AstConst($2,V3Number($2,"'b1")))); }
| yP_PLUSPLUS fexprLvalue { $$ = new AstAssign($1,$2,new AstAdd ($1,$2->cloneTree(true),new AstConst($1,V3Number($1,"'b1")))); }
| yP_MINUSMINUS fexprLvalue { $$ = new AstAssign($1,$2,new AstSub ($1,$2->cloneTree(true),new AstConst($1,V3Number($1,"'b1")))); }
fexprLvalue yP_PLUSPLUS { $$ = new AstAssign($2,$1,new AstAdd ($2,$1->cloneTree(true),new AstConst($2, AstConst::StringToParse(), "'b1"))); }
| fexprLvalue yP_MINUSMINUS { $$ = new AstAssign($2,$1,new AstSub ($2,$1->cloneTree(true),new AstConst($2, AstConst::StringToParse(), "'b1"))); }
| yP_PLUSPLUS fexprLvalue { $$ = new AstAssign($1,$2,new AstAdd ($1,$2->cloneTree(true),new AstConst($1, AstConst::StringToParse(), "'b1"))); }
| yP_MINUSMINUS fexprLvalue { $$ = new AstAssign($1,$2,new AstSub ($1,$2->cloneTree(true),new AstConst($1, AstConst::StringToParse(), "'b1"))); }
;
//************************************************
@ -2798,8 +2798,8 @@ system_t_call<nodep>: // IEEE: system_tf_call (as task)
;
system_f_call<nodep>: // IEEE: system_tf_call (as func)
yaD_IGNORE parenE { $$ = new AstConst($<fl>1,V3Number($<fl>1,"'b0")); } // Unsized 0
| yaD_IGNORE '(' exprList ')' { $$ = new AstConst($2,V3Number($2,"'b0")); } // Unsized 0
yaD_IGNORE parenE { $$ = new AstConst($<fl>1, AstConst::StringToParse(), "'b0"); } // Unsized 0
| yaD_IGNORE '(' exprList ')' { $$ = new AstConst($2, AstConst::StringToParse(), "'b0"); } // Unsized 0
//
| yaD_DPI parenE { $$ = new AstFuncRef($<fl>1,*$1,NULL); }
| yaD_DPI '(' exprList ')' { $$ = new AstFuncRef($2,*$1,$3); GRAMMARP->argWrapList(VN_CAST($$, FuncRef)); }
@ -3781,7 +3781,7 @@ str<strp>: // yaSTRING but with \{escapes} need decoded
;
strAsInt<nodep>:
yaSTRING { $$ = new AstConst($<fl>1,V3Number(V3Number::VerilogStringLiteral(),$<fl>1,GRAMMARP->deQuote($<fl>1,*$1)));}
yaSTRING { $$ = new AstConst($<fl>1, AstConst::VerilogStringLiteral(), GRAMMARP->deQuote($<fl>1, *$1));}
;
strAsIntIgnore<nodep>: // strAsInt, but never matches for when expr shouldn't parse strings
@ -3988,7 +3988,8 @@ void V3ParseGrammar::argWrapList(AstNodeFTaskRef* nodep) {
AstNode* V3ParseGrammar::createSupplyExpr(FileLine* fileline, string name, int value) {
return new AstAssignW(fileline, new AstVarRef(fileline, name, true),
new AstConst(fileline, V3Number(fileline, (value ? "'1" : "'0"))));
new AstConst(fileline, AstConst::StringToParse(),
(value ? "'1" : "'0")));
}
AstRange* V3ParseGrammar::scrubRange(AstNodeRange* nrangep) {