diff --git a/hw/top_chip/dv/mocha_sim_cfgs.hjson b/hw/top_chip/dv/mocha_sim_cfgs.hjson index 13dd99898..1619e262f 100644 --- a/hw/top_chip/dv/mocha_sim_cfgs.hjson +++ b/hw/top_chip/dv/mocha_sim_cfgs.hjson @@ -31,6 +31,7 @@ "{proj_root}/hw/vendor/lowrisc_ip/ip/i2c/dv/i2c_sim_cfg.hjson", "{proj_root}/hw/vendor/lowrisc_ip/ip/kmac/dv/kmac_unmasked_sim_cfg.hjson", "{proj_root}/hw/top_chip/ip/xbar_peri/dv/autogen/xbar_peri_sim_cfg.hjson", + "{proj_root}/hw/top_chip/ip_autogen/clkmgr/dv/clkmgr_sim_cfg.hjson", "{proj_root}/hw/top_chip/ip_autogen/gpio/dv/gpio_sim_cfg.hjson", "{proj_root}/hw/top_chip/ip_autogen/pwrmgr/dv/pwrmgr_sim_cfg.hjson", "{proj_root}/hw/top_chip/ip_autogen/rstmgr/dv/rstmgr_sim_cfg.hjson", diff --git a/hw/top_chip/ip_autogen/clkmgr/data/clkmgr.hjson b/hw/top_chip/ip_autogen/clkmgr/data/clkmgr.hjson index d3a28c362..3c2fe2b11 100644 --- a/hw/top_chip/ip_autogen/clkmgr/data/clkmgr.hjson +++ b/hw/top_chip/ip_autogen/clkmgr/data/clkmgr.hjson @@ -319,6 +319,11 @@ ''' }, ] + // Clock measurement is intentionally disabled in this configuration: the source clocks are + // supplied from outside the top and are assumed already stable, so there is no calibration + // step. calib_rdy is therefore tied MuBi4False, and hardware holds this regwen at 1, making + // the rw0c behaviour unobservable and randomized CSR writes unpredictable. + tags: ["excl:CsrNonInitTests:CsrExclWrite"] }, { name: "IO_MEAS_CTRL_EN", desc: ''' diff --git a/hw/top_chip/ip_autogen/clkmgr/data/clkmgr_sec_cm_testplan.hjson b/hw/top_chip/ip_autogen/clkmgr/data/clkmgr_sec_cm_testplan.hjson index e286eb3dc..2091154b5 100644 --- a/hw/top_chip/ip_autogen/clkmgr/data/clkmgr_sec_cm_testplan.hjson +++ b/hw/top_chip/ip_autogen/clkmgr/data/clkmgr_sec_cm_testplan.hjson @@ -43,7 +43,9 @@ - Measurement error should trigger a recoverable alert ''' stage: V2S - tests: ["clkmgr_frequency"] + // Unverified: measurement is intentionally disabled in this configuration, so this + // countermeasure cannot be exercised. The clkmgr_meas_chk hardware is still instantiated. + tests: [] } { name: sec_cm_timeout_clk_bkgn_chk @@ -55,7 +57,9 @@ - Timeout should cause a recoverable alert ''' stage: V2S - tests: ["clkmgr_frequency_timeout"] + // Unverified: measurement is intentionally disabled in this configuration, so this + // countermeasure cannot be exercised. The clkmgr_meas_chk hardware is still instantiated. + tests: [] } { name: sec_cm_meas_config_shadow diff --git a/hw/top_chip/ip_autogen/clkmgr/data/clkmgr_testplan.hjson b/hw/top_chip/ip_autogen/clkmgr/data/clkmgr_testplan.hjson index 5debb3a72..8f1a262d8 100644 --- a/hw/top_chip/ip_autogen/clkmgr/data/clkmgr_testplan.hjson +++ b/hw/top_chip/ip_autogen/clkmgr/data/clkmgr_testplan.hjson @@ -3,14 +3,14 @@ // SPDX-License-Identifier: Apache-2.0 { name: "clkmgr" - import_testplans: ["hw/dv/tools/dvsim/testplans/csr_testplan.hjson", - "hw/dv/tools/dvsim/testplans/intr_test_testplan.hjson", - "hw/dv/tools/dvsim/testplans/alert_test_testplan.hjson", - "hw/dv/tools/dvsim/testplans/tl_device_access_types_testplan.hjson", - "hw/dv/tools/dvsim/testplans/stress_all_with_reset_testplan.hjson", - "hw/dv/tools/dvsim/testplans/shadow_reg_errors_testplan.hjson", + // clkmgr has no interrupts, so intr_test_testplan.hjson is deliberately not imported. + import_testplans: ["hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/csr_testplan.hjson", + "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/alert_test_testplan.hjson", + "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/tl_device_access_types_testplan.hjson", + "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/stress_all_with_reset_testplan.hjson", + "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/shadow_reg_errors_testplan.hjson", "clkmgr_sec_cm_testplan.hjson", - "hw/dv/tools/dvsim/testplans/sec_cm_count_testplan.hjson"] + "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/sec_cm_count_testplan.hjson"] testpoints: [ { name: smoke @@ -129,72 +129,6 @@ stage: V2 tests: ["clkmgr_smoke"] } - { - name: frequency - desc: '''This tests the frequency counters measured count functionality. - - These counters compute the number of cycles of each clock relative - to the aon timer, and compares it to the corresponding - thresholds written into the `*_meas_ctrl_shadowed` CSR. Measurements - beyond these thresholds trigger a recoverable alert and set a bit - in the `recov_err_code` CSR. Also, if the counters reach their - maximum value they don't wrap around. - - If clock calibration is lost, indicated by the `calib_rdy_i` input - being `prim_mubi_pkg::MuBi4False`, the measurements stop, no - error is triggered, and `measure_ctrl_regwen` is set to 1. - - **Stimulus**: - - Randomly set slow, correct, and fast interval for each counter - and test. - - Randomly set the `calib_rdy_i` input. - - Randomly trigger a clock saturation by forcing its cycle count - to be near its maximum value while counting. - - **Check**: - - Slow and fast intervals should cause a recoverable alert. - - Coverage collected per clock. - ''' - stage: V2 - tests: ["clkmgr_frequency"] - } - { - name: frequency_timeout - desc: '''This tests the frequency counters timeout functionality. - - These counters compute the number of cycles of some clock relative - to the aon timer. It should trigger a recoverable alert when there - is no valid measurement when enabled, leading to a timeout. This is - separate from the `frequently` testpoint to simplify the test checks. - - **Stimulus**: - - Randomly stop measured clocks to trigger a timeout. - - **Check**: - - Timeout should cause a recoverable alert. - - Coverage collected per clock. - ''' - stage: V2 - tests: ["clkmgr_frequency_timeout"] - } - { - name: frequency_overflow - desc: '''This tests the overflow feature in prim_clock_meas. - - This needs to modify the state of the counter to trigger the - feature. - - **Stimulus**: - - Program the counter. Whenever it hits the value of 1, set it to - the range - 2. - - **Check**: - - The internal cnt_ovfl flop is set. - - The fast_o output should be set. - ''' - stage: V2 - tests: ["clkmgr_frequency"] - } { name: regwen desc: '''This tests the behavior of the regwen CSRs. @@ -218,8 +152,6 @@ desc: '''This runs random sequences in succession. Randomly chooses from the following sequences: - - clkmgr_frequency_timeout_vseq, - - clkmgr_frequency_vseq, - clkmgr_peri_vseq, - clkmgr_smoke_vseq, - clkmgr_trans_vseq diff --git a/hw/top_chip/ip_autogen/clkmgr/dv/clkmgr_sim_cfg.hjson b/hw/top_chip/ip_autogen/clkmgr/dv/clkmgr_sim_cfg.hjson index 88395d721..ee53e854d 100644 --- a/hw/top_chip/ip_autogen/clkmgr/dv/clkmgr_sim_cfg.hjson +++ b/hw/top_chip/ip_autogen/clkmgr/dv/clkmgr_sim_cfg.hjson @@ -12,7 +12,7 @@ tb: tb // Simulator used to sign off this block - tool: vcs + tool: xcelium // Fusesoc core file used for building the file list. fusesoc_core: lowrisc:mocha_dv:clkmgr_sim:0.1 @@ -25,14 +25,14 @@ // Import additional common sim cfg files. import_cfgs: [// Project wide common sim cfg file - "{proj_root}/hw/dv/tools/dvsim/common_sim_cfg.hjson", + "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/common_sim_cfg.hjson", // Common CIP test lists - "{proj_root}/hw/dv/tools/dvsim/tests/csr_tests.hjson", - "{proj_root}/hw/dv/tools/dvsim/tests/alert_test.hjson", - "{proj_root}/hw/dv/tools/dvsim/tests/tl_access_tests.hjson", - "{proj_root}/hw/dv/tools/dvsim/tests/stress_tests.hjson", - "{proj_root}/hw/dv/tools/dvsim/tests/sec_cm_tests.hjson", - "{proj_root}/hw/dv/tools/dvsim/tests/shadow_reg_errors_tests.hjson" + "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/csr_tests.hjson", + "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/alert_test.hjson", + "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/tl_access_tests.hjson", + "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/stress_tests.hjson", + "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/sec_cm_tests.hjson", + "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/shadow_reg_errors_tests.hjson" ] // Add additional tops for simulation. @@ -70,14 +70,6 @@ name: clkmgr_smoke uvm_test_seq: clkmgr_smoke_vseq } - { - name: clkmgr_frequency - uvm_test_seq: clkmgr_frequency_vseq - } - { - name: clkmgr_frequency_timeout - uvm_test_seq: clkmgr_frequency_timeout_vseq - } { name: clkmgr_peri uvm_test_seq: clkmgr_peri_vseq diff --git a/hw/top_chip/ip_autogen/clkmgr/dv/env/clkmgr_if.sv b/hw/top_chip/ip_autogen/clkmgr/dv/env/clkmgr_if.sv index 2ad83c548..971ee3bd3 100644 --- a/hw/top_chip/ip_autogen/clkmgr/dv/env/clkmgr_if.sv +++ b/hw/top_chip/ip_autogen/clkmgr/dv/env/clkmgr_if.sv @@ -52,13 +52,13 @@ interface clkmgr_if ( clk_hints_t clk_hints_csr; always_comb clk_hints_csr = '{ - none: `CLKMGR_HIER.reg2hw.clk_hints.clk_main_none_hint.q + none: `CLKMGR_HIER.reg2hw.clk_hints.q }; clk_hints_t clk_hints_status_csr; always_comb clk_hints_status_csr = '{ - none: `CLKMGR_HIER.u_reg.clk_hints_status_clk_main_none_val_qs + none: `CLKMGR_HIER.u_reg.clk_hints_status_qs }; prim_mubi_pkg::mubi4_t jitter_enable_csr; always_comb begin diff --git a/hw/top_chip/ip_autogen/clkmgr/dv/env/seq_lib/clkmgr_regwen_vseq.sv b/hw/top_chip/ip_autogen/clkmgr/dv/env/seq_lib/clkmgr_regwen_vseq.sv index 45e54b2ae..16388d8e9 100644 --- a/hw/top_chip/ip_autogen/clkmgr/dv/env/seq_lib/clkmgr_regwen_vseq.sv +++ b/hw/top_chip/ip_autogen/clkmgr/dv/env/seq_lib/clkmgr_regwen_vseq.sv @@ -24,45 +24,6 @@ class clkmgr_regwen_vseq extends clkmgr_base_vseq; `uvm_info(`gfn, "Check jitter_regwen done", UVM_MEDIUM) endtask : check_jitter_regwen - // This must be careful to turn measurements off right after checking the updates - // to avoid measurement errors. We could set the thresholds correctly, but we - // might as well set them randomly for good measure. Carefully masks only the - // real bits for the comparison. - task check_meas_ctrl_regwen(); - bit regwen_enable; - `DV_CHECK_STD_RANDOMIZE_FATAL(regwen_enable) - csr_wr(.ptr(ral.measure_ctrl_regwen), .value(regwen_enable)); - foreach (ExpectedCounts[clk]) begin - clk_mesr_e clk_mesr = clk_mesr_e'(clk); - uvm_reg ctrl_shadowed = meas_ctrl_regs[clk_mesr].ctrl_lo.get_dv_base_reg_parent(); - uvm_reg_data_t prev_en; - mubi4_t new_en = get_rand_mubi4_val(1, 1, 2); - int prev_ctrl; - int max_threshold = ExpectedCounts[clk] + 2; - int min_threshold = ExpectedCounts[clk] - 2; - int new_ctrl = get_meas_ctrl_value(min_threshold, max_threshold, - meas_ctrl_regs[clk_mesr].ctrl_lo, meas_ctrl_regs[clk_mesr].ctrl_hi); - int actual_ctrl; - int lo_mask = ((1 << meas_ctrl_regs[clk_mesr].ctrl_lo.get_n_bits()) - 1) << - meas_ctrl_regs[clk_mesr].ctrl_lo.get_lsb_pos(); - int hi_mask = ((1 << meas_ctrl_regs[clk_mesr].ctrl_hi.get_n_bits()) - 1) << - meas_ctrl_regs[clk_mesr].ctrl_hi.get_lsb_pos(); - `uvm_info(`gfn, $sformatf( - "Check %0s regwen = %b", meas_ctrl_regs[clk_mesr].name, regwen_enable), - UVM_MEDIUM) - csr_rd(.ptr(meas_ctrl_regs[clk_mesr].en), .value(prev_en)); - csr_rd(.ptr(ctrl_shadowed), .value(prev_ctrl)); - csr_wr(.ptr(ctrl_shadowed), .value(new_ctrl)); - csr_wr(.ptr(meas_ctrl_regs[clk_mesr].en), .value(new_en)); - csr_rd_check(.ptr(meas_ctrl_regs[clk_mesr].en), - .compare_value(mubi4_t'(regwen_enable ? new_en : prev_en))); - csr_wr(.ptr(meas_ctrl_regs[clk_mesr].en), .value(MuBi4False)); - csr_rd_check(.ptr(ctrl_shadowed), .compare_value(regwen_enable ? new_ctrl : prev_ctrl), - .compare_mask(lo_mask | hi_mask)); - `uvm_info(`gfn, $sformatf("Check %0s regwen done", meas_ctrl_regs[clk_mesr].name), - UVM_MEDIUM) - end - endtask : check_meas_ctrl_regwen task body(); // Make sure the aon clock is running as slow as it is meant to, otherwise the aon clock @@ -73,7 +34,6 @@ class clkmgr_regwen_vseq extends clkmgr_base_vseq; `uvm_info(`gfn, $sformatf("Will run %0d rounds", num_trans), UVM_MEDIUM) for (int i = 0; i < num_trans; ++i) begin check_jitter_regwen(); - check_meas_ctrl_regwen(); apply_reset("HARD"); // This is to make sure we don't start writes immediately after reset, // otherwise the tl_agent could mistakenly consider the following read diff --git a/hw/top_chip/ip_autogen/clkmgr/dv/env/seq_lib/clkmgr_smoke_vseq.sv b/hw/top_chip/ip_autogen/clkmgr/dv/env/seq_lib/clkmgr_smoke_vseq.sv index 32a3dc315..ac16c42f0 100644 --- a/hw/top_chip/ip_autogen/clkmgr/dv/env/seq_lib/clkmgr_smoke_vseq.sv +++ b/hw/top_chip/ip_autogen/clkmgr/dv/env/seq_lib/clkmgr_smoke_vseq.sv @@ -67,10 +67,7 @@ class clkmgr_smoke_vseq extends clkmgr_base_vseq; uvm_reg_field value_bit; } trans_descriptor_t; trans_descriptor_t trans_descriptors[NUM_TRANS] = '{ - '{TransAes, ral.clk_hints.clk_main_aes_hint, ral.clk_hints_status.clk_main_aes_val}, - '{TransHmac, ral.clk_hints.clk_main_hmac_hint, ral.clk_hints_status.clk_main_hmac_val}, - '{TransKmac, ral.clk_hints.clk_main_kmac_hint, ral.clk_hints_status.clk_main_kmac_val}, - '{TransOtbn, ral.clk_hints.clk_main_otbn_hint, ral.clk_hints_status.clk_main_otbn_val} + '{TransNone, ral.clk_hints.clk_main_hint_hint, ral.clk_hints_status.clk_main_hint_val} }; idle = 0; // Changes in idle take at least 10 cycles to stick. diff --git a/hw/top_chip/ip_autogen/clkmgr/dv/env/seq_lib/clkmgr_stress_all_vseq.sv b/hw/top_chip/ip_autogen/clkmgr/dv/env/seq_lib/clkmgr_stress_all_vseq.sv index 7f97b4257..b288f6eba 100644 --- a/hw/top_chip/ip_autogen/clkmgr/dv/env/seq_lib/clkmgr_stress_all_vseq.sv +++ b/hw/top_chip/ip_autogen/clkmgr/dv/env/seq_lib/clkmgr_stress_all_vseq.sv @@ -11,8 +11,6 @@ class clkmgr_stress_all_vseq extends clkmgr_base_vseq; task body(); string seq_names[] = { - "clkmgr_frequency_timeout_vseq", - "clkmgr_frequency_vseq", "clkmgr_peri_vseq", "clkmgr_smoke_vseq", "clkmgr_trans_vseq" diff --git a/hw/top_chip/ip_autogen/clkmgr/dv/sva/clkmgr_bind.sv b/hw/top_chip/ip_autogen/clkmgr/dv/sva/clkmgr_bind.sv index 5a098e45e..7c736abf8 100644 --- a/hw/top_chip/ip_autogen/clkmgr/dv/sva/clkmgr_bind.sv +++ b/hw/top_chip/ip_autogen/clkmgr/dv/sva/clkmgr_bind.sv @@ -40,10 +40,10 @@ module clkmgr_bind; bind clkmgr clkmgr_trans_sva_if clkmgr_none_trans_sva_if ( .clk(clk_main_i), .rst_n(rst_main_ni), - .hint(reg2hw.clk_hints.clk_main_hint_hint.q), + .hint(reg2hw.clk_hints.q), .idle(idle_i[HintMainHint] == prim_mubi_pkg::MuBi4True), .scanmode(scanmode_i == prim_mubi_pkg::MuBi4True), - .status(hw2reg.clk_hints_status.clk_main_hint_val.d), + .status(hw2reg.clk_hints_status.d), .trans_clk(clocks_o.clk_main_hint) ); diff --git a/hw/top_chip/ip_autogen/clkmgr/dv/tb.sv b/hw/top_chip/ip_autogen/clkmgr/dv/tb.sv index 60d58bc41..30d97bc45 100644 --- a/hw/top_chip/ip_autogen/clkmgr/dv/tb.sv +++ b/hw/top_chip/ip_autogen/clkmgr/dv/tb.sv @@ -77,10 +77,7 @@ module tb; .clk_enables({ reg2hw.clk_enables.q}), .clk_hints({ - reg2hw.clk_hints.clk_main_otbn_hint.q, - reg2hw.clk_hints.clk_main_kmac_hint.q, - reg2hw.clk_hints.clk_main_hmac_hint.q, - reg2hw.clk_hints.clk_main_aes_hint.q}) + reg2hw.clk_hints.q}) ); rst_shadowed_if rst_shadowed_if ( diff --git a/hw/vendor/lowrisc_ip.vendor.hjson b/hw/vendor/lowrisc_ip.vendor.hjson index 17483f5fc..e64bb6f99 100644 --- a/hw/vendor/lowrisc_ip.vendor.hjson +++ b/hw/vendor/lowrisc_ip.vendor.hjson @@ -42,7 +42,7 @@ // Hardware IP templates. {from: "hw/ip_templates/alert_handler", to: "ip_templates/alert_handler"}, // Dependency of reset manager. - {from: "hw/ip_templates/clkmgr", to: "ip_templates/clkmgr"}, + {from: "hw/ip_templates/clkmgr", to: "ip_templates/clkmgr", patch_dir: "clkmgr"}, {from: "hw/ip_templates/gpio", to: "ip_templates/gpio", patch_dir: "gpio"}, // General purpose I/O {from: "hw/ip_templates/pwrmgr", to: "ip_templates/pwrmgr", patch_dir: "pwrmgr"}, {from: "hw/ip_templates/rstmgr", to: "ip_templates/rstmgr", patch_dir: "rstmgr"}, diff --git a/hw/vendor/lowrisc_ip/dv/sv/alert_esc_agent/seq_lib/alert_receiver_alert_rsp_seq.sv b/hw/vendor/lowrisc_ip/dv/sv/alert_esc_agent/seq_lib/alert_receiver_alert_rsp_seq.sv index 433439e2d..db8d2baa4 100644 --- a/hw/vendor/lowrisc_ip/dv/sv/alert_esc_agent/seq_lib/alert_receiver_alert_rsp_seq.sv +++ b/hw/vendor/lowrisc_ip/dv/sv/alert_esc_agent/seq_lib/alert_receiver_alert_rsp_seq.sv @@ -54,7 +54,19 @@ task alert_receiver_alert_rsp_seq::default_rsp_thread(); int_err == 0; ) finish_item(rsp); - get_response(rsp); + // Stop waiting for the response on reset. The driver only reports done for items already + // queued in m_pending_alert_rsps, so an item accepted just as reset asserts never gets its + // response and get_response() would block forever, leaving this agent unable to ack any + // further alert for the rest of the simulation. Only the response wait is escaped here: + // killing start_item/finish_item instead would abort sequencer arbitration and trip + // SEQREQZMB. + fork begin : isolation_fork + fork + get_response(rsp); + wait (cfg.in_reset); + join_any + disable fork; + end join end : send_rsp join endtask : default_rsp_thread diff --git a/hw/vendor/lowrisc_ip/dv/sv/cip_lib/seq_lib/cip_base_vseq__shadow_reg_errors.svh b/hw/vendor/lowrisc_ip/dv/sv/cip_lib/seq_lib/cip_base_vseq__shadow_reg_errors.svh index ec13cf5ac..119ed918f 100644 --- a/hw/vendor/lowrisc_ip/dv/sv/cip_lib/seq_lib/cip_base_vseq__shadow_reg_errors.svh +++ b/hw/vendor/lowrisc_ip/dv/sv/cip_lib/seq_lib/cip_base_vseq__shadow_reg_errors.svh @@ -238,7 +238,10 @@ virtual task glitch_shadowed_reset(ref dv_base_reg shadowed_csr[$], // Randomly choose to glitch `rst_n` or `shadowed_rst_n` pin. if ($urandom_range(0, 1)) begin - ready_to_trigger_csr_rw = 1; + // Do not release the csr_rw sequence here. While rst_shadowed_n is held low a reg_top asserts + // shadow_busy, which drives tlul_adapter_reg's busy_i and holds a_ready low, so every CSR + // access blocks until the pin is reconnected at the end of this task. csr_rw is released + // there instead, matching the ordering the IP-reset branch below already uses. `uvm_info(`gfn, "toggle shadow reset pin", UVM_HIGH) cfg.rst_shadowed_vif.drive_shadow_rst_pin(0); end else begin @@ -274,6 +277,11 @@ virtual task glitch_shadowed_reset(ref dv_base_reg shadowed_csr[$], cfg.clk_rst_vif.wait_clks($urandom_range(50, 200)); cfg.rst_shadowed_vif.reconnect_shadowed_rst_n_to_rst_n(); + + // The CSR interface is reachable again now that the shadow reset is reconnected, so the csr_rw + // sequence can safely be released (a no-op if the IP-reset branch already did so). + ready_to_trigger_csr_rw = 1; + has_fatal_alert = alert_name != ""; endtask diff --git a/hw/vendor/lowrisc_ip/ip_templates/clkmgr/data/clkmgr.hjson.tpl b/hw/vendor/lowrisc_ip/ip_templates/clkmgr/data/clkmgr.hjson.tpl index f47d0210e..9d0670659 100644 --- a/hw/vendor/lowrisc_ip/ip_templates/clkmgr/data/clkmgr.hjson.tpl +++ b/hw/vendor/lowrisc_ip/ip_templates/clkmgr/data/clkmgr.hjson.tpl @@ -553,6 +553,13 @@ rg_srcs = get_rg_srcs(typed_clocks) ''' }, ] +% if not ext_clk_bypass: + // Clock measurement is intentionally disabled in this configuration: the source clocks are + // supplied from outside the top and are assumed already stable, so there is no calibration + // step. calib_rdy is therefore tied MuBi4False, and hardware holds this regwen at 1, making + // the rw0c behaviour unobservable and randomized CSR writes unpredictable. + tags: ["excl:CsrNonInitTests:CsrExclWrite"] +% endif }, % for src in rg_srcs: { name: "${src.upper()}_MEAS_CTRL_EN", diff --git a/hw/vendor/lowrisc_ip/ip_templates/clkmgr/data/clkmgr_sec_cm_testplan.hjson.tpl b/hw/vendor/lowrisc_ip/ip_templates/clkmgr/data/clkmgr_sec_cm_testplan.hjson.tpl index 05ec432a8..50acce77a 100644 --- a/hw/vendor/lowrisc_ip/ip_templates/clkmgr/data/clkmgr_sec_cm_testplan.hjson.tpl +++ b/hw/vendor/lowrisc_ip/ip_templates/clkmgr/data/clkmgr_sec_cm_testplan.hjson.tpl @@ -21,6 +21,7 @@ // // Please ensure that this testplan is imported in: // .../clkmgr/data/clkmgr_testplan.hjson +<% measurement_live = ext_clk_bypass %>\ { testpoints: [ { @@ -43,7 +44,13 @@ - Measurement error should trigger a recoverable alert ''' stage: V2S + % if measurement_live: tests: ["clkmgr_frequency"] + % else: + // Unverified: measurement is intentionally disabled in this configuration, so this + // countermeasure cannot be exercised. The clkmgr_meas_chk hardware is still instantiated. + tests: [] + % endif } { name: sec_cm_timeout_clk_bkgn_chk @@ -55,7 +62,13 @@ - Timeout should cause a recoverable alert ''' stage: V2S + % if measurement_live: tests: ["clkmgr_frequency_timeout"] + % else: + // Unverified: measurement is intentionally disabled in this configuration, so this + // countermeasure cannot be exercised. The clkmgr_meas_chk hardware is still instantiated. + tests: [] + % endif } { name: sec_cm_meas_config_shadow diff --git a/hw/vendor/lowrisc_ip/ip_templates/clkmgr/data/clkmgr_testplan.hjson.tpl b/hw/vendor/lowrisc_ip/ip_templates/clkmgr/data/clkmgr_testplan.hjson.tpl index 42a26b6ca..a86a5be48 100644 --- a/hw/vendor/lowrisc_ip/ip_templates/clkmgr/data/clkmgr_testplan.hjson.tpl +++ b/hw/vendor/lowrisc_ip/ip_templates/clkmgr/data/clkmgr_testplan.hjson.tpl @@ -1,16 +1,17 @@ // Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 +<% measurement_live = ext_clk_bypass %>\ { name: "clkmgr" - import_testplans: ["hw/dv/tools/dvsim/testplans/csr_testplan.hjson", - "hw/dv/tools/dvsim/testplans/intr_test_testplan.hjson", - "hw/dv/tools/dvsim/testplans/alert_test_testplan.hjson", - "hw/dv/tools/dvsim/testplans/tl_device_access_types_testplan.hjson", - "hw/dv/tools/dvsim/testplans/stress_all_with_reset_testplan.hjson", - "hw/dv/tools/dvsim/testplans/shadow_reg_errors_testplan.hjson", + // clkmgr has no interrupts, so intr_test_testplan.hjson is deliberately not imported. + import_testplans: ["hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/csr_testplan.hjson", + "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/alert_test_testplan.hjson", + "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/tl_device_access_types_testplan.hjson", + "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/stress_all_with_reset_testplan.hjson", + "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/shadow_reg_errors_testplan.hjson", "clkmgr_sec_cm_testplan.hjson", - "hw/dv/tools/dvsim/testplans/sec_cm_count_testplan.hjson"] + "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/sec_cm_count_testplan.hjson"] testpoints: [ { name: smoke @@ -183,6 +184,7 @@ stage: V2 tests: ["clkmgr_smoke"] } + % if measurement_live: { name: frequency desc: '''This tests the frequency counters measured count functionality. @@ -249,6 +251,7 @@ stage: V2 tests: ["clkmgr_frequency"] } + % endif { name: regwen desc: '''This tests the behavior of the regwen CSRs. @@ -275,8 +278,10 @@ % if ext_clk_bypass: - clkmgr_extclk_vseq, % endif + % if measurement_live: - clkmgr_frequency_timeout_vseq, - clkmgr_frequency_vseq, + % endif - clkmgr_peri_vseq, - clkmgr_smoke_vseq, - clkmgr_trans_vseq diff --git a/hw/vendor/lowrisc_ip/ip_templates/clkmgr/dv/clkmgr_sim_cfg.hjson.tpl b/hw/vendor/lowrisc_ip/ip_templates/clkmgr/dv/clkmgr_sim_cfg.hjson.tpl index 7a869dc33..996c23d7d 100644 --- a/hw/vendor/lowrisc_ip/ip_templates/clkmgr/dv/clkmgr_sim_cfg.hjson.tpl +++ b/hw/vendor/lowrisc_ip/ip_templates/clkmgr/dv/clkmgr_sim_cfg.hjson.tpl @@ -1,6 +1,14 @@ // Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 +<%doc> +Clock measurement is intentionally disabled in this configuration: the source clocks are supplied +from outside the top and are assumed already stable, so there is no calibration step and calib_rdy +is tied MuBi4False. clkmgr_meas_chk then clears the measurement enable and measure_ctrl_regwen is +held open, so any sequence exercising measurement cannot pass. These are gated on measurement_live +rather than deleted, so they return automatically if the configuration ever changes. +\ +<% measurement_live = ext_clk_bypass %>\ { // Name of the sim cfg - typically same as the name of the DUT. name: clkmgr @@ -12,7 +20,7 @@ tb: tb // Simulator used to sign off this block - tool: vcs + tool: xcelium // Fusesoc core file used for building the file list. fusesoc_core: ${instance_vlnv("lowrisc:dv:clkmgr_sim:0.1")} @@ -25,14 +33,14 @@ // Import additional common sim cfg files. import_cfgs: [// Project wide common sim cfg file - "{proj_root}/hw/dv/tools/dvsim/common_sim_cfg.hjson", + "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/common_sim_cfg.hjson", // Common CIP test lists - "{proj_root}/hw/dv/tools/dvsim/tests/csr_tests.hjson", - "{proj_root}/hw/dv/tools/dvsim/tests/alert_test.hjson", - "{proj_root}/hw/dv/tools/dvsim/tests/tl_access_tests.hjson", - "{proj_root}/hw/dv/tools/dvsim/tests/stress_tests.hjson", - "{proj_root}/hw/dv/tools/dvsim/tests/sec_cm_tests.hjson", - "{proj_root}/hw/dv/tools/dvsim/tests/shadow_reg_errors_tests.hjson" + "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/csr_tests.hjson", + "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/alert_test.hjson", + "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/tl_access_tests.hjson", + "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/stress_tests.hjson", + "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/sec_cm_tests.hjson", + "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/shadow_reg_errors_tests.hjson" ] // Add additional tops for simulation. @@ -76,6 +84,7 @@ uvm_test_seq: clkmgr_extclk_vseq } % endif + % if measurement_live: { name: clkmgr_frequency uvm_test_seq: clkmgr_frequency_vseq @@ -84,6 +93,7 @@ name: clkmgr_frequency_timeout uvm_test_seq: clkmgr_frequency_timeout_vseq } + % endif { name: clkmgr_peri uvm_test_seq: clkmgr_peri_vseq diff --git a/hw/vendor/lowrisc_ip/ip_templates/clkmgr/dv/env/clkmgr_if.sv.tpl b/hw/vendor/lowrisc_ip/ip_templates/clkmgr/dv/env/clkmgr_if.sv.tpl index e6c751f24..dbdc84061 100644 --- a/hw/vendor/lowrisc_ip/ip_templates/clkmgr/dv/env/clkmgr_if.sv.tpl +++ b/hw/vendor/lowrisc_ip/ip_templates/clkmgr/dv/env/clkmgr_if.sv.tpl @@ -85,18 +85,26 @@ interface clkmgr_if ( clk_hints_t clk_hints_csr; always_comb clk_hints_csr = '{ -% for target in list(reversed(hint_targets)): +% for clk, sig in list(reversed(list(typed_clocks['hint_clks'].items()))): <% sep = '' if loop.last else ',' %>\ - ${target}: `CLKMGR_HIER.reg2hw.clk_hints.clk_main_${target}_hint.q${sep} + % if len(typed_clocks['hint_clks']) == 1: + ${sig['endpoint_ip']}: `CLKMGR_HIER.reg2hw.clk_hints.q${sep} + % else: + ${sig['endpoint_ip']}: `CLKMGR_HIER.reg2hw.clk_hints.${clk}_hint.q${sep} + % endif % endfor }; clk_hints_t clk_hints_status_csr; always_comb clk_hints_status_csr = '{ -% for target in list(reversed(hint_targets)): +% for clk, sig in list(reversed(list(typed_clocks['hint_clks'].items()))): <% sep = '' if loop.last else ',' %>\ - ${target}: `CLKMGR_HIER.u_reg.clk_hints_status_clk_main_${target}_val_qs${sep} + % if len(typed_clocks['hint_clks']) == 1: + ${sig['endpoint_ip']}: `CLKMGR_HIER.u_reg.clk_hints_status_qs${sep} + % else: + ${sig['endpoint_ip']}: `CLKMGR_HIER.u_reg.clk_hints_status_${clk}_val_qs${sep} + % endif % endfor }; % if ext_clk_bypass: diff --git a/hw/vendor/lowrisc_ip/ip_templates/clkmgr/dv/env/seq_lib/clkmgr_regwen_vseq.sv.tpl b/hw/vendor/lowrisc_ip/ip_templates/clkmgr/dv/env/seq_lib/clkmgr_regwen_vseq.sv.tpl index 20ae44349..c790da7e1 100644 --- a/hw/vendor/lowrisc_ip/ip_templates/clkmgr/dv/env/seq_lib/clkmgr_regwen_vseq.sv.tpl +++ b/hw/vendor/lowrisc_ip/ip_templates/clkmgr/dv/env/seq_lib/clkmgr_regwen_vseq.sv.tpl @@ -1,6 +1,7 @@ // Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 +<% measurement_live = ext_clk_bypass %>\ // The regwen vseq attempts to write to registers whose regwen is randomly on or off to check // the register contents is not updated when off. More details in the clkmgr_testplan.hjson file. @@ -39,6 +40,7 @@ class clkmgr_regwen_vseq extends clkmgr_base_vseq; endtask : check_extclk_regwen % endif +% if measurement_live: // This must be careful to turn measurements off right after checking the updates // to avoid measurement errors. We could set the thresholds correctly, but we // might as well set them randomly for good measure. Carefully masks only the @@ -78,6 +80,7 @@ class clkmgr_regwen_vseq extends clkmgr_base_vseq; UVM_MEDIUM) end endtask : check_meas_ctrl_regwen +% endif task body(); // Make sure the aon clock is running as slow as it is meant to, otherwise the aon clock @@ -91,7 +94,9 @@ class clkmgr_regwen_vseq extends clkmgr_base_vseq; % if ext_clk_bypass: check_extclk_regwen(); % endif + % if measurement_live: check_meas_ctrl_regwen(); + % endif apply_reset("HARD"); // This is to make sure we don't start writes immediately after reset, // otherwise the tl_agent could mistakenly consider the following read diff --git a/hw/vendor/lowrisc_ip/ip_templates/clkmgr/dv/env/seq_lib/clkmgr_smoke_vseq.sv.tpl b/hw/vendor/lowrisc_ip/ip_templates/clkmgr/dv/env/seq_lib/clkmgr_smoke_vseq.sv.tpl index 567295e56..a851d99da 100644 --- a/hw/vendor/lowrisc_ip/ip_templates/clkmgr/dv/env/seq_lib/clkmgr_smoke_vseq.sv.tpl +++ b/hw/vendor/lowrisc_ip/ip_templates/clkmgr/dv/env/seq_lib/clkmgr_smoke_vseq.sv.tpl @@ -70,10 +70,10 @@ class clkmgr_smoke_vseq extends clkmgr_base_vseq; uvm_reg_field value_bit; } trans_descriptor_t; trans_descriptor_t trans_descriptors[NUM_TRANS] = '{ - '{TransAes, ral.clk_hints.clk_main_aes_hint, ral.clk_hints_status.clk_main_aes_val}, - '{TransHmac, ral.clk_hints.clk_main_hmac_hint, ral.clk_hints_status.clk_main_hmac_val}, - '{TransKmac, ral.clk_hints.clk_main_kmac_hint, ral.clk_hints_status.clk_main_kmac_val}, - '{TransOtbn, ral.clk_hints.clk_main_otbn_hint, ral.clk_hints_status.clk_main_otbn_val} +% for clk, sig in typed_clocks['hint_clks'].items(): +<% sep = '' if loop.last else ',' %>\ + '{Trans${sig['endpoint_ip'].capitalize()}, ral.clk_hints.${clk}_hint, ral.clk_hints_status.${clk}_val}${sep} +% endfor }; idle = 0; // Changes in idle take at least 10 cycles to stick. diff --git a/hw/vendor/lowrisc_ip/ip_templates/clkmgr/dv/env/seq_lib/clkmgr_stress_all_vseq.sv.tpl b/hw/vendor/lowrisc_ip/ip_templates/clkmgr/dv/env/seq_lib/clkmgr_stress_all_vseq.sv.tpl index 87ac1e2b0..3991f3346 100644 --- a/hw/vendor/lowrisc_ip/ip_templates/clkmgr/dv/env/seq_lib/clkmgr_stress_all_vseq.sv.tpl +++ b/hw/vendor/lowrisc_ip/ip_templates/clkmgr/dv/env/seq_lib/clkmgr_stress_all_vseq.sv.tpl @@ -1,6 +1,7 @@ // Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 +<% measurement_live = ext_clk_bypass %>\ // combine all clkmgr seqs (except below seqs) in one seq to run sequentially // 1. csr seq, which requires scb to be disabled @@ -14,8 +15,10 @@ class clkmgr_stress_all_vseq extends clkmgr_base_vseq; % if ext_clk_bypass: "clkmgr_extclk_vseq", % endif + % if measurement_live: "clkmgr_frequency_timeout_vseq", "clkmgr_frequency_vseq", + % endif "clkmgr_peri_vseq", "clkmgr_smoke_vseq", "clkmgr_trans_vseq" diff --git a/hw/vendor/lowrisc_ip/ip_templates/clkmgr/dv/sva/clkmgr_bind.sv.tpl b/hw/vendor/lowrisc_ip/ip_templates/clkmgr/dv/sva/clkmgr_bind.sv.tpl index 7eb396fd1..0ced01285 100644 --- a/hw/vendor/lowrisc_ip/ip_templates/clkmgr/dv/sva/clkmgr_bind.sv.tpl +++ b/hw/vendor/lowrisc_ip/ip_templates/clkmgr/dv/sva/clkmgr_bind.sv.tpl @@ -48,10 +48,18 @@ module clkmgr_bind; bind clkmgr clkmgr_trans_sva_if clkmgr_${sig['endpoint_ip']}_trans_sva_if ( .clk(clk_${sig['src_name']}_i), .rst_n(rst_${sig['src_name']}_ni), +% if len(typed_clocks['hint_clks']) == 1: + .hint(reg2hw.clk_hints.q), +% else: .hint(reg2hw.clk_hints.${clk}_hint.q), +% endif .idle(idle_i[${hint_names[clk]}] == prim_mubi_pkg::MuBi4True), .scanmode(scanmode_i == prim_mubi_pkg::MuBi4True), +% if len(typed_clocks['hint_clks']) == 1: + .status(hw2reg.clk_hints_status.d), +% else: .status(hw2reg.clk_hints_status.${clk}_val.d), +% endif .trans_clk(clocks_o.${clk}) ); diff --git a/hw/vendor/lowrisc_ip/ip_templates/clkmgr/dv/tb.sv.tpl b/hw/vendor/lowrisc_ip/ip_templates/clkmgr/dv/tb.sv.tpl index 5a2e8ef9a..8fb888352 100644 --- a/hw/vendor/lowrisc_ip/ip_templates/clkmgr/dv/tb.sv.tpl +++ b/hw/vendor/lowrisc_ip/ip_templates/clkmgr/dv/tb.sv.tpl @@ -90,10 +90,14 @@ module tb; % endif % endfor .clk_hints({ - reg2hw.clk_hints.clk_main_otbn_hint.q, - reg2hw.clk_hints.clk_main_kmac_hint.q, - reg2hw.clk_hints.clk_main_hmac_hint.q, - reg2hw.clk_hints.clk_main_aes_hint.q}) +% for clk in list(reversed(list(typed_clocks['hint_clks'].keys()))): +<% sep = "})" if loop.last else "," %>\ + % if len(typed_clocks['hint_clks']) == 1: + reg2hw.clk_hints.q${sep} + % else: + reg2hw.clk_hints.${clk}_hint.q${sep} + % endif +% endfor ); rst_shadowed_if rst_shadowed_if ( diff --git a/hw/vendor/patches/lowrisc_ip/clkmgr/0001_Fix_DV_Paths.patch b/hw/vendor/patches/lowrisc_ip/clkmgr/0001_Fix_DV_Paths.patch new file mode 100644 index 000000000..0d485213f --- /dev/null +++ b/hw/vendor/patches/lowrisc_ip/clkmgr/0001_Fix_DV_Paths.patch @@ -0,0 +1,61 @@ +diff --git a/data/clkmgr_testplan.hjson.tpl b/data/clkmgr_testplan.hjson.tpl +index 42a26b6c..61293f6b 100644 +--- a/data/clkmgr_testplan.hjson.tpl ++++ b/data/clkmgr_testplan.hjson.tpl +@@ -3,14 +3,14 @@ + // SPDX-License-Identifier: Apache-2.0 + { + name: "clkmgr" +- import_testplans: ["hw/dv/tools/dvsim/testplans/csr_testplan.hjson", +- "hw/dv/tools/dvsim/testplans/intr_test_testplan.hjson", +- "hw/dv/tools/dvsim/testplans/alert_test_testplan.hjson", +- "hw/dv/tools/dvsim/testplans/tl_device_access_types_testplan.hjson", +- "hw/dv/tools/dvsim/testplans/stress_all_with_reset_testplan.hjson", +- "hw/dv/tools/dvsim/testplans/shadow_reg_errors_testplan.hjson", ++ import_testplans: ["hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/csr_testplan.hjson", ++ "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/intr_test_testplan.hjson", ++ "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/alert_test_testplan.hjson", ++ "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/tl_device_access_types_testplan.hjson", ++ "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/stress_all_with_reset_testplan.hjson", ++ "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/shadow_reg_errors_testplan.hjson", + "clkmgr_sec_cm_testplan.hjson", +- "hw/dv/tools/dvsim/testplans/sec_cm_count_testplan.hjson"] ++ "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/sec_cm_count_testplan.hjson"] + testpoints: [ + { + name: smoke +diff --git a/dv/clkmgr_sim_cfg.hjson.tpl b/dv/clkmgr_sim_cfg.hjson.tpl +index 7a869dc3..746d9b7d 100644 +--- a/dv/clkmgr_sim_cfg.hjson.tpl ++++ b/dv/clkmgr_sim_cfg.hjson.tpl +@@ -12,7 +12,7 @@ + tb: tb + + // Simulator used to sign off this block +- tool: vcs ++ tool: xcelium + + // Fusesoc core file used for building the file list. + fusesoc_core: ${instance_vlnv("lowrisc:dv:clkmgr_sim:0.1")} +@@ -25,14 +25,14 @@ + + // Import additional common sim cfg files. + import_cfgs: [// Project wide common sim cfg file +- "{proj_root}/hw/dv/tools/dvsim/common_sim_cfg.hjson", ++ "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/common_sim_cfg.hjson", + // Common CIP test lists +- "{proj_root}/hw/dv/tools/dvsim/tests/csr_tests.hjson", +- "{proj_root}/hw/dv/tools/dvsim/tests/alert_test.hjson", +- "{proj_root}/hw/dv/tools/dvsim/tests/tl_access_tests.hjson", +- "{proj_root}/hw/dv/tools/dvsim/tests/stress_tests.hjson", +- "{proj_root}/hw/dv/tools/dvsim/tests/sec_cm_tests.hjson", +- "{proj_root}/hw/dv/tools/dvsim/tests/shadow_reg_errors_tests.hjson" ++ "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/csr_tests.hjson", ++ "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/alert_test.hjson", ++ "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/tl_access_tests.hjson", ++ "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/stress_tests.hjson", ++ "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/sec_cm_tests.hjson", ++ "{proj_root}/hw/vendor/lowrisc_ip/dv/tools/dvsim/tests/shadow_reg_errors_tests.hjson" + ] + + // Add additional tops for simulation. diff --git a/hw/vendor/patches/lowrisc_ip/clkmgr/0002_Generalize_Hint_Clocks.patch b/hw/vendor/patches/lowrisc_ip/clkmgr/0002_Generalize_Hint_Clocks.patch new file mode 100644 index 000000000..3a9c7e24f --- /dev/null +++ b/hw/vendor/patches/lowrisc_ip/clkmgr/0002_Generalize_Hint_Clocks.patch @@ -0,0 +1,100 @@ +diff --git a/dv/env/clkmgr_if.sv.tpl b/dv/env/clkmgr_if.sv.tpl +index e6c751f2..dbdc8406 100644 +--- a/dv/env/clkmgr_if.sv.tpl ++++ b/dv/env/clkmgr_if.sv.tpl +@@ -85,18 +85,26 @@ interface clkmgr_if ( + clk_hints_t clk_hints_csr; + always_comb + clk_hints_csr = '{ +-% for target in list(reversed(hint_targets)): ++% for clk, sig in list(reversed(list(typed_clocks['hint_clks'].items()))): + <% sep = '' if loop.last else ',' %>\ +- ${target}: `CLKMGR_HIER.reg2hw.clk_hints.clk_main_${target}_hint.q${sep} ++ % if len(typed_clocks['hint_clks']) == 1: ++ ${sig['endpoint_ip']}: `CLKMGR_HIER.reg2hw.clk_hints.q${sep} ++ % else: ++ ${sig['endpoint_ip']}: `CLKMGR_HIER.reg2hw.clk_hints.${clk}_hint.q${sep} ++ % endif + % endfor + }; + + clk_hints_t clk_hints_status_csr; + always_comb + clk_hints_status_csr = '{ +-% for target in list(reversed(hint_targets)): ++% for clk, sig in list(reversed(list(typed_clocks['hint_clks'].items()))): + <% sep = '' if loop.last else ',' %>\ +- ${target}: `CLKMGR_HIER.u_reg.clk_hints_status_clk_main_${target}_val_qs${sep} ++ % if len(typed_clocks['hint_clks']) == 1: ++ ${sig['endpoint_ip']}: `CLKMGR_HIER.u_reg.clk_hints_status_qs${sep} ++ % else: ++ ${sig['endpoint_ip']}: `CLKMGR_HIER.u_reg.clk_hints_status_${clk}_val_qs${sep} ++ % endif + % endfor + }; + % if ext_clk_bypass: +diff --git a/dv/env/seq_lib/clkmgr_smoke_vseq.sv.tpl b/dv/env/seq_lib/clkmgr_smoke_vseq.sv.tpl +index 567295e5..a851d99d 100644 +--- a/dv/env/seq_lib/clkmgr_smoke_vseq.sv.tpl ++++ b/dv/env/seq_lib/clkmgr_smoke_vseq.sv.tpl +@@ -70,10 +70,10 @@ class clkmgr_smoke_vseq extends clkmgr_base_vseq; + uvm_reg_field value_bit; + } trans_descriptor_t; + trans_descriptor_t trans_descriptors[NUM_TRANS] = '{ +- '{TransAes, ral.clk_hints.clk_main_aes_hint, ral.clk_hints_status.clk_main_aes_val}, +- '{TransHmac, ral.clk_hints.clk_main_hmac_hint, ral.clk_hints_status.clk_main_hmac_val}, +- '{TransKmac, ral.clk_hints.clk_main_kmac_hint, ral.clk_hints_status.clk_main_kmac_val}, +- '{TransOtbn, ral.clk_hints.clk_main_otbn_hint, ral.clk_hints_status.clk_main_otbn_val} ++% for clk, sig in typed_clocks['hint_clks'].items(): ++<% sep = '' if loop.last else ',' %>\ ++ '{Trans${sig['endpoint_ip'].capitalize()}, ral.clk_hints.${clk}_hint, ral.clk_hints_status.${clk}_val}${sep} ++% endfor + }; + idle = 0; + // Changes in idle take at least 10 cycles to stick. +diff --git a/dv/sva/clkmgr_bind.sv.tpl b/dv/sva/clkmgr_bind.sv.tpl +index 7eb396fd..0ced0128 100644 +--- a/dv/sva/clkmgr_bind.sv.tpl ++++ b/dv/sva/clkmgr_bind.sv.tpl +@@ -48,10 +48,18 @@ module clkmgr_bind; + bind clkmgr clkmgr_trans_sva_if clkmgr_${sig['endpoint_ip']}_trans_sva_if ( + .clk(clk_${sig['src_name']}_i), + .rst_n(rst_${sig['src_name']}_ni), ++% if len(typed_clocks['hint_clks']) == 1: ++ .hint(reg2hw.clk_hints.q), ++% else: + .hint(reg2hw.clk_hints.${clk}_hint.q), ++% endif + .idle(idle_i[${hint_names[clk]}] == prim_mubi_pkg::MuBi4True), + .scanmode(scanmode_i == prim_mubi_pkg::MuBi4True), ++% if len(typed_clocks['hint_clks']) == 1: ++ .status(hw2reg.clk_hints_status.d), ++% else: + .status(hw2reg.clk_hints_status.${clk}_val.d), ++% endif + .trans_clk(clocks_o.${clk}) + ); + +diff --git a/dv/tb.sv.tpl b/dv/tb.sv.tpl +index 5a2e8ef9..8fb88835 100644 +--- a/dv/tb.sv.tpl ++++ b/dv/tb.sv.tpl +@@ -90,10 +90,14 @@ module tb; + % endif + % endfor + .clk_hints({ +- reg2hw.clk_hints.clk_main_otbn_hint.q, +- reg2hw.clk_hints.clk_main_kmac_hint.q, +- reg2hw.clk_hints.clk_main_hmac_hint.q, +- reg2hw.clk_hints.clk_main_aes_hint.q}) ++% for clk in list(reversed(list(typed_clocks['hint_clks'].keys()))): ++<% sep = "})" if loop.last else "," %>\ ++ % if len(typed_clocks['hint_clks']) == 1: ++ reg2hw.clk_hints.q${sep} ++ % else: ++ reg2hw.clk_hints.${clk}_hint.q${sep} ++ % endif ++% endfor + ); + + rst_shadowed_if rst_shadowed_if ( diff --git a/hw/vendor/patches/lowrisc_ip/clkmgr/0003_Exclude_Measure_Ctrl_Regwen.patch b/hw/vendor/patches/lowrisc_ip/clkmgr/0003_Exclude_Measure_Ctrl_Regwen.patch new file mode 100644 index 000000000..d8fa4f11f --- /dev/null +++ b/hw/vendor/patches/lowrisc_ip/clkmgr/0003_Exclude_Measure_Ctrl_Regwen.patch @@ -0,0 +1,17 @@ +diff --git a/data/clkmgr.hjson.tpl b/data/clkmgr.hjson.tpl +--- a/data/clkmgr.hjson.tpl ++++ b/data/clkmgr.hjson.tpl +@@ -553,6 +553,13 @@ + ''' + }, + ] ++% if not ext_clk_bypass: ++ // Clock measurement is intentionally disabled in this configuration: the source clocks are ++ // supplied from outside the top and are assumed already stable, so there is no calibration ++ // step. calib_rdy is therefore tied MuBi4False, and hardware holds this regwen at 1, making ++ // the rw0c behaviour unobservable and randomized CSR writes unpredictable. ++ tags: ["excl:CsrNonInitTests:CsrExclWrite"] ++% endif + }, + % for src in rg_srcs: + { name: "${src.upper()}_MEAS_CTRL_EN", diff --git a/hw/vendor/patches/lowrisc_ip/clkmgr/0004_Drop_Intr_Test_Testplan.patch b/hw/vendor/patches/lowrisc_ip/clkmgr/0004_Drop_Intr_Test_Testplan.patch new file mode 100644 index 000000000..f49e0b7f3 --- /dev/null +++ b/hw/vendor/patches/lowrisc_ip/clkmgr/0004_Drop_Intr_Test_Testplan.patch @@ -0,0 +1,13 @@ +diff --git a/data/clkmgr_testplan.hjson.tpl b/data/clkmgr_testplan.hjson.tpl +--- a/data/clkmgr_testplan.hjson.tpl ++++ b/data/clkmgr_testplan.hjson.tpl +@@ -3,8 +3,8 @@ + // SPDX-License-Identifier: Apache-2.0 + { + name: "clkmgr" ++ // clkmgr has no interrupts, so intr_test_testplan.hjson is deliberately not imported. + import_testplans: ["hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/csr_testplan.hjson", +- "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/intr_test_testplan.hjson", + "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/alert_test_testplan.hjson", + "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/tl_device_access_types_testplan.hjson", + "hw/vendor/lowrisc_ip/dv/tools/dvsim/testplans/stress_all_with_reset_testplan.hjson", diff --git a/hw/vendor/patches/lowrisc_ip/clkmgr/0005_Gate_Measurement_On_Ext_Clk_Bypass.patch b/hw/vendor/patches/lowrisc_ip/clkmgr/0005_Gate_Measurement_On_Ext_Clk_Bypass.patch new file mode 100644 index 000000000..96bcc4a2c --- /dev/null +++ b/hw/vendor/patches/lowrisc_ip/clkmgr/0005_Gate_Measurement_On_Ext_Clk_Bypass.patch @@ -0,0 +1,170 @@ +diff --git a/data/clkmgr_testplan.hjson.tpl b/data/clkmgr_testplan.hjson.tpl +--- a/data/clkmgr_testplan.hjson.tpl ++++ b/data/clkmgr_testplan.hjson.tpl +@@ -1,6 +1,7 @@ + // Copyright lowRISC contributors (OpenTitan project). + // Licensed under the Apache License, Version 2.0, see LICENSE for details. + // SPDX-License-Identifier: Apache-2.0 ++<% measurement_live = ext_clk_bypass %>\ + { + name: "clkmgr" + // clkmgr has no interrupts, so intr_test_testplan.hjson is deliberately not imported. +@@ -183,6 +184,7 @@ + stage: V2 + tests: ["clkmgr_smoke"] + } ++ % if measurement_live: + { + name: frequency + desc: '''This tests the frequency counters measured count functionality. +@@ -249,6 +251,7 @@ + stage: V2 + tests: ["clkmgr_frequency"] + } ++ % endif + { + name: regwen + desc: '''This tests the behavior of the regwen CSRs. +@@ -275,8 +278,10 @@ + % if ext_clk_bypass: + - clkmgr_extclk_vseq, + % endif ++ % if measurement_live: + - clkmgr_frequency_timeout_vseq, + - clkmgr_frequency_vseq, ++ % endif + - clkmgr_peri_vseq, + - clkmgr_smoke_vseq, + - clkmgr_trans_vseq +diff --git a/data/clkmgr_sec_cm_testplan.hjson.tpl b/data/clkmgr_sec_cm_testplan.hjson.tpl +--- a/data/clkmgr_sec_cm_testplan.hjson.tpl ++++ b/data/clkmgr_sec_cm_testplan.hjson.tpl +@@ -21,6 +21,7 @@ + // + // Please ensure that this testplan is imported in: + // .../clkmgr/data/clkmgr_testplan.hjson ++<% measurement_live = ext_clk_bypass %>\ + { + testpoints: [ + { +@@ -43,7 +44,13 @@ + - Measurement error should trigger a recoverable alert + ''' + stage: V2S ++ % if measurement_live: + tests: ["clkmgr_frequency"] ++ % else: ++ // Unverified: measurement is intentionally disabled in this configuration, so this ++ // countermeasure cannot be exercised. The clkmgr_meas_chk hardware is still instantiated. ++ tests: [] ++ % endif + } + { + name: sec_cm_timeout_clk_bkgn_chk +@@ -55,7 +62,13 @@ + - Timeout should cause a recoverable alert + ''' + stage: V2S ++ % if measurement_live: + tests: ["clkmgr_frequency_timeout"] ++ % else: ++ // Unverified: measurement is intentionally disabled in this configuration, so this ++ // countermeasure cannot be exercised. The clkmgr_meas_chk hardware is still instantiated. ++ tests: [] ++ % endif + } + { + name: sec_cm_meas_config_shadow +diff --git a/dv/clkmgr_sim_cfg.hjson.tpl b/dv/clkmgr_sim_cfg.hjson.tpl +--- a/dv/clkmgr_sim_cfg.hjson.tpl ++++ b/dv/clkmgr_sim_cfg.hjson.tpl +@@ -1,6 +1,14 @@ + // Copyright lowRISC contributors (OpenTitan project). + // Licensed under the Apache License, Version 2.0, see LICENSE for details. + // SPDX-License-Identifier: Apache-2.0 ++<%doc> ++Clock measurement is intentionally disabled in this configuration: the source clocks are supplied ++from outside the top and are assumed already stable, so there is no calibration step and calib_rdy ++is tied MuBi4False. clkmgr_meas_chk then clears the measurement enable and measure_ctrl_regwen is ++held open, so any sequence exercising measurement cannot pass. These are gated on measurement_live ++rather than deleted, so they return automatically if the configuration ever changes. ++\ ++<% measurement_live = ext_clk_bypass %>\ + { + // Name of the sim cfg - typically same as the name of the DUT. + name: clkmgr +@@ -76,6 +84,7 @@ + uvm_test_seq: clkmgr_extclk_vseq + } + % endif ++ % if measurement_live: + { + name: clkmgr_frequency + uvm_test_seq: clkmgr_frequency_vseq +@@ -84,6 +93,7 @@ + name: clkmgr_frequency_timeout + uvm_test_seq: clkmgr_frequency_timeout_vseq + } ++ % endif + { + name: clkmgr_peri + uvm_test_seq: clkmgr_peri_vseq +diff --git a/dv/env/seq_lib/clkmgr_regwen_vseq.sv.tpl b/dv/env/seq_lib/clkmgr_regwen_vseq.sv.tpl +--- a/dv/env/seq_lib/clkmgr_regwen_vseq.sv.tpl ++++ b/dv/env/seq_lib/clkmgr_regwen_vseq.sv.tpl +@@ -1,6 +1,7 @@ + // Copyright lowRISC contributors (OpenTitan project). + // Licensed under the Apache License, Version 2.0, see LICENSE for details. + // SPDX-License-Identifier: Apache-2.0 ++<% measurement_live = ext_clk_bypass %>\ + + // The regwen vseq attempts to write to registers whose regwen is randomly on or off to check + // the register contents is not updated when off. More details in the clkmgr_testplan.hjson file. +@@ -39,6 +40,7 @@ + endtask : check_extclk_regwen + + % endif ++% if measurement_live: + // This must be careful to turn measurements off right after checking the updates + // to avoid measurement errors. We could set the thresholds correctly, but we + // might as well set them randomly for good measure. Carefully masks only the +@@ -78,6 +80,7 @@ + UVM_MEDIUM) + end + endtask : check_meas_ctrl_regwen ++% endif + + task body(); + // Make sure the aon clock is running as slow as it is meant to, otherwise the aon clock +@@ -91,7 +94,9 @@ + % if ext_clk_bypass: + check_extclk_regwen(); + % endif ++ % if measurement_live: + check_meas_ctrl_regwen(); ++ % endif + apply_reset("HARD"); + // This is to make sure we don't start writes immediately after reset, + // otherwise the tl_agent could mistakenly consider the following read +diff --git a/dv/env/seq_lib/clkmgr_stress_all_vseq.sv.tpl b/dv/env/seq_lib/clkmgr_stress_all_vseq.sv.tpl +--- a/dv/env/seq_lib/clkmgr_stress_all_vseq.sv.tpl ++++ b/dv/env/seq_lib/clkmgr_stress_all_vseq.sv.tpl +@@ -1,6 +1,7 @@ + // Copyright lowRISC contributors (OpenTitan project). + // Licensed under the Apache License, Version 2.0, see LICENSE for details. + // SPDX-License-Identifier: Apache-2.0 ++<% measurement_live = ext_clk_bypass %>\ + + // combine all clkmgr seqs (except below seqs) in one seq to run sequentially + // 1. csr seq, which requires scb to be disabled +@@ -14,8 +15,10 @@ + % if ext_clk_bypass: + "clkmgr_extclk_vseq", + % endif ++ % if measurement_live: + "clkmgr_frequency_timeout_vseq", + "clkmgr_frequency_vseq", ++ % endif + "clkmgr_peri_vseq", + "clkmgr_smoke_vseq", + "clkmgr_trans_vseq" diff --git a/hw/vendor/patches/lowrisc_ip/dv_sv/0003-alert_agent_rsp_seq_reset_race.patch b/hw/vendor/patches/lowrisc_ip/dv_sv/0003-alert_agent_rsp_seq_reset_race.patch new file mode 100644 index 000000000..84a824be1 --- /dev/null +++ b/hw/vendor/patches/lowrisc_ip/dv_sv/0003-alert_agent_rsp_seq_reset_race.patch @@ -0,0 +1,25 @@ +diff --git a/alert_esc_agent/seq_lib/alert_receiver_alert_rsp_seq.sv b/alert_esc_agent/seq_lib/alert_receiver_alert_rsp_seq.sv +index 433439e2..db8d2baa 100644 +--- a/alert_esc_agent/seq_lib/alert_receiver_alert_rsp_seq.sv ++++ b/alert_esc_agent/seq_lib/alert_receiver_alert_rsp_seq.sv +@@ -54,7 +54,19 @@ task alert_receiver_alert_rsp_seq::default_rsp_thread(); + int_err == 0; + ) + finish_item(rsp); +- get_response(rsp); ++ // Stop waiting for the response on reset. The driver only reports done for items already ++ // queued in m_pending_alert_rsps, so an item accepted just as reset asserts never gets its ++ // response and get_response() would block forever, leaving this agent unable to ack any ++ // further alert for the rest of the simulation. Only the response wait is escaped here: ++ // killing start_item/finish_item instead would abort sequencer arbitration and trip ++ // SEQREQZMB. ++ fork begin : isolation_fork ++ fork ++ get_response(rsp); ++ wait (cfg.in_reset); ++ join_any ++ disable fork; ++ end join + end : send_rsp + join + endtask : default_rsp_thread diff --git a/hw/vendor/patches/lowrisc_ip/dv_sv/0004-shadow_reg_csr_rw_ordering.patch b/hw/vendor/patches/lowrisc_ip/dv_sv/0004-shadow_reg_csr_rw_ordering.patch new file mode 100644 index 000000000..78a4ed911 --- /dev/null +++ b/hw/vendor/patches/lowrisc_ip/dv_sv/0004-shadow_reg_csr_rw_ordering.patch @@ -0,0 +1,27 @@ +diff --git a/cip_lib/seq_lib/cip_base_vseq__shadow_reg_errors.svh b/cip_lib/seq_lib/cip_base_vseq__shadow_reg_errors.svh +--- a/cip_lib/seq_lib/cip_base_vseq__shadow_reg_errors.svh ++++ b/cip_lib/seq_lib/cip_base_vseq__shadow_reg_errors.svh +@@ -238,7 +238,10 @@ + + // Randomly choose to glitch `rst_n` or `shadowed_rst_n` pin. + if ($urandom_range(0, 1)) begin +- ready_to_trigger_csr_rw = 1; ++ // Do not release the csr_rw sequence here. While rst_shadowed_n is held low a reg_top asserts ++ // shadow_busy, which drives tlul_adapter_reg's busy_i and holds a_ready low, so every CSR ++ // access blocks until the pin is reconnected at the end of this task. csr_rw is released ++ // there instead, matching the ordering the IP-reset branch below already uses. + `uvm_info(`gfn, "toggle shadow reset pin", UVM_HIGH) + cfg.rst_shadowed_vif.drive_shadow_rst_pin(0); + end else begin +@@ -274,6 +277,11 @@ + cfg.clk_rst_vif.wait_clks($urandom_range(50, 200)); + + cfg.rst_shadowed_vif.reconnect_shadowed_rst_n_to_rst_n(); ++ ++ // The CSR interface is reachable again now that the shadow reset is reconnected, so the csr_rw ++ // sequence can safely be released (a no-op if the IP-reset branch already did so). ++ ready_to_trigger_csr_rw = 1; ++ + has_fatal_alert = alert_name != ""; + endtask +