feat(cpu): retain fetch access kinds across instruction execution
This commit is contained in:
parent
2d7eb6e4eb
commit
86321f0071
21 changed files with 637 additions and 61 deletions
|
|
@ -52,12 +52,13 @@ The repository is a Cargo workspace with three crates:
|
|||
| `crates/gba-core/src/dma.rs` | DMA registers, internal pointers, retained channel data, trigger state, priority, and completion IRQs |
|
||||
| `crates/gba-core/src/machine.rs` | Timed CPU/DMA/device stepping and IRQ delivery |
|
||||
| `crates/gba-core/src/timing.rs` | Bus widths, wait-state costs, and timing breakdowns |
|
||||
| `crates/gba-core/src/cpu/pipeline.rs` | CPU-owned ARM/Thumb instructions, PC/state tags, deferred fetch diagnostics, refill sampling, and explicit invalidation |
|
||||
| `crates/gba-core/src/cpu/pipeline.rs` | CPU-owned ARM/Thumb instructions, PC/state tags, next fetch kind, deferred diagnostics, refills, and invalidation |
|
||||
| `crates/gba-core/src/cpu/arm_pipeline_tests.rs` | ARM self-modifying code, branches, target pairs, DMA isolation, exceptions, errors, and timing equivalence |
|
||||
| `crates/gba-core/src/cpu/thumb_pipeline_tests.rs` | Thumb retained halfwords, BL prefix/suffix, state-tagged refills, DMA isolation, rollback, and timing equivalence |
|
||||
| `crates/gba-core/src/cpu/timing.rs` | Source-fetch/target-pair costs, IRQ fetch integration, nominal access kinds, and data accounting |
|
||||
| `crates/gba-core/src/cpu/timing.rs` | Source-fetch/target-pair costs, IRQ integration, next-fetch classification, and data accounting |
|
||||
| `crates/gba-core/src/cpu/fetch_timing_tests.rs` | Fetch-region/page/wait-window costs, DMA resume, WAITCNT stores, deferred errors, and timer/IRQ effects |
|
||||
| `crates/gba-core/src/cpu/refill_timing_tests.rs` | Refill source/target widths, wait settings, boundaries, DMA resume, and IRQ diagnostics |
|
||||
| `crates/gba-core/src/cpu/fetch_sequence_tests.rs` | Instruction-pair access kinds, transfer/internal-cycle breaks, refills, IRQ/DMA composition, and rollback |
|
||||
| `crates/gba-core/src/memory/irq_fetch_tests.rs` | Discarded IRQ fetch lanes, cold/retained entry, BIOS-history isolation, and deferred vector errors |
|
||||
| `crates/gba-core/src/cpu/dma_resume_tests.rs` | One-shot non-sequential DMA resume costs, wait settings, failures, idle, IRQs, and API isolation |
|
||||
| `crates/gba-core/src/cpu/timing_tests.rs` | Instruction timing and semantic-equivalence checks |
|
||||
|
|
|
|||
|
|
@ -104,16 +104,18 @@ A buffered fetch error fails only if execution reaches that slot. No automatic h
|
|||
A failed instruction preserves all CPU state, including the old buffer; its speculative advance is discarded.
|
||||
A successful branch discards abandoned-path errors and replaces them with target fetch results.
|
||||
|
||||
CPU clones and equality include the buffer. Architectural state checks are separate from full-state rollback checks in tests.
|
||||
CPU clones and equality include the buffer and its next fetch access kind.
|
||||
Architectural state checks are separate from full-state rollback checks in tests.
|
||||
`Cpu::invalidate_pipeline()` explicitly discards buffered instructions without changing registers, flags, or device clocks.
|
||||
Use it after debugger code repair or when attaching different memory to a retained CPU.
|
||||
Invalidation also resets the CPU fetch kind to the nominal cold-start S policy; Memory's DMA override remains separate.
|
||||
Do not call it for ordinary CPU/DMA stores: that would hide self-modifying-code behavior.
|
||||
|
||||
This is instruction buffering, not a complete timed fetch pipeline.
|
||||
Sampling adds no data accesses or independent device-clock updates.
|
||||
Code timing charges the source fetch and target pair once, with a DMA resume override on the source access.
|
||||
Instruction buffering and supported bus history now consume the same mapped fetch samples.
|
||||
Complete fetch-driven bus history, access-kind sequencing, per-access device updates, and DMA arbitration remain incomplete.
|
||||
Complete fetch-driven bus history, per-access device updates, and DMA arbitration remain incomplete.
|
||||
See the [ARM evidence and diagnostic policy](../research/arm-instruction-buffer.md), [Thumb extension](../research/thumb-instruction-buffer.md),
|
||||
and [shared fetch samples](../research/shared-fetch-samples.md).
|
||||
|
||||
|
|
@ -287,7 +289,7 @@ ARM `TST`, `TEQ`, `CMP`, and `CMN` encodings with unused destination bits set to
|
|||
These compare/status forms do not write the arithmetic result to PC. Execution continues at the next sequential address.
|
||||
In User/System modes, they perform ordinary test/compare flag updates without a mode change.
|
||||
Invalid saved modes still produce an atomic diagnostic. Failed conditions do not restore or validate status.
|
||||
Nominal timing remains one sequential code access, plus an internal cycle for register-specified shifts; there is no refill cost.
|
||||
Nominal timing uses the incoming code access kind, plus an internal cycle for register-specified shifts; there is no refill cost.
|
||||
This fixes the mode-switch expectation in public `jsmolka/gba-tests` ARM test 234 and agrees with mGBA's shared ALU flag handling.
|
||||
Instruction buffering is discarded on a state change without an ordinary refill.
|
||||
Instruction-state-changing compare forms and exact pipeline behavior remain hardware-unverified.
|
||||
|
|
@ -311,29 +313,35 @@ Neither constructor provides Nintendo BIOS services or initializes BIOS-managed
|
|||
|
||||
## Instruction and bus timing
|
||||
|
||||
The timing model uses ARM7 cycle summaries:
|
||||
The timing model distinguishes these ARM7 cycle types:
|
||||
|
||||
- **S:** sequential memory access.
|
||||
- **N:** non-sequential memory access.
|
||||
- **I:** internal CPU cycle, always one clock cycle.
|
||||
|
||||
An ordinary arithmetic instruction costs 1S. A register-specified shift adds 1I, even for a zero shift amount.
|
||||
Loads cost a code S access, a data N access, and 1I. Stores use N for code and data.
|
||||
Block transfers charge N for the first data word and S for each following word.
|
||||
Loads add 1I. Loading PC also adds the branch refill cost.
|
||||
Every instruction charges its source fetch using the incoming access kind retained by the CPU buffer.
|
||||
Ordinary arithmetic and immediate shifts leave the next fetch S.
|
||||
Register-specified shifts add 1I, even for a zero shift amount, and leave the next fetch N.
|
||||
Loads and stores start their data accesses with N and leave the next source fetch N.
|
||||
Block transfers use N for the first data word and S for each following word.
|
||||
Loads add 1I. Loading PC also fetches a target pair, which restores S for subsequent target execution.
|
||||
Branches, PC writes, software interrupts, and IRQ entry charge one source fetch plus a target N+S pair.
|
||||
The source fetch uses the incoming state at P+2W. The target pair uses the resulting state at T and T+W.
|
||||
The first target instruction charges T+2W when it executes; the refill does not charge it early.
|
||||
A skipped conditional instruction only pays its code S access.
|
||||
A skipped conditional instruction only pays its incoming code access and leaves the following fetch S.
|
||||
Thumb `BL` charges one source fetch for each half; only its suffix adds the target N+S pair.
|
||||
Multiply costs vary with the incoming multiplier's upper bytes; accumulate and long forms add internal cycles.
|
||||
ARM uses Rs for this calculation. Thumb multiply uses the incoming destination register.
|
||||
Multiply internal cycles leave the following fetch N. Swaps also leave N after their data/internal work.
|
||||
Successful target refills end with S, overriding sequence breaks from preceding data/internal work.
|
||||
IRQ entry uses the interrupted buffer's incoming kind before replacing that buffer.
|
||||
|
||||
Source code costs use the new instruction fetch address: P+8 for ARM and P+4 for Thumb.
|
||||
The incoming instruction state selects the width. The sampled fetch address selects the memory region and ROM wait-state window.
|
||||
A 128 KiB ROM boundary therefore forces N timing when lookahead reaches it, not when execution reaches it later.
|
||||
This applies to cold and retained pipelines without adding separate startup-fill costs.
|
||||
See [fetch-address timing](../research/fetch-address-timing.md) and [refill timing](../research/refill-fetch-timing.md) for evidence and limits.
|
||||
See [fetch-address timing](../research/fetch-address-timing.md), [refill timing](../research/refill-fetch-timing.md),
|
||||
and [persistent access kinds](../research/fetch-access-sequencing.md) for evidence and limits.
|
||||
|
||||
Data costs use the addresses and widths of actual CPU bus calls, after alignment handling.
|
||||
BIOS, internal work RAM, OAM, and supported I/O accesses cost one cycle.
|
||||
|
|
@ -355,7 +363,8 @@ This applies even when DMA only accesses RAM. Consecutive units retain one pendi
|
|||
The source fetch uses its actual lookahead address, incoming width, and current WAITCNT with N instead of S.
|
||||
This includes branches and accepted IRQ entry; target pairs still use N then S.
|
||||
ARM word accesses retain an S cost for their second halfword.
|
||||
Stores and ROM boundaries that already use N do not receive an additional cost.
|
||||
CPU history and ROM boundaries that already require N do not receive an additional access.
|
||||
A completed load or store can establish a new N requirement after consuming the DMA override.
|
||||
|
||||
Successful timed or untimed CPU execution consumes pending resume, including skipped conditions and internal-memory instructions.
|
||||
Successful machine IRQ entry also consumes it. Failed CPU/DMA steps preserve it.
|
||||
|
|
@ -370,8 +379,9 @@ See [the evidence and limitations](../research/dma-resume-timing.md).
|
|||
|
||||
Important timing limits:
|
||||
|
||||
- Source S/N kinds follow instruction-local summaries, not complete neighboring instruction/data-access sequencing.
|
||||
- Source S/N kinds follow the preceding successful instruction; data timing still uses an instruction-local trace.
|
||||
- Code costs follow actual source and target-pair addresses, but cold current/decode fills have no separate startup charge.
|
||||
Cold entry, debugger invalidation, and PC/state mismatches use nominal S, not hardware-validated startup timing.
|
||||
- Refill cost calculation does not read target bytes. ARM/Thumb instruction-buffer and local IWRAM bus-history samples add no extra cycles.
|
||||
- Target-pair sampling cannot fail the branch early. An invalid branch target still fails on the following instruction fetch.
|
||||
- Game Pak prefetch is not implemented. WAITCNT bit 14 is stored but does not accelerate execution.
|
||||
|
|
|
|||
|
|
@ -189,6 +189,16 @@ Refill and IRQ fetch-timing research:
|
|||
See [source-fetch and target-pair timing](research/refill-fetch-timing.md) for the implementation and public-report audit.
|
||||
Source review and comparisons between our own core versions are not physical-hardware timing validation.
|
||||
|
||||
Persistent fetch access-kind research:
|
||||
|
||||
- [ARM7TDMI load-multiple timing](https://support.arm.com/documentation/ddi0210/c/Instruction-Cycle-Timings/Load-multiple-registers), for separate prefetch, data-transfer, and internal-cycle phases.
|
||||
- [NanoBoyAdvance ARM handlers](https://github.com/nba-emu/NanoBoyAdvance/blob/55b5cf0ae3d929582ac5bfd486558173502b8354/src/nba/src/arm/handlers/handler32.inl) and [Thumb handlers](https://github.com/nba-emu/NanoBoyAdvance/blob/55b5cf0ae3d929582ac5bfd486558173502b8354/src/nba/src/arm/handlers/handler16.inl), for next-fetch kinds after data/internal work.
|
||||
- Its [bus timing](https://github.com/nba-emu/NanoBoyAdvance/blob/55b5cf0ae3d929582ac5bfd486558173502b8354/src/nba/src/bus/timing.cc), for separate internal and ROM costs when prefetch is inactive.
|
||||
- [ares processor memory helpers](https://github.com/ares-emulator/ares/blob/6f6786e04f0822a3475463df284f313ab8518d51/ares/component/processor/arm7tdmi/memory.cpp), [instruction loop](https://github.com/ares-emulator/ares/blob/6f6786e04f0822a3475463df284f313ab8518d51/ares/component/processor/arm7tdmi/instruction.cpp), and [ARM handlers](https://github.com/ares-emulator/ares/blob/6f6786e04f0822a3475463df284f313ab8518d51/ares/component/processor/arm7tdmi/instructions-arm.cpp), for independent burst termination and fetch-before-execution ordering.
|
||||
|
||||
See [persistent fetch access kinds](research/fetch-access-sequencing.md) for scope, cold-start policy, and regression-report changes.
|
||||
These are source comparisons, not hardware timing measurements or external-emulator test runs.
|
||||
|
||||
Use [GBATEK](https://problemkaputt.de/gbatek.htm) and ARM7TDMI documentation for further hardware work.
|
||||
Only use game ROMs that you may lawfully use. Do not commit game ROMs, BIOS files, or game assets.
|
||||
The ignore file excludes `roms/`, common game ROM extensions, and save files.
|
||||
|
|
|
|||
|
|
@ -72,7 +72,8 @@ Cold fill and target-pair samples do not add nominal cycles or data accesses.
|
|||
The later [refill timing extension](refill-fetch-timing.md) replaces destination-only costs with source-fetch and target-pair costs.
|
||||
IRQ entry also samples its discarded old-state fetch before the vector pair.
|
||||
The later [fetch-address timing extension](fetch-address-timing.md) selects non-refill code cost from the newly sampled address.
|
||||
Access kinds, cold-fill startup costs, and refill scheduling remain incomplete.
|
||||
The later [sequencing extension](fetch-access-sequencing.md) stores the next fetch kind in the instruction buffer.
|
||||
Cold-fill startup costs and per-access scheduling remain incomplete.
|
||||
|
||||
ARM PC+8 open bus and protected BIOS readback remain separate snapshots.
|
||||
The [shared fetch sample](shared-fetch-samples.md) supplies the instruction-buffer entry and supported bus snapshots without duplicate reads.
|
||||
|
|
|
|||
|
|
@ -53,7 +53,9 @@ DMA still executes only between instructions, not between data accesses or durin
|
|||
The later [refill timing extension](refill-fetch-timing.md) replaces destination-only summaries with source-fetch and target-pair costs.
|
||||
Resume changes the source access to N; the first target access independently remains N.
|
||||
No extra access is appended. A resumed ROM branch can therefore cost more than its non-resumed refill.
|
||||
Stores and fetches at 128 KiB ROM boundaries already use N and receive no duplicate cost.
|
||||
The later [sequencing extension](fetch-access-sequencing.md) applies each instruction's data/internal effects to the following source fetch.
|
||||
CPU history, DMA resume, and ROM page boundaries can all require N without duplicating an access.
|
||||
A completed transfer after DMA can establish a new N requirement for the following fetch.
|
||||
Game Pak prefetch remains unimplemented; WAITCNT bit 14 does not alter this nominal timing path.
|
||||
|
||||
This change does not select a DMA value for CPU open-bus reads.
|
||||
|
|
|
|||
129
docs/research/fetch-access-sequencing.md
Normal file
129
docs/research/fetch-access-sequencing.md
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
# Persistent CPU fetch access kinds
|
||||
|
||||
S means sequential access; N means non-sequential access. W is the instruction width.
|
||||
|
||||
## Finding and evidence
|
||||
|
||||
Source-fetch addresses and refill target pairs were already timed separately.
|
||||
However, the current instruction still selected its own source access kind.
|
||||
Stores selected N immediately; loads, register shifts, and multiplies did not affect the following instruction.
|
||||
IRQ entry always selected S unless DMA had completed.
|
||||
This lost the sequence break between instruction execution and the next fetch.
|
||||
|
||||
The [ARM7TDMI load-multiple description](https://support.arm.com/documentation/ddi0210/c/Instruction-Cycle-Timings/Load-multiple-registers) separates the initial prefetch, data transfers, and final internal cycle.
|
||||
Instruction cycle totals alone do not identify which neighboring fetch receives the bus-sequence change.
|
||||
Two pinned implementations provide a source-level cross-check:
|
||||
|
||||
- [NanoBoyAdvance ARM handlers at 55b5cf0a](https://github.com/nba-emu/NanoBoyAdvance/blob/55b5cf0ae3d929582ac5bfd486558173502b8354/src/nba/src/arm/handlers/handler32.inl) set the next pipeline access to N after transfers, swaps, register shifts, and multiplies.
|
||||
- Its [Thumb handlers](https://github.com/nba-emu/NanoBoyAdvance/blob/55b5cf0ae3d929582ac5bfd486558173502b8354/src/nba/src/arm/handlers/handler16.inl) do the same for corresponding Thumb operations.
|
||||
- Its [CPU loop and refill helpers](https://github.com/nba-emu/NanoBoyAdvance/blob/55b5cf0ae3d929582ac5bfd486558173502b8354/src/nba/src/arm/arm7tdmi.hh) consume that kind before execution, including discarded IRQ fetches.
|
||||
Failed ARM conditions set the following access to S. Target refills end with S.
|
||||
- Its [bus timing](https://github.com/nba-emu/NanoBoyAdvance/blob/55b5cf0ae3d929582ac5bfd486558173502b8354/src/nba/src/bus/timing.cc) charges internal cycles and requested ROM wait costs separately when prefetch is inactive.
|
||||
- [ares memory helpers at 6f6786e0](https://github.com/ares-emulator/ares/blob/6f6786e04f0822a3475463df284f313ab8518d51/ares/component/processor/arm7tdmi/memory.cpp) end a burst on internal cycles and data loads/stores.
|
||||
Its [instruction loop](https://github.com/ares-emulator/ares/blob/6f6786e04f0822a3475463df284f313ab8518d51/ares/component/processor/arm7tdmi/instruction.cpp) fetches before execution and restarts target refills with N followed by S.
|
||||
Its [ARM handlers](https://github.com/ares-emulator/ares/blob/6f6786e04f0822a3475463df284f313ab8518d51/ares/component/processor/arm7tdmi/instructions-arm.cpp) supply the corresponding internal cycles.
|
||||
|
||||
This is agreement between source implementations, not a physical-hardware timing result.
|
||||
No external emulator was executed. No external implementation or ROM was imported into the repository.
|
||||
Game Pak prefetch and within-instruction bus scheduling remain outside this subset.
|
||||
|
||||
## Implemented subset
|
||||
|
||||
The CPU instruction buffer retains the next source-fetch kind alongside its expected PC and instruction state.
|
||||
The current source fetch consumes the incoming kind, with the existing one-shot DMA override.
|
||||
Successful execution then selects the following kind:
|
||||
|
||||
| Completed operation | Following fetch |
|
||||
| --- | --- |
|
||||
| Arithmetic without an internal cycle, immediate shifts, status transfers, skipped conditions, BL prefix | S |
|
||||
| Loads/stores, block/stack transfers, swaps | N |
|
||||
| Register-controlled shifts and multiplies | N |
|
||||
| Branch, PC load/write, SWI, or machine IRQ target refill | S |
|
||||
|
||||
Register-controlled shifts break the sequence even when the shift amount is zero.
|
||||
Data operations break it even when data lies in RAM or I/O rather than ROM.
|
||||
A PC load finishes its data/internal work before its target pair; the pair therefore establishes S for target execution.
|
||||
The target pair itself remains N(T), S(T+W).
|
||||
|
||||
`Cpu::step` and `Cpu::step_timed` commit the same sequence state.
|
||||
Clones and full CPU equality include it. Failed instructions preserve it with the existing instruction buffer.
|
||||
A failed current-slot fetch cannot consume it. Deferred lookahead errors do not prevent a successful current instruction from updating it.
|
||||
IRQ entry captures the incoming kind before exception entry discards the old buffer.
|
||||
Masked IRQ requests leave it unchanged.
|
||||
|
||||
DMA history stays in `Memory`, separate from CPU continuation state.
|
||||
Either source can require N; their combination does not add a second fetch or a fixed surcharge.
|
||||
A completed load after DMA can establish a new N requirement for the following fetch.
|
||||
Host reads/writes, clock advancement, and HALT/STOP idle do not consume the CPU continuation.
|
||||
|
||||
Cold startup still uses nominal S and has no separate current/decode fill charge.
|
||||
Debugger invalidation and PC/state mismatches deliberately return to that cold policy.
|
||||
They cannot reuse another continuation's access kind. Debugger invalidation does not clear Memory's DMA override.
|
||||
This policy is not a claim about hardware reset/startup timing.
|
||||
A status-restoration quirk that changes instruction state without a normal refill also retains the existing cold-buffer policy.
|
||||
|
||||
## Example with default WS0 settings
|
||||
|
||||
For ARM code away from ROM boundaries, S costs 6 cycles and N costs 8 cycles.
|
||||
Consider a RAM word load followed by two ordinary arithmetic instructions:
|
||||
|
||||
1. The load consumes its incoming S source fetch, then performs its data read and internal cycle.
|
||||
2. The first arithmetic instruction consumes N because of the preceding load.
|
||||
3. The second arithmetic instruction consumes S again.
|
||||
|
||||
A store follows the same source-kind sequence, without the load's internal cycle.
|
||||
The store no longer changes its own source fetch retroactively.
|
||||
A WAITCNT store uses old settings for its source fetch, then new settings and N for the following fetch.
|
||||
A branch after a load consumes N at the source and still charges the target N+S pair.
|
||||
|
||||
N is an access kind, not always a positive cycle penalty.
|
||||
Some wait settings make N cheaper than S. Tests use independent N/S tables rather than adding a fixed cost.
|
||||
ROM page boundaries can force N independently; a forced boundary and a retained N do not duplicate an access.
|
||||
|
||||
## Original regression coverage
|
||||
|
||||
Instruction-pair tests cover:
|
||||
|
||||
- Supported ARM/Thumb transfer families, block/stack operations, signed loads, swaps, shifts, multiplies, and status operations.
|
||||
- Skipped conditions, zero shift amounts, BL prefixes, and ordinary arithmetic.
|
||||
- Every ROM window and wait setting, both instruction widths, and stored prefetch-bit values.
|
||||
- Repeated transfers, branches after loads, and PC-load refills that restore S.
|
||||
- Timed/untimed equivalence, cloning, failed data accesses, missing current slots, and masked IRQ requests.
|
||||
- DMA and CPU sequence-break composition, IRQ source timing, and handler refill state.
|
||||
- Host and HALT isolation, debugger invalidation, PC mismatches, and page/wait-window crossings.
|
||||
|
||||
Existing rollback, instruction semantics, load data/internal costs, and deferred diagnostics remain unchanged.
|
||||
WAITCNT and DMA tests now distinguish a consumed resume from a new sequence break caused by the completed instruction.
|
||||
|
||||
## Validation and report audit
|
||||
|
||||
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 refill-timing change:
|
||||
|
||||
- ARM nominal cycles increase by 208; Thumb increases by 106; memory increases by 32.
|
||||
Their other report fields remain unchanged.
|
||||
- BIOS executes 963 fewer instructions and steps, with the same final nominal cycle total and all other report fields unchanged.
|
||||
|
||||
An original temporary trace runner compared both core versions against the pinned BIOS fixture.
|
||||
The VBlank polling loop now costs 36 rather than 34 cycles because its load makes the following test instruction fetch N.
|
||||
The updated core executes 321 fewer three-instruction polling loops.
|
||||
IRQ entry moves to another position in the loop; the final checkpoint still has r12=0 and one IRQ entry.
|
||||
This is an audit between our core versions, not external-emulator or hardware timing validation.
|
||||
|
||||
The original timer demo keeps its IRQ step and total duration.
|
||||
Moving store fetch costs to following instructions shifts timer start two cycles earlier.
|
||||
The timer therefore runs two additional cycles before the handler stops it.
|
||||
|
||||
## Remaining limits
|
||||
|
||||
- Cold-start costs and state-changing test/compare quirks are not hardware-validated.
|
||||
- Data timing still uses an instruction-local access trace. This is not a complete bus-event scheduler.
|
||||
- Device clocks still update once per instruction, IRQ entry, or DMA unit.
|
||||
- Game Pak prefetch, configurable EWRAM timing, display contention, and DMA during internal cycles remain unimplemented.
|
||||
- IRQ synchronization delays and complete BIOS/general-bus latch history remain incomplete.
|
||||
|
||||
The next timing work is Game Pak prefetch, with explicit startup and invalidation rules and independent tests.
|
||||
|
|
@ -27,7 +27,8 @@ All programs are original; no external source code or ROM was imported.
|
|||
|
||||
`Cpu::step_timed` captures the address of `Fetched.lookahead` before execution.
|
||||
For a non-refill instruction, it passes that address to `bus_cycles` with the incoming instruction width.
|
||||
The existing instruction summary selects sequential or non-sequential access, with the pending DMA resume override.
|
||||
The later [sequencing extension](fetch-access-sequencing.md) retains the incoming access kind from the preceding instruction.
|
||||
The pending DMA resume still overrides that source access to N.
|
||||
WAITCNT is captured before CPU execution, so a CPU store cannot retroactively change its own fetch cost.
|
||||
|
||||
The same rule applies to cold and retained pipelines.
|
||||
|
|
@ -65,8 +66,8 @@ Timer tests and the original timer demo now reflect this bounded rule.
|
|||
|
||||
The later [refill timing extension](refill-fetch-timing.md) also charges source fetches and target pairs for branches and IRQ entry.
|
||||
|
||||
- Instruction-local S/N summaries remain in use, including the existing store rule.
|
||||
Neighboring instruction/data-access sequencing is not a complete chronological bus trace.
|
||||
- Source S/N kinds now follow the preceding instruction's data/internal work.
|
||||
Data timing and device scheduling still do not form a complete chronological bus trace.
|
||||
- Refills now charge one source fetch plus the target N+S pair, not an additional fetch beside the old destination-only summary.
|
||||
- Thumb BL prefixes use their lookahead address; suffixes add the target pair.
|
||||
- Cold fills have no separate startup charge, even though their samples update supported bus history.
|
||||
|
|
@ -74,7 +75,7 @@ The later [refill timing extension](refill-fetch-timing.md) also charges source
|
|||
- Game Pak prefetch, display contention, configurable EWRAM timing, and sub-instruction DMA arbitration remain unimplemented.
|
||||
|
||||
This is a fetch-address correction within the existing timing model, not cycle-accurate emulation.
|
||||
The next timing step is verified access-kind sequencing between instructions and data accesses.
|
||||
The next timing step is Game Pak prefetch with verified startup and invalidation rules.
|
||||
|
||||
## Original regression coverage
|
||||
|
||||
|
|
|
|||
|
|
@ -78,7 +78,8 @@ A retry takes a new lookahead sample from current memory.
|
|||
|
||||
The later [fetch-address timing extension](fetch-address-timing.md) charges non-refill code at the actual lookahead address.
|
||||
The [refill timing extension](refill-fetch-timing.md) also charges source fetches and target pairs individually.
|
||||
Instruction-local access kinds and cold-start costs remain nominal.
|
||||
The later [sequencing extension](fetch-access-sequencing.md) retains source kinds across CPU data/internal work.
|
||||
Cold-start costs remain nominal.
|
||||
Per-access device updates, video-bus contention, general DMA handoff, and Game Pak prefetch remain incomplete.
|
||||
No boundary timing accuracy is claimed.
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ For an instruction executing at P, `Cpu::step_timed` charges its sampled lookahe
|
|||
|
||||
- ARM source: P+8, word width.
|
||||
- Thumb source: P+4, halfword width.
|
||||
- Access kind: the existing instruction-local summary, overridden to N after successful DMA.
|
||||
- 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.
|
||||
|
|
@ -112,11 +112,11 @@ The stopped counter therefore increases by five even though the final machine-cy
|
|||
|
||||
## Remaining limits
|
||||
|
||||
- Source access kinds still use instruction-local summaries, including the existing store rule.
|
||||
Neighboring instruction/data-access sequencing is not a complete chronological bus trace.
|
||||
- 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.
|
||||
- Game Pak prefetch, per-access device updates, display contention, configurable EWRAM timing, and sub-instruction DMA arbitration remain unimplemented.
|
||||
|
||||
The next timing work is independently verified access-kind sequencing between instructions and data accesses.
|
||||
The next timing work is Game Pak prefetch with verified startup and invalidation rules.
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ Strict instruction reads never use protected BIOS or unused-memory data fallback
|
|||
- All unused-memory data reads within an instruction still use its entry snapshot.
|
||||
- DMA remains scheduled between whole instructions. Sampling does not add an interleaving point.
|
||||
- Non-refill timing now consumes the sample's address in the [fetch-address extension](fetch-address-timing.md).
|
||||
- Refills now charge the source fetch and target pair; instruction-local source access kinds remain nominal.
|
||||
- Refills now charge the source fetch and target pair; the [sequencing extension](fetch-access-sequencing.md) retains incoming source kinds.
|
||||
- Per-access device updates, Game Pak prefetch, and exact refill/arbitration timing remain incomplete.
|
||||
|
||||
## Original tests
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ CPU stores, DMA transfers, and host writes never replace retained instructions a
|
|||
`Cpu::invalidate_pipeline()` explicitly discards retained instructions for debugger repair or attachment to different memory.
|
||||
It does not clear separate BIOS or IWRAM bus history.
|
||||
CPU clones own independent buffers; full CPU equality includes them.
|
||||
The later [sequencing extension](fetch-access-sequencing.md) also retains the next fetch kind in each buffer.
|
||||
|
||||
## Separation from bus history and timing
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ Update this file when a feature lands or a limit is removed.
|
|||
- CPU/device stepping with nominal ARM7 instruction costs and memory wait states.
|
||||
- Code costs use actual ARM PC+8/Thumb PC+4 source fetches and branch/exception target pairs, including region and ROM boundaries.
|
||||
- IRQ entry samples its discarded incoming-state fetch before the ARM vector pair, with local IWRAM history updates.
|
||||
- Persistent fetch access kinds follow CPU data/internal work, compose with DMA resume, and reset after target refills.
|
||||
- Game Pak wait-state control (`WAITCNT`) for all three ROM windows.
|
||||
- Sequential/non-sequential data accesses, branch refill costs, and variable multiply timing.
|
||||
- Optional caller-supplied 16 KiB BIOS mapping, with CPU read protection based on retained ARM PC+8 or aligned Thumb PC+4 words.
|
||||
|
|
@ -114,6 +115,7 @@ Block transfers validate all accesses before committing register, RAM, or I/O ch
|
|||
This diagnostic policy does not reproduce partial transfers during hardware data aborts.
|
||||
CPU instructions, including swaps, finish before a newly requested DMA unit runs. Sub-instruction bus arbitration is not modeled.
|
||||
CPU/bus costs are nominal estimates, not a cycle-accurate implementation.
|
||||
The instruction buffer retains the next fetch kind; cold startup costs and per-access device scheduling remain unmodeled.
|
||||
Graphics support includes Mode 0–5 debug snapshots and HBlank row capture with sprites, mosaic, windows, and color effects.
|
||||
Internal affine origins, vertical window flags, and vertical mosaic counters track line boundaries.
|
||||
Horizontal window comparators retain four-cycle event history.
|
||||
|
|
@ -164,8 +166,8 @@ Writes to cartridge addresses return errors instead of modeling cartridge hardwa
|
|||
Keep unknown history diagnostic until fetch ordering and latch ownership have independent coverage.
|
||||
Validate BIOS snapshots with independent hardware tests before claiming exact refill or data-access history.
|
||||
The desktop runner still uses only the original BIOS. Keep protected reads image-derived for all supplied images.
|
||||
2. Extend instruction-local source access kinds into verified neighboring instruction/data-access sequencing.
|
||||
Add startup costs, Game Pak prefetch, per-access device updates, and timer/IRQ delays.
|
||||
2. Add Game Pak prefetch with verified startup and invalidation rules.
|
||||
Validate cold-start costs, then extend per-access device updates, bus arbitration, and timer/IRQ delays.
|
||||
3. Validate keypad retrigger behavior with hardware tests and add remaining device registers; extend BIOS reset coverage as sound/serial support becomes available.
|
||||
Validate STOP entry/wake edges and add external wake sources and remaining DMA device modes.
|
||||
4. Replace nominal sprite work limits with verified individual fetch timing; add background fetch timing and per-pixel composition.
|
||||
|
|
|
|||
|
|
@ -88,7 +88,8 @@ Timed/untimed tests verify CPU results and nominal clock costs.
|
|||
Host/fetch isolation, separate BIOS history, unsupported stores/data regions, nominal device progression, and DMA diagnostics also have checks.
|
||||
ARM instruction-buffer tests verify retained P+4/P+8 words across CPU stores, DMA transfers, and host writes.
|
||||
They cover refill target pairs, PC writes to fallthrough, conditional branches, ARM/Thumb transitions, exception entry/return, and deferred fetch errors.
|
||||
Full CPU equality checks buffer rollback and cloning. Successful instruction-semantic tests compare architectural state separately.
|
||||
Full CPU equality checks buffer and next-fetch-kind rollback and cloning.
|
||||
Successful instruction-semantic tests compare architectural state separately.
|
||||
Explicit invalidation tests cover debugger repair. Timed/untimed tests verify equal buffers without added nominal cycles.
|
||||
The display-runner error test allows an already buffered branch to complete before the patched unsupported word executes.
|
||||
Thumb instruction-buffer tests verify retained P+2/P+4 halfwords, BL prefix/suffix behavior, and state-tagged target pairs.
|
||||
|
|
@ -259,6 +260,11 @@ Refill timing tests cover incoming/outgoing widths, all ROM wait settings, and t
|
|||
They verify source DMA overrides, split wait-window pairs, missing source/target diagnostics, masked IRQ isolation, and device totals.
|
||||
IRQ history tests verify word/halfword lane updates without invented cold fills or BIOS instruction snapshots.
|
||||
See [refill timing](research/refill-fetch-timing.md) for source evidence and public-report changes.
|
||||
Instruction-pair tests cover following-fetch kinds after transfers, swaps, register shifts, multiplies, status operations, and skipped conditions.
|
||||
They use independent N/S tables across every ROM window and wait setting, including settings where N is cheaper than S.
|
||||
They check timed/untimed equivalence, clones, IRQ/DMA composition, repeated transfers, PC-load refills, failed steps, and cold-start policy.
|
||||
Page/wait-window crossings, masked IRQs, host/HALT isolation, and pre-write WAITCNT settings retain separate checks.
|
||||
See [persistent fetch access kinds](research/fetch-access-sequencing.md) for evidence and public-report changes.
|
||||
Instruction timing tests cover arithmetic, shifts, branches, transfers, block operations, multiply, and exception returns.
|
||||
Timed and untimed execution are compared across all 65,536 Thumb encodings with fixed initial registers.
|
||||
Timer/IRQ tests verify that changing WAITCNT changes when an interrupt is sampled.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue