Internals: Move width internals to inside class; move WidthCommit. No functional change

This commit is contained in:
Wilson Snyder 2011-07-06 19:03:40 -04:00
parent 1b3d252bfe
commit 4fa1e45d45
2 changed files with 396 additions and 380 deletions

View File

@ -57,6 +57,10 @@
#include "V3Const.h" #include "V3Const.h"
#include "V3Task.h" #include "V3Task.h"
// More code; this file was getting too large; see actions there
#define _V3WIDTH_CPP_
#include "V3WidthCommit.h"
//###################################################################### //######################################################################
// Width state, as a visitor of each AstNode // Width state, as a visitor of each AstNode
@ -99,19 +103,16 @@ private:
// VISITORS // VISITORS
// Naming: width_{output size rule}_{lhs rule}_{rhs rule} // Naming: width_{output size rule}_{lhs rule}_{rhs rule}
// Widths: 1 bit out, lhs 1 bit // Widths: 1 bit out, lhs 1 bit
void width_O1_L1(AstNode* nodep, AstNUser* vup);
virtual void visit(AstLogNot* nodep, AstNUser* vup) { width_O1_L1(nodep,vup); } virtual void visit(AstLogNot* nodep, AstNUser* vup) { width_O1_L1(nodep,vup); }
virtual void visit(AstPslBool* nodep, AstNUser* vup) { width_O1_L1(nodep,vup); } virtual void visit(AstPslBool* nodep, AstNUser* vup) { width_O1_L1(nodep,vup); }
// Widths: 1 bit out, lhs 1 bit, rhs 1 bit // Widths: 1 bit out, lhs 1 bit, rhs 1 bit
void width_O1_L1_R1(AstNode* nodep, AstNUser* vup);
virtual void visit(AstLogAnd* nodep, AstNUser* vup) { width_O1_L1_R1(nodep,vup); } virtual void visit(AstLogAnd* nodep, AstNUser* vup) { width_O1_L1_R1(nodep,vup); }
virtual void visit(AstLogOr* nodep, AstNUser* vup) { width_O1_L1_R1(nodep,vup); } virtual void visit(AstLogOr* nodep, AstNUser* vup) { width_O1_L1_R1(nodep,vup); }
virtual void visit(AstLogIf* nodep, AstNUser* vup) { width_O1_L1_R1(nodep,vup); } virtual void visit(AstLogIf* nodep, AstNUser* vup) { width_O1_L1_R1(nodep,vup); }
virtual void visit(AstLogIff* nodep, AstNUser* vup) { width_O1_L1_R1(nodep,vup); } virtual void visit(AstLogIff* nodep, AstNUser* vup) { width_O1_L1_R1(nodep,vup); }
// Widths: 1 bit out, Any width lhs // Widths: 1 bit out, Any width lhs
void width_O1_L(AstNode* nodep, AstNUser* vup);
virtual void visit(AstRedAnd* nodep, AstNUser* vup) { width_O1_L(nodep,vup); } virtual void visit(AstRedAnd* nodep, AstNUser* vup) { width_O1_L(nodep,vup); }
virtual void visit(AstRedOr* nodep, AstNUser* vup) { width_O1_L(nodep,vup); } virtual void visit(AstRedOr* nodep, AstNUser* vup) { width_O1_L(nodep,vup); }
virtual void visit(AstRedXnor* nodep, AstNUser* vup){ width_O1_L(nodep,vup); } virtual void visit(AstRedXnor* nodep, AstNUser* vup){ width_O1_L(nodep,vup); }
@ -121,7 +122,6 @@ private:
virtual void visit(AstOneHot0* nodep,AstNUser* vup) { width_O1_L(nodep,vup); } virtual void visit(AstOneHot0* nodep,AstNUser* vup) { width_O1_L(nodep,vup); }
// Widths: 1 bit out, lhs width == rhs width // Widths: 1 bit out, lhs width == rhs width
void width_O1_L_Rlhs(AstNode* nodep, AstNUser* vup);
virtual void visit(AstEq* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); } virtual void visit(AstEq* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); }
virtual void visit(AstEqCase* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); } virtual void visit(AstEqCase* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); }
virtual void visit(AstEqWild* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); } virtual void visit(AstEqWild* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); }
@ -138,7 +138,6 @@ private:
virtual void visit(AstNeqWild* nodep, AstNUser* vup){ width_O1_L_Rlhs(nodep,vup); } virtual void visit(AstNeqWild* nodep, AstNUser* vup){ width_O1_L_Rlhs(nodep,vup); }
// Widths: out width = lhs width = rhs width // Widths: out width = lhs width = rhs width
void width_Omax_L_Rlhs(AstNode* nodep, AstNUser* vup);
virtual void visit(AstAnd* nodep, AstNUser* vup) { width_Omax_L_Rlhs(nodep,vup); } virtual void visit(AstAnd* nodep, AstNUser* vup) { width_Omax_L_Rlhs(nodep,vup); }
virtual void visit(AstOr* nodep, AstNUser* vup) { width_Omax_L_Rlhs(nodep,vup); } virtual void visit(AstOr* nodep, AstNUser* vup) { width_Omax_L_Rlhs(nodep,vup); }
virtual void visit(AstXnor* nodep, AstNUser* vup) { width_Omax_L_Rlhs(nodep,vup); } virtual void visit(AstXnor* nodep, AstNUser* vup) { width_Omax_L_Rlhs(nodep,vup); }
@ -156,26 +155,20 @@ private:
virtual void visit(AstMulS* nodep, AstNUser* vup) { width_Omax_L_Rlhs(nodep,vup); } virtual void visit(AstMulS* nodep, AstNUser* vup) { width_Omax_L_Rlhs(nodep,vup); }
// Widths: out width = lhs width, but upper matters // Widths: out width = lhs width, but upper matters
void width_Olhs_L(AstNodeUniop* nodep, AstNUser* vup);
virtual void visit(AstNot* nodep, AstNUser* vup) { width_Olhs_L(nodep,vup); } virtual void visit(AstNot* nodep, AstNUser* vup) { width_Olhs_L(nodep,vup); }
virtual void visit(AstUnaryMin* nodep, AstNUser* vup) { width_Olhs_L(nodep,vup); } virtual void visit(AstUnaryMin* nodep, AstNUser* vup) { width_Olhs_L(nodep,vup); }
// Widths: out width = lhs width, upper doesn't matter // Widths: out width = lhs width, upper doesn't matter
void width_Olhs_Lforce(AstNodeUniop* nodep, AstNUser* vup);
virtual void visit(AstSigned* nodep, AstNUser* vup) { width_Olhs_Lforce(nodep,vup); } virtual void visit(AstSigned* nodep, AstNUser* vup) { width_Olhs_Lforce(nodep,vup); }
virtual void visit(AstUnsigned* nodep, AstNUser* vup) { width_Olhs_Lforce(nodep,vup); } virtual void visit(AstUnsigned* nodep, AstNUser* vup) { width_Olhs_Lforce(nodep,vup); }
// Widths: Output width from lhs, rhs<33 bits // Widths: Output width from lhs, rhs<33 bits
void width_Olhs_L_R32(AstNode* nodep, AstNUser* vup);
virtual void visit(AstPow* nodep, AstNUser* vup) { width_Olhs_L_R32(nodep,vup); } virtual void visit(AstPow* nodep, AstNUser* vup) { width_Olhs_L_R32(nodep,vup); }
virtual void visit(AstPowS* nodep, AstNUser* vup) { width_Olhs_L_R32(nodep,vup); } virtual void visit(AstPowS* nodep, AstNUser* vup) { width_Olhs_L_R32(nodep,vup); }
virtual void visit(AstShiftL* nodep, AstNUser* vup) { width_Olhs_L_R32(nodep,vup); } virtual void visit(AstShiftL* nodep, AstNUser* vup) { width_Olhs_L_R32(nodep,vup); }
virtual void visit(AstShiftR* nodep, AstNUser* vup) { width_Olhs_L_R32(nodep,vup); } virtual void visit(AstShiftR* nodep, AstNUser* vup) { width_Olhs_L_R32(nodep,vup); }
virtual void visit(AstShiftRS* nodep, AstNUser* vup) { width_Olhs_L_R32(nodep,vup); } virtual void visit(AstShiftRS* nodep, AstNUser* vup) { width_Olhs_L_R32(nodep,vup); }
// Widths: Fixed
void width_Ofixed_L(AstNodeUniop* nodep, AstNUser* vup, int width);
// Widths: Constant, terminal // Widths: Constant, terminal
virtual void visit(AstTime* nodep, AstNUser*) { nodep->width(64,64); } virtual void visit(AstTime* nodep, AstNUser*) { nodep->width(64,64); }
virtual void visit(AstTestPlusArgs* nodep, AstNUser*) { nodep->width(32,32); } virtual void visit(AstTestPlusArgs* nodep, AstNUser*) { nodep->width(32,32); }
@ -1047,47 +1040,19 @@ private:
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
// METHODS //----------------------------------------------------------------------
bool widthBad (AstNode* nodep, int expWidth, int expWidthMin); // METHODs
void widthCheck (AstNode* nodep, const char* side,
AstNode* underp, int expWidth, int expWidthMin,
bool ignoreWarn=false);
void widthCheckReduce (AstNode* nodep, const char* side,
AstNode* underp, int expWidth, int expWidthMin,
bool ignoreWarn=false);
void widthCheckPin (AstNode* nodep, AstNode* underp, int expWidth, bool inputPin);
bool fixAutoExtend (AstNode*& nodepr, int expWidth);
void fixWidthExtend (AstNode* nodep, int expWidth);
void fixWidthReduce (AstNode* nodep, int expWidth);
public: bool widthBad (AstNode* nodep, int expWidth, int expWidthMin) {
// CONSTUCTORS
WidthVisitor(bool paramsOnly) {
m_paramsOnly = paramsOnly;
m_taskDepth = 0;
m_cellRangep = NULL;
m_casep = NULL;
m_funcp = NULL;
}
AstNode* mainAcceptEdit(AstNode* nodep) {
return nodep->acceptSubtreeReturnEdits(*this, WidthVP(ANYSIZE,0,BOTH).p());
}
virtual ~WidthVisitor() {}
};
//----------------------------------------------------------------------
// METHODs
bool WidthVisitor::widthBad (AstNode* nodep, int expWidth, int expWidthMin) {
if (nodep->width()==0) nodep->v3fatalSrc("Under node "<<nodep->prettyTypeName()<<" has no expected width?? Missing Visitor func?"); if (nodep->width()==0) nodep->v3fatalSrc("Under node "<<nodep->prettyTypeName()<<" has no expected width?? Missing Visitor func?");
if (expWidth==0) nodep->v3fatalSrc("Node "<<nodep->prettyTypeName()<<" has no expected width?? Missing Visitor func?"); if (expWidth==0) nodep->v3fatalSrc("Node "<<nodep->prettyTypeName()<<" has no expected width?? Missing Visitor func?");
if (expWidthMin==0) expWidthMin = expWidth; if (expWidthMin==0) expWidthMin = expWidth;
if (nodep->widthSized() && nodep->width() != expWidthMin) return true; if (nodep->widthSized() && nodep->width() != expWidthMin) return true;
if (!nodep->widthSized() && nodep->widthMin() > expWidthMin) return true; if (!nodep->widthSized() && nodep->widthMin() > expWidthMin) return true;
return false; return false;
} }
void WidthVisitor::fixWidthExtend (AstNode* nodep, int expWidth) { void fixWidthExtend (AstNode* nodep, int expWidth) {
// Fix the width mismatch by extending or truncating bits // Fix the width mismatch by extending or truncating bits
// Truncation is rarer, but can occur: parameter [3:0] FOO = 64'h12312; // Truncation is rarer, but can occur: parameter [3:0] FOO = 64'h12312;
// A(CONSTwide)+B becomes A(CONSTwidened)+B // A(CONSTwide)+B becomes A(CONSTwidened)+B
@ -1123,9 +1088,9 @@ void WidthVisitor::fixWidthExtend (AstNode* nodep, int expWidth) {
} }
nodep->width(expWidth,expWidth); nodep->width(expWidth,expWidth);
UINFO(4," _new: "<<nodep<<endl); UINFO(4," _new: "<<nodep<<endl);
} }
void WidthVisitor::fixWidthReduce (AstNode* nodep, int expWidth) { void fixWidthReduce (AstNode* nodep, int expWidth) {
// Fix the width mismatch by adding a reduction OR operator // Fix the width mismatch by adding a reduction OR operator
// IF (A(CONSTwide)) becomes IF (A(CONSTreduced)) // IF (A(CONSTwide)) becomes IF (A(CONSTreduced))
// IF (A(somewide)) becomes IF (A(REDOR(somewide))) // IF (A(somewide)) becomes IF (A(REDOR(somewide)))
@ -1148,9 +1113,9 @@ void WidthVisitor::fixWidthReduce (AstNode* nodep, int expWidth) {
} }
nodep->width(expWidth,expWidth); nodep->width(expWidth,expWidth);
UINFO(4," _new: "<<nodep<<endl); UINFO(4," _new: "<<nodep<<endl);
} }
bool WidthVisitor::fixAutoExtend (AstNode*& nodepr, int expWidth) { bool fixAutoExtend (AstNode*& nodepr, int expWidth) {
// For SystemVerilog '0,'1,'x,'z, autoextend and don't warn // For SystemVerilog '0,'1,'x,'z, autoextend and don't warn
if (AstConst* constp = nodepr->castConst()) { if (AstConst* constp = nodepr->castConst()) {
if (constp->num().autoExtend() && !constp->num().sized() && constp->width()==1) { if (constp->num().autoExtend() && !constp->num().sized() && constp->width()==1) {
@ -1169,11 +1134,11 @@ bool WidthVisitor::fixAutoExtend (AstNode*& nodepr, int expWidth) {
} }
} }
return false; // No change return false; // No change
} }
void WidthVisitor::widthCheck (AstNode* nodep, const char* side, void widthCheck (AstNode* nodep, const char* side,
AstNode* underp, int expWidth, int expWidthMin, AstNode* underp, int expWidth, int expWidthMin,
bool ignoreWarn) { bool ignoreWarn=false) {
//UINFO(9,"wchk "<<side<<endl<<" "<<nodep<<endl<<" "<<underp<<endl<<" e"<<expWidth<<" m"<<expWidthMin<<" i"<<ignoreWarn<<endl); //UINFO(9,"wchk "<<side<<endl<<" "<<nodep<<endl<<" "<<underp<<endl<<" e"<<expWidth<<" m"<<expWidthMin<<" i"<<ignoreWarn<<endl);
if (expWidthMin==0) expWidthMin = expWidth; if (expWidthMin==0) expWidthMin = expWidth;
bool bad = widthBad(underp,expWidth,expWidthMin); bool bad = widthBad(underp,expWidth,expWidthMin);
@ -1205,11 +1170,11 @@ void WidthVisitor::widthCheck (AstNode* nodep, const char* side,
if (bad || underp->width()!=expWidth) { if (bad || underp->width()!=expWidth) {
fixWidthExtend(underp, expWidth); underp=NULL;//Changed fixWidthExtend(underp, expWidth); underp=NULL;//Changed
} }
} }
void WidthVisitor::widthCheckReduce (AstNode* nodep, const char* side, void widthCheckReduce (AstNode* nodep, const char* side,
AstNode* underp, int expWidth, int expWidthMin, AstNode* underp, int expWidth, int expWidthMin,
bool ignoreWarn) { bool ignoreWarn=false) {
// Before calling this, iterate into underp with FINAL state, so numbers get resized appropriately // Before calling this, iterate into underp with FINAL state, so numbers get resized appropriately
if (expWidthMin==0) expWidthMin = expWidth; if (expWidthMin==0) expWidthMin = expWidth;
if (expWidth!=1) nodep->v3fatalSrc("Only for binary functions"); if (expWidth!=1) nodep->v3fatalSrc("Only for binary functions");
@ -1226,9 +1191,9 @@ void WidthVisitor::widthCheckReduce (AstNode* nodep, const char* side,
} }
fixWidthReduce(underp, expWidth); underp=NULL;//Changed fixWidthReduce(underp, expWidth); underp=NULL;//Changed
} }
} }
void WidthVisitor::widthCheckPin (AstNode* nodep, AstNode* underp, int expWidth, bool inputPin) { void widthCheckPin (AstNode* nodep, AstNode* underp, int expWidth, bool inputPin) {
// Before calling this, iterate into underp with FINAL state, so numbers get resized appropriately // Before calling this, iterate into underp with FINAL state, so numbers get resized appropriately
bool bad = widthBad(underp,expWidth,expWidth); bool bad = widthBad(underp,expWidth,expWidth);
if (bad && fixAutoExtend(underp/*ref*/,expWidth)) bad=false; // Changes underp if (bad && fixAutoExtend(underp/*ref*/,expWidth)) bad=false; // Changes underp
@ -1246,9 +1211,9 @@ void WidthVisitor::widthCheckPin (AstNode* nodep, AstNode* underp, int expWidth,
if (bad && inputPin) { if (bad && inputPin) {
fixWidthExtend(underp, expWidth); underp=NULL;//Changed fixWidthExtend(underp, expWidth); underp=NULL;//Changed
} }
} }
void WidthVisitor::width_O1_L1(AstNode* nodep, AstNUser* vup) { void width_O1_L1(AstNode* nodep, AstNUser* vup) {
// Widths: 1 bit out, lhs 1 bit // Widths: 1 bit out, lhs 1 bit
// We calculate the width of the UNDER expression. // We calculate the width of the UNDER expression.
// We then check its width to see if it's legal, and edit if not // We then check its width to see if it's legal, and edit if not
@ -1261,9 +1226,9 @@ void WidthVisitor::width_O1_L1(AstNode* nodep, AstNUser* vup) {
if (vup->c()->final()) { if (vup->c()->final()) {
widthCheckReduce(nodep,"LHS",nodep->op1p(),1,1); widthCheckReduce(nodep,"LHS",nodep->op1p(),1,1);
} }
} }
void WidthVisitor::width_O1_L1_R1(AstNode* nodep, AstNUser* vup) { void width_O1_L1_R1(AstNode* nodep, AstNUser* vup) {
// Widths: 1 bit out, lhs 1 bit, rhs 1 bit // Widths: 1 bit out, lhs 1 bit, rhs 1 bit
if (!nodep->op2p()) nodep->v3fatalSrc("For binary ops only!"); if (!nodep->op2p()) nodep->v3fatalSrc("For binary ops only!");
if (vup->c()->prelim()) { if (vup->c()->prelim()) {
@ -1275,18 +1240,18 @@ void WidthVisitor::width_O1_L1_R1(AstNode* nodep, AstNUser* vup) {
widthCheckReduce(nodep,"LHS",nodep->op1p(),1,1); widthCheckReduce(nodep,"LHS",nodep->op1p(),1,1);
widthCheckReduce(nodep,"RHS",nodep->op2p(),1,1); widthCheckReduce(nodep,"RHS",nodep->op2p(),1,1);
} }
} }
void WidthVisitor::width_O1_L(AstNode* nodep, AstNUser* vup) { void width_O1_L(AstNode* nodep, AstNUser* vup) {
// Widths: 1 bit out, Any width lhs // Widths: 1 bit out, Any width lhs
if (nodep->op2p()) nodep->v3fatalSrc("For unary ops only!"); if (nodep->op2p()) nodep->v3fatalSrc("For unary ops only!");
if (vup->c()->prelim()) { if (vup->c()->prelim()) {
nodep->op1p()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); nodep->op1p()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
} }
nodep->width(1,1); nodep->width(1,1);
} }
void WidthVisitor::width_O1_L_Rlhs(AstNode* nodep, AstNUser* vup) { void width_O1_L_Rlhs(AstNode* nodep, AstNUser* vup) {
// Widths: 1 bit out, lhs width == rhs width // Widths: 1 bit out, lhs width == rhs width
if (!nodep->op2p()) nodep->v3fatalSrc("For binary ops only!"); if (!nodep->op2p()) nodep->v3fatalSrc("For binary ops only!");
if (vup->c()->prelim()) { if (vup->c()->prelim()) {
@ -1302,18 +1267,18 @@ void WidthVisitor::width_O1_L_Rlhs(AstNode* nodep, AstNUser* vup) {
widthCheck(nodep,"LHS",nodep->op1p(),width,ewidth); widthCheck(nodep,"LHS",nodep->op1p(),width,ewidth);
widthCheck(nodep,"RHS",nodep->op2p(),width,ewidth); widthCheck(nodep,"RHS",nodep->op2p(),width,ewidth);
} }
} }
void WidthVisitor::width_Ofixed_L(AstNodeUniop* nodep, AstNUser* vup, int width) { void width_Ofixed_L(AstNodeUniop* nodep, AstNUser* vup, int width) {
// Widths: out width = specified width // Widths: out width = specified width
if (nodep->op2p()) nodep->v3fatalSrc("For unary ops only!"); if (nodep->op2p()) nodep->v3fatalSrc("For unary ops only!");
if (vup->c()->prelim()) { if (vup->c()->prelim()) {
nodep->op1p()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); nodep->op1p()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
} }
nodep->width(width,width); nodep->width(width,width);
} }
void WidthVisitor::width_Olhs_L(AstNodeUniop* nodep, AstNUser* vup) { void width_Olhs_L(AstNodeUniop* nodep, AstNUser* vup) {
// Widths: out width = lhs width // Widths: out width = lhs width
// "Interim results shall take the max of operands, including LHS of assignments" // "Interim results shall take the max of operands, including LHS of assignments"
if (nodep->op2p()) nodep->v3fatalSrc("For unary ops only!"); if (nodep->op2p()) nodep->v3fatalSrc("For unary ops only!");
@ -1327,9 +1292,9 @@ void WidthVisitor::width_Olhs_L(AstNodeUniop* nodep, AstNUser* vup) {
nodep->lhsp()->iterateAndNext(*this,WidthVP(width,ewidth,FINAL).p()); nodep->lhsp()->iterateAndNext(*this,WidthVP(width,ewidth,FINAL).p());
widthCheck(nodep,"LHS",nodep->lhsp(),width,ewidth); widthCheck(nodep,"LHS",nodep->lhsp(),width,ewidth);
} }
} }
void WidthVisitor::width_Olhs_Lforce(AstNodeUniop* nodep, AstNUser* vup) { void width_Olhs_Lforce(AstNodeUniop* nodep, AstNUser* vup) {
// Widths: out width = lhs width // Widths: out width = lhs width
// It always comes exactly from LHS; ignores any upper operand // It always comes exactly from LHS; ignores any upper operand
if (nodep->op2p()) nodep->v3fatalSrc("For unary ops only!"); if (nodep->op2p()) nodep->v3fatalSrc("For unary ops only!");
@ -1344,9 +1309,9 @@ void WidthVisitor::width_Olhs_Lforce(AstNodeUniop* nodep, AstNUser* vup) {
nodep->lhsp()->iterateAndNext(*this,WidthVP(width,ewidth,FINAL).p()); nodep->lhsp()->iterateAndNext(*this,WidthVP(width,ewidth,FINAL).p());
widthCheck(nodep,"LHS",nodep->lhsp(),width,ewidth); widthCheck(nodep,"LHS",nodep->lhsp(),width,ewidth);
} }
} }
void WidthVisitor::width_Olhs_L_R32(AstNode* nodep, AstNUser* vup) { void width_Olhs_L_R32(AstNode* nodep, AstNUser* vup) {
// Widths: Output width from lhs, rhs<33 bits // Widths: Output width from lhs, rhs<33 bits
if (!nodep->op2p()) nodep->v3fatalSrc("For binary ops only!"); if (!nodep->op2p()) nodep->v3fatalSrc("For binary ops only!");
if (vup->c()->prelim()) { if (vup->c()->prelim()) {
@ -1363,9 +1328,9 @@ void WidthVisitor::width_Olhs_L_R32(AstNode* nodep, AstNUser* vup) {
nodep->op2p()->v3error("Unsupported: Shifting of by a over 32 bit number isn't supported." nodep->op2p()->v3error("Unsupported: Shifting of by a over 32 bit number isn't supported."
<<" (This isn't a shift of 32 bits, but a shift of 2^32, or 4 billion!)\n"); <<" (This isn't a shift of 32 bits, but a shift of 2^32, or 4 billion!)\n");
} }
} }
void WidthVisitor::width_Omax_L_Rlhs(AstNode* nodep, AstNUser* vup) { void width_Omax_L_Rlhs(AstNode* nodep, AstNUser* vup) {
// Widths: out width = lhs width = rhs width // Widths: out width = lhs width = rhs width
if (!nodep->op2p()) nodep->v3fatalSrc("For binary ops only!"); if (!nodep->op2p()) nodep->v3fatalSrc("For binary ops only!");
// If errors are off, we need to follow the spec; thus we really need to do the max() // If errors are off, we need to follow the spec; thus we really need to do the max()
@ -1396,42 +1361,21 @@ void WidthVisitor::width_Omax_L_Rlhs(AstNode* nodep, AstNUser* vup) {
widthCheck(nodep,"LHS",nodep->op1p(),width,mwidth,lhsOk); widthCheck(nodep,"LHS",nodep->op1p(),width,mwidth,lhsOk);
widthCheck(nodep,"RHS",nodep->op2p(),width,mwidth,rhsOk); widthCheck(nodep,"RHS",nodep->op2p(),width,mwidth,rhsOk);
} }
} }
//######################################################################
class WidthCommitVisitor : public AstNVisitor {
// Now that all widthing is complete,
// Copy all width() to widthMin(). V3Const expects this
private:
// VISITORS
virtual void visit(AstConst* nodep, AstNUser*) {
nodep->width(nodep->width(),nodep->width());
if ((nodep->width() != nodep->num().width()) || !nodep->num().sized()) {
V3Number num (nodep->fileline(), nodep->width());
num.opAssign(nodep->num());
num.isSigned(nodep->isSigned());
AstNode* newp = new AstConst(nodep->fileline(), num);
nodep->replaceWith(newp);
//if (debug()>4) nodep->dumpTree(cout," fixConstSize_old: ");
//if (debug()>4) newp->dumpTree(cout," _new: ");
pushDeletep(nodep); nodep=NULL;
}
}
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->width(nodep->width(),nodep->width());
nodep->iterateChildren(*this);
}
virtual void visit(AstNodePreSel* nodep, AstNUser*) {
// This check could go anywhere after V3Param
nodep->v3fatalSrc("Presels should have been removed before this point");
}
public: public:
// CONSTUCTORS // CONSTUCTORS
WidthCommitVisitor(AstNetlist* nodep) { WidthVisitor(bool paramsOnly) {
nodep->accept(*this); m_paramsOnly = paramsOnly;
m_taskDepth = 0;
m_cellRangep = NULL;
m_casep = NULL;
m_funcp = NULL;
} }
virtual ~WidthCommitVisitor() {} AstNode* mainAcceptEdit(AstNode* nodep) {
return nodep->acceptSubtreeReturnEdits(*this, WidthVP(ANYSIZE,0,BOTH).p());
}
virtual ~WidthVisitor() {}
}; };
//###################################################################### //######################################################################

72
src/V3WidthCommit.h Normal file
View File

@ -0,0 +1,72 @@
// -*- C++ -*-
//*************************************************************************
// DESCRIPTION: Verilator: Cleanup stage in V3Width
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
//
// Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//*************************************************************************
#ifndef _V3WIDTHCOMMIT_H_
#define _V3WIDTHCOMMIT_H_ 1
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
#ifndef _V3WIDTH_CPP_
# error "V3WidthCommit for V3Width internal use only"
#endif
//######################################################################
class WidthCommitVisitor : public AstNVisitor {
// Now that all widthing is complete,
// Copy all width() to widthMin(). V3Const expects this
private:
// VISITORS
virtual void visit(AstConst* nodep, AstNUser*) {
nodep->width(nodep->width(),nodep->width());
if ((nodep->width() != nodep->num().width()) || !nodep->num().sized()) {
V3Number num (nodep->fileline(), nodep->width());
num.opAssign(nodep->num());
num.isSigned(nodep->isSigned());
AstNode* newp = new AstConst(nodep->fileline(), num);
nodep->replaceWith(newp);
//if (debug()>4) nodep->dumpTree(cout," fixConstSize_old: ");
//if (debug()>4) newp->dumpTree(cout," _new: ");
pushDeletep(nodep); nodep=NULL;
}
}
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->width(nodep->width(),nodep->width());
nodep->iterateChildren(*this);
}
virtual void visit(AstNodePreSel* nodep, AstNUser*) {
// This check could go anywhere after V3Param
nodep->v3fatalSrc("Presels should have been removed before this point");
}
public:
// CONSTUCTORS
WidthCommitVisitor(AstNetlist* nodep) {
nodep->accept(*this);
}
virtual ~WidthCommitVisitor() {}
};
//######################################################################
#endif // Guard