# Wave 2 Mini-Plan: DMAC Channel 2 to GIF to BGCOLOR

This document defines the first Wave 2 implementation target after the
completed Wave 1 milestones and the generated-golden Phase 1 harness.

The target is deliberately narrow:

- establish DMAC as real transfer ownership, not just register plumbing,
- establish GIF as the first programmatic ingress into the GS path,
- produce a visible result through the existing Milestone A video chain.

Working milestone name:

`programmable BGCOLOR via DMA/GIF`

That means:

- software- or testbench-visible programming of DMAC channel 2 intent,
- a minimal packet path into GIF,
- a narrow GIF-to-GS handoff that updates `gs_stub` BGCOLOR,
- visible raster output change through `platform_video_stub`,
- end-to-end traces proving each stage participated.

## Why this path goes first

This is the best next Wave 2 target because it:

- starts from the DMAC contract, which is central PS2 structure,
- keeps the first new ingress path graphics-visible,
- extends Milestone A instead of redoing it,
- avoids pulling in IOP/SIF policy too early,
- sets up a natural bridge into later VIF/VU and broader GIF work.

## Deliverables

The first Wave 2 pass should land:

1. `rtl/dmac/dmac_reg_stub.sv`
2. `rtl/gif_gs/gif_path_stub.sv`
3. one integrated testbench:
   - `sim/tb/integration/tb_bgcolor_via_dma.sv`
4. trace vocabulary additions in:
   - `rtl/debug/trace_pkg.sv`
5. a short README or note in the integration TB directory if one does not
   already exist

## Scope boundary

This plan is not trying to implement:

- generic EE main RAM,
- full DMAC arbitration,
- full GIF decoding,
- any drawing primitive,
- GS VRAM,
- VIF/VU,
- SIF,
- IOP interaction.

The point is to create the smallest correct-shaped programmatic path:

`channel 2 intent -> minimal DMA payload -> minimal GIF packet -> gs_stub BGCOLOR`

## `dmac_reg_stub` exact scope

Status target:

- channel-2-focused, not a pretend full DMAC

### Owns in this phase

- selected DMAC register shell for channel 2,
- channel state machine for a single programmed transfer,
- transfer-start / transfer-active / transfer-done transitions,
- narrow payload handoff into `gif_path_stub`,
- trace events for register writes and transfer lifecycle.

### Explicit non-goals

- multi-channel fairness or arbitration,
- linked-list / chain mode completeness,
- stall/ring semantics,
- interrupt-controller integration beyond trace-visible placeholders,
- memory-backed payload fetch from real EE RAM.

### First-pass data source

For the first integrated proof, allow a testbench-provided or locally-loaded
payload path rather than requiring real main RAM first.

Acceptable phase-1 shapes:

- a tiny internal payload register/FIFO loaded through a narrow debug/test port,
- or a direct payload input interface used only by the integration testbench.

Not acceptable:

- a `dmac_reg_stub` that stops at register writes and never emits payload.

### Recommended channel-2 register surface

Implement only what is needed to express one narrow transfer cleanly.

Suggested first surface:

- `CHCR` for channel 2
  - start bit / direction / mode subset as needed
- `MADR`
  - recorded for trace and future upgrade path
- `QWC`
  - transfer length in 16-byte units
- optional `TADR`
  - only if the implementation wants to reserve chain-mode shape early

Suggested interpretation for first pass:

- one direct transfer mode only
- `QWC == 1` is sufficient for the first visible proof
- `MADR` may be recorded and traced even if the payload is not yet fetched from
  real memory

### Minimal state machine

Recommended states:

- `IDLE`
- `ARMED`
- `ACTIVE`
- `DONE`

Behavior:

- CPU/testbench writes register values
- start condition on `CHCR`
- one payload issued toward `gif_path_stub`
- wait for `gif_path_stub` accept/done handshake
- transition to `DONE`
- optionally clear busy/start-visible state and return to `IDLE`

### `dmac_reg_stub` acceptance criteria

`dmac_reg_stub` is not "done" when registers can be written.

It is done for this phase when:

1. channel 2 can be programmed into a single transfer sequence,
2. it emits a payload/handshake toward `gif_path_stub`,
3. traces show start, active transfer, and done,
4. the integrated testbench proves that this sequence ultimately changes
   `gs_stub` BGCOLOR.

## `gif_path_stub` exact scope

Status target:

- minimal GIF ingress and decode sufficient for BGCOLOR update only

### Owns in this phase

- accepting one narrow DMA-fed packet stream,
- extracting just enough tag/selection information to identify the path,
- decoding only the BGCOLOR-relevant payload form,
- forwarding a GS privileged-register-style write into `gs_stub`,
- trace events for GIF tag and GS-write handoff.

### Explicit non-goals

- PATH arbitration completeness,
- packed register lists beyond what BGCOLOR requires,
- image transfer paths,
- primitive drawing,
- texture or VRAM-visible behavior.

### Recommended first packet shape

Keep the first proof simple and explicit.

Suggested approach:

- a synthetic single-packet format representing:
  - PATH source = channel 2 / GIF
  - destination register = BGCOLOR
  - payload = 24-bit RGB value

This can be encoded as either:

- a tiny project-local "GIF-like" packet for the first integrated proof, or
- a very narrow real GIFtag/register pair if Claude wants to stay closer to the
  real packet model immediately.

My recommendation:

- use a narrow real-looking shape, but only if it stays easy to trace
- otherwise use a project-local packet format and document it clearly as a
  temporary ingress format

### PATH selection

For this phase, hard-scope the path to one source:

- PATH = channel 2 / DMAC GIF path

No arbitration needed yet. Just make the trace name the source explicitly so
future work can preserve the boundary.

### `gif_path_stub` acceptance criteria

1. accepts one payload from `dmac_reg_stub`
2. emits a trace that identifies a GIF-side handoff/tag
3. issues one BGCOLOR update into `gs_stub`
4. integrated testbench sees the new color on the platform video side

## Trace vocabulary additions

Wave 2 needs trace events that express transfer ownership and GIF ingress
without overfitting future behavior.

Recommended additions to `trace_pkg.sv`:

- `EV_DMA_CFG`
- `EV_DMA_START`
- `EV_DMA_BEAT`
- `EV_DMA_DONE`
- `EV_GIFTAG`
- `EV_GS_WRITE`

These names keep the event model readable while leaving room for later detail.

### Recommended payload schemas

#### `DMAC EV_DMA_CFG`

- `arg0 = channel`
- `arg1 = CHCR subset`
- `arg2 = MADR`
- `arg3 = QWC`
- `flags = optional mode bits`

#### `DMAC EV_DMA_START`

- `arg0 = channel`
- `arg1 = qwc`
- `arg2 = payload words/beats planned`
- `arg3 = path id`

#### `DMAC EV_DMA_BEAT`

- `arg0 = channel`
- `arg1 = beat index`
- `arg2 = low payload word or packet id`
- `arg3 = remaining count`

For wide payloads, trace summary over full raw data is acceptable in this phase.

#### `DMAC EV_DMA_DONE`

- `arg0 = channel`
- `arg1 = beats transferred`
- `arg2 = completion code`
- `arg3 = path id`

#### `GIF EV_GIFTAG`

- `arg0 = path source`
- `arg1 = tag summary or local packet type`
- `arg2 = register target`
- `arg3 = payload summary`

#### `GS EV_GS_WRITE`

- `arg0 = register offset`
- `arg1 = write value`
- `arg2 = source id`
- `arg3 = reserved`

### Trace policy note

Do not delete or overload `EV_MODE` / `EV_BGCOLOR`.

Wave 2 should add ingress/transfer visibility, not destroy the simple Wave 1
events that already make debugging easy.

## Integrated testbench shape

Recommended file:

- `sim/tb/integration/tb_bgcolor_via_dma.sv`

This should be the first cross-subsystem Wave 2 harness.

### DUT chain

- `dmac_reg_stub`
- `gif_path_stub`
- `gs_stub`
- `platform_video_stub`
- `trace_sink_stub` instances for at least:
  - DMAC
  - GIF
  - GS
  - PLAT

### Suggested stimulus model

Use a fully controlled synthetic transfer first.

Sequence:

1. reset chain
2. confirm default mid-grey frame behavior
3. configure channel 2 registers
4. provide one payload representing a BGCOLOR update
5. trigger transfer start
6. wait for transfer-done trace/event
7. confirm:
   - GIF saw a tag/payload
   - GS latched the new BGCOLOR
   - platform output changed on active pixels
   - frame event occurred after the color change

### Recommended checks

- one `EV_DMA_CFG`
- one `EV_DMA_START`
- at least one `EV_DMA_BEAT`
- one `EV_DMA_DONE`
- one `EV_GIFTAG`
- one GS-side write event (`EV_GS_WRITE` and/or `EV_BGCOLOR`)
- visible raster color change during active pixels

### Pass criteria

Suggested summary line:

```text
[tb_bgcolor_via_dma] dma_start=1 dma_done=1 giftag=1 gs_write=1 frames=... errors=0
```

A pass requires:

- zero errors
- at least one trace event from each stage
- end-to-end visible color change

## Implementation order inside Wave 2

Recommended order:

1. extend `trace_pkg.sv` with Wave 2 events
2. implement `dmac_reg_stub`
3. implement `gif_path_stub`
4. add integration TB
5. wire `Makefile` target(s)
6. update `sim/README.md`

Rationale:

- event vocabulary first keeps instrumentation coherent
- DMAC first preserves ownership
- GIF second provides the first consumer
- the integration TB defines success better than isolated unit benches here

## Interaction with existing milestones

This work does not replace Wave 1 milestones.

It creates a new intermediate milestone:

`Milestone A+`: visible screen color change driven through DMAC/GIF ownership

That is the right next visible proof before:

- fuller EE work,
- real memory-backed command fetch,
- IOP/SIF bring-up.

## Guardrails

- Do not let `dmac_reg_stub` become a dead-end register shell.
- Do not let `gif_path_stub` accept direct testbench writes that bypass DMAC in
  the integrated proof.
- Do not broaden to generic drawing before the BGCOLOR path is working.
- Do not pull in IOP/SIF just to make Wave 2 feel larger.

## Exit criteria for mini-plan acceptance

This mini-plan is accepted when Claude can implement:

1. a channel-2-focused `dmac_reg_stub`,
2. a narrow `gif_path_stub`,
3. one integrated DMA/GIF/BGCOLOR testbench,
4. with traces proving each stage, not just end-state color.
