blob: 3fb970a02dda56641feb197039c573c791b395d7 [file] [log] [blame]
# Copyright 2022 GlobalFoundries PDK Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#===========================================================================================================================
#------------------------------------------- GF 0.18um MCU LVS RULE DECK --------------------------------------------------
#===========================================================================================================================
require 'time'
require "logger"
exec_start_time = Time.now
logger = Logger.new(STDOUT)
logger.formatter = proc do |severity, datetime, progname, msg|
"#{datetime}: Memory Usage (" + `pmap #{Process.pid} | tail -1`[10,40].strip + ") : #{msg}
"
end
#================================================
#----------------- FILE SETUP -------------------
#================================================
logger.info("Starting running GF180MCU Klayout LVS runset on %s" % [$input])
#=== GET LAYOUT ===
if $input
source($input)
logger.info("Layout file: #{$input}")
else
logger.info("No layout loaded, please add your layout file")
end
#=== GET THREADS ===
if $thr
threads($thr)
logger.info("Number of threads: #{$thr}")
else
threads(16)
logger.info("Number of threads: 16")
end
#=== GET REPORT ===
if $report
report_lvs($report)
logger.info("Final report: #{$report}")
else
report_lvs(source.cell_name+".lvsdb")
logger.info("Final report: #{source.cell_name}.lvsdb")
end
#=== GET SUBSTRATE NAME ===
if $lvs_sub
substrate_name = $lvs_sub
logger.info("Substrate name: #{$lvs_sub}")
else
substrate_name = "gf180mcu_gnd"
logger.info("No substrate name given, default name is gf180mcu_gnd")
end
#=== NET NAMES OPTION ===
# true: use net names instead of numbers
# false: use numbers for nets
if $spice_net_names
spice_with_net_names = $spice_net_names
logger.info("Extracted netlist with net names: #{$spice_net_names}")
else
spice_with_net_names = true
logger.info("Extracted netlist with net names: true")
end
#=== COMMENTS OPTION ===
# true: put in comments with details
# false: no comments
if $spice_comments
spice_with_comments = $spice_comments
logger.info("Extracted netlist with comments in details: #{$spice_comments}")
else
spice_with_comments = false
logger.info("Extracted netlist with comments in details: false")
end
if $target_netlist
target_netlist($target_netlist)
logger.info("Extracted netlist file: #{$target_netlist}")
else
target_netlist(File.join(File.dirname(RBA::CellView::active.filename), source.cell_name+"_extracted.cir"), write_spice(spice_with_net_names, spice_with_comments), "Extracted by KLayout with GF180 LVS runset on : #{Time.now.strftime("%d/%m/%Y %H:%M")}")
logger.info("Extracted netlist file: #{source.cell_name}_extracted.cir")
end
#=== EXTRACTION SCALE ===
if $scale
device_scaling(1000000)
logger.info("device_scaling: true")
end
#=== PRINT DETAILS ===
if $verbose == "true"
logger.info("Verbose mode: #{$verbose}")
verbose(true)
else
verbose(false)
logger.info("Verbose mode: false")
end
# === TILING MODE ===
if $run_mode == "tiling"
# use a tile size of 1mm - not used in deep mode-
# tiles(500.um)
# use a tile border of 10 micron:
# tile_borders(10.um)
tiles(1000)
logger.info("Tiling mode is enabled.")
elsif $run_mode == "deep"
#=== HIER MODE ===
deep
logger.info("deep mode is enabled.")
elsif $run_mode == "flat"
#=== FLAT MODE ===
flat
logger.info("flat mode is enabled.")
else
#=== FLAT MODE ===
flat
logger.info("flat mode is enabled.")
end # run_mode
#================================================
# --------------- CUSTOM CLASSES ----------------
#================================================
#====================== CUSTOM READER =========================
class SubcircuitModelsReader < RBA::NetlistSpiceReaderDelegate
def parse_element(s, element)
if element == "C"
super(s + " C=2e-16", element)
else
super
end
end
# implements the delegate interface:
# take and translate the element
def element(circuit, el, name, model, value, nets, params)
if el == "C"
if nets.size != 2
error("Capacitor needs two nodes")
end
# provide a device class
cls = circuit.netlist.device_class_by_name(model)
if ! cls
cls = RBA::DeviceClassCapacitor::new
cls.name = model
circuit.netlist.add(cls)
end
# create a device
device = circuit.create_device(cls, name)
# and configure the device
[ "A", "B" ].each_with_index do |t,index|
device.connect_terminal(t, nets[index])
end
# parameters in the model are given in micrometer units, so
# we need to translate the parameter values from SI to um values:
device.set_parameter("A", ((params["W"] || 0.0) * (params["L"] || 0.0)) * 1e12)
device.set_parameter("P", ((params["W"] || 0.0) + (params["L"] || 0.0)) * 2e6)
device.set_parameter("C", (params["C"] || 0.0))
elsif el == "R"
if nets.size == 3
# provide a device class
cls = circuit.netlist.device_class_by_name(model)
if ! cls
cls = RBA::DeviceClassResistorWithBulk::new
cls.name = model
circuit.netlist.add(cls)
end
# create a device
device = circuit.create_device(cls, name)
# and configure the device
[ "A", "B", "W" ].each_with_index do |t,index|
device.connect_terminal(t, nets[index])
end
elsif nets.size == 2
# provide a device class
cls = circuit.netlist.device_class_by_name(model)
if ! cls
cls = RBA::DeviceClassResistor::new
cls.name = model
circuit.netlist.add(cls)
end
# create a device
device = circuit.create_device(cls, name)
# and configure the device
[ "A", "B" ].each_with_index do |t,index|
device.connect_terminal(t, nets[index])
end
else
error("Resistor needs two or three nodes")
end
# parameters in the model are given in micrometer units, so
# we need to translate the parameter values from SI to um values:
device.set_parameter("W", ((params["W"] || 0.0) * (params["PAR"] || 1.0)) * 1e6)
device.set_parameter("L", ((params["L"] || 0.0) * (params["S"] || 1.0)) * 1e6)
device.set_parameter("R", (params["R"] * (params["S"] || 1.0) / (params["PAR"] || 1.0)))
else
return super
end
return true
end
end
# Instantiate a reader using the new delegate
reader = RBA::NetlistSpiceReader::new(SubcircuitModelsReader::new)
#=== GET NETLIST ===
if $schematic
schematic($schematic, reader)
logger.info("Netlist file: #{$schematic}")
else
puts "No schematic loaded , please add your netlist file"
logger.info("No schematic loaded , please add your netlist file")
end
class BResistor < RBA::DeviceClassResistorWithBulk
def initialize
super
enable_parameter("R", false)
enable_parameter("W", true)
enable_parameter("L", true)
end
end
class NResistor < RBA::DeviceClassResistor
def initialize
super
enable_parameter("R", false)
enable_parameter("W", true)
enable_parameter("L", true)
end
end
class MosCap < RBA::DeviceClassCapacitor
def initialize
super
enable_parameter("C", false)
enable_parameter("A", true)
enable_parameter("P", true)
end
end
class MIMCap < RBA::DeviceClassCapacitor
def initialize
super
enable_parameter("C", true)
enable_parameter("A", true)
enable_parameter("P", true)
end
end
#================================================
#------------- LAYERS DERIVATIONS ---------------
#================================================
logger.info("Read in polygons from layers.")
#=== DRAWINGS ===
comp = polygons(22 , 0 )
dnwell = polygons(12 , 0 )
nwell = polygons(21 , 0 )
lvpwell = polygons(204, 0 )
dualgate = polygons(55 , 0 )
poly2 = polygons(30 , 0 )
nplus = polygons(32 , 0 )
pplus = polygons(31 , 0 )
sab = polygons(49 , 0 )
esd = polygons(24 , 0 )
contact = polygons(33 , 0 )
metal1 = polygons(34 , 0 )
via1 = polygons(35 , 0 )
metal2 = polygons(36 , 0 )
via2 = polygons(38 , 0 )
metal3 = polygons(42 , 0 )
via3 = polygons(40 , 0 )
metal4 = polygons(46 , 0 )
via4 = polygons(41 , 0 )
metal5 = polygons(81 , 0 )
via5 = polygons(82 , 0 )
metaltop = polygons(53 , 0 )
pad = polygons(37 , 0 )
resistor = polygons(62 , 0 )
fhres = polygons(227, 0 )
fusetop = polygons(75 , 0 )
fusewindow_d = polygons(96 , 1 )
polyfuse = polygons(220, 0 )
mvsd = polygons(210, 0 )
mvpsd = polygons(11 , 39)
nat = polygons(5 , 0 )
comp_dummy = polygons(22 , 4 )
poly2_dummy = polygons(30 , 4 )
metal1_dummy = polygons(34 , 4 )
metal2_dummy = polygons(36 , 4 )
metal3_dummy = polygons(42 , 4 )
metal4_dummy = polygons(46 , 4 )
metal5_dummy = polygons(81 , 4 )
metaltop_dummy = polygons(53 , 4 )
metal1_slot = polygons(34 , 3 )
metal2_slot = polygons(36 , 3 )
metal3_slot = polygons(42 , 3 )
metal4_slot = polygons(46 , 3 )
metal5_slot = polygons(81 , 3 )
metaltop_slot = polygons(53 , 3 )
ubmpperi = polygons(183, 0 )
ubmparray = polygons(184, 0 )
ubmeplate = polygons(185, 0 )
schottky_diode = polygons(241, 0 )
zener = polygons(178, 0 )
res_mk = polygons(110, 5 )
opc_drc = polygons(124, 5 )
ndmy = polygons(111, 5 )
pmndmy = polygons(152, 5 )
v5_xtor = polygons(112, 1 )
cap_mk = polygons(117, 5 )
mos_cap_mk = polygons(166, 5 )
ind_mk = polygons(151, 5 )
diode_mk = polygons(115, 5 )
drc_bjt = polygons(127, 5 )
lvs_bjt = polygons(118, 5 )
mim_l_mk = polygons(117, 10)
latchup_mk = polygons(137, 5 )
guard_ring_mk = polygons(167, 5 )
otp_mk = polygons(173, 5 )
mtpmark = polygons(122, 5 )
neo_ee_mk = polygons(88 , 17)
sramcore = polygons(108, 5 )
lvs_rf = polygons(100, 5 )
lvs_drain = polygons(100, 7 )
ind_mk = polygons(151, 5 )
hvpolyrs = polygons(123, 5 )
lvs_io = polygons(119, 5 )
probe_mk = polygons(13 , 17)
esd_mk = polygons(24 , 5 )
lvs_source = polygons(100, 8 )
well_diode_mk = polygons(153, 51)
ldmos_xtor = polygons(226, 0 )
plfuse = polygons(125, 5 )
efuse_mk = polygons(80 , 5 )
mcell_feol_mk = polygons(11 , 17)
ymtp_mk = polygons(86 , 17)
dev_wf_mk = polygons(128, 17)
metal1_blk = polygons(34 , 5 )
metal2_blk = polygons(36 , 5 )
metal3_blk = polygons(42 , 5 )
metal4_blk = polygons(46 , 5 )
metal5_blk = polygons(81 , 5 )
metalt_blk = polygons(53 , 5 )
pr_bndry = polygons(0 , 0 )
mdiode = polygons(116, 5 )
metal1_res = polygons(110, 11)
metal2_res = polygons(110, 12)
metal3_res = polygons(110, 13)
metal4_res = polygons(110, 14)
metal5_res = polygons(110, 15)
metal6_res = polygons(110, 16)
border = polygons(63 , 0 )
logger.info("Read in labels from layers.")
#=== LABELS ===
comp_label = labels(22 , 10)
poly2_label = labels(30 , 10)
metal1_label = labels(34 , 10)
metal2_label = labels(36 , 10)
metal3_label = labels(42 , 10)
metal4_label = labels(46 , 10)
metal5_label = labels(81 , 10)
metaltop_label = labels(53 , 10)
#=== BULK LAYER ===
sub = polygon_layer
#================================================
#------------------ SWITCHES --------------------
#================================================
logger.info("Evaluate switches start.")
# METAL_TOP
if $metal_top
METAL_TOP = $metal_top
else
METAL_TOP = "9K"
end # METAL_TOP
logger.info("METAL_TOP Selected is %s" % [METAL_TOP])
# METAL_LEVEL
if $metal_level
METAL_LEVEL = $metal_level
else
METAL_LEVEL = "6LM"
end # METAL_LEVEL
logger.info("METAL_STACK Selected is %s" % [METAL_LEVEL])
if $poly_res
POLY_RES = $poly_res
else
POLY_RES = false
end # POLY_RES
logger.info("POLY_RES Selected is %s" % [POLY_RES])
if $mim_option
MIM_OPTION = $mim_option
else
MIM_OPTION = false
end # MIM_OPTION
if $mim_cap
MIM_CAP = $mim_cap
else
MIM_CAP = false
end # MIM_CAP
logger.info("MIM Option selected %s" % [MIM_OPTION])
if $schematic_simplify
SCH_SIMPLE = $schematic_simplify
else
SCH_SIMPLE = false
end # SCH_SIMPLE
logger.info("SCH_SIMPLE enabled %s" % [SCH_SIMPLE])
if $net_only
NET_ONLY = true
else
NET_ONLY = false
end
logger.info("NET_ONLY enabled %s" % [NET_ONLY])
if $top_lvl_pins
TOP_LVL_PINS = true
else
TOP_LVL_PINS = false
end
logger.info("TOP_LVL_PINS enabled %s" % [TOP_LVL_PINS])
if $combine
COMBINE = true
else
COMBINE = false
end
logger.info("COMBINE enabled %s" % [COMBINE])
if $purge
PURGE = true
else
PURGE = false
end
logger.info("PURGE enabled %s" % [PURGE])
if $purge_nets
PURGE_NETS = true
else
PURGE_NETS = false
end
logger.info("PURGE_NETS enabled %s" % [PURGE_NETS])
if $net_only || $top_lvl_pins || $combine || $purge || $purge_nets
SIMPLIFY = false
else
SIMPLIFY = true
end # SIMPLIFY
logger.info("SIMPLIFY enabled %s" % [SIMPLIFY])
logger.info("Evaluate switches end.")
#================================================
#------------- METAL LEVEL SWITCHES -------------
#================================================
if METAL_LEVEL == "6LM"
top_via = via5
topmin1_via = via4
top_metal = metaltop
topmin1_metal = metal5
elsif METAL_LEVEL == "5LM"
top_via = via4
topmin1_via = via3
top_metal = metal5
topmin1_metal = metal4
elsif METAL_LEVEL == "4LM"
top_via = via3
topmin1_via = via2
top_metal = metal4
topmin1_metal = metal3
elsif METAL_LEVEL == "3LM"
top_via = via2
topmin1_via = via1
top_metal = metal3
topmin1_metal = metal2
elsif METAL_LEVEL == "2LM"
top_via = via1
topmin1_via = via1
top_metal = metal2
topmin1_metal = metal1
end #METAL_LEVEL
#================================================================
#------------------------- MAIN RUNSET --------------------------
#================================================================
logger.info("GF180 LVS rules started")
#================================================
#------------- LAYERS DERIVATIONS ---------------
#================================================
logger.info("Starting deriving base layers.")
#==================================
# ------ GENERAL DERIVATIONS ------
#==================================
ncomp = comp.and(nplus)
pcomp = comp.and(pplus)
tgate = poly2.and(comp).not(res_mk)
ngate = nplus.and(tgate)
nsd = ncomp.outside(nwell).interacting(ngate).not(ngate).not(res_mk)
ptap = pcomp.outside(nwell).outside(dnwell).not(res_mk)
pgate = pplus.and(tgate)
psd = pcomp.inside(nwell).interacting(pgate).not(pgate).not(res_mk)
ntap = ncomp.inside(nwell).not(res_mk)
ngate_dw = ngate.and(lvpwell).and(dnwell)
ptap_dw = pcomp.inside(lvpwell).inside(dnwell).outside(well_diode_mk).not(res_mk)
pgate_dw = pgate.inside(dnwell).outside(lvpwell)
ntap_dw = ncomp.outside(lvpwell).inside(dnwell).not(res_mk)
psd_dw = pcomp.not(lvpwell).and(dnwell).interacting(pgate).not(pgate).not(res_mk)
nwell_con = nwell.not(res_mk)
lvpwell_con = lvpwell.not(res_mk)
poly2_con = poly2.not(res_mk).not(plfuse)
metal1_con = metal1.not(metal1_res)
metal2_con = metal2.not(metal2_res)
metal3_con = metal3.not(metal3_res)
metaltop_con = metaltop.not(metal6_res)
#==================================
# ------ MOSFET DERIVATIONS -------
#==================================
logger.info("Starting MOSFET DERIVATIONS")
# ==============
# ---- PMOS ----
# ==============
logger.info("Starting PMOS layers DERIVATIONS")
# 3.3V PMOS transistor outside DNWELL
pgate_3p3v = pgate.not(v5_xtor).not(dualgate).not(dnwell).not(sab).not_interacting(mos_cap_mk)
# 5V PMOS transistor outside DNWELL
pgate_5v = pgate.and(v5_xtor).and(dualgate).not(dnwell).not(sab).not_interacting(mos_cap_mk)
# 6V PMOS transistor outside DNWELL
pgate_6v = pgate.not(v5_xtor).and(dualgate).not(nat).not(ldmos_xtor).not(dnwell).not(sab).not_interacting(mos_cap_mk)
# 3.3V PMOS transistor inside DNWELL
pgate_3p3v_dw = pgate_dw.not(v5_xtor).not(dualgate).not(sab).not_interacting(mos_cap_mk)
# 5V PMOS transistor inside DNWELL
pgate_5v_dw = pgate_dw.and(v5_xtor).and(dualgate).not(sab).not_interacting(mos_cap_mk)
# 6V PMOS transistor inside DNWELL
pgate_6v_dw = pgate_dw.not(v5_xtor).and(dualgate).not(nat).not(ldmos_xtor).not(sab).not_interacting(mos_cap_mk)
# LDPMOS transistor
pgate_ldmos = pgate_dw.interacting(mvpsd).not(v5_xtor).and(dualgate).and(ldmos_xtor).and(dnwell).not(mvpsd).not_interacting(mos_cap_mk)
pd_ldmos = psd_dw.not(v5_xtor).and(dualgate).and(ldmos_xtor).and(dnwell).and(mvpsd)
ps_ldmos = psd_dw.not(v5_xtor).and(dualgate).and(ldmos_xtor).and(dnwell).not(mvpsd)
psd_ldmos = pcomp.not(v5_xtor).and(dualgate).and(ldmos_xtor).and(dnwell).interacting(mvpsd).sized(0.29.um).sized(-0.29.um).extents.not(pgate_ldmos)
# ==============
# ---- NMOS ----
# ==============
logger.info("Starting NMOS layers DERIVATIONS")
# 3.3V NMOS transistor outside DNWELL
ngate_3p3v = ngate.not(v5_xtor).not(dualgate).not(dnwell).not(sab).not_interacting(mos_cap_mk)
# 5V NMOS transistor outside DNWELL
ngate_5v = ngate.and(v5_xtor).and(dualgate).not(dnwell).not(sab).not_interacting(mos_cap_mk)
# 6V NMOS transistor outside DNWELL
ngate_6v = ngate.not(v5_xtor).and(dualgate).not(nat).not(ldmos_xtor).not(dnwell).not(sab).not_interacting(mos_cap_mk)
# 3.3V NMOS transistor inside DNWELL
ngate_3p3v_dw = ngate_dw.not(v5_xtor).not(dualgate).not(sab).not_interacting(mos_cap_mk)
# 5V NMOS transistor inside DNWELL
ngate_5v_dw = ngate_dw.and(v5_xtor).and(dualgate).not(sab).not_interacting(mos_cap_mk)
# 6V NMOS transistor inside DNWELL
ngate_6v_dw = ngate_dw.not(v5_xtor).and(dualgate).not(nat).not(ldmos_xtor).not(sab).not_interacting(mos_cap_mk)
# Native Vt NMOS transistor
ngate_nat = ngate.not(v5_xtor).and(dualgate).and(nat).not_interacting(mos_cap_mk)
# LDNMOS transistor
ngate_ldmos = ngate.interacting(mvsd).not(v5_xtor).and(dualgate).and(ldmos_xtor).not(dnwell).not(mvsd).not_interacting(mos_cap_mk)
nd_ldmos = ncomp.not(ngate).not(v5_xtor).and(dualgate).and(ldmos_xtor).not(dnwell).and(mvsd)
ns_ldmos = nsd.not(v5_xtor).and(dualgate).and(ldmos_xtor).not(dnwell).not(mvsd)
nsd_ldmos = ncomp.not(v5_xtor).and(dualgate).and(ldmos_xtor).not(dnwell).interacting(mvsd).sized(0.37.um).sized(-0.37.um).extents.not(ngate_ldmos)
#================================
# ------ BJT DERIVATIONS --------
#================================
logger.info("Starting BJT DERIVATIONS")
# ==============
# ---- vnpn ----
# ==============
logger.info("Starting vnpn layers DERIVATIONS")
# vnpn general nodes DERIVATIONS
vnpn_e = ncomp.interacting(lvs_bjt).inside(dnwell)
vnpn_b = pcomp.and(lvpwell).inside(dnwell).inside(drc_bjt)
vnpn_c = ncomp.inside(dnwell).outside(lvs_bjt).inside(drc_bjt)
# vnpn_10x10 nodes DERIVATIONS
vnpn_10x10_e = vnpn_e.with_area(99.5.um,100.5.um).interacting(vnpn_e.edges.with_length(9.8.um,10.2.um))
vnpn_10x10_b = vnpn_b.interacting(vnpn_b.extents.interacting(vnpn_10x10_e))
vnpn_10x10_c = vnpn_c.interacting(vnpn_c.extents.interacting(vnpn_10x10_e))
# vnpn_5x5 nodes DERIVATIONS
vnpn_5x5_e = vnpn_e.with_area(24.5.um,25.5.um).interacting(vnpn_e.edges.with_length(4.8.um,5.2.um))
vnpn_5x5_b = vnpn_b.interacting(vnpn_b.extents.interacting(vnpn_5x5_e))
vnpn_5x5_c = vnpn_c.interacting(vnpn_c.extents.interacting(vnpn_5x5_e))
# vnpn_0p54x16 nodes DERIVATIONS
vnpn_0p54x16_e = vnpn_e.with_area(8.um,9.um).interacting(vnpn_e.edges.with_length(15.5.um,16.5.um))
vnpn_0p54x16_b = vnpn_b.interacting(vnpn_b.extents.interacting(vnpn_0p54x16_e))
vnpn_0p54x16_c = vnpn_c.interacting(vnpn_c.extents.interacting(vnpn_0p54x16_e))
# vnpn_0p54x8 nodes DERIVATIONS
vnpn_0p54x8_e = vnpn_e.with_area(4.um,5.um).interacting(vnpn_e.edges.with_length(7.5.um,8.5.um))
vnpn_0p54x8_b = vnpn_b.interacting(vnpn_b.extents.interacting(vnpn_0p54x8_e))
vnpn_0p54x8_c = vnpn_c.interacting(vnpn_c.extents.interacting(vnpn_0p54x8_e))
# vnpn_0p54x4 nodes DERIVATIONS
vnpn_0p54x4_e = vnpn_e.with_area(1.5.um,2.5.um).interacting(vnpn_e.edges.with_length(3.8.um,4.2.um))
vnpn_0p54x4_b = vnpn_b.interacting(vnpn_b.extents.interacting(vnpn_0p54x4_e))
vnpn_0p54x4_c = vnpn_c.interacting(vnpn_c.extents.interacting(vnpn_0p54x4_e))
# vnpn_0p54x2 nodes DERIVATIONS
vnpn_0p54x2_e = vnpn_e.with_area(0.8.um,1.5.um).interacting(vnpn_e.edges.with_length(1.8.um,2.2.um))
vnpn_0p54x2_b = vnpn_b.interacting(vnpn_b.extents.interacting(vnpn_0p54x2_e))
vnpn_0p54x2_c = vnpn_c.interacting(vnpn_c.extents.interacting(vnpn_0p54x2_e))
# ==============
# ---- vpnp ----
# ==============
logger.info("Starting vpnp layers DERIVATIONS")
# vpnp general nodes DERIVATIONS
vpnp_e = pcomp.inside(nwell).interacting(lvs_bjt)
vpnp_b = ncomp.and(nwell).inside(drc_bjt)
vpnp_c = ptap.outside(lvs_bjt).inside(drc_bjt)
# vpnp_10x10 nodes DERIVATIONS
vpnp_10x10_e = vpnp_e.with_area(99.5.um,100.5.um).interacting(vpnp_e.edges.with_length(9.8.um,10.2.um))
vpnp_10x10_b = vpnp_b.interacting(vpnp_b.extents.interacting(vpnp_10x10_e))
vpnp_10x10_c = vpnp_c.interacting(vpnp_c.extents.interacting(vpnp_10x10_e))
# vpnp_5x5 nodes DERIVATIONS
vpnp_5x5_e = vpnp_e.with_area(24.5.um,25.5.um).interacting(vpnp_e.edges.with_length(4.8.um,5.2.um))
vpnp_5x5_b = vpnp_b.interacting(vpnp_b.extents.interacting(vpnp_5x5_e))
vpnp_5x5_c = vpnp_c.interacting(vpnp_c.extents.interacting(vpnp_5x5_e))
# vpnp_0p42x10 nodes DERIVATIONS
vpnp_0p42x10_e = vpnp_e.with_area(4.um,4.5.um).interacting(vpnp_e.edges.with_length(9.8.um,10.2.um))
vpnp_0p42x10_b = vpnp_b.interacting(vpnp_b.extents.interacting(vpnp_0p42x10_e))
vpnp_0p42x10_c = vpnp_c.interacting(vpnp_c.extents.interacting(vpnp_0p42x10_e))
# vpnp_0p42x5 nodes DERIVATIONS
vpnp_0p42x5_e = vpnp_e.with_area(2.um,2.2.um).interacting(vpnp_e.edges.with_length(4.8.um,5.2.um))
vpnp_0p42x5_b = vpnp_b.interacting(vpnp_b.extents.interacting(vpnp_0p42x5_e))
vpnp_0p42x5_c = vpnp_c.interacting(vpnp_c.extents.interacting(vpnp_0p42x5_e))
#================================
# ----- DIODE DERIVATIONS -------
#================================
logger.info("Starting DIODE DERIVATIONS")
# np_3p3 diode
np_3p3_terminal_n = ncomp.not(v5_xtor).not(dualgate).outside(dnwell).interacting(diode_mk)
# np_3p3_dw diode
np_3p3_dw_terminal_n = ncomp.not(v5_xtor).not(dualgate).inside(dnwell).interacting(diode_mk)
# np_6p0 diode
np_6p0_terminal_n = ncomp.and(dualgate).outside(dnwell).interacting(diode_mk)
# np_6p0_dw diode
np_6p0_dw_terminal_n = ncomp.and(dualgate).inside(dnwell).interacting(diode_mk)
# pn_3p3 diode
pn_3p3_terminal_p = pcomp.not(v5_xtor).not(dualgate).outside(dnwell).interacting(diode_mk)
# pn_3p3_dw diode
pn_3p3_dw_terminal_p = pcomp.not(v5_xtor).not(dualgate).inside(dnwell).interacting(diode_mk)
# pn_6p0 diode
pn_6p0_terminal_p = pcomp.and(dualgate).outside(dnwell).interacting(diode_mk)
# pn_6p0_dw diode
pn_6p0_dw_terminal_p = pcomp.and(dualgate).inside(dnwell).interacting(diode_mk)
# nwp_3p3 diode
nwp_3p3_terminal_p = pcomp.not(v5_xtor).not(dualgate).outside(dnwell).interacting(well_diode_mk)
nwp_3p3_terminal_n = well_diode_mk.not(v5_xtor).not(dualgate).covering(nwell)
# nwp_6p0 diode
nwp_6p0_terminal_p = pcomp.and(dualgate).outside(dnwell).interacting(well_diode_mk)
nwp_6p0_terminal_n = well_diode_mk.and(dualgate).covering(nwell)
# dnwpw_3p3 diode
dnwpw_3p3_terminal_p = lvpwell.not(v5_xtor).not(dualgate).interacting(well_diode_mk)
# dnwpw_6p0 diode
dnwpw_6p0_terminal_p = lvpwell.and(dualgate).interacting(well_diode_mk)
# dnwps_3p3 diode
dnwps_3p3_terminal_p = ptap.extents.not_interacting(lvpwell).not_covering(v5_xtor).not_covering(dualgate).interacting(well_diode_mk)
# dnwps_6p0 diode
dnwps_6p0_terminal_p = ptap.extents.not_interacting(lvpwell).covering(dualgate).interacting(well_diode_mk)
# sc_diode diode
sc_diode_terminal_n = ncomp.inside(dnwell).inside(schottky_diode)
sc_diode_terminal_p = metal1.inside(dnwell).not_interacting(sc_diode_terminal_n)
#================================
# ---- RESISTOR DERIVATIONS -----
#================================
logger.info("Starting RESISTOR DERIVATIONS")
# ===============
# --DIFF & WELL--
# ===============
# NPLUS_U
nplus_u_layer = ncomp.and(lvpwell).and(sab).and(res_mk).not(dnwell)
nplus_cont = ncomp.outside(nwell).not_interacting(ngate).interacting(res_mk).not(res_mk)
# NPLUS_U_DW
nplus_u_dw_layer = ncomp.and(lvpwell).and(sab).and(res_mk).and(dnwell)
# PPLUS_U
pplus_u_layer = pcomp.and(nwell).and(sab).and(res_mk).not(dnwell)
pplus_cont = pcomp.inside(nwell).not_interacting(pgate).interacting(res_mk).not(res_mk)
# PPLUS_U_DW
pplus_u_dw_layer = pcomp.and(sab).and(res_mk).and(dnwell)
pplus_dw_cont = pcomp.not(lvpwell).and(dnwell).not_interacting(pgate).interacting(res_mk).not(res_mk)
# NPLUS_S
nplus_s_layer = ncomp.and(lvpwell).and(res_mk).not_interacting(sab).not(dnwell)
# NPLUS_S_DW
nplus_s_dw_layer = ncomp.and(lvpwell).and(res_mk).and(dnwell).not_interacting(sab)
# PPLUS_S
pplus_s_layer = pcomp.and(nwell).and(res_mk).not_interacting(sab).not(dnwell)
# PPLUS_S_DW
pplus_s_dw_layer = pcomp.not_interacting(sab).and(res_mk).and(dnwell).not_interacting(sab)
# NWELL
nwell_res = nwell.and(res_mk).not(dnwell).not_covering(comp)
# PWELL
pwell_res = lvpwell.and(res_mk).and(dnwell).not_covering(comp)
# ==============
# ---- POLY ----
# ==============
# NPOLYF_U
npolyf_u_layer = nplus.and(poly2).and(sab).and(res_mk).not(dnwell)
# NPOLYF_U_DW
npolyf_u_dw_layer = nplus.and(poly2).and(sab).and(res_mk).and(dnwell)
# PPOLYF_U
ppolyf_u_layer = pplus.and(poly2).and(sab).and(res_mk).not_interacting(resistor).not(dnwell)
# PPOLYF_U_DW
ppolyf_u_dw_layer = pplus.and(poly2).and(sab).and(res_mk).not_interacting(resistor).and(dnwell)
# NPOLYF_S
npolyf_s_layer = nplus.and(poly2).and(res_mk).not(dnwell).not_interacting(sab)
# NPOLYF_S_DW
npolyf_s_dw_layer = nplus.and(poly2).and(res_mk).and(dnwell).not_interacting(sab)
# PPOLYF_S
ppolyf_s_layer = pplus.and(poly2).and(res_mk).not(dnwell).not_interacting(sab)
# PPOLYF_S_DW
ppolyf_s_dw_layer = pplus.and(poly2).and(res_mk).and(dnwell).not_interacting(sab)
# ==============
# --H-POLY RES--
# ==============
if POLY_RES == "1k"
# PPOLYF_U_1K
ppolyf_u_1k_layer = poly2.and(sab).and(res_mk).and(resistor).not(dnwell).not(v5_xtor).not(dualgate)
# PPOLYF_U_DW_1K
ppolyf_u_1k_dw_layer = poly2.and(res_mk).and(dnwell).and(resistor).not(v5_xtor).not(dualgate)
# PPOLYF_U_1K_6p0
ppolyf_u_1k_6p0_layer = poly2.and(sab).and(res_mk).and(resistor).not(dnwell).not(v5_xtor).and(dualgate)
# PPOLYF_U_DW_1K_6p0
ppolyf_u_1k_6p0_dw_layer = poly2.and(res_mk).and(dnwell).and(resistor).not(v5_xtor).and(dualgate)
elsif POLY_RES == "2k"
# PPOLYF_U_2K
ppolyf_u_2k_layer = poly2.and(sab).and(res_mk).and(resistor).not(dnwell).not(v5_xtor).not(dualgate)
# PPOLYF_U_DW_2K
ppolyf_u_2k_dw_layer = poly2.and(res_mk).and(dnwell).and(resistor).not(v5_xtor).not(dualgate)
# PPOLYF_U_2K_6p0
ppolyf_u_2k_6p0_layer = poly2.and(sab).and(res_mk).and(resistor).not(dnwell).not(v5_xtor).and(dualgate)
# PPOLYF_U_DW_2K_6p0
ppolyf_u_2k_6p0_dw_layer = poly2.and(res_mk).and(dnwell).and(resistor).not(v5_xtor).and(dualgate)
elsif POLY_RES == "3k"
# PPOLYF_U_3K
ppolyf_u_3k_layer = poly2.and(sab).and(res_mk).and(resistor).not(dnwell).not(v5_xtor).not(dualgate)
# PPOLYF_U_DW_3K
ppolyf_u_3k_dw_layer = poly2.and(res_mk).and(dnwell).and(resistor).not(v5_xtor).not(dualgate)
# PPOLYF_U_3K_6p0
ppolyf_u_3k_6p0_layer = poly2.and(sab).and(res_mk).and(resistor).not(dnwell).not(v5_xtor).and(dualgate)
# PPOLYF_U_DW_3K_6p0
ppolyf_u_3k_6p0_dw_layer = poly2.and(res_mk).and(dnwell).and(resistor).not(v5_xtor).and(dualgate)
end
# ===============
# ---- METAL ----
# ===============
# Metal1 resistor
rm1_res = metal1.and(metal1_res)
# Metal2 resistor
rm2_res = metal2.and(metal2_res)
# Metal3 resistor
rm3_res = metal3.and(metal3_res)
# Metaltop resistor
tm_res = metaltop.and(metal6_res)
#==================================
# ------ MIMCAP DERIVATIONS -------
#==================================
logger.info("Starting MIMCAP DERIVATIONS")
# mim option A
mim_virtual = fusetop.sized(1.06.um).and(metal2.interacting(fusetop))
metal2_ncap = metal2_con.not(mim_virtual)
fuse_cap = fusetop.interacting(cap_mk).interacting(mim_l_mk)
# mim_option B
mimtm_virtual = fusetop.sized(1.06.um).and(topmin1_metal.interacting(fusetop))
metal3_ncap = metal3_con.not(mimtm_virtual)
metal4_ncap = metal4.not(mimtm_virtual)
metal5_ncap = metal5.not(mimtm_virtual)
#==================================
# ------ MOSCAP DERIVATIONS -------
#==================================
logger.info("Starting MOSCAP DERIVATIONS")
# nmoscap_3p3 capacitor
nmos_gate_3p3 = ngate.not(v5_xtor).not(dualgate).outside(dnwell).interacting(mos_cap_mk)
# nmoscap_3p3_dw capacitor
nmos_gate_3p3_dw = ngate.not(v5_xtor).not(dualgate).inside(dnwell).interacting(mos_cap_mk)
# pmoscap_3p3 capacitor
pmos_gate_3p3 = pgate.not(v5_xtor).not(dualgate).outside(dnwell).interacting(mos_cap_mk)
# pmoscap_3p3_dw capacitor
pmos_gate_3p3_dw = pgate.not(v5_xtor).not(dualgate).inside(dnwell).interacting(mos_cap_mk)
# nmoscap_6p0 capacitor
nmos_gate_6p0 = ngate.and(dualgate).outside(dnwell).interacting(mos_cap_mk)
# nmoscap_6p0_dw capacitor
nmos_gate_6p0_dw = ngate.and(dualgate).inside(dnwell).interacting(mos_cap_mk)
# pmoscap_6p0 capacitor
pmos_gate_6p0 = pgate.and(dualgate).outside(dnwell).interacting(mos_cap_mk)
# pmoscap_6p0_dw capacitor
pmos_gate_6p0_dw = pgate.and(dualgate).inside(dnwell).interacting(mos_cap_mk)
# nmoscap_3p3_b capacitor
nmoscap_3p3_b = ngate.not(v5_xtor).not(dualgate).inside(nwell).interacting(mos_cap_mk)
# pmoscap_3p3_b capacitor
pmoscap_3p3_b = pgate.not(v5_xtor).not(dualgate).inside(ptap).interacting(mos_cap_mk)
# nmoscap_6p0_b capacitor
nmoscap_6p0_b = ngate.and(dualgate).inside(nwell).interacting(mos_cap_mk)
# pmoscap_6p0_b capacitor
pmoscap_6p0_b = pgate.and(dualgate).inside(ptap).interacting(mos_cap_mk)
#================================
# ------ ESD DERIVATIONS --------
#================================
logger.info("Starting MOS SAB DERIVATIONS")
# ==============
# ---- PMOS ----
# ==============
logger.info("Starting PMOS SAB DERIVATIONS")
# 3.3V ESD PMOS transistor outside DNWELL
pgate_sab_3p3v = pgate.not(v5_xtor).not(dualgate).not(dnwell).and(esd_mk).interacting(sab)
# 5V ESD PMOS transistor outside DNWELL
pgate_sab_5v = pgate.and(v5_xtor).and(dualgate).not(dnwell).and(esd_mk).interacting(sab)
# 6V ESD PMOS transistor outside DNWELL
pgate_sab_6v = pgate.not(v5_xtor).and(dualgate).not(dnwell).and(esd_mk).interacting(sab)
# 3.3V ESD PMOS transistor inside DNWELL
pgate_dw_sab_3p3v = pgate_dw.not(v5_xtor).not(dualgate).and(esd_mk).interacting(sab)
# 5V ESD PMOS transistor inside DNWELL
pgate_dw_sab_5v = pgate_dw.and(v5_xtor).and(dualgate).and(esd_mk).interacting(sab)
# 6V ESD PMOS transistor inside DNWELL
pgate_dw_sab_6v = pgate_dw.not(v5_xtor).and(dualgate).and(esd_mk).interacting(sab)
# ==============
# ---- NMOS ----
# ==============
logger.info("Starting NMOS SAB DERIVATIONS")
# 3.3V ESD NMOS transistor outside DNWELL
ngate_sab_3p3v = ngate.not(v5_xtor).not(dualgate).not(dnwell).and(esd_mk).interacting(sab)
# 5V ESD NMOS transistor outside DNWELL
ngate_sab_5v = ngate.and(v5_xtor).and(dualgate).not(dnwell).and(esd_mk).interacting(sab)
# 6V ESD NMOS transistor outside DNWELL
ngate_sab_6v = ngate.not(v5_xtor).and(dualgate).not(dnwell).and(esd_mk).interacting(sab)
# 3.3V ESD NMOS transistor inside DNWELL
ngate_dw_sab_3p3v = ngate_dw.not(v5_xtor).not(dualgate).and(esd_mk).interacting(sab)
# 5V ESD NMOS transistor inside DNWELL
ngate_dw_sab_5v = ngate_dw.and(v5_xtor).and(dualgate).and(esd_mk).interacting(sab)
# 6V ESD NMOS transistor inside DNWELL
ngate_dw_sab_6v = ngate_dw.not(v5_xtor).and(dualgate).and(esd_mk).interacting(sab)
#================================
# ------ EFUSE DERIVATIONS ------
#================================
logger.info("Starting NMOS EFUSE DERIVATIONS")
cathode = poly2.inside(efuse_mk).not(lvs_source.or(plfuse))
anode = poly2.and(lvs_source).inside(efuse_mk)
efuse_link = (poly2).and(plfuse).inside(efuse_mk)
efuse_con_layer = cathode | anode
#================================================
#------------ DEVICES CONNECTIVITY --------------
#================================================
logger.info("Starting GF180 LVS connectivity setup")
#================================
# ----- GENERAL CONNECTIONS -----
#================================
logger.info("Starting GF180 LVS connectivity setup (Inter-layer)")
# Inter-layer
connect(sub , ptap)
connect(lvpwell_con , ptap)
connect(lvpwell_con , ptap_dw)
connect(dnwell , ntap_dw)
connect(nwell_con , ntap)
connect(ptap , contact)
connect(ptap_dw , contact)
connect(ntap , contact)
connect(ntap_dw , contact)
connect(psd , contact)
connect(psd_dw , contact)
connect(nsd , contact)
connect(poly2_con , contact)
connect(contact , metal1_con)
connect(metal1_con , via1)
connect(via1 , metal2_ncap)
connect(metal2_ncap , via2)
connect(via2 , metal3_ncap)
connect(metal3_ncap , via3)
connect(via3 , metal4_ncap)
connect(metal4_ncap , via4)
connect(via4 , metal5_ncap)
connect(metal5_ncap , via5)
connect(via5 , metaltop_con)
logger.info("Starting GF180 LVS connectivity setup (Attaching labels)")
# Attaching labels
connect(comp , comp_label)
connect(poly2_con , poly2_label)
connect(metal1_con , metal1_label)
connect(metal2_ncap , metal2_label)
connect(metal3_ncap , metal3_label)
connect(metal4_ncap , metal4_label)
connect(metal5_ncap , metal5_label)
connect(metaltop_con, metaltop_label)
logger.info("Starting GF180 LVS connectivity setup (Global)")
# Global
connect_global(sub , substrate_name)
logger.info("Starting GF180 LVS connectivity setup (Multifinger Devices)")
# Multifinger Devices
connect_implicit("*")
#================================
# ----- MOSFET CONNECTIONS ------
#================================
logger.info("Starting LVS MOSFET CONNECTIONS")
connect(psd_dw, contact)
connect(nd_ldmos, contact)
connect(ns_ldmos, contact)
connect(pd_ldmos, contact)
connect(ps_ldmos, contact)
#================================
# ------ BJT CONNECTIONS --------
#================================
logger.info("Starting LVS BJT CONNECTIONS")
# ==============
# ---- vnpn ----
# ==============
# vnpn_10x10 nodes connections
connect(vnpn_10x10_e,contact)
connect(vnpn_10x10_b,contact)
connect(vnpn_10x10_c,contact)
# vnpn_5x5 nodes connections
connect(vnpn_5x5_e,contact)
connect(vnpn_5x5_b,contact)
connect(vnpn_5x5_c,contact)
# vnpn_0p54x16 nodes connections
connect(vnpn_0p54x16_e,contact)
connect(vnpn_0p54x16_b,contact)
connect(vnpn_0p54x16_c,contact)
# vnpn_0p54x8 nodes connections
connect(vnpn_0p54x8_e,contact)
connect(vnpn_0p54x8_b,contact)
connect(vnpn_0p54x8_c,contact)
# vnpn_0p54x4 nodes connections
connect(vnpn_0p54x4_e,contact)
connect(vnpn_0p54x4_b,contact)
connect(vnpn_0p54x4_c,contact)
# vnpn_0p54x2 nodes connections
connect(vnpn_0p54x2_e,contact)
connect(vnpn_0p54x2_b,contact)
connect(vnpn_0p54x2_c,contact)
# ==============
# ---- vpnp ----
# ==============
# vpnp_10x10 nodes connections
connect(vpnp_10x10_e,contact)
connect(vpnp_10x10_b,contact)
connect(vpnp_10x10_c,contact)
# vpnp_5x5 nodes connections
connect(vpnp_5x5_e,contact)
connect(vpnp_5x5_b,contact)
connect(vpnp_5x5_c,contact)
# vpnp_0p42x10 nodes connections
connect(vpnp_0p42x10_e,contact)
connect(vpnp_0p42x10_b,contact)
connect(vpnp_0p42x10_c,contact)
# vpnp_0p42x5 nodes connections
connect(vpnp_0p42x5_e,contact)
connect(vpnp_0p42x5_b,contact)
connect(vpnp_0p42x5_c,contact)
#================================
# ----- DIODE CONNECTIONS -------
#================================
logger.info("Starting LVS DIODE CONNECTIONS")
# np_3p3 diode
connect(np_3p3_terminal_n,contact)
# np_3p3_dw diode
connect(np_3p3_dw_terminal_n,contact)
# np_6p0 diode
connect(np_6p0_terminal_n,contact)
# np_6p0_dw diode
connect(np_6p0_dw_terminal_n,contact)
# pn_3p3 diode
connect(pn_3p3_terminal_p,contact)
# pn_3p3_dw diode
connect(pn_3p3_dw_terminal_p,contact)
# pn_6p0 diode
connect(pn_6p0_terminal_p,contact)
# pn_6p0_dw diode
connect(pn_6p0_dw_terminal_p,contact)
# nwp_3p3 diode
connect(nwp_3p3_terminal_p,contact)
connect(nwp_3p3_terminal_n,nwell)
# nwp_6p0 diode
connect(nwp_6p0_terminal_p,contact)
connect(nwp_6p0_terminal_n,nwell)
# dnwpw_3p3 diode
connect(dnwpw_3p3_terminal_p,contact)
# dnwpw_6p0 diode
connect(dnwpw_6p0_terminal_p,contact)
# dnwps_3p3 diode
connect(dnwps_3p3_terminal_p,ptap)
# dnwps_6p0 diode
connect(dnwps_6p0_terminal_p,ptap)
# sc_diode diode
connect(sc_diode_terminal_n,contact)
connect(sc_diode_terminal_p,schottky_diode)
#================================
# ---- RESISTOR DERIVATIONS -----
#================================
logger.info("Starting LVS RESISTOR CONNECTIONS")
connect(nplus_cont , contact)
connect(pplus_cont , contact)
connect(pplus_dw_cont, contact)
#==================================
# ------ MIMCAP CONNECTIONS -------
#==================================
logger.info("Starting LVS MIMCAP CONNECTIONS")
if MIM_OPTION == "A"
# mim option A
connect(metal2,mim_virtual)
connect(fuse_cap,via2)
elsif MIM_OPTION == "B"
# mim_option B
connect(topmin1_metal,mimtm_virtual)
connect(fuse_cap,top_via)
end
#================================
# ------ EFUSE CONNECTIONS ------
#================================
logger.info("Starting LVS EFUSE CONNECTIONS")
connect(cathode, contact)
connect(anode, contact)
#================================================
#------------- DEVICES EXTRACTION ---------------
#================================================
logger.info("Starting GF180 LVS DEVICES EXTRACTION")
#================================
# ----- MOSFET EXTRACTION -------
#================================
logger.info("Starting MOSFET EXTRACTION")
# ==============
# ---- PMOS ----
# ==============
logger.info("Starting PMOS EXTRACTION")
# 3.3V PMOS transistor outside DNWELL
logger.info("Extracting 3.3V PMOS transistor outside DNWEL")
extract_devices(mos4("pmos_3p3"), { "SD" => psd, "G" => pgate_3p3v, "tS" => psd, "tD" => psd, "tG" => poly2_con, "W" => nwell_con })
# 5V PMOS transistor outside DNWELL
logger.info("Extracting 5V PMOS transistor outside DNWELL")
extract_devices(mos4("pmos_5p0"), { "SD" => psd, "G" => pgate_5v, "tS" => psd, "tD" => psd, "tG" => poly2_con, "W" => nwell_con })
# 6V PMOS transistor outside DNWELL
logger.info("Extracting 6V PMOS transistor outside DNWELL")
extract_devices(mos4("pmos_6p0"), { "SD" => psd, "G" => pgate_6v, "tS" => psd, "tD" => psd, "tG" => poly2_con, "W" => nwell_con })
# 3.3V PMOS transistor inside DNWELL
logger.info("Extracting 3.3V PMOS transistor inside DNWELL")
extract_devices(mos4("pmos_3p3_dw"), { "SD" => psd_dw, "G" => pgate_3p3v_dw, "tS" => psd_dw, "tD" => psd_dw, "tG" => poly2_con, "W" => dnwell })
# 5V PMOS transistor inside DNWELL
logger.info("Extracting 5V PMOS transistor inside DNWELL")
extract_devices(mos4("pmos_5p0_dw"), { "SD" => psd_dw, "G" => pgate_5v_dw, "tS" => psd_dw, "tD" => psd_dw, "tG" => poly2_con, "W" => dnwell })
# 6V PMOS transistor inside DNWELL
logger.info("Extracting 6V PMOS transistor inside DNWELL")
extract_devices(mos4("pmos_6p0_dw"), { "SD" => psd_dw, "G" => pgate_6v_dw, "tS" => psd_dw, "tD" => psd_dw, "tG" => poly2_con, "W" => dnwell })
# LDPMOS transistor
logger.info("Extracting LDPMOS transistor")
extract_devices(mos4("pmos_10p0_asym"), { "SD" => psd_ldmos, "G" => pgate_ldmos, "tS" => ps_ldmos, "tD" => pd_ldmos, "tG" => poly2_con, "W" => dnwell })
# ==============
# ---- NMOS ----
# ==============
logger.info("Starting NMOS EXTRACTION")
# 3.3V NMOS transistor outside DNWELL
logger.info("3.3V NMOS transistor outside DNWELL")
extract_devices(mos4("nmos_3p3"), { "SD" => nsd, "G" => ngate_3p3v, "tS" => nsd, "tD" => nsd, "tG" => poly2_con, "W" => sub })
# 5V NMOS transistor outside DNWELL
logger.info("5V NMOS transistor outside DNWELL")
extract_devices(mos4("nmos_5p0"), { "SD" => nsd, "G" => ngate_5v, "tS" => nsd, "tD" => nsd, "tG" => poly2_con, "W" => sub })
# 6V NMOS transistor outside DNWELL
logger.info("6V NMOS transistor outside DNWELL")
extract_devices(mos4("nmos_6p0"), { "SD" => nsd, "G" => ngate_6v, "tS" => nsd, "tD" => nsd, "tG" => poly2_con, "W" => sub })
# 3.3V NMOS transistor inside DNWELL
logger.info("3.3V NMOS transistor inside DNWELL")
extract_devices(mos4("nmos_3p3_dw"), { "SD" => nsd, "G" => ngate_3p3v_dw, "tS" => nsd, "tD" => nsd, "tG" => poly2_con, "W" => lvpwell_con })
# 5V NMOS transistor inside DNWELL
logger.info("5V NMOS transistor inside DNWELL")
extract_devices(mos4("nmos_5p0_dw"), { "SD" => nsd, "G" => ngate_5v_dw, "tS" => nsd, "tD" => nsd, "tG" => poly2_con, "W" => lvpwell_con })
# 6V NMOS transistor inside DNWELL
logger.info("6V NMOS transistor inside DNWELL")
extract_devices(mos4("nmos_6p0_dw"), { "SD" => nsd, "G" => ngate_6v_dw, "tS" => nsd, "tD" => nsd, "tG" => poly2_con, "W" => lvpwell_con })
# Native Vt NMOS transistor
logger.info("Native Vt NMOS transistor")
extract_devices(mos4("nmos_6p0_nat"), { "SD" => nsd, "G" => ngate_nat, "tS" => nsd, "tD" => nsd, "tG" => poly2_con, "W" => sub })
# LDNMOS transistor
logger.info("Extracting LDNMOS transistor")
extract_devices(mos4("nmos_10p0_asym"), { "SD" => nsd_ldmos, "G" => ngate_ldmos, "tS" => ns_ldmos, "tD" => nd_ldmos, "tG" => poly2_con, "W" => sub })
#================================
# ------- BJT EXTRACTION --------
#================================
logger.info("Starting BJT EXTRACTION")
# ====================
# ------ vnpn --------
# ====================
logger.info("Starting vnpn BJT EXTRACTION")
# vnpn_10x10 BJT
ignore_parameter("vnpn_10x10","AE")
logger.info("Extracting vnpn_10x10 BJT")
extract_devices(bjt4("vnpn_10x10"), { "C" => vnpn_10x10_c.extents , "B" => vnpn_10x10_b.extents , "E" => vnpn_10x10_e,"S" => sub.extents,
"tC" => vnpn_10x10_c , "tB" => vnpn_10x10_b, "tE" => vnpn_10x10_e, "tS" => sub })
# vnpn_5x5 BJT
ignore_parameter("vnpn_5x5","AE")
logger.info("Extracting vnpn_5x5 BJT")
extract_devices(bjt4("vnpn_5x5"), { "C" => vnpn_5x5_c.extents , "B" => vnpn_5x5_b.extents , "E" => vnpn_5x5_e,"S" => sub.extents,
"tC" => vnpn_5x5_c , "tB" => vnpn_5x5_b, "tE" => vnpn_5x5_e, "tS" => sub })
# vnpn_0p54x16 BJT
ignore_parameter("vnpn_0p54x16","AE")
logger.info("Extracting vnpn_0p54x16 BJT")
extract_devices(bjt4("vnpn_0p54x16"), { "C" => vnpn_0p54x16_c.extents , "B" => vnpn_0p54x16_b.extents , "E" => vnpn_0p54x16_e,"S" => sub.extents,
"tC" => vnpn_0p54x16_c , "tB" => vnpn_0p54x16_b, "tE" => vnpn_0p54x16_e, "tS" => sub })
# vnpn_0p54x8 BJT
ignore_parameter("vnpn_0p54x8","AE")
logger.info("Extracting vnpn_0p54x8 BJT")
extract_devices(bjt4("vnpn_0p54x8"), { "C" => vnpn_0p54x8_c.extents , "B" => vnpn_0p54x8_b.extents , "E" => vnpn_0p54x8_e,"S" => sub.extents,
"tC" => vnpn_0p54x8_c , "tB" => vnpn_0p54x8_b, "tE" => vnpn_0p54x8_e, "tS" => sub })
# vnpn_0p54x4 BJT
ignore_parameter("vnpn_0p54x4","AE")
logger.info("Extracting vnpn_0p54x4 BJT")
extract_devices(bjt4("vnpn_0p54x4"), { "C" => vnpn_0p54x4_c.extents , "B" => vnpn_0p54x4_b.extents , "E" => vnpn_0p54x4_e,"S" => sub.extents,
"tC" => vnpn_0p54x4_c , "tB" => vnpn_0p54x4_b, "tE" => vnpn_0p54x4_e, "tS" => sub })
# vnpn_0p54x2 BJT
ignore_parameter("vnpn_0p54x2","AE")
logger.info("Extracting vnpn_0p54x2 BJT")
extract_devices(bjt4("vnpn_0p54x2"), { "C" => vnpn_0p54x2_c.extents , "B" => vnpn_0p54x2_b.extents , "E" => vnpn_0p54x2_e,"S" => sub.extents,
"tC" => vnpn_0p54x2_c , "tB" => vnpn_0p54x2_b, "tE" => vnpn_0p54x2_e, "tS" => sub })
# ====================
# ------- vpnp--------
# ====================
logger.info("Starting vpnp BJT EXTRACTION")
# vpnp_10x10 BJT
ignore_parameter("vpnp_10x10","AE")
logger.info("Extracting vpnp_10x10 BJT")
extract_devices(bjt3("vpnp_10x10"), { "C" => vpnp_10x10_c.extents , "B" => vpnp_10x10_b.extents , "E" => vpnp_10x10_e,
"tC" => vpnp_10x10_c , "tB" => vpnp_10x10_b, "tE" => vpnp_10x10_e })
# vpnp_5x5 BJT
ignore_parameter("vpnp_5x5","AE")
logger.info("Extracting vpnp_5x5 BJT")
extract_devices(bjt3("vpnp_5x5"), { "C" => vpnp_5x5_c.extents , "B" => vpnp_5x5_b.extents , "E" => vpnp_5x5_e,
"tC" => vpnp_5x5_c , "tB" => vpnp_5x5_b, "tE" => vpnp_5x5_e })
# vpnp_0p42x10 BJT
ignore_parameter("vpnp_0p42x10","AE")
logger.info("Extracting vpnp_0p42x10 BJT")
extract_devices(bjt3("vpnp_0p42x10"), { "C" => vpnp_0p42x10_c.extents , "B" => vpnp_0p42x10_b.extents , "E" => vpnp_0p42x10_e,
"tC" => vpnp_0p42x10_c , "tB" => vpnp_0p42x10_b, "tE" => vpnp_0p42x10_e })
# vpnp_0p42x5 BJT
ignore_parameter("vpnp_0p42x5","AE")
logger.info("Extracting vpnp_0p42x5 BJT")
extract_devices(bjt3("vpnp_0p42x5"), { "C" => vpnp_0p42x5_c.extents , "B" => vpnp_0p42x5_b.extents , "E" => vpnp_0p42x5_e,
"tC" => vpnp_0p42x5_c , "tB" => vpnp_0p42x5_b, "tE" => vpnp_0p42x5_e })
#================================
# ------ DIODE EXTRACTION -------
#================================
logger.info("Starting DIODE EXTRACTION")
# np_3p3 diode
logger.info("Extracting np_3p3 diode")
extract_devices(diode("np_3p3"), { "N" => np_3p3_terminal_n , "P" => lvpwell_con})
# np_3p3_dw diode
logger.info("Extracting np_3p3_dw diode")
extract_devices(diode("np_3p3_dw"), { "N" => np_3p3_dw_terminal_n , "P" => lvpwell_con})
# np_6p0 diode
logger.info("Extracting np_6p0 diode")
extract_devices(diode("np_6p0"), { "N" => np_6p0_terminal_n , "P" => lvpwell_con})
# np_6p0_dw diode
logger.info("Extracting np_6p0_dw diode")
extract_devices(diode("np_6p0_dw"), { "N" => np_6p0_dw_terminal_n , "P" => lvpwell_con})
# pn_3p3 diode
logger.info("Extracting pn_3p3 diode")
extract_devices(diode("pn_3p3"), { "N" => nwell_con , "P" => pn_3p3_terminal_p})
# pn_3p3_dw diode
logger.info("Extractingpn_3p3_dw diode")
extract_devices(diode("pn_3p3_dw"), { "N" => nwell_con , "P" => pn_3p3_dw_terminal_p})
# pn_6p0 diode
logger.info("Extracting pn_6p0 diode")
extract_devices(diode("pn_6p0"), { "N" => nwell_con , "P" => pn_6p0_terminal_p})
# pn_6p0_dw diode
logger.info("Extracting pn_6p0_dw diode")
extract_devices(diode("pn_6p0_dw"), { "N" => nwell_con , "P" => pn_6p0_dw_terminal_p})
# nwp_3p3 diode
logger.info("Extracting nwp_3p3 diode")
extract_devices(diode("nwp_3p3"), { "N" => nwp_3p3_terminal_n , "P" => nwp_3p3_terminal_p})
# nwp_6p0 diode
logger.info("Extracting nwp_6p0 diode")
extract_devices(diode("nwp_6p0"), { "N" => nwp_6p0_terminal_n , "P" => nwp_6p0_terminal_p})
# dnwpw_3p3 diode
logger.info("Extracting dnwpw_3p3 diode")
extract_devices(diode("dnwpw_3p3"), { "N" => dnwell , "P" => dnwpw_3p3_terminal_p})
# dnwpw_6p0 diode
logger.info("Extracting dnwpw_6p0 diode")
extract_devices(diode("dnwpw_6p0"), { "N" => dnwell , "P" => dnwpw_6p0_terminal_p})
# dnwps_3p3 diode
logger.info("Extracting dnwps_3p3 diode")
extract_devices(diode("dnwps_3p3"), { "N" => dnwell , "P" => dnwps_3p3_terminal_p})
# dnwps_6p0 diode
logger.info("Extracting dnwps_6p0 diode")
extract_devices(diode("dnwps_6p0"), { "N" => dnwell , "P" => dnwps_6p0_terminal_p})
# sc_diode diode
logger.info("Extracting sc_diode diode")
extract_devices(diode("sc_diode"), { "N" => sc_diode_terminal_n , "P" => schottky_diode})
#================================
# ---- RESISTOR EXTRACTIONS -----
#================================
logger.info("Starting RESISTOR EXTRACTION")
# ===============
# --DIFF & WELL--
# ===============
# NPLUS_U
logger.info("Extracting NPLUS_U device")
extract_devices(resistor_with_bulk("nplus_u", 60, BResistor), { "R" => nplus_u_layer, "C" => nplus_cont, "W" => sub})
# NPLUS_U_DW
logger.info("Extracting NPLUS_U_DW device")
extract_devices(resistor_with_bulk("nplus_u_dw", 60, BResistor), { "R" => nplus_u_dw_layer, "C" => nplus_cont, "W" => lvpwell_con })
# PPLUS_U
logger.info("Extracting PPLUS_U device")
extract_devices(resistor_with_bulk("pplus_u", 185, BResistor), { "R" => pplus_u_layer, "C" => pplus_cont, "W" => nwell_con})
# PPLUS_U_DW
logger.info("Extracting PPLUS_U_DW device")
extract_devices(resistor_with_bulk("pplus_u_dw", 185, BResistor), { "R" => pplus_u_dw_layer, "C" => pplus_dw_cont, "W" => dnwell })
# NPLUS_S
logger.info("Extracting NPLUS_S device")
extract_devices(resistor_with_bulk("nplus_s", 6.3, BResistor), { "R" => nplus_s_layer, "C" => nplus_cont, "W" => sub})
# NPLUS_S_DW
logger.info("Extracting NPLUS_S_DW device")
extract_devices(resistor_with_bulk("nplus_s_dw", 6.3, BResistor), { "R" => nplus_s_dw_layer, "C" => nplus_cont, "W" => lvpwell_con })
# PPLUS_S
logger.info("Extracting PPLUS_S device")
extract_devices(resistor_with_bulk("pplus_s", 7, BResistor), { "R" => pplus_s_layer, "C" => pplus_cont, "W" => nwell_con})
# PPLUS_S_DW
logger.info("Extracting PPLUS_S_DW device")
extract_devices(resistor_with_bulk("pplus_s_dw", 7, BResistor), { "R" => pplus_s_dw_layer, "C" => pplus_dw_cont, "W" => dnwell })
# NWELL
logger.info("Extracting NWELL device")
extract_devices(resistor_with_bulk("nwell", 1000, BResistor), { "R" => nwell_res, "C" => nwell_con, "W" => sub})
# PWELL
logger.info("Extracting PWELL device")
extract_devices(resistor_with_bulk("pwell", 1000, BResistor), { "R" => pwell_res, "C" => lvpwell_con, "W" => dnwell})
# ==============
# ---- POLY ----
# ==============
# NPOLYF_U
extract_devices(resistor_with_bulk("npolyf_u", 310, BResistor), { "R" => npolyf_u_layer, "C" => poly2_con, "W" => sub})
# NPOLYF_U_DW
extract_devices(resistor_with_bulk("npolyf_u_dw", 310, BResistor), { "R" => npolyf_u_dw_layer, "C" => poly2_con, "W" => dnwell })
# PPOLYF_U
extract_devices(resistor_with_bulk("ppolyf_u", 350, BResistor), { "R" => ppolyf_u_layer, "C" => poly2_con, "W" => sub})
# PPOLYF_U_DW
extract_devices(resistor_with_bulk("ppolyf_u_dw", 350, BResistor), { "R" => ppolyf_u_dw_layer, "C" => poly2_con, "W" => dnwell })
# NPOLYF_S
extract_devices(resistor_with_bulk("npolyf_s", 6.8, BResistor), { "R" => npolyf_s_layer, "C" => poly2_con, "W" => sub})
# NPOLYF_S_DW
extract_devices(resistor_with_bulk("npolyf_s_dw", 6.8, BResistor), { "R" => npolyf_s_dw_layer, "C" => poly2_con, "W" => dnwell })
# PPOLYF_S
extract_devices(resistor_with_bulk("ppolyf_s", 7.3, BResistor), { "R" => ppolyf_s_layer, "C" => poly2_con, "W" => sub})
# PPOLYF_S_DW
extract_devices(resistor_with_bulk("ppolyf_s_dw", 7.3, BResistor), { "R" => ppolyf_s_dw_layer, "C" => poly2_con, "W" => dnwell })
# ==============
# --H-POLY RES--
# ==============
if POLY_RES == "1k"
# PPOLYF_U_1K
extract_devices(resistor_with_bulk("ppolyf_u_1k", 1000, BResistor), { "R" => ppolyf_u_1k_layer, "C" => poly2_con, "W" => sub})
# PPOLYF_U_DW_1K
extract_devices(resistor_with_bulk("ppolyf_u_1k_dw", 1000, BResistor), { "R" => ppolyf_u_1k_dw_layer, "C" => poly2_con, "W" => dnwell })
# PPOLYF_U_1K_6p0
extract_devices(resistor_with_bulk("ppolyf_u_1k_6p0", 1000, BResistor), { "R" => ppolyf_u_1k_6p0_layer, "C" => poly2_con, "W" => sub})
# PPOLYF_U_DW_1K_6p0
extract_devices(resistor_with_bulk("ppolyf_u_1k_6p0_dw", 1000, BResistor), { "R" => ppolyf_u_1k_6p0_dw_layer, "C" => poly2_con, "W" => dnwell })
elsif POLY_RES == "2k"
# PPOLYF_U_2K
extract_devices(resistor_with_bulk("ppolyf_u_2k", 2000, BResistor), { "R" => ppolyf_u_2k_layer, "C" => poly2_con, "W" => sub})
# PPOLYF_U_DW_2K
extract_devices(resistor_with_bulk("ppolyf_u_2k_dw", 2000, BResistor), { "R" => ppolyf_u_2k_dw_layer, "C" => poly2_con, "W" => dnwell })
# PPOLYF_U_2K_6p0
extract_devices(resistor_with_bulk("ppolyf_u_2k_6p0", 2000, BResistor), { "R" => ppolyf_u_2k_6p0_layer, "C" => poly2_con, "W" => sub})
# PPOLYF_U_DW_2K_6p0
extract_devices(resistor_with_bulk("ppolyf_u_2k_6p0_dw", 2000, BResistor), { "R" => ppolyf_u_2k_6p0_dw_layer, "C" => poly2_con, "W" => dnwell })
elsif POLY_RES == "3k"
# PPOLYF_U_3K
extract_devices(resistor_with_bulk("ppolyf_u_3k", 3000, BResistor), { "R" => ppolyf_u_3k_layer, "C" => poly2_con, "W" => sub})
# PPOLYF_U_DW_3K
extract_devices(resistor_with_bulk("ppolyf_u_3k_dw", 3000, BResistor), { "R" => ppolyf_u_3k_dw_layer, "C" => poly2_con, "W" => dnwell })
# PPOLYF_U_3K_6p0
extract_devices(resistor_with_bulk("ppolyf_u_3k_6p0", 3000, BResistor), { "R" => ppolyf_u_3k_6p0_layer, "C" => poly2_con, "W" => sub})
# PPOLYF_U_DW_3K_6p0
extract_devices(resistor_with_bulk("ppolyf_u_3k_6p0_dw", 3000, BResistor), { "R" => ppolyf_u_3k_6p0_dw_layer, "C" => poly2_con, "W" => dnwell })
end
# ===============
# ---- METAL ----
# ===============
# RM1
logger.info("Extracting RM1 device")
extract_devices(resistor("rm1", 0.09, NResistor), { "R" => rm1_res, "C" => metal1_con })
# RM2
logger.info("Extracting RM2 device")
extract_devices(resistor("rm2", 0.09, NResistor), { "R" => rm2_res, "C" => metal2_ncap })
# RM3
logger.info("Extracting RM3 device")
extract_devices(resistor("rm3", 0.09, NResistor), { "R" => rm3_res, "C" => metal3_ncap })
if METAL_TOP == "6K"
# TM6K
logger.info("Extracting TM6K device")
extract_devices(resistor("tm6k", 0.06, NResistor), { "R" => tm_res, "C" => metaltop_con })
elsif METAL_TOP == "9K"
# TM9K
logger.info("Extracting TM9K device")
extract_devices(resistor("tm9k", 0.04, NResistor), { "R" => tm_res, "C" => metaltop_con })
elsif METAL_TOP == "11K"
# TM11K
logger.info("Extracting TM11K device")
extract_devices(resistor("tm11k", 0.04, NResistor), { "R" => tm_res, "C" => metaltop_con })
elsif METAL_TOP == "30K"
# TM30K
logger.info("Extracting TM30K device")
extract_devices(resistor("tm30k", 0.0095, NResistor), { "R" => tm_res, "C" => metaltop_con })
end
#==================================
# ------- MIMCAP EXTRACTION -------
#==================================
logger.info("Starting MIMCAP EXTRACTION")
if MIM_OPTION == "A"
if MIM_CAP == "1"
# mim_1p0fF capacitor
logger.info("Extracting mim_1p0fF device")
extract_devices(capacitor("mim_1p0fF", 1.0e-15, MIMCap), { "P1" => mim_virtual, "P2" => fuse_cap })
tolerance("mim_1p0fF", "C", :relative => 0.25)
elsif MIM_CAP == "1.5"
# mim_1p5fF capacitor
logger.info("Extracting mim_1p5fF device")
extract_devices(capacitor("mim_1p5fF", 1.5e-15, MIMCap), { "P1" => mim_virtual, "P2" => fuse_cap })
tolerance("mim_1p5fF", "C", :relative => 0.25)
elsif MIM_CAP == "2"
# mim_single_2p0fF capacitor
logger.info("Extracting mim_single_2p0fF device")
extract_devices(capacitor("mim_single_2p0fF", 2.0e-15, MIMCap), { "P1" => mim_virtual, "P2" => fuse_cap })
tolerance("mim_single_2p0fF", "C", :relative => 0.25)
end
elsif MIM_OPTION == "B"
if MIM_CAP == "1"
# mim_1p0fF capacitor
logger.info("Extracting mim_1p0fF device")
extract_devices(capacitor("mim_1p0fF", 1.0e-15, MIMCap), { "P1" => mimtm_virtual, "P2" => fuse_cap })
tolerance("mim_1p0fF", "C", :relative => 0.25)
elsif MIM_CAP == "1.5"
# mim_1p5fF capacitor
logger.info("Extracting mim_1p5fF device")
extract_devices(capacitor("mim_1p5fF", 1.5e-15, MIMCap), { "P1" => mimtm_virtual, "P2" => fuse_cap })
tolerance("mim_1p5fF", "C", :relative => 0.25)
elsif MIM_CAP == "2"
# mim_single_2p0fF capacitor
logger.info("Extracting mim_single_2p0fF device")
extract_devices(capacitor("mim_single_2p0fF", 2.0e-15, MIMCap), { "P1" => mimtm_virtual, "P2" => fuse_cap })
tolerance("mim_single_2p0fF", "C", :relative => 0.25)
end
end
#==================================
# ------- MOSCAP EXTRACTION -------
#==================================
logger.info("Starting MOSCAP EXTRACTION")
#nmoscap_3p3
logger.info("Extracting nmoscap_3p3 device")
extract_devices(capacitor("nmoscap_3p3", 4.4e-15, MosCap), { "P1" => nmos_gate_3p3, "P2" => lvpwell_con, "tA" => poly2_con, "tB" => nsd})
#nmoscap_3p3_dw
logger.info("Extracting nmoscap_3p3_dw device")
extract_devices(capacitor("nmoscap_3p3_dw", 4.4e-15, MosCap), { "P1" => nmos_gate_3p3_dw, "P2" => lvpwell_con, "tA" => poly2_con, "tB" => nsd })
#pmoscap_3p3
logger.info("Extracting pmoscap_3p3 device")
extract_devices(capacitor("pmoscap_3p3", 4.4e-15, MosCap), { "P1" => pmos_gate_3p3, "P2" => nwell_con, "tA" => poly2_con, "tB" => psd })
#pmoscap_3p3_dw
logger.info("Extracting pmoscap_3p3_dw device")
extract_devices(capacitor("pmoscap_3p3_dw", 4.4e-15, MosCap), { "P1" => pmos_gate_3p3_dw, "P2" => dnwell, "tA" => poly2_con, "tB" => psd_dw })
#nmoscap_6p0
logger.info("Extracting nmoscap_6p0 device")
extract_devices(capacitor("nmoscap_6p0", 2.3e-15, MosCap), { "P1" => nmos_gate_6p0, "P2" => lvpwell_con, "tA" => poly2_con, "tB" => nsd })
#nmoscap_6p0_dw
logger.info("Extracting nmoscap_6p0_dw device")
extract_devices(capacitor("nmoscap_6p0_dw", 2.3e-15, MosCap), { "P1" => nmos_gate_6p0_dw, "P2" => lvpwell_con, "tA" => poly2_con, "tB" => nsd })
#pmoscap_6p0
logger.info("Extracting pmoscap_6p0 device")
extract_devices(capacitor("pmoscap_6p0", 2.3e-15, MosCap), { "P1" => pmos_gate_6p0, "P2" => nwell_con, "tA" => poly2_con, "tB" => psd })
#pmoscap_6p0
logger.info("Extracting pmoscap_6p0 device")
extract_devices(capacitor("pmoscap_6p0_dw", 2.3e-15, MosCap), { "P1" => pmos_gate_6p0_dw, "P2" => dnwell, "tA" => poly2_con, "tB" => psd_dw })
# nmoscap_3p3_b capacitor
extract_devices(capacitor("nmoscap_3p3_b", 4.4e-15, MosCap), { "P1" => nmoscap_3p3_b, "P2" => nwell_con, "tA" => poly2_con, "tB" => ntap })
#pmoscap_3p3_b
logger.info("Extracting pmoscap_3p3_b device")
extract_devices(capacitor("pmoscap_3p3_b", 4.4e-15, MosCap), { "P1" => pmoscap_3p3_b, "P2" => ptap, "tA" => poly2_con, "tB" => ptap })
#nmoscap_6p0_b
logger.info("Extracting nmoscap_6p0_b device")
extract_devices(capacitor("nmoscap_6p0_b", 2.3e-15, MosCap), { "P1" => nmoscap_6p0_b, "P2" => nwell_con, "tA" => poly2_con, "tB" => ntap })
#pmoscap_6p0_b
logger.info("Extracting pmoscap_6p0_b device")
extract_devices(capacitor("pmoscap_6p0_b", 2.3e-15, MosCap), { "P1" => pmoscap_6p0_b, "P2" => ptap, "tA" => poly2_con, "tB" => ptap })
#================================
# ------- ESD EXTRACTION --------
#================================
logger.info("Starting MOS SAB EXTRACTION")
# ==============
# ---- PMOS ----
# ==============
logger.info("Starting PMOS SAB EXTRACTION")
#3.3V ESD PMOS transistor outside DNWELL
logger.info("Extracting 3.3V ESD PMOS transistor outside DNWELL device")
extract_devices(mos4("pmos_3p3_sab"), { "SD" => psd, "G" => pgate_sab_3p3v, "tS" => psd, "tD" => psd, "tG" => poly2_con, "W" => nwell_con })
#5V ESD PMOS transistor outside DNWELL
logger.info("Extracting 5V ESD PMOS transistor outside DNWELL device")
extract_devices(mos4("pmos_5p0_sab"), { "SD" => psd, "G" => pgate_sab_5v, "tS" => psd, "tD" => psd, "tG" => poly2_con, "W" => nwell_con })
#6V ESD PMOS transistor outside DNWELL
logger.info("Extracting 6V ESD PMOS transistor outside DNWELL device")
extract_devices(mos4("pmos_6p0_sab"), { "SD" => psd, "G" => pgate_sab_6v, "tS" => psd, "tD" => psd, "tG" => poly2_con, "W" => nwell_con })
#3.3V ESD PMOS transistor inside DNWELL
logger.info("Extracting 3.3V ESD PMOS transistor inside DNWELL device")
extract_devices(mos4("pmos_3p3_dw_sab"), { "SD" => psd_dw, "G" => pgate_dw_sab_3p3v, "tS" => psd_dw, "tD" => psd_dw, "tG" => poly2_con, "W" => dnwell })
#5V ESD PMOS transistor inside DNWELL
logger.info("Extracting 5V ESD PMOS transistor inside DNWELL device")
extract_devices(mos4("pmos_5p0_dw_sab"), { "SD" => psd_dw, "G" => pgate_dw_sab_5v, "tS" => psd_dw, "tD" => psd_dw, "tG" => poly2_con, "W" => dnwell })
#6V ESD PMOS transistor inside DNWELL
logger.info("Extracting 6V ESD PMOS transistor inside DNWELL device")
extract_devices(mos4("pmos_6p0_dw_sab"), { "SD" => psd_dw, "G" => pgate_dw_sab_6v, "tS" => psd_dw, "tD" => psd_dw, "tG" => poly2_con, "W" => dnwell })
# ==============
# ---- NMOS ----
# ==============
logger.info("Starting NMOS SAB EXTRACTION")
#3.3V ESD NMOS transistor outside DNWELL
logger.info("Extracting 3.3V ESD NMOS transistor outside DNWELL device")
extract_devices(mos4("nmos_3p3_sab"), { "SD" => nsd, "G" => ngate_sab_3p3v, "tS" => nsd, "tD" => nsd, "tG" => poly2_con, "W" => sub })
#5V ESD NMOS transistor outside DNWELL
logger.info("Extracting 5V ESD NMOS transistor outside DNWELL device")
extract_devices(mos4("nmos_5p0_sab"), { "SD" => nsd, "G" => ngate_sab_5v, "tS" => nsd, "tD" => nsd, "tG" => poly2_con, "W" => sub })
#6V ESD NMOS transistor outside DNWELL
logger.info("Extracting 6V ESD NMOS transistor outside DNWELL device")
extract_devices(mos4("nmos_6p0_sab"), { "SD" => nsd, "G" => ngate_sab_6v, "tS" => nsd, "tD" => nsd, "tG" => poly2_con, "W" => sub })
#3.3V ESD NMOS transistor inside DNWELL
logger.info("Extracting 3.3V ESD NMOS transistor inside DNWELL device")
extract_devices(mos4("nmos_3p3_dw_sab"), { "SD" => nsd, "G" => ngate_dw_sab_3p3v, "tS" => nsd, "tD" => nsd, "tG" => poly2_con, "W" => lvpwell_con })
#5V ESD NMOS transistor inside DNWELL
logger.info("Extracting 5V ESD NMOS transistor inside DNWELL device")
extract_devices(mos4("nmos_5p0_dw_sab"), { "SD" => nsd, "G" => ngate_dw_sab_5v, "tS" => nsd, "tD" => nsd, "tG" => poly2_con, "W" => lvpwell_con })
#6V ESD NMOS transistor inside DNWELL
logger.info("Extracting 6V ESD NMOS transistor inside DNWELL device")
extract_devices(mos4("nmos_6p0_dw_sab"), { "SD" => nsd, "G" => ngate_dw_sab_6v, "tS" => nsd, "tD" => nsd, "tG" => poly2_con, "W" => lvpwell_con })
#================================
# ------ EFUSE EXTRACTIONS ------
#================================
logger.info("Starting EFUSE EXTRACTION")
extract_devices(resistor("efuse", 28.5714), { "R" => efuse_link, "C" => efuse_con_layer, "tA" => anode, "tB" => cathode })
ignore_parameter("efuse", "R")
#================================================
#------------- COMPARISON OPTIONS ---------------
#================================================
logger.info("Starting GF180 LVS comparison section")
#=== FLATTEN CELLS ===
align
#=== NETLIST EXTRACTION ===
if SIMPLIFY
netlist.simplify
end
#=== NETLIST OPTIONS ===
if NET_ONLY
netlist
end
if TOP_LVL_PINS
netlist.make_top_level_pins
end
if COMBINE
netlist.combine_devices
end
if PURGE
netlist.purge
end
if PURGE_NETS
netlist.purge_nets
end
#=== SCHEMATIC OPTIONS ===
if SCH_SIMPLE
schematic.simplify
end
#=== IGNORE EXTREME VALUES ===
max_res(1e7)
min_caps(1e-16)
compare
exec_end_time = Time.now
run_time = exec_end_time - exec_start_time
logger.info("DRC Total Run time %f seconds" % [run_time])
if ! compare
logger.info("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
logger.error("ERROR : Netlists don't match")
logger.info("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
else
logger.info("==========================================")
logger.info("INFO : Congratulations! Netlists match.")
logger.info("==========================================")
end