diff --git a/CHANGELOG.md b/CHANGELOG.md index eaa48397..bb42aabc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,19 @@ cycle-accurate core later replaced. ### Changed +- **MiSTer co-simulation, rung 5 (sibling repository).** The NROM cartridge, the + work RAM, the console's CPU bus, the controller ports and DMC DMA are landed + and gated at **50 gates green**. The DUT's CPU is driven by the RTL bus and a + DMC fetch is a real bus cycle by a second requester — no flat testbench array + in either path. Assembling `nes_top` is what remains, and because that top + level must divide the master clock — the apparatus rung 3's phase calibration + was built on — it is a change to the timing substrate rather than a rewiring, + and is named as its own step. + + **The ladder caught the oracle for the first time**, which is what the + accuracy-ledger entry below records. No `rustynes-*` crate changes, so + AccuracyCoin and nestest are untouched by construction. + - **Dependency and toolchain-adjacent refresh.** 17 crates moved to their newest semver-compatible versions (including `cc` 1.4.3 → 1.4.4 and `log` 0.4.33 → 0.4.34), `directories` 5 → 6, and four GitHub Actions advanced — diff --git a/README.md b/README.md index b8c24aca..003e8bec 100644 --- a/README.md +++ b/README.md @@ -892,11 +892,22 @@ testbench links, plus a `nes_golden_export` CLI emitting golden traces. Progress is a **rung ladder**, and a rung may not open until the one below is green: rung 0 the compare surface, rung 1 the 6502, rung 2 the bus and interrupts, rung 3 the 2C02, rung 4 the 2A03, rung 5 AccuracyCoin parity, rung 6 -hardware bring-up, rung 7 mappers. Rungs 0-3 are closed; rung 4 is the current -work. Every rung is labelled in [`docs/mister.md`](docs/mister.md) by whether it -has an **independent** oracle — because 141/141 on AccuracyCoin is not the same -as "matches silicon", and a rung verified only against this emulator inherits -whatever this emulator has wrong. +hardware bring-up, rung 7 mappers. **Rungs 0-4 are closed; rung 5 is the current +work** — the NROM cartridge, the work RAM, the CPU bus, the controller ports and +DMC DMA are all landed and gated (50 gates green), and assembling the core's own +top level is what remains. Every rung is labelled in +[`docs/mister.md`](docs/mister.md) by whether it has an **independent** oracle — +because 141/141 on AccuracyCoin is not the same as "matches silicon", and a rung +verified only against this emulator inherits whatever this emulator has wrong. + +**Rung 5 has already shown why that caveat is not decorative.** A `cpu_bus` +module written from the wiki disagreed with this emulator at `$6000-$7FFF`: an +NROM board decodes nothing there and reads open bus, while RustyNES allocates +8 KiB of PRG-RAM unconditionally. The wiki names that emulator default as a +problem and lists games that crash on it. **The DUT is the more accurate of the +two**, and the finding is recorded in +[`docs/accuracy-ledger.md`](docs/accuracy-ledger.md) rather than fixed inside a +co-simulation step — it changes shipped behaviour on every iNES NROM cartridge. **The emulation core is unchanged by this line.** Releases in it touch the co-simulation apparatus and the DUT, not the shipped emulator, so AccuracyCoin diff --git a/docs/mister.md b/docs/mister.md index dc50b8d0..0546bdac 100644 --- a/docs/mister.md +++ b/docs/mister.md @@ -764,6 +764,36 @@ Every rung is therefore labelled by whether it has an **independent** oracle: nestest (Nintendulator) and the blargg ROMs do; trace fields with no Mesen2 counterpart do not, and are advisory only. +### It happened, at rung 5 (2026-08-25) + +This stopped being a stated risk and became a measurement. + +`rtl/cpu_bus.sv` was written from `nesdev_wiki/CPU_memory_map.xhtml` and +`Open_bus_behavior.xhtml` and run against this emulator. The two agreed on +`$4016`, `$4017`, `$5000` and `$5C34` — including the open-bus value, which the +DUT *derives* from a latch where the testbench had hardcoded `$40` — and +disagreed only in `$6000-$7FFF`. + +**The DUT was right.** An NROM board decodes nothing there, so the window reads +open bus. `crates/rustynes-mappers/src/m000_nrom.rs` allocates 8 KiB of PRG-RAM +unconditionally so accesses "don't fall off the edge", which is the iNES-era +emulator default the wiki names as a problem in its own words — and it lists +games that break on the WRAM answer, *Low G Man* and *Battletoads & Double +Dragon* among them. + +Three things this establishes, in order of how much they matter: + +1. **The ladder can catch the oracle.** That was asserted when the programme was + planned and is now demonstrated, which is a different kind of claim. +2. **The correct response was to record, not to fix.** Changing it alters + shipped behaviour on every iNES-header NROM cartridge and needs the NES 2.0 + WRAM-size field, the per-game database and the full accuracy battery. It is + in [`accuracy-ledger.md`](accuracy-ledger.md) with its citation. +3. **The gate ROM was narrowed rather than the DUT bent.** `busopen045` reads + `$4020-$5FFF` and not `$6000-$7FFF`, because a gate that fails for the + oracle's limitation rather than the DUT's teaches the wrong lesson and + eventually gets switched off. + ## The two risks that had to be settled before any RTL Both were settled in v2.4.3, and **both were answered by evidence that diff --git a/to-dos/mister/TASKS.md b/to-dos/mister/TASKS.md index 2cd154e7..1208aa55 100644 --- a/to-dos/mister/TASKS.md +++ b/to-dos/mister/TASKS.md @@ -90,11 +90,24 @@ Legend: `[ ]` open · `[~]` in progress · `[x]` done `docs/accuracy-ledger.md` with the wiki citation and the games the wiki names as breaking on it. First time the ladder has caught the oracle; risk 6 in the v2.5.0 plan - - [ ] **DMA is still `tb/cpu_main.cpp`.** On stalled cycles the bus mux is - not the requester, which is also why two mutations are provably inert - today and should flip to CAUGHT when it moves - - [ ] **`rtl/nes_top.sv` is still a shell.** The chips are tied together by - the co-simulation wrapper rather than by the core's own top level + - [x] `rtl/dma.sv` — the documented four-phase DMC sequence, load-bearing. + The byte comes off `cpu_bus` at the DMA's own address, so a DMC fetch is + a real bus cycle by a **second requester**. Two ordering defects found + by side-by-side comparison, in opposite directions: the load delay one + cycle late (non-blocking assignment), then one cycle early (a `$4015` + write landing on an APU phase edge must be armed AND decremented by it) + - [x] `rtl/controller.sv` — and the address mux placed at the CONSOLE level, + not inside the read mux, so the memories see the DMA's address + - [x] **Prediction recorded as WRONG.** The previous step predicted in writing + that two inert open-bus mutations would flip to CAUGHT once DMA drove + the bus. They did not, and a third joined them. The cause is stimulus: + no ROM in the corpus both runs DMC fetches and reads open bus + - [ ] **`rtl/nes_top.sv` is still a shell** — the one remaining piece. Every + part exists and is gated, but they are tied together by the + co-simulation wrapper rather than by the core's own top level, and that + top level must also divide the master clock. That is the apparatus rung + 3's phase calibration was built on, so it is a change to the timing + substrate rather than a rewiring — named as its own step for that reason - [ ] First end-to-end AccuracyCoin run — blocked on the above, and NOT attempted. Producing a status vector is v2.6.3; matching it is v2.6.4 - [ ] v2.6.4 status vector identical **entry-for-entry**, including `Skipped` and