Files
axipg/src/axi/axi_agent.sv
2025-08-23 17:03:40 -07:00

107 lines
4.5 KiB
Systemverilog

// ----------------------------------------------------------------------
// Agent to operate AXI transactions
// This agent includes a driver, monitor, and sequencer for AXI transactions
// ----------------------------------------------------------------------
typedef axi_sequencer;
class axi_agent extends uvm_agent;
axi_agent_type_t agent_type;
virtual `AXI_INTF.MANAGER m_if;
virtual `AXI_INTF.SUBORDINATE s_if;
virtual `AXI_INTF mon_if;
// Declare the sequencer and driver
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)
`uvm_component_utils_end
// --------------------------------------------------
// Constructor
function new(string name = "axi_agent", uvm_component parent = null);
super.new(name, parent);
endfunction
// --------------------------------------------------
// Set agent type
function void set_agent_type(axi_agent_type_t atype);
agent_type = atype;
`uvm_info("set_agent_type", $sformatf("Agent type set to %s", agent_type.name()), UVM_LOW)
endfunction
// --------------------------------------------------
// Build phase
virtual function void build_phase(uvm_phase phase);
sequencer = axi_sequencer::type_id::create("sequencer", this);
if (agent_type == MANAGER) begin
// TODO: Additional variable md should not be needed. We should
// able to use the 'driver' variable directly. But in Verilator
// it results in an error: "No common base class exists"
axi_manager_driver md = axi_manager_driver::type_id::create("driver", this);
driver = md;
end else begin // if (agent_type == SUBORDINATE) begin
axi_subordinate_driver sd = axi_subordinate_driver::type_id::create("driver", this);
driver = sd;
end
monitor = axi_monitor::type_id::create("monitor", this);
// Propagete the agent type to driver and monitor
driver.set_agent_type(agent_type);
monitor.set_agent_type(agent_type);
// Acquire the virtual interfaces from the configuration database
if (agent_type == MANAGER) begin
if (!uvm_config_db#(virtual `AXI_INTF.MANAGER)::get(this, "", "axi_dvr_vif", m_if)) begin
`uvm_fatal("axi_agent", "AXI agent MANAGER interface not configured")
end
`uvm_info("axi_agent", $sformatf("Using AXI agent MANAGER interface: axi_dvr_vif"), UVM_LOW)
end else begin // if (agent_type == SUBORDINATE) begin
if (!uvm_config_db#(virtual `AXI_INTF.SUBORDINATE)::get(this, "", "axi_dvr_vif", s_if)) begin
`uvm_fatal("axi_agent", "AXI agent SUBORDINATE interface not configured")
end
`uvm_info("axi_agent", $sformatf("Using AXI agent SUBORDINATE interface: axi_dvr_vif"), UVM_LOW)
end
if (!uvm_config_db#(virtual `AXI_INTF)::get(this.get_parent(), "", "axi_mon_vif", mon_if)) begin
`uvm_fatal("axi_agent", "AXI monitor interface not configured")
end
`uvm_info("axi_agent", $sformatf("Using AXI monitor interface: axi_mon_vif"), UVM_LOW)
// Propagate the virtual interfaces to driver and monitor
driver.set_virtual_interfaces(m_if, s_if);
monitor.set_virtual_interfaces(m_if, s_if);
monitor.set_monitor_virtual_interface(mon_if);
endfunction
// --------------------------------------------------
// Connect phase
virtual function void connect_phase(uvm_phase phase);
// Connect the driver to the sequencer
driver.seq_item_port.connect(sequencer.seq_item_export);
driver.rsp_port.connect(sequencer.rsp_export);
// Connect the monitor to the sequencer
// driver.rsp_port.connect(monitor.rsp_export);
endfunction
// --------------------------------------------------
// Run phase
virtual function void run_phase(uvm_phase phase);
`uvm_info("axi_agent", $sformatf("Running AXI agent: %s as %s",
get_full_name(), agent_type.name()), UVM_LOW)
endfunction
endclass : axi_agent
// ----------------------------------------------------------------------
class axi_sequencer extends uvm_sequencer;
`uvm_component_utils(axi_sequencer)
// Constructor
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
endclass : axi_sequencer