code wiki / _hdl_build / nx_pcb_drc.nx
nx_pcb_drc.nx source
↩ module page · 43 lines · 2294 B
1// nx_pcb_drc.nx -- LIB: PCB design-rule-check DIGITAL TWIN. Verifies a routed board against REAL fabrication rules
2// in REAL units (mils) -- a twin of the fab's own DRC, so "passes DRC" means "really manufacturable at this fab class".
3// Rules (data-driven, rule #11): min copper-to-copper CLEARANCE and min trace WIDTH. A standard 2-layer fab is 6/6 mil;
4// advanced is 4/4. The edge-to-edge gap between two orthogonally-adjacent traces is (pitch - trace_width) mils; if that
5// is below the clearance rule the board shorts/bridges in real fab -> a violation. A trace narrower than the width rule
6// can't be etched reliably -> a violation. Composes the routed grid from nx_pcb_autoroute. never-brick #26: pure
7// arithmetic, bounded, deterministic. license_tier: ORIGINAL
8import "nx_syscalls.nx"
9
10// real fab classes (mils): standard 2-layer = 6/6 (clearance/width). Not magic numbers -- the real manufacturable limits.
11const FAB_STD_CLEAR_MIL: i64 = 6
12const FAB_STD_WIDTH_MIL: i64 = 6
13
14// count design-rule violations on the routed board (usedby[c] = net id per grid cell, -1 = empty).
15// pitch_mils = grid step, tw_mils = trace width. Returns total violations (width-rule + clearance-rule).
16func drc_check(usedby: *i64, W: i64, H: i64, pitch_mils: i64, tw_mils: i64, min_clear_mils: i64, min_width_mils: i64) -> i64 {
17 var viol: i64 = 0
18 if tw_mils < min_width_mils { viol = viol + 1 } // width rule (global)
19 let ortho_gap: i64 = pitch_mils - tw_mils // edge-to-edge gap for orthogonal adjacency
20 var cy: i64 = 0
21 while cy < H {
22 var cx: i64 = 0
23 while cx < W {
24 let c: i64 = cy*W + cx
25 let n: i64 = usedby[c]
26 if n >= 0 {
27 if cx + 1 < W {
28 let c2: i64 = cy*W + (cx+1)
29 let n2: i64 = usedby[c2]
30 if n2 >= 0 { if n2 != n { if ortho_gap < min_clear_mils { viol = viol + 1 } } }
31 }
32 if cy + 1 < H {
33 let c2: i64 = (cy+1)*W + cx
34 let n2: i64 = usedby[c2]
35 if n2 >= 0 { if n2 != n { if ortho_gap < min_clear_mils { viol = viol + 1 } } }
36 }
37 }
38 cx = cx + 1
39 }
40 cy = cy + 1
41 }
42 return viol
43}