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

* [dvsim] Introduce {self_dir} as variable (Philipp Wagner)
* [dvsim] Small cleanups (Philipp Wagner)
* [prim_lfsr] Minor lint fix (Michael Schaffner)
* [dv] Update sec_cm testplan (Weicai Yang)
* [prim/lint] Move waiver to correct waiver file (Michael Schaffner)
* [prim_assert] Relocate waivers to dedicated prim_assert.waiver file
  (Michael Schaffner)
* [alert_handler] Lint fixes and waiver updates (Michael Schaffner)
* [prim_lc_receiver] Add parameter to select reset value (Michael
  Schaffner)
* [lint] Add lint waiver for IP regfiles with shadow resets (Michael
  Schaffner)
* [fpv] Fix Verible lint errors (Philipp Wagner)
* [prim_lfsr] Minor lint fixes (Timothy Chen)
* [clkmgr] Fix measurement control CDC (Timothy Chen)
* [fpv/prim_counter] Pad one bit to include overflow case (Cindy Chen)
* [fpv] Fix issue lowRISC#8371 (Zeeshan Rafique)
* [flash_ctrl] Flash ctrl security hardening (Timothy Chen)
* [dv] Fix CI error (Cindy Chen)
* [prim_alert_*] Extend SVAs for FPV (Michael Schaffner)
* [prim_alert_*] Update DV TB to respect initialization timing
  (Michael Schaffner)
* [prim_alert_rxtx_fpv] Update FPV environment and fix SVAs (Michael
  Schaffner)
* [prim_alert_sender] Update sender to support in-band reset mechanism
  (Michael Schaffner)
* [prim_alert_sender] Simplify sender and clear ping req upon sigint
  (Michael Schaffner)
* [prim_lc_sender] Add option to select reset value (Michael
  Schaffner)
* [prim] Correct assertion valid term (Timothy Chen)
* [prim_lc_combine] Align behavior of lc combine with mubi functions
  (Michael Schaffner)
* [fpv/tool] Support GUI mode on dvsim (Cindy Chen)
* [prim_lfsr] Further permutation refinements for SBox layer (Michael
  Schaffner)
* [dv/shadow_reg] Shadow register write by field (Cindy Chen)
* [prim] Fix the edge type (Eunchan Kim)
* [checklist] Updates to checklist for D2 status (Tom Roberts)
* [prim_mubi_pkg] Add a generic multibit type and associated functions
  (Michael Schaffner)
* [prim] Minor fix and clarification to prim_count (Timothy Chen)
* [keymgr/dv] Update testplan and covergroup plan (Weicai Yang)
* [prim_lc_combine] Fix parameterization error (Michael Schaffner)
* [fpv/prim_count] Small update on prim_count assertions (Cindy Chen)
* [dv] Add ip_name in reg_block (Weicai Yang)
* [keymgr] Finalize keymgr hardening (Timothy Chen)
* [prim_lc_combine] Add a prim to compute logical AND/OR for LC
  signals (Michael Schaffner)
* [dv] Remove common_cov_excl.el from unr.cfg (Weicai Yang)
* [dv/top_level] Loop through the SW test multiple times (Cindy Chen)
* [flash_ctrl] Various clean-up and updates (Timothy Chen)
* [prim] Change prim_reg_cdc assertions (Timothy Chen)
* [prim, keymgr] Migrate keymgr_cnt to prim_count (Timothy Chen)
* [sw dv] Multi-site support for Verilator (Martin Lueker-Boden)
* [dv/csr] Update write exclusion wdata value (Cindy Chen)
* [dv/dv_base_reg] remove debug display (Cindy Chen)
* [dv/shadow_reg] Fix alert shadow_reg regression error (Cindy Chen)
* [top] Integrate ast into fpga (Timothy Chen)
* [prim_lfsr] Improve statistics of non-linear output (Michael
  Schaffner)
* [prim_esc_receiver] Fix response toggling corner case (Michael
  Schaffner)
* option to use partner ast_pkg (Sharon Topaz)
* [dv/prim_esc] Double the ping timeout cycles (Cindy Chen)
* [dv] Use sed to add -elfile for each excl file (Weicai Yang)
* [dv] Fix coverage report error (Weicai Yang)
* [dv] Update common exclusion file (Weicai Yang)
* [dv/prim_esc] Improve FSM coverage (Cindy Chen)
* [reggen] Add a check to limit the swaccess type for shadow regs
  (Michael Schaffner)
* [prim_subreg_shadow] Fix for W1S/W0C corner case (Michael Schaffner)
* [prim_subreg_shadow] Disallow phase updates when storage err is
  present (Michael Schaffner)
* [dvsim] Add passing count by milestone in reports (Srikrishna Iyer)
* [dv/tool] Include toggle coverage for prim_alert_sender in
  cover_reg_top (Cindy Chen)
* [clkmgr] Harden clock manager through frequency measurements
  (Timothy Chen)
* [dv] Only enable VCS -kdb when dumping waves (Weicai Yang)
* [dv] Fix shadow reg (Weicai Yang)
* [dvsim] Allow non-integral values of --reseed-multiplier (Rupert
  Swarbrick)
* [ast] Fixes for various ast issues (Timothy Chen)
* [prim_esc_receiver] Assert escalation in case of sigint error
  (Michael Schaffner)
* [prim_esc_receiver] Minor signal renaming for consistency (Michael
  Schaffner)
* [dv/alert_handler] Support shadow register sequence (Cindy Chen)
* [verilator] Use FileSz rather than MemSz when flattening ELF files
  (Michael Munday)
* [prim_subreg_shadow] Only assert QE when committed_reg is written
  (Michael Schaffner)
* [dv,verilator] Round up SV_MEM_WIDTH_BYTES to a multiple of 4
  (Rupert Swarbrick)
* [prim] Add missing include (Pirmin Vogel)
* [dv/cover_cfg] Exclude prim_alert/esc from xcelium (Cindy Chen)
* [dv/cover_cfg] Exclude prim_alert/esc pairs (Cindy Chen)
* [clkmgr] Use local BUFHCE clock gates on FPGA (Pirmin Vogel)
* [prim_prince] Mark "leaf" functions in prince_ref.h as static inline
  (Rupert Swarbrick)
* [dv/shadow_reg] Check status after shadow_reg write (Cindy Chen)
* [dv/shadwo_reg] Shadow reg common sequence update (Cindy Chen)
* [otp_ctrl/lc_ctrl] Add 32bit OTP vendor test ctrl/status regs to LC
  TAP (Michael Schaffner)
* [otp_ctrl] Add VENDOR_TEST partition (Michael Schaffner)
* [prim] Edge Detector (Eunchan Kim)
* [prim_diff_decode] Fix asynchronous assertions (Michael Schaffner)
* [spi_device] Instantiate Upload module (Eunchan Kim)
* [dv] Add sv_flist_gen_flags HJson var for FuseSoc (Srikrishna Iyer)
* [dv, xcelium] Properly pass excl files to IMC (Srikrishna Iyer)
* [reg] Fix shadow reg update during storage error (Timothy Chen)
* [regfile] Refactor cdc handling to the reg level (Timothy Chen)
* [dv/prim_esc] Add a testplan and increase coverage (Cindy Chen)
* [dv] Update TLUL and EDN frequency (Weicai Yang)
* [rstmgr, top] Add support for shadow resets (Timothy Chen)
* [dv] Update Xcelium cover ccf (Srikrishna Iyer)
* [dv] reduce seeds for CSR tests (Weicai Yang)
* [usb/top] Remove AND gates on non-AON domain and rename 3.3V signal
  (Michael Schaffner)
* [dv/prim_alert] Improvement on prim_alert tb (Cindy Chen)
* [prim] FIFO SRAM Adapter fix (Eunchan Kim)
* [prim] Add Write Mask port (Eunchan Kim)
* [dv] Fix timescale issue with Xcelium (Weicai Yang)
* [dv/prim_esc] Fix prim_esc regression error (Cindy Chen)
* [dv/dv_base_reg] change from uvm_low to uvm_high (Cindy Chen)
* [sram_ctrl] Harden initialization counter (Michael Schaffner)
* [tools/uvmdvgen] Fix path in testplan inclusion (Guillermo Maturana)
* [dv] Change stress_all_with_rand_reset to V3 (Weicai Yang)
* [dv] fix tl error coverage (Weicai Yang)
* [dv] Add macro DV_GET_ENUM_PLUSARG (Weicai Yang)
* [prim] SRAM Async FIFO (Eunchan Kim)
* [dv, xcelium] Fix statement coverage extraction (Srikrishna Iyer)
* [dvsim] Minor fixes to coverage extraction (Srikrishna Iyer)
* [prim_lfsr] Do not shadow |state| variable (Philipp Wagner)
* [prim] Add non-linear out option to prim_lfsr (Timothy Chen)
* [dv] Constrain TLUL to 24Mhz or higher (Weicai Yang)
* [primgen] Instantiate tech libs in stable order (Philipp Wagner)
* [primgen] Actually find the Verible Python wrapper (Philipp Wagner)
* [dv/prim_esc] fix regression error (Cindy Chen)
* [dv] Fix shadow reg predict (Weicai Yang)
* [dv/common] Exclude assertion coverage from IP level testbench
  (Cindy Chen)
* [dv/prince] hit additional toggle coverpoints (Udi Jonnalagadda)
* [sram_ctrl] Update docs (Michael Schaffner)
* [sram_ctrl] Absorb prim_ram_1p_scr (Michael Schaffner)
* [dv/prim_alert/esc] Improvements for prim_alert/esc_tb (Cindy Chen)
* [dv/dvsim] Add "testfile" grading option (Guillermo Maturana)
* [dv/prim_esc] Direct test for prim_rx/tx (Cindy Chen)
* [dv/utils] added 6MHz to clk_freq_mhz_e (Dror Kabely)
* [prim_xor2/lint] Add waiver for .* use in generated prim (Michael
  Schaffner)
* [dv, doc] Replace all 'dv.plan' with testplan (Srikrishna Iyer)
* Fix the testplan link in dvsim code (Srikrishna Iyer)
* [dv/dsim] Add dsim workaround for issue 242 (Guillermo Maturana)
* [util, reggen] Support standardized cdc handling for regfile
  (Timothy Chen)
* [dv/shadow_reg] Align shadow_reg field update behavior (Cindy Chen)
* [dvsim] Fix publish report summary typo (Cindy Chen)
* [rtl/prim_alert_sender] Allow ping_req to stay high without error
  (Cindy Chen)
* [dvsim] Separate publish report from dvsim flow [PART3] (Cindy Chen)
* [dv/prim_alert] Add a testbench for prim_alert (Cindy Chen)
* [otp_ctrl] Connect test-related GPIO signal (Michael Schaffner)
* [prim_subreg_shadow] Make local parameter a localparam (Philipp
  Wagner)
* [prim_subreg] Make software access type an enum (Philipp Wagner)
* [rtl/prim_diff_decode] Add prim_flop_2sync dependency (Cindy Chen)
* [otp_ctrl] Update AscentLint waiver file (Michael Schaffner)
* [edn] Add MaxLatency assertion (Eunchan Kim)
* [prim_subreg_shadow] Correct write data signal usage (Michael
  Schaffner)
* [script/dvsim] Separate publish report from dvsim flow [PART2]
  (Cindy Chen)
* [prim_lfsr] Fix assertion issue occuring right after reset (Michael
  Schaffner)
* [dv/shadow_reg] Handle CSR automated sequence write abort (Cindy
  Chen)
* [dv/dv_lib] Add post_apply_reset for extra delay (Guillermo
  Maturana)
* [dv] Add function coverage plan for tl_errors, tl_intg_err (Weicai
  Yang)
* [dv] Remove tl_intg_err in top-level and increase seeds for
  tl_intg_err (Weicai Yang)
* [dv/shadow_reg] Fix alert shadow reg regression error (Cindy Chen)

Signed-off-by: Rupert Swarbrick <rswarbrick@lowrisc.org>
This commit is contained in:
Rupert Swarbrick 2021-10-05 12:35:08 +01:00 committed by Rupert Swarbrick
parent e70add7228
commit b66f199151
151 changed files with 5374 additions and 883 deletions

View file

@ -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);
wdata = get_csr_wdata_with_write_excl(test_csrs[i], wdata, CsrHwResetTest);
`downcast(dv_csr, test_csrs[i])
if (en_rand_backdoor_write && !dv_csr.get_is_ext_reg()) begin
@ -232,6 +232,7 @@ class csr_rw_seq extends csr_base_seq;
uvm_reg_data_t wdata;
uvm_reg_data_t compare_mask;
uvm_reg_field test_fields[$];
dv_base_reg test_dv_csr;
// check if parent block or register is excluded from write
if (is_excl(test_csrs[i], CsrExclWrite, CsrRwTest)) begin
@ -244,7 +245,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);
wdata = get_csr_wdata_with_write_excl(test_csrs[i], wdata, 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
@ -253,6 +254,14 @@ class csr_rw_seq extends csr_base_seq;
// register is getting the updated access information.
csr_wr(.ptr(test_csrs[i]), .value(wdata), .blocking(0), .predict(!external_checker));
// Shadow register requires two writes with the same value to write registers into DUT.
// In `csr_wr` task, the `predict` task is triggered after two shadow writes are done.
// To avoid non-blocking access where shadow register read might be triggered between two
// consecutive shadow register write, we will wait until all outstanding accesses finish,
// then issue a shadow register read.
`downcast(test_dv_csr, test_csrs[i])
if (test_dv_csr.get_is_shadowed) wait_no_outstanding_access();
do_check_csr_or_field_rd(.csr(test_csrs[i]),
.blocking(0),
.compare(!external_checker),
@ -413,7 +422,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);
wdata = get_csr_wdata_with_write_excl(test_csrs[i], wdata, CsrAliasingTest);
csr_wr(.ptr(test_csrs[i]), .value(wdata), .blocking(0), .predict(!external_checker));
all_csrs.shuffle();

View file

@ -125,14 +125,6 @@ package csr_utils_pkg;
return result;
endfunction : decode_csr_or_field
// mask and shift data to extract the value specific to that supplied field
function automatic uvm_reg_data_t get_field_val(uvm_reg_field field,
uvm_reg_data_t value);
uvm_reg_data_t mask = (1 << field.get_n_bits()) - 1;
uint shift = field.get_lsb_pos();
get_field_val = (value >> shift) & mask;
endfunction
// get updated reg value by using new specific field value
function automatic uvm_reg_data_t get_csr_val_with_updated_field(uvm_reg_field field,
uvm_reg_data_t csr_value,
@ -152,6 +144,8 @@ package csr_utils_pkg;
csr.get_full_name(), csr.m_is_busy), UVM_HIGH)
endtask
// Use `csr_wr` to construct `csr_update` to avoid replicated codes to handle nonblocking,
// shadow writes etc
task automatic csr_update(input uvm_reg csr,
input uvm_check_e check = default_csr_check,
input uvm_path_e path = UVM_DEFAULT_PATH,
@ -159,53 +153,21 @@ package csr_utils_pkg;
input uint timeout_ns = default_timeout_ns,
input uvm_reg_map map = null,
input bit en_shadow_wr = 1);
if (blocking) begin
csr_update_sub(csr, check, path, timeout_ns, map, en_shadow_wr);
end else begin
fork
csr_update_sub(csr, check, path, timeout_ns, map, en_shadow_wr);
join_none
// Add #0 to ensure that this thread starts executing before any subsequent call
#0;
uvm_reg_field fields[$];
uvm_reg_data_t value;
// below is partial replication of the uvm_reg_field::update() logic in UVM1.2 source code
if (!csr.needs_update()) return;
csr.get_fields(fields);
// Concatenate the write-to-update values from each field
// Fields are stored in LSB or MSB order
value = 0;
foreach (fields[i]) begin
value |= fields[i].XupdateX() << fields[i].get_lsb_pos();
end
endtask
// subroutine of csr_update, don't use it directly
task automatic csr_update_sub(input uvm_reg csr,
input uvm_check_e check = default_csr_check,
input uvm_path_e path = UVM_DEFAULT_PATH,
input uint timeout_ns = default_timeout_ns,
input uvm_reg_map map = null,
input bit en_shadow_wr = 1);
fork
begin : isolation_fork
uvm_status_e status;
string msg_id = {csr_utils_pkg::msg_id, "::csr_update"};
fork
begin
increment_outstanding_access();
csr_pre_write_sub(csr, en_shadow_wr);
csr.update(.status(status), .path(path), .map(map), .prior(100));
csr_post_write_sub(csr, en_shadow_wr);
// when reset occurs, all items will be dropped immediately. This may end up getting
// d_error = 1 from previous item on the bus. Skip checking it during reset
if (check == UVM_CHECK && !under_reset) begin
`DV_CHECK_EQ(status, UVM_IS_OK,
$sformatf("trying to update csr %0s", csr.get_full_name()),
error, msg_id)
end
decrement_outstanding_access();
end
begin
wait_timeout(timeout_ns, msg_id,
$sformatf("Timeout waiting to csr_update %0s (addr=0x%0h)",
csr.get_full_name(), csr.get_address()));
end
join_any
disable fork;
end : isolation_fork
join
csr_wr(.ptr(csr), .value(value), .check(check), .path(path), .blocking(blocking), .backdoor(0),
.timeout_ns(timeout_ns), .predict(0), .map(map), .en_shadow_wr(en_shadow_wr));
endtask
task automatic csr_wr(input uvm_object ptr,
@ -254,25 +216,24 @@ package csr_utils_pkg;
input bit en_shadow_wr = 1);
fork
begin : isolation_fork
uvm_status_e status;
string msg_id = {csr_utils_pkg::msg_id, "::csr_wr"};
fork
begin
dv_base_reg dv_reg;
`downcast(dv_reg, csr, "", fatal, msg_id)
increment_outstanding_access();
csr_pre_write_sub(csr, en_shadow_wr);
csr.write(.status(status), .value(value), .path(path), .map(map), .prior(100));
csr_wr_and_predict_sub(.csr(csr), .value(value), .check(check), .path(path),
.predict(predict), .map(map));
if (en_shadow_wr && dv_reg.get_is_shadowed()) begin
csr_wr_and_predict_sub(.csr(csr), .value(value), .check(check), .path(path),
.predict(predict), .map(map));
end
csr_post_write_sub(csr, en_shadow_wr);
if (check == UVM_CHECK && !under_reset) begin
`DV_CHECK_EQ(status, UVM_IS_OK,
$sformatf("trying to write csr %0s", csr.get_full_name()),
error, msg_id)
end
// Only update the predicted value if status is ok (otherwise the write isn't completed
// successfully and the design shouldn't have accepted the written value)
if (status == UVM_IS_OK && predict) begin
void'(csr.predict(.value(value), .kind(UVM_PREDICT_WRITE)));
end
decrement_outstanding_access();
end
begin
@ -286,27 +247,42 @@ package csr_utils_pkg;
join
endtask
task automatic csr_pre_write_sub(ref uvm_reg csr, bit en_shadow_wr);
dv_base_reg dv_reg;
`downcast(dv_reg, csr, "", fatal, msg_id)
if (dv_reg.get_is_shadowed()) begin
if (en_shadow_wr) increment_outstanding_access();
dv_reg.atomic_en_shadow_wr.get(1);
dv_reg.set_en_shadow_wr(en_shadow_wr);
// internal task, don't use it directly
task automatic csr_wr_and_predict_sub(uvm_reg csr,
uvm_reg_data_t value,
uvm_check_e check,
uvm_path_e path,
bit predict,
uvm_reg_map map);
uvm_status_e status;
csr.write(.status(status), .value(value), .path(path), .map(map), .prior(100));
if (under_reset) return;
if (check == UVM_CHECK) begin
`DV_CHECK_EQ(status, UVM_IS_OK,
$sformatf("trying to write csr %0s", csr.get_full_name()),
error, msg_id)
end
// Only update the predicted value if status is ok (otherwise the write isn't completed
// successfully and the design shouldn't have accepted the written value)
if (status == UVM_IS_OK && predict) begin
void'(csr.predict(.value(value), .kind(UVM_PREDICT_WRITE)));
end
endtask
task automatic csr_post_write_sub(ref uvm_reg csr, bit en_shadow_wr);
task automatic csr_pre_write_sub(uvm_reg csr, bit en_shadow_wr);
dv_base_reg dv_reg;
`downcast(dv_reg, csr, "", fatal, msg_id)
if (dv_reg.get_is_shadowed()) begin
// try setting en_shadow_wr back to default value 1, this function will only work if the
// shadow reg finished both writes
dv_reg.set_en_shadow_wr(1);
if (dv_reg.get_is_shadowed() && en_shadow_wr) begin
dv_reg.atomic_en_shadow_wr.get(1);
end
endtask
task automatic csr_post_write_sub(uvm_reg csr, bit en_shadow_wr);
dv_base_reg dv_reg;
`downcast(dv_reg, csr, "", fatal, msg_id)
if (dv_reg.get_is_shadowed() && en_shadow_wr) begin
dv_reg.atomic_en_shadow_wr.put(1);
if (en_shadow_wr) begin
decrement_outstanding_access();
end
end
endtask
@ -726,6 +702,30 @@ package csr_utils_pkg;
end
endfunction
// Returns the write data value masked with excluded fields.
//
// Some fields in the CSR may be excluded from writes. In that case, we need to revert those
// fields to their mirrored values and write the rest of the fields with the given value.
function automatic uvm_reg_data_t get_csr_wdata_with_write_excl(
uvm_reg csr,
uvm_reg_data_t wdata,
csr_test_type_e csr_test_type,
csr_excl_item m_csr_excl_item = get_excl_item(csr)
);
uvm_reg_field flds[$];
csr.get_fields(flds);
foreach (flds[i]) begin
if (m_csr_excl_item.is_excl(flds[i], CsrExclWrite, csr_test_type)) begin
`uvm_info(msg_id, $sformatf(
"Retain mirrored value 0x%0h for field %0s due to CsrExclWrite exclusion",
`gmv(flds[i]), flds[i].get_full_name()), UVM_MEDIUM)
wdata = get_csr_val_with_updated_field(flds[i], wdata, `gmv(flds[i]));
end
end
return wdata;
endfunction
function automatic csr_excl_item get_excl_item(uvm_object ptr);
csr_field_t csr_or_fld;
dv_base_reg_block blk;

View file

@ -8,20 +8,17 @@ class dv_base_reg extends uvm_reg;
// hence, backdoor write isn't available
local bit is_ext_reg;
local uvm_reg_data_t staged_shadow_val, committed_val, shadowed_val;
local bit is_shadowed;
local bit shadow_wr_staged; // stage the first shadow reg write
local bit shadow_update_err;
local bit en_shadow_wr = 1;
// In certain shadow reg (e.g. in AES), fatal error can lock write access
local bit backdoor_write_shadow_val; // flag to avoid predict `shadow_wr_staged`
// Update internal shadow committed and shadowed values when register access is not `RW`.
local bit do_update_shadow_vals;
// In certain shadow reg (e.g. in AES), fatal error can lock write access.
local bit shadow_fatal_lock;
local string update_err_alert_name;
local string storage_err_alert_name;
// atomic_shadow_wr: semaphore to guarantee atomicity of the two writes for shadowed registers.
// In case a parallel thread writing a different value to the same reg causing an update_err
semaphore atomic_shadow_wr;
// atomic_en_shadow_wr: semaphore to guarantee setting or resetting en_shadow_wr is unchanged
// through the 1st/2nd (or both) writes
semaphore atomic_en_shadow_wr;
@ -31,13 +28,16 @@ class dv_base_reg extends uvm_reg;
int has_coverage);
super.new(name, n_bits, has_coverage);
atomic_en_shadow_wr = new(1);
atomic_shadow_wr = new(1);
endfunction : new
function void get_dv_base_reg_fields(ref dv_base_reg_field dv_fields[$]);
foreach (m_fields[i]) `downcast(dv_fields[i], m_fields[i])
endfunction
function dv_base_reg_block get_dv_base_reg_block();
`downcast(get_dv_base_reg_block, get_parent())
endfunction
// get_n_bits will return number of all the bits in the csr
// while this function will return actual number of bits used in reg field
function uint get_n_used_bits();
@ -65,6 +65,15 @@ class dv_base_reg extends uvm_reg;
return dv_fld;
endfunction
// Return a mask of valid bits in the register.
virtual function uvm_reg_data_t get_reg_mask();
dv_base_reg_field flds[$];
this.get_dv_base_reg_fields(flds);
foreach (flds[i]) begin
get_reg_mask |= flds[i].get_field_mask();
end
endfunction
// this function can only be called when this reg is intr_state reg
// Example: ral.intr_state.get_intr_pins_exp_value(). And it returns value of
// intr_state & intr_enable, which represents value of interrupt pins
@ -138,19 +147,12 @@ class dv_base_reg extends uvm_reg;
is_shadowed = 1;
endfunction
function uvm_reg_data_t get_staged_shadow_val();
return staged_shadow_val;
endfunction
function void set_en_shadow_wr(bit val);
// do not update en_shadow_wr if shadow register write is in process
if ((en_shadow_wr ^ val) && shadow_wr_staged) begin
`uvm_info(`gfn,
$sformatf("unable to %0s en_shadow_wr because register already completed first write",
val ? "set" : "clear"), UVM_HIGH)
return;
// A helper function for shadow register or field read to clear the `shadow_wr_staged` flag.
virtual function void clear_shadow_wr_staged();
if (is_shadowed) begin
if (shadow_wr_staged) `uvm_info(`gfn, "clear shadow_wr_staged", UVM_HIGH)
shadow_wr_staged = 0;
end
en_shadow_wr = val;
endfunction
function bit get_is_shadowed();
@ -162,53 +164,71 @@ class dv_base_reg extends uvm_reg;
endfunction
function bit get_shadow_storage_err();
uvm_reg_data_t mask = (1'b1 << (get_msb_pos() + 1)) - 1;
uvm_reg_data_t shadowed_val_temp = (~shadowed_val) & mask;
uvm_reg_data_t committed_val_temp = committed_val & mask;
`uvm_info(`gfn, $sformatf("shadow_val %0h, commmit_val %0h", shadowed_val_temp,
committed_val_temp), UVM_DEBUG)
return shadowed_val_temp != committed_val_temp;
dv_base_reg_field flds[$];
this.get_dv_base_reg_fields(flds);
foreach (flds[i]) begin
get_shadow_storage_err |= flds[i].get_shadow_storage_err();
end
endfunction
virtual function void clear_shadow_update_err();
shadow_update_err = 0;
endfunction
// post_write callback to handle special regs:
// do_predict callback to handle special regs. This function doesn't update mirror values, but
// update local variables used for the special regs.
// - shadow register: shadow reg won't be updated until the second write has no error
// - lock register: if wen_fld is set to 0, change access policy to all the lockable_flds
// TODO: create an `enable_field_access_policy` variable and set the template code during
// automation.
virtual task post_write(uvm_reg_item rw);
dv_base_reg_field fields[$];
virtual function void pre_do_predict(uvm_reg_item rw, uvm_predict_e kind);
// no need to update shadow value or access type if access is not OK, as access is aborted
if (rw.status != UVM_IS_OK) return;
// Skip updating shadow value or access type if:
// 1). Access is not OK, as access is aborted.
// 2). The operation is not write.
// 3). The update is triggered by backdoor poke.
if (rw.status != UVM_IS_OK || kind != UVM_PREDICT_WRITE || backdoor_write_shadow_val) return;
if (is_shadowed && !shadow_fatal_lock) begin
// first write
if (!shadow_wr_staged) begin
shadow_wr_staged = 1;
// rw.value is a dynamic array
staged_shadow_val = rw.value[0];
return;
end begin
// second write
shadow_wr_staged = 0;
if (staged_shadow_val != rw.value[0]) begin
shadow_update_err = 1;
return;
dv_base_reg_field flds[$];
this.get_dv_base_reg_fields(flds);
foreach (flds[i]) begin
// `rw.value` is a dynamic array.
uvm_reg_data_t wr_data = get_field_val(flds[i], rw.value[0]);
// Skip updating shadow value or access type for this field if:
// 1). A storage error is triggered, which means the field is locked to error status.
// 2). The register is "RO". This condition is used to cover enable register locks shadowed
// register's write access.
if (flds[i].get_shadow_storage_err() || flds[i].get_access() == "RO") continue;
// first write
if (!shadow_wr_staged) begin
flds[i].update_staged_val(wr_data);
continue;
end begin
// second write
if (flds[i].get_staged_val() == wr_data) begin
flds[i].update_committed_val(wr_data);
flds[i].update_shadowed_val(~wr_data);
end else begin
shadow_update_err = 1;
end
end
committed_val = staged_shadow_val;
shadowed_val = ~committed_val;
end
if (!shadow_wr_staged) shadow_wr_staged = 1;
else shadow_wr_staged = 0;
// Update committed and shadowed values if the field access is not "RW".
// Used for register with special access policy such as `RW1S`.
if (!shadow_wr_staged && flds[0].get_access() != "RW") do_update_shadow_vals = 1;
end
lock_lockable_flds(rw.value[0]);
endtask
endfunction
// shadow register read will clear its phase tracker
virtual task post_read(uvm_reg_item rw);
if (is_shadowed) shadow_wr_staged = 0;
if (rw.status == UVM_IS_OK) clear_shadow_wr_staged();
endtask
virtual function void set_is_ext_reg(bit is_ext);
@ -219,42 +239,45 @@ class dv_base_reg extends uvm_reg;
return is_ext_reg;
endfunction
// if it is a shadowed register, and is enabled to write it twice, this task will write the
// register twice with the same value and address.
virtual task write(output uvm_status_e status,
input uvm_reg_data_t value,
input uvm_path_e path = UVM_DEFAULT_PATH,
input uvm_reg_map map = null,
input uvm_sequence_base parent=null,
input int prior = -1,
input uvm_object extension = null,
input string fname = "",
input int lineno = 0);
if (is_shadowed) atomic_shadow_wr.get(1);
super.write(status, value, path, map, parent, prior, extension, fname, lineno);
if (is_shadowed && en_shadow_wr) begin
super.write(status, value, path, map, parent, prior, extension, fname, lineno);
end
if (is_shadowed) atomic_shadow_wr.put(1);
endtask
// Override do_predict function to support shadow_reg.
// Skip predict in one of the following conditions:
// 1). It is shadow_reg's first write.
// 2). It is shadow_reg's second write with an update_err.
// 2). The shadow_reg is locked due to fatal storage error and it is not a backdoor write.
// Note that if shadow_register write has update error, we only update the value with correct
// fields.
virtual function void do_predict(uvm_reg_item rw,
uvm_predict_e kind = UVM_PREDICT_DIRECT,
uvm_reg_byte_en_t be = -1);
if (is_shadowed && kind != UVM_PREDICT_READ && (shadow_wr_staged || shadow_update_err ||
(shadow_fatal_lock && rw.path != UVM_BACKDOOR))) begin
`uvm_info(`gfn, $sformatf(
"skip predict %s: due to shadow_reg_first_wr=%0b, update_err=%0b, shadow_fatal_lock=%0b",
get_name(), shadow_wr_staged, shadow_update_err, shadow_fatal_lock), UVM_HIGH)
return;
pre_do_predict(rw, kind);
if (is_shadowed && kind != UVM_PREDICT_READ) begin
if (shadow_wr_staged || (shadow_fatal_lock && rw.path != UVM_BACKDOOR)) begin
`uvm_info(`gfn, $sformatf(
"skip predict %s: due to shadow_reg_first_wr=%0b, shadow_fatal_lock=%0b",
get_name(), shadow_wr_staged, shadow_fatal_lock), UVM_HIGH)
return;
end else begin
`uvm_info(`gfn, $sformatf(
"Shadow reg %0s has update error, update rw.value from %0h to %0h",
get_name(), rw.value[0], get_committed_val()), UVM_HIGH)
rw.value[0] = get_committed_val();
end
end
super.do_predict(rw, kind, be);
// For register with special access policies, update committed and shadowed value again with
// the actual predicted value.
if (do_update_shadow_vals) begin
dv_base_reg_field flds[$];
this.get_dv_base_reg_fields(flds);
foreach (flds[i]) begin
if (!flds[i].get_shadow_storage_err()) begin
flds[i].update_committed_val(`gmv(flds[i]));
flds[i].update_shadowed_val(~`gmv(flds[i]));
end
end
do_update_shadow_vals = 0;
end
lock_lockable_flds(rw.value[0]);
endfunction
// This function is used for wen_reg to lock its lockable flds by changing the lockable flds'
@ -287,31 +310,35 @@ class dv_base_reg extends uvm_reg;
input uvm_object extension = null,
input string fname = "",
input int lineno = 0);
if (kind == "BkdrRegPathRtlShadow") shadowed_val = value;
else if (kind == "BkdrRegPathRtlCommitted") committed_val = value;
dv_base_reg_field flds[$];
this.get_dv_base_reg_fields(flds);
foreach (flds[i]) begin
if (kind == "BkdrRegPathRtlShadow") begin
flds[i].update_shadowed_val(get_field_val(flds[i], value));
backdoor_write_shadow_val = 1;
end else if (kind == "BkdrRegPathRtlCommitted") begin
flds[i].update_committed_val(get_field_val(flds[i], value));
backdoor_write_shadow_val = 1;
end
end
super.poke(status, value, kind, parent, extension, fname, lineno);
backdoor_write_shadow_val = 0;
endtask
virtual function uvm_reg_data_t get_committed_val();
dv_base_reg_field flds[$];
this.get_dv_base_reg_fields(flds);
foreach (flds[i]) begin
get_committed_val |= flds[i].get_committed_val() << flds[i].get_lsb_pos();
end
endfunction
// Callback function to update shadowed values according to specific design.
// Should only be called after post-write.
// If a shadow reg is locked due to fatal error, this function will return without updates
virtual function void update_shadowed_val(uvm_reg_data_t val, bit do_predict = 1);
if (shadow_fatal_lock) return;
if (shadow_wr_staged) begin
// update value after first write
staged_shadow_val = val;
end else begin
// update value after second write
if (staged_shadow_val != val) begin
shadow_update_err = 1;
end else begin
shadow_update_err = 0;
committed_val = staged_shadow_val;
shadowed_val = ~committed_val;
end
end
if (do_predict) void'(predict(val));
// TODO: find a better way to support for AES.
endfunction
virtual function void reset(string kind = "HARD");
@ -320,12 +347,8 @@ class dv_base_reg extends uvm_reg;
shadow_update_err = 0;
shadow_wr_staged = 0;
shadow_fatal_lock = 0;
committed_val = get_mirrored_value();
shadowed_val = ~committed_val;
// in case reset is issued during shadowed writes
void'(atomic_shadow_wr.try_get(1));
void'(atomic_en_shadow_wr.try_get(1));
atomic_shadow_wr.put(1);
atomic_en_shadow_wr.put(1);
end
endfunction
@ -339,13 +362,11 @@ class dv_base_reg extends uvm_reg;
endfunction
function string get_update_err_alert_name();
string parent_name = this.get_parent().get_name();
// block level alert name is input alert name from hjson
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));
// top-level alert name is ${ip_name} + alert name from hjson
return ($sformatf("%0s_%0s", get_dv_base_reg_block().get_ip_name(), update_err_alert_name));
endfunction
function void lock_shadow_reg();
@ -357,13 +378,13 @@ class dv_base_reg extends uvm_reg;
endfunction
function string get_storage_err_alert_name();
string parent_name = this.get_parent().get_name();
string ip_name;
// block level alert name is input alert name from hjson
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));
// top-level alert name is ${ip_name} + alert name from hjson
return ($sformatf("%0s_%0s", get_dv_base_reg_block().get_ip_name(), storage_err_alert_name));
endfunction
endclass

View file

@ -6,6 +6,12 @@
class dv_base_reg_block extends uvm_reg_block;
`uvm_object_utils(dv_base_reg_block)
// Since an IP may contains more than one reg block we construct reg_block name as
// {ip_name}_{reg_interface_name}.
// All the reg_blocks in the IP share the same alert. In top-level, We construct the alert
// name as {ip_name}_{alert_name}. Hence, we need this ip_name in reg_block
local string ip_name;
csr_excl_item csr_excl;
// The address mask for the register block specific to a map. This will be (1 << K) - 1 for some
@ -29,6 +35,17 @@ class dv_base_reg_block extends uvm_reg_block;
super.new(name, has_coverage);
endfunction
function void set_ip_name(string name);
ip_name = name;
endfunction
function string get_ip_name();
// `DV_CHECK_NE_FATAL can't take "" as an input
string empty_str = "";
`DV_CHECK_NE_FATAL(ip_name, empty_str, "ip_name hasn't been set yet")
return ip_name;
endfunction
// provide build function to supply base addr
virtual function void build(uvm_reg_addr_t base_addr,
csr_excl_item csr_excl = null);
@ -277,4 +294,13 @@ class dv_base_reg_block extends uvm_reg_block;
return (word_aligned ? get_word_aligned_addr(byte_offset) : byte_offset) + map.get_base_addr();
endfunction
// The design ignores the address bits that aren't enabled by addr_mask.
// Normalize these ignored bits to enable locating which CSR/mem is at the returned address.
function uvm_reg_addr_t get_normalized_addr(uvm_reg_addr_t byte_addr, uvm_reg_map map = null);
if (map == null) map = get_default_map();
return get_addr_from_offset(.byte_offset(byte_addr & addr_mask[map]),
.word_aligned(1),
.map(map));
endfunction
endclass

View file

@ -7,6 +7,7 @@ class dv_base_reg_field extends uvm_reg_field;
local string m_original_access;
local dv_base_reg_field lockable_flds[$];
local bit is_intr_test_fld;
local uvm_reg_data_t staged_val, committed_val, shadowed_val;
`uvm_object_utils(dv_base_reg_field)
`uvm_object_new
@ -34,6 +35,7 @@ class dv_base_reg_field extends uvm_reg_field;
value.rand_mode(is_rand);
is_intr_test_fld = !(uvm_re_match("intr_test*", get_parent().get_name()));
shadowed_val = ~committed_val;
endfunction
virtual function dv_base_reg get_dv_base_reg_parent();
@ -126,11 +128,50 @@ class dv_base_reg_field extends uvm_reg_field;
lockable_flds_q = lockable_flds;
endfunction
// shadow register field read will clear its phase tracker
virtual task post_read(uvm_reg_item rw);
if (rw.status == UVM_IS_OK) begin
dv_base_reg parent_csr = get_dv_base_reg_parent();
parent_csr.clear_shadow_wr_staged();
end
endtask
function bit get_shadow_storage_err();
uvm_reg_data_t mask = (1 << get_n_bits()) - 1;
uvm_reg_data_t shadowed_val_temp = (~shadowed_val) & mask;
uvm_reg_data_t committed_val_temp = committed_val & mask;
`uvm_info(`gfn, $sformatf("shadow_val %0h, commmit_val %0h", shadowed_val_temp,
committed_val_temp), UVM_HIGH)
return shadowed_val_temp != committed_val_temp;
endfunction
function void update_staged_val(uvm_reg_data_t val);
staged_val = val;
endfunction
function uvm_reg_data_t get_staged_val();
return staged_val;
endfunction
function void update_shadowed_val(uvm_reg_data_t val);
shadowed_val = val;
endfunction
function void update_committed_val(uvm_reg_data_t val);
committed_val = val;
endfunction
function uvm_reg_data_t get_committed_val();
return committed_val;
endfunction
// override RAL's reset function to support enable registers
// when reset issued - the lockable field's access will be reset to original access
virtual function void reset(string kind = "HARD");
super.reset(kind);
set_fld_access(0);
committed_val = get_mirrored_value();
shadowed_val = ~committed_val;
endfunction
// this function can only be called when this reg is intr_test reg

View file

@ -73,4 +73,12 @@ package dv_base_reg_pkg;
end
endfunction
// mask and shift data to extract the value specific to that supplied field
function automatic uvm_reg_data_t get_field_val(uvm_reg_field field,
uvm_reg_data_t value);
uvm_reg_data_t mask = (1 << field.get_n_bits()) - 1;
uint shift = field.get_lsb_pos();
get_field_val = (value >> shift) & mask;
endfunction
endpackage

View file

@ -43,8 +43,15 @@ class dv_base_env_cfg #(type RAL_T = dv_base_reg_block) extends uvm_object;
// 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];
rand uint clk_freq_mhz;
rand uint clk_freqs_mhz[string];
constraint clk_freq_mhz_c {
`DV_COMMON_CLK_CONSTRAINT(clk_freq_mhz)
foreach (clk_freqs_mhz[i]) {
`DV_COMMON_CLK_CONSTRAINT(clk_freqs_mhz[i])
}
}
`uvm_object_param_utils_begin(dv_base_env_cfg #(RAL_T))
`uvm_field_int (is_active, UVM_DEFAULT)
@ -74,7 +81,7 @@ class dv_base_env_cfg #(type RAL_T = dv_base_reg_block) extends uvm_object;
// add items to clk_freqs_mhz before randomizing it
foreach (ral_model_names[i]) begin
clk_freqs_mhz[ral_model_names[i]] = ClkFreq24Mhz;
clk_freqs_mhz[ral_model_names[i]] = 0;
end
endfunction

View file

@ -78,8 +78,10 @@ class dv_base_vseq #(type RAL_T = dv_base_reg_block,
* startup, reset and shutdown related tasks
*/
virtual task dut_init(string reset_kind = "HARD");
if (do_apply_reset) apply_reset(reset_kind);
else if (do_wait_for_reset) wait_for_reset(reset_kind);
if (do_apply_reset) begin
apply_reset(reset_kind);
post_apply_reset(reset_kind);
end else if (do_wait_for_reset) wait_for_reset(reset_kind);
// delay after reset for tl agent check seq_item_port empty
#1ps;
endtask
@ -137,6 +139,11 @@ class dv_base_vseq #(type RAL_T = dv_base_reg_block,
end
endtask
// This is called after apply_reset in this class and after apply_resets_concurrently
// in cip_base_vseq::run_stress_all_with_rand_reset_vseq.
virtual task post_apply_reset(string reset_kind = "HARD");
endtask
virtual task wait_for_reset(string reset_kind = "HARD",
bit wait_for_assert = 1,
bit wait_for_deassert = 1);

View file

@ -409,6 +409,24 @@
end
`endif
// This macro converts a string input from plusarg to an enum variable
// ENUM_: the name of enum type
// PLUSARG_: the name of the plusargs, which is also the name of the enum variable
// CHECK_EXIST_: set to 1, `$value$plusargs()` should return true
`ifndef DV_GET_ENUM_PLUSARG
`define DV_GET_ENUM_PLUSARG(ENUM_, PLUSARG_, CHECK_EXIST_ = 0, ID_ = `gfn) \
begin \
string str; \
if ($value$plusargs("``PLUSARG_``=%0s", str)) begin \
if (!uvm_enum_wrapper#(ENUM_)::from_name(str, PLUSARG_)) begin \
`uvm_fatal(ID_, $sformatf("Cannot find %s from enum ``ENUM_``", PLUSARG_.name)) \
end \
end else if (CHECK_EXIST_) begin \
`uvm_fatal(ID_, "Can't find plusargs ``PLUSARG_``") \
end \
end
`endif
// Enable / disable assertions at a module hierarchy identified by LABEL_.
//
// This goes in conjunction with `DV_ASSERT_CTRL() macro above, but is invoked in the entity that is
@ -492,3 +510,18 @@
`endif
`endif // UVM
// Macros for constrain clk with common frequencies
// constrain clock to run at 24Mhz - 100Mhz and use higher weights on 24, 25, 48, 50, 100
`ifndef DV_COMMON_CLK_CONSTRAINT
`define DV_COMMON_CLK_CONSTRAINT(FREQ_) \
FREQ_ dist { \
[24:25] :/ 2, \
[26:47] :/ 1, \
[48:50] :/ 2, \
[51:95] :/ 1, \
96 :/ 1, \
[97:99] :/ 1, \
100 :/ 1 \
};
`endif

View file

@ -44,15 +44,6 @@ package dv_utils_pkg;
Device
} if_mode_e;
// speed for the clock
typedef enum int {
ClkFreq24Mhz = 24,
ClkFreq25Mhz = 25,
ClkFreq48Mhz = 48,
ClkFreq50Mhz = 50,
ClkFreq100Mhz = 100
} clk_freq_mhz_e;
// compare operator types
typedef enum {
CompareOpEq,
@ -85,6 +76,14 @@ package dv_utils_pkg;
HostReqReadWrite = 3
} host_req_type_e;
// Enum representing clock frequency difference on 2 clocks
typedef enum bit [1:0] {
ClkFreqDiffNone,
ClkFreqDiffSmall,
ClkFreqDiffBig,
ClkFreqDiffAny
} clk_freq_diff_e;
string msg_id = "dv_utils_pkg";
// return the smaller value of 2 inputs

View file

@ -137,19 +137,19 @@
// Project defaults for VCS
vcs_cov_cfg_file: "{{build_mode}_vcs_cov_cfg_file}"
vcs_unr_cfg_file: "{dv_root}/tools/vcs/unr.cfg"
vcs_cov_excl_files: ["{dv_root}/tools/vcs/common_cov_excl.el"]
vcs_cov_excl_files: []
// Build-specific coverage cfg files for VCS.
default_vcs_cov_cfg_file: "-cm_hier {dv_root}/tools/vcs/cover.cfg"
cover_reg_top_vcs_cov_cfg_file: "-cm_hier {dv_root}/tools/vcs/cover_reg_top.cfg"
default_vcs_cov_cfg_file: "-cm_hier {dv_root}/tools/vcs/cover.cfg+{dv_root}/tools/vcs/common_cov_excl.cfg"
cover_reg_top_vcs_cov_cfg_file: "-cm_hier {dv_root}/tools/vcs/cover_reg_top.cfg+{dv_root}/tools/vcs/common_cov_excl.cfg"
// Project defaults for Xcelium
xcelium_cov_cfg_file: "{dv_root}/tools/xcelium/xcelium.ccf"
xcelium_cov_refine_files: []
xcelium_cov_cfg_file: "{{build_mode}_xcelium_cov_cfg_file}"
xcelium_unr_cfg_file: "{dv_root}/tools/xcelium/unr.cfg"
xcelium_common_excl_file: ["{dv_root}/tools/xcelium/exclude.tcl"]
xcelium_cov_excl_script: "{dv_root}/tools/xcelium/common_cov_excl.tcl"
xcelium_cov_refine_files: []
// Build-specific coverage cfg files for Xcelium.
// default_xcelium_cov_cfg_file: "-covfile {dv_root}/tools/xcelium/cover.ccf"
// cover_reg_top_xcelium_cov_cfg_file: "-covfile {dv_root}/tools/xcelium/cover_reg_top.ccf"
default_xcelium_cov_cfg_file: "{dv_root}/tools/xcelium/cover.ccf"
cover_reg_top_xcelium_cov_cfg_file: "{dv_root}/tools/xcelium/cover_reg_top.ccf"
}

View file

@ -20,6 +20,9 @@
// List multiple tops for the simulation. Prepend each top level with `-top`.
"{eval_cmd} echo {sim_tops} | sed -E 's/(\\S+)/-top \\1/g'",
"+incdir+{build_dir}",
// TODO Remove buggy optimization when dsim fixes bug
// https://gitlab.metrics.ca/google/google/-/issues/242.
"-noopt-task-func",
// Suppress following DSim errors and warnings:
// EnumMustBePositive - UVM 1.2 violates this
"-suppress EnumMustBePositive"]

View file

@ -6,11 +6,12 @@
fusesoc_core_: "{eval_cmd} echo \"{fusesoc_core}\" | tr ':' '_'"
sv_flist_gen_opts: ["{fusesoc_cores_root_dirs}",
"run",
"--flag=fileset_{design_level}",
"{sv_flist_gen_flags}",
"--target=sim",
"--build-root={build_dir}",
"--setup {fusesoc_core}"]
fusesoc_cores_root_dirs: ["--cores-root {proj_root}"]
sv_flist_gen_dir: "{build_dir}/sim-vcs"
sv_flist: "{sv_flist_gen_dir}/{fusesoc_core_}.scr"
sv_flist_gen_flags: ["--flag=fileset_{design_level}"]
}

View file

@ -0,0 +1,52 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
{
// TODO, split this into several testplan for each CM
testpoints: [
{
name: one_hot_check
desc: ''' Verify design behavior is correct when one-hot coding is violated.
Stimulus:
- Backdoor force one-hot coding signals to not one-hot.
- Randomly flip the value back to ensure the error is latched and won't go away until
reset.
Checks:
- Check that fatal alert is triggered.
- Check that err_code/fault_status is updated correctly and preserved until reset.
- Check the following operation should be failed if applicable.'''
milestone: V2
tests: ["{name}_sec_cm"]
}
{
name: redundant_coding_fsm_check
desc: ''' Verify design behavior is correct when the redundant FSM enters an invalid state.
Stimulus:
- Backdoor force the FSM to any of the undefined values.
- Randomly flip the value back to a defined state to ensure the error is latched and
won't go away until reset.
Same checks as `one_hot_check`'''
milestone: V2
tests: ["{name}_sec_cm"]
}
{
name: hardened_counter_check
desc: ''' Verify design behavior is correct when the harden counter is changed to an
unexpected value.
Stimulus:
- At the falling edge (non-active edge), force the counter to a different value.
- Randomly flip the value back to any other value to ensure the error is latched and
won't go away until reset.
Same checks as `one_hot_check`'''
milestone: V2
tests: ["{name}_sec_cm"]
}
]
}

View file

@ -5,23 +5,47 @@
testpoints: [
{
// this testplan should be imported by all IPs containing shadowed CSRs
name: shadow_reg_errors
desc: '''
Verify shadow registers' update and storage errors.
- Issue reset at random to clear all the internal stored values and phases trackers
in shadow registers.
- Select all the shadow registers and a random amount of the rest of the non-excluded
registers. Shuffle and write random values to the selected registers.
For shadow registers, the second write is not enabled.
There is a 50% possibility that the shadow register's write value is identical to its
previous write value.
If shadow register's second write value does not match the first write value,
ensure that the update error alert is triggered.
- Randomly inject storage errors by modifying the shadow register's staged or committed
values via backdoor method. Ensure that the storage error alert is triggered.
- Randomly decide to read all the non-excluded registers or fields. Then check the read
values against predicted values.
A read on a shadow register will clear its phase tracker.
name: shadow_reg_update_error
desc: '''Verify shadowed registers' update error.
- Randomly pick a shadowed register in the DUT.
- Write it twice with different values.
- Verify that the update error alert is triggered and the register value remains
unchanged.
- Verify the update_error status register field is set to 1.
- Repeat the above steps a bunch of times.
'''
milestone: V1
tests: ["{name}_shadow_reg_errors"]
}
{
name: shadow_reg_read_clear_staged_value
desc: '''Verify reading a shadowed register will clear its staged value.
- Randomly pick a shadowed register in the DUT.
- Write it once and read it back to clear the staged value.
- Then write it twice with the same new value (but different from the previous step).
- Read it back to verify the new value and ensure that the update error alert did not
trigger.
- Verify the update_error status register field remains the same value.
- Repeat the above steps a bunch of times.
'''
milestone: V1
tests: ["{name}_shadow_reg_errors"]
}
{
name: shadow_reg_storage_error
desc: '''Verify shadowed registers' storage error.
- Randomly pick a shadowed register in the DUT.
- Backdoor write to shadowed or committed flops to create a storage fatal alert.
- Check if fatal alert continuously fires until reset.
- Verify that all other frontdoor write attempts are blocked during the storage error.
- Verify that storage_error status register field is set to 1.
- Reset the DUT.
- Read all CSRs to ensure the DUT is properly reset.
- Repeat the above steps a bunch of times.
'''
milestone: V1

View file

@ -8,7 +8,7 @@
desc: '''This test runs 3 parallel threads - stress_all, tl_errors and random reset.
After reset is asserted, the test will read and check all valid CSR registers.
'''
milestone: V2
milestone: V3
tests: ["{name}_stress_all_with_rand_reset"]
}
]

View file

@ -27,7 +27,8 @@
- write a CSR with unaligned address, e.g. `a_address[1:0] != 0`
- write a CSR less than its width, e.g. when CSR is 2 bytes wide, only write 1 byte
- write a memory with `a_mask != '1` when it doesn't support partial accesses
- read a WO (write-only) memory'''
- read a WO (write-only) memory
- write a RO (read-only) memory'''
milestone: V2
tests: ["{name}_tl_errors"]
}
@ -63,5 +64,30 @@
tests: ["{name}_tl_intg_err"]
}
]
covergroups: [
{
name: tl_errors_cg
desc: '''Cover the following error cases on TL-UL bus:
- TL-UL protocol error cases.
- OpenTitan defined error cases, refer to testpoint `tl_d_illegal_access`.
'''
}
{
name: tl_intg_err_cg
desc: '''Cover all kinds of integrity errors (command, data or both) and cover number of
error bits on each integrity check.
'''
}
{
name: tl_intg_err_mem_subword_cg
desc: '''Cover the kinds of integrity errors with byte enabled write on memory.
Some memories store the integrity values. When there is a subword write, design
re-calculate the integrity with full word data and update integrity in the memory.
This coverage ensures that memory byte write has been issued and the related design
logic has been verfied.
'''
}
]
}

View file

@ -22,6 +22,7 @@
build_mode: "cover_reg_top"
run_opts: ["+csr_hw_reset"]
en_run_modes: ["csr_tests_mode"]
reseed: 5
}
{
@ -29,6 +30,7 @@
build_mode: "cover_reg_top"
run_opts: ["+csr_rw"]
en_run_modes: ["csr_tests_mode"]
reseed: 20
}
{
@ -36,6 +38,7 @@
build_mode: "cover_reg_top"
run_opts: ["+csr_bit_bash"]
en_run_modes: ["csr_tests_mode"]
reseed: 5
}
{
@ -43,6 +46,7 @@
build_mode: "cover_reg_top"
run_opts: ["+csr_aliasing"]
en_run_modes: ["csr_tests_mode"]
reseed: 5
}
{
@ -50,6 +54,7 @@
build_mode: "cover_reg_top"
run_opts: ["+run_same_csr_outstanding"]
en_run_modes: ["csr_tests_mode"]
reseed: 20
}
{
@ -57,6 +62,7 @@
build_mode: "cover_reg_top"
run_opts: ["+run_csr_mem_rw_with_rand_reset", "+test_timeout_ns=10000000000"]
en_run_modes: ["csr_tests_mode"]
reseed: 20
}
]

View file

@ -13,6 +13,7 @@
name: mem_tests_mode
uvm_test_seq: "{name}_common_vseq"
run_opts: ["+en_scb=0"]
reseed: 5
}
]

View file

@ -21,9 +21,7 @@
build_mode: "cover_reg_top"
uvm_test_seq: "{name}_common_vseq"
run_opts: ["+run_tl_intg_err", "+en_scb=0"]
// TODO, lower the reseed to avoid having many failed tests in regression as not all the IPs
// have the integrity alert connected
reseed: 1
reseed: 20
}
]
}

View file

@ -6,7 +6,7 @@
build_ex: "{build_dir}/simv"
run_cmd: "{job_prefix} {build_ex}"
build_opts: ["-sverilog -full64 -licqueue -kdb -ntb_opts uvm-1.2",
build_opts: ["-sverilog -full64 -licqueue -ntb_opts uvm-1.2",
"-timescale=1ns/1ps",
"-Mdir={build_ex}.csrc",
"-o {build_ex}",
@ -155,8 +155,10 @@
"+urg+lic+wait",
// Lists all the tests that covered a given object.
"-show tests",
// Enable test grading.
"-grade index",
// Enable test grading using the "index" scheme, and the
// generation of the list of contributing tests with
// "testfile".
"-grade index testfile",
// Use simple ratio of total covered bins over total bins across cps & crs,
"-group ratio",
// Compute overall coverage for per-instance covergroups individually rather
@ -165,7 +167,8 @@
"-dir {cov_merge_db_dir}",
"-line nocasedef",
"-format both",
"-elfile {vcs_cov_excl_files}",
// Prepend each el file with `-elfile`.
"{eval_cmd} echo {vcs_cov_excl_files} | sed -E 's/(\\S+)/-elfile \\1/g'",
"-report {cov_report_dir}"]
cov_report_txt: "{cov_report_dir}/dashboard.txt"
cov_report_page: "dashboard.html"
@ -246,7 +249,9 @@
{
name: vcs_waves
is_sim_mode: 1
build_opts: ["-debug_access"]
build_opts: [// Enable generating Verdi Knowledge Database
"-kdb",
"-debug_access"]
}
{
name: vcs_cov

View file

@ -21,6 +21,9 @@
"-snapshot {tb}",
// for uvm_hdl_* used by csr backdoor
"-access +rw",
// This is to fix a timescale issue due to using `resetall to reset timescale and
// `-sv` compile option. #7178
"-enable_strict_timescale",
// Use this to conditionally compile for Xcelium (example: LRM interpretations differ
// across tools).
"+define+XCELIUM",
@ -76,8 +79,10 @@
// Note that this needs to be set as -covfile <file>.
xcelium_cov_cfg_file: ""
// Supply the cov refinement files.
// Note that this needs to be set as -load_refinement <file>.
// Supply the cov exclusion tcl script - passed on to IMC using the -init switch.
xcelium_cov_excl_script: ""
// Supply the cov refinement files - passed on to IMC using the -load_refinement switch.
xcelium_cov_refine_files: []
// Set the coverage directories.
@ -103,8 +108,10 @@
cov_report_cmd: "{job_prefix} imc"
cov_report_opts: ["-64bit",
"-licqueue",
"-exec {dv_root}/tools/xcelium/cov_report.tcl",
"{xcelium_cov_refine_files}"]
"-load {cov_merge_db_dir}",
" {eval_cmd} echo {xcelium_cov_excl_script} | sed -E 's/(\\S+)/-init \\1/g' ",
" {eval_cmd} echo {xcelium_cov_refine_files} | sed -E 's/(\\S+)/-load_refinement \\1/g' ",
"-exec {dv_root}/tools/xcelium/cov_report.tcl"]
cov_report_txt: "{cov_report_dir}/cov_report.txt"
cov_report_page: "index.html"
@ -112,11 +119,10 @@
// GUI for visual analysis.
cov_analyze_dir: "{scratch_path}/cov_analyze"
cov_analyze_cmd: "{job_prefix} imc"
cov_analyze_opts: ["-gui",
"-64bit",
cov_analyze_opts: ["-64bit",
"-licqueue",
"-load {cov_merge_db_dir}",
"-init {xcelium_common_excl_file}",
" {eval_cmd} echo {xcelium_cov_excl_script} | sed -E 's/(\\S+)/-init \\1/g' ",
" {eval_cmd} echo {xcelium_cov_refine_files} | sed -E 's/(\\S+)/-load_refinement \\1/g' "]
cov_unr_dir: "{scratch_path}/cov_unr"
@ -171,7 +177,10 @@
// Limit the scope of coverage collection to the DUT.
"-covdut {dut}",
// Set the coverage configuration file
"-covfile {xcelium_cov_cfg_file}"]
"-covfile {xcelium_cov_cfg_file}",
// Don't warn about the switches we set that will be default in future releases.
"-nowarn COVDEF",
]
run_opts: [// Put the coverage model (*.ucm) and the database (*.ucd) together.
"-covmodeldir {cov_db_test_dir}",
// Coverage database output location.

View file

@ -0,0 +1,16 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
// [UNSUPPORTED] Based on our Comportable IP spec, these TL pins are reserved / unused and hence,
// tied off.
-node tb.dut *tl_i.a_user.rsvd
-node tb.dut *tl_i.a_param
// [UNR] design ties these outputs to zeros.
-node tb.dut *tl_o.d_param
-node tb.dut *tl_o.d_opcode[1]
-node tb.dut *tl_o.d_opcode[2]
-node tb.dut *tl_o.d_sink
// [LOW_RISK] Verified in prim_alert_receiver TB."
-node tb.dut *alert_rx_*.ping_*

View file

@ -1,16 +0,0 @@
// Copyright lowRISC contributors.
// 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 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_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_i.a_param "logic tl_i.a_param[2:0]"

View file

@ -8,7 +8,11 @@
+tree tb.dut
-module pins_if // DV construct.
-module clk_rst_if // DV construct.
-moduletree prim_alert_sender // prim_alert_sender is verified in FPV.
// Prim_alert/esc pairs are verified in FPV and DV testbenches.
-moduletree prim_alert_sender
-moduletree prim_alert_receiver
-moduletree prim_esc_sender
-moduletree prim_esc_receiver
-moduletree prim_prince // prim_prince is verified in a separate DV environment.
-moduletree prim_lfsr // prim_lfsr is verified in FPV.
@ -16,6 +20,20 @@ begin tgl
-tree tb
+tree tb.dut 1
+module prim_alert_sender
+module prim_alert_receiver
+module prim_esc_sender
+module prim_esc_receiver
+module prim_prince
+module prim_lfsr
end
begin assert
// These three assertions in prim_lc_sync check when `lc_ctrl_pkg::lc_tx_e` input is neither `On`
// or `Off`, it is interrupted to the correct `On` or `Off` after one clock cycle. This behavior
// is implemented outside of IP level design thus these assertions are not covered in IP level
// testbenchs.
// TODO: check these assertions in top-level or FPV.
-assert PrimLcSyncCheckTransients_A
-assert PrimLcSyncCheckTransients0_A
-assert PrimLcSyncCheckTransients1_A
end

View file

@ -8,7 +8,10 @@
+moduletree *_reg_top
+node tb.dut tl_*
// Remove everything else from toggle coverage.
// Remove everything else from toggle coverage except:
// - `prim_alert_sender`: the `alert_test` task under `cip_base_vseq` drives `alert_test_i` and
// verifies `alert_rx/tx` handshake in each IP.
begin tgl
-tree tb
+module prim_alert_sender
end

View file

@ -13,9 +13,6 @@
# Black box some of the modules
# -blackBoxes -type design *
# Include common el file, so that it doesn't generate reviewed common exclusions
-covEL $dv_root/tools/vcs/common_cov_excl.el
# Name of the generated exclusion file
-save_exclusion $SCRATCH_PATH/cov_unr/unr_exclude.el

View file

@ -0,0 +1,57 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
// Common coverage commands that apply to all DUTs.
//
// This coverge config file is provided by Xcelium and is located at:
// ${XCELIUM_HOME}/tools/icc/include/all_coverage.ccf
// Xcelium recommends including it, since it bundles together the common set of commands that enable
// coverage collection on various design elements, that are otherwise turned off by default. We
// maintain it locally with minor amends.
// Enables expression coverage of various Verilog operators.
set_expr_coverable_operators -all -event_or
// Enables expression coverage of operators in various conditions and assignments.
set_expr_coverable_statements -all
// Enables scoring of Verilog modules compiled with -v/-y or -libcell option but continues to
// disable the scoring of Verilog modules defined with the 'celldefine compiler directive.
set_libcell_scoring
// Enables scoring of block and expression coverage for functions and tasks defined directly inside
// SystemVerilog packages.
set_subprogram_scoring -svpackage
// Enables scoring of SystemVerilog continuous assignments, which is by disabled by default.
set_assign_scoring
// Scores branches together with block coverage.
set_branch_scoring
// Scores statements within a block.
set_statement_scoring
// Enables expression coverage for expression containing structs (packed and unpacked).
set_expr_scoring -struct
// Enables Toggle scoring and reporting of SystemVerilog enumerations and multidimensional static
// arrays , vectors, packed union, modport and generate blocks.
set_toggle_scoring -sv_enum enable_mda -sv_struct_with_enum -sv_modport -sv_mda 16 -sv_mda_of_struct -sv_generate -sv_packed_union
// Enables scoring of reset states and transitions for identified FSMs.
set_fsm_reset_scoring
// Enables scoring of immediate assertions inside a class in a package and assertions inside AMS
// modules.
select_functional -ams_control -imm_asrt_class_package
// Improve the scoping and naming of covergroup instances.
set_covergroup -new_instance_reporting
// Enable toggle coverage only on ports.
set_toggle_portsonly
// Enable scoring of FSM arcs (state transitions).
set_fsm_arc_scoring

View file

@ -0,0 +1,9 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
exclude -inst $::env(DUT_TOP) -toggle '*tl_i.a_user.rsvd' -comment "\[UNSUPPORTED\] Based on our Comportability Spec. Exercising this will result in assertion errors thrown."
exclude -inst $::env(DUT_TOP) -toggle '*tl_i.a_param' -comment "\[UNSUPPORTED\] Based on our Comportability Spec. Exercising this will result in assertion errors thrown."
exclude -inst $::env(DUT_TOP) -toggle '*tl_o.d_param' -comment "\[UNR\] Follows tl_i.a_param which is unsupported."
exclude -inst $::env(DUT_TOP) -toggle '*tl_o.d_sink' -comment "\[UNR\] Based on our Comportability Spec."
exclude -inst $::env(DUT_TOP) -toggle '*alert_rx_*.ping_*' -comment "\[LOW_RISK\] Verified in prim_alert_receiver TB."

View file

@ -8,14 +8,14 @@
# using the env var 'cov_db_dirs' (which is a space separated list of directories).
# Append each of these directories with /* wildcard at the end to allow the tool to
# find all available test databases.
set cov_db_dirs_env [string trim $::env(cov_db_dirs) " \""]
set cov_db_dirs_env [string trim $::env(cov_db_dirs) " \"'"]
foreach i $cov_db_dirs_env { append cov_db_dirs "[string trim $i]/* "; }
puts "Input coverage directories:\n$cov_db_dirs"
# Set the output directory for the merged database using the env var 'cov_merge_db_dir'.
# The supplied env var may have quotes or spaces that needs to be trimmed.
puts "Output directory for merged coverage:"
set cov_merge_db_dir [string trim $::env(cov_merge_db_dir) " \""]
set cov_merge_db_dir [string trim $::env(cov_merge_db_dir) " \"'"]
# Run the merge command.
merge $cov_db_dirs -out $cov_merge_db_dir -overwrite

View file

@ -3,22 +3,18 @@
# SPDX-License-Identifier: Apache-2.0
# Generate reports for the merged coverage in HTML and text format.
# Set the input merged coverage database directory using the env var 'cov_merge_db_dir'.
# The supplied env var may have quotes or spaces that needs to be trimmed.
set cov_merge_db_dir [string trim $::env(cov_merge_db_dir) " \""]
#
# This file is passed to IMC using the -exec switch. Ensure that the merged coverage database, the
# exclusion script and the coverage refinement files are passed to the IMC invocation using the
# -load, -init and -load_refinement switches respectively (whichever ones are applicable).
# Set the output directory for the reports database using the env var 'cov_report_dir'.
# The supplied env var may have quotes or spaces that needs to be trimmed.
set cov_report_dir [string trim $::env(cov_report_dir) " \""]
set cov_report_dir [string trim $::env(cov_report_dir) " \"'"]
# Set the DUT name.
set dut [string trim $::env(DUT_TOP)]
set dut_uc [string toupper $dut]
set dut_instance [string trim $::env(dut_instance)]
# Load the merged coverage database.
load -run $cov_merge_db_dir
# Generate the text report (summary is sufficient).
report -summary \
@ -35,7 +31,6 @@ report -summary \
-type \
-all \
-metrics covergroup \
-kind abstract \
-source off \
-out $cov_report_dir/cov_report_cg.txt

View file

@ -0,0 +1,26 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
// Include our common coverage CCF.
include_ccf ${dv_root}/tools/xcelium/common.ccf
// Black-box pre-verified IPs from coverage collection.
deselect_coverage -betfs -module pins_if
deselect_coverage -betfs -module clk_rst_if
deselect_coverage -betfs -module prim_alert_sender...
deselect_coverage -betfs -module prim_alert_receiver...
deselect_coverage -betfs -module prim_esc_sender...
deselect_coverage -betfs -module prim_esc_receiver...
deselect_coverage -betfs -module prim_prince...
deselect_coverage -betfs -module prim_lfsr...
// Only collect toggle coverage on the DUT and the black-boxed IP (above) ports.
deselect_coverage -toggle -module ${DUT_TOP}...
select_coverage -toggle -module ${DUT_TOP}
select_coverage -toggle -module prim_alert_sender
select_coverage -toggle -module prim_alert_receiver
select_coverage -toggle -module prim_esc_sender
select_coverage -toggle -module prim_esc_receiver
select_coverage -toggle -module prim_prince
select_coverage -toggle -module prim_lfsr

View file

@ -0,0 +1,21 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
// Include our common coverage CCF.
include_ccf ${dv_root}/tools/xcelium/common.ccf
// Only collect code coverage on the *_reg_top instance.
deselect_coverage -betfs -module ${DUT_TOP}...
select_coverage -befs -module *_reg_top...
// Include toggle coverage on `prim_alert_sender` because the `alert_test` task under
// `cip_base_vseq` drives `alert_test_i` and verifies `alert_rx/tx` handshake in each IP.
select_coverage -toggle -module prim_alert_sender
// TODO: The intent below is to only enable coverage on the DUT's TL interfaces (tests using this
// ccf file are meant to fully exercise the TL interfaces, but they do not verify the rest of the
// functionality of the block). We enable coverage on all DUT ports but exclude ports that do not
// contain tl_i or tl_o in the port name using a separate excludefile that supports regexes.
select_coverage -toggle -module ${DUT_TOP}
set_toggle_excludefile ${dv_root}/tools/xcelium/cover_reg_top_toggle_excl

View file

@ -0,0 +1,7 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
// Exclude all but the TL ports of the DUT.
// TODO: This does not work.
-ere module ^((?!tl_i$|tl_o$).)*$

View file

@ -1,11 +0,0 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
exclude -inst $::env(DUT_TOP) -toggle 'tl_i.a_user.parity'
exclude -inst $::env(DUT_TOP) -toggle 'tl_i.a_user.parity_en'
exclude -inst $::env(DUT_TOP) -toggle 'tl_i.a_param'
exclude -inst $::env(DUT_TOP) -toggle 'tl_o.d_param'
exclude -inst $::env(DUT_TOP) -toggle 'tl_o.d_sink'
exclude -inst $::env(DUT_TOP) -toggle 'tl_o.d_user'
exclude -inst $::env(DUT_TOP) -toggle 'tl_i.a_user.rsvd1'

View file

@ -1,18 +0,0 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
// only collect toggle coverage on dut
deselect_coverage -toggle -instance tb.dut.*...
// only collect toggle coverage on ports
set_toggle_portsonly
// enable toggle scoring of structs and multidim arrays + MDA structs
set_toggle_scoring -sv_mda -sv_mda_of_struct
// filter glitches
set_toggle_strobe 0ps
// Filter unreachable/statically constant blocks
set_com -log

View file

@ -146,7 +146,7 @@ static std::vector<uint8_t> FlattenElfFile(const std::string &filepath) {
continue;
}
if (phdr.p_memsz == 0) {
if (phdr.p_filesz == 0) {
continue;
}
@ -154,11 +154,11 @@ static std::vector<uint8_t> FlattenElfFile(const std::string &filepath) {
low = phdr.p_paddr;
}
Elf32_Addr seg_top = phdr.p_paddr + (phdr.p_memsz - 1);
Elf32_Addr seg_top = phdr.p_paddr + (phdr.p_filesz - 1);
if (seg_top < phdr.p_paddr) {
std::ostringstream oss;
oss << "phdr for segment " << i << " has start 0x" << std::hex
<< phdr.p_paddr << " and size 0x" << phdr.p_memsz
<< phdr.p_paddr << " and size 0x" << phdr.p_filesz
<< ", which overflows the address space.";
throw ElfError(filepath, oss.str());
}
@ -201,15 +201,12 @@ static std::vector<uint8_t> FlattenElfFile(const std::string &filepath) {
throw ElfError(filepath, oss.str());
}
uint32_t off = phdr.p_paddr - low;
uint32_t dst_len = phdr.p_memsz;
uint32_t src_len = std::min(phdr.p_filesz, dst_len);
if (!dst_len)
if (phdr.p_filesz == 0)
continue;
std::vector<uint8_t> seg(dst_len, 0);
memcpy(&seg[0], file_data + phdr.p_offset, src_len);
uint32_t off = phdr.p_paddr - low;
std::vector<uint8_t> seg(phdr.p_filesz, 0);
memcpy(&seg[0], file_data + phdr.p_offset, phdr.p_filesz);
ret.AddSegment(off, std::move(seg));
}
@ -473,11 +470,11 @@ void DpiMemUtil::StageElf(bool verbose, const std::string &path) {
if (phdr.p_type != PT_LOAD)
continue;
if (phdr.p_memsz == 0)
if (phdr.p_filesz == 0)
continue;
size_t mem_area_idx =
GetRegionForSegment(path, i, phdr.p_paddr, phdr.p_memsz);
GetRegionForSegment(path, i, phdr.p_paddr, phdr.p_filesz);
const MemArea &mem_area = *mem_areas_[mem_area_idx];
uint32_t mem_area_base = base_addrs_[mem_area_idx];
@ -518,8 +515,8 @@ void DpiMemUtil::StageElf(bool verbose, const std::string &path) {
StagedMem &staged_mem = staging_area_[name];
const char *seg_data = file_data + phdr.p_offset;
std::vector<uint8_t> vec(phdr.p_memsz, 0);
memcpy(&vec[0], seg_data, std::min(phdr.p_filesz, phdr.p_memsz));
std::vector<uint8_t> vec(phdr.p_filesz, 0);
memcpy(&vec[0], seg_data, phdr.p_filesz);
staged_mem.AddSegment(local_base, std::move(vec));
}

View file

@ -12,7 +12,11 @@
// This is the maximum width of a memory that's supported by the code in
// prim_util_memload.svh
#define SV_MEM_WIDTH_BITS 312
#define SV_MEM_WIDTH_BYTES ((SV_MEM_WIDTH_BITS + 7) / 8)
// This is the number of bytes to reserve for buffers used to pass data between
// C++ and SystemVerilog using prim_util_memload.svh. Since this goes over DPI
// using the svBitVecVal type, we have to round up to the next 32-bit word.
#define SV_MEM_WIDTH_BYTES (4 * ((SV_MEM_WIDTH_BITS + 31) / 32))
/**
* A "memory area", representing a memory in the simulated design.