code wiki / _hdl_build / nx_nhdl.nx

nx_nhdl.nx source

↩ module page · 106 lines · 5576 B

1// nx_nhdl.nx -- LIB: NHDL H1 -- the sovereign Nishi netlist format (a Verilog COMPETITOR, not a Verilog emit). 2// 3// Operator 2026-06-26: "verilog should only be a benchmark build our own verilog competitor in nishi ecosystem 4// from the hardware rung up each rung." So instead of serializing our LUT4/DFF fabric to third-party Verilog 5// (now a benchmark yardstick only), this is OUR OWN textual netlist interchange format -- flat, instance-based 6// (cells=instances, nets=wires; the canonical netlist structure per the researched Wikipedia 'Netlist' entry: 7// a header + a per-instance table, one line per entry, space-separated fields). Designed to round-trip the 8// fabric byte-exact AND to be far more compact than Verilog's verbose `assign comb[k]=(INIT>>(...))&1; //@C...`. 9// 10// GRAMMAR (v1): 11// .nhdl 1 12// .module <name> <npi> <npo> <ncells> 13// L <init> <s0> <s1> <s2> <s3> # a LUT4 cell (combinational): 16-bit init + 4 input nets 14// D <dsrc> # a DFF cell (sequential): the D-input net (init unused, Q is caller state) 15// ... (ncells lines, in cell-index order; net s<npi => primary input s, else cell (s-npi)'s output) 16// .po <net0> <net1> ... <net_{npo-1}> 17// .end 18// NEVER-BRICK (#26): pure text emit/parse, bounded, deterministic, zero hardware-state writes. license_tier: ORIGINAL 19import "nx_syscalls.nx" 20 21func nh_ws(buf: *u8, o: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){ buf[o]=s[i]; o=o+1; i=i+1 } return o } 22func nh_wi(buf: *u8, o: i64, v: i64) -> i64 { 23 var p: i64=o; var m: i64=v 24 if m<0 { buf[p]=45 as u8; p=p+1; m=0-m } 25 if m==0 { buf[p]=48 as u8; return p+1 } 26 let t: *u8=sys_mmap(28); var k: i64=0 27 while m>0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 } 28 var j: i64=0; while j<k { buf[p]=t[k-1-j]; p=p+1; j=j+1 } 29 return p 30} 31 32// EMIT the fabric as NHDL text into buf. Returns length. 33func nhdl_emit(buf: *u8, name: *u8, ncells: i64, npi: i64, npo: i64, kind: *i64, init: *i64, src: *i64, po: *i64) -> i64 { 34 var o: i64=0 35 o=nh_ws(buf,o,".nhdl 1\n\x00" as *u8) 36 o=nh_ws(buf,o,".module \x00" as *u8); o=nh_ws(buf,o,name) 37 o=nh_ws(buf,o," \x00" as *u8); o=nh_wi(buf,o,npi); o=nh_ws(buf,o," \x00" as *u8); o=nh_wi(buf,o,npo); o=nh_ws(buf,o," \x00" as *u8); o=nh_wi(buf,o,ncells); o=nh_ws(buf,o,"\n\x00" as *u8) 38 var k: i64=0 39 while k<ncells { 40 if kind[k]==1 { 41 o=nh_ws(buf,o,"D \x00" as *u8); o=nh_wi(buf,o,src[k*4+0]); o=nh_ws(buf,o,"\n\x00" as *u8) 42 } else { 43 o=nh_ws(buf,o,"L \x00" as *u8); o=nh_wi(buf,o,init[k]) 44 o=nh_ws(buf,o," \x00" as *u8); o=nh_wi(buf,o,src[k*4+0]) 45 o=nh_ws(buf,o," \x00" as *u8); o=nh_wi(buf,o,src[k*4+1]) 46 o=nh_ws(buf,o," \x00" as *u8); o=nh_wi(buf,o,src[k*4+2]) 47 o=nh_ws(buf,o," \x00" as *u8); o=nh_wi(buf,o,src[k*4+3]); o=nh_ws(buf,o,"\n\x00" as *u8) 48 } 49 k=k+1 50 } 51 o=nh_ws(buf,o,".po\x00" as *u8) 52 var p: i64=0; while p<npo { o=nh_ws(buf,o," \x00" as *u8); o=nh_wi(buf,o,po[p]); p=p+1 } 53 o=nh_ws(buf,o,"\n.end\n\x00" as *u8) 54 return o 55} 56 57func nh_isdig(c: i64) -> i64 { if c<48 { return 0 } if c>57 { return 0 } return 1 } 58func nh_isws(c: i64) -> i64 { if c==32 { return 1 } if c==10 { return 1 } if c==9 { return 1 } if c==13 { return 1 } return 0 } 59func nh_skip_ws(buf: *u8, p: i64, len: i64) -> i64 { var q: i64=p; var go: i64=1; while go==1 { if q<len { if nh_isws(buf[q] as i64)==1 { q=q+1 } else { go=0 } } else { go=0 } } return q } 60// skip one whitespace-delimited token (a keyword like .module / .po, or the module name) 61func nh_skip_word(buf: *u8, pp: *i64, len: i64) -> i64 { 62 var p: i64=nh_skip_ws(buf, pp[0], len) 63 var go: i64=1 64 while go==1 { if p<len { if nh_isws(buf[p] as i64)==1 { go=0 } else { p=p+1 } } else { go=0 } } 65 pp[0]=p; return 0 66} 67func nh_rd_int(buf: *u8, pp: *i64, len: i64) -> i64 { 68 var p: i64=nh_skip_ws(buf, pp[0], len) 69 var v: i64=0; var neg: i64=0 70 if p<len { if buf[p]==(45 as u8) { neg=1; p=p+1 } } 71 var go: i64=1 72 while go==1 { if p<len { if nh_isdig(buf[p] as i64)==1 { v=v*10+((buf[p] as i64)-48); p=p+1 } else { go=0 } } else { go=0 } } 73 if neg==1 { v=0-v } 74 pp[0]=p; return v 75} 76 77// PARSE NHDL text -> reconstruct kind/init/src/po (caller-allocated). npi via pnpi, npo via pnpo. Returns ncells. 78func nhdl_parse(buf: *u8, len: i64, kind: *i64, init: *i64, src: *i64, po: *i64, pnpi: *i64, pnpo: *i64) -> i64 { 79 let pp: *i64=sys_mmap(16) as *i64; pp[0]=0 80 nh_skip_word(buf, pp, len) // ".nhdl" 81 nh_skip_word(buf, pp, len) // version "1" 82 nh_skip_word(buf, pp, len) // ".module" 83 nh_skip_word(buf, pp, len) // <name> 84 let npi: i64=nh_rd_int(buf, pp, len) 85 let npo: i64=nh_rd_int(buf, pp, len) 86 let ncells: i64=nh_rd_int(buf, pp, len) 87 pnpi[0]=npi; pnpo[0]=npo 88 var k: i64=0 89 while k<ncells { 90 pp[0]=nh_skip_ws(buf, pp[0], len) 91 let kc: i64=buf[pp[0]] as i64 // 'L'(76)=LUT or 'D'(68)=DFF 92 pp[0]=pp[0]+1 93 if kc==68 { 94 kind[k]=1; init[k]=0 95 src[k*4+0]=nh_rd_int(buf, pp, len); src[k*4+1]=0; src[k*4+2]=0; src[k*4+3]=0 96 } else { 97 kind[k]=0 98 init[k]=nh_rd_int(buf, pp, len) 99 src[k*4+0]=nh_rd_int(buf, pp, len); src[k*4+1]=nh_rd_int(buf, pp, len); src[k*4+2]=nh_rd_int(buf, pp, len); src[k*4+3]=nh_rd_int(buf, pp, len) 100 } 101 k=k+1 102 } 103 nh_skip_word(buf, pp, len) // ".po" 104 var p: i64=0; while p<npo { po[p]=nh_rd_int(buf, pp, len); p=p+1 } 105 return ncells 106}