diff --git a/src/V3Ast.h b/src/V3Ast.h index 4a8e66f67..cf6c9a100 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -938,6 +938,8 @@ public: bool isAllOnesV(); // Verilog width rules apply // METHODS - data type changes especially for initial creation + void dtypeSetBitSized(int widthf, int widthMinf, AstNumeric numericf) { numeric(numericf); width(widthf,widthMinf); } + void dtypeSetLogicSized(int widthf, int widthMinf, AstNumeric numericf) { numeric(numericf); width(widthf,widthMinf); } void dtypeSetLogicBool() { numeric(AstNumeric::UNSIGNED); width(1,1); } void dtypeSetDouble() { numeric(AstNumeric::DOUBLE); } void dtypeSetSigned32() { numeric(AstNumeric::SIGNED); width(VL_WORDSIZE,VL_WORDSIZE); } diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 919fa3df9..c11d764d8 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -52,18 +52,21 @@ public: if (m_num.isDouble()) { dtypeSetDouble(); } else { - width(m_num.width(), m_num.sized()?0:m_num.widthMin()); - numeric(m_num.isSigned() ? AstNumeric::SIGNED - : AstNumeric::UNSIGNED); + dtypeSetLogicSized(m_num.width(), m_num.sized()?0:m_num.widthMin(), + m_num.isSigned() ? AstNumeric::SIGNED + : AstNumeric::UNSIGNED); } } AstConst(FileLine* fl, uint32_t num) :AstNodeMath(fl) - ,m_num(V3Number(fl,32,num)) { width(m_num.width(), m_num.sized()?0:m_num.widthMin()); } + ,m_num(V3Number(fl,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); width(32,m_num.widthMin()); } + ,m_num(V3Number(fl,32,num)) { m_num.width(32,false); dtypeSetLogicSized(32,m_num.widthMin(), + AstNumeric::UNSIGNED); } class RealDouble {}; // for creator type-overload selection AstConst(FileLine* fl, RealDouble, double num) :AstNodeMath(fl) @@ -105,9 +108,9 @@ public: } void rewidth() { if (m_name.length()==0) { - width(1,1); // 0 width isn't allowed due to historic special cases + dtypeSetLogicSized(1,1,AstNumeric::UNSIGNED); // 0 width isn't allowed due to historic special cases } else { - width(((int)m_name.length())*8, ((int)m_name.length())*8); + dtypeSetLogicSized(((int)m_name.length())*8, ((int)m_name.length())*8, AstNumeric::UNSIGNED); } } ASTNODE_NODE_FUNCS(ConstString, CONSTSTRING) @@ -2862,7 +2865,9 @@ private: public: AstCCast(FileLine* fl, AstNode* lhsp, int setwidth) : AstNodeUniop(fl, lhsp) { m_size=setwidth; - if (setwidth) { width(setwidth,setwidth); } + if (setwidth) { + dtypeSetLogicSized(setwidth,setwidth,AstNumeric::UNSIGNED); + } } AstCCast(FileLine* fl, AstNode* lhsp, AstNode* typeFromp) : AstNodeUniop(fl, lhsp) { if (typeFromp) { widthSignedFrom(typeFromp); } @@ -3318,7 +3323,7 @@ struct AstLteS : public AstNodeBiop { struct AstShiftL : public AstNodeBiop { AstShiftL(FileLine* fl, AstNode* lhsp, AstNode* rhsp, int setwidth=0) : AstNodeBiop(fl, lhsp, rhsp) { - if (setwidth) { width(setwidth,setwidth); } + if (setwidth) { dtypeSetLogicSized(setwidth,setwidth,AstNumeric::UNSIGNED); } } ASTNODE_NODE_FUNCS(ShiftL, SHIFTL) virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opShiftL(lhs,rhs); } @@ -3332,7 +3337,7 @@ struct AstShiftL : public AstNodeBiop { struct AstShiftR : public AstNodeBiop { AstShiftR(FileLine* fl, AstNode* lhsp, AstNode* rhsp, int setwidth=0) : AstNodeBiop(fl, lhsp, rhsp) { - if (setwidth) { width(setwidth,setwidth); } + if (setwidth) { dtypeSetLogicSized(setwidth,setwidth,AstNumeric::UNSIGNED); } } ASTNODE_NODE_FUNCS(ShiftR, SHIFTR) virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opShiftR(lhs,rhs); } @@ -4089,7 +4094,7 @@ public: AstCMath(FileLine* fl, const string& textStmt, int setwidth, bool cleanOut=true) : AstNodeMath(fl), m_cleanOut(cleanOut) { addNOp1p(new AstText(fl, textStmt, true)); - if (setwidth) { width(setwidth,setwidth); } + if (setwidth) { dtypeSetLogicSized(setwidth,setwidth,AstNumeric::UNSIGNED); } } ASTNODE_NODE_FUNCS(CMath, CMATH) virtual bool isGateOptimizable() const { return false; } diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 52d063803..c67d7a5ad 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -275,8 +275,9 @@ private: } else { int width = max(vup->c()->width(), max(nodep->expr1p()->width(), nodep->expr2p()->width())); int mwidth = max(vup->c()->widthMin(), max(nodep->expr1p()->widthMin(), nodep->expr2p()->widthMin())); - nodep->isSigned(nodep->expr1p()->isSigned() && nodep->expr2p()->isSigned()); - nodep->width(width,mwidth); + nodep->dtypeSetLogicSized(width,mwidth, + ((nodep->expr1p()->isSigned() && nodep->expr2p()->isSigned()) + ? AstNumeric::SIGNED : AstNumeric::UNSIGNED)); } if (vup->c()->final()) { // Final width known, so make sure children recompute & check their sizes @@ -298,9 +299,9 @@ private: nodep->rhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); checkCvtUS(nodep->lhsp()); checkCvtUS(nodep->rhsp()); - nodep->width(nodep->lhsp()->width() + nodep->rhsp()->width(), - nodep->lhsp()->widthMin() + nodep->rhsp()->widthMin()); - nodep->numeric(AstNumeric::UNSIGNED); + nodep->dtypeSetLogicSized(nodep->lhsp()->width() + nodep->rhsp()->width(), + nodep->lhsp()->widthMin() + nodep->rhsp()->widthMin(), + AstNumeric::UNSIGNED); // Cleanup zero width Verilog2001 {x,{0{foo}}} now, // otherwise having width(0) will cause later assertions to fire if (AstReplicate* repp=nodep->lhsp()->castReplicate()) { @@ -338,9 +339,9 @@ private: if (times==0 && !nodep->backp()->castConcat()) { // Concat Visitor will clean it up. nodep->v3error("Replication value of 0 is only legal under a concatenation."); times=1; } - nodep->numeric(AstNumeric::UNSIGNED); - nodep->width((nodep->lhsp()->width() * times), - (nodep->lhsp()->widthMin() * times)); + nodep->dtypeSetLogicSized((nodep->lhsp()->width() * times), + (nodep->lhsp()->widthMin() * times), + AstNumeric::UNSIGNED); } if (vup->c()->final()) { if (!nodep->widthSized()) { @@ -385,14 +386,13 @@ private: nodep->dtypeSetLogicBool(); return; } int width = nodep->widthConst(); - nodep->width(width,width); - nodep->numeric(AstNumeric::UNSIGNED); + nodep->dtypeSetLogicSized(width,width,AstNumeric::UNSIGNED); if (nodep->lsbp()->castConst() && nodep->msbConst() < nodep->lsbConst()) { nodep->v3error("Unsupported: MSB < LSB of bit extract: " <msbConst()<<"<"<lsbConst()); width = (nodep->lsbConst() - nodep->msbConst() + 1); - nodep->width(width,width); + nodep->dtypeSetLogicSized(width,width,AstNumeric::UNSIGNED); nodep->widthp()->replaceWith(new AstConst(nodep->widthp()->fileline(), width)); nodep->lsbp()->replaceWith(new AstConst(nodep->lsbp()->fileline(), 0)); @@ -546,13 +546,12 @@ private: } } virtual void visit(AstUCFunc* nodep, AstNUser* vup) { - nodep->numeric(AstNumeric::UNSIGNED); // If want otherwise use a dpi import // Give it the size the user wants. if (vup && vup->c()->prelim()) { - nodep->width(32,1); // We don't care + nodep->dtypeSetLogicSized(32,1,AstNumeric::UNSIGNED); // We don't care } if (vup->c()->final()) { - nodep->width(vup->c()->width(),vup->c()->widthMin()); // We don't care + nodep->dtypeSetLogicSized(vup->c()->width(),vup->c()->widthMin(),AstNumeric::UNSIGNED); // We don't care if (nodep->width()>64) nodep->v3error("Unsupported: $c can't generate wider than 64 bits"); } // Just let all arguments seek their natural sizes @@ -596,8 +595,7 @@ private: checkCvtUS(nodep->lhsp()); // If it's a 32 bit number, we need a 6 bit number as we need to return '32'. int selwidth = V3Number::log2b(nodep->lhsp()->width())+1; - nodep->numeric(AstNumeric::UNSIGNED); - nodep->width(selwidth,selwidth); + nodep->dtypeSetLogicSized(selwidth,selwidth,AstNumeric::UNSIGNED); // Spec doesn't indicate if an integer } } virtual void visit(AstCvtPackString* nodep, AstNUser* vup) { @@ -993,8 +991,7 @@ private: } virtual void visit(AstFEof* nodep, AstNUser*) { nodep->filep()->iterateAndNext(*this,WidthVP(32,32,BOTH).p()); - nodep->numeric(AstNumeric::UNSIGNED); - nodep->width(1,1); + nodep->dtypeSetLogicSized(32,1,AstNumeric::SIGNED); // Spec says integer return widthCheck(nodep,"file_descriptor",nodep->filep(),32,32); } virtual void visit(AstFFlush* nodep, AstNUser*) { @@ -1006,7 +1003,7 @@ private: virtual void visit(AstFGetC* nodep, AstNUser* vup) { nodep->filep()->iterateAndNext(*this,WidthVP(32,32,BOTH).p()); if (vup->c()->prelim()) { - nodep->width(32,8); + nodep->dtypeSetLogicSized(32,8,AstNumeric::SIGNED); // Spec says integer return } widthCheck(nodep,"file_descriptor",nodep->filep(),32,32); } @@ -1475,8 +1472,7 @@ private: } int width = nodep->lhsp()->width(); int ewidth = nodep->lhsp()->width(); // Not widthMin; force it. - nodep->width(width,ewidth); - nodep->numeric(rs_out); + nodep->dtypeSetLogicSized(width,ewidth,rs_out); if (vup->c()->final()) { // Final call, so make sure children check their sizes nodep->lhsp()->iterateAndNext(*this,WidthVP(width,ewidth,FINAL).p());