Transaction driving and responding updates. Tracker updates

This commit is contained in:
2025-12-28 18:08:21 -08:00
parent 90dbd81844
commit e1b0143830
8 changed files with 196 additions and 59 deletions

View File

@@ -4,5 +4,7 @@
.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))
.DATA_WIDTH_DIV_8(`DATA_WIDTH_DIV_8), \
.BRESP_WIDTH(`BRESP_WIDTH) \
)

View File

@@ -6,7 +6,7 @@
// `define ARSNOOP_WIDTH 1
// `define AWCMO_WIDTH 1
// `define AWSNOOP_WIDTH 1
// `define BRESP_WIDTH 1
`define BRESP_WIDTH 1
`define CEIL_DATA_WIDTH_DIV_128 1
`define CEIL_DATA_WIDTH_DIV_128_TMS_4 4
`define CEIL_DATA_WIDTH_DIV_64 1

View File

@@ -9,6 +9,9 @@ class axi_driver extends uvm_driver; // #(axi_transaction);
axi_agent_type_t agent_type;
axi_agent_config cfg;
// Filehandle for transaction tracker file
int trk_file;
`uvm_component_utils(axi_driver)
// --------------------------------------------------
@@ -41,4 +44,32 @@ class axi_driver extends uvm_driver; // #(axi_transaction);
cfg = agt.get_cfg();
end
endfunction
// --------------------------------------------------
// Run phase
virtual function void run_phase(uvm_phase phase);
// Open transaction log file
trk_file = $fopen($sformatf("axi_driver.%s.log", agent_type.name()), "w");
if (trk_file == 0) begin
`uvm_error("run_phase", "Failed to open transaction log file")
end else begin
`uvm_info("run_phase", "Transaction log file opened successfully", UVM_LOW)
end
// Start driver
drive_axi(phase);
endfunction
// --------------------------------------------------
virtual task drive_axi(uvm_phase phase);
$fwrite(trk_file, "AXI driver (%0s Mode)\n", agent_type.name());
$fwrite(trk_file, "--------------------------------------------------\n");
$fwrite(trk_file, "%s\n", axi_transaction::tracker_line_hdr());
endtask
// --------------------------------------------------
// Function to write captured transaction into a file
function void write_transaction_to_file(axi_transaction txn);
$fwrite(trk_file, "%s\n", txn.tracker_line());
endfunction
endclass : axi_driver

View File

@@ -19,25 +19,27 @@ class axi_manager_driver extends axi_driver;
endfunction
// --------------------------------------------------
virtual task run_phase(uvm_phase phase);
`uvm_info("run_phase", $sformatf("Running AXI manager driver: %s",
virtual task drive_axi(uvm_phase phase);
super.drive_axi(phase);
`uvm_info("drive_axi", $sformatf("Running AXI manager driver: %s",
get_full_name()), UVM_LOW)
if (m_if == null) begin
`uvm_error("run_phase", "MANAGER interface is null, cannot drive transactions")
`uvm_error("drive_axi", "MANAGER interface is null, cannot drive transactions")
end
forever begin
`uvm_info("run_phase", $sformatf("Starting to drive transactions for %s (rst_n = %0b)",
`uvm_info("drive_axi", $sformatf("Starting to drive transactions for %s (rst_n = %0b)",
get_full_name(), m_if.ARESETn), UVM_LOW)
// Wait for reset to be de-asserted
if (m_if.ARESETn == 0) begin
`uvm_info("run_phase", $sformatf("Waiting for reset to be released (rst_n = %0b)",
`uvm_info("drive_axi", $sformatf("Waiting for reset to be released (rst_n = %0b)",
m_if.ARESETn), UVM_LOW)
@(posedge m_if.ARESETn);
end
`uvm_info("run_phase", $sformatf("Starting to drive transactions for %s (rst_n = %0b)",
`uvm_info("drive_axi", $sformatf("Starting to drive transactions for %s (rst_n = %0b)",
get_full_name(), m_if.ARESETn), UVM_LOW)
// Drive transactions until reset is asserted
@@ -45,7 +47,7 @@ class axi_manager_driver extends axi_driver;
uvm_sequence_item txn;
axi_transaction req;
`uvm_info("run_phase", $sformatf("Waiting for next transaction"), UVM_LOW)
`uvm_info("drive_axi", $sformatf("Waiting for next transaction"), UVM_LOW)
seq_item_port.get_next_item(txn);
@@ -53,9 +55,9 @@ class axi_manager_driver extends axi_driver;
`uvm_fatal("drive_txn", "Invalid transaction type")
end
while (txn_trk.size() > (3-1)) begin
`uvm_info("run_phase", $sformatf("Waiting for next transaction Txn-trk size=%0d to be under 3", txn_trk.size()), UVM_LOW)
`uvm_info("drive_axi", $sformatf("Waiting for next transaction Txn-trk size=%0d to be under 3", txn_trk.size()), UVM_LOW)
@(txn_trk.size());
`uvm_info("run_phase", $sformatf("Txn-trk size changed to %0d to be under 3", txn_trk.size()), UVM_LOW)
`uvm_info("drive_axi", $sformatf("Txn-trk size changed to %0d to be under 3", txn_trk.size()), UVM_LOW)
end
fork
drive_txn(req);
@@ -73,6 +75,8 @@ class axi_manager_driver extends axi_driver;
`uvm_info("drive_txn", $sformatf("Driving AXI transaction ID=%s:\n%s",
req.show_tid(), req.sprint()), UVM_LOW)
write_transaction_to_file(req);
txn_trk[tid] = req;
// Pre transaction delay

View File

@@ -2,13 +2,11 @@
// Monitor for AXI transactions
// ----------------------------------------------------------------------
class axi_monitor extends uvm_monitor; // #(axi_transaction);
virtual `AXI_INTF.MANAGER m_if;
virtual `AXI_INTF.SUBORDINATE s_if;
virtual `AXI_INTF mon_if;
axi_agent_type_t agent_type;
// Declare the analysis export
uvm_analysis_port ap;
uvm_analysis_port#(axi_transaction) ap;
// Filehandle for transaction tracker file
int trk_file;
@@ -34,9 +32,6 @@ class axi_monitor extends uvm_monitor; // #(axi_transaction);
function void set_virtual_interfaces(virtual `AXI_INTF.MANAGER m_if_p,
virtual `AXI_INTF.SUBORDINATE s_if_p);
`uvm_info("set_virtual_interfaces", $sformatf("Setting virtual interfaces"), UVM_LOW)
m_if = m_if_p;
s_if = s_if_p;
endfunction
// --------------------------------------------------
@@ -68,62 +63,135 @@ class axi_monitor extends uvm_monitor; // #(axi_transaction);
$fwrite(trk_file, "AXI monitor (%0s Mode)\n", agent_type.name());
$fwrite(trk_file, "--------------------------------------------------\n");
fork
monitor_write();
monitor_read();
join
endtask
// --------------------------------------------------
// Monitor logic for Write transactions
virtual task monitor_write();
bit prev_awready, prev_awvalid;
bit prev_wready, prev_wvalid;
bit prev_bready, prev_bvalid;
axi_transaction txn;
int txn_ph = 0; // IDLE
forever begin
@(posedge mon_if.ACLK);
if (mon_if.ARESETn != 0) begin
if ((mon_if.AWVALID == 1) && (mon_if.AWREADY == 1)) begin
$fwrite(trk_file, "%10t: AXI WRITE - ADDR=0x%h DATA=0x%h STRB=%h\n",
$time, mon_if.AWADDR, mon_if.WDATA, mon_if.WSTRB);
end
if ((mon_if.ARVALID == 1) && (mon_if.ARREADY == 1)) begin
$fwrite(trk_file, "%10t: AXI READ - ADDR=0x%h\n",
$time, mon_if.ARADDR);
// Address phase
if (txn_ph == 0) begin
if (((mon_if.AWREADY != prev_awready) || (mon_if.AWVALID != prev_awvalid))
&& ((mon_if.AWREADY === 1'b1) && (mon_if.AWVALID === 1'b1))) begin
txn_ph = 1; // ADDR
txn = axi_transaction::type_id::create("txn");
// Capture transaction details here
txn.txn_type = AXI_WRITE;
txn.addr = mon_if.AWADDR;
txn.length = mon_if.AWLEN;
end
end
end
// if (agent_type == MANAGER) begin
// do_manager_monitor();
// end else if (agent_type == SUBORDINATE) begin
// do_subordinate_monitor();
// end else begin
// `uvm_fatal("AXI_MONITOR", "Unknown agent type")
// end
endtask
// Data phase - may overlap with address phase
if (txn_ph inside {0, 1}) begin
if (((mon_if.WREADY != prev_wready) || (mon_if.WVALID != prev_wvalid))
&& ((mon_if.WREADY === 1'b1) && (mon_if.WVALID === 1'b1))) begin
txn_ph = 2; // DATA
// --------------------------------------------------
// Monitor logic for MANAGER agent
virtual task do_manager_monitor();
// Placeholder for actual monitoring logic
// This would typically involve sampling signals and creating transactions
forever begin
axi_transaction txn;
@(posedge m_if.ACLK);
// Capture transaction details here
txn.data = mon_if.WDATA;
txn.strb = mon_if.WSTRB;
end
end
txn = axi_transaction::type_id::create("txn");
// Response phase - must come after address and data phases
if (txn_ph == 2) begin
if (((mon_if.BREADY != prev_bready) || (mon_if.BVALID != prev_bvalid))
&& ((mon_if.BREADY === 1'b1) && (mon_if.BVALID === 1'b1))) begin
txn_ph = 2; // DATA
// Capture transaction details here
// Capture transaction details here
txn.resp = mon_if.WSTRB;
ap.write(txn);
write_transaction_to_file(txn);
ap.write(txn);
write_transaction_to_file(txn);
end
end
// Update previous values
prev_awready = mon_if.AWREADY;
prev_awvalid = mon_if.AWVALID;
prev_wready = mon_if.WREADY;
prev_wvalid = mon_if.WVALID;
prev_bready = mon_if.BREADY;
prev_bvalid = mon_if.BVALID;
end
endtask
// --------------------------------------------------
// Monitor logic for SUBORDINATE agent
virtual task do_subordinate_monitor();
// Placeholder for actual monitoring logic
// This would typically involve sampling signals and creating transactions
// Monitor logic for Read transactions
virtual task monitor_read();
bit prev_arready, prev_arvalid;
bit prev_rready, prev_rvalid;
axi_transaction txn;
int txn_ph = 0;
forever begin
axi_transaction txn;
@(posedge s_if.ACLK);
@(posedge mon_if.ACLK);
txn = axi_transaction::type_id::create("txn");
// Address phase
if (txn_ph == 0) begin
if (((mon_if.ARREADY != prev_arready) || (mon_if.ARVALID != prev_arvalid))
&& ((mon_if.ARREADY === 1'b1) && (mon_if.ARVALID === 1'b1))) begin
txn_ph = 1;
// Capture transaction details here
txn = axi_transaction::type_id::create("txn");
ap.write(txn);
write_transaction_to_file(txn);
// Capture transaction details here
txn.txn_type = AXI_READ;
txn.addr = mon_if.ARADDR;
txn.length = mon_if.ARLEN;
end
end
// Data/response phase - must come after address phase
if (txn_ph == 1) begin
if (((mon_if.RREADY != prev_rready) || (mon_if.RVALID != prev_rvalid))
&& ((mon_if.RREADY === 1'b1) && (mon_if.RVALID === 1'b1))) begin
txn_ph = 0;
// Capture transaction details here
txn.data = mon_if.RDATA;
ap.write(txn);
write_transaction_to_file(txn);
end
end
if (((mon_if.ARREADY != prev_arready) || (mon_if.ARVALID != prev_arvalid))
&& ((mon_if.ARREADY === 1'b1) && (mon_if.ARVALID === 1'b1))) begin
axi_transaction txn;
txn = axi_transaction::type_id::create("txn");
// Capture transaction details here
txn.txn_type = AXI_READ;
txn.addr = mon_if.ARADDR;
txn.length = mon_if.ARLEN;
ap.write(txn);
write_transaction_to_file(txn);
end
// Update previous values
prev_arready = mon_if.ARREADY;
prev_arvalid = mon_if.ARVALID;
prev_rready = mon_if.RREADY;
prev_rvalid = mon_if.RVALID;
end
endtask

View File

@@ -18,12 +18,14 @@ class axi_subordinate_driver extends axi_driver;
endfunction
// --------------------------------------------------
virtual task run_phase(uvm_phase phase);
`uvm_info("run_phase", $sformatf("Running AXI subordinate driver: %s",
virtual task drive_axi(uvm_phase phase);
super.drive_axi(phase);
`uvm_info("drive_axi", $sformatf("Running AXI subordinate driver: %s",
get_full_name()), UVM_LOW)
if (s_if == null) begin
`uvm_error("run_phase", "subordinate interface is null, cannot respond to transactions")
`uvm_error("drive_axi", "subordinate interface is null, cannot respond to transactions")
end
forever begin
@@ -118,6 +120,9 @@ class axi_subordinate_driver extends axi_driver;
s_if.BVALID = 0;
`uvm_info("respond_to_write_txn", $sformatf("[%s] Response phase done",
req.show_tag()), UVM_LOW)
write_transaction_to_file(req);
write_request_sem.put();
endtask
@@ -177,6 +182,8 @@ class axi_subordinate_driver extends axi_driver;
`uvm_info("respond_to_read_txn", $sformatf("[%s] Response phase done",
req.show_tag()), UVM_LOW)
write_transaction_to_file(req);
read_request_sem.put();
endtask
endclass : axi_subordinate_driver

View File

@@ -5,6 +5,7 @@ class axi_transaction extends uvm_sequence_item;
rand bit [`ADDR_WIDTH-1:0] addr; // Address
rand bit [`DATA_WIDTH-1:0] data; // Data
rand bit [`DATA_WIDTH_DIV_8-1:0] strb; // Byte enable
rand bit [`BRESP_WIDTH-1:0] resp; // Response code
rand bit [2:0] size; // Size
rand bit [7:0] length; // Length
@@ -13,6 +14,7 @@ class axi_transaction extends uvm_sequence_item;
`uvm_field_int(addr, UVM_DEFAULT)
`uvm_field_int(data, UVM_DEFAULT)
`uvm_field_int(strb, UVM_DEFAULT)
`uvm_field_int(resp, UVM_DEFAULT)
`uvm_field_int(size, UVM_DEFAULT)
`uvm_field_int(length, UVM_DEFAULT)
`uvm_object_utils_end
@@ -58,6 +60,7 @@ class axi_transaction extends uvm_sequence_item;
copy.addr = this.addr;
copy.data = this.data;
copy.strb = this.strb;
copy.resp = this.resp;
copy.size = this.size;
copy.length = this.length;
return copy;
@@ -75,5 +78,17 @@ class axi_transaction extends uvm_sequence_item;
(this.length == other.length);
endfunction
// Tracker print line
static function string tracker_line_hdr();
return $sformatf("%7s %10s %16s %16s %4s %3s %3s",
"TIME", "TYPE", "ADDR", "DATA", "STRB", "SZ", "LEN");
endfunction
function string tracker_line();
return $sformatf("%7t %10s %16h %16h %4h %3d %3d",
$time, this.txn_type.name(), this.addr,
this.data, this.strb, this.size, this.length);
endfunction
endclass : axi_transaction

View File

@@ -20,6 +20,8 @@ class tb_env extends uvm_env;
// Set agent types in AXI agents
axi_m.set_agent_type(MANAGER);
axi_s.set_agent_type(SUBORDINATE);
set_up_reporting();
endfunction
// ------------------------------------------------------------
@@ -33,6 +35,14 @@ class tb_env extends uvm_env;
// Add any specific report phase tasks here
endfunction
// ------------------------------------------------------------
function void set_up_reporting();
uvm_coreservice_t cs = uvm_coreservice_t::get();
uvm_tree_printer tree_printer = new();
cs.set_default_printer(tree_printer);
endfunction
// ------------------------------------------------------------
function uvm_sequencer_base get_axi_m_sequencer();
return axi_m.sequencer;