code wiki / _hdl_build / nx_rv64_fast_dev_gate.nx
nx_rv64_fast_dev_gate.nx source
↩ module page · 110 lines · 7893 B
1// nx_rv64_fast_dev_gate.nx -- GATE: the DEVICE-AWARE predecoded interpreter drives a REAL virtio device, matching the
2// golden behavioral sim, and stays faster. Eats the debt that nx_rv64_fast's speedup only helped pure compute: now
3// the same virtio identity-read+verify driver runs on BOTH the golden sim (virtio-blk attached) and the device-aware
4// fast interpreter, both discovering DeviceID=2 from live MMIO -- equivalence + device capability -- and the fast
5// engine is still measurably faster on a compute-heavy workload. Teeth: no device attached -> the fast engine reads 0
6// (no false device). expect_exit:0
7import "nx_syscalls.nx"
8import "nishi_hdl_primitives.nx"
9import "rv64im_min_decoder.nx"
10import "rv64im_min_alu.nx"
11import "rv64im_min_regfile.nx"
12import "rv64im_min_csr.nx"
13import "rv64im_min_clint.nx"
14import "rv64im_min_uart.nx"
15import "rv64im_min_virtio.nx"
16import "rv64im_min_sim.nx"
17import "nx_rv64_asm.nx"
18import "nx_rv64_fast.nx"
19
20func g_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
21func g_pn(v: i64) -> i64 { let b: *u8=sys_mmap(28); var x: i64=v; if x<0{b[0]=45;sys_write(1,b,1);x=0-x} if x==0{b[0]=48;sys_write(1,b,1);return 0} var d: i64=0; var y: i64=x; while y>0{d=d+1;y=y/10} var i: i64=d-1; y=x; while i>=0{b[i]=(48+(y%10)) as u8;y=y/10;i=i-1} sys_write(1,b,d); return 0 }
22func ck(name: *u8, c: i64) -> i64 { if c==1 { g_puts(" PASS " as *u8) } else { g_puts(" FAIL " as *u8) } g_puts(name); g_puts("\n" as *u8); return c }
23
24const DMEM_BASE: i64 = 0x80000000
25const DMEM_SIZE: i64 = 65536
26const DSCRATCH_OFF: i64 = 0x8000
27
28func mk_virtio() -> *NxVirtioMmio {
29 let v: *NxVirtioMmio = sys_mmap(64) as *NxVirtioMmio
30 let st: *i64 = sys_mmap(8 * NX_VIRTIO_SLOT_N) as *i64
31 nx_virtio_init(v, st) // blk: base 0x10001000, DeviceID 2
32 return v
33}
34// run on the golden behavioral sim with a virtio-blk device attached; return scratch word + steps/us.
35func run_sim_dev(code: *u8, nb: i64, steps_out: *i64, us_out: *i64) -> i64 {
36 let rf_storage: *i64 = sys_mmap(8 * NX_RV64IM_RF_N_REGS) as *i64
37 let csr_storage: *i64 = sys_mmap(8 * NX_CSR_SLOT_N) as *i64
38 let clint_storage: *i64 = sys_mmap(8 * NX_CLINT_SLOT_N) as *i64
39 let uart_storage: *i64 = sys_mmap(8 * NX_UART_SLOT_N) as *i64
40 let mem: *u8 = sys_mmap(DMEM_SIZE); let tx_buf: *u8 = sys_mmap(256)
41 let rf: *NxRv64imRegfile = sys_mmap(64) as *NxRv64imRegfile
42 let csr: *NxRv64imCsrFile = sys_mmap(64) as *NxRv64imCsrFile
43 let clint: *NxClint = sys_mmap(64) as *NxClint
44 let uart: *NxUart = sys_mmap(64) as *NxUart
45 let sim: *NxRv64imSim = sys_mmap(128) as *NxRv64imSim
46 nx_rv64im_rf_init(rf, rf_storage); nx_rv64im_csr_init(csr, csr_storage, 0); nx_clint_init(clint, clint_storage); nx_uart_init(uart, uart_storage, tx_buf, 256)
47 nx_rv64im_sim_init(sim, rf, csr, clint, uart, DMEM_BASE, mem, DMEM_SIZE, 0)
48 nx_rv64im_sim_attach_virtio(sim, mk_virtio())
49 var i: i64=0; while i<nb { mem[i]=code[i]; i=i+1 }
50 let t0: i64=sys_now_us(); nx_rv64im_sim_run(sim, 200000000); let t1: i64=sys_now_us()
51 steps_out[0]=sim.steps; us_out[0]=t1-t0
52 return fk_ld(mem, DSCRATCH_OFF, 4)
53}
54// run on the device-aware fast interpreter; dev_present=1 attaches a virtio-blk device, 0 = none.
55func run_fast_dev(code: *u8, nb: i64, dev_present: i64, steps_out: *i64, us_out: *i64) -> i64 {
56 let mem: *u8 = sys_mmap(DMEM_SIZE)
57 var i: i64=0; while i<nb { mem[i]=code[i]; i=i+1 }
58 let nw: i64 = nb/4
59 let opk: *i64=sys_mmap(nw*8) as *i64; let rd: *i64=sys_mmap(nw*8) as *i64; let rs1: *i64=sys_mmap(nw*8) as *i64; let rs2: *i64=sys_mmap(nw*8) as *i64; let imm: *i64=sys_mmap(nw*8) as *i64
60 let nc: i64 = fk_predecode(code, nb, opk, rd, rs1, rs2, imm)
61 let reg: *i64 = sys_mmap(32*8) as *i64; var z: i64=0; while z<32 { reg[z]=0; z=z+1 }
62 var dev: *NxVirtioMmio = (0 as i64) as *NxVirtioMmio
63 if dev_present==1 { dev = mk_virtio() }
64 let t0: i64=sys_now_us()
65 let st: i64 = fk_run(opk, rd, rs1, rs2, imm, nc, reg, mem, DMEM_SIZE, 200000000, dev)
66 let t1: i64=sys_now_us()
67 steps_out[0]=st; us_out[0]=t1-t0
68 return fk_ld(mem, DSCRATCH_OFF, 4)
69}
70
71func main() -> i64 {
72 g_puts("nx_rv64_fast_dev_gate (device-aware fast interpreter: drives a REAL virtio device, matches the golden sim, stays faster)\n" as *u8)
73 var pass: i64=0; var total: i64=0
74 let code: *u8 = sys_mmap(65536)
75 let so: *i64=sys_mmap(8) as *i64; let uo: *i64=sys_mmap(8) as *i64
76 let so2: *i64=sys_mmap(8) as *i64; let uo2: *i64=sys_mmap(8) as *i64
77
78 // driver: read virtio blk magic@0x10001000, verify==0x74726976, read DeviceID@+8 (=2), store to scratch; then a
79 // compute loop (timing). No device -> magic reads 0 -> store 255.
80 let nb: i64 = rvasm_assemble_str(" lui t2, 0x10001\n lw t0, 0(t2)\n lui t1, 0x74727\n addi t1, t1, -0x68a\n bne t0, t1, bad\n lw t3, 8(t2)\n j store\nbad:\n li t3, 255\nstore:\n lui s0, 0x80008\n slli s0, s0, 32\n srli s0, s0, 32\n sw t3, 0(s0)\n li t4, 0\n lui t5, 0x400\nbusy:\n addi t4, t4, 1\n blt t4, t5, busy\n lui a0, 0x100\n lui a1, 0x5\n addi a1, a1, 0x555\n sw a1, 0(a0)\nspin:\n j spin\n" as *u8, code, 65536)
81 if nb < 0 { g_puts(" ASSEMBLE FAILED\n" as *u8); sys_exit(1); return 1 }
82
83 let sim_id: i64 = run_sim_dev(code, nb, so, uo); let sim_steps: i64=so[0]; let sim_us: i64=uo[0]
84 let fast_id: i64 = run_fast_dev(code, nb, 1, so2, uo2); let fast_steps: i64=so2[0]; let fast_us: i64=uo2[0]
85 let nodev_id: i64 = run_fast_dev(code, nb, 0, so, uo)
86
87 g_puts(" golden sim (virtio attached): DeviceID read="); g_pn(sim_id); g_puts(" steps="); g_pn(sim_steps); g_puts(" time="); g_pn(sim_us); g_puts("us\n" as *u8)
88 g_puts(" device-aware fast interp: DeviceID read="); g_pn(fast_id); g_puts(" steps="); g_pn(fast_steps); g_puts(" time="); g_pn(fast_us); g_puts("us\n" as *u8)
89 g_puts(" fast interp, NO device: DeviceID read="); g_pn(nodev_id); g_puts(" (255 = no device found)\n" as *u8)
90
91 var t1: i64=0; if sim_id==2 { t1=1 }
92 pass=pass+ck("T1: the golden behavioral sim discovers DeviceID=2 from live virtio MMIO" as *u8, t1); total=total+1
93 var t2: i64=0; if fast_id==2 { if fast_id==sim_id { t2=1 } }
94 pass=pass+ck("T2: the DEVICE-AWARE fast interpreter discovers the SAME DeviceID=2 (equivalence + device capability)" as *u8, t2); total=total+1
95 var t3: i64=0; if nodev_id==255 { t3=1 }
96 pass=pass+ck("T3 (teeth): with NO device attached the fast interpreter reads 0 -> stores 255 (no false device)" as *u8, t3); total=total+1
97 var t4: i64=0; if fast_steps==sim_steps { if fast_us < sim_us { t4=1 } }
98 var sp: i64=0; if fast_us>0 { sp=(sim_us*100)/fast_us }
99 g_puts(" device-workload SPEEDUP = "); g_pn(sp/100); g_puts("."); if sp%100<10 { g_puts("0" as *u8) } g_pn(sp%100); g_puts("x (step-exact, decode-once still wins with MMIO on the path)\n" as *u8)
100 pass=pass+ck("T4: same step count + the fast interpreter is faster on the device-touching workload" as *u8, t4); total=total+1
101
102 var okall: i64=0; if pass==total { okall=1 }
103 g_puts("---- nx_rv64_fast_dev_gate: passed "); g_pn(pass); g_puts(" / "); g_pn(total); g_puts(" ----\n" as *u8)
104 if okall==1 {
105 let logf: i64=sys_openat_append("knowledge/status/rv64_fast_dev.log" as *u8, 420)
106 if logf>=0 { let z: i64=sys_write(logf,"NXRV64FASTDEV GREEN: device-aware predecoded interpreter drives a REAL virtio device (DeviceID match with the golden sim) + stays faster; no-device teeth; the speedup now applies to real driver workloads\n" as *u8,204); sys_close(logf) }
107 g_puts("verdict=GREEN (the fast interpreter is now device-aware -- drives a real virtio device identical to the golden sim AND stays faster; the speedup applies to real driver workloads, not just compute)\n" as *u8); sys_exit(0); return 0
108 }
109 g_puts("verdict=RED\n" as *u8); sys_exit(1); return 1
110}