blob: f442a999faa3245d7d118462cc24ab542c9639cb [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
{
name: "otp_ctrl"
import_testplans: ["hw/dv/tools/dvsim/testplans/csr_testplan.hjson",
"hw/dv/tools/dvsim/testplans/mem_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/sec_cm_count_testplan.hjson",
"hw/dv/tools/dvsim/testplans/sec_cm_fsm_testplan.hjson",
"hw/dv/tools/dvsim/testplans/stress_all_with_reset_testplan.hjson",
"otp_ctrl_sec_cm_testplan.hjson"]
testpoints: [
{
name: wake_up
desc: '''
Wake_up test walks through otp_ctrl's power-on initialization, read, program, and
digest functionalities.
- drive pwrmgr's request pin to trigger OTP initialization after reset, check status
after OTP initialization
- write all-ones to a random address within OTP partition 0, wait until this operation
completes
- read out the random selected write address, check if the readout value is all-ones
- trigger a digest calculation for a Software partition, check if the OtpError
interrupt is set
- trigger a digest calculation for a non-software partition, expect operation completes
without the OtpError interrupt
- read out secrets through the hardware interfaces
'''
stage: V1
tests: ["otp_ctrl_wake_up"]
}
{
name: smoke
desc: '''
OTP_CTRL smoke test provisions and locks partitions.
- drive pwrmgr's request pin to trigger OTP initialization after reset, check status
after OTP initialization
- randomly read out keys pertaining to `key_manager`, `flash`, `sram`, `otbn`
- randomly issue LC program request
- write random values to random addresses within each OTP partition
- read out the random selected write addresses, check if the readout values are expected
- during read and write operations, check if direct_access_regwen is correctly set by HW
- perform a system-level reset and check corresponding CSRs are set correctly
- lock all partitions except life_cycle by triggering digest calculations
- read back and verify the digest
- perform a system-level reset to verify the corresponding CSRs exposing the digests
have been populated
**Checks**:
- Assertion checks to ensure vendor specific I/Os: `otp_vendor_test_status_o`,
`otp_vendor_test_ctrl_i`, `cio_test_o`, and `cio_test_en_o` are connected currently
with `lc_dft_en_i` On and Off.
'''
stage: V1
tests: ["otp_ctrl_smoke"]
}
{
name: dai_access_partition_walk
desc: '''
Similar to UVM's memory walk test, this test ensures every address in each partition
can be accessed successfully via DAI and TLUL interfacs according to its access policy.
'''
stage: V2
tests: ["otp_ctrl_partition_walk"]
}
{
name: init_fail
desc: '''
Based on OTP_CTRL smoke test, this test creates OTP_CTRL's initialization failure:
- write and read OTP memory via DAI interface
- randomly issue DAI digest command to lock HW partitions
- keep writing to OTP memory via DAI interface without asserting reset
- if digests are not locked, backdoor inject ECC correctable or uncorrectable errors
- issue reset and power initialization
- if the injected errors are all correctable errors, disable the `lc_bypass_chk_en`
after LC program request to create an LC partition check failure
If fatal error is triggered, this test will check:
- OTP initialization failure triggers fatal alert
- `status`, `intr_state`, `err_code` CSRs reflect correct fatal error
If OTP initialization finished without any fatal error, this test will check:
- OTP initialization finishes with power init output goes to 1
- `status`, `intr_state`, `err_code` CSRs reflect ECC correctable error
'''
stage: V2
tests: ["otp_ctrl_init_fail"]
}
{
name: partition_check
desc: '''
Randomly program the partition check related CSRs including:
- `check_timeout`
- `integrity_check_period`
- `consistency_check_period`
- `check_trigger`
Create a failure scenario by randomly picking one of these three methods:
- inject ECC errors into the OTP macro via backdoor
- set the `check_timeout` CSR with a very small value
- write to a random OTP partition after digest is issued but before reset is asserted
**Checks**:
- the corresponding alerts are triggered
- the error_code register is set correctly
Note that due to limited simulation time, for background checks, this test only write
random value that is less than 20 to the check period.
'''
stage: V2
tests: ["otp_ctrl_check_fail", "otp_ctrl_background_chks"]
}
{
name: regwen_during_otp_init
desc: '''
The `direct_access_regwen` is a RO register which controls the write-enable of other
reigsters. It is not verified by the common CSR tests. HW sets it to 0 when the DAI
interface is busy.
Stimulus and checks:
- randomly read `direct_access_regwen` and verify that it returns 0 during OTP
initialization
- verify that the writes to the registers controlled by it do not go through during OTP
initialization
'''
stage: V2
tests: ["otp_ctrl_regwen"]
}
{
name: partition_lock
desc: '''
This test will cover two methods of locking read and write: digest calculation and CSR
write. After locking the partitions, issue read or program sequences and check if the
operations are locked correctly, and check if the `AccessError` is set.
'''
stage: V2
tests: ["otp_ctrl_dai_lock"]
}
{
name: interface_key_check
desc: '''
OTP_CTRL will generate keys to `flash`, `sram`, and `otbn` upon their requests.
Based on the DAI access sequence, this test will run key requests sequence in
parallel, and check if correct keys are generated.
'''
stage: V2
tests: ["otp_ctrl_parallel_key_req"]
}
{
name: lc_interactions
desc: '''
Verify the procotols between OTP_CTRL and LC_CTRL. Based on the DAI access sequence,
run the following sequences in parallel:
- request a LC state transition via the programming interface
- enable the `lc_escalation_en` signal
**Checks**:
- if the LC program request has `AccessError`, check the LC program response sets
the `error` bit to 1
- if `lc_escalation_en` is enabled, verify that alert is triggered and OTP_CTRL entered
terminal state
'''
stage: V2
tests: ["otp_ctrl_parallel_lc_req", "otp_ctrl_parallel_lc_esc"]
}
{ name: otp_dai_errors
desc: '''
Based on the otp_dai_lock test, this test will randomly run the following OTP errors:
- DAI interface writes non-blank OTP address
- DAI interface accesses LC partition
- DAI interface writes HW digests
- DAI interface writes non-empty memory
**Checks**:
- `err_code` and `status` CSRs
- `otp_error` interrupt
'''
stage: V2
tests: ["otp_ctrl_dai_errs"]
}
{ name: otp_macro_errors
desc: '''
Randomly run the following OTP errors:
- MacroError
- MacroEccCorrError
- MacroEccUncorrError
**Checks**:
- `err_code` and `status` CSRs
- `otp_error` interrupt
- if the error is unrecoverable, verify that alert is triggered and OTP_CTRL entered
terminal state
'''
stage: V2
tests: ["otp_ctrl_macro_errs"]
}
{
name: test_access
desc: '''
This test checks if the test access to OTP macro is connected correctly.
**Stimulus and Checks**:
- Write and check read results from the prim_tl_i/o.
- Ensure no error or alert occurs from DUT.
'''
stage: V2
tests: ["otp_ctrl_test_access"]
}
{
name: stress_all
desc: '''
- combine above sequences in one test to run sequentially, except csr sequence
- randomly add reset between each sequence
'''
stage: V2
tests: ["{name}_stress_all"]
}
{
name: sec_cm_additional_check
desc: '''
Verify the outcome of injecting faults to security countermeasures.
Stimulus:
As mentioned in `prim_count_check`, `prim_fsm_check` and `prim_double_lfsr_check`.
Checks:
- Check the value of status register according to where the fault is injected.
- Check OTP_CTRL is locked after the fatal fault injection by trying to access OTP_CTRL
via dai, kdi, and lci interfaces.
'''
stage: V2S
tests: ["otp_ctrl_sec_cm"]
}
{
name: otp_ctrl_low_freq_read
desc: '''
This test checks if OTP's read operation can operate successfully in a low clock
frequency before the clock is calibrated.
**Stimulus and Checks**:
- Configure OTP_CTRL's clock to 6MHz low frequency.
- Backdoor write OTP memory.
- Use DAI access to read each memory address and compare if the value is correct.
- If DAI address is in a SW partition, read and check again via TLUL interface.
'''
stage: V3
tests: ["otp_ctrl_low_freq_read"]
}
]
covergroups: [
{
name: power_on_cg
desc: '''Covers the following conditions when OTP_CTRL finishes power-on initialization:
- whether `lc_escalation_en` is On
- whether any partition (except life cycle partition) is locked
'''
}
{
name: flash_req_cg
desc: '''Covers whether secret1 partition is locked during `flash` data or address
request.'''
}
{
name: sram_req_cg
desc: '''Covers whether secret1 partition is locked during all `srams` key request.'''
}
{
name: otbn_req_cg
desc: '''Covers whether secret1 partition is locked during `otbn` key request.'''
}
{
name: lc_prog_cg
desc: '''Covers whether the error bit is set during LC program request.'''
}
{
name: keymgr_o_cg
desc: '''Covers the following conditions when scoreboard checks `keymgr_o` value:
- whether secret2 partition is locked
- whether `lc_seed_hw_rd_en_i` is On
'''
}
{
name: req_dai_access_after_alert_cg
desc: '''Covers if sequence issued various DAI requests after any fatal alert is
triggered.'''
}
{
name: issue_checks_after_alert_cg
desc: '''Covers if sequence issued various OTP_CTRL's background checks after any fatal alert
is triggered.'''
}
{ // TODO: this is from a wrapper class, confirm if this is the correct format
name: csr_rd_after_alert_cg
desc: '''Covers if the following CSRs are being read and the value is checked in scoreboard
after any fatal alert is triggered:
- unbuffered partitions' digest CSRs
- HW partition's digest CSRs
- secrets partitions' digest CSRs
- direct_access read data CSRs
- status CSR
- error_code CSR
'''
}
{
name: dai_err_code_cg
desc: '''Covers all applicable error codes in DAI, and cross each error code with all
7 partitions.'''
}
{
name: lci_err_code_cg
desc: '''Covers all applicable error codes in LCI.'''
}
{ // TODO: this is an array of covergroups, confirm if this is the correct format
name: unbuf_err_code_cg
desc: '''This is an array of covergroups to cover all applicable error codes in three
unbuffered partitions.'''
}
{ // TODO: this is an array of covergroups, confirm if this is the correct format
name: buf_err_code_cg
desc: '''This is an array of covergroups to cover all applicable error codes in five
buffered partitions.'''
}
{ // TODO: this is an array of covergroups, confirm if this is the correct format
name: unbuf_access_lock_cg_wrap_cg
desc: '''This is an array of covergroups to cover lock conditions below in three
unbuffered partitions:
- the partition is write-locked
- the partition is read-locked
- the current operation type
Then cross the three coverpoints.'''
}
{
name: dai_access_secret2_cg
desc: '''Covers whether `lc_creator_seed_sw_rw_en` is On during any DAI accesses.'''
}
{ // TODO: this is an array of covergroups, confirm if this is the correct format
name: status_csr_cg
desc: '''Covers the value of every bit in `status` CSR.'''
}
// The following covergroups are implemented in `otp_ctrl_cov_if.sv`.
{
name: lc_esc_en_condition_cg
desc: '''Covers the following conditions when `lc_escalation_en` is On:
- whether any key requests is in progress
- whether LC program reqeust is in progress
- whether DAI interface is busy
'''
}
{
name: flash_data_req_condition_cg
desc: '''Covers the following conditions when `lc_escalation_en` is On:
- whether any key requests is in progress
- whether DAI interface is busy
- whether lc_esc_en is On
'''
}
{
name: flash_addr_req_condition_cg
desc: '''Covers the following conditions when `lc_escalation_en` is On:
- whether any key requests is in progress
- whether DAI interface is busy
- whether lc_esc_en is On
'''
}
{
name: sram_0_req_condition_cg
desc: '''Covers the following conditions when `lc_escalation_en` is On:
- whether any key requests is in progress
- whether DAI interface is busy
- whether lc_esc_en is On
'''
}
{
name: sram_1_req_condition_cg
desc: '''Covers the following conditions when `lc_escalation_en` is On:
- whether any key requests is in progress
- whether DAI interface is busy
- whether lc_esc_en is On
'''
}
{
name: otbn_req_condition_cg
desc: '''Covers the following conditions when `lc_escalation_en` is On:
- whether any key requests is in progress
- whether DAI interface is busy
- whether lc_esc_en is On
'''
}
{
name: lc_prog_req_condition_cg
desc: '''Covers the following conditions when `lc_escalation_en` is On:
- whether any key requests is in progress
- whether DAI interface is busy
- whether lc_esc_en is On
'''
}
]
}