123 lines
7.6 KiB
Markdown
123 lines
7.6 KiB
Markdown
# Source-fetch and target-pair refill timing
|
|
|
|
## Finding and evidence
|
|
|
|
The instruction buffer already sampled a branch's old-state lookahead and its two target instructions.
|
|
However, timing charged three destination accesses: N(T), S(T+W), and S(T+2W).
|
|
That omitted the source-region cost and charged the third target fetch before target execution.
|
|
The totals often matched within one memory region, hiding cross-region and instruction-state errors.
|
|
Machine IRQ entry also omitted the discarded source sample entirely.
|
|
|
|
The [ARM7TDMI branch timing description](https://support.arm.com/documentation/ddi0029/g/instruction-cycle-timings/branch-and-branch-with-link) specifies three accesses:
|
|
|
|
1. Prefetch from the current PC while calculating the destination. The decision cannot prevent this fetch.
|
|
2. Fetch the branch destination.
|
|
3. Fetch destination plus one instruction length to refill the pipeline.
|
|
|
|
The [software-interrupt and exception-entry description](https://support.arm.com/documentation/ddi0029/g/instruction-cycle-timings/software-interrupt-and-exception-entry) likewise describes a forced-address construction cycle followed by pipeline refill.
|
|
Its first address is `pc+2L`, using the incoming instruction state.
|
|
The vector pair uses ARM state.
|
|
|
|
[NanoBoyAdvance at 55b5cf0a](https://github.com/nba-emu/NanoBoyAdvance/blob/55b5cf0ae3d929582ac5bfd486558173502b8354/src/nba/src/arm/arm7tdmi.hh) provides a source cross-check:
|
|
|
|
- `Run` fetches the old-state lookahead before instruction execution.
|
|
- `ReloadPipeline16` and `ReloadPipeline32` read the target N and the next instruction S.
|
|
- `SignalIRQ` first performs a discarded halfword/word fetch using the incoming state and access kind.
|
|
It then changes mode/state and reloads the ARM vector pair.
|
|
|
|
This supports source-address and target-pair accounting, not complete chronological bus sequencing in this emulator.
|
|
The existing [DMA resume evidence](dma-resume-timing.md) supports changing the next source access to N.
|
|
No physical-hardware measurement or external-emulator differential run was performed.
|
|
Tests and tracing code are original. No external source code, ROM, or BIOS was added to the repository.
|
|
|
|
## Implemented subset
|
|
|
|
For an instruction executing at P, `Cpu::step_timed` charges its sampled lookahead once:
|
|
|
|
- ARM source: P+8, word width.
|
|
- Thumb source: P+4, halfword width.
|
|
- Access kind: now retained from the preceding instruction by the [sequencing extension](fetch-access-sequencing.md), with DMA override.
|
|
- WAITCNT: captured before instruction effects.
|
|
|
|
If the instruction refills, timing also charges N(T) and S(T+W) using the resulting state.
|
|
The existing pipeline samples supply those instructions and update supported local history.
|
|
T+2W is sampled and charged when the first target instruction executes, not during the refill.
|
|
The same rule covers taken branches, BX, PC loads/writes, SWI, saved-state returns, and Thumb BL suffixes.
|
|
Untaken conditions and BL prefixes do not add a target pair.
|
|
|
|
Accepted machine IRQ entry samples the discarded incoming-state P+2W fetch, then the ARM vector pair.
|
|
It does not fetch or execute the interrupted current opcode, nor invent a cold current/decode fill.
|
|
The discarded sample drives its addressed IWRAM lanes when mapped; other regions leave that local history unchanged.
|
|
An unavailable discarded sample cannot prevent entry and is not retained as a current-slot diagnostic.
|
|
Unavailable vector samples fail only when execution reaches them.
|
|
IRQ sampling does not commit a BIOS instruction snapshot because no BIOS instruction executed.
|
|
The separate successful-BIOS-instruction history policy remains unchanged.
|
|
|
|
Masked IRQ requests have no fetch, history, CPU, or resume-state effects.
|
|
DMA still takes priority at machine-step boundaries.
|
|
Successful IRQ entry consumes pending DMA resume through normal machine-step completion.
|
|
Devices advance once by the total entry cost, not between its accesses.
|
|
The public memory-free `Cpu::enter_exception` and `Cpu::take_interrupt` APIs remain unchanged.
|
|
|
|
## Examples with default WAITCNT
|
|
|
|
| Operation | Source | Target pair | Code cycles |
|
|
| --- | --- | --- | --- |
|
|
| IWRAM ARM BX to Thumb WS1 | 1 | 5 + 5 | 11 |
|
|
| IWRAM Thumb BX to ARM WS0 | 1 | 8 + 6 | 15 |
|
|
| ARM WS0 branch to IWRAM | 6 | 1 + 1 | 8 |
|
|
| ARM WS0 branch within WS0 | 6 | 8 + 6 | 20 |
|
|
| Same branch after DMA | 8 | 8 + 6 | 22 |
|
|
| IRQ from ARM WS0 | 6 | 1 + 1 | 8 |
|
|
| IRQ from ARM WS0 after DMA | 8 | 1 + 1 | 10 |
|
|
|
|
These examples exclude ROM page boundaries.
|
|
Every access independently selects its actual region, wait window, and forced-N 128 KiB boundary cost.
|
|
A target pair can cross a region or wait-window boundary.
|
|
A boundary at T+2W is charged on target execution, not during the preceding branch.
|
|
DMA can produce two N accesses: the source fetch and the first target fetch. No fourth fetch is added.
|
|
|
|
## Original regression coverage
|
|
|
|
Tests cover:
|
|
|
|
- Incoming/outgoing ARM and Thumb widths, all ROM wait settings, and the stored prefetch bit.
|
|
- Boundaries in the first, second, and third target slots, plus split wait-window target pairs.
|
|
- ROM source boundaries and DMA resume before a RAM refill, with no delayed resume penalty.
|
|
- Cross-region source lookahead, data/internal costs for PC loads, and saved-state returns.
|
|
- IRQ source widths, missing ROM, masked requests, LR/SPSR preservation, and device-clock totals.
|
|
- IRQ IWRAM word and halfword lane updates, cold entry without invented fills, and retained Thumb entry.
|
|
- Missing-vector rollback after accepted entry, BIOS-history isolation, and timed/untimed CPU equivalence.
|
|
|
|
## Validation and report changes
|
|
|
|
Workspace and core/demo tests pass in debug and release on Darwin arm64.
|
|
Formatting, clippy, rustdoc, Python preparation tests, native ROM windows, and all graphics smoke modes pass.
|
|
The release executable is native Mach-O arm64.
|
|
Public ARM, Thumb, memory, and BIOS checkpoint assertions pass. Debug and release reports match.
|
|
|
|
Compared with the preceding fetch-address change, the ARM, Thumb, and memory reports each lose five nominal cycles.
|
|
Their step counts and all other report fields remain unchanged.
|
|
The BIOS report gains three instructions and 29 nominal cycles; all other fields remain unchanged.
|
|
|
|
A temporary original trace runner compared the preceding and updated cores against the pinned BIOS fixture.
|
|
The changed VBlank arrival position causes one extra three-instruction polling loop, adding 34 cycles.
|
|
Cross-region firmware transfers and IRQ entry together remove five cycles, giving the observed net increase of 29.
|
|
The trace still reaches the same checkpoint with r12=0 and one IRQ entry.
|
|
This trace comparison is a regression audit between our core versions, not external hardware validation.
|
|
|
|
The original timer demo retains its total nominal duration and IRQ step.
|
|
IRQ entry gains five cycles before the handler stops the timer; the return loses five cycles afterward.
|
|
The stopped counter therefore increases by five even though the final machine-cycle total is unchanged.
|
|
|
|
## Remaining limits
|
|
|
|
- The later [sequencing extension](fetch-access-sequencing.md) retains the next source kind after CPU data/internal work.
|
|
Data timing and device scheduling still do not form a complete chronological bus trace.
|
|
- Cold current/decode fills have no separate startup timing charge.
|
|
- BIOS retained history is not a complete refill/data-access bus latch.
|
|
- Missing instruction bytes remain diagnostics, not hardware prefetch aborts.
|
|
- Per-access device updates, display contention, configurable EWRAM timing, and sub-instruction DMA arbitration remain unimplemented.
|
|
- The later [nominal prefetch queue](gamepak-prefetch.md) can change source and target costs when bit 14 is enabled.
|
|
|
|
Game Pak prefetch followed this baseline; independent startup and invalidation timing validation remains necessary.
|