code wiki / (root) / nx_gtm_build.nx

nx_gtm_build.nx source

↩ module page · 129 lines · 4569 B

1// nx_gtm_build.nx -- GO-TO-MARKET / BUILD PLAN. Turns the BOM's parts into 2// an ORDERED assembly plan: the steps, durations, and precedence constraints 3// (what must be done before what). Computes the build CRITICAL PATH -- the 4// longest dependency chain, i.e. the minimum build time with unlimited 5// parallel hands -- so the bottleneck is explicit and the parallel saving is 6// quantified. (Named nx_gtm_build to avoid the existing nx_assembly CAD 7// exploded-view engine + nx_build_plan printer scheduler.) 8// 9// INTEGER-EXACT. Durations in minutes. Step ids are in topological orde 10// (every prerequisite has a lower id), so the earliest-finish of each step is 11// a single forward pass: ef(i) = duration(i) + max(ef of its prerequisites). 12// Instantiated for the water AWG bench prototype. 13// 14// THE exceed: the build schedule + its bottleneck are COMPUTED from the 15// precedence DAG, not sketched -- the 4-hour enclosure print is the critical 16// path, so it should be pre-printed or started first. 17// 18// grounded: critical_path_method + assembly_line_precedence + design_for_assembly 19// genealogy_id: assembly_build_plan + nishi_go_to_market 20 21import "nx_syscalls.nx" 22 23// ===== Build steps (topological order) ============================ 24 25const GB_PRINT_ENCLOSURE: i64 = 0 26const GB_COLD_STACK: i64 = 1 // peltier + heatsink + cold plate 27const GB_MOUNT_FANS: i64 = 2 28const GB_COLLECTION: i64 = 3 // tray + tubing + pump + tank 29const GB_TREATMENT: i64 = 4 // UV-C + carbon 30const GB_MINERAL: i64 = 5 31const GB_WIRE_CONTROL: i64 = 6 // MCU + sensors + PSU + wiring 32const GB_INTEGRATE: i64 = 7 // mount all subsystems in the enclosure 33const GB_LEAK_TEST: i64 = 8 34const GB_POWER_ON_TEST: i64 = 9 35const GB_N: i64 = 10 36 37func gb_count() -> i64 { 38 return GB_N 39} 40 41// Duration of each step (minutes). 42func gb_duration(id: i64) -> i64 { 43 if id == GB_PRINT_ENCLOSURE { return 240 } // the 3D print (long pole) 44 if id == GB_COLD_STACK { return 30 } 45 if id == GB_MOUNT_FANS { return 15 } 46 if id == GB_COLLECTION { return 40 } 47 if id == GB_TREATMENT { return 25 } 48 if id == GB_MINERAL { return 15 } 49 if id == GB_WIRE_CONTROL { return 45 } 50 if id == GB_INTEGRATE { return 60 } 51 if id == GB_LEAK_TEST { return 20 } 52 if id == GB_POWER_ON_TEST { return 30 } 53 return 0 54} 55 56// The `slot`-th prerequisite of a step (up to 4), or -1 if none. 57func gb_prereq(id: i64, slot: i64) -> i64 { 58 if id == GB_MOUNT_FANS { if slot == 0 { return GB_COLD_STACK } } 59 if id == GB_TREATMENT { if slot == 0 { return GB_COLLECTION } } 60 if id == GB_MINERAL { if slot == 0 { return GB_TREATMENT } } 61 if id == GB_INTEGRATE { 62 if slot == 0 { return GB_PRINT_ENCLOSURE } 63 if slot == 1 { return GB_MOUNT_FANS } 64 if slot == 2 { return GB_MINERAL } 65 if slot == 3 { return GB_WIRE_CONTROL } 66 } 67 if id == GB_LEAK_TEST { if slot == 0 { return GB_INTEGRATE } } 68 if id == GB_POWER_ON_TEST { if slot == 0 { return GB_LEAK_TEST } } 69 return 0 - 1 70} 71 72// Total work if done serially (sum of all step durations). 73func gb_total_time() -> i64 { 74 var t: i64 = 0 75 var i: i64 = 0 76 while i < GB_N { 77 t = t + gb_duration(i) 78 i = i + 1 79 } 80 return t 81} 82 83// Critical-path length = max earliest-finish over the precedence DAG 84// (minimum build time with parallel hands). 85func gb_critical_path() -> i64 { 86 let ef: *i64 = sys_mmap(GB_N * 8) as *i64 87 var i: i64 = 0 88 while i < GB_N { 89 var maxpre: i64 = 0 90 var s: i64 = 0 91 while s < 4 { 92 let pre: i64 = gb_prereq(i, s) 93 if pre >= 0 { if ef[pre] > maxpre { maxpre = ef[pre] } } 94 s = s + 1 95 } 96 ef[i] = gb_duration(i) + maxpre 97 i = i + 1 98 } 99 var m: i64 = 0 100 i = 0 101 while i < GB_N { 102 if ef[i] > m { m = ef[i] } 103 i = i + 1 104 } 105 return m 106} 107 108// Earliest finish of one step (same forward pass, returns ef[target]). 109func gb_earliest_finish(target: i64) -> i64 { 110 let ef: *i64 = sys_mmap(GB_N * 8) as *i64 111 var i: i64 = 0 112 while i < GB_N { 113 var maxpre: i64 = 0 114 var s: i64 = 0 115 while s < 4 { 116 let pre: i64 = gb_prereq(i, s) 117 if pre >= 0 { if ef[pre] > maxpre { maxpre = ef[pre] } } 118 s = s + 1 119 } 120 ef[i] = gb_duration(i) + maxpre 121 i = i + 1 122 } 123 return ef[target] 124} 125 126// Time saved by building in parallel vs serially. 127func gb_parallel_savings() -> i64 { 128 return gb_total_time() - gb_critical_path() 129}