Updated the technology file to better represent the exact DRC errors for the RPM layer, and updated the device generator to generate the precision resistors with either nwell or p-sub (or HV version of either) underneath, with appropriate spacing.
diff --git a/VERSION b/VERSION index 46bd1d8..be76a0c 100644 --- a/VERSION +++ b/VERSION
@@ -1 +1 @@ -1.0.145 +1.0.146
diff --git a/sky130/magic/sky130.tcl b/sky130/magic/sky130.tcl index 0ff4489..ee46bb7 100644 --- a/sky130/magic/sky130.tcl +++ b/sky130/magic/sky130.tcl
@@ -2247,7 +2247,7 @@ rho 48.2 val 241 dummy 0 dw 0.0 term 0.0 \ sterm 0.0 caplen 0.4 snake 0 guard 1 \ glc 1 grc 1 gtc 1 gbc 1 roverlap 0 endcov 100 \ - full_metal 1 hv_guard 0 vias 1 \ + full_metal 1 hv_guard 0 n_guard 0 vias 1 \ viagb 0 viagt 0 viagl 0 viagr 0} } @@ -2259,7 +2259,7 @@ compatible {sky130_fd_pr__res_high_po_0p35 \ sky130_fd_pr__res_high_po_0p69 sky130_fd_pr__res_high_po_1p41 \ sky130_fd_pr__res_high_po_2p85 sky130_fd_pr__res_high_po_5p73} \ - full_metal 1 wmax 0.350 vias 1 \ + full_metal 1 wmax 0.350 vias 1 n_guard 0 hv_guard 0 \ viagb 0 viagt 0 viagl 0 viagr 0} } proc sky130::sky130_fd_pr__res_high_po_0p69_defaults {} { @@ -2269,7 +2269,7 @@ compatible {sky130_fd_pr__res_high_po_0p35 \ sky130_fd_pr__res_high_po_0p69 sky130_fd_pr__res_high_po_1p41 \ sky130_fd_pr__res_high_po_2p85 sky130_fd_pr__res_high_po_5p73} \ - full_metal 1 wmax 0.690 vias 1 \ + full_metal 1 wmax 0.690 n_guard 0 hv_guard 0 vias 1 \ viagb 0 viagt 0 viagl 0 viagr 0} } proc sky130::sky130_fd_pr__res_high_po_1p41_defaults {} { @@ -2279,7 +2279,7 @@ compatible {sky130_fd_pr__res_high_po_0p35 \ sky130_fd_pr__res_high_po_0p69 sky130_fd_pr__res_high_po_1p41 \ sky130_fd_pr__res_high_po_2p85 sky130_fd_pr__res_high_po_5p73} \ - full_metal 1 wmax 1.410 vias 1 \ + full_metal 1 wmax 1.410 n_guard 0 hv_guard 0 vias 1 \ viagb 0 viagt 0 viagl 0 viagr 0} } proc sky130::sky130_fd_pr__res_high_po_2p85_defaults {} { @@ -2289,7 +2289,7 @@ compatible {sky130_fd_pr__res_high_po_0p35 \ sky130_fd_pr__res_high_po_0p69 sky130_fd_pr__res_high_po_1p41 \ sky130_fd_pr__res_high_po_2p85 sky130_fd_pr__res_high_po_5p73} \ - full_metal 1 wmax 2.850 vias 1 \ + full_metal 1 wmax 2.850 n_guard 0 hv_guard 0 vias 1 \ viagb 0 viagt 0 viagl 0 viagr 0} } proc sky130::sky130_fd_pr__res_high_po_5p73_defaults {} { @@ -2299,7 +2299,7 @@ compatible {sky130_fd_pr__res_high_po_0p35 \ sky130_fd_pr__res_high_po_0p69 sky130_fd_pr__res_high_po_1p41 \ sky130_fd_pr__res_high_po_2p85 sky130_fd_pr__res_high_po_5p73} \ - full_metal 1 wmax 5.730 vias 1 \ + full_metal 1 wmax 5.730 n_guard 0 hv_guard 0 vias 1 \ viagb 0 viagt 0 viagl 0 viagr 0} } @@ -2312,7 +2312,7 @@ compatible {sky130_fd_pr__res_xhigh_po_0p35 \ sky130_fd_pr__res_xhigh_po_0p69 sky130_fd_pr__res_xhigh_po_1p41 \ sky130_fd_pr__res_xhigh_po_2p85 sky130_fd_pr__res_xhigh_po_5p73} \ - full_metal 1 vias 1 \ + full_metal 1 n_guard 0 hv_guard 0 vias 1 \ viagb 0 viagt 0 viagl 0 viagr 0} } proc sky130::sky130_fd_pr__res_xhigh_po_0p69_defaults {} { @@ -2323,7 +2323,7 @@ compatible {sky130_fd_pr__res_xhigh_po_0p35 \ sky130_fd_pr__res_xhigh_po_0p69 sky130_fd_pr__res_xhigh_po_1p41 \ sky130_fd_pr__res_xhigh_po_2p85 sky130_fd_pr__res_xhigh_po_5p73} \ - full_metal 1 vias 1 \ + full_metal 1 n_guard 0 hv_guard 0 vias 1 \ viagb 0 viagt 0 viagl 0 viagr 0} } proc sky130::sky130_fd_pr__res_xhigh_po_1p41_defaults {} { @@ -2334,7 +2334,7 @@ compatible {sky130_fd_pr__res_xhigh_po_0p35 \ sky130_fd_pr__res_xhigh_po_0p69 sky130_fd_pr__res_xhigh_po_1p41 \ sky130_fd_pr__res_xhigh_po_2p85 sky130_fd_pr__res_xhigh_po_5p73} \ - full_metal 1 vias 1 \ + full_metal 1 n_guard 0 hv_guard 0 vias 1 \ viagb 0 viagt 0 viagl 0 viagr 0} } proc sky130::sky130_fd_pr__res_xhigh_po_2p85_defaults {} { @@ -2345,7 +2345,7 @@ compatible {sky130_fd_pr__res_xhigh_po_0p35 \ sky130_fd_pr__res_xhigh_po_0p69 sky130_fd_pr__res_xhigh_po_1p41 \ sky130_fd_pr__res_xhigh_po_2p85 sky130_fd_pr__res_xhigh_po_5p73} \ - full_metal 1 vias 1 \ + full_metal 1 n_guard 0 hv_guard 0 vias 1 \ viagb 0 viagt 0 viagl 0 viagr 0} } proc sky130::sky130_fd_pr__res_xhigh_po_5p73_defaults {} { @@ -2356,7 +2356,7 @@ compatible {sky130_fd_pr__res_xhigh_po_0p35 \ sky130_fd_pr__res_xhigh_po_0p69 sky130_fd_pr__res_xhigh_po_1p41 \ sky130_fd_pr__res_xhigh_po_2p85 sky130_fd_pr__res_xhigh_po_5p73} \ - full_metal 1 vias 1 \ + full_metal 1 n_guard 0 hv_guard 0 vias 1 \ viagb 0 viagt 0 viagl 0 viagr 0} } @@ -2616,6 +2616,9 @@ if {[dict exists $parameters hv_guard]} { magic::add_checkbox hv_guard "High-voltage guard ring" $parameters } + if {[dict exists $parameters n_guard]} { + magic::add_checkbox n_guard "N-well connected guard ring" $parameters + } if {[dict exists $parameters full_metal]} { magic::add_checkbox full_metal "Full metal guard ring" $parameters } @@ -2632,6 +2635,7 @@ magic::add_checkbox gbc "Add bottom guard ring contact" $parameters } + magic::add_entry viagb "Bottom guard ring via coverage \[+/-\](%)" $parameters magic::add_entry viagt "Top guard ring via coverage \[+/-\](%)" $parameters magic::add_entry viagr "Right guard ring via coverage \[+/-\](%)" $parameters @@ -3216,16 +3220,41 @@ set $key [dict get $sky130::ruleset $key] } + # Handle options related to guard ring type (high/low voltage, nwell/psub) if {[dict exists $parameters hv_guard]} { - if {[dict get $parameters hv_guard] == 1} { + set use_hv_guard [dict get $parameters hv_guard] + } else { + set use_hv_guard 0 + } + if {[dict exists $parameters n_guard]} { + set use_n_guard [dict get $parameters n_guard] + } else { + set use_n_guard 0 + } + + if {$use_hv_guard == 1} { + if {$use_n_guard == 1} { set gdifftype mvnsd set gdiffcont mvnsc - set gsurround 0.33 } else { + set gdifftype mvpsd + set gdiffcont mvpsc + } + set gsurround 0.33 + } else { + if {$use_n_guard == 1} { set gdifftype nsd set gdiffcont nsc - set gsurround $sub_surround + } else { + set gdifftype psd + set gdiffcont psc } + set gsurround $sub_surround + } + if {$use_n_guard == 1} { + set gsubtype nwell + } else { + set gsubtype psub } set newdict [dict create \ @@ -3234,7 +3263,7 @@ end_contact_type pc \ plus_diff_type $gdifftype \ plus_contact_type $gdiffcont \ - sub_type nwell \ + sub_type $gsubtype \ guard_sub_surround $gsurround \ end_surround $poly_surround \ end_spacing 0.48 \ @@ -3259,22 +3288,64 @@ set $key [dict get $sky130::ruleset $key] } + # Handle options related to guard ring type (high/low voltage, nwell/psub) + if {[dict exists $parameters hv_guard]} { + set use_hv_guard [dict get $parameters hv_guard] + } else { + set use_hv_guard 0 + } + if {[dict exists $parameters n_guard]} { + set use_n_guard [dict get $parameters n_guard] + } else { + set use_n_guard 0 + } + + if {$use_hv_guard == 1} { + if {$use_n_guard == 1} { + set gdifftype mvnsd + set gdiffcont mvnsc + } else { + set gdifftype mvpsd + set gdiffcont mvpsc + } + set gsurround 0.33 + } else { + if {$use_n_guard == 1} { + set gdifftype nsd + set gdiffcont nsc + } else { + set gdifftype psd + set gdiffcont psc + } + set gsurround $sub_surround + } + if {$use_n_guard == 1} { + set gsubtype nwell + set gresdiff_spacing 0.785 + set gresdiff_end 0.525 + } else { + set gsubtype psub + set gresdiff_spacing 0.48 + set gresdiff_end 0.48 + } + set newdict [dict create \ res_type ppres \ res_idtype res0p35 \ end_type xpc \ end_contact_type xpc \ end_contact_size 0 \ - plus_diff_type psd \ - plus_contact_type psc \ - sub_type psub \ + plus_diff_type $gdifftype \ + plus_contact_type $gdiffcont \ + sub_type $gsubtype \ + guard_sub_surround $gsurround \ end_surround $poly_surround \ - end_spacing 0.48 \ + end_spacing $gresdiff_end \ end_to_end_space 0.52 \ end_contact_size 0.19 \ res_to_endcont 1.985 \ res_spacing 1.24 \ - res_diff_spacing 0.48 \ + res_diff_spacing $gresdiff_spacing \ mask_clearance 0.52 \ overlap_compress 0.36 \ ] @@ -3289,22 +3360,64 @@ set $key [dict get $sky130::ruleset $key] } + # Handle options related to guard ring type (high/low voltage, nwell/psub) + if {[dict exists $parameters hv_guard]} { + set use_hv_guard [dict get $parameters hv_guard] + } else { + set use_hv_guard 0 + } + if {[dict exists $parameters n_guard]} { + set use_n_guard [dict get $parameters n_guard] + } else { + set use_n_guard 0 + } + + if {$use_hv_guard == 1} { + if {$use_n_guard == 1} { + set gdifftype mvnsd + set gdiffcont mvnsc + } else { + set gdifftype mvpsd + set gdiffcont mvpsc + } + set gsurround 0.33 + } else { + if {$use_n_guard == 1} { + set gdifftype nsd + set gdiffcont nsc + } else { + set gdifftype psd + set gdiffcont psc + } + set gsurround $sub_surround + } + if {$use_n_guard == 1} { + set gsubtype nwell + set gresdiff_spacing 0.615 + set gresdiff_end 0.525 + } else { + set gsubtype psub + set gresdiff_spacing 0.48 + set gresdiff_end 0.48 + } + set newdict [dict create \ res_type ppres \ res_idtype res0p69 \ end_type xpc \ end_contact_type xpc \ end_contact_size 0 \ - plus_diff_type psd \ - plus_contact_type psc \ - sub_type psub \ + plus_diff_type $gdifftype \ + plus_contact_type $gdiffcont \ + sub_type $gsubtype \ + guard_sub_surround $gsurround \ end_surround $poly_surround \ - end_spacing 0.48 \ + end_spacing $gresdiff_end \ end_to_end_space 0.52 \ end_contact_size 0.19 \ res_to_endcont 1.985 \ res_spacing 1.24 \ - res_diff_spacing 0.48 \ + res_diff_spacing $gresdiff_spacing \ mask_clearance 0.52 \ overlap_compress 0.36 \ ] @@ -3319,22 +3432,64 @@ set $key [dict get $sky130::ruleset $key] } + # Handle options related to guard ring type (high/low voltage, nwell/psub) + if {[dict exists $parameters hv_guard]} { + set use_hv_guard [dict get $parameters hv_guard] + } else { + set use_hv_guard 0 + } + if {[dict exists $parameters n_guard]} { + set use_n_guard [dict get $parameters n_guard] + } else { + set use_n_guard 0 + } + + if {$use_hv_guard == 1} { + if {$use_n_guard == 1} { + set gdifftype mvnsd + set gdiffcont mvnsc + } else { + set gdifftype mvpsd + set gdiffcont mvpsc + } + set gsurround 0.33 + } else { + if {$use_n_guard == 1} { + set gdifftype nsd + set gdiffcont nsc + } else { + set gdifftype psd + set gdiffcont psc + } + set gsurround $sub_surround + } + if {$use_n_guard == 1} { + set gsubtype nwell + set gresdiff_spacing 0.525 + set gresdiff_end 0.525 + } else { + set gsubtype psub + set gresdiff_spacing 0.48 + set gresdiff_end 0.48 + } + set newdict [dict create \ res_type ppres \ res_idtype res1p41 \ end_type xpc \ end_contact_type xpc \ end_contact_size 0 \ - plus_diff_type psd \ - plus_contact_type psc \ - sub_type psub \ + plus_diff_type $gdifftype \ + plus_contact_type $gdiffcont \ + sub_type $gsubtype \ + guard_sub_surround $gsurround \ end_surround $poly_surround \ - end_spacing 0.48 \ + end_spacing $gresdiff_end \ end_to_end_space 0.52 \ end_contact_size 0.19 \ res_to_endcont 1.985 \ res_spacing 1.24 \ - res_diff_spacing 0.48 \ + res_diff_spacing $gresdiff_spacing \ mask_clearance 0.52 \ overlap_compress 0.36 \ ] @@ -3349,22 +3504,64 @@ set $key [dict get $sky130::ruleset $key] } + # Handle options related to guard ring type (high/low voltage, nwell/psub) + if {[dict exists $parameters hv_guard]} { + set use_hv_guard [dict get $parameters hv_guard] + } else { + set use_hv_guard 0 + } + if {[dict exists $parameters n_guard]} { + set use_n_guard [dict get $parameters n_guard] + } else { + set use_n_guard 0 + } + + if {$use_hv_guard == 1} { + if {$use_n_guard == 1} { + set gdifftype mvnsd + set gdiffcont mvnsc + } else { + set gdifftype mvpsd + set gdiffcont mvpsc + } + set gsurround 0.33 + } else { + if {$use_n_guard == 1} { + set gdifftype nsd + set gdiffcont nsc + } else { + set gdifftype psd + set gdiffcont psc + } + set gsurround $sub_surround + } + if {$use_n_guard == 1} { + set gsubtype nwell + set gresdiff_spacing 0.525 + set gresdiff_end 0.525 + } else { + set gsubtype psub + set gresdiff_spacing 0.48 + set gresdiff_end 0.48 + } + set newdict [dict create \ res_type ppres \ res_idtype res2p85 \ end_type xpc \ end_contact_type xpc \ end_contact_size 0 \ - plus_diff_type psd \ - plus_contact_type psc \ - sub_type psub \ + plus_diff_type $gdifftype \ + plus_contact_type $gdiffcont \ + sub_type $gsubtype \ + guard_sub_surround $gsurround \ end_surround $poly_surround \ - end_spacing 0.48 \ + end_spacing $gresdiff_end \ end_to_end_space 0.52 \ end_contact_size 0.19 \ res_to_endcont 1.985 \ res_spacing 1.24 \ - res_diff_spacing 0.48 \ + res_diff_spacing $gresdiff_spacing \ mask_clearance 0.52 \ overlap_compress 0.36 \ ] @@ -3379,22 +3576,64 @@ set $key [dict get $sky130::ruleset $key] } + # Handle options related to guard ring type (high/low voltage, nwell/psub) + if {[dict exists $parameters hv_guard]} { + set use_hv_guard [dict get $parameters hv_guard] + } else { + set use_hv_guard 0 + } + if {[dict exists $parameters n_guard]} { + set use_n_guard [dict get $parameters n_guard] + } else { + set use_n_guard 0 + } + + if {$use_hv_guard == 1} { + if {$use_n_guard == 1} { + set gdifftype mvnsd + set gdiffcont mvnsc + } else { + set gdifftype mvpsd + set gdiffcont mvpsc + } + set gsurround 0.33 + } else { + if {$use_n_guard == 1} { + set gdifftype nsd + set gdiffcont nsc + } else { + set gdifftype psd + set gdiffcont psc + } + set gsurround $sub_surround + } + if {$use_n_guard == 1} { + set gsubtype nwell + set gresdiff_spacing 0.525 + set gresdiff_end 0.525 + } else { + set gsubtype psub + set gresdiff_spacing 0.48 + set gresdiff_end 0.48 + } + set newdict [dict create \ res_type ppres \ res_idtype res5p73 \ end_type xpc \ end_contact_type xpc \ end_contact_size 0 \ - plus_diff_type psd \ - plus_contact_type psc \ - sub_type psub \ + plus_diff_type $gdifftype \ + plus_contact_type $gdiffcont \ + sub_type $gsubtype \ + guard_sub_surround $gsurround \ end_surround $poly_surround \ - end_spacing 0.48 \ + end_spacing $gresdiff_end \ end_to_end_space 0.52 \ end_contact_size 0.19 \ res_to_endcont 1.985 \ res_spacing 1.24 \ - res_diff_spacing 0.48 \ + res_diff_spacing $gresdiff_spacing \ mask_clearance 0.52 \ overlap_compress 0.36 \ ] @@ -3411,22 +3650,64 @@ set $key [dict get $sky130::ruleset $key] } + # Handle options related to guard ring type (high/low voltage, nwell/psub) + if {[dict exists $parameters hv_guard]} { + set use_hv_guard [dict get $parameters hv_guard] + } else { + set use_hv_guard 0 + } + if {[dict exists $parameters n_guard]} { + set use_n_guard [dict get $parameters n_guard] + } else { + set use_n_guard 0 + } + + if {$use_hv_guard == 1} { + if {$use_n_guard == 1} { + set gdifftype mvnsd + set gdiffcont mvnsc + } else { + set gdifftype mvpsd + set gdiffcont mvpsc + } + set gsurround 0.33 + } else { + if {$use_n_guard == 1} { + set gdifftype nsd + set gdiffcont nsc + } else { + set gdifftype psd + set gdiffcont psc + } + set gsurround $sub_surround + } + if {$use_n_guard == 1} { + set gsubtype nwell + set gresdiff_spacing 0.785 + set gresdiff_end 0.525 + } else { + set gsubtype psub + set gresdiff_spacing 0.48 + set gresdiff_end 0.48 + } + set newdict [dict create \ res_type xpres \ res_idtype res0p35 \ end_type xpc \ end_contact_type xpc \ end_contact_size 0 \ - plus_diff_type psd \ - plus_contact_type psc \ - sub_type psub \ + plus_diff_type $gdifftype \ + plus_contact_type $gdiffcont \ + sub_type $gsubtype \ + guard_sub_surround $gsurround \ end_surround $poly_surround \ - end_spacing 0.48 \ + end_spacing $gresdiff_end \ end_to_end_space 0.52 \ end_contact_size 0.19 \ res_to_endcont 1.985 \ res_spacing 1.24 \ - res_diff_spacing 0.48 \ + res_diff_spacing $gresdiff_spacing \ mask_clearance 0.52 \ overlap_compress 0.36 \ ] @@ -3441,22 +3722,64 @@ set $key [dict get $sky130::ruleset $key] } + # Handle options related to guard ring type (high/low voltage, nwell/psub) + if {[dict exists $parameters hv_guard]} { + set use_hv_guard [dict get $parameters hv_guard] + } else { + set use_hv_guard 0 + } + if {[dict exists $parameters n_guard]} { + set use_n_guard [dict get $parameters n_guard] + } else { + set use_n_guard 0 + } + + if {$use_hv_guard == 1} { + if {$use_n_guard == 1} { + set gdifftype mvnsd + set gdiffcont mvnsc + } else { + set gdifftype mvpsd + set gdiffcont mvpsc + } + set gsurround 0.33 + } else { + if {$use_n_guard == 1} { + set gdifftype nsd + set gdiffcont nsc + } else { + set gdifftype psd + set gdiffcont psc + } + set gsurround $sub_surround + } + if {$use_n_guard == 1} { + set gsubtype nwell + set gresdiff_spacing 0.615 + set gresdiff_end 0.525 + } else { + set gsubtype psub + set gresdiff_spacing 0.48 + set gresdiff_end 0.48 + } + set newdict [dict create \ res_type xpres \ res_idtype res0p69 \ end_type xpc \ end_contact_type xpc \ end_contact_size 0 \ - plus_diff_type psd \ - plus_contact_type psc \ - sub_type psub \ + plus_diff_type $gdifftype \ + plus_contact_type $gdiffcont \ + sub_type $gsubtype \ + guard_sub_surround $gsurround \ end_surround $poly_surround \ - end_spacing 0.48 \ + end_spacing $gresdiff_end \ end_to_end_space 0.52 \ end_contact_size 0.19 \ res_to_endcont 1.985 \ res_spacing 1.24 \ - res_diff_spacing 0.48 \ + res_diff_spacing $gresdiff_spacing \ mask_clearance 0.52 \ overlap_compress 0.36 \ ] @@ -3471,22 +3794,64 @@ set $key [dict get $sky130::ruleset $key] } + # Handle options related to guard ring type (high/low voltage, nwell/psub) + if {[dict exists $parameters hv_guard]} { + set use_hv_guard [dict get $parameters hv_guard] + } else { + set use_hv_guard 0 + } + if {[dict exists $parameters n_guard]} { + set use_n_guard [dict get $parameters n_guard] + } else { + set use_n_guard 0 + } + + if {$use_hv_guard == 1} { + if {$use_n_guard == 1} { + set gdifftype mvnsd + set gdiffcont mvnsc + } else { + set gdifftype mvpsd + set gdiffcont mvpsc + } + set gsurround 0.33 + } else { + if {$use_n_guard == 1} { + set gdifftype nsd + set gdiffcont nsc + } else { + set gdifftype psd + set gdiffcont psc + } + set gsurround $sub_surround + } + if {$use_n_guard == 1} { + set gsubtype nwell + set gresdiff_spacing 0.525 + set gresdiff_end 0.525 + } else { + set gsubtype psub + set gresdiff_spacing 0.48 + set gresdiff_end 0.48 + } + set newdict [dict create \ res_type xpres \ res_idtype res1p41 \ end_type xpc \ end_contact_type xpc \ end_contact_size 0 \ - plus_diff_type psd \ - plus_contact_type psc \ - sub_type psub \ + plus_diff_type $gdifftype \ + plus_contact_type $gdiffcont \ + sub_type $gsubtype \ + guard_sub_surround $gsurround \ end_surround $poly_surround \ - end_spacing 0.48 \ + end_spacing $gresdiff_end \ end_to_end_space 0.52 \ end_contact_size 0.19 \ res_to_endcont 1.985 \ res_spacing 1.24 \ - res_diff_spacing 0.48 \ + res_diff_spacing $gresdiff_spacing \ mask_clearance 0.52 \ overlap_compress 0.36 \ ] @@ -3501,22 +3866,64 @@ set $key [dict get $sky130::ruleset $key] } + # Handle options related to guard ring type (high/low voltage, nwell/psub) + if {[dict exists $parameters hv_guard]} { + set use_hv_guard [dict get $parameters hv_guard] + } else { + set use_hv_guard 0 + } + if {[dict exists $parameters n_guard]} { + set use_n_guard [dict get $parameters n_guard] + } else { + set use_n_guard 0 + } + + if {$use_hv_guard == 1} { + if {$use_n_guard == 1} { + set gdifftype mvnsd + set gdiffcont mvnsc + } else { + set gdifftype mvpsd + set gdiffcont mvpsc + } + set gsurround 0.33 + } else { + if {$use_n_guard == 1} { + set gdifftype nsd + set gdiffcont nsc + } else { + set gdifftype psd + set gdiffcont psc + } + set gsurround $sub_surround + } + if {$use_n_guard == 1} { + set gsubtype nwell + set gresdiff_spacing 0.525 + set gresdiff_end 0.525 + } else { + set gsubtype psub + set gresdiff_spacing 0.48 + set gresdiff_end 0.48 + } + set newdict [dict create \ res_type xpres \ res_idtype res2p85 \ end_type xpc \ end_contact_type xpc \ end_contact_size 0 \ - plus_diff_type psd \ - plus_contact_type psc \ - sub_type psub \ + plus_diff_type $gdifftype \ + plus_contact_type $gdiffcont \ + sub_type $gsubtype \ + guard_sub_surround $gsurround \ end_surround $poly_surround \ - end_spacing 0.48 \ + end_spacing $gresdiff_end \ end_to_end_space 0.52 \ end_contact_size 0.19 \ res_to_endcont 1.985 \ res_spacing 1.24 \ - res_diff_spacing 0.48 \ + res_diff_spacing $gresdiff_spacing \ mask_clearance 0.52 \ overlap_compress 0.36 \ ] @@ -3531,22 +3938,64 @@ set $key [dict get $sky130::ruleset $key] } + # Handle options related to guard ring type (high/low voltage, nwell/psub) + if {[dict exists $parameters hv_guard]} { + set use_hv_guard [dict get $parameters hv_guard] + } else { + set use_hv_guard 0 + } + if {[dict exists $parameters n_guard]} { + set use_n_guard [dict get $parameters n_guard] + } else { + set use_n_guard 0 + } + + if {$use_hv_guard == 1} { + if {$use_n_guard == 1} { + set gdifftype mvnsd + set gdiffcont mvnsc + } else { + set gdifftype mvpsd + set gdiffcont mvpsc + } + set gsurround 0.33 + } else { + if {$use_n_guard == 1} { + set gdifftype nsd + set gdiffcont nsc + } else { + set gdifftype psd + set gdiffcont psc + } + set gsurround $sub_surround + } + if {$use_n_guard == 1} { + set gsubtype nwell + set gresdiff_spacing 0.525 + set gresdiff_end 0.525 + } else { + set gsubtype psub + set gresdiff_spacing 0.48 + set gresdiff_end 0.48 + } + set newdict [dict create \ res_type xpres \ res_idtype res5p73 \ end_type xpc \ end_contact_type xpc \ end_contact_size 0 \ - plus_diff_type psd \ - plus_contact_type psc \ - sub_type psub \ + plus_diff_type $gdifftype \ + plus_contact_type $gdiffcont \ + sub_type $gsubtype \ + guard_sub_surround $gsurround \ end_surround $poly_surround \ - end_spacing 0.48 \ + end_spacing $gresdiff_end \ end_to_end_space 0.52 \ end_contact_size 0.19 \ res_to_endcont 1.985 \ res_spacing 1.24 \ - res_diff_spacing 0.48 \ + res_diff_spacing $gresdiff_spacing \ mask_clearance 0.52 \ overlap_compress 0.36 \ ]
diff --git a/sky130/magic/sky130.tech b/sky130/magic/sky130.tech index d18b620..e5df31a 100644 --- a/sky130/magic/sky130.tech +++ b/sky130/magic/sky130.tech
@@ -1651,6 +1651,30 @@ shrink 345 and-not hvntm_block + # RPM spacing checks require recreating RPM + templayer rpm_generate + bloat-all xhrpoly,uhrpoly xpc + grow 200 + grow-min 1270 + grow 420 + shrink 420 + + # Check distance RPM to NSDM + templayer rpm_nsd_check rpm_generate + grow 325 + and allndifflv,allndiffmv + + # Check distance RPM to (unrelated) POLY + templayer rpm_poly_check rpm_generate + grow 200 + and-not xhrpoly,uhrpoly,xpc + and allpoly + + # Check distance RPM to HVNTM + templayer rpm_hvntm_check rpm_generate + grow 385 + and allndiffmvnontap + templayer m1_small_hole allm1,obsm1,obsmcon close 140000 @@ -4177,12 +4201,28 @@ 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 \ + variants (fast) + + spacing xhrpoly,uhrpoly,xpc allndifflv,allndiffmv 525 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)" + spacing xhrpoly,uhrpoly,xpc allndiffmvnontap 585 touching_illegal \ + "Distance from precision resistor to MV N+ device < %d (rpm.3 + rpm.9 + hvntm.3)" + + # Minimum width requirement means actual spacing from res to ndiff has to be + # constructed from mask rules. These supercede the simpler checks. + + variants (full) + + cifmaxwidth rpm_nsd_check 0 bend_illegal \ + "Distance from precision resistor to N+ diffusion < 0.525um (rpm.3 + rpm.6 + nsd.5a)" + cifmaxwidth rpm_poly_check 0 bend_illegal \ + "Distance from precision resistor to unrelated poly < 0.4um (rpm.3 + rpm.7)" + cifmaxwidth rpm_hvntm_check 0 bend_illegal \ + "Distance from precision resistor to MV N+ device < 0.585um (rpm.3 + rpm.9 + hvntm.3)" + + variants (fast,full) angles allpoly,polyfill 90 "Only 90 degree angles permitted on poly (x.2)"