Interface clean up. WA for verilator tracing

This commit is contained in:
2025-08-24 11:27:11 -07:00
parent 8d8ea4443c
commit 5451131e1a
7 changed files with 233 additions and 43 deletions

View File

@@ -28,6 +28,9 @@ CPP_SRC=sim_$(PROJ).cpp
TIMESCALE= --timescale '1ns/1ns' TIMESCALE= --timescale '1ns/1ns'
ifndef VERI_TRACE_DIS
TB_DEFINES=+define+VERI_TRACE_EN
endif
UVM_DEFINES=+define+UVM_NO_DPI \ UVM_DEFINES=+define+UVM_NO_DPI \
+define+UVM_REPORT_DISABLE_FILE_LINE +define+UVM_REPORT_DISABLE_FILE_LINE
DISABLED_WARNINGS=-Wno-WIDTHTRUNC -Wno-WIDTHEXPAND \ DISABLED_WARNINGS=-Wno-WIDTHTRUNC -Wno-WIDTHEXPAND \
@@ -41,7 +44,9 @@ BUILD_ARGS=-I$(UVM_HOME)/src -I. \
--error-limit 10 \ --error-limit 10 \
--timing $(TIMESCALE) \ --timing $(TIMESCALE) \
--trace \ --trace \
--top tb_top \
+define+SVA_ON \ +define+SVA_ON \
$(TB_DEFINES) \
$(UVM_DEFINES) \ $(UVM_DEFINES) \
$(DISABLED_WARNINGS) \ $(DISABLED_WARNINGS) \
+incdir+common +incdir+src/axi +incdir+tb \ +incdir+common +incdir+src/axi +incdir+tb \

47
axi.gtkw Normal file
View File

@@ -0,0 +1,47 @@
[*]
[*] GTKWave Analyzer v3.3.124 (w)1999-2025 BSI
[*] Sun Aug 24 18:22:14 2025
[*]
[dumpfile] "/home/mahesh/dev/sv/axipg/runs/test_basic/wave.vcd"
[dumpfile_mtime] "Sun Aug 24 18:18:15 2025"
[dumpfile_size] 19493
[savefile] "/home/mahesh/dev/sv/axipg/axi.gtkw"
[timestart] 0
[size] 1388 1348
[pos] -1 -1
*-6.502242 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] tb_top.
[sst_width] 290
[signals_width] 126
[sst_expanded] 1
[sst_vpaned_height] 417
@28
tb_top.t_if.ARESETn
tb_top.t_if.ACLK
tb_top.t_if.ARVALID
tb_top.t_if.ARREADY
@22
tb_top.t_if.ARADDR[31:0]
tb_top.t_if.ARLEN[7:0]
@200
-
@28
tb_top.t_if.AWVALID
tb_top.t_if.AWREADY
@22
tb_top.t_if.AWADDR[31:0]
tb_top.t_if.AWLEN[7:0]
@200
-
@28
tb_top.t_if.WVALID
tb_top.t_if.WREADY
@22
tb_top.t_if.WSTRB[7:0]
tb_top.t_if.WDATA[63:0]
@28
tb_top.t_if.WLAST
@200
-
[pattern_trace] 1
[pattern_trace] 0

View File

@@ -38,6 +38,8 @@ sub gen_intf {
show_modport($app, 'Subordinate'); show_modport($app, 'Subordinate');
print "endinterface // axi_intf\n"; print "endinterface // axi_intf\n";
show_trace_interface_driver($app);
} }
# ----------------- # -----------------
@@ -88,6 +90,35 @@ sub show_interface {
} }
} }
# -----------------
sub show_trace_interface_driver {
my ($app) = @_;
print qq{
`ifdef VERI_TRACE_EN
// --------------------------------------------------
// Work around Verilator's lack of support for virutal interface tracing
`AXI_INTF t_if (.ACLK(clk), .ARESETn(rst_n));
};
foreach my $section (@{$app->{'intf_data'}->{'sections'}}) {
print " // $section->{'name'}\n";
# Display signals
foreach my $signal (@{$section->{'signals'}}) {
if ($signal->{'s'} eq 'External') {
printf " // External signal: %-$app->{'intf_data'}->{'info'}->{'sig_width'}s // $signal->{'d'} [$signal->{'s'}]\n",
"$signal->{'n'};";
} else {
printf " always @(a_if.$signal->{'n'}) t_if.$signal->{'n'} <= a_if.$signal->{'n'};\n";
}
}
}
print qq{
`endif
};
}
# ----------------- # -----------------
sub show_modport{ sub show_modport{
my ($app, $role) = @_; my ($app, $role) = @_;

View File

@@ -32,7 +32,7 @@ class axi_monitor extends uvm_monitor; // #(axi_transaction);
// -------------------------------------------------- // --------------------------------------------------
// Set virtual interfaces // Set virtual interfaces
function void set_virtual_interfaces(virtual `AXI_INTF.MANAGER m_if_p, function void set_virtual_interfaces(virtual `AXI_INTF.MANAGER m_if_p,
virtual `AXI_INTF.SUBORDINATE s_if_p); virtual `AXI_INTF.SUBORDINATE s_if_p);
`uvm_info("set_virtual_interfaces", $sformatf("Setting virtual interfaces"), UVM_LOW) `uvm_info("set_virtual_interfaces", $sformatf("Setting virtual interfaces"), UVM_LOW)
m_if = m_if_p; m_if = m_if_p;
@@ -68,7 +68,6 @@ class axi_monitor extends uvm_monitor; // #(axi_transaction);
$fwrite(trk_file, "AXI monitor (%0s Mode)\n", agent_type.name()); $fwrite(trk_file, "AXI monitor (%0s Mode)\n", agent_type.name());
$fwrite(trk_file, "--------------------------------------------------\n"); $fwrite(trk_file, "--------------------------------------------------\n");
forever begin forever begin
@(posedge mon_if.ACLK); @(posedge mon_if.ACLK);
if (mon_if.ARESETn != 0) begin if (mon_if.ARESETn != 0) begin

View File

@@ -1,26 +1,30 @@
// Testbench interface for UVM-based verification environment // Testbench interface for UVM-based verification environment
interface testbench_if ( interface testbench_if (
input clk, output clk,
virtual axi_intf #(.ADDR_WIDTH(`ADDR_WIDTH), output rst_n
.CEIL_DATA_WIDTH_DIV_128(`CEIL_DATA_WIDTH_DIV_128), );
.CEIL_DATA_WIDTH_DIV_128_TMS_4(`CEIL_DATA_WIDTH_DIV_128_TMS_4),
.CEIL_DATA_WIDTH_DIV_64(`CEIL_DATA_WIDTH_DIV_64),
.DATA_WIDTH(`DATA_WIDTH),
.DATA_WIDTH_DIV_8(`DATA_WIDTH_DIV_8)) m_if,
virtual axi_intf #(.ADDR_WIDTH(`ADDR_WIDTH),
.CEIL_DATA_WIDTH_DIV_128(`CEIL_DATA_WIDTH_DIV_128),
.CEIL_DATA_WIDTH_DIV_128_TMS_4(`CEIL_DATA_WIDTH_DIV_128_TMS_4),
.CEIL_DATA_WIDTH_DIV_64(`CEIL_DATA_WIDTH_DIV_64),
.DATA_WIDTH(`DATA_WIDTH),
.DATA_WIDTH_DIV_8(`DATA_WIDTH_DIV_8)) s_if);
logic rst_n; logic clk_w;
logic rst_n_w;
assign clk = clk_w;
assign rst_n = rst_n_w;
// --------------------------------------------------
// Clock generation
initial begin initial begin
clk_w = 0; // Initialize clock to 0 at time 0
forever begin forever begin
@(clk or rst_n); #5ns clk_w = ~clk_w; // Toggle clock every 5 ns
$monitor("@%6t: %b %b ", $time,
rst_n, clk);
end end
end end
// --------------------------------------------------
// Initial reset
initial begin
rst_n_w = 0;
repeat(20) @(posedge clk_w);
rst_n_w = 1; // Release reset after 20 clocks
end
endinterface endinterface

View File

@@ -5,22 +5,17 @@ module tb_top (input logic sys_clk);
logic clk; logic clk;
logic rst_n; logic rst_n;
// Testbench interface to controll clocks, reset, etc.
testbench_if tb_if(.clk(clk), .rst_n(rst_n));
// AXI interface for manager and subordinate // AXI interface for manager and subordinate
`AXI_INTF a_if (.ACLK(clk), .ARESETn(rst_n)); `AXI_INTF a_if (.ACLK(clk), .ARESETn(rst_n));
// // Instantiate the UVM testbench interface
// testbench_if tb_if (
// .clk(clk),
// .m_if(m_if),
// .s_if(s_if)
// );
// assign tb_if.rst_n = rst_n;
// -------------------------------------------------- // --------------------------------------------------
initial begin initial begin
uvm_config_db#(virtual `AXI_INTF.MANAGER)::set(uvm_root::get(), "uvm_test_top.env.axi_m", "axi_dvr_vif", a_if.MANAGER); uvm_config_db#(virtual `AXI_INTF.MANAGER)::set(uvm_root::get(), "uvm_test_top.env.axi_m", "axi_dvr_vif", a_if.MANAGER);
uvm_config_db#(virtual `AXI_INTF.SUBORDINATE)::set(uvm_root::get(), "uvm_test_top.env.axi_s", "axi_dvr_vif", a_if.SUBORDINATE); uvm_config_db#(virtual `AXI_INTF.SUBORDINATE)::set(uvm_root::get(), "uvm_test_top.env.axi_s", "axi_dvr_vif", a_if.SUBORDINATE);
uvm_config_db#(virtual `AXI_INTF)::set(uvm_root::get(), "uvm_test_top.env", "axi_mon_vif", a_if); uvm_config_db#(virtual `AXI_INTF)::set(uvm_root::get(), "uvm_test_top.env", "axi_mon_vif", a_if);
uvm_config_db#(virtual testbench_if)::set(uvm_root::get(), "uvm_test_top.env", "tb_vif", tb_if);
run_test(); run_test();
end end
@@ -31,20 +26,5 @@ module tb_top (input logic sys_clk);
$dumpvars(0, "tb_top"); $dumpvars(0, "tb_top");
end end
// -------------------------------------------------- `include "verilator_trace_workaround.svh"
// Clock generation
// TODO: Move to interface. Parameterize frequency
initial begin
clk = 0; // Initialize clock to 0 at time 0
forever begin
#5ns clk = ~clk; // Toggle clock every 5 ns
end
end
// --------------------------------------------------
initial begin
rst_n = 0;
#20ns rst_n = 1; // Release reset after 20 ns
end
endmodule endmodule

View File

@@ -0,0 +1,124 @@
// Issue #5044: Wires driven through virtual interface traced improperly
// https://github.com/verilator/verilator/issues/5044
`ifdef VERI_TRACE_EN
// --------------------------------------------------
// Work around Verilator's lack of support for virutal interface tracing
`AXI_INTF t_if (.ACLK(clk), .ARESETn(rst_n));
// A2.4.1 Clock and reset signals
// External signal: ACLK; // External Global clock signal [External]
// External signal: ARESETn; // External Global reset signal [External]
// A2.1.1 Write request channel
always @(a_if.AWVALID) t_if.AWVALID <= a_if.AWVALID;
always @(a_if.AWREADY) t_if.AWREADY <= a_if.AWREADY;
always @(a_if.AWID) t_if.AWID <= a_if.AWID;
always @(a_if.AWADDR) t_if.AWADDR <= a_if.AWADDR;
always @(a_if.AWREGION) t_if.AWREGION <= a_if.AWREGION;
always @(a_if.AWLEN) t_if.AWLEN <= a_if.AWLEN;
always @(a_if.AWSIZE) t_if.AWSIZE <= a_if.AWSIZE;
always @(a_if.AWBURST) t_if.AWBURST <= a_if.AWBURST;
always @(a_if.AWLOCK) t_if.AWLOCK <= a_if.AWLOCK;
always @(a_if.AWCACHE) t_if.AWCACHE <= a_if.AWCACHE;
always @(a_if.AWPROT) t_if.AWPROT <= a_if.AWPROT;
always @(a_if.AWNSE) t_if.AWNSE <= a_if.AWNSE;
always @(a_if.AWQOS) t_if.AWQOS <= a_if.AWQOS;
always @(a_if.AWUSER) t_if.AWUSER <= a_if.AWUSER;
always @(a_if.AWDOMAIN) t_if.AWDOMAIN <= a_if.AWDOMAIN;
always @(a_if.AWSNOOP) t_if.AWSNOOP <= a_if.AWSNOOP;
always @(a_if.AWSTASHNID) t_if.AWSTASHNID <= a_if.AWSTASHNID;
always @(a_if.AWSTASHNIDEN) t_if.AWSTASHNIDEN <= a_if.AWSTASHNIDEN;
always @(a_if.AWSTASHLPID) t_if.AWSTASHLPID <= a_if.AWSTASHLPID;
always @(a_if.AWSTASHLPIDEN) t_if.AWSTASHLPIDEN <= a_if.AWSTASHLPIDEN;
always @(a_if.AWTRACE) t_if.AWTRACE <= a_if.AWTRACE;
always @(a_if.AWLOOP) t_if.AWLOOP <= a_if.AWLOOP;
always @(a_if.AWMMUVALID) t_if.AWMMUVALID <= a_if.AWMMUVALID;
always @(a_if.AWMMUSECSID) t_if.AWMMUSECSID <= a_if.AWMMUSECSID;
always @(a_if.AWMMUSID) t_if.AWMMUSID <= a_if.AWMMUSID;
always @(a_if.AWMMUSSIDV) t_if.AWMMUSSIDV <= a_if.AWMMUSSIDV;
always @(a_if.AWMMUSSID) t_if.AWMMUSSID <= a_if.AWMMUSSID;
always @(a_if.AWMMUATST) t_if.AWMMUATST <= a_if.AWMMUATST;
always @(a_if.AWMMUFLOW) t_if.AWMMUFLOW <= a_if.AWMMUFLOW;
always @(a_if.AWPBHA) t_if.AWPBHA <= a_if.AWPBHA;
always @(a_if.AWNSAID) t_if.AWNSAID <= a_if.AWNSAID;
always @(a_if.AWSUBSYSID) t_if.AWSUBSYSID <= a_if.AWSUBSYSID;
always @(a_if.AWATOP) t_if.AWATOP <= a_if.AWATOP;
always @(a_if.AWMPAM) t_if.AWMPAM <= a_if.AWMPAM;
always @(a_if.AWIDUNQ) t_if.AWIDUNQ <= a_if.AWIDUNQ;
always @(a_if.AWCMO) t_if.AWCMO <= a_if.AWCMO;
always @(a_if.AWTAGOP) t_if.AWTAGOP <= a_if.AWTAGOP;
always @(a_if.AWMECID) t_if.AWMECID <= a_if.AWMECID;
// A2.1.1 Write request channel
always @(a_if.WVALID) t_if.WVALID <= a_if.WVALID;
always @(a_if.WREADY) t_if.WREADY <= a_if.WREADY;
always @(a_if.WDATA) t_if.WDATA <= a_if.WDATA;
always @(a_if.WSTRB) t_if.WSTRB <= a_if.WSTRB;
always @(a_if.WTAG) t_if.WTAG <= a_if.WTAG;
always @(a_if.WTAGUPDATE) t_if.WTAGUPDATE <= a_if.WTAGUPDATE;
always @(a_if.WLAST) t_if.WLAST <= a_if.WLAST;
always @(a_if.WUSER) t_if.WUSER <= a_if.WUSER;
always @(a_if.WPOISON) t_if.WPOISON <= a_if.WPOISON;
always @(a_if.WTRACE) t_if.WTRACE <= a_if.WTRACE;
// A2.1.3 Write response channel
always @(a_if.BVALID) t_if.BVALID <= a_if.BVALID;
always @(a_if.BREADY) t_if.BREADY <= a_if.BREADY;
always @(a_if.BID) t_if.BID <= a_if.BID;
always @(a_if.BIDUNQ) t_if.BIDUNQ <= a_if.BIDUNQ;
always @(a_if.BRESP) t_if.BRESP <= a_if.BRESP;
always @(a_if.BCOMP) t_if.BCOMP <= a_if.BCOMP;
always @(a_if.BPERSIST) t_if.BPERSIST <= a_if.BPERSIST;
always @(a_if.BTAGMATCH) t_if.BTAGMATCH <= a_if.BTAGMATCH;
always @(a_if.BUSER) t_if.BUSER <= a_if.BUSER;
always @(a_if.BTRACE) t_if.BTRACE <= a_if.BTRACE;
always @(a_if.BLOOP) t_if.BLOOP <= a_if.BLOOP;
always @(a_if.BBUSY) t_if.BBUSY <= a_if.BBUSY;
// A2.2.1 Read request channel
always @(a_if.ARVALID) t_if.ARVALID <= a_if.ARVALID;
always @(a_if.ARREADY) t_if.ARREADY <= a_if.ARREADY;
always @(a_if.ARID) t_if.ARID <= a_if.ARID;
always @(a_if.ARADDR) t_if.ARADDR <= a_if.ARADDR;
always @(a_if.ARREGION) t_if.ARREGION <= a_if.ARREGION;
always @(a_if.ARLEN) t_if.ARLEN <= a_if.ARLEN;
always @(a_if.ARSIZE) t_if.ARSIZE <= a_if.ARSIZE;
always @(a_if.ARBURST) t_if.ARBURST <= a_if.ARBURST;
always @(a_if.ARLOCK) t_if.ARLOCK <= a_if.ARLOCK;
always @(a_if.ARCACHE) t_if.ARCACHE <= a_if.ARCACHE;
always @(a_if.ARPROT) t_if.ARPROT <= a_if.ARPROT;
always @(a_if.ARNSE) t_if.ARNSE <= a_if.ARNSE;
always @(a_if.ARQOS) t_if.ARQOS <= a_if.ARQOS;
always @(a_if.ARUSER) t_if.ARUSER <= a_if.ARUSER;
always @(a_if.ARDOMAIN) t_if.ARDOMAIN <= a_if.ARDOMAIN;
always @(a_if.ARSNOOP) t_if.ARSNOOP <= a_if.ARSNOOP;
always @(a_if.ARTRACE) t_if.ARTRACE <= a_if.ARTRACE;
always @(a_if.ARLOOP) t_if.ARLOOP <= a_if.ARLOOP;
always @(a_if.ARMMUVALID) t_if.ARMMUVALID <= a_if.ARMMUVALID;
always @(a_if.ARMMUSECSID) t_if.ARMMUSECSID <= a_if.ARMMUSECSID;
always @(a_if.ARMMUSID) t_if.ARMMUSID <= a_if.ARMMUSID;
always @(a_if.ARMMUSSIDV) t_if.ARMMUSSIDV <= a_if.ARMMUSSIDV;
always @(a_if.ARMMUSSID) t_if.ARMMUSSID <= a_if.ARMMUSSID;
always @(a_if.ARMMUATST) t_if.ARMMUATST <= a_if.ARMMUATST;
always @(a_if.ARMMUFLOW) t_if.ARMMUFLOW <= a_if.ARMMUFLOW;
always @(a_if.ARPBHA) t_if.ARPBHA <= a_if.ARPBHA;
always @(a_if.ARNSAID) t_if.ARNSAID <= a_if.ARNSAID;
always @(a_if.ARSUBSYSID) t_if.ARSUBSYSID <= a_if.ARSUBSYSID;
always @(a_if.ARCHUNKEN) t_if.ARCHUNKEN <= a_if.ARCHUNKEN;
always @(a_if.ARIDUNQ) t_if.ARIDUNQ <= a_if.ARIDUNQ;
always @(a_if.ARTAGOP) t_if.ARTAGOP <= a_if.ARTAGOP;
always @(a_if.ARMECID) t_if.ARMECID <= a_if.ARMECID;
// A2.2.2 Read data channel
always @(a_if.RVALID) t_if.RVALID <= a_if.RVALID;
always @(a_if.RREADY) t_if.RREADY <= a_if.RREADY;
always @(a_if.RID) t_if.RID <= a_if.RID;
always @(a_if.RIDUNQ) t_if.RIDUNQ <= a_if.RIDUNQ;
always @(a_if.RDATA) t_if.RDATA <= a_if.RDATA;
always @(a_if.RTAG) t_if.RTAG <= a_if.RTAG;
always @(a_if.RRESP) t_if.RRESP <= a_if.RRESP;
always @(a_if.RLAST) t_if.RLAST <= a_if.RLAST;
always @(a_if.RUSER) t_if.RUSER <= a_if.RUSER;
always @(a_if.RPOISON) t_if.RPOISON <= a_if.RPOISON;
always @(a_if.RTRACE) t_if.RTRACE <= a_if.RTRACE;
always @(a_if.RLOOP) t_if.RLOOP <= a_if.RLOOP;
always @(a_if.RCHUNKV) t_if.RCHUNKV <= a_if.RCHUNKV;
always @(a_if.RCHUNKNUM) t_if.RCHUNKNUM <= a_if.RCHUNKNUM;
always @(a_if.RCHUNKSTRB) t_if.RCHUNKSTRB <= a_if.RCHUNKSTRB;
always @(a_if.RBUSY) t_if.RBUSY <= a_if.RBUSY;
`endif