We distinguish between architectural and micro-architectural functional coverage.
The idea is that the points that go into architectural coverage are those that a DV engineer could derive by reading the block specification.
The points that go into micro-architectural coverage are those that require knowledge of the block's micro-architecture.
Some of these will come from DV engineers; others from the block's designers.
These two views are complementary and will probably duplicate coverage points.
For example, an architectural coverage point might be "the processor executed ADDI
and the result overflowed".
This might overlap with something like "the overflow
signal in the ALU was true when adding".
The call stack is exposed as a special register behind x1
.
It has a bounded depth of 8 elements.
We expect to see the following events:
- Push to the call stack
- Pop from the call stack
- Push and pop from the call stack on a single instruction
- An instruction with multiple reads from
x1
All four of these events should be crossed with the three states of the call stack: empty, partially full, and full.
Coverage for these points is tracked in the
call_stack_cg
covergroup. We track all possible combinations of push/pop flags (8 possibilities) inflags_cp
. The 3 different fullness states are tracked asfullness_cp
. These are then crossed to giveflags_fullness_cross
.
The loop stack is accessed by executing LOOP
and LOOPI
instructions.
Events concerning the start of loops are tracked at those instructions, but we can't track things like loop completion there.
Coverage for these points is tracked with cover properties in the
otbn_loop_if
interface.
We expect to:
- Complete a loop.
Tracked as
LoopEnd_C
. - Complete the last loop on the stack (emptying it) after the stack has been full.
Tracked as
FullToEmpty_C
. - Complete a loop with one instruction and an iteration count of one.
Tracked as
ShortestLoop_C
. - Complete a loop with the maximal number of iterations.
Obviously, this isn't a reasonable thing to do for real in a test (there's a 32-bit iteration counter!).
The testbench will have to force a signal to skip past some iterations.
Tracked as
MaximalLoop_C
. - Run through a "badly nested" loop, where the body contains the final instruction from an outer loop (checking that we don't wrongly skip back).
Tracked as
BadNestingEnd_C
andBadNestingMiddle_C
. - Jump into a loop body from outside.
Tracked as
JumpIntoLoop_C
. - Jump/branch to the final instruction of a loop
Tracked as
JumpToLoopEnd_C
.
Accesses to CSRs and WSRs are tracked in the coverage for the instructions that access them. See CSRRS and CSRRW for CSRs; BN.WSRR and BN.WSRW for WSRs.
Random numbers are exposed to OTBN code through the RND
and URND
CSRs and WSRs.
A new random number can be prefetched for RND
with the RND_PREFETCH
CSR.
We track uses of each of these CSRs and WSRs in the instructions that access them.
See CSRRS and CSRRW for CSRs; BN.WSRR and BN.WSRW for WSRs.
However, we also want to see some interactions between RND
and RND_PREFETCH
.
These are all tracked with cover properties in otbn_rnd_if.sv
.
Specifically, we expect to see:
- An read of
RND
(either CSR or WSR) before any write toRND_PREFETCH
. This is tracked with theRndWithNoPrefetch_C
cover property. - Two consecutive writes to
RND_PREFETCH
without a random value arriving between. This is tracked with thePrefetchPrefetch_C
cover property. - Two consecutive writes to
RND_PREFETCH
, where a random value arrives between them. This is tracked with theFullPrefetch_C
cover property. - A write to
RND_PREFETCH
followed by a read fromRND
after the random value has arrived. This is tracked with theFullRead_C
cover property. - A write to
RND_PREFETCH
followed by a read fromRND
before the random value has arrived. This is tracked with thePrefetchingRead_C
cover property.
Each flag in each flag group should be set to one from zero by some instruction. Similarly, each flag in each flag group should be cleared to zero from one by some instruction.
These events are tracked in
flag_write_cg
. This is called fromon_insn()
once for each flag group that is being written. The covergroup contains eight coverpoints (for each flag set and cleared). These are then crossed with the flag group.
See the instruction counter saturate.
This is tracked in the
insn_cnt_if
interface with theInsnCntSaturated_C
cover property.
We expect to see reads from this interface (both when a key is present and when it is not). The coverage for these reads is tracked in the BN.WSRR instruction which does the reading.
The contents of IMEM and DMEM, the register file, and other pieces of internal state are protected by ECC integrity bits. We want to see errors/alerts caused by corrupting each of these pieces of state. Rather than tracking this with functional coverage, we rely on testplan entries.
See the mem_integrity
and internal_integrity
entries in the testplan for more details.
The lifecycle controller can send a "lifecycle escalation" signal to tell OTBN to clear its internal state and to raise its own fatal error.
We expect to see this happen.
However, we don't track coverage for this explicitly since it's handled at the testplan level (with the lc_escalation
testpoint).
If the CTRL.software_errs_fatal
field is set then a software error which would normally trigger a recoverable alert will trigger a fatal alert.
We expect to see each software error triggered and upgraded to a fatal alert.
This is tracked in the promoted_err_cg
covergroup.
Note that we already track seeing each software error triggered (but not upgraded) with the coverage for ERR_BITS
in the external
CSRs section below.
A portion of DMEM is inaccessible from the bus.
We want to see accesses (read and write) to both endpoints of the inaccessible portion of DMEM when OTBN is in an idle state (so would otherwise allow them).
These are tracked in the addr_cp
coverpoint in scratchpad_writes_cg
.
We also want to see a successful write to the top word of accessible DMEM.
We don't track that explicitly, since it is covered by the otbn_mem_walk
test.
The OTBN block exposes functionality to a bus host through bus-accessible CSRs. Behavior of some CSRs depends on OTBN's operational state.
For every CSR (no matter its access restrictions), we want to see an attempt to read it and an attempt to write it.
The CSRs are tracked in covergroups based on the CSR name, with the format: ext_csr_<name>_cg
.
Each has an access_type_cp
coverpoint which will track read and write attempts.
If writes to the CSR behave differently depending on the operational state, we cross attempts to write with the operational state.
For CSRs like CMD
, which have an immediate effect, this is easy to handle.
For CSRs that need a follow-up read to check their value, this is handled with the ext_csr_wr_operational_state_cg
covergroup.
We track the last write state for a CSR and then sample that covergroup when the value is read back.
Coverage is tracked in the ext_csr_cmd_cg
covergroup.
We want to see all valid commands (plus at least one invalid command) being written in each operational state. This ensures commands are ignored as expected when OTBN is busy or locked. It also ensures that bad commands are ignored as expected.
The cmd_cp
bin covers the different types of commands.
It is crossed with the operational state in cmd_state_cross
.
We check that we see a read (as well as a write) with the access_type_cp
coverpoint.
Coverage is tracked in the ext_csr_ctrl_cg
covergroup.
We expect to see this written with each of zero and one in the idle state (where it should take an effect).
This is tracked in value_cp
.
We check that we see a read (as well as a write) with the access_type_cp
coverpoint.
We expect to see this written in each operational state, tracked with the ext_csr_wr_operational_state_cg
covergroup.
We also want to see this be set back to zero after an operation has run with it set to one, then trigger a software error. This ensures that we can indeed disable the fatal error promotion mechanism.
TODO: This part is not currently tracked.
Coverage is tracked in the ext_csr_status_cg
covergroup.
We want to see a read of all valid status codes.
This is tracked in status_cp
.
We check that we see a write (as well as a read) with the access_type_cp
coverpoint.
Coverage is tracked in the ext_csr_err_bits_cg
covergroup.
We want to see that every valid bit is read at least once.
This is tracked in coverpoints with names of the form err_bits_<errcode>_cp
.
We also want to see a read in each operational state.
This is tracked in state_cp
.
We want to see a write to this register in each operational state when it was previously nonzero.
This checks that the clearing behaviour works properly.
We don't have to follow up with another read because we've got continuous checks that the RTL value of this register matches the ISS.
This is tracked in clear_state_cross
.
We want to see both reads and writes.
This is tracked in access_type_cp
.
Coverage is tracked in the ext_csr_fatal_alert_cause_cg
covergroup.
We want to see that every valid bit is read at least once.
This is tracked in coverpoints with names of the form fatal_alert_cause_<errcode>_cp
.
We also want to see a read in each operational state.
This is tracked in state_cp
.
We check that we see a write (as well as a read) with the access_type_cp
coverpoint.
Coverage is tracked in the ext_csr_insn_cnt_cg
covergroup.
We want to see a read returning a zero and a non-zero value.
This is tracked in insn_cnt_cp
.
We also want to see a read in every operational state.
This is tracked in state_cp
.
We want to see a write to this register in each operational state when it was previously nonzero.
This checks that the clearing behaviour works properly.
We don't have to follow up with another read because we've got continuous checks that the RTL value of this register matches the ISS.
This is tracked in clear_state_cross
.
We want to see a write to the register (that changes its value), followed by an update caused by writing to memory, finally followed by a read of the register value.
This is tracked in the ext_csr_load_checksum_wur_cg
covergroup.
We also want to see a write in every operational state, followed by a read before the next write.
This is tracked in the ext_csr_wr_operational_state_cg
covergroup.
As a processor, much of OTBN's coverage points are described in terms of instructions being executed. Because OTBN doesn't have a complicated multi-stage pipeline or any real exception handling, we don't track much temporal information (such as sequences of instructions).
As well as instruction-specific coverage points detailed below, we include a requirement that each instruction is executed at least once.
For any instruction with one or more immediate fields, we require "toggle coverage" for those fields.
That is, we expect to see execution with each bit of each immediate field being zero and one.
We also expect to see each field with values '0
and '1
(all zeros and all ones).
If the field is treated as a signed number, we also expect to see it with the extremal values for its range (just the MSB set, for the most negative value; all but the MSB set, for the most positive value).
The code to track this is split by encoding schema in
otbn_env_cov
. Each instruction listed below will specify its encoding schema. Each encoding schema then has its own covergroup. Rather than tracking toggle coverage as described above, we just track extremal values in a coverpoint. This also implies toggle coverage for both signed and unsigned fields. For unsigned fields of widthN
, the extremal values are0
and(1 << N) - 1
, represented by the bits'0
and'1
respectively. For signed fields of widthN+1
, the extremal values are-(1 << N)
and(1 << N) - 1
. These are represented by{1'b1, {N{1'b0}}}
and{1'b0, {N{1'b1}}}
: again, these toggle all the bits. For example,beq
uses theB
schema, which then maps to theenc_b_cg
covergroup. This encoding schema'sOFF
field is tracked with theoff_cp
coverpoint. Finally, the relevant cross is calledoff_cross
.
For any instruction that reads from or writes to a GPR, we expect to see that operand equal to x0
, x1
and an arbitrary register in the range x2 .. x31
.
We don't have any particular coverage requirements for WDRs (since all of them work essentially the same).
As for immediates, the code to track this is split by encoding schema in
otbn_env_cov
. Each register field gets a coverpoint with the same name, defined with theDEF_GPR_CP
helper macro. If the encoding schema has more than one instruction, the coverpoint is then crossed with the mnemonic, using theDEF_MNEM_CROSS
helper macro. For example,add
is in theenc_bnr_cg
covergroup. This encoding schema'sGRD
field is tracked with thegrd_cp
coverpoint. Finally, the relevant cross is calledgrd_cross
.
For any source GPR or WDR, we require "toggle coverage" for its value.
For example, ADD
reads from its grs1
operand.
We want to see each of the 32 bits of that operand set and unset (giving 64 coverage points).
Similarly, BN.ADD
reads from its wrs1
operand.
We want to see each of the 256 bits of that operand set and unset (giving 512 coverage points).
Again, the code to track this is split by encoding schema in
otbn_env_cov
. The trace interface takes a copy of GPR and WDR read data. The relevant register read data are then passed to the encoding schema's covergroup in theon_insn
method. To avoid extremely repetitive code, the actual coverpoints and crosses are defined with the help of macros. The coverpoints are named with the base-2 expansion of the bit in question. For example, the cross in theenc_bnr_cg
that tracks whether we've seen both values of bit 12 for thegrs1
operand is calledgrs1_01100_cross
(since 12 is5'b01100
).
If an instruction can generate flag changes, we expect to see each flag that the instruction can change being both set and cleared by the instruction.
This needn't be crossed with the two flag groups (that's tracked separately in the "Flags" block above).
For example, BN.ADD
can write to each of the flags C
, M
, L
and Z
.
This paragraph implies eight coverage points (four flags times two values) for that instruction.
Again, the code to track this is split by encoding schema in
otbn_env_cov
. The trace interface takes a copy of flag write data. It doesn't bother storing the flag write flags, since these are implied by the instruction anyway. There is a coverage coverpoint tracking both values for each of the flags that can be written. This is then crossed with the instruction mnemonic. For example, the coverpoint for the C flag (bit zero) in thebnaf
encoding used byBN.ADD
is calledflags_00_cp
. Some instructions only write theM
,L
andZ
flags. These are found in thebna
,bnan
,bnaqs
andbnaqw
encoding groups. For these instructions, we only track bits1
,2
and3
of the flags structure.
For any instruction that can cause multiple errors in a single cycle, we expect to see each possible combination of errors. This is described in more detail in the per-instruction text below. If an instruction below doesn't describe triggering multiple errors, that means we don't think it's possible.
This instruction uses the R
encoding schema, with covergroup enc_r_cg
.
The instruction-specific covergroup is insn_addsub_cg
(also used for SUB
).
- Cross the three possible signs (negative, zero, positive) for each input operand (giving 9 points).
Tracked as
sign_a_sign_b_cross
.
This instruction uses the I
encoding schema, with covergroup enc_i_cg
.
The instruction-specific covergroup is insn_addi_cg
.
- Cross the three possible signs (negative, zero, positive) for each input operand (giving 9 points).
Tracked as
sign_cross
.
This instruction uses the U
encoding schema, with covergroup enc_u_cg
.
There are no further coverage points.
This instruction uses the R
encoding schema, with covergroup enc_r_cg
.
The instruction-specific covergroup is insn_addsub_cg
.
- Cross the three possible signs (negative, zero, positive) for each input operand (giving 9 points).
Tracked as
sign_a_sign_b_cross
.
This instruction uses the R
encoding schema, with covergroup enc_r_cg
.
The instruction-specific covergroup is insn_sll_cg
.
- A shift of a nonzero value by zero.
Tracked as
nz_by_z_cp
. - A shift of a value by
0x1f
which leaves the top bit set. Tracked asshift15_cp
.
This instruction uses the Is
encoding schema, with covergroup enc_is_cg
.
The instruction-specific covergroup is insn_slli_cg
.
- A shift of a nonzero value by zero.
Tracked as
nz_by_z_cp
. - A shift of a value by
0x1f
which leaves the top bit set. Tracked asshift15_cp
.
This instruction uses the R
encoding schema, with covergroup enc_r_cg
.
The instruction-specific covergroup is insn_srl_cg
.
- A shift of a nonzero value by zero.
Tracked as
nz_by_z_cp
. - A shift of a value by
0x1f
which leaves the bottom bit set. Tracked asshift15_cp
. Note that this point also checks that we're performing a logical, rather than arithmetic, right shift.
This instruction uses the Is
encoding schema, with covergroup enc_is_cg
.
The instruction-specific covergroup is insn_srli_cg
.
- A shift of a nonzero value by zero.
Tracked as
nz_by_z_cp
. - A shift of a value by
0x1f
which leaves the bottom bit set. Tracked asshift15_cp
. Note that this point also checks that we're performing a logical, rather than arithmetic, right shift.
This instruction uses the R
encoding schema, with covergroup enc_r_cg
.
The instruction-specific covergroup is insn_sra_cg
.
- A shift of a nonzero value by zero.
Tracked as
nz_by_z_cp
. - A shift of a value by
0x1f
which leaves the bottom bit set. Tracked asshift15_cp
. Note that this point also checks that we're performing an arithmetic, rather than logical, right shift.
This instruction uses the Is
encoding schema, with covergroup enc_is_cg
.
The instruction-specific covergroup is insn_srai_cg
.
- A shift of a nonzero value by zero.
Tracked as
nz_by_z_cp
. - A shift of a value by
0x1f
which leaves the bottom bit set. Tracked asshift15_cp
. Note that this point also checks that we're performing an arithmetic, rather than logical, right shift.
This instruction uses the R
encoding schema, with covergroup enc_r_cg
.
The instruction-specific covergroup is insn_log_binop_cg
(shared with other logical binary operations).
- Toggle coverage of the output result, not to
x0
(to ensure we're not just AND'ing things with zero) Tracked aswrite_data_XXXXX_cross
, whereXXXXX
is the base-2 representation of the bit being checked.
This instruction uses the I
encoding schema, with covergroup enc_i_cg
.
The instruction-specific covergroup is insn_log_binop_cg
(shared with other logical binary operations).
- Toggle coverage of the output result, not to
x0
(to ensure we're not just AND'ing things with zero) Tracked aswrite_data_XXXXX_cross
, whereXXXXX
is the base-2 representation of the bit being checked.
This instruction uses the R
encoding schema, with covergroup enc_r_cg
.
The instruction-specific covergroup is insn_log_binop_cg
(shared with other logical binary operations).
- Toggle coverage of the output result, not to
x0
(to ensure we're not just OR'ing things with'1
) Tracked aswrite_data_XXXXX_cross
, whereXXXXX
is the base-2 representation of the bit being checked.
This instruction uses the I
encoding schema, with covergroup enc_i_cg
.
The instruction-specific covergroup is insn_log_binop_cg
(shared with other logical binary operations).
- Toggle coverage of the output result, not to
x0
(to ensure we're not just OR'ing things with'1
) Tracked aswrite_data_XXXXX_cross
, whereXXXXX
is the base-2 representation of the bit being checked.
This instruction uses the R
encoding schema, with covergroup enc_r_cg
.
The instruction-specific covergroup is insn_log_binop_cg
(shared with other logical binary operations).
- Toggle coverage of the output result, not to
x0
(to ensure we're not just XOR'ing things with zero) Tracked aswrite_data_XXXXX_cross
, whereXXXXX
is the base-2 representation of the bit being checked.
This instruction uses the I
encoding schema, with covergroup enc_i_cg
.
The instruction-specific covergroup is insn_log_binop_cg
(shared with other logical binary operations).
- Toggle coverage of the output result, not to
x0
(to ensure we're not just XOR'ing things with zero) Tracked aswrite_data_XXXXX_cross
, whereXXXXX
is the base-2 representation of the bit being checked.
This instruction uses the I
encoding schema, with covergroup enc_i_cg
.
The instruction-specific covergroup is insn_xw_cg
(shared with SW
).
- Load from a valid address, where
<grs1>
is above the top of memory and a negative<offset>
brings the load address in range. Tracked asoob_base_neg_off_cross
. - Load from a valid address, where
<grs1>
is negative and a positive<offset>
brings the load address in range. Tracked asneg_base_pos_off_cross
. - Load from address zero.
Tracked as
addr0_cross
. - Load from the top word of memory
Tracked as
top_addr_cross
. - Load from an invalid address (aligned but above the top of memory)
Tracked as
oob_addr_cross
. - Load from a calculated negative invalid address (aligned but unsigned address exceeds the top of memory)
Tracked as
oob_addr_neg_cross
. - Load from a "barely invalid" address (just above the top of memory)
Tracked as
barely_oob_addr_cross
. - Misaligned address tracking.
Track loads from addresses that are in range for the size of the memory.
Cross the different values modulo 4 for
grs1
andoffset
. Tracked asalign_cross
.
It is possible for LW to trigger multiple errors in a single cycle. The possible errors are: underflow call stack, invalid DMEM address, and overflow call stack. It's not possible to under- and overflow the call stack in a single cycle. Similarly, if we underflow the call stack, we won't have an address at all (valid or otherwise). This leaves a single combination to check:
- Overflow the call stack when loading from an invalid address.
Tracked as
overflow_cs_invalid_addr_cp
.
This instruction uses the I
encoding schema, with covergroup enc_s_cg
.
The instruction-specific covergroup is insn_xw_cg
(shared with LW
).
- Store to a valid address, where
<grs1>
is above the top of memory and a negative<offset>
brings the load address in range. Tracked asoob_base_neg_off_cross
. - Store to a valid address, where
<grs1>
is negative and a positive<offset>
brings the load address in range. Tracked asneg_base_pos_off_cross
. - Store to address zero
Tracked as
addr0_cross
. - Store to the top word of memory
Tracked as
top_addr_cross
. - Store to an invalid address (aligned but above the top of memory)
Tracked as
oob_addr_cross
. - Store to a calculated negative invalid address (aligned but unsigned address exceeds the top of memory)
Tracked as
oob_addr_neg_cross
. - Store to a "barely invalid" address (aligned but overlapping the top of memory)
Tracked as
barely_oob_addr_cross
. - Misaligned address tracking.
Track stores from addresses that are in range for the size of the memory.
Cross the different values modulo 4 for
grs1
andoffset
. Tracked asalign_cross
.
It is possible for SW to trigger multiple errors in a single cycle. The possible errors are: underflow call stack and invalid DMEM address. These can happen together, giving a single combination to check:
- Underflow the call stack when reading the value to be stored and try to write it to an invalid address.
Tracked as
underflow_cs_invalid_addr_cp
.
This instruction uses the B
encoding schema, with covergroup enc_b_cg
.
The instruction-specific covergroup is insn_bxx_cg
(shared with BNE
).
All points should be crossed with branch taken / branch not taken.
- See each branch direction (forwards, backwards, current address).
Tracked as
eq_dir_cross
. - Branch to a misaligned address (offset not a multiple of 4)
PC is always 4-bit aligned and offset is a multiple of 2 by definition.
Therefore the only misalignment would be by setting the second bit of the offset to 1.
Offset alignment is tracked in
eq_offset_align_cross
. - Branch forwards to an invalid address, above the top of memory
Tracked as
eq_oob_cross
. - Branch backwards to an invalid address (wrapping past zero)
Tracked as
eq_neg_cross
. - Branch instruction at end of a loop.
Tracked as
eq_at_loop_end_cross
(which also crosses with whether the branch was taken or not).
The "branch to current address" item is problematic if we want to take the branch. Probably we need some tests with short timeouts to handle this properly.
It is possible for BEQ to trigger multiple errors in a single cycle. The possible errors are: underflow call stack, bad target address, and branch at end of loop. Since the target address check only triggers if the branch is taken, which requires a value for comparison, it's not possible to underflow the call stack and see a bad target address at the same time. This leaves two possible combinations:
- Underflow the call stack in a branch at the end of a loop.
Tracked as
underflow_at_loop_end_cross
. - Take a branch to an invalid address where the branch instruction is at the end of a loop.
Tracked as
bad_addr_at_loop_end_cross
.
This instruction uses the B
encoding schema, with covergroup enc_b_cg
.
The instruction-specific covergroup is insn_bxx_cg
(shared with BEQ
).
All points should be crossed with branch taken / branch not taken.
- See each branch direction (forwards, backwards, current address).
Tracked as
eq_dir_cross
. - Branch to a misaligned address (offset not a multiple of 4)
PC is always 4-bit aligned and offset is a multiple of 2 by definition.
Therefore the only misalignment would be by setting the second bit of the offset to 1.
Offset alignment is tracked in
eq_offset_align_cross
. - Branch forwards to an invalid address, above the top of memory
Tracked as
eq_oob_cross
. - Branch backwards to an invalid address (wrapping past zero)
Tracked as
eq_neg_cross
. - Branch instruction at end of a loop.
Tracked as
eq_at_loop_end_cross
(which also crosses with whether the branch was taken or not).
The "branch to current address" item is problematic if we want to take the branch. Probably we need some tests with short timeouts to handle this properly.
It is possible for BNE to trigger multiple errors in a single cycle. The possible errors are: underflow call stack, bad target address, and branch at end of loop. Since the target address check only triggers if the branch is taken, which requires a value for comparison, it's not possible to underflow the call stack and see a bad target address at the same time. This leaves two possible combinations:
- Underflow the call stack in a branch at the end of a loop.
Tracked as
underflow_at_loop_end_cross
. - Take a branch to an invalid address where the branch instruction is at the end of a loop.
Tracked as
bad_addr_at_loop_end_cross
.
This instruction uses the J
encoding schema, with covergroup enc_j_cg
.
The instruction-specific covergroup is insn_jal_cg
.
- See each jump direction (forwards, backwards, current address).
Tracked as
dir_cp
. - Jump to a misaligned address (offset not a multiple of 4)
Offset alignments are tracked in
offset_align_cp
. - Jump forwards to an invalid address, above the top of memory
Tracked as
oob_cp
. - Jump backwards to an invalid address (wrapping past zero)
Tracked as
neg_cp
. - Jump when the current PC is the top word in IMEM.
Tracked as
from_top_cp
. - Jump instruction at end of a loop.
Tracked as
at_loop_end_cp
.
Note that the "jump to current address" item won't be a problem to test since it will quickly overflow the call stack.
It is possible for JAL to trigger multiple errors in a single cycle. The possible errors are: overflow call stack, bad target address, and jump at end of loop. All four combinations are possible:
- Overflow call stack when jumping to an invalid address.
Tracked as
overflow_and_invalid_addr_cp
. - Overflow call stack from a jump at the end of a loop.
Tracked as
overflow_at_loop_end_cp
. - Jump to an invalid address from the end of a loop.
Tracked as
invalid_addr_at_loop_end_cp
. - Overflow call stack when jumping to an invalid address from the end of a loop.
Tracked as
overflow_and_invalid_addr_at_loop_end_cp
.
This instruction uses the I
encoding schema, with covergroup enc_i_cg
.
The instruction-specific covergroup is insn_jalr_cg
.
- See each jump offset (forwards, backwards, zero).
Tracked as
off_dir_cp
. - Jump with a misaligned base address which
<offset>
aligns. Pairs of base address / offset alignments tracked inalign_cross
. - Jump with a large base address which wraps to a valid address by adding a positive
<offset>
. Tracked aspos_wrap_cp
. - Jump with a base address just above top of IMEM but with a negative
<offset>
to give a valid target. Tracked assub_cp
. - Jump with a negative offset, wrapping to give an invalid target.
Tracked as
neg_wrap_cp
. - Jump to an aligned address above top of IMEM.
Tracked as
oob_cp
. - Jump to current address.
Tracked as
self_cp
. - Jump when the current PC is the top word in IMEM.
Tracked as
from_top_cp
. - Jump instruction at end of a loop.
Tracked as
at_loop_end_cp
.
Note that the "jump to current address" item won't be a problem to test since it will quickly over- or underflow the call stack, provided <grd>
and <grs1>
aren't both x1
.
It is possible for JALR to trigger multiple errors in a single cycle. The possible errors are: underflow call stack, overflow call stack, bad target address, and jump at end of loop. If we underflow the call stack, we can't also overflow it, nor do we have a target address. This means the only error that can occur in combination with underflowing the call stack is a jump at the end of a loop. Otherwise, all other combinations are possible.
- Underflow call stack in a jump instruction at the end of a loop.
Tracked as
underflow_at_loop_end_cp
. - Overflow call stack when jumping to an invalid address.
Tracked as
overflow_and_bad_addr_cp
. - Overflow call stack from a jump at the end of a loop.
Tracked as
overflow_at_loop_end_cp
. - Jump to an invalid address from the end of a loop.
Tracked as
bad_addr_at_loop_end_cp
. - Overflow call stack when jumping to an invalid address from the end of a loop.
Tracked as
overflow_and_bad_addr_at_loop_end_cp
.
This instruction uses the I
encoding schema, with covergroup enc_i_cg
.
The instruction-specific covergroup is insn_csrrs_cg
.
- Write with a non-zero
bits_to_set
to each valid CSR. - Write to an invalid CSR.
These points are tracked with csr_cross
in insn_csrrs_cg
.
It crosses csr_cp
(which tracks each valid CSR, plus an invalid CSR) with bits_to_set_cp
(which tracks whether bits_to_set
is nonzero).
It is possible for CSRRS to trigger multiple errors in a single cycle. The possible errors are: underflow call stack, overflow call stack, and invalid CSR. It's not possible to under- and overflow the call stack in a single cycle. The other two combinations are possible:
- Underflow the call stack and access an invalid CSR
Tracked as
underflow_with_bad_csr_cp
. - Overflow the call stack and access an invalid CSR
Tracked as
overflow_with_bad_csr_cp
.
This instruction uses the I
encoding schema, with covergroup enc_i_cg
.
The instruction-specific covergroup is insn_csrrw_cg
.
- Write to every valid CSR with a
<grd>
other thanx0
. - Write to every valid CSR with
<grd>
equal tox0
. - Write to an invalid CSR.
These points are tracked with csr_cross
in insn_csrrw_cg
.
It crosses csr_cp
(which tracks each valid CSR, plus an invalid CSR) with grd_cp_to_set_cp
(which tracks whether grd
is equal to x0
.
It is possible for CSRRW to trigger multiple errors in a single cycle. The possible errors are: underflow call stack, overflow call stack, and invalid CSR. It's not possible to under- and overflow the call stack in a single cycle. The other two combinations are possible:
- Underflow the call stack and access an invalid CSR
Tracked as
underflow_with_bad_csr_cp
. - Overflow the call stack and access an invalid CSR
Tracked as
overflow_with_bad_csr_cp
.
This instruction uses the I
encoding schema, but with every field set to a fixed value.
Encoding-level coverpoints are tracked in covergroup enc_ecall_cg
.
No special coverage points for this instruction.
This instruction uses the loop
encoding schema, with covergroup enc_loop_cg
.
The instruction-specific covergroup is insn_loop_cg
.
- Loop with a zero iteration count (causing an error)
Tracked as the
'0
bin ofiterations_cp
. - Loop with a count of
'1
(the maximal value) Tracked as the'1
bin ofiterations_cp
. - Loop when the loop end address would be above the top of memory.
Tracked as
oob_end_addr_cp
. - Loop when the loop stack is full, causing an overflow.
Tracked as
loop_stack_fullness_cp
. - Loop at the end of a loop.
Tracked as
at_loop_end_cp
. - Duplicate loop end address, matching top of stack
Tracked as
duplicate_loop_end_cp
.
It is possible for LOOP to trigger multiple errors in a single cycle. The possible errors are: underflow call stack, zero loop count, and loop at end of loop. It's not possible to underflow the call stack and see a zero loop count (because if we underflow the call stack, we have no loop count), so we get two pairs:
- Underflow the call stack and loop at the end of a loop.
Tracked as
underflow_at_loop_end_cp
. - Loop with a zero loop count at the end of a loop.
Tracked as
zero_count_at_loop_end_cp
.
This instruction uses the loopi
encoding schema, with covergroup enc_loopi_cg
.
The instruction-specific covergroup is insn_loopi_cg
.
- Loop with a zero iteration count (causing an error)
This is tracked in
enc_loopi_cg
with the'0
bin ofiterations_cp
. - Loop when the loop end address would be above the top of memory.
Tracked as
oob_end_addr_cp
. - Loop when the loop stack is full, causing an overflow.
Tracked as
loop_stack_fullness_cp
. - Loop at the end of a loop.
Tracked as
at_loop_end_cp
. - Duplicate loop end address, matching top of stack
Tracked as
duplicate_loop_end_cp
.
It is possible for LOOPI to trigger multiple errors in a single cycle. The possible errors are: zero loop count and loop at end of loop. These can happen together:
- Loop with a zero loop count at the end of a loop.
Tracked as
zero_count_at_loop_end_cp
.
This instruction uses the bnaf
encoding schema, with covergroup enc_bnaf_cg
.
There is no instruction-specific covergroup.
- Extremal values of shift for both directions where the shifted value is nonzero.
This is tracked in
enc_bnaf_cg
asst_sb_nz_shifted_cross
. - A nonzero right shift with a value in
wrs2
whose top bit is set This is tracked inenc_bnaf_cg
assrl_cross
.
This instruction uses the bnaf
encoding schema, with covergroup enc_bnaf_cg
.
The instruction-specific covergroup is insn_bn_addc_cg
.
- Extremal values of shift for both directions where the shifted value is nonzero
This is tracked in
enc_bnaf_cg
asst_sb_nz_shifted_cross
. - A nonzero right shift with a value in
wrs2
whose top bit is set This is tracked inenc_bnaf_cg
assrl_cross
. - Execute with both values of the carry flag for both flag groups (to make sure things are wired through properly)
Tracked as
carry_cross
.
This instruction uses the bnai
encoding schema, with covergroup enc_bnai_cg
.
There is no instruction-specific covergroup.
No special coverage.
This instruction uses the bnam
encoding schema, with covergroup enc_bnam_cg
.
The instruction-specific covergroup is insn_bn_addm_cg
.
- Execute with the two extreme values of
MOD
(zero and all ones) Tracked asmod_cp
. - Don't perform a subtraction (because the sum is less than
MOD
) whenMOD
is nonzero. Tracked assum_lt_cp
. - A calculation where the sum exactly equals a nonzero
MOD
Tracked assum_eq_cp
. - A calculation where the sum is greater than a nonzero
MOD
. Tracked assum_gt_cp
. - Perform a subtraction where the sum is at least twice a nonzero value of
MOD
. Tracked assum_gt2_cp
. - A calculation where the intermediate sum is greater than
2^256-1
, crossed with whether the subtraction ofMOD
results in a value that will wrap. Tracked asoverflow_wrap_cross
.
This instruction uses the bnaq
encoding schema, with covergroup enc_bnaq_cg
.
The instruction-specific covergroup is insn_bn_mulqaccx_cg
(shared with the other BN.MULQACC*
instructions).
- Cross
wrs1_qwsel
withwrs2_qwsel
to make sure they are applied to the right inputs This is tracked inenc_bnaq_cg
asqwsel_cross
. - See the accumulator overflow
This is tracked in
insn_bnmulqaccx_cg
asoverflow_cross
.
This instruction uses the bnaq
encoding schema, with an extra field not present in bn.mulqacc
.
Encoding-level coverpoints are tracked in covergroup enc_bnaqw_cg
.
The instruction-specific covergroup is insn_bn_mulqaccx_cg
(shared with the other BN.MULQACC*
instructions).
- Cross
wrs1_qwsel
withwrs2_qwsel
to make sure they are applied to the right inputs This is tracked inenc_bnaqw_cg
asqwsel_cross
. - See the accumulator overflow
This is tracked in
insn_bnmulqaccx_cg
asoverflow_cross
.
This instruction uses the bnaq
encoding schema, with an extra field not present in bn.mulqacc
.
Encoding-level coverpoints are tracked in covergroup enc_bnaqs_cg
.
The instruction-specific covergroup is insn_bn_mulqaccx_cg
(shared with the other BN.MULQACC*
instructions).
- Cross
wrs1_qwsel
withwrs2_qwsel
to make sure they are applied to the right inputs This is tracked inenc_bnaqs_cg
asqwsel_cross
. - See the accumulator overflow
This is tracked in
insn_bnmulqaccx_cg
asoverflow_cross
. - Cross the generic flag updates with
wrd_hwsel
, since the flag changes are different in the two modes. This is tracked inenc_bnaqs_cg
asflags_01_cross
,flags_10_cross
andflags_11_cross
.
This instruction uses the bnaf
encoding schema, with covergroup enc_bnaf_cg
.
There is no instruction-specific covergroup.
- Extremal values of shift for both directions where the shifted value is nonzero
This is tracked in
enc_bnaf_cg
asst_sb_nz_shifted_cross
. - A nonzero right shift with a value in
wrs2
whose top bit is set This is tracked inenc_bnaf_cg
assrl_cross
.
This instruction uses the bnaf
encoding schema, with covergroup enc_bnaf_cg
.
The instruction-specific covergroup is insn_bn_subcmpb_cg
.
- Extremal values of shift for both directions where the shifted value is nonzero
This is tracked in
enc_bnaf_cg
asst_sb_nz_shifted_cross
. - A nonzero right shift with a value in
wrs2
whose top bit is set This is tracked inenc_bnaf_cg
assrl_cross
. - Execute with both values of the carry flag for both flag groups (to make sure things are wired through properly)
Tracked as
fg_carry_flag_cross
.
This instruction uses the bnai
encoding schema, with covergroup enc_bnai_cg
.
There is no instruction-specific covergroup.
No special coverage.
This instruction uses the bnam
encoding schema, with covergroup enc_bnam_cg
.
The instruction-specific covergroup is insn_bn_subm_cg
.
- Execute with the two extreme values of
MOD
(zero and all ones) Tracked asmod_cp
. - A non-negative intermediate result with a nonzero
MOD
(soMOD
is not added). Tracked asdiff_nonneg_cp
. - An intermediate result that exactly equals a nonzero
-MOD
. Tracked asdiff_minus_mod_cp
. - A negative intermediate result with a nonzero
MOD
, soMOD
is added and the result is positive. Tracked asdiff_neg_cp
. - A very negative intermediate result with a nonzero
MOD
(soMOD
is added, but the top bit is still set) Tracked asdiff_neg2_cp
.
This instruction uses the bna
encoding schema, with covergroup enc_bna_cg
.
There is no instruction-specific covergroup.
- Extremal values of shift for both directions where the shifted value is nonzero
Tracked in
enc_bna_cg
asst_sb_nz_shifted_cross
. - Toggle coverage of the output result (to ensure we're not just AND'ing things with zero)
Tracked in
enc_bna_cg
aswrd_XXXXXXXX_cross
, whereXXXXXXXX
is the base-2 representation of the bit being checked.
This instruction uses the bna
encoding schema, with covergroup enc_bna_cg
.
There is no instruction-specific covergroup.
- Extremal values of shift for both directions where the shifted value is nonzero
Tracked in
enc_bna_cg
asst_sb_nz_shifted_cross
. - Toggle coverage of the output result (to ensure we're not just OR'ing things with zero)
Tracked in
enc_bna_cg
aswrd_XXXXXXXX_cross
, whereXXXXXXXX
is the base-2 representation of the bit being checked.
This instruction uses the bnan
encoding schema, with covergroup enc_bnan_cg
.
There is no instruction-specific covergroup.
- Extremal values of shift for both directions where the shifted value is nonzero
Tracked in
enc_bnan_cg
asst_sb_nz_shifted_cross
. - Toggle coverage of the output result (to ensure nothing gets clamped)
Tracked in
enc_bnan_cg
aswrd_XXXXXXXX_cp
, whereXXXXXXXX
is the base-2 representation of the bit being checked.
This instruction uses the bna
encoding schema, with covergroup enc_bna_cg
.
There is no instruction-specific covergroup.
- Extremal values of shift for both directions where the shifted value is nonzero
Tracked in
enc_bna_cg
asst_sb_nz_shifted_cross
. - Toggle coverage of the output result (to ensure we're not just XOR'ing things with zero)
Tracked in
enc_bna_cg
aswrd_XXXXXXXX_cross
, whereXXXXXXXX
is the base-2 representation of the bit being checked.
This instruction uses the bnr
encoding schema, with covergroup enc_bnr_cg
.
There is no instruction-specific covergroup.
No special coverage.
This instruction uses the bns
encoding schema, with covergroup enc_bns_cg
.
There is no instruction-specific covergroup.
- Cross flag group, flag and flag value (2 times 4 times 2 points)
Tracked in
enc_bns_cg
asflag_cross
.
This instruction uses the bnc
encoding schema, with covergroup enc_bnc_cg
.
There is no instruction-specific covergroup.
- Extremal values of shift for both directions where the shifted value is nonzero
Tracked in
enc_bnc_cg
asst_sb_nz_shifted_cross
. - A nonzero right shift with a value in
wrs2
whose top bit is set Tracked inenc_bnc_cg
assrl_cross
.
This instruction uses the bnc
encoding schema, with covergroup enc_bnc_cg
.
The instruction-specific covergroup is insn_bn_subcmpb_cg
.
- Extremal values of shift for both directions where the shifted value is nonzero
Tracked in
enc_bnc_cg
asst_sb_nz_shifted_cross
. - A nonzero right shift with a value in
wrs2
whose top bit is set Tracked inenc_bnc_cg
assrl_cross
. - Execute with both values of the carry flag for both flag groups (to make sure things are wired through properly)
Tracked as
fg_carry_flag_cross
.
This instruction uses the bnxid
encoding schema, with covergroup enc_bnxid_cg
.
The instruction-specific covergroup is insn_bn_xid_cg
(shared with BN.SID
).
- Load from a valid address, where
grs1
is above the top of memory and a negativeoffset
brings the load address in range. Tracked asoob_base_neg_off_cross
. - Load from a valid address, where
grs1
is negative and a positiveoffset
brings the load address in range. Tracked asneg_base_pos_off_cross
. - Load from address zero
Tracked as
addr0_cross
. - Load from the top word of memory
Tracked as
top_addr_cross
. - Load from an invalid address (aligned but above the top of memory)
Tracked as
oob_addr_cross
. - Load from a calculated negative invalid address (aligned but unsigned address exceeds the top of memory)
Tracked as
oob_addr_neg_cross
. - Misaligned address tracking.
Track loads from addresses that are in range for the size of the memory.
We track all possible alignments of the sum as
addr_align_cross
. The reason for not tracking offset and register value misalignments separately is because the offset would always be shifted by 5 bits, which makes it always aligned. - See an invalid instruction with both increments specified
Tracked in
enc_bnxid_cg
as a bin ofincd_inc1_cross
. - See
grd
greater than 31, giving an illegal instruction error Tracked asbigb_cross
. - Cross the three types of GPR for
grd
withgrd_inc
Tracked inenc_bnxid_cg
asgrx_incd_cross
. - Cross the three types of GPR for
grs1
withgrd_inc
Tracked inenc_bnxid_cg
asgrs1_inc1_cross
.
It is possible for BN.LID to trigger multiple errors in a single cycle.
The possible errors are: underflow call stack (for grs1
), underflow call stack (for grd
), both increments set, invalid WDR index and bad data address.
If we underflow the call stack for grs1
, there's no architectural address, so that can't happen at the same time as a bad data address.
Similarly, if we underflow the call stack for grd
, there's no WDR index, so that can't cause an invalid WDR index.
However, every other combination is possible.
Binning together the two underflows unless it makes a difference to the possible behaviour gives the following list:
- Underflow call stack and set both increments.
Tracked as
underflow_and_inc_both_cross
. - Underflow call stack for
grs1
and have a bad WDR index in*grd
. Tracked asunderflow_and_badb_cross
. - Underflow call stack for
grd
and compute a bad address from*grs1
. Tracked asunderflow_and_bad_addr_cross
. - Set both increments and have a bad WDR index.
Tracked as
inc_both_and_bad_wdr_cross
. - Set both increments and load from a bad address.
Tracked as
inc_both_and_bad_addr_cross
. - Have a bad WDR index when loading from a bad address.
Tracked as
bad_wdr_and_bad_addr_cross
. - Underflow call stack for
grs1
, setting both increments and have a bad WDR index in*grd
. Tracked asunderflow_and_inc_both_and_bad_wdr_cross
. - Underflow call stack for
grd
, setting both increments and compute a bad address from*grs1
. Tracked asunderflow_and_inc_both_and_bad_addr_cross
. - Set both increments and have both a bad WDR index and a bad address.
Tracked as
inc_both_and_bad_wdr_and_bad_addr_cross
.
This instruction uses the bnxid
encoding schema, with covergroup enc_bnxid_cg
.
The instruction-specific covergroup is insn_bn_xid_cg
(shared with BN.LID
).
- Store to a valid address, where
grs1
is above the top of memory and a negativeoffset
brings the load address in range. Tracked asoob_base_neg_off_cross
. - Store to a valid address, where
grs1
is negative and a positiveoffset
brings the load address in range. Tracked asneg_base_pos_off_cross
. - Store to address zero
Tracked as
addr0_cross
. - Store to the top word of memory
Tracked as
top_addr_cross
. - Store to an invalid address (aligned but above the top of memory)
Tracked as
oob_addr_cross
. - Store to a calculated negative invalid address (aligned but unsigned address exceeds the top of memory)
Tracked as
oob_addr_neg_cross
. - Misaligned address tracking.
Track stores to addresses that are in range for the size of the memory.
We track all possible alignments of the sum as
addr_align_cross
. The reason for not tracking offset and register value misalignments separately is because the offset would always be shifted by 5 bits, which makes it always aligned. - See an invalid instruction with both increments specified
Tracked in
enc_bnxid_cg
as a bin ofincd_inc1_cross
. - See
grd
greater than 31, giving an illegal instruction error Tracked asbigb_cross
. - Cross the three types of GPR for
grs2
withgrs2_inc
Tracked inenc_bnxid_cg
asgrx_incd_cross
. - Cross the three types of GPR for
grs1
withgrd_inc
Tracked inenc_bnxid_cg
asgrs1_inc1_cross
.
It is possible for BN.SID to trigger multiple errors in a single cycle.
The possible errors are: underflow call stack (for grs1
), underflow call stack (for grs2
), both increments set, invalid WDR index and bad data address.
If we underflow the call stack for grs1
, there's no architectural address, so that can't happen at the same time as a bad data address.
Similarly, if we underflow the call stack for grs2
, there's no WDR index, so that can't cause an invalid WDR index.
However, every other combination is possible.
Binning together the two underflows unless it makes a difference to the possible behaviour gives the following list:
- Underflow call stack and set both increments.
Tracked as
underflow_and_inc_both_cross
. - Underflow call stack for
grs1
and have a bad WDR index in*grs2
. Tracked asunderflow_and_badb_cross
. - Underflow call stack for
grs2
and compute a bad address from*grs1
. Tracked asunderflow_and_bad_addr_cross
. - Set both increments and have a bad WDR index.
Tracked as
inc_both_and_bad_wdr_cross
. - Set both increments and store to a bad address.
Tracked as
inc_both_and_bad_addr_cross
. - Have a bad WDR index when storing to a bad address.
Tracked as
bad_wdr_and_bad_addr_cross
. - Underflow call stack for
grs1
, setting both increments and have a bad WDR index in*grs2
. Tracked asunderflow_and_inc_both_and_bad_wdr_cross
. - Underflow call stack for
grs2
, setting both increments and compute a bad address from*grs1
. Tracked asunderflow_and_inc_both_and_bad_addr_cross
. - Set both increments and have both a bad WDR index and a bad address.
Tracked as
inc_both_and_bad_wdr_and_bad_addr_cross
.
This instruction uses the bnmov
encoding schema, with covergroup enc_bnmov_cg
.
There is no instruction-specific covergroup.
No special coverage otherwise.
This instruction uses the bnmovr
encoding schema, with covergroup enc_bnmovr_cg
.
The instruction-specific covergroup is insn_bn_movr_cg
.
- See an invalid instruction with both increments specified
Tracked in
enc_bnmovr_cg
as a bin ofincd_inc1_cross
. - Since MOVR signals an error if either of its source registers has a value greater than 31, cross whether the input register value at
grd
is greater than 31 with whether the register value atgrs
is greater than 31 Tracked inenc_bnmovr_cg
asbig_gpr_cross
.
It is possible for BN.MOVR to trigger multiple errors in a single cycle.
The possible errors are: underflow call stack (for grs
), underflow call stack (for grd
), both increments set, invalid WDR index (from *grs
) and invalid WDR index (from *grd
).
If we underflow the call stack for grs
, there's no WDR index from *grs
, so it's not also possible to see an invalid WDR index from that.
Similarly, if we underflow the call stack for grd
then there's no WDR index from *grd
, so it's not also possible to see an invalid WDR index from that.
Binning together the two underflows and WDR indices unless it makes a difference to the possible behaviour gives the following list:
- Underflow call stack and set both increments.
Tracked as
underflow_and_inc_both_cp
. - Underflow call stack for
grs
and have a bad WDR index in*grd
. Tracked asunderflow_and_bad_grd_cp
. - Underflow call stack for
grd
and have a bad WDR index in*grs
. Tracked asunderflow_and_bad_grs_cp
. - Set both increments and have a bad WDR index.
Tracked as
inc_both_and_bad_wdr_cp
. - Underflow call stack for
grs
, setting both increments and have a bad WDR index in*grd
. Tracked asunderflow_grs_and_inc_both_and_bad_wdr_cp
. - Underflow call stack for
grd
, setting both increments and have a bad WDR index in*grs
. Tracked asunderflow_grd_and_inc_both_and_bad_wdr_cp
.
This instruction uses the bnwcsr
encoding schema, with covergroup enc_wcsr_cg
.
There is no instruction-specific covergroup.
- Read from each valid WSR and an invalid WSR.
Tracked with
wsr_cross
inenc_wcsr_cg
. - Read from each key sideload WSR, getting a valid response.
Tracked as part of
key_avail_cross
ininsn_bn_wsrr_cg
. - Read from each key sideload WSR, getting a KEY_INVALID error.
Tracked as part of
key_avail_cross
ininsn_bn_wsrr_cg
.
These points are tracked with wsr_cross
in enc_wcsr_cg
.
This instruction uses the bnwcsr
encoding schema, with covergroup enc_wcsr_cg
.
There is no instruction-specific covergroup.
- Write to each valid WSR, including read-only WSRs.
- Write to an invalid WSR
These points are tracked with wsr_cross
in enc_wcsr_cg
.