Interface clean up. WA for verilator tracing
This commit is contained in:
5
Makefile
5
Makefile
@@ -28,6 +28,9 @@ CPP_SRC=sim_$(PROJ).cpp
|
||||
|
||||
TIMESCALE= --timescale '1ns/1ns'
|
||||
|
||||
ifndef VERI_TRACE_DIS
|
||||
TB_DEFINES=+define+VERI_TRACE_EN
|
||||
endif
|
||||
UVM_DEFINES=+define+UVM_NO_DPI \
|
||||
+define+UVM_REPORT_DISABLE_FILE_LINE
|
||||
DISABLED_WARNINGS=-Wno-WIDTHTRUNC -Wno-WIDTHEXPAND \
|
||||
@@ -41,7 +44,9 @@ BUILD_ARGS=-I$(UVM_HOME)/src -I. \
|
||||
--error-limit 10 \
|
||||
--timing $(TIMESCALE) \
|
||||
--trace \
|
||||
--top tb_top \
|
||||
+define+SVA_ON \
|
||||
$(TB_DEFINES) \
|
||||
$(UVM_DEFINES) \
|
||||
$(DISABLED_WARNINGS) \
|
||||
+incdir+common +incdir+src/axi +incdir+tb \
|
||||
|
47
axi.gtkw
Normal file
47
axi.gtkw
Normal 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
|
@@ -38,6 +38,8 @@ sub gen_intf {
|
||||
show_modport($app, 'Subordinate');
|
||||
|
||||
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{
|
||||
my ($app, $role) = @_;
|
||||
|
@@ -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, "--------------------------------------------------\n");
|
||||
|
||||
|
||||
forever begin
|
||||
@(posedge mon_if.ACLK);
|
||||
if (mon_if.ARESETn != 0) begin
|
||||
|
@@ -1,26 +1,30 @@
|
||||
// Testbench interface for UVM-based verification environment
|
||||
interface testbench_if (
|
||||
input clk,
|
||||
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)) 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);
|
||||
output clk,
|
||||
output rst_n
|
||||
);
|
||||
|
||||
logic rst_n;
|
||||
logic clk_w;
|
||||
logic rst_n_w;
|
||||
|
||||
assign clk = clk_w;
|
||||
assign rst_n = rst_n_w;
|
||||
|
||||
// --------------------------------------------------
|
||||
// Clock generation
|
||||
initial begin
|
||||
clk_w = 0; // Initialize clock to 0 at time 0
|
||||
forever begin
|
||||
@(clk or rst_n);
|
||||
$monitor("@%6t: %b %b ", $time,
|
||||
rst_n, clk);
|
||||
#5ns clk_w = ~clk_w; // Toggle clock every 5 ns
|
||||
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
|
||||
|
28
tb/tb_top.sv
28
tb/tb_top.sv
@@ -5,22 +5,17 @@ module tb_top (input logic sys_clk);
|
||||
logic clk;
|
||||
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_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
|
||||
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)::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();
|
||||
end
|
||||
@@ -31,20 +26,5 @@ module tb_top (input logic sys_clk);
|
||||
$dumpvars(0, "tb_top");
|
||||
end
|
||||
|
||||
// --------------------------------------------------
|
||||
// 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
|
||||
`include "verilator_trace_workaround.svh"
|
||||
endmodule
|
||||
|
124
tb/verilator_trace_workaround.svh
Normal file
124
tb/verilator_trace_workaround.svh
Normal 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
|
Reference in New Issue
Block a user