code wiki / _hdl_build / nx_pattern_emit_rtlsynth.nx

nx_pattern_emit_rtlsynth.nx source

↩ module page · 100 lines · 4859 B

1// nx_pattern_emit_rtlsynth.nx -- PATTERN EMITTER: RTL_SYNTH (shape 23). Authors a SYNTHESIS core that LOWERS a 2// 3-address op-DAG spec (the NRTL statement shape: dst = s1 OP s2) to a baked dataflow computation -- bit-parallel 3// AND/OR/XOR/ADD over i64 lanes, statements composed by data dependency (a src refs an input or a prior result). 4// 3rd of the session's 5-emitter autonomy backlog; a MEATIER core than the rank emitters (it bakes a whole DAG), 5// proving the template handles non-trivial shapes. TEAM-AUTHORABLE hands-off (author=emitter, no Claude logic). 6// spec[0]=ninputs (>=1) spec[1]=nstmts (1..16) 7// spec[2+3*i]=op (0 AND,1 OR,2 XOR,3 ADD) spec[3+3*i]=src1 spec[4+3*i]=src2 8// src r: r<ninputs -> inp[r]; else -> t(r-ninputs) (a prior statement, r<ninputs+i) 9// Authored fn: <name>_compute(inp: *i64) -> i64 (returns the last statement's result) 10// EMIT-TIME RAILS: ninputs<1, nstmts outside 1..16, op outside 0..3, or a forward/oob src -> REFUSED. ORIGINAL 11import "nx_syscalls.nx" 12 13func prs_w(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd, s, n); return 0 } 14func prs_wn(fd: i64, v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m; sys_write(fd,"-" as *u8,1)} let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1} sys_write(fd,bb,k); return 0 } 15 16func prs_spec_ok(spec: *i64) -> i64 { 17 let ni: i64=spec[0]; let ns: i64=spec[1] 18 if ni < 1 { return 0 } 19 if ns < 1 { return 0 } 20 if ns > 16 { return 0 } 21 var i: i64=0 22 while i < ns { 23 let op: i64=spec[2+3*i]; let s1: i64=spec[3+3*i]; let s2: i64=spec[4+3*i] 24 if op < 0 { return 0 } 25 if op > 3 { return 0 } 26 if s1 < 0 { return 0 } 27 if s2 < 0 { return 0 } 28 if s1 >= ni + i { return 0 } 29 if s2 >= ni + i { return 0 } 30 i = i + 1 31 } 32 return 1 33} 34 35// deterministic emit-time evaluator (for the KAT): apply the DAG over inp 36func prs_eval(spec: *i64, inp: *i64) -> i64 { 37 let ni: i64=spec[0]; let ns: i64=spec[1] 38 let vals: *i64=sys_mmap(8*(ni+ns+4)) as *i64 39 var i: i64=0; while i<ni { vals[i]=inp[i]; i=i+1 } 40 i=0 41 while i<ns { 42 let op: i64=spec[2+3*i]; let a: i64=vals[spec[3+3*i]]; let b: i64=vals[spec[4+3*i]] 43 var r: i64=0 44 if op==0 { r=a&b } 45 if op==1 { r=a|b } 46 if op==2 { r=a^b } 47 if op==3 { r=a+b } 48 vals[ni+i]=r 49 i=i+1 50 } 51 return vals[ni+ns-1] 52} 53 54func prs_emit_ref(fd: i64, r: i64, ni: i64) -> i64 { 55 if r < ni { prs_w(fd, "inp[" as *u8); prs_wn(fd, r); prs_w(fd, "]" as *u8) } else { prs_w(fd, "t" as *u8); prs_wn(fd, r-ni) } 56 return 0 57} 58func prs_emit_op(fd: i64, op: i64) -> i64 { 59 if op==0 { prs_w(fd, " & " as *u8) } 60 if op==1 { prs_w(fd, " | " as *u8) } 61 if op==2 { prs_w(fd, " ^ " as *u8) } 62 if op==3 { prs_w(fd, " + " as *u8) } 63 return 0 64} 65 66func pe_rs_emit_core(fd: i64, name: *u8, spec: *i64) -> i64 { 67 let ni: i64=spec[0]; let ns: i64=spec[1] 68 prs_w(fd, "// AUTHORED BY THE NISHI BUILDER (pattern: RTL_SYNTH) -- op-DAG lowered to a baked dataflow, no Claude logic\n" as *u8) 69 prs_w(fd, "func " as *u8); prs_w(fd, name); prs_w(fd, "_compute(inp: *i64) -> i64 {\n" as *u8) 70 var i: i64=0 71 while i<ns { 72 prs_w(fd, " let t" as *u8); prs_wn(fd, i); prs_w(fd, ": i64 = " as *u8) 73 prs_emit_ref(fd, spec[3+3*i], ni); prs_emit_op(fd, spec[2+3*i]); prs_emit_ref(fd, spec[4+3*i], ni) 74 prs_w(fd, "\n" as *u8) 75 i=i+1 76 } 77 prs_w(fd, " return t" as *u8); prs_wn(fd, ns-1); prs_w(fd, "\n}\n" as *u8) 78 return 1 79} 80 81func pe_rs_emit_test(fd: i64, name: *u8, spec: *i64) -> i64 { 82 let ni: i64=spec[0] 83 let inp: *i64=sys_mmap(8*(ni+2)) as *i64 84 var j: i64=0; while j<ni { inp[j]=j*2+3; j=j+1 } 85 let want: i64=prs_eval(spec, inp) 86 prs_w(fd, "import \"" as *u8); prs_w(fd, name); prs_w(fd, ".nx\"\nimport \"nx_syscalls.nx\"\n" as *u8) 87 prs_w(fd, "func main() -> i64 {\n let inp: *i64=sys_mmap(" as *u8); prs_wn(fd, 8*(ni+2)); prs_w(fd, ") as *i64\n" as *u8) 88 j=0; while j<ni { prs_w(fd, " inp[" as *u8); prs_wn(fd, j); prs_w(fd, "]=" as *u8); prs_wn(fd, inp[j]); prs_w(fd, "\n" as *u8); j=j+1 } 89 prs_w(fd, " if " as *u8); prs_w(fd, name); prs_w(fd, "_compute(inp) == " as *u8); prs_wn(fd, want); prs_w(fd, " { sys_exit(0) }\n sys_exit(1)\n return 1\n}\n" as *u8) 90 return 1 91} 92 93func pe_rs_author(name: *u8, modpath: *u8, testpath: *u8, spec: *i64) -> i64 { 94 if prs_spec_ok(spec) != 1 { return 0 } 95 let mf: i64=sys_openat_wr(modpath, 0x1a4); if mf < 0 { return 0 } 96 pe_rs_emit_core(mf, name, spec); sys_close(mf) 97 let tf: i64=sys_openat_wr(testpath, 0x1a4); if tf < 0 { return 0 } 98 pe_rs_emit_test(tf, name, spec); sys_close(tf) 99 return 1 100}