code wiki / (root) / nx_select_joint_chain_test.nx

nx_select_joint_chain_test.nx source

↩ module page · 202 lines · 9400 B

1// nx_select_joint_chain_test.nx -- smoke for nx_select_joint_chain 2// SA-5 N-node linear chain selector. 3// 4// Exercises: 5// 1. Degenerate N=1 chain falls back to single-class selection 6// 2. N=0 -> BAD_INPUT 7// 3. N=3 linear chain A -> B -> C demonstrates the LOAD-BEARING 8// property: middle node forced into non-locally-optimal variant 9// so the chain composes 10// 4. N=4 linear chain A -> B -> C -> D where the optimal pick at 11// each interior node depends on BOTH neighbors 12// 5. No-feasible-chain detection (incompatible layouts in any pair) 13// 14// SA-5 remainder verification gate per NISHI_SELF_ASSEMBLY_ROADMAP.md 15// ยง8: "DAG composition smoke -- same algorithm, two layout choices, 16// joint solver picks bit-coherent layouts across nodes". 17 18import "nx_syscalls.nx" 19import "nx_probe.nx" 20import "nx_calibrate.nx" 21import "nx_select.nx" 22import "nx_select_joint.nx" 23 24func _make_probe_rv64() -> *NxProbeRecord { 25 let p: *NxProbeRecord = nx_probe_new() 26 p.actual_isa_family = NX_ISA_RV64 27 p.actual_endianness = NX_ENDIAN_LITTLE 28 p.actual_pointer_width_bits = 64 29 p.actual_page_size_bytes = 4096 30 p.actual_mmap_works = 1 31 p.actual_write_works = 1 32 p.actual_mono_clock_works = 1 33 return p 34} 35 36// Helper: build a manifest with given variant_id, cost, in_layout, 37// out_layout. All other fields default-compatible with RV64. 38func _mk(variant_id: i64, cost: i64, in_layout: i64, out_layout: i64) -> *NxManifest { 39 let m: *NxManifest = nx_manifest_new( 40 100, variant_id, 41 nx_isa_bit(NX_ISA_RV64), 42 0, 4096, 43 NX_TIER_INF_MOBILE, NX_TIER_INF_HPC, 44 cost, 0, 0, 0) 45 nx_manifest_set_layout(m, in_layout, out_layout) 46 return m 47} 48 49func main() -> i64 { 50 let probe: *NxProbeRecord = _make_probe_rv64() 51 let policy: *NxPolicy = nx_policy_throughput_default() 52 53 // ----- 1. BAD_INPUT for n_nodes <= 0 ----- 54 let empty_ptrs: *i64 = (sys_mmap(8)) as *i64 55 let empty_out: *i64 = (sys_mmap(8)) as *i64 56 let rc_empty: i64 = nx_select_joint_chain(empty_ptrs, 0, probe, 57 NX_TIER_INF_LAPTOP, 1048576, 0, 58 policy, empty_out) 59 if rc_empty != NX_SEL_JOINT_BAD_INPUT { return 1 } 60 61 // ----- 2. Degenerate N=1 chain falls back to single-class ----- 62 let n1_m_cheap: *NxManifest = _mk(1001, 100, NX_LAYOUT_OPAQUE_PASS, NX_LAYOUT_OPAQUE_PASS) 63 let n1_m_exp: *NxManifest = _mk(1002, 500, NX_LAYOUT_OPAQUE_PASS, NX_LAYOUT_OPAQUE_PASS) 64 let n1_ptrs: *i64 = (sys_mmap(16)) as *i64 65 n1_ptrs[0] = n1_m_cheap as i64 66 n1_ptrs[1] = n1_m_exp as i64 67 let n1_node: *NxJointNode = nx_joint_node_new(100, n1_ptrs, 2) 68 let n1_nodes_arr: *i64 = (sys_mmap(8)) as *i64 69 n1_nodes_arr[0] = n1_node as i64 70 let n1_out: *i64 = (sys_mmap(8)) as *i64 71 let rc_n1: i64 = nx_select_joint_chain(n1_nodes_arr, 1, probe, 72 NX_TIER_INF_LAPTOP, 1048576, 0, 73 policy, n1_out) 74 if rc_n1 != NX_SEL_JOINT_OK { return 2 } 75 if n1_out[0] != 0 { return 3 } // n1_m_cheap wins 76 77 // ----- 3. N=3 chain with NON-LOCAL middle pick ----- 78 // A produces ROW or COL. B consumes either ROW or COL, produces 79 // the SAME shape (in == out). C consumes COL only. 80 // 81 // Per-node argmin: A_cheap (cheapest), B_cheap_row (cheapest), 82 // C_only_col_cheap (only option). Chain: A.out=ROW -> 83 // B_cheap_row.in=ROW OK -> B_cheap_row.out=ROW -> C.in=COL FAIL. 84 // 85 // Joint argmin: must route through a COL middle. Either 86 // (A_row, B_row_to_col_transform, C_col) -- but we don't have 87 // a transform variant yet, so the chain must pick: 88 // (A_medium_col, B_col_pass, C_col_cheap) where each component 89 // is layout-consistent. 90 let a_cheap_row: *NxManifest = _mk(2001, 100, NX_LAYOUT_OPAQUE_PASS, NX_LAYOUT_ROW_MAJOR) 91 let a_med_col: *NxManifest = _mk(2002, 300, NX_LAYOUT_OPAQUE_PASS, NX_LAYOUT_COL_MAJOR) 92 let b_cheap_row: *NxManifest = _mk(2101, 100, NX_LAYOUT_ROW_MAJOR, NX_LAYOUT_ROW_MAJOR) 93 let b_med_col: *NxManifest = _mk(2102, 200, NX_LAYOUT_COL_MAJOR, NX_LAYOUT_COL_MAJOR) 94 let c_col_cheap: *NxManifest = _mk(2201, 100, NX_LAYOUT_COL_MAJOR, NX_LAYOUT_OPAQUE_PASS) 95 96 let a_ptrs: *i64 = (sys_mmap(16)) as *i64 97 a_ptrs[0] = a_cheap_row as i64 98 a_ptrs[1] = a_med_col as i64 99 let b_ptrs: *i64 = (sys_mmap(16)) as *i64 100 b_ptrs[0] = b_cheap_row as i64 101 b_ptrs[1] = b_med_col as i64 102 let c_ptrs: *i64 = (sys_mmap(8)) as *i64 103 c_ptrs[0] = c_col_cheap as i64 104 105 let a_node: *NxJointNode = nx_joint_node_new(100, a_ptrs, 2) 106 let b_node: *NxJointNode = nx_joint_node_new(200, b_ptrs, 2) 107 let c_node: *NxJointNode = nx_joint_node_new(300, c_ptrs, 1) 108 109 let chain3_nodes: *i64 = (sys_mmap(24)) as *i64 110 chain3_nodes[0] = a_node as i64 111 chain3_nodes[1] = b_node as i64 112 chain3_nodes[2] = c_node as i64 113 114 let chain3_out: *i64 = (sys_mmap(24)) as *i64 115 let rc3: i64 = nx_select_joint_chain(chain3_nodes, 3, probe, 116 NX_TIER_INF_LAPTOP, 1048576, 0, 117 policy, chain3_out) 118 if rc3 != NX_SEL_JOINT_OK { return 4 } 119 120 // Expected joint solution: (a_med_col=1, b_med_col=1, c_col_cheap=0). 121 // Total = 300 + 200 + 100 = 600 vs. (a_cheap_row, b_cheap_row, ???) = 122 // no compatible C -> infeasible. Other compatible chain: 123 // (a_med_col, b_med_col, c_col_cheap) = 600 ONLY feasible. 124 if chain3_out[0] != 1 { return 5 } 125 if chain3_out[1] != 1 { return 6 } 126 if chain3_out[2] != 0 { return 7 } 127 128 // Verify layout compatibility across the picked chain. 129 let pa: *NxManifest = a_ptrs[chain3_out[0]] as *NxManifest 130 let pb: *NxManifest = b_ptrs[chain3_out[1]] as *NxManifest 131 let pc: *NxManifest = c_ptrs[chain3_out[2]] as *NxManifest 132 if nx_layout_compatible(pa.out_layout, pb.in_layout) != 1 { return 8 } 133 if nx_layout_compatible(pb.out_layout, pc.in_layout) != 1 { return 9 } 134 135 // Verify variant IDs survived. 136 if pa.variant_id != 2002 { return 10 } 137 if pb.variant_id != 2102 { return 11 } 138 if pc.variant_id != 2201 { return 12 } 139 140 // ----- 4. N=4 chain where every interior node is forced ----- 141 // A -> B -> C -> D. All four must agree on COL. 142 let d_col_cheap: *NxManifest = _mk(2301, 100, NX_LAYOUT_COL_MAJOR, NX_LAYOUT_OPAQUE_PASS) 143 let d_ptrs: *i64 = (sys_mmap(8)) as *i64 144 d_ptrs[0] = d_col_cheap as i64 145 let d_node: *NxJointNode = nx_joint_node_new(400, d_ptrs, 1) 146 147 let chain4_nodes: *i64 = (sys_mmap(32)) as *i64 148 chain4_nodes[0] = a_node as i64 149 chain4_nodes[1] = b_node as i64 150 chain4_nodes[2] = b_node as i64 // reuse b_node candidates 151 chain4_nodes[3] = d_node as i64 152 153 let chain4_out: *i64 = (sys_mmap(32)) as *i64 154 let rc4: i64 = nx_select_joint_chain(chain4_nodes, 4, probe, 155 NX_TIER_INF_LAPTOP, 1048576, 0, 156 policy, chain4_out) 157 if rc4 != NX_SEL_JOINT_OK { return 13 } 158 // All four nodes must pick the COL-consistent variant. 159 if chain4_out[0] != 1 { return 14 } // a_med_col 160 if chain4_out[1] != 1 { return 15 } // b_med_col 161 if chain4_out[2] != 1 { return 16 } // b_med_col again 162 if chain4_out[3] != 0 { return 17 } // d_col_cheap 163 164 // ----- 5. No-feasible-chain detection ----- 165 // Force a chain where the first node produces ROW only and the 166 // second consumes COL only -- no compatible bridge. 167 let only_row_out: *NxManifest = _mk(3001, 100, NX_LAYOUT_OPAQUE_PASS, NX_LAYOUT_ROW_MAJOR) 168 let only_col_in: *NxManifest = _mk(3002, 100, NX_LAYOUT_COL_MAJOR, NX_LAYOUT_OPAQUE_PASS) 169 let row_only_ptrs: *i64 = (sys_mmap(8)) as *i64 170 row_only_ptrs[0] = only_row_out as i64 171 let col_only_ptrs: *i64 = (sys_mmap(8)) as *i64 172 col_only_ptrs[0] = only_col_in as i64 173 let row_node: *NxJointNode = nx_joint_node_new(100, row_only_ptrs, 1) 174 let col_node: *NxJointNode = nx_joint_node_new(200, col_only_ptrs, 1) 175 176 let infeasible_nodes: *i64 = (sys_mmap(16)) as *i64 177 infeasible_nodes[0] = row_node as i64 178 infeasible_nodes[1] = col_node as i64 179 let infeasible_out: *i64 = (sys_mmap(16)) as *i64 180 let rc_inf: i64 = nx_select_joint_chain(infeasible_nodes, 2, probe, 181 NX_TIER_INF_LAPTOP, 1048576, 0, 182 policy, infeasible_out) 183 if rc_inf != NX_SEL_JOINT_NO_FEASIBLE_PAIR { return 18 } 184 if infeasible_out[0] != -1 { return 19 } 185 if infeasible_out[1] != -1 { return 20 } 186 187 // ----- 6. Bad input gates ----- 188 let null_out: *i64 = (0 as i64) as *i64 189 let rc_null: i64 = nx_select_joint_chain(chain3_nodes, 3, probe, 190 NX_TIER_INF_LAPTOP, 1048576, 0, 191 policy, null_out) 192 if rc_null != NX_SEL_JOINT_BAD_INPUT { return 21 } 193 194 // Oversized N rejected. 195 let too_big_out: *i64 = (sys_mmap(8)) as *i64 196 let rc_too_big: i64 = nx_select_joint_chain(chain3_nodes, 999, probe, 197 NX_TIER_INF_LAPTOP, 1048576, 0, 198 policy, too_big_out) 199 if rc_too_big != NX_SEL_JOINT_BAD_INPUT { return 22 } 200 201 return 0 202}