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}