code wiki / _hdl_build / nx_mask_geom_test.nx
nx_mask_geom_test.nx source
↩ module page · 89 lines · 4673 B
1// nx_mask_geom_test.nx -- ACCEPTANCE GATE for the mask geometry + DRC. Exact-integer KATs on a
2// simple 2-feature transistor-ish layout (a 1um gate + a 1um contact, 500nm apart) plus the
3// makeable gate tying the critical dimension to machine resolution (the CPU-accuracy bridge).
4import "nx_mask_geom.nx"
5import "nx_syscalls.nx"
6
7func mt_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
8func mt_putn(v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m;sys_write(1,"-" as *u8,1)} let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1} sys_write(1,bb,k); return 0 }
9
10func main() -> i64 {
11 var pass: i64 = 0
12 var total: i64 = 0
13 let out: *i64 = sys_mmap(64) as *i64
14
15 // layout: two 1um x 1um features, A at (0,0), B at (1500,0) -> 500nm horizontal spacing, same y-band
16 let x: *i64 = sys_mmap(64) as *i64
17 let y: *i64 = sys_mmap(64) as *i64
18 let w: *i64 = sys_mmap(64) as *i64
19 let h: *i64 = sys_mmap(64) as *i64
20 x[0]=0; y[0]=0; w[0]=1000; h[0]=1000
21 x[1]=1500; y[1]=0; w[1]=1000; h[1]=1000
22 let N: i64 = 2
23
24 // T1: critical dimension = 1000nm (the smallest dim); area of one feature = 1,000,000 nm^2
25 total = total + 1
26 var t1: i64 = 1
27 if mk_critical_dimension(w, h, N) != 1000 { t1 = 0 }
28 if mk_area(w[0], h[0]) != 1000000 { t1 = 0 }
29 if t1 == 1 { pass = pass + 1 } else { mt_puts("T1 FAIL cd=" as *u8); mt_putn(mk_critical_dimension(w,h,N)); mt_puts("\n" as *u8) }
30
31 // T2: spacing between A and B = 500nm; they do NOT overlap
32 total = total + 1
33 var t2: i64 = 1
34 if mk_spacing(x[0],y[0],w[0],h[0], x[1],y[1],w[1],h[1]) != 500 { t2 = 0 }
35 if mk_overlap(x[0],y[0],w[0],h[0], x[1],y[1],w[1],h[1]) != 0 { t2 = 0 }
36 if t2 == 1 { pass = pass + 1 } else { mt_puts("T2 FAIL spacing=" as *u8); mt_putn(mk_spacing(x[0],y[0],w[0],h[0],x[1],y[1],w[1],h[1])); mt_puts("\n" as *u8) }
37
38 // T3: DRC PASSES with min_width 500, min_spacing 500 (1000>=500, 500>=500)
39 total = total + 1
40 if mk_drc(x, y, w, h, N, 500, 500, out) == MK_DRC_OK { pass = pass + 1 } else { mt_puts("T3 FAIL drc code=" as *u8); mt_putn(out[0]); mt_puts(" i=" as *u8); mt_putn(out[1]); mt_puts(" j=" as *u8); mt_putn(out[2]); mt_puts("\n" as *u8) }
41
42 // T4: DRC FAILS CLOSE with a tighter min_spacing 600 (500 < 600) -- names the offending pair
43 total = total + 1
44 var t4: i64 = 1
45 if mk_drc(x, y, w, h, N, 500, 600, out) != MK_DRC_CLOSE { t4 = 0 }
46 if out[1] != 0 { t4 = 0 }
47 if out[2] != 1 { t4 = 0 }
48 if t4 == 1 { pass = pass + 1 } else { mt_puts("T4 FAIL close code=" as *u8); mt_putn(out[0]); mt_puts("\n" as *u8) }
49
50 // T5: DRC FAILS THIN -- shrink feature B to 300nm wide, min_width 500 -> THIN at feature 1
51 total = total + 1
52 w[1] = 300
53 var t5: i64 = 1
54 if mk_drc(x, y, w, h, N, 500, 500, out) != MK_DRC_THIN { t5 = 0 }
55 if out[1] != 1 { t5 = 0 }
56 if t5 == 1 { pass = pass + 1 } else { mt_puts("T5 FAIL thin\n" as *u8) }
57 w[1] = 1000 // restore
58
59 // T6: DRC FAILS OVERLAP -- move B onto A (x=500) -> illegal intersection
60 total = total + 1
61 x[1] = 500
62 if mk_drc(x, y, w, h, N, 100, 100, out) == MK_DRC_OVERLAP { pass = pass + 1 } else { mt_puts("T6 FAIL overlap code=" as *u8); mt_putn(out[0]); mt_puts("\n" as *u8) }
63 x[1] = 1500 // restore
64
65 // T7: MAKEABLE bridge -- the 1um-CD layout is makeable by a 300nm (SUBMICRON) machine, NOT by an
66 // FDM machine (120um resolution). This is the CPU-accuracy gate on a real layout.
67 total = total + 1
68 var t7: i64 = 1
69 if mk_makeable(w, h, N, 300) != 1 { t7 = 0 } // 300nm resolution can make a 1000nm feature
70 if mk_makeable(w, h, N, 120000) != 0 { t7 = 0 } // 120um FDM cannot make a 1um feature
71 if t7 == 1 { pass = pass + 1 } else { mt_puts("T7 FAIL makeable\n" as *u8) }
72
73 // T8: bounding box of the layout = (0,0)-(2500,1000), area 2,500,000 nm^2
74 total = total + 1
75 let bb: *i64 = sys_mmap(64) as *i64
76 let area: i64 = mk_bbox(x, y, w, h, N, bb)
77 var t8: i64 = 1
78 if bb[0] != 0 { t8 = 0 }
79 if bb[1] != 0 { t8 = 0 }
80 if bb[2] != 2500 { t8 = 0 }
81 if bb[3] != 1000 { t8 = 0 }
82 if area != 2500000 { t8 = 0 }
83 if t8 == 1 { pass = pass + 1 } else { mt_puts("T8 FAIL bbox " as *u8); mt_putn(bb[2]); mt_puts("," as *u8); mt_putn(bb[3]); mt_puts("\n" as *u8) }
84
85 mt_puts("MASK-GEOM " as *u8); mt_putn(pass); mt_puts("/" as *u8); mt_putn(total); mt_puts("\n" as *u8)
86 if pass == total { mt_puts("MASK-GEOM ALL-PASS\n" as *u8); sys_exit(0) }
87 sys_exit(1)
88 return 1
89}