code wiki / _hdl_build / nx_latency_metric_test.nx

nx_latency_metric_test.nx

buildroot/runtime/_hdl_build/nx_latency_metric_test.nx

11818 B206 linesdepth 10pulls 12 transitivereach 0 importersview sourcekind gate/proof
docsdependenciesstructsconstsfunctions

about

nx_latency_metric_test.nx -- proves the HONEST latency-metric organ and uses it to race three divider TOPOLOGIES at W=16: radix-2 (W stages), radix-4 (W/2 stages), and the scalar-equivalent Newton-Raphson reciprocal structure (~log W iterations of multiply-heavy work). WHAT THIS PROVES (FAIL LOUD on every leg): (1) The organ's UNIT metric matches the functional sim's implicit depth-1 model: on a tiny hand-built chain whose longest path is known by hand, nx_lat_unit returns exactly that hand-counted op-depth. (2) The HONEST metric does NOT treat a multiplier as depth-1: a single MUL cell costs 2*ceil(log2 W) gate levels, an ADD costs ceil(log2 W), a boolean costs 1 -- asserted directly against nx_lat_kind_weight, and asserted on a one-MUL chain whose honest depth > its unit depth. (3) THE RACE, told HONESTLY across WIDTH -- the trap, and where it flips. The SAME Newton topology is measured with a DEEP multiplier (the real nx_mul_wide 32-bit-limb schoolbook) and a SHALLOW one (single-cell Wallace model, 2*logW), at W=16 and W=64. The MEASURED honest critical paths are: W=16: radix-2=181 radix-4=139 Newton-deep=363 Newton-shallow=166 W=64: radix-2=967 radix-4=743 Newton-deep=709 Newton-shallow=320 So, honestly: - At SMALL width (W=16) the multiplicative method does NOT pay off: radix-4 wins; the DEEP-multiplier Newton is the WORST (363); and even the SHALLOW-multiplier Newton (166) still loses to radix-4 (139). The naive "log(W) multiplies beats W subtracts" LATENCY claim is FALSE here. - At LARGE width (W=64) the log(W) FRONTIER appears: BOTH Newton variants beat BOTH radix dividers (320 and 709 vs 743 and 967), because the radix dividers' stage count grows linearly in W while Newton's iteration count grows only ~log W. Ordering: shallow-Newton < deep-Newton < r4 < r2. - THE CROSSOVER is the headline: the SAME shallow-multiplier Newton goes from LOSING to radix-4 at W=16 to BEATING it at W=64. That measured sign- flip IS the multiplicative-divider latency win -- and the honest metric refuses to award it at a width where it is not real. Invariant independent of width + multiplier: radix-4 (W/2 stages) always beats radix-2 (W stages). All orderings are ASSERTED, not assumed. Known-answer lines (printed for the gate): four honest critical paths at W=16, then at W=64, then the kind-weight spot-checks. exit 0 iff all asserts hold. HONESTY SCOPE: the Newton network here is the algorithm's STRUCTURAL skeleton (the exact operator dependency chain of nx_alu_divider_newton.nx: normalize ->

dependencies 4 imports · 0 importers

nx_latency_metric.nx nx_alu_divider_r4.nx nx_mul_wide.nx nx_newton_struct.nx nx_latency_metric_test.nx

imports: nx_latency_metric.nxnx_alu_divider_r4.nxnx_mul_wide.nxnx_newton_struct.nx

imported by: nobody (leaf or entry point)

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main _mk_depth _mk_gsim div_op2 nx_lat_unit nx_lat_critical_path nx_gsim_kind_supported nx_lat_kind_weight nx_lat_log2_ceil nx_lat_honest nx_lat_critical_path ↻ nx_lat_log2_ceil ↻ nx_lat_kind_weight ↻ _measure _mk_gsim ↻ nx_div_synth nx_sink_init_mem nx_div_synth_sink nx_sink_const nx_hdl_wire nx_hdl_signal_alloc nx_sink_cell nx_hdl_wire ↻ sys_mmap nx_lat_honest ↻ nx_div_synth_r4 div_const div_op2 ↻ div_mux nx_newton_struct div_const ↻ div_op2 ↻ nx_newton_mulprod nx_mul_wide_synth nx_sink_init_mem ↻ nx_mul_wide_sink nx_sink_const ↻ nx_sink_cell ↻ div_op2 ↻ div_mux ↻

structs

none

consts

none

functions

54func _emit_num(v: i64) -> i64
called by 1: main
62func _nl() -> i64 { let z: *u8 = sys_mmap(2); z[0] = 10; sys_write(1, z, 1); return 0 }
called by 1: main
65func _mk_gsim(ninputs: i64) -> *NxGsim
called by 2: _measuremain
74func _mk_depth() -> *i64 { return sys_mmap(8192 * 8) as *i64 }
called by 1: main
79func _measure(W: i64, iters: i64, depth: *i64, out: *i64) -> i64
102func main() -> i64