code wiki / _hdl_build / nx_drvgen.nx

nx_drvgen.nx

buildroot/runtime/_hdl_build/nx_drvgen.nx

20331 B349 linesdepth 3pulls 4 transitivereach 0 importersview sourcekind tool
docsdependenciesstructsconstsfunctions

about

SUPERSEDED 2026-06-13 (no-sprawl consolidation): the CANONICAL driver-from-spec emitter is the op-list-driven nx_drv_proto_emit.nx -- there a NEW device class is a NEW op-list SPEC with ZERO emitter change (the protocol step-sequence is DATA). nx_drvgen hardcodes the NVMe stage ORDERING in code (a per-class emitter), which the X-DRV-W1 council flagged as a generality dilution. NVMe is now carried as an op-list spec: knowledge/specs/nvme_oplist_virt.spec, gate-proven by _nvme_oplist_gate (knowledge/status/driver_spec.log::NVMEOPGATE verdict=GREEN). nx_drvgen + nx_driver_shapes are KEPT as the regression reference (NVMEGATE stage=B), not extended. New work -> add an op-list spec to nx_drv_proto_emit, NOT a new bespoke emitter. nx_drvgen.nx -- the GENERIC driver-image author for the 2nd device class (X-DRV-W1 stage B). A NEW device class IS A SPEC FILE: nx_drvgen reads an NVMe-class controller spec (knowledge/specs/nvme_admin_enable_virt.spec) and AUTHORS a bare-metal rv64 flat image whose driver performs the REAL NVMe controller bring-up by routing EVERY byte through the SAME device-agnostic shape library (nx_driver_shapes: WIRE_TLV / COMMAND_QUEUE / STATE_MACHINE / STRUCT_WALK) that re-emits the virtio image byte-identically in PROOF-1. The shape library knows ZERO NVMe -- the controller identity, offsets, queue bases, SQE/CQE layout, and the phase-tag KAT all arrive from the spec. So the NVMe driver's distinctness comes from spec DATA, not from any virtio code path. The driver the image runs (NVMe 1.4 base spec bring-up subset): verify VS == 0x00010400 (1.4.0) -> emit "VIO-NVME " write CC.EN=1, POLL CSTS until RDY set (STATE_MACHINE poll loop) -> emit "EN " <-- a REAL backward branch (the structural fingerprint virtio's straight-line handshake lacks) bind AQA + ASQ/ACQ base-address regs, read ASQ_LO back + verify -> emit "RDY " lay the 64-byte SQE (opcode/CID/CDW10) into ASQ_base (STRUCT_WALK) -> emit "ASQ " ring the SQ-Tail doorbell (the device posts the phase-tagged CQE) -> emit "SQE " POLL the CQE phase bit in ACQ RAM, read NvmeCqPeek back + verify -> emit "CQ\n" <-- a SECOND backward branch (the CQE phase-tag poll); the verify is the tamper canary write the SiFive finisher -> clean halt. Any verify that fails BRANCHES PAST the rest of the bring-up straight to the finisher, so the transcript loses its tail (the " CQ" canary, etc.) -- the gate's tamper test exploits this. nx_drvgen <specpath> -> writes the flat image to the spec's `out` + the golden to <out>.gold VERDICT log -> knowledge/status/virtio_blk.log (DRVGEN rows). Sovereign: syscalls only, no gcc/.sh. NVMe/PCI is a last-mile interop PROBE + measuring stick to EXCEED, never a substrate -- the emitted driver + shapes are Nishi-native. license_tier: ORIGINAL

dependencies 3 imports · 0 importers

nx_syscalls.nx nx_itoa_lib.nx nx_driver_shapes.nx nx_drvgen.nx

imports: nx_syscalls.nxnx_itoa_lib.nxnx_driver_shapes.nx

imported by: nobody (leaf or entry point)

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main nv_p sys_write sys_exit sys_mmap sys_read_file sys_openat_rd sys_lseek sys_mmap ↻ sys_read sys_close nv_log sys_openat_append nv_fp sys_write ↻ nv_fn nxi_fd sys_mmap ↻ ccz_cat_num sys_write ↻ sys_munmap sys_close ↻ nv_num_field sys_mmap ↻ nv_parse_num nv_str_field nv_fn ↻ nv_emit_image ds_w32 ds_lui ds_emit_verify ds_w32 ↻ ds_load ds_li32 ds_w32 ↻ ds_lui ↻ ds_addi ds_branch ds_emit_str ds_w32 ↻

structs

none

consts

36const NV_MAGIC_8192: i64 = 8192
39const NV_X0: i64 = 0
40const NV_T2: i64 = 7 // device base
41const NV_T3: i64 = 28 // loaded register value (actual)
42const NV_T5: i64 = 30 // struct-base scratch (ASQ / ACQ guest addr)
45const NC_BASE: i64 = 0
46const NC_OFF_CAP: i64 = 1
47const NC_OFF_VS: i64 = 2
48const NC_OFF_CC: i64 = 3
49const NC_OFF_CSTS: i64 = 4
50const NC_OFF_AQA: i64 = 5
51const NC_OFF_ASQ_LO: i64 = 6
52const NC_OFF_ASQ_HI: i64 = 7
53const NC_OFF_ACQ_LO: i64 = 8
54const NC_OFF_ACQ_HI: i64 = 9
55const NC_OFF_SQ0TDBL: i64 = 10
56const NC_OFF_CQ0HDBL: i64 = 11
57const NC_OFF_CQPEEK: i64 = 12
58const NC_VS_EXPECTED: i64 = 13
59const NC_CC_EN: i64 = 14
60const NC_CSTS_RDY_MASK: i64 = 15
61const NC_ASQ_ADDR: i64 = 16
62const NC_ACQ_ADDR: i64 = 17
63const NC_AQA_VAL: i64 = 18
64const NC_SQE_OPCODE: i64 = 19
65const NC_SQE_CID: i64 = 20
66const NC_SQE_OFF_OPCODE:i64 = 21
67const NC_SQE_OFF_CID: i64 = 22
68const NC_SQE_OFF_CDW10: i64 = 23
69const NC_SQE_CDW10: i64 = 24
70const NC_CQE_OFF_CID: i64 = 25
71const NC_CQE_OFF_STATUS:i64 = 26
72const NC_CQE_PHASE_BIT: i64 = 27
73const NC_CQE_CID_EXP: i64 = 28
74const NC_CQE_STATUS_EXP:i64 = 29
75const NC_CQPEEK_EXP: i64 = 30
76const NC_N: i64 = 31

functions

78func nv_p(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
called by 1: main calls 1: sys_write
79func nv_fp(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 }
called by 1: nv_log calls 1: sys_write
84func nv_fn(fd: i64, v: i64) -> i64 { nxi_fd(fd, v); return 0 }
called by 2: nv_logmain calls 1: nxi_fd
85func nv_hex(fd: i64, v: i64) -> i64 { let d: *u8=sys_mmap(16); var i: i64=0; while i<8{let nib: i64=(v >> ((7-i)*4)) & 0xf; if nib<10{d[i]=(48+nib) as u8} else {d[i]=(87+nib) as u8} i=i+1}; sys_write(fd,d,8); return 0 }
called by 1: main calls 2: sys_mmapsys_write
92func nv_emit_image(buf: *u8, cfg: *i64, tail: *u8, segs: *i64, fail_off: i64) -> i64
141func nv_parse_num(buf: *u8, p: i64, le: i64, endp: *i64) -> i64
called by 1: nv_num_field
171func nv_num_field(buf: *u8, ls: i64, le: i64, key: *u8, out: *i64) -> i64
called by 1: main calls 2: sys_mmapnv_parse_num
183func nv_str_field(buf: *u8, ls: i64, le: i64, key: *u8, out: *u8) -> i64
called by 1: main
197func nv_log(name: *u8, bytes: i64, golden: *u8, verdict: *u8) -> i64
208func main(argc: i64, argv: *i64) -> i64