diff --git a/src/V3Active.cpp b/src/V3Active.cpp index 9d190d507..32f51c7a3 100644 --- a/src/V3Active.cpp +++ b/src/V3Active.cpp @@ -394,7 +394,7 @@ private: nodep->unlinkFrBack()->deleteTree(); nodep=NULL; } else if (nodep->varrefp()) { // V3LinkResolve should have cleaned most of these up - if (nodep->varrefp()->width()>1) nodep->v3error("Unsupported: Non-single bit wide signal pos/negedge sensitivity: " + if (!nodep->varrefp()->width1()) nodep->v3error("Unsupported: Non-single bit wide signal pos/negedge sensitivity: " <varrefp()->prettyName()); m_itemSequent = true; nodep->varrefp()->varp()->usedClock(true); diff --git a/src/V3Ast.h b/src/V3Ast.h index 5917f1724..0b23f5afd 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -932,15 +932,17 @@ public: bool isAllOnes(); bool isAllOnesV(); // Verilog width rules apply - // METHODS + // METHODS - dump and error + void v3errorEnd(ostringstream& str) const; + virtual void dump(ostream& str=cout); + + // METHODS - Tree modifications AstNode* addNext(AstNode* newp); // Returns this, adds to end of list AstNode* addNextNull(AstNode* newp); // Returns this, adds to end of list, NULL is OK void addNextHere(AstNode* newp); // Adds after speced node void addPrev(AstNode* newp) { replaceWith(newp); newp->addNext(this); } void addHereThisAsNext(AstNode* newp); // Adds at old place of this, this becomes next void replaceWith(AstNode* newp); // Replace current node in tree with new node - void v3errorEnd(ostringstream& str) const; - virtual void dump(ostream& str=cout); AstNode* unlinkFrBack(AstNRelinker* linkerp=NULL); // Unlink this from whoever points to it. AstNode* unlinkFrBackWithNext(AstNRelinker* linkerp=NULL); // Unlink this from whoever points to it, keep entire next list with unlinked node void swapWith(AstNode* bp); @@ -1493,7 +1495,7 @@ public: inline bool AstNode::isZero() { return (this->castConst() && this->castConst()->num().isEqZero()); } inline bool AstNode::isNeqZero() { return (this->castConst() && this->castConst()->num().isNeqZero()); } inline bool AstNode::isOne() { return (this->castConst() && this->castConst()->num().isEqOne()); } -inline bool AstNode::isAllOnes() { return (this->castConst() && this->castConst()->num().isEqAllOnes(this->width())); } -inline bool AstNode::isAllOnesV() { return (this->castConst() && this->castConst()->num().isEqAllOnes(this->widthMin())); } +inline bool AstNode::isAllOnes() { return (this->castConst() && this->castConst()->isEqAllOnes()); } +inline bool AstNode::isAllOnesV() { return (this->castConst() && this->castConst()->isEqAllOnesV()); } #endif // Guard diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 6f698ac62..62a7f3c4d 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -49,18 +49,18 @@ public: AstConst(FileLine* fl, const V3Number& num) :AstNodeMath(fl) ,m_num(num) { - width(m_num.width(), m_num.sized()?0:m_num.minWidth()); + width(m_num.width(), m_num.sized()?0:m_num.widthMin()); numeric(m_num.isDouble() ? AstNumeric::DOUBLE : 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.minWidth()); } + ,m_num(V3Number(fl,32,num)) { width(m_num.width(), m_num.sized()?0:m_num.widthMin()); } 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.minWidth()); } + ,m_num(V3Number(fl,32,num)) { m_num.width(32,false); width(32,m_num.widthMin()); } class RealDouble {}; // for creator type-overload selection AstConst(FileLine* fl, RealDouble, double num) :AstNodeMath(fl) @@ -87,6 +87,8 @@ public: virtual bool same(AstNode* samep) const { return num().isCaseEq(samep->castConst()->num()); } virtual int instrCount() const { return widthInstrs(); } + bool isEqAllOnes() const { return num().isEqAllOnes(width()); } + bool isEqAllOnesV() const { return num().isEqAllOnes(widthMin()); } }; struct AstConstString : public AstNodeMath { @@ -2595,8 +2597,8 @@ struct AstRedXor : public AstNodeUniop { virtual string emitVerilog() { return "%f(^ %l)"; } virtual string emitC() { return "VL_REDXOR_%lq(%lW, %P, %li)"; } virtual bool cleanOut() {return false;} - virtual bool cleanLhs() {return (lhsp()->width()!=1 && lhsp()->width()!=2 && lhsp()->width()!=4 - && lhsp()->width()!=8 && lhsp()->width()!=16);} + virtual bool cleanLhs() {int w = lhsp()->width(); + return (w!=1 && w!=2 && w!=4 && w!=8 && w!=16); } virtual bool sizeMattersLhs() {return false;} virtual int instrCount() const { return 1+V3Number::log2b(width()); } }; diff --git a/src/V3Clean.cpp b/src/V3Clean.cpp index 697944d54..3ce9b1104 100644 --- a/src/V3Clean.cpp +++ b/src/V3Clean.cpp @@ -24,7 +24,7 @@ // For each math operator, if it requires a clean operand, // and the operand is dirty, insert a CLEAN node. // Resize operands to C++ 32/64/wide types. -// Copy all width() values to minWidth() so RANGE, etc can still see orig widths +// Copy all width() values to widthMin() so RANGE, etc can still see orig widths // //************************************************************************* @@ -47,7 +47,7 @@ private: // NODE STATE // Entire netlist: // AstNode::user() -> CleanState. For this node, 0==UNKNOWN - // AstNode::user2() -> bool. True indicates minWidth has been propagated + // AstNode::user2() -> bool. True indicates widthMin has been propagated AstUser1InUse m_inuser1; AstUser2InUse m_inuser2; diff --git a/src/V3Clock.cpp b/src/V3Clock.cpp index ccffe2fa7..6e095eaeb 100644 --- a/src/V3Clock.cpp +++ b/src/V3Clock.cpp @@ -83,10 +83,9 @@ private: AstVarScope* getCreateLastClk(AstVarScope* vscp) { if (vscp->user1p()) return ((AstVarScope*)vscp->user1p()); AstVar* varp = vscp->varp(); - if (varp->width()!=1) varp->v3error("Unsupported: Clock edge on non-single bit signal: "<prettyName()); + if (!varp->width1()) varp->v3error("Unsupported: Clock edge on non-single bit signal: "<prettyName()); string newvarname = ((string)"__Vclklast__"+vscp->scopep()->nameDotless()+"__"+varp->shortName()); AstVar* newvarp = new AstVar (vscp->fileline(), AstVarType::MODULETEMP, newvarname, AstLogicPacked(), 1); - newvarp->width(1,1); m_modp->addStmtp(newvarp); AstVarScope* newvscp = new AstVarScope(vscp->fileline(), m_scopep, newvarp); vscp->user1p(newvscp); diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index e2b3afa86..cb9d84602 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -552,7 +552,7 @@ public: nodep->v3error("Unsupported: 4-state numbers in this context"); } else if (nodep->isWide()) { putbs("VL_CONST_W_"); - puts(cvtToStr(VL_WORDS_I(nodep->num().minWidth()))); + puts(cvtToStr(VL_WORDS_I(nodep->num().widthMin()))); puts("X("); puts(cvtToStr(nodep->widthMin())); puts(","); @@ -564,7 +564,7 @@ public: } else { assigntop->iterateAndNext(*this); } - for (int word=VL_WORDS_I(nodep->num().minWidth())-1; word>0; word--) { + for (int word=VL_WORDS_I(nodep->num().widthMin())-1; word>0; word--) { // Only 32 bits - llx + long long here just to appease CPP format warning ofp()->printf(",0x%08" VL_PRI64 "x", (vluint64_t)(nodep->num().dataWord(word))); } diff --git a/src/V3LinkJump.cpp b/src/V3LinkJump.cpp index 9e9f4fb25..f270b37b6 100644 --- a/src/V3LinkJump.cpp +++ b/src/V3LinkJump.cpp @@ -149,7 +149,8 @@ private: 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))); - AstNode* zerosp = new AstConst(nodep->fileline(), 0); zerosp->numeric(AstNumeric::SIGNED); + V3Number zero (nodep->fileline(), 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(); diff --git a/src/V3Number.cpp b/src/V3Number.cpp index 67f7f5d97..22b2d7c3c 100644 --- a/src/V3Number.cpp +++ b/src/V3Number.cpp @@ -626,7 +626,7 @@ bool V3Number::isLt(const V3Number& rhs) const { return 0; } -int V3Number::minWidth() const { +int V3Number::widthMin() const { for(int bit=width()-1; bit>0; bit--) { if (!bitIs0(bit)) return bit+1; } diff --git a/src/V3Number.h b/src/V3Number.h index 1734a2970..48b445a3e 100644 --- a/src/V3Number.h +++ b/src/V3Number.h @@ -150,7 +150,7 @@ public: string displayed(const string& format) const; static bool displayedFmtLegal(char format); // Is this a valid format letter? int width() const { return m_width; } - int minWidth() 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; } diff --git a/src/V3Width.cpp b/src/V3Width.cpp index cfeeffc5f..3f3ba94ae 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -85,12 +85,12 @@ enum Stage { PRELIM=1,FINAL=2,BOTH=3 }; class WidthVP : public AstNUser { // Parameters to pass down hierarchy with visit functions. int m_width; // Expression width, for (2+2), it's 32 bits - int m_minWidth; // Minimum width, for (2+2), it's 2 bits, for 32'2+32'2 it's 32 bits + int m_widthMin; // Minimum width, for (2+2), it's 2 bits, for 32'2+32'2 it's 32 bits Stage m_stage; // If true, report errors public: - WidthVP(int width, int minWidth, Stage stage) : m_width(width), m_minWidth(minWidth), m_stage(stage) {} + WidthVP(int width, int widthMin, Stage stage) : m_width(width), m_widthMin(widthMin), m_stage(stage) {} int width() const { return m_width; } - int widthMin() const { return m_minWidth?m_minWidth:m_width; } + int widthMin() const { return m_widthMin?m_widthMin:m_width; } bool prelim() const { return m_stage&1; } bool final() const { return m_stage&2; } }; @@ -526,7 +526,7 @@ private: if (nodep->num().sized()) { nodep->width(nodep->num().width(), nodep->num().width()); } else { - nodep->width(nodep->num().width(), nodep->num().minWidth()); + nodep->width(nodep->num().width(), nodep->num().widthMin()); } } // We don't size the constant until we commit the widths, as need parameters @@ -1474,7 +1474,7 @@ private: checkCvtUS(nodep->lhsp()); } int width = nodep->lhsp()->width(); - int ewidth = nodep->lhsp()->width(); // Not minWidth; force it. + int ewidth = nodep->lhsp()->width(); // Not widthMin; force it. nodep->width(width,ewidth); nodep->numeric(rs_out); if (vup->c()->final()) { diff --git a/src/V3WidthSel.cpp b/src/V3WidthSel.cpp index bd89946cc..63c4a6f9c 100644 --- a/src/V3WidthSel.cpp +++ b/src/V3WidthSel.cpp @@ -126,7 +126,7 @@ private: AstNode* newp = new AstSub(rhsp->fileline(), new AstConst(rhsp->fileline(), AstConst::Unsized32(), lhs), rhsp); - newp->numericFrom(rhsp); // Important as AstSub default is lhs's sign + newp->widthSignedFrom(rhsp); // Important as AstSub default is lhs's sign return newp; }