Update code from upstream repository
https://github.com/lowRISC/opentitan to revision
ca950b43a0e9ef5013b8e2e5de765bc34fb59b74

Two updates to the Ibex code were required:
* Adjust the prim_secded port names to match the changes in
  OpenTitan.
* Replace `has_ral` in `ibex_icache_env_cfg.sv` and
  `ibex_icache_base_test.sv` with its newer equivalent, matching
  https://github.com/lowRISC/opentitan/pull/5932 and the additional
  updates in https://github.com/lowRISC/opentitan/pull/5951.

Upstream changes include:
* [prim_secded] Use _i/_o suffix for port names (Philipp Wagner)
* [tl,dv] Allow bits to be set in responses regardless of mask (Rupert
  Swarbrick)
* [push_pull agent] Driver code refactor (Srikrishna Iyer)
* [dv/dvsim] Group failures per test in buckets (Guillermo Maturana)
* [dv/uvmdvgen] Flag error for paths in block name (Guillermo
  Maturana)
* [prim_fifo_async] Style fixes (Philipp Wagner)
* Remove non-ASCII characters from SV code and meson.build (Rupert
  Swarbrick)
* [dv/spi_device] Fix spi_device_csr_wr_with_rand_reset timeout issue
  (Cindy Chen)
* [otp] Update to match latest foundry wrapper (Timothy Chen)
* [flash] update to match latest foundry wrapper (Timothy Chen)
* [top] Latest ast integration (Timothy Chen)
* [lint] Strengthen Verible lint check to 100-character lines (Rupert
  Swarbrick)
* [ prim ] Suppress unneeded assertion when clearing prim_packer_fifo
  (Martin Lueker-Boden)
* [dv/otp_ctrl] Add coverage exclusions (Cindy Chen)
* [dv/dvsim] Add "^Error:" as a run fail pattern. (Guillermo Maturana)
* [dvsim] Fix column bug in DV summary report (Srikrishna Iyer)
* [dvsim] Fix testplan test counts (Srikrishna Iyer)
* [dvsim] Fix lowRISC/opentitan#6061 (Srikrishna Iyer)
* [prim_clock_div] Update waiver (Michael Schaffner)
* [fpv] dvsim script error (Cindy Chen)
* [prim_otp] Update interface (Michael Schaffner)
* [dvsim] update edacloudlauncher imports (Udi Jonnalagadda)
* [dv/doc] Minor fix on dv_doc (Cindy Chen)
* [dvsim] Scheduler updates - max_parallel, max_poll (Srikrishna Iyer)
* [dvsim] Set `Deploy.job_name` more robustly (Srikrishna Iyer)
* [prim] Make SECDED prim generation deterministic (Rupert Swarbrick)
* [tool, xcel] Support dumpping the array of struct in shm/vcd (Tung
  Hoang)
* [dv/otp_ctrl] OTP_CTRL DV doc (Cindy Chen)
* [dv/dv_macros] Fix DV_PRINT_ARR_CONTENTS (Guillermo Maturana)
* [prim_pad_attr/prim_flop_en] Add waiver files (Michael Schaffner)
* [prim_usb_diff] Minor lint fix (Michael Schaffner)
* [prim_clock_div] Update waiver file (Michael Schaffner)
* [top] change prim_generic usage into prim (Timothy Chen)
* [formal/conn] Support dvsim to publish regression result summary
  (Cindy Chen)
* Add formatting changes from allow list (Rafal Kapuscik)
* [prim] Add generic and Xilinx-specific xor2 primitives (Pirmin
  Vogel)
* [prim] Add Width parameter to buffer primitives (Pirmin Vogel)
* [prim] Add generic and Xilinx-specific enable-FF primitives (Pirmin
  Vogel)
* [prim] Remove temporary workaround in parameter list related to
  primgen (Pirmin Vogel)
* [dv/dvsim] Provides more context on some failures. (Guillermo
  Maturana)
* [dvsim] Fix local run error. (Eunchan Kim)
* [dv] Support multi-ral (part 4) (Weicai Yang)
* [dv/dvsim] Adds failure bucketizer for triage. (Guillermo Maturana)
* [lint/docs] Update ascentlint dvsim command in readme (Michael
  Schaffner)
* [top] Various top level lint fixes (Timothy Chen)
* [pinmux/padring] Wire up the pad attribute WARL behavior modules
  (Michael Schaffner)
* [dv] Fix tl_error failure (Weicai Yang)
* [pinout] Update flash test mode and voltage signals/pads (Michael
  Schaffner)
* [pad_wrapper] Extend the generic and Xilinx pad wrapper models
  (Michael Schaffner)
* [dv] Update scb for all blocks (Weicai Yang)
* [dv] Support multi-ral (part 3) (Weicai Yang)
* [prim_arbiter,lint] Tell Verilator to split variables for scheduling
  (Rupert Swarbrick)
* [prim] Fix lint warnings, replace inline AscentLint waivers (Pirmin
  Vogel)
* [dvsim] Scratch root default to $REPO_TOP/scratch (Srikrishna Iyer)
* [dv] Update `process_tl_access` args for all blocks (Weicai Yang)
* [dv] Support multi-ral (part 2) (Weicai Yang)
* [formal] Clean up some formal warnings (Cindy Chen)
* [topgen] Rework pinmux datastructure and templatize tops (Michael
  Schaffner)
* [otp_ctrl] Several small lint fixes (Michael Schaffner)
* [prim_fifo_async] Make async FIFO output zero when empty (Noah
  Moroze)
* [flash] Improve flash ECC handling based on transasction attribute
  (Timothy Chen)
* [dv] Remove toggle coverage excl for a_user/d_user (Weicai Yang)
* [dvsim] Fix remaining comments  from lowRISC/opentitan#5876
  (Srikrishna Iyer)
* [dv] Support multi-ral (part 1) (Weicai Yang)

Signed-off-by: Philipp Wagner <phw@lowrisc.org>
This commit is contained in:
Philipp Wagner 2021-05-11 10:43:04 +01:00 committed by Philipp Wagner
parent 8ef06de73d
commit c7cb958f0d
107 changed files with 2699 additions and 1569 deletions

View file

@ -23,10 +23,9 @@
class csr_base_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item));
`uvm_object_utils(csr_base_seq)
uvm_reg_block models[$];
uvm_reg_block models[string];
uvm_reg all_csrs[$];
uvm_reg test_csrs[$];
csr_excl_item m_csr_excl_item;
// By default, assume external checker (example, scoreboard) is turned off. If that is the case,
// then writes are followed by call to predict function to update the mirrored value. Reads are
@ -48,12 +47,6 @@ class csr_base_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item));
// create test_csrs list only if its empty
if (test_csrs.size() == 0) set_csr_test_range();
// create dummy m_csr_excl_item if not supplied
if (m_csr_excl_item == null) begin
`uvm_info(`gtn, "m_csr_excl_item is null, creating a dummy one locally", UVM_LOW)
m_csr_excl_item = csr_excl_item::type_id::create("m_csr_excl_item");
end
endtask
// post_start
@ -63,10 +56,6 @@ class csr_base_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item));
test_csrs.delete();
endtask
function void set_csr_excl_item(csr_excl_item item);
this.m_csr_excl_item = item;
endfunction
// extract csrs and split and prune to a specified test_csr_chunk
virtual function void set_csr_test_range();
int start_idx;
@ -112,6 +101,18 @@ class csr_base_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item));
test_csrs.shuffle();
endfunction
// check if this csr/fld is excluded from test based on the excl info in blk.csr_excl
// TODO, consider to put excl info in dv_base_reg and dv_base_reg_field
function bit is_excl(uvm_object obj,
csr_excl_type_e csr_excl_type,
csr_test_type_e csr_test_type);
csr_excl_item csr_excl = get_excl_item(obj);
if (csr_excl == null) begin
return 0;
end else begin
return csr_excl.is_excl(obj, csr_excl_type, csr_test_type);
end
endfunction
endclass
//--------------------------------------------------------------------------------------------------
@ -131,7 +132,7 @@ class csr_hw_reset_seq extends csr_base_seq;
uvm_reg_data_t compare_mask;
// check if parent block or register is excluded from init check
if (m_csr_excl_item.is_excl(test_csrs[i], CsrExclInitCheck, CsrHwResetTest)) begin
if (is_excl(test_csrs[i], CsrExclInitCheck, CsrHwResetTest)) begin
`uvm_info(`gtn, $sformatf("Skipping register %0s due to CsrExclInitCheck exclusion",
test_csrs[i].get_full_name()), UVM_MEDIUM)
continue;
@ -140,8 +141,7 @@ class csr_hw_reset_seq extends csr_base_seq;
`uvm_info(`gtn, $sformatf("Verifying reset value of register %0s",
test_csrs[i].get_full_name()), UVM_MEDIUM)
compare_mask = get_mask_excl_fields(test_csrs[i], CsrExclInitCheck, CsrHwResetTest,
m_csr_excl_item);
compare_mask = get_mask_excl_fields(test_csrs[i], CsrExclInitCheck, CsrHwResetTest);
csr_rd_check(.ptr (test_csrs[i]),
.blocking (0),
.compare (!external_checker),
@ -190,7 +190,7 @@ class csr_write_seq extends csr_base_seq;
dv_base_reg dv_csr;
bit backdoor;
// check if parent block or register is excluded from write
if (m_csr_excl_item.is_excl(test_csrs[i], CsrExclWrite, CsrHwResetTest)) begin
if (is_excl(test_csrs[i], CsrExclWrite, CsrHwResetTest)) begin
`uvm_info(`gtn, $sformatf("Skipping register %0s due to CsrExclWrite exclusion",
test_csrs[i].get_full_name()), UVM_MEDIUM)
continue;
@ -200,7 +200,7 @@ class csr_write_seq extends csr_base_seq;
test_csrs[i].get_full_name()), UVM_MEDIUM)
`DV_CHECK_STD_RANDOMIZE_FATAL(wdata)
wdata &= get_mask_excl_fields(test_csrs[i], CsrExclWrite, CsrHwResetTest, m_csr_excl_item);
wdata &= get_mask_excl_fields(test_csrs[i], CsrExclWrite, CsrHwResetTest);
`downcast(dv_csr, test_csrs[i])
if (en_rand_backdoor_write && !dv_csr.get_is_ext_reg()) begin
@ -234,7 +234,7 @@ class csr_rw_seq extends csr_base_seq;
uvm_reg_field test_fields[$];
// check if parent block or register is excluded from write
if (m_csr_excl_item.is_excl(test_csrs[i], CsrExclWrite, CsrRwTest)) begin
if (is_excl(test_csrs[i], CsrExclWrite, CsrRwTest)) begin
`uvm_info(`gtn, $sformatf("Skipping register %0s due to CsrExclWrite exclusion",
test_csrs[i].get_full_name()), UVM_MEDIUM)
continue;
@ -244,7 +244,7 @@ class csr_rw_seq extends csr_base_seq;
test_csrs[i].get_full_name()), UVM_MEDIUM)
`DV_CHECK_STD_RANDOMIZE_FATAL(wdata)
wdata &= get_mask_excl_fields(test_csrs[i], CsrExclWrite, CsrRwTest, m_csr_excl_item);
wdata &= get_mask_excl_fields(test_csrs[i], CsrExclWrite, CsrRwTest);
// if external checker is not enabled and writes are made non-blocking, then we need to
// pre-predict so that the mirrored value will be updated. if we dont, then csr_rd_check task
@ -258,8 +258,7 @@ class csr_rw_seq extends csr_base_seq;
.compare(!external_checker),
.compare_vs_ral(1),
.csr_excl_type(CsrExclWriteCheck),
.csr_test_type(CsrRwTest),
.csr_excl_item(m_csr_excl_item));
.csr_test_type(CsrRwTest));
wait_if_max_outstanding_accesses_reached();
end
@ -281,8 +280,8 @@ class csr_bit_bash_seq extends csr_base_seq;
virtual task body();
foreach (test_csrs[i]) begin
// check if parent block or register is excluded from write
if (m_csr_excl_item.is_excl(test_csrs[i], CsrExclWrite, CsrBitBashTest) ||
m_csr_excl_item.is_excl(test_csrs[i], CsrExclWriteCheck, CsrBitBashTest)) begin
if (is_excl(test_csrs[i], CsrExclWrite, CsrBitBashTest) ||
is_excl(test_csrs[i], CsrExclWriteCheck, CsrBitBashTest)) begin
`uvm_info(`gtn, $sformatf("Skipping register %0s due to CsrExclWrite/WriteCheck exclusion",
test_csrs[i].get_full_name()), UVM_MEDIUM)
continue;
@ -323,15 +322,15 @@ class csr_bit_bash_seq extends csr_base_seq;
endcase
// skip fields that are wr-excluded
if (m_csr_excl_item.is_excl(fields[j], CsrExclWrite, CsrBitBashTest)) begin
if (is_excl(fields[j], CsrExclWrite, CsrBitBashTest)) begin
`uvm_info(`gtn, $sformatf("Skipping field %0s due to CsrExclWrite exclusion",
fields[j].get_full_name()), UVM_MEDIUM)
dc = 1;
end
// ignore fields that are init or rd-excluded
cmp = m_csr_excl_item.is_excl(fields[j], CsrExclInitCheck, CsrBitBashTest) ||
m_csr_excl_item.is_excl(fields[j], CsrExclWriteCheck, CsrBitBashTest) ;
cmp = is_excl(fields[j], CsrExclInitCheck, CsrBitBashTest) ||
is_excl(fields[j], CsrExclWriteCheck, CsrBitBashTest) ;
// Any unused bits on the right side of the LSB?
while (next_lsb < lsb) mode[next_lsb++] = "RO";
@ -404,7 +403,7 @@ class csr_aliasing_seq extends csr_base_seq;
uvm_reg_data_t wdata;
// check if parent block or register is excluded
if (m_csr_excl_item.is_excl(test_csrs[i], CsrExclWrite, CsrAliasingTest)) begin
if (is_excl(test_csrs[i], CsrExclWrite, CsrAliasingTest)) begin
`uvm_info(`gtn, $sformatf("Skipping register %0s due to CsrExclWrite exclusion",
test_csrs[i].get_full_name()), UVM_MEDIUM)
continue;
@ -414,7 +413,7 @@ class csr_aliasing_seq extends csr_base_seq;
test_csrs[i].get_full_name()), UVM_MEDIUM)
`DV_CHECK_STD_RANDOMIZE_FATAL(wdata)
wdata &= get_mask_excl_fields(test_csrs[i], CsrExclWrite, CsrAliasingTest, m_csr_excl_item);
wdata &= get_mask_excl_fields(test_csrs[i], CsrExclWrite, CsrAliasingTest);
csr_wr(.ptr(test_csrs[i]), .value(wdata), .blocking(0), .predict(!external_checker));
all_csrs.shuffle();
@ -427,15 +426,14 @@ class csr_aliasing_seq extends csr_base_seq;
uvm_reg_data_t compare_mask;
// check if parent block or register is excluded
if (m_csr_excl_item.is_excl(all_csrs[j], CsrExclInitCheck, CsrAliasingTest) ||
m_csr_excl_item.is_excl(all_csrs[j], CsrExclWriteCheck, CsrAliasingTest)) begin
if (is_excl(all_csrs[j], CsrExclInitCheck, CsrAliasingTest) ||
is_excl(all_csrs[j], CsrExclWriteCheck, CsrAliasingTest)) begin
`uvm_info(`gtn, $sformatf("Skipping register %0s due to CsrExclInit/WriteCheck exclusion",
all_csrs[j].get_full_name()), UVM_MEDIUM)
continue;
end
compare_mask = get_mask_excl_fields(all_csrs[j], CsrExclWriteCheck, CsrAliasingTest,
m_csr_excl_item);
compare_mask = get_mask_excl_fields(all_csrs[j], CsrExclWriteCheck, CsrAliasingTest);
csr_rd_check(.ptr (all_csrs[j]),
.blocking (0),
.compare (!external_checker),

View file

@ -14,7 +14,7 @@ package csr_utils_pkg;
// local types and variables
uint outstanding_accesses = 0;
uint default_timeout_ns = 1_000_000; // 1ms
uint default_timeout_ns = 2_000_000; // 2ms
uint default_spinwait_timeout_ns = 10_000_000; // 10ms
string msg_id = "csr_utils";
bit default_csr_blocking = 1;
@ -540,7 +540,7 @@ package csr_utils_pkg;
input bit compare_vs_ral = 1,
input csr_excl_type_e csr_excl_type = CsrNoExcl,
input csr_test_type_e csr_test_type = CsrRwTest,
input csr_excl_item csr_excl_item = null);
input csr_excl_item csr_excl_item = get_excl_item(csr));
uvm_reg_data_t compare_mask;
// Check if parent block or register is excluded from read-check
@ -730,10 +730,12 @@ package csr_utils_pkg;
function automatic uvm_reg_data_t get_mask_excl_fields(uvm_reg csr,
csr_excl_type_e csr_excl_type,
csr_test_type_e csr_test_type,
csr_excl_item m_csr_excl_item);
csr_excl_item m_csr_excl_item =
get_excl_item(csr));
uvm_reg_field flds[$];
csr.get_fields(flds);
get_mask_excl_fields = '1;
if (m_csr_excl_item != null) begin
foreach (flds[i]) begin
if (m_csr_excl_item.is_excl(flds[i], csr_excl_type, csr_test_type)) begin
@ -746,6 +748,20 @@ package csr_utils_pkg;
end
endfunction
function automatic csr_excl_item get_excl_item(uvm_object ptr);
csr_field_t csr_or_fld;
dv_base_reg_block blk;
csr_or_fld = decode_csr_or_field(ptr);
`downcast(blk, csr_or_fld.csr.get_parent(), , , msg_id)
// csr_excl is at the highest level of reg block
while (blk.csr_excl == null) begin
`downcast(blk, blk.get_parent(), , , msg_id)
`DV_CHECK_NE_FATAL(blk, null, "", msg_id)
end
return blk.csr_excl;
endfunction
// sources
`include "csr_seq_lib.sv"

View file

@ -342,7 +342,7 @@ class dv_base_reg extends uvm_reg;
string parent_name = this.get_parent().get_name();
// block level alert name is input alert name from hjson
if (parent_name == "ral") return update_err_alert_name;
if (get_parent().get_parent() == null) return update_err_alert_name;
// top-level alert name is ${block_name} + alert name from hjson
return ($sformatf("%0s_%0s", parent_name, update_err_alert_name));
@ -360,7 +360,7 @@ class dv_base_reg extends uvm_reg;
string parent_name = this.get_parent().get_name();
// block level alert name is input alert name from hjson
if (parent_name == "ral") return storage_err_alert_name;
if (get_parent().get_parent() == null) return storage_err_alert_name;
// top-level alert name is ${block_name} + alert name from hjson
return ($sformatf("%0s_%0s", parent_name, storage_err_alert_name));

View file

@ -20,6 +20,9 @@ class dv_base_agent_cfg extends uvm_object;
// use for phase_ready_to_end to add additional delay after ok_to_end is set
int ok_to_end_delay_ns = 1000;
// Indicates that the interface is under reset. The derived monitor detects and maintains it.
bit in_reset;
`uvm_object_utils_begin(dv_base_agent_cfg)
`uvm_field_int (is_active, UVM_DEFAULT)
`uvm_field_int (en_cov, UVM_DEFAULT)

View file

@ -16,17 +16,42 @@ class dv_base_env #(type CFG_T = dv_base_env_cfg,
`uvm_component_new
virtual function void build_phase(uvm_phase phase);
string default_ral_name;
super.build_phase(phase);
// get dv_base_env_cfg object from uvm_config_db
if (!uvm_config_db#(CFG_T)::get(this, "", "cfg", cfg)) begin
`uvm_fatal(`gfn, $sformatf("failed to get %s from uvm_config_db", cfg.get_type_name()))
end
// get vifs
if (!uvm_config_db#(virtual clk_rst_if)::get(this, "", "clk_rst_vif", cfg.clk_rst_vif)) begin
`uvm_fatal(get_full_name(), "failed to get clk_rst_if from uvm_config_db")
// get vifs for RAL models
if (cfg.ral_model_names.size > 0) begin
default_ral_name = cfg.ral.get_type_name();
foreach (cfg.ral_model_names[i]) begin
string ral_name = cfg.ral_model_names[i];
string if_name;
if (ral_name == default_ral_name) if_name = "clk_rst_vif";
else if_name = {"clk_rst_vif_", ral_name};
if (!uvm_config_db#(virtual clk_rst_if)::get(this, "", if_name,
cfg.clk_rst_vifs[ral_name])) begin
`uvm_fatal(`gfn, $sformatf("failed to get clk_rst_if for %0s from uvm_config_db", ral_name))
end
cfg.clk_rst_vifs[ral_name].set_freq_mhz(cfg.clk_freqs_mhz[ral_name]);
end
// assign default clk_rst_vif
`DV_CHECK_FATAL(cfg.clk_rst_vifs.exists(default_ral_name))
cfg.clk_rst_vif = cfg.clk_rst_vifs[default_ral_name];
end else begin
// no RAL model, get the default clk_rst_vif for the block
// such as xbar, it doesn't has ral model, but it also needs a default clk_rst_vif
if (!uvm_config_db#(virtual clk_rst_if)::get(this, "", "clk_rst_vif", cfg.clk_rst_vif))
begin
`uvm_fatal(`gfn, "failed to get clk_rst_if from uvm_config_db")
end
cfg.clk_rst_vif.set_freq_mhz(cfg.clk_freq_mhz);
end
cfg.clk_rst_vif.set_freq_mhz(cfg.clk_freq_mhz);
// create components
if (cfg.en_cov) begin

View file

@ -9,7 +9,7 @@ class dv_base_env_cfg #(type RAL_T = dv_base_reg_block) extends uvm_object;
bit en_scb_tl_err_chk = 1;
bit en_scb_mem_chk = 1;
bit en_cov = 0; // Enable via plusarg, only if coverage collection is turned on.
bit has_ral = 1;
bit under_reset = 0;
bit is_initialized; // Indicates that the initialize() method has been called.
@ -29,20 +29,31 @@ class dv_base_env_cfg #(type RAL_T = dv_base_reg_block) extends uvm_object;
// reg model & q of valid csr addresses
RAL_T ral;
dv_base_reg_block ral_models[$];
bit [bus_params_pkg::BUS_AW-1:0] csr_addrs[$];
addr_range_t mem_ranges[$];
dv_base_reg_block ral_models[string];
// A queue of the names of RAL models that should be created in the `initialize` function
// Related agents, adapters will be created in env as well as connecting them with scb
// For example, if the IP has an additional RAL model named `ral1`, add it into the list as below
// virtual function void initialize(bit [TL_AW-1:0] csr_base_addr = '1);
// ral_model_names.push_back("ral1");
// super.initialize(csr_base_addr);
string ral_model_names[$] = {RAL_T::type_name};
bit [bus_params_pkg::BUS_AW-1:0] csr_addrs[string][$];
addr_range_t mem_ranges[string][$];
// clk_rst_if & freq
// clk_rst_vif and clk_freq_mhz are used for default clk/rst. If more than one RAL, the other
// clk_rst_vif and clk_freq_mhz can be found from the associative arrays
virtual clk_rst_if clk_rst_vif;
virtual clk_rst_if clk_rst_vifs[string];
rand clk_freq_mhz_e clk_freq_mhz;
rand clk_freq_mhz_e clk_freqs_mhz[string];
`uvm_object_param_utils_begin(dv_base_env_cfg #(RAL_T))
`uvm_field_int (is_active, UVM_DEFAULT)
`uvm_field_int (en_scb, UVM_DEFAULT)
`uvm_field_int (en_cov, UVM_DEFAULT)
`uvm_field_int (zero_delays, UVM_DEFAULT)
`uvm_field_enum (clk_freq_mhz_e, clk_freq_mhz, UVM_DEFAULT)
`uvm_object_utils_end
`uvm_object_new
@ -51,36 +62,22 @@ class dv_base_env_cfg #(type RAL_T = dv_base_reg_block) extends uvm_object;
`DV_CHECK_FATAL(is_initialized, "Please invoke initialize() before randomizing this object.")
endfunction
function void post_randomize();
if (clk_freqs_mhz.size > 0) begin
`DV_CHECK_FATAL(clk_freqs_mhz.exists(RAL_T::type_name))
clk_freqs_mhz[RAL_T::type_name] = clk_freq_mhz;
end
endfunction
virtual function void initialize(bit [bus_params_pkg::BUS_AW-1:0] csr_base_addr = '1);
is_initialized = 1'b1;
// build the ral model
if (has_ral) begin
uvm_reg_addr_t base_addr;
create_ral_models(csr_base_addr);
ral = RAL_T::type_id::create("ral");
// Build the register block with an arbitrary base address (we choose 0). We'll change it
// later.
ral.build(.base_addr(0), .csr_excl(null));
apply_ral_fixes();
ral.lock_model();
// Now the model is locked, we know its layout. Set the base address for the register block.
// The function internally picks a random one if we pass '1 to it, and performs an integrity
// check on the set address.
//
// The definition of base_addr explicitly casts from a bus address to a uvm_reg_addr_t (to
// correctly handle the case where a bus address is narrower than a uvm_reg_addr_t).
base_addr = (&csr_base_addr ?
{`UVM_REG_ADDR_WIDTH{1'b1}} :
{{(`UVM_REG_ADDR_WIDTH - bus_params_pkg::BUS_AW){1'b0}}, csr_base_addr});
ral.set_base_addr(base_addr);
// Get list of valid csr addresses (useful in seq to randomize addr as well as in scb checks)
get_csr_addrs(ral, csr_addrs);
get_mem_addr_ranges(ral, mem_ranges);
ral_models.push_back(ral);
// add items to clk_freqs_mhz before randomizing it
foreach (ral_model_names[i]) begin
clk_freqs_mhz[ral_model_names[i]] = ClkFreq24Mhz;
end
endfunction
@ -100,4 +97,58 @@ class dv_base_env_cfg #(type RAL_T = dv_base_reg_block) extends uvm_object;
csr_utils_pkg::reset_deasserted();
endfunction
virtual function void create_ral_models(bit [bus_params_pkg::BUS_AW-1:0] csr_base_addr = '1);
foreach (ral_model_names[i]) begin
string ral_name = ral_model_names[i];
uvm_reg_addr_t base_addr;
dv_base_reg_block reg_blk = create_ral_by_name(ral_name);
if (reg_blk.get_name() == RAL_T::type_name) `downcast(ral, reg_blk)
// Build the register block with an arbitrary base address (we choose 0). We'll change it
// later.
reg_blk.build(.base_addr(0), .csr_excl(null));
apply_ral_fixes();
reg_blk.lock_model();
// Now the model is locked, we know its layout. Set the base address for the register block.
// The function internally picks a random one if we pass '1 to it, and performs an integrity
// check on the set address.
//
// The definition of base_addr explicitly casts from a bus address to a uvm_reg_addr_t (to
// correctly handle the case where a bus address is narrower than a uvm_reg_addr_t).
base_addr = (&csr_base_addr ?
{`UVM_REG_ADDR_WIDTH{1'b1}} :
{{(`UVM_REG_ADDR_WIDTH - bus_params_pkg::BUS_AW){1'b0}}, csr_base_addr});
reg_blk.set_base_addr(base_addr);
// Get list of valid csr addresses (useful in seq to randomize addr as well as in scb checks)
get_csr_addrs(reg_blk, csr_addrs[ral_name]);
get_mem_addr_ranges(reg_blk, mem_ranges[ral_name]);
ral_models[ral_name] = reg_blk;
end
if (ral_model_names.size > 0) begin
`DV_CHECK_FATAL(ral_models.exists(RAL_T::type_name))
end
endfunction
virtual function dv_base_reg_block create_ral_by_name(string name);
uvm_object obj;
uvm_factory factory;
dv_base_reg_block ral;
factory = uvm_factory::get();
obj = factory.create_object_by_name(.requested_type_name(name), .name(name));
if (obj == null) begin
// print factory overrides to help debug
factory.print();
`uvm_fatal(msg_id, $sformatf("could not create %0s as a RAL model, see above for a list of \
type/instance overrides", name))
end
if (!$cast(ral, obj)) begin
`uvm_fatal(msg_id, $sformatf("cast failed - %0s is not a dv_base_reg_block", name))
end
return ral;
endfunction
endclass

View file

@ -50,9 +50,7 @@ class dv_base_scoreboard #(type RAL_T = dv_base_reg_block,
virtual function void reset(string kind = "HARD");
// reset the ral model
if (cfg.has_ral) begin
foreach (cfg.ral_models[i]) cfg.ral_models[i].reset(kind);
end
foreach (cfg.ral_models[i]) cfg.ral_models[i].reset(kind);
endfunction
virtual function void pre_abort();

View file

@ -86,8 +86,22 @@ class dv_base_vseq #(type RAL_T = dv_base_reg_block,
virtual task apply_reset(string kind = "HARD");
if (kind == "HARD") begin
cfg.clk_rst_vif.apply_reset();
end
if (cfg.clk_rst_vifs.size > 0) begin
fork
begin : isolation_fork
foreach (cfg.clk_rst_vifs[i]) begin
automatic string ral_name = i;
fork
cfg.clk_rst_vifs[ral_name].apply_reset();
join_none
end
wait fork;
end : isolation_fork
join
end else begin // no ral model and only has default clk_rst_vif
cfg.clk_rst_vif.apply_reset();
end
end // if (kind == "HARD")
endtask
virtual task wait_for_reset(string reset_kind = "HARD",
@ -109,62 +123,37 @@ class dv_base_vseq #(type RAL_T = dv_base_reg_block,
csr_utils_pkg::wait_no_outstanding_access();
endtask
// function to add csr exclusions of the given type using the csr_excl_item item
// arg csr_test_type: this the the type of csr test run - we may want additional exclusions
// depending on what test seq we are running
// arg csr_excl: this is the csr exclusion object that maintains the list of exclusions
// the same object handle is to be passed to csr sequences in csr_seq_lib so that they can query
// those exclusions
virtual function void add_csr_exclusions(string csr_test_type,
csr_excl_item csr_excl,
string scope = "ral");
`uvm_info(`gfn, "no exclusion item added from this function", UVM_DEBUG)
endfunction
// TODO: temp support, can delete this once all IPs update their exclusion in hjson
virtual function csr_excl_item add_and_return_csr_excl(string csr_test_type);
add_csr_exclusions(csr_test_type, ral.csr_excl);
ral.csr_excl.print_exclusions();
return ral.csr_excl;
endfunction
// wrapper task around run_csr_vseq - the purpose is to be able to call this directly for actual
// csr tests (as opposed to higher level stress test that could also run csr seq as a fork by
// calling run_csr_vseq(..) task)
virtual task run_csr_vseq_wrapper(int num_times = 1);
string csr_test_type;
csr_excl_item csr_excl;
// env needs to have a ral instance
`DV_CHECK_EQ_FATAL(cfg.has_ral, 1'b1)
`DV_CHECK_GE_FATAL(cfg.ral_models.size(), 1)
// get csr_test_type from plusarg
void'($value$plusargs("csr_%0s", csr_test_type));
// create csr exclusions before running the csr seq
csr_excl = add_and_return_csr_excl(csr_test_type);
// run the csr seq
for (int i = 1; i <= num_times; i++) begin
`uvm_info(`gfn, $sformatf("running csr %0s vseq iteration %0d/%0d",
csr_test_type, i, num_times), UVM_LOW)
run_csr_vseq(.csr_test_type(csr_test_type), .csr_excl(csr_excl));
run_csr_vseq(.csr_test_type(csr_test_type));
end
endtask
// capture the entire csr seq as a task that can be overridden if desired
// arg csr_test_type: what csr test to run {hw_reset, rw, bit_bash, aliasing}
// arg csr_excl: csr exclusion object - needs to be created and exclusions set before call
// arg num_test_csrs:instead of testing the entire ral model or passing test chunk info via
// plusarg, provide ability to set a random number of csrs to test from higher level sequence
virtual task run_csr_vseq(string csr_test_type = "",
csr_excl_item csr_excl = null,
int num_test_csrs = 0,
bit do_rand_wr_and_reset = 1);
csr_base_seq m_csr_seq;
// env needs to have a ral instance
`DV_CHECK_EQ_FATAL(cfg.has_ral, 1'b1)
`DV_CHECK_GE_FATAL(cfg.ral_models.size(), 1)
// check which csr test type
case (csr_test_type)
@ -193,7 +182,6 @@ class dv_base_vseq #(type RAL_T = dv_base_reg_block,
m_csr_write_seq.models = cfg.ral_models;
m_csr_write_seq.external_checker = cfg.en_scb;
m_csr_write_seq.en_rand_backdoor_write = 1'b1;
m_csr_write_seq.set_csr_excl_item(csr_excl);
m_csr_write_seq.start(null);
// run dut_shutdown before asserting reset
@ -211,7 +199,6 @@ class dv_base_vseq #(type RAL_T = dv_base_reg_block,
m_csr_seq.models = cfg.ral_models;
m_csr_seq.external_checker = cfg.en_scb;
m_csr_seq.num_test_csrs = num_test_csrs;
m_csr_seq.set_csr_excl_item(csr_excl);
m_csr_seq.start(null);
endtask

View file

@ -270,7 +270,7 @@
`define DV_PRINT_ARR_CONTENTS(ARR_, V_=uvm_pkg::UVM_MEDIUM, ID_=`gfn) \
begin \
foreach (ARR_[i]) begin \
`dv_info($sformatf("%s[%0d] = 0x%0d[0x%0h]", `"ARR_`", i, ARR_[i], ARR_[i]), V_, ID_) \
`dv_info($sformatf("%s[%0d] = %0d (0x%0h)", `"ARR_`", i, ARR_[i], ARR_[i]), V_, ID_) \
end \
end
`endif

View file

@ -18,8 +18,7 @@ package dv_test_status_pkg;
$display(" | | __/\\__ \\ |_ | |_) | (_| \\__ \\__ \\ __/ (_| |_|");
$display(" |_|\\___||___/\\__| | .__/ \\__,_|___/___/\\___|\\__,_(_)");
$display(" |_| \n");
end
else begin
end else begin
$display("\nTEST FAILED CHECKS");
$display(" _____ _ __ _ _ _ _ ");
$display("|_ _|__ ___| |_ / _| __ _(_) | ___ __| | |");

View file

@ -74,8 +74,8 @@ class mem_model #(int AddrWidth = bus_params_pkg::BUS_AW,
if (mask[0]) begin
compare_byte(addr + i, byte_data);
end else begin
`DV_CHECK_EQ(byte_data, 0,
$sformatf("addr 0x%0h masked data aren't 0, mask 0x%0h", addr, mask))
// Nothing to do here: since this byte wasn't selected by the mask, there are no
// requirements about what data came back.
end
act_data = act_data>> 8;
mask = mask >> 1;

View file

@ -28,7 +28,8 @@
"^UVM_WARNING\\s[^:].*$",
"^Assert failed: ",
"^\\s*Offending '.*'",
"^TEST FAILED (UVM_)?CHECKS$"]
"^TEST FAILED (UVM_)?CHECKS$",
"^Error:.*$"] // ISS errors
// Default TileLink widths
tl_aw: 32

View file

@ -2,14 +2,18 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
// Exclude below TL toggle coverage as these pins won't be changed in the comportable IPs
// Exclude below TL toggle coverage as these pins won't be changed in the comportable IPs.
// Exclude alert_sender as it is fully verified in FPV. Note that user might also need to exclude
// prim_diff_decode module, but it is not listed here because modules other than prim_alert_sender
// might instantiate this prim_diff_decode as well.
INSTANCE: tb.dut
Toggle tl_i.a_user.parity "logic tl_i.a_user.parity[7:0]"
Toggle tl_i.a_user.parity_en "logic tl_i.a_user.parity_en"
Toggle tl_i.a_user.rsvd1 "logic tl_i.a_user.rsvd1[6:0]"
Toggle tl_o.d_opcode [1] "logic tl_o.d_opcode[2:0]"
Toggle tl_o.d_opcode [2] "logic tl_o.d_opcode[2:0]"
Toggle tl_o.d_param "logic tl_o.d_param[2:0]"
Toggle tl_o.d_sink "logic tl_o.d_sink[0:0]"
Toggle tl_o.d_user "logic tl_o.d_user[15:0]"
Toggle tl_i.a_param "logic tl_i.a_param[2:0]"
// TODO: revisit after issue #6089 is implemented
ANNOTATION: "[EXTERNAL] alert_sender is fully verified by FPV testbench."
MODULE:prim_alert_sender

View file

@ -110,7 +110,7 @@ proc wavedumpScope {scope fid {depth 0} {fsdb_flags "+all"} {probe_flags "-all"
if {$depth == 0} {
set depth "all"
}
probe "$scope" $probe_flags -depth $depth -shm
probe "$scope" $probe_flags -depth $depth -memories -shm
}
"vpd" {
@ -124,7 +124,7 @@ proc wavedumpScope {scope fid {depth 0} {fsdb_flags "+all"} {probe_flags "-all"
if {$depth == 0} {
set depth "all"
}
probe "$scope" $probe_flags -depth $depth -vcd
probe "$scope" $probe_flags -depth $depth -memories -vcd
}
}