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}