code wiki / _hdl_build / nx_alu_emit_text_test.nx

nx_alu_emit_text_test.nx source

↩ module page · 96 lines · 3503 B

1// nx_alu_emit_text_test.nx -- SOVEREIGN gate (NishiLang verdict, no shell/grep): 2// drives the SHIPPING .nxgate emitter (nx_emit_alu_gates) and SELF-VERIFIES that 3// the emitted text carries the proven divider. The same builder the MEM verifier 4// proved at 21/7 runs here with a TEXT sink -> one source, two sinks. 5// 6// A stub ALU emits ~28 MUX / ~2 SUB / ~1 LTU cells; the divider-wired ALU emits 7// 4x64 of each. This test scans its OWN emitted buffer (no grep) and exits 0 IFF 8// the divider's signature is present + the .nxgate is structurally valid. 9// Verdict (exit code): 0 PROVEN; 1 MUX low; 2 SUB low; 3 LTU low; 4 no header; 10// 5 no .END; 20 emit failed. 11 12import "synth_emit_alu_gates.nx" 13 14const NX_ALU_MAX_SIG: i64 = 8192 15 16// Count non-overlapping occurrences of NUL-terminated `pat` in buf[0..used). 17func _count_sub(buf: *u8, used: i64, pat: *u8) -> i64 { 18 var plen: i64 = 0 19 while pat[plen] != (0 as u8) { plen = plen + 1 } 20 var c: i64 = 0 21 var i: i64 = 0 22 while i + plen <= used { 23 var hit: i64 = 1 24 var j: i64 = 0 25 while j < plen { 26 if buf[i + j] != pat[j] { hit = 0 } 27 j = j + 1 28 } 29 if hit == 1 { c = c + 1 } 30 i = i + 1 31 } 32 return c 33} 34 35func _emit_cstr(s: *u8) -> i64 { 36 var n: i64 = 0 37 while s[n] != (0 as u8) { n = n + 1 } 38 sys_write(1, s, n) 39 return 0 40} 41func _emit_dec(v: i64) -> i64 { 42 let b: *u8 = sys_mmap(28) 43 let t2: *u8 = sys_mmap(28) 44 var n: i64 = v 45 if n < 0 { n = 0 - n } 46 var t: i64 = 0 47 if n == 0 { t2[0] = 48; t = 1 } 48 while n > 0 { t2[t] = 48 + (n % 10); n = n / 10; t = t + 1 } 49 var i: i64 = 0 50 while i < t { b[i] = t2[t - 1 - i]; i = i + 1 } 51 sys_write(1, b, t) 52 return 0 53} 54 55func main() -> i64 { 56 let m: *NxHdlModule = sys_mmap(128) as *NxHdlModule 57 let sigs: *i64 = sys_mmap(8 * 4 * NX_ALU_MAX_SIG) as *i64 58 let npool: *u8 = sys_mmap(8192) 59 nx_hdl_module_init(m, "rv64im_alu" as *u8, 10, sigs, npool, 8192) 60 61 let ports: *NxRv64imAluPorts = sys_mmap(64) as *NxRv64imAluPorts 62 nx_rv64im_alu_build(m, ports) 63 64 let buf: *u8 = sys_mmap(2097152) 65 let s: *NxSynthSink = sys_mmap(64) as *NxSynthSink 66 nx_synth_sink_init(s, buf, 2097152) 67 68 let rc: i64 = nx_emit_alu_gates(s, m, ports) 69 if rc != NX_HDL_OK { sys_exit(20); return 20 } 70 71 let nmux: i64 = _count_sub(s.buf, s.used, "kind=MUX" as *u8) 72 let nsub: i64 = _count_sub(s.buf, s.used, "kind=SUB" as *u8) 73 let nltu: i64 = _count_sub(s.buf, s.used, "kind=LTU" as *u8) 74 let nmul: i64 = _count_sub(s.buf, s.used, "kind=MUL" as *u8) 75 let nhdr: i64 = _count_sub(s.buf, s.used, ".NXGATE 1" as *u8) 76 let nend: i64 = _count_sub(s.buf, s.used, ".END" as *u8) 77 78 _emit_cstr("emit-text: MUX=" as *u8); _emit_dec(nmux) 79 _emit_cstr(" SUB=" as *u8); _emit_dec(nsub) 80 _emit_cstr(" LTU=" as *u8); _emit_dec(nltu) 81 _emit_cstr(" MUL=" as *u8); _emit_dec(nmul) 82 _emit_cstr(" hdr=" as *u8); _emit_dec(nhdr) 83 _emit_cstr(" end=" as *u8); _emit_dec(nend) 84 _emit_cstr("\n" as *u8) 85 86 if nmux < 280 { sys_exit(1); return 1 } 87 if nsub < 250 { sys_exit(2); return 2 } 88 if nltu < 250 { sys_exit(3); return 3 } 89 if nhdr < 1 { sys_exit(4); return 4 } 90 if nend < 1 { sys_exit(5); return 5 } 91 // mulh shipped: each of MULH/MULHSU/MULHU emits a wide multiplier (4 MUL cells), 92 // so >= 12 MUL cells beyond the 2 single-MUL ops (MUL, MULW). A stub had ~5. 93 if nmul < 14 { sys_exit(6); return 6 } 94 sys_exit(0) 95 return 0 96}