code wiki / _hdl_build / rv64im_min_nndev.nx
rv64im_min_nndev.nx
buildroot/runtime/_hdl_build/rv64im_min_nndev.nx
about
rv64im_min_nndev.nx -- the NISHI-NATIVE DEVICE PROTOCOL (NNDP) device model.
The genuine "exceed virtio" target (nishi-ecosystem-only law: virtio is the last-mile/benchmark
transport, NOT the substrate -- the NATIVE protocol that EXCEEDS it is the real goal, the census
`sovereign-device-protocol` ABSENT exceed-row). NNDP is a SOVEREIGN, deliberately LEAN block
device protocol designed to complete one I/O in FAR fewer MMIO accesses + memory ops than legacy
virtio-MMIO -- measured head-to-head on the SAME sovereign rv64 emu (apples-to-apples).
Why it is leaner than virtio-MMIO (the measurable exceed):
- SELF-DESCRIBING IDENTITY: MAGIC + DEVCLASS (2 reads), no Version/VendorID/HostFeatures/
GuestFeatures negotiation.
- SINGLE-STEP BRING-UP: one ENABLE write, NOT the 4-stage ACK->DRIVER->FEATURES_OK->DRIVER_OK
Status handshake (+ the FEATURES_OK re-read).
- NO SPLIT VIRTQUEUE: one INLINE command descriptor at CMD_ADDR (data_addr/len/op), NOT a
descriptor table + avail ring + used ring with index bookkeeping and TWO notify kicks.
- SINGLE DOORBELL, DIRECT COMPLETION: one DOORBELL write -> the device DMA-processes the command
and latches STATUS + RESULT inline; the driver reads them back directly (no used-ring walk,
no used.idx/avail.idx, no separate status descriptor).
Register window @ NX_NNDEV_BASE (256 bytes), an INDEPENDENT instance (virtio/nvme untouched):
0x00 MAGIC (RO) 0x4E4E4431 ("NND1", little-endian) -- identity, self-describing
0x04 DEVCLASS (RO) 1 = block
0x08 ENABLE (RW) driver writes 1 to bring the device up (single-step); read-back = latched
0x0C CMD_ADDR (RW) guest-physical address of the inline command descriptor; read-back = latched
0x10 DOORBELL (WO) write 1 -> device runs the command at CMD_ADDR (DMA) and completes inline
0x14 STATUS (RO) completion status latched on the last doorbell (0 = OK)
0x18 RESULT (RO) first 32-bit word the device DMA-read from the command's data buffer (the
data round-trip binding proof; the driver reads it back == its written word)
Inline command descriptor (at CMD_ADDR in guest RAM):
+0 data_addr (4, low 32 of the data-buffer guest-physical address)
+4 data_len (4)
+8 op (4; 0 = read/round-trip)
Status: SEED 2026-06-13 (X-DRV sovereign-device-protocol). Block read round-trip + identity +
single-step enable + single-doorbell completion. license_tier: ORIGINAL
dependencies 2 imports · 1 importers
imports: nx_syscalls.nxnishi_hdl_primitives.nx
imported by: rv64im_min_sim.nx
structs
| 73 | struct NxNnDev |
consts
| 41 | const NX_NNDEV_BASE: i64 = 0x10005000 // just past the NVMe window (0x10003000..0x10005000); no overlap |
| 42 | const NX_NNDEV_END: i64 = 0x10005100 |
| 45 | const NX_NNDEV_OFF_MAGIC: i64 = 0x00 |
| 46 | const NX_NNDEV_OFF_DEVCLASS: i64 = 0x04 |
| 47 | const NX_NNDEV_OFF_ENABLE: i64 = 0x08 |
| 48 | const NX_NNDEV_OFF_CMDADDR: i64 = 0x0C |
| 49 | const NX_NNDEV_OFF_DOORBELL: i64 = 0x10 |
| 50 | const NX_NNDEV_OFF_STATUS: i64 = 0x14 |
| 51 | const NX_NNDEV_OFF_RESULT: i64 = 0x18 |
| 54 | const NX_NNDEV_MAGIC: i64 = 0x4E4E4431 // "NND1" |
| 55 | const NX_NNDEV_DEVCLASS: i64 = 1 // block |
| 58 | const NX_NNDEV_CMD_OFF_DATAADDR: i64 = 0 |
| 59 | const NX_NNDEV_CMD_OFF_DATALEN: i64 = 4 |
| 60 | const NX_NNDEV_CMD_OFF_OP: i64 = 8 |
| 63 | const NX_NNDEV_SLOT_ENABLE: i64 = 0 |
| 64 | const NX_NNDEV_SLOT_CMDADDR: i64 = 1 |
| 65 | const NX_NNDEV_SLOT_STATUS: i64 = 2 |
| 66 | const NX_NNDEV_SLOT_RESULT: i64 = 3 |
| 67 | const NX_NNDEV_SLOT_N: i64 = 4 |
| 70 | const NX_NNDEV_OK: i64 = 0 |
| 71 | const NX_NNDEV_ADDR_OUT_OF_RANGE: i64 = 1 |
functions
| 80 | func nx_nndev_reset(storage: *i64) -> i64 |
| 88 | func nx_nndev_init(d: *NxNnDev, storage: *i64) -> i64 |
| 99 | func nx_nndev_addr_in_range(d: *NxNnDev, addr: i64) -> i64 |
| 106 | func nx_nndev_read32(d: *NxNnDev, addr: i64, value_out: *i64) -> i64 |
| 124 | func nx_nndev_write32(d: *NxNnDev, addr: i64, value: i64) -> i64 |
| 147 | func nx_nndev_rd32(mem_buf: *u8, off: i64) -> i64 called by 1: nx_nndev_doorbell_dma |
| 154 | func nx_nndev_inrange(off: i64, w: i64, mem_size: i64) -> i64 called by 1: nx_nndev_doorbell_dma |
| 166 | func nx_nndev_doorbell_dma(d: *NxNnDev, mem_buf: *u8, mem_base: i64, mem_size: i64) -> i64 |