Files
retroSoC/docs/ip/apu.md
T

296 KiB

Mini Audio Processing Unit

Purpose and Research Boundary

This document is the authoritative architecture, interface, microcode, software, and verification contract for the retroSoC Mini Audio Processing Unit (APU). The stable feature slug is apu. The current release provides autonomous WAV/PCM and native FLAC decode, fixed-point sample processing, private DMA, direct I2S streaming, and continuous keyword spotting (KWS).

Current-release scope: APU-P6 MP3 decoding is explicitly DEFERRED. The stable Phase 6 ID/title remain as an inactive placeholder; Phase 7 proceeds from the reviewed Phase 5 baseline and Phase 8 does not require Phase 6 completion. The retained P6 design/reference sections are historical, non-normative notes for a future refreeze. They do not enable MP3 or require MP3 dependencies, three-active-codec packing, PSNR or MP3 real-time evidence in this release. This scope rule takes precedence over those deferred notes. All other active WAV/FLAC, KWS, transport, ABI, ownership and physical-evidence requirements remain in force.

APU-P7 is refrozen on 2026-09-11 by the P7 sections below. They fix the reference inputs, APUM 1.0 wire format, numerical profile, capture settings, HAL and acceptance rules; they do not assert that P7 is implemented. The starting implementation for that freeze was reviewed P5 with CAPABILITY0=0x000001bd. Completed pre-P9 KWS qualification permits 0x000001fd. No P6 work is reactivated.

The 2026-09-24 APU-P9 macro-backed storage refreeze supersedes the physical ROM representation and inferred loader-memo implementation, not their numerical or proof semantics. Its objective is to remove large synthesis-inferred memories, prioritizing additional physical SRAM macros, then additional bounded processing cycles. It does not shrink the advertised model/workspace capacity or weaken real-time/accuracy requirements. P9 introduces a separately loaded APUC coefficient image and additive APB V1.2 discovery/control; APUM 1.0, APUMC V1/V2 and the job descriptor remain unchanged. The detailed P9 contract below takes precedence for the post-P9 release; earlier phase identities and their historical discovery values remain valid for those earlier profiles. This refreeze is a future implementation contract, not a synthesis/PPA result.

The APU is deliberately coreless. LP loads one validated codec-microcode bundle at startup and HP or LP later submits jobs. The APU contains a bounded codec sequencer and fixed processing engines; it does not contain Hazard3, VexiiRiscv, a DSP CPU, a general-purpose instruction set, or a C runtime.

The design was frozen on 2026-09-02 from these repository sources of truth:

  • rtl/mini/address_map/memory_map.json for the reserved APB4_APU window;
  • rtl/mini/integration/soc_topology.json for APB4, IRQ, resource, and data integration;
  • rtl/mini/integration/clock_reset_domains.json for clock/reset and CDC/RDC;
  • docs/lp-hp-architecture.md, docs/axi4-interconnect.md, and docs/axi4-stream.md for the control, memory, and stream planes;
  • docs/ip/dma.md, docs/ip/i2s.md, docs/ip/jpeg.md, docs/ip/xpi.md, and docs/ip/resource-controller.md for DMA, stream, fixed-pipeline, programmable-LUT, and lifecycle patterns; and
  • dependencies/dependencies.lock.json for managed inputs.

APU-P2 implements the private AXI4 DMA, descriptor ring scheduler, fair Gateway A arbitration, and the production audio stream router with two 64-word Common FIFOs. The shell reports only private-DMA and ring capabilities; public direct start, ring doorbell, and APU stream routes remain fail-closed until their later-phase engines exist. No claim is made that microcode, sequencer, codec engines, KWS, codec conformance, Linux driver, timing closure, power closure, CDC/RDC signoff, or silicon qualification exists.

Commercial References

The selected design uses public architectural lessons and does not reproduce proprietary decoder RTL or microcode.

Reference Relevant behavior and status Reuse boundary Avoided boundary
Cadence Tensilica HiFi DSP family Current programmable audio/voice IP with codec, bitstream, SIMD, and AI support. Keep codec behavior updateable and separate scalar control from fixed arithmetic. Do not import a DSP core, proprietary ISA/toolchain, floating point, or vendor PPA claims.
Ceva-BX1 Current compact controller/DSP with MACs, queue management, accelerator ports, and light-AI support. Use bounded queues and explicit accelerator commands. Do not instantiate a controller core or project 7 nm frequency/GMAC data onto Mini.
NXP FlexSPI Active programmable command-LUT controller with distinct mapped and indirect data paths. Reuse the model of host-loaded, validated sequences executed by a hardware sequencer. A serial-memory phase LUT is much simpler than audio parsing; its eight-instruction scale is not reused.
CAST H264-D-BP Current standalone streaming decoder IP with zero host decode overhead, errors, bit-accurate model, and AXI wrappers. Reuse autonomous decode, flow-controlled streams, explicit errors, and independent BAM delivery. Video codec gates, memory, throughput, and PPA are not Audio/Mini evidence.
AMD Audio Formatter Maintained AXI4 memory/stream audio mover with DMA, completion/error interrupts, timeout, and graceful halt. Reuse independent memory/stream paths, bounded halt, and period/error observability. It formats PCM/AES audio and is not a compressed-file decoder.
MP3 hardware/software co-design A programmable parser controls dedicated IMDCT/filterbank hardware, showing the split between irregular bitstream control and regular arithmetic. Implement irregular parsing in bounded microcode and regular kernels in fixed engines. Its process, area, frequency, and embedded parser processor are not reused.
RFC 9639 FLAC Current standards-track FLAC definition; decode uses integer bit parsing, Rice residuals, fixed/LPC prediction, and channel decorrelation. Implement the native streamable decoder using integer primitives and bounded history. Ogg/Matroska/MP4 mappings and the full 1..8-channel standard are outside MVP.
MLPerf Tiny KWS Reproducible 49 by 10 INT8 MFCC/DS-CNN workload with 12 classes and a 90 percent quality threshold. Use its operator set, corpus, accuracy threshold, and reproducibility rules. Do not claim an MLPerf result unless the applicable runner and reporting rules are followed exactly.

The selected pattern is bounded microcode plus fixed decoder primitives. A general-purpose processor is not retained as normative behavior. Separate per-format RTL is also not selected because it would duplicate bitstream, entropy, arithmetic, DMA, and recovery logic and make fixes silicon changes.

Requirements and Non-goals

MVP requirements

ID Requirement
APU-MVP-001 The APU MUST expose APB4 configuration at the reserved APB4_APU window 0x1001_3000..0x1001_3fff.
APU-MVP-002 The APU MUST use a private 32-bit AXI4 DMA master for microcode, model, descriptors, compressed input, and optional PCM output.
APU-MVP-003 The APU MUST expose 32-bit AXI4-Stream PCM input and output integrated with existing I2S RX/TX streams.
APU-MVP-004 WAV/PCM and native FLAC decode MUST execute entirely in the coreless APU. MP3 decoding is deferred and MUST NOT be advertised by this release.
APU-MVP-005 LP MUST load one bundle containing exactly three entry descriptors: active WAV and FLAC entries plus the existing unsupported-MP3 trap stub. Successful load MUST lock microcode until hard reset.
APU-MVP-006 The codec sequencer MUST execute only the bounded V1 microcode ISA and MUST NOT execute RV32, C, ELF, or arbitrary system-memory instructions.
APU-MVP-007 Continuous 16 kHz mono KWS MUST use an independent fixed MFCC/INT8 DS-CNN engine and MUST run concurrently with decode.
APU-MVP-008 DMA, sequencer, primitive, stream, resampler, and KWS work MUST have timeout, abort, first-error, and recovery behavior.
APU-MVP-009 Microcode, KWS model, descriptors, tables, and buffers MUST use versioned, bounds-checked formats with no dynamic allocation.
APU-MVP-010 The APU MUST integrate as Resource Controller index 7 and route its interrupt exclusively to LP IRQ31 or HP PLIC source 10 according to owner.
APU-MVP-011 Hardware/software register, descriptor, microcode, and model definitions MUST remain independently handwritten and pass parity tests; no register generator is allowed.
APU-MVP-012 Compatible Common APB4, AXI4, AXI4-Stream, register, FIFO, round-robin, synchronizer, and warm-flush CDC components MUST be reused.
APU-MVP-013 LP/HP host software MUST remain freestanding at SDK boundaries and MUST NOT introduce hosted I/O, malloc, or free.

Target requirements

  • Sequencer, primitive engines, KWS, SRAM banks, and DMA MUST be independently clock-gateable when idle, subject to later physical implementation evidence.
  • Microcode capacity, arithmetic lane count, SRAM bank geometry, and internal pipelines MUST remain outside the public job/HAL ABI.
  • Every normal completion, rejection, timeout, trap, xrun, handoff, and reset MUST be diagnosable without a waveform.
  • A commercial release MUST add full conformance, reusable VIP, coverage, CDC/RDC, DFT/MBIST, PVT/MMMC, power, post-layout, and silicon evidence.

Deferred work and non-goals

The following work is DEFERRED outside the active implementation phases of this release and MUST NOT be silently inserted into an MVP phase:

  • APU-P6 MPEG-1/2/2.5 Layer III MP3 decoding, its production microprogram, reference/corpus setup, three-active-codec packing, PSNR and MP3 real-time qualification; the Phase 6 slot remains reserved for an explicit future refreeze and is not a release blocker;
  • AAC, HE-AAC, Opus, Vorbis, Ogg-FLAC, ALAC, WMA, Dolby, DTS, LC3, or any format beyond the three frozen entry points;
  • encoding, transcoding, MPEG Layer I/II, more than two channels, object audio, TDM, PDM, beamforming, AEC, or ANC;
  • a general-purpose processor, DSP core, arbitrary microcode compiler, C/ELF execution, runtime code download per job, or HP software decode fallback;
  • hardware cache coherency, IOMMU, virtual contexts, preemption, or more than one active decode job;
  • an independent retained KWS power island, PCLK-independent cold wake, DVFS, or quantified always-on power claim;
  • microcode/model signatures, secure boot, encryption, anti-rollback, DRM, or protected-content claims;
  • ECC, repair, or production MBIST for APU SRAM; and
  • a generic NPU or arbitrary TFLite/ONNX operator runtime.

Selected Architecture

Module hierarchy

apb4_apu
  apu_reg
  apu_microcode_loader
    apu_proof_memo          (P9: 16 key SRAMs + one valid-bitmap SRAM)
  apu_job_scheduler
  apu_dma
  apu_codec_sequencer
    apu_control_store       (4096 x 64, 32 KiB from the P5 capacity refreeze)
    apu_scalar_registers    (16 x 32)
    apu_loop_stack
  apu_bitstream_engine
  apu_entropy_engine
  apu_reconstruction_engine
  apu_transform_engine
  apu_resampler
  apu_local_sram            (112 KiB)
  apu_kws_frontend
  apu_kws_engine
  apu_kws_coeff_loader     (P9: LP-controlled APUC DMA/CRC/readback/lock)
  apu_kws_coeff_store      (P9: 15 coefficient/profile SRAMs)
  apu_stream_router

There is no CPU inside this hierarchy. apu_codec_sequencer cannot issue a system load/store, execute from AXI memory, address APB4, take a CPU interrupt, or run a compiler-generated program. It fetches one validated 64-bit control word per cycle from local control store and orchestrates fixed engines.

From the P5 capacity refreeze, total image/data storage is 144 KiB instead of the earlier 128 KiB target. P3/P4 implemented capacities remain as reported in their capability profiles:

Region Capacity Use
control store 32 KiB 4096 64-bit instructions containing codec programs and common subroutines; P3/P4 retain 2048 words / 16 KiB.
codec table/scratch 24 KiB Huffman tables, MP3 reservoir/coefficient state, FLAC predictor/Rice state
compressed/PCM staging 16 KiB input and output DMA/stream buffers
KWS 64 KiB model weights, 49 by 10 history, and tiled activations
common/result reserve 8 KiB descriptors, counters, CRC, and bounded temporary state

The regions are statically partitioned. Software discovers capacities through capability registers but never physical bank count. The implementation uses existing 4 KiB technology SRAM abstractions and records the actual macro map in PPA evidence.

P9 retains these 144 KiB advertised regions. Auxiliary physical storage adds 32 KiB of existing verifier path stack, 68 KiB of macro-backed memo/valid storage and 60 KiB of coefficients/profile constants: 304 KiB / 76 logical 4 KiB wrappers in the full macro-backed P9 APU. These auxiliary bytes are not new APUM scratch, codec-addressable SRAM or system memory windows.

Fixed engines

  • Bitstream engine: 64-bit refill reservoir, 1..32-bit peek/get/skip, byte alignment, frame sync, CRC8, and CRC16.
  • Entropy engine: table-driven MP3 Huffman pair/quad, canonical symbol decode, unary scan, Rice/Rice2 remainder, sign restoration, and bounded table index.
  • Reconstruction engine: four initial 32x32-to-64 fixed-point MAC lanes, rounding, shifts, saturation, MP3 requant/stereo, and FLAC fixed/LPC order 0..32 plus channel decorrelation. Lane count is implementation-private.
  • Transform engine: MP3 IMDCT6/18, DCT32/polyphase synthesis, overlap/history, and fixed coefficient-table access.
  • Resampler/packer: deterministic fixed-point polyphase conversion, volume, downmix, S16/S24 saturation, memory packing, and I2S packing.

The sequencer issues a kernel command and either continues independent scalar work or waits for completion. Each kernel has a specified maximum latency and cannot access outside its assigned local-memory range.

Previously delivered P4 primitives remain implemented and tested even where their names or research rationale mention MP3. Their presence does not enable format ID 1. Deferring MP3 does not remove these engines, shrink the 4096-word control store or 112 KiB data store, or change the P5 instruction/transport ABI.

Independent KWS

I2S RX feeds a dedicated KWS input FIFO, mono/downmix, 16 kHz resampling, 512-point fixed FFT/MFCC, and a 16-lane INT8/INT32 DS-CNN engine. Supported operators are Conv2D, depthwise 3 by 3, pointwise 1 by 1, bias, requantization/ReLU, the pinned 25 by 5 average pool, fully connected, and INT8 Softmax. The source model's shape-only reshape is folded by the converter.

KWS evaluates a 49 by 10 INT8 window every 100 ms. Score threshold and 1..255 consecutive-hit debounce are programmable. KWS does not use codec microcode or codec MAC lanes, so it remains live during file decode. Only SRAM arbitration, PCLK, stream routing, IRQ collection, and lifecycle control are shared.

Control and data flow

  1. LP programs read/write ACLs and the APUMC bundle address/size/CRC.
  2. Private DMA loads the WAV/FLAC bundle with the retained MP3 trap entry. Hardware and the offline verifier validate header, capabilities, control flow, ranges, loop bounds, tables, and CRC before publishing valid.
  3. Successful load automatically sets a hard-reset-cleared microcode lock. HP cannot load or replace microcode.
  4. LP similarly loads and locks one APUM KWS model, then may hand APU ownership to HP.
  5. The owner submits a direct job or advances a descriptor ring. The scheduler selects the frozen codec entry, fetches compressed input, and starts the sequencer.
  6. PCM is written to memory or emitted through AXI4-Stream to I2S TX. Progress advances only after successful AXI responses or stream handshakes.
  7. Concurrent I2S RX KWS maintains its own FIFO and model context. Stable KWS hits and codec/DMA events enter the aggregate sticky interrupt state.

There is one active decode job plus continuous KWS. Accepted AXI4 or AXI4-Stream transfers are never withdrawn. Decode abort stops new work, drains accepted traffic, terminates the sequencer, and flushes local codec state only after drain.

Interfaces

APB4 configuration

The APU is a 32-bit APB4 slave at 0x1001_3000..0x1001_3fff. Registers are naturally aligned and follow the repository setup/access and response-retention contract.

  • Reads have no side effects except explicit snapshot results.
  • RW registers honor byte strobes. Commands, addresses, sizes, CRCs, ring control, and portals require PSTRB=4'hf.
  • Unaligned/unmapped accesses, unsupported strobes, invalid direction, active-configuration writes, or illegal commands complete with PSLVERR.
  • Configuration is latched on job start or KWS enable.
  • Command bits are pulses, not stored levels.

Private AXI4 DMA

The APU provides one PCLK-domain 32-bit AXI4 master with 32-bit addresses, one-bit ID/user, and ID zero. It occupies the unused third input of I/O Gateway A and uses the existing PCLK-to-HP axi4_async_bridge and 32-to-64 upsizer. It retains global data-master identity 3; the nine-master crossbar and seven-bit global ID width preserve that identity.

Gateway A MUST replace its fixed-priority selection with a burst-boundary Common round-robin arbiter among APU, SDIO0, and USB2. Ownership is retained through terminal B or RLAST; a continuously eligible source cannot starve while downstream traffic completes.

DMA behavior:

  • one internal read and one internal write transaction may be active, although the shared gateway may serialize addresses;
  • aligned 4-byte addresses, arbitrary nonzero byte counts, and partial final write strobes;
  • 1..16-beat INCR bursts that never cross 4 KiB;
  • 64-byte-aligned microcode/model images and 128-byte-aligned descriptors;
  • AxCACHE=0, data-only attributes, and no executable system-memory access;
  • reads from SRAM, SDRAM, QPI, OPI, or XPI; writes to SRAM, SDRAM, QPI, or OPI;
  • inclusive local read/write base/limit ACLs, with reset denying all access;
  • SLVERR, DECERR, bad ID, malformed RLAST, ACL overflow, timeout, or bridge flush recorded against the active load/job; and
  • abort blocks new addresses, drains accepted responses, then discards local in-flight codec data.

The DMA no-progress timer runs only while an AXI request is presented or an accepted AXI read/write/descriptor transaction is outstanding. A handshake on AW, W, B, AR, or R is progress and reloads the full nonzero DMA_TIMEOUT value. Merely holding VALID, moving data between local FIFOs, or waiting on a codec/stream endpoint is not DMA progress. The first cycle with an unaccepted address/data VALID or an accepted transaction starts the epoch. Expiry blocks new AXI addresses, records error 17 against the owning direction and address, and drains any accepted transaction before terminal completion. The timer stops when no AXI request or response is pending and clears on abort, soft reset, resource reset, or hard reset.

Gateway A has one fabric identity, so local first-error and per-client counters are required for attribution. Handoff conservatively waits for APU, USB2, and SDIO0 gateway traffic to become idle.

AXI4-Stream

The APU input/output use 32-bit axi4_stream_if in PCLK with ID/destination/ user zero and TKEEP/TSTRB=4'hf.

  • S16 stereo packs the earlier sample in [15:0] and later sample in [31:16], matching I2S.
  • S24 uses one signed sample in [23:0] and sign extension in [31:24].
  • Mono playback is duplicated to I2S left/right; mono memory output remains mono.
  • Payload and sidebands remain stable under backpressure.
  • TLAST marks the final PCM word of a finite decode job; continuous KWS does not depend on TLAST.

TX producer and RX consumer are selected independently. Reset preserves the existing central-DMA route. APU mode selects APU-to-I2S TX and I2S RX-to-KWS, which may operate concurrently. Active-direction route changes are rejected. No external pad is added; I2S retains audio-clock-domain sampling and CDC.

Phase 2 implements and verifies the production stream router and two 64-word Common FIFOs through a test-only wrapper, but it has no production APU PCM producer or KWS consumer. Consequently, in the SoC integration through Phase 2, CAPABILITY0.STREAMS remains zero and any STREAM_ROUTE direction value 1 returns PSLVERR. Reset value 0 continues to select central DMA. The test-only wrapper is in the verification filelist only, drives the production FIFO/router interfaces directly, and creates no register, descriptor operation, capability, or synthesized diagnostic path. TX value 1 becomes legal only when the first codec stream producer is delivered; RX value 1 becomes legal only with KWS.

A TX direction is active when its route is APU and at least one of the endpoint session-active input, a nonempty TX FIFO, or an asserted unaccepted output TVALID is true. An RX direction is active when its route is APU and at least one of the endpoint session-active input, a nonempty RX FIFO, or an accepted but unretired input beat is true. A STREAM_ROUTE write that changes one direction returns PSLVERR while that direction is active; changing only the inactive direction or rewriting the same value is legal. Phase-2 production endpoint session-active inputs are tied low.

STREAM_WATERMARK programs an RX/input high watermark in bits [7:0] and a TX/output low watermark in bits [15:8]; [31:16] are reserved zero. Each value is 0 (disabled) or 1..64 words. The input event occurs on an occupancy crossing from below to greater-than-or-equal-to its threshold and rearms below the threshold. The output event occurs on a crossing from above to less-than-or-equal-to its threshold while TX is active and rearms above it. The events set sticky IRQ bits 6 and 7. Setting a threshold to zero disables future events and resets its crossing detector but does not clear an already sticky IRQ; software clears that through IRQ_STATE. Hardware set wins a same-cycle W1C.

DMA and Interrupt Contract

Direct and ring operation

Direct mode uses JOB_* registers. Ring mode uses 2..256 power-of-two entries. Each descriptor is exactly 128 bytes and 128-byte aligned. Head is hardware owned; tail is software owned.

Software writes payload, sets OWN last, executes fence rw,rw, advances tail, and rings the doorbell. Hardware fetches only owned descriptors, writes all results, clears OWN, advances head, then raises completion. An unowned head stalls without consumption. An invalid owned entry completes with error and advances head; stop-on-error prevents the next fetch. IOC overrides coalescing.

Phase 2 does not add a public diagnostic operation and does not make decode or KWS executable. Because every public operation depends on later phases, START_DIRECT and RING_DOORBELL continue to return PSLVERR until valid locked microcode and the selected format/KWS capability are both present. Phase-2 verification instead instantiates the production DMA and ring scheduler behind a verification-only backend. The backend drives the internal transport request/completion interface, exercises memory-to-memory direct transfers, fetches public 128-byte descriptors, supplies deterministic result writeback, and tests OWN-last, unowned stalls, invalid-owned completion, wrap, coalescing, abort, and every bus error. It is excluded from behavioral/synthesis product filelists and has no public opcode or runtime path. Thus successful P2 direct/ring verification does not pull microcode, primitives, codecs, or KWS forward.

For non-IOC completions, an internal pending-completion count increments after descriptor result writeback and OWN clear. A zero-to-one transition starts a coalescing timeout epoch loaded from RING_COALESCE[31:16]; the timer decrements once per PCLK cycle. A ring event is generated when the post-completion pending count reaches RING_COALESCE[7:0] or the timer expires with a nonzero count. Either event clears the pending count and stops the epoch. An IOC completion immediately generates one ring event covering the IOC descriptor and all prior pending completions, then clears the count/epoch regardless of the programmed threshold. IRQ W1C does not reset or rearm the count/timer. Ring disable, abort, soft/resource/hard reset, or stop-on-error terminal writeback clears the pending count and timer. Both coalescing fields remain nonzero as already required by the P1 ABI. If an error descriptor also has IOC, its terminal writeback first generates the IOC ring event covering pending completions, then stop-on-error halts and clears the coalescing state; the error IRQ is collected independently.

Descriptor ABI

Word Field Direction and meaning
0 CONTROL SW to HW: operation [3:0], input format [7:4], output mode [9:8], downmix 10, resample 11, IOC 30, OWN 31.
1 RESULT_STATUS HW to SW: done 0, error 1, aborted 2, error code [8:3], stage [12:9], AXI response [14:13].
2 INPUT_ADDRESS Aligned compressed-file or diagnostic PCM source.
3 INPUT_LENGTH Nonzero source bytes.
4 OUTPUT_ADDRESS Aligned PCM destination for decode; zero for stream output or operation1.
5 OUTPUT_CAPACITY Destination bytes for decode; zero for stream output or operation1.
6 INPUT_CONFIG Expected rate [16:0], channels [18:17], source bits/sample [25:20]; zero fields mean derive.
7 OUTPUT_CONFIG Rate [16:0], channels [18:17], PCM format [20:19].
8 JOB_FLAGS Strict decode bit 0; all other V1 bits zero.
9 KWS_CONFIG Memory-window threshold [7:0], debounce [15:8]; zero for decode.
10 RESULT_INPUT_USED Bytes consumed.
11 RESULT_OUTPUT_BYTES PCM bytes written or streamed.
12 RESULT_FRAMES PCM sample frames produced by decode; input sample frames consumed by operation1.
13 RESULT_SOURCE_INFO Detected rate [16:0], channels [18:17], bits/sample [24:19].
14 RESULT_CYCLES Saturating job cycle count.
15 RESULT_DETAIL Format-, microcode-, or primitive-specific diagnostic.
16-17 COOKIE Opaque 64-bit value preserved.
18-19 START_TIMESTAMP 64-bit PCLK cycle timestamp.
20-21 FINISH_TIMESTAMP 64-bit PCLK cycle timestamp.
22 KWS_RESULT Class [7:0], score [15:8], hit 16 for memory-window operation.
23 MICROCODE_BUILD_ID Low 32 bits of the loaded APUMC build ID.
24-31 Reserved Software writes zero; hardware writes/preserves zero.

Operation 0 is file decode and operation 1 is one KWS memory window. Input format 0 is WAV/PCM, 1 MP3 Layer III, and 2 native FLAC. Output mode 0 is memory and 1 is I2S stream. PCM format 0 is interleaved S16_LE and 1 is S24_32LE. All other V1 encodings fail validation.

Format ID 1 remains allocated for compatibility but MP3 decode (operation 0, format 1) is unsupported throughout this release, including after P7 KWS is enabled. RS_APU_MP3 remains declared and HAL decode/submission returns RS_ENOTSUP for it. A raw direct start returns PSLVERR without payload DMA or result mutation; an owned ring entry completes code 3/stage 2/detail 0x01000001 at its CONTROL address and follows existing writeback/OWN-clear rules. This does not defer KWS operation 1. No host MP3 fallback is allowed. MP3 format ID 1, capability bit 1, and format-1 parser-detail reasons 0x0100..0x0140 remain reserved for future MP3 reactivation and may not be reassigned. Those deferred parser details are not emitted in this release; the existing unsupported result/stub detail 0x01000001 is unchanged.

Interrupts

Bit Sticky event
0 direct job done
1 ring/coalescing event
2 stable KWS hit
3 microcode load done
4 model load done
5 abort done
6 input watermark
7 output watermark
8 first error
9 stream underrun/overrun
10 sequencer trap/watchdog
11 P9 coefficient-load terminal completion; inspect KWS_COEFF_STATUS for success/failure.
12-31 reserved

IRQ_ENABLE gates delivery, not collection. IRQ_TEST sets implemented state only. IRQ_STATE is W1C; hardware set wins a simultaneous clear. irq_o is the OR of enabled sticky state. Bit 11 is implemented only with the P9 coefficient interface; earlier profiles retain mask 0x000007ff and reject it. The P9 mask is 0x00000fff; LP/HP interrupt routes and existing bit meanings do not change.

The APU is Resource Controller index 7. LP owner routes to APB-peripheral group bit23 and Hazard3 IRQ31. HP owner suppresses LP delivery and routes to HP PLIC source10. Reset masks both. Hardware never delivers one event to both owners.

Register and Software ABI

Register map

Unlisted offsets are reserved and return PSLVERR.

Offset Register Access Reset Contract
0x000 IP_ID RO 0x41505530 ASCII APU0.
0x004 IP_VERSION RO implementation APB V1.0 0x00010000 for P1..P4 and pre-expansion P5; expanded pre-P9 profiles use V1.1 0x00010001; P9 coefficient-interface profiles use V1.2 0x00010002.
0x008 CAPABILITY0 RO implementation Bits 0..2 WAV/MP3/FLAC, 3 private DMA, 4 ring, 5 streams, 6 KWS, 7 sequencer, 8 resampler; P9 appends coefficient-load interface bit 9. P1 0; P2 0x18; P3 0x98; P4 0x198; P5 0x1bd; qualified pre-P9 KWS 0x1fd; qualified P9 0x3fd. MP3 bit 1 remains zero.
0x00c CAPABILITY1 RO implementation Control-store KiB [7:0], data SRAM KiB [15:8], max channels [17:16], max source-rate kHz [25:18]; P1/P2 are 0; P3 is 0x00000010; P4 is 0x01827010; expanded P5 onward is 0x01827020 (32/112/2/96).
0x010 COMMAND WO 0 Start-direct 0, abort 1, soft-reset 2, ring-kick 3, microcode-load 4, model-load 5, clear-counters 6.
0x014 STATUS RO 0x00000100 Microcode valid 0, model valid 1, busy 2, ring 3, decode 4, KWS listening 5, quiesced 6, aborting 7, idle 8, sequencer trapped 9.
0x018 IRQ_STATE RW1C 0 Sticky events.
0x01c IRQ_ENABLE RW 0 Event enables.
0x020 IRQ_TEST WO 0 Software event injection.
0x024 ERROR_STATUS RW1C 0 Valid 0/W1C, code [6:1], stage [10:7], AXI response [12:11], descriptor index [20:13].
0x028 ERROR_ADDRESS RO 0 First failing AXI/local/PC address.
0x02c ERROR_DETAIL RO 0 First format/opcode/primitive/model diagnostic.
0x030 SEQUENCER_TIMEOUT RW idle 0x0000ffff Nonzero maximum no-retirement cycles.
0x034 STREAM_ROUTE RW idle 0 TX [1:0]: DMA0/APU1; RX [3:2]: DMA0/APU1.
0x038 STREAM_STATUS RO P1 0, P2+ 0x00000014 Frozen live/sticky allocation below.
0x03c OWNER_STATUS RO 0 Resource owner [1:0], owner lock 8, quiesce 9, reset request 10.
0x040 READ_BASE RW idle/LP 0xffffffff Inclusive local DMA read base.
0x044 READ_LIMIT RW idle/LP 0 Base greater than limit denies all.
0x048 WRITE_BASE RW idle/LP 0xffffffff Inclusive local DMA write base.
0x04c WRITE_LIMIT RW idle/LP 0 Inclusive write limit.
0x050 DMA_TIMEOUT RW idle 0x0000ffff Nonzero no-progress timeout.
0x054 ABI_DIGEST RO 0 until MVP CRC32 digest over the complete frozen V1 tables; partial P1..P7 implementations report zero.
0x058 SEQUENCER_STATUS RO 0 PC low [10:0], class [14:11], opcode [18:15], wait 19, loop-active 20; APB V1.1 appends PC bit 11 at bit 21.
0x05c SEQUENCER_RETIRED RO 0 Saturating instructions retired in current frame/block.
0x060 STREAM_WATERMARK RW idle 0 RX/input high [7:0], TX/output low [15:8], reserved [31:16]=0; zero disables, otherwise 1..64. Added in P2.
0x080 MC_IMAGE_ADDRESS RW idle/LP 0 64-byte-aligned APUMC address.
0x084 MC_IMAGE_SIZE RW idle/LP 0 Exact nonzero bundle bytes.
0x088 MC_EXPECTED_CRC RW idle/LP 0 Expected payload CRC32, equal to header.
0x08c MC_STATUS RO 0 Busy 0, valid 1, header error 2, range error 3, control-flow error 4, table error 5, CRC error 6, capability error 7; [31:8] reserved zero.
0x090 MC_ABI RO 0 Loaded APUMC/ISA version: V1.0 0x00010000 or V2.0 0x00020000, according to the validated image. Independent of APB IP_VERSION.
0x094 MC_BUILD_ID_LO RO 0 Build ID low.
0x098 MC_BUILD_ID_HI RO 0 Build ID high.
0x09c MC_LOCK RO 0 Lock bit 0 sets automatically after successful load; [31:1] reserved zero; hard reset clears.
0x0a0 MC_ACTUAL_CRC RO 0 Observed microcode payload CRC32.
0x0a4 MC_LOAD_COUNT RO 0 Saturating successful-load count.
0x100 JOB_CONTROL RW idle 0 Descriptor word0 operation/format/output/downmix/resample without OWN/IOC.
0x104 JOB_INPUT_ADDRESS RW idle 0 Direct input address.
0x108 JOB_INPUT_LENGTH RW idle 0 Direct input bytes.
0x10c JOB_OUTPUT_ADDRESS RW idle 0 Direct output address.
0x110 JOB_OUTPUT_CAPACITY RW idle 0 Direct output capacity.
0x114 JOB_INPUT_CONFIG RW idle 0 Descriptor word6.
0x118 JOB_OUTPUT_CONFIG RW idle 0 Descriptor word7.
0x11c JOB_FLAGS RW idle 0 Descriptor word8.
0x120 JOB_STATUS RO 0 Frozen live/sticky allocation below.
0x124 JOB_INPUT_USED RO 0 Result input bytes.
0x128 JOB_OUTPUT_BYTES RO 0 Result output bytes.
0x12c JOB_FRAMES RO 0 Result PCM frames.
0x130 JOB_SOURCE_INFO RO 0 Detected source geometry.
0x134 JOB_CYCLES RO 0 Saturating job cycles.
0x138 JOB_DETAIL RO 0 Diagnostic detail.
0x180 RING_BASE RW idle 0 128-byte-aligned descriptor base.
0x184 RING_SIZE RW idle 0 2..256 entries, power of two.
0x188 RING_HEAD RO 0 Hardware index.
0x18c RING_TAIL RW 0 Software index.
0x190 RING_CONTROL RW idle 0 Enable 0, stop-on-error 1.
0x194 RING_STATUS RO P1 0, P2+ 0x00000004 Frozen live/sticky allocation below.
0x198 RING_COMPLETED RO 0 Saturating completion count.
0x19c RING_COALESCE RW idle 0x00010001 Count [7:0], nonzero timeout [31:16].
0x1a0 RING_DOORBELL WO 0 Write one to rescan.
0x200 KWS_MODEL_ADDRESS RW idle/LP 0 64-byte-aligned APUM address.
0x204 KWS_MODEL_SIZE RW idle/LP 0 Exact model bytes.
0x208 KWS_MODEL_EXPECTED_CRC RW idle/LP 0 Expected payload CRC32.
0x20c KWS_CONTROL RW idle 0 Enable 0, memory-window 1, clear-history pulse 2.
0x210 KWS_CONFIG RW idle 0x00000380 Threshold [7:0] 128, debounce [15:8] 3.
0x214 KWS_STATUS RO 0 Listening, inference busy, history full, hit, overrun, model valid/locked.
0x218 KWS_RESULT RO 0 Class [7:0], score [15:8], stable hit 16.
0x21c KWS_TIMESTAMP_LO RO 0 Detection timestamp low.
0x220 KWS_TIMESTAMP_HI RO 0 Detection timestamp high.
0x224 KWS_FRAME_COUNT RO 0 Accepted feature frames.
0x228 KWS_INFERENCE_COUNT RO 0 Completed inferences.
0x22c KWS_HIT_COUNT RO 0 Stable hits.
0x230 KWS_OVERRUN_COUNT RO 0 Dropped/late windows.
0x234 KWS_MODEL_STATUS RO 0 Busy, valid/lock, header/range/size/CRC/operator errors.
0x238 KWS_MODEL_ACTUAL_CRC RO 0 Observed payload CRC32.
0x23c KWS_INPUT_CONFIG RW disabled/idle 0x0104bb80 P7 append: rate [16:0], physical channels [18:17], precision [25:20]; see P7 capture rules.
0x240 KWS_COEFF_ADDRESS RW idle/LP 0 P9: 64-byte-aligned APUC DMA source.
0x244 KWS_COEFF_SIZE RW idle/LP 0 P9: exact 61504-byte APUC image size.
0x248 KWS_COEFF_EXPECTED_CRC RW idle/LP 0 P9: expected APUC payload CRC32.
0x24c KWS_COEFF_COMMAND WO 0 P9: full-word value 1 starts coefficient loading.
0x250 KWS_COEFF_STATUS RO 0 P9: busy, valid, lock and terminal validation errors.
0x254 KWS_COEFF_ACTUAL_CRC RO 0 P9: finalized SRAM-readback CRC32.
0x258 KWS_COEFF_ID_LO RO 0 P9: published coefficient ID bits 31:0.
0x25c KWS_COEFF_ID_HI RO 0 P9: published coefficient ID bits 63:32.
0x260 KWS_COEFF_CAPACITY RO 0x0000f000 P9: auxiliary coefficient payload capacity in bytes.
0x300 PERF_CONTROL RW 0 Enable 0, clear pulse 1, snapshot pulse 2.
0x304 PERF_STATUS RO 0 Snapshot valid and overflow summary.
0x308..0x354 PERF_* RO snapshot 0 Ten 64-bit pairs: active cycles, input/output bytes, decoded frames, DMA read/write stalls, stream stalls, sequencer instructions, KWS cycles, and faults.

P2 freezes these status layouts. Reserved bits read zero and writes to every status register return PSLVERR.

STREAM_STATUS bits Semantics
0 TX_ACTIVE, live according to the active-direction definition in the stream contract.
1 RX_ACTIVE, live according to the active-direction definition in the stream contract.
2 TX_FIFO_EMPTY, live; reset one from P2 onward.
3 TX_FIFO_FULL, live.
4 RX_FIFO_EMPTY, live; reset one from P2 onward.
5 RX_FIFO_FULL, live.
6 TX_UNDERRUN, sticky until IRQ-state stream-xrun W1C or reset.
7 RX_OVERRUN, sticky until IRQ-state stream-xrun W1C or reset.
15:8 Saturating low-byte count of TX words accepted by I2S since counter clear/reset.
23:16 Saturating low-byte count of RX words accepted from I2S since counter clear/reset.
31:24 Reserved zero.

The two xrun bits clear together when software W1C-clears IRQ bit 9. A new xrun in that cycle wins and leaves the corresponding status/IRQ state set.

JOB_STATUS bits Semantics
0 BUSY, live while a direct or ring-owned job has not reached terminal writeback.
1 DONE, sticky terminal success.
2 ERROR, sticky terminal failure.
3 ABORTED, sticky terminal abort.
4 DIRECT_ACTIVE, live while the current job came from direct registers.
5 INPUT_PENDING, live while input AXI/stream work is outstanding.
6 OUTPUT_PENDING, live while output AXI/stream work is outstanding.
7 WRITEBACK_PENDING, live while descriptor/direct results have not retired.
13:8 Terminal six-bit error code.
17:14 Terminal four-bit stage.
19:18 Terminal AXI response.
31:20 Reserved zero.

DONE denotes success and is mutually exclusive with ERROR. ABORTED may coexist with ERROR when drain encounters a higher-priority fault. Terminal sticky/result fields clear when a new valid internal/public job is accepted or on soft/resource/hard reset; they do not clear on status read.

RING_STATUS bits Semantics
0 ACTIVE, live after scheduler start until disabled, aborted, or stopped.
1 STALLED_UNOWNED, live while head points to an unowned descriptor.
2 EMPTY, live when head equals tail and no descriptor/writeback is pending; reset one from P2 onward.
3 ERROR, sticky after a descriptor/ring error.
4 WRAPPED, sticky after head wraps to zero.
5 COALESCE_PENDING, live while pending-completion count is nonzero.
6 WRITEBACK_PENDING, live while result/OWN-clear is outstanding.
7 STOPPED_ON_ERROR, sticky when stop-on-error halts after terminal writeback.
15:8 Live pending-completion count used by coalescing.
23:16 Last descriptor index whose result writeback and OWN clear completed.
31:24 Reserved zero.

Ring sticky fields, pending count, last index, and coalescing epoch clear on a legal ring-enable transition from zero to one or on soft/resource/hard reset. Status reads and IRQ W1C do not clear them.

Capability bits describe implemented hardware, not whether a codec job is currently legal. P2 reports CAPABILITY0=0x00000018 for private DMA and ring, while format, streams, KWS, sequencer, and resampler bits remain zero; CAPABILITY1=0. P3 reports CAPABILITY0=0x00000098 for private DMA, ring, and the sequencer, and CAPABILITY1=0x00000010 for the 16 KiB control store. P3 continues to report zero for every format, stream, KWS, resampler, data-SRAM, channel, and sample-rate field. P4 reports CAPABILITY0=0x00000198 for private DMA, ring, sequencer, and the implemented resampler primitive, and CAPABILITY1=0x01827010 for 16 KiB control store, 112 KiB local data SRAM, two-channel primitive capacity, and 96 kHz maximum source-rate capacity. P4 format bits 0..2, streams bit 5, and KWS bit 6 remain zero because no public codec or stream session exists. A caller must require both the requested format/KWS bit and the necessary engine/model state before submitting. The P2 stream router remains unadvertised through P4 because its production endpoints remain unavailable. ABI_DIGEST is zero for every partial Phase1..7 build and becomes the nonzero CRC32 over the complete canonical APB V1 register/field/job-descriptor, supported APUMC V1/V2, APUM, opcode, format/IRQ/error tables only in the Phase8 supported MVP. For this release, the digest includes reserved MP3 identifiers and the P5 rejection/stub contract but excludes the inactive P6 design archive. A zero digest means prototype/incomplete ABI and is not a compatibility hash for a subset.

The P8 digest input is canonical ASCII JSON over sections discovery, apb, kws_model, formats, apumc, apum, isa, and mp3_stub. Object keys are recursively sorted, separators are literal comma and colon with no whitespace, integers are JSON decimal numbers, non-ASCII text is escaped, and the byte stream has no terminal newline. Apply reflected CRC-32/ISO-HDLC to the complete byte stream. The checked-in tool, handwritten RTL constant, handwritten C constant, and parity test must agree on the exact nonzero result 0xf5005d7c.

Expanded P5 keeps CAPABILITY0=0x000001bd and primitive mask 0x001fffff, but advertises CAPABILITY1=0x01827020 and IP_VERSION=0x00010001 for the 32 KiB store and appended PC-high status bit. This hardware discovery is constant even while a legacy V1 image is loaded. Format, TX/RX, KWS, data-SRAM, channel, rate, IRQ, ownership, and job behavior are otherwise unchanged.

Hardware set wins same-cycle W1C. Snapshot captures all 64-bit counters atomically; software reads low then high.

MICROCODE_LOAD and MODEL_LOAD require LP owner, quiesced/idle state, valid ACLs, and a clear corresponding lock; KWS must also be disabled for model load. P3 makes MICROCODE_LOAD legal under those conditions, but does not make any decode or stream transport public; MODEL_LOAD remains rejected until its later phase. START_DIRECT requires valid locked microcode and a validated direct job whose requested format/KWS capability is set. RING_KICK requires an enabled valid ring plus valid locked microcode and a supported operation at head. ABORT requires active work. SOFT_RESET and CLEAR_COUNTERS require idle. Therefore P2 and P3 reject public start and doorbell, and reject STREAM_ROUTE value 1 in either direction, while accepting and validating their configuration registers. The P3 dummy-program sequencer launch path is verification-only and creates no public command, descriptor operation, route, capability, or ABI. Violations return PSLVERR without changing state.

APUMC microcode bundle ABI

Versioned P5 control-store expansion

The selected P5 capacity remedy is a 4096-word, 64-bit control store. The reported compacted 2437-word trial was already 389 words over the old limit and still omitted cross-frame FLAC resampling and complete long-Rice paths. That report is sizing evidence, not a complete-codec acceptance result. The expanded store leaves 1659 words relative to that incomplete trial; the final complete image must still demonstrate that it fits. No compact opcode, dynamic-kernel operand, parser/CRC shortcut in RTL, host decode, overlay, or runtime code replacement is authorized by this refreeze.

APB register ABI and APUMC binary ABI have independent versions. APB V1.1 is an additive status/capacity extension. APUMC V2.0 versions the widened PC and branch operands so legacy images retain their exact V1 validation rules.

Target / image APB IP_VERSION CAPABILITY1 Header word 1 / loaded MC_ABI Instruction count / PC width
Historical P3 0x00010000 0x00000010 0x00010000 only 1..2048 / 11 bits
Historical P4 0x00010000 0x01827010 0x00010000 only 1..2048 / 11 bits
Pre-expansion P5 compatibility image Historical hardware remains 0x00010000 Historical hardware remains 0x01827010 0x00010000 1..2048 / 11 bits
Expanded P5, legacy image loaded 0x00010001 0x01827020 0x00010000 1..2048 / 11-bit validation on the 12-bit engine
Expanded P5, V2 image loaded 0x00010001 0x01827020 0x00020000 1..4096 / 12 bits

Expanded P5 must load both exact header versions. Unknown versions fail with the existing loader header-error tuple, locating header word 1 and reporting its observed value. A V1 image with count 2049..4096, a high descriptor PC bit, or branch immediate bit 11 set still fails V1 validation even on the expanded hardware. A V2 image is legal with fewer than 2049 instructions too; image size must never be used to infer the encoding. Older P3/P4/pre-expansion P5 loaders reject V2 at the header before publishing valid or fetching its instructions.

Version-related loader failures keep code 9, stage 1, response/index zero: unknown version sets MC_STATUS header-error and uses address MC_IMAGE_ADDRESS+4, detail header word 1; invalid count sets range-error and uses MC_IMAGE_ADDRESS+12, detail header word 3. Invalid PC/reserved bits in entry word 0 or 1 set range-error and locate that entry word with its observed 32-bit value. A branch's nonzero reserved immediate bits set control-flow-error and use its full instruction source address plus the existing trap_detail(1) encoding. These are the same category precedence and locator rules as before; the selected version supplies only new bounds and masks. V2 does not create a new error code or IRQ.

The 64-byte header, three 32-byte entry descriptors, 64-bit instruction format, opcode/predicate IDs, primitive masks, scratch/table fields, CRC algorithm and coverage, build ID, and MP3 stub contents are retained. Only the versioned instruction-count, PC fields and branch immediates below expand. The 128-byte public job/ring descriptor does not change. No image can switch ISA versions while executing, and lock/reset/admission/publication semantics are unchanged.

All multibyte bundle fields and instructions are little-endian. The bundle starts with this exact 64-byte header:

Word Field
0 magic 0x41504d43 (APMC)
1 combined APUMC/ISA ABI: major [31:16], minor [15:0]; V1.0 0x00010000 or V2.0 0x00020000 under the target matrix above
2 total bundle bytes
3 instruction count, 1..2048 for V1 or 1..4096 for V2
4 64-byte-aligned instruction offset
5 table-payload offset, 4-byte aligned
6 table-payload bytes
7 entry-descriptor offset, 32-byte aligned
8 entry count; V1 and V2 require exactly 3
9 required primitive mask, equal to the OR of all entry primitive masks
10 maximum declared local scratch bytes
11 CRC32/ISO-HDLC over all bytes after the header
12 build ID bits [31:0]
13 build ID bits [63:32]
14-15 reserved zero

The header total must equal MC_IMAGE_SIZE and be at least 160 bytes. The instruction byte count is exactly instruction count multiplied by eight. The header, descriptor array, instruction array, and table payload must lie wholly inside the total, must not overlap, and address arithmetic must not wrap. A zero-byte table payload is represented by word 6 equal to zero; word 5 remains range checked and aligned but is otherwise ignored. Bytes not occupied by one of those regions are padding and must be zero. MC_EXPECTED_CRC, header word 11, and the CRC32/ISO-HDLC calculated over bundle bytes 64 through the end in increasing byte-address order must all agree. CRC parameters are reflected polynomial 0xedb88320 (normal form 0x04c11db7), initial value 0xffffffff, and final XOR 0xffffffff. Any other word-1 value, reserved bit, entry count, alignment, size, range, overlap, or CRC relation is invalid.

The descriptor array contains three 32-byte, eight-word entries. Header word 1 selects exactly one of the following PC allocations; there is no mixed-layout array. Unlisted fields below retain the same meaning in both versions.

Word Bit allocation and units
0 format ID [3:0]; V1 entry PC [14:4], reserved [31:15]; V2 entry PC [15:4], reserved [31:16]; all reserved bits zero
1 V1 first PC [10:0], last PC [26:16], reserved [15:11] and [31:27]; V2 first PC [11:0], last PC [27:16], reserved [15:12] and [31:28]; all reserved bits zero
2 scratch base byte offset [16:0]; [31:17] reserved zero
3 scratch size in bytes [16:0]; [31:17] reserved zero
4 maximum loop count [15:0]; [31:16] reserved zero
5 maximum retired instructions per frame/block [23:0]; [31:24] reserved zero
6 required primitive mask [31:0]
7 table-relative byte offset [15:0]; table bytes [31:16]

Word 0 reserved masks are 0xffff8000 (V1) and 0xffff0000 (V2). Word 1 reserved masks are 0xf800f800 (V1) and 0xf000f000 (V2). Words 2..7 retain masks 0xfffe0000, 0xfffe0000, 0xffff0000, 0xff000000, 0xffe00000 (reserved primitive bits), and zero respectively; implemented-mask checks are additional to the word-6 reserved mask. V2 word 0 is format_id | (entry_pc<<4) and word 1 is first_pc | (last_pc<<16), without truncating any of the 12 PC bits. Entry format IDs/order remain 0/1/2. For PCs below 2048 these words have exactly the same values in V1 and V2; the header version still governs all checks.

PC fields are 64-bit instruction indices, not byte addresses. Descriptor array indices 0, 1, and 2 have format IDs 0, 1, and 2 for WAV, MP3, and FLAC respectively. For each entry, first PC is less than or equal to entry PC, entry PC is less than or equal to last PC, and last PC is less than the header instruction count. Scratch base and size are four-byte aligned, do not wrap, and lie within the advertised local data SRAM. Maximum loop count is 1..65535 and maximum retired count is nonzero. Table offset and size are four-byte aligned and select a non-wrapping range inside the global table payload. Word 10 of the header equals the greatest scratch end declared by any entry.

P3 has no local data SRAM or primitive engine. It therefore accepts only scratch base/size zero, table offset/size zero, header table bytes zero, and header/entry primitive masks zero. Its required three entries may contain only class-0 control and class-1 scalar instructions. A nonzero scratch/table field, primitive mask, or class-2 through class-6 instruction fails load validation; P3 never publishes table bytes. P4 adds the local table/SRAM and primitive capabilities needed to admit those already frozen encodings. This restriction does not pull a codec, table engine, or P4 storage into P3.

Primitive mask bits are fixed as follows. Bits 21..31 are reserved zero. Every instruction's listed primitive must appear in its entry mask, every entry mask must be a subset of the implemented mask, and the header mask is exactly the OR of the three entry masks.

Bit Primitive Bit Primitive
0 bitstream reservoir 11 fixed predictor
1 CRC 12 LPC
2 Huffman 13 channel decorrelate
3 Rice 14 resampler
4 local memory/table 15 PCM pack
5 local FIFO 16 DMA input
6 requantize 17 DMA output
7 stereo processing 18 stream output
8 IMDCT6 19 frame commit/job result
9 IMDCT18 20 event
10 DCT32/polyphase

Instructions are little-endian 64-bit words:

63     60 59     56 55     52 51     48 47     44 43     40 39      32 31       0
+---------+---------+---------+---------+---------+---------+----------+-----------+
| class   | opcode  | pred    | dst     | src0    | src1    | aux      | immediate |
+---------+---------+---------+---------+---------+---------+----------+-----------+

The sequencer has 16 32-bit GPRs, three comparison flags (EQ, signed LT, and unsigned LT), four return-stack entries, and four loop slots. Saved return PCs and loop-start PCs are 11 bits in P3/P4 and 12 bits in expanded P5; V1 execution still checks the 11-bit range. All are cleared at entry launch and on soft, resource, or hard reset. Every GPR is writable. GPR writes become visible to the next retired instruction. CMP is the only instruction that changes comparison flags. Arithmetic ADD and SUB wrap modulo 2^32; only SAT saturates. Variable shifts use the low five bits of src1. Default next PC is current PC plus one.

Predicate encodings are exact:

pred Condition
0 always
1 comparison EQ
2 not comparison EQ
3 comparison signed LT
4 not comparison signed LT
5 comparison unsigned LT
6 not comparison unsigned LT
7 descriptor input exhausted and bit reservoir empty
8 input FIFO nonempty
9 output FIFO not full
10 fixed-kernel completion latch set
11 no transport outstanding and the last transport command succeeded
12-15 invalid

A false predicate is a one-cycle semantic NOP: it retires, increments the per-frame retired count, and advances PC by one without other side effects. Encoding and operand legality are still checked by the loader regardless of the predicate. Unless an opcode says otherwise, reserved operand fields must be zero. Register fields required by an opcode are 0..15; an opcode that produces multiple registers states the tighter dst limit.

Opcode classes are:

Class Operations
0 NOP, END, TRAP, forward conditional jump/call, RET, loop setup/back, bounded wait
1 move/immediate, add/sub, and/or/xor, logical/arithmetic shift, compare, min/max, saturate
2 bitstream refill/peek/get/skip/align, frame sync, CRC8, CRC16
3 Huffman symbol/pair/quad, unary scan, Rice/Rice2, sign restore
4 bounded local load/store/table read, FIFO pop/push
5 requant, stereo, IMDCT6/18, DCT32/polyphase, fixed/LPC, decorrelate, resample, PCM pack
6 input refill, output commit/stream, DMA wait, frame commit, job result, event
7-15 invalid in V1

Within each class, V1 opcode numbers are fixed:

Class Opcode allocation
0 0 NOP, 1 END, 2 TRAP, 3 JUMP_FWD, 4 CALL_FWD, 5 RET, 6 LOOP_SETUP, 7 LOOP_BACK, 8 WAIT
1 0 MOV, 1 MOVI, 2 ADD, 3 SUB, 4 AND, 5 OR, 6 XOR, 7 SHL, 8 SHR, 9 SAR, 10 CMP, 11 MIN, 12 MAX, 13 SAT
2 0 REFILL, 1 PEEK, 2 GET, 3 SKIP, 4 ALIGN, 5 FRAME_SYNC, 6 CRC8, 7 CRC16
3 0 HUFF_SYMBOL, 1 HUFF_PAIR, 2 HUFF_QUAD, 3 UNARY, 4 RICE4, 5 RICE5, 6 SIGN_RESTORE
4 0 LD32, 1 ST32, 2 TABLE8, 3 TABLE16, 4 TABLE32, 5 FIFO_POP, 6 FIFO_PUSH
5 0 REQUANT, 1 STEREO, 2 IMDCT6, 3 IMDCT18, 4 DCT32_POLY, 5 FIXED, 6 LPC, 7 DECORRELATE, 8 RESAMPLE, 9 PCM_PACK
6 0 INPUT_REFILL, 1 OUTPUT_COMMIT, 2 OUTPUT_STREAM, 3 DMA_WAIT, 4 FRAME_COMMIT, 5 JOB_RESULT, 6 EVENT

Unallocated opcodes in every valid class are illegal. Class-specific use of dst, src0, src1, aux, and immediate is frozen below. A use not listed is rejected rather than ignored.

Control and scalar semantics

Class.op Operands and execution
0.0 NOP dst/src0/src1/aux/immediate=0; no effect.
0.1 END all operand fields zero; when true, stalls until accepted kernel/transport/writeback work has drained, then terminates and commits the latched JOB_RESULT; code zero is success and a nonzero code is terminal error. If none was latched, the committed result is zero/success. A drained engine/transport fault traps instead.
0.2 TRAP dst/src0/src1/aux=0; when true, traps with immediate as ERROR_DETAIL.
0.3 JUMP_FWD V1 uses immediate[10:0] in 1..2047; V2 uses immediate[11:0] in 1..4095; higher immediate bits and other operands are zero. Target is PC+1+delta and must be inside the entry program range.
0.4 CALL_FWD same target rule as JUMP_FWD; pushes PC+1, then branches; a fifth nested call traps.
0.5 RET all operands zero and predicate must be always; pops and branches; empty stack traps.
0.6 LOOP_SETUP predicate always; aux[1:0] selects an inactive loop slot, aux[7:2]=0, count is R[src0][15:0], and other fields are zero. Count must be nonzero and no greater than the descriptor maximum; the slot records count and PC+1 as its loop-start PC.
0.7 LOOP_BACK predicate always; aux[1:0] selects the active slot. V1 uses nonzero distance immediate[10:0] in 1..2047; V2 uses immediate[11:0] in 1..4095; higher immediate bits and other operands are zero. PC+1-distance must equal the slot's recorded loop-start. Count greater than one is decremented and branches there; count one clears the slot and falls through. Inactive slot, underflow, or target mismatch/range failure traps.
0.8 WAIT predicate always; aux source 0 DMA, 1 kernel, 2 input-FIFO ready, 3 output-FIFO ready, 4 TX-stream accepted/idle, or 5 ring writeback complete; all other operands zero. It stalls without retiring until true. Other sources are invalid.
1.0 MOV R[dst]=R[src0]; src1/aux/immediate=0.
1.1 MOVI R[dst]=immediate; src0/src1/aux=0.
1.2 ADD R[dst]=R[src0]+R[src1] modulo 2^32; aux/immediate=0.
1.3 SUB R[dst]=R[src0]-R[src1] modulo 2^32; aux/immediate=0.
1.4 AND R[dst]=R[src0]&R[src1]; aux/immediate=0.
1.5 OR `R[dst]=R[src0]
1.6 XOR R[dst]=R[src0]^R[src1]; aux/immediate=0.
1.7 SHL R[dst]=R[src0]<<R[src1][4:0]; aux/immediate=0.
1.8 SHR logical right shift by R[src1][4:0]; aux/immediate=0.
1.9 SAR signed arithmetic right shift by R[src1][4:0]; aux/immediate=0.
1.10 CMP sets EQ, signed LT, and unsigned LT from R[src0] versus R[src1]; dst/aux/immediate=0.
1.11 MIN aux[0] selects unsigned 0 or signed 1 minimum of R[src0] and R[src1]; aux[7:1]=0, immediate=0.
1.12 MAX aux[0] selects unsigned 0 or signed 1 maximum; aux[7:1]=0, immediate=0.
1.13 SAT saturates R[src0] to a width selected by aux[4:0]: 0 means 32, or literal 8, 16, or 24; aux[5] selects unsigned 0 or signed 1, aux[7:6]=0, src1/immediate=0; result is zero- or sign-extended into R[dst].

WAIT source 0 is true when no private AXI command/beat/response is pending and the last DMA command succeeded; a latched DMA error traps instead. Source 1 is true when the kernel completion latch is set, source 2 when the input FIFO is nonempty, source 3 when the output FIFO is not full, source 4 when no microcode-issued stream payload remains unaccepted, and source 5 when no ring writeback remains pending. Source 0 or 5 requires the relevant DMA primitive, source 1 requires the entry's kernel primitive, sources 2/3 require local FIFO, and source 4 requires stream output. P3 zero-mask dummy programs therefore cannot contain WAIT.

Bitstream, entropy, and local-data semantics

Class.op Operands and execution
2.0 REFILL immediate[5:0] is 1..32 required valid bits; stalls until present or descriptor EOF and writes the valid-bit count to R[dst]; EOF itself does not trap. Other operands are zero.
2.1 PEEK width is immediate[5:0], 1..32; writes the next bits to R[dst] without consuming. Insufficient bits at EOF trap as truncated stream. Other operands are zero.
2.2 GET same as PEEK, then consumes the bits.
2.3 SKIP width is immediate[5:0], 1..32; consumes without a result; insufficient bits trap. Other operands are zero.
2.4 ALIGN all operands zero; consumes 0..7 bits to reach the next input byte.
2.5 FRAME_SYNC byte-aligned scan for a masked 8..16-bit value: pattern R[src0][15:0], mask R[src1][15:0], width aux[4:0], maximum scan bytes immediate[15:0] 1..65535; R[dst] receives skipped bytes and the matching byte remains at the head. No match before limit/EOF traps. Upper aux/immediate bits are zero.
2.6 CRC8 updates accumulator R[src0][7:0] with byte R[src1][7:0] using the MSB-first polynomial 0x07, initial/final XOR zero, and writes the eight-bit result to R[dst]; no reservoir side effect; aux/immediate=0.
2.7 CRC16 updates accumulator R[src0][15:0] with byte R[src1][7:0] using the MSB-first polynomial 0x8005, initial/final XOR zero, and writes the 16-bit result to R[dst]; no reservoir side effect; aux/immediate=0.
3.0 HUFF_SYMBOL canonical table starts at entry-table byte offset R[src0], contains R[src1] entries, and has maximum code length aux[4:0] 1..24; consumes a code and writes its 16-bit symbol to R[dst]; immediate=0.
3.1 HUFF_PAIR same lookup fields as HUFF_SYMBOL; decoded symbol nibbles are written to R[dst] and R[dst+1], so dst<=14.
3.2 HUFF_QUAD same lookup fields; four decoded one-bit values are written to R[dst..dst+3], so dst<=12.
3.3 UNARY aux[0] selects zeros-until-one 0 or ones-until-zero 1; immediate[15:0] is a nonzero maximum; consumes the terminator and writes the run length to R[dst]; source fields and upper bits are zero.
3.4 RICE4 parameter k=R[src0][3:0]; for k<15, reads zero-run quotient q, its one terminator, and k remainder bits, then maps `u=(q<<k)
3.5 RICE5 as RICE4, with k=R[src0][4:0], escape value 31, and the same 1..32-bit raw width.
3.6 SIGN_RESTORE base magnitude is R[src0] and linbits count is R[src1][4:0]; nonzero magnitude consumes linbits to form magnitude+extra, then one sign bit and writes its positive value for sign 0 or two's-complement negative for sign 1 to R[dst]. Zero magnitude consumes neither and returns zero; aux/immediate=0.
4.0 LD32 loads R[dst] from descriptor scratch base plus R[src0]+sign_extend(immediate[15:0]); src1/aux and upper immediate bits are zero.
4.1 ST32 stores R[src1] to the same scratch address calculation; dst/aux and upper immediate bits are zero.
4.2 TABLE8 loads and zero-extends table element at entry table base plus R[src0]+R[src1]; aux/immediate=0.
4.3 TABLE16 as TABLE8, with index R[src1]*2; address must be two-byte aligned.
4.4 TABLE32 as TABLE8, with index R[src1]*4; address must be four-byte aligned.
4.5 FIFO_POP aux=0 selects the input-byte FIFO; stalls while empty, writes a little-endian 32-bit word to R[dst] and literal valid-byte count 1..4 [2:0] plus last flag bit 8 to R[dst+1]; dst<=14, sources/immediate zero, and all other sideband bits are zero.
4.6 FIFO_PUSH aux=0 selects the PCM-output FIFO; stalls while full, pushes little-endian R[src0] with literal valid-byte count 1..4 [2:0] and last flag bit 8 from R[src1]; other sideband bits must be zero and trap before push otherwise; dst/immediate=0.

A PEEK or GET result is right-aligned in the destination; the earliest bit in the MSB-first reservoir becomes result bit width-1. CRC results and Huffman symbols are zero-extended to 32 bits. A canonical Huffman table entry is one 32-bit word with symbol [15:0], code length [20:16] in 1..24, and [31:21] zero, in canonical-code order. All entries are ordered first by increasing length and then increasing canonical code; the first code of each length is derived by the canonical prefix rule. An invalid prefix or exhausted bounded table traps as entropy/decode failure. All reservoir reads use the codec-defined most-significant-bit-first order. Local loads/stores are little-endian, must be naturally aligned, stay within the active entry scratch range, and must not access the read-only table range. Table reads must stay inside the active entry table slice. Range checks include the complete access and trap before any partial side effect.

Kernel and transport semantics

Only one fixed-kernel request may be outstanding. For class 5, the values in R[src0], R[src1], and pre-issue R[dst] are input, coefficient/state, and output byte offsets relative to the descriptor scratch base. The low 16 bits of immediate are a nonzero element/block count and upper bits are zero. Issue stalls until accepted, retires on acceptance, clears the kernel-done latch, and completion sets that latch and replaces R[dst] with the produced element count. dst is pending between acceptance and completion; any instruction that would read or overwrite a pending GPR stalls. An unsuccessful kernel completion traps at the next retirement boundary with error code 8, or code 22 for reported FIFO/local/arithmetic overflow. A dynamic range/alignment failure traps before issue.

Class.op aux and operation
5.0 REQUANT shift [4:0], round-to-nearest bit 5, output width [7:6]: 0 S16, 1 S24, 2 S32, 3 invalid.
5.1 STEREO mode [1:0]: independent, left-side, side-right, or mid-side; [7:2]=0.
5.2 IMDCT6 six-point transform blocks; aux=0.
5.3 IMDCT18 eighteen-point transform blocks; aux=0.
5.4 DCT32_POLY 32-point/polyphase subband blocks; aux=0.
5.5 FIXED predictor order aux[2:0] 0..4; [7:3]=0.
5.6 LPC predictor order aux[5:0] 1..32; [7:6]=0.
5.7 DECORRELATE channel mode [1:0] as STEREO; [7:2]=0.
5.8 RESAMPLE coefficient profile aux[3:0] 0..15; [7:4]=0; count is input frames.
5.9 PCM_PACK format [1:0]: 0 S16_LE, 1 S24_32LE, 2..3 invalid; mono-duplicate bit 2; [7:3]=0.

The class-5 opcode requires its correspondingly named primitive bit, except STEREO requires bit 7 and DECORRELATE requires bit 13. Class-2 operations require bitstream bit 0, with CRC operations additionally requiring bit 1. Huffman operations require bits 0 and 2; unary/Rice/sign operations require bits 0 and 3. Local accesses require bit 4 and FIFO accesses require bit 5.

Class.op Operands and execution
6.0 INPUT_REFILL scratch-relative destination byte offset R[src0], nonzero requested bytes R[src1], returned transferred bytes R[dst]; aux/immediate=0; uses only the active descriptor input cursor and requires primitive bit 16.
6.1 OUTPUT_COMMIT scratch-relative source byte offset R[src0], nonzero bytes R[src1], returned committed bytes R[dst]; aux/immediate=0; uses only the active descriptor memory-output cursor and requires bit 17.
6.2 OUTPUT_STREAM same operands as OUTPUT_COMMIT, through the active TX stream, and requires bit 18.
6.3 DMA_WAIT all operands except dst zero; waits for transport quiescence, writes zero on success, and traps on the latched transport error. The entry must declare every DMA/stream primitive that may be outstanding.
6.4 FRAME_COMMIT saturating-adds input-used R[src0] and output-produced R[src1] to job counters, saturating-increments frame count, then resets the per-frame retired counter; dst/aux/immediate=0; requires bit 19.
6.5 JOB_RESULT latches terminal code R[src0][5:0], detail R[src1], and stage aux[3:0] without terminating; R[src0][31:6], dst, immediate, and aux[7:4] must be zero, and codes 23..63 trap as an illegal runtime value; requires bit 19.
6.6 EVENT sets sticky IRQ state selected by nonzero immediate[10:0]; only bits 6 and 7 may be one; all register/aux fields and upper immediate bits are zero; requires bit 20.

Transport operations never accept a raw system address from microcode. They advance only the active validated descriptor cursor and inherit its ACL, 4 KiB-boundary, burst, timeout, abort, and first-error rules. At most one microcode read command and one write/stream command may be outstanding. An input/output opcode stalls until its command is admitted, retires on admission, marks dst pending, and writes the completed byte count on successful completion. A read or overwrite of that pending GPR stalls. DMA_WAIT and FRAME_COMMIT stall until every applicable pending command has completed; a latched failure traps instead. All these stalls count toward the no-retirement watchdog.

Control-flow, watchdog, and trap rules

Only LOOP_BACK may branch backward. The loader proves all direct targets, fall-throughs, returns, and loop-back targets remain inside the entry's inclusive program range; call depth never exceeds four; each loop slot has one setup and one matching back edge; loop intervals are disjoint or properly nested rather than crossing; and every reachable path reaches END or TRAP. Runtime rechecks dynamic return, loop, local, table, and transport ranges before side effects.

The no-retirement counter clears on entry launch and each retired instruction, increments once per running cycle with no retirement, and traps after exactly SEQUENCER_TIMEOUT consecutive such cycles. A legal timeout value is nonzero. The per-frame counter starts at zero and counts every retired instruction, including predicate-false instructions. If the next instruction would exceed the descriptor maximum, it traps before instruction side effects; END may be the last allowed retirement. FRAME_COMMIT resets the counter only after its counter/result update commits. Falling through program-last PC or control-store word 2047 for V1, or word 4095 for V2, traps. Branch/call/loop/return targets are checked before assignment to the PC: V2 arithmetic uses at least 13 bits to detect underflow, overflow and a target of 4096 rather than wrapping it to zero. The width change does not permit arbitrary backward branches, increase call depth, add loop slots, alter loop counts, or change watchdog budgets. END/TRAP may legally occupy the final loaded word, including V2 PC 4095.

An asynchronous P2 transport error is sampled at the next retirement boundary, then fetch and new commands stop while accepted transfers drain. Trap reason allocations are 1 illegal encoding, 2 PC/program range, 3 call stack, 4 loop, 5 local/table range, 6 unavailable/undeclared primitive, 7 no-retirement watchdog, 8 per-frame retirement budget, 9 engine/transport fault, and 10 explicit TRAP; 0 and 11..255 are reserved. A trap sets sticky STATUS.SEQUENCER_TRAPPED and IRQ bit 10. IRQ bit 10 clears only by its W1C or reset. A trap leaves a previously loaded MC_STATUS.VALID and MC_LOCK set because the bundle itself remains loaded.

For the table below, PC is the trapping control-store word index (11 bits for V1, 12 for V2). The 32-bit trap_detail(reason) keeps its V1 allocation: reason [7:0], PC low 11 bits [18:8], class [22:19], opcode [26:23], and aux[4:0] [31:27]. Every primary non-AXI trap sets ERROR_STATUS.VALID=1, AXI response 0, descriptor index 0, and ERROR_ADDRESS=zero_extend(PC)<<3. APUMC entry indices are not job/ring descriptor indices and therefore never enter ERROR_STATUS.DESCRIPTOR_INDEX.

ERROR_ADDRESS always uses the full PC, including V2 bit 11: PC 2048 reports 0x00004000 and PC 4095 reports 0x00007ff8, including explicit reason-10 TRAP. No bit of reason/class/opcode/aux is stolen to extend ERROR_DETAIL. For loader instruction diagnostics, the address remains the absolute bundle address MC_IMAGE_ADDRESS + instruction_offset + 8*PC, using the full PC; trap_detail there also retains the low-11-bit PC field. Reason 9 still preserves an existing causative AXI/engine tuple; its address must not be reinterpreted as a PC. Software uses retained SEQUENCER_STATUS for that case.

Trap reason ERROR_STATUS code Stage AXI response Descriptor index ERROR_ADDRESS ERROR_DETAIL
1 illegal encoding 11 11 0 0 PC<<3 trap_detail(1)
2 PC/program range 11 11 0 0 PC<<3 trap_detail(2)
3 call stack 11 11 0 0 PC<<3 trap_detail(3)
4 loop 11 11 0 0 PC<<3 trap_detail(4)
5 local/table range 11 11 0 0 PC<<3 trap_detail(5)
6 unavailable/undeclared primitive 11 11 0 0 PC<<3 trap_detail(6)
7 no-retirement watchdog 11 11 0 0 PC<<3 trap_detail(7)
8 per-frame retirement budget 11 11 0 0 PC<<3 trap_detail(8)
9 non-AXI engine semantic failure 8 6 for reconstruction/transform; 7 for resampler/PCM 0 0 PC<<3 trap_detail(9)
9 non-AXI FIFO/local/arithmetic overflow 22 stage of the failing engine, 6 or 7 0 0 PC<<3 trap_detail(9)
9 AXI/DMA/stream cause unchanged causative code 15..19 unchanged causative stage unchanged causative value unchanged causative value unchanged causative address unchanged causative detail
9 without a valid causative error 11 11 0 0 PC<<3 trap_detail(9)
10 explicit TRAP 11 11 0 0 PC<<3 the instruction's 32-bit immediate

Reason 9 is secondary when an AXI/DMA/stream first-error tuple has already been captured: it sets sequencer trap status and IRQ bit 10 but does not alter that tuple. A reason-9 assertion without a causative error is an internal sequencer trap and uses the fail-closed row above. If another global terminal condition and a sequencer trap coincide, hard reset, forced resource reset, AXI write, AXI read, DMA timeout, RX overrun, and TX underrun retain their existing order above the trap; the trap outranks forced abort. Every applicable sticky event still sets.

Under APB V1.0, SEQUENCER_STATUS bits [31:21] remain reserved zero. APB V1.1 appends PC_HIGH at bit 21 (reset zero), with [31:22] reserved zero; PC-low, class, opcode, wait, and loop-active keep their original bit positions. The V1.1 reserved mask is 0xffc00000, versus V1.0 0xffe00000. Decode the full PC as (status & 0x7ff) | (((status >> 21) & 1) << 11); legacy V1 execution has PC_HIGH zero. While running, PC, class, opcode, wait, and loop-active are live for the current instruction. Wait is one for any current-instruction stall, including explicit wait, pending-GPR, kernel, DMA, FIFO, or backpressure stall. The terminal readback rules are:

Event SEQUENCER_STATUS after the event SEQUENCER_RETIRED after the event
END, with either a zero or nonzero latched terminal result Retains the terminal END PC/class/opcode and the wait/loop-active values sampled immediately before retirement. Retains the saturating current-frame count including the retired END.
Trap, including watchdog Retains the trapping current-instruction PC/class/opcode and its wait/loop-active values when the trap was recognized. Retains the count before the non-retired trapping instruction or stall.
Accepted abort with an active sequencer Further retirement stops; retains the current-instruction tuple sampled when abort was accepted through terminal abort completion. Retains the count sampled when abort was accepted.
Accepted abort without an active sequencer Remains unchanged. Remains unchanged.
Soft reset Clears to zero when the reset is applied. Clears to zero.
Normally drained or forced resource reset Clears to zero when resource-reset state is applied after drain. Clears to zero.
Hard/PCLK reset Clears immediately to reset value zero. Clears immediately to reset value zero.

END, trap, and abort snapshots persist through status reads, ERROR_STATUS/IRQ W1C, CLEAR_COUNTERS, and microcode load. The next accepted entry launch clears SEQUENCER_RETIRED to zero and initializes SEQUENCER_STATUS to entry PC with class/opcode/wait/loop-active zero until the first instruction fetch updates it. STATUS.SEQUENCER_TRAPPED clears on that launch or on soft/resource/hard reset; END and abort do not set it. The P3 verification-only launch follows the same rules and creates no public launch mechanism.

PC_HIGH participates in the same atomic running/terminal snapshot as PC-low: END/trap/abort retain it; accepted launch initializes it from the new entry PC; soft/resource/hard reset clears it; IRQ/error W1C and counter clear do not alter it. SEQUENCER_RETIRED, all first-error precedence, trap reasons, and terminal retention rules are otherwise unchanged. Readers requiring a stable PC while running read the single 32-bit status word rather than combining separately sampled status and ERROR_ADDRESS from different events.

P3 loader, status, and control store

MC_STATUS reset is zero. BUSY bit 0 is live, VALID bit 1 is retained state, bits 2..7 are sticky terminal validation errors, and bits 8..31 are reserved zero. STATUS.MICROCODE_VALID is an exact mirror of MC_STATUS.VALID. A legal load start clears VALID, bits 2..7, MC_ABI, build ID, and MC_ACTUAL_CRC, then sets BUSY. A prior successful load has automatically set MC_LOCK, so the clear-lock admission rule prevents it from being overwritten. Busy, valid, and terminal-error states are mutually exclusive.

The loader first validates header/ranges sufficiently to bound DMA, may then write the private control store while the sequencer is held idle and VALID=0, and publishes the new image atomically only after full validation and CRC. Success in one PCLK edge clears BUSY, sets VALID and MC_LOCK, writes MC_ABI from the accepted header word 1 (0x00010000 for P3/P4/V1 or 0x00020000 for an expanded-P5 V2 image), build ID and actual CRC, saturating-increments MC_LOAD_COUNT, and sets sticky IRQ bit 3. Load-done IRQ and count occur only on successful publication; the count saturates at 0xffffffff. A failed attempt clears BUSY, keeps VALID and lock clear, does not increment the count, does not set IRQ bit 3, and makes any partially written store inaccessible; the next attempt overwrites it.

Load admission also requires 64-byte-aligned MC_IMAGE_ADDRESS, nonzero MC_IMAGE_SIZE, and a non-wrapping complete source range inside the local read ACL. Admission failure returns PSLVERR without setting BUSY or changing loader state. Once admitted, validation-error categories are exact: header is bad magic/ABI/header reserved/total/entry count; range is offset, alignment, overlap, instruction-count, PC, scratch, or arithmetic range; control-flow is instruction encoding, predicate, operand-reserved, branch/call/loop, or termination proof; table is global/entry table layout or content, including any nonzero P3 table field; capability is an unsupported primitive mask, class-2..6 instruction in P3, or header/entry mask mismatch; CRC is the final three-way CRC mismatch. A nonzero P3 scratch field is a range error.

Every non-AXI loader validation failure sets ERROR_STATUS.VALID=1, stage 1, AXI response 0, descriptor index 0, and the code/address/detail tuple below, subject to the global immutable-first-error rule. Loader diagnostics use an absolute DMA source byte address, MC_IMAGE_ADDRESS + bundle byte offset. APUMC entry indices do not use the job/ring descriptor-index field.

Loader category MC_STATUS bit Error code ERROR_ADDRESS ERROR_DETAIL
Header 2 9 Address of the first offending header word, or the aligned 32-bit word containing the first nonzero padding byte. Observed little-endian 32-bit word at ERROR_ADDRESS.
Range 3 9 Address of the first header/entry field participating in the failed range relation. Observed little-endian 32-bit field value.
Control flow 4 9 Address of the first offending 64-bit instruction: MC_IMAGE_ADDRESS + instruction_offset + (PC<<3). trap_detail(1) for encoding/predicate/reserved-operand failure, trap_detail(2) for target/fall-through/termination failure, trap_detail(3) for call/return proof failure, or trap_detail(4) for loop proof failure.
Table 5 9 Address of the first nonzero P3 table field: header word 5, header word 6, then entry-descriptor word 7 in entry-index order. Observed little-endian 32-bit field value.
Capability 7 10 Address of header word 9, an entry word 6, or an instruction, whichever is the first offending item under the order below. header_mask XOR (entry0_mask OR entry1_mask OR entry2_mask) for a mask mismatch; observed_mask AND NOT implemented_mask for an unsupported-mask failure; trap_detail(6) for a class-2..6 instruction rejected by P3.
CRC 6 10 Address of header word 11, MC_IMAGE_ADDRESS+0x2c. MC_ACTUAL_CRC.

For header, range, and table categories, “first” means lowest bundle byte offset. For a range relation with more than one participating field, the lowest-addressed participant owns the diagnostic. Control-flow instructions are checked by entry index 0, 1, 2 and then increasing PC; a proof failure without a unique instruction uses that entry's entry PC, and the lower entry index wins a tie. For capability checking, header-mask mismatch precedes unsupported header-mask bits; header word 9 then precedes entry word 6 in entry order, which precedes instructions in that same entry/PC order. These locator rules apply after the already frozen category precedence and do not change which MC_STATUS bit wins.

Exactly one validation-error bit is set on failure using precedence header, range, control-flow, table, capability, then CRC. Header/range/control-flow/ table failures use code 9; capability/CRC failures use code 10. An AXI read/protocol failure records code 15 and sets no validation-error bit. All failure classes set sticky first-error IRQ bit 8 under the global first-error rules. MC_ACTUAL_CRC is zero on early-validation or AXI failure; header/range failures are early. For an admitted range-safe image, the loader continues through the complete payload before reporting control-flow, table, capability, or CRC failure, and MC_ACTUAL_CRC contains the computed value, including on CRC mismatch. A later legal load start clears the loader error bits. Clearing ERROR_STATUS or IRQ state does not clear MC_STATUS. Idle CLEAR_COUNTERS clears MC_LOAD_COUNT but not valid, lock, ABI/build/CRC, or loader errors. Hardware terminal updates win any same-cycle software clear elsewhere.

Hard/PCLK reset has highest precedence and clears all loader state, valid, lock, ABI/build/CRC, and load count without an IRQ. Resource reset is next: if a load is active, it blocks new DMA, drains accepted traffic, cancels the load, clears all MC_STATUS bits plus lock/ABI/build/CRC, leaves the count unchanged, suppresses load-done IRQ, and records forced lifecycle error 21 because the accepted load was canceled. Idle-only soft reset cannot be accepted while loader BUSY. A software abort accepted during a load uses the existing P2 block-new-and-drain behavior, then cancels publication, clears all MC_STATUS bits plus lock/ABI/build/CRC, leaves the count unchanged, suppresses IRQ bit 3, and sets abort-done IRQ bit 5. A successfully drained abort records no first error; a drain fault or timeout uses the existing global error and precedence rules. When no load is active, soft or normally drained resource reset clears loader error bits while preserving valid, lock, ABI/build/CRC, and load count. Terminal precedence is hard reset, resource reset, accepted abort, load failure, then load success.

The P3/P4 control store is exactly 2048x64 (16 KiB), with the mapping below; expanded P5 uses the separately frozen 4096x64 mapping. Both have synchronous one-PCLK-cycle sequencer fetches, no architecturally visible reset contents, and are fetchable only when valid. With HAVE_SRAM_MACRO=YES, the P3/P4 store is implemented as four tc_sram_1024x32 instances: two depth banks by low/high 32-bit halves; loader writes the halves and sequencer fetches the combined word, with mutually exclusive loader/fetch ownership. If a selected PDK advertises the macro but cannot elaborate that mapping, elaboration must fail.

For P3/P4 with HAVE_SRAM_MACRO=NO, including the supported ICS55 profile, apu_control_store selects a portable inferred synchronous logic [63:0] mem [0:2047] implementation with identical admission, latency, byte/word ordering, and loader/fetch exclusion. It must not instantiate an unconnected macro wrapper. This path is functional and synthesis-compatibility evidence only; it is not an SRAM-macro, PPA, or tapeout claim.

Expanded P5 uses eight tc_sram_1024x32 instances: four depth banks selected by word-address [11:10], each with low/high 32-bit halves, and row [9:0]. Both halves form one 64-bit control word; loader writes, loader verification reads, and sequencer fetch retain the same exclusive ownership and one-cycle synchronous read behavior. The selected bank is registered with each read so the 2047/2048 boundary cannot return the preceding bank's data. The no-macro path is logic [63:0] mem [0:4095] with identical word ordering and latency. Memory contents need not reset. Header version, loaded instruction count, valid/lock state, and entry bounds gate every fetch: an accepted V1 image cannot access the upper half or stale words from an earlier image.

Every loader/scanner/sequencer/fetch/return/loop PC path and saved verifier state must carry 12 bits on expanded P5. An instruction count or end sentinel must represent 4096 without truncation (at least 13 bits); the payload length must represent 32768 instruction bytes. Loader proof storage scales from 2048 to 4096 pending path records for V2, retaining the V1 limit for V1 validation; the offline verifier's maximum-instruction-count-times-64 bound becomes 262144 for V2 versus 131072 for V1. Exceeding a proof bound remains a control-flow loader failure, never a reason to skip paths. Internal proof-record layouts are not APUMC fields, but all saved PCs must round-trip bit 11. Proof workspace is implementation overhead and must be reported separately from the advertised control/data capacities.

No local-data partition, primitive latency, PCLK frequency, reset ownership, CDC/RDC crossing, DMA interface, or atomic table/control-store publication rule changes. MC_LOAD_COUNT and loader IRQ count one complete publication, not a bank or halfword. A late CRC/range/proof failure or an abort after an upper-bank write still publishes neither code nor tables. Existing soft/ resource-reset lock retention and hard-reset invalidation apply to all banks.

apu-mcasm is the single assembler/verifier and produces the binary, symbols, control-flow/loop report, primitive manifest, deterministic trace input, and canonical ABI-input manifest. A separate Python interpreter executes the exact enabled ISA for BAM and microcode/RTL differential tests. In P3 both tools execute class 0/1 and reject class 2..6 under the P3 target capabilities; later phases extend execution without changing these encodings. No partial tool-table fingerprint is exposed as the public ABI_DIGEST, which remains zero through P7. Neither tool accepts C, ELF, RV32, dynamic linking, or runtime code generation.

For the capacity migration, --target p3 and --target p4 continue to emit APUMC V1 and enforce 2048 words. --target p5 emits APUMC V2 by default and enforces 4096 words. The assembler adds an explicit --mc-abi 1.0 or --mc-abi 2.0 selector; p3/p4 with 2.0 is rejected. --target p5 --mc-abi 1.0 is the retained legacy P5 build path, including its 2048-word rejection. Parser and interpreter select the exact PC/operand limits from header word 1, then check the requested target's allowed primitives. Python helpers must take the version explicitly or derive it from this target default; no global widening may silently relax V1 checks.

All generated reports record APB compatibility, APUMC version, actual/maximum instruction words, byte size, free words, entry ranges, branch-delta maxima, source/coefficient hashes, bundle SHA-256 and CRC, and proof high-water. The canonical ABI manifest includes both descriptor/operand variants and the additive PC_HIGH field. RTL/C definitions remain independently handwritten and parity-tested; no generator is introduced. A source binary is rebuilt with the selected version, not patched in place; header/size/CRC/build-ID provenance must correspond to the exact resulting bytes. Existing legacy fixture bytes remain fixed.

P4 primitive and local-SRAM profile

P4 implements primitive-mask bits 0..15, so its implemented primitive mask is exactly 0x0000ffff. It admits classes 0..5 and rejects class 6 and classes 7..15 at load time. Within class 0, WAIT sources 1 (kernel), 2 (input FIFO), and 3 (output FIFO) are admitted; sources 0, 4, and 5 remain unavailable. Primitive bits 16..20, every class-6 transport opcode, and public transport-driven entry launch remain deferred. Each entry mask may be any subset of 0x0000ffff, but every admitted instruction must have all of its required bits in that entry mask and the header mask remains the exact OR of the three entry masks.

The assembler, parser, reference interpreter, RTL package, and handwritten C mirror expose a separate P4 target with this mask and class admission. The P3 target remains mask zero/class 0..1 and is not widened retroactively. P4 adds no opcode, predicate, primitive-bit number, descriptor field, or APUMC header field.

P4 reports CAPABILITY0=0x00000198 and CAPABILITY1=0x01827010 as defined in the register table. Format bits, streams, and KWS stay zero; ABI_DIGEST stays zero. Consequently START_DIRECT, RING_DOORBELL, and STREAM_ROUTE value 1 remain fail-closed. P4 exercises primitive programs only through the verification-only launch and data-injection path, which adds no public command, operation, address, interrupt, or route.

The P4 112 KiB local-data address space is byte addressed and fixed:

Local byte range Size P4 ownership and access
0x00000..0x05fff 24 KiB Active-bundle table followed by per-entry codec scratch.
0x06000..0x07fff 8 KiB Input staging, internal and verification-only until class 6 is enabled.
0x08000..0x09fff 8 KiB Output staging, internal and verification-only until class 6 is enabled.
0x0a000..0x19fff 64 KiB Reserved for P7 KWS; inaccessible in P4.
0x1a000..0x1bfff 8 KiB Primitive scoreboard, FIFO metadata, and bounded internal result state; not microcode addressable.

Let T be header word 6, the table-payload byte count. P4 requires 0<=T<=0x6000 and four-byte alignment, and copies bundle[header_word5+i] exactly to local byte address i for 0<=i<T. Entry table slices may overlap because they are read-only, but each must be wholly inside [0,T). Each nonempty entry scratch range must be wholly inside [T,0x6000), must not wrap, and must not overlap its table slice; scratch ranges belonging to different entries may overlap because only one codec entry can execute. Header word 10 remains the greatest declared scratch end and must be at most 0x6000. A zero-table, zero-scratch P3-compatible bundle remains legal in P4.

For P4 load diagnostics, T or entry-table-slice failure sets MC_STATUS.TABLE_ERROR, code 9/stage 1, and locates header word 6 or the first failing entry word 7. Scratch/base/end/header-word-10 failure sets MC_STATUS.RANGE_ERROR, code 9/stage 1, and locates the first participating field. A mask bit above 15, class-6 instruction, or unavailable WAIT source sets MC_STATUS.CAPABILITY_ERROR, code 10/stage 1, using the already frozen mask/instruction locator and detail. Classes 7..15 remain illegal V1 encodings and use MC_STATUS.CONTROL_FLOW_ERROR. All are non-AXI loader tuples with response/index zero and retain the existing category precedence.

The loader owns the local-data port while loading and writes only [0,T). Control-store words and table bytes are a single publication unit: both remain inaccessible while MC_STATUS.VALID=0, and the existing successful-load edge publishes both before setting lock/IRQ/count. Header, descriptor, instruction, table, or CRC failure; load abort; hard reset; or forced resource reset during load leaves both unpublished. Physical SRAM contents need not be cleared. After successful publication, the table is read-only and survives sequencer trap, job abort, soft reset, and normally drained resource reset exactly with the locked control store. Only hard reset invalidates that retained bundle.

Scratch, staging, FIFO, and internal-result contents have no architectural reset value. Each accepted entry launch starts a new mutable-data epoch: its scratch range, both staging ranges, both primitive FIFOs, and internal result state are logically invalid until written in that epoch. A read of an invalid word traps with reason 5 before data is consumed; a successful ST32, injector write, or kernel write marks only the written SRAM words valid, while FIFO push marks only its new entry valid. Abort and soft, resource, or hard reset invalidate all mutable epochs and flush both FIFOs. This may use validity metadata rather than physically clearing SRAM, but stale bits must never affect a result or become externally visible. The P4 verification-only injector may initialize scratch/FIFO data and validity for a test launch; it is excluded from product filelists and public ABI.

apu_local_sram presents one active codec-side 32-bit, byte-write-enabled port with a one-PCLK-cycle synchronous read. With HAVE_SRAM_MACRO=YES, local address bits select 28 existing tc_sram_1024x32 instances: banks 0..9 are codec table/scratch/staging, banks 10..25 are the disabled P4 KWS partition, and banks 26..27 are internal common/result state. With HAVE_SRAM_MACRO=NO, it selects an inferred synchronous logic [31:0] mem [0:28671] implementation with identical ordering, latency, and byte masks; it must not instantiate an unavailable macro wrapper. Loader access is exclusive. Outside loading, the one outstanding fixed kernel owns the SRAM port until completion; otherwise class-4 sequencer access owns it. This makes arbitration bounded and prevents a scalar/local instruction from perturbing an accepted kernel's latency. The inferred path is compatibility evidence, not SRAM-macro, PPA, or tapeout evidence. P7 may enable a separate KWS client on banks 10..25 without sharing codec banks or changing this P4 address/latency contract; common-bank contention remains governed by its later phase.

P4 implements two 64-entry, 41-bit primitive FIFOs using the existing Common stream_fifo: payload is data [31:0], valid-byte count [34:32], reserved [39:35]=0, and last [40]. They implement class-4 FIFO_POP/PUSH and remain separate from the already frozen P2 stream-router FIFOs. They run in PCLK, add no CDC/RDC boundary, and have only the verification producer/consumer in P4; class 6 later connects production transport.

P4 bit-accurate numerical contract

Scratch samples are little-endian signed two's-complement 32-bit integers. Fractional coefficients are signed Q2.30 words. A signed multiply produces the exact 64-bit product; a dot product accumulates in signed 72 bits. Exceeding the signed 72-bit range traps as code 22 before the affected output is made valid. RNE(x,s) divides signed integer x by 2^s and rounds the magnitude to nearest with an exact half going to an even quotient, then restores the sign; RNE(x,0)=x. An unrounded right shift is a two's-complement arithmetic shift, rounding toward negative infinity. SATb(x) clamps to [-2^(b-1),2^(b-1)-1]. All formulas below use these operations and contain no floating-point or implementation-dependent intermediate.

R[src1] points to an opcode-specific parameter block in entry scratch. A 32-bit reference word in such a block uses bit 31 as table select: zero means scratch-relative byte offset [16:0] with [30:17]=0, and one means entry-table-relative byte offset [15:0] with [30:16]=0. References are four-byte aligned, the complete referenced range is checked before issue, and table-selected ranges are read-only. State and history references must select scratch; input/output array references must also select scratch. Coefficient and scale references may select table or scratch. Coefficients are therefore explicit operands rather than hidden RTL constants. Static coefficient banks originate in CRC-covered APUMC data; dynamic scales or predictors may be written to scratch by microcode. Hardware, assembler, interpreter, and BAM consume identical words. Codec-specific static values are selected with the P5 bundles, or a future explicitly reactivated P6 bundle, without changing the P4 arithmetic contract.

For the class-5 table, N=immediate[15:0], P is the transform or predictor order defined by the opcode, and the pre-issue value of R[dst] is the scratch-relative output base:

Opcode Parameter block and exact output
REQUANT Word 0 references N Q2.30 scales. For element i, product=input[i]*scale[i]; aux bit 5 selects RNE(product,30+shift) or arithmetic shift by 30+shift, where shift is aux [4:0]. Apply SAT16, SAT24, or SAT32 from aux [7:6], sign-extend to 32 bits, and write N outputs.
STEREO Word 0 references the second N-sample input. Inputs are planar A and B; output is planar left then right. Modes produce (A,B), (A,A-B), (A+B,B), or mid=(A*2)+(B&1); ((mid+B)>>1,(mid-B)>>1) for independent, left-side, side-right, or mid-side. Signed 64-bit intermediates are clamped with SAT32; result count is 2N.
IMDCT6 / IMDCT18 Word 0 references a row-major Q2.30 matrix C[2P][P], with P=6 or 18. For every block and 0<=n<2P, output SAT32(RNE(sum(k=0..P-1,input[k]*C[n][k]),30)). There is no hidden scale; results contain 12N or 36N samples.
DCT32_POLY Words 0/1 reference Q2.30 C[32][32] and W[16][32]; word 2 references signed-32 history[16][32]; word 3 holds phase [3:0] and has other bits zero. Compute v[n]=SAT32(RNE(sum(k=0..31,input[k]*C[n][k]),30)), replace history[phase][n], then output SAT32(RNE(sum(m=0..15,history[(phase-m)&15][j]*W[m][j]),30)) for j=0..31; advance phase modulo 16 and write it back to word 3 per block. Result count is 32N.
FIXED Word 0 references a newest-first signed-32 history with P=aux[2:0] in 0..4. Predictor is 0, s1, 2s1-s2, 3s1-3s2+s3, or 4s1-6s2+4s3-s4. Add each signed-32 residual, require the exact signed-64 result to fit signed 32 bits, write it, and update history. Result count is N.
LPC Word 0 references P=aux[5:0] signed-32 coefficients, word 1 references newest-first signed-32 history, and word 2 is a sign-extended predictor shift in -31..31. Accumulate sum(j=0..P-1,coeff[j]*history[j]) in signed 72 bits; arithmetic-shift right for nonnegative shift or exact-shift left for negative shift, add the residual, require signed-32 range, write, and update history. Result count is N.
DECORRELATE Word 0 references the second planar input and uses the four STEREO equations, but any result outside signed 32 bits traps rather than saturates. Result count is 2N.
RESAMPLE Words 0/1/2 reference the full-band, two-thirds-band, and half-band coefficient banks; each bank is Q2.30 H[32][16]. Mutable words 3/4 hold 64-bit next_output_num, words 5/6 hold 64-bit input_base_index, and word 7 is channel count 1 or 2. The exact rational/phase/filter rules below produce interleaved signed-32 frames and update both 64-bit state values. Result count is produced frames.
PCM_PACK Word 0 is signed Q2.30 gain and word 1 is input channels 1 or 2; N counts input frames. For each input sample use RNE(sample*gain,30), then SAT16 or SAT24. S16_LE emits two little-endian bytes; S24_32LE emits the sign-extended 24-bit result in a four-byte little-endian word. Mono-duplicate is legal only for one input channel and emits two equal channels. Result count is emitted bytes.

The 16 RESAMPLE profile ratios are output/input in lowest terms:

Profile Ratio L/M Coefficient bank Profile Ratio L/M Coefficient bank
0 1/1 exact bypass none 8 6/1 full-band
1 1/2 half-band 9 8/1 full-band
2 80/147 half-band 10 12/1 full-band
3 160/147 full-band 11 320/147 full-band
4 3/2 full-band 12 640/147 full-band
5 2/1 full-band 13 1280/147 full-band
6 3/1 full-band 14 2/3 two-thirds-band
7 4/1 full-band 15 4/3 full-band

Profile 0 copies exactly N interleaved frames, adds N to both next_output_num and input_base_index, and reports N frames. For profiles 1..15, source frame indices are absolute. At invocation, R[src0] addresses frame input_base_index and its buffer must also contain seven valid history frames before it and nine valid look-ahead frames after the N frames. While floor(next_output_num/L)<input_base_index+N, let i=floor(next_output_num/L) and remainder r=next_output_num mod L. Phase is the nearest-even integer to 32*r/L; phase 32 is represented as phase 0 with i incremented. For every channel, output SAT32(RNE(sum(t=0..15,sample[i+t-7]*H[phase][t]),30)), then add M to next_output_num. After the invocation add N to input_base_index. Both state values start at zero; the first seven history frames and final nine look-ahead frames are explicit valid zeros supplied by microcode. A profile cannot change within a job; a new job reinitializes both state values. The three coefficient banks are APUMC data and have no hidden normalization or scale; the active P5 bundle provides its codec-quality values while P4 BAM compares the exact supplied Q2.30 words.

P4 latency and fault bounds

Latency is counted in PCLK cycles from accepted execute/issue through retire or kernel-done, inclusive. The bounds assume required local words are valid and a required FIFO word/space is present. Time waiting for external FIFO data or space is instead covered by SEQUENCER_TIMEOUT. B is scanned bytes, E is Huffman entries (1..4096), q is a Rice quotient limited to 65535, k is the Rice parameter/raw width, maximum_run is the UNARY immediate, S is emitted PCM samples, and O/C are resampler output frames/channels.

An entropy request with E outside 1..4096, a unary run beyond its declared maximum, or a Rice quotient above 65535 traps as invalid entropy before a result is written. EOF before the required entropy bits is a truncated-stream fault rather than a latency-bound exception.

Primitive/opcode Maximum PCLK cycles
REFILL 3
PEEK, GET, SKIP, ALIGN, CRC8, CRC16 1
FRAME_SYNC 2+2B
HUFF_SYMBOL, HUFF_PAIR, HUFF_QUAD 2+24+E
UNARY 2+maximum_run
RICE4, RICE5 4+q+k; escape path 4+raw_width
SIGN_RESTORE 3+linbits
LD32, TABLE8, TABLE16, TABLE32 2
ST32, ready FIFO_POP, ready FIFO_PUSH 1
REQUANT 8+4N
STEREO, DECORRELATE 8+4N
IMDCT6 8+94N
IMDCT18 8+706N
DCT32_POLY 8+2304N
FIXED 8+(P+4)N
LPC 8+(2P+5)N
RESAMPLE profile 0 8+2NC
RESAMPLE profiles 1..15 8+2NC+36OC
PCM_PACK 8+5S

N, output size, every referenced array, and each latency expression must fit 32-bit unsigned arithmetic and the active scratch range before issue. A bound violation traps before a write. A conforming implementation may complete earlier but never later under the stated ready-data conditions. The interpreter and RTL expose identical completion cycles in the P4 latency corpus.

P4 extends reason-9 causative errors without changing P3 behavior: frame-sync failure captures code 4/stage 4; required-bit exhaustion captures code 5 with stage 4 for class 2 or stage 5 for class 3; and invalid Huffman/unary/Rice content or a frozen entropy bound violation captures code 7/stage 5. These non-AXI tuples use response/index zero, ERROR_ADDRESS=PC<<3, and ERROR_DETAIL=trap_detail(9) before setting the existing secondary reason-9 trap. CRC opcodes only calculate values; codec checksum policy remains in the codec phases. Local range/validity faults use reason 5. Class-5 semantic and overflow faults retain the already frozen code 8 or 22 and stage 6/7 mapping.

P5 public codec and transport profile

This section freezes P5 against the reviewed P4 interfaces present at 57ffd03216502804f1108041184fdd6e6a328217. It specifies the production controller that replaces the tied-off job, FIFO, and TX-session connections; it does not declare that controller already implemented.

P5 discovery/admission Exact value or rule
CAPABILITY0 0x000001bd: WAV 0, FLAC 2, DMA 3, ring 4, TX streams 5, sequencer 7, resampler 8. MP3 1 and KWS 6 remain zero.
CAPABILITY1 Expanded P5: 0x01827020, 32 KiB control, 112 KiB data, two channels, 96 kHz maximum source rate.
Implemented primitive mask 0x001fffff, bits 0..20; reserved bits 21..31 remain zero.
ISA target Add p5 to the assembler/parser/interpreter and hardware capability validation. Classes 0..6 and all six existing WAIT sources are admitted subject to entry masks. Existing p3 and p4 targets retain their masks and behavior.
Public job Operation 0 with format 0 WAV or 2 FLAC; one active job, direct or ring. MP3, KWS operation 1, and model load remain unavailable.
Stream route TX 0/1 legal; RX only 0 legal. Bit 5 means at least one implemented stream direction, not permission for RX/KWS. RX 1 and reserved direction values return PSLVERR.
ABI identity Expanded P5 APB V1.1, IP_VERSION=0x00010001; new release bundles use APUMC V2.0 / MC_ABI=0x00020000 and legacy V1 images remain loadable. Existing APB offsets, job descriptor, 64-bit instruction positions/opcodes, and topology stay fixed. ABI_DIGEST=0 through P7.

Direct acceptance snapshots all job fields, requires owner/unblocked/idle, locked valid microcode, a supported format, valid ranges and output geometry, and no enabled active ring. Rejected direct starts cause no payload DMA and leave result state unchanged. Ring doorbell requires an enabled valid ring, owner/unblocked state, locked microcode, and no direct job; it does not inspect the head format during the APB transfer. Each invalid owned descriptor, including MP3/KWS, completes with the existing P2 error/writeback/OWN-clear sequence. Thus an unsupported ring head cannot prevent its own rejection writeback. Direct and ring configuration words retain their existing layouts. Buffers and the complete 128-byte descriptor must fit the relevant ACL; input/output and descriptor/result memory may not overlap. Shared storage must remain immutable/non-cacheable or explicitly cache-maintained while owned.

Production entry context and class-6 movement

GPRs still start at zero. Before the first instruction, after the P4 mutable epoch clear, the controller writes the following 64-byte context into the last 64 bytes of the active entry's scratch range. This is a microprogram ABI inside existing scratch, not a new APB register window. The P5 WAV/FLAC bundle reserves it; kernels and transport data buffers may not overlap it. LD32 and ST32 use the existing scratch-relative addressing to access it.

Word Value/owner
0..3 Controller writes descriptor CONTROL without OWN/IOC, INPUT_CONFIG, OUTPUT_CONFIG, and JOB_FLAGS; microcode reads only.
4 Microcode's cumulative parsed input bytes, initially zero; monotonically increasing and at most INPUT_LENGTH.
5 Microcode's diagnostic byte offset from input start, initially zero; may equal INPUT_LENGTH for EOF.
6 Microcode's detected SOURCE_INFO in the existing result layout, initially zero; written after header validation and constant thereafter.
7 Microcode final-output marker, bit 0 only; initially zero. It marks the next output command as the final one and is consumed/cleared when that command is accepted.
8 Controller writes INPUT_LENGTH; microcode reads only.
9 Controller writes OUTPUT_CAPACITY; microcode reads only.
10 Controller writes current private-DMA input cursor after each refill completion; microcode reads only.
11 Controller writes completed transport output bytes after each output completion; microcode reads only.
12..15 Reserved zero.

The controller owns transport cursors and checks context bounds when consumed. APUMC loader validation retains all P4 table/scratch range rules. Job dispatch additionally requires a WAV/FLAC entry with at least 64 scratch bytes; a generic primitive-only bundle may still load but cannot run a public codec job without this space. Only released, verified P5 microprograms define codec semantics; load CRC/lock is not authentication of an arbitrary program.

INPUT_REFILL has exactly one source: the active descriptor input cursor. Its requested count is a multiple of four in 4..256, and its scratch destination is four-byte aligned and has space for the request. Actual bytes are min(request, INPUT_LENGTH-cursor). The controller buffers an entire request in the P4 input staging region at 0x06000 before publishing it; on success it copies the actual bytes to scratch, zeroes unused lanes of the final local word, and queues the same bytes in the primitive input FIFO. Completion and cursor increment occur once both copies have been accepted. Source bytes are not reread or decoded by LP/HP. Zero actual bytes completes with zero without issuing AXI; it sets the EOF state and emits no zero-byte FIFO item.

Refill admission reserves enough free FIFO entries for the entire actual request, as well as the read-command slot, and waits for an active fixed kernel to complete before claiming SRAM. A reservation need not wait for the reservoir to empty. The primitive FIFO's last is set only on the item ending the descriptor input, not on each 256-byte refill. Valid-byte counts remain literal 1..4 and byte order is increasing address. FIFO_POP and bitstream refill consume one shared FIFO; the microprogram must not use FIFO_POP while the bitstream reservoir holds unconsumed bits. Scratch copies are for CRC/header inspection and do not implicitly consume the reservoir. The parser tracks available bits and schedules explicit refills before an operation would exhaust queued input. Long unary/Rice tokens spanning refill boundaries are decoded with bounded bit-read/refill microcode loops; issuing an entropy primitive that stalls waiting for its own not-yet-issued refill is forbidden in the released bundle. This needs no autonomous host refill.

OUTPUT_COMMIT and OUTPUT_STREAM both take authoritative bytes from the specified scratch range; their byte count is 1..256 and a multiple of a complete destination PCM sample frame. The scratch base is four-byte aligned. They first copy those bytes into output staging at 0x08000, then enqueue them into the primitive output FIFO, then drain that FIFO to private AXI DMA or to the P2 TX router respectively. Output-command admission requires this FIFO empty. FIFO_PUSH remains executable for primitive programs, but an output command with older manually pushed entries is a reason-5 contract fault; it may not discard or substitute those entries. During transport's FIFO ownership, manual pushes stall. SRAM and FIFO payloads are not two alternative public output modes.

Only one read and one output command may be pending. Local SRAM ownership is loader exclusive, then an already accepted fixed kernel, then a transport copy, then a class-4 request; newly eligible kernel/transport/local requests use round robin and cannot preempt an accepted operation. Each transport copy is at most 64 words. Transport waits outside a running kernel do not change P4's accepted-kernel latency guarantee. The DMA owner remains held until done through the P2 channel/response drain, including ring fetch and writeback.

Output-memory cursor advances only by bytes from bursts with successful B responses. OUTPUT_COMMIT returns its requested count only after all B responses succeed. OUTPUT_STREAM returns only after the last word of that command crosses the router-to-I2S handshake, not merely the primitive FIFO or router enqueue. Source/context data cannot be modified while its command is pending; unrelated mutable words may still be used. Existing GPR-pending, DMA_WAIT, and WAIT semantics apply. WAIT 4 includes the router FIFO and unaccepted TX word; WAIT 5 observes ring result/OWN writeback. It is initially true before a writeback begins and is not a prerequisite for the running entry's own future writeback.

The final-output context marker asserts TLAST only on the final I2S word of the marked command. Memory output consumes the marker without an external TLAST. A marked command forbids later output commands in that job. Empty audio emits no word or TLAST. A nonempty successful stream job must have exactly one final marker. The microprogram checks EOF/container end using look-ahead before releasing the final PCM frame. There is no fabricated TLAST on a previously accepted word when a job aborts or fails.

FRAME_COMMIT retires once per destination PCM sample frame, never once per compressed FLAC frame or DMA command. Its source0/source1 values add logical input-used/output-produced deltas and it increments the existing frame counter by one. Source1 equals destination bytes per frame, including mono-to-stereo duplication for I2S; input deltas may be zero during upsampling. Hardware also tracks physical successful bytes independently, so commits cannot exceed transported bytes. On normal END, logical output bytes/frames must equal physical bytes/complete PCM frames; mismatch is a contract failure. Parsed input context word 4 supplies final input-used, including header/trailing chunks not associated with the last PCM frame, and must not be less than the committed input-used. FRAME_COMMIT continues to reset the per-frame retired watchdog budget. EVENT retains IRQ bits 6/7 semantics; it does not replace the router's watermark detectors.

On failure or abort, results report parsed input context word 4, the physical successful output prefix, and complete PCM frames in that prefix. A burst with failing B is excluded from that prefix even though some destination bytes may physically have changed. No rollback of AXI or accepted audio is promised. Successful DMA byte counters count each wire transfer once; sequencer commits and local staging copies do not double-count them. Loader and ring traffic retain their existing counter attribution. JOB_CYCLES saturates from job acceptance through terminal drain/result construction; ring finish timestamp precedes OWN clear, as in the P2 scheduler.

Abort/resource block-new stops instruction retirement and new transfers. An output command is not issued to AXI until its complete payload is in staging; its accepted W/B work drains even if mutable epochs are invalidated. A presented unaccepted stream word remains stable and drains, as do already queued router words. Unpresented staging/primitive-FIFO data may be discarded after the command's outstanding obligations are tracked. Resource reset is applied only after drain; hard/PCLK reset retains the P2 warm-flush rules. If the sink/fabric never responds, idle/abort-done must not falsely assert. AXI response/protocol and DMA-timeout precedence remains unchanged. New codec errors enter below the existing AXI/DMA/xrun causes, below a sequencer trap, and above forced abort on the same cycle; otherwise the first captured error remains immutable. Empty/full primitive FIFOs alone are backpressure, not audio xrun. The P2 router's real I2S xrun events retain codes 18/19. On successful END, any prefetched-but-unparsed input tail is discarded after all read responses drain; it is not counted as parsed input and cannot carry into the next entry epoch. This includes relaxed trailing bytes.

P5 WAV and native-FLAC file profiles

Files are finite, contiguous DMA inputs of at most 0x7fffffff bytes. These limits are the P5 acceptance subset; a valid file outside them is unsupported, not malformed. WAV syntax uses the Microsoft RIFF rules and PCM/extensible format definitions. Native FLAC syntax is RFC 9639; the bounded profile and error policy below override any freedom it gives a decoder. LP/HP neither parse these files for the APU nor provide decoded PCM.

WAV property P5 rule
Container Exactly little-endian RIFF, 32-bit size, WAVE; no RF64, RIFX, WAVE64, compressed WAVE, or leading tags. Compute riff_end=8+size with checked wide arithmetic. It must be at least 12 and not exceed input length.
Required chunks Exactly one fmt before exactly one data. Chunk headers are eight bytes; every chunk payload and its odd-size pad must fit riff_end. data before fmt , duplicate required chunks, overlapping/wrapped sizes, or a partial final chunk header fail.
PCM fmt Tag 1; length 16, or length 18 with cbSize=0. Channels 1/2, integer rate 8000..96000 Hz, bits 8/16/24/32. blockAlign=channels*(bits/8) and avgBytesPerSec=rate*blockAlign must match exactly.
Extensible fmt Tag 0xfffe; length 40, cbSize=22, PCM subtype GUID 00000001-0000-0010-8000-00aa00389b71. Valid bits must equal container bits, both from 8/16/24/32. Mono channel mask is 0 or 0x4; stereo is 0 or 0x3. Float subtype, other masks, and padded-valid-bit variants are unsupported.
Unknown chunks Skip bounded payloads by consuming input; do not interpret LIST, JUNK, fact, bext, or embedded metadata. At most 1024 chunks and 1 MiB total skipped payload plus padding, including chunks after data.
Alignment/padding Odd chunk lengths have exactly one pad byte; strict mode requires zero, relaxed mode accepts any value. Missing required pad is truncated input. data size must be a multiple of blockAlign, including a valid zero-length data chunk.
End Parse remaining chunks through riff_end. Strict requires riff_end==INPUT_LENGTH; relaxed ignores bytes beyond riff_end and sets warning bit 1. RESULT_INPUT_USED=riff_end on success.
Sample representation Eight-bit samples are unsigned with bias 128; 16/24/32-bit samples are signed little-endian two's complement. No host conversion or dither.
Native FLAC property P5 rule
Signature/metadata fLaC at byte zero; first metadata block is exactly one 34-byte STREAMINFO. At most 128 metadata blocks and 1 MiB total metadata payload. A terminating last-metadata flag is mandatory. Types 1..6 are bounded opaque skips; reserved types 7..126 are unsupported; type 127 and duplicate STREAMINFO are malformed.
Geometry 1/2 channels, 16/24 bits/sample, rate 8000..96000 Hz. Nonzero total-samples is a required exact end count; zero means unknown until EOF. Nonzero min/max frame-byte hints must be ordered; STREAMINFO min/max block sizes must be legal and contain each nonfinal frame's block size.
Workspace bound Maximum coded block is 4096 samples for mono or 2048 for stereo. Maximum encoded frame is 65536 bytes. A larger advertised maximum or frame/block is unsupported before PCM from that frame is released. This explicitly excludes common 4096-sample stereo files in P5; broader block support needs a later memory/streaming design.
Frame header Accept fixed- and variable-blocking strategies, all RFC block-size codes 1..15 and sample-rate codes 0..14 when the decoded values fit the profile. Code 0 block size, code 15 sample rate, reserved bits/bit-depth codes, and invalid UTF-8-style frame/sample numbers fail. A file keeps one blocking strategy. Numbers start at zero and advance contiguously; final short blocks, including 1..15 samples, are allowed.
Property changes Rate, bit depth, and channel count must match STREAMINFO and stay constant. Channel assignment may vary per frame among independent/left-side/side-right/mid-side; mono uses independent only. All expected nonzero INPUT_CONFIG fields must match the detected source.
Subframes Constant, verbatim, fixed order 0..4, LPC order 1..32; predictor order is no larger than block size. LPC coefficient precision 1..15 and signed shift -16..15 are accepted. Restore predictor warmups and residuals exactly; side subframes use the required extra bit.
Wasted bits Accept any legal wasted-bit count leaving at least one coded bit. Restore wasted bits before stereo decorrelation and check the final nominal sample range. Invalid counts or reconstruction overflow fail.
Residuals Rice and Rice2 with legal partition order 0..15, block divisibility, first-partition warmup subtraction, and exact sample count. Honor P4's quotient limit 65535; a legal larger quotient is unsupported. Escape raw width 0 represents an all-zero residual partition and is synthesized by microcode without issuing the P4 raw-width primitive; raw widths 1..31 use sign extension.
Integrity Mandatory header CRC8 and frame CRC16, initialized zero with the existing P4 polynomials, in both strict modes. All subframe-to-footer pad bits must be zero. Decode and validate the full frame before releasing any of its PCM. No resynchronization, concealment, or checksum bypass.
MD5 STREAMINFO MD5 is retained as metadata but not computed by P5. Zero and nonzero MD5 fields are accepted; success always sets warning bit 0, MD5 unchecked. Strict does not turn on an absent MD5 engine. External reference tests may verify MD5; APU success does not assert whole-file MD5 verification.
End/truncation With a known sample count, stop at exactly that count; a final frame may not exceed it. Strict rejects trailing bytes; relaxed ignores trailing bytes and sets warning bit 1. With unknown count, only exact EOF after a valid frame is success; incomplete next headers/frames fail in either mode. Empty streams are accepted only at the metadata end with total-samples zero.

The P5 released bundle uses at most 6144 table bytes and reserves at least 18432 scratch bytes for each supported entry, wholly within the existing 0x00000..0x05fff workspace. Up to 16384 scratch bytes hold one full decoded FLAC frame; at least 2048 remain for input copies, predictor state, parameter blocks, resampling tiles, CRC and job context. Process resampling in tiles of at most eight source frames so expansion up to 12:1 fits that remainder. Predictor reconstruction uses at most 64 residual samples per kernel request, preserving history across requests. Required P5 bundles bound each kernel's ready-data latency below the existing default SEQUENCER_TIMEOUT=0xffff and prove their maximum retired count between commits (including metadata skip) fits the entry's 24-bit budget. No artificial FRAME_COMMIT may be used to reset a watchdog before producing an output PCM frame. This is a release-bundle packing requirement, not a reduction of P4 loader capacity. The staging regions and P7 KWS reservation retain their P4 addresses. WAV processes at most 256 source PCM frames per validation block, using a smaller tile when needed. A terminal container/metadata error can occur after earlier valid audio has already been emitted; its prefix is retained. For resampling across FLAC frames, retain only the bounded history and pending end tile while decoding the next full frame into the main planar buffer; do not allocate a second full-frame buffer or read unverified next-frame samples. On a next-frame CRC error, pending unissued output may be discarded. Accumulate small packed tiles until an output command can carry 256 bytes, except at final output or remaining capacity, so I2S startup prefill can complete without waiting on a shorter nonfinal command's sink handshake.

P5 PCM, rate, and completion policy

For source precision b, normalize signed source integer s to signed Q1.31 with the exact integer s*2^(32-b) (WAV unsigned eight-bit first subtracts 128). Stereo-to-mono is RNE(left+right,1) using a signed 33-bit sum in that domain, followed by signed-32 saturation. Bit 10 in CONTROL authorizes this reduction; it is illegal when not doing stereo-to-mono. Mono-to-stereo is exact duplication and does not use bit 10. Output channel zero means derive from source for memory, and two for I2S. Memory permits 1/2 output channels; I2S requires two physical slots. To request downmixed audio on I2S, select one logical output channel with bit 10, then duplicate it into the two slots.

CONTROL bit 11 zero requires output rate zero (derive) or exactly source rate. With bit 11 one, rate must explicitly be 48000 or 96000 Hz and the reduced output/source ratio must match a P4 profile, including profile 0 for equal rates. Other ratios are unsupported; no nearest-rate choice is made. Memory pass-through accepts every source rate in the file profile; I2S output must resolve to 48 or 96 kHz. Its width/rate are configured through the existing I2S HAL before submission. The APU does not write I2S registers; the driver requires matching I2S format and stream-TX configuration and an idle central DMA TX path before enabling APU TX route.

The shipped P5 resampler tables are three fixed 32-phase/16-tap Q2.30 banks. Their values are uniquely defined by the following offline formula, not by host floating-point defaults. For cutoff c=1,2/3,1/2, phase p=0..31, and tap t=0..15, let x=t-7-p/32, sinc(z)=sin(pi*z)/(pi*z) with sinc(0)=1, w(t)=(1-cos(2*pi*(t+1/2)/16))/2, and a(t)=c*sinc(c*x)*w(t). Round 2^30*a(t)/sum(a) to nearest-even to obtain each coefficient; add the integer residual 2^30-sum(coefficients) to tap 7. Coefficient generation must resolve rounding using increased precision/interval bounds, emit all 1536 little-endian signed words, and compare independently generated words before shipping. The binary is covered by the APUMC CRC/build manifest. P4 arithmetic, profile mapping, phase rounding, history/look-ahead, and saturation are unchanged. Identity bypass is exact; nonidentity conversion is not a lossless-output claim.

After downmix/resampling, convert Q1.31 to signed output precision by arithmetic right shift 16 for S16 or 8 for S24, then saturation. There is no dither or implicit gain. Before using PCM_PACK, microcode has already made that shift and sets packer gain to 0x40000000. Thus native 16/24-bit FLAC pass-through at matching precision/rate/channels is bit-exact, and changing precision has a deterministic amplitude-preserving result. Stereo S16 uses one full 32-bit I2S word per frame; stereo S24 uses two sign-extended words. TKEEP=TSTRB=0xf; all other I2S sidebands are zero except final TLAST.

Output capacity is enforced before issuing each command, with checked cursor+bytes arithmetic; only whole destination PCM frames may be issued. Memory output requires nonzero capacity and four-byte-aligned address. Stream output uses address/capacity zero. In either mode total output bytes must fit 32 bits; detect a prospective overflow as code 22/stage 8 before issue rather than allowing a cursor to wrap. If the entire next command cannot fit, issue no byte from it and terminate with code 8/capacity detail. The released microprogram must shorten a tile to the remaining whole-frame capacity first, then report exhaustion if more audio remains. A known too-small capacity need not prevent earlier valid frames from being returned. Input format errors never publish a partly decoded or CRC-unverified FLAC frame; transport faults may leave partial output from an already verified frame. Success is distinct from partial prefix plus terminal error.

Memory success waits for every output B response. Stream success waits for the final router-to-I2S handshake and an empty APU TX router, not for the last sample to leave the DAC pin. The stream session remains active until that drain, so route changes still use the P2 active-direction rule. Software that needs audible completion must separately drain I2S before disabling it. Empty jobs need no final beat. IRQ, ring coalescing/IOC, result writeback and OWN-last release follow P2; direct completion uses IRQ bit 0, ring uses bit 1. JOB_FLAGS[0] affects only the explicitly stated padding/trailing-byte checks; it never disables bounds, codec CRC, overflow, or output-capacity checks.

P5 format diagnostics and unsupported MP3 entry

Codec RESULT_DETAIL, JOB_DETAIL, and codec ERROR_DETAIL use format ID [31:24], warnings [23:16], and reason [15:0]. Warnings are bit 0 MD5 unchecked (FLAC only), bit 1 relaxed trailing bytes ignored, bit 2 relaxed nonzero WAV pad accepted; bits 3..7 are zero. Warnings describe checks actually skipped, including on a later failure. All unspecified reason values are reserved. On success reason/code are zero. On a codec error the tuple has VALID=1, AXI response=0, direct descriptor index=0 or the owning ring index, and ERROR_ADDRESS=INPUT_ADDRESS+context_word5, with checked arithmetic. The location is the first byte of the failing field/chunk/frame, or exactly one-past-input for truncation. W1C, existing first-error preservation and P3 loader/trap tuples remain unchanged.

Reason Meaning Code / stage
0x0001 Unsupported operation/format 3 / 2
0x0002 Unsupported rate/channels/precision or expected-input mismatch 3 / 4
0x0003 Unsupported valid encoding/container/metadata type 3 / 4
0x0004 File/chunk/metadata/block/frame/Rice quotient profile limit 3 / 4 (container/block) or 5 (Rice)
0x0010 Bad file signature 4 / 4
0x0011 RIFF size/wrap or malformed container extent 4 / 4
0x0012 Missing/duplicate/misordered required chunk 4 / 4
0x0013 Chunk data length not frame-aligned or invalid chunk extent 4 / 4
0x0014 Invalid PCM format fields/alignment/byte rate 4 / 4
0x0015 Invalid STREAMINFO 4 / 4
0x0016 Invalid FLAC metadata structure 4 / 4
0x0017 Invalid/reserved frame header 4 / 4
0x0018 Midstream geometry/blocking-strategy change 4 / 4
0x0019 Forbidden nonzero pad bits/strict pad byte 4 / 4
0x001a Invalid/noncontiguous frame or sample number 4 / 4
0x001b Strict trailing bytes 4 / 4
0x0020 Required bytes/bits missing 5 / 4 for class 2/parser; 5 / 5 for entropy
0x0030, 0x0031 Header CRC8, frame CRC16 mismatch 6 / 4
0x0032 Nonzero STREAMINFO total differs at complete-frame EOF or is exceeded 4 / 4
0x0040 Malformed entropy/partition encoding 7 / 5
0x0041 Invalid wasted-bit count 7 / 5
0x0042 Invalid Rice escape/partition sample count 7 / 5
0x0043 Reconstruction or restored sample out of range 22 / 6
0x0050 Unsupported output rate/channel/flag combination 3 / 0
0x0051 Destination capacity exhausted 8 / 8
0x0052 Invalid context/cursor/commit/final-marker contract 11 / 11; uses existing sequencer reason-9 trap detail, not codec detail

Structural APB rejections still return PSLVERR without inventing a new codec result. For unsupported ring descriptors, reason 1 uses descriptor CONTROL address rather than an input-file address. Transport/primitive/trap errors keep their existing P2/P3/P4 tuple (including PC addresses), and the job result copies that detail. The format table applies to microcode parser JOB_RESULT failures, not a reinterpretation of those lower-level failures. For output capacity reason 0x0051, use OUTPUT_ADDRESS+output_cursor for memory (response zero, stage 8, owning job index). A total-byte overflow on stream uses address zero and code 22/stage 8 with trap_detail(9); on memory it uses the checked next destination address, saturating at 0xffffffff if that address itself overflows. Invalid context reason 0x0052 uses the existing reason-9 fallback code 11/stage 11/index zero/PC address. When multiple parser checks at the same position fail, structural extent and reserved-bit errors precede unsupported-profile checks, then CRC checks; the first check in field order otherwise wins.

The released P5 APUMC uses V2.0 and still contains exactly three entries. Instruction word 0 is always 0x0200000001000001 (unconditional class-0 TRAP, detail 0x01000001). The MP3 entry at descriptor index 1 has the exact eight words [0x00000001, 0, 0, 0, 1, 1, 0, 0]: entry/first/last PC zero, zero scratch, table and primitive mask, maximum loop/retired one. A verification-only launch of it produces code 11/stage 11/response 0/index 0/address 0/detail 0x01000001, retired zero. Public MP3 requests are rejected with unsupported format before reaching that trap. WAV and FLAC entries start after PC 0; their masks contain the primitives they declare and may share read-only tables and scratch as already allowed. The header mask is the OR of entries, not forcibly 0x001fffff; the implemented mask advertises hardware capacity.

Deferred APU-P6 design archive — not current-release requirements

P6 MP3 profile, compatibility, and capacity

Status: DEFERRED. Everything in this archive through the following closing details marker, including its capability/target, active-MP3 entry, packing and MP3 decode rules, is retained for future design reference only. It is not normative for the current release and cannot authorize implementation or advertising MP3. Reactivation requires an explicit refreeze. The current release uses the P5 WAV/FLAC image and MP3 stub, with MP3 capability bit 1 zero.

This refreeze is grounded in code baseline 836371663feff6554ee923bb63a6a42978f4d777. Its P5 microassembly contains 4073 instructions, leaving 23 of the 4096 words unused. This establishes that appending a decoder to the current layout is not a credible capacity plan; it does not establish a size for a reorganized complete P6 bundle.

P6 property Archived proposal (inactive for this release)
Discovery CAPABILITY0=0x000001bf, CAPABILITY1=0x01827020, IP_VERSION=0x00010001, ABI_DIGEST=0. MP3 bit 1 becomes implemented; KWS bit 6 remains zero.
Image and ISA Add target p6, default APUMC V2 / MC_ABI=0x00020000, mask 0x001fffff, existing classes 0..6 and 12-bit PC/branches. Preserve p3/p4/p5 targets and V1 rejection/compatibility rules. p6 may explicitly read/emit V1 within its 2048-word limit; the production P6 release is V2.
Job and route Operation 0, formats 0 WAV, 1 MP3, 2 FLAC, direct/ring, memory or TX stream. RX route 1, KWS, model loading and other formats remain unavailable. No new register offset, IRQ, resource index, system master, pad, clock or CDC/RDC allocation.
Resident image One boot-loaded, validated and hard-reset-locked three-entry bundle contains all three real decoder entries. It replaces the P5 release image as a whole; MP3 entry 1 is no longer the P5 trap stub. No per-job reload, overlay, host parsing/decoding, C/DSP core, or unlocked code bank is introduced.
Hard limits 4096 total 64-bit words including every entry/common routine/padding; 32 KiB control store and 112 KiB data store. P4/P5 local partitions and published PCM/transport/HAL semantics are retained. No implicit 8192-word expansion or new ISA operand mode is authorized.
Allowed compaction The P6 emitter may regenerate, relocate, share routines and tables, change register allocation, tile kernels, and remove provably unreachable/duplicate instructions. It may not delete supported P5 paths, weaken diagnostics, change P4 arithmetic, or move parser decisions into RTL. No fixed fraction of the store is reserved for MP3; the only code budget is the complete 4096-word image.

Before changing production RTL or advertising P6 capability, implementation must produce a complete three-format microassembly packing report and a local table/scratch live-range report, covering MP3 and every P5 path. The current 4073-word layout is not immutable inside the new image; the committed P5 image and its builder/fixtures remain reproducible compatibility artifacts. Passing P6 means the new image also passes the P5 corpus with identical PCM, parsed input/output/frame accounting, acceptance/rejection, and semantic error tuple. Build IDs, code PCs, retired counts and cycle measurements naturally describe the new image; their definitions and PC-to-symbol diagnostics stay unchanged. Packing is the first bounded implementation milestone, not an artifact this documentation-only refreeze claims to have produced. Preflight must distinguish a decision-complete contract from an unproven packing result and make the packing gate visible before authorizing downstream production changes.

The packing gate must include all MP3 parsing, reservoir/Huffman/scalefactor, requantization/reorder/antialias/stereo, long/start/short/stop IMDCT, overlap, polyphase synthesis, output/resampling and error paths. P5 coefficient banks and its FLAC workspace cannot simply be displaced by MP3 tables. MP3 may reuse scratch between nonoverlapping lifetimes, generate coefficients there with the existing arithmetic, and use explicit table/bit-reader routines; it cannot reinterpret the P4 canonical-Huffman, REQUANT, or DCT32_POLY opcode semantics as a different hardwired MP3 operation. The report must show the actual lowering to existing primitives and its numerical/latency evidence. The existing 24 KiB combined codec table/scratch ceiling applies to the complete bundle, not independently to each static table image.

If those complete packing reports exceed code or data limits, return SPEC_CONFLICT before downstream implementation; do not claim that this refreeze proves the three decoders fit. Increasing capacity or changing the ISA requires a separate explicit architectural refreeze. This is an evidence gate with an exact budget, not permission to omit unimplemented branches.

P6 hardware continues to accept supported legacy images. It must recognize the exact P5 entry-1 trap descriptor/body already specified and reject a public MP3 job against that stub before executing it: direct start returns PSLVERR with no job mutation; an owned ring entry completes code 3/stage 2/detail 0x01000001 at its CONTROL address. WAV/FLAC jobs remain legal. Release software uses the manifest of the loaded image when selecting formats; CAPABILITY0 describes hardware and alone does not certify arbitrary loaded microcode. The P5 verification-only stub launch keeps its original trap tuple.

P6 file, header, and metadata rules

P6 accepts finite elementary Layer III streams, at most 0x7fffffff input bytes, with the following exact subset. Bitstream constants are cross-checked against the pinned independent decoder sources in the P6 reference section; ID3 framing follows ID3v2.3 and ID3v2.4. Reference decoder tolerance does not override the rejection rules here.

Field or structure Accepted values and required handling
Leading ID3 Zero to four consecutive ID3v2.2/2.3/2.4 tags at byte zero, revision 0. Each has a complete 10-byte header and four synchsafe size bytes with high bits zero. Total skipped tag bodies, headers and footers must be at most 1 MiB. There is no arbitrary junk search before the first audio frame.
ID3 flags v2.2 allowed mask 0xc0; v2.3 0xe0; v2.4 0xf0. Other flag bits fail. Tag body is an opaque skip of the declared on-disk bytes, including unsynchronisation, compression and any extended header; no ID3 text/CRC/decryption semantics are claimed. v2.4 footer bit 0x10 adds 10 bytes beyond header+body and requires 3DI plus identical version/flags/size fields. Other versions have no footer. Checked range arithmetic precedes the skip.
MPEG version Header version bits 3 MPEG-1, 2 MPEG-2, 0 MPEG-2.5; value 1 is reserved and fails. Layer bits must be 1 (Layer III); Layers I/II are unsupported.
Bitrate Indices 1..14 use the exact tables below. Index 0 (free format) is always unsupported, even if a reference can infer its frame length; index 15 is malformed. No scan-ahead free-format heuristic.
Sample rate Index 0/1/2 uses the exact table below; index 3 is malformed. Version and rate are constant for the entire job.
Channels/mode Modes 0 stereo, 1 joint stereo, 2 dual channel produce two channels; mode 3 produces one. Stereo/dual/joint may switch without changing channel count. A mono/stereo transition is rejected. Both joint-stereo extension bits (intensity and MS) are supported; extension bits are ignored outside joint mode.
Other header bits Padding 0/1 and bitrate may change per frame (CBR/VBR/ABR accepted). Protection may change; zero means the two-byte CRC is present. Private/copyright/original bits are accepted without affecting output. Emphasis 0 is supported, 1/3 are unsupported, and reserved 2 is malformed.
Frame byte count MPEG-1: floor(144000*bitrate_kbps/rate_hz)+padding; MPEG-2/2.5: floor(72000*bitrate_kbps/rate_hz)+padding. The count includes header/CRC/side-info and must fit the input and be at least their sum. Maximum supported frame length is 1441 bytes.
Side-info size MPEG-1: 17 bytes mono, 32 stereo; MPEG-2/2.5: 9 mono, 17 stereo. Two granules/frame for MPEG-1, one for MPEG-2/2.5; every granule/channel represents 576 samples.
Geometry changes Reject version/rate/channel-count changes at the first differing header field. Expected nonzero INPUT_CONFIG rate/channels must match. MP3 has no encoded PCM bit depth: P6 reports decoded source precision 24; expected bits is zero or 24, otherwise unsupported.
End tags One final 128-byte ID3v1 block beginning TAG is accepted and consumed in either strict mode. No APE or midstream ID3 parsing. Other trailing bytes are rejected in strict mode and ignored only after at least one complete audio frame in relaxed mode. A partial sync/header or a valid next header whose frame is truncated is always an error, not relaxed trailing junk.
VBR metadata Xing/Info/VBRI/LAME ancillary bytes do not supply authoritative duration, seek points, gain, encoder delay, padding, or frame count. Their containing MPEG frames are decoded/count normally. No gapless trim or ReplayGain is applied; actual validated frame headers determine accounting.
MPEG family Bitrate indices 1..14, kbit/s Rate indices 0,1,2, Hz Samples/channel/frame
MPEG-1 32,40,48,56,64,80,96,112,128,160,192,224,256,320 44100,48000,32000 1152
MPEG-2 8,16,24,32,40,48,56,64,80,96,112,128,144,160 22050,24000,16000 576
MPEG-2.5 8,16,24,32,40,48,56,64,80,96,112,128,144,160 11025,12000,8000 576

At least one complete audio frame is required; a tag-only or empty MP3 input returns malformed/no-audio. Frame boundaries follow the computed byte count. There is no silent resynchronization, concealment, skipped bad frame, or property-dependent restart inside a job. At an expected initial audio header, a nonempty remainder shorter than four bytes is truncated input. After a valid frame, a short suffix beginning with 0xff and matching the available MPEG sync/version/layer bits is a truncated header; other short suffixes follow the strict/relaxed trailing-byte rule. A recognized ID3 or TAG prefix with insufficient bytes for its required header/block is truncated in both modes. These checks precede a relaxed skip.

P6 side-info, reservoir, and integrity rules

Let P be the cumulative number of main-data slot bytes in all preceding frames, excluding their header, optional CRC and side-info. Let M be the current frame's main-data slot count and B=main_data_begin. MPEG-1 B is a 9-bit value 0..511; MPEG-2/2.5 B is 8 bits 0..255. The current coded data starts at byte P-B of that main-data-only stream. At job start history and overlap are zero/empty, so the first frame requires B=0. Retain the last 511 main-data slot bytes plus current frame slots, at most 1952 bytes. Headers, ID3 and CRC bytes never become reservoir bytes. Reset/abort or the next job clears this history; it is never shared between ring jobs.

Require B no larger than actual retained history. The start bit must not precede the previous frame's consumed main-data end bit, and the sum of all part2_3_length values must end no later than 8*(P+M). Ancillary gaps and byte-alignment stuffing between coded frame payloads are allowed. A reference decoder that substitutes silence on reservoir underflow does not define P6 behavior: P6 terminates without PCM from the affected frame.

Side-info is parsed in transmitted granule/channel order. Each big_values is 0..288; each part2_3 length is a 12-bit bit budget, not a byte count. Reject reserved codebook selections 4/14 and region boundaries outside 576 lines. Table 0 produces zero pairs without consuming Huffman bits. Window switching requires block_type 1/2/3; mixed_block is legal only with short block type 2. Support long/start/short/stop and mixed blocks, MPEG-1 scfsi/preflag, MPEG-2/2.5 scalefactor-compress and intensity rules, scalefac_scale, subblock_gain, both count1 tables, all nonreserved pair codebooks and linbits. Scalefactor bits are charged against part2_3 before Huffman data. Pair/quad decoding cannot publish past line 575 or consume another part's bit budget; remaining uncoded lines are zero and legal count1 termination/stuffing is handled without reading beyond that budget. Truncated physical input and a budget violation are distinct errors.

When protection is zero, read the stored big-endian CRC16 immediately after the four-byte header. Compute MSB-first CRC with initial 0xffff, polynomial 0x8005, no final XOR, over the header's final 16 bits (bitrate index through emphasis), followed by all side-info bits in transmitted order. Exclude the stored CRC and main-data bytes. CRC checking is mandatory in strict and relaxed modes. It is MPEG error protection, not a whole-audio checksum. The existing CRC16 primitive can use this nonzero initial accumulator; its opcode behavior does not change.

No PCM from a frame is issued until its complete physical byte range, side-info, CRC (when present), reservoir range and compressed-sample decode have passed. Earlier valid output remains on later failure. Synthesis history may be updated speculatively only if it cannot affect another job after an error. Source bit extraction may use bounded scalar/table routines on the saved reservoir; the original input FIFO is not rewound or fed duplicate header bytes. The P5 explicit refill/cursor/EOF contract remains unchanged.

P6 PCM, counts, and first-offender diagnostics

MP3 decoding includes requantization, short-block reorder, alias reduction, joint-stereo reconstruction, windowed IMDCT/overlap-add, frequency inversion and synthesis polyphase filtering, in MPEG order. Intermediate representations and coefficient realization must lower to the existing fixed-point primitives and are qualified by the bit-accurate lowering report and the numerical gates below. No synthesis stage or frequency band may be dropped to meet capacity. Decoded samples enter the P5 post-processing path as signed Q1.31. Native S24_32 output is the arithmetic right shift by 8 with saturation; S16 is the right shift by 16. P5 downmix, duplication, resampling, capacity, TLAST, and whole-output-frame rules are inherited exactly. The reported precision 24 describes the canonical decoded PCM representation; already normalized MP3 Q1.31 samples must not be shifted left again as if they were raw 24-bit input samples.

Count every decoded MPEG frame including Xing/Info/VBRI-containing frames. Native source sample-frame count is 1152 per MPEG-1 frame or 576 per lower rate frame. No leading synthesis delay, encoder padding, or final samples are trimmed, and no extra overlap tail is flushed beyond that count. JOB_FRAMES/descriptor RESULT_FRAMES count destination PCM sample frames after P5 rate conversion, not MPEG frames or channel samples. SOURCE_INFO contains rate, 1/2 channels, and precision 24. INPUT_USED is the parsed physical file prefix including accepted ID3 tags and frame bytes, never reservoir rereads or prefetched bytes. Relaxed ignored trailing junk is excluded. Output bytes/partial output and all direct/ring completion ordering remain P5 rules.

For MP3 parser failures, DETAIL [31:24]=1, [23:16] is warnings, and [15:0] is the reason below. Warning bit 1 means relaxed trailing bytes were ignored; other MP3 warning bits are zero. On success reason is zero. Each row sets ERROR_STATUS valid=1, response=0, direct index=0 or owning ring index, with the specified code/stage. Addresses below are absolute input addresses: F is the current four-byte MPEG header address, S=F+4+crc_bytes, and a field address is the byte containing the first transmitted bit of that field. For reservoir-derived entropy bits, retain their original physical-byte provenance across frames; do not report a scratch pointer as an input address.

Reason Failure Code / stage First-offender address
0x0100 Unsupported ID3 major/revision 3 / 4 Tag start + 3
0x0101 Reserved ID3 flags 4 / 4 Tag start + 5
0x0102 Nonsynchsafe ID3 size 4 / 4 First size byte with bit 7 set
0x0103 ID3 count/1 MiB limit or extent arithmetic overflow 3 / 4 for limit, 4 / 4 for overflow Offending tag start
0x0104 ID3v2.4 footer mismatch 4 / 4 First differing footer byte
0x0110 Missing sync/no audio/invalid reserved version 4 / 4 F (no audio: parsed tag end)
0x0111 Unsupported layer 3 / 4 F + 1
0x0112 Free-format bitrate index 0 3 / 4 F + 2
0x0113 Bitrate index 15 or rate index 3 4 / 4 F + 2
0x0114 Unsupported/reserved emphasis 3 / 4 for 1/3, 4 / 4 for 2 F + 3
0x0115 Frame shorter than its mandatory structures 4 / 4 F + 2
0x0116 Version/rate/channel-count change 4 / 4 First changed field in header byte order
0x0117 Expected source-geometry mismatch 3 / 4 First offending version/rate/mode field; expected precision mismatch uses F
0x0120 Mandatory ID3/header/side-info/frame bytes missing 5 / 4 INPUT_ADDRESS + INPUT_LENGTH
0x0121 Strict unrecognized trailing bytes 4 / 4 First trailing byte
0x0130 Side-info big_values/window/codebook/region invalid 7 / 5 First invalid transmitted field
0x0131 Reservoir history underflow 7 / 5 S (main_data_begin field)
0x0132 Reservoir overlap or summed part2_3 range violation 7 / 5 S for overlap; first part2_3_length field making the sum exceed available bits otherwise
0x0133 Scalefactor/entropy part budget invalid 7 / 5 Start of that part's first undecodable code, mapped to physical input
0x0134 Illegal Huffman prefix/line count 7 / 5 First offending code's original physical byte
0x0140 Stored MPEG CRC mismatch 6 / 4 F + 4

Within a frame, validate complete header and its range, then side-info field legality, then MPEG CRC, then reservoir bounds, then scalefactors/entropy. A missing mandatory byte outranks checks that require that missing structure; an already invalid earlier header is reported without reading later bytes. Within side-info use transmitted bit order and granule/channel order. Global AXI/DMA/xrun/trap/abort precedence and immutable-first-error capture remain unchanged. Primitive/kernel overflow, sequencer faults, and output-capacity errors retain P4/P5 tuples and PC_HIGH handling; they are not relabeled as one of these parser reasons. HAL status mapping treats format 1 explicitly: MP3 uses CAPABILITY0 bit 1 and these codes, not the previous non-WAV-to-FLAC fallback. Existing job/result structures and API signatures are retained.

APUM KWS model ABI

This is the first byte-level definition of APUM 1.0; no P1..P5 implementation accepts an APUM image. All multibyte fields are little-endian, offsets are byte offsets, signed integers are two's complement, and padding/reserved bytes MUST be zero. APUM is not a TFLite FlatBuffer and is independent of APUMC and APB versions. P7 accepts only the graph/quantization below, not a general NPU graph.

APUM header and layout

The image base is 64-byte aligned. The header is exactly 64 bytes. The image is exactly 32768 bytes: 12 operator records at 0x0040, 13 tensor records at 0x0340, zero padding at 0x04e0..0x04ff, parameters at 0x0500..0x768f, and zero tail padding at 0x7690..0x7fff. There are no external pointers, compressed parameters, optional sections, alias records, or variable shapes.

Header byte Type Field / required P7 value
0x00 u32 Magic 0x4d555041 (bytes APUM).
0x04 u32 APUM ABI 0x00010000.
0x08 u32 Total image bytes 32768.
0x0c u32 Operator-set ID 1.
0x10 u32 MFCC rows [15:0]=49, coefficients [31:16]=10.
0x14 u32 Classes [15:0]=12, operator count [31:16]=12.
0x18 u32 Parameter bytes 29072, starting at fixed offset 0x0500.
0x1c u32 Scratch reservation 32768 bytes, separate from image bytes.
0x20 u32 Quantization profile ID 1, defined below.
0x24 u32 CRC-32/ISO-HDLC over bytes [64,32768), including padding.
0x28 u64 Model ID 0xce4f70006843eaae; first eight SHA-256 digest bytes of the pinned TFLite, interpreted little-endian.
0x30 u32 Default threshold [7:0]=128, debounce [15:8]=3, upper bits zero.
0x34 u32 Tensor count 13.
0x38 u32 Scratch-layout ID 1.
0x3c u32 Reserved zero.

CRC uses reflected polynomial 0xedb88320, initial state 0xffffffff, bytes in increasing address order, and final XOR 0xffffffff (123456789 gives 0xcbf43926). The header CRC word and KWS_MODEL_EXPECTED_CRC MUST both equal the observed payload CRC. Header fields are validated separately; neither CRC nor the truncated model ID authenticates an image. The complete upstream SHA and generated-image SHA belong in the host release manifest.

An independent freeze-time in-memory packing of the pinned model under these rules gives the following golden values. The implementation converter MUST reproduce them; these are computed bytes, not a claimed RTL/converter test.

Golden object Required value
Payload CRC / production expected CRC 0xb9034b22
Complete 32768-byte APUM SHA-256 87861b5f866182969e34917b4bf57cab61cd2245c3ab9b933797209322e3ce63
Parameters [0x0500,0x7690) SHA-256 0e4eb210d247a45747049ef9602bbd7e90868e9cb1c04fb2a02f128db44e241e
Weighted operators' multiplier then shift arrays, graph order, no delimiters, SHA-256 222e05821695f3fdd47be682b2cc75e0e735aa106436bf941cdda3ef8cb03b59

The corresponding 64-byte header, consecutive hexadecimal bytes, is:

4150554d00000100008000000100000031000a000c000c009071000000800000
01000000224b03b9aeea436800704fce800300000d0000000100000000000000

The runtime CRC check compares observed/header/register values as specified; it is not a SHA validator or authorization for a differently trained release model. The release flow additionally requires the complete golden APUM hash.

Each operator record is 64 bytes:

Byte in record Type Meaning
0x00 u16 Opcode: 1 Conv2D (also pointwise), 2 depthwise, 3 average pool, 4 fully connected, 5 Softmax.
0x02 u16 Flags: bit 0 fused ReLU; all others zero.
0x04, 0x06 u16 each Input and output tensor IDs.
0x08, 0x0c u32 each Image-relative weight and bias offsets.
0x10, 0x14 u32 each Image-relative Q31 multiplier and signed-shift array offsets.
0x18, 0x1c u32 each Weight byte count; output channel count.
0x20, 0x22 u16 each Kernel height and width.
0x24, 0x26 u16 each Height and width stride.
0x28..0x2b u8 each Top, bottom, left, right zero-point padding.
0x2c, 0x30 i32 each Input and output zero points.
0x34, 0x38 i32 each Inclusive output clamp minimum and maximum.
0x3c u32 Reserved zero.

Convolution weights are signed INT8 in [out,h,w,in] order; depthwise weights are [1,h,w,channel], depth multiplier one; FC weights are [out,in]. All weight zero points are zero. Bias, multiplier and shift arrays contain one signed-32 word per output channel. FC's single source scale is broadcast to 12 output channels. For each weighted operator in graph order, append weights, biases, multipliers, then shifts, each 16-byte aligned. These arrays total 22016 + 2352 + 2352 + 2352 = 29072 bytes; no array is deduplicated. Pool and Softmax have zero in all four parameter offsets and weight-byte count. FC and Softmax use kernel/stride 1 by 1 and zero padding. Pool uses kernel/stride 25 by 5, VALID padding. Pool/FC/Softmax have no ReLU; clamp is -128..127.

Each tensor record is 32 bytes: u16 N,H,W,C at bytes 0,2,4,6; u32 scratch-relative offset at 8; u32 byte count at 12; u32 element type 1=INT8 at 16; u32 IEEE-754 binary32 scale bits at 20; i32 zero point at 24; u32 zero at 28. Scale bits are immutable metadata checked against the pinned tensor table, not permission to execute floating-point arithmetic in hardware. Byte count equals N*H*W*C, checked without overflow. All tensors are NHWC, batch one. Pool/FC tensors use the four-dimensional shapes below; the upstream reshape changes no bytes and creates no APUM operator or additional buffer.

P7 fixed graph and quantization profile 1

The immutable source is TFLite SHA-256 aeea436800704fce17b17292e4412630ad856e9d777c044c64ef748a880bd0ae. The binary, not a freshly trained Keras graph or its prose README, is the authority for every weight, bias and per-channel scale. It contains 13 TFLite operators and 35 tensors; folding only reshape yields the 12 operators and 13 activation tensors below. Batch normalization and ReLU are already fused.

APUM tensor Producer / source TFLite output Shape N,H,W,C Scale bits / zero point Scratch offset
0 MFCC / 0 1,49,10,1 0x3f15af17 / 83 0x4000
1 Conv 10x4, stride 2x2 / 22 1,25,5,64 0x3da13ac8 / -128 0x0000
2 Depthwise 3x3 / 23 1,25,5,64 0x3da99aea / -128 0x2000
3 Pointwise 1x1 / 24 1,25,5,64 0x3d75dd81 / -128 0x0000
4 Depthwise 3x3 / 25 1,25,5,64 0x3d808854 / -128 0x2000
5 Pointwise 1x1 / 26 1,25,5,64 0x3d19329e / -128 0x0000
6 Depthwise 3x3 / 27 1,25,5,64 0x3d3c02c1 / -128 0x2000
7 Pointwise 1x1 / 28 1,25,5,64 0x3d070c5a / -128 0x0000
8 Depthwise 3x3 / 29 1,25,5,64 0x3d3fdf8a / -128 0x2000
9 Pointwise 1x1 / 30 1,25,5,64 0x3da452db / -128 0x0000
10 Average pool 25x5 / 31 (32 aliases 31) 1,1,1,64 0x3da452db / -128 0x2000
11 FC 64 to 12 / 33 1,1,1,12 0x3e142a46 / 14 0x0000
12 Softmax beta 1 / 34 1,1,1,12 0x3b800000 / -128 0x2000

Operator i consumes tensor i and produces i+1. First-convolution padding is top 4, bottom 5, left 1, right 1. Depthwise padding is one on every side; pointwise has zero padding. All other convolution strides are one, dilation is one, and all nine convolution operators fuse ReLU. The source weight/bias tensor pairs in weighted-operator order are (17,3), (5,4), (18,6), (8,7), (19,9), (11,10), (20,12), (14,13), (21,15), (16,1). Per-channel scales use the source quantized dimension (Conv axis 0, depthwise axis 3); FC is per-tensor. No recalibration, retraining, bias re-rounding, channel permutation, pruning, or alternative model is part of P7.

For output channel c, accumulate bias[c] + sum((input-zin)*weight[c]) in signed INT32 with checked wider intermediates, in h,w,input-channel order. Padding contributes input=zin. Overflow is an arithmetic fault, not wrap or silent accumulator saturation. Convert the effective multiplier double(input_scale)*double(weight_scale[c])/double(output_scale) with the pinned TFLite QuantizeMultiplier: binary64 operations without contraction, frexp, positive nearest/ties-away Q31 rounding, carry renormalization, and the upstream shift-below-minus-31 flush. Record the resulting Q31 word and shift, not a decimal approximation. Runtime requantization uses the pinned MultiplyByQuantizedMultiplier double-rounding behavior: checked left shift, SaturatingRoundingDoublingHighMul, then RoundingDivideByPOT. Add zout and clamp to [max(-128,zout),127] for ReLU, otherwise [-128,127]. Do not replace these rules with nearest-even rounding or single-rounding DSP modes.

Average pool sums the 125 signed input bytes in INT32 and divides by 125 with nearest rounding, ties away from zero, retaining the same scale/zero point; it is not the 24x5 pool suggested by the training source's shape calculation. Softmax is the pinned tflite::reference_ops::Softmax<int8_t,int8_t> with input_multiplier=1242899200, input_left_shift=24, diff_min=-124, Q5.26 scaled differences and Q12 accumulation, using the pinned gemmlowp fixed-point exp/reciprocal routines. The host oracle and RTL must agree on all twelve output bytes, including underflow, saturation and tied maxima. No float exp, alternative LUT approximation, omitted Softmax, or CMSIS-NN rounding substitution is permitted in the inference reference path.

P7 memory and loader validation

The existing KWS partition remains banks 10..25, local 0x0a000..0x19fff, 64 KiB total. Banks 10..17 hold the 32 KiB APUM; banks 18..25 are the 32 KiB scratch reservation. Codec/control-store banks, Gateway A identity, IRQ and resource allocations do not change. A new independently arbitrated KWS client may access only these KWS banks; it cannot borrow codec buffers or MAC lanes.

P8 maps each of these sixteen logical banks to one tc_sram_1024x32 wrapper. Within the APUM and scratch halves, physical bank is byte offset [4:2] XOR [8:6] and wrapper word address is byte offset [14:5]; this reversible word-interleaving distributes both consecutive and fixed 64-byte stride lanes without changing logical addresses. Every bank accepts at most one read or write per PCLK. The client snapshots one fixed-engine operand vector, coalesces duplicate word reads, issues at most one access per bank per cycle, and stalls the KWS state transition until every synchronous read and required write has retired. A model load is globally idle and has exclusive access; for engine traffic a write wins a same-bank read and the read remains pending. Successful bank activity resets the KWS no-progress watchdog, while a wedged client remains bounded by that watchdog. HAVE_SRAM_MACRO=NO uses the same bank selection, one-cycle read latency, arbitration, and stall contract with inferred arrays. This internal scheduling changes no APUM address, tensor, scratch, register, descriptor, result, or error ABI and must re-pass the P7 accuracy, cycle, concurrency, xrun, abort, reset, and handoff gates.

Scratch layout 1 has A at 0x0000..0x1fff, B at 0x2000..0x3fff, MFCC at 0x4000..0x41ff, a 50x40 u32 raw-mel ring at 0x4200..0x61ff, complex FFT workspace at 0x6200..0x71ff, 768 S16 ingress samples at 0x7200..0x77ff, and metadata at 0x7800..0x7fff (peak ring, FIR state, counters, pending stereo word and reduction state). A/B lifetimes alternate exactly as in the tensor table. Scratch range checking cannot treat the entire 112 KiB local store as available. The one-second history is retained as raw mel bands plus peak metadata, not an additional unbudgeted 32000-byte PCM buffer. Immutable frontend coefficients are immutable numerical constants generated from the numerical recipe. Pre-P9 uses generated engine ROM functions; P9 requires the separately loaded and locked macro-backed coefficient store below. Report that auxiliary storage independently from these sixteen KWS banks.

MODEL_LOAD is LP-only, globally idle and quiesced, KWS disabled, ACL-valid and model unlocked. Fetch/validate header first, then exact-size payload and CRC, then records, ranges and quantization. Validate every fixed field, zero byte, opcode, tensor ID, shape, scale/zero point, array length/alignment, graph edge, padding/stride, scratch lifetime and parameter region before publishing valid. Unsupported major/minor/quantization/operator-set/layout versions fail closed. The loader MUST compare the records and requantization arrays with the frozen profile; arbitrary parameters with internally consistent but different shapes or arithmetic do not become a second supported model. All address additions are checked; no DMA may escape the inclusive read ACL or image range.

An accepted load clears previous unlocked loader diagnostics and actual CRC, sets busy and keeps valid clear. Success atomically publishes valid/locked and the observed CRC, applies the header defaults to KWS_CONFIG and raises IRQ 4. Any failure leaves valid/locked clear and execution disabled, records the specified error and raises terminal IRQ 4 plus first-error IRQ 8. A retry is allowed only after draining and clearing/recovering the error. A successful lock cannot be cleared or reloaded by software, HP, abort, soft reset or resource reset; only hard/PCLK reset invalidates it. An aborted partial load never publishes valid or raises a successful-load indication.

P7 frontend numerical profile 1

This profile closes the former 10 ms/49-row contradiction: a one-second, 16000-sample mono window uses 480-sample (30 ms) frames, 320-sample (20 ms) hop, and a 512-point FFT. Frame r uses samples 320*r .. 320*r+479, r=0..48; the last 160 samples contribute to the normalization peak but not to a frame. Inference windows end after samples 16000,17600,19200,... in continuous mode. There is no pre-emphasis, DC removal, noise augmentation, AGC, dither, lifter, center padding or trailing STFT padding. The frozen floating reference is the pinned get_dataset.py MFCC branch, not its LFBE/microfrontend branch.

Let RNE denote exact nearest integer with ties to even and TZ truncation toward zero. All constant generation uses increased precision with interval bounds until rounding is unambiguous; independently generate and compare the ROM words, and put their SHA-256 and profile ID in every release report. Host math-library defaults are not the numerical specification.

  1. Input is signed S16 after the capture conversion below. Use the positive peak P=max(1,max(x[0..15999])), not max absolute value. The max(1,...) rule explicitly defines silence/all-nonpositive inputs where the upstream division would otherwise be invalid or unsuitable. On the official corpus the positive-peak rule is unchanged. Retain maxima for 100 successive 160-sample blocks so each rolling window has its own exact P.
  2. Hann coefficients are H[n]=RNE(2^30*(1-cos(2*pi*n/480))/2), n=0..479. Build a 512-element complex input with real part RNE(x[n]*H[n]/2^15) and imaginary zero; n=480..511 is zero. This carries 15 fractional bits of the unnormalized S16 value. Do not normalize each frame with a different peak.
  3. Use radix-2 decimation-in-time FFT, bit-reversed input, stages of length 2,4,...,512 and ascending butterfly indices. Twiddles are independently RNE-quantized Q2.30 cos and negative sin. For each complex multiply, form both signed-64 sums of products before one RNE divide by 2^30; butterfly sum/difference is then RNE divided by two at every stage. Components are signed-32; overflow faults rather than wrapping. Thus final components represent the unscaled DFT times 64. Keep bins 0..256 and use nearest integer square root of the unsigned-64 sum of component squares (ties even); no magnitude-squared/power substitution or log10 is allowed.
  4. Define mel(f)=1127*ln(1+f/700). Forty triangular filters have 42 evenly spaced mel edges from mel(20) to mel(4000). Convert those edges back to Hz and evaluate the linear triangle ramps in Hz at f[k]=16000*k/512, as in the committed generator/BAM; this clarifies the coordinate convention without changing any committed coefficient. Clamp each to [0,1], force DC-bin weights to zero, and quantize weights to Q2.30 using RNE. For each band store M=RNE(sum(magnitude[k]*weight[k])/2^32) as unsigned UQ28.4. This is raw, unnormalized magnitude, not power. Products/reduction use unsigned 64-bit checked arithmetic. A 50-row ring holds these 40-word frames.
  5. At a window endpoint, capture P and the 49 corresponding mel rows. For each band form the positive rational z=(1000000*M+16*P)/(16000000*P); this is M/(16*P)+1e-6. Normalize z exactly as 2^e*m, 1<=m<2. The fixed log table contains L[i]=RNE(2^24*ln(1+i/1024)), i=0..1024, and LN2=RNE(2^24*ln(2)). Set i=floor(1024*(m-1)) and f=RNE(65536*(1024*(m-1)-i)), allowing f=65536. Output signed Q8.24 e*LN2+L[i]+RNE((L[i+1]-L[i])*f/65536). Integer divisions and exponent selection must use the exact rational; no intermediate float is implied.
  6. DCT coefficients are D[j,b]=RNE(2^30*sqrt(2/40)*cos(pi*(b+1/2)*j/40)), j=0..9,b=0..39. Compute C[j]=RNE(sum(log[b]*D[j,b])/2^30) in signed Q8.24 using signed-64 checked reduction. Coefficient zero has the same scaling as the other coefficients, matching TensorFlow MFCC rather than an orthonormal DCT-II.
  7. Quantize with q=TZ(C[j]/(2^24*S)+83) using the exact binary32 scale S=0x3f15af17. Store the low eight bits, interpreted signed INT8. This intentional modulo-256 conversion matches upstream NumPy INT8 export; it is NOT saturation. The published corpus includes 15 features in tst_000563_Go_1.bin for which saturation gives different bytes. This compatibility exception applies only at the MFCC boundary; inference requantization and PCM conversion retain their own saturation rules.

For the independently evaluated floating recipe on all 1000 reconstructed waveforms, 1381 of 490000 feature bytes differed from the published bytes when using saturation: 15 were the export-wrap case and the others were within one LSB. This 2026-09-11 host cross-check supports the corpus mapping and exposes the quantizer distinction; it is NOT fixed-point RTL accuracy evidence. P7 MUST implement a bit-accurate model (BAM) of the integer profile above and compare every frontend stage and every inference tensor against RTL. Report wrapped INT8 feature distance, per-stage error versus the floating reference, and end-to-end top-1 separately. No feature-distance tolerance waives the 900/1000 hardware top-1 gate, and no implementation may change the formulas or constants merely to improve that score without another refreeze.

P7 capture, scheduling, status and diagnostic operation

P7 appends one register; existing offsets and reserved masks are unchanged:

Offset Name Access / reset Meaning
0x23c KWS_INPUT_CONFIG RW disabled/idle; 0x0104bb80 Rate [16:0], physical channels [18:17], precision [25:20]; all other bits zero. Reset is stereo S16 at 48000 Hz.

This register is needed because AXI4-Stream audio has no rate/precision tag. It does not cause APU to read or write I2S APB registers. Legal continuous values are two physical channels, 16 or 24 bits, and 16000/48000/96000 Hz. The caller must configure matching I2S master/dividers/stream RX while I2S is disabled, then select RX route 1. The current I2S HAL's exact divider checks remain authoritative; programmable 16 kHz capture is a P7 integration test. Memory-window operation ignores KWS_INPUT_CONFIG and is always mono S16/16 kHz. Unsupported rates, mono physical I2S, or reserved fields return PSLVERR before state changes. P1..P5 continue returning PSLVERR at the new offset. Software must test KWS capability before access; IP_VERSION remains 0x00010001. KWS_INPUT_CONFIG uses byte-strobe merge and validates the merged full value, like KWS_CONFIG. KWS_CONTROL pulses/transitions require a full-word strobe.

S16 RX consumes the older low half then newer high half of each full 32-bit beat. S24 RX pairs consecutive beats using signed bits 23:0; upper bits are ignored. The mono pair is defined by wire order, not a nonexistent LRCK/channel tag: after flush, its first member is the first complete accepted sample, then the next sample. Do not infer left/right identity from a paused 24-bit stream. Downmix is arithmetic floor((older+newer)/2) in a widened signed accumulator. S24 is then arithmetic-shifted right eight and saturated to S16. TKEEP=TSTRB=0xf, no RX TLAST; malformed sidebands or unrecoverable half-pairs cause code 19/stage 9, clear history and stop KWS.

P7 exports the I2S wrapper's existing synchronized PCLK s_rx_flush_busy as a same-domain rx_flush_busy_o, connected to APU i2s_rx_flush_busy_i. This is an internal integration status wire, not an AXI sideband, APB register, pad or new CDC. It reuses the existing Common warm-flush detection, including unilateral audio reset. While asserted, APU must not accept RX data and must invalidate any pending half-pair/history; a live unplanned epoch loss counts one overrun and requires explicit restart. For planned quiesce/reset, use the existing non-error/forced-loss distinction. No new complete inference may contain samples from both sides of a flush.

At 16 kHz conversion is exact bypass. At 48/96 kHz use a dedicated 63-tap causal FIR and decimation D=3/6. With input indices starting at zero, emit at n=D-1,2D-1,... using sum(t=0..62,H_D[t]*x[n-t]), zero history for n<t. Let c=1/D, x=t-31, w=(1-cos(2pit/62))/2 and a=c*sinc(c*x)*w, sinc(z)=sin(piz)/(piz), sinc(0)=1. Quantize normalized coefficients to Q2.30 by RNE and add the unity-sum residual to tap 31. Use signed-64 reduction, RNE divide by 2^30, then S16 saturation. These 126 fixed coefficient words are independent of P5 codec resampler profiles/state. Record the 31-input-sample filter delay; do not trim it or silently resample the official mono16k diagnostic corpus. Neither this FIR nor the FFT may use codec microcode, codec scratch or codec MAC lanes.

KWS_CONTROL bits remain ENABLE 0, MEMORY_WINDOW 1 and CLEAR_HISTORY pulse 2. An enable rising edge latches continuous input/config, requires valid locked model and starts empty history. ENABLE=1/MEMORY_WINDOW=0 is continuous RX; value 3 arms memory-window operation without listening. Mode may change only disabled. Configuration/clear-history writes require KWS disabled and global idle, except KWS_CONFIG may be changed while memory mode is armed and no finite job is active. The full-word write that clears ENABLE while retaining mode and writing no pulse is additionally legal while KWS is active: stop admitting new work, finish the current feature/inference, drain accepted input/DMA, then become disabled. It does not abort a concurrent codec job. Mode/config changes during this drain are rejected. CLEAR_HISTORY resets feature/peak/FIR history, debounce and result-valid, but not the model, counters or IRQ state.

Global STATUS.IDLE and the resource idle output still require every client idle; continuous listening counts as busy until disabled or quiesced. P7 separates that global lifecycle condition from finite-job admission: job/ring configuration and codec START/RING_KICK may proceed when the finite-job path is idle even while continuous KWS runs. This narrow admission exception does not permit ACL/model/microcode/route/reset changes during listening. Configure and enable continuous KWS before starting concurrent decode. Quiesce drains the current KWS work, suppresses new windows and preserves enable/mode/model; release resumes with fresh history and a one-second warm-up. If a nonempty history was discarded, count one abandoned window, without first-error IRQ. Do not combine samples across the gap. Abort disables KWS; soft/resource reset clears enable/mode, capture/config registers to reset values, history, results, IRQs and counters while preserving valid locked model bytes and actual CRC. Forced loss and unilateral resets follow the existing error/CDC precedence.

Continuous inference begins only with a complete history, then every 1600 accepted 16 kHz samples. The deadline is the next such endpoint. The 49-row MFCC snapshot must be consumed before its oldest raw-mel row is overwritten; no partially updated input tensor may reach inference. A missed deadline, mel-ring overwrite or RX overrun abandons that window, increments overrun once, clears history/debounce, records code19/stage9 and stops KWS. Recovery is bounded disable/drain, RX flush, error/IRQ clear, history clear and enable; the validated model is retained. No silent catch-up, sample duplication or completion of a corrupted window is allowed. Frontend/inference watchdogs use the existing nonzero SEQUENCER_TIMEOUT as a maximum consecutive no-progress PCLK-cycle count independently per KWS work item. Progress means an accepted PCM sample, completed butterfly/band/feature, completed MAC reduction step or committed output tensor element, not merely an active state machine. Expiry is code14 at stage9/10 and quiesces the APU. Slow PCLK correctness tests may increase that timeout but may not claim 48 MHz real-time performance. DMA stalls continue to use DMA_TIMEOUT.

KWS_STATUS bit Meaning
0 Listening, live continuous capture (not quiesced/draining).
1 Inference busy, including preparation of its immutable MFCC snapshot.
2 History full, belonging to the current uninterrupted capture epoch.
3 Current published result is a stable hit (same as KWS_RESULT bit16).
4 Sticky overrun, cleared with the existing stream-xrun IRQ_STATE bit9 W1C or soft/resource/hard reset. A new overrun also raises IRQ9; hardware set wins clear.
5, 6 Model valid, model locked.
7 Result valid; at least one result has been published since history/reset clear.
31:8 Reserved zero.

KWS_MODEL_STATUS bits 0,1,2 are busy, valid, locked. Bits 8,9,10,11,12 are header, range, size, CRC and operator/quantization failure respectively; all other bits read zero. They are sticky until the next accepted unlocked load or reset, with exactly one semantic failure bit selected. Validation order is size, header fields in byte order, payload DMA/CRC, then records in byte order; range is checked before dereferencing each field. Failures use code12/stage1, except CRC uses code13/stage1. ERROR_ADDRESS is the first bad field's external byte address (size uses KWS_MODEL_SIZE's APB address; CRC uses model base+0x24), and ERROR_DETAIL is 0x07000000 | reason, reason 1=size, 2=header, 3=range, 4=CRC, 5=operator/quantization. AXI/timeout/abort faults retain their existing codes and precedence. Internal KWS arithmetic uses code14/stage9 or10, address equal to the failing local byte address, detail 0x07000100 | operator_index (frontend index 0xff). If new KWS and existing codec semantic faults coincide, the pre-existing global AXI/lifecycle/xrun precedence still wins; otherwise retain the codec fault, then KWS frontend, then KWS inference in that order. Model loading is globally exclusive. Collect every applicable sticky event/counter without overwriting the first error. Actual model CRC remains zero until the entire payload has been received, then reports the observed finalized CRC even if subsequent CRC/record validation fails.

Choose the lowest class ID on tied final INT8 scores. Class order is Down, Go, Left, No, Off, On, Right, Stop, Up, Yes, Silence, Unknown (0..11). Unsigned confidence is int32(softmax[class])+128 (0..255); threshold is an inclusive comparison. Only classes 0..9 can be hits. A run increments only for the same above-threshold keyword on consecutive completed windows; a different class starts at one, and silence/unknown/below-threshold/gap resets the run. Emit one stable-hit event when run count first reaches debounce (1..255), saturating the run count at debounce, not emitting on later matching windows. Hold hit for that uninterrupted run; re-arm on the first nonmatching/below-threshold result or explicit clear. KWS_RESULT holds every latest completed top-1 result, including non-hits; IRQ2 and HIT_COUNT change only on the event edge. IRQ W1C does not re-arm or clear the classifier history. Hardware set wins W1C.

The timestamp is the 64-bit PCLK timestamp of the accepted last sample of the evaluated one-second window, not the time software services the IRQ. Reading KWS_RESULT atomically latches its timestamp for subsequent LO/HI reads; a later inference cannot tear that pair. A read does not acknowledge IRQ or consume the result. Frame, inference, hit and overrun counters are unsigned-32 saturating: completed raw-mel frames, completed inferences, stable-hit edges and abandoned windows respectively. CLEAR_COUNTERS is globally idle-only and clears these without clearing model/history/IRQ.

Diagnostic operation 1 uses the existing direct/ring slot, not a second concurrent finite job. It requires valid locked microcode (compatibility admission only; no codec entry executes), valid locked model and memory mode armed; it is rejected while continuous KWS is enabled. CONTROL operation=1, format=0, output-mode=0, downmix/resample=0; INPUT_ADDRESS is four-byte aligned, INPUT_LENGTH=32000, INPUT_CONFIG explicitly mono/16000/16. OUTPUT_ADDRESS, OUTPUT_CAPACITY, OUTPUT_CONFIG and JOB_FLAGS are zero. This is the sole operation-1 exception to the decode rule requiring a nonzero memory output. All other reserved fields remain zero; OWN/IOC/cookie/ring ordering are unchanged. KWS_CONFIG is descriptor word9 for ring jobs and the KWS_CONFIG register latched at START for direct jobs. Each independent memory window clears debounce history and RESULT_VALID at acceptance, so debounce>1 returns hit=0 even when top-1 is a keyword. Accuracy uses top-1, not hit; use debounce=1 for standalone hit tests.

Success returns INPUT_USED=32000, OUTPUT_BYTES=0, FRAMES=16000, SOURCE_INFO=mono/16000/16, DETAIL=0 and the normal done/cycles/timestamps/cookie; descriptor word22 and KWS_RESULT contain the result. No PCM output DMA is issued. Direct reads use existing job result registers plus KWS_RESULT; ring reads use word22 before slot reuse. A failed/aborted operation sets word22=0, does not publish a fresh KWS result or inference/hit count, and uses existing terminal writeback/OWN-clear rules. Input-used is the contiguous number of successfully consumed bytes, a multiple of two, at failure. RESULT_FRAMES on failure is INPUT_USED/2; OUTPUT_BYTES stays zero. A ring may mix decode and operation1 entries while memory mode is armed, but cannot silently switch a running continuous listener into memory mode. Invalid raw direct requests return PSLVERR without payload DMA/result change; invalid owned ring requests use code2/stage2 at the first invalid descriptor word, DETAIL=0x07000200 | word_index, then normal error writeback.

P9 macro-backed auxiliary storage

Objective, inspected baseline and claim boundary

This is a storage/latency refreeze, not a smaller KWS network or a new numerical profile. Priority is physical macros first, exact multi-cycle processing second. Do not replace the tables with a larger combinational case/mux network, reset- initialized flops, a hidden duplicate register file, or approximate CORDIC/log/ polynomial coefficients to improve a memory statistic. Keep the 16 MAC lanes, the model/corpus/APUM hashes, all rounding/overflow rules and proof coverage.

The inspected source baseline is commit 0b73994772068e5fac00fb1a98f87f88ed121cdf:

Confirmed from source P9 action
apu_kws_sram_client.sv already has sixteen synchronous 4 KiB physical banks for APUM/scratch, operand coalescing and stall-until-retired control. Retain that implementation boundary; do not claim these 64 KiB as newly removed inferred memory.
apu_kws_rom.svh has 12948 32-bit words; apu_kws_apum_profile.svh has 1496 expected APUM words. Multiple combinational calls include repeated twiddle/log/Softmax lookups. Move all 14444 words (57776 logical bytes) to one shared, banked, immutable-after-load physical store.
apu_microcode_loader.sv stores 8192 full 64-bit memo keys and 8192 valid bits as inferred memories: 532480 bits. Replace both arrays with dedicated physical SRAMs; retain hashing, exact-key comparison and proof traversal.
The 4096x64 proof path stack is already eight SRAM wrappers, separate from eight control-store plus 28 local-data wrappers. Retain and count it; the full pre-P9 structural inventory is 44 wrappers, not just the 36 advertised-capacity wrappers.
apu_reg.sv reports pre-P9 V1.1, CAPABILITY0 0x1fd, CAPABILITY1 0x01827020, digest 0xf5005d7c with EnableP7. Append V1.2 coefficient discovery/control; regenerate the digest from the new complete tables.

The user-supplied synthesis note reports 1900786 whole-SoC inferred bits, 799680 KWS-table bits and 532480 memo bits for a 2026-09-23 IHP130 run, with the long-running pass after memory lowering being opt_dff -sat -nodffe -nosdff. Those remote raw logs were not available in this checkout and are not newly measured evidence. Inferred memories may be padded/duplicated by elaboration; the 462208 logical table bits above are not interchangeable with that tool statistic. Removing the two reported groups would arithmetically leave 568626 bits (about 70.1 percent lower), but that is a projection, not a synthesis speed, RSS or measured memory claim. Vexii and other IP memories are outside P9 scope. Fresh like-for-like reports below are required.

Stable requirements:

  • APU-P9-001: IHP130 macro builds MUST contain no inferred coefficient, APUM-profile, memo-key or memo-valid memories and no logic-array substitutes.
  • APU-P9-002: macro-backed APU inferred storage MUST fall by at least 90 percent versus the inspected baseline and total at most 65536 bits at the same pre-memory checkpoint. Small FIFOs, vector registers and metadata must be individually inventoried; target arrays may not be relabeled as metadata.
  • APU-P9-003: numerical outputs, accepted/rejected microcode programs, first errors, reset/ownership behavior and published results MUST remain equivalent apart from the explicitly appended coefficient-init protocol and latency.
  • APU-P9-004: extra cycles are permitted within the frozen 20 ms feature / 100 ms inference schedule, 48 MHz qualification and zero-xrun concurrency gates. Cold initialization is measured separately from steady-state latency.
  • APU-P9-005: completed same-configuration A/B synthesis, pass timing, peak RSS, standard-cell/macro area and STA evidence are mandatory. Smaller inferred-bit counts alone are not evidence of a faster or smaller chip.

Selected macro geometry and bank ownership

Reuse rtl/tech/tc_sram.sv::tc_sram_1024x32. Under the committed configs/ci/ihp130.mk (HAVE_SRAM_MACRO=YES), each wrapper is one RM_IHPSG13_1P_1024x32_c2_bm_bist with synchronous reads and byte write masks. Use the locked PDK/tool inputs; no new memory compiler or vendor macro is selected. Unsupported macro mappings fail elaboration rather than becoming flops or undriven wrappers. Non-macro profiles use synchronous inferred RAM with the same transactions and LP initialization; they establish functional compatibility, not the P9 inferred-memory reduction or physical acceptance.

Full P9 APU allocation 4 KiB wrappers Physical KiB
Control store 8 32
Codec/common local data 12 48
KWS model/scratch 16 64
Verifier path stack 8 32
Verifier memo keys 16 64
Verifier valid bitmap 1 4 (1 KiB used)
Coefficients plus APUM validation profile 15 60
Total 76 304

Thus P9 adds exactly 32 wrappers / 128 KiB to the 44-wrapper source baseline. Neither verifier nor coefficient banks alias existing code/data/KWS banks. CAPABILITY1 continues to describe 32 KiB control + 112 KiB local data, not 304 KiB software-addressable storage. Physical wrapper and PDK-cell counts are different on PDKs that assemble one wrapper from multiple macros.

The coefficient payload is fifteen banks of 1024 little-endian 32-bit words, bank-major. Payload word 1024*bank+row maps directly to that macro row. The following lossless placement avoids runtime frontend/Softmax bank conflicts without duplicating a lookup table:

Bank / row Stored words / index mapping
0 / 0..479 Hann[0..479]
0 / 480..879 DCT[j*40+b], j=0..9,b=0..39
0 / 880..942; 943..1005 FIR3[0..62]; FIR6[0..62]
1 / 0..255; 2 / 0..255 Twiddle real[0..255]; imaginary[0..255]
1 / 256..768 Log[2*r], r=0..512
2 / 256..767 Log[2*r+1], r=0..511
3..12 / 0..1023 Mel[i], i=0..10239, bank=3+floor(i/1024), row=i mod 1024
13 / 0..39 Mel[10240..10279]
13 / 40..1023 APUM fixed-profile words[0..983]
14 / 0..511 APUM fixed-profile words[984..1495]
14 / 512..636 Softmax exp[-difference], difference=0..124

All other 916 words are zero padding. The profile word order is the current generator's sorted unique APUM offsets: every word in [0,0x500), followed by the multiplier/shift arrays at the ten weighted-operator offsets. It is not a duplicate model or weight image. Preserve the existing candidate-offset selection: ordinary weight/bias words that are not profile candidates must not acquire an unintended comparison. LN2 remains scalar constant 11629080, not an additional ROM array.

APUC 1.0 image, identity and startup

SRAM has no specified power-on contents. A synthesizable initial/readmemh block, a macro INIT attribute, or a giant case-ROM that copies itself into SRAM is NOT an implementation of this contract. LP loads the generated APUC image through the existing private AXI DMA while globally idle/quiesced, then hardware validates it and locks the store until hard/PCLK reset. No CPU MFCC/inference or runtime coefficient approximation is introduced.

APUC has a 64-byte header and 61440-byte payload, total 61504 (0xf040) bytes, with 64-byte-aligned source address. It is separate from the unchanged 32768-byte APUM. All header words are little-endian u32:

Byte Field / required value
0x00 Magic 0x43555041 (bytes APUC).
0x04 Container ABI 0x00010000.
0x08, 0x0c Total bytes 61504; payload offset 64.
0x10, 0x14 Payload bytes 61440; numerical coefficient profile 1.
0x18, 0x1c Bank-layout ID 1; bank count 15.
0x20, 0x24 Table count 10; payload CRC 0x25e7c27d.
0x28, 0x2c Coefficient ID low 0x8a0b038d, high 0x806c780d.
0x30, 0x34 Associated APUM payload CRC 0xb9034b22; LN2 Q24 11629080.
0x38, 0x3c Reserved zero.

CRC is the existing CRC-32/ISO-HDLC over exactly bytes [64,61504), including zero padding. Source range additions must be checked without wrapping and all DMA bytes must remain in the snapshotted inclusive read ACL. Reject an illegal size/address/state before payload DMA. Check every fixed header field before payload, every padding word, and equality of observed/header/register/frozen payload CRC. After writing, read back all 15360 physical words and recompute CRC before atomically publishing valid+locked+ID. Readback has an exclusive port schedule and must finish within 15364 PCLK cycles once started; pipeline one word per cycle, with no clock-gated request left pending. The ready-target cold-load acceptance budget is 100000 PCLK cycles from command to publication; AXI starvation is separately bounded by DMA_TIMEOUT and reported as stalls.

Freeze-time parsing of the committed tables and independent in-memory bank packing produced these golden identities (no RTL migration is claimed):

Byte stream SHA-256
Logical words in order Hann, real twiddle, imaginary twiddle, Mel, DCT, Log, FIR3, FIR6, Softmax, APUM profile, each word LE32, no delimiters f416585119e488c82e5cea1dabb17424e33a16dd8041393135903a613edced46
61440-byte physical payload 8d030b8a0d786c80a7fa072439700a4485711971d79a6a62e78fcafb1657d83a
Complete APUC image d670688442ea6efe1e638108157f55fc55c75218c8edbee931aaca3497567818

The coefficient ID is the first eight payload-SHA digest bytes interpreted little-endian. SHA checks are release/tooling checks; hardware CRC is not authentication, anti-rollback or runtime ECC. The authoritative word source for migration is the two table files at the inspected commit and the existing generator/BAM parity tests, including the current Hz-linear Mel ramps. Do not change the numerical profile while changing its storage representation.

Extend scripts/generate_apu_kws_rtl_constants.py to emit APUC and a bank/ table/hash manifest from the same exact generators and frozen APUM. Add make CONFIG=configs/ci/ihp130.mk apu-p9-coefficients as a P9 implementation deliverable; it does not exist merely because it is specified here. Generated images/reports belong under the variant's apu/coefficients/ directory. Keep old SV lookup functions only as host/test reference collateral, excluded from the production synthesizable hierarchy. Extend the release-asset generator and LP startup sequence to load microcode, APUC, then APUM before HP handoff. Account for the extra 61504 firmware/source bytes without changing a committed on-chip SRAM profile or silently truncating an image.

Additive APB V1.2 and HAL contract

P9 appends CAPABILITY0 bit9 = coefficient-load interface and reports IP_VERSION=0x00010002, qualified release CAPABILITY0 0x000003fd, unchanged CAPABILITY1 0x01827020, and IRQ mask 0x00000fff. Bit9 describes an interface, not whether a particular PDK uses hard macros. Existing COMMAND bits, register offsets, descriptor, APUM/APUMC versions, MP3 stub and system IRQ/resource/DMA/ clock/reset allocations are unchanged. Earlier profiles reject these new offsets and bit11 IRQ writes. P9-only software tests discovery before access.

Offset Register Access Reset Contract
0x240 KWS_COEFF_ADDRESS RW idle/LP 0 64-byte-aligned DMA source.
0x244 KWS_COEFF_SIZE RW idle/LP 0 Exact 61504 bytes.
0x248 KWS_COEFF_EXPECTED_CRC RW idle/LP 0 Expected APUC payload CRC.
0x24c KWS_COEFF_COMMAND WO 0 Full-word value 1 starts load; all other values reject.
0x250 KWS_COEFF_STATUS RO 0 Busy0, valid1, locked2; header-declared size8, other header9, CRC10, padding11 error flags.
0x254 KWS_COEFF_ACTUAL_CRC RO 0 Finalized SRAM-readback CRC, zero until a complete readback.
0x258 KWS_COEFF_ID_LO RO 0 Published coefficient ID bits 31:0; zero until success.
0x25c KWS_COEFF_ID_HI RO 0 Published coefficient ID bits 63:32; zero until success.
0x260 KWS_COEFF_CAPACITY RO 0x0000f000 Auxiliary payload bytes, not APUM scratch bytes.

RW/WO writes require full-word strobes; reserved status bits read zero and RO writes reject. Load admission requires LP owner, globally idle/quiesced, disabled KWS, valid read ACL, unlocked coefficient store and no valid model, SIZE=61504, aligned ADDRESS and the complete checked image range inside the ACL. Failed command admission returns PSLVERR with the existing APB error collection; it issues no DMA, leaves loader status unchanged and does not raise IRQ11. After an accepted header transfer, mismatched words 0x08/0x10 are header-declared size errors; other fixed-field mismatches are header errors. The DMA grant is exclusive with other APU loaders/jobs, reusing their drain and epoch protocol rather than adding a fabric master or CDC. Reuse the P8 LP-quiesced-loader admission exception: the resource's block-new condition must not deadlock the already admitted asset load. Global busy/idle includes coefficient DMA, readback and all pending SRAM responses. An accepted load snapshots address/size/CRC/ACL, clears unlocked diagnostics/ID/actual CRC, and keeps both coefficient-valid and model execution clear until success.

Terminal success/failure raises new local IRQ11; failures also collect the existing first-error IRQ8 and counters. Size/header/padding faults use code12, stage1, CRC/readback faults code13/stage1. ERROR_DETAIL is 0x09000000 | reason, reason 1=header-declared size, 2=header, 3=payload CRC, 4=padding, 5=readback CRC. ERROR_ADDRESS is the first bad external size/header/ padding word or byte (size uses source+0x08 or source+0x10), or source+0x24 for either CRC failure respectively. Bus/timeout faults keep codes15/17 and their existing address/response precedence; semantic error flags stay zero for bus/abort faults. For coexisting semantic errors choose size, header-byte order, padding- byte order, payload CRC, then readback CRC; incomplete/failed DMA outranks checks requiring its missing bytes. Failures never publish valid/lock/ID.

A successful coefficient lock is irrevocable until hard/PCLK reset. A failed or aborted load is retryable after drain/recovery and cannot execute partial contents. A clean abort emits abort-done, not IRQ11 or first error; forced loss retains existing lifecycle precedence. Soft/resource reset cancels an unpublished load but retains a validated locked coefficient image and its readback CRC/ID, just as it retains a validated model. It resets configuration registers and unlocked diagnostics, not retained SRAM contents. Hard reset invalidates coefficient and model locks together and requires both loads again. No macro array is asynchronously reset; flags and pending-response state are. Quiesce/owner handoff cannot expose half-loaded assets, and HP cannot load, write, unlock or alias these banks.

On V1.2, MODEL_LOAD and KWS enable/operation1 require coefficient valid+locked with profile1/associated-model identity in addition to their existing checks. APUM1 is still accepted byte-for-byte after APUC initialization. An old firmware that never initializes APUC must fail closed, not find a hidden ROM fallback; a HAL that only accepts V1.1 must be updated to negotiate V1.2. WAV/FLAC-only work needs no coefficient load. Existing numerical/result/descriptor timestamps and model-lock semantics do not change.

Append, without resizing existing public structs:

typedef struct {
    uint32_t status;
    uint32_t actual_crc;
    uint32_t coefficient_id[2];
    uint32_t capacity_bytes;
} rs_apu_kws_coeff_status_t;

rs_status_t rs_apu_kws_coeff_load(const rs_apu_image_t *image, rs_timeout_t timeout);
rs_status_t rs_apu_kws_coeff_status_read(rs_apu_kws_coeff_status_t *status);

Load is bounded/blocking, with existing image address/bytes/expected_crc and poll budget max(1,timeout). It validates state/range/cache visibility before MMIO, starts the new command, then requires valid+locked, expected CRC and coefficient ID for RS_OK. Use RS_ENOTSUP for missing interface/version, RS_EINVAL for caller/state/range failures, RS_EFORMAT for hardware size/header/ padding rejection, RS_EIO for CRC/bus/internal failures, RS_ETIMEOUT for exhausted polling. Timeout does not release buffers, cancel DMA, clear IRQs or reset the APU. Use explicit abort/drain recovery. Status read is non-consuming. Update the existing probe to accept supported minor versions 0,1,2; model/ enable helpers check the new readiness only when bit9 is advertised.

Independently append RTL/C constants, parity fixtures, Python image definitions and the APUC schema/identity to scripts/apu_abi_digest.py's canonical inventory. Keep its existing serialization/CRC algorithm. The pre-P9 0xf5005d7c digest is not valid for V1.2; compute and review the new nonzero value during P9 implementation, and require RTL/C/tool equality before release. Partial implementations report zero rather than advertising the old complete digest.

Coefficient access, latency and exact multi-cycle arithmetic

Coefficient/profile reads are synchronous transactions, not calls to a large combinational function. A frontend request carries kind and index; kinds are Hann=0, twiddle pair=1, Mel=2, DCT=3, Log pair=4, FIR3=5, FIR6=6. Softmax and APUM profile use kind codes 7 and 8 for diagnostics. The response returns one 32-bit word or {imaginary,real} / {L[i+1],L[i]} as appropriate. Single-word responses have zero in the unused upper half. Preserve each old function's signed/unsigned interpretation at its arithmetic consumer; SRAM returns raw bits, not a newly sign-extended numerical format. Legal index ranges are 0..479, 0..255, 0..10279, 0..399, 0..1023, 0..62, 0..62. Both Log words always occupy different banks, including i=1023. A separate inference request reads Softmax differences 0..124 from bank14. Model validation alone uses the 1496-word profile read port and is globally exclusive with runtime.

Allow one outstanding request per frontend/inference/profile client, stable payload until ready, and a retained response until consumed. Without consumer backpressure, an accepted request returns in at most two PCLK cycles (macro read plus response register). Frontend and inference requests may be accepted together; their banks never conflict in this layout. Model/APUC loading owns the banks exclusively. Illegal kind/index or invalid-store access returns a bounded fault, not default zero or a masked address. Use code14/stage9 or10 for engine access faults and code12/stage1 for a model-profile access fault; detail 0x09000100 | kind, address=4*requested logical table index. It is not a new CPU-addressable window.

Issue coefficient and existing scratch requests in parallel where both are needed. Snapshot work identity, indices and operands and commit an arithmetic step exactly once only when both responses belong to that work item. Reuse the returned twiddle pair for all four products and the same L[i] for the interpolation/base term; never replicate the large ROM to gain read ports. Small response/operand holding registers are allowed, not a shadow table. Abort/reset/epoch change discards stale responses before new work; a blocked response does not count repeatedly as watchdog progress. Actual request issue, retired response, arithmetic iteration or scratch commit is progress.

Additional pipeline/iterative cycles MUST preserve exact signed widths, RNE/TZ, Softmax scalar behavior and overflow faults. In particular the existing 96-bit log normalization/divisions may be serialized using exact integer operations (at most 320 arithmetic PCLK cycles per band, excluding explicitly counted operand stalls), and nearest-isqrt may use at most 40 arithmetic cycles per bin. These are ceilings, not required delays or approximation permissions. No coefficient-generation CORDIC, smaller/recalibrated model, new LUT values, changed hop/window/threshold or reduced MAC-lane count is authorized.

Every lookup wait and iteration contributes to measured KWS cycles. Preserve SEQUENCER_TIMEOUT as a consecutive no-progress bound, not a total-job budget; do not enlarge its reset value to mask a stalled handshake. The 100 ms window deadline and protection against overwriting the oldest of the 49 mel rows remain blocking even if individual transactions meet their local bounds. Qualify actual combined SRAM/arithmetic scheduling, not an ideal zero-latency lookup model. Other clock dividers make no new real-time claim.

Macro-backed microcode proof memo

Keep PathMemoDepth=8192 for expanded P5/P9, the existing full 64-bit key {loop_active,return_pc[3:0],pc}, hash constant 0x9e3779b97f4a7c15, hash selection, linear probing and exact-key equality. Do not shorten keys, use hash-only matches, evict entries, skip deeper proof paths or lower path limits to save hardware. The call-depth>2 bypass, full-table normal-traversal fallback, V1/V2 traversal limits 131072/262144 and path-stack bounds remain unchanged.

Map entry i to key bank-pair floor(i/1024) (0..7), row i mod 1024, low/high words in two 1024x32 macros, sixteen in total. The seventeenth macro stores valid bits: row floor(i/32) (0..255), bit i mod 32; other rows are unused. Read key halves and bitmap word in parallel, latch them synchronously, then perform the existing comparison/probe decision. One lookup/probe requires at most four PCLK cycles including controller staging. Insert both key halves and the previously read bitmap word OR its selected valid bit as one logical commit; never publish a valid bit before both key writes. Only one proof transaction is outstanding, so bitmap read/modify/write cannot lose an update.

Before every memoized entry proof and every restarted load, clear the 256 used bitmap rows and drain the final write (at most 260 cycles). Keys need not be reset. Abort during clear/lookup/insert must drain at most the accepted transaction, suppress image publication and restart a complete clear on retry. Soft/resource reset never makes stale memo contents usable for a new proof. Use synchronous full-word writes, not a resettable 8192-bit valid flop vector. The actual checked path-visit counter still counts proof states, not SRAM service cycles; report visits, memo hits/probes/full events and wall cycles separately. Bounded probing/clearing must not be hidden from abort/idle logic. Smaller power-of-two depths used by directed tests retain their existing semantics; they are not permission to shrink the production table.

HAL and compatibility

<retrosoc/hal/apu.h> owns discovery, ACL, microcode/model load, direct/ring submit, stream routing, KWS, interrupt, error, statistics, bounded wait, abort, and reset. Fallible functions return rs_status_t and waits take a timeout. <retrosoc/hal/apu_regs.h> independently mirrors every public constant.

The APB/job ABI is append-only within major version 1. Existing offsets, job-descriptor size, opcode/format/error/IRQ IDs, ownership, and lock semantics retain their meaning. APB V1.1 adds PC_HIGH and capacity discovery without moving an existing field. APUMC has its own binary/ISA version: legacy V1 is immutable, and the approved V2 widens its entry-PC and branch fields with explicit version negotiation. APUM model ABI does not change. Software fails closed on unknown major versions in the relevant namespace, not by equating APB IP_VERSION to MC_ABI.

The updated P5 HAL accepts APB major 1, minor 0 or 1 for the supported legacy and expanded profiles, comparing the extracted major against 1 rather than against the full V1.1 word. It reads actual control-store KiB from CAPABILITY1. Release software targeting APUMC V2 requires APB V1.1 with 32 KiB before submitting that image. The existing microcode-load API and image structure remain unchanged; the hardware validates header word 1, and successful HAL load accepts/readbacks the corresponding MC_ABI 1.0 or 2.0. It must not require MC_ABI to be 1.0 on a valid V2 load or infer it from image size. Unknown image versions retain the existing header-failure/RS_EIO path. Existing legacy software can submit V1 images to expanded hardware; software displaying full PCs must use PC_HIGH or the full trap address. Functional PCM/job/error rules and every public HAL function signature remain unchanged.

STREAM_WATERMARK at 0x060 is the sole P2 ABI append. P1 continues to return PSLVERR for that formerly reserved offset, while P2 implements it; no P1 offset, accepted field, reset value, or reserved mask is repurposed. P2 updates the independently handwritten SVH/C tables and parity tests together.

P5 HAL contract

The following declarations are the required P5 additions to <retrosoc/hal/apu.h>, implemented in crt/src/hal/apu.c with deterministic packing/validation tests. They describe software interfaces to implement in P5; this freeze does not add code. Existing rs_apu_probe, rs_apu_info_t, rs_apu_descriptor_t, and every 128-byte descriptor member offset are retained. Enums use the already frozen integer encodings. These host-side structures are not DMA wire formats; only rs_apu_descriptor_t is the shared layout.

typedef enum { RS_APU_WAV = 0, RS_APU_MP3 = 1, RS_APU_FLAC = 2 } rs_apu_format_t;
typedef enum { RS_APU_MEMORY = 0, RS_APU_I2S = 1 } rs_apu_output_t;
typedef enum { RS_APU_S16 = 0, RS_APU_S24_32 = 1 } rs_apu_pcm_t;

typedef struct {
    rs_apu_format_t format;
    rs_apu_output_t output;
    rs_apu_pcm_t pcm;
    uint32_t input_address, input_bytes;
    uint32_t output_address, output_capacity;
    uint32_t expected_rate, expected_channels, expected_bits;
    uint32_t output_rate, output_channels;
    uint32_t downmix, resample, strict; /* each exactly zero or one */
    uint32_t cookie[2];
} rs_apu_job_t;

typedef struct { uint32_t address, bytes, expected_crc; } rs_apu_image_t;
typedef struct { uint32_t status, address, detail; } rs_apu_error_t;
typedef struct {
    uint32_t status; /* descriptor RESULT_STATUS encoding, including direct */
    uint32_t input_used, output_bytes, frames, source_info, cycles, detail;
    uint32_t cookie[2], start_timestamp[2], finish_timestamp[2];
    uint32_t microcode_build_id;
    rs_apu_error_t first_error;
} rs_apu_result_t;

typedef struct {
    rs_apu_descriptor_t *descriptors; /* aligned CPU mapping, caller-owned */
    uint32_t dma_address, entries, tail;
} rs_apu_ring_t;

rs_status_t rs_apu_set_acl(uint32_t read_base, uint32_t read_limit,
                           uint32_t write_base, uint32_t write_limit);
rs_status_t rs_apu_microcode_load(const rs_apu_image_t *image, rs_timeout_t timeout);
rs_status_t rs_apu_validate_job(const rs_apu_job_t *job);
rs_status_t rs_apu_submit_direct(const rs_apu_job_t *job);
rs_status_t rs_apu_wait_direct(rs_apu_result_t *result, rs_timeout_t timeout);
rs_status_t rs_apu_decode(const rs_apu_job_t *job, rs_apu_result_t *result,
                          rs_timeout_t timeout);
rs_status_t rs_apu_ring_configure(rs_apu_ring_t *ring, uint32_t stop_on_error,
                                 uint32_t coalesce_count, uint32_t coalesce_timeout);
rs_status_t rs_apu_ring_submit(rs_apu_ring_t *ring, const rs_apu_job_t *job,
                              uint32_t ioc, uint32_t *slot);
rs_status_t rs_apu_ring_result(const rs_apu_ring_t *ring, uint32_t slot,
                              rs_apu_result_t *result, rs_timeout_t timeout);
rs_status_t rs_apu_ring_disable(rs_timeout_t timeout);
rs_status_t rs_apu_stream_route(uint32_t tx_route, uint32_t rx_route);
rs_status_t rs_apu_abort(rs_timeout_t timeout);
rs_status_t rs_apu_soft_reset(void);
rs_status_t rs_apu_error_read(rs_apu_error_t *error);
rs_status_t rs_apu_error_clear(void);
rs_status_t rs_apu_irq_read(uint32_t *state);
rs_status_t rs_apu_irq_enable(uint32_t mask);
rs_status_t rs_apu_irq_ack(uint32_t mask);

All pointers are mandatory; addresses are 32-bit DMA addresses, never silently truncated CPU pointers. Validation rejects unknown enums, nonboolean flags, reserved fields, misalignment, overflow, overlap, unsupported capabilities, and invalid capacity/route combinations before any job-register mutation. Header-dependent checks are performed by APU microcode after submission, not by reading the file on LP/HP. Direct submission packs the same descriptor words into JOB_*, fences, and issues START once; it is asynchronous. rs_apu_decode is exactly submit-direct followed by wait-direct. Direct results normalize JOB_STATUS into descriptor-result bit positions; direct cookie is the saved submitted cookie, and direct start/finish timestamps are zero because no corresponding APB registers exist. The direct build ID is read from the locked MC build ID. first_error is a raw snapshot of the global first-error tuple and may belong to an earlier fault; per-job status/detail are authoritative for the returned job. No API implicitly clears first error.

rs_timeout_t uses the existing unsigned poll-budget convention here: timeout n permits at most max(1,n) status observations; zero is a nonblocking single observation, not infinite. RS_TIMEOUT_DEFAULT is the existing SDK default. A poll has no assumed wall-clock duration. Exhaustion returns RS_ETIMEOUT, leaves the output result structure untouched, and does not abort, reset, release buffers, or retry a command. An admitted operation can still be active; buffers remain owned until a later successful terminal wait or drained abort. A successful poll populates the complete result even when its terminal status maps to a nonzero rs_status_t.

Return mapping: RS_EINVAL for invalid arguments, range/packing violations, or illegal idle/owner conditions; RS_ENOTSUP for a clear required capability or error code 3; RS_ENOSPC for full software ring or reason 0x0051 capacity exhaustion; RS_ETIMEOUT for poll exhaustion; RS_EFORMAT for codec codes 4..7; RS_EIO for hardware DMA, trap, overflow, abort, or other terminal failures. Successful operation is RS_OK. Busy is not encoded as success; terminal DMA timeout is RS_EIO with hardware code 17, distinct from a HAL poll budget expiring while hardware is still running.

The caller owns resource acquisition/quiesce, I2S setup, cache maintenance, and serialization between LP/HP/interrupt contexts. APU HAL calls never transfer resource ownership, decode on the host, allocate memory, or load a replacement image automatically. ACL programming and microcode load are LP-only and quiesced/idle; a locked image returns RS_EINVAL without trying to unlock it. Load waits for busy to clear, then checks MC valid/lock/CRC and returns the frozen loader result. Timeout does not cancel the load.

Ring configure requires idle with ring disabled, 2..256 power-of-two entries, 128-byte-aligned CPU/DMA bases, a non-cacheable descriptor mapping, boolean stop-on-error, count 1..255, and timeout 1..65535. It programs base/size/coalescing, tail zero, then enables; software must have cleared every OWN bit before configuring. At most entries-1 slots are queued to disambiguate head==tail. Submit fills a free slot, zeros result/reserved/KWS words, preserves the requested cookie, writes OWN last, fences, advances tail, and rings the doorbell. The P5 ring helper requires non-cacheable descriptor storage so no cache-maintenance callback is needed between its payload stores and OWN publication. Payload-buffer cache clean/invalidate remains the caller's responsibility before submit and after completion; manual cached-descriptor operation still follows the existing P2 CBO contract. Submit does not wait. Result polling observes OWN clear with an acquire fence and then copies the immutable descriptor result. A slot with OWN clear and no terminal result is not a completed job and returns RS_EINVAL; callers must collect a slot before resubmitting it. Result polling never recycles or advances a producer slot. Ring disable uses abort when active, waits for idle, then clears enable. Abort on an idle APU is a HAL no-op returning OK; otherwise it issues ABORT once and waits for idle/abort completion. Soft reset requires idle and preserves the locked bundle.

rs_apu_stream_route changes the requested directions only after checking their active state and P5 directional capabilities; it preserves the P2 same-value write rule. IRQ enable replaces the enable mask, IRQ ack W1C-clears only requested implemented bits, and reads never clear. Invalid mask bits are RS_EINVAL. Error clear writes only ERROR_STATUS valid/W1C and cannot clear a same-cycle hardware fault. None of these calls changes existing IRQ routing.

P7 HAL additions

These declarations are frozen additions to <retrosoc/hal/apu.h> for implementation in crt/src/hal/apu.c. Existing P5 structures/functions and the 128-byte descriptor retain their layout and signatures. The new structs are host-side objects, not DMA wire layouts; all flags/enumerated integers must be range checked. No dynamic allocation or hosted-library dependency is permitted. Independently extend apu_regs.h and apu_define.svh, and maintain handwritten Python APUM constants and deterministic parity tests.

typedef struct {
    uint32_t threshold;       /* 0..255, inclusive */
    uint32_t debounce;        /* 1..255 */
    uint32_t input_rate;      /* 16000, 48000 or 96000 */
    uint32_t input_bits;      /* 16 or 24; physical I2S channels fixed at two */
} rs_apu_kws_config_t;

typedef struct {
    uint32_t input_address;   /* exactly 32000 mono S16_LE bytes */
    uint32_t threshold;
    uint32_t debounce;
    uint32_t cookie[2];
} rs_apu_kws_job_t;

typedef struct {
    uint32_t class_id;
    uint32_t score;
    uint32_t hit;
    uint32_t timestamp[2];   /* low, high; evaluated-window endpoint */
} rs_apu_kws_result_t;

typedef struct {
    uint32_t status;
    uint32_t model_status;
    uint32_t model_crc;
    uint32_t frame_count;
    uint32_t inference_count;
    uint32_t hit_count;
    uint32_t overrun_count;
} rs_apu_kws_status_t;

typedef struct {
    rs_apu_result_t job;
    uint32_t class_id;
    uint32_t score;
    uint32_t hit;
} rs_apu_kws_completion_t;

rs_status_t rs_apu_kws_model_load(const rs_apu_image_t *image, rs_timeout_t timeout);
rs_status_t rs_apu_kws_configure(const rs_apu_kws_config_t *config);
rs_status_t rs_apu_kws_enable(uint32_t memory_window);
rs_status_t rs_apu_kws_disable(rs_timeout_t timeout);
rs_status_t rs_apu_kws_clear_history(void);
rs_status_t rs_apu_kws_status_read(rs_apu_kws_status_t *status);
rs_status_t rs_apu_kws_result_read(rs_apu_kws_result_t *result);
rs_status_t rs_apu_kws_validate_job(const rs_apu_kws_job_t *job);
rs_status_t rs_apu_kws_submit_direct(const rs_apu_kws_job_t *job);
rs_status_t rs_apu_kws_wait_direct(rs_apu_kws_completion_t *result, rs_timeout_t timeout);
rs_status_t rs_apu_kws_ring_submit(rs_apu_ring_t *ring, const rs_apu_kws_job_t *job,
                                    uint32_t ioc, uint32_t *slot);
rs_status_t rs_apu_kws_ring_result(const rs_apu_ring_t *ring, uint32_t slot,
                                    rs_apu_kws_completion_t *result, rs_timeout_t timeout);
  • model_load is blocking and reuses rs_apu_image_t's DMA address, exact byte size and expected payload CRC. Validate size=32768, alignment, checked inclusive ACL range, LP ownership, quiesce/global idle, disabled KWS and unlocked model; perform the same CBO/fence discipline as microcode load. Program the three existing model registers, issue COMMAND bit5, and poll KWS_MODEL_STATUS. Success requires valid AND locked and matching actual CRC. No unlock, implicit hard reset, IRQ acknowledgement or retry is hidden.
  • configure requires disabled/global idle, packs the two fields of KWS_CONFIG and the appended KWS_INPUT_CONFIG, and preserves all other settings. It does not configure I2S, change route or clear history/errors. enable(memory_window) accepts only 0/1, validates capability/model/owner and nonquiesced admission, and writes control 1 or 3. Continuous mode also requires RX route1; the caller is responsible for matching I2S settings. No codec microcode executes in either KWS mode.
  • disable initiates the KWS-only bounded drain, preserving mode. Poll until ENABLE reads zero and both listening/inference-busy clear; hardware keeps ENABLE readback one until drain completes. Already-disabled is RS_OK. Do not abort a concurrent codec job or silently reroute RX to central DMA. clear_history issues only bit2 while disabled/global idle, preserving mode and model lock. Neither call clears unrelated IRQ or first-error state.
  • status_read returns the raw status/model words, actual CRC and individual monotonic counters. These live counter reads are not a multi-register atomic snapshot; use the existing PERF snapshot for cycle comparisons. result_read checks RESULT_VALID, reads KWS_RESULT (latching its timestamp), then timestamp LO/HI, and decodes class/score/hit. It returns the latest valid result without consuming it; no-result returns RS_ETIMEOUT immediately.
  • validate_job is pure, performs no MMIO and validates nonnull pointer, four-byte alignment, checked 32000-byte range and threshold/debounce. Submit functions additionally check capability, model/microcode locks, owner/quiesce/ACL state and armed memory mode. They are nonblocking: pack operation1 exactly as above and either issue START or publish the owned ring entry with the existing cache/fence/doorbell discipline. Ring submission preserves caller cookie and sets IOC from exactly 0/1. Do not call the P5 WAV decoder to process these raw PCM bytes.
  • wait_direct and ring_result are bounded completion readers with normal P5 job/result/error semantics. Read descriptor word22 only after completed OWN-clear and cache invalidation, before the caller reuses that slot; ring results use that word, not the newest global result. Both completion APIs return the unchanged job START/FINISH timestamps in job; they do not claim a per-descriptor capture-endpoint timestamp. On a failed job, zero the returned class_id/score/hit fields and return its error; a previous successful global result is never presented as the failed job.

The global KWS result reports a capture endpoint, whereas the immutable descriptor records job start/finish. All START/FINISH fields keep their original meanings, including operation1. A per-descriptor capture-endpoint timestamp is explicitly deferred because it requires a new descriptor ABI.

All fallible APIs use existing rs_status_t values: RS_EINVAL for null/range/ state/ownership/mode errors; RS_ENOTSUP for missing KWS or unsupported APB major version (test discovery before touching the P7-only offset); RS_EFORMAT for model size/header/range/operator rejection (code12); RS_EIO for CRC, AXI, arithmetic and other hardware terminal failures; RS_ETIMEOUT for an exhausted poll budget; RS_OK only on the specified successful state/result. Waits use the existing rs_timeout_t poll budget max(1,timeout), not milliseconds and never an infinite wait. Timeout does not transfer ownership, clear OWN, unlock the model, acknowledge IRQs or cancel outstanding DMA. The caller retains input storage until bounded disable/abort/drain confirms completion; global abort/reset is an explicit caller decision. Existing rs_apu_irq_* and error APIs manage IRQ2/4/8/9 without new interrupt allocation. The owner driver serializes register configuration, submission and result reads; these freestanding APIs add no OS lock and are not implicitly reentrant.

Deterministic host tests cover exact packing/offsets and model CRC, every rejection and return mapping, zero/one/max timeouts, no-MMIO pure validation, no writes after failed validation, result freshness, ring slot reuse, cache ordering, and P5 discovery fail-closed behavior. The implementation must review applicable MISRA rules and add a reviewed deviation only if actually needed; this documentation freeze grants no new MISRA deviation.

Clock, Reset, CDC/RDC, and Lifecycle

APB4, DMA source, sequencer, local SRAM, fixed engines, KWS, and stream router run in PCLK. Mini caps PCLK at 48 MHz. Correctness is required at all supported dividers; real-time MVP performance is qualified only at 48 MHz.

I2S retains clk_aud_i, rst_aud_n_i, and existing cdc_2phase/ cdc_fifo_warm_flush crossings to PCLK. APU consumes only synchronized PCLK streams. APU AXI crosses PCLK to HP through the existing Common warm-flush bridge. Topology adds an apu_data crossing to the clock/reset inventory; internal streams remain same-domain.

  • Hard/PCLK reset invalidates microcode/model, clears their locks, denies DMA, and clears jobs, KWS history, IRQ, errors, and counters.
  • Soft reset is idle-only. It resets scheduler, sequencer, engines, streams, KWS history, IRQ, and first error while preserving validated locked microcode/model and ACLs.
  • Busy recovery is abort, wait abort-done/idle, then soft reset. Busy soft reset returns PSLVERR.
  • Resource reset blocks new work, drains accepted AXI/stream traffic, then uses soft-reset semantics.
  • Quiesce blocks new jobs, stops sequencer at a frame/block boundary, stops KWS after the current feature/inference, drains DMA/output, and reports idle only after all engines/FIFOs and Gateway A are idle.
  • Microcode/model load is legal only with LP owner, quiesced, idle, valid ACL, and corresponding lock clear. HP cannot load or unlock them.
  • Owner change follows Resource Controller block-new, CDC acknowledgement, drain, owner update, and release. Retained KWS enable resumes under the new owner; the finite gap is counted.

Unilateral HP reset does not reset PCLK APU state. The AXI bridge warm-flushes and the active job waits for recovery or timeout. Unilateral PCLK reset invalidates local state and requires bridge epoch recovery. The inventory and formal checks do not replace commercial CDC/RDC signoff.

Errors, Recovery, Security, and Observability

Error allocation

Code Meaning
0 no error
1 invalid configuration/APB command
2 invalid descriptor/ring
3 unsupported format/feature
4 malformed container/header
5 truncated stream
6 codec CRC/checksum
7 entropy/decode failure
8 reconstruction/resampler/PCM failure
9 invalid microcode header/range/control flow
10 microcode CRC/capability failure
11 sequencer trap/watchdog
12 invalid KWS model/coefficient header, range or operator
13 KWS model/coefficient CRC
14 KWS arithmetic/tensor failure
15 AXI read response/protocol
16 AXI write response/protocol
17 DMA timeout
18 stream underrun
19 stream overrun
20 abort terminal result
21 resource reset/forced lifecycle termination
22 FIFO/local-memory/arithmetic overflow
23-63 reserved

Stages are APB/config 0, loader 1, descriptor/ring 2, DMA read 3, bitstream 4, entropy 5, reconstruction/transform 6, resampler/PCM 7, DMA write/stream 8, KWS frontend 9, KWS inference 10, and sequencer-control/lifecycle 11.

First error is immutable until W1C/reset. Later faults increment counters but do not overwrite code, stage, address/PC, detail, AXI response, or descriptor index. A requested, successfully drained abort or quiesced resource reset sets terminal status/IRQ but not first error; code20/21 enters first error only when forced, timed out, or accepted work was lost.

Simultaneous terminal conditions use this fixed first-error precedence:

  1. Hard/PCLK reset clears all status and records no retained error.
  2. Forced resource reset or lifecycle loss records code21.
  3. AXI write response/protocol failure records code16.
  4. AXI read response/protocol failure records code15.
  5. DMA no-progress timeout records code17.
  6. RX stream overrun records code19.
  7. TX stream underrun records code18.
  8. A forced abort records code20.

A normal resource reset or successfully drained software abort is not an error. When several non-reset events coincide, every applicable sticky IRQ/status and counter is updated, but only the highest item above enters the immutable first error. An AXI fault observed while abort drains therefore outranks abort. RX overrun outranks TX underrun because it represents lost input. Hardware event capture outranks a same-cycle first-error or IRQ W1C.

Format errors terminate the owning job. AXI protocol loss, sequencer trap, watchdog, impossible internal state, or repeated timeout quiesces the whole APU until abort/reset. Bad microcode/model never publishes valid or unlocks execution.

Security boundary

There is no hardware coherency. Microcode/model bundles, descriptors, input, output, and writeback use DMA-visible non-cacheable/shared memory or explicit 64-byte CBO maintenance plus fence rw,rw. Descriptor OWN is the ownership handoff point.

Every byte of every DMA burst must fit the local inclusive ACL. Range arithmetic is overflow checked. Microcode cannot address system memory, APB, or another local partition directly. LP-only load, static verification, capability checks, CRC, automatic lock, watchdog, and fail-closed traps are reliability controls, not authentication. MVP claims no secure boot, confidentiality, DRM, functional safety, ASIL, or IEC 61508 compliance.

Observability

The APU exposes loader/model status, current PC/class/opcode, retired instructions, sticky first error, descriptor results, ring state, stream FIFO/xrun state, KWS result/timestamp, and atomic snapshot counters. Required 64-bit counters are active cycles, input/output bytes, decoded frames, DMA read/write stalls, stream stalls, sequencer instructions, KWS cycles, and faults. Counters saturate.

No waveform-only state is required to diagnose completion, rejection, trap, bus fault, timeout, abort, xrun, model failure, or lifecycle failure.

MVP and Commercial-grade Roadmap

Exact MVP

  • WAV RIFF PCM: mono/stereo, 8/16/24/32-bit, 8..96 kHz, checked unknown-chunk skip and deterministic sign extension/truncation/saturation without dither.
  • MP3 is not part of this release. Format ID 1 and the three-descriptor APUMC layout are retained with the P5 unsupported-MP3 trap stub; MP3 requests continue to fail closed.
  • Native FLAC: mono/stereo, 16/24-bit, 8..96 kHz, constant/verbatim/fixed/LPC order0..32, Rice/Rice2, independent/left-side/side-right/mid-side, CRC8/16, and bounded metadata skip. Ogg mapping is unsupported.
  • S16_LE or S24_32LE memory/I2S output; fixed-point resampling to 48/96 kHz, including 44.1-to-48 kHz.
  • Continuous KWS: 16 kHz mono S16, one-second history, 20 ms feature stride, 49 by 10 INT8 MFCC, 12 classes, inference each 100 ms, configurable threshold and debounce.
  • One decode job plus concurrent KWS, direct/ring DMA, APB4, LP/HP ownership, interrupts, ACL, timeout, abort/reset, first error, and counters.

MVP acceptance

  1. WAV and FLAC produce bit-exact approved PCM with the P5 frame/sample/channel accounting and deterministic output-conversion rules. MP3 unsupported-request and trap-stub compatibility tests pass; positive MP3 decode, PSNR and three-active-codec packing are not acceptance gates.
  2. The official MLPerf Tiny KWS 1000-utterance set reaches at least 90 percent top-1 through the hardware MFCC/inference path.
  3. At 48 MHz PCLK, the P5 supported WAV/FLAC playback workloads run concurrently with continuous KWS with zero I2S underrun and zero KWS overrun under the active P5 ready-memory qualification conditions. MP3 performance workloads and the archived P6 service-envelope gate are not prerequisites.
  4. 24-bit/96 kHz FLAC completes without xrun; byte/frame/cycle/stall counters match the scoreboard.
  5. APUMC static verification, instruction interpreter/RTL differential, opcode mutation, loop/stack/range/watchdog, loader atomicity, and trap paths all fail closed as specified.
  6. Random AXI backpressure, 4 KiB boundaries, tails, every AXI error, ring wrap, abort/reset at every state, stream backpressure, and LP/HP handoff complete with the specified result or bounded error.
  7. RTL/C register, descriptor, APUMC, APUM, instruction, format, IRQ, and error definitions pass parity tests.
  8. IHP130 firmware, behavioral, formal, synthesis, netlist, and OpenSTA evidence is reviewed with no unowned warning; metrics remain under policy.

Post-MVP work may optimize MAC lanes, pipeline kernels, bank SRAM, or add a dedicated fabric identity only after counters identify a bottleneck. It must preserve V1 public ABI and microcode capability semantics. Deferred codecs, power, coherency, or security require a new approved phase/spec revision.

Verification and Software Validation

Golden models and tools

  • apu-mcasm and the Python microcode interpreter are self-owned and tested from the same frozen ISA definitions without generated register RTL.
  • WAV uses the existing bounded reader model extended for the frozen subset.
  • The minimp3/mpg123 pins and MP3 numerical/performance rules below are archived P6 research only. This release does not require installing those inputs, adding target p6, or running positive MP3 qualification. Existing generic P4 primitive tests and P5 unsupported-MP3 tests remain required.
  • FLAC uses RFC 9639, locked Xiph libFLAC, and the official FLAC test files.
  • MLPerf Tiny inputs/model/converter revision and generated APUM are locked and reproducible.

All new external corpora or reference packages require exact revisions or archive checksums in the dependency lock. Managed source retains notices and does not become evidence of self-owned MISRA conformance.

P7 locked reference inputs and corpus provenance

The following revisions and complete archive SHA-256 values were verified from upstream bytes on 2026-09-11. Register them in the executable dependency lock during P7 implementation, using the existing shared dependency helpers and scripts/setup_apu_reference.py; this refreeze changes documentation only. No floating branch, newly trained model, arbitrary first-1000 selection, unverified cache hit or direct CI download is an equivalent input.

Source lock key Repository / full revision License and retained notice
sources.apu_mlperf_tiny https://github.com/mlcommons/tiny.git at 4addd0fa08d216e20637637874e084895f289da4 Apache-2.0; LICENSE.md and source/model notices.
sources.apu_kws_mfcc https://github.com/eembc/benchmark-runner-ml.git at cf7c2f2634608a7c0ea7458ab7cb3379f2863424 Mixed tree: lock NOASSERTION, consume only datasets/kws01; retain source README and Speech Commands CC-BY-4.0 attribution. Do not package the runner or unrelated datasets.
sources.apu_tfds https://github.com/tensorflow/datasets.git at 8997c4140cd4fc145f0693787b1da78691930459 (v4.3.0) Apache-2.0; LICENSE and per-file notices; ordering reference only.
sources.apu_tensorflow https://github.com/tensorflow/tensorflow.git at fcc4b966f1265f466e82617020af93670141b009 (v2.3.1) Apache-2.0; LICENSE and per-file notices; host numerical reference only.
sources.apu_gemmlowp https://github.com/google/gemmlowp.git at fda83bdc38b118cc6b56753bd540caa49e570745 Apache-2.0; LICENSE and per-file notices; scalar fixed-point oracle only.

Source destinations are .cache/retrosoc/sources/<source-key-with-underscores-replaced-by-hyphens> (for example .cache/retrosoc/sources/apu-mlperf-tiny). Archive keys below match source keys where applicable. Archive download destinations are .cache/retrosoc/downloads/apu/<key>-<revision>.<tar.gz-or-zip>; the Google corpus uses speech_commands_test_set_v0.02.tar.gz. These are managed inputs, not installed Python runtime versions or code permitted in freestanding CRT.

Archive key Immutable URL SHA-256
archives.apu_mlperf_tiny https://codeload.github.com/mlcommons/tiny/tar.gz/4addd0fa08d216e20637637874e084895f289da4 70012ee5a8fc3367b466854b1840fb0246e0525744262631a98c5fc0971a04b0
archives.apu_kws_mfcc https://codeload.github.com/eembc/benchmark-runner-ml/tar.gz/cf7c2f2634608a7c0ea7458ab7cb3379f2863424 87e431a6b4d3f011d672180a3fb1f08856d8074310f37653d5388ec2affc5209
archives.apu_tfds https://codeload.github.com/tensorflow/datasets/tar.gz/8997c4140cd4fc145f0693787b1da78691930459 e300258c247fe8607f3c0200a34343c6a28efb69f0d2b822606a8a66cccea651
archives.apu_tensorflow https://codeload.github.com/tensorflow/tensorflow/tar.gz/fcc4b966f1265f466e82617020af93670141b009 ad41490904b0313c00f3729c7e2ba931b2b8d1e54ea1a859a4bcea3054d4fdc0
archives.apu_gemmlowp https://storage.googleapis.com/mirror.tensorflow.org/github.com/google/gemmlowp/archive/fda83bdc38b118cc6b56753bd540caa49e570745.zip 43146e6f56cb5218a8caaab6b5d1601a083f1f31c06ff474a4378a7d35be9cfb
archives.apu_kws_pcm https://storage.googleapis.com/download.tensorflow.org/data/speech_commands_test_set_v0.02.tar.gz cc2a00c1147c2254e9be3fa0f779d8c17421dc349b86366567a8edfa9acd51df

The PCM archive is exactly 112563277 bytes and contains 4890 WAV files. Extract it to .cache/retrosoc/sources/apu-kws-pcm with the shared safe extractor. License is CC-BY-4.0; retain its LICENSE and README.md, attribute Pete Warden / Google Speech Commands Data Set Test Files v0.02, and identify padding and feature extraction as modifications in redistributed derivatives. Managed reference code/data is excluded from self-owned MISRA claims. P7 release notices must cover any derived model/ROM/data actually shipped; benchmark inputs themselves are host-only unless explicitly included as test fixtures.

The model path under apu-mlperf-tiny is benchmark/training/keyword_spotting/trained_models/kws_ref_model.tflite, 53936 bytes, SHA-256 aeea436800704fce17b17292e4412630ad856e9d777c044c64ef748a880bd0ae. Do not substitute the README's obsolete aww_ref_model name, the float32 model, or a newly generated kws_model.tflite. Source preprocessing/converter reference files are benchmark/training/keyword_spotting/{get_dataset.py,kws_util.py,make_bin_files.py} at that same full revision. The scalar inference reference is tensorflow/lite/kernels/internal/{common.h,quantization_util.cc,reference/softmax.h,reference/integer_ops/conv.h,reference/integer_ops/depthwise_conv.h,reference/integer_ops/pooling.h,reference/integer_ops/fully_connected.h} at the pinned TensorFlow revision, with scalar fixedpoint/fixedpoint.h from pinned gemmlowp. No TensorFlow wheel, network-accessing training script or TFDS runtime is needed to reconstruct the frozen PCM manifest.

Exact 1000-window selection

apu-kws-corpus.tsv is a normative input manifest, not a build report. It has no header, UTF-8/ASCII text, six tab-separated columns and LF terminators including the last line: six-digit index, official binary name, relative source WAV path, decimal class ID, source WAV SHA-256, padded PCM SHA-256. Its canonical-text SHA-256 is 57fa600948ef7a19ed5eb0d0e73c7d09fef7d0dbb12bc8833a0a8caad1d6845e. When checkout line endings differ, normalize CRLF to LF only before checking this text hash. Binary WAV/PCM/MFCC hashes never normalize bytes.

The verified selection reproduces TFDS speech_commands 0.0.2 ordering as used by the upstream test exporter: take each WAV's key <directory>_<filename>, sort by the unsigned 128-bit MD5 of UTF-8 test followed by that key, divide the 4890 sorted records into four contiguous shards of 1222,1223,1223,1222 records (round-to-nearest-even boundaries 0,1222,2445,3668,4890), then read 16 records from each shard in order, repeatedly. Take the first 1000. The MD5 here is an ordering algorithm, not an integrity/security checksum. All 1000 labels match the official list. No filename remapping based only on class labels, nearest-feature search or host-dependent TFDS iteration is used.

Read each selected RIFF WAV as mono 16000 Hz signed S16, preserve sample bits, right-pad with signed-zero samples to exactly 16000 samples, and emit exactly 32000 little-endian bytes. Reject a longer file or different rate/precision. The first source is stop/563aa4e6_nohash_3.wav; the last is up/c22d3f18_nohash_2.wav. The PCM manifest is independently reproducible from the public Google archive; an unavailable/deleted EEMBC td_samples package or user-supplied licensed download is not a prerequisite.

Object / byte-order of concatenation Required SHA-256
1000 padded PCM files, index 0..999, no delimiters (32000000 bytes) abd1ff2c988ac168dd68c29f934d95114d1094d7818d79fe73adb166ac009bee
Official datasets/kws01/y_labels.csv; identical to Tiny benchmark/evaluation/datasets/kws01/y_labels.csv 6cb3709762d53fe64eb00eaf4a75796248bb3c1386f1d1f93ccdb07b071e9698
Official 1000 datasets/kws01/tst_*.bin, index order, 490 bytes each, no delimiters c2e5f02def82726f5c49dfe85c311c52f295ad68561f6bae89931fdadaaedc73

The future self-owned converter is scripts/apu_kws_convert.py, contract revision apu-kws-convert/1.0.0, target p7, APUM ABI 1.0 and frontend profile 1. It performs the specified static import/packing, not training or quantization calibration. Its source commit/hash cannot exist before implementation: each P7 artifact MUST record the exact implemented converter Git revision, dirty status, source-file SHA-256 and contract revision. A dirty or missing converter identity cannot qualify a release. Two independent imports of the pinned source must give identical APUM bytes, CRC, ROM words and manifest. Check the generated APUM CRC/SHA and parameter/requantization hashes against the independent freeze-time golden values above, and record the actual results. The production converter is still an implementation deliverable; its existence or correctness is not implied by that byte-layout cross-check.

P7 qualification artifacts and gates

The implementation extends the existing APU reference setup flow with target P7 and offline doctor checks. Its generated corpus, model, coefficients, per-layer tensors and JSON reports belong below the selected committed profile's build/<profile>-<date>-<hash>/apu-kws/. Setup/doctor must check all archive, source model, label, manifest, per-file and aggregate hashes above. It must fail for missing input rather than downloading outside the shared dependency helpers or replacing the corpus with synthetic stimuli.

Required report names are provenance.json, apum-layout.json, frontend-differential.json, layer-differential.json, accuracy.json, concurrent.json, and lifecycle.json. They record input/converter/BAM/RTL revisions, model/ROM hashes, profile, simulator/tool versions, seed, exact command, success/failure, counts and artifact paths. Layout includes every image interval, scratch lifetime, bank access and high-water, not just the 53 KiB source TFLite size. That source file must never be copied verbatim into the 32 KiB APUM model reservation.

  • Official feature-input inference is a separate host/verification-only layer differential on all 1000 MFCC files; it exposes no new public operation or bypass bit. Each INT8 layer and final result is bit-exact against the pinned scalar inference reference.
  • End-to-end accuracy feeds all 1000 padded PCM windows through operation 1 and the real hardware frontend/inference path, resets history per input, threshold=128/debounce=1, and requires at least 900 correct top-1 labels out of exactly 1000. Silence/unknown remain part of the denominator. No skipped/duplicated utterance, CPU MFCC or precomputed-input substitution is allowed. Report per-class counts and every incorrect index.
  • Continuous tests cover the initial one-second warm-up, 20 ms feature hop, 100 ms inference cadence, every tie/threshold/debounce edge, snapshot coherency, counter saturation, planned gaps and stale-result prevention. Raw-mel reuse must equal recomputing the same window's integer frontend.
  • Mutate every APUM header/record/range/CRC/reserved field, per-channel scaling, sign/rounding extrema and scratch boundary. Test partial load, retry, lock, HP denial, no payload DMA before admission and no valid on failure. Independently handwritten RTL/C/Python constants and wire fixtures must agree; a register generator is still prohibited.
  • Concurrent WAV and every qualified P5 FLAC performance workload run with continuous RX KWS for at least 60 simulated seconds at 48 MHz, at both 48 and 96 kHz I2S and both precisions, with the active P5 ready-memory qualification. Require zero codec underrun and KWS overrun, every full uninterrupted scheduled window completed before its successor, and matching byte/frame/cycle/stall scoreboards. Do not promote archived P6 memory-service envelopes to new P7 prerequisites.
  • Separately inject AXI stalls/errors, RX/TX xrun, abort/reset/quiesce/handoff at each loader/frontend/layer/writeback state, descriptor wrap/ownership, half stereo pairs and unilateral clock-domain resets. These stress cases require the bounded specified recovery, not an impossible zero-xrun claim under arbitrary starvation. KWS failure must not corrupt codec SRAM, model lock or previously published descriptor completions.

IHP130 synthesis/netlist/OpenSTA and final commercial physical evidence remain P8 work, as for P5. P7 records cycle/memory/ROM/CDC integration evidence but does not claim area/timing/power closure or an official MLPerf submission. The current release still advertises no MP3 support.

P5 locked reference inputs and qualification

The following pins were read from upstream and both archive SHA-256 values were computed from the complete fixed-revision archive bytes on 2026-09-05. They are authoritative P5 setup inputs, not floating branch/tag selections. This documentation freeze does not modify the executable dependency lock. Adding the exact entries and setup/test integration below is the first P5 implementation step; missing installed inputs are setup work, not an open architecture choice. No direct download is added to CI or firmware flows.

Lock key / use Upstream and full revision Destination License handling
sources.apu_libflac / host-only reference https://github.com/xiph/flac.git, release 1.5.0 commit 1507800de4b70e21be71f38caa0d9079d0bc6e45 .cache/retrosoc/sources/apu-libflac Lock license NOASSERTION for the mixed source tree; libFLAC/libFLAC++ are BSD-3-Clause (COPYING.Xiph), CLI code is GPL-2.0-or-later. Retain COPYING.Xiph, COPYING.GPL, COPYING.LGPL, COPYING.FDL and per-file notices.
sources.apu_flac_corpus / host-only corpus https://github.com/ietf-wg-cellar/flac-test-files.git, commit aa7b0c6cf32994c106ae517a08134c28a96ff5b2 .cache/retrosoc/sources/apu-flac-corpus CC0-1.0; retain LICENSE.txt and root/per-group README.txt attribution.
Archive lock key URL SHA-256 Download destination
archives.apu_libflac https://codeload.github.com/xiph/flac/tar.gz/1507800de4b70e21be71f38caa0d9079d0bc6e45 d80ef5facdb21972efe91774da03d6b9abf216aa17093d740fcc411cd8afbb41 .cache/retrosoc/downloads/apu/libflac-1507800de4b70e21be71f38caa0d9079d0bc6e45.tar.gz
archives.apu_flac_corpus https://codeload.github.com/ietf-wg-cellar/flac-test-files/tar.gz/aa7b0c6cf32994c106ae517a08134c28a96ff5b2 36de2310155b4084011fbd56f24603dfef91a26c5433e3f92bd21995b45089c3 .cache/retrosoc/downloads/apu/flac-corpus-aa7b0c6cf32994c106ae517a08134c28a96ff5b2.tar.gz

Archive license fields match the corresponding source entries. Git checkout and verified archive extraction are two encodings of the same pinned source; setup selects one explicitly and must not silently fall back to a newer revision after a checksum failure. Build the host reference with Ogg disabled, and keep its binaries/build products in the variant build tree. No libFLAC, GPL CLI, or corpus code is linked into crt/, LP/HP firmware, RTL, or shipped APUMC; comparison is through host test processes. If reference tools are redistributed, retain their applicable source/license obligations. NOASSERTION is not a relicensing or compliance claim. P5's self-owned HAL and microassembly are independent artifacts; any copied upstream material needs explicit notice review before inclusion.

P5 delivers deterministic WAV/FLAC microassembly, the three-entry APUMC bundle, 1536-word resampler coefficient file, symbols, instruction/control-store and scratch high-water reports, and a per-file corpus manifest. The manifest records each pinned corpus relative path and SHA-256, its expected supported/rejected/ malformed result, profile reason, PCM geometry, and reference-output hash. Every official corpus file is classified, including files above P5 block limits; unsupported files must be tested for clean rejection, not silently omitted. Generated valid/malformed vectors supplement the official corpus for every WAV chunk boundary, FLAC escape width zero, wasted-bit count, predictor order, CRC fault, strict/relaxed case, and 2048/4096 block boundary. Host libFLAC supplies PCM truth; the independent integer post-processing model supplies downmix/resample/packing truth. CRC-only success with MD5 unchecked must be visible in expected results. The host harness obtains PCM even for an MD5-only mismatch and records that reference integrity failure separately; it must not mislabel the P5 documented MD5-unchecked acceptance as a PCM decoding mismatch.

Directed tests must exercise production direct and ring submission, invalid owned MP3/KWS entries, class-6 cursor/FIFO backpressure, all three required bundle entries, every format error tuple, exact output capacity and one-frame short capacity, I2S final TLAST/drain, abort/reset during every transport stage, and cross-format ring sequences. Differential Icarus and Verilator runs use the same fixtures and result scoreboard; no verification injector may appear in product behavioral or synthesis filelists. Formal covers exclusive DMA/SRAM ownership, range checks, stable stream payload under stalls, accepted-transfer drain, OWN-clear ordering, and no public MP3/KWS/RX execution. P3/P4 target and observability regressions remain required.

At 48 MHz PCLK, a ready memory target must sustain the P5 supported WAV/FLAC rates and 44.1-to-48 kHz conversion in cycle-counted simulation. The I2S test starts consumption after a 64-word APU prefill (or the whole output for a shorter job), then supplies ready memory without injected stalls; between first and last samples it must record zero xrun. Separate random-stall tests verify bounded error/drain rather than claim uninterrupted playback under unbounded stalls. Measured maximum tolerable AXI stalls, source properties, instruction budget, and occupancy must accompany results. Static timing, area, power, netlist, and physical 48 MHz closure remain Phase8 evidence.

Deferred APU-P6 references and qualification — inactive for this release

P6 locked MP3 inputs and numerical evidence

Status: DEFERRED. This section and its PSNR, real-time and physical-evidence subsections are historical notes, not current-release requirements. No MP3 dependency setup, decoder/corpus build, PSNR run, 320 kbit/s workload or three-active-codec report is required by this release. Current P8 physical requirements are stated in the active Synthesis, Timing, and Physical Evidence section; archiving these P6 notes does not remove those P8 requirements.

These fixed revisions and archive SHA-256 values were read and computed from the complete upstream archive bytes on 2026-09-11. P6 implementation extends scripts/setup_apu_reference.py and the executable dependency lock with these exact keys. This refreeze changes documentation only. Existing FLAC lock keys, setup and qualification remain intact.

Source lock key URL / full revision Source destination License record
apu_minimp3 https://github.com/lieff/minimp3.git / ea99364f61c14656440e8d77e9c233ccf3124633 .cache/retrosoc/sources/apu-minimp3 CC0-1.0, retain LICENSE and upstream attribution.
apu_mpg123 https://github.com/madebr/mpg123.git / f6c19f46031088efc8d0e5b83305a6f36ceceb65 .cache/retrosoc/sources/apu-mpg123 LGPL-2.1-only as the default COPYING terms; retain COPYING, AUTHORS and any per-file exceptions.
apu_mp3_corpus Same minimp3 URL / ea99364f61c14656440e8d77e9c233ccf3124633; select vectors/ .cache/retrosoc/sources/apu-mp3-corpus Record upstream CC0-1.0 declaration and retain LICENSE; preserve vector provenance and any per-file notices. Host-only test material, not a claim of ISO certification or a new license grant over third-party vectors.
Archive key URL SHA-256 Download destination
apu_minimp3 https://codeload.github.com/lieff/minimp3/tar.gz/ea99364f61c14656440e8d77e9c233ccf3124633 5628166eb82a9bb581317918a334c317a2c0a30278bb14a20381307976768f34 .cache/retrosoc/downloads/apu/minimp3-ea99364f61c14656440e8d77e9c233ccf3124633.tar.gz
apu_mpg123 https://codeload.github.com/madebr/mpg123/tar.gz/f6c19f46031088efc8d0e5b83305a6f36ceceb65 1b42d961c56ec0e47510e69768277dd6726316a3063116bfd8264f19b9e1c218 .cache/retrosoc/downloads/apu/mpg123-f6c19f46031088efc8d0e5b83305a6f36ceceb65.tar.gz
apu_mp3_corpus Same fixed minimp3 archive URL 5628166eb82a9bb581317918a334c317a2c0a30278bb14a20381307976768f34 Same minimp3 download destination, verified once and reused for extraction.

The mpg123 mirror is linked by the project's download page. The two decoders have independent implementations; one decoder executed with two configurations is not sufficient. All reference programs and corpus files are host-only, outside firmware, RTL and APUMC release outputs. Use shared checksum/download/extraction helpers; there is no floating HEAD/tag fallback. Retain notices with cached sources and any redistributed reference artifacts. Product microassembly and numerical tables must have independently recorded provenance; copying GPL/LGPL decoder code into the product is not authorized by these test-input pins.

Setup keeps the existing --build-dir interface and adds --phase p5|p6 (default p5). P6 installs all P5 inputs plus the three keys above. It checks CMake at least 3.27, Ninja, and a C compiler before building the pinned mpg123 tree at ports/cmake; use BUILD_PROGRAMS=OFF, BUILD_LIBOUT123=OFF, BUILD_SHARED_LIBS=OFF, GAPLESS=OFF, NO_LAYER1=ON, NO_LAYER2=ON, NO_NTOM=ON, NO_EQUALIZER=ON, NETWORK=OFF, NO_REAL=OFF, and HAVE_FPU=ON. Select the library's generic decoder explicitly. Build minimp3 with MINIMP3_IMPLEMENTATION, MINIMP3_ONLY_MP3, MINIMP3_NO_SIMD, and MINIMP3_FLOAT_OUTPUT. Both host wrappers disable fast-math and FP contraction, use native source rate/channels and float32 output, and record compiler, configuration and binary hashes. Missing build tools are explicit setup prerequisites, not skipped evidence or direct unpinned installer downloads.

mpg123 uses feeder decoding with GAPLESS removed, IGNORE_INFOFRAME set, unity scale, ReplayGain disabled and no forced resampling or mono mode. minimp3 uses the frame decoder with persistent state, not the extended whole-file helper's automatic gapless trimming. Both receive the same exact MPEG frame bytes after this specification's metadata classification. Assert frame count, sample count, rate and channels before comparing PCM. A reference that silently resynchronizes or omits an Info frame is a harness failure. Neither reference's CRC/underflow tolerance is the oracle for malformed files: a separate bounded header/reservoir/CRC model implements the P6 rejection rules.

Every pinned vectors/**/*.bit and vectors/**/*.mp3 is classified in a committed deterministic manifest by path and SHA-256. Unsupported layer/free- format/geometry/emphasis cases are rejection tests, not silently excluded tests. Every valid in-profile file is a numerical test. Paired upstream .pcm files are supplementary evidence with their byte order/count recorded; the primary normalized oracle is the pinned mpg123 wrapper. Required stress families include l3-compl.bit, l3-he_32khz.bit, l3-he_44khz.bit, l3-he_48khz.bit, l3-he_mode.bit, l3-si.bit, l3-si_block.bit, l3-si_huff.bit, l3-sin1k0db.bit, M2L3_bitrate_16_all.bit, M2L3_bitrate_22_all.bit, M2L3_bitrate_24_all.bit, M2L3_compl24.bit, and the performance vectors below. A named file may fail the P6 profile; its exact first-offender result is then tested instead of treating tolerant reference decoding as evidence of support.

Self-owned deterministic vectors supplement missing corners: all nine rates, both channel counts, all supported bitrate indices, MPEG-2.5, protected frames, all block/mixed modes and joint-stereo combinations, maximum reservoir, VBR, zero main-data, every ID3 flag/size/footer boundary, and truncated headers, side-info and entropy. Generate exact coded frames from documented literal headers/side-info/Huffman symbols and pair every valid frame sequence with both decoders; no new encoder dependency or opaque Internet audio sample is needed. No coverage item is waived merely because the pinned corpus lacks it.

P6 PSNR calculation and comparison windows

Compare native-rate, source-channel MP3 PCM before P5 downmix/resampling. Promote each reference float32 x to float64 before normalization. Clamp it to [-1,1-2^-31], round x*2^31 to nearest-even, then arithmetic-shift right eight bits to obtain signed 24-bit r. Obtain APU a from S24_32 output using the same native geometry and no optional processing. Full-scale peak is fixed at P=8388607, not the measured signal peak. For N samples, SSE=sum((a-r)^2), MSE=SSE/N, and PSNR=10*log10(P^2/MSE); SSE zero means positive infinity. NaN/infinite reference samples fail the harness before quantization. Accumulate integer SSE in at least 128 bits or arbitrary-precision integers without overflow. The acceptance comparison is strictly SSE < N*P^2/10^9.6 (>96 dB), evaluated with enough precision to resolve the boundary; printed rounded dB is never the verdict.

Require >96 dB against each independent reference on the full file, on each individual channel, and on consecutive 1152-source-sample-frame windows (including the final nonempty short window). Also compare the two references to each other with the same threshold; disagreement blocks qualification and must be investigated, not resolved by choosing the easier oracle. Report SSE, N, maximum absolute error and worst-window PSNR. Do not optimize delay, gain, sample offset, or channel permutation to raise PSNR. Start all decoder histories empty, include encoder/synthesis delay and padding samples, include Info frames, and require exactly 1152/576 frames per MPEG frame; there is no trimmed warmup window. Empty/tag-only inputs are error tests, not infinite- PSNR successes.

Separate S16, downmix and resampling tests compare against applying the frozen P5 integer post-processing model to the APU's native decoded sequence. This isolates post-processing correctness from MP3 approximation error; the native PSNR gates still apply. Run the unchanged WAV/FLAC bit-exact corpus against both the legacy P5 image and the rewritten P6 image. Code relocation may change build IDs and cycle/PC measurements, but not PCM, accounting or semantic errors.

P6 real-time envelope and physical-evidence boundary

The mandatory 320 kbit/s, 48 kHz joint-stereo workloads come from the pinned corpus. Their file hashes are:

Relative path under vectors SHA-256
performance/MIPSTest.mp3 197265fa09d1b6777b71269d986055035f3e9e1f4d74e4cbaa0e55034447a9ca
performance/MEANDR_PHASE90.mp3 b8a8f2b38e2cacc42849af754a926552b87478003738a9f40c86ff0e22f555a1
performance/noise_meandr.mp3 423a97ef5b01c8253940d04bf93ee0d9508b77ef17608c69a1b3c09ae8667c0d

Run each as a finite job and in a descriptor ring for at least 60 simulated seconds, restarting decoder history at each job boundary as specified. Test S16 and S24_32, at 48 MHz PCLK, 48 kHz I2S; test 48-to-96 kHz output separately using the P5 resampler. KWS is disabled in P6; simultaneous KWS qualification is still a P7/P8 requirement. Do not label a clock divider slower than 48 MHz or a different source corpus as the qualified run.

The qualified AXI service envelope is measured at the APU PCLK master and includes Gateway A/CDC/target delay: AR or AW handshake within 64 PCLK cycles of continuously asserted VALID; first RVALID within 32 cycles after AR; at most four cycles between available R beats when the APU is ready; WREADY at least once every four cycles after AW; BVALID within 16 cycles after the last W handshake. Bursts are the existing 1..16 beats/4 KiB subset, responses OKAY. The BFM must cover both zero-delay and maximum-delay schedules and randomized legal schedules. APU-generated backpressure and local-SRAM stalls are not subtracted from execution time. This is a qualified environment assumption, not a new QoS guarantee imposed on the entire SoC or on slow serial memories.

Start I2S consumption after 64 APU-router words are prefetched, or the whole output for a shorter job; initial prefill must finish within 2400000 PCLK cycles from the first MPEG header after ID3. Per job, the steady interval from the first consumed PCM sample through the last must show zero I2S underrun, zero dropped/reordered/duplicated PCM frames, exactly one final TLAST for a nonempty output, and exact P5 byte/frame counters. Queue gaps between jobs are excluded only if explicitly recorded; they are not a gapless-playback claim. Clear xrun state before the window and check both sticky state and event scoreboard during it. Report effective clocks, per-frame/granule cycles, minimum FIFO occupancy, refill stalls, last-sample time and the full service trace. An average faster-than-real-time result cannot excuse an underrun.

Randomized tests beyond the service envelope verify the existing timeout, first-error and drain behavior; uninterrupted playback is not required under unbounded stalls. Physical signoff remains deferred to P8 as in the approved APU execution policy. P6 completion requires functional/cycle/formal evidence, not a claim that an RTL cycle model closes physical timing.

P8 must synthesize this exact P6/P7 hierarchy and compare with the reviewed P5 baseline under the same committed IHP130 profile and locked tools. Static acceptance is max-delay WNS >= 0 ns and TNS = 0 at the 20.833 ns PCLK target, no unconstrained active APU clock/data paths, no inferred latch or unresolved non-PDK black box, and all macro/clock/reset views accounted for. Report hold analysis separately; pre-layout STA is not post-layout signoff. Area acceptance requires the unchanged eight control plus 28 data SRAM wrappers, complete cell/macro accounting and reviewed per-block/total deltas versus P5. There is no approved absolute standard-cell mm2 or power ceiling before measurement: those metrics remain explicitly report-only under repository policy, and a missing area report is not an area pass. No global warning or metric policy is changed by these feature evidence requirements.

Required evidence matrix

Area Required evidence
APB/register Decode, waits, strobes, RO/WO, busy protection, W1C/set priority, reset, capability, and RTL/C parity.
DMA/ring Native AXI BFM plus the P2 verification-only backend cover internal direct/ring ownership, writeback, wrap, coalescing epochs/IOC, 4 KiB split, tails, ACL overflow, faults, abort, and timeout without a public diagnostic operation.
Streams P2 verification-only endpoints cover both production router/FIFO directions, random backpressure, watermark/xrun, active detection, and route protection; later phases add S16/S24/TLAST and concurrent codec/KWS product endpoints.
Assembler/loader Syntax and semantic rejection, deterministic binary, all control-flow/loop/stack/range checks, CRC, capability, atomic valid/lock, mutation/fuzz.
Sequencer/formal PC/control-store bounds, only bounded loop-back, counter decrement, call depth, watchdog, no system/APB access, descriptor-only DMA handles, legal traps.
Primitives Bitstream/CRC, every Huffman/Rice mode, arithmetic extremes, saturation, transform/LPC/resampler differential, latency bounds.
Codecs WAV/FLAC complete-file differential, sample/rate/channel counts, malformed/truncated/adversarial corpus, metadata limits, FLAC predictor/Rice extremes, and long playlists; MP3 is tested only for unsupported-request/stub compatibility.
KWS MFCC differential, every INT8 layer tensor, converter rejection, official accuracy, threshold/debounce, continuous stream and overrun.
SoC Address/topology, Gateway A fairness, Resource7, IRQ31/PLIC10 exclusion, cache maintenance, handoff, warm flush, HP reset, USB2/SDIO0 contention.
Software HAL validation/timeouts/errors, microcode/model load, owner handoff, bare-metal LP/HP acceptance, and cache/handoff tests. Linux ASoC is deferred.

An internal KWS result is not called MLPerf unless the exact applicable rules and runner are followed. File interoperability alone is not codec certification.

P9 memory-reduction verification and evidence

Use the same committed IHP130 profile, locked Yosys (currently dependency-lock 0.67), Slang build, PDK revision, macro views, PCLK/SDC, ABC recipe, flatten/ keep-hierarchy rules, host resources and timeouts for baseline A and candidate B. Record executable/plugin hashes as well as version strings. Baseline A is the inspected pre-P9 revision; B includes the migration and generated APUC. Separate checkouts/output roots preserve both artifact sets. Non-APU inputs must match; otherwise rebaseline explicitly rather than attribute unrelated changes to P9.

Do not confuse the existing EnableP7=0 versus EnableP7=1 block report with this A/B test: memory-reduction A and B both have KWS enabled. Also retain the existing P5-versus-KWS physical comparison. Use the production SRAM-macro configuration, real model/coefficient loaders and full arithmetic datapaths, not a stub, preinitialized inferred RAM or disabled KWS elaboration.

Required evidence below the variant root in apu/p9/evidence/:

Report Required evidence
coefficient-layout.json All ten table word counts/hashes, logical-to-bank inverse mapping, zero padding, image/header CRC/SHA, generator revision and the exact 15-wrapper map.
coefficient-lifecycle.json LP admission, unsupported discovery, cache/ACL checks, DMA/backpressure, payload/readback corruption, partial load/retry, lock, ownership, hard/soft/resource reset, quiesce-load and abort-at-every-state tests.
memo-equivalence.json Baseline versus macro-memo proof verdicts/first errors/visited states on valid and mutated APUMC V1/V2; duplicate keys, collisions, wrap, full table, deeper-call bypass, key/bitmap boundaries and interrupted clearing/insertion.
numerical-latency.json Every coefficient and all scalar/table boundary cases, variable response backpressure, no double commit/stale response, bit-exact MFCC/layer/final outputs, component and complete-window cycle counts.
memory-synthesis-ab.json Per-hierarchy pre-memory bits/ports/instances, source and lowered memory forms, flop/mux counts, macro types/counts, memory/opt_dff/ABC/whole-flow times, peak RSS, return status/timeouts and raw report paths for A/B.
physical.json Logic area and macro area separately, total area, WNS/TNS, unconstrained paths, hold reports, macro timing views and netlist-model coverage; no PDK black box silently omitted.

The layout test must enumerate every valid logical table index, prove the inverse mapping, count exactly 14444 populated positions and 916 zero-padding positions (populated coefficient/profile words may themselves be zero), and compare the generated APUC to the frozen hashes. Compare every lookup against the pre-P9 reference, including last Hann/Mel/DCT/FIR indices, both twiddle components, Log[1024], Softmax differences 0/124 and rejection of 125, and all 1496 APUM profile words. Candidate tables/ROM helper functions cannot serve as the only oracle for their own SRAM addresses. Use unknown/random macro power-on data in tests; a successful LP load must establish all contents.

Model validation must still reject profile-word mutations and CRC-consistent adversarial images as before; replacing the expected-word source with SRAM must not replace structural validation with CRC alone. Test access at key indices 0/31/32/1023/1024/8191, stale invalid-key data, same-bitmap-word inserts, full hash wrap and equality differing only in upper key bits. A memo hit may only skip a state that the unchanged exact-key policy permits. P9 may take more cycles but must not reject a formerly accepted image by counting SRAM cycles against the semantic traversal bound.

Run the full existing 1000-PCM hardware accuracy path (at least 900/1000), per-stage/layer differentials and 60-second concurrent WAV/FLAC + KWS matrix, including 48/96 kHz and S16/S24. Neither reduced smoke windows nor a CPU reference replaces these reports. Reuse/extend run_apu_p7_kws_rtl.py, run_apu_p7_concurrent_rtl.py and the P8 LP/HP/quiesce/contention tests to load APUC through the public interface. Permit extra measured processing cycles only while every complete continuous window finishes before its successor, mel/input history is not overwritten and no xrun occurs under qualified ready-memory conditions. Keep arbitrary-starvation fault recovery separate.

For structural acceptance, count memories with hierarchy multiplicity and width*depth consistently at the existing pre-memory checkpoint. The four targeted storage classes must contribute zero inferred bits. Require at least 90 percent reduction in APU-owned inferred bits and the 65536-bit residual ceiling, plus exactly the live macro groups in the P9 allocation table. Do not move memory_map before the checkpoint, remove hierarchy from the report, replace memories with equivalent giant flop/mux banks, or alter the SAT/ABC recipe merely to meet this statistic. Archive post-memory/pre-tech mapped logic inventories as the cross-check. Wrapper simulation arrays are not counted as physical macro storage in an IHP130 synthesis report.

The candidate must complete memory lowering and the unchanged opt_dff -sat -nodffe -nosdff pass within the existing flow limits; compare their combined runtime, full synthesis wall time and peak process-tree RSS. Require demonstrated improvement in post-memory processing and peak RSS for the memory-reduction handoff, not just fewer inferred bits. If A times out, record a censored observation and a lower time bound, not a made-up finished runtime or percentage. A completed B below that bound establishes a bounded runtime improvement; RSS needs its own measured comparison. Unavailable evidence is UNRUN, a timeout is not PASS, and absent improvement remains an explicit P9 acceptance gap. No new absolute area/power ceiling is invented.

Update report_apu_block.py's classifications and tests: source-era text that describes the KWS window as flops is already stale, and counts omitting the path stack, new memo/bitmap or coefficient banks are invalid. Distinguish advertised capacity, physical provision, utilized payload and alignment waste. Report added macro area/power/fanout and startup traffic alongside reduced standard-cell storage. These are phase acceptance/review requirements, not authorization to change the repository's observe-mode metrics policy, warning baselines, synthesis timeouts or global CI quality policy.

Synthesis, Timing, and Physical Evidence

The committed MVP profile is configs/ci/ihp130.mk. Block and full-SoC synthesis use locked Yosys. OpenSTA analyzes the 20.833 ns/48 MHz PCLK target and existing asynchronous relationships. Correctness at slower dividers is required but no slower-clock real-time claim follows.

Current P8 physical acceptance covers the active P5 WAV/FLAC and P7 KWS hierarchy, compared with the reviewed P5 baseline under the same IHP130 profile and locked tools. Max-delay WNS must be >= 0 ns and TNS = 0 at the 20.833 ns PCLK target, with no unconstrained active APU path, inferred latch, or unresolved non-PDK black box; all macro/clock/reset views must be accounted for and hold analysis reported separately. Retain the eight control-store plus 28 data-store SRAM wrappers and report verifier/auxiliary macros separately. The post-P9 hierarchy adds the frozen memo/bitmap/coefficient banks and must meet the full 76-wrapper inventory, not a historical 36-wrapper total. Complete per-block cell/macro/delta accounting is mandatory. Standard-cell area and power remain report-only with no approved absolute ceiling, and missing reports do not count as passes. Pre-layout STA does not replace physical signoff. No MP3 hierarchy, decoder quality or MP3 performance result is required for this release's P8 acceptance.

Evidence includes:

  • control-store and local-SRAM macro count/utilization; expanded P5 uses eight 4 KiB control-store wrappers plus the unchanged 28 local-data wrappers (36 advertised-capacity wrappers versus 32 before expansion). Control storage increases 16 KiB and combined image/data storage increases from 128 to 144 KiB. These are capacity counts, not measured area/power; report verifier workspace, additional PC/branch flops, muxing, and fetch paths separately;
  • sequencer, entropy, transform, reconstruction, resampler, and KWS cells/area;
  • max/min WNS/TNS, worst APU paths, reset/fanout, clock gates, and black boxes;
  • instruction/control-store high-water, maximum frame instruction count, loop/call high-water, local SRAM high-water, and primitive cycles;
  • decoder/KWS cycles, DMA/stream stalls, sustained bandwidth, and concurrent workload utilization;
  • netlist simulation, warning JSON, metrics JSON, and manifest evidence.

No target area or power number is approved before measurement. A successful tool exit is not closure. Commercial release additionally needs qualified SRAM views for every product PDK, CDC/RDC, scan/ATPG, MBIST/repair, PVT/MMMC, CTS, extracted STA, activity power, IR/EM, SDF, package/board audio timing, and silicon characterization.

Development Order

The following phase IDs and titles are frozen. They MUST NOT be renamed, renumbered, or reused; later work receives a new phase.

The active order is P0..P5, then P7 functionality, then the new P9 storage migration, then final P8 physical/release closure. Existing P8 software and banked-KWS integration work is reused; P9 does not depend on completed P8 physical signoff. Phase numbers are stable identities, not a reason to create a circular prerequisite. P6 is a deferred placeholder, not an implementation task or a prerequisite for P7/P8/P9. Record it as DEFERRED, not completed or verified. Resuming MP3 requires a later explicit scope refreeze; the retained reference material is not authorization to start it automatically.

Phase 0 - Freeze Coreless Microcode Architecture and ABI

ID: APU-P0.

Scope: this specification, requirements, coreless hierarchy, ISA, APUMC, APUM, descriptor/register/error/IRQ ABI, format limits, KWS baseline, golden models, dependency plan, and stable phases.

Changes: documentation/index/RTL guide only. It freezes future public interfaces but changes no executable RTL, address map, software, dependency, clock/reset inventory, or CI.

Validation:

git diff --check

Completion: all links/commands resolve, rejected processor/host-decode behavior is absent from normative requirements, and all deferred work is explicit.

Phase 1 - APB4 Shell, Resource Ownership, and IRQ Topology

ID: APU-P1.

Scope: APB register shell, reset/capability/command/error/IRQ, fail-closed datapath stubs, Resource index7, APB slot, LP IRQ31, HP PLIC10, HAL discovery, manual C/SVH definitions, and parity tests.

Dependencies: Phase0.

Public changes: activates APB4_APU, extends resource count and IRQ topology; no DMA, microcode, stream, or CDC behavior is implemented.

Validation:

make check-memory-map check-soc-topology
make sw-format-check sw-policy-check sw-host-test
python3 -m pytest -q
make CONFIG=configs/ci/ihp130.mk APP=ci_smoke firmware

Completion: every APB/reset/access case and topology/parity check passes; datapath commands return the frozen unsupported/error behavior.

Phase 2 - Private AXI4 DMA and Audio Stream Routing

ID: APU-P2.

Scope: direct/ring DMA, descriptors, ACL, fair Gateway A arbitration, PCLK-to-HP integration, stream router/FIFOs, I2S directions, abort/drain, bus errors, P2 status/watermark semantics, and counters.

Dependencies: Phase1 and existing Common interfaces/FIFO/CDC/arbitration.

Public changes: implements DMA/ring/ACL transport, the appended STREAM_WATERMARK register, frozen STREAM_STATUS/JOB_STATUS/ RING_STATUS fields, CAPABILITY0=0x00000018, and the apu_data CDC inventory. CAPABILITY1, ABI_DIGEST, format/stream/KWS/sequencer/resampler capabilities, public start/doorbell, and public APU stream routes remain at the specified fail-closed P1 values. No sequencer, primitive, codec, KWS, public diagnostic operation, or synthesized diagnostic endpoint is added.

Validation:

make check-soc-topology check-clock-reset-domains
python3 -m pytest -q
make CONFIG=configs/ci/ihp130.mk formal
make CONFIG=configs/ci/ihp130.mk SIMU=VERILATOR rtl-lint
make CONFIG=configs/ci/ihp130.mk APP=ci_smoke SIMU=VERILATOR firmware sim

Completion: the production DMA and ring scheduler pass direct/ring directed and random tests through the verification-only backend; the production router and both 64-word FIFO directions pass standalone backpressure/watermark/xrun tests; public start/doorbell and route value1 remain rejected; every bus fault, timeout, coalescing epoch, writeback, and abort path is bounded; status/IRQ/C parity passes; Gateway A fairness is demonstrated. No P3..P7 engine is required for P2 completion.

Phase 3 - Microcode Assembler, Loader, and Sequencer

ID: APU-P3.

Scope: apu-mcasm, reference interpreter, ISA tables, APUMC loader, 2048x64 control store, scalar/loop/call state, load-time local/table protection, watchdog/traps, loader lock/atomic publication, ABI parity, co-simulation, and formal. Class-2 through class-6 execution, codec tables, and data SRAM remain outside this phase.

Dependencies: Phase2, the Common tc_sram_1024x32 wrapper for macro profiles, and the frozen inferred-control-store fallback for HAVE_SRAM_MACRO=NO.

Public changes: implements the frozen microcode loader, class-0/class-1 sequencer, MC_STATUS, MC_ABI, build/CRC/lock/count, IRQ bit 3, and exact P3 values CAPABILITY0=0x00000098 and CAPABILITY1=0x00000010. ABI_DIGEST remains zero. Public direct/ring commands and APU stream routes remain fail-closed, and the verification-only dummy launch adds no public ABI. It adds no processor, system hart, new clock domain, or arbitrary code execution.

Validation:

python3 -m pytest -q
make CONFIG=configs/ci/ihp130.mk formal
make CONFIG=configs/ci/ihp130.mk SIMU=VERILATOR rtl-lint
make CONFIG=configs/ci/ihp130.mk APP=ci_smoke LINK_TYPE=ld2_all_sram SOC_SIM_TIME=360 VERILATOR_SIM_ARGS=--fast-flash SIMU=VERILATOR HAVE_SVA=YES firmware sim
make CONFIG=configs/ci/ihp130.mk SYNTH=YOSYS synth
make CONFIG=configs/ci/ics55.mk SYNTH=YOSYS synth

The 360-second command with --fast-flash is the supported P3 SoC-level Verilator acceptance command; fast flash changes only boot/XPI timing and does not bypass APU logic. Directed loader/sequencer tests remain the functional evidence for the P3 paths.

Completion: all three required zero-table/zero-primitive entries load atomically and deterministic class-0/class-1 dummy programs execute through the verification-only launch. Every malformed header/descriptor/ISA/control- flow/range/table/CRC/capability/watchdog case fails closed with the frozen status, IRQ, count, and reset result. Macro and inferred control-store mappings, including ICS55 elaboration/synthesis, are reviewed. No P4..P7 engine is required for P3 completion.

Phase 4 - Shared Bitstream, Entropy, and DSP Primitive Engines

ID: APU-P4.

Scope: reservoir, CRC, Huffman/Rice, scalar reconstruction, transform, resampler/PCM packer, 112 KiB local SRAM arbitration, primitive scoreboard, latency counters, extreme arithmetic tests, and formal bounds. The implemented primitive mask is 0x0000ffff; class 6 and primitive bits 16..20 remain outside this phase.

Dependencies: Phase3, Common tc_sram_1024x32, and Common stream_fifo.

Public changes: reports exact P4 values CAPABILITY0=0x00000198 and CAPABILITY1=0x01827010, admits the frozen class-2..5 ISA and APUMC table/ scratch fields, and retains ABI_DIGEST=0. Format, stream, and KWS capabilities remain zero, while primitive channel/rate discovery becomes 2/96 kHz; public direct/ring/stream behavior stays fail-closed. No new public register, opcode class, format ID, IRQ, resource, address, clock/reset boundary, or CDC/RDC entry is added.

Validation:

python3 -m pytest -q
make CONFIG=configs/ci/ihp130.mk formal-apu
make CONFIG=configs/ci/ihp130.mk SIMU=VERILATOR HAVE_SVA=YES rtl-lint

tests/test_apu_primitives.py is a required P4 deliverable and runs the same golden corpus through the Python BAM/interpreter plus focused Icarus and Verilator primitive testbenches. formal-apu must include the P4 dispatcher, local-range/validity, single-kernel, and latency-counter properties.

Completion: every primitive matches BAM over directed/random/extreme inputs, meets the frozen ready-data latency bound, reports the frozen fault tuple, proves local/table/FIFO bounds, and preserves all fail-closed public paths. Yosys synthesis, OpenSTA, netlist simulation, macro PPA, and 48 MHz closure are explicitly deferred to Phase8 and are not P4 completion gates.

Phase 5 - WAV and FLAC Microprograms

ID: APU-P5.

Scope: WAV/FLAC microassembly, tables, metadata/frame parsing, PCM conversion, Rice/fixed/LPC/decorrelation, resampling, memory/I2S output, interpreter/RTL differential, conformance corpus, and the frozen P5 HAL. Includes production class-6 transport, controller entry context, direct/ring backend connection, TX stream routing, and exact codec/result policies in the P5 sections above. The capacity refreeze adds the 4096x64 store, 12-bit PC/branch datapaths, APUMC V2 plus legacy V1 decoding, and APB V1.1 PC_HIGH/capacity discovery to this phase. Previously completed transport, HAL, formal, and corpus work is the implementation base and is preserved except for the required version/ capacity/width integration.

Dependencies: reviewed Phase4 and the exact RFC/libFLAC/corpus inputs above. Implement their dependency-lock/setup entries before reference tests. No host decoder enters the product path.

Public changes: CAPABILITY0=0x000001bd, CAPABILITY1=0x01827020, implemented primitive mask 0x001fffff, classes 0..6, format IDs 0/2, TX route 1, and the documented HAL. IP_VERSION=0x00010001; new release images are APUMC V2.0, with widened entry PC/branch operands and PC_HIGH at SEQUENCER_STATUS bit 21. MP3/KWS/RX route 1 remain unavailable and ABI_DIGEST=0. No existing APB offset, job-descriptor layout, legacy APUMC V1 encoding, P1..P4 target behavior, Resource7, APB group23, IRQ31/PLIC10, Gateway A identity, or clock/CDC allocation changes.

Validation:

python3 scripts/dependency_lock.py --lock dependencies/dependencies.lock.json
make sw-format-check sw-policy-check sw-host-test
python3 -m pytest -q
make CONFIG=configs/ci/ihp130.mk firmware
make CONFIG=configs/ci/ihp130.mk SIMU=VERILATOR HAVE_SVA=YES rtl-lint
make CONFIG=configs/ci/ihp130.mk formal-apu formal-apu-loader formal-apu-sequencer
make CONFIG=configs/ci/ihp130.mk APP=ci_smoke LINK_TYPE=ld2_all_sram SOC_SIM_TIME=360 VERILATOR_SIM_ARGS=--fast-flash SIMU=VERILATOR HAVE_SVA=YES firmware sim

tests/test_apu_codecs.py and tests/test_apu_codec_transport.py are P5 deliverables included by the full Pytest command; missing required EDA/reference tools are reported as unrun, never counted as passing skipped tests. The ci_smoke command proves SoC integration and does not replace the directed codec corpus or long-playback evidence.

Capacity-migration verification is mandatory in those same test/formal flows:

  • V1 accepts 2048 words and rejects 2049; V2 accepts complete 2049/2437/4096- word fixtures and rejects 4097. A count of zero is rejected in both. Test V1 high descriptor bits and immediate bit 11, V2 reserved bits and immediate bit 12, unknown ABI, bad CRC, and field/region overflow with exact loader error tuples and no valid/lock publication.
  • Round-trip entry/first/last PCs 0, 2047, 2048, and 4095 in handwritten SV/C and Python tables. Exercise jump/call/return/loop crossings in both directions across 2047/2048, zero/maximum deltas, underflow and a target of 4096; call and loop depth/budgets retain their existing limits. No high bit may alias.
  • Verify loader writes, proof-state save/restore and fetches across all four depth banks with distinct low/high words. Verify eight-macro and inferred mappings in behavioral tests, including the no-macro profile. Abort/reset/ CRC failure after upper-bank writes must leave stale code unexecutable; legacy images cannot execute it. Run the complete existing V1 P3/P4/P5 fixtures, retaining their original binary bytes and terminal tuples.
  • At PCs 2048 and 4095, verify SEQUENCER_STATUS PC_HIGH and all existing class/opcode/wait/loop fields, full ERROR_ADDRESS, unchanged low-PC detail packing, explicit-TRAP immediate, and END/trap/abort/reset retention. Include an aux value with bit 4 set so no diagnostic bit is silently lost.
  • Rebuild the shared production WAV/FLAC bundle with every previously frozen parser/output/error path, cross-frame FLAC resampling, and complete supported long-Rice handling. Count every control-store word including the MP3 stub, common subroutines and padding. The complete bundle must use at most 4096 words and publish exact size, free words, CRC/build/SHA-256 and source hashes. A larger capacity alone, the incomplete 2437-word trial, or passing only already-delivered transport tests cannot establish P5 completion. If the complete image still exceeds 4096, report a capacity conflict; do not remove required paths or move parsing into RTL/LP/HP.

Completion: the exact supported/rejected matrices, malformed corpus, published error/count rules, HAL host tests, and production direct/ring/TX paths pass. Matching-precision/rate/channel FLAC is bit-exact; 44.1-to-48 and 24-bit/96 kHz playback meet the cycle-counted xrun gate. Larger FLAC blocks, whole-file MD5, unlisted conversion ratios, MP3 and KWS are outside P5. Synthesis/STA/netlist/ PPA remain deferred to Phase8; functional cycle evidence is not timing signoff.

Phase 6 - MP3 Layer III Microprogram and Real-Time Closure

ID: APU-P6.

Status: DEFERRED for the current release. The ID and title are retained for traceability; this phase must not be reported as implemented, passed or merged merely because it has been excluded.

Scope: no MP3 implementation in this release. Do not add an active p6 target, MP3 microprogram, three-real-codec bundle, MP3 reference/corpus setup, or MP3 PSNR/real-time qualification on behalf of this phase. Retain the existing format ID, enum, reserved diagnostic IDs and unsupported-MP3 trap entry. Previously implemented P4 primitives, 4096-word control store, APUMC V1/V2 compatibility, and all P5 functionality remain unchanged.

Dependencies: none for the current active release path. A future MP3 effort requires an explicit refreeze and a fresh capacity/behavior/evidence review; the archived P6 notes do not activate it.

Public changes: none from this deferred phase. MP3 CAPABILITY0 bit 1 stays zero. Discovery remains 0x000001bd before KWS and becomes 0x000001fd only when P7's KWS capabilities are actually implemented and qualified. CAPABILITY1=0x01827020 and IP_VERSION=0x00010001 are retained; ABI_DIGEST=0 through P7. P5 direct/ring MP3 rejection and the exact verification-only trap-stub result remain required.

Validation: no positive MP3, dual-decoder, MP3 dependency, 320 kbit/s, >96 dB or three-active-codec packing gate applies. Continue the existing P5 unsupported-request, legacy image, ABI parity, and primitive regressions.

Exit status for release planning: DEFERRED, not COMPLETE. The next active phase is P7 from reviewed P5; P8 reviews the active WAV/FLAC/KWS release and does not wait for P6.

Phase 7 - Independent Continuous KWS Engine

ID: APU-P7.

Scope: 16 kHz input, MFCC, APUM converter/loader/lock, fixed INT8 engine, continuous scheduler, threshold/debounce, diagnostic operation1, IRQ, accuracy, performance, and concurrent decode/KWS.

Dependencies: reviewed Phase5; the P7 source/model/corpus/converter contracts above are frozen inputs. Registering their exact dependency entries and installing them through the shared setup flow is P7 implementation work, not an open choice of model/dataset or a missing-user-data prerequisite. Deferred Phase6 is not a prerequisite and its MP3 reports are not required.

Public changes: implements frozen KWS/model/descriptor-operation/IRQ/counter ABI, the additive KWS HAL and KWS_INPUT_CONFIG at 0x23c, and RX route 1. The I2S wrapper also exports its existing synchronized RX flush-busy state to APU over the specified same-PCLK internal wire. Existing offsets/reserved masks, 128-byte descriptor, APUMC V1/V2, 4096-word control store, bank count, Gateway/IRQ/resource/pad/clock/CDC allocations are unchanged. CAPABILITY1=0x01827020, IP_VERSION=0x00010001 and ABI_DIGEST=0 remain required. Only after every P7 gate passes does the release capability change from P5 0x000001bd to 0x000001fd; MP3 bit1 remains zero. No generic NPU interface, CPU MFCC, host inference or shared-codec-lane fallback.

Implementation order within this single phase:

  1. Add exact dependency inputs, offline verification and the fixed corpus manifest import; implement converter contract 1.0.0 and independent BAM.
  2. Add handwritten RTL/C/Python APUM/register parity, wire fixtures and deterministic HAL packing tests before enabling public commands.
  3. Implement bounded model DMA/CRC/validation/atomic lock and failure tests.
  4. Add the independent banks10..25 client, capture/FIR/MFCC/16-lane inference, fixed graph, scheduler, snapshot/status/counters and lifecycle integration.
  5. Activate RX route1 and direct/ring operation1 with HAL, firmware and fault/ownership tests; retain all reviewed P5 and MP3-stub behavior.
  6. Produce the complete P7 differential, 1000-window accuracy, concurrency and lifecycle reports, then promote only the KWS capability bit.

Validation after implementation (these commands are not evidence of results from this documentation-only refreeze):

python3 scripts/dependency_lock.py --lock dependencies/dependencies.lock.json
ruff check .
make sw-format-check sw-policy-check sw-host-test
python3 -m pytest -q
make CONFIG=configs/ci/ihp130.mk formal
make CONFIG=configs/ci/ihp130.mk APP=ci_smoke SIMU=VERILATOR firmware sim
git diff --check

P7 must additionally register and run directed KWS model/frontend/inference, HAL and full qualification tests under Pytest and the affected formal/firmware flow; a green generic smoke is not a substitute for the seven named reports. Extend scripts/setup_apu_reference.py with --target p7 and --doctor, preserving its current --build-dir and P5 default behavior. The future converter accepts --target p7 --model <verified-tflite> --output <apum> and --manifest <json>; all paths resolve inside the active build directory except read-only managed model input. These options are implementation deliverables, not commands assumed to exist before P7.

Completion: every byte/schema/loader/HAL/lifecycle gate above passes, every layer is bit-exact, all 1000 windows execute through hardware with top-1

=900/1000, and concurrent WAV/FLAC plus KWS meets the stated zero-xrun gate. The source manifest and generation hashes must be reported, not inferred from a successful simulator exit. Synthesis, netlist, OpenSTA, full LP/HP contention and commercial physical closure remain P8; P6 remains deferred.

Phase 8 - LP/HP Software, Contention, and Physical Evidence

ID: APU-P8.

Scope: complete freestanding HAL, LP-only startup load, HP ownership/jobs, cache maintenance, handoff, USB2/SDIO0 contention, full regression, synthesis recipes, netlist, OpenSTA, warnings/metrics, and commercial-gap report. Linux ASoC is deferred because this phase does not freeze a Linux DT binding, kernel driver ABI, or ALSA ownership protocol.

Dependencies: Phases1..5 and Phase7. Phase6 remains DEFERRED and is not a release prerequisite. Post-P9 physical/release closure additionally requires Phase9; previously completed P8 software work need not be repeated except for the new asset-loading/discovery integration and affected regression.

Public changes: completes frozen HAL and bare-metal LP/HP surfaces; Linux ASoC is not part of this phase. It introduces no further public changes beyond the separately approved P9 V1.2 extension; descriptor, APUM/APUMC, address-map, system IRQ/resource/clock allocations remain fixed.

Validation:

make sw-format-check sw-policy-check sw-host-test
python3 -m pytest -q
make regress-pr
make regress-nightly

Completion: every active WAV/FLAC/KWS MVP item passes; IHP130 block/full-SoC evidence is reviewed; unrun commercial gates remain explicit; no unsupported claim ships. MP3 remains unadvertised and its absence does not block this release. Pre-P9 capability remains 0x000001fd; the post-P9 release uses 0x000003fd. P8's digest covers the actual released contract, including the P9 coefficient extension when present and the reserved MP3 IDs/stub, and excludes inactive P6 proposals. Reusing pre-P9 physical results or digest as proof of the new macro-backed release is not permitted.

Phase 9 - Macro-backed Coefficients and Loader Memoization

ID: APU-P9.

Scope: replace the large synthesized KWS coefficient/profile tables and microcode memo arrays with the exact dedicated physical-bank layout, add bounded synchronous access and LP APUC initialization, and qualify inferred- memory, synthesis resource, numerical and real-time behavior. This is not a new model, reduced workspace, approximate frontend or MP3 phase.

Dependencies: the inspected P5/P7 implementation and its existing banked KWS client/P8 ownership integration, the frozen generators/BAM/model/corpus, the current Common/technology wrappers and IHP130 macro views. Existing functional evidence must be rechecked at preflight; missing evidence is not assumed PASS. Full P8 physical signoff is an output after this phase, not its prerequisite.

Public changes: APB V1.2, CAPABILITY0 bit9, registers 0x240..0x260, local IRQ11, APUC1 container and two additive HAL APIs as specified above. Existing field meanings/offsets, APUM1 bytes, APUMC V1/V2, 128-byte descriptors, advertised capacities and system topology/clock/reset allocations are retained. An extra LP coefficient load is intentionally required for KWS after hard reset.

Implementation order within this phase:

  1. Capture baseline A inventory/flow status and deterministic table/proof fixtures; generate the exact APUC image and independent layout oracle.
  2. Migrate memo keys/bitmap to 17 macros, reusing Common register/control primitives and preserving exact proof, clear/insert and abort semantics.
  3. Add 15 coefficient SRAMs, tagged synchronous ports and exclusive loader/ readback/lock, then the handwritten APB/C/Python constants and HAL.
  4. Replace all production function lookups, including APUM fixed-word checks, with SRAM transactions. Retain bit-exact arithmetic and add only bounded state/latency needed by the macro interface or exact iterative operations.
  5. Update LP/HP startup and evidence fixtures to load APUC, extend lifecycle/ formal/host tests, update ABI-digest and macro-accounting tooling, and run the full existing numerical/concurrent corpus gates.
  6. Capture candidate B using the unchanged comparison flow, verify the inferred-bit reduction and actual runtime/RSS change, then refresh P8 macro/netlist/STA/area evidence. No acceptance status is inferred from the design estimates or from a timeout.

Profile: configs/ci/ihp130.mk, locked tools, HAVE_SRAM_MACRO=YES, 48 MHz PCLK performance target. Required existing entry points after implementation:

python3 scripts/dependency_lock.py --lock dependencies/dependencies.lock.json
ruff check .
make sw-format-check sw-policy-check sw-host-test
python3 -m pytest -q
python3 scripts/apu_abi_digest.py --check
make CONFIG=configs/ci/ihp130.mk formal
make CONFIG=configs/ci/ihp130.mk APP=ci_smoke SIMU=VERILATOR firmware sim
make CONFIG=configs/ci/ihp130.mk APU_BLOCK_ENABLE_P7=1 apu-block-synth apu-block-sta
make CONFIG=configs/ci/ihp130.mk apu-block-evidence
make CONFIG=configs/ci/ihp130.mk SYNTH=YOSYS synth
make CONFIG=configs/ci/ihp130.mk STA=OPENSTA sta
make regress-pr
make regress-nightly
git diff --check

The generic entry points do not replace the full 1000-window/60-second P7 qualification or the six P9 reports; register those tests and their exact commands during implementation. Run A and B in separate revision-qualified variants, not successive overwrites of the same outputs. New coefficient- asset targets and extended report fields are deliverables, not tools assumed already present in the source baseline.

Completion: every P9 requirement passes, all affected P5/P7 semantic results remain equivalent, the added software-visible init flow is qualified, target inferred memories are absent in macro synthesis, and the reported physical inventory is 76 wrappers / 304 KiB with no hidden large register-file copy. Timing/area/RSS/runtime evidence must describe the actual post-P9 hierarchy. If functional or real-time gates fail, do not compensate by weakening accuracy, using CPU inference, shrinking the memo or increasing the 100 ms period. P6, Linux ASoC and commercial post-layout/silicon qualification remain explicitly deferred/outside this phase.

Commercial Delivery Gaps

The following remain release blockers after MVP unless separately closed:

These gaps apply to capabilities claimed by the delivered release. MP3/MPEG decoder qualification is deferred with P6 and is not a blocker for the current WAV/FLAC/KWS release.

  • full requirements-to-test traceability and functional/code coverage closure;
  • reusable APB4/AXI4/AXI4-Stream/I2S/microcode/descriptor/fault VIP;
  • independent long-run WAV/FLAC interoperability, fuzzing, vulnerability intake, and codec maintenance process; licensed MPEG conformance applies only if MP3 is explicitly reactivated in a future release;
  • KWS false-positive/false-negative qualification across speakers, accents, noise, microphones, rooms, and target languages;
  • authenticated/anti-rollback microcode/model update, confidential storage, secure debug, and protected-content architecture;
  • CDC/RDC and reset/clock-gating signoff with unilateral-reset fault injection;
  • qualified SRAM for every PDK, ECC decision, MBIST/repair, scan/ATPG, and DFT;
  • PVT/MMMC, CTS, extracted STA, SI, IR/EM, power, thermal, package, and board;
  • gate/SDF, FPGA prototype, silicon characterization, audio quality, sustained contention, and production soak;
  • upstream-quality Linux ASoC, recovery/update policy, release notes, SBOM, notices, integration examples, and versioned artifacts; and
  • qualification of deferred codec, channel, low-power, coherency, safety or security capabilities when they are later included in an advertised release.