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}