Skip to content

Commit

Permalink
[rom_ctrl, dv] Improvements for V3
Browse files Browse the repository at this point in the history
Introduced extern method for declaring members of a class
for better readibility.

Signed-off-by: Kinza Qamar <[email protected]>
  • Loading branch information
KinzaQamar committed Jan 4, 2025
1 parent 8d63d0b commit 658f511
Show file tree
Hide file tree
Showing 12 changed files with 1,212 additions and 1,089 deletions.
47 changes: 25 additions & 22 deletions hw/ip/rom_ctrl/dv/env/rom_ctrl_env.sv
Original file line number Diff line number Diff line change
Expand Up @@ -15,34 +15,37 @@ class rom_ctrl_env extends cip_base_env #(
// KMAC interface agent
kmac_app_agent m_kmac_agent;

function void build_phase(uvm_phase phase);
super.build_phase(phase);
extern function void build_phase(uvm_phase phase);
extern function void connect_phase(uvm_phase phase);

// Get the mem_bkdr interface
if (!uvm_config_db#(mem_bkdr_util)::get(this, "", "mem_bkdr_util", cfg.mem_bkdr_util_h)) begin
`uvm_fatal(`gfn, "failed to get mem_bkdr_util from uvm_config_db")
end
// Get the rom_ctrl interface
if (!uvm_config_db#(rom_ctrl_vif)::get(this, "", "rom_ctrl_vif", cfg.rom_ctrl_vif)) begin
`uvm_fatal(`gfn, "failed to get rom_ctrl_vif from uvm_config_db")
end
endclass

// Build the KMAC agent
m_kmac_agent = kmac_app_agent::type_id::create("m_kmac_agent", this);
uvm_config_db#(kmac_app_agent_cfg)::set(this, "m_kmac_agent", "cfg", cfg.m_kmac_agent_cfg);
function void rom_ctrl_env::build_phase(uvm_phase phase);
super.build_phase(phase);

cfg.scoreboard = scoreboard;
// Get the mem_bkdr interface
if (!uvm_config_db#(mem_bkdr_util)::get(this, "", "mem_bkdr_util", cfg.mem_bkdr_util_h)) begin
`uvm_fatal(`gfn, "failed to get mem_bkdr_util from uvm_config_db")
end
// Get the rom_ctrl interface
if (!uvm_config_db#(rom_ctrl_vif)::get(this, "", "rom_ctrl_vif", cfg.rom_ctrl_vif)) begin
`uvm_fatal(`gfn, "failed to get rom_ctrl_vif from uvm_config_db")
end

endfunction
// Build the KMAC agent
m_kmac_agent = kmac_app_agent::type_id::create("m_kmac_agent", this);
uvm_config_db#(kmac_app_agent_cfg)::set(this, "m_kmac_agent", "cfg", cfg.m_kmac_agent_cfg);

function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
cfg.scoreboard = scoreboard;

m_kmac_agent.monitor.analysis_port.connect(scoreboard.kmac_rsp_fifo.analysis_export);
m_kmac_agent.monitor.req_analysis_port.connect(scoreboard.kmac_req_fifo.analysis_export);
endfunction

virtual_sequencer.kmac_sequencer_h = m_kmac_agent.sequencer;
function void rom_ctrl_env::connect_phase(uvm_phase phase);
super.connect_phase(phase);

endfunction
m_kmac_agent.monitor.analysis_port.connect(scoreboard.kmac_rsp_fifo.analysis_export);
m_kmac_agent.monitor.req_analysis_port.connect(scoreboard.kmac_req_fifo.analysis_export);

endclass
virtual_sequencer.kmac_sequencer_h = m_kmac_agent.sequencer;

endfunction
133 changes: 69 additions & 64 deletions hw/ip/rom_ctrl/dv/env/rom_ctrl_env_cfg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -23,72 +23,77 @@ class rom_ctrl_env_cfg extends cip_base_env_cfg #(.RAL_T(rom_ctrl_regs_reg_block
// A handle to the scoreboard, used to flag expected errors.
rom_ctrl_scoreboard scoreboard;

// Control the device-side delay for the kmac app agent that talks to the dut. If it is large,
// rom_ctrl will spend all its time waiting for kmac to accept words that rom_ctrl is trying to
// send to kmac. Randomise this to be small with high probability and occasionally make it 10 (to
// check that the interface from rom_ctrl to kmac can be stalled properly).
constraint kmac_accept_delay_max_c {
if (!m_kmac_agent_cfg.m_data_push_agent_cfg.zero_delays) {
m_kmac_agent_cfg.m_data_push_agent_cfg.device_delay_max dist { 1 :/ 10, 10 :/ 1 };
}
}
extern constraint kmac_accept_delay_max_c;
extern function new (string name="");
extern virtual function void initialize(bit [31:0] csr_base_addr = '1);
extern virtual function dv_base_reg_block create_ral_by_name(string name);

`uvm_object_utils_begin(rom_ctrl_env_cfg)
`uvm_object_utils_end

function new (string name="");
super.new(name);

can_reset_with_csr_accesses = 1'b1;

list_of_alerts = rom_ctrl_env_pkg::LIST_OF_ALERTS;
tl_intg_alert_name = "fatal";
ral_model_names.push_back("rom_ctrl_prim_reg_block");

num_interrupts = 0;

m_kmac_agent_cfg = kmac_app_agent_cfg::type_id::create("m_kmac_agent_cfg");
m_kmac_agent_cfg.if_mode = dv_utils_pkg::Device;
m_kmac_agent_cfg.start_default_device_seq = 1'b1;
m_kmac_agent_cfg.constant_share_means_error = 1'b0;
// The checker reads the upper 8 words of ROM which takes 9 cycles. The rsp_delay_max has been
// rounded off by 9*2=18 cycles along with adding 2 just to give an extra precision.
m_kmac_agent_cfg.rsp_delay_min = 'd0;
m_kmac_agent_cfg.rsp_delay_max = 'd20;

sec_cm_alert_name = "fatal";
endfunction

virtual function void initialize(bit [31:0] csr_base_addr = '1);
super.initialize(csr_base_addr);

// default TLUL supports 1 outstanding item, the rom TLUL supports 2 outstanding items.
m_tl_agent_cfgs[RAL_T::type_name].max_outstanding_req = 1;
m_tl_agent_cfgs[rom_ral_name].max_outstanding_req = 2;

// Tell the CIP base code what bit gets set if we see a TL fault.
tl_intg_alert_fields[ral.fatal_alert_cause.integrity_error] = 1;
endfunction

// Override the default implementation in dv_base_env_cfg.
//
// This is required for the ROM environment for reuse at the chip level as 2 different
// parameterizations of the design and testbench exist, as a result the custom RAL model for the
// ROM memory primitive must also be explicitly parameterized.
//
// We cannot instantiate parameterized UVM objects/components using the standard factory
// mechanisms, so a custom instantiation method is required here.
//
// Note that the ROM only has 2 RAL models, one is the "default" CSR model,
// and the other is the custom model to represent the memory primitive.
virtual function dv_base_reg_block create_ral_by_name(string name);
if (name == RAL_T::type_name) begin
return super.create_ral_by_name(name);
end else if (name == rom_ral_name) begin
return rom_ctrl_prim_reg_block#(ROM_WORD_ADDR_WIDTH)::type_id::create(rom_ral_name);
end else begin
`uvm_error(`gfn, $sformatf("%0s is an illegal RAL model name", name))
end
endfunction

endclass

// Control the device-side delay for the kmac app agent that talks to the dut. If it is large,
// rom_ctrl will spend all its time waiting for kmac to accept words that rom_ctrl is trying to
// send to kmac. Randomise this to be small with high probability and occasionally make it 10 (to
// check that the interface from rom_ctrl to kmac can be stalled properly).
constraint rom_ctrl_env_cfg::kmac_accept_delay_max_c {
if (!m_kmac_agent_cfg.m_data_push_agent_cfg.zero_delays) {
m_kmac_agent_cfg.m_data_push_agent_cfg.device_delay_max dist { 1 :/ 10, 10 :/ 1 };
}
}

function rom_ctrl_env_cfg::new (string name="");
super.new(name);

can_reset_with_csr_accesses = 1'b1;

list_of_alerts = rom_ctrl_env_pkg::LIST_OF_ALERTS;
tl_intg_alert_name = "fatal";
ral_model_names.push_back("rom_ctrl_prim_reg_block");

num_interrupts = 0;

m_kmac_agent_cfg = kmac_app_agent_cfg::type_id::create("m_kmac_agent_cfg");
m_kmac_agent_cfg.if_mode = dv_utils_pkg::Device;
m_kmac_agent_cfg.start_default_device_seq = 1'b1;
m_kmac_agent_cfg.constant_share_means_error = 1'b0;
// The checker reads the upper 8 words of ROM which takes 9 cycles. The rsp_delay_max has been
// rounded off by 9*2=18 cycles along with adding 2 just to give an extra precision.
m_kmac_agent_cfg.rsp_delay_min = 'd0;
m_kmac_agent_cfg.rsp_delay_max = 'd20;

sec_cm_alert_name = "fatal";
endfunction

function void rom_ctrl_env_cfg::initialize(bit [31:0] csr_base_addr = '1);
super.initialize(csr_base_addr);

// default TLUL supports 1 outstanding item, the rom TLUL supports 2 outstanding items.
m_tl_agent_cfgs[RAL_T::type_name].max_outstanding_req = 1;
m_tl_agent_cfgs[rom_ral_name].max_outstanding_req = 2;

// Tell the CIP base code what bit gets set if we see a TL fault.
tl_intg_alert_fields[ral.fatal_alert_cause.integrity_error] = 1;
endfunction

// Override the default implementation in dv_base_env_cfg.
//
// This is required for the ROM environment for reuse at the chip level as 2 different
// parameterizations of the design and testbench exist, as a result the custom RAL model for the
// ROM memory primitive must also be explicitly parameterized.
//
// We cannot instantiate parameterized UVM objects/components using the standard factory
// mechanisms, so a custom instantiation method is required here.
//
// Note that the ROM only has 2 RAL models, one is the "default" CSR model,
// and the other is the custom model to represent the memory primitive.
function dv_base_reg_block rom_ctrl_env_cfg::create_ral_by_name(string name);
if (name == RAL_T::type_name) begin
return super.create_ral_by_name(name);
end else if (name == rom_ral_name) begin
return rom_ctrl_prim_reg_block#(ROM_WORD_ADDR_WIDTH)::type_id::create(rom_ral_name);
end else begin
`uvm_error(`gfn, $sformatf("%0s is an illegal RAL model name", name))
end
endfunction
25 changes: 14 additions & 11 deletions hw/ip/rom_ctrl/dv/env/rom_ctrl_env_cov.sv
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,19 @@ class rom_ctrl_env_cov extends cip_base_env_cov #(.CFG_T(rom_ctrl_env_cfg));
// covergroups
// [add covergroups here]

function new(string name, uvm_component parent);
super.new(name, parent);
// [instantiate covergroups here]
endfunction : new

virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
// [or instantiate covergroups here]
// Please instantiate sticky_intr_cov array of objects for all interrupts that are sticky
// See cip_base_env_cov for details
endfunction
extern function new(string name, uvm_component parent);
extern virtual function void build_phase(uvm_phase phase);

endclass

function rom_ctrl_env_cov::new(string name, uvm_component parent);
super.new(name, parent);
// [instantiate covergroups here]
endfunction : new

function void rom_ctrl_env_cov::build_phase(uvm_phase phase);
super.build_phase(phase);
// [or instantiate covergroups here]
// Please instantiate sticky_intr_cov array of objects for all interrupts that are sticky
// See cip_base_env_cov for details
endfunction
80 changes: 46 additions & 34 deletions hw/ip/rom_ctrl/dv/env/rom_ctrl_prim_ral_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -16,50 +16,62 @@ package rom_ctrl_prim_ral_pkg;

`uvm_object_param_utils(rom_ctrl_prim_mem_rom_mem#(MemDepth))

function new(string name = "rom_ctrl_prim_mem_rom_mem",
longint unsigned size = MemDepth,
int unsigned n_bits = 32,
string access = "RO",
int has_coverage = UVM_NO_COVERAGE);
super.new(name, size, n_bits, access, has_coverage);
set_mem_partial_write_support(1);
set_data_intg_passthru(1);
endfunction : new
extern function new(string name = "rom_ctrl_prim_mem_rom_mem",
longint unsigned size = MemDepth,
int unsigned n_bits = 32,
string access = "RO",
int has_coverage = UVM_NO_COVERAGE);

endclass : rom_ctrl_prim_mem_rom_mem

function rom_ctrl_prim_mem_rom_mem::new(string name = "rom_ctrl_prim_mem_rom_mem",
longint unsigned size = MemDepth,
int unsigned n_bits = 32,
string access = "RO",
int has_coverage = UVM_NO_COVERAGE);
super.new(name, size, n_bits, access, has_coverage);
set_mem_partial_write_support(1);
set_data_intg_passthru(1);
endfunction : new


class rom_ctrl_prim_reg_block #(parameter int AddrWidth = 10) extends dv_base_reg_block;
// memories
rand rom_ctrl_prim_mem_rom_mem #(2 ** AddrWidth) rom_mem;

`uvm_object_param_utils(rom_ctrl_prim_reg_block#(AddrWidth))

function new(string name = "rom_ctrl_prim_reg_block",
int has_coverage = UVM_NO_COVERAGE);
super.new(name, has_coverage);
endfunction : new

virtual function void build(uvm_reg_addr_t base_addr,
csr_excl_item csr_excl = null);
// create default map
this.default_map = create_map(.name("default_map"),
.base_addr(base_addr),
.n_bytes(4),
.endian(UVM_LITTLE_ENDIAN));
if (csr_excl == null) begin
csr_excl = csr_excl_item::type_id::create("csr_excl");
this.csr_excl = csr_excl;
end

// create memories
rom_mem = rom_ctrl_prim_mem_rom_mem#(2 ** AddrWidth)::type_id::create("rom_mem");
rom_mem.configure(.parent(this));
default_map.add_mem(.mem(rom_mem),
.offset(32'h0),
.rights("RO"));

endfunction : build
extern function new(string name = "rom_ctrl_prim_reg_block",
int has_coverage = UVM_NO_COVERAGE);

extern virtual function void build(uvm_reg_addr_t base_addr, csr_excl_item csr_excl = null);

endclass : rom_ctrl_prim_reg_block

function rom_ctrl_prim_reg_block::new(string name = "rom_ctrl_prim_reg_block",
int has_coverage = UVM_NO_COVERAGE);
super.new(name, has_coverage);
endfunction : new

function void rom_ctrl_prim_reg_block::build(uvm_reg_addr_t base_addr,
csr_excl_item csr_excl = null);
// create default map
this.default_map = create_map(.name("default_map"),
.base_addr(base_addr),
.n_bytes(4),
.endian(UVM_LITTLE_ENDIAN));
if (csr_excl == null) begin
csr_excl = csr_excl_item::type_id::create("csr_excl");
this.csr_excl = csr_excl;
end

// create memories
rom_mem = rom_ctrl_prim_mem_rom_mem#(2 ** AddrWidth)::type_id::create("rom_mem");
rom_mem.configure(.parent(this));
default_map.add_mem(.mem(rom_mem),
.offset(32'h0),
.rights("RO"));

endfunction : build

endpackage
Loading

0 comments on commit 658f511

Please sign in to comment.