Re-fix bug729 due to bug733; other internal sign extension cleanups too.
This commit is contained in:
parent
14fcfd8a40
commit
5c39420d91
2
Changes
2
Changes
|
|
@ -25,7 +25,7 @@ indicates the contributor was also the author of the fix; Thanks!
|
|||
|
||||
**** Fix modport function import not-found error.
|
||||
|
||||
**** Fix signed extension problem with -Wno-WIDTH, bug729. [Clifford Wolf]
|
||||
**** Fix signed extension problems with -Wno-WIDTH, bug729. [Clifford Wolf]
|
||||
|
||||
**** Fix power operator calculation, bug730. [Clifford Wolf]
|
||||
|
||||
|
|
|
|||
136
src/V3Width.cpp
136
src/V3Width.cpp
|
|
@ -103,6 +103,7 @@ public:
|
|||
AstNodeDType* dtypep() const { return m_dtypep; }
|
||||
bool prelim() const { return m_stage&1; }
|
||||
bool final() const { return m_stage&2; }
|
||||
bool isSelfDetermined() const { return m_dtypep == NULL; } // i.e. made with ANYSIZE
|
||||
char stageAscii() const { return "-PFB"[m_stage]; }
|
||||
};
|
||||
ostream& operator<<(ostream& str, const WidthVP* vup) {
|
||||
|
|
@ -123,6 +124,13 @@ private:
|
|||
bool m_doGenerate; // Do errors later inside generate statement
|
||||
int m_dtTables; // Number of created data type tables
|
||||
|
||||
// ENUMS
|
||||
enum ExtendRule {
|
||||
EXTEND_EXP, // Extend if expect sign and node signed, e.g. where node=x/y in "x + y"
|
||||
EXTEND_ZERO, // Extend with zeros. e.g. node=x/y in "$signed(x) == $unsigned(y)"
|
||||
EXTEND_LHS // Extend with sign if node signed. e.g. node=x/y in "$signed(x) == $signed(y)"
|
||||
};
|
||||
|
||||
// CLASSES
|
||||
#define ANYSIZE 0
|
||||
|
||||
|
|
@ -295,8 +303,8 @@ private:
|
|||
nodep->expr2p()->iterateAndNext(*this,WidthVP(subDTypep,FINAL).p());
|
||||
// Error report and change sizes for suboperands of this node.
|
||||
widthCheckReduce(nodep,"Conditional Test",nodep->condp());
|
||||
widthCheck(nodep,"Conditional True",nodep->expr1p(),subDTypep);
|
||||
widthCheck(nodep,"Conditional False",nodep->expr2p(),subDTypep);
|
||||
widthCheck(nodep,"Conditional True",nodep->expr1p(),subDTypep,EXTEND_EXP);
|
||||
widthCheck(nodep,"Conditional False",nodep->expr2p(),subDTypep,EXTEND_EXP);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstConcat* nodep, AstNUser* vup) {
|
||||
|
|
@ -427,7 +435,7 @@ private:
|
|||
<<" bits from only "<<nodep->fromp()->width()<<" bit number");
|
||||
// Extend it.
|
||||
AstNodeDType* subDTypep = nodep->findLogicDType(width,width,nodep->fromp()->dtypep()->numeric());
|
||||
widthCheck(nodep,"errorless...",nodep->fromp(),subDTypep,true/*noerror*/);
|
||||
widthCheck(nodep,"errorless...",nodep->fromp(),subDTypep,EXTEND_EXP,true/*noerror*/);
|
||||
}
|
||||
// Check bit indexes.
|
||||
// What is the MSB? We want the true MSB, not one starting at 0,
|
||||
|
|
@ -482,7 +490,7 @@ private:
|
|||
if (!m_doGenerate) {
|
||||
AstNodeDType* subDTypep = nodep->findLogicDType(selwidth, selwidth,
|
||||
nodep->lsbp()->dtypep()->numeric());
|
||||
widthCheck(nodep,"Extract Range",nodep->lsbp(),subDTypep,true);
|
||||
widthCheck(nodep,"Extract Range",nodep->lsbp(),subDTypep,EXTEND_EXP,true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -529,7 +537,7 @@ private:
|
|||
UINFO(1," Related dtype: "<<nodep->dtypep()<<endl);
|
||||
}
|
||||
}
|
||||
widthCheck(nodep,"Extract Range",nodep->bitp(),selDTypep,true);
|
||||
widthCheck(nodep,"Extract Range",nodep->bitp(),selDTypep,EXTEND_EXP,true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -629,7 +637,7 @@ private:
|
|||
nodep->lhsp()->iterateAndNext(*this,WidthVP(width,ewidth,FINAL).p());
|
||||
// rhs already finalized in shift_prelim
|
||||
nodep->dtypeChgSigned(nodep->lhsp()->isSigned());
|
||||
widthCheck(nodep,"LHS",nodep->lhsp(),nodep->dtypep());
|
||||
widthCheck(nodep,"LHS",nodep->lhsp(),nodep->dtypep(),EXTEND_EXP);
|
||||
AstNode* newp = NULL; // No change
|
||||
if (nodep->lhsp()->isSigned() && nodep->rhsp()->isSigned()) {
|
||||
newp = new AstPowSS (nodep->fileline(), nodep->lhsp()->unlinkFrBack(),
|
||||
|
|
@ -811,7 +819,7 @@ private:
|
|||
// Note widthCheck might modify nodep->lhsp()
|
||||
AstNodeDType* subDTypep = nodep->findLogicDType(nodep->width(),nodep->width(),
|
||||
nodep->lhsp()->dtypep()->numeric());
|
||||
widthCheck(nodep,"Cast",nodep->lhsp(),subDTypep,true);
|
||||
widthCheck(nodep,"Cast",nodep->lhsp(),subDTypep,EXTEND_EXP,true);
|
||||
}
|
||||
AstNode* newp = nodep->lhsp()->unlinkFrBack();
|
||||
if (basicp->isDouble() && !newp->isDouble()) {
|
||||
|
|
@ -852,7 +860,7 @@ private:
|
|||
AstNode* underp = nodep->lhsp()->unlinkFrBack();
|
||||
nodep->replaceWith(underp);
|
||||
if (underp->width()!=width) {
|
||||
fixWidthExtend(underp, newDtp);
|
||||
fixWidthExtend(underp, newDtp, EXTEND_EXP);
|
||||
}
|
||||
pushDeletep(nodep); nodep=NULL;
|
||||
}
|
||||
|
|
@ -942,10 +950,7 @@ private:
|
|||
//if (debug()) nodep->dumpTree(cout," final: ");
|
||||
if (!didchk) nodep->valuep()->iterateAndNext(*this,WidthVP(nodep->dtypep(),BOTH).p());
|
||||
if (!nodep->valuep()->castInitArray()) { // No dtype at present, perhaps TODO
|
||||
widthCheck(nodep,"Initial value",nodep->valuep(),nodep->dtypep());
|
||||
}
|
||||
if (nodep->isDouble() && !nodep->valuep()->isDouble()) {
|
||||
spliceCvtD(nodep->valuep());
|
||||
widthCheck(nodep,"Initial value",nodep->valuep(),nodep->dtypep(),EXTEND_EXP);
|
||||
}
|
||||
}
|
||||
UINFO(4,"varWidthed "<<nodep<<endl);
|
||||
|
|
@ -1032,7 +1037,7 @@ private:
|
|||
nodep->valuep()->iterateAndNext(*this,WidthVP(width,0,BOTH).p());
|
||||
int mwidth = nodep->valuep()->widthMin(); // Value determines minwidth
|
||||
nodep->dtypeChgWidth(width, mwidth);
|
||||
widthCheck(nodep,"Enum value",nodep->valuep(),nodep->dtypep());
|
||||
widthCheck(nodep,"Enum value",nodep->valuep(),nodep->dtypep(),EXTEND_EXP);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstEnumItemRef* nodep, AstNUser* vup) {
|
||||
|
|
@ -1076,9 +1081,9 @@ private:
|
|||
nodep->exprp()->iterateAndNext(*this,WidthVP(width,mwidth,FINAL).p());
|
||||
AstNodeDType* subDTypep = nodep->findLogicDType(width,mwidth,nodep->exprp()->dtypep()->numeric());
|
||||
for (AstNode* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()) {
|
||||
widthCheck(nodep,"Inside Item",itemp,subDTypep);
|
||||
widthCheck(nodep,"Inside Item",itemp,subDTypep,EXTEND_EXP);
|
||||
}
|
||||
widthCheck(nodep,"Inside expression",nodep->exprp(),subDTypep);
|
||||
widthCheck(nodep,"Inside expression",nodep->exprp(),subDTypep,EXTEND_EXP);
|
||||
nodep->dtypeSetLogicBool();
|
||||
if (debug()>=9) nodep->dumpTree(cout,"-inside-in: ");
|
||||
// Now rip out the inside and replace with simple math
|
||||
|
|
@ -1422,7 +1427,7 @@ private:
|
|||
if (nodep->lhssp()->nextp()) nodep->v3fatalSrc("PatMember value should be singular w/replicates removed");
|
||||
nodep->lhssp()->dtypeFrom(nodep);
|
||||
nodep->iterateChildren(*this,WidthVP(nodep->dtypep(),BOTH).p());
|
||||
widthCheck(nodep,"Value",nodep->lhssp(),vdtypep);
|
||||
widthCheck(nodep,"Value",nodep->lhssp(),vdtypep,EXTEND_EXP);
|
||||
}
|
||||
int visitPatMemberRep(AstPatMember* nodep) {
|
||||
uint32_t times = 1;
|
||||
|
|
@ -1479,10 +1484,10 @@ private:
|
|||
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
||||
for (AstNode* condp = itemp->condsp(); condp; condp=condp->nextp()) {
|
||||
condp->iterate(*this,WidthVP(subDTypep,FINAL).p());
|
||||
widthCheck(nodep,"Case Item",condp,subDTypep);
|
||||
widthCheck(nodep,"Case Item",condp,subDTypep,EXTEND_EXP);
|
||||
}
|
||||
}
|
||||
widthCheck(nodep,"Case expression",nodep->exprp(),subDTypep);
|
||||
widthCheck(nodep,"Case expression",nodep->exprp(),subDTypep,EXTEND_EXP);
|
||||
}
|
||||
virtual void visit(AstNodeFor* nodep, AstNUser*) {
|
||||
// TOP LEVEL NODE
|
||||
|
|
@ -1542,7 +1547,8 @@ private:
|
|||
// it using the normal width reduction checks.
|
||||
//UINFO(0,"aw "<<awidth<<" w"<<nodep->rhsp()->width()<<" m"<<nodep->rhsp()->widthMin()<<endl);
|
||||
AstNodeDType* subDTypep = nodep->dtypep();
|
||||
widthCheck(nodep,"Assign RHS",nodep->rhsp(),subDTypep);
|
||||
// Note assignments do not look at the LHS's sign, extend based on right only
|
||||
widthCheck(nodep,"Assign RHS",nodep->rhsp(),subDTypep,EXTEND_LHS);
|
||||
//if (debug()) nodep->dumpTree(cout," AssignOut: ");
|
||||
}
|
||||
}
|
||||
|
|
@ -1892,7 +1898,7 @@ private:
|
|||
// (get an ASSIGN with EXTEND on the lhs instead of rhs)
|
||||
}
|
||||
if (portp->basicp() && !portp->basicp()->isOpaque()) {
|
||||
widthCheck(nodep,"Function Argument",pinp,portp->dtypep());
|
||||
widthCheck(nodep,"Function Argument",pinp,portp->dtypep(),EXTEND_EXP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1933,7 +1939,7 @@ private:
|
|||
checkCvtUS(nodep->lhsp());
|
||||
nodep->dtypeSetDouble();
|
||||
AstNodeDType* subDTypep = nodep->findLogicDType(64,64, nodep->lhsp()->dtypep()->numeric());
|
||||
widthCheck(nodep,"LHS",nodep->lhsp(),subDTypep);
|
||||
widthCheck(nodep,"LHS",nodep->lhsp(),subDTypep,EXTEND_EXP);
|
||||
}
|
||||
}
|
||||
void visit_Or_Ls32(AstNodeUniop* nodep, AstNUser* vup) {
|
||||
|
|
@ -1944,7 +1950,7 @@ private:
|
|||
checkCvtUS(nodep->lhsp());
|
||||
nodep->dtypeSetDouble();
|
||||
AstNodeDType* subDTypep = nodep->findLogicDType(32,32, nodep->lhsp()->dtypep()->numeric());
|
||||
widthCheck(nodep,"LHS",nodep->lhsp(),subDTypep);
|
||||
widthCheck(nodep,"LHS",nodep->lhsp(),subDTypep,EXTEND_EXP);
|
||||
}
|
||||
}
|
||||
void visit_Os32_Lr(AstNodeUniop* nodep, AstNUser* vup) {
|
||||
|
|
@ -2016,10 +2022,12 @@ private:
|
|||
// Widths: 1 bit out, lhs width == rhs width
|
||||
// Signed: if RHS&LHS signed, OPERATOR CHANGES to signed flavor
|
||||
// Real: allowed on RHS, if RHS|LHS is real, both become real, and OPERATOR CHANGES
|
||||
// IEEE, 11.4.4: relational compares (<,>,<=,>=,==,===,!=,!==) use "zero padding" on unsigned
|
||||
if (vup->c()->prelim()) {
|
||||
nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,PRELIM).p());
|
||||
nodep->rhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,PRELIM).p());
|
||||
}
|
||||
bool signedFl = nodep->lhsp()->isSigned() && nodep->rhsp()->isSigned();
|
||||
if (nodep->lhsp()->isDouble() || nodep->rhsp()->isDouble()) {
|
||||
spliceCvtD(nodep->lhsp());
|
||||
spliceCvtD(nodep->rhsp());
|
||||
|
|
@ -2027,7 +2035,6 @@ private:
|
|||
nodep = newp; // Process new node instead
|
||||
}
|
||||
} else {
|
||||
bool signedFl = nodep->lhsp()->isSigned() && nodep->rhsp()->isSigned();
|
||||
if (AstNodeBiop* newp=replaceWithUOrSVersion(nodep, signedFl)) { nodep=NULL;
|
||||
nodep = newp; // Process new node instead
|
||||
}
|
||||
|
|
@ -2036,12 +2043,12 @@ private:
|
|||
int width = max(nodep->lhsp()->width(), nodep->rhsp()->width());
|
||||
int ewidth = max(nodep->lhsp()->widthMin(), nodep->rhsp()->widthMin());
|
||||
AstNodeDType* subDTypep = nodep->findLogicDType(width, ewidth,
|
||||
AstNumeric::fromBool(nodep->signedFlavor()));
|
||||
AstNumeric::fromBool(signedFl));
|
||||
if (vup->c()->final()) {
|
||||
nodep->lhsp()->iterateAndNext(*this,WidthVP(subDTypep,FINAL).p());
|
||||
nodep->rhsp()->iterateAndNext(*this,WidthVP(subDTypep,FINAL).p());
|
||||
widthCheck(nodep, "LHS", nodep->lhsp(), subDTypep);
|
||||
widthCheck(nodep, "RHS", nodep->rhsp(), subDTypep);
|
||||
widthCheck(nodep,"LHS",nodep->lhsp(),subDTypep,signedFl?EXTEND_LHS:EXTEND_ZERO);
|
||||
widthCheck(nodep,"RHS",nodep->rhsp(),subDTypep,signedFl?EXTEND_LHS:EXTEND_ZERO);
|
||||
}
|
||||
}
|
||||
void visit_cmp_O1_LRrus(AstNodeBiop* nodep, AstNUser* vup, bool real_lhs) {
|
||||
|
|
@ -2050,6 +2057,7 @@ private:
|
|||
// Widths: 1 bit out, lhs width == rhs width
|
||||
// Signed compare (not output) if both sides signed
|
||||
// Real if and only if real_lhs set
|
||||
// IEEE, 11.4.4: relational compares (<,>,<=,>=,==,===,!=,!==) use "zero padding" on unsigned
|
||||
if (!nodep->rhsp()) nodep->v3fatalSrc("For binary ops only!");
|
||||
if (vup->c()->prelim()) {
|
||||
nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,PRELIM).p());
|
||||
|
|
@ -2071,8 +2079,8 @@ private:
|
|||
if (vup->c()->final()) {
|
||||
nodep->lhsp()->iterateAndNext(*this,WidthVP(subDTypep,FINAL).p());
|
||||
nodep->rhsp()->iterateAndNext(*this,WidthVP(subDTypep,FINAL).p());
|
||||
widthCheck(nodep,"LHS",nodep->lhsp(),subDTypep);
|
||||
widthCheck(nodep,"RHS",nodep->rhsp(),subDTypep);
|
||||
widthCheck(nodep,"LHS",nodep->lhsp(),subDTypep,signedFl?EXTEND_LHS:EXTEND_ZERO);
|
||||
widthCheck(nodep,"RHS",nodep->rhsp(),subDTypep,signedFl?EXTEND_LHS:EXTEND_ZERO);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2105,25 +2113,28 @@ private:
|
|||
AstNodeDType* subDTypep = nodep->dtypep();
|
||||
if (vup->c()->final()) {
|
||||
nodep->lhsp()->iterateAndNext(*this,WidthVP(subDTypep,FINAL).p());
|
||||
widthCheck(nodep,"LHS",nodep->lhsp(),subDTypep);
|
||||
widthCheck(nodep,"LHS",nodep->lhsp(),subDTypep,EXTEND_EXP);
|
||||
}
|
||||
}
|
||||
|
||||
void visit_Ous_Lus_Wforce(AstNodeUniop* nodep, AstNUser* vup, AstNumeric rs_out) {
|
||||
// CALLER: Signed, Unsigned
|
||||
// Widths: lhs is self determined width
|
||||
// Output though still may require extension
|
||||
// See IEEE-2012 6.24.1 "returns packed array, of size $bits(expression),
|
||||
// bit if expression is 2-state, otherwise type logic."
|
||||
if (nodep->op2p()) nodep->v3fatalSrc("For unary ops only!");
|
||||
if (vup->c()->prelim()) {
|
||||
nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,PRELIM).p());
|
||||
checkCvtUS(nodep->lhsp());
|
||||
}
|
||||
int width = nodep->lhsp()->width();
|
||||
int ewidth = nodep->lhsp()->width(); // Not widthMin; force it.
|
||||
nodep->dtypeSetLogicSized(width,ewidth,rs_out);
|
||||
int width = nodep->lhsp()->width();
|
||||
nodep->dtypeSetLogicSized(width,width,rs_out);
|
||||
if (vup->c()->final()) {
|
||||
// Final call, so make sure children check their sizes
|
||||
nodep->lhsp()->iterateAndNext(*this,WidthVP(width,ewidth,FINAL).p());
|
||||
// The child's width is self determined
|
||||
AstNodeDType* subDTypep = nodep->dtypep();
|
||||
nodep->lhsp()->iterateAndNext(*this,WidthVP(subDTypep,FINAL).p());
|
||||
// Now extend
|
||||
widthCheck(nodep,"LHS",nodep->lhsp(),subDTypep,EXTEND_EXP);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2161,7 +2172,7 @@ private:
|
|||
nodep->lhsp()->iterateAndNext(*this,WidthVP(width,ewidth,FINAL).p());
|
||||
AstNodeDType* sublhsDTypep = nodep->findLogicDType(width, ewidth,
|
||||
nodep->lhsp()->dtypep()->numeric());
|
||||
widthCheck(nodep,"LHS",nodep->lhsp(),sublhsDTypep);
|
||||
widthCheck(nodep,"LHS",nodep->lhsp(),sublhsDTypep,EXTEND_EXP);
|
||||
if (nodep->rhsp()->width()>32) {
|
||||
AstConst* shiftp = nodep->rhsp()->castConst();
|
||||
if (shiftp && shiftp->num().mostSetBitP1() <= 32) {
|
||||
|
|
@ -2214,8 +2225,8 @@ private:
|
|||
rhsOk = (mwidth >= (nodep->rhsp()->widthMin()));
|
||||
}
|
||||
// Error report and change sizes for suboperands of this node.
|
||||
widthCheck(nodep,"LHS",nodep->lhsp(),subDTypep,lhsOk);
|
||||
widthCheck(nodep,"RHS",nodep->rhsp(),subDTypep,rhsOk);
|
||||
widthCheck(nodep,"LHS",nodep->lhsp(),subDTypep,EXTEND_EXP,lhsOk);
|
||||
widthCheck(nodep,"RHS",nodep->rhsp(),subDTypep,EXTEND_EXP,rhsOk);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2270,8 +2281,8 @@ private:
|
|||
rhsOk = (mwidth >= (nodep->rhsp()->widthMin()));
|
||||
}
|
||||
// Error report and change sizes for suboperands of this node.
|
||||
widthCheck(nodep,"LHS",nodep->lhsp(),nodep->dtypep(),lhsOk);
|
||||
widthCheck(nodep,"RHS",nodep->rhsp(),nodep->dtypep(),rhsOk);
|
||||
widthCheck(nodep,"LHS",nodep->lhsp(),nodep->dtypep(),EXTEND_EXP,lhsOk);
|
||||
widthCheck(nodep,"RHS",nodep->rhsp(),nodep->dtypep(),EXTEND_EXP,rhsOk);
|
||||
}
|
||||
//if (debug()>=9) nodep->dumpTree(cout,"-rusou-");
|
||||
}
|
||||
|
|
@ -2307,16 +2318,20 @@ private:
|
|||
return false;
|
||||
}
|
||||
|
||||
void fixWidthExtend (AstNode* nodep, AstNodeDType* expDTypep) {
|
||||
void fixWidthExtend (AstNode* nodep, AstNodeDType* expDTypep, ExtendRule extendRule) {
|
||||
// Fix the width mismatch by extending or truncating bits
|
||||
// Truncation is rarer, but can occur: parameter [3:0] FOO = 64'h12312;
|
||||
// A(CONSTwide)+B becomes A(CONSTwidened)+B
|
||||
// A(somewide)+B becomes A(TRUNC(somewide,width))+B
|
||||
// or A(EXTRACT(somewide,width,0))+B
|
||||
UINFO(4," widthExtend_old: "<<nodep<<endl);
|
||||
// Sign extension depends on the type of the *present*
|
||||
// node, while the output dtype is the *expected* sign.
|
||||
// It is reasonable to have sign extension with unsigned output,
|
||||
// for example $unsigned(a)+$signed(b), the SIGNED(B) will be unsigned dtype out
|
||||
UINFO(4," widthExtend_(r="<<extendRule<<") old: "<<nodep<<endl);
|
||||
AstConst* constp = nodep->castConst();
|
||||
int expWidth = expDTypep->width();
|
||||
if (constp && !expDTypep->isSigned()) {
|
||||
if (constp && !nodep->isSigned()) {
|
||||
// Save later constant propagation work, just right-size it.
|
||||
V3Number num (nodep->fileline(), expWidth);
|
||||
num.opAssign(constp->num());
|
||||
|
|
@ -2336,13 +2351,26 @@ private:
|
|||
// Extend
|
||||
AstNRelinker linker;
|
||||
nodep->unlinkFrBack(&linker);
|
||||
AstNode* newp = ((expDTypep->isSigned() && nodep->isSigned())
|
||||
bool doSigned;
|
||||
switch (extendRule) {
|
||||
case EXTEND_ZERO: doSigned = false; break;
|
||||
case EXTEND_EXP: doSigned = nodep->isSigned() && expDTypep->isSigned(); break;
|
||||
case EXTEND_LHS: doSigned = nodep->isSigned(); break;
|
||||
default: nodep->v3fatalSrc("bad case");
|
||||
}
|
||||
AstNode* newp = (doSigned
|
||||
? (new AstExtendS(nodep->fileline(), nodep))->castNode()
|
||||
: (new AstExtend (nodep->fileline(), nodep))->castNode());
|
||||
linker.relink(newp);
|
||||
nodep=newp;
|
||||
}
|
||||
nodep->dtypeChgWidth(expWidth,expWidth);
|
||||
if (expDTypep->isDouble() && !nodep->isDouble()) {
|
||||
// For AstVar init() among others
|
||||
// TODO do all to-real and to-integer conversions in this function rather than in callers
|
||||
AstNode* newp = spliceCvtD(nodep);
|
||||
nodep = newp;
|
||||
}
|
||||
nodep->dtypeFrom(expDTypep);
|
||||
UINFO(4," _new: "<<nodep<<endl);
|
||||
}
|
||||
|
||||
|
|
@ -2398,16 +2426,11 @@ private:
|
|||
|
||||
void widthCheckFileDesc (AstNode* nodep, AstNode* underp) {
|
||||
AstNodeDType* expDTypep = underp->findUInt32DType();
|
||||
widthCheck(nodep,"file_descriptor",underp,expDTypep,false);
|
||||
}
|
||||
void widthCheck (AstNode* nodep, const char* side,
|
||||
AstNode* underp, int expWidth, int expWidthMin,
|
||||
bool ignoreWarn=false) {
|
||||
AstNodeDType* expDTypep = underp->findLogicDType(expWidth, expWidthMin, underp->dtypep()->numeric());
|
||||
widthCheck(nodep,side,underp,expDTypep,ignoreWarn);
|
||||
widthCheck(nodep,"file_descriptor",underp,expDTypep,EXTEND_EXP,false);
|
||||
}
|
||||
void widthCheck (AstNode* nodep, const char* side,
|
||||
AstNode* underp, AstNodeDType* expDTypep,
|
||||
ExtendRule extendRule,
|
||||
bool ignoreWarn=false) {
|
||||
//UINFO(9,"wchk "<<side<<endl<<" "<<nodep<<endl<<" "<<underp<<endl<<" e="<<expDTypep<<" i"<<ignoreWarn<<endl);
|
||||
int expWidth = expDTypep->width();
|
||||
|
|
@ -2444,7 +2467,7 @@ private:
|
|||
<<" bits.");
|
||||
}
|
||||
if (bad || underp->width()!=expWidth) {
|
||||
fixWidthExtend(underp, expDTypep); underp=NULL;//Changed
|
||||
fixWidthExtend(underp, expDTypep, extendRule); underp=NULL;//Changed
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2488,7 +2511,7 @@ private:
|
|||
}
|
||||
// We only fix input mismatches
|
||||
if (bad && inputPin) {
|
||||
fixWidthExtend(underp, expDTypep); underp=NULL;//Changed
|
||||
fixWidthExtend(underp, expDTypep, EXTEND_EXP); underp=NULL;//Changed
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2519,7 +2542,7 @@ private:
|
|||
linker.relink(newp);
|
||||
}
|
||||
}
|
||||
void spliceCvtD(AstNode* nodep) {
|
||||
AstNode* spliceCvtD(AstNode* nodep) {
|
||||
// For integer used in REAL context, convert to real
|
||||
// We don't warn here, "2.0 * 2" is common and reasonable
|
||||
if (nodep && !nodep->isDouble()) {
|
||||
|
|
@ -2528,6 +2551,9 @@ private:
|
|||
nodep->unlinkFrBack(&linker);
|
||||
AstNode* newp = new AstIToRD(nodep->fileline(), nodep);
|
||||
linker.relink(newp);
|
||||
return newp;
|
||||
} else {
|
||||
return nodep;
|
||||
}
|
||||
}
|
||||
void spliceCvtS(AstNode* nodep, bool ignoreWarn) {
|
||||
|
|
|
|||
|
|
@ -16,14 +16,6 @@ module t (/*AUTOARG*/
|
|||
reg signed[7:0] delay_minmax[31:0];
|
||||
integer k;
|
||||
|
||||
wire [1:0] bug729_a = ~0;
|
||||
wire [2:0] bug729_b = ~0;
|
||||
// verilator lint_off WIDTH
|
||||
// the $signed becomes EXTEND(SIGNED(bug729_a)), not EXTENDS because the == is unsigned
|
||||
wire [0:0] bug729_y = $signed(bug729_a) == bug729_b;
|
||||
// verilator lint_on WIDTH
|
||||
initial if (bug729_y) $stop;
|
||||
|
||||
initial begin
|
||||
in = 11'b10000001000;
|
||||
for(k=0;k<32;k=k+1)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 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.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0)
|
||||
|
||||
module t (/*AUTOARG*/);
|
||||
|
||||
// verilator lint_off WIDTH
|
||||
wire [1:0] bug729_au = ~0;
|
||||
wire signed [1:0] bug729_as = ~0;
|
||||
wire [2:0] bug729_b = ~0;
|
||||
// the $signed output is unsigned because the input is unsigned; the signedness does not change.
|
||||
// See IEEE-2012 6.24.1 "The signedness shall pass through unchanged".
|
||||
wire [0:0] bug729_yuu = $signed(2'b11) == 3'b111; //1'b0
|
||||
wire [0:0] bug729_ysu = $signed(2'sb11) == 3'b111; //1'b0
|
||||
wire [0:0] bug729_yus = $signed(2'b11) == 3'sb111; //1'b1
|
||||
wire [0:0] bug729_yss = $signed(2'sb11) == 3'sb111; //1'b1
|
||||
wire [0:0] bug729_zuu = 2'sb11 == 3'b111; //1'b0
|
||||
wire [0:0] bug729_zsu = 2'sb11 == 3'b111; //1'b0
|
||||
wire [0:0] bug729_zus = 2'sb11 == 3'sb111; //1'b1
|
||||
wire [0:0] bug729_zss = 2'sb11 == 3'sb111; //1'b1
|
||||
|
||||
wire [3:0] bug733_a = 4'b0010;
|
||||
wire [3:0] bug733_yu = $signed(|bug733_a); // 4'b1111 note | is always unsigned
|
||||
wire signed [3:0] bug733_ys = $signed(|bug733_a); // 4'b1111
|
||||
|
||||
wire [3:0] bug733_zu = $signed(2'b11); // 4'b1111
|
||||
wire signed [3:0] bug733_zs = $signed(2'sb11); // 4'b1111
|
||||
|
||||
// When RHS of assignment is fewer bits than lhs, RHS sign or zero extends based on RHS's sign
|
||||
|
||||
wire [3:0] bug733_qu = 2'sb11; // 4'b1111
|
||||
wire signed [3:0] bug733_qs = 2'sb11; // 4'b1111
|
||||
reg signed [32:0] bug349_s;
|
||||
reg signed [32:0] bug349_u;
|
||||
|
||||
wire [3:0] subout_u;
|
||||
sub sub (.a(2'sb11), .z(subout_u));
|
||||
initial `checkh(subout_u, 4'b1111);
|
||||
|
||||
wire [5:0] cond_a = 1'b1 ? 3'sb111 : 5'sb11111;
|
||||
initial `checkh(cond_a, 6'b111111);
|
||||
wire [5:0] cond_b = 1'b0 ? 3'sb111 : 5'sb11111;
|
||||
initial `checkh(cond_b, 6'b111111);
|
||||
|
||||
initial begin
|
||||
// verilator lint_on WIDTH
|
||||
`checkh(bug729_yuu, 1'b0);
|
||||
`checkh(bug729_ysu, 1'b0);
|
||||
`checkh(bug729_yus, 1'b1);
|
||||
`checkh(bug729_yss, 1'b1);
|
||||
|
||||
`checkh(bug729_zuu, 1'b0);
|
||||
`checkh(bug729_zsu, 1'b0);
|
||||
`checkh(bug729_zus, 1'b1);
|
||||
`checkh(bug729_zss, 1'b1);
|
||||
|
||||
`checkh(bug733_yu, 4'b1111);
|
||||
`checkh(bug733_ys, 4'b1111);
|
||||
|
||||
`checkh(bug733_zu, 4'b1111);
|
||||
`checkh(bug733_zs, 4'b1111);
|
||||
|
||||
`checkh(bug733_qu, 4'b1111);
|
||||
`checkh(bug733_qs, 4'b1111);
|
||||
|
||||
// verilator lint_off WIDTH
|
||||
bug349_s = 4'sb1111;
|
||||
`checkh(bug349_s, 33'h1ffffffff);
|
||||
bug349_u = 4'sb1111;
|
||||
`checkh(bug349_u, 33'h1ffffffff);
|
||||
|
||||
bug349_s = 4'sb1111 - 1'b1;
|
||||
`checkh(bug349_s,33'he);
|
||||
|
||||
bug349_s = 4'sb1111 - 5'b00001;
|
||||
`checkh(bug349_s,33'he);
|
||||
|
||||
case (2'sb11)
|
||||
4'b1111: ;
|
||||
default: $stop;
|
||||
endcase
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
|
||||
module sub (input [3:0] a,
|
||||
output [3:0] z);
|
||||
assign z = a;
|
||||
endmodule
|
||||
Loading…
Reference in New Issue