code wiki / _hdl_build / nx_nrtl.nx

nx_nrtl.nx source

↩ module page · 108 lines · 5464 B

1// nx_nrtl.nx -- LIB: NHDL H3+H4 -- sovereign RTL + SYNTHESIS (the Yosys competitor). H1/H2 gave a netlist format + 2// hierarchy that you EMIT from a fabric; this is the layer you AUTHOR in: a tiny RTL where you write bus-level 3// equations, and a SYNTHESIZER that LOWERS them to the LUT4 fabric -- reusing the proven fabric builders (ripple 4// adder, per-bit logic LUTs) + fab_append (R32a) to compose. Author 3 lines of RTL -> a 32-gate netlist, sovereignly. 5// 6// NRTL GRAMMAR (v1): single-char bus names (a,b,t,u,y...), 3-address combinational statements. 7// .nrtl 1 8// .module <name> <W> # bus width W 9// .in a b # input buses (each W bits; assigned PI nets in order) 10// .out y # the output bus 11// t = a & b # one binary op per statement: & (AND) | (OR) ^ (XOR) + (ADD), bit-parallel @ W 12// u = a ^ b 13// y = t + u 14// .end 15// SYNTHESIS: each statement -> build the op's fabric sub-network (logic LUTs or the ripple adder), fab_append it 16// wiring its inputs to the operand buses' nets; the result bus = the appended outputs. The output bus -> the POs. 17// NEVER-BRICK (#26): pure memory, bounded, deterministic, zero hardware-state writes. license_tier: ORIGINAL 18import "nx_nhdl.nx" 19import "nx_fpga_compose.nx" 20import "nx_fpga_adder.nx" 21import "nx_fpga_lut.nx" 22import "nx_fpga_fabric.nx" 23import "nx_syscalls.nx" 24 25// read one whitespace-delimited single char token (skips ws, returns the char, advances past it) 26func nr_rdc(buf: *u8, pp: *i64, len: i64) -> i64 { let p: i64=nh_skip_ws(buf,pp[0],len); let c: i64=buf[p] as i64; pp[0]=p+1; return c } 27 28// build a per-bit binary-logic-op fabric (ncells=W): cell i = a_i OP b_i. npi=2W (a[W] then b[W]). flk = FL_AND/OR/XOR. 29func build_bitop(W: i64, flk: i64, init: *i64, src: *i64, po: *i64) -> i64 { 30 let npi: i64=2*W 31 let k: i64=fl_gate_to_lut4(flk) 32 var i: i64=0 33 while i<W { init[i]=k; src[i*4+0]=i; src[i*4+1]=W+i; src[i*4+2]=i; src[i*4+3]=i; po[i]=npi+i; i=i+1 } 34 return npi 35} 36 37// SYNTHESIZE NRTL source -> a flat LUT4 fabric. Returns ncells; outnpi/outnpo/outW set; cpo filled with W output nets. 38func nrtl_synth(buf: *u8, len: i64, cinit: *i64, csrc: *i64, ckind: *i64, cpo: *i64, outnpi: *i64, outnpo: *i64, outW: *i64) -> i64 { 39 let pp: *i64=sys_mmap(16) as *i64; pp[0]=0 40 nh_skip_word(buf,pp,len) // .nrtl 41 nh_skip_word(buf,pp,len) // 1 42 nh_skip_word(buf,pp,len) // .module 43 nh_skip_word(buf,pp,len) // <name> 44 let W: i64=nh_rd_int(buf,pp,len) 45 outW[0]=W 46 let c2b: *i64=sys_mmap(8*256) as *i64; var ci: i64=0; while ci<256 { c2b[ci]=0-1; ci=ci+1 } 47 let bnet: *i64=sys_mmap(8*32*W) as *i64 // bus_net[bus*W + bit] = composed net 48 var nbus: i64=0 49 // .in -- read single-char input buses until the next '.' directive 50 nh_skip_word(buf,pp,len) // .in 51 var ninp: i64=0 52 var go1: i64=1 53 while go1==1 { 54 let p: i64=nh_skip_ws(buf,pp[0],len) 55 if (buf[p] as i64)==46 { go1=0 } else { 56 let c: i64=buf[p] as i64; pp[0]=p+1 57 c2b[c]=nbus 58 var bit: i64=0; while bit<W { bnet[nbus*W+bit]=ninp*W+bit; bit=bit+1 } 59 nbus=nbus+1; ninp=ninp+1 60 } 61 } 62 let NPI: i64=ninp*W + 1 63 let ZERO: i64=ninp*W 64 outnpi[0]=NPI; outnpo[0]=W 65 nh_skip_word(buf,pp,len) // .out 66 let outc: i64=nr_rdc(buf,pp,len) 67 // statements 68 let bi: *i64=sys_mmap(8*128) as *i64; let bs: *i64=sys_mmap(8*512) as *i64; let bpo: *i64=sys_mmap(8*64) as *i64; let bk: *i64=sys_mmap(8*128) as *i64 69 let inmap: *i64=sys_mmap(8*128) as *i64 70 var cn: i64=0 71 var go2: i64=1 72 while go2==1 { 73 let p: i64=nh_skip_ws(buf,pp[0],len) 74 if (buf[p] as i64)==46 { go2=0 } else { // '.end' 75 let dst: i64=nr_rdc(buf,pp,len) 76 let eq: i64=nr_rdc(buf,pp,len) // '=' 77 let s1: i64=nr_rdc(buf,pp,len) 78 let op: i64=nr_rdc(buf,pp,len) 79 let s2: i64=nr_rdc(buf,pp,len) 80 let s1b: i64=c2b[s1]; let s2b: i64=c2b[s2] 81 var z: i64=0; while z<2*W { bk[z]=0; z=z+1 } 82 if op==43 { // '+' ADD -> ripple adder 83 let anpi: i64=fab_build_ripple_adder(W, bi, bs, bpo) 84 var b: i64=0; while b<W { inmap[b]=bnet[s1b*W+b]; inmap[W+b]=bnet[s2b*W+b]; b=b+1 } 85 inmap[2*W]=ZERO 86 let base: i64=fab_append(NPI, cinit, csrc, ckind, cn, anpi, 2*W, bi, bs, bk, inmap) 87 cn=cn+2*W 88 c2b[dst]=nbus 89 b=0; while b<W { bnet[nbus*W+b]=fab_sub_out(NPI, base, anpi, bpo[b], inmap); b=b+1 } 90 nbus=nbus+1 91 } else { // logic op 92 var flk: i64=FL_AND 93 if op==124 { flk=FL_OR } 94 if op==94 { flk=FL_XOR } 95 let bnpi: i64=build_bitop(W, flk, bi, bs, bpo) 96 var b: i64=0; while b<W { inmap[b]=bnet[s1b*W+b]; inmap[W+b]=bnet[s2b*W+b]; b=b+1 } 97 let base: i64=fab_append(NPI, cinit, csrc, ckind, cn, bnpi, W, bi, bs, bk, inmap) 98 cn=cn+W 99 c2b[dst]=nbus 100 b=0; while b<W { bnet[nbus*W+b]=fab_sub_out(NPI, base, bnpi, bpo[b], inmap); b=b+1 } 101 nbus=nbus+1 102 } 103 } 104 } 105 let ob: i64=c2b[outc] 106 var t: i64=0; while t<W { cpo[t]=bnet[ob*W+t]; t=t+1 } 107 return cn 108}