parent
413183bad8
commit
66e105b444
2
Changes
2
Changes
|
@ -17,7 +17,7 @@ Verilator 5.037 devel
|
|||
* Add PROCINITASSIGN on initial assignments to process variables (#2481). [Niraj Menon]
|
||||
* Fix filename backslash escapes in C code (#5947).
|
||||
* Fix C++ widths in V3Expand (#5953) (#5975). [Geza Lore]
|
||||
* Fix constant propagation making upper bits Xs (#5955) (#5969).
|
||||
* Fix constant propagation of post-expand stages (#5955) (#5963) (#5969) (#5972).
|
||||
* Fix sign extension of signed compared with unsigned case items (#5968).
|
||||
* Fix always processes ignoring $finish (#5971). [Hennadii Chernyshchyk]
|
||||
* Fix streaming to/from packed arrays (#5976). [Geza Lore]
|
||||
|
|
|
@ -427,6 +427,8 @@ public:
|
|||
string prettyDTypeName(bool full) const override;
|
||||
const char* broken() const override {
|
||||
BROKEN_RTN(dtypep() != this);
|
||||
BROKEN_RTN(v3Global.widthMinUsage() == VWidthMinUsage::VERILOG_WIDTH
|
||||
&& widthMin() > width());
|
||||
return nullptr;
|
||||
}
|
||||
void setSignedState(const VSigning& signst) {
|
||||
|
|
|
@ -927,6 +927,18 @@ class ConstVisitor final : public VNVisitor {
|
|||
|
||||
// METHODS
|
||||
|
||||
V3Number constNumV(AstNode* nodep) {
|
||||
// Contract C width to V width (if needed, else just direct copy)
|
||||
// The upper zeros in the C representation can otherwise cause
|
||||
// wrong results in some operations, e.g. MulS
|
||||
const V3Number& numc = VN_AS(nodep, Const)->num();
|
||||
return !numc.isNumber() ? numc : V3Number{nodep, nodep->widthMinV(), numc};
|
||||
}
|
||||
V3Number toNumC(AstNode* nodep, V3Number& numv) {
|
||||
// Extend V width back to C width for given node
|
||||
return !numv.isNumber() ? numv : V3Number{nodep, nodep->width(), numv};
|
||||
}
|
||||
|
||||
bool operandConst(AstNode* nodep) { return VN_IS(nodep, Const); }
|
||||
bool operandAsvConst(const AstNode* nodep) {
|
||||
// BIASV(CONST, BIASV(CONST,...)) -> BIASV( BIASV_CONSTED(a,b), ...)
|
||||
|
@ -1614,31 +1626,32 @@ class ConstVisitor final : public VNVisitor {
|
|||
VL_DO_DANGLING(replaceNum(nodep, ones), nodep);
|
||||
}
|
||||
void replaceConst(AstNodeUniop* nodep) {
|
||||
V3Number num{nodep, nodep->width()};
|
||||
nodep->numberOperate(num, VN_AS(nodep->lhsp(), Const)->num());
|
||||
V3Number numv{nodep, nodep->widthMinV()};
|
||||
nodep->numberOperate(numv, constNumV(nodep->lhsp()));
|
||||
const V3Number& num = toNumC(nodep, numv);
|
||||
UINFO(4, "UNICONST -> " << num << endl);
|
||||
VL_DO_DANGLING(replaceNum(nodep, num), nodep);
|
||||
}
|
||||
void replaceConst(AstNodeBiop* nodep) {
|
||||
V3Number num{nodep, nodep->width()};
|
||||
nodep->numberOperate(num, VN_AS(nodep->lhsp(), Const)->num(),
|
||||
VN_AS(nodep->rhsp(), Const)->num());
|
||||
V3Number numv{nodep, nodep->widthMinV()};
|
||||
nodep->numberOperate(numv, constNumV(nodep->lhsp()), constNumV(nodep->rhsp()));
|
||||
const V3Number& num = toNumC(nodep, numv);
|
||||
UINFO(4, "BICONST -> " << num << endl);
|
||||
VL_DO_DANGLING(replaceNum(nodep, num), nodep);
|
||||
}
|
||||
void replaceConst(AstNodeTriop* nodep) {
|
||||
V3Number num{nodep, nodep->width()};
|
||||
nodep->numberOperate(num, VN_AS(nodep->lhsp(), Const)->num(),
|
||||
VN_AS(nodep->rhsp(), Const)->num(),
|
||||
VN_AS(nodep->thsp(), Const)->num());
|
||||
V3Number numv{nodep, nodep->widthMinV()};
|
||||
nodep->numberOperate(numv, constNumV(nodep->lhsp()), constNumV(nodep->rhsp()),
|
||||
constNumV(nodep->thsp()));
|
||||
const V3Number& num = toNumC(nodep, numv);
|
||||
UINFO(4, "TRICONST -> " << num << endl);
|
||||
VL_DO_DANGLING(replaceNum(nodep, num), nodep);
|
||||
}
|
||||
void replaceConst(AstNodeQuadop* nodep) {
|
||||
V3Number num{nodep, nodep->width()};
|
||||
nodep->numberOperate(
|
||||
num, VN_AS(nodep->lhsp(), Const)->num(), VN_AS(nodep->rhsp(), Const)->num(),
|
||||
VN_AS(nodep->thsp(), Const)->num(), VN_AS(nodep->fhsp(), Const)->num());
|
||||
V3Number numv{nodep, nodep->widthMinV()};
|
||||
nodep->numberOperate(numv, constNumV(nodep->lhsp()), constNumV(nodep->rhsp()),
|
||||
constNumV(nodep->thsp()), constNumV(nodep->fhsp()));
|
||||
const V3Number& num = toNumC(nodep, numv);
|
||||
UINFO(4, "QUADCONST -> " << num << endl);
|
||||
VL_DO_DANGLING(replaceNum(nodep, num), nodep);
|
||||
}
|
||||
|
@ -1719,6 +1732,7 @@ class ConstVisitor final : public VNVisitor {
|
|||
nodep->rhsp(cp);
|
||||
rp->lhsp(ap);
|
||||
rp->rhsp(bp);
|
||||
rp->dtypeFrom(nodep); // Upper widthMin more likely correct
|
||||
if (VN_IS(rp->lhsp(), Const) && VN_IS(rp->rhsp(), Const)) replaceConst(rp);
|
||||
// if (debug()) nodep->dumpTree("- repAsvConst_new: ");
|
||||
}
|
||||
|
@ -1732,6 +1746,7 @@ class ConstVisitor final : public VNVisitor {
|
|||
nodep->rhsp(lp);
|
||||
lp->lhsp(lrp);
|
||||
lp->rhsp(rp);
|
||||
lp->dtypeFrom(nodep); // Upper widthMin more likely correct
|
||||
// if (debug()) nodep->dumpTree("- repAsvLUp_new: ");
|
||||
}
|
||||
void replaceAsvRUp(AstNodeBiop* nodep) {
|
||||
|
@ -1744,6 +1759,7 @@ class ConstVisitor final : public VNVisitor {
|
|||
nodep->rhsp(rp);
|
||||
rp->lhsp(lp);
|
||||
rp->rhsp(rrp);
|
||||
rp->dtypeFrom(nodep); // Upper widthMin more likely correct
|
||||
// if (debug()) nodep->dumpTree("- repAsvRUp_new: ");
|
||||
}
|
||||
void replaceAndOr(AstNodeBiop* nodep) {
|
||||
|
@ -3278,7 +3294,7 @@ class ConstVisitor final : public VNVisitor {
|
|||
if (argp) {
|
||||
AstNode* const nextp = argp->nextp();
|
||||
if (VN_IS(argp, Const)) { // Convert it
|
||||
const string out = VN_AS(argp, Const)->num().displayed(nodep, fmt);
|
||||
const string out = constNumV(argp).displayed(nodep, fmt);
|
||||
UINFO(9, " DispConst: " << fmt << " -> " << out << " for "
|
||||
<< argp << endl);
|
||||
// fmt = out w/ replace % with %% as it must be literal.
|
||||
|
|
|
@ -639,6 +639,7 @@ public:
|
|||
bool isEqZero() const VL_MT_SAFE;
|
||||
bool isNeqZero() const;
|
||||
bool isBitsZero(int msb, int lsb) const;
|
||||
bool isBroken(int vwidth) const;
|
||||
bool isEqOne() const;
|
||||
bool isEqAllOnes(int optwidth = 0) const;
|
||||
bool isCaseEq(const V3Number& rhs) const; // operator==
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2025 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.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.compile(verilator_flags2=['--binary', '-fno-expand'])
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
|
@ -0,0 +1,42 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2025 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
`define stop $stop
|
||||
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0h\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||
|
||||
module t;
|
||||
// Issue #5972
|
||||
|
||||
reg clk;
|
||||
reg signed [28:28] in1;
|
||||
reg signed [21:8] reg_10;
|
||||
|
||||
// verilator lint_off WIDTHEXPAND
|
||||
always @(negedge clk) begin
|
||||
// Issue #5972
|
||||
reg_10[14:8] <= {1'b1, ~((in1[28:28] & ~(in1[28:28])))};
|
||||
end
|
||||
|
||||
initial begin
|
||||
clk = 1;
|
||||
in1 = 1'b0;
|
||||
reg_10 = '0;
|
||||
#2;
|
||||
clk = 0;
|
||||
#2;
|
||||
`checkh(reg_10, 3);
|
||||
|
||||
in1 = 1'b1;
|
||||
clk = 1;
|
||||
#2;
|
||||
clk = 0;
|
||||
#2;
|
||||
`checkh(reg_10, 3);
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2025 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.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.compile(verilator_flags2=["--binary"])
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
|
@ -0,0 +1,78 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2025 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
`define stop $stop
|
||||
`define checks(gotv,expv) do if ((gotv) != (expv)) begin $write("%%Error: %s:%0d: got='%s' exp='%s'\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||
|
||||
module t;
|
||||
wire signed [21:10] out0;
|
||||
|
||||
sub sub (
|
||||
.out0(out0)
|
||||
);
|
||||
|
||||
sub2 sub2 ();
|
||||
|
||||
string s;
|
||||
|
||||
initial begin
|
||||
#20;
|
||||
// Bug with sformat, so can't just number-compare
|
||||
s = $sformatf("out0=%0d", out0);
|
||||
`checks(s, "out0=-12");
|
||||
if (out0 > 0) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
|
||||
module sub (out0);
|
||||
reg signed [27:20] reg_4;
|
||||
output wire [21:10] out0;
|
||||
|
||||
initial begin
|
||||
#1;
|
||||
reg_4 = 0;
|
||||
end
|
||||
|
||||
wire [11:0] w55;
|
||||
wire [11:0] w23;
|
||||
// verilator lint_off WIDTHEXPAND
|
||||
assign w55 = ~reg_4[20];
|
||||
// verilator lint_on WIDTHEXPAND
|
||||
assign { w23[3], w23[1:0] } = 3'h0;
|
||||
assign { w23[11:4], w23[2] } = { w55[11:4], w55[2] };
|
||||
assign out0 = w23;
|
||||
endmodule
|
||||
|
||||
module sub2;
|
||||
reg [27:5] in0;
|
||||
reg [26:11] in1;
|
||||
wire [24:14] wire_0;
|
||||
wire [26:5] out1;
|
||||
wire w085;
|
||||
wire w082;
|
||||
wire [10:0] w092;
|
||||
wire [9:0] w028;
|
||||
|
||||
string s;
|
||||
|
||||
initial begin
|
||||
in0 = 6902127;
|
||||
in1 = 10000;
|
||||
#10;
|
||||
s = $sformatf("out0=%0d", out1);
|
||||
`checks(s, "out0=0");
|
||||
end
|
||||
|
||||
assign w028 = ~ { 9'h000, in0[23] };
|
||||
assign w092[1] = 1'h0;
|
||||
assign { w092[10:2], w092[0] } = w028;
|
||||
assign wire_0 = w092;
|
||||
assign w082 = | wire_0[18:17];
|
||||
assign w085 = w082 ? in1[11] : 1'h0;
|
||||
assign out1 = { 21'h000000, w085 };
|
||||
endmodule
|
Loading…
Reference in New Issue