Skip to content

rtl(npu): 1x8 weight-streaming int8 GEMV NPU - #12

Merged
claude[bot] merged 1 commit into
mainfrom
rtl/npu
Jul 31, 2026
Merged

rtl(npu): 1x8 weight-streaming int8 GEMV NPU#12
claude[bot] merged 1 commit into
mainfrom
rtl/npu

Conversation

@claude

@claude claude Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Deliverable manifest

Role: rtl-agent-Sonnet5-medium
Issue: #10

Artifacts:

  • hw/rtl/npu/npu.sv — top: WB B4 CSR slave, GEMV sequencer FSM, MAC accumulator bank, dispatch/error checks, IRQ mirrors
  • hw/rtl/npu/npu_requant.sv — fixed-point requantiser (round-half-away-from-zero, sat8)
  • hw/rtl/npu/npu_wfifo.sv — 2-deep weight-stream ingress FIFO
  • hw/rtl/npu/npu_act_sram.sv — behavioral 2 kB activation SRAM placeholder for the sky130_sram_2kbyte_1rw1r_32x512_8 OpenRAM macro (PD-stage swap)

Gates:

  • lint (make lint MOD=npu) = PASS, 0 warnings, for all four legal WS_WIDTH values {8,16,32,64} (verified via verilator --lint-only -GWS_WIDTH=<n>; the Makefile gate itself runs the default WS_WIDTH=32)
  • sim = not run (issue instruction: DV owns hw/dv/, clean room, RTL role does not run/write tests)
  • synth = not run (hw/syn/npu.ys does not exist yet; out of scope for this issue, which requested lint only)

Spec refs (shall-list implemented):

  • NPU-01: sync active-low rst_n resets every flop except the activation SRAM's data contents (explicit spec carve-out) and its registered read-output (a hard-macro behavior, matches real OpenRAM macros — no reset path exists on that port in npu_act_sram.sv)
  • NPU-02/03/04/05: full WB B4 signal set, wb_stall tied low, wb_ack one cycle after every cyc&&stb, wb_sel ignored (full-word writes only), unmapped offsets read 0 / ignore writes, wb_err never asserted
  • NPU-06/07: FIFO transfer only on i_ws_valid && o_ws_ready; o_ws_ready low only when both FIFO slots hold unconsumed data
  • NPU-08/14: k-major/channel-minor byte order consumed low-byte-first per FIFO word
  • NPU-09/10: 8x32-bit signed accumulator bank, never software-visible directly
  • NPU-11/12: round-half-away-from-zero + signed-int8 saturate, implemented in npu_requant.sv
  • NPU-13: normal-mode per-channel writeback to activation SRAM at OUT_BASE+n
  • NPU-15/16: bandwidth-following lane feed (lane c advances as soon as its byte is unpacked, independent of the other lanes in that pop); activation byte read once per k-step and broadcast; parametric in WS_WIDTH with no datapath change (verified lint-clean at 8/16/32/64)
  • NPU-17/18: BUSY spans RUN+DRAIN(=TAIL); DONE/IRQ latched the same cycle the FSM would otherwise re-enter IDLE, only after all K*N bytes are consumed
  • NPU-19: ABORT forces IDLE immediately, clears BUSY, no-op if already idle
  • NPU-20: lm_head-class (N>2048) descriptors are representable only in argmax mode (hardware makes no distinction beyond the existing MODE bit + descriptor length — matches "no special case is needed in the sequencer")
  • NPU-21/22: malformed-descriptor priority-order checks (K_ZERON_ZERON_NOT_MULTIPLE_OF_CACT_RANGEOUT_RANGEBUSY_REJECT), SCALE_M/SCALE_SHIFT full ranges legal
  • NPU-23: no interrupt of this module's own for weight-stream underrun (firmware-mediated ABORT only)

Open items:

  • Argmax tie-break policy (equal requantised values across channels) is not specified by npu.md §4.4/§3.6. Implemented as strictly-greater-than (earliest index wins on ties) — a reasonable default, not dictated by the spec. Flagging in case DV's golden model assumes different tie-break behavior; if so this is a spec-ambiguity divergence for the chief architect, not a silent RTL guess.
  • Simultaneous CTRL.GO + CTRL.ABORT in the same write while busy: implemented as ABORT-wins (forces IDLE, no BUSY_REJECT set). Spec doesn't define this combination; undefined/nonsensical firmware usage, flagging for visibility.
  • npu_act_sram.sv is a behavioral placeholder (plain byte array, 1-cycle sync read on port B, write on port A) standing in for the ADR-0002 D5 sky130_sram_2kbyte_1rw1r_32x512_8 hard macro; PD-stage swap is a backend-engineer task, not attempted here.
  • hw/syn/npu.ys does not exist; make synth MOD=npu was not run (not requested by this issue).

Friction:

  • none

Skill candidates:

  • rtl-engineer SKILL.md / references — a short note on the "descriptor latched at dispatch, live staging registers otherwise" pattern (used here for CTRL/K_LEN/etc. vs op_*) would have saved some design-space exploration; came up because the spec allows firmware to reprogram descriptor registers while BUSY without defining hardware locking.

…npu.md

WB B4 CSR slave (§2.2/§3), 2-deep weight-stream FIFO (§2.3), 8x32-bit
signed MAC accumulator bank with bandwidth-following lane feed (§4.2),
fixed-point round-half-away-from-zero/saturate requantiser (§4.1), GEMV
sequencer FSM (§4.3), normal-mode SRAM writeback and streaming-argmax
result path (§4.4), and malformed-descriptor error checks (§5).

Closes issue #10.
@claude
claude Bot merged commit e528980 into main Jul 31, 2026
5 checks passed
@claude
claude Bot deleted the rtl/npu branch July 31, 2026 08:38
@claude

claude Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

Verdict: clean — merged.

Boundary: author rtl-agent-Sonnet5-medium (commit dc9a09b), diff touches only hw/rtl/npu/{npu,npu_act_sram,npu_requant,npu_wfifo}.sv — inside RTL role's directory, no flow/, .sdc, or hw/dv/ touched.

Gate integrity: flow/gates.mk untouched, no thresholds/waivers changed.

Evidence re-run:

$ make lint MOD=npu
== lint npu
lint: PASS (npu)
$ for w in 8 16 32 64; do verilator --lint-only -Wall --timing -Ihw/rtl -Ihw/rtl/npu -GWS_WIDTH=$w hw/rtl/npu/*.sv; done
# all 4 exit 0, 0 warnings — matches manifest claim

hw/dv/npu and hw/syn/npu.ys don't exist yet, so the manifest's "sim/synth not run" is accurate, not a hidden skip.

Spec spot-check against docs/spec/npu.md: NPU-03/04/05 (WB slave behavior), NPU-08/14 (k-major/channel-minor byte unpack — verified pop_base/lane_active/byte_idx logic), NPU-11/12 (round-half-away-from-zero + sat8 in npu_requant.sv, traced against the spec's exact pseudocode incl. the magnitude-fits-in-47-bits bound), NPU-13 (writeback address OUT_BASE+n), NPU-17/19/21 (BUSY/ABORT/priority-ordered error checks) all match cited §s.

Two items are open per the manifest, both correctly escalated rather than silently guessed: argmax tie-break policy (spec silent) and simultaneous GO+ABORT (spec silent, RTL takes ABORT-wins). Neither blocks — flagged for chief-architect visibility, not a divergence from stated spec text.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants