This commit is contained in:
parent
0e423a4b39
commit
a2874b324a
|
|
@ -186,6 +186,7 @@ Maxim Fonarev
|
|||
Michael Bedford Taylor
|
||||
Michael Bikovitsky
|
||||
Michael Killough
|
||||
Michael Rogenmoser
|
||||
Michal Czyz
|
||||
Michaël Lefebvre
|
||||
Miguel Perez Andrade
|
||||
|
|
|
|||
|
|
@ -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("vlt")
|
||||
|
||||
test.compile(verilator_flags2=["--binary"])
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// Regression test: Class member is an array of virtual interfaces.
|
||||
// The conditional trigger must handle VIF accesses through array
|
||||
// elements correctly.
|
||||
//
|
||||
// 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='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0)
|
||||
// verilog_format: on
|
||||
|
||||
interface SimpleIf;
|
||||
logic [7:0] data;
|
||||
endinterface
|
||||
|
||||
class VifHolder;
|
||||
virtual SimpleIf vifs[2];
|
||||
|
||||
function new(virtual SimpleIf a, virtual SimpleIf b);
|
||||
vifs[0] = a;
|
||||
vifs[1] = b;
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
module t;
|
||||
logic clk = 0;
|
||||
int cyc = 0;
|
||||
|
||||
SimpleIf intf0();
|
||||
SimpleIf intf1();
|
||||
|
||||
virtual SimpleIf vi0 = intf0;
|
||||
virtual SimpleIf vi1 = intf1;
|
||||
|
||||
VifHolder holder = new(intf0, intf1);
|
||||
|
||||
// Write through virtual interface handles
|
||||
always @(posedge clk) begin
|
||||
if (cyc == 1) vi0.data <= 8'hAA;
|
||||
if (cyc == 2) vi1.data <= 8'hBB;
|
||||
if (cyc == 3) vi0.data <= 8'hCC;
|
||||
if (cyc == 4) vi1.data <= 8'hDD;
|
||||
end
|
||||
|
||||
// Read through array-of-VIF class member
|
||||
logic [7:0] obs0, obs1;
|
||||
assign obs0 = holder.vifs[0].data;
|
||||
assign obs1 = holder.vifs[1].data;
|
||||
|
||||
always @(posedge clk) begin
|
||||
cyc <= cyc + 1;
|
||||
case (cyc)
|
||||
2: `checkh(obs0, 8'hAA);
|
||||
3: `checkh(obs1, 8'hBB);
|
||||
4: `checkh(obs0, 8'hCC);
|
||||
5: `checkh(obs1, 8'hDD);
|
||||
6: begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
initial begin
|
||||
repeat (20) #5 clk = ~clk;
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -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("vlt")
|
||||
|
||||
test.compile(verilator_flags2=["--binary"])
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// Regression test for virtual interface trigger convergence.
|
||||
// When combinational logic continuously writes the same value to a virtual
|
||||
// interface signal (via continuous assign), the VIF trigger must only fire
|
||||
// on actual value changes. Otherwise, the ICO/NBA scheduling loop never
|
||||
// converges.
|
||||
//
|
||||
// This reproduces the pattern from the AXI bus_compare testbench:
|
||||
// 1. A DV (driver) interface instance is accessed via virtual interface
|
||||
// in a class (drv_if)
|
||||
// 2. A plain interface instance (dut_if) is connected to drv_if via
|
||||
// continuous assigns in both directions (request & response)
|
||||
// 3. Combinational logic (always_comb) reads from dut_if members (extracted
|
||||
// into struct-like variables) and writes response variables back
|
||||
// 4. Response variables are assigned back to dut_if, which flow to drv_if
|
||||
// 5. Writing to drv_if fires VIF triggers unconditionally, causing
|
||||
// re-evaluation of all VIF-dependent logic in the ICO loop
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 Wilson Snyder
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// Simple bus interface with request and response signals
|
||||
interface BusIf #(
|
||||
parameter int DW = 8
|
||||
) (
|
||||
input logic clk
|
||||
);
|
||||
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
|
||||
);
|
||||
virtual BusIf #(.DW(DW)) vif;
|
||||
|
||||
function new(virtual BusIf #(.DW(DW)) vif);
|
||||
this.vif = vif;
|
||||
endfunction
|
||||
|
||||
task reset();
|
||||
vif.req_valid <= 1'b0;
|
||||
vif.req_data <= '0;
|
||||
endtask
|
||||
|
||||
task send(input logic [DW-1:0] data);
|
||||
vif.req_valid <= 1'b1;
|
||||
vif.req_data <= data;
|
||||
@(posedge vif.clk);
|
||||
while (!vif.req_ready) @(posedge vif.clk);
|
||||
vif.req_valid <= 1'b0;
|
||||
endtask
|
||||
endclass
|
||||
|
||||
module t;
|
||||
|
||||
logic clk = 0;
|
||||
int cyc = 0;
|
||||
|
||||
// Driver interface (like AXI_BUS_DV) -- used via virtual interface in class
|
||||
BusIf #(.DW(8)) drv_if (.clk(clk));
|
||||
|
||||
// DUT interface (like AXI_BUS) -- plain interface
|
||||
BusIf #(.DW(8)) dut_if (.clk(clk));
|
||||
|
||||
// Instantiate driver class with virtual interface handle
|
||||
Driver #(.DW(8)) drv = new(drv_if);
|
||||
|
||||
// --- 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;
|
||||
// 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 [7:0] ext_data;
|
||||
assign ext_valid = dut_if.req_valid;
|
||||
assign ext_data = dut_if.req_data;
|
||||
|
||||
// --- Combinational response logic (like always_comb in tb_axi_bus_compare) ---
|
||||
logic rsp_ready;
|
||||
always_comb begin
|
||||
rsp_ready = 1'b1; // Always accept
|
||||
end
|
||||
|
||||
// --- Write response back to dut_if (like AXI_ASSIGN_FROM_RESP) ---
|
||||
assign dut_if.req_ready = rsp_ready;
|
||||
|
||||
// --- Testbench stimulus using the driver class ---
|
||||
initial begin
|
||||
drv.reset();
|
||||
@(posedge clk);
|
||||
@(posedge clk);
|
||||
// These writes to drv_if (VIF) trigger VIF triggers. The response
|
||||
// path writes back to drv_if.req_ready with the same value (1'b1),
|
||||
// which should NOT re-trigger infinitely.
|
||||
drv.send(8'hAB);
|
||||
@(posedge clk);
|
||||
// Send same value again
|
||||
drv.send(8'hAB);
|
||||
@(posedge clk);
|
||||
drv.send(8'h00);
|
||||
@(posedge clk);
|
||||
@(posedge clk);
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
initial begin
|
||||
repeat (30) #5ns clk = ~clk;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -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("vlt")
|
||||
|
||||
test.compile(verilator_flags2=["--binary"])
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// Regression test for virtual interface trigger convergence.
|
||||
// When combinational logic continuously writes the same value to a virtual
|
||||
// interface signal (via continuous assign), the VIF trigger must only fire
|
||||
// on actual value changes. Otherwise, the ICO/NBA scheduling loop never
|
||||
// converges.
|
||||
//
|
||||
// This reproduces the pattern:
|
||||
// 1. A initial block drived the interface via virtual interface (drv_if)
|
||||
// 2. A plain interface instance (dut_if) is connected to drv_if via
|
||||
// continuous assigns in both directions (request & response)
|
||||
// 3. Combinational logic (assign) reads from dut_if members and writes
|
||||
// response variables back
|
||||
// 4. Response variables are assigned back to dut_if, which flow to drv_if
|
||||
// 5. Writing to drv_if fires VIF triggers unconditionally, causing
|
||||
// re-evaluation of all VIF-dependent logic in the ICO loop
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 Wilson Snyder
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// Simple bus interface with request and response signals
|
||||
interface BusIf ();
|
||||
logic req_valid;
|
||||
logic req_ready;
|
||||
endinterface
|
||||
|
||||
module t;
|
||||
|
||||
logic clk = 0;
|
||||
int cyc = 0;
|
||||
|
||||
// Driver interface -- used via virtual interface in class
|
||||
BusIf drv_if();
|
||||
|
||||
// DUT interface -- plain interface
|
||||
BusIf dut_if();
|
||||
|
||||
// Instantiate virtual interface handle
|
||||
virtual BusIf vif = drv_if;
|
||||
|
||||
// --- Bidirectional continuous assigns ---
|
||||
// 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;
|
||||
|
||||
// --- Extract signals from dut_if ---
|
||||
logic ext_valid;
|
||||
assign ext_valid = dut_if.req_valid;
|
||||
|
||||
// --- Write response back to dut_if (like AXI_ASSIGN_FROM_RESP) ---
|
||||
assign dut_if.req_ready = 1'b1;
|
||||
|
||||
// --- Testbench stimulus using the vif ---
|
||||
initial begin
|
||||
vif.req_valid = 1'b0;
|
||||
@(posedge clk);
|
||||
@(posedge clk);
|
||||
// These writes to drv_if (VIF) trigger VIF triggers. The response
|
||||
// path writes back to drv_if.req_ready with the same value (1'b1),
|
||||
// which should NOT re-trigger infinitely.
|
||||
vif.req_valid = 1'b1;
|
||||
@(posedge clk);
|
||||
while (!vif.req_ready) @(posedge clk);
|
||||
vif.req_valid = 1'b0;
|
||||
@(posedge clk);
|
||||
// Send same value again
|
||||
vif.req_valid = 1'b1;
|
||||
@(posedge clk);
|
||||
while (!vif.req_ready) @(posedge clk);
|
||||
vif.req_valid = 1'b0;
|
||||
@(posedge clk);
|
||||
vif.req_valid = 1'b1;
|
||||
@(posedge clk);
|
||||
while (!vif.req_ready) @(posedge clk);
|
||||
vif.req_valid = 1'b0;
|
||||
@(posedge clk);
|
||||
@(posedge clk);
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
initial begin
|
||||
repeat (30) #5ns clk = ~clk;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -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("vlt")
|
||||
|
||||
test.compile(verilator_flags2=["--binary"])
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// Regression test: VIF member written through two different virtual
|
||||
// interface handles pointing to the same underlying interface instance.
|
||||
// The conditional trigger must detect value changes correctly regardless
|
||||
// of which virtual handle performs the write.
|
||||
//
|
||||
// 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='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0)
|
||||
// verilog_format: on
|
||||
|
||||
interface SimpleIf;
|
||||
logic [7:0] data;
|
||||
endinterface
|
||||
|
||||
module t;
|
||||
logic clk = 0;
|
||||
int cyc = 0;
|
||||
|
||||
SimpleIf intf();
|
||||
|
||||
// Two different virtual interface handles to the same interface
|
||||
virtual SimpleIf vi1 = intf;
|
||||
virtual SimpleIf vi2 = intf;
|
||||
virtual SimpleIf vi_rd = intf;
|
||||
|
||||
// Write through first virtual handle on odd cycles, second on even
|
||||
always @(posedge clk) begin
|
||||
if (cyc == 1) vi1.data <= 8'hAA;
|
||||
if (cyc == 2) vi2.data <= 8'hBB;
|
||||
if (cyc == 3) vi1.data <= 8'hCC;
|
||||
if (cyc == 4) vi2.data <= 8'hDD;
|
||||
end
|
||||
|
||||
// Combinational logic reading through yet another virtual handle
|
||||
logic [7:0] observed;
|
||||
assign observed = vi_rd.data;
|
||||
|
||||
always @(posedge clk) begin
|
||||
cyc <= cyc + 1;
|
||||
case (cyc)
|
||||
2: `checkh(observed, 8'hAA);
|
||||
3: `checkh(observed, 8'hBB);
|
||||
4: `checkh(observed, 8'hCC);
|
||||
5: `checkh(observed, 8'hDD);
|
||||
6: begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
initial begin
|
||||
repeat (20) #5 clk = ~clk;
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -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("vlt")
|
||||
|
||||
test.compile(verilator_flags2=["--binary"])
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// Regression test: VIF member written through both a virtual interface and
|
||||
// a non-virtual (plain) interface reference. The conditional trigger must
|
||||
// detect value changes correctly even when the member is updated through
|
||||
// the non-virtual path.
|
||||
//
|
||||
// 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='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0)
|
||||
// verilog_format: on
|
||||
|
||||
interface SimpleIf;
|
||||
logic [7:0] data;
|
||||
endinterface
|
||||
|
||||
module t;
|
||||
logic clk = 0;
|
||||
int cyc = 0;
|
||||
|
||||
SimpleIf intf();
|
||||
virtual SimpleIf vi = intf;
|
||||
|
||||
// Write through virtual interface
|
||||
always @(posedge clk) begin
|
||||
if (cyc == 1) vi.data <= 8'hAA;
|
||||
if (cyc == 3) vi.data <= 8'hBB;
|
||||
end
|
||||
|
||||
// Write through non-virtual (plain) interface
|
||||
always @(posedge clk) begin
|
||||
if (cyc == 2) intf.data <= 8'hCC;
|
||||
if (cyc == 4) intf.data <= 8'hDD;
|
||||
end
|
||||
|
||||
// Combinational logic reading through virtual interface
|
||||
logic [7:0] observed;
|
||||
assign observed = vi.data;
|
||||
|
||||
always @(posedge clk) begin
|
||||
cyc <= cyc + 1;
|
||||
case (cyc)
|
||||
2: `checkh(observed, 8'hAA);
|
||||
3: `checkh(observed, 8'hCC);
|
||||
4: `checkh(observed, 8'hBB);
|
||||
5: `checkh(observed, 8'hDD);
|
||||
6: begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
initial begin
|
||||
repeat (20) #5 clk = ~clk;
|
||||
end
|
||||
endmodule
|
||||
Loading…
Reference in New Issue