// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 { name: “rv_dm” // TODO: remove the common testplans if not applicable import_testplans: [“hw/dv/tools/dvsim/testplans/csr_testplan.hjson”, “hw/dv/tools/dvsim/testplans/mem_testplan.hjson”, “hw/dv/tools/dvsim/testplans/alert_test_testplan.hjson”, “hw/dv/tools/dvsim/testplans/stress_all_with_reset_testplan.hjson”, “hw/dv/tools/dvsim/testplans/tl_device_access_types_testplan.hjson”, “rv_dm_sec_cm_testplan.hjson”] testpoints: [ // Note that the CSR tests in the imported csr_testplan.hjson will cover CSRs attached to both, // the main RV_DM device interface as well as the debug ROM interface. { name: smoke desc: ‘’’ A basic smoke test.
. Read the DTM register `idcode` and verify that it reflects the correct value.
- Enable debug by setting lc_hw_debug_en to true.
- Write to the DMI register field dmcontrol[dmactive] via JTAG and verify that the
`dmactive` output pin reflects the same value.
- Write to the DMI register field dmcontrol[haltreq] via JTAG and verify that the
`debug_req` output pin reflects the same value.
- Write to the DMI register field dmcontrol[ndmreset] via JTAG and verify that the
`ndmreset` output pin reflects the same value.
- Wiggle the `unavailable` input and read the DTM register field dmstatus[allunavail]
to verify that it reflects the same value as the input signal.
'''
stage: V1
tests: ["rv_dm_smoke"]
}
{
name: jtag_dtm_csr_hw_reset
desc: '''
Verify the reset values of JTAG DTM CSRs as indicated in the RAL specification.
See hw/dv/tools/dvsim/testplans/csr_testplan.hjson for more description, This follows
the same approach, but applies to the JTAG DTM regisers.
In these set of tests, the lc_hw_debug_en is set to true, scanmode & scan_rst_n inputs
to false.
'''
stage: V1
tests: ["rv_dm_jtag_dtm_csr_hw_reset"]
}
{
name: jtag_dtm_csr_rw
desc: '''
Verify accessibility of JTAG DTM CSRs as indicated in the RAL specification.
See hw/dv/tools/dvsim/testplans/csr_testplan.hjson for more description, This follows
the same approach, but applies to the JTAG DTM regisers.
'''
stage: V1
tests: ["rv_dm_jtag_dtm_csr_rw"]
}
{
name: jtag_dtm_csr_bit_bash
desc: '''
Verify no aliasing within individual bits of JTAG DTM CSR.
See hw/dv/tools/dvsim/testplans/csr_testplan.hjson for more description, This follows
the same approach, but applies to the JTAG DTM regisers.
'''
stage: V1
tests: ["rv_dm_jtag_dtm_csr_bit_bash"]
}
{
name: jtag_dtm_csr_aliasing
desc: '''
Verify no aliasing within the JTAG DTM CSR address space.
See hw/dv/tools/dvsim/testplans/csr_testplan.hjson for more description, This follows
the same approach, but applies to the JTAG DTM regisers.
'''
stage: V1
tests: ["rv_dm_jtag_dtm_csr_aliasing"]
}
{
name: jtag_dmi_csr_hw_reset
desc: '''
Verify the reset values of JTAG DMI CSRs as indicated in the RAL specification.
See hw/dv/tools/dvsim/testplans/csr_testplan.hjson for more description, This follows
the same approach, but applies to the JTAG DMI regisers.
In these set of tests, the lc_hw_debug_en is set to true, scanmode & scan_rst_n inputs
to false.
Also, the dmcontrol[dmactive] field is set to 1 at the start, to ensure CSR accesses to
all other registers go through.
'''
stage: V1
tests: ["rv_dm_jtag_dmi_csr_hw_reset"]
}
{
name: jtag_dmi_csr_rw
desc: '''
Verify accessibility of JTAG DMI CSRs as indicated in the RAL specification.
See hw/dv/tools/dvsim/testplans/csr_testplan.hjson for more description, This follows
the same approach, but applies to the JTAG DMI regisers.
'''
stage: V1
tests: ["rv_dm_jtag_dmi_csr_rw"]
}
{
name: jtag_dmi_csr_bit_bash
desc: '''
Verify no aliasing within individual bits of JTAG DMI CSR.
See hw/dv/tools/dvsim/testplans/csr_testplan.hjson for more description, This follows
the same approach, but applies to the JTAG DMI regisers.
'''
stage: V1
tests: ["rv_dm_jtag_dmi_csr_bit_bash"]
}
{
name: jtag_dmi_csr_aliasing
desc: '''
Verify no aliasing within the JTAG DMI CSR address space.
See hw/dv/tools/dvsim/testplans/csr_testplan.hjson for more description, This follows
the same approach, but applies to the JTAG DMI regisers.
'''
stage: V1
tests: ["rv_dm_jtag_dmi_csr_aliasing"]
}
{
name: idcode
desc: '''
Verify that the JTAG IDCODE reads the correct value.
- Set a different JTAG ID code an rv_dm design parameter.
- Read the IDCODE register in JTAG DTM register space, via JTAG.
- Verify it reads back what was set.
'''
stage: V2
tests: ["rv_dm_smoke"]
}
{
name: jtag_dtm_hard_reset
desc: '''
Verify that the debugger can cancel an on-going DMI transaction with a hard reset.
- Perform DMI register read and check the data value.
- Write 1 to dtmcs[dmihardreset] bit.
- Perform DMI register read and check the data value to make sure the reset doesn't
create any harmful event.
'''
stage: V2
tests: ["rv_dm_jtag_dtm_hard_reset"]
}
{
name: jtag_dtm_idle_hint
desc: '''
Verify that the JTAG debugger does not need to stay any longer than the advertized idle
time indicated in dtmcs register.
- Read the dtmcs[idle] value and configure the JTAG DMI register adapter to insert that
many delay between transactions.
- Issue random legal DMI accesses back to back and ensure that all of them complete
successfully, without dmistat reflecting an error.
'''
stage: V2
tests: ["rv_dm_jtag_dtm_idle_hint"]
}
{
name: jtag_dmi_failed_op
desc: '''
Verify that a failed DMI op is reflected properly in dtmcs register.
- Issue a random legal DMI write to a chosen DMI register.
- Before that access completes, issue another random legal DMI access.
- Read the dtmcs[dmistat] register to verify busy error.
- Clear it by writing to dtmcs[dmireset] register.
- Poll the DMI access for completion and verify that the first write completed
successfully by doing a read-check.
'''
stage: V2
tests: ["rv_dm_dmi_failed_op"]
}
{
name: jtag_dmi_dm_inactive
desc: '''
Verify that DMI writes to data other than dmcontrol.dmactive are ignored when dmactive
is false. All of these registers should return their reset values on reads.
- Write 0 to DMCONTROL.DMACTIVE to put the debug module into its reset state.
- Perform random DMI writes, constrained only by requiring that they don't write 1 to
DMCONTROL.DMACTIVE.
- Write 1 to DMCONTROL.DMACTIVE to leave the reset state.
- Read DMI registers back and check they have their POR values.
'''
stage: V2
tests: ["rv_dm_jtag_dmi_dm_inactive"]
}
{
name: sba
desc: '''
Verify all types of accesses from JTAG to SBA.
- Enable debug by setting lc_hw_debug_en to true and activate the dm
- Write to SBA registers to inject randomized 8/16/32bit writes and reads.
- Randomize readonaddr and readondata settings and ensure those have the intended
effect.
- Generate sbbusy = 1 scenario by picking a very large response delay, since JTAG
accesses are much slower (SBA TL accesses tend to complete faster than JTAG can
read the SBCS register).
'''
stage: V2
tests: ["rv_dm_sba_tl_access", "rv_dm_delayed_resp_sba_tl_access"]
}
{
name: bad_sba
desc: '''
Verify attempts to make bad SBA accesses results in the error sticky bits getting set.
- Enable debug by setting lc_hw_debug_en to true and activate the dm.
- Build on the previous `sba` test and randomly inject errors in the following
ways:
- Inject a response error on the TL response channel (d_error = 1) and verify that
the sberror bit is set to 2.
- Inject a randomized SBA access that is not aligned to the size of the transfer and
verify that the sberror bit is set to 3.
- Inject a randomized SBA access that is greater that the supported transfer size and
verify that the sberror bit is set to 4.
- Inject an integrity error on the TL response channel and verify that the sberror
bit is set to 7. Verify that an alert is seen. Reset the DUT.
- Inject a new SBA traffic before the previous one completes - verify that the
sbbusyerror asserts. This is achieved by setting a large TL response delay (TODO).
- Have more than one of these types of errors trigger at the same time.
Note: The following error scenarios are not supported by the design:
- pulp-platform/riscv-dbg#128: response timeout (sberror = 1) is not implemented.
'''
stage: V2
tests: ["rv_dm_bad_sba_tl_access"]
}
{
name: sba_autoincrement
desc: '''
Verify the address autoincrement functionality of SBA.
- Enable debug by setting lc_hw_debug_en to true and activate the dm.
- Write to the SBCS register to inject randomized 8/16/32bit writes. Set the
autoincrement bit.
- Pick a random address and write to sbaddress0 register.
- Write a random value to sbdata0, repeating a randomized number of times.
- Each write should trigger a new SBA TL write access with the address incremented with
the transfer size. Verify that the SBA TL access shows up.
- Repeat the same procedure for reads. For reads, set the readondata register and read
the sbdata0 a randomized number of times - each read should trigger a new SBA TL read
access.
- Intermittently also generate busy and error conditions.
'''
stage: V2
tests: ["rv_dm_autoincr_sba_tl_access"]
}
{
name: jtag_dmi_debug_disabled
desc: '''
Verify that the JTAG DMI register space cannot be accessed if pinmux_hw_debug_en is a non
strict true value.
- Set pinmux_hw_debug_en to true and activate the dm.
- Write a known value to a randomly picked DMI CSR.
- Set pinmux_hw_debug_en to non-true value.
- Write a different value to the same DMI CSR.
- Attempt to read that DMI CSR - it should read all 0s.
- Note that the above steps are rendered moot because the JTAG DTM itself will not
receive any incoming JTAG transactions.
- Set pinmux_hw_debug_en to true and again read the DMI CSR - it should reflect the
originally written value.
'''
stage: V2
tests: ["rv_dm_jtag_dmi_debug_disabled"]
}
{
name: sba_debug_disabled
desc: '''
Verify that access to SBA interface is disabled if lc_hw_debug_en is set to a value
other than lc_ctrl_pkg::On.
- Set lc_hw_debug_en to non-true value and activate the dm.
- Attempt to send some legal randomized SBA accesses. Checks in the scoreboard will
assert that no SBA TL accesses appear on the TL interface.
'''
stage: V2
tests: ["rv_dm_sba_debug_disabled"]
}
{
name: ndmreset_req
desc: '''
Verify that the debugger can issue a non-debug reset to the rest of the system.
- Set lc_hw_debug_en / pinmux_hw_debug_en to true value and activate the dm.
- Pick a random set of write/readable CSRs in the debug RALs (JTAG DMI and debug
memory). Write known values to them.
- Write the dmcontrol register to assert ndmreset - verify that the ndmreset output
is asserted.
- Mimic the CPU going into reset by asserting the unavailable input.
- Set lc_hw_debug_en to something other than On (since it should no longer be needed).
At this point the ndmreset output signal will drop. Keep pinmux_hw_debug_en set to On
to keep the JTAG side open while the ndmreset is in progress.
- Read the dmstatus register to verify allunavail is asserted.
- De-assert the ndmreset by writing 0 to the dmcontrol register field, verify the
ndmreset output deasserted as well.
- Mimic the CPU going out of reset by de-asserting unavailable input
after some delay. Set lc_hw_debug_en to true again as well.
- Read the previously written registers back and verify that they reflect the previously
written value, proving that ndmreset assertion had no effect on them.
'''
stage: V2
tests: ["rv_dm_ndmreset_req"]
}
{
name: hart_unavail
desc: '''
Verify that the debugger can read the status of unavailable hart
- Set lc_hw_debug_en to true value and activate the dm.
- Randomly assert and de-assert the `unavailable` input (indicates the CPU is under
reset). This ideally happens when ndmreset is issued by the debugger.
- Periodically issue reads to dmstatus register to verify allunavail matches the
`unavailable` input value
'''
stage: V2
tests: ["rv_dm_hart_unavail"]
}
{
name: tap_ctrl_transitions
desc: '''
Verify all JTAG TAP controller FSM transitions
This test should verify that the standardized JTAG TAP FSM is working correctly.
'''
stage: V2
tests: ["rv_dm_tap_fsm", "rv_dm_tap_fsm_rand_reset"]
}
{
name: jtag_dmi_cmderr_busy
desc: '''
Generate the "busy" command error in abstractcs.
- Start an abstract command executing (but don't allow it to stop)
- Write to one of command, abstractcs, abstractauto or access (read or write) the data
or progbuf register.
- Read the abstractcs register and check that cmderr is now set to 1 (the encoding of
"busy")
'''
stage: V1
tests: ["rv_dm_cmderr_busy"]
}
{
name: jtag_dmi_cmderr_not_supported
desc: '''
Generate the "not supported" command error in abstractcs
This command error is generated when trying to run an abstract command that is not
supported.
- Write a command to the command register where cmdtype is definitely not supported.
- Check that the cmderr field of abstractcs register is set to 2.
'''
stage: V1
tests: ["rv_dm_cmderr_not_supported"]
}
{
name: cmderr_exception
desc: '''
Verify that if an exception occurs when executing a command then cmderr is set to 3.
- Start an abstract command.
- While it's running, write to the exception register over TL.
- Check that the cmderr field of abstractcs register is now 3.
'''
stage: V1
tests: ["rv_dm_cmderr_exception"]
}
{
name: mem_tl_access_resuming
desc: '''
Verify whether the selected hart has been resumed or not.
-Write into memory mapped register called RESUMING(0x110) through tl-device interface.
-Verify that the anyresumeack and allresumeack bits of the dmstatus register are set.
-After that, set the resumereq bit of dmcontrol register.
-Verify that the anyresumeack and allresumeack bits of the dmstatus register are cleared.
'''
stage: V1
tests: ["rv_dm_mem_tl_access_resuming"]
}
{
name: mem_tl_access_halted
desc: '''
Verify whether the selected hart has been halted or not.
- Set the haltreq bit of dmcontrol register.
- Write into memory mapped register called HALTED(0x100) through tl-device(mem_tl_if) interface.
- Verify that the anyhalted and allhalted bits of the dmstatus register are set.
'''
stage: V1
tests: ["rv_dm_mem_tl_access_halted"]
}
{
name: cmderr_halt_resume
desc: '''
Verify that attempt to generate command error result in cmderr field of abstractcs
register are set.
- Try to execute abstract command when hart is not in halt/resume state.
- Assert unavailable signal through core interface.
- The abstract command could not be execute.
- Verify that the cmderr field of abstractcs register is set to 4.
'''
stage: V1
tests: ["rv_dm_cmderr_halt_resume"]
}
{
name: dataaddr_rw_access
desc: '''
Verify the read write access of the data registers through the memory mapped DataAddr register.
- Write random data to the shadowed data registers via the corresponding DataAddr registers.
- Read back the written data and verify that it matches the expected values.
'''
stage: V1
tests: ["rv_dm_dataaddr_rw_access"]
}
{
name: halt_resume
desc: '''
Verify debug module halt/going/resume behavior.
- Request a halt over DMI, then send an abstract command.
- Check that the debug module reports itself to be busy.
- Check that the debug module's internal state machine is in the Go state.
- As the hart, respond to the message from the debug module to say that it has started handling it.
- Check the debug module still reports itself to be busy.
- Check that WHERETO points at the expected address (which contains the start of the abstract command)
- As the hart, tell the debug module that we have halted.
- Check the debug module no longer reports itself to be busy.
- Tell the debug module to resume again, by clearing the halt request and sending a resume request.
- Check the debug module now reports itself busy again (since it should be asking the hart to resume)
- Check flags to make sure the debug module is in the Resume state.
- As the hart, acknowledge the resume request.
- Check the debug module no longer reports itself to be busy.
'''
stage: V1
tests: ["rv_dm_halt_resume_whereto"]
}
{
name: progbuf_busy
desc: '''
Verify that writing on DM progbuf registers while abstract command is executing
causes jtag_dmi_ral.abstractcs.busy to be set to 1.
This is implemented by rv_dm_cmderr_busy, which chooses a random operation to generate
the busy command error. One possible operation is writing to progbuf[0].
'''
stage: V1
tests: ["rv_dm_cmderr_busy"]
}
{
name: abstractcmd_status
desc: '''
Verify the functionality of abstract command by reading tl_mem_ral.abstractcmd0-9
registers.
- Program jtag_dmi_ral.dmcontrol.haltreq to 1'b1.
- Verify that the 'debug_req_o' is set to 1.
- Acknowledge haltreq by setting tl_mem_ral.halted to 0.
- Send a valid abstract command (command type AccessRegister).
- Verify that the jtag_dmi_ral.abstractcs.busy is set to 1.
- Read tl_mem_ral.abstractcmd0-9 registers to verify that due to executing specific
abstract command we can read instructions stored in these registers.
'''
stage: V1
tests: ["rv_dm_abstractcmd_status"]
}
{
name: progbuf_read_write_execute
desc: '''
Verify the functionality of program buffer by writing random data on program buffer.
- Program jtag_dmi_ral.dmcontrol.haltreq to 1'b1.
- Verify that 'debug_req_o' is set to 1.
- Acknowledge haltreq by setting tl_mem_ral.halted to 0.
- Fill the program buffer by writing random data to jtag_dmi_ral.progbuf0-7
registers.
- Read tl_mem_ral.program_buffer0-7 registers to
verify that the data we wrote is what we read back.
'''
stage: V1
tests: ["rv_dm_progbuf_read_write_execute"]
}
{
name: progbuf_exception
desc: '''
Verify that writing on tl_mem_ral.exception register while an abstract command
is executing causes jtag_dmi_ral.abstractcs.cmderr to be set to 3.
- Program jtag_dmi_ral.dmcontrol.haltreq to 1'b1.
- Verify that 'debug_req_o' is set to 1.
- Acknowledge haltreq by setting tl_mem_ral.halted to 0.
- Send access register abstract command with postexec bit set.
- Write on tl_mem_ral.exception register.
- Verify that jtag_dmi_ral.abstractcs.cmderr is set to 3.
'''
stage: V1
tests: ["rv_dm_cmderr_exception"]
}
{
name: rom_read_access
desc: '''
Verify the read accessability of rom.
- Read from the addresses of rom and verify that it reads the expected data.
'''
stage: V1
tests: ["rv_dm_rom_read_access"]
}
{
name: hartsel_warl
desc: '''
Check the WARL behaviour of the hartsel field in dmcontrol
- Write '1 to hartsel and then read dmcontrol back again.
- Check resulting value of hartsel equals the maximum hart index.
'''
stage: V2
tests: ["rv_dm_hartsel_warl"]
}
{
name: stress_all
desc: '''
A 'bug hunt' test that stresses the DUT to its limits.
- Combine above sequences in one test and run as many of them as possible in parallel.
Run the rest sequentially.
- Randomly inject a full device reset intermittently.
'''
stage: V2
tests: ["rv_dm_stress_all"]
}
]
covergroups: [ { name: sba_access_cg desc: ‘’’Cover all possible types of accesses over SBA.
- cp: reads and write accesses
- cp: supported transfer sizes
- cp: auto-increment address with back-to-back acesses
- cp: for reads, cover readonaddr and readondata settings
- cp: sberror cases with unaligned address and unsupported size
- cp: sbbusyerror case - attempt new access before the previous one completed
- cr: cross all of the above
'''
}
] }