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}