code wiki / _hdl_build / nx_fpga_compose.nx
nx_fpga_compose.nx source
↩ module page · 50 lines · 3052 B
1// nx_fpga_compose.nx -- LIB: RUNG 32a -- COMPOSE separate module-fabrics into ONE unified fabric.
2//
3// The CPU rungs (R11..R20) build SEPARATE fabrics (decode, ALU, regfile, PC, IMEM/DMEM RAM) and wire them
4// together in host NishiLang per clock step. To emit the WHOLE CPU as ONE Yosys-synthesizable Verilog netlist
5// (R29 emitted only the ALU) -- the artifact nextpnr/prjtrellis consume toward an ECP5 bitstream -- the datapath
6// must BE a single composed fabric. fab_append copies a sub-fabric's cells into a growing composed fabric,
7// REMAPPING every net: a sub-fabric cell ref (s >= snpi) -> the composed cell slot it landed in; a sub-fabric
8// PI ref (s < snpi) -> the composed net it is WIRED to (inmap[s], either a composed PI or a prior sub-fabric's
9// output). LUT (kind 0) and DFF (kind 1) cells are copied uniformly, so sequential state (regfile/PC/RAM)
10// composes exactly like combinational logic. The composed fabric runs unchanged on fab_eval / seq_eval / seq_tick
11// and serializes through nx_fpga_verilog.
12// NEVER-BRICK (#26): pure memory, bounded by total cells, deterministic (same inputs -> same netlist), zero
13// hardware-state writes. license_tier: ORIGINAL
14import "nx_fpga_fabric.nx"
15import "nx_syscalls.nx"
16
17// Append one sub-fabric's bitstream into the composed fabric arrays. Returns the base cell-offset where the
18// sub-fabric's cell 0 landed (so its cell c is composed NET NPI + base + c, usable to wire later sub-fabrics).
19// NPI composed fabric primary-input count (constant across the whole compose)
20// cinit,csrc,ckind growing composed bitstream (caller-allocated big enough), already holding `cn` cells
21// cn current composed cell count
22// snpi,sn sub-fabric PI count / cell count
23// sinit,ssrc,skind sub-fabric bitstream (skind = its per-cell kind; pass all-0 for a combinational module)
24// inmap inmap[p] = composed NET each sub-fabric PI p reads from (composed PI <NPI, or NPI+base'+c)
25func fab_append(NPI: i64, cinit: *i64, csrc: *i64, ckind: *i64, cn: i64,
26 snpi: i64, sn: i64, sinit: *i64, ssrc: *i64, skind: *i64, inmap: *i64) -> i64 {
27 let base: i64 = cn
28 var k: i64 = 0
29 while k < sn {
30 let dst: i64 = base + k
31 ckind[dst] = skind[k]
32 cinit[dst] = sinit[k]
33 var j: i64 = 0
34 while j < 4 {
35 let s: i64 = ssrc[k*4+j]
36 var rs: i64 = NPI + base + (s - snpi) // default: a cell ref -> remapped composed cell net
37 if s < snpi { rs = inmap[s] } // a PI ref -> the wired composed net
38 csrc[dst*4+j] = rs
39 j = j + 1
40 }
41 k = k + 1
42 }
43 return base
44}
45
46// Map a sub-fabric OUTPUT (one of its po_src[] entries) to a composed NET id, for wiring into a later sub-fabric.
47func fab_sub_out(NPI: i64, base: i64, snpi: i64, sub_po: i64, inmap: *i64) -> i64 {
48 if sub_po < snpi { return inmap[sub_po] } // a passthrough PI
49 return NPI + base + (sub_po - snpi) // a cell output
50}