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/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)"