blob: c5681e59deed6839226c35802c31f8e9cab896e6 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
// ---------------------------------------------
// Xbar environment class
// ---------------------------------------------
class xbar_env extends dv_base_env#(.CFG_T (xbar_env_cfg),
.VIRTUAL_SEQUENCER_T(xbar_virtual_sequencer),
.SCOREBOARD_T (xbar_scoreboard),
.COV_T (xbar_env_cov));
tl_agent host_agent[];
tl_agent device_agent[];
`uvm_component_utils(xbar_env)
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction : new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
// use cip_tl_seq_item to create tl_seq_item with correct integrity values and obtain integrity
// related functions
tl_seq_item::type_id::set_type_override(cip_tl_seq_item::get_type());
// Connect TileLink host and device agents
host_agent = new[cfg.num_hosts];
foreach (host_agent[i]) begin
host_agent[i] = tl_agent::type_id::create(
$sformatf("%0s_agent", xbar_hosts[i].host_name), this);
uvm_config_db#(tl_agent_cfg)::set(this,
$sformatf("%0s_agent", xbar_hosts[i].host_name),"cfg", cfg.host_agent_cfg[i]);
cfg.host_agent_cfg[i].en_cov = cfg.en_cov;
end
device_agent = new[cfg.num_devices];
foreach (device_agent[i]) begin
device_agent[i] = tl_agent::type_id::create(
$sformatf("%0s_agent", xbar_devices[i].device_name), this);
uvm_config_db#(tl_agent_cfg)::set(this,
$sformatf("%0s_agent", xbar_devices[i].device_name), "cfg", cfg.device_agent_cfg[i]);
cfg.device_agent_cfg[i].en_cov = cfg.en_cov;
end
// this clock isn't connected to design but only used for TB, like measure timeout, drive long
// enough reset (bigger than 1 cycle of any DUT clock). Use fixed frequency 100 Mhz
cfg.clk_rst_vif.set_freq_mhz(100);
// increase timer as device may respond very slowly in test - xbar_main_random_slow_rsp
scoreboard.timeout_cycle_limit = 100_000;
// create analysis_fifos and scoreboard_queue
foreach (xbar_hosts[i]) begin
scoreboard.add_item_port({"a_chan_", xbar_hosts[i].host_name}, scoreboard_pkg::kSrcPort);
scoreboard.add_item_port({"d_chan_", xbar_hosts[i].host_name}, scoreboard_pkg::kDstPort);
// this queue is used to store expected rsp in d channel for unmapped address
scoreboard.add_item_queue({"host_unmapped_addr_", xbar_hosts[i].host_name},
scoreboard_pkg::kInOrderCheck);
end
foreach (xbar_devices[i]) begin
scoreboard.add_item_port({"a_chan_", xbar_devices[i].device_name}, scoreboard_pkg::kDstPort);
scoreboard.add_item_port({"d_chan_", xbar_devices[i].device_name}, scoreboard_pkg::kSrcPort);
scoreboard.add_item_queue({"a_chan_", xbar_devices[i].device_name},
scoreboard_pkg::kOutOfOrderCheck);
scoreboard.add_item_queue({"d_chan_", xbar_devices[i].device_name},
scoreboard_pkg::kOutOfOrderCheck);
end
endfunction : build_phase
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
// Connect virtual sequencer
if (cfg.is_active) begin
virtual_sequencer.host_seqr = new[cfg.num_hosts];
virtual_sequencer.device_seqr = new[cfg.num_devices];
foreach (host_agent[i]) begin
virtual_sequencer.host_seqr[i] = host_agent[i].sequencer;
end
foreach (device_agent[i]) begin
virtual_sequencer.device_seqr[i] = device_agent[i].sequencer;
end
end
// Connect scoreboard
foreach (host_agent[i]) begin
host_agent[i].monitor.a_chan_port.connect(
scoreboard.item_fifos[{"a_chan_", xbar_hosts[i].host_name}].analysis_export);
host_agent[i].monitor.d_chan_port.connect(
scoreboard.item_fifos[{"d_chan_", xbar_hosts[i].host_name}].analysis_export);
end
foreach (device_agent[i]) begin
device_agent[i].monitor.a_chan_port.connect(
scoreboard.item_fifos[{"a_chan_", xbar_devices[i].device_name}].analysis_export);
device_agent[i].monitor.d_chan_port.connect(
scoreboard.item_fifos[{"d_chan_", xbar_devices[i].device_name}].analysis_export);
end
endfunction : connect_phase
endclass