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}