Finished pass through the DRC rule templates and fixed all of them that I could determine how to fix, leaving only a handful of errors not handled correctly.
diff --git a/sky130/magic/sky130.tech b/sky130/magic/sky130.tech index 5be057a..69faf54 100644 --- a/sky130/magic/sky130.tech +++ b/sky130/magic/sky130.tech
@@ -367,6 +367,8 @@ allnfets nfet,npass,npd,scnfet,mvnfet,mvnnfet,nfetlvt,nsonos allpfets pfet,ppu,scpfet,mvpfet,pfethvt,pfetlvt,pfetmvt allfets allnfets,allpfets,varactor,mvvaractor,varhvt + allfetsstd nfet,mvnfet,mvnnfet,nfetlvt,pfet,mvpfet,pfethvt,pfetlvt,pfetmvt + allfetsspecial npass,npd,scnfet,nsonos,ppu,scpfet allnactivenonfet *ndiff,*nsd,*ndiode,*nndiode,*mvndiff,*mvnsd,*mvndiode,*ndiodelvt allnactive allnactivenonfet,allnfets @@ -1313,6 +1315,19 @@ templayer dnwell_missing nsonos and-not dnwell + # SONOS nFET devices must be in cell with abutment box + templayer abutment_box + boundary + + templayer bbox_missing nsonos + and-not abutment_box + + # Make sure nwell covers varactor poly + templayer var_poly_no_nwell + bloat-all *poly varactor,mvvaractor + grow 150 + and-not nwell + # Define MiM cap bottom plate for spacing rule templayer mim_bottom bloat-all *mimcap *metal3 @@ -1472,6 +1487,17 @@ and-not dnwell and allpdifflv,allpdiffmv + templayer nwell_with_tap + bloat-all nsc,mvnsc nwell + + templayer nwell_missing_tap nwell + and-not nwell_with_tap + + # Make sure varactor nwell contains no P diffusion + templayer pdiff_in_varactor_well + bloat-all varactor,mvvaractor nwell + and allpactive + templayer m1_small_hole allm1,obsm1,obslic close 140000 @@ -1484,6 +1510,42 @@ templayer m2_hole_empty m2_small_hole and-not allm2,obsm2 + templayer m1_huge allm1 + shrink 1500 + grow 1500 + + templayer m1_large_halo m1_huge + grow 280 + and-not m1_huge + and allm1 + + templayer m2_huge allm2 + shrink 1500 + grow 1500 + + templayer m2_large_halo m2_huge + grow 280 + and-not m2_huge + and allm2 + + templayer m3_huge allm3 + shrink 1500 + grow 1500 + + templayer m3_large_halo m3_huge + grow 400 + and-not m3_huge + and allm3 + + templayer m4_huge allm4 + shrink 1500 + grow 1500 + + templayer m4_large_halo m4_huge + grow 400 + and-not m4_huge + and allm4 + #ifdef EXPERIMENTAL #---------------------------------------------------------------- style paint @@ -4917,12 +4979,16 @@ spacing dnwell dnwell 6300 touching_ok "Deep N-well spacing < %d (dnwell.3)" spacing dnwell allnwell 4500 surround_ok \ "Deep N-well spacing to N-well < %d (nwell.7)" + + variants (full) cifmaxwidth nwell_missing 0 bend_illegal \ "N-well overlap of Deep N-well < 0.4um outside, 1.03um inside (nwell.5a, 7)" cifmaxwidth dnwell_missing 0 bend_illegal \ "SONOS nFET must be in Deep N-well (tunm.6a)" + cifmaxwidth pdiff_crosses_dnwell 0 bend_illegal \ "P+ diff cannot straddle Deep N-well (dnwell.5)" + variants (fast),(full) #----------------------------- # NWELL @@ -4931,6 +4997,11 @@ width allnwell 840 "N-well width < %d (nwell.1)" spacing allnwell allnwell 1270 touching_ok "N-well spacing < %d (nwell.2a)" + variants (full) + cifmaxwidth nwell_missing_tap 0 bend_illegal \ + "All nwells must contain metal-connected N+ taps (nwell.4)" + variants (fast),(full) + #----------------------------- # DIFF #----------------------------- @@ -4939,6 +5010,7 @@ 150 "Diffusion width < %d (diff/tap.1)" width *mvndiff,mvnfet,mvnnfet,*mvndiode,*nndiode,mvndiffres,*mvpdiff,mvpfet,*mvpdiode 290 \ "MV Diffusion width < %d (diff/tap.14)" + width *mvnsd,*mvpsd 150 "MV Tap width < %d (diff/tap.1)" extend *mvpsd *mvndiff 700 "MV Butting tap length < %d (diff/tap.16)" extend *mvnsd *mvpdiff 700 "MV Butting tap length < %d (diff/tap.16)" @@ -4983,22 +5055,26 @@ # Butting junction rules edge4way (*psd)/a ~(*ndiff,*psd)/a 125 ~(*ndiff)/a (*ndiff)/a 125 \ - "N-Diffusion to P-tap spacing < %d across butted junction" + "N-Diffusion to P-tap spacing < %d across butted junction (psd.5b)" edge4way (*ndiff)/a ~(*ndiff,*psd)/a 125 ~(*psd)/a (*psd)/a 125 \ - "N-Diffusion to P-tap spacing < %d across butted junction" + "N-Diffusion to P-tap spacing < %d across butted junction (psd.5a)" edge4way (*nsd)/a ~(*pdiff,*nsd)/a 125 ~(*pdiff)/a (*pdiff)/a 125 \ - "P-Diffusion to N-tap spacing < %d across butted junction" + "P-Diffusion to N-tap spacing < %d across butted junction (nsd.5b)" edge4way (*pdiff)/a ~(*pdiff,*nsd)/a 125 ~(*nsd)/a (*nsd)/a 125 \ - "P-Diffusion to N-tap spacing < %d across butted junction" + "P-Diffusion to N-tap spacing < %d across butted junction (nsd.5a)" edge4way (*mvpsd)/a ~(*mvndiff,*mvpsd)/a 125 ~(*mvndiff)/a (*mvndiff)/a 125 \ - "MV N-Diffusion to MV P-tap spacing < %d across butted junction" + "MV N-Diffusion to MV P-tap spacing < %d across butted junction (psd.5b)" edge4way (*mvndiff)/a ~(*mvndiff,*mvpsd)/a 125 ~(*mvpsd)/a (*mvpsd)/a 125 \ - "MV N-Diffusion to MV P-tap spacing < %d across butted junction" + "MV N-Diffusion to MV P-tap spacing < %d across butted junction (psd.5a)" edge4way (*mvnsd)/a ~(*mvpdiff,*mvnsd)/a 125 ~(*mvpdiff)/a (*mvpdiff)/a 125 \ - "MV P-Diffusion to MV N-tap spacing < %d across butted junction" + "MV P-Diffusion to MV N-tap spacing < %d across butted junction (nsd.5b)" edge4way (*mvpdiff)/a ~(*mvpdiff,*mvnsd)/a 125 ~(*mvnsd)/a (*mvnsd)/a 125 \ - "MV P-Diffusion to MV N-tap spacing < %d across butted junction" + "MV P-Diffusion to MV N-tap spacing < %d across butted junction (nsd.5a)" + + # Sandwiched butting junction restrictions + edge4way (*pdiff)/a (*nsd)/a 400 ~(*pdiff)/a 0 0 "NSDM width < %d (diff/tap.5) + edge4way (*ndiff)/a (*psd)/a 400 ~(*ndiff)/a 0 0 "PSDM width < %d (diff/tap.5) variants (full) @@ -5010,7 +5086,7 @@ cifmaxwidth ntap_missing 0 bend_illegal \ "P-diff distance to N-tap must be < 15.0um (LU.3)" - variants * + variants (fast),(full) #----------------------------- # POLY @@ -5018,8 +5094,11 @@ width allpoly 150 "poly width < %d (poly.1a)" spacing allpoly allpoly 210 touching_ok "poly spacing < %d (poly.2)" - spacing allpolynonfet alldifflvnonfet 75 corner_ok allfets \ - "poly spacing to Diffusion < %d (poly.4a)" + + spacing allpolynonfet \ + *ndif,*ndiode,*nndiode,ndiffres,*ndiodelvt,*pdif,*pdiode,pdiffres,*pdiodelvt,*pdiodehvt \ + 75 corner_ok allfets \ + "poly spacing to Diffusion < %d (poly.4)" spacing npres *nsd 480 touching_illegal \ "poly resistor spacing to N-tap < %d (poly.9)" overhang *ndiff,rndiff nfet,scnfet,npd,npass 250 "N-Diffusion overhang of nmos < %d (poly.7)" @@ -5032,9 +5111,16 @@ rect_only xhrpoly,uhrpoly "No bends in poly resistors (poly.11)" extend xpc/a xhrpoly,uhrpoly 2160 \ "poly contact extends poly resistor by < %d (licon.1c + li.5)" - spacing xhrpoly,uhrpoly xhrpoly,uhrpoly 1240 touching_illegal \ + spacing xhrpoly,uhrpoly,xpc xhrpoly,uhrpoly,xpc 1240 touching_illegal \ "Distance between precision resistors < %d (rpm.2 + 2 * rpm.3)" + spacing xhrpoly,uhrpoly,xpc allndifflv,allndiffmv 780 touching_illegal \ + "Distance from precision resistor to N+ diffusion < %d (rpm.3 + rpm.6 + nsd.5a)" + spacing xhrpoly,uhrpoly,xpc *poly 400 touching_illegal \ + "Distance from precision resistor to unrelated poly < %d (rpm.3 + rpm.7)" + spacing xhrpoly,uhrpoly,xpc allndiffmvnontap 830 touching_illegal \ + "Distance from precision resistor to MV N+ diffusion < %d (rpm.3 + rpm.9)" + #-------------------------------------------------------------------- # HVTP #-------------------------------------------------------------------- @@ -5043,6 +5129,9 @@ 360 touching_illegal \ "Min. spacing between pFET and HVTP < %d (hvtp.4)" + spacing pmoshvt,pdiodehvt,varactorhvt varactor 360 touching_illegal \ + "Min. spacing between varactor and HVTP < %d (hvtp.4 + varac.3)" + #-------------------------------------------------------------------- # LVTN #-------------------------------------------------------------------- @@ -5192,6 +5281,8 @@ # LI - Local interconnect layer #------------------------------------------------------------- +variants * + width *li 170 "Local interconnect width < %d (li.1)" width rli 290 "Local interconnect width < %d (li.7)" width coreli 140 "Core local interconnect width < %d (li.c1)" @@ -5231,13 +5322,16 @@ variants (fast),(full) widespacing allm1 3000 allm1,*obsm1 280 touching_ok \ - "Metal1 > 3um spacing to unrelated m1 < %d (met1.3a)" + "Metal1 > 3um spacing to unrelated m1 < %d (met1.3b)" widespacing *obsm1 3000 allm1 280 touching_ok \ - "Metal1 > 3um spacing to unrelated m1 < %d (met1.3a)" + "Metal1 > 3um spacing to unrelated m1 < %d (met1.3b)" variants (full) cifmaxwidth m1_hole_empty 0 bend_illegal \ "Min area of metal1 holes > 0.14um^2 (met1.7)" + + cifspacing m1_large_halo m1_large_halo 280 touching_ok \ + "Spacing of metal1 features attached to and within 0.28um of large metal1 < %d (met1.3a)" variants * #-------------------------------------------------- @@ -5263,13 +5357,16 @@ variants (fast),(full) widespacing allm2 3000 allm2,obsm2 280 touching_ok \ - "Metal2 > 3um spacing to unrelated m2 < %d (met2.3)" + "Metal2 > 3um spacing to unrelated m2 < %d (met2.3b)" widespacing obsm2 3000 allm2 280 touching_ok \ - "Metal2 > 3um spacing to unrelated m2 < %d (met2.3)" + "Metal2 > 3um spacing to unrelated m2 < %d (met2.3b)" variants (full) cifmaxwidth m2_hole_empty 0 bend_illegal \ "Min area of metal2 holes > 0.14um^2 (met2.7)" + + cifspacing m2_large_halo m2_large_halo 280 touching_ok \ + "Spacing of metal2 features attached to and within 0.28um of large metal2 < %d (met2.3a)" variants * #-------------------------------------------------- @@ -5299,6 +5396,8 @@ "Metal3 > 3um spacing to unrelated m3 < %d (met3.3d)" widespacing obsm3 3000 allm3 400 touching_ok \ "Metal3 > 3um spacing to unrelated m3 < %d (met3.3d)" + cifspacing m3_large_halo m3_large_halo 400 touching_ok \ + "Spacing of metal3 features attached to and within 0.40um of large metal3 < %d (met3.3c)" variants * @@ -5332,6 +5431,8 @@ "Metal4 > 3um spacing to unrelated m4 < %d (met4.5b)" widespacing obsm4 3000 allm4 400 touching_ok \ "Metal4 > 3um spacing to unrelated m4 < %d (met4.5b)" + cifspacing m4_large_halo m4_large_halo 400 touching_ok \ + "Spacing of metal4 features attached to and within 0.40um of large metal4 < %d (met4.5a)" variants * #-------------------------------------------------- @@ -5365,7 +5466,7 @@ surround glass metrdl 10750 absence_ok "RDL must surround glass cut by %d (rdl.3)" spacing metrdl padl 19660 surround_ok "RDL spacing to unrelated pad < %d (rdl.6)" -variants * +variants (fast),(full) #endif (REDISTRIBUTION) @@ -5373,14 +5474,18 @@ # NMOS, PMOS #-------------------------------------------------- - extend allfets *poly 420 "Transistor width < %d (diff/tap.2)" + edge4way *poly allfetsstd 420 allfets 0 0 \ + "Transistor width < %d (diff/tap.2)" + edge4way *poly allfetsspecial 360 allfets 0 0 \ + "Transistor in standard cell width < %d (diff/tap.2)" + # Except: Note that standard cells allow transistor width minimum 0.36um width pfetlvt 350 "LVT PMOS gate length < %d (poly.1b)" - spacing *nsd,*mvnsd allpolynonfet 55 touching_illegal \ - "N-tap spacing to field poly < %d (poly.5)" - spacing *psd,*mvpsd allpolynonfet 55 touching_illegal \ - "P-tap spacing to field poly < %d (poly.5)" + spacing allpolynonfet *nsd 55 corner_ok varactor \ + "poly spacing to diffusion tap < %d (poly.5)" + spacing allpolynonfet *mvnsd 55 corner_ok mvvaractor \ + "poly spacing to diffusion tap < %d (poly.5)" # Full edge rule required to describe FET to butted tap distance edge4way *psd *ndiff 300 *ndiff *psd 300 \ @@ -5426,19 +5531,31 @@ #-------------------------------------------------- # xhrpoly (P+ poly resistor) -#-------------------------------------------------- - - width xhrpoly 350 "xhrpoly resistor width < %d (P+ poly.1a)" - # NOTE: xhrpoly resistor requires choice of discrete widths 0.35, 0.69, ... up to 1.27. - -#-------------------------------------------------- # uhrpoly (P+ poly resistor, 2kOhm/sq) #-------------------------------------------------- - width uhrpoly 350 "uhrpoly resistor width < %d" + # NOTE: u/xhrpoly resistor requires discrete widths 0.35, 0.69, ... up to 1.27. + width xhrpoly 350 "xhrpoly resistor width < %d (P+ poly.1a)" + width uhrpoly 350 "uhrpoly resistor width < %d (P+ poly.1a)" + spacing xhrpoly,uhrpoly,xpc alldiff 480 touching_illegal \ "xhrpoly/uhrpoly resistor spacing to diffusion < %d (poly.9)" + spacing allpolyres,xpc *poly,allfets 480 touching_illegal \ + "Poly resistor spacing to poly < %d (poly.9)" + + spacing allpolyres,xpc alldiff 480 touching_illegal \ + "Poly resistor spacing to diffusion < %d (poly.9)" + +#------------------------------------ +# nsonos +#------------------------------------ + +variants (full) + cifmaxwidth bbox_missing 0 bend_illegal \ + "SONOS transistor must be in cell with abutment box (tunm.8)" +variants (fast),(full) + #------------------------------------ # MOS Varactor device rules #------------------------------------ @@ -5452,6 +5569,14 @@ width var,varhvt,mvvar 180 "Varactor length < %d (var.1)" extend var,varhvt,mvvar *poly 1000 "Varactor width < %d (var.2)" +variants (full) + cifmaxwidth var_poly_no_nwell 0 bend_illegal \ + "N-well overlap of varactor poly < 0.15um (varac.5)" + + cifmaxwidth pdiff_in_varactor_well 0 bend_illegal \ + "Varactor N-well must not contain P+ diffusion (varac.7)" +variants (fast),(full) + #ifdef MIM #----------------------------------------------------------- # MiM CAP (CAPM) - @@ -5471,8 +5596,11 @@ spacing via3 *mimcap 140 touching_illegal "MiM cap spacing to via3 < %d (capm.8)" spacing *mimcap *metal3/m3 500 surround_ok \ "MiM cap spacing to unrelated metal3 < %d (capm.11)" + +variants (full) cifspacing mim_bottom mim_bottom 1200 touching_ok \ "MiM cap bottom plate spacing < %d (capm.2b)" +variants (fast),(full) # MiM cap contact rules (VIA3) @@ -5496,8 +5624,11 @@ spacing via4 *mimcap2 140 touching_illegal "MiM cap spacing to via4 < %d (cap2m.8)" spacing *mimcap *metal4/m4 500 surround_ok \ "MiM cap spacing to unrelated metal4 < %d (cap2m.11)" + +variants (full) cifspacing mim2_bottom mim2_bottom 1200 touching_ok \ "MiM2 cap bottom plate spacing < %d (cap2m.2b)" +variants (fast),(full) # MiM cap contact rules (VIA4)