code wiki / _hdl_build / nx_self_measure_cost.nx
nx_self_measure_cost.nx source
↩ module page · 53 lines · 2601 B
1// nx_self_measure_cost.nx -- BUILD OUR OWN cost data, on whatever chip the seed
2// lands on. uops.info only characterizes Intel; this measures THIS silicon directly
3// with rdtsc/rdcycle -- so a sovereign RV64 core, an ARM garden sensor, or a
4// throttled/damaged unit each get a REAL profile uops.info never had. The node
5// times dependent op-chains (latency) and normalizes to add. This is the seed
6// growing to meet its hardware's measured reality (Cardinal: optimize to THIS chip).
7
8import "nx_syscalls.nx"
9const SM_MAGIC_3750763034362895579: i64 = 3750763034362895579
10const SM_MAGIC_1099511628211: i64 = 1099511628211
11
12const SM_ITERS: i64 = 2000000
13
14// each loop is a DEPENDENT chain so the timing reflects the op's real latency, and
15// the fed-back accumulator can't be optimized away.
16func sm_add() -> i64 { let t0: i64 = __rdtsc(); var a: i64 = 7; var i: i64 = 0; while i < SM_ITERS { a = a + i; i = i + 1 } let t1: i64 = __rdtsc(); if a == 0 - 1 { sys_write(1, "" as *u8, 0) } return t1 - t0 }
17func sm_mul() -> i64 { let t0: i64 = __rdtsc(); var a: i64 = 7; var i: i64 = 0; while i < SM_ITERS { a = a * 3; a = a | 1; i = i + 1 } let t1: i64 = __rdtsc(); if a == 0 - 1 { sys_write(1, "" as *u8, 0) } return t1 - t0 }
18func sm_shl() -> i64 { let t0: i64 = __rdtsc(); var a: i64 = 7; var i: i64 = 0; while i < SM_ITERS { a = a << 1; a = a | 1; i = i + 1 } let t1: i64 = __rdtsc(); if a == 0 - 1 { sys_write(1, "" as *u8, 0) } return t1 - t0 }
19
20// profile this chip -> out[0]=add, out[1]=mul, out[2]=shl (cycles/op x100, add=100).
21// best-of-3 to cut scheduler noise.
22func sm_profile(out: *i64) -> i64 {
23 var ba: i64 = sm_add(); var bm: i64 = sm_mul(); var bs: i64 = sm_shl()
24 var r: i64 = 0
25 while r < 2 {
26 let a: i64 = sm_add(); if a < ba { ba = a }
27 let m: i64 = sm_mul(); if m < bm { bm = m }
28 let s: i64 = sm_shl(); if s < bs { bs = s }
29 r = r + 1
30 }
31 if ba <= 0 { ba = 1 }
32 out[0] = 100
33 out[1] = (bm * 100) / ba
34 out[2] = (bs * 100) / ba
35 return 0
36}
37
38// SANITY (the contribution trust check): a real chip NEVER has multiply cheaper
39// than add. A profile claiming otherwise is impossible -> poisoned/buggy -> rejected.
40func sm_sane(p: *i64) -> i64 {
41 if p[0] <= 0 { return 0 }
42 if p[1] < p[0] { return 0 }
43 if p[2] <= 0 { return 0 }
44 return 1
45}
46
47// FNV-1a over the profile -> integrity key for a contributed measurement.
48func sm_hash(p: *i64, n: i64) -> i64 {
49 var h: i64 = 0 - SM_MAGIC_3750763034362895579
50 var i: i64 = 0
51 while i < n { h = h ^ p[i]; h = h * SM_MAGIC_1099511628211; i = i + 1 }
52 return h
53}