code wiki / _hdl_build / nx_energy_probe_test.nx

nx_energy_probe_test.nx source

↩ module page · 89 lines · 4362 B

1// nx_energy_probe_test.nx -- exercise the real-hardware probe end to end: detect 2// the node's energy source, measure a fixed workload's real consumption in that 3// source's native unit, and report HONESTLY (joules only from a joule source; 4// cycles labeled as the speed proxy when no power sensor exists). This is the 5// "real hardware, any hardware" half of the triangle -- on a RAPL/battery node it 6// yields real energy; on a bare node it falls to the universal cycle counter. 7// 8// Known answer: detection returns a usable source (never NONE) AND the live 9// counter advances over real work. exit 0. 10 11import "nx_energy_probe.nx" 12 13const EP_ITERS: i64 = 2000000 14 15// a non-eliminable compute workload (acc fed back + consumed by the caller). 16func ep_workload(seed: i64) -> i64 { 17 var acc: i64 = seed | 1 18 var i: i64 = 0 19 while i < EP_ITERS { acc = acc * 3; acc = acc | 1; i = i + 1 } 20 return acc 21} 22 23func _emit(name: *u8, v: i64) -> i64 { 24 var n: i64 = 0; while name[n] != (0 as u8) { n = n + 1 } sys_write(1, name, n) 25 let b: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { m = 0 - m } 26 let t: *u8 = sys_mmap(28); var k: i64 = 0 27 if m == 0 { t[0] = 48; k = 1 } 28 while m > 0 { t[k] = 48 + (m % 10); m = m / 10; k = k + 1 } 29 var i: i64 = 0; while i < k { b[i] = t[k - 1 - i]; i = i + 1 } 30 b[k] = 10; sys_write(1, b, k + 1); return 0 31} 32func _puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 33 34func main() -> i64 { 35 _puts("=== REAL-HARDWARE ENERGY PROBE (any hardware, graceful degradation) ===\n" as *u8) 36 let src: i64 = ep_detect() 37 _puts(" source: " as *u8); _puts(ep_src_name(src)); _puts("\n" as *u8) 38 _emit(" workload ops : " as *u8, EP_ITERS) 39 40 if ep_is_power_source(src) == 1 { 41 // BATTERY DISCHARGING: integrate instantaneous power over measured time -> 42 // real microjoules (works even for a short workload the uWh gauge can't see). 43 let p0: i64 = ep_psu_power_uw() 44 let t0: i64 = sys_now_us() 45 let r: i64 = ep_workload(7) 46 let t1: i64 = sys_now_us() 47 let p1: i64 = ep_psu_power_uw() 48 if r == 0 - 1 { sys_write(1, "" as *u8, 0) } 49 let p_avg: i64 = (p0 + p1) / 2 // microwatts 50 let dt_us: i64 = t1 - t0 // microseconds 51 let e_uj: i64 = p_avg * dt_us / 1000000 // uW * s = uJ 52 _emit(" measured power (uW) : " as *u8, p_avg) 53 _emit(" elapsed (us) : " as *u8, dt_us) 54 _emit(" REAL energy (uJ) : " as *u8, e_uj) 55 _puts(" -> joules from the node's own fuel-gauge (P x t); calibrates the\n" as *u8) 56 _puts(" gate-toggle model (nx_gate_energy) into joules for THIS silicon.\n" as *u8) 57 if dt_us <= 0 { sys_exit(3); return 3 } 58 sys_exit(0); return 0 59 } 60 61 // ACCUMULATING sources (RAPL microjoules / CYCLE cycles): read before/after. 62 let e0: i64 = ep_read(src) 63 let r: i64 = ep_workload(7) 64 let e1: i64 = ep_read(src) 65 if r == 0 - 1 { sys_write(1, "" as *u8, 0) } 66 let delta: i64 = e1 - e0 67 68 if ep_is_joule_source(src) == 1 { 69 _emit(" REAL energy (uJ) : " as *u8, delta) // RAPL accumulating 70 _puts(" -> joules measured from the node's own sensor; calibrates the\n" as *u8) 71 _puts(" gate-toggle model into joules for THIS silicon.\n" as *u8) 72 } else { 73 if src == ENERGY_SRC_I2C { 74 _puts(" I2C bus present; INA219 register read streams as a later seed piece.\n" as *u8) 75 } 76 if ep_psu_present() == 1 { 77 _puts(" (a battery is present but CHARGING/on-AC -> it cannot attribute\n" as *u8) 78 _puts(" CPU energy; need RAPL or a discharging pack. Falling to cycles.)\n" as *u8) 79 } 80 _emit(" REAL cycle delta : " as *u8, delta) // rdtsc/rdcycle: real speed 81 _puts(" -> no joule sensor active here: cycles are the speed proxy and the\n" as *u8) 82 _puts(" gate-activity model is the energy currency. Joules NOT fabricated.\n" as *u8) 83 } 84 85 // GATE: a usable source AND, on the universal floor, the counter really advanced. 86 if src == ENERGY_SRC_NONE { sys_exit(1); return 1 } 87 if src == ENERGY_SRC_CYCLE { if delta <= 0 { sys_exit(2); return 2 } } 88 sys_exit(0); return 0 89}