Audit status:
TASKS.md§31.4 is closed by the fail-hard matrices named below. This is subsystem evidence, not whole-core release sign-off; the remaining bus, debug, validation, and FPGA gates in §31 still apply.
Seven exception types per the ARM7TDMI-S r4p3 TRM §2.9. This doc captures their entry semantics, priorities, and where they fire in our pipelined core.
0x00 Reset ← deassertion of nRESET
0x04 Undefined ← INSTR_UNDEF + cond_pass, cond=1111 policy, unhandled coprocessor
0x08 SWI ← INSTR_SWI + cond_pass
0x0C PABT ← fd_q.pabort (= ABORT during this instruction's fetch)
0x10 DABT ← ABORT during a memory data cycle
0x14 reserved
0x18 IRQ ← nIRQ low + !cpsr.i
0x1C FIQ ← nFIQ low + !cpsr.f
The vector slots typically hold B <handler> branches.
Higher priority wins when multiple exceptions are simultaneously raised:
1. Reset
2. DABT → mode=ABT, vec=0x10, spsr_idx=3
3. FIQ → mode=FIQ, vec=0x1C, spsr_idx=0
4. IRQ → mode=IRQ, vec=0x18, spsr_idx=1
5. PABT → mode=ABT, vec=0x0C, spsr_idx=3
6. UNDEF → mode=UND, vec=0x04, spsr_idx=4
7. SWI → mode=SVC, vec=0x08, spsr_idx=2
Reset dominates through the reset path rather than the ordinary event selector.
DABT is selected at a memory-completion boundary; the dedicated DABT+FIQ
interlock enters Abort first and retains a coincident FIQ for the immediately
following boundary. At an ordinary Execute boundary, the one-hot selectors
enforce FIQ > IRQ > PABT > UNDEF > SWI before exc_mode_target maps the
selected event to its mode, SPSR bank, and vector.
For any exception E (gated by any_exc_fires):
1. r14_<E-mode> := exception_lr_value (class/source-state-specific return address)
2. SPSR_<E-mode> := current CPSR (saved program status)
3. CPSR.M := exc_mode_target (switch banks)
4. CPSR.I := 1 (mask IRQs in handler)
5. CPSR.F := 1 if FIQ-entry only (FIQs auto-disable on FIQ entry)
6. CPSR.T := 0 (ARM state in handler)
7. PC := vector address (flush + branch)
All steps commit at the same posedge. The pipeline flush invalidates F/D state; the next cycle's fetch is from the new PC.
The saved link is not one universal PC+4 value. ARM SWI/Undefined save the
source instruction address plus 4, while their Thumb forms save plus 2.
PABT/IRQ/FIQ save plus 4, and DABT saves the source instruction address plus 8
for the faulting transfer. The retained FIQ entry after a coincident DABT links back to
the untouched Abort vector so the standard SUBS pc,lr,#4 return resumes it.
During exception entry, the regfile is muxed to the target mode (regfile_mode_eff = any_exc_fires ? exc_mode_target : cpsr.m) so the r14 writeback lands in the target bank, not the current mode's bank. E.g., UNDEF from SVC writes r14_und (slot 30 in the flat regfile layout), not r14_svc.
u_psr.exc_enter_en triggers SPSR write to the indexed bank. The SPSR captures the current CPSR (pre-mode-switch) so the handler can MOVS PC, LR (or LDM ^ with PC) to atomically restore both PC and CPSR.
wire undef_pending = executing
&& ((condition_pass
&& (instr_is_undef || block_policy_undef
|| swp_policy_undef))
|| cond_is_nv
|| cp_undef_trap);
wire undef_fires = undef_pending && !fiq_pending && !irq_pending
&& !pabt_pending;instr_is_undef matches the decoded INSTR_UNDEF class. ARMv4 specifies
cond=1111 as UNPREDICTABLE, not as the ARMv5+ unconditional extension
space. This implementation freezes a precise Undefined trap as its
deterministic policy; cond_is_nv is a defense-in-depth trap route even
though the ARM decoder also returns INSTR_UNDEF. cp_undef_trap fires on
coprocessor instructions the core does not handle (CDP/MCR/MRC/LDC/STC with
cp_num outside the internal CP14 subset and no external acceptor).
The ARM decoder applies the ARM ARM extension-space rule before selecting an
execute unit. It rejects all unallocated [27:20]/[7:4] decode rows,
including the signed-store encodings later used for doubleword transfers and
the 11000x0x coprocessor double-register-transfer space. Consequently a
reserved word cannot perform a memory transfer or assert CPnI before taking
Undefined. The exhaustive evidence is reserved_decode_tb (4,096 ARM decode
rows, all 4,096 cond=1111 variants, and all 65,536 Thumb words) plus the
pin-level arm7tdmis_reserved_execute_tb.
An Undefined-class word whose ordinary ARM condition fails is unexecuted; it
does not set undef_pending. The corrected erratum-11 policy carries no
residual Undefined state into the next instruction. Consequently an
immediately following SWI selects the SWI vector, while Prefetch Abort
metadata attached to the following opcode selects PABT. The fourth and third
scenarios in arm7tdmis_pabt_pipeline_tb, respectively, check the selected
event signal, vector handler, LR/SPSR, and absence of a false Undefined
exception. There is no r4p3 defect-emulation parameter.
fd_q.pabort is carried into de_q.pabort. A monitor-mode instruction
breakpoint supplies the same instruction-associated request through
debug_pabt_pending; the explicit priority selector only asserts
pabt_fires when no DABT, FIQ, or IRQ is selected.
fd_q.pabort latches at the F-stage RDATA capture; carried through D into de_q.pabort. When the aborted instruction reaches E, this fires. The same instruction is not committed (no regfile write, no PC advance — exception entry takes over).
wire data_abort_now = ABORT && ((state_q == S_DDATA)
|| (state_q == S_BLOCK_DATA)
|| (state_q == S_SWP_RDATA)
|| (state_q == S_SWP_WDATA));
logic data_abort_q;
// latched on data_abort_now, cleared on S_EXEC entry
wire dabt_fires = (data_abort_q || data_abort_now)
&& (state_next == S_EXEC)
&& (state_q != S_EXEC);The data_abort_now term is load-bearing: for single-beat LDR/STR, the S_DDATA cycle IS the transition out (state_next == S_EXEC), so data_abort_q hasn't been latched yet. Including the live signal catches this case; the latched data_abort_q covers multi-beat LDM/STM where the abort fires mid-iteration and persists through S_BLOCK_WB.
The raw active-low levels are sampled only on enabled architectural instruction boundaries. Ordinary multicycle instructions defer recognition to their final substate; a busy external coprocessor can be abandoned at its defined wait boundary. FIQ wins over IRQ. A coincident one-cycle FIQ at a failed data response is retained by the DABT interlock until the complete three-cycle Abort entry has finished.
Note that nIRQ / nFIQ are pre-gated at the top by IFEN (the EmbeddedICE-RT interrupt-mask logic — see DEBUG.md):
nIRQ_eff = nIRQ | ~ice_ifen
nFIQ_eff = nFIQ | ~ice_ifen
So a debug session can mask interrupts entirely via the Debug Control Register INTDIS bit.
wire swi_fires = passes_cond && instr_is_swi;Fires on commit of an INSTR_SWI (= cond | 0b1111 | comment24).
The r4p3 TRM requires an LDM/STM to complete its transfer sequence after a Data Abort and leave the requested modified base visible. Implementation:
-
LDM destination suppression:
block_writes_ldmis gated by!data_abort_q && !data_abort_now. Loads before the abort commit; the aborting and every later destination write are suppressed. Because r15 is last, an abort on any beat prevents the PC write. -
LDM Base Updated result: normal writeback occurs in
S_BLOCK_WB. After an abort that port is needed for LR_abt, soblock_ldm_abort_writebackrestoresblock_writeback_addr_qinto Rn on the final data beat. This also prevents an earlier base-in-list load from replacing the modified base. -
STM writeback and stores: requested STM writeback commits in the setup cycle, before any response can abort. All beats are still presented; the external memory contract determines that the selected failed store does not commit, while the independent non-aborted beats do.
-
Latched snapshots:
block_writeback_q,block_writeback_addr_q, andblock_rn_qare captured at S_EXEC end so completion never relies ondec.*after the pipeline advances.
arm7tdmis_ldm_abort_tb, arm7tdmis_ldm_abort_base_list_tb, and
arm7tdmis_stm_abort_tb inject ABORT independently on every beat and check
all four transfers, register/store reachability, modified-base writeback,
r15 protection, exception state, and successor suppression.
A precise abort on the locked read cancels the write address immediately; the operation behaves as though it had not executed. An abort reported for the write response also suppresses the loaded-value writeback. In either case Rd is unchanged, the failed memory operation does not commit, the successor is flushed, LR_abt receives the swap instruction address plus eight, and LOCK is released before exception handling.
arm7tdmis_swp_read_abort_tb covers the architecture-required read-abort
contract independently for both widths. arm7tdmis_swp_bus_matrix_tb covers
both read- and write-response aborts alongside normal, stalled, reset, and
debug exits.
ARMv4T provides two mechanisms here: any data-processing instruction with
S=1 and Rd=PC restores CPSR from the current mode's SPSR, while an LDM with
S=1 and PC in the list performs the same restore on the PC beat. The TRM's
recommended data-processing idioms are MOVS and SUBS.
MOVS r15, r14
SUBS r15, r14, #4
SUBS r15, r14, #8
A DP instruction with Rd=15 and S=1. The direct
dp_writes_pc && dec.s_bit path, or its latched S_DP_SHIFT counterpart,
triggers cpsr_restore_now, which atomically:
- Writes PC := the data-processing result (r14 for
MOVS, or r14 minus the encoded return adjustment forSUBS). - Restores CPSR := SPSR_of_current_mode.
SWI and Undefined normally use MOVS; PABT, IRQ, and FIQ subtract 4; DABT
subtracts 8. SPSR.T controls target alignment and fetch width. SPSR.M controls
the first target fetch's privilege even on the fast refill, where the old
handler CPSR is still live until the capturing edge.
LDMFD sp!, {r0-r12, lr, pc}^
The ^ form with PC in the register list. When r15 loads (in S_BLOCK_DATA with block_curr_reg_q==15), block_ldm_pc_restore fires:
block_ldm_pc_restore = (state_q == S_BLOCK_DATA)
&& block_load_q
&& (block_curr_reg_q == 4'd15)
&& block_user_mode_q;
cpsr_restore_now ORs this into the SPSR-restore trigger.
Force-user-bank routing is gated off for this variant (block_has_pc_q set, force_user_bank_eff zero) because the ARM ARM specifies the current bank for r0-r14 when PC is in the list — only the SPSR restore is the "S=1" effect.
If writeback is requested, block_mode_q retains the source exception mode
through the final PC/CPSR-restore beat and the following S_BLOCK_WB cycle.
This ensures a banked SP/LR base is written in the handler bank rather than
the newly restored destination bank.
arm7tdmis_exception_return_matrix_tb validates 60 reset-per-row cases:
all five SPSR-owning exception modes, ARM and Thumb destinations, and six
direct/deferred DP or LDM return forms. It checks complete CPSR restoration,
physical SPSR/LR/SP banks, alignment, first-refill bus controls and privilege,
LDM beats/writeback, successor flushing, and otherwise-unchanged state.
arm7tdmis_ldm_pc_tb and arm7tdmis_pc_write_alignment_tb remain independent
focused regressions.
| Test | Coverage |
|---|---|
arm7tdmis_irq_tb |
nIRQ pin → vector 0x18 → handler |
arm7tdmis_fiq_tb |
nFIQ pin → vector 0x1C → handler |
arm7tdmis_abort_tb |
DABT during LDR → vector 0x10 → handler |
arm7tdmis_pabt_tb |
PABT during fetch → vector 0x0C → handler |
arm7tdmis_pabt_pipeline_tb |
Flush-associated PABT metadata and condition-failed-UDF → SWI/PABT sequencing |
arm7tdmis_pabt_debug_flush_tb |
PABT metadata retained through debug halt and discarded by scan-loaded-PC redirect |
arm7tdmis_exception_priority_tb |
FIQ+IRQ, IRQ+PABT, PABT+UNDEF, and PABT+SWI selection/discard behavior |
arm7tdmis_dabt_fiq_tb |
Coincident DABT+FIQ interlock, links, SPSRs, and Abort-vector resumption |
arm7tdmis_interrupt_sampling_matrix_tb |
Masking, held/pulsed levels, CLKEN stalls, late arrival, and FIQ+IRQ |
arm7tdmis_interrupt_latency_tb |
Four-cycle synchronized minimum and 27-cycle LDM-abort/FIQ maximum |
arm7tdmis_arm_exception_lr_tb |
All six ARM-state exception links and physical save banks |
arm7tdmis_thumb_exception_lr_tb |
All six Thumb-state exception links and physical save banks |
arm7tdmis_exception_bus_matrix_tb |
Table 7-16 entry pins for six classes × ARM/Thumb |
arm7tdmis_cond_fail_matrix_tb |
Every condition-failed class suppresses exceptions and all other side effects |
arm7tdmis_ldm_abort_tb |
DABT on every LDM beat → later destinations suppressed, Base Updated, r15 protected |
arm7tdmis_ldm_abort_base_list_tb |
DABT on every LDM beat with Rn in list → modified base restored |
arm7tdmis_stm_abort_tb |
DABT on every STM beat → sequence completes and requested writeback remains |
arm7tdmis_swp_read_abort_tb |
SWP/SWPB read abort → no write address, memory/Rd preserved |
arm7tdmis_swp_bus_matrix_tb |
SWP/SWPB read/write abort and LOCK exit matrix |
arm7tdmis_ldm_pc_tb |
LDM ^ PC exception return → CPSR restore |
arm7tdmis_exception_return_matrix_tb |
Five modes × ARM/Thumb × six DP/LDM return forms |
arm7tdmis_reset_multicycle_matrix_tb |
Reset dominance and quiescence in all 15 non-Execute states |
arm7tdmis_tb_top |
SWI (in smoke flow) |
arm7tdmis_undef_tb, arm7tdmis_reserved_execute_tb, and the exhaustive
reserved-decode unit test provide independent Undefined-instruction evidence.