Files
rosenblatt/userspace/npu-probe/rkt_matmul_cna.c
T
claude-noether 60e7709d7b Rosenblatt Phase-2: userspace regcmd builder — U3 wrapper + CNA stage (4a)
- librocket.{c,h}: thin ioctl wrapper over the rocket accel uAPI (open + CREATE_BO/
  SUBMIT/PREP_BO/FINI_BO + mmap). Compiles with -I/usr/include/drm.
- rkt_matmul_cna.{c,h} + cna_defs.h: CNA-stage regcmd emit for an INT8 matmul-as-
  1x1-conv, faithful port of Mesa rocket fill_first_regcmd's CNA section. Compiles
  clean (-Wall -Wextra), 85 emits. Cross-validated: two independent ports (dspark
  Montessori-scaffolded + big-pickle autonomous) agree at the emit level.
- rkt_matmul_coredpu.{c,h} + coredpu_defs.h: CORE+DPU+PC scaffold (empty body,
  @@INSERT@@ marker). Params struct incl. float scales + 3 DMA-addr fields.
  Body port is WIP: 82 DPU emits + float requant + PC tail remain (needs slicing).
- *_reference.txt: curated Mesa rocket emit excerpts + register defines (implementer
  reference bundles).

Implementer: dspark (DeepSeek-V4-Flash NVFP4, local) via Montessori scaffolding;
autonomous CNA also produced by opencode/big-pickle. Multi-model benchmark in
claude-memory reference_dspark_implementer. NOT golden-verified (faithful-to-Mesa;
needs a Mesa build or NPU hardware to byte-check).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EWpfhDgYNA21tETDP9ueBE
2026-07-13 19:23:34 +00:00

238 lines
9.1 KiB
C

#include "rkt_matmul_cna.h"
#include "cna_defs.h"
#include <stdint.h>
/*
* Packed register command: (target << 48) | (value << 16) | reg
* target = block_enum + 1. CNA block = 0x200 -> target 0x201; DPU = 0x1000 -> 0x1001.
*/
static int rkt_push(uint64_t *out, int *n, int cap, uint32_t target,
uint32_t reg, uint32_t value)
{
if (*n >= cap)
return -1;
out[*n] = ((uint64_t)target << 48) | ((uint64_t)value << 16) | (uint64_t)reg;
(*n)++;
return 0;
}
#define EMIT_CNA(reg, val) do { if (rkt_push(out, &n, cap, 0x201, (reg), (val)) < 0) return -1; } while (0)
#define EMIT_DPU(reg, val) do { if (rkt_push(out, &n, cap, 0x1001, (reg), (val)) < 0) return -1; } while (0)
/* Field-set: (value << FIELD__SHIFT) & FIELD__MASK */
#define F(v, name) (((uint32_t)(v) << name##__SHIFT) & name##__MASK)
int rkt_emit_cna(uint64_t *out, int cap, const struct cna_params *p)
{
int n = 0;
/* ==== CNA emit sequence (Montessori, chunk by chunk) ==== */
uint32_t con0 = F(p->weights_banks, CNA_CBUF_CON0_WEIGHT_BANK) |
F(p->input_banks, CNA_CBUF_CON0_DATA_BANK);
if (p->task_num > 0 && p->reuse_weights_cbuf)
con0 |= F(1, CNA_CBUF_CON0_WEIGHT_REUSE);
EMIT_CNA(REG_CNA_CBUF_CON0, con0);
EMIT_CNA(REG_CNA_DCOMP_REGNUM, 0);
EMIT_CNA(REG_CNA_DCOMP_CTRL, 0);
uint32_t con1 = 0x0;
if (p->input_channels_real == 1) {
con1 |= F(1, CNA_CONV_CON1_NONALIGN_DMA) | F(1, CNA_CONV_CON1_GROUP_LINE_OFF) |
F(8, CNA_CONV_CON1_ARGB_IN);
}
if (p->depthwise)
con1 |= F(3, CNA_CONV_CON1_CONV_MODE);
EMIT_CNA(REG_CNA_CONV_CON1, con1);
EMIT_DPU(REG_DPU_S_POINTER, F(1, DPU_S_POINTER_POINTER_PP_MODE) |
F(1, DPU_S_POINTER_EXECUTER_PP_EN) |
F(1, DPU_S_POINTER_POINTER_PP_EN));
EMIT_DPU(REG_DPU_RDMA_RDMA_S_POINTER,
F(1, DPU_RDMA_RDMA_S_POINTER_POINTER_PP_MODE) |
F(1, DPU_RDMA_RDMA_S_POINTER_EXECUTER_PP_EN) |
F(1, DPU_RDMA_RDMA_S_POINTER_POINTER_PP_EN));
EMIT_CNA(REG_CNA_CONV_CON1, con1);
EMIT_CNA(REG_CNA_CONV_CON2,
F(50 + p->stride_y + 1, CNA_CONV_CON2_FEATURE_GRAINS)); /* Magic: Seems to pass the most tests */
EMIT_CNA(REG_CNA_CONV_CON3, F(p->stride_x, CNA_CONV_CON3_CONV_X_STRIDE) |
F(p->stride_y, CNA_CONV_CON3_CONV_Y_STRIDE));
EMIT_CNA(REG_CNA_DATA_SIZE0,
F(p->input_width, CNA_DATA_SIZE0_DATAIN_WIDTH) |
F(p->input_height, CNA_DATA_SIZE0_DATAIN_HEIGHT));
EMIT_CNA(REG_CNA_DATA_SIZE1,
F(p->input_channels_real - 1, CNA_DATA_SIZE1_DATAIN_CHANNEL_REAL) |
F(p->input_channels, CNA_DATA_SIZE1_DATAIN_CHANNEL));
EMIT_CNA(REG_CNA_DATA_SIZE2, F(p->output_width, CNA_DATA_SIZE2_DATAOUT_WIDTH));
EMIT_CNA(REG_CNA_DATA_SIZE3, F(p->atomic_count, CNA_DATA_SIZE3_DATAOUT_ATOMICS));
EMIT_CNA(REG_CNA_WEIGHT_SIZE0, p->weights_width * p->weights_height *
p->input_channels * p->weights_kernels);
EMIT_CNA(REG_CNA_WEIGHT_SIZE1,
p->weights_width * p->weights_height * p->input_channels);
EMIT_CNA(REG_CNA_WEIGHT_SIZE2,
F(p->weights_width, CNA_WEIGHT_SIZE2_WEIGHT_WIDTH) |
F(p->weights_height, CNA_WEIGHT_SIZE2_WEIGHT_HEIGHT) |
F(p->weights_kernels, CNA_WEIGHT_SIZE2_WEIGHT_KERNELS));
EMIT_CNA(REG_CNA_CBUF_CON0, con0);
EMIT_CNA(REG_CNA_CBUF_CON1, F(p->input_data_entries, CNA_CBUF_CON1_DATA_ENTRIES));
if (p->input_channels_real == 1) {
unsigned truncate = 14;
unsigned scale = 16384;
unsigned offset = 65408;
if (p->addition_input || p->add_tensor != -1) {
truncate = 15;
scale = 32388;
}
EMIT_CNA(REG_CNA_CVT_CON0, F(truncate, CNA_CVT_CON0_CVT_TRUNCATE_3) |
F(truncate, CNA_CVT_CON0_CVT_TRUNCATE_2) |
F(truncate, CNA_CVT_CON0_CVT_TRUNCATE_1) |
F(truncate, CNA_CVT_CON0_CVT_TRUNCATE_0));
EMIT_CNA(REG_CNA_CVT_CON1,
F(scale, CNA_CVT_CON1_CVT_SCALE0) | F(offset, CNA_CVT_CON1_CVT_OFFSET0));
EMIT_CNA(REG_CNA_CVT_CON2,
F(scale, CNA_CVT_CON2_CVT_SCALE1) | F(offset, CNA_CVT_CON2_CVT_OFFSET1));
EMIT_CNA(REG_CNA_CVT_CON3,
F(scale, CNA_CVT_CON3_CVT_SCALE2) | F(offset, CNA_CVT_CON3_CVT_OFFSET2));
EMIT_CNA(REG_CNA_CVT_CON4,
F(scale, CNA_CVT_CON4_CVT_SCALE3) | F(offset, CNA_CVT_CON4_CVT_OFFSET3));
} else {
EMIT_CNA(REG_CNA_CVT_CON0, F(1, CNA_CVT_CON0_DATA_SIGN) |
F(1, CNA_CVT_CON0_CVT_TYPE) |
F(1, CNA_CVT_CON0_CVT_BYPASS));
EMIT_CNA(REG_CNA_CVT_CON1, F(1, CNA_CVT_CON1_CVT_SCALE0));
EMIT_CNA(REG_CNA_CVT_CON2, F(1, CNA_CVT_CON2_CVT_SCALE1));
EMIT_CNA(REG_CNA_CVT_CON3, F(1, CNA_CVT_CON3_CVT_SCALE2));
EMIT_CNA(REG_CNA_CVT_CON4, F(1, CNA_CVT_CON4_CVT_SCALE3));
}
EMIT_CNA(REG_CNA_FC_CON0, 0);
EMIT_CNA(REG_CNA_FC_CON1, 0);
EMIT_CNA(REG_CNA_CONV_CON2,
F(50 + p->stride_y + 1, CNA_CONV_CON2_FEATURE_GRAINS)); /* Magic: Seems to pass the most tests */
EMIT_CNA(REG_CNA_CONV_CON3, F(p->stride_x, CNA_CONV_CON3_CONV_X_STRIDE) |
F(p->stride_y, CNA_CONV_CON3_CONV_Y_STRIDE));
EMIT_CNA(REG_CNA_DATA_SIZE0,
F(p->input_width, CNA_DATA_SIZE0_DATAIN_WIDTH) |
F(p->input_height, CNA_DATA_SIZE0_DATAIN_HEIGHT));
EMIT_CNA(REG_CNA_DATA_SIZE1,
F(p->input_channels_real - 1, CNA_DATA_SIZE1_DATAIN_CHANNEL_REAL) |
F(p->input_channels, CNA_DATA_SIZE1_DATAIN_CHANNEL));
EMIT_CNA(REG_CNA_DATA_SIZE2, F(p->output_width, CNA_DATA_SIZE2_DATAOUT_WIDTH));
EMIT_CNA(REG_CNA_DATA_SIZE3, F(p->atomic_count, CNA_DATA_SIZE3_DATAOUT_ATOMICS));
EMIT_CNA(REG_CNA_WEIGHT_SIZE0, p->weights_width * p->weights_height *
p->input_channels * p->weights_kernels);
EMIT_CNA(REG_CNA_WEIGHT_SIZE1,
p->weights_width * p->weights_height * p->input_channels);
EMIT_CNA(REG_CNA_WEIGHT_SIZE2,
F(p->weights_width, CNA_WEIGHT_SIZE2_WEIGHT_WIDTH) |
F(p->weights_height, CNA_WEIGHT_SIZE2_WEIGHT_HEIGHT) |
F(p->weights_kernels, CNA_WEIGHT_SIZE2_WEIGHT_KERNELS));
EMIT_CNA(REG_CNA_CBUF_CON0, con0);
EMIT_CNA(REG_CNA_CBUF_CON1, F(p->input_data_entries, CNA_CBUF_CON1_DATA_ENTRIES));
if (p->input_channels_real == 1) {
unsigned truncate = 14;
unsigned scale = 16384;
unsigned offset = 65408;
if (p->addition_input || p->add_tensor != -1) {
truncate = 15;
scale = 32388;
}
EMIT_CNA(REG_CNA_CVT_CON0, F(truncate, CNA_CVT_CON0_CVT_TRUNCATE_3) |
F(truncate, CNA_CVT_CON0_CVT_TRUNCATE_2) |
F(truncate, CNA_CVT_CON0_CVT_TRUNCATE_1) |
F(truncate, CNA_CVT_CON0_CVT_TRUNCATE_0));
EMIT_CNA(REG_CNA_CVT_CON1,
F(scale, CNA_CVT_CON1_CVT_SCALE0) | F(offset, CNA_CVT_CON1_CVT_OFFSET0));
EMIT_CNA(REG_CNA_CVT_CON2,
F(scale, CNA_CVT_CON2_CVT_SCALE1) | F(offset, CNA_CVT_CON2_CVT_OFFSET1));
EMIT_CNA(REG_CNA_CVT_CON3,
F(scale, CNA_CVT_CON3_CVT_SCALE2) | F(offset, CNA_CVT_CON3_CVT_OFFSET2));
EMIT_CNA(REG_CNA_CVT_CON4,
F(scale, CNA_CVT_CON4_CVT_SCALE3) | F(offset, CNA_CVT_CON4_CVT_OFFSET3));
} else {
EMIT_CNA(REG_CNA_CVT_CON0, F(1, CNA_CVT_CON0_DATA_SIGN) |
F(1, CNA_CVT_CON0_CVT_TYPE) |
F(1, CNA_CVT_CON0_CVT_BYPASS));
EMIT_CNA(REG_CNA_CVT_CON1, F(1, CNA_CVT_CON1_CVT_SCALE0));
EMIT_CNA(REG_CNA_CVT_CON2, F(1, CNA_CVT_CON2_CVT_SCALE1));
EMIT_CNA(REG_CNA_CVT_CON3, F(1, CNA_CVT_CON3_CVT_SCALE2));
EMIT_CNA(REG_CNA_CVT_CON4, F(1, CNA_CVT_CON4_CVT_SCALE3));
}
EMIT_CNA(REG_CNA_FC_CON0, 0);
EMIT_CNA(REG_CNA_FC_CON1, 0);
EMIT_CNA(REG_CNA_PAD_CON0, F(p->pad_left, CNA_PAD_CON0_PAD_LEFT) |
F(p->pad_top, CNA_PAD_CON0_PAD_TOP));
EMIT_CNA(REG_CNA_FEATURE_DATA_ADDR,
(uint32_t)p->input_dma);
EMIT_CNA(REG_CNA_FC_CON2, 0);
EMIT_CNA(REG_CNA_DMA_CON0,
F(15, CNA_DMA_CON0_WEIGHT_BURST_LEN) | F(15, CNA_DMA_CON0_DATA_BURST_LEN));
EMIT_CNA(REG_CNA_DMA_CON1, F(p->input_line_stride, CNA_DMA_CON1_LINE_STRIDE));
EMIT_CNA(REG_CNA_DMA_CON2, F(p->input_surface_stride, CNA_DMA_CON2_SURF_STRIDE));
EMIT_CNA(REG_CNA_FC_DATA_SIZE0,
F(p->input_width, CNA_FC_DATA_SIZE0_DMA_WIDTH) |
F(p->input_height, CNA_FC_DATA_SIZE0_DMA_HEIGHT));
EMIT_CNA(REG_CNA_FC_DATA_SIZE1,
F(p->input_channels, CNA_FC_DATA_SIZE1_DMA_CHANNEL));
EMIT_CNA(REG_CNA_DCOMP_CTRL, 0);
EMIT_CNA(REG_CNA_DCOMP_REGNUM, 0);
EMIT_CNA(REG_CNA_DCOMP_ADDR0, (uint32_t)p->weights_dma);
EMIT_CNA(REG_CNA_DCOMP_AMOUNT0, 0);
EMIT_CNA(REG_CNA_DCOMP_AMOUNT1, 0);
EMIT_CNA(REG_CNA_DCOMP_AMOUNT2, 0);
EMIT_CNA(REG_CNA_DCOMP_AMOUNT3, 0);
EMIT_CNA(REG_CNA_DCOMP_AMOUNT4, 0);
EMIT_CNA(REG_CNA_DCOMP_AMOUNT5, 0);
EMIT_CNA(REG_CNA_DCOMP_AMOUNT6, 0);
EMIT_CNA(REG_CNA_DCOMP_AMOUNT7, 0);
EMIT_CNA(REG_CNA_DCOMP_AMOUNT8, 0);
EMIT_CNA(REG_CNA_DCOMP_AMOUNT9, 0);
EMIT_CNA(REG_CNA_DCOMP_AMOUNT10, 0);
EMIT_CNA(REG_CNA_DCOMP_AMOUNT11, 0);
EMIT_CNA(REG_CNA_DCOMP_AMOUNT12, 0);
EMIT_CNA(REG_CNA_DCOMP_AMOUNT13, 0);
EMIT_CNA(REG_CNA_DCOMP_AMOUNT14, 0);
EMIT_CNA(REG_CNA_DCOMP_AMOUNT15, 0);
if (p->input_channels_real == 1) {
EMIT_CNA(REG_CNA_CVT_CON5, 65535);
} else {
EMIT_CNA(REG_CNA_CVT_CON5, 0);
}
int32_t pad_con1;
if (p->weights_width >= 3 && p->input_zero_point == 0x0)
pad_con1 = 0xffff8080;
else
pad_con1 = p->input_zero_point - 0x80;
if (p->addition_input || p->add_tensor != -1)
pad_con1 = 0xffffff80;
if (p->depthwise && p->input_zero_point == 0x8b)
pad_con1 = 0x0b0b;
EMIT_CNA(REG_CNA_PAD_CON1, pad_con1);
/* ==== end CNA stage ==== */
return n;
}