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_128_TMS_4(`CEIL_DATA_WIDTH_DIV_128_TMS_4), \
.CEIL_DATA_WIDTH_DIV_64(`CEIL_DATA_WIDTH_DIV_64), \ .CEIL_DATA_WIDTH_DIV_64(`CEIL_DATA_WIDTH_DIV_64), \
.DATA_WIDTH(`DATA_WIDTH), \ .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 ARSNOOP_WIDTH 1
// `define AWCMO_WIDTH 1 // `define AWCMO_WIDTH 1
// `define AWSNOOP_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 1
`define CEIL_DATA_WIDTH_DIV_128_TMS_4 4 `define CEIL_DATA_WIDTH_DIV_128_TMS_4 4
`define CEIL_DATA_WIDTH_DIV_64 1 `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_type_t agent_type;
axi_agent_config cfg; axi_agent_config cfg;
// Filehandle for transaction tracker file
int trk_file;
`uvm_component_utils(axi_driver) `uvm_component_utils(axi_driver)
// -------------------------------------------------- // --------------------------------------------------
@@ -41,4 +44,32 @@ class axi_driver extends uvm_driver; // #(axi_transaction);
cfg = agt.get_cfg(); cfg = agt.get_cfg();
end end
endfunction 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 endclass : axi_driver

View File

@@ -19,25 +19,27 @@ class axi_manager_driver extends axi_driver;
endfunction endfunction
// -------------------------------------------------- // --------------------------------------------------
virtual task run_phase(uvm_phase phase); virtual task drive_axi(uvm_phase phase);
`uvm_info("run_phase", $sformatf("Running AXI manager driver: %s", super.drive_axi(phase);
`uvm_info("drive_axi", $sformatf("Running AXI manager driver: %s",
get_full_name()), UVM_LOW) get_full_name()), UVM_LOW)
if (m_if == null) begin 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 end
forever begin 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) get_full_name(), m_if.ARESETn), UVM_LOW)
// Wait for reset to be de-asserted // Wait for reset to be de-asserted
if (m_if.ARESETn == 0) begin 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) m_if.ARESETn), UVM_LOW)
@(posedge m_if.ARESETn); @(posedge m_if.ARESETn);
end 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) get_full_name(), m_if.ARESETn), UVM_LOW)
// Drive transactions until reset is asserted // Drive transactions until reset is asserted
@@ -45,7 +47,7 @@ class axi_manager_driver extends axi_driver;
uvm_sequence_item txn; uvm_sequence_item txn;
axi_transaction req; 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); 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") `uvm_fatal("drive_txn", "Invalid transaction type")
end end
while (txn_trk.size() > (3-1)) begin 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()); @(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 end
fork fork
drive_txn(req); 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", `uvm_info("drive_txn", $sformatf("Driving AXI transaction ID=%s:\n%s",
req.show_tid(), req.sprint()), UVM_LOW) req.show_tid(), req.sprint()), UVM_LOW)
write_transaction_to_file(req);
txn_trk[tid] = req; txn_trk[tid] = req;
// Pre transaction delay // Pre transaction delay

View File

@@ -2,13 +2,11 @@
// Monitor for AXI transactions // Monitor for AXI transactions
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
class axi_monitor extends uvm_monitor; // #(axi_transaction); 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; virtual `AXI_INTF mon_if;
axi_agent_type_t agent_type; axi_agent_type_t agent_type;
// Declare the analysis export // Declare the analysis export
uvm_analysis_port ap; uvm_analysis_port#(axi_transaction) ap;
// Filehandle for transaction tracker file // Filehandle for transaction tracker file
int trk_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, 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;
s_if = s_if_p;
endfunction 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, "AXI monitor (%0s Mode)\n", agent_type.name());
$fwrite(trk_file, "--------------------------------------------------\n"); $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 forever begin
@(posedge mon_if.ACLK); @(posedge mon_if.ACLK);
if (mon_if.ARESETn != 0) begin
if ((mon_if.AWVALID == 1) && (mon_if.AWREADY == 1)) begin // Address phase
$fwrite(trk_file, "%10t: AXI WRITE - ADDR=0x%h DATA=0x%h STRB=%h\n", if (txn_ph == 0) begin
$time, mon_if.AWADDR, mon_if.WDATA, mon_if.WSTRB); if (((mon_if.AWREADY != prev_awready) || (mon_if.AWVALID != prev_awvalid))
end && ((mon_if.AWREADY === 1'b1) && (mon_if.AWVALID === 1'b1))) begin
if ((mon_if.ARVALID == 1) && (mon_if.ARREADY == 1)) begin txn_ph = 1; // ADDR
$fwrite(trk_file, "%10t: AXI READ - ADDR=0x%h\n",
$time, mon_if.ARADDR); 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 end
end
// if (agent_type == MANAGER) begin // Data phase - may overlap with address phase
// do_manager_monitor(); if (txn_ph inside {0, 1}) begin
// end else if (agent_type == SUBORDINATE) begin if (((mon_if.WREADY != prev_wready) || (mon_if.WVALID != prev_wvalid))
// do_subordinate_monitor(); && ((mon_if.WREADY === 1'b1) && (mon_if.WVALID === 1'b1))) begin
// end else begin txn_ph = 2; // DATA
// `uvm_fatal("AXI_MONITOR", "Unknown agent type")
// end
endtask
// -------------------------------------------------- // Capture transaction details here
// Monitor logic for MANAGER agent txn.data = mon_if.WDATA;
virtual task do_manager_monitor(); txn.strb = mon_if.WSTRB;
// Placeholder for actual monitoring logic end
// This would typically involve sampling signals and creating transactions end
forever begin
axi_transaction txn;
@(posedge m_if.ACLK);
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); ap.write(txn);
write_transaction_to_file(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 end
endtask endtask
// -------------------------------------------------- // --------------------------------------------------
// Monitor logic for SUBORDINATE agent // Monitor logic for Read transactions
virtual task do_subordinate_monitor(); virtual task monitor_read();
// Placeholder for actual monitoring logic bit prev_arready, prev_arvalid;
// This would typically involve sampling signals and creating transactions bit prev_rready, prev_rvalid;
axi_transaction txn;
int txn_ph = 0;
forever begin forever begin
axi_transaction txn; @(posedge mon_if.ACLK);
@(posedge s_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); // Capture transaction details here
write_transaction_to_file(txn); 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 end
endtask endtask

View File

@@ -18,12 +18,14 @@ class axi_subordinate_driver extends axi_driver;
endfunction endfunction
// -------------------------------------------------- // --------------------------------------------------
virtual task run_phase(uvm_phase phase); virtual task drive_axi(uvm_phase phase);
`uvm_info("run_phase", $sformatf("Running AXI subordinate driver: %s", super.drive_axi(phase);
`uvm_info("drive_axi", $sformatf("Running AXI subordinate driver: %s",
get_full_name()), UVM_LOW) get_full_name()), UVM_LOW)
if (s_if == null) begin 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 end
forever begin forever begin
@@ -118,6 +120,9 @@ class axi_subordinate_driver extends axi_driver;
s_if.BVALID = 0; s_if.BVALID = 0;
`uvm_info("respond_to_write_txn", $sformatf("[%s] Response phase done", `uvm_info("respond_to_write_txn", $sformatf("[%s] Response phase done",
req.show_tag()), UVM_LOW) req.show_tag()), UVM_LOW)
write_transaction_to_file(req);
write_request_sem.put(); write_request_sem.put();
endtask endtask
@@ -177,6 +182,8 @@ class axi_subordinate_driver extends axi_driver;
`uvm_info("respond_to_read_txn", $sformatf("[%s] Response phase done", `uvm_info("respond_to_read_txn", $sformatf("[%s] Response phase done",
req.show_tag()), UVM_LOW) req.show_tag()), UVM_LOW)
write_transaction_to_file(req);
read_request_sem.put(); read_request_sem.put();
endtask endtask
endclass : axi_subordinate_driver 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 [`ADDR_WIDTH-1:0] addr; // Address
rand bit [`DATA_WIDTH-1:0] data; // Data rand bit [`DATA_WIDTH-1:0] data; // Data
rand bit [`DATA_WIDTH_DIV_8-1:0] strb; // Byte enable 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 [2:0] size; // Size
rand bit [7:0] length; // Length 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(addr, UVM_DEFAULT)
`uvm_field_int(data, UVM_DEFAULT) `uvm_field_int(data, UVM_DEFAULT)
`uvm_field_int(strb, UVM_DEFAULT) `uvm_field_int(strb, UVM_DEFAULT)
`uvm_field_int(resp, UVM_DEFAULT)
`uvm_field_int(size, UVM_DEFAULT) `uvm_field_int(size, UVM_DEFAULT)
`uvm_field_int(length, UVM_DEFAULT) `uvm_field_int(length, UVM_DEFAULT)
`uvm_object_utils_end `uvm_object_utils_end
@@ -58,6 +60,7 @@ class axi_transaction extends uvm_sequence_item;
copy.addr = this.addr; copy.addr = this.addr;
copy.data = this.data; copy.data = this.data;
copy.strb = this.strb; copy.strb = this.strb;
copy.resp = this.resp;
copy.size = this.size; copy.size = this.size;
copy.length = this.length; copy.length = this.length;
return copy; return copy;
@@ -75,5 +78,17 @@ class axi_transaction extends uvm_sequence_item;
(this.length == other.length); (this.length == other.length);
endfunction 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 endclass : axi_transaction

View File

@@ -20,6 +20,8 @@ class tb_env extends uvm_env;
// Set agent types in AXI agents // Set agent types in AXI agents
axi_m.set_agent_type(MANAGER); axi_m.set_agent_type(MANAGER);
axi_s.set_agent_type(SUBORDINATE); axi_s.set_agent_type(SUBORDINATE);
set_up_reporting();
endfunction endfunction
// ------------------------------------------------------------ // ------------------------------------------------------------
@@ -33,6 +35,14 @@ class tb_env extends uvm_env;
// Add any specific report phase tasks here // Add any specific report phase tasks here
endfunction 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(); function uvm_sequencer_base get_axi_m_sequencer();
return axi_m.sequencer; return axi_m.sequencer;