code wiki / _hdl_build / nx_alu_divider_race_test.nx
nx_alu_divider_race_test.nx source
↩ module page · 82 lines · 4379 B
1// nx_alu_divider_race_test.nx -- the RACE step (theory -> proof -> RACED). Not a
2// correctness test: it MEASURES our divider's latency/area from the netlist and
3// races it against the RESEARCH algorithm ladder. "How fast vs what exists."
4//
5// Digit-recurrence dividers are dominated by LATENCY = #sequential stages (the
6// remainder dependency chain). Research ladder (stages for a W-bit divide):
7// restoring / non-restoring (radix-2): W [the floor]
8// radix-4 SRT: ceil(W/2) [~2x]
9// Goldschmidt / Newton (multiplicative): ceil(log2 W) [the FRONTIER, quadratic]
10// We MACHINE-COUNT our radix-2 and radix-4 stages (= SUB cells) + total cells
11// (area proxy) and print them next to the ladder, with the HONEST verdict.
12//
13// HONEST scope: a gate-level structural race (stages/gates = what DETERMINES
14// eventual latency/area); a true ns/cycle race vs a synthesized incumbent needs
15// place-&-route/silicon (the L8 gap). Output (FAIL LOUD on a measurement error):
16// "<r2_stages> <r2_cells> <r4_stages> <r4_cells> <goldschmidt_frontier>".
17
18import "nx_alu_divider_r4.nx"
19
20func _emit_num(v: i64) -> i64 {
21 let b: *u8 = sys_mmap(28); var n: i64 = v; if n < 0 { n = 0 - n }
22 let t2: *u8 = sys_mmap(28); var t: i64 = 0
23 if n == 0 { t2[0] = 48; t = 1 }
24 while n > 0 { t2[t] = 48 + (n % 10); n = n / 10; t = t + 1 }
25 var i: i64 = 0; while i < t { b[i] = t2[t - 1 - i]; i = i + 1 }
26 b[t] = 32; sys_write(1, b, t + 1); return 0
27}
28func _puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != 0 as u8 { n = n + 1 } sys_write(1, s, n); return 0 }
29func _nl() -> i64 { let z: *u8 = sys_mmap(2); z[0] = 10; sys_write(1, z, 1); return 0 }
30
31func count_kind(g: *NxGsim, kind: i64) -> i64 {
32 var c: i64 = 0; var i: i64 = 0
33 while i < g.n_cells { if g.cells[i].kind == kind { c = c + 1 } i = i + 1 }
34 return c
35}
36
37func build_r2(width: i64) -> i64 { // returns SUB-stage count; cells in a global-ish via the g it builds
38 return 0
39}
40
41func main() -> i64 {
42 let W: i64 = 63
43
44 // radix-2 netlist
45 let v2: *i64 = sys_mmap(2048 * 8) as *i64
46 let c2: *NxGsimCell = sys_mmap(2048 * 48) as *NxGsimCell
47 let g2: *NxGsim = sys_mmap(64) as *NxGsim
48 g2.vals = v2; g2.n_nets = 2; g2.cells = c2; g2.n_cells = 0
49 let r2o: *i64 = sys_mmap(8) as *i64; r2o[0] = 0
50 let d2: i64 = nx_div_synth(g2, 0, 1, W, r2o)
51 let r2_stages: i64 = count_kind(g2, NX_GATE_KIND_SUB)
52 let r2_cells: i64 = g2.n_cells
53
54 // radix-4 netlist
55 let v4: *i64 = sys_mmap(2048 * 8) as *i64
56 let c4: *NxGsimCell = sys_mmap(2048 * 48) as *NxGsimCell
57 let g4: *NxGsim = sys_mmap(64) as *NxGsim
58 g4.vals = v4; g4.n_nets = 2; g4.cells = c4; g4.n_cells = 0
59 let r4o: *i64 = sys_mmap(8) as *i64; r4o[0] = 0
60 let d4: i64 = nx_div_synth_r4(g4, 0, 1, W, r4o)
61 let r4_stages: i64 = count_kind(g4, NX_GATE_KIND_SUB)
62 let r4_cells: i64 = g4.n_cells
63
64 // research frontier: Goldschmidt ~ ceil(log2 W)
65 var gold: i64 = 0; var p: i64 = 1
66 while p < W { p = p * 2; gold = gold + 1 }
67
68 _puts("DIVIDER RACE (stages = latency; cells = area) vs the research ladder, W=63:\n" as *u8)
69 _puts(" ours radix-2 : stages=" as *u8); _emit_num(r2_stages); _puts(" cells=" as *u8); _emit_num(r2_cells); _nl()
70 _puts(" ours radix-4 : stages=" as *u8); _emit_num(r4_stages); _puts(" cells=" as *u8); _emit_num(r4_cells); _nl()
71 _puts(" research frontier (Goldschmidt ~log2 W) stages=" as *u8); _emit_num(gold); _nl()
72 _puts(" VERDICT: radix-4 BEATS our radix-2 on latency (" as *u8); _emit_num(r4_stages); _puts(" vs " as *u8); _emit_num(r2_stages)
73 _puts(" stages); BUT the frontier (" as *u8); _emit_num(gold); _puts(") is faster -> we are LAPPED ~5x = NOT competitive. Scale: competitive=within 99%, win=better, S-class=better-by-as-much-as-possible (to the physics/math limit). DON'T-MOVE-UP: iterate this car (Goldschmidt/Newton) before any new car.\n" as *u8)
74
75 // machine-readable summary line
76 _emit_num(r2_stages); _emit_num(r2_cells); _emit_num(r4_stages); _emit_num(r4_cells); _emit_num(gold); _nl()
77 // sanity (FAIL LOUD on a measurement error): radix-4 must have fewer stages than radix-2,
78 // and both must be > the frontier (else our measurement is wrong).
79 if r4_stages >= r2_stages { sys_exit(1); return 1 }
80 if r2_stages <= gold { sys_exit(2); return 2 }
81 sys_exit(0); return 0
82}