code wiki / _hdl_build / nx_nhdl_hier.nx
nx_nhdl_hier.nx source
↩ module page · 98 lines · 4961 B
1// nx_nhdl_hier.nx -- LIB: NHDL H2 -- HIERARCHY for the sovereign netlist format: a module DEFINED ONCE and
2// INSTANTIATED many times (the "folded" netlist the researched 'Netlist' entry describes: "5 definitions ->
3// 128 instances -> a million cells" -- compact reuse, the thing a flat netlist or a Verilog cell-dump can't do).
4//
5// GRAMMAR (v2):
6// .nhdl 2
7// .def <name> <npi> <npo> <ncells> # a reusable module definition (local net numbering)
8// L .. / D .. # its cells
9// .po <local nets>
10// .enddef
11// .top <npi> <npo> # the top module
12// .inst <name> <innet0> .. <innet{npi-1}> # instantiate <name>, wiring its PIs to top nets (PI / prior-inst output)
13// ...
14// .po <top nets>
15// .end
16//
17// ELABORATION (unfolding) -> a single flat fabric, via the PROVEN fab_append (R32a): each .inst appends the module's
18// cells with an inmap from its listed inputs; the instance's outputs become new top nets (tracked h2c[]). The flat
19// result runs on fab_eval and round-trips through H1. NEVER-BRICK (#26): pure memory, bounded, deterministic.
20// license_tier: ORIGINAL
21import "nx_nhdl.nx"
22import "nx_fpga_compose.nx"
23import "nx_fpga_fabric.nx"
24import "nx_syscalls.nx"
25const K_MAGIC_2048: i64 = 2048
26const K_MAGIC_4096: i64 = 4096
27
28// emit cell lines (no wrapper) -- for a .def body
29func nh_emit_cells(buf: *u8, o: i64, ncells: i64, kind: *i64, init: *i64, src: *i64) -> i64 {
30 var oo: i64=o; var k: i64=0
31 while k<ncells {
32 if kind[k]==1 { oo=nh_ws(buf,oo,"D \x00" as *u8); oo=nh_wi(buf,oo,src[k*4+0]); oo=nh_ws(buf,oo,"\n\x00" as *u8) }
33 else {
34 oo=nh_ws(buf,oo,"L \x00" as *u8); oo=nh_wi(buf,oo,init[k])
35 oo=nh_ws(buf,oo," \x00" as *u8); oo=nh_wi(buf,oo,src[k*4+0]); oo=nh_ws(buf,oo," \x00" as *u8); oo=nh_wi(buf,oo,src[k*4+1])
36 oo=nh_ws(buf,oo," \x00" as *u8); oo=nh_wi(buf,oo,src[k*4+2]); oo=nh_ws(buf,oo," \x00" as *u8); oo=nh_wi(buf,oo,src[k*4+3]); oo=nh_ws(buf,oo,"\n\x00" as *u8)
37 }
38 k=k+1
39 }
40 return oo
41}
42
43// parse ncells cell lines into kind/init/src (pp advanced)
44func nh_parse_cells(buf: *u8, pp: *i64, len: i64, ncells: i64, kind: *i64, init: *i64, src: *i64) -> i64 {
45 var k: i64=0
46 while k<ncells {
47 pp[0]=nh_skip_ws(buf, pp[0], len)
48 let kc: i64=buf[pp[0]] as i64
49 pp[0]=pp[0]+1
50 if kc==68 { kind[k]=1; init[k]=0; 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 }
51 else { kind[k]=0; init[k]=nh_rd_int(buf,pp,len); 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) }
52 k=k+1
53 }
54 return 0
55}
56
57// ELABORATE hierarchical NHDL (one .def + N .inst) -> flat fabric. Returns flat ncells; outnpi/outnpo set; cpo filled.
58func nhdl_hier_elaborate(buf: *u8, len: i64, cinit: *i64, csrc: *i64, ckind: *i64, cpo: *i64, outnpi: *i64, outnpo: *i64) -> i64 {
59 let pp: *i64=sys_mmap(16) as *i64; pp[0]=0
60 nh_skip_word(buf,pp,len) // .nhdl
61 nh_skip_word(buf,pp,len) // 2
62 // ----- the module definition -----
63 nh_skip_word(buf,pp,len) // .def
64 nh_skip_word(buf,pp,len) // <name>
65 let m_npi: i64=nh_rd_int(buf,pp,len); let m_npo: i64=nh_rd_int(buf,pp,len); let m_nc: i64=nh_rd_int(buf,pp,len)
66 let mk: *i64=sys_mmap(8*512) as *i64; let mi: *i64=sys_mmap(8*512) as *i64; let ms: *i64=sys_mmap(8*K_MAGIC_2048) as *i64; let mpo: *i64=sys_mmap(8*128) as *i64
67 nh_parse_cells(buf,pp,len,m_nc,mk,mi,ms)
68 nh_skip_word(buf,pp,len) // .po
69 var jj: i64=0; while jj<m_npo { mpo[jj]=nh_rd_int(buf,pp,len); jj=jj+1 }
70 nh_skip_word(buf,pp,len) // .enddef
71 // ----- the top module -----
72 nh_skip_word(buf,pp,len) // .top
73 let NPI: i64=nh_rd_int(buf,pp,len); let TNPO: i64=nh_rd_int(buf,pp,len)
74 outnpi[0]=NPI; outnpo[0]=TNPO
75 let h2c: *i64=sys_mmap(8*K_MAGIC_4096) as *i64 // hierarchical net -> composed net
76 var h: i64=0; while h<NPI { h2c[h]=h; h=h+1 }
77 var next_h: i64=NPI
78 var cn: i64=0
79 let inmap: *i64=sys_mmap(8*128) as *i64
80 // ----- instances until .po (peek: '.inst' starts with 'i', '.po' with 'p') -----
81 var go: i64=1
82 while go==1 {
83 let q: i64=nh_skip_ws(buf, pp[0], len)
84 if (buf[q+1] as i64)==105 {
85 nh_skip_word(buf,pp,len) // .inst
86 nh_skip_word(buf,pp,len) // <name>
87 var p: i64=0
88 while p<m_npi { inmap[p]=h2c[nh_rd_int(buf,pp,len)]; p=p+1 }
89 let base: i64=fab_append(NPI, cinit, csrc, ckind, cn, m_npi, m_nc, mi, ms, mk, inmap)
90 cn=cn+m_nc
91 var o: i64=0
92 while o<m_npo { h2c[next_h]=fab_sub_out(NPI, base, m_npi, mpo[o], inmap); next_h=next_h+1; o=o+1 }
93 } else { go=0 }
94 }
95 nh_skip_word(buf,pp,len) // .po
96 var t: i64=0; while t<TNPO { cpo[t]=h2c[nh_rd_int(buf,pp,len)]; t=t+1 }
97 return cn
98}