code wiki / _hdl_build / nx_alu_netlist_test.nx

nx_alu_netlist_test.nx source

↩ module page · 86 lines · 4205 B

1// nx_alu_netlist_test.nx -- VERIFIER on the REAL ALU op-select topology 2// (SIL-3 closure, layer-7). Builds a 3-op (ADD/SUB/DIV) ALU netlist using the 3// EXACT structure the .nxgate ALU emitter (synth_emit_alu_gates.nx) emits: 4// per op a CONST(opcode) + a binop subnet + an EQ(op_in==opcode) match, then a 5// cascade MUX(match, this, prev). DIV is emitted as an ADD cell -- the SIL-1 6// stub (emitter lines 151-158, "TODO_SILICON proper divider"). 7// 8// Simulating over op_in proves: the correct ops (ADD/SUB) match the behavioral 9// ALU, and DIV (= a+b stub) DIVERGES from behavioral a/b -- the verifier CATCHES 10// the silent gate-emit miscompile via op-selection (what structural-only smokes 11// miss). 12// 13// a=20 b=4. Known answer (FAIL LOUD): "24 24 16 16 24 5 " = 14// res_add beh_add res_sub beh_sub res_div beh_div. (res_div=24 != beh=5 -> caught) 15 16import "nx_nxgate_sim.nx" 17 18func _emit_num(v: i64) -> i64 { 19 let b: *u8 = sys_mmap(28); var n: i64 = v; if n < 0 { n = 0 - n } 20 let t2: *u8 = sys_mmap(28); var t: i64 = 0 21 if n == 0 { t2[0] = 48; t = 1 } 22 while n > 0 { t2[t] = 48 + (n % 10); n = n / 10; t = t + 1 } 23 var i: i64 = 0; while i < t { b[i] = t2[t - 1 - i]; i = i + 1 } 24 b[t] = 32; sys_write(1, b, t + 1); return 0 25} 26func _nl() -> i64 { let z: *u8 = sys_mmap(2); z[0] = 10; sys_write(1, z, 1); return 0 } 27 28func _setcell(cells: *NxGsimCell, id: i64, kind: i64, fanout: i64, f0: i64, f1: i64, f2: i64) -> i64 { 29 cells[id].kind = kind 30 cells[id].fanout = fanout 31 cells[id].f0 = f0 32 cells[id].f1 = f1 33 cells[id].f2 = f2 34 return 0 35} 36 37func main() -> i64 { 38 let vals: *i64 = sys_mmap(64 * 8) as *i64 39 let cells: *NxGsimCell = sys_mmap(32 * 48) as *NxGsimCell 40 let g: *NxGsim = sys_mmap(64) as *NxGsim 41 g.vals = vals 42 g.n_nets = 16 43 g.cells = cells 44 g.n_cells = 13 45 46 // nets: 0=a 1=b 2=op_in (inputs); op codes ADD=1 SUB=2 DIV=3 47 _setcell(cells, 0, NX_GATE_KIND_CONST, 3, 0 - 1, 0 - 1, 0 - 1); cells[0].val = 1 // op-code ADD 48 _setcell(cells, 1, NX_GATE_KIND_ADD, 4, 0, 1, 0 - 1) // ADD subnet 49 _setcell(cells, 2, NX_GATE_KIND_EQ, 5, 2, 3, 0 - 1) // match ADD 50 _setcell(cells, 3, NX_GATE_KIND_CONST, 6, 0 - 1, 0 - 1, 0 - 1); cells[3].val = 2 // op-code SUB 51 _setcell(cells, 4, NX_GATE_KIND_SUB, 7, 0, 1, 0 - 1) // SUB subnet 52 _setcell(cells, 5, NX_GATE_KIND_EQ, 8, 2, 6, 0 - 1) // match SUB 53 _setcell(cells, 6, NX_GATE_KIND_CONST, 9, 0 - 1, 0 - 1, 0 - 1); cells[6].val = 3 // op-code DIV 54 _setcell(cells, 7, NX_GATE_KIND_ADD, 10, 0, 1, 0 - 1) // DIV subnet = STUB (ADD) 55 _setcell(cells, 8, NX_GATE_KIND_EQ, 11, 2, 9, 0 - 1) // match DIV 56 _setcell(cells, 9, NX_GATE_KIND_CONST,12, 0 - 1, 0 - 1, 0 - 1); cells[9].val = 0 // INVALID prev0 57 _setcell(cells, 10, NX_GATE_KIND_MUX, 13, 5, 4, 12) // matchADD ? subADD : prev 58 _setcell(cells, 11, NX_GATE_KIND_MUX, 14, 8, 7, 13) // matchSUB ? subSUB : prev 59 _setcell(cells, 12, NX_GATE_KIND_MUX, 15, 11, 10, 14) // matchDIV ? subDIV : prev 60 61 vals[0] = 20 62 vals[1] = 4 63 64 vals[2] = 1 65 if nx_gsim_run(g) != NX_GSIM_OK { sys_exit(10); return 10 } 66 let res_add: i64 = vals[15] 67 68 vals[2] = 2 69 if nx_gsim_run(g) != NX_GSIM_OK { sys_exit(11); return 11 } 70 let res_sub: i64 = vals[15] 71 72 vals[2] = 3 73 if nx_gsim_run(g) != NX_GSIM_OK { sys_exit(12); return 12 } 74 let res_div: i64 = vals[15] 75 76 let beh_add: i64 = 20 + 4 77 let beh_sub: i64 = 20 - 4 78 let beh_div: i64 = 20 / 4 79 _emit_num(res_add); _emit_num(beh_add); _emit_num(res_sub); _emit_num(beh_sub); _emit_num(res_div); _emit_num(beh_div) 80 _nl() 81 82 if res_add != beh_add { sys_exit(1); return 1 } // ADD op == behavioral ADD 83 if res_sub != beh_sub { sys_exit(2); return 2 } // SUB op == behavioral SUB 84 if res_div == beh_div { sys_exit(3); return 3 } // STUB CATCH: DIV stub(24) must NOT equal behavioral(5) 85 sys_exit(0); return 0 86}