Internals: V3Number tracks node information, part of bug1305.
Signed-off-by: Wilson Snyder <wsnyder@wsnyder.org>
This commit is contained in:
parent
00efa05b50
commit
eac3458647
14
src/V3Ast.h
14
src/V3Ast.h
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
100
src/V3AstNodes.h
100
src/V3AstNodes.h
|
|
@ -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(); }
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
186
src/V3Number.cpp
186
src/V3Number.cpp
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 =
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue