code wiki / _hdl_build / nx_cell_sink.nx

nx_cell_sink.nx source

↩ module page · 91 lines · 3022 B

1// nx_cell_sink.nx -- ONE cell-emit interface, TWO backends. The true SIL-3/SIL-1 2// "one source" closure: a netlist builder written against NxCellSink emits the 3// SAME gate graph to either 4// (a) an in-memory NxGsim -> the functional Verifier (nx_gsim_run) runs it, 5// (b) a .nxgate text sink -> the shipping synth output downstream PnR reads. 6// So the divider/ALU is described ONCE and the verifier provably checks exactly 7// what the emitter ships -- no hand-kept copy, no op->kind-only shortcut. 8// 9// Net allocation: MEM mode hands out integer net ids (g.n_nets++); TEXT mode 10// allocates a real module wire (nx_hdl_wire, width-typed) and emits the cell 11// line. Width is used only by TEXT (the sim is word-level / width-agnostic). 12 13import "nx_syscalls.nx" 14import "nx_nxgate_sim.nx" 15import "nishi_synth_gates.nx" 16import "nishi_hdl_primitives.nx" 17 18const NX_SINK_MEM: i64 = 0 19const NX_SINK_TEXT: i64 = 1 20 21struct NxCellSink { 22 mode: i64 23 g: *NxGsim // MEM backend 24 s: *NxSynthSink // TEXT backend 25 m: *NxHdlModule // TEXT backend (net allocator) 26 cell_seq: i64 // TEXT cell-id counter 27} 28 29func nx_sink_init_mem(k: *NxCellSink, g: *NxGsim) -> i64 { 30 k.mode = NX_SINK_MEM 31 k.g = g 32 k.cell_seq = 0 33 return 0 34} 35 36func nx_sink_init_text(k: *NxCellSink, s: *NxSynthSink, m: *NxHdlModule, seq0: i64) -> i64 { 37 k.mode = NX_SINK_TEXT 38 k.s = s 39 k.m = m 40 k.cell_seq = seq0 41 return 0 42} 43 44// Append a CONST cell driving a fresh net = value; return the net id. 45func nx_sink_const(k: *NxCellSink, width: i64, value: i64) -> i64 { 46 if k.mode == NX_SINK_MEM { 47 let g: *NxGsim = k.g 48 let nn: i64 = g.n_nets 49 let nc: i64 = g.n_cells 50 g.cells[nc].kind = NX_GATE_KIND_CONST 51 g.cells[nc].fanout = nn 52 g.cells[nc].f0 = 0 - 1 53 g.cells[nc].f1 = 0 - 1 54 g.cells[nc].f2 = 0 - 1 55 g.cells[nc].val = value 56 g.n_nets = nn + 1 57 g.n_cells = nc + 1 58 return nn 59 } 60 let net: i64 = nx_hdl_wire(k.m, width) 61 nx_gate_emit_const(k.s, k.cell_seq, width, value) 62 k.cell_seq = k.cell_seq + 1 63 return net 64} 65 66// Append a cell (kind, up to 3 fanins; pass 0-1 for unused) -> fresh net. 67func nx_sink_cell(k: *NxCellSink, kind: i64, width: i64, 68 f0: i64, f1: i64, f2: i64, nfan: i64) -> i64 { 69 if k.mode == NX_SINK_MEM { 70 let g: *NxGsim = k.g 71 let nn: i64 = g.n_nets 72 let nc: i64 = g.n_cells 73 g.cells[nc].kind = kind 74 g.cells[nc].fanout = nn 75 g.cells[nc].f0 = f0 76 g.cells[nc].f1 = f1 77 g.cells[nc].f2 = f2 78 g.cells[nc].val = 0 79 g.n_nets = nn + 1 80 g.n_cells = nc + 1 81 return nn 82 } 83 let net: i64 = nx_hdl_wire(k.m, width) 84 let fanin: *i64 = sys_mmap(32) as *i64 85 fanin[0] = f0 86 if nfan > 1 { fanin[1] = f1 } 87 if nfan > 2 { fanin[2] = f2 } 88 nx_gate_emit_cell(k.s, k.cell_seq, kind, net, fanin, nfan) 89 k.cell_seq = k.cell_seq + 1 90 return net 91}