Multiple changes to multiple PDKs:
1) Fixed the gf180mcu_fd_io GDS. Previously the GDS was being
updated with a modification after building the magic
database files with GDS file pointers, rendering the file
pointers incorrect. The script has been moved to a filter
so that it occurs before the magic database files are
generated.
2) The gf180mcu device generator script updated mainly to remove
the drain-extended and asymmetric devices from the device menu,
since the drawing routines are unfinished (work in progress).
3) The sky130 tech file updated to add the extended drain layer,
along with GDS generation rules and DRC rules. The device
generator for the extended drain devices is still a work in
progress.
4) The gf180mcu "torture test" script corrected for device names
and updated with additional devices.
5) The xschemrc file for gf180mcu updated to add the PDK path
corresponding to the open_pdks installation location.
diff --git a/VERSION b/VERSION
index d99b186..d5d91cf 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.0.452
+1.0.453
diff --git a/gf180mcu/Makefile.in b/gf180mcu/Makefile.in
index 649665c..ac291f0 100644
--- a/gf180mcu/Makefile.in
+++ b/gf180mcu/Makefile.in
@@ -752,7 +752,9 @@
cp -rp ${GF180MCU_PR_PATH}/cells/xschem/symbols ${XSCHEM_STAGING_$*}
cp -rp ${GF180MCU_PR_PATH}/cells/xschem/tests ${XSCHEM_STAGING_$*}
cp -rp ${GF180MCU_PR_PATH}/cells/xschem/xschemrc ${XSCHEM_STAGING_$*}
- cat ./custom/xschem/xschemrc_append >> ${XSCHEM_STAGING_$*}/xschemrc
+ # Make open_pdks-specific modifications to the xschemrc file
+ ./custom/scripts/fix_xschemrc.py ${XSCHEM_STAGING_$*}/xschemrc \
+ ${GF180MCU$*} 2>&1 | tee -a ${GF180MCU$*}_make.log || true
openlane-%: openlane/config.tcl openlane/gf180mcu_fd_sc_mcu7t5v0/config.tcl openlane/gf180mcu_fd_sc_mcu9t5v0/config.tcl
mkdir -p ${OPENLANETOP_STAGING_$*}
@@ -1192,6 +1194,7 @@
filter=custom/scripts/convert_io_cdl.py \
-gds cells/*/*_${$*_STACK}.gds compile-only \
options=custom/scripts/gds_import_io.tcl \
+ filter=custom/scripts/fix_io_cor_gds.py \
-lef cells/*/*_${$*_STACK}.lef \
annotate lefopts=-hide compile-only \
filter=custom/scripts/fix_io_lef.py \
@@ -1201,10 +1204,6 @@
# in the corner clamp cell that contains the devices being isolated.
${ADDLAYER} ${STAGING_PATH}/${GF180MCU$*} gf180mcu_fd_io ESD_CLAMP_COR \
isosubstrate "-42 43458 56113 57130 40932 43016 57057 55812" -mag
- # Permanent solution to the extraction issue---modify the GDS with the
- # isolated substrate layer.
- ./custom/scripts/fix_io_cor_gds.py \
- ${STAGING_PATH}/${GF180MCU$*}/libs.ref/${IO_GDS}/gf180mcu_fd_io.gds
sram-%:
# Install SRAM macros from vendor files
diff --git a/gf180mcu/custom/scripts/fix_io_cor_gds.py b/gf180mcu/custom/scripts/fix_io_cor_gds.py
index 397a7d3..aae539f 100755
--- a/gf180mcu/custom/scripts/fix_io_cor_gds.py
+++ b/gf180mcu/custom/scripts/fix_io_cor_gds.py
@@ -2,41 +2,75 @@
#
# fix_io_cor_gds.py ---
#
-# Special-purpose script that does the work of what ought to be a simple
-# binary diff and patch. Except that no such thing exists as a standard
-# offering on most Linux systems, so instead of adding another OS
-# package requirement, I'm just writing a binary search-and-replace in
-# python.
-#
-# The purpose of the patch is to add the isolated substrate layer
+# The purpose of this filter is to add the isolated substrate layer
# (GDS layer 23:5) to the ESD_CLAMP_COR cell, which is the only way to
# get the cell to be LVS-correct at that level of hierarchy. The layer
# is simply copied down from further up in the hierarchy. There is no
# mask change to the corner cell itself, but the change allows the corner
# cell to be read back from GDS, extract, and pass LVS.
+import os
import sys
-if len(sys.argv) != 2:
- print('Usage: fix_io_cor_gds.py <filename>')
- sys.exit(1)
-else:
- file_name = sys.argv[1]
+def filter(inname, outname):
-# orig_data is the STRNAME record for ESD_CLAMP_COR. Insert the isosub layer
-# data after this record.
-orig_data = b'\x00\x12\x06\x06\x45\x53\x44\x5f\x43\x4c\x41\x4d\x50\x5f\x43\x4f\x52\x00'
+ # Read input
+ try:
+ with open(inname, 'rb') as inFile:
+ data = inFile.read()
+ except:
+ print('fix_io_cor_gds.py: failed to open ' + inname + ' for reading.', file=sys.stderr)
+ return 1
-append_data = b'\x00\x04\x08\x00\x00\x06\x0d\x02\x00\x17\x00\x06\x0e\x02\x00\x05\x00\x3c\x10\x03\xff\xff\xff\x2e\x00\x03\x48\x2d\xff\xff\xff\x2e\x00\x04\x5b\xd2\x00\x04\x47\xf5\x00\x04\x5b\xd2\x00\x04\x47\xf5\x00\x04\x42\x14\x00\x04\x5a\x65\x00\x04\x42\x14\x00\x04\x5a\x65\x00\x03\x48\x2d\xff\xff\xff\x2e\x00\x03\x48\x2d\x00\x04\x11\x00'
+ # orig_data is the STRNAME record for ESD_CLAMP_COR. Insert the isosub layer
+ # data after this record.
+ orig_data = b'\x00\x12\x06\x06\x45\x53\x44\x5f\x43\x4c\x41\x4d\x50\x5f\x43\x4f\x52\x00'
-# This is not efficient, but only needs to be done once.
+ append_data = b'\x00\x04\x08\x00\x00\x06\x0d\x02\x00\x17\x00\x06\x0e\x02\x00\x05\x00\x3c\x10\x03\xff\xff\xff\x2e\x00\x03\x48\x2d\xff\xff\xff\x2e\x00\x04\x5b\xd2\x00\x04\x47\xf5\x00\x04\x5b\xd2\x00\x04\x47\xf5\x00\x04\x42\x14\x00\x04\x5a\x65\x00\x04\x42\x14\x00\x04\x5a\x65\x00\x03\x48\x2d\xff\xff\xff\x2e\x00\x03\x48\x2d\x00\x04\x11\x00'
-with open(file_name, 'rb') as ifile:
- data = ifile.read()
- data = data.replace(orig_data, orig_data + append_data)
+ # This is not efficient, but only needs to be done once.
+ # Avoid doing it to any file other than the corner I/O.
-# Write back into the same file
-with open(file_name, 'wb') as ofile:
- ofile.write(data)
+ if '__cor' in inname:
+ data = data.replace(orig_data, orig_data + append_data)
-print("Done!")
+ # If the output is a symbolic link but no modifications have been made,
+ # then leave it alone. If it was modified, then remove the symbolic
+ # link before writing.
+ if os.path.islink(outname):
+ os.unlink(outname)
+
+ # Write output
+ try:
+ with open(outname, 'wb') as ofile:
+ ofile.write(data)
+ except:
+ print('fix_io_cor_gds.py: failed to open ' + outname + ' for writing.', file=sys.stderr)
+ return 1
+
+
+if __name__ == '__main__':
+
+ # This script expects to get one or two arguments. One argument is
+ # mandatory and is the input file. The other argument is optional and
+ # is the output file. The output file and input file may be the same
+ # name, in which case the original input is overwritten.
+
+ options = []
+ arguments = []
+ for item in sys.argv[1:]:
+ if item.find('-', 0) == 0:
+ options.append(item[1:])
+ else:
+ arguments.append(item)
+
+ if len(arguments) > 0:
+ infilename = arguments[0]
+
+ if len(arguments) > 1:
+ outfilename = arguments[1]
+ else:
+ outfilename = None
+
+ result = filter(infilename, outfilename)
+ sys.exit(result)
diff --git a/gf180mcu/custom/scripts/fix_xschemrc.py b/gf180mcu/custom/scripts/fix_xschemrc.py
new file mode 100755
index 0000000..41dd798
--- /dev/null
+++ b/gf180mcu/custom/scripts/fix_xschemrc.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python3
+#
+# fix_xschemrc.py ---
+#
+# Special-purpose script that does the work of modifying a few items in
+# the source xschemrc file to make it open_pdks-specific
+
+import sys
+
+if len(sys.argv) != 3:
+ print('Usage: fix_xschemrc.py <filename> <techname>')
+ sys.exit(1)
+else:
+ file_name = sys.argv[1]
+ tech_name = sys.argv[2]
+
+with open(file_name, 'r') as ifile:
+ xlines = ifile.read().splitlines()
+
+# Replace lines which assume PDK is in the user directory above
+outlines = []
+skipnext = 0
+for line in xlines:
+ if skipnext == 0:
+ if 'trying to find' in line:
+ skipnext = 2
+ outlines.append(line)
+ else:
+ skipnext -= 1
+ if skipnext == 0:
+ outlines.append(' if {[file isdir /usr/share/pdk]} {set PDK_ROOT /usr/share/pdk')
+ outlines.append(' } elseif {[file isdir /usr/local/share/pdk]} {set PDK_ROOT /usr/local/share/pdk')
+ outlines.append(' } elseif {[file isdir $env(HOME)/share/pdk]} {set PDK_ROOT $env(HOME)/share/pdk')
+
+# Append these lines:
+outlines.append('')
+outlines.append('# open_pdks-specific')
+outlines.append('set XSCHEM_START_WINDOW ${PDK_ROOT}/' + tech_name + '/libs.tech/xschem/tests/0_top.sch')
+outlines.append('append XSCHEM_LIBRARY_PATH :${PDK_ROOT}/' + tech_name + '/libs.tech/xschem')
+outlines.append('')
+outlines.append('# allow a user-specific path add-on')
+outlines.append('if { [info exists ::env(XSCHEM_USER_LIBRARY_PATH) ] } {')
+outlines.append(' append XSCHEM_LIBRARY_PATH :$env(XSCHEM_USER_LIBRARY_PATH)')
+outlines.append('}')
+
+# Write back into the same file
+with open(file_name, 'w') as ofile:
+ for line in outlines:
+ print(line, file=ofile)
+
+print("Done!")
diff --git a/gf180mcu/custom/xschem/xschemrc_append b/gf180mcu/custom/xschem/xschemrc_append
deleted file mode 100644
index fa1b707..0000000
--- a/gf180mcu/custom/xschem/xschemrc_append
+++ /dev/null
@@ -1,5 +0,0 @@
-
-# allow a user-specific path add-on (https://github.com/iic-jku/iic-osic-tools/issues/7)
-if { [info exists ::env(XSCHEM_USER_LIBRARY_PATH) ] } {
- append XSCHEM_LIBRARY_PATH :$env(XSCHEM_USER_LIBRARY_PATH)
-}
diff --git a/gf180mcu/magic/gf180mcu.tcl b/gf180mcu/magic/gf180mcu.tcl
index 6de2076..e3a28f9 100644
--- a/gf180mcu/magic/gf180mcu.tcl
+++ b/gf180mcu/magic/gf180mcu.tcl
@@ -71,9 +71,9 @@
dict set ruleset diffres_spacing 0.40 ;# Diffusion resistor spacing rule
dict set ruleset polyres_spacing 0.40 ;# Poly resistor spacing rule
dict set ruleset diff_poly_space 0.10 ;# Diffusion to poly spacing rule
- dict set ruleset diff_gate_space 0.10 ;# Diffusion to gate poly spacing rule
+ dict set ruleset diff_gate_space 0.11 ;# Diffusion to gate poly spacing rule
dict set ruleset metal_spacing 0.23 ;# Metal1 spacing rule
- dict set ruleset mmetal_spacing 0.23 ;# Metal spacing rule (above metal1)
+ dict set ruleset mmetal_spacing 0.38 ;# Metal spacing rule (above metal1)
dict set ruleset sblk_to_cont 0.33 ;# resistor to contact center
dict set ruleset sblk_diff_space 0.44 ;# resistor to guard ring
}
@@ -98,15 +98,15 @@
magic::add_toolkit_command $layoutframe "nmos - nMOSFET" "magic::gencell gf180mcu::nfet_03v3" pdk1
magic::add_toolkit_command $layoutframe "pmos - pMOSFET" "magic::gencell gf180mcu::pfet_03v3" pdk1
- magic::add_toolkit_separator $layoutframe pdk1
- magic::add_toolkit_command $layoutframe "nfet_03v3_dss - mosfet (unsalicided drain)" "magic::gencell gf180mcu::nfet_03v3_dss" pdk1
- magic::add_toolkit_command $layoutframe "pfet_03v3_dss - mosfet (unsalicided drain)" "magic::gencell gf180mcu::pfet_03v3_dss" pdk1
- magic::add_toolkit_command $layoutframe "nfet_06v0_dss - mosfet (unsalicided drain, thick oxide)" "magic::gencell gf180mcu::nfet_06v0_dss" pdk1
- magic::add_toolkit_command $layoutframe "pfet_06v0_dss - mosfet (unsalicided drain, thick oxide)" "magic::gencell gf180mcu::pfet_06v0_dss" pdk1
+# (NOT ADDED YET---DRAW ROUTINE IS INCOMPLETE)
+# magic::add_toolkit_separator $layoutframe pdk1
+# magic::add_toolkit_command $layoutframe "nfet_dss - mosfet (unsalicided drain)" "magic::gencell gf180mcu::nfet_03v3_dss" pdk1
+# magic::add_toolkit_command $layoutframe "pfet_dss - mosfet (unsalicided drain)" "magic::gencell gf180mcu::pfet_03v3_dss" pdk1
- magic::add_toolkit_separator $layoutframe pdk1
- magic::add_toolkit_command $layoutframe "ldnmos - nMOSFET" "magic::gencell gf180mcu::nfet_10v0_asym" pdk1
- magic::add_toolkit_command $layoutframe "ldpmos - nMOSFET" "magic::gencell gf180mcu::pfet_10v0_asym" pdk1
+# (NOT ADDED YET---DRAW ROUTINE IS INCOMPLETE)
+# magic::add_toolkit_separator $layoutframe pdk1
+# magic::add_toolkit_command $layoutframe "ldnmos - nMOSFET" "magic::gencell gf180mcu::nfet_10v0_asym" pdk1
+# magic::add_toolkit_command $layoutframe "ldpmos - nMOSFET" "magic::gencell gf180mcu::pfet_10v0_asym" pdk1
magic::add_toolkit_separator $layoutframe pdk1
magic::add_toolkit_command $layoutframe "diode_nd2ps_03v3 - n-diode" "magic::gencell gf180mcu::diode_nd2ps_03v3" pdk1
@@ -2780,10 +2780,10 @@
plus_contact_type psc \
sub_type pwell \
end_surround $diff_surround \
- end_spacing 1.2 \
+ end_spacing 1.4 \
overlap_compress -0.84 \
- res_to_endcont 0.22 \
- res_spacing 1.2 \
+ res_to_endcont 0.38 \
+ res_spacing 1.4 \
res_diff_spacing 0.28 \
well_res_overlap 0.24 \
]
@@ -2954,7 +2954,7 @@
end_type m5 \
end_surround 0.0 \
end_spacing 0.0 \
- res_to_endcont 0.2 \
+ res_to_endcont 0.265 \
res_spacing $mmetal_spacing \
]
set drawdict [dict merge $gf180mcu::ruleset $newdict $parameters]
@@ -3242,7 +3242,7 @@
guard 1 glc 1 grc 1 gtc 0 gbc 0 tbcov 100 rlcov 100 \
topc 1 botc 1 poverlap 0 doverlap 1 lmin 0.28 wmin 0.22 \
full_metal 1 \
- compatible {pfet_03v3_dss}}
+ compatible {pfet_03v3_dss pfet_06v0_dss}}
}
proc gf180mcu::pfet_06v0_dss_defaults {} {
@@ -3250,7 +3250,7 @@
guard 1 glc 1 grc 1 gtc 0 gbc 0 tbcov 100 rlcov 100 \
topc 1 botc 1 poverlap 0 doverlap 1 lmin 0.5 wmin 0.3 \
full_metal 1 \
- compatible {pfet_06v0_dss}}
+ compatible {pfet_03v3_dss pfet_06v0_dss}}
}
#----------------------------------------------------------------
# nmos: Specify all user-editable default values and those
@@ -3282,16 +3282,16 @@
}
proc gf180mcu::nfet_10v0_asym_defaults {} {
- return {w 1.0 l 1.0 m 1 nf 1 diffcov 100 polycov 100 \
+ return {w 4.0 l 0.6 m 1 nf 1 diffcov 100 polycov 100 \
guard 1 glc 1 grc 1 gtc 0 gbc 0 tbcov 100 rlcov 100 \
- topc 1 botc 1 poverlap 0 doverlap 1 lmin 1.0 wmin 1.0 \
+ topc 1 botc 1 poverlap 0 doverlap 1 lmin 0.6 wmin 4.0 \
full_metal 1 }
}
proc gf180mcu::pfet_10v0_asym_defaults {} {
- return {w 1.0 l 1.0 m 1 nf 1 diffcov 100 polycov 100 \
+ return {w 4.0 l 0.6 m 1 nf 1 diffcov 100 polycov 100 \
guard 1 glc 1 grc 1 gtc 0 gbc 0 tbcov 100 rlcov 100 \
- topc 1 botc 1 poverlap 0 doverlap 1 lmin 1.0 wmin 1.0 \
+ topc 1 botc 1 poverlap 0 doverlap 1 lmin 0.6 wmin 4.0 \
full_metal 1 }
}
@@ -3300,7 +3300,7 @@
guard 1 glc 1 grc 1 gtc 0 gbc 0 tbcov 100 rlcov 100 \
topc 1 botc 1 poverlap 0 doverlap 1 lmin 0.28 wmin 0.22 \
full_metal 1 \
- compatible {nfet_03v3_dss}}
+ compatible {nfet_03v3_dss nfet_06v0_dss}}
}
proc gf180mcu::nfet_06v0_dss_defaults {} {
@@ -3308,7 +3308,7 @@
guard 1 glc 1 grc 1 gtc 0 gbc 0 tbcov 100 rlcov 100 \
topc 1 botc 1 poverlap 0 doverlap 1 lmin 0.6 wmin 0.3 \
full_metal 1 \
- compatible {nfet_06v0_dss}}
+ compatible {nfet_03v3_dss nfet_06v0_dss}}
}
#----------------------------------------------------------------
@@ -3772,7 +3772,7 @@
# MOSFET: Draw a single device
#----------------------------------------------------------------
-proc gf180mcu::mos_device {xcount parameters} {
+proc gf180mcu::mos_device {parameters} {
# Epsilon for avoiding round-off errors
set eps 0.0005
@@ -3783,6 +3783,7 @@
set topc 1 ;# draw top poly contact
set botc 1 ;# draw bottom poly contact
set dev_sub_type "" ;# device substrate type (if different from guard ring)
+ set evens 1 ;# even or odd (evens = 1 means drain is on left)
# Set a local variable for each parameter (e.g., $l, $w, etc.)
foreach key [dict keys $parameters] {
@@ -3812,8 +3813,8 @@
box grow s ${hw}um
box grow e ${hl}um
box grow w ${hl}um
- # Set drain and source sides based on xcount.
- if {[% $xcount 2] == 1} {
+ # Set drain and source sides based on "evens".
+ if {$evens == 0} {
set dside e
set sside w
} else {
@@ -4032,7 +4033,7 @@
# to duplicate it here with calculations.
tech lock *
- set bbox [gf180mcu::mos_device 0 $parameters]
+ set bbox [gf180mcu::mos_device $parameters]
# puts stdout "Diagnostic: Device bounding box e $bbox (um)"
tech unlock *
@@ -4123,10 +4124,13 @@
pushbox
box move w ${corellx}um
box move s ${corelly}um
+ set evens 1
for {set xp 0} {$xp < $nf} {incr xp} {
+ dict set parameters evens $evens
+ set evens [- 1 $evens]
pushbox
for {set yp 0} {$yp < $m} {incr yp} {
- gf180mcu::mos_device $xp $parameters
+ gf180mcu::mos_device $parameters
box move n ${dy}um
}
popbox
diff --git a/gf180mcu/magic/gf180mcu.tech b/gf180mcu/magic/gf180mcu.tech
index b8ce0fd..30c5604 100644
--- a/gf180mcu/magic/gf180mcu.tech
+++ b/gf180mcu/magic/gf180mcu.tech
@@ -1550,7 +1550,7 @@
templayer pohmic_missing_pwell *psd
grow 120
and dnwell
- and-not pwell
+ and-not pwell,pbase
templayer mvpohmic_missing_pwell *mvpsd,mvpvaractor
grow 160
@@ -1707,7 +1707,7 @@
scalefactor 50 nanometers
gridlimit 5
- options ignore-unknown-layer-labels options no-reconnect-labels
+ options ignore-unknown-layer-labels
ignore SRAMDEF
ignore FET5VDEF
@@ -1774,7 +1774,6 @@
copyup mvndifcheck
layer mvndiff mvndiffarea
- labels DIFF
# Copy mvndiff areas up for contact checks
templayer mvxndifcheck mvndifcheck
@@ -1795,7 +1794,6 @@
grow 140
shrink 140
and-not sccathode
- labels DIFF
# Schottky contact
layer schottkyc SCHOTTKY
@@ -1814,7 +1812,6 @@
and-not PPLUS
and-not DUALGATE
and-not NAT
- labels DIFF
layer nndiode DIFF
and NPLUS
@@ -1824,7 +1821,6 @@
and-not PPLUS
and-not DUALGATE
and NAT
- labels DIFF
templayer ndiodearea DIODE
and NPLUS
@@ -1837,7 +1833,6 @@
and SBLK
and NPLUS
and-not DUALGATE
- labels DIFF
templayer pdiffarea DIFF
and-not POLY
@@ -1850,7 +1845,6 @@
copyup pdifcheck
layer pdiff pdiffarea
- labels DIFF
layer mvndiode DIFF
and NPLUS
@@ -1859,7 +1853,6 @@
and-not PPLUS
and DUALGATE
and-not NAT
- labels DIFF
layer mvnndiode DIFF
and NPLUS
@@ -1868,7 +1861,6 @@
and-not PPLUS
and DUALGATE
and NAT
- labels DIFF
templayer mvndiodearea DIODE
and NPLUS
@@ -1881,7 +1873,6 @@
and SBLK
and NPLUS
and DUALGATE
- labels DIFF
templayer mvpdiffarea DIFF
and-not POLY
@@ -1894,7 +1885,6 @@
copyup mvpdifcheck
layer mvpdiff mvpdiffarea
- labels DIFF
# Copy pdiff areas up for contact checks
templayer xpdifcheck pdifcheck
@@ -1906,7 +1896,6 @@
and-not NPLUS
and-not DUALGATE
and DIODE
- labels DIFF
templayer pdiodearea DIODE
and PPLUS
@@ -1923,11 +1912,9 @@
layer pfet pfetarea
and-not MOSCAP
- labels DIFF
layer pcap pfetarea
and MOSCAP
- labels DIFF
templayer pfetexpand pfetarea
grow 530
@@ -1947,7 +1934,6 @@
and-not RESDEF
and DUALGATE
and DIODE
- labels DIFF
templayer mvpdiodearea DIODE
and PPLUS
@@ -1964,11 +1950,9 @@
layer mvpfet mvpfetarea
and-not MOSCAP
- labels DIFF
layer mvpcap mvpfetarea
and MOSCAP
- labels DIFF
templayer mvpfetexpand mvpfetarea
grow 530
@@ -1979,14 +1963,12 @@
and-not POLY
and nwelldef
and pfetexpand
- labels DIFF
layer pdiffres DIFF
and-not POLY
and PPLUS
and nwelldef
and SBLK
- labels DIFF
layer nfet DIFF
and POLY
@@ -1996,7 +1978,6 @@
and NPLUS
and-not NAT
and-not MOSCAP
- labels DIFF
layer ncap DIFF
and POLY
@@ -2006,7 +1987,6 @@
and NPLUS
and-not NAT
and MOSCAP
- labels DIFF
layer nnfet DIFF
and POLY
@@ -2015,7 +1995,6 @@
and-not nwelldef
and NPLUS
and NAT
- labels DIFF
templayer nsdarea DIFF
and NPLUS
@@ -2025,7 +2004,6 @@
and-not DUALGATE
layer nsd nsdarea
- labels DIFF
templayer nsdexpand nsdarea
grow 500
@@ -2044,7 +2022,6 @@
copyup psubcheck
layer psd psdarea
- labels DIFF
templayer psdexpand psdarea
grow 500
@@ -2055,14 +2032,12 @@
and nwelldef
and DUALGATE
and mvpfetexpand
- labels DIFF
layer mvpdiffres DIFF
and-not POLY
and PPLUS
and SBLK
and DUALGATE
- labels DIFF
layer mvnfet DIFF
and POLY
@@ -2072,7 +2047,6 @@
and-not nwelldef
and DUALGATE
and-not MOSCAP
- labels DIFF
layer mvncap DIFF
and POLY
@@ -2082,7 +2056,6 @@
and-not nwelldef
and DUALGATE
and MOSCAP
- labels DIFF
layer mvnnfet DIFF
and POLY
@@ -2091,7 +2064,6 @@
and NAT
and-not nwelldef
and DUALGATE
- labels DIFF
templayer mvnsdarea DIFF
and NPLUS
@@ -2102,7 +2074,6 @@
copyup mvnsubcheck
layer mvnsd mvnsdarea
- labels DIFF
templayer mvnsdexpand mvnsdarea
grow 500
@@ -2121,7 +2092,6 @@
copyup mvpsubcheck
layer mvpsd mvpsdarea
- labels DIFF
templayer mvpsdexpand mvpsdarea
grow 500
@@ -2191,13 +2161,11 @@
and-not SBLK
and PPLUS
and RESDEF
- labels POLY
layer rnps POLY
and-not SBLK
and NPLUS
and RESDEF
- labels POLY
layer rpp POLY
and SBLK
@@ -2206,7 +2174,6 @@
and-not HRES
#endif (HRPOLY1K)
and RESDEF
- labels POLY
# POLY + SBLK without RESDEF may be a salicide-blocked transistor.
# The SBLK will be regenerated on GDS output and the poly should be
@@ -2215,12 +2182,10 @@
and-not DIFF
and SBLK
and-not RESDEF
- labels POLY
layer efuse POLY
and-not DIFF
and PLFUSE
- labels POLY
layer rnp POLY
and SBLK
@@ -2229,7 +2194,6 @@
#ifdef HRPOLY1K
and-not HRES
#endif (HRPOLY1K)
- labels POLY
#ifdef HRPOLY1K
layer hires POLY
@@ -2237,14 +2201,12 @@
and HRES
and RESDEF
and-not DUALGATE
- labels POLY
layer mvhires POLY
and SBLK
and HRES
and RESDEF
and DUALGATE
- labels POLY
# We define poly under HRES but not under SBLK to be plain poly
layer poly POLY
@@ -2778,28 +2740,24 @@
and NPLUS
and nwelldef
and-not DUALGATE
- labels POLY
layer mvnvar POLY
and DIFF
and NPLUS
and nwelldef
and DUALGATE
- labels POLY
layer pvar POLY
and DIFF
and PPLUS
and-not nwelldef
and-not DUALGATE
- labels POLY
layer mvpvar POLY
and DIFF
and PPLUS
and-not nwelldef
and DUALGATE
- labels POLY
calma DNWELL 12 0
calma NWELL 21 0
diff --git a/gf180mcu/magic/gf180mcu_make_torture.tcl b/gf180mcu/magic/gf180mcu_make_torture.tcl
index dc1d3aa..3a84bf7 100644
--- a/gf180mcu/magic/gf180mcu_make_torture.tcl
+++ b/gf180mcu/magic/gf180mcu_make_torture.tcl
@@ -46,7 +46,7 @@
magic::gencell gf180mcu::${devname} ${devname}_$i w $w l $l m $m nf $nf diffcov $dcov polycov $pcov rlcov $rlcov poverlap $pov doverlap $dov topc $tc botc $bc full_metal $fm glc $gl grc $gr gbc $gb gtc $gt
select cell ${devname}_$i
set bh [box height]
- set bh [+ $bh 124]
+ set bh [+ $bh 200]
box move n $bh
incr i
}
@@ -88,7 +88,7 @@
magic::gencell gf180mcu::${devname} ${devname}_$i w $w l $l m $m nx $nx endcov $ecov roverlap $rov snake $sn full_metal $fm glc $gl grc $gr gbc $gb gtc $gt
select cell ${devname}_$i
set bh [box height]
- set bh [+ $bh 124]
+ set bh [+ $bh 200]
box move n $bh
incr i
}
@@ -130,7 +130,7 @@
magic::gencell gf180mcu::${devname} ${devname}_$i w $w l $l nx $nx ny $ny doverlap $dov full_metal $fm elc $el erc $er etc $et ebc $eb glc $gl grc $gr gbc $gb gtc $gt
select cell ${devname}_$i
set bh [box height]
- set bh [+ $bh 124]
+ set bh [+ $bh 200]
box move n $bh
incr i
}
@@ -213,60 +213,69 @@
snap int
box size 0 0
-# Layout:
-# apmom_bb
-# pmos_3p3 mim_sm_bb
-# pplus_u ppolyf_s ppolyf_u pplus_u_3p3
-# nmos_3p3 pn_3p3
-# np_3p3
-# pmos_1p2
-# nplus_u nwell_1p2 npolyf_u nplus_u_3p3 pn_1p2
-# pmos_1p2 np_1p2
+#
+# Generate device arrays
#
+mos_array 6 nfet_03v3 0 0
+mos_array 6 pfet_03v3 0 75000
+mos_array 6 nfet_06v0 0 150000
+mos_array 6 pfet_06v0 0 225000
+mos_array 6 nfet_03v3_nvt 0 300000
+mos_array 6 nfet_03v3_dss 0 375000
+mos_array 6 pfet_03v3_dss 0 450000
+mos_array 6 nfet_06v0_dss 0 525000
+mos_array 6 nfet_06v0_dss 0 600000
+mos_array 6 pfet_06v0_nat 0 675000
+mos_array 6 nfet_10v0_asym 0 675000
+mos_array 6 pfet_10v0_asym 0 725000
-mos_array 6 nmos_3p3 0 0
-mos_array 6 pmos_3p3 0 75000
-mos_array 6 nmos_6p0 0 150000
-mos_array 6 pmos_6p0 0 225000
-mos_array 6 pmos_3p3_lvt 0 300000
-mos_array 6 pmos_3p3_hvt 0 375000
-mos_array 6 nmos_3p3_lvt 0 450000
-mos_array 6 nmos_3p3_hvt 0 525000
-mos_array 6 nmos_3p3_nat 0 600000
-mos_array 6 nmos_6p0_nat 0 675000
+res_array 6 npolyf_u 100000 0
+res_array 6 ppolyf_u 100000 180000
-res_array 6 nplus_u 100000 0
-res_array 6 pplus_u 100000 180000
+res_array 6 ppolyf_u_1k 200000 0
+res_array 6 ppolyf_u_1k_6p0 200000 180000
-res_array 6 nwell_1p2 200000 0
-res_array 6 ppolyf_s 200000 180000
+res_array 6 nplus_u 300000 0
+res_array 6 pplus_u 300000 180000
-res_array 6 npolyf_u 300000 0
-res_array 6 ppolyf_u 300000 180000
-
-res_array 6 nplus_u_3p3 400000 0
-res_array 6 pplus_u_3p3 400000 180000
+res_array 6 npolyf_s 400000 0
+res_array 6 ppolyf_s 400000 180000
-diode_array 6 np_1p2 500000 0
-diode_array 6 pn_1p2 500000 30000
-diode_array 6 np_3p3 500000 60000
-diode_array 6 pn_3p3 500000 90000
-diode_array 6 np_1p2_lvt 500000 120000
-diode_array 6 np_1p2_hvt 500000 150000
-diode_array 6 np_1p2_nat 500000 180000
-diode_array 6 pn_1p2_lvt 500000 210000
-diode_array 6 pn_1p2_hvt 500000 240000
-diode_array 6 np_3p3_nat 500000 270000
+res_array 6 nwell 500000 0
+res_array 6 rm1 500000 180000
+res_array 6 rm2 500000 360000
+res_array 6 rm3 500000 540000
+res_array 6 rm4 500000 720000
+res_array 6 rm5 500000 900000
+
+diode_array 6 diode_nd2ps_03v3 600000 0
+diode_array 6 diode_pd2nw_03v3 600000 30000
+diode_array 6 diode_nd2ps_06v0 600000 60000
+diode_array 6 diode_pd2nw_06v0 600000 90000
+diode_array 6 diode_nw2pw_03v3 600000 120000
+diode_array 6 diode_nw2pw_06v0 600000 150000
+diode_array 6 diode_dnw2pw 600000 180000
+diode_array 6 diode_dnw2ps 600000 210000
+diode_array 6 sc_diode 600000 240000
+diode_array 6 diode_nd2ps_06v0_nvt 600000 270000
+
+cap_array 6 cap_mim_2p0fF 700000 0
+cap_array 6 nmoscap_3p3 700000 100000
+cap_array 6 nmoscap_6p0 700000 200000
# Add individual devices from primdev, check GDS pointers
-fixed_array 2 vnpn_2x2 600000 0
-fixed_array 2 vnpn_5x0p42 600000 50000
-fixed_array 2 vnpn_5x5 600000 100000
-fixed_array 2 vnpn_10x0p42 600000 150000
+fixed_array 2 efuse_cell 800000 0
+fixed_array 2 npn_00p54x02p00 800000 50000
+fixed_array 2 npn_00p54x04p00 800000 100000
+fixed_array 2 npn_00p54x08p00 800000 150000
+fixed_array 2 npn_00p54x16p00 800000 200000
+fixed_array 2 npn_05p00x05p00 800000 250000
+fixed_array 2 npn_10p00x10p00 800000 300000
+fixed_array 2 pnp_05p00x00p42 800000 350000
+fixed_array 2 pnp_05p00x05p00 800000 400000
+fixed_array 2 pnp_10p00x00p42 800000 450000
+fixed_array 2 pnp_10p00x10p00 800000 500000
-cap_array 6 mim_sm_bb 600000 200000
-# cap_array 6 apmom_bb 600000 250000
-
-save torture_test_gf013
-gds write torture_test_gf013
+save torture_test_gf180mcu
+gds write torture_test_gf180mcu
diff --git a/sky130/magic/sky130.tcl b/sky130/magic/sky130.tcl
index 4dba385..48367fa 100644
--- a/sky130/magic/sky130.tcl
+++ b/sky130/magic/sky130.tcl
@@ -98,6 +98,12 @@
magic::add_toolkit_command $layoutframe "pmos (MOSFET)" \
"magic::gencell sky130::sky130_fd_pr__pfet_01v8" pdk1
+ # magic::add_toolkit_separator $layoutframe pdk1
+ # magic::add_toolkit_command $layoutframe "LDNMOS (extended drain)" \
+ # "magic::gencell sky130::sky130_fd_pr__nfet_g5v0d16v0" pdk1
+ # magic::add_toolkit_command $layoutframe "LDPMOS (extended drain)" \
+ # "magic::gencell sky130::sky130_fd_pr__pfet_g5v0d16v0" pdk1
+
magic::add_toolkit_separator $layoutframe pdk1
magic::add_toolkit_command $layoutframe "n-diode" \
"magic::gencell sky130::sky130_fd_pr__diode_pw2nd_05v5" pdk1
@@ -4986,6 +4992,13 @@
viagb 0 viagr 0 viagl 0 viagt 0}
}
+proc sky130::sky130_fd_pr__pfet_g5v0d16v0_defaults {} {
+ return {w 5.00 l 1.050 m 1 nf 1 diffcov 100 polycov 100 \
+ tbcov 100 rlcov 100 topc 1 botc 1 \
+ poverlap 0 doverlap 0 lmin 1.050 wmin 5.00 \
+ viasrc 100 viadrn 100 viagate 100 }
+}
+
#----------------------------------------------------------------
# nmos: Specify all user-editable default values and those
# needed by mos_check
@@ -5063,6 +5076,13 @@
viagb 0 viagr 0 viagl 0 viagt 0}
}
+proc sky130::sky130_fd_pr__nfet_g5v0d16v0_defaults {} {
+ return {w 5.00 l 1.055 m 1 nf 1 diffcov 100 polycov 100 \
+ tbcov 100 rlcov 100 topc 1 botc 1 \
+ poverlap 0 doverlap 0 lmin 1.055 wmin 5.00 \
+ viasrc 100 viadrn 100 viagate 100 }
+}
+
#----------------------------------------------------------------
# mos varactor: Specify all user-editable default values and those
# needed by mosvc_check
@@ -5158,6 +5178,10 @@
return [sky130::mos_convert $parameters]
}
+proc sky130::sky130_fd_pr__nfet_g5v0d16v0_convert {parameters} {
+ return [sky130::mos_convert $parameters]
+}
+
proc sky130::sky130_fd_pr__nfet_05v0_nvt_convert {parameters} {
return [sky130::mos_convert $parameters]
}
@@ -5182,6 +5206,10 @@
return [sky130::mos_convert $parameters]
}
+proc sky130::sky130_fd_pr__pfet_g5v0d16v0_convert {parameters} {
+ return [sky130::mos_convert $parameters]
+}
+
proc sky130::sky130_fd_pr__cap_var_lvt_convert {parameters} {
return [sky130::mos_convert $parameters]
}
@@ -5270,6 +5298,10 @@
sky130::mos_dialog sky130_fd_pr__nfet_g5v0d10v5 $parameters
}
+proc sky130::sky130_fd_pr__nfet_g5v0d16v0_dialog {parameters} {
+ sky130::mos_dialog sky130_fd_pr__nfet_g5v0d16v0 $parameters
+}
+
proc sky130::sky130_fd_pr__nfet_05v0_nvt_dialog {parameters} {
sky130::mos_dialog sky130_fd_pr__nfet_05v0_nvt $parameters
}
@@ -5294,6 +5326,10 @@
sky130::mos_dialog sky130_fd_pr__pfet_g5v0d10v5 $parameters
}
+proc sky130::sky130_fd_pr__pfet_g5v0d16v0_dialog {parameters} {
+ sky130::mos_dialog sky130_fd_pr__pfet_g5v0d16v0 $parameters
+}
+
proc sky130::sky130_fd_pr__cap_var_lvt_dialog {parameters} {
sky130::mos_dialog sky130_fd_pr__cap_var_lvt $parameters
}
@@ -5709,6 +5745,20 @@
}
#----------------------------------------------------------------
+# LDNMOS: Sub-procedure to draw the extended drain
+#----------------------------------------------------------------
+
+proc sky130::draw_ldnmos_drain {parameters} {
+}
+
+#----------------------------------------------------------------
+# LDPMOS: Sub-procedure to draw the extended drain
+#----------------------------------------------------------------
+
+proc sky130::draw_ldpmos_drain {parameters} {
+}
+
+#----------------------------------------------------------------
# MOSFET: Draw a single device
#----------------------------------------------------------------
@@ -5725,12 +5775,13 @@
set viasrc 100 ;# draw source vias
set viadrn 100 ;# draw drain vias
set viagate 100 ;# draw gate vias
- set evens 1 ;# even or odd numbered device finger, in X
+ set evens 1 ;# even or odd (evens = 1 means drain is on the left)
set dev_sub_type "" ;# device substrate type (if different from guard ring)
set dev_sub_dist 0 ;# device substrate distance (if nondefault dev_sub_type)
set min_effl 0 ;# gate length below which finger pitch must be stretched
set diff_overlap_cont 0 ;# extra overlap of end contact by diffusion
set gshield 0 ;# no metal shield over gate (used for varactors)
+ set drain_proc {} ;# no special procedure to draw the drain
# Set a local variable for each parameter (e.g., $l, $w, etc.)
foreach key [dict keys $parameters] {
@@ -5749,13 +5800,23 @@
box grow s ${hw}um
box grow e ${hl}um
box grow w ${hl}um
+
+ # Set drain and source sides based on "evens".
+ if {$evens == 0} {
+ set dside e
+ set sside w
+ } else {
+ set dside w
+ set sside e
+ }
+
pushbox
if {${diff_extension} > ${gate_to_diffcont}} {
- box grow e ${diff_extension}um
- box grow w ${diff_extension}um
+ box grow $dside ${diff_extension}um
+ box grow $sside ${diff_extension}um
} else {
- box grow e ${gate_to_diffcont}um
- box grow w ${gate_to_diffcont}um
+ box grow $dside ${gate_to_diffcont}um
+ box grow $sside ${gate_to_diffcont}um
}
paint ${diff_type}
popbox
@@ -5853,52 +5914,57 @@
set cpl [* ${cpl} [/ ${polycov} 100.0]]
}
- # Right diffusion contact
- pushbox
- box move e ${he}um
- box move e ${gate_to_diffcont}um
+ if {$drain_proc != {}} {
+ set cext [sky130::unionbox $cext [eval $drain_proc parameters]]
+ } else {
+ # Drain diffusion contact
+ pushbox
+ box move $dside ${he}um
+ box move $dside ${gate_to_diffcont}um
- # Source via on top of contact
- if {$evens == 1} {set viatype $viasrc} else {set viatype $viadrn}
- if {$viatype != 0} {
- pushbox
- set cw $via_size
- set ch [* $cdwfull [/ [expr abs($viatype)] 100.0]]
- if {$ch < $via_size} {set ch $via_size}
- box grow e [/ $cw 2]um
- box grow w [/ $cw 2]um
- set anchor [string index $viatype 0]
- if {$anchor == "+"} {
- box move s [/ [- $cdwfull $via_size] 2]um
- box grow n ${ch}um
- } elseif {$anchor == "-"} {
- box move n [/ [- $cdwfull $via_size] 2]um
- box grow s ${ch}um
- } else {
- box grow n [/ $ch 2]um
- box grow s [/ $ch 2]um
+ # Drain via on top of contact
+ set viatype $viadrn
+ if {$viatype != 0} {
+ pushbox
+ set cw $via_size
+ set ch [* $cdwfull [/ [expr abs($viatype)] 100.0]]
+ if {$ch < $via_size} {set ch $via_size}
+ box grow $dside [/ $cw 2]um
+ box grow $sside [/ $cw 2]um
+ set anchor [string index $viatype 0]
+ if {$anchor == "+"} {
+ box move s [/ [- $cdwfull $via_size] 2]um
+ box grow n ${ch}um
+ } elseif {$anchor == "-"} {
+ box move n [/ [- $cdwfull $via_size] 2]um
+ box grow s ${ch}um
+ } else {
+ box grow n [/ $ch 2]um
+ box grow s [/ $ch 2]um
+ }
+ sky130::mcon_draw vert
+ popbox
}
- sky130::mcon_draw vert
- popbox
- }
- set cext [sky130::unionbox $cext [sky130::draw_contact 0 ${cdw} \
+ set cext [sky130::unionbox $cext [sky130::draw_contact 0 ${cdw} \
${diff_surround} ${metal_surround} ${contact_size}\
${diff_type} ${diff_contact_type} li vert]]
- popbox
- # Left diffusion contact
- pushbox
- box move w ${he}um
- box move w ${gate_to_diffcont}um
+ popbox
+ }
- # Drain via on top of contact
- if {$evens == 1} {set viatype $viadrn} else {set viatype $viasrc}
+ # Source diffusion contact
+ pushbox
+ box move $sside ${he}um
+ box move $sside ${gate_to_diffcont}um
+
+ # Source via on top of contact
+ set viatype $viasrc
if {$viatype != 0} {
pushbox
set cw $via_size
set ch [* $cdwfull [/ [expr abs($viatype)] 100.0]]
if {$ch < $via_size} {set ch $via_size}
- box grow e [/ $cw 2]um
- box grow w [/ $cw 2]um
+ box grow $sside [/ $cw 2]um
+ box grow $dside [/ $cw 2]um
set anchor [string index $viatype 0]
if {$anchor == "+"} {
box move s [/ [- $cdwfull $via_size] 2]um
@@ -6540,6 +6606,48 @@
}
#----------------------------------------------------------------
+# 16V extended-drain devices LDNMOS and LDPMOS
+#----------------------------------------------------------------
+
+proc sky130::sky130_fd_pr__nfet_g5v0d16v0_draw {parameters} {
+ set newdict [dict create \
+ gate_type mvnfet \
+ diff_type mvndiff \
+ diff_contact_type mvndc \
+ plus_diff_type mvpsd \
+ plus_contact_type mvpsc \
+ poly_type poly \
+ poly_contact_type pc \
+ sub_type psub \
+ diff_spacing 0.31 \
+ diff_tap_space 0.38 \
+ diff_gate_space 0.38 \
+ drain_proc sky130::draw_ldnmos_drain \
+ ]
+ set drawdict [dict merge $sky130::ruleset $newdict $parameters]
+ return [sky130::mos_draw $drawdict]
+}
+
+proc sky130::sky130_fd_pr__pfet_g5v0d16v0_draw {parameters} {
+ set newdict [dict create \
+ gate_type mvpfet \
+ diff_type mvpdiff \
+ diff_contact_type mvpdc \
+ plus_diff_type mvnsd \
+ plus_contact_type mvnsc \
+ poly_type poly \
+ poly_contact_type pc \
+ sub_type nwell \
+ diff_spacing 0.31 \
+ diff_tap_space 0.38 \
+ diff_gate_space 0.38 \
+ drain_proc sky130::draw_ldpmos_drain \
+ ]
+ set drawdict [dict merge $sky130::ruleset $newdict $parameters]
+ return [sky130::mos_draw $drawdict]
+}
+
+#----------------------------------------------------------------
# MOSFET: Check device parameters for out-of-bounds values
#----------------------------------------------------------------
@@ -6724,6 +6832,10 @@
return [sky130::mos_check sky130_fd_pr__nfet_g5v0d10v5 $parameters]
}
+proc sky130::sky130_fd_pr__nfet_g5v0d16v0_check {parameters} {
+ return [sky130::mos_check sky130_fd_pr__nfet_g5v0d16v0 $parameters]
+}
+
proc sky130::sky130_fd_pr__nfet_05v0_nvt_check {parameters} {
return [sky130::mos_check sky130_fd_pr__nfet_05v0_nvt $parameters]
}
@@ -6748,6 +6860,10 @@
return [sky130::mos_check sky130_fd_pr__pfet_g5v0d10v5 $parameters]
}
+proc sky130::sky130_fd_pr__pfet_g5v0d16v0_check {parameters} {
+ return [sky130::mos_check sky130_fd_pr__pfet_g5v0d16v0 $parameters]
+}
+
proc sky130::sky130_fd_pr__cap_var_lvt_check {parameters} {
return [sky130::mos_check sky130_fd_pr__cap_var_lvt $parameters]
}
diff --git a/sky130/magic/sky130.tech b/sky130/magic/sky130.tech
index 8d4ad2f..9cde973 100644
--- a/sky130/magic/sky130.tech
+++ b/sky130/magic/sky130.tech
@@ -58,6 +58,8 @@
# sky130_fd_pr__pfet_g5v0d10v5 mvpfet thickox pFET
# sky130_fd_pr__nfet_g5v0d10v5 mvnfet thickox nFET
# sky130_fd_pr__nfet_01v8_nvt mvnnfet thickox native nFET
+# sky130_fd_pr__nfet_g5v0d16v0 mvnfet extended-drain nFET***
+# sky130_fd_pr__pfet_g5v0d16v0 mvpfet extended-drain pFET***
# sky130_fd_pr__diode_pw2nd_05v5 ndiode n+ diff diode
# sky130_fd_pr__diode_pw2nd_05v5_lvt ndiodelvt low Vt n+ diff diode
# sky130_fd_pr__diode_pw2nd_05v5_nvt nndiode diode with nndiff
@@ -95,6 +97,10 @@
# outside of the standard cell except for the DRC rule for
# FET to diffusion contact spacing (which is 0.05um, not 0.055um)
#
+# (***) The extended-drain devices have the same identifying
+# FET type as the thick oxide devices, but the drain side of the
+# device is represented by layer extdrain extending to nsd or psd.
+#
#-------------------------------------------------------------
# The following devices are not extracted but are represented
# only by script-generated subcells in the PDK.
@@ -201,6 +207,7 @@
active nsubdiffcont,nsubstratencontact,nsc,ntapc
active mvpsubdiffcont,mvpsubstratepcontact,mvpsc,mvptapc
active mvnsubdiffcont,mvnsubstratencontact,mvnsc,mvntapc
+ active extdrain,ed
-active obsactive
-active mvobsactive
@@ -522,6 +529,8 @@
mvnsc ndiff_in_nwell metal1 contact_X'es hvndiff_mask
mvpsc pdiff_in_pwell metal1 contact_X'es hvpdiff_mask
+ extdrain nselect pselect
+
poly polysilicon
polyfill polysilicon
pc polysilicon metal1 contact_X'es
@@ -721,8 +730,8 @@
#-----------------------------------------------------
connect
- *nwell,*nsd,*mvnsd,dnwell,pnp,photo *nwell,*nsd,*mvnsd,dnwell,pnp,photo
- pwell,*psd,*mvpsd,npn,isosub pwell,*psd,*mvpsd,npn,isosub
+ *nwell,*nsd,*mvnsd,dnwell,pnp,photo,ed *nwell,*nsd,*mvnsd,dnwell,pnp,photo,ed
+ pwell,*psd,*mvpsd,npn,isosub,ed pwell,*psd,*mvpsd,npn,isosub,ed
*li,coreli,lifill *li,coreli,lifill
*m1,m1fill,obsmcon *m1,m1fill,obsmcon
#ifdef RERAM
@@ -801,9 +810,21 @@
# NWELL
#----------------------------------------------------------------
- layer NWELL allnwell
+ # Generate n-well under extended-drain nFET
+ templayer extnwell
+ bloat-or *mvnsd * 0 extdrain 1150
+ and-not *mvnsd
+ grow 660
+
+ # Erase n-well under extended-drain pFET
+ templayer extpwell
+ bloat-or *mvpsd * 0 extdrain 590
+ and-not *mvpsd
+ grow 860
+
+ layer NWELL allnwell,extnwell
bloat-all rpw dnwell
- and-not rpw,pwell
+ and-not rpw,pwell,extpwell
calma 64 20
layer WELLTXT
@@ -830,7 +851,13 @@
# DIFF
#----------------------------------------------------------------
+ # Extended-drain FETs cut the diffusion under the gate
+ templayer ldbreak
+ bloat-or *mvnsd * 0 extdrain 1585
+ bloat-or *mvpsd * 0 extdrain 1190
+
layer DIFF allnactivenontap,allpactivenontap,allactiveres
+ and-not ldbreak
calma 65 20
layer DIFFTXT
@@ -900,6 +927,15 @@
calma 93 44
#----------------------------------------------------------------
+# EDID (Extended drain identifier)
+#----------------------------------------------------------------
+
+ layer EDID
+ bloat-all extdrain *mvnsd,*mvpsd,mvnfet,mvpfet,*mvndiff,*mvpdiff
+ labels extdrain
+ calma 81 57
+
+#----------------------------------------------------------------
# LVID
#----------------------------------------------------------------
@@ -2362,7 +2398,7 @@
scalefactor 10 nanometers
gridlimit 5
- options ignore-unknown-layer-labels no-reconnect-labels
+ options ignore-unknown-layer-labels
#ifndef MIM
ignore CAPM
@@ -2380,6 +2416,7 @@
ignore POLYMOD
ignore LOWTAPDENSITY
ignore FILLOBSPOLY
+ ignore FILLOBSFOM
ignore MET5BLOCK
ignore OUTLINE
ignore POLYCUT
@@ -3878,8 +3915,6 @@
and-not FILLOBSM5
labels FILLOBSM1,FILLOBSM2,FILLOBSM3,FILLOBSM4
- layer obsactive FILLOBSFOM
-
# MOS Varactor
layer var POLY
@@ -4256,6 +4291,15 @@
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)"
+ # Extended drain rules
+ edge4way space/a ed/a 5000 ~(space)/a 0 0 "LDNFET/LDPFET width < %d (denmos/depmos.2)"
+ edge4way (*mvndiff)/a mvnfet 1055 ~(ed)/a 0 0 "LDNFET length < %d (denmos.1)"
+ edge4way (*mvnsd)/a ed/a 2510 ~(*mvndiff)/a 0 0 \
+ "LDNFET drain to source < %d (denmos.6 + denmos.3)"
+ edge4way (*mvpdiff)/a mvpfet 1050 ~(ed)/a 0 0 "LDPFET length < %d (depmos.1)"
+ edge4way (*mvpsd)/a ed/a 2510 ~(*mvpdiff)/a 0 0 \
+ "LDPFET drain to source < %d (depmos.6 + depmos.3)"
+
area *nsd,*mvnsd 70110 150 "N-tap minimum area < 0.07011um^2 (nsd.10b)"
area *psd,*mvpsd 70110 150 "P-tap minimum area < 0.07011um^2 (psd.10b)"
@@ -6392,6 +6436,10 @@
device msubcircuit Ignore mvpfet *mvpdiff,mvpdiffres pwell,space/w nwell error +npn,pnp
# Extended drain devices (must appear before the regular devices)
+ device msubcircuit sky130_fd_pr__nfet_g5v0d16v0 mvnfet *mvndiff \
+ extdrain,*mvnsd pwell,space/w error l=l w=w a1=as p1=ps a2=ad p2=pd
+ device msubcircuit sky130_fd_pr__pfet_g5v0d16v0 mvpfet *mvpdiff \
+ extdrain,*mvpsd nwell error l=l w=w a1=as p1=ps a2=ad p2=pd
device msubcircuit sky130_fd_pr__nfet_20v0_nvt mvnnfet *mvndiff,mvndiffres \
dnwell pwell,space/w error l=l w=w a1=as a2=ad p1=ps p2=pd
device msubcircuit sky130_fd_pr__nfet_20v0 mvnfet *mvndiff,mvndiffres \