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}