code wiki / _hdl_build / nx_isa_run_sov.nx
nx_isa_run_sov.nx source
↩ module page · 98 lines · 5484 B
1// nx_isa_run_sov.nx -- CLOSE THE LOOP (hardware -> derive -> hardware). A search-derived
2// RV64 program RUNS on the genesis sim rv64im_min_sim (god). The instruction sequence
3// MUL x3,x1,x2 ; ADD x3,x3,x1 is exactly what nx_evo_isa derives for f(a,b)=a*b+a; here we
4// ENCODE it to real RV64 machine code (the encoders -- rv_lui IS the search-derived enc_u),
5// wrap it to load a,b + write the result byte to the NS16550A UART + halt via the SiFive
6// finisher, LOAD it into the sim, RUN it, and VERIFY the captured UART byte == (a*b+a)&0xff.
7// Mirrors rv64im_min_sim_smoke's device setup. license_tier: ORIGINAL
8import "nx_syscalls.nx"
9import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc)
10import "nishi_hdl_primitives.nx"
11import "rv64im_min_decoder.nx"
12import "rv64im_min_alu.nx"
13import "rv64im_min_regfile.nx"
14import "rv64im_min_csr.nx"
15import "rv64im_min_clint.nx"
16import "rv64im_min_uart.nx"
17import "rv64im_min_sim.nx"
18
19const IR_MEM_BASE: i64 = 0x80000000
20const IR_MEM_SIZE: i64 = 4096
21const IR_TX_CAP: i64 = 256
22
23func ir_p(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
24// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer
25// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the
26// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls).
27// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign.
28func ir_n(v: i64) -> i64 { nxi_out(v); return 0 }
29
30// ---- RV64 encoders (rv_lui = the search-derived enc_u; the rest are the matching forms) ----
31func rv_addi(rd: i64, rs1: i64, imm: i64) -> i64 { return ((imm & 0xFFF) << 20) | (rs1 << 15) | (rd << 7) | 0x13 }
32func rv_lui(rd: i64, imm20: i64) -> i64 { return ((imm20 & 0xFFFFF) << 12) | (rd << 7) | 0x37 }
33func rv_rtype(f7: i64, rs2: i64, rs1: i64, f3: i64, rd: i64) -> i64 { return (f7 << 25) | (rs2 << 20) | (rs1 << 15) | (f3 << 12) | (rd << 7) | 0x33 }
34func rv_store(rs2: i64, rs1: i64, f3: i64) -> i64 { return (rs2 << 20) | (rs1 << 15) | (f3 << 12) | 0x23 } // imm = 0
35func rv_w32(buf: *u8, off: i64, w: i64) -> i64 {
36 buf[off] = (w & 0xff) as u8
37 buf[off+1] = ((w >> 8) & 0xff) as u8
38 buf[off+2] = ((w >> 16) & 0xff) as u8
39 buf[off+3] = ((w >> 24) & 0xff) as u8
40 return off + 4
41}
42
43// emit: li x1=a; li x2=b; <derived: MUL x3,x1,x2 ; ADD x3,x3,x1>; sb x3,UART; finisher halt.
44func ir_emit(mem: *u8, a: i64, b: i64) -> i64 {
45 var o: i64 = 0
46 o = rv_w32(mem, o, rv_addi(1, 0, a)) // addi x1, x0, a
47 o = rv_w32(mem, o, rv_addi(2, 0, b)) // addi x2, x0, b
48 o = rv_w32(mem, o, rv_rtype(0x01, 2, 1, 0, 3)) // MUL x3, x1, x2 (the derived program...)
49 o = rv_w32(mem, o, rv_rtype(0x00, 1, 3, 0, 3)) // ADD x3, x3, x1 (...= a*b + a)
50 o = rv_w32(mem, o, rv_lui(5, 0x10000)) // lui x5, 0x10000 (x5 = UART base 0x10000000)
51 o = rv_w32(mem, o, rv_store(3, 5, 0)) // sb x3, 0(x5) (UART <- result low byte)
52 o = rv_w32(mem, o, rv_lui(7, 0x100)) // lui x7, 0x100 (x7 = finisher 0x100000)
53 o = rv_w32(mem, o, rv_lui(6, 0x5)) // lui x6, 0x5 (x6 = 0x5000)
54 o = rv_w32(mem, o, rv_addi(6, 6, 0x555)) // addi x6, x6, 0x555 (x6 = 0x5555 PASS)
55 o = rv_w32(mem, o, rv_store(6, 7, 2)) // sw x6, 0(x7) (finisher <- 0x5555 -> halt)
56 o = rv_w32(mem, o, 0x6F) // jal x0, 0 (spin)
57 return o
58}
59
60func main() -> i64 {
61 let rf_storage: *i64 = (sys_mmap(8 * NX_RV64IM_RF_N_REGS)) as *i64
62 let csr_storage: *i64 = (sys_mmap(8 * NX_CSR_SLOT_N)) as *i64
63 let clint_storage: *i64 = (sys_mmap(8 * NX_CLINT_SLOT_N)) as *i64
64 let uart_storage: *i64 = (sys_mmap(8 * NX_UART_SLOT_N)) as *i64
65 let mem: *u8 = sys_mmap(IR_MEM_SIZE)
66 let tx_buf: *u8 = sys_mmap(IR_TX_CAP)
67 let rf: *NxRv64imRegfile = (sys_mmap(64)) as *NxRv64imRegfile
68 let csr: *NxRv64imCsrFile = (sys_mmap(64)) as *NxRv64imCsrFile
69 let clint: *NxClint = (sys_mmap(64)) as *NxClint
70 let uart: *NxUart = (sys_mmap(64)) as *NxUart
71 let sim: *NxRv64imSim = (sys_mmap(128)) as *NxRv64imSim
72
73 nx_rv64im_rf_init(rf, rf_storage)
74 nx_rv64im_csr_init(csr, csr_storage, 0)
75 nx_clint_init(clint, clint_storage)
76 nx_uart_init(uart, uart_storage, tx_buf, IR_TX_CAP)
77 nx_rv64im_sim_init(sim, rf, csr, clint, uart, IR_MEM_BASE, mem, IR_MEM_SIZE, 0)
78
79 let a: i64 = 6
80 let b: i64 = 7
81 ir_emit(mem, a, b)
82 nx_rv64im_sim_run(sim, 200)
83
84 let expected: i64 = (a * b + a) & 0xff
85 if sim.halted != 1 { ir_p("ISARUNSOV RED reason=no-clean-halt\n" as *u8); sys_exit(1); return 1 }
86 if nx_uart_tx_count(uart) < 1 { ir_p("ISARUNSOV RED reason=no-uart-output\n" as *u8); sys_exit(1); return 1 }
87 let got: i64 = tx_buf[0] as i64 & 0xff
88 ir_p("ISARUNSOV: a=" as *u8); ir_n(a); ir_p(" b=" as *u8); ir_n(b)
89 ir_p(" -- search-derived RV64 program (MUL;ADD = a*b+a) RAN on rv64im_min_sim -> UART byte=" as *u8); ir_n(got)
90 ir_p(" expected=" as *u8); ir_n(expected); ir_p(" steps=" as *u8); ir_n(sim.steps); ir_p("\n" as *u8)
91 if got == expected {
92 ir_p("ISARUNSOV GREEN: the loop is closed -- derive -> encode -> EXECUTE ON THE HARDWARE SIM (god) -> verified\n" as *u8)
93 sys_exit(0); return 0
94 }
95 ir_p("ISARUNSOV RED: output mismatch\n" as *u8)
96 sys_exit(1)
97 return 1
98}