code wiki / _hdl_build / nx_mask_geom.nx

nx_mask_geom.nx source

↩ module page · 119 lines · 5635 B

1// nx_mask_geom.nx -- Arc D2: GDSII-class MASK GEOMETRY + DESIGN-RULE CHECK (the chip-fab equivalent 2// of STL->G-code for the printer). The assignment generator queued this from the chip-fab research; 3// this is the team building what it assigned itself. A mask is a set of rectangular FEATURES on a 4// layer, in NANOMETER coordinates (nx_micron_geom). The S-class gate is DRC -- the design-rule check 5// every real chip layout must pass before a fab will run it: 6// * MIN WIDTH -- no feature thinner than the process can resolve (the critical dimension, CD) 7// * MIN SPACING-- no two features closer than the process can separate (or they short together) 8// * NO OVERLAP -- features on the same layer must not illegally intersect 9// The CD ties straight to the CPU goal via nx_metrology: a layout is MAKEABLE only if the machine's 10// resolution <= the layout's critical dimension (SUBMICRON makes transistors; FDM cannot). 11// HONEST SCOPE: rectangles only (Manhattan); arbitrary polygons + the GDSII BINARY record emit are 12// the flagged next rungs -- the geometry + DRC math here is exact. Rects stored as parallel i64 13// arrays x[],y[],w[],h[] (nm). LAWS: struct-free, integer-only. license_tier: ORIGINAL 14import "nx_micron_geom.nx" 15import "nx_metrology.nx" 16import "nx_syscalls.nx" 17 18const MK_DRC_OK: i64 = 0 19const MK_DRC_THIN: i64 = 1 // a feature narrower than min width 20const MK_DRC_CLOSE: i64 = 2 // two features closer than min spacing 21const MK_DRC_OVERLAP: i64 = 3 // illegal overlap on the same layer 22 23func mk_max2(a: i64, b: i64) -> i64 { if a > b { return a } return b } 24func mk_min2(a: i64, b: i64) -> i64 { if a < b { return a } return b } 25 26func mk_right(x: i64, w: i64) -> i64 { return x + w } 27func mk_top(y: i64, h: i64) -> i64 { return y + h } 28 29// area of a rectangle (nm^2) 30func mk_area(w: i64, h: i64) -> i64 { return w * h } 31 32// CRITICAL DIMENSION: the smallest width OR height across all features (the process must resolve it) 33func mk_critical_dimension(w: *i64, h: *i64, n: i64) -> i64 { 34 if n <= 0 { return 0 } 35 var cd: i64 = w[0] 36 var i: i64 = 0 37 while i < n { 38 if w[i] < cd { cd = w[i] } 39 if h[i] < cd { cd = h[i] } 40 i = i + 1 41 } 42 return cd 43} 44 45// is this layout MAKEABLE by a machine of `resolution_nm`? (resolution must be <= the CD) 46// composes nx_metrology mt_can_make: only a fine-enough machine can print the smallest feature. 47func mk_makeable(w: *i64, h: *i64, n: i64, resolution_nm: i64) -> i64 { 48 let cd: i64 = mk_critical_dimension(w, h, n) 49 return mt_can_make(resolution_nm, cd) 50} 51 52// signed gap between two rects along X: >0 = separated by that gap, <=0 = overlapping in X 53func mk_gap_x(x1: i64, w1: i64, x2: i64, w2: i64) -> i64 { 54 return mk_max2(x1, x2) - mk_min2(mk_right(x1, w1), mk_right(x2, w2)) 55} 56func mk_gap_y(y1: i64, h1: i64, y2: i64, h2: i64) -> i64 { 57 return mk_max2(y1, y2) - mk_min2(mk_top(y1, h1), mk_top(y2, h2)) 58} 59 60// do two rects OVERLAP? (strict intersection -> illegal on one layer). Touching edges (gap==0) is allowed. 61func mk_overlap(x1: i64, y1: i64, w1: i64, h1: i64, x2: i64, y2: i64, w2: i64, h2: i64) -> i64 { 62 if mk_gap_x(x1, w1, x2, w2) < 0 { if mk_gap_y(y1, h1, y2, h2) < 0 { return 1 } } 63 return 0 64} 65 66// Manhattan SPACING between two non-overlapping rects = the larger axis gap (0 if they touch/overlap). 67func mk_spacing(x1: i64, y1: i64, w1: i64, h1: i64, x2: i64, y2: i64, w2: i64, h2: i64) -> i64 { 68 let gx: i64 = mk_gap_x(x1, w1, x2, w2) 69 let gy: i64 = mk_gap_y(y1, h1, y2, h2) 70 let g: i64 = mk_max2(gx, gy) 71 if g < 0 { return 0 } 72 return g 73} 74 75// the DESIGN-RULE CHECK: returns MK_DRC_OK or the first violation code. out[0]=violation_code 76// out[1]=feature_i out[2]=feature_j (j=-1 for width violations). min_width + min_spacing in nm. 77func mk_drc(x: *i64, y: *i64, w: *i64, h: *i64, n: i64, min_width: i64, min_spacing: i64, out: *i64) -> i64 { 78 // 1) min width: every feature's both dimensions >= min_width 79 var i: i64 = 0 80 while i < n { 81 if w[i] < min_width { out[0] = MK_DRC_THIN; out[1] = i; out[2] = 0 - 1; return MK_DRC_THIN } 82 if h[i] < min_width { out[0] = MK_DRC_THIN; out[1] = i; out[2] = 0 - 1; return MK_DRC_THIN } 83 i = i + 1 84 } 85 // 2) pairwise: no overlap, and spacing >= min_spacing 86 i = 0 87 while i < n { 88 var j: i64 = i + 1 89 while j < n { 90 if mk_overlap(x[i], y[i], w[i], h[i], x[j], y[j], w[j], h[j]) == 1 { 91 out[0] = MK_DRC_OVERLAP; out[1] = i; out[2] = j; return MK_DRC_OVERLAP 92 } 93 if mk_spacing(x[i], y[i], w[i], h[i], x[j], y[j], w[j], h[j]) < min_spacing { 94 out[0] = MK_DRC_CLOSE; out[1] = i; out[2] = j; return MK_DRC_CLOSE 95 } 96 j = j + 1 97 } 98 i = i + 1 99 } 100 out[0] = MK_DRC_OK; out[1] = 0 - 1; out[2] = 0 - 1 101 return MK_DRC_OK 102} 103 104// overall bounding box of the layout into out[0..3] = minx,miny,maxx,maxy (nm). returns area. 105func mk_bbox(x: *i64, y: *i64, w: *i64, h: *i64, n: i64, out: *i64) -> i64 { 106 if n <= 0 { out[0]=0; out[1]=0; out[2]=0; out[3]=0; return 0 } 107 var minx: i64 = x[0]; var miny: i64 = y[0] 108 var maxx: i64 = mk_right(x[0], w[0]); var maxy: i64 = mk_top(y[0], h[0]) 109 var i: i64 = 1 110 while i < n { 111 if x[i] < minx { minx = x[i] } 112 if y[i] < miny { miny = y[i] } 113 if mk_right(x[i], w[i]) > maxx { maxx = mk_right(x[i], w[i]) } 114 if mk_top(y[i], h[i]) > maxy { maxy = mk_top(y[i], h[i]) } 115 i = i + 1 116 } 117 out[0]=minx; out[1]=miny; out[2]=maxx; out[3]=maxy 118 return (maxx - minx) * (maxy - miny) 119}