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}