mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-24 13:57:19 -04:00
Update lowrisc_ip to lowRISC/opentitan@ad629e3e6
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:
parent
e70add7228
commit
b66f199151
151 changed files with 5374 additions and 883 deletions
15
vendor/lowrisc_ip/dv/sv/csr_utils/csr_seq_lib.sv
vendored
15
vendor/lowrisc_ip/dv/sv/csr_utils/csr_seq_lib.sv
vendored
|
@ -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();
|
||||
|
|
160
vendor/lowrisc_ip/dv/sv/csr_utils/csr_utils_pkg.sv
vendored
160
vendor/lowrisc_ip/dv/sv/csr_utils/csr_utils_pkg.sv
vendored
|
@ -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;
|
||||
|
|
227
vendor/lowrisc_ip/dv/sv/dv_base_reg/dv_base_reg.sv
vendored
227
vendor/lowrisc_ip/dv/sv/dv_base_reg/dv_base_reg.sv
vendored
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
11
vendor/lowrisc_ip/dv/sv/dv_lib/dv_base_vseq.sv
vendored
11
vendor/lowrisc_ip/dv/sv/dv_lib/dv_base_vseq.sv
vendored
|
@ -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);
|
||||
|
|
33
vendor/lowrisc_ip/dv/sv/dv_utils/dv_macros.svh
vendored
33
vendor/lowrisc_ip/dv/sv/dv_utils/dv_macros.svh
vendored
|
@ -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
|
||||
|
|
17
vendor/lowrisc_ip/dv/sv/dv_utils/dv_utils_pkg.sv
vendored
17
vendor/lowrisc_ip/dv/sv/dv_utils/dv_utils_pkg.sv
vendored
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
3
vendor/lowrisc_ip/dv/tools/dvsim/dsim.hjson
vendored
3
vendor/lowrisc_ip/dv/tools/dvsim/dsim.hjson
vendored
|
@ -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"]
|
||||
|
|
|
@ -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}"]
|
||||
}
|
||||
|
|
52
vendor/lowrisc_ip/dv/tools/dvsim/testplans/sec_cm_testplan.hjson
vendored
Normal file
52
vendor/lowrisc_ip/dv/tools/dvsim/testplans/sec_cm_testplan.hjson
vendored
Normal 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"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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"]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -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.
|
||||
'''
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
]
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
name: mem_tests_mode
|
||||
uvm_test_seq: "{name}_common_vseq"
|
||||
run_opts: ["+en_scb=0"]
|
||||
reseed: 5
|
||||
}
|
||||
]
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
15
vendor/lowrisc_ip/dv/tools/dvsim/vcs.hjson
vendored
15
vendor/lowrisc_ip/dv/tools/dvsim/vcs.hjson
vendored
|
@ -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
|
||||
|
|
25
vendor/lowrisc_ip/dv/tools/dvsim/xcelium.hjson
vendored
25
vendor/lowrisc_ip/dv/tools/dvsim/xcelium.hjson
vendored
|
@ -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.
|
||||
|
|
16
vendor/lowrisc_ip/dv/tools/vcs/common_cov_excl.cfg
vendored
Normal file
16
vendor/lowrisc_ip/dv/tools/vcs/common_cov_excl.cfg
vendored
Normal 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_*
|
|
@ -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]"
|
20
vendor/lowrisc_ip/dv/tools/vcs/cover.cfg
vendored
20
vendor/lowrisc_ip/dv/tools/vcs/cover.cfg
vendored
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
3
vendor/lowrisc_ip/dv/tools/vcs/unr.cfg
vendored
3
vendor/lowrisc_ip/dv/tools/vcs/unr.cfg
vendored
|
@ -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
|
||||
|
||||
|
|
57
vendor/lowrisc_ip/dv/tools/xcelium/common.ccf
vendored
Normal file
57
vendor/lowrisc_ip/dv/tools/xcelium/common.ccf
vendored
Normal 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
|
9
vendor/lowrisc_ip/dv/tools/xcelium/common_cov_excl.tcl
vendored
Normal file
9
vendor/lowrisc_ip/dv/tools/xcelium/common_cov_excl.tcl
vendored
Normal 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."
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
26
vendor/lowrisc_ip/dv/tools/xcelium/cover.ccf
vendored
Normal file
26
vendor/lowrisc_ip/dv/tools/xcelium/cover.ccf
vendored
Normal 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
|
21
vendor/lowrisc_ip/dv/tools/xcelium/cover_reg_top.ccf
vendored
Normal file
21
vendor/lowrisc_ip/dv/tools/xcelium/cover_reg_top.ccf
vendored
Normal 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
|
7
vendor/lowrisc_ip/dv/tools/xcelium/cover_reg_top_toggle_excl
vendored
Normal file
7
vendor/lowrisc_ip/dv/tools/xcelium/cover_reg_top_toggle_excl
vendored
Normal 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$).)*$
|
11
vendor/lowrisc_ip/dv/tools/xcelium/exclude.tcl
vendored
11
vendor/lowrisc_ip/dv/tools/xcelium/exclude.tcl
vendored
|
@ -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'
|
18
vendor/lowrisc_ip/dv/tools/xcelium/xcelium.ccf
vendored
18
vendor/lowrisc_ip/dv/tools/xcelium/xcelium.ccf
vendored
|
@ -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
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue