Re-fix bug729 due to bug733; other internal sign extension cleanups too.

This commit is contained in:
Wilson Snyder 2014-04-07 21:34:00 -04:00
parent 14fcfd8a40
commit 5c39420d91
5 changed files with 189 additions and 64 deletions

View File

@ -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]

View File

@ -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) {

View File

@ -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)

View File

@ -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;

View File

@ -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