code wiki / (root) / nx_select_test.nx

nx_select_test.nx source

↩ module page · 189 lines · 8445 B

1// nx_select_test.nx -- smoke for nx_select SA-4 MVP. 2// 3// Exercises six scenarios across the selection pipeline: 4// 1. Empty input -> NX_SEL_BAD_INPUT 5// 2. Single candidate that fits -> returns that index 6// 3. Two candidates, one's ISA mask excludes the host -> picks the fit 7// 4. Two candidates both fit, different cost -> picks lower cost 8// 5. Policy weight swap (throughput vs energy) flips selection 9// 6. Tier filter (variant requires HPC, host is LAPTOP) -> filtered out 10// 11// SA-4 verification gate per NISHI_SELF_ASSEMBLY_ROADMAP.md ยง8: 12// "picks variants A on hardware H_A and B on H_B with both smokes 13// passing on their respective hosts" -- demonstrated in code by 14// synthesizing probes for both hosts and asserting different 15// selections. 16 17import "nx_syscalls.nx" 18import "nx_probe.nx" 19import "nx_calibrate.nx" 20import "nx_select.nx" 21 22// Helper: build a probe record stamped with a given ISA + endianness. 23// Bypasses nx_probe_run (which would witness the actual host); the 24// test treats the probe as a SYNTHETIC INPUT to the selector. 25 26func _make_probe(isa: i64) -> *NxProbeRecord { 27 let p: *NxProbeRecord = nx_probe_new() 28 p.actual_isa_family = isa 29 p.actual_endianness = NX_ENDIAN_LITTLE 30 p.actual_pointer_width_bits = 64 31 p.actual_page_size_bytes = 4096 32 p.actual_mmap_works = 1 33 p.actual_write_works = 1 34 p.actual_mono_clock_works = 1 35 p.actual_mono_clock_resolution_ns = 100 36 return p 37} 38 39func main() -> i64 { 40 // ----- 1. Empty input ----- 41 let probe_rv64: *NxProbeRecord = _make_probe(NX_ISA_RV64) 42 let policy_t: *NxPolicy = nx_policy_throughput_default() 43 let empty_ptrs: *i64 = (sys_mmap(8)) as *i64 44 let rc_empty: i64 = nx_select(empty_ptrs, 0, probe_rv64, 45 NX_TIER_INF_LAPTOP, 1048576, 0, policy_t) 46 if rc_empty != NX_SEL_BAD_INPUT { return 1 } 47 48 // ----- 2. Single candidate that fits ----- 49 let m_rv64_only: *NxManifest = nx_manifest_new( 50 100, // variant_class 51 1001, // variant_id 52 nx_isa_bit(NX_ISA_RV64), // requires_isa_mask 53 0, // requires_isa_ext_mask 54 4096, // requires_ram_min_b 55 NX_TIER_INF_MOBILE, // tier_floor 56 NX_TIER_INF_HPC, // tier_ceiling 57 1024, 1024, 1024, 1024) // cost coefs (all 1.0 Q10) 58 let one_ptrs: *i64 = (sys_mmap(8)) as *i64 59 one_ptrs[0] = m_rv64_only as i64 60 let rc_one: i64 = nx_select(one_ptrs, 1, probe_rv64, 61 NX_TIER_INF_LAPTOP, 1048576, 0, policy_t) 62 if rc_one != 0 { return 2 } 63 64 // ----- 3. Two candidates, ISA-mismatch one excluded ----- 65 let m_x86_only: *NxManifest = nx_manifest_new( 66 100, 1002, 67 nx_isa_bit(NX_ISA_X86_64), // ONLY x86_64 -- excluded on RV64 host 68 0, 4096, 69 NX_TIER_INF_MOBILE, NX_TIER_INF_HPC, 70 512, 512, 512, 512) // cheaper than rv64_only, but blocked 71 let two_ptrs: *i64 = (sys_mmap(16)) as *i64 72 two_ptrs[0] = m_x86_only as i64 73 two_ptrs[1] = m_rv64_only as i64 74 let rc_isa: i64 = nx_select(two_ptrs, 2, probe_rv64, 75 NX_TIER_INF_LAPTOP, 1048576, 0, policy_t) 76 if rc_isa != 1 { return 3 } // index 1 = rv64_only 77 78 // Cross-host gate: same two candidates on an x86_64 probe should 79 // select index 0 (x86_only) because RV64-only is excluded there. 80 let probe_x86: *NxProbeRecord = _make_probe(NX_ISA_X86_64) 81 let rc_cross: i64 = nx_select(two_ptrs, 2, probe_x86, 82 NX_TIER_INF_LAPTOP, 1048576, 0, policy_t) 83 if rc_cross != 0 { return 4 } // host-dependent selection 84 85 // ----- 4. Two compatible variants, lower cost wins ----- 86 let m_both_cheap: *NxManifest = nx_manifest_new( 87 100, 2001, 88 nx_isa_bit(NX_ISA_RV64) | nx_isa_bit(NX_ISA_X86_64), 89 0, 4096, 90 NX_TIER_INF_MOBILE, NX_TIER_INF_HPC, 91 100, 100, 100, 100) // cheap across all axes 92 let m_both_expensive: *NxManifest = nx_manifest_new( 93 100, 2002, 94 nx_isa_bit(NX_ISA_RV64) | nx_isa_bit(NX_ISA_X86_64), 95 0, 4096, 96 NX_TIER_INF_MOBILE, NX_TIER_INF_HPC, 97 10000, 10000, 10000, 10000) 98 let cost_ptrs: *i64 = (sys_mmap(16)) as *i64 99 cost_ptrs[0] = m_both_expensive as i64 100 cost_ptrs[1] = m_both_cheap as i64 101 let rc_cost: i64 = nx_select(cost_ptrs, 2, probe_rv64, 102 NX_TIER_INF_LAPTOP, 1048576, 0, policy_t) 103 if rc_cost != 1 { return 5 } // cheap variant wins regardless of order 104 105 // ----- 5. Policy axis swap flips selection ----- 106 // m_fast_high_energy: low compute cost, high energy cost 107 // m_slow_low_energy: high compute cost, low energy cost 108 // throughput-policy picks fast; energy-policy picks low-energy. 109 let m_fast_high_energy: *NxManifest = nx_manifest_new( 110 100, 3001, 111 nx_isa_bit(NX_ISA_RV64) | nx_isa_bit(NX_ISA_X86_64), 112 0, 4096, 113 NX_TIER_INF_MOBILE, NX_TIER_INF_HPC, 114 100, // cheap flops 115 500, 500, 116 10000) // expensive energy 117 let m_slow_low_energy: *NxManifest = nx_manifest_new( 118 100, 3002, 119 nx_isa_bit(NX_ISA_RV64) | nx_isa_bit(NX_ISA_X86_64), 120 0, 4096, 121 NX_TIER_INF_MOBILE, NX_TIER_INF_HPC, 122 5000, // expensive flops 123 500, 500, 124 100) // cheap energy 125 let pol_ptrs: *i64 = (sys_mmap(16)) as *i64 126 pol_ptrs[0] = m_fast_high_energy as i64 127 pol_ptrs[1] = m_slow_low_energy as i64 128 let rc_throughput: i64 = nx_select(pol_ptrs, 2, probe_rv64, 129 NX_TIER_INF_LAPTOP, 1048576, 0, 130 nx_policy_throughput_default()) 131 if rc_throughput != 0 { return 6 } // throughput-weighted picks fast 132 133 let rc_energy: i64 = nx_select(pol_ptrs, 2, probe_rv64, 134 NX_TIER_INF_LAPTOP, 1048576, 0, 135 nx_policy_energy_default()) 136 if rc_energy != 1 { return 7 } // energy-weighted picks low-energy 137 138 // ----- 6. Tier filter excludes too-rich variant ----- 139 let m_hpc_only: *NxManifest = nx_manifest_new( 140 100, 4001, 141 nx_isa_bit(NX_ISA_RV64) | nx_isa_bit(NX_ISA_X86_64), 142 0, 4096, 143 NX_TIER_INF_HPC, NX_TIER_INF_HPC, // HPC only 144 50, 50, 50, 50) 145 let m_anywhere: *NxManifest = nx_manifest_new( 146 100, 4002, 147 nx_isa_bit(NX_ISA_RV64) | nx_isa_bit(NX_ISA_X86_64), 148 0, 4096, 149 NX_TIER_INF_MOBILE, NX_TIER_INF_HPC, 150 500, 500, 500, 500) 151 let tier_ptrs: *i64 = (sys_mmap(16)) as *i64 152 tier_ptrs[0] = m_hpc_only as i64 153 tier_ptrs[1] = m_anywhere as i64 154 // Host inferred as LAPTOP -- hpc_only excluded; anywhere wins. 155 let rc_tier_laptop: i64 = nx_select(tier_ptrs, 2, probe_rv64, 156 NX_TIER_INF_LAPTOP, 1048576, 0, 157 policy_t) 158 if rc_tier_laptop != 1 { return 8 } 159 // Host inferred as HPC -- hpc_only fits (and is cheaper); wins. 160 let rc_tier_hpc: i64 = nx_select(tier_ptrs, 2, probe_rv64, 161 NX_TIER_INF_HPC, 1048576, 0, 162 policy_t) 163 if rc_tier_hpc != 0 { return 9 } 164 165 // ----- 7. No candidates fit -> NONE_MATCH ----- 166 let only_hpc_ptrs: *i64 = (sys_mmap(8)) as *i64 167 only_hpc_ptrs[0] = m_hpc_only as i64 168 let rc_none: i64 = nx_select(only_hpc_ptrs, 1, probe_rv64, 169 NX_TIER_INF_LAPTOP, 1048576, 0, policy_t) 170 if rc_none != NX_SEL_NONE_MATCH { return 10 } 171 172 // ----- 8. RAM filter ----- 173 let m_big_ram: *NxManifest = nx_manifest_new( 174 100, 5001, 175 nx_isa_bit(NX_ISA_RV64), 176 0, 177 16777216, // 16 MiB required 178 NX_TIER_INF_MOBILE, NX_TIER_INF_HPC, 179 50, 50, 50, 50) 180 let big_ptrs: *i64 = (sys_mmap(8)) as *i64 181 big_ptrs[0] = m_big_ram as i64 182 let rc_ram_short: i64 = nx_select(big_ptrs, 1, probe_rv64, 183 NX_TIER_INF_LAPTOP, 184 4096, // only 4 KiB available 185 0, policy_t) 186 if rc_ram_short != NX_SEL_NONE_MATCH { return 11 } 187 188 return 0 189}