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}