Fix wide conditional short circuiting (#7155).

Fixes #7155.
This commit is contained in:
Wilson Snyder 2026-02-28 09:40:10 -05:00
parent 5ae285d268
commit d40036239b
5 changed files with 134 additions and 25 deletions

View File

@ -13,6 +13,7 @@ Verilator 5.047 devel
**Other:**
* Fix wide conditional short circuiting (#7155).
Verilator 5.046 2026-02-28

View File

@ -2792,10 +2792,9 @@ static inline void VL_SELASSIGN_WW(int rbits, int obits, WDataOutP iowp, WDataIn
//======================================================================
// Triops
static inline WDataOutP VL_COND_WIWW(int obits, WDataOutP owp, int cond, WDataInP const w1p,
WDataInP const w2p) VL_MT_SAFE {
return VL_MEMCPY_W(owp, cond ? w1p : w2p, VL_WORDS_I(obits));
}
// This must be a macro in order for short-circuiting of the values to work.
#define VL_COND_WIWW(obits, owp, cond, w1p, w2p) \
VL_MEMCPY_W(owp, (cond) ? (w1p) : (w2p), VL_WORDS_I(obits))
//======================================================================
// Constification

View File

@ -39,37 +39,37 @@
-000009 point: type=line comment=block hier=top.t
%000009 {intf_sel_ff.foo, intf_sel_ff.bar, intf_sel_ff.baz} <=
-000009 point: type=line comment=block hier=top.t
%000009 cyc[0] ?
-000009 point: type=branch comment=cond_then hier=top.t
%000009 {intfs[1].foo, intfs[1].bar, intfs[1].baz} :
-000009 point: type=branch comment=cond_then hier=top.t
-000009 point: type=branch comment=cond_else hier=top.t
%000009 {intfs[0].foo, intfs[0].bar, intfs[0].baz};
-000009 point: type=branch comment=cond_else hier=top.t
%000005 cyc[0] ?
-000005 point: type=branch comment=cond_then hier=top.t
%000005 {intfs[1].foo, intfs[1].bar, intfs[1].baz} :
-000005 point: type=branch comment=cond_then hier=top.t
-000004 point: type=branch comment=cond_else hier=top.t
%000004 {intfs[0].foo, intfs[0].bar, intfs[0].baz};
-000004 point: type=branch comment=cond_else hier=top.t
end
000010 always_comb begin
+000010 point: type=line comment=block hier=top.t
000010 {intf_sel_comb.foo, intf_sel_comb.bar, intf_sel_comb.baz} =
+000010 point: type=line comment=block hier=top.t
000010 cyc[0] ?
+000010 point: type=branch comment=cond_then hier=top.t
000010 {intfs[1].foo, intfs[1].bar, intfs[1].baz} :
+000010 point: type=branch comment=cond_then hier=top.t
+000010 point: type=branch comment=cond_else hier=top.t
000010 {intfs[0].foo, intfs[0].bar, intfs[0].baz};
+000010 point: type=branch comment=cond_else hier=top.t
%000005 cyc[0] ?
-000005 point: type=branch comment=cond_then hier=top.t
%000005 {intfs[1].foo, intfs[1].bar, intfs[1].baz} :
-000005 point: type=branch comment=cond_then hier=top.t
-000005 point: type=branch comment=cond_else hier=top.t
%000005 {intfs[0].foo, intfs[0].bar, intfs[0].baz};
-000005 point: type=branch comment=cond_else hier=top.t
end
assign
{intf_sel_assign.foo, intf_sel_assign.bar, intf_sel_assign.baz} =
000010 cyc[0] ?
+000010 point: type=branch comment=cond_then hier=top.t
000010 {intfs[1].foo, intfs[1].bar, intfs[1].baz} :
+000010 point: type=branch comment=cond_then hier=top.t
+000010 point: type=branch comment=cond_else hier=top.t
000010 {intfs[0].foo, intfs[0].bar, intfs[0].baz};
+000010 point: type=branch comment=cond_else hier=top.t
%000005 cyc[0] ?
-000005 point: type=branch comment=cond_then hier=top.t
%000005 {intfs[1].foo, intfs[1].bar, intfs[1].baz} :
-000005 point: type=branch comment=cond_then hier=top.t
-000005 point: type=branch comment=cond_else hier=top.t
%000005 {intfs[0].foo, intfs[0].bar, intfs[0].baz};
-000005 point: type=branch comment=cond_else hier=top.t
%000009 always @ (posedge clk) begin
-000009 point: type=line comment=block hier=top.t

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# 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-FileCopyrightText: 2026 Wilson Snyder
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios('simulator')
test.compile()
test.execute()
test.passes()

View File

@ -0,0 +1,91 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain.
// SPDX-FileCopyrightText: 2026 Wilson Snyder
// SPDX-License-Identifier: CC0-1.0
// verilog_format: off
`define stop $stop
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0x exp=%0x (%s !== %s)\n", `__FILE__,`__LINE__, (gotv), (expv), `"gotv`", `"expv`"); `stop; end while(0);
`ifdef verilator
`define optimize_barrier $c("")
`else
`define optimize_barrier
`endif
// verilog_format: on
module t;
class Map;
virtual function bit [95:0] get_value();
bit [95:0] result = 96'h11111111_22222222_33333333;
`optimize_barrier;
return result;
endfunction
endclass
class Cls;
function bit [95:0] get_default();
bit [95:0] result = 96'haaaaaaaa_bbbbbbbb_cccccccc;
`optimize_barrier;
return result;
endfunction
function bit [95:0] compute_LL(Map map);
bit [95:0] result;
`optimize_barrier;
// Wide operation is required, as results in VL_COND call which evaluates
// arguments
result = map == null ? this.get_default() : map.get_value();
`optimize_barrier;
return result;
endfunction
function bit [95:0] compute_LC(Map map);
bit [95:0] result;
bit sel1 = map == null;
`optimize_barrier;
result = sel1 ? 96'hffffffff_ffffffff_ffffffff : map.get_value();
`optimize_barrier;
return result;
endfunction
function bit [95:0] compute_CL(Map map);
bit [95:0] result;
bit sel1 = map != null;
`optimize_barrier;
result = sel1 ? map.get_value() : 96'hffffffff_ffffffff_ffffffff;
`optimize_barrier;
return result;
endfunction
endclass
initial begin
Cls c;
Map mnull;
Map m;
bit [95:0] res;
c = new;
m = new;
res = c.compute_LL(mnull);
`checkh(res, 96'haaaaaaaa_bbbbbbbb_cccccccc);
res = c.compute_LL(m);
`checkh(res, 96'h11111111_22222222_33333333);
res = c.compute_LC(mnull);
`checkh(res, 96'hffffffff_ffffffff_ffffffff);
res = c.compute_LC(m);
`checkh(res, 96'h11111111_22222222_33333333);
res = c.compute_CL(mnull);
`checkh(res, 96'hffffffff_ffffffff_ffffffff);
res = c.compute_CL(m);
`checkh(res, 96'h11111111_22222222_33333333);
$finish;
end
endmodule