forked from github/verilator
Fix width propagation on sized casts, bug925.
This commit is contained in:
parent
491539ff32
commit
9e61b9f696
2
Changes
2
Changes
@ -23,6 +23,8 @@ indicates the contributor was also the author of the fix; Thanks!
|
||||
|
||||
**** Fix width extension on mis-width ports, bug918. [Patrick Maupin]
|
||||
|
||||
**** Fix width propagation on sized casts, bug925. [Jonathon Donaldson]
|
||||
|
||||
**** Fix MSVC++ compiler error, bug927. [Hans Tichelaar]
|
||||
|
||||
|
||||
|
@ -1009,8 +1009,10 @@ private:
|
||||
//if (debug()) newp->dumpTree(cout," CastOut: ");
|
||||
}
|
||||
virtual void visit(AstCastSize* nodep, AstNUser* vup) {
|
||||
// IEEE: Signedness of result is same as self-determined signedness
|
||||
// However, the result is same as BITSEL, so we do not sign extend the LHS
|
||||
if (!nodep->rhsp()->castConst()) nodep->v3fatalSrc("Unsupported: Non-const cast of size");
|
||||
//if (debug()) nodep->dumpTree(cout," CastPre: ");
|
||||
//if (debug()) nodep->dumpTree(cout," CastSizePre: ");
|
||||
if (vup->c()->prelim()) {
|
||||
int width = nodep->rhsp()->castConst()->toSInt();
|
||||
if (width < 1) { nodep->v3error("Size-changing cast to zero or negative size"); width=1; }
|
||||
@ -1020,12 +1022,29 @@ private:
|
||||
nodep->v3error("Unsupported: Size-changing cast on non-basic data type");
|
||||
underDtp = nodep->findLogicBoolDType()->castBasicDType();
|
||||
}
|
||||
AstNodeDType* newDtp = (underDtp->keyword().isFourstate()
|
||||
? nodep->findLogicDType(width, width, underDtp->numeric())
|
||||
: nodep->findBitDType(width, width, underDtp->numeric()));
|
||||
nodep->dtypep(newDtp);
|
||||
// We ignore warnings as that is sort of the point of a cast
|
||||
iterateCheck(nodep,"Cast LHS",nodep->lhsp(),CONTEXT,FINAL,newDtp,EXTEND_EXP,false);
|
||||
// A cast propagates its size to the lower expression and is included in the maximum
|
||||
// width, so 23'(1'b1 + 1'b1) uses 23-bit math, but 1'(2'h2 * 2'h1) uses two-bit math.
|
||||
// However the output width is exactly that requested.
|
||||
// So two steps, first do the calculation's width (max of the two widths)
|
||||
{
|
||||
int calcWidth = max(width, underDtp->width());
|
||||
AstNodeDType* calcDtp = (underDtp->keyword().isFourstate()
|
||||
? nodep->findLogicDType(calcWidth, calcWidth, underDtp->numeric())
|
||||
: nodep->findBitDType(calcWidth, calcWidth, underDtp->numeric()));
|
||||
nodep->dtypep(calcDtp);
|
||||
// We ignore warnings as that is sort of the point of a cast
|
||||
iterateCheck(nodep,"Cast expr",nodep->lhsp(),CONTEXT,FINAL,calcDtp,EXTEND_EXP,false);
|
||||
}
|
||||
if (debug()) nodep->dumpTree(cout," CastSizeClc: ");
|
||||
// Next step, make the proper output width
|
||||
{
|
||||
AstNodeDType* outDtp = (underDtp->keyword().isFourstate()
|
||||
? nodep->findLogicDType(width, width, underDtp->numeric())
|
||||
: nodep->findBitDType(width, width, underDtp->numeric()));
|
||||
nodep->dtypep(outDtp);
|
||||
// We ignore warnings as that is sort of the point of a cast
|
||||
widthCheckSized(nodep,"Cast expr",nodep->lhsp(),outDtp,EXTEND_EXP,false);
|
||||
}
|
||||
}
|
||||
if (vup->c()->final()) {
|
||||
// CastSize not needed once sizes determined
|
||||
@ -1033,6 +1052,7 @@ private:
|
||||
nodep->replaceWith(underp);
|
||||
pushDeletep(nodep); nodep=NULL;
|
||||
}
|
||||
//if (debug()) nodep->dumpTree(cout," CastSizeOut: ");
|
||||
}
|
||||
virtual void visit(AstVar* nodep, AstNUser* vup) {
|
||||
//if (debug()) nodep->dumpTree(cout," InitPre: ");
|
||||
|
@ -13,6 +13,23 @@ module t;
|
||||
logic [15:0] allones = 16'hffff;
|
||||
parameter FOUR = 4;
|
||||
|
||||
// bug925
|
||||
localparam [6:0] RESULT = 7'((6*9+92)%96);
|
||||
|
||||
logic signed [14:0] samp0 = 15'h0000;
|
||||
logic signed [14:0] samp1 = 15'h0000;
|
||||
logic signed [14:0] samp2 = 15'h6000;
|
||||
logic signed [11:0] coeff0 = 12'h009;
|
||||
logic signed [11:0] coeff1 = 12'h280;
|
||||
logic signed [11:0] coeff2 = 12'h4C5;
|
||||
logic signed [26:0] mida = ((27'(coeff2 * samp2) >>> 11));
|
||||
// verilator lint_off WIDTH
|
||||
logic signed [26:0] midb = 15'((27'(coeff2 * samp2) >>> 11));
|
||||
// verilator lint_on WIDTH
|
||||
logic signed [14:0] outa = 15'((27'(coeff0 * samp0) >>> 11) + // 27' size casting in order for intermediate result to not be truncated to the width of LHS vector
|
||||
(27'(coeff1 * samp1) >>> 11) +
|
||||
(27'(coeff2 * samp2) >>> 11)); // 15' size casting to avoid synthesis/simulator warnings
|
||||
|
||||
initial begin
|
||||
if (4'shf > 4'sh0) $stop;
|
||||
if (signed'(4'hf) > 4'sh0) $stop;
|
||||
@ -24,10 +41,15 @@ module t;
|
||||
if ((4+2)'(allones) !== 6'h3f) $stop;
|
||||
if ((4-2)'(allones) !== 2'h3) $stop;
|
||||
if ((FOUR+2)'(allones) !== 6'h3f) $stop;
|
||||
if (50 !== RESULT) $stop;
|
||||
|
||||
o = tocast_t'(4'b1);
|
||||
if (o != 4'b1) $stop;
|
||||
|
||||
if (15'h6cec != outa) $stop;
|
||||
if (27'h7ffecec != mida) $stop;
|
||||
if (27'h7ffecec != midb) $stop;
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
@ -169,6 +169,10 @@
|
||||
`checkh(w32_u, 32'h0000_0180);
|
||||
w32_u = 32'(signed'({4'b0011,5'b10000}) << 3);
|
||||
`checkh(w32_u, 32'h0000_0380);
|
||||
w32_u = signed'(32'({4'b0001,5'b10000}) << 3);
|
||||
`checkh(w32_u, 32'h0000_0180);
|
||||
w32_u = signed'(32'({4'b0011,5'b10000}) << 3);
|
||||
`checkh(w32_u, 32'h0000_0380);
|
||||
// verilator lint_on WIDTH
|
||||
w32_u = 32'(signed'({4'b0011,5'b10000})) << 3; // Check no width warning
|
||||
`checkh(w32_u, 32'h0000_0380);
|
||||
|
Loading…
Reference in New Issue
Block a user