Added agent config and random transaction delays

This commit is contained in:
2025-08-24 22:59:43 -07:00
parent 1e484bc2c6
commit 728d2a0f6d
6 changed files with 119 additions and 7 deletions

View File

@@ -10,10 +10,12 @@ class axi_agent extends uvm_agent;
virtual `AXI_INTF.SUBORDINATE s_if;
virtual `AXI_INTF mon_if;
// Configuration object
rand axi_agent_config cfg;
// Declare the sequencer and driver
axi_sequencer sequencer;
axi_driver driver;
axi_monitor monitor;
axi_sequencer sequencer;
axi_driver driver;
axi_monitor monitor;
`uvm_component_utils_begin(axi_agent)
`uvm_field_enum(axi_agent_type_t, agent_type, UVM_DEFAULT)
@@ -32,9 +34,21 @@ class axi_agent extends uvm_agent;
`uvm_info("set_agent_type", $sformatf("Agent type set to %s", agent_type.name()), UVM_LOW)
endfunction
// --------------------------------------------------
function axi_agent_config get_cfg();
return cfg;
endfunction
// --------------------------------------------------
// Build phase
virtual function void build_phase(uvm_phase phase);
cfg = axi_agent_config::type_id::create("cfg");
if (!cfg.randomize()) begin
`uvm_fatal("build_phase", "Randomization of cfg failed")
end else begin
`uvm_info("build_phase", $sformatf("%s randomized:\n%s", cfg.get_full_name(), cfg.sprint()), UVM_LOW)
end
sequencer = axi_sequencer::type_id::create("sequencer", this);
if (agent_type == MANAGER) begin
// TODO: Additional variable md should not be needed. We should

View File

@@ -0,0 +1,67 @@
// Configuration class to hold options used in the agent. This contains
// options for anything in side the agent
class axi_agent_config extends uvm_object;
/// Minimum value of pre_transaction_delay
int pre_transaction_delay_min = 0;
/// Maximum value of pre_transaction_delay
int pre_transaction_delay_max = 20;
/// Minimum value of pre_response_delay
int pre_response_delay_min = 1;
/// Maximum value of pre_response_delay
int pre_response_delay_max = 20;
`uvm_object_utils_begin(axi_agent_config)
`uvm_field_int(pre_transaction_delay_min, UVM_DEFAULT)
`uvm_field_int(pre_transaction_delay_max, UVM_DEFAULT)
`uvm_field_int(pre_response_delay_min, UVM_DEFAULT)
`uvm_field_int(pre_response_delay_max, UVM_DEFAULT)
`uvm_object_utils_end
// --------------------------------------------------
function new(string name = "axi_agent_config");
super.new(name);
endfunction
// --------------------------------------------------
function post_randomize();
`uvm_info("post_randomzie", $sformatf("AXI Agent Config:\n%s", this.sprint()), UVM_LOW)
endfunction
// TODO: Using $urandom_range() since Verilator does not have support for
// std::randomize() with {}
// --------------------------------------------------
function int get_pre_transaction_delay();
int dly = 0;
// if (!std::randomzie(dly) with {
// dly dist {
// pre_transaction_delay_min :/ 4,
// pre_transaction_delay_max :/ 4,
// [pre_transaction_delay_min
// :pre_transaction_delay_max] :/ 2
// };
// }) begin
// `uvm_error("get_pre_transaction_delay", "Randomization failed")
// end
dly = $urandom_range(pre_transaction_delay_max, pre_transaction_delay_min);
return dly;
endfunction
// --------------------------------------------------
function int get_pre_response_delay();
int dly = 0;
// if (!std::randomzie(dly) with {
// dly dist {
// pre_response_delay_min :/ 4,
// pre_response_delay_max :/ 4,
// [pre_response_delay_min
// :pre_response_delay_max] :/ 2
// };
// }) begin
// `uvm_error("get_pre_response_delay", "Randomization failed")
// end
dly = $urandom_range(pre_response_delay_max, pre_response_delay_min);
return dly;
endfunction
endclass

View File

@@ -1,10 +1,13 @@
// ----------------------------------------------------------------------
// Driver for AXI transactions
// ----------------------------------------------------------------------
typedef axi_agent;
class axi_driver extends uvm_driver; // #(axi_transaction);
virtual `AXI_INTF.MANAGER m_if;
virtual `AXI_INTF.SUBORDINATE s_if;
axi_agent_type_t agent_type;
axi_agent_config cfg;
`uvm_component_utils(axi_driver)
@@ -24,9 +27,18 @@ class axi_driver extends uvm_driver; // #(axi_transaction);
// --------------------------------------------------
// Set virtual interfaces
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)
m_if = m_if_p;
s_if = s_if_p;
endfunction
// --------------------------------------------------
virtual function void end_of_elaboration_phase(uvm_phase phase);
axi_agent agt;
if ($cast(agt, get_parent())) begin
cfg = agt.get_cfg();
end
endfunction
endclass : axi_driver

View File

@@ -53,8 +53,14 @@ class axi_manager_driver extends axi_driver;
// ------------------------------------------------------------
task drive_txn(axi_transaction req);
int dly = cfg.get_pre_transaction_delay();
`uvm_info("drive_txn", $sformatf("Driving AXI transaction:\n%s", req.sprint()), UVM_LOW)
// Pre transaction delay
`uvm_info("drive_txn", $sformatf("Waiting pre_transaction_delay = %0d cycles",
dly), UVM_LOW)
repeat(dly) @(posedge m_if.ACLK);
if (req.txn_type == AXI_WRITE) begin
drive_write_txn(req);
end else if (req.txn_type == AXI_READ) begin

View File

@@ -5,6 +5,7 @@ package axi_pkg;
`include "uvm_macros.svh"
// UVM data items
`include "axi_agent_config.sv"
`include "axi_transaction.sv"
// UVM components

View File

@@ -41,6 +41,7 @@ class axi_subordinate_driver extends axi_driver;
// ------------------------------------------------------------
task respond_to_write_txn();
axi_transaction req;
int dly = cfg.get_pre_response_delay();
req = axi_transaction::type_id::create("req");
req.txn_type = AXI_WRITE;
@@ -48,25 +49,36 @@ class axi_subordinate_driver extends axi_driver;
req.data = s_if.WDATA;
req.strb = s_if.WSTRB;
@(posedge s_if.ACLK);
// Pre response delay
`uvm_info("drive_txn", $sformatf("Waiting pre_response_delay = %0d cycles",
dly), UVM_LOW)
repeat(dly) @(posedge s_if.ACLK);
`uvm_info("respond_to_write_txn", $sformatf("Responding to AXI write transaction:\n%s", req.sprint()), UVM_LOW)
s_if.AWREADY = 1'b1;
@(posedge s_if.ACLK);
s_if.AWREADY = 1'b0;
endtask
// ------------------------------------------------------------
task respond_to_read_txn();
axi_transaction req;
int dly = cfg.get_pre_response_delay();
req = axi_transaction::type_id::create("req");
req.txn_type = AXI_READ;
req.addr = s_if.ARADDR;
@(posedge s_if.ACLK);
// Pre response delay
`uvm_info("respond_to_write_txn", $sformatf("Waiting pre_response_delay = %0d cycles",
dly), UVM_LOW)
repeat(dly) @(posedge s_if.ACLK);
`uvm_info("respond_to_write_txn", $sformatf("Responding to AXI write transaction:\n%s", req.sprint()), UVM_LOW)
s_if.ARREADY = 1'b1;
@(posedge s_if.ACLK);
s_if.ARREADY = 1'b0;
endtask
endclass : axi_subordinate_driver