Commentary: Changes update

This commit is contained in:
Wilson Snyder 2026-05-09 19:22:47 -04:00
parent c69c11b2db
commit 1630a2724b
19 changed files with 154 additions and 122 deletions

16
Changes
View File

@ -12,14 +12,20 @@ Verilator 5.049 devel
==========================
* Support `s_eventually` (#7291) (#7508). [Bartłomiej Chmiel, Antmicro Ltd.]
* Support writing to inout in fork after timing (#7345). [Kamil Danecki, Antmicro Ltd.]
* Support `always` / `always[m:n]` / `s_always[m:n]` property operators (#7482). [Yilou Wang]
* Support rand_mode() on static rand class members (#7484) (#7510). [Yilou Wang]
* Support `randomize() with (identifier_list) {constraint_block}` (#7486) (#7507). [Yilou Wang]
* Support functions on RHS of force (#7491). [Artur Bieniek, Antmicro Ltd.]
* Support `obj.randomize(null)` (#7487) (#7509). [Yilou Wang]
* Support functions on RHS of force (#7491). [Artur Bieniek, Antmicro Ltd.]
* Support procedural continuous assign/deassign (#7493). [Artur Bieniek, Antmicro Ltd.]
* Support randsequence production function ports (#7522). [Yilou Wang]
* Support followed-by operators `#-#` and `#=#` in properties (#7523). [Yilou Wang]
* Improve `--coverage-fsm` (#7490). [Yogish Sekhar]
* Add peak memory usage to `--stats`. [Geza Lore, Testorrent USA, Inc.]
* Improve `--coverage-fsm` (#7490) (#7529). [Yogish Sekhar]
* Change `+verilator+seed` to default to 1, and 0 to randomly select (#7325) (#7516). [Miguel]
* Change JSON to include parameter constant mnemonics for FSM Coverage (#7531). [Yogish Sekhar]
* Optimize additional DFG peephole cases (#7553). [Varun Koyyalagunta, Testorrent USA, Inc.]
* Fix inlining static initializer in V3Gate (#5381) (#7503). [Andrew Nolte] [Geza Lore, Testorrent USA, Inc.]
* Fix generic interface port forwarded to a nested instance (#7454) (#7457). [Yilou Wang]
* Fix internal error on multi-cycle SVA under default clocking (#7472) (#7506). [Yilou Wang]
@ -31,7 +37,11 @@ Verilator 5.049 devel
* Fix virtual interface method call inlining and IMPURE suppression (#7505). [Nikolay Puzanov]
* Fix expression coverage in loops (#7511). [Todd Strader]
* Fix $bits on local struct with chained-interface (#7515) (#7517).
* Fix array indexing side effects in compound assignments (#7519). [Kamil Danecki, Antmicro Ltd.]
* Fix array indexing side effects in compound assignments (#7519) (#7540) (#7544). [Kamil Danecki, Antmicro Ltd.]
* Fix class::localparam during elaboration (#7524) (#7534).
* Fix events in observed region (#7546). [Todd Strader]
* Fix regression rejecting boolean `!x` inside sequence expressions (#7549) (#7551). [Yilou Wang]
* Fix exponential expansion in V3Gate (#7550). [Geza Lore, Testorrent USA, Inc.]
Verilator 5.048 2026-04-26

View File

@ -73,7 +73,7 @@ public:
EC_FIRST_WARN, // Just a code so the program knows where to start warnings
//
ALWCOMBORDER, // Always_comb with unordered statements
ALWNEVER, // always will never execute
ALWNEVER, // Always will never execute
ASCRANGE, // Ascending bit range vector
ASSIGNDLY, // Assignment delays
ASSIGNEQEXPR, // Assignment equal (=) in expression

View File

@ -20,10 +20,12 @@ module t;
always @(posedge clock) {a, b, c, d} = 4'h3;
always @(control)
if (control)
if (control) begin
assign {a, b, c, d} = 4'h2;
else
end
else begin
deassign {a, b, c, d};
end
always begin
#2;

View File

@ -4,60 +4,66 @@
// SPDX-FileCopyrightText: 2026 Antmicro
// 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='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
// verilog_format: on
module t (/*AUTOARG*/
// Inputs
clk
);
module t (
input clk
);
input clk;
integer cyc; initial cyc = 0;
int cyc;
wire q;
logic d=0, clear, preset;
logic d = 0, clear, preset;
dff flipflop(q, d, clear, preset, clk);
dff flipflop (
q,
d,
clear,
preset,
clk
);
//clear and preset signals are in inverted logic
always @ (posedge clk) begin
always @(posedge clk) begin
cyc <= cyc + 1;
if(cyc==0) begin
clear=1;
preset=0;
d=0;
if (cyc == 0) begin
clear = 1;
preset = 0;
d = 0;
end
else if(cyc==1) begin
else if (cyc == 1) begin
`checkh(q, 1);
preset=1;
d=1;
preset = 1;
d = 1;
end
else if(cyc==2) begin
else if (cyc == 2) begin
`checkh(q, 1);
clear=0;
clear = 0;
end
else if(cyc==3) begin
else if (cyc == 3) begin
`checkh(q, 0);
preset=0;
preset = 0;
end
else if(cyc==4) begin
else if (cyc == 4) begin
`checkh(q, 0);
clear=1;
preset=1;
clear = 1;
preset = 1;
end
else if(cyc==5) begin
else if (cyc == 5) begin
`checkh(q, 1);
d=0;
d = 0;
end
else if(cyc==6) begin
else if (cyc == 6) begin
`checkh(q, 0);
d=1;
d = 1;
end
else if(cyc==7) begin
else if (cyc == 7) begin
`checkh(q, 1);
end
else if (cyc==8) begin
else if (cyc == 8) begin
$write("*-* All Finished *-*\n");
$finish;
end
@ -66,18 +72,20 @@ endmodule
// From IEEE 1800-2023 10.6.1
module dff (q, d, clear, preset, clock);
module dff (
q,
d,
clear,
preset,
clock
);
output q;
input d, clear, preset, clock;
logic q;
always @(clear or preset)
if (!clear)
assign q = 0;
else if (!preset)
assign q = 1;
else
deassign q;
always @(posedge clock)
q = d;
if (!clear) assign q = 0;
else if (!preset) assign q = 1;
else deassign q;
always @(posedge clock) q = d;
endmodule

View File

@ -4,17 +4,29 @@
// SPDX-FileCopyrightText: 2026 Wilson Snyder
// SPDX-License-Identifier: CC0-1.0
// verilog_format: off
`define stop $stop
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d (%s !== %s)\n", `__FILE__,`__LINE__, (gotv), (expv), `"gotv`", `"expv`"); `stop; end while(0);
// verilog_format: on
// Tests reference into a parameterized class via :: in a parameter expression.
virtual class C #(parameter int a = 0);
virtual class C #(
parameter int a = 0
);
localparam int b = a;
static function int get_a();
return a;
endfunction
typedef enum {E0 = 100, E1 = 101} e_t;
typedef enum {
E0 = 100,
E1 = 101
} e_t;
endclass
class D #(parameter int v = C#(7)::b);
class D #(
parameter int v = C#(7)::b
);
static function int get_v();
return v;
endfunction
@ -25,7 +37,7 @@ typedef C#(1) inst1;
typedef C#(4) chain_a;
typedef chain_a chain_b;
module t (/*AUTOARG*/);
module t ( /*AUTOARG*/);
// Wilson's exact case: typedef-aliased paramed class lparam.
localparam int LP_TYPEDEF_LPARAM = inst0::b;
@ -74,21 +86,21 @@ module t (/*AUTOARG*/);
localparam int LP_CHAINED_TYPEDEF_INNER = D#(c13_alias::b)::get_v();
initial begin
if (LP_TYPEDEF_LPARAM !== 0) begin $write("%%Error: TYPEDEF_LPARAM=%0d\n", LP_TYPEDEF_LPARAM); $stop; end
if (LP_DIRECT_LPARAM !== 2) begin $write("%%Error: DIRECT_LPARAM=%0d\n", LP_DIRECT_LPARAM); $stop; end
if (LP_STATIC_FUNC !== 1) begin $write("%%Error: STATIC_FUNC=%0d\n", LP_STATIC_FUNC); $stop; end
if (LP_ENUM_DIRECT !== 100) begin $write("%%Error: ENUM_DIRECT=%0d\n", LP_ENUM_DIRECT); $stop; end
if (LP_ENUM_TYPEDEF !== 101) begin $write("%%Error: ENUM_TYPEDEF=%0d\n", LP_ENUM_TYPEDEF); $stop; end
if (LP_OVERRIDE !== 7) begin $write("%%Error: OVERRIDE=%0d\n", LP_OVERRIDE); $stop; end
if (LP_MATH !== 5) begin $write("%%Error: MATH=%0d\n", LP_MATH); $stop; end
if (LP_PARAM_DRIVES_PARAM !== 5) begin $write("%%Error: PARAM_DRIVES_PARAM=%0d\n", LP_PARAM_DRIVES_PARAM); $stop; end
if (LP_CHAIN_TYPEDEF !== 4) begin $write("%%Error: CHAIN_TYPEDEF=%0d\n", LP_CHAIN_TYPEDEF); $stop; end
if (LP_MULTI !== 3) begin $write("%%Error: MULTI=%0d\n", LP_MULTI); $stop; end
if (LP_CLASS_DEFAULT !== 7) begin $write("%%Error: CLASS_DEFAULT=%0d\n", LP_CLASS_DEFAULT); $stop; end
if (LP_NESTED_ARG !== 9) begin $write("%%Error: NESTED_ARG=%0d\n", LP_NESTED_ARG); $stop; end
if (LP_NESTED_TYPEDEF_INNER !== 13) begin $write("%%Error: NESTED_TYPEDEF_INNER=%0d\n", LP_NESTED_TYPEDEF_INNER); $stop; end
if (LP_THREE_LEVEL !== 15) begin $write("%%Error: THREE_LEVEL=%0d\n", LP_THREE_LEVEL); $stop; end
if (LP_CHAINED_TYPEDEF_INNER !== 13) begin $write("%%Error: CHAINED_TYPEDEF_INNER=%0d\n", LP_CHAINED_TYPEDEF_INNER); $stop; end
`checkd(LP_TYPEDEF_LPARAM, 0);
`checkd(LP_DIRECT_LPARAM, 2);
`checkd(LP_STATIC_FUNC, 1);
`checkd(LP_ENUM_DIRECT, 100);
`checkd(LP_ENUM_TYPEDEF, 101);
`checkd(LP_OVERRIDE, 7);
`checkd(LP_MATH, 5);
`checkd(LP_PARAM_DRIVES_PARAM, 5);
`checkd(LP_CHAIN_TYPEDEF, 4);
`checkd(LP_MULTI, 3);
`checkd(LP_CLASS_DEFAULT, 7);
`checkd(LP_NESTED_ARG, 9);
`checkd(LP_NESTED_TYPEDEF_INNER, 13);
`checkd(LP_THREE_LEVEL, 15);
`checkd(LP_CHAINED_TYPEDEF_INNER, 13);
$write("*-* All Finished *-*\n");
$finish;
end

View File

@ -1,6 +1,6 @@
%Error: t/t_class_localparam_dotref_bad.v:17:33: Can't find definition of scope/variable/func: 'nonexistent'
%Error: t/t_class_localparam_dotref_bad.v:19:33: Can't find definition of scope/variable/func: 'nonexistent'
: ... note: In instance 't'
17 | localparam int LP_BAD = inst::nonexistent;
19 | localparam int LP_BAD = inst::nonexistent;
| ^~~~~~~~~~~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: Exiting due to

View File

@ -7,7 +7,9 @@
// Negative test: a parameterized class :: ref to a member that does not exist
// in a parameter expression should produce a clean error, not crash.
class C #(parameter int a = 0);
class C #(
parameter int a = 0
);
localparam int b = a;
endclass

View File

@ -1,12 +1,12 @@
%Error-UNSUPPORTED: t/t_class_localparam_dotref_funcref_arg_bad.v:23:32: dotted expressions in parameters
%Error-UNSUPPORTED: t/t_class_localparam_dotref_funcref_arg_bad.v:27:32: dotted expressions in parameters
: ... note: In instance 't'
: ... Suggest use a typedef
23 | localparam int y = D#(C#(7)::get_a())::x;
27 | localparam int y = D#(C#(7)::get_a())::x;
| ^~~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error: t/t_class_localparam_dotref_funcref_arg_bad.v:23:32: Can't convert defparam value to constant: Param '__paramNumber1' of 'D'
%Error: t/t_class_localparam_dotref_funcref_arg_bad.v:27:32: Can't convert defparam value to constant: Param '__paramNumber1' of 'D'
: ... note: In instance 't'
23 | localparam int y = D#(C#(7)::get_a())::x;
27 | localparam int y = D#(C#(7)::get_a())::x;
| ^~~~~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: Exiting due to

View File

@ -9,13 +9,17 @@
// Folding the function call to a constant during specialization requires
// constant-function evaluation that this fix does not provide.
class C #(parameter int a = 0);
class C #(
parameter int a = 0
);
static function int get_a();
return a;
endfunction
endclass
class D #(parameter int v = 0);
class D #(
parameter int v = 0
);
localparam int x = v;
endclass

View File

@ -16,7 +16,7 @@ module t;
initial begin
#1;
data = 1;
-> e;
->e;
#1;
if (cb.data !== 1'b1) $stop;
$write("*-* All Finished *-*\n");

View File

@ -14,7 +14,7 @@
// verilator lint_off WIDTHTRUNC
module t (
input logic src,
input logic src,
output logic assign_out,
output logic comb_out,
output logic latch_out
@ -27,7 +27,7 @@ module t (
reg q, d;
event foo;
real rl;
int ar [];
int ar[];
int start = 0;
int stop = 1;
int step = 1;
@ -59,14 +59,14 @@ module t (
deassign assign_sig;
end
always_comb begin: blk_name
always_comb begin : blk_name
event int1, int2;
real intrl;
q <= d;
-> foo;
->foo;
rl = 0.0;
rl <= 1.0;
ar = new [2];
ar = new[2];
for (int idx = start; idx < stop; idx += step) $display("For: %0d", idx);
for (int idx = 0; done; idx = done + 1) $stop;
for (int idx = 0; idx; done = done + 1) $stop;
@ -79,23 +79,22 @@ module t (
a_task;
assign a = 1'b0;
deassign a;
do $display("do/while");
while (a);
do $display("do/while"); while (a);
force a = 1'b1;
release a;
while(a) begin
while (a) begin
$display("while");
a = 1'b0;
end
repeat(2) $display("repeat");
repeat (2) $display("repeat");
disable out_name;
forever begin
$display("forever");
disable blk_name; // This one should not generate a warning
disable blk_name; // This one should not generate a warning
end
end
initial begin: out_name
initial begin : out_name
#2 $stop;
end

View File

@ -75,7 +75,7 @@ module t;
`checkd(x, -1)
endtask
task t3(output int x);
task t3(output int x);
if ($time < 10) begin
`checkd(x, 0)
end

View File

@ -4,8 +4,8 @@
// SPDX-FileCopyrightText: 2026 Wilson Snyder
// SPDX-License-Identifier: CC0-1.0
module top(
input wire [31:0] a
module top (
input wire [31:0] a
);
wire [31:0] w00, w01, w02, w03, w04, w05, w06, w07, w08, w09;

View File

@ -30,8 +30,8 @@ module t;
logic clk = 0;
int cyc = 0;
SimpleIf intf0();
SimpleIf intf1();
SimpleIf intf0 ();
SimpleIf intf1 ();
virtual SimpleIf vi0 = intf0;
virtual SimpleIf vi1 = intf1;

View File

@ -23,19 +23,19 @@
// Simple bus interface with request and response signals
interface BusIf #(
parameter int DW = 8
parameter int DW = 8
) (
input logic clk
input logic clk
);
logic req_valid;
logic req_ready;
logic req_valid;
logic req_ready;
logic [DW-1:0] req_data;
endinterface
// Driver class that holds a virtual interface reference.
// This is what makes drv_if a "virtual interface" in Verilator's eyes.
class Driver #(
parameter int DW = 8
parameter int DW = 8
);
virtual BusIf #(.DW(DW)) vif;
@ -45,12 +45,12 @@ class Driver #(
task reset();
vif.req_valid <= 1'b0;
vif.req_data <= '0;
vif.req_data <= '0;
endtask
task send(input logic [DW-1:0] data);
vif.req_valid <= 1'b1;
vif.req_data <= data;
vif.req_data <= data;
@(posedge vif.clk);
while (!vif.req_ready) @(posedge vif.clk);
vif.req_valid <= 1'b0;
@ -60,7 +60,7 @@ endclass
module t;
logic clk = 0;
int cyc = 0;
int cyc = 0;
// Driver interface (like AXI_BUS_DV) -- used via virtual interface in class
BusIf #(.DW(8)) drv_if (.clk(clk));
@ -74,15 +74,15 @@ module t;
// --- Bidirectional continuous assigns (like `AXI_ASSIGN(dut_if, drv_if)) ---
// Request direction: drv_if -> dut_if
assign dut_if.req_valid = drv_if.req_valid;
assign dut_if.req_data = drv_if.req_data;
assign dut_if.req_data = drv_if.req_data;
// Response direction: dut_if -> drv_if (WRITES TO VIF!)
assign drv_if.req_ready = dut_if.req_ready;
// --- Extract signals from dut_if (like AXI_ASSIGN_TO_REQ) ---
logic ext_valid;
logic ext_valid;
logic [7:0] ext_data;
assign ext_valid = dut_if.req_valid;
assign ext_data = dut_if.req_data;
assign ext_data = dut_if.req_data;
// --- Combinational response logic (like always_comb in tb_axi_bus_compare) ---
logic rsp_ready;

View File

@ -22,20 +22,20 @@
// Simple bus interface with request and response signals
interface BusIf ();
logic req_valid;
logic req_ready;
logic req_valid;
logic req_ready;
endinterface
module t;
logic clk = 0;
int cyc = 0;
int cyc = 0;
// Driver interface -- used via virtual interface in class
BusIf drv_if();
BusIf drv_if ();
// DUT interface -- plain interface
BusIf dut_if();
BusIf dut_if ();
// Instantiate virtual interface handle
virtual BusIf vif = drv_if;
@ -44,10 +44,10 @@ module t;
// Request direction: drv_if -> dut_if
assign dut_if.req_valid = drv_if.req_valid;
// Response direction: dut_if -> drv_if (WRITES TO VIF!)
assign drv_if.req_ready = 1'b1; // dut_if.req_ready;
assign drv_if.req_ready = 1'b1; // dut_if.req_ready;
// --- Extract signals from dut_if ---
logic ext_valid;
logic ext_valid;
assign ext_valid = dut_if.req_valid;
// --- Write response back to dut_if (like AXI_ASSIGN_FROM_RESP) ---

View File

@ -22,7 +22,7 @@ module t;
logic clk = 0;
int cyc = 0;
SimpleIf intf();
SimpleIf intf ();
// Two different virtual interface handles to the same interface
virtual SimpleIf vi1 = intf;

View File

@ -22,7 +22,7 @@ module t;
logic clk = 0;
int cyc = 0;
SimpleIf intf();
SimpleIf intf ();
virtual SimpleIf vi = intf;
// Write through virtual interface

View File

@ -21,20 +21,17 @@ module t;
#5 `checkd(x, expected);
endtask
task factorial1 (input [31:0] x, output [31:0] out);
task factorial1(input [31:0] x, output [31:0] out);
if (x >= 2) begin
factorial1 (x - 1, out);
factorial1(x - 1, out);
out = out * x;
end
else
out = 1;
else out = 1;
endtask
function int factorial2 (input int x);
if (x >= 2)
factorial2 = factorial2(x - 1) * x;
else
factorial2 = 1;
function int factorial2(input int x);
if (x >= 2) factorial2 = factorial2(x - 1) * x;
else factorial2 = 1;
endfunction
int result;
@ -79,8 +76,7 @@ module t;
end
join_none
#10
expected = 10;
#10 expected = 10;
fork
begin
static int x3 = 99;
@ -105,8 +101,7 @@ module t;
end
join_none
#10
#10;
$write("*-* All Finished *-*\n");
$finish;
end