Transaction driving and responding updates. Tracker updates
This commit is contained in:
@@ -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) \
|
||||
)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
10
tb/tb_env.sv
10
tb/tb_env.sv
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user