blob: 43b359bf885f75cd17ad9df09fa0456adec8f7bf [file] [log] [blame]
# Copyright 2022 Mabrains
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#===========================================================================================================================
#------------------------------------------------- SKY130 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}\n"
end
#================================================
#----------------- FILE SETUP -------------------
#================================================
logger.info("Starting running SKY130 Klayout LVS runset on %s" % [$input])
#=== GET LAYOUT ===
if $input
source($input)
logger.info("Layout file: #{$input}")
else
logger.error("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 = "sky130_gnd"
logger.info("No substrate name given, default name is sky130_gnd")
end
#=== CUSTOM WRITER CLASS ===
class SubcircuitModels < RBA::NetlistSpiceWriterDelegate
def write_device(device)
device_class = device.device_class
if device_class.name.include?('fet')
str = "M" + device.expanded_name
elsif device_class.name.include?('diode')
str = "D" + device.expanded_name
elsif device_class.name.include?('npn') or device_class.name.include?('pnp')
str = "Q" + device.expanded_name
elsif device_class.name.include?('res')
str = "R" + device.expanded_name
elsif device_class.name.include?('ind') or device_class.name.include?('coil')
str = "L" + device.expanded_name
elsif device_class.name.include?('cap')
str = "C" + device.expanded_name
else
str = "#{device.id}" + device.expanded_name
end
device_class.terminal_definitions.each do |td|
str += " " + net_to_string(device.net_for_terminal(td.id))
end
str += " " + device_class.name
unless device_class.name.include?('vpp') || device_class.name.include?('ind')
device_class.parameter_definitions.each do |pd|
str += " " + pd.name + ("=%.12g" % device.parameter(pd.id))
end
end
emit_line(str)
end
end
#=== CUSTOM WRITER ===
custom_spice_writer = RBA::NetlistSpiceWriter::new(SubcircuitModels::new)
#=== NET NAMES OPTION ===
# true: use net names instead of numbers
# false: use numbers for nets
if $spice_net_names == "false"
custom_spice_writer.use_net_names = false
logger.info("Extracted netlist with net names: #{$spice_net_names}")
else
custom_spice_writer.use_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 == "true"
custom_spice_writer.with_comments = true
logger.info("Extracted netlist with comments in details: #{$spice_comments}")
else
custom_spice_writer.with_comments = false
logger.info("Extracted netlist with comments in details: false")
end
if $target_netlist
target_netlist($target_netlist, custom_spice_writer, "Extracted by KLayout with SKY130 LVS runset on : #{Time.now.strftime("%d/%m/%Y %H:%M")}")
logger.info("Extracted netlist file: #{$target_netlist}")
else
target_netlist(File.join(File.dirname(RBA::CellView::active.filename), source.cell_name+"_extracted.cir"), custom_spice_writer, "Extracted by KLayout with SKY130 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 == "true"
device_scaling(1000000)
logger.info("device_scaling: true")
else
logger.info("device_scaling: false")
end
#=== PRINT DETAILS ===
if $verbose == "true"
verbose(true)
logger.info("Verbose mode: #{$verbose}")
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
#=== DEFAULT MODE ===
deep
logger.info("deep 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)
elsif element == "R"
super(s + " R=0", element)
elsif element == "L"
super(s + " L=0", element)
else
super
end
end
# take and translate the element
def element(circuit, el, name, model, value, nets, params)
if el == "C" && model.include?('SKY130') && model.include?('VPP')
if nets.size == 4
cls = RBA::DeviceClassMOS4Transistor::new
cls.name = model
circuit.netlist.add(cls)
# create a device
device = circuit.create_device(cls, name)
# and configure the device
[ "S", "G", "D", "B" ].each_with_index do |t,index|
device.connect_terminal(t, nets[index])
end
else
cls = RBA::DeviceClassCapacitorWithBulk::new
cls.name = model
circuit.netlist.add(cls)
# 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
device.set_parameter("C", params["C"] || 2e-16)
end
elsif el == "L" && model.include?('SKY130') && (model.include?('IND') || model.include?('COIL'))
cls = RBA::DeviceClassResistorWithBulk::new
cls.name = model
circuit.netlist.add(cls)
# 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
device.set_parameter("R", params["R"] || 0)
else
# all other elements are left to the standard implementation
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
begin
schematic("#{source.cell_name}.cdl", reader)
logger.info("Netlist file: #{source.cell_name}.cdl")
rescue
puts "No schematic loaded , please add your netlist file"
logger.error("No schematic loaded , please add your netlist file")
end
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 MIMCap < RBA::DeviceClassCapacitor
def initialize
super
enable_parameter("C", false)
enable_parameter("A", true)
enable_parameter("P", true)
end
end
class VarCap < RBA::DeviceClassCapacitorWithBulk
def initialize
super
enable_parameter("C", false)
enable_parameter("A", true)
enable_parameter("P", true)
end
end
# class Vpp3Cap < RBA::DeviceClassCapacitorWithBulk
# def initialize
# super
# enable_parameter("C", false)
# enable_parameter("A", false)
# enable_parameter("P", false)
# end
# end
class Diode < RBA::DeviceClassDiode
def initialize
super
enable_parameter("A", true)
enable_parameter("P", true)
end
end
#================================================
#------------- Custom Devices ---------------
#================================================
#====================== CUSTOM FOUR TERMINAL BJT EXTRACTOR =========================
class FixBJT4Transistor < RBA::GenericDeviceExtractor
def initialize(name)
self.name = name
end
def setup
define_layer("BJT", "BJT Seed Layer")
define_layer("tC", "Collector Terminal")
define_layer("tB", "Base Terminal")
define_layer("tE", "Emitter Terminal")
define_layer("tS", "Substrate Terminal")
register_device_class(RBA::DeviceClassBJT4Transistor::new)
end
def get_connectivity(layout, layers)
conn = RBA::Connectivity::new
conn.connect(layers[0], layers[0])
conn.connect(layers[0], layers[1])
conn.connect(layers[0], layers[2])
conn.connect(layers[0], layers[3])
return conn
end
def extract_devices(layer_geometry)
# layer_geometry provides the input layers in the order they are
# defined with "define_layer"
# conductor is supposed to be "conductor outside marker"
bjt = layer_geometry[0]
t_collector = layer_geometry[1]
t_base = layer_geometry[2]
t_emitter = layer_geometry[3]
t_bulk = layer_geometry[4]
bjt.each_merged do |c|
dev_c = t_collector & c
dev_b = t_base & c
dev_e = t_emitter & c
dev_c.each_merged do |cc|
dev_b.each_merged do |b|
dev_e.each_merged do |e|
device = create_device()
# provide the device terminals to connect the metal to later
define_terminal(device, RBA::DeviceClassBJT4Transistor::TERMINAL_C, 1, cc)
define_terminal(device, RBA::DeviceClassBJT4Transistor::TERMINAL_B, 2, b)
define_terminal(device, RBA::DeviceClassBJT4Transistor::TERMINAL_E, 3, e)
define_terminal(device, RBA::DeviceClassBJT4Transistor::TERMINAL_S, 4, e)
end
end
end
end
end
end
#====================== CUSTOM INDUCTOR EXTRACTOR =========================
class InductorExtractor < RBA::GenericDeviceExtractor
def initialize(name)
self.name = name
end
def setup
define_layer("C1", "Conductor1")
define_layer("C2", "Conductor2")
define_layer("M", "Marker")
register_device_class(RBA::DeviceClassResistorWithBulk::new)
end
def extract_devices(layer_geometry)
# layer_geometry provides the input layers in the order they are
# defined with "define_layer"
# conductor is supposed to be "conductor outside marker"
conductor1 = layer_geometry[0]
conductor2 = layer_geometry[1]
marker = layer_geometry[2]
marker_merged = marker.merged
# this will be the edge where the marker turns into conductor
marker_edges = (marker_merged.edges & (conductor1))
marker_edges2 = (marker_merged.edges & (conductor2))
marker_merged.each do |r|
# identify the edges where this marker shape ends
interface_edges = marker_edges.interacting(RBA::Region::new(r))
# form terminal shapes from these edges
terminals = conductor1.merged.interacting(interface_edges.extended_out(1).merged)
terminals2 = marker_edges2.extended_out(1).merged
if (terminals.size > 1) and (terminals2.size > 0)
terminals.each do |term|
if "#{RBA::Region::new(term).interacting(conductor1.merged.interacting(RBA::Region::new(terminals[0])))}".empty?
terminals = [terminals[0], term]
break
end
end
device = create_device
device.set_parameter(RBA::DeviceClassResistorWithBulk::PARAM_R, 0)
define_terminal(device, RBA::DeviceClassResistorWithBulk::TERMINAL_A, 0, terminals[0]);
define_terminal(device, RBA::DeviceClassResistorWithBulk::TERMINAL_B, 0, terminals[1]);
define_terminal(device, RBA::DeviceClassResistorWithBulk::TERMINAL_W, 1, terminals2[0]);
end
end
end
def get_connectivity(layout, layers)
# marker is used for extraction
# conductor is used for producing the terminals
conductor1 = layers[0]
conductor2 = layers[1]
marker = layers[2]
conn = RBA::Connectivity::new
conn.connect(marker , marker)
conn.connect(conductor1, marker)
conn.connect(conductor2, marker)
return conn
end
end
#====================== CUSTOM FOUR TERMINAL VPP EXTRACTOR =========================
class VPP4Extractor < RBA::GenericDeviceExtractor
def initialize(name)
self.name = name
end
def setup
define_layer("C1", "Conductor1")
define_layer("C2", "Conductor2")
define_layer("M", "Marker")
define_layer("B", "Bulk")
register_device_class(RBA::DeviceClassMOS4Transistor::new)
end
def extract_devices(layer_geometry)
# layer_geometry provides the input layers in the order they are
# defined with "define_layer"
# conductor is supposed to be "conductor outside marker"
conductor1 = layer_geometry[0]
conductor2 = layer_geometry[1]
marker = layer_geometry[2]
bulk = layer_geometry[3]
marker_merged = marker.merged
bulk_merged = bulk.merged
# this will be the edge where the marker turns into conductor
marker_edges = (marker_merged & (conductor1))
marker_edges2 = (marker_merged & (conductor2))
marker_merged.each do |r|
# identify the edges where this marker shape ends
interface_edges = marker_edges.interacting(RBA::Region::new(r))
# form terminal shapes from these edges
terminals = interface_edges.merged
terminals2 = marker_edges2.merged
if (terminals.size > 1) and (terminals2.size > 0)
terminals.each do |term|
if terminals[0] == term
next
end
if !"#{RBA::Region::new(term).extents.interacting(RBA::Region::new(terminals[0]).extents)}".empty?
terminals = [terminals[0], term]
break
end
end
device = create_device
define_terminal(device, RBA::DeviceClassMOS4Transistor::TERMINAL_S, 0, terminals[0]);
define_terminal(device, RBA::DeviceClassMOS4Transistor::TERMINAL_G, 0, terminals[1]);
define_terminal(device, RBA::DeviceClassMOS4Transistor::TERMINAL_D, 1, terminals2[0]);
define_terminal(device, RBA::DeviceClassMOS4Transistor::TERMINAL_B, 3, bulk_merged[0]);
end
end
end
def get_connectivity(layout, layers)
# marker is used for extraction
# conductor is used for producing the terminals
conductor1 = layers[0]
conductor2 = layers[1]
marker = layers[2]
bulk = layers[3]
conn = RBA::Connectivity::new
conn.connect(marker , marker)
conn.connect(conductor1, marker)
conn.connect(conductor2, marker)
conn.connect(bulk , marker)
return conn
end
end
#====================== CUSTOM THREE TERMINAL VPP EXTRACTOR =========================
class VPP3Extractor < RBA::GenericDeviceExtractor
def initialize(name)
self.name = name
end
def setup
define_layer("C", "Conductor")
define_layer("M", "Marker")
define_layer("B", "Bulk")
register_device_class(RBA::DeviceClassCapacitorWithBulk::new)
end
def extract_devices(layer_geometry)
# layer_geometry provides the input layers in the order they are
# defined with "define_layer"
# conductor is supposed to be "conductor outside marker"
conductor = layer_geometry[0]
marker = layer_geometry[1]
bulk = layer_geometry[2]
marker_merged = marker.merged
bulk_merged = bulk.merged
# this will be the edge where the marker turns into conductor
marker_edges = (marker_merged & (conductor))
marker_merged.each do |r|
# identify the edges where this marker shape ends
interface_edges = marker_edges.interacting(RBA::Region::new(r))
# form terminal shapes from these edges
terminals = interface_edges.merged
if terminals.size > 1
terminals.each do |term|
if terminals[0] == term
next
end
if !"#{RBA::Region::new(term).extents.interacting(RBA::Region::new(terminals[0]).extents)}".empty?
terminals = [terminals[0], term]
break
end
end
device = create_device
device.set_parameter(RBA::DeviceClassCapacitorWithBulk::PARAM_C, 2e-16)
define_terminal(device, RBA::DeviceClassCapacitorWithBulk::TERMINAL_A, 0, terminals[0]);
define_terminal(device, RBA::DeviceClassCapacitorWithBulk::TERMINAL_B, 0, terminals[1]);
define_terminal(device, RBA::DeviceClassCapacitorWithBulk::TERMINAL_W, 2, bulk_merged[0]);
end
end
end
def get_connectivity(layout, layers)
# marker is used for extraction
# conductor is used for producing the terminals
conductor = layers[0]
marker = layers[1]
bulk = layers[2]
conn = RBA::Connectivity::new
conn.connect(marker , marker)
conn.connect(conductor, marker)
conn.connect(bulk , marker)
return conn
end
end
#====================== CUSTOM VPP NHV EXTRACTOR =========================
class VPP3NHVExtractor < RBA::GenericDeviceExtractor
def initialize(name)
self.name = name
end
def setup
define_layer("MARKER", "VPP Seed Layer")
define_layer("tA", "Terminal A")
define_layer("tB", "Terminal B")
define_layer("tW", "Substrate Terminal")
register_device_class(RBA::DeviceClassCapacitorWithBulk::new)
end
def get_connectivity(layout, layers)
conn = RBA::Connectivity::new
conn.connect(layers[0], layers[0])
conn.connect(layers[0], layers[1])
conn.connect(layers[0], layers[2])
conn.connect(layers[0], layers[3])
return conn
end
def extract_devices(layer_geometry)
vpp_cap = layer_geometry[0]
t_top = layer_geometry[1]
t_bot = layer_geometry[2]
t_bulk = layer_geometry[3]
vpp_cap.each_merged do |c|
dev_a = t_top & c
dev_b = t_bot & c
dev_w = t_bulk & c
device = create_device()
# provide the device terminals to connect the metal to later
device.set_parameter(RBA::DeviceClassCapacitorWithBulk::PARAM_C, 2e-16)
define_terminal(device, RBA::DeviceClassCapacitorWithBulk::TERMINAL_A, 1, dev_a[0])
define_terminal(device, RBA::DeviceClassCapacitorWithBulk::TERMINAL_B, 2, dev_b[0])
define_terminal(device, RBA::DeviceClassCapacitorWithBulk::TERMINAL_W, 3, dev_w[0])
end
end
end
#================================================
#------------- LAYERS DERIVATIONS ---------------
#================================================
logger.info("Read in polygons from layers.")
#=== INPUTS ===
diff = input(65 , 20 )
poly = input(66 , 20 )
li = input(67 , 20 )
met1 = input(68 , 20 )
met2 = input(69 , 20 )
met3 = input(70 , 20 )
met4 = input(71 , 20 )
met5 = input(72 , 20 )
pad = input(76 , 20 )
#=== DRAWINGS ===
bound = polygons(235, 4 )
sub_pin = polygons(64 , 59 )
dnwell = polygons(64 , 18 )
pwell_pin = polygons(122, 16 )
pwell_res = polygons(64 , 13 )
pwbm = polygons(19 , 44 )
pwde = polygons(124, 20 )
nwell = polygons(64 , 20 )
nwell_pin = polygons(64 , 16 )
tap = polygons(65 , 44 )
psdm = polygons(94 , 20 )
nsdm = polygons(93 , 44 )
lvtn = polygons(125, 44 )
hvtr = polygons(18 , 20 )
hvtp = polygons(78 , 44 )
tunm = polygons(80 , 20 )
sonos = polygons(80 , 20 )
coreid = polygons(81 , 2 )
stdcell = polygons(81 , 4 )
npnid = polygons(82 , 20 )
pnpid = polygons(82 , 44 )
rpm = polygons(86 , 20 )
urpm = polygons(79 , 20 )
ldntm = polygons(11 , 44 )
hvntm = polygons(125, 20 )
poly_pin = polygons(66 , 16 )
poly_res = polygons(66 , 13 )
poly_cut = polygons(66 , 14 )
poly_short = polygons(66 , 15 )
hvi = polygons(75 , 20 )
licon = polygons(66 , 44 )
npc = polygons(95 , 20 )
diff_res = polygons(65 , 13 )
diff_cut = polygons(65 , 14 )
diode = polygons(81 , 23 )
li_pin = polygons(67 , 16 )
li_res = polygons(67 , 13 )
li_cut = polygons(67 , 14 )
mcon = polygons(67 , 44 )
met1_pin = polygons(68 , 16 )
met1_res = polygons(68 , 13 )
met1_cut = polygons(68 , 14 )
via1 = polygons(68 , 44 )
met2_pin = polygons(69 , 16 )
met2_res = polygons(69 , 13 )
met2_cut = polygons(69 , 14 )
met2_fuse = polygons(69 , 17 )
via2 = polygons(69 , 44 )
met3_pin = polygons(70 , 16 )
met3_res = polygons(70 , 13 )
met3_cut = polygons(70 , 14 )
met3_fuse = polygons(70 , 17 )
via3 = polygons(70 , 44 )
met4_pin = polygons(71 , 16 )
met4_res = polygons(71 , 13 )
met4_cut = polygons(71 , 14 )
met4_fuse = polygons(71 , 17 )
via4 = polygons(71 , 44 )
met5_pin = polygons(72 , 16 )
met5_res = polygons(72 , 13 )
met5_cut = polygons(72 , 14 )
rdl = polygons(74 , 20 )
rdl_pin = polygons(74 , 16 )
glass = polygons(76 , 20 )
capm = polygons(89 , 44 )
capm2 = polygons(97 , 44 )
lowtapd = polygons(81 , 14 )
fillobsm1 = polygons(62 , 24 )
fillobsm2 = polygons(105, 52 )
fillobsm3 = polygons(107, 24 )
fillobsm4 = polygons(112, 4 )
ncm = polygons(92 , 44 )
natfet = polygons(124, 21 )
nsm = polygons(61 , 20 )
vhvi = polygons(74 , 21 )
uhvi = polygons(74 , 22 )
inductor = polygons(82 , 24 )
vpp = polygons(82 , 64 )
lvs_prune = polygons(84 , 44 )
padcenter = polygons(81 , 20 )
mf = polygons(76 , 44 )
areaid_sl = polygons(81 , 1 )
areaid_ce = polygons(81 , 2 )
areaid_fe = polygons(81 , 3 )
areaid_sc = polygons(81 , 4 )
areaid_sf = polygons(81 , 6 )
areaid_sw = polygons(81 , 7 )
areaid_sr = polygons(81 , 8 )
areaid_mt = polygons(81 , 10 )
areaid_dt = polygons(81 , 11 )
areaid_ft = polygons(81 , 12 )
areaid_ww = polygons(81 , 13 )
areaid_ld = polygons(81 , 14 )
areaid_ns = polygons(81 , 15 )
areaid_ij = polygons(81 , 17 )
areaid_zr = polygons(81 , 18 )
areaid_ed = polygons(81 , 19 )
areaid_de = polygons(81 , 23 )
areaid_rd = polygons(81 , 24 )
areaid_dn = polygons(81 , 50 )
areaid_cr = polygons(81 , 51 )
areaid_cd = polygons(81 , 52 )
areaid_st = polygons(81 , 53 )
areaid_op = polygons(81 , 54 )
areaid_en = polygons(81 , 57 )
areaid_en20 = polygons(81 , 58 )
areaid_le = polygons(81 , 60 )
areaid_hl = polygons(81 , 63 )
areaid_sd = polygons(81 , 70 )
areaid_po = polygons(81 , 81 )
areaid_it = polygons(81 , 84 )
areaid_et = polygons(81 , 101)
areaid_lvt = polygons(81 , 108)
areaid_re = polygons(81 , 125)
areaid_ag = polygons(81 , 79 )
cfom = polygons(22 , 20 )
uhv_mos_1 = polygons(110, 14 )
uhv_mos_2 = polygons(173, 0 )
uhv_mos_3 = polygons(174, 0 )
logger.info("Read in labels from layers.")
#=== LABELS ===
sub_label = labels(122, 5)
pwelliso_label = labels(44 , 5)
nwell_label = labels(64 , 5)
pwell_label = labels(64 ,59)
tap_label = labels(65 , 5)
diff_label = labels(65 , 6)
poly_label = labels(66 , 5)
poly_model = labels(66 ,83)
li_label = labels(67 , 5)
met1_label = labels(68 , 5)
met2_label = labels(69 , 5)
met3_label = labels(70 , 5)
met4_label = labels(71 , 5)
met5_label = labels(72 , 5)
rdl_label = labels(74 , 5)
pad_label = labels(76 , 5)
txt_label = labels(83 ,44)
#=== BULK LAYER ===
sub = polygon_layer
#================================================
#------------------ SWITCHES --------------------
#================================================
logger.info("Evaluate switches start")
# FUSE
if $fuse
FUSE = $fuse
else
FUSE = "m4"
end # FUSE
# SCH_SIMPLE
if $schematic_simplify == "true"
SCH_SIMPLE = $schematic_simplify
else
SCH_SIMPLE = false
end # SCH_SIMPLE
logger.info("SCH_SIMPLE enabled %s" % [SCH_SIMPLE])
# NET_ONLY
if $net_only == "true"
NET_ONLY = true
else
NET_ONLY = false
end # NET_ONLY
logger.info("NET_ONLY enabled %s" % [NET_ONLY])
# TOP_LVL_PINS
if $top_lvl_pins == "true"
TOP_LVL_PINS = true
else
TOP_LVL_PINS = false
end # TOP_LVL_PINS
logger.info("TOP_LVL_PINS enabled %s" % [TOP_LVL_PINS])
# COMBINE
if $combine == "true"
COMBINE = true
else
COMBINE = false
end # COMBINE
logger.info("COMBINE enabled %s" % [COMBINE])
# PURGE
if $purge == "true"
PURGE = true
else
PURGE = false
end # PURGE
logger.info("PURGE enabled %s" % [PURGE])
# PURGE_NETS
if $purge_nets == "true"
PURGE_NETS = true
else
PURGE_NETS = false
end # PURGE_NETS
logger.info("PURGE_NETS enabled %s" % [PURGE_NETS])
# SIMPLIFY
if $net_only == "true" || $top_lvl_pins == "true" || $combine == "true" || $purge == "true" || $purge_nets == "true"
SIMPLIFY = false
else
SIMPLIFY = true
end # SIMPLIFY
logger.info("SIMPLIFY enabled %s" % [SIMPLIFY])
logger.info("Evaluate switches end.")
#================================================================
#------------------------- MAIN RUNSET --------------------------
#================================================================
logger.info("SKY130 LVS rules started")
#================================================
#------------- LAYERS DERIVATIONS ---------------
#================================================
logger.info("Starting deriving base layers.")
#==================================
# ------ GENERAL DERIVATIONS ------
#==================================
ncomp = diff.and(nsdm)
pcomp = diff.and(psdm)
sd = diff.not(poly).not(diff_res).not(diff_cut).not(tap).not(areaid_po).not(npnid).not(pnpid).not(areaid_de).not(uhv_mos_1).not(uhv_mos_2).not(uhv_mos_3)
tgate = poly.and(diff).not(poly_res).not(poly_cut).not(tap).not(tunm).not(rpm).not(npc).not(hvtr).not(uhv_mos_1).not(uhv_mos_2).not(uhv_mos_3)
ngate = nsdm.and(tgate).not(nwell).not(pwde).not(hvtp).not(psdm)
nsd = nsdm.and(sd).not(nwell).interacting(ngate)
ptap_conn = tap.and(psdm).not(nwell).not(diff_res).not(diff_cut).not(npnid).not(pnpid)
ptap_bjt = tap.and(psdm).not(diff_res).not(diff_cut)
pgate = psdm.and(tgate).and(nwell).not(ldntm).not(nsdm).not(areaid_le)
psd = psdm.and(sd).and(nwell).interacting(pgate)
ntap_conn = tap.and(nsdm).and(nwell).not(diff_res).not(diff_cut).not(npnid).not(pnpid)
ntap_bjt = tap.and(nsdm).not(diff_res).not(diff_cut)
poly_con = poly.not(poly_res).not(vpp).not(npnid)
li_con = li.not( li_res ).not(vpp)
met1_con = met1.not(met1_res).not(vpp)
met2_con = met2.not(met2_res).not(inductor).not(met2_fuse).not(vpp)
met3_con = met3.not(met3_res).not(inductor).not(met3_fuse).not(vpp)
met4_con = met4.not(met4_res).not(met4_fuse).not(vpp)
met5_con = met5.not(met5_res).not(vpp)
#==================================
# ------ MOSFET DERIVATIONS -------
#==================================
logger.info("Starting MOSFET DERIVATIONS")
# ==============
# ---- PMOS ----
# ==============
logger.info("Starting PMOS layers DERIVATIONS")
# General PMOS derivations
pgate_low_voltage = pgate.not(hvi).not(uhvi).not(pwbm).not(pwde).not(areaid_en).not(areaid_en20)
pgate_low_voltage_not_pass = pgate_low_voltage.not_interacting(poly_model).not(ncm).not(areaid_ce)
pgate_high_voltage = pgate.and(hvi).not(hvtp).not(areaid_ce)
# 1.8V PMOS transistor standard
pgate_1p8v = pgate_low_voltage_not_pass.not(hvtp).not(lvtn)
# 1.8V PMOS transistor low threshold voltage
pgate_1p8v_lvt = pgate_low_voltage_not_pass.not(hvtp).and(lvtn)
# 1.8V PMOS transistor high threshold voltage
pgate_1p8v_hvt = pgate_low_voltage_not_pass.and(hvtp).not(lvtn)
# 5V gate 10.5V drain PMOS transistor
pgate_5p0v_hv = pgate_high_voltage.not(lvtn).not(areaid_en).not(areaid_en20)
# ==============
# ---- NMOS ----
# ==============
logger.info("Starting NMOS layers DERIVATIONS")
# General NMOS derivations
ngate_low_voltage = ngate.not(hvi).not(uhvi).not(pwbm).not(areaid_en).not(areaid_en20)
ngate_low_voltage_not_pass = ngate_low_voltage.not_interacting(poly_model).not(ncm).not(ldntm).not(areaid_ce).not(ldntm)
ngate_high_voltage = ngate.and(hvi).not(uhvi).not(ncm).not(areaid_ce).not(ldntm).not(pwbm)
ngate_nvt = ngate_high_voltage.and(lvtn).not(areaid_ed).not(areaid_ce)
# 1.8V NMOS transistor standard
ngate_1p8v = ngate_low_voltage_not_pass.not(lvtn)
# 1.8V NMOS transistor low threshold voltage
ngate_1p8v_lvt = ngate_low_voltage_not_pass.and(lvtn)
# 3.3V NMOS transistor native voltage
ngate_3p0v_nvt = ngate_nvt.and(areaid_le)
# 5V NMOS transistor native voltage
ngate_5p0v_nvt = ngate_nvt.not(areaid_le).not_interacting(vpp)
# 5V gate 10.5V drain NMOS transistor
ngate_5p0v_hv = ngate_high_voltage.not(lvtn).not(areaid_en).not(areaid_en20)
#================================
# ------ BJT DERIVATIONS --------
#================================
logger.info("Starting BJT DERIVATIONS")
# BJT DERIVATIONS
bjt_exclude = diff_res.or(diff_cut).or(pwbm).or(pwde).or(hvtr).or(lvtn).or(ncm).or(poly_res).or(poly_cut).or(li_res).or(li_cut)
npn_exclude = bjt_exclude.or(pwell_res)
pnp_exclude = bjt_exclude.or(dnwell)
#==============
# ---- npn ----
#==============
logger.info("Starting NPN layers DERIVATIONS")
# NPN general nodes DERIVATIONS
npn_e = ncomp.inside(dnwell).inside(npnid).not(npn_exclude)
npn_b = ptap_bjt.inside(dnwell).inside(npnid).not(npn_exclude)
npn_c = ntap_bjt.inside(nwell).inside(dnwell).interacting(npnid).not(npn_exclude)
# 5V NPN with emitter size of 1umx1um nodes DERIVATIONS
npn_5v0_1x1_e = npn_e.with_area(0.81.um, 1.21.um).interacting(npn_e.edges.with_length(0.9.um, 1.1.um)).not_interacting(poly)
npn_5v0_1x1_b = npn_b.interacting(npn_b.extents.interacting(npn_5v0_1x1_e))
npn_5v0_1x1_c = npn_c.interacting(npn_c.extents.interacting(npn_5v0_1x1_e))
# 5V NPN with emitter size of 1umx2um DERIVATIONS
npn_5v0_1x2_e = npn_e.with_area(1.71.um, 2.31.um).interacting(npn_e.edges.with_length(1.9.um, 2.1.um)).not_interacting(poly)
npn_5v0_1x2_b = npn_b.interacting(npn_b.extents.interacting(npn_5v0_1x2_e))
npn_5v0_1x2_c = npn_c.interacting(npn_c.extents.interacting(npn_5v0_1x2_e))
# 11V NPN poly-gated with octagonal emitter nodes DERIVATIONS
npn_11v0_1x1_e = npn_e.interacting(poly)
npn_11v0_1x1_b = npn_b.interacting(npn_b.extents.interacting(npn_11v0_1x1_e))
npn_11v0_1x1_c = npn_c.interacting(npn_c.extents.interacting(npn_11v0_1x1_e))
#==============
# ---- pnp ----
#==============
logger.info("Starting PNP layers DERIVATIONS")
# PNP general nodes DERIVATIONS
pnp_e = pcomp.inside(nwell).inside(pnpid).not(pnp_exclude).not_interacting(poly)
pnp_b = ntap_bjt.inside(pnpid).not(pnp_exclude).not_interacting(poly)
pnp_c = ptap_bjt.interacting(pnpid).not(pnp_exclude).not_interacting(poly)
# 5V PNP with emitter size of 0.68umx0.68um DERIVATIONS
pnp_5v0_0p68x0p68_e = pnp_e.with_area(0.3364.um, 0.6084.um).interacting(pnp_e.edges.with_length(0.58.um, 0.78.um))
pnp_5v0_0p68x0p68_b = pnp_b.interacting(pnp_b.extents.interacting(pnp_5v0_0p68x0p68_e))
pnp_5v0_0p68x0p68_c = pnp_c.interacting(pnp_c.extents.interacting(pnp_5v0_0p68x0p68_e))
# 5V PNP with emitter size of 3.4umx3.4um DERIVATIONS
pnp_5v0_3p4x3p4_e = pnp_e.with_area(10.24.um, 12.96.um).interacting(pnp_e.edges.with_length(3.2.um, 3.6.um))
pnp_5v0_3p4x3p4_b = pnp_b.interacting(pnp_b.extents.interacting(pnp_5v0_3p4x3p4_e))
pnp_5v0_3p4x3p4_c = pnp_c.interacting(pnp_c.extents.interacting(pnp_5v0_3p4x3p4_e))
#================================
# ----- DIODE DERIVATIONS -------
#================================
logger.info("Starting DIODE DERIVATIONS")
# N+ diffusion diode
ndiode_terminal_n = ncomp.outside(dnwell).not(hvtp).interacting(areaid_de).not_interacting(areaid_ed)
ndiode_terminal_p = ptap_conn.holes.interacting(ndiode_terminal_n).not_interacting(areaid_ed)
# P+ diffusion diode
pdiode_terminal_n = pcomp.outside(dnwell).interacting(areaid_de).not_interacting(areaid_ed)
pdiode_terminal_p = nwell.interacting(areaid_de).not_interacting(areaid_ed)
# 5V N+ diffusion diode
ndiode_5v0_terminal_n = ndiode_terminal_n.not(hvi).not(lvtn)
ndiode_5v0_terminal_p = ndiode_terminal_p.interacting(ndiode_5v0_terminal_n)
# 5V N+ diffusion diode low threshold voltage [lvt]
ndiode_5v0_lvt_terminal_n = ndiode_terminal_n.not(hvi).and(lvtn)
ndiode_5v0_lvt_terminal_p = ndiode_terminal_p.interacting(ndiode_5v0_lvt_terminal_n)
# 5V N+ diffusion diode native threshold voltage [lvt & hvi]
ndiode_5v0_nvt_terminal_n = ndiode_terminal_n.and(hvi).and(lvtn)
ndiode_5v0_nvt_terminal_p = ndiode_terminal_p.interacting(ndiode_5v0_nvt_terminal_n)
# 11V N+ diffusion diode
ndiode_11v0_terminal_n = ndiode_terminal_n.and(hvi).not(lvtn)
ndiode_11v0_terminal_p = ndiode_terminal_p.interacting(ndiode_11v0_terminal_n)
# 5V P+ diffusion diode
pdiode_5v0_terminal_n = pdiode_terminal_n.not(hvtp).not(hvi).not(lvtn)
pdiode_5v0_terminal_p = pdiode_terminal_p.interacting(pdiode_5v0_terminal_n)
# 5V P+ diffusion diode low threshold voltage [lvt]
pdiode_5v0_lvt_terminal_n = pdiode_terminal_n.not(hvtp).not(hvi).and(lvtn)
pdiode_5v0_lvt_terminal_p = pdiode_terminal_p.interacting(pdiode_5v0_lvt_terminal_n)
# 5V P+ diffusion diode high threshold voltage [hvtp]
pdiode_5v0_hvt_terminal_n = pdiode_terminal_n.and(hvtp).not(hvi).not(lvtn)
pdiode_5v0_hvt_terminal_p = pdiode_terminal_p.interacting(pdiode_5v0_hvt_terminal_n)
# 11V P+ diffusion diode [hvi]
pdiode_11v0_terminal_n = pdiode_terminal_n.not(hvtp).and(hvi).not(lvtn)
pdiode_11v0_terminal_p = pdiode_terminal_p.interacting(pdiode_11v0_terminal_n)
#================================
# --- PHOTODIODE DERIVATIONS ----
#================================
logger.info("Starting PHOTODIODE DERIVATIONS")
# Photodiode
photodiode_exclude = diff.or(pwbm).or(pwde).or(hvtr).or(hvtp).or(areaid_de).or(areaid_ed)
photodiode_n_init = ntap_conn.and(nwell).and(dnwell).interacting(areaid_po).not(photodiode_exclude)
photodiode_n = photodiode_n_init.with_area(0.16.um, 0.1764.um).interacting(photodiode_n_init.edges.with_length(0.4.um, 0.42.um))
photodiode_p = ptap_conn.holes.interacting(photodiode_n)
#================================
# ---- RESISTOR DERIVATIONS -----
#================================
logger.info("Starting RESISTOR DERIVATIONS")
# ===============
# --DIFF & WELL--
# ===============
# RES DERIVATIONS
nplus_res_init = ncomp.and(diff_res)
pplus_res_init = pcomp.and(nwell).and(diff_res)
nplus_cont_init = ncomp.not_interacting(ngate).interacting(diff_res).not(diff_res)
pplus_cont_init = pcomp.and(nwell).not_interacting(pgate).interacting(diff_res).not(diff_res)
# N+ diffusion resistor
nplus_res = nplus_res_init.not(hvi)
nplus_cont = nplus_cont_init.not(hvi)
# N+ diffusion high voltage resistor
nplus_hv_res = nplus_res_init.and(hvi)
nplus_hv_cont = nplus_cont_init.and(hvi)
# P+ diffusion resistor
pplus_res = pplus_res_init.not(hvi)
pplus_cont = pplus_cont_init.not(hvi)
# P+ diffusion high voltage resistor
pplus_hv_res = pplus_res_init.and(hvi)
pplus_hv_cont = pplus_cont_init.and(hvi)
# Isolated PWELL resistor
pwell_resistor = pwell_res.not(nwell).and(dnwell)
pwell_term = ptap_conn.and(dnwell).interacting(pwell_res).not(pwell_res)
pwell_cont = nwell.holes.covering(pwell_term)
# ==============
# ---- POLY ----
# ==============
# Poly resistor
poly_res_exclude = diff.or(diff_res).or(diff_cut).or(tap).or(pwbm).or(hvtr).or(hvtp).or(lvtn).or(li_cut).or(vpp).or(npnid)
poly_res_init = poly.and(poly_res).not(poly_res_exclude)
# Poly resistor generic
poly_res_generic = poly_res_init.not(rpm).not(urpm)
# 300 ohm Poly resistor
poly_res_300 = poly_res_init.and(psdm).and(rpm).not(urpm)
poly_high_0p35 = poly_res_300.interacting(poly_res_300.edges.with_length(0.34.um, 0.36.um))
poly_high_0p69 = poly_res_300.interacting(poly_res_300.edges.with_length(0.68.um, 0.7.um ))
poly_high_1p41 = poly_res_300.interacting(poly_res_300.edges.with_length(1.4.um , 1.42.um))
poly_high_2p85 = poly_res_300.interacting(poly_res_300.edges.with_length(2.84.um, 2.86.um))
poly_high_5p73 = poly_res_300.interacting(poly_res_300.edges.with_length(5.72.um, 5.74.um))
# 2K ohm Poly resistor
poly_res_2k = poly_res_init.and(psdm).not(rpm).and(urpm)
poly_xhigh_0p35 = poly_res_2k.interacting(poly_res_2k.edges.with_length(0.34.um, 0.36.um))
poly_xhigh_0p69 = poly_res_2k.interacting(poly_res_2k.edges.with_length(0.68.um, 0.7.um ))
poly_xhigh_1p41 = poly_res_2k.interacting(poly_res_2k.edges.with_length(1.4.um , 1.42.um))
poly_xhigh_2p85 = poly_res_2k.interacting(poly_res_2k.edges.with_length(2.84.um, 2.86.um))
poly_xhigh_5p73 = poly_res_2k.interacting(poly_res_2k.edges.with_length(5.72.um, 5.74.um))
# ===============
# ---- METAL ----
# ===============
# Local inter-connect resistor
li_resistor = li.and(li_res)
# Metal1 resistor
met1_resistor = met1.and(met1_res)
# Metal2 resistor
met2_resistor = met2.and(met2_res)
# Metal3 resistor
met3_resistor = met3.and(met3_res)
# Metal4 resistor
met4_resistor = met4.and(met4_res)
# Metal5 resistor
met5_resistor = met5.and(met5_res)
#==================================
# ------- FUSE DERIVATIONS --------
#==================================
logger.info("Starting FUSE DERIVATIONS")
if FUSE == "m2"
# Metal2 fuse
met2_fuse_res_layer = met2.and(met2_fuse)
elsif FUSE == "m3"
# Metal3 fuse
met3_fuse_res_layer = met3.and(met3_fuse)
else
# Metal4 fuse
met4_fuse_res_layer = met4.and(met4_fuse)
end
#==================================
# ----- MIM DERIVATIONS ------
#==================================
logger.info("Starting MIM DERIVATIONS")
# mim on metal3
met3_ncap = met3_con.not(capm)
# mim on metal3
met4_ncap = met4_con.not(capm2) # mim on metal4
#==================================
# ----- VARACTOR DERIVATIONS ------
#==================================
logger.info("Starting VARACTOR DERIVATIONS")
# voltage varactor
varactor_exclude = dnwell.or(hvtr).or(pwbm).or(pwde).or(ncm).or(tunm).or(rpm).or(ldntm).or(npc).or(psdm).or(li_res).or(li_cut).or(areaid_de)
varactor_gate = poly_con.and(ntap_conn).not(varactor_exclude)
# Low threshold voltage varactor
varactor_gate_lvt = poly_con.interacting(varactor_gate.not(hvtp).not(hvi))
varactor_nsd_lvt = ntap_conn.not(hvtp).not(hvi).interacting(varactor_gate_lvt).not(varactor_exclude)
varactor_bulk_lvt = ptap_conn.holes.interacting(varactor_gate_lvt)
# High threshold voltage varactor
varactor_gate_hvt = poly_con.interacting(varactor_gate.and(hvtp).not(hvi))
varactor_nsd_hvt = ntap_conn.and(hvtp).not(hvi).interacting(varactor_gate_hvt).not(varactor_exclude)
varactor_bulk_hvt = ptap_conn.holes.interacting(varactor_gate_hvt)
#==================================
# ----- INDUCTOR DERIVATIONS ------
#==================================
logger.info("Starting INDUCTOR DERIVATIONS")
# General Inductor derivations
met3_ind = met3.and(inductor)
# RF Inductor with 3 turns and internal diameter of 90um
coil_1 = inductor.interacting(met3.or(met2).and(inductor.covering(met2.and(inductor), 3, 3)).holes.width(100.um, projection).with_distance(89.um, 91.um).polygons)
# RF Inductor with 5 turns and internal diameter of 125um
coil_2 = inductor.interacting(met3.or(met2).and(inductor.covering(met2.and(inductor), 5, 5)).holes.width(135.um, projection).with_distance(124.um, 126.um).polygons)
# RF Inductor with 5 turns and internal diameter of 220um
coil_3 = inductor.interacting(met3.or(met2).and(inductor.covering(met2.and(inductor), 5, 5)).holes.width(230.um, projection).with_distance(219.um, 221.um).polygons)
#==================================
# ------ VPP CAP DERIVATIONS ------
#==================================
logger.info("Starting VPP CAP DERIVATIONS")
# General VPP capacitor derivation
vpp_sub = vpp.and(extent)
# ===============
# --- LENGTHS ---
# ===============
vpp_1_43 = vpp.edges.with_length(1.42 , 1.44 )
vpp_2_08 = vpp.edges.with_length(2.07 , 2.09 )
vpp_2_36 = vpp.edges.with_length(2.35 , 2.37 )
vpp_2_51 = vpp.edges.with_length(2.50 , 2.52 )
vpp_4_04 = vpp.edges.with_length(4.03 , 4.05 )
vpp_4_25 = vpp.edges.with_length(4.24 , 4.26 )
vpp_4_38 = vpp.edges.with_length(4.37 , 4.39 )
vpp_4_59 = vpp.edges.with_length(4.58 , 4.60 )
vpp_5_49 = vpp.edges.with_length(5.48 , 5.50 )
vpp_5_75 = vpp.edges.with_length(5.74 , 5.76 )
vpp_5_76 = vpp.edges.with_length(5.75 , 5.77 )
vpp_6_46 = vpp.edges.with_length(6.45 , 6.47 )
vpp_7_50 = vpp.edges.with_length(7.49 , 7.51 )
vpp_7_84 = vpp.edges.with_length(7.83 , 7.85 )
vpp_8_24 = vpp.edges.with_length(8.23 , 8.25 )
vpp_8_58 = vpp.edges.with_length(8.57 , 8.59 )
vpp_10_40 = vpp.edges.with_length(10.39, 10.41)
vpp_10_76 = vpp.edges.with_length(10.75, 10.77)
vpp_10_99 = vpp.edges.with_length(10.98, 11.00)
vpp_11_07 = vpp.edges.with_length(11.06, 11.08)
vpp_11_17 = vpp.edges.with_length(11.16, 11.18)
vpp_11_27 = vpp.edges.with_length(11.26, 11.28)
vpp_11_35 = vpp.edges.with_length(11.34, 11.36)
vpp_11_53 = vpp.edges.with_length(11.52, 11.54)
vpp_20_76 = vpp.edges.with_length(20.75, 20.77)
vpp_22_27 = vpp.edges.with_length(22.26, 22.28)
vpp_22_63 = vpp.edges.with_length(22.62, 22.64)
vpp_33_31 = vpp.edges.with_length(33.30, 33.32)
vpp_40_76 = vpp.edges.with_length(40.75, 40.77)
vpp_44_33 = vpp.edges.with_length(44.32, 44.34)
vpp_55_39 = vpp.edges.with_length(55.38, 55.40)
vpp_55_45 = vpp.edges.with_length(55.44, 55.46)
vpp_55_47 = vpp.edges.with_length(55.46, 55.48)
# ===============
# ---- METAL ----
# ===============
poly_vpp = poly.and(vpp)
li_vpp = li.and(vpp)
met1_vpp = met1.and(vpp)
met2_vpp = met2.and(vpp)
met3_vpp = met3.and(vpp)
met4_vpp = met4.and(vpp)
met5_vpp = met5.and(vpp)
licon_vpp = licon.and(vpp)
mcon_vpp = mcon.and(vpp)
via1_vpp = via1.and(vpp)
via2_vpp = via2.and(vpp)
via3_vpp = via3.and(vpp)
via4_vpp = via4.and(vpp)
# met4_xvpp = met4.interacting(met4.extents.edges.with_length(55.1.um , 55.12.um )).interacting(met4.extents.edges.with_length(28.89.um , 28.91.um ))
# ===============
# ---- AREAS ----
# ===============
vpp_04p4x04p6 = vpp.interacting(vpp_4_04).interacting(vpp_4_25)
vpp_06p8x06p1 = vpp.interacting(vpp_6_46).interacting(vpp_5_75)
vpp_08p6x07p8 = vpp.interacting(vpp_8_24).interacting(vpp_7_50)
vpp_11p5x11p7 = vpp.interacting(vpp_11_07).interacting(vpp_11_35)
# ===============
# ---- STACK ----
# ===============
vpp_m1m2 = vpp.not_interacting(poly).not_interacting(li).not_interacting(met3).not_interacting(met4).not_interacting(met5)
vpp_m1m2m3 = vpp.not_interacting(poly).not_interacting(li).interacting(met3).not_interacting(met4).not_interacting(met5)
vpp_m1m2m3m4 = vpp.not_interacting(poly).not_interacting(li).interacting(met3).interacting(met4).not_interacting(met5)
vpp_m1m2m3m4m5 = vpp.not_interacting(poly).not_interacting(li).interacting(met3).interacting(met4).interacting(met5)
vpp_l1m1m2 = vpp.not_interacting(poly).interacting(li).not_interacting(met3).not_interacting(met4).not_interacting(met5)
vpp_l1m1m2m3 = vpp.not_interacting(poly).interacting(li).interacting(met3).not_interacting(met4).not_interacting(met5)
vpp_l1m1m2m3m4 = vpp.not_interacting(poly).interacting(li).interacting(met3).interacting(met4).not_interacting(met5)
vpp_l1m1m2m3m4m5 = vpp.not_interacting(poly).interacting(li).interacting(met3).interacting(met4).interacting(met5)
vpp_pol1m1m2m3 = vpp.interacting(poly).interacting(li).interacting(met3).not_interacting(met4).not_interacting(met5)
vpp_pol1m1m2m3m4 = vpp.interacting(poly).interacting(li).interacting(met3).interacting(met4).not_interacting(met5)
vpp_pol1m1m2m3m4m5 = vpp.interacting(poly).interacting(li).interacting(met3).interacting(met4).interacting(met5)
# ===============
# --- DEVICES ---
# ===============
# vpp_02p4x04p6_m1m2_noshield device
vpp_02p4x04p6_m1m2_noshield = vpp.interacting(vpp_2_08).interacting(vpp_4_25)
# vpp_02p7x06p1_m1m2m3m4_shieldl1_fingercap device
vpp_02p7x06p1_m1m2m3m4_shieldl1_fingercap = vpp.interacting(vpp_2_36).interacting(vpp_5_76)
# vpp_02p7x11p1_m1m2m3m4_shieldl1_fingercap device
vpp_02p7x11p1_m1m2m3m4_shieldl1_fingercap = vpp.interacting(vpp_2_36).interacting(vpp_10_76)
# vpp_02p7x21p1_m1m2m3m4_shieldl1_fingercap device
vpp_02p7x21p1_m1m2m3m4_shieldl1_fingercap = vpp.interacting(vpp_2_36).interacting(vpp_20_76)
# vpp_02p7x41p1_m1m2m3m4_shieldl1_fingercap device
vpp_02p7x41p1_m1m2m3m4_shieldl1_fingercap = vpp.interacting(vpp_2_36).interacting(vpp_40_76)
# vpp_02p9x06p1_m1m2m3m4_shieldl1_fingercap2 device
vpp_02p9x06p1_m1m2m3m4_shieldl1_fingercap2 = vpp.interacting(vpp_2_51).interacting(vpp_5_76)
# vpp_03p9x03p9_m1m2_shieldl1_floatm3 device
vpp_03p9x03p9_m1m2_shieldl1_floatm3 = vpp.interacting(vpp_1_43).interacting(vpp_1_43)
# vpp_04p4x04p6_l1m1m2_noshield device
vpp_04p4x04p6_l1m1m2_noshield = vpp.interacting(vpp_04p4x04p6).interacting(vpp_l1m1m2).covering(li.holes)
# vpp_04p4x04p6_l1m1m2_noshield_o2subcell device
vpp_04p4x04p6_l1m1m2_noshield_o2subcell = vpp.interacting(vpp_4_38).interacting(vpp_4_59).interacting(vpp_l1m1m2)
# vpp_04p4x04p6_l1m1m2_shieldpo_floatm3 device
vpp_04p4x04p6_l1m1m2_shieldpo_floatm3 = vpp.interacting(vpp_04p4x04p6).interacting(vpp_pol1m1m2m3)
# vpp_04p4x04p6_m1m2m3_shieldl1 device
vpp_04p4x04p6_m1m2m3_shieldl1 = vpp.interacting(vpp_04p4x04p6).interacting(vpp_l1m1m2m3)
# vpp_04p4x04p6_m1m2m3_shieldl1m5_floatm4 device
vpp_04p4x04p6_m1m2m3_shieldl1m5_floatm4 = vpp.interacting(vpp_04p4x04p6).interacting(vpp_l1m1m2m3m4m5)
# vpp_04p4x04p6_m1m2_noshield device
vpp_04p4x04p6_m1m2_noshield = vpp.interacting(vpp_04p4x04p6).interacting(vpp_m1m2).covering(met1.holes)
# vpp_04p4x04p6_m1m2_noshield_o2 device
vpp_04p4x04p6_m1m2_noshield_o2 = vpp.interacting(vpp_04p4x04p6).interacting(vpp_m1m2).not_covering(met1.holes)
# vpp_04p4x04p6_m1m2_shieldl1 device
vpp_04p4x04p6_m1m2_shieldl1 = vpp.interacting(vpp_04p4x04p6).interacting(vpp_l1m1m2).not_covering(li.holes)
# vpp_05p9x05p9_m1m2m3m4_shieldl1_wafflecap device
vpp_05p9x05p9_m1m2m3m4_shieldl1_wafflecap = vpp.interacting(vpp_5_49).interacting(vpp_5_49)
# vpp_06p8x06p1_l1m1m2m3_shieldpom4 device
vpp_06p8x06p1_l1m1m2m3_shieldpom4 = vpp.interacting(vpp_06p8x06p1).interacting(vpp_pol1m1m2m3m4)
# vpp_06p8x06p1_m1m2m3_shieldl1m4 device
vpp_06p8x06p1_m1m2m3_shieldl1m4 = vpp.interacting(vpp_06p8x06p1).interacting(vpp_l1m1m2m3m4)
# vpp_08p6x07p8_l1m1m2_noshield device
vpp_08p6x07p8_l1m1m2_noshield = vpp.interacting(vpp_08p6x07p8).interacting(vpp_l1m1m2).covering(li.holes)
# vpp_08p6x07p8_l1m1m2_noshield_o2subcell device
vpp_08p6x07p8_l1m1m2_noshield_o2subcell = vpp.interacting(vpp_7_84).interacting(vpp_8_58).interacting(vpp_l1m1m2)
# vpp_08p6x07p8_l1m1m2_shieldpo_floatm3 device
vpp_08p6x07p8_l1m1m2_shieldpo_floatm3 = vpp.interacting(vpp_08p6x07p8).interacting(vpp_pol1m1m2m3)
# vpp_08p6x07p8_m1m2m3_shieldl1 device
vpp_08p6x07p8_m1m2m3_shieldl1 = vpp.interacting(vpp_08p6x07p8).interacting(vpp_l1m1m2m3)
# vpp_08p6x07p8_m1m2m3_shieldl1m5_floatm4 device
vpp_08p6x07p8_m1m2m3_shieldl1m5_floatm4 = vpp.interacting(vpp_08p6x07p8).interacting(vpp_l1m1m2m3m4m5)
# vpp_08p6x07p8_m1m2_noshield device
vpp_08p6x07p8_m1m2_noshield = vpp.interacting(vpp_08p6x07p8).interacting(vpp_m1m2)
# vpp_08p6x07p8_m1m2_shieldl1 device
vpp_08p6x07p8_m1m2_shieldl1 = vpp.interacting(vpp_08p6x07p8).interacting(vpp_l1m1m2).not_covering(li.holes)
# vpp_11p3x11p3_m1m2m3m4_shieldl1_wafflecap device
vpp_11p3x11p3_m1m2m3m4_shieldl1_wafflecap = vpp.interacting(vpp_10_99).interacting(vpp_10_99)
# vpp_11p3x11p8_l1m1m2m3m4_shieldm5_nhv device
vpp_11p3x11p8_l1m1m2m3m4_shieldm5_nhv = vpp.interacting(vpp_10_40).interacting(vpp_11_53)
# vpp_11p5x11p7_l1m1m2m3m4_shieldm5 device
vpp_11p5x11p7_l1m1m2m3m4_shieldm5 = vpp.interacting(vpp_11p5x11p7).interacting(vpp_l1m1m2m3m4m5).covering(li.holes).covering(met4.holes)
# vpp_11p5x11p7_l1m1m2m3m4_shieldpom5 device
vpp_11p5x11p7_l1m1m2m3m4_shieldpom5 = vpp.interacting(vpp_11p5x11p7).interacting(vpp_pol1m1m2m3m4m5).interacting(met5.covering(vpp))
# vpp_11p5x11p7_l1m1m2m3m4_shieldpom5_x device
vpp_11p5x11p7_l1m1m2m3m4_shieldpom5_x = vpp.interacting(vpp_11p5x11p7).interacting(vpp_pol1m1m2m3m4m5).interacting(met5.not_covering(vpp))
# # vpp_11p5x11p7_l1m1m2m3m4_shieldpom5_x6 device
# vpp_11p5x11p7_l1m1m2m3m4_shieldpom5_x6 = vpp.interacting(vpp_11p5x11p7).interacting(vpp_pol1m1m2m3m4m5).interacting(met5.covering(vpp)).inside(vpp.sized(15.um).interacting(ptap_conn)).interacting(met4.not_covering(vpp))
# # vpp_11p5x11p7_l1m1m2m3m4_shieldpom5_x7 device
# vpp_11p5x11p7_l1m1m2m3m4_shieldpom5_x7 = vpp.interacting(vpp_11p5x11p7).interacting(vpp_pol1m1m2m3m4m5).interacting(met5.not_covering(vpp)).inside(vpp.sized(15.um).interacting(ptap_conn)).interacting(met4.not_covering(vpp))
# # vpp_11p5x11p7_l1m1m2m3m4_shieldpom5_x8 device
# vpp_11p5x11p7_l1m1m2m3m4_shieldpom5_x8 = vpp.interacting(vpp_11p5x11p7).interacting(vpp_pol1m1m2m3m4m5).interacting(met5.covering(vpp)).interacting(met4_xvpp)
# # vpp_11p5x11p7_l1m1m2m3m4_shieldpom5_x9 device
# vpp_11p5x11p7_l1m1m2m3m4_shieldpom5_x9 = vpp.interacting(vpp_11p5x11p7).interacting(vpp_pol1m1m2m3m4m5).interacting(met5.not_covering(vpp)).interacting(met4_xvpp)
# vpp_11p5x11p7_l1m1m2m3_shieldm4 device
vpp_11p5x11p7_l1m1m2m3_shieldm4 = vpp.interacting(vpp_11p5x11p7).interacting(vpp_l1m1m2m3m4)
# vpp_11p5x11p7_l1m1m2m3_shieldpom4 device
vpp_11p5x11p7_l1m1m2m3_shieldpom4 = vpp.interacting(vpp_11p5x11p7).interacting(vpp_pol1m1m2m3m4)
# vpp_11p5x11p7_l1m1m2_noshield device
vpp_11p5x11p7_l1m1m2_noshield = vpp.interacting(vpp_11p5x11p7).interacting(vpp_l1m1m2).covering(li.holes)
# vpp_11p5x11p7_l1m1m2_shieldpom3 device
vpp_11p5x11p7_l1m1m2_shieldpom3 = vpp.interacting(vpp_11p5x11p7).interacting(vpp_pol1m1m2m3)
# vpp_11p5x11p7_m1m2m3m4_shieldl1m5 device
vpp_11p5x11p7_m1m2m3m4_shieldl1m5 = vpp.interacting(vpp_11p5x11p7).interacting(vpp_l1m1m2m3m4m5).not_covering(li.holes).covering(met4.holes)
# vpp_11p5x11p7_m1m2m3m4_shieldm5 device
vpp_11p5x11p7_m1m2m3m4_shieldm5 = vpp.interacting(vpp_11p5x11p7).interacting(vpp_m1m2m3m4m5)
# vpp_11p5x11p7_m1m2m3_shieldl1 device
vpp_11p5x11p7_m1m2m3_shieldl1 = vpp.interacting(vpp_11p5x11p7).interacting(vpp_l1m1m2m3)
# vpp_11p5x11p7_m1m2m3_shieldl1m5_floatm4 device
vpp_11p5x11p7_m1m2m3_shieldl1m5_floatm4 = vpp.interacting(vpp_11p5x11p7).interacting(vpp_l1m1m2m3m4m5).not_covering(met4.holes)
# vpp_11p5x11p7_m1m2_noshield device
vpp_11p5x11p7_m1m2_noshield = vpp.interacting(vpp_11p5x11p7).interacting(vpp_m1m2)
# vpp_11p5x11p7_m1m2_shieldl1 device
vpp_11p5x11p7_m1m2_shieldl1 = vpp.interacting(vpp_11p5x11p7).interacting(vpp_l1m1m2).not_covering(li.holes)
# vpp_11p5x11p7_m1m4_noshield device
vpp_11p5x11p7_m1m4_noshield = vpp.interacting(vpp_11p5x11p7).interacting(vpp_m1m2m3m4)
# vpp_11p5x11p7_pol1m1m2m3m4m5_noshield device
vpp_11p5x11p7_pol1m1m2m3m4m5_noshield = vpp.interacting(vpp_11_17).interacting(vpp_11_27)
# vpp_11p5x23p1_pol1m1m2m3m4m5_noshield device
vpp_11p5x23p1_pol1m1m2m3m4m5_noshield = vpp.interacting(vpp_11_17).interacting(vpp_22_63)
# vpp_22p5x11p7_pol1m1m2m3m4m5_noshield device
vpp_22p5x11p7_pol1m1m2m3m4m5_noshield = vpp.interacting(vpp_22_27).interacting(vpp_11_27)
# vpp_22p5x23p1_pol1m1m2m3m4m5_noshield device
vpp_22p5x23p1_pol1m1m2m3m4m5_noshield = vpp.interacting(vpp_22_27).interacting(vpp_22_63)
# vpp_33p6x11p7_pol1m1m2m3m4m5_noshield device
vpp_33p6x11p7_pol1m1m2m3m4m5_noshield = vpp.interacting(vpp_33_31).interacting(vpp_11_27)
# vpp_33p6x23p1_pol1m1m2m3m4m5_noshield device
vpp_33p6x23p1_pol1m1m2m3m4m5_noshield = vpp.interacting(vpp_33_31).interacting(vpp_22_63)
# vpp_44p7x11p7_pol1m1m2m3m4m5_noshield device
vpp_44p7x11p7_pol1m1m2m3m4m5_noshield = vpp.interacting(vpp_44_33).interacting(vpp_11_27)
# vpp_44p7x23p1_pol1m1m2m3m4m5_noshield device
vpp_44p7x23p1_pol1m1m2m3m4m5_noshield = vpp.interacting(vpp_44_33).interacting(vpp_22_63)
# vpp_55p8x11p7_pol1m1m2m3m4m5_noshield device
vpp_55p8x11p7_pol1m1m2m3m4m5_noshield = vpp.interacting(vpp_55_45).interacting(vpp_11_27)
# vpp_55p8x11p7_pol1m1m2m3m4m5_noshield_m5pullin device
vpp_55p8x11p7_pol1m1m2m3m4m5_noshield_m5pullin = vpp.interacting(vpp_55_47).interacting(vpp_11_27)
# vpp_55p8x23p1_pol1m1m2m3m4m5_noshield device
vpp_55p8x23p1_pol1m1m2m3m4m5_noshield = vpp.interacting(vpp_55_45).interacting(vpp_22_63)
# vpp_55p8x23p1_pol1m1m2m3m4m5_noshield_m5pullin device
vpp_55p8x23p1_pol1m1m2m3m4m5_noshield_m5pullin = vpp.interacting(vpp_55_47).interacting(vpp_22_63)
# vpp_55p8x23p1_pol1m1m2m3m4m5_noshield_test device
vpp_55p8x23p1_pol1m1m2m3m4m5_noshield_test = vpp.interacting(vpp_55_39).interacting(vpp_22_63)
#==================================
# ------- SONOS DERIVATIONS -------
#==================================
logger.info("Starting SONOS DERIVATIONS")
# Build space flash special SONOSFET original/star
sonos_exclude = diff_res.or(diff_cut).or(tap).or(pwbm).or(pwde).or(hvtr).or(nwell).or(hvtp).or(ncm).or(hvi).or(rpm).or(poly_res).or(poly_cut).or(npc)
sonos_tgate = poly.and(diff).not(sonos_exclude)
sonos_ngate = nsdm.and(sonos_tgate).not(psdm)
sonos_gate = sonos_ngate.and(lvtn).and(dnwell).and(tunm).and(ldntm).interacting(areaid_ce)
sonos_nsd = nsdm.and(sd).not(nwell).interacting(sonos_gate)
#================================================
#------------ DEVICES CONNECTIVITY --------------
#================================================
logger.info("Starting SKY130 LVS connectivity setup")
#================================
# ----- GENERAL CONNECTIONS -----
#================================
logger.info("Starting SKY130 LVS connectivity setup (Inter-layer)")
# Inter-layer
connect(sub , ptap_conn)
connect(dnwell , ntap_conn)
connect(nwell , ntap_conn)
connect(ptap_conn , licon)
connect(ntap_conn , licon)
connect(psd , licon)
connect(nsd , licon)
connect(poly_con , licon)
connect(licon , li_con)
connect(li_con , mcon)
connect(mcon , met1_con)
connect(met1_con , via1)
connect(via1 , met2_con)
connect(met2_con , via2)
connect(via2 , met3_ncap)
connect(met3_ncap , via3)
connect(via3 , met4_ncap)
connect(met4_ncap , via4)
connect(via4 , met5_con)
logger.info("Starting SKY130 LVS connectivity setup (Attaching labels)")
# Attaching labels
connect(sub , sub_label)
connect(nwell , nwell_label)
connect(tap , tap_label)
connect(nsd , diff_label)
connect(psd , diff_label)
connect(poly_con , poly_label)
connect(li_con , li_label)
connect(met1_con , met1_label)
connect(met2_con , met2_label)
connect(met3_ncap , met3_label)
connect(met4_ncap , met4_label)
connect(met5_con , met5_label)
connect(rdl , rdl_label)
connect(pad , pad_label)
logger.info("Starting SKY130 LVS connectivity setup (Global connections)")
# Global
connect_global(sub , substrate_name)
logger.info("Starting SKY130 LVS connectivity setup (Multifinger Devices)")
# Multifinger Devices
connect_implicit("*")
#================================
# ------ BJT CONNECTIONS --------
#================================
logger.info("Starting LVS BJT CONNECTIONS")
# ==============
# ---- npn ----
# ==============
# npn_5v0_1x1 nodes connections
connect(npn_5v0_1x1_e,licon)
connect(npn_5v0_1x1_b,licon)
connect(npn_5v0_1x1_c,licon)
# npn_5v0_1x2 nodes connections
connect(npn_5v0_1x2_e,licon)
connect(npn_5v0_1x2_b,licon)
connect(npn_5v0_1x2_c,licon)
# npn_11v0_1x1 nodes connections
connect(npn_11v0_1x1_e,licon)
connect(npn_11v0_1x1_b,licon)
connect(npn_11v0_1x1_c,licon)
# ==============
# ---- pnp ----
# ==============
# pnp_5v0_0p68x0p68 connections
connect(pnp_5v0_0p68x0p68_e,licon)
connect(pnp_5v0_0p68x0p68_b,licon)
connect(pnp_5v0_0p68x0p68_c,licon)
# pnp_5v0_3p4x3p4 nodes
connect(pnp_5v0_3p4x3p4_e,licon)
connect(pnp_5v0_3p4x3p4_b,licon)
connect(pnp_5v0_3p4x3p4_c,licon)
#================================
# ----- DIODE CONNECTIONS -------
#================================
logger.info("Starting LVS DIODE CONNECTIONS")
# N+ diffusion diode
connect(ndiode_terminal_n, licon)
connect(ndiode_terminal_p, ptap_conn)
# P+ diffusion diode
connect(pdiode_terminal_n, licon)
connect(pdiode_terminal_p, nwell)
#================================
# --- PHOTODIODE CONNECTIONS ----
#================================
logger.info("Starting LVS PHOTODIODE CONNECTIONS")
# Photodiode
connect(photodiode_n, licon)
connect(photodiode_p, ptap_conn)
#==================================
# ------ MIMCAP CONNECTIONS -------
#==================================
logger.info("Starting LVS MIMCAP CONNECTIONS")
# mim on metal3
connect(capm , via3 )
connect(met3_ncap , met3_con)
# mim on metal4
connect(capm2 , via4 )
connect(met4_ncap , met4_con)
#================================
# ---- VARACTOR CONNECTIONS -----
#================================
logger.info("Starting LVS VARACTOR CONNECTIONS")
# Low threshold voltage varactor
connect(varactor_bulk_lvt, ptap_conn)
# High threshold voltage varactor
connect(varactor_bulk_hvt, ptap_conn)
#================================
# ---- RESISTOR CONNECTIONS -----
#================================
logger.info("Starting LVS RESISTOR CONNECTIONS")
# Diffusions and Wells
connect(nplus_cont , licon)
connect(nplus_hv_cont , licon)
connect(pplus_cont , licon)
connect(pplus_hv_cont , licon)
connect(pwell_term , licon)
#================================
# ---- INDUCTOR CONNECTIONS -----
#================================
logger.info("Starting LVS INDUCTOR CONNECTIONS")
connect(met3_ind , met3_ncap)
connect(met3_ind , met3_label)
#================================
# ------- VPP CONNECTIONS -------
#================================
logger.info("Starting LVS VPP CAP CONNECTIONS")
# General VPP capacitor connections
connect(vpp_sub , pwell_label)
connect(met1_vpp , met1_con)
connect(met1_vpp , met1_label)
connect(met2_vpp , met2_con)
connect(met2_vpp , met2_label)
connect(met3_vpp , met3_ncap)
connect(met3_vpp , met3_label)
connect(met4_vpp , met4_ncap)
connect(met4_vpp , met4_label)
connect(met5_vpp , met5_con)
connect(met5_vpp , met5_label)
connect(poly_vpp , licon_vpp)
connect(licon_vpp , li_vpp)
connect(li_vpp , mcon_vpp)
connect(mcon_vpp , met1_vpp)
connect(met1_vpp , via1_vpp)
connect(via1_vpp , met2_vpp)
connect(met2_vpp , via2_vpp)
connect(via2_vpp , met3_vpp)
connect(met3_vpp , via3_vpp)
connect(via3_vpp , met4_vpp)
connect(met4_vpp , via4_vpp)
connect(via4_vpp , met5_vpp)
#================================
# ---- SONOS CONNECTIONS -----
#================================
logger.info("Starting LVS SONOS CONNECTIONS")
connect(sonos_nsd , licon)
#================================================
#------------- DEVICES EXTRACTION ---------------
#================================================
logger.info("Starting MOSFET EXTRACTION")
# ==============
# ---- PMOS ----
# ==============
logger.info("Starting PMOS EXTRACTION")
# 1.8V PMOS transistor standard
logger.info("Extracting 1.8V PMOS transistor standard")
extract_devices(mos4("sky130_fd_pr__pfet_01v8"), { "SD" => psd, "G" => pgate_1p8v, "tS" => psd, "tD" => psd, "tG" => poly_con, "W" => nwell })
# 1.8V PMOS transistor low threshold voltage
logger.info("Extracting 1.8V PMOS transistor low threshold voltage")
extract_devices(mos4("sky130_fd_pr__pfet_01v8_lvt"), { "SD" => psd, "G" => pgate_1p8v_lvt, "tS" => psd, "tD" => psd, "tG" => poly_con, "W" => nwell })
# 1.8V PMOS transistor high threshold voltage
logger.info("Extracting 1.8V PMOS transistor high threshold voltage")
extract_devices(mos4("sky130_fd_pr__pfet_01v8_hvt"), { "SD" => psd, "G" => pgate_1p8v_hvt, "tS" => psd, "tD" => psd, "tG" => poly_con, "W" => nwell })
# 5V gate 10.5V drain PMOS transistor
logger.info("Extracting 5V gate 10.5V drain PMOS transistor")
extract_devices(mos4("sky130_fd_pr__pfet_g5v0d10v5"), { "SD" => psd, "G" => pgate_5p0v_hv, "tS" => psd, "tD" => psd, "tG" => poly_con, "W" => nwell })
# ==============
# ---- NMOS ----
# ==============
logger.info("Starting NMOS EXTRACTION")
# 1.8V NMOS transistor standard
logger.info("Extracting 1.8V NMOS transistor standard")
extract_devices(mos4("sky130_fd_pr__nfet_01v8"), { "SD" => nsd, "G" => ngate_1p8v, "tS" => nsd, "tD" => nsd, "tG" => poly_con, "W" => sub })
# 1.8V NMOS transistor low threshold voltage
logger.info("Extracting 1.8V NMOS transistor low threshold voltage")
extract_devices(mos4("sky130_fd_pr__nfet_01v8_lvt"), { "SD" => nsd, "G" => ngate_1p8v_lvt, "tS" => nsd, "tD" => nsd, "tG" => poly_con, "W" => sub })
# 3.3V NMOS transistor native voltage
logger.info("Extracting 3.3V NMOS transistor native voltage")
extract_devices(mos4("sky130_fd_pr__nfet_03v3_nvt"), { "SD" => nsd, "G" => ngate_3p0v_nvt, "tS" => nsd, "tD" => nsd, "tG" => poly_con, "W" => sub })
# 5V NMOS transistor native voltage
logger.info("Extracting 5V NMOS transistor native voltage")
extract_devices(mos4("sky130_fd_pr__nfet_05v0_nvt"), { "SD" => nsd, "G" => ngate_5p0v_nvt, "tS" => nsd, "tD" => nsd, "tG" => poly_con, "W" => sub })
# 5V gate 10.5V drain NMOS transistor
logger.info("Extracting 5V gate 10.5V drain NMOS transistor")
extract_devices(mos4("sky130_fd_pr__nfet_g5v0d10v5"), { "SD" => nsd, "G" => ngate_5p0v_hv, "tS" => nsd, "tD" => nsd, "tG" => poly_con, "W" => sub })
#================================
# ------- BJT EXTRACTION --------
#================================
logger.info("Starting BJT EXTRACTION")
# ====================
# ------ NPN --------
# ====================
logger.info("Starting NPN BJT EXTRACTION")
# sky130_fd_pr__npn_05v5_W1p00L1p00 BJT
logger.info("Extracting sky130_fd_pr__npn_05v5_W1p00L1p00 BJT")
cls = extract_devices(bjt4("sky130_fd_pr__npn_05v5_W1p00L1p00"), { "C" => npn_5v0_1x1_c.extents , "B" => npn_5v0_1x1_b.extents , "E" => npn_5v0_1x1_e,"S" => sub.extents,
"tC" => npn_5v0_1x1_c , "tB" => npn_5v0_1x1_b, "tE" => npn_5v0_1x1_e, "tS" => sub })
ignore_parameter("sky130_fd_pr__npn_05v5_W1p00L1p00","AE")
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# sky130_fd_pr__npn_05v5_W1p00L2p00 BJT
logger.info("Extracting sky130_fd_pr__npn_05v5_W1p00L2p00 BJT")
cls = extract_devices(bjt4("sky130_fd_pr__npn_05v5_W1p00L2p00"), { "C" => npn_5v0_1x2_c.extents , "B" => npn_5v0_1x2_b.extents , "E" => npn_5v0_1x2_e,"S" => sub.extents,
"tC" => npn_5v0_1x2_c , "tB" => npn_5v0_1x2_b, "tE" => npn_5v0_1x2_e, "tS" => sub })
ignore_parameter("sky130_fd_pr__npn_05v5_W1p00L2p00","AE")
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# sky130_fd_pr__npn_11v0_W1p00L1p00 BJT
logger.info("Extracting sky130_fd_pr__npn_11v0_W1p00L1p00 BJT")
cls = extract_devices(FixBJT4Transistor::new("sky130_fd_pr__npn_11v0_W1p00L1p00"), { "BJT" => npn_11v0_1x1_c.extents, "tC" => npn_11v0_1x1_c , "tB" => npn_11v0_1x1_b,
"tE" => npn_11v0_1x1_e, "tS" => sub })
ignore_parameter("sky130_fd_pr__npn_11v0_W1p00L1p00","AE")
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# ====================
# ------- PNP --------
# ====================
logger.info("Starting PNP BJT EXTRACTION")
# sky130_fd_pr__pnp_05v5_W0p68L0p68 BJT
logger.info("Extracting sky130_fd_pr__pnp_05v5_W0p68L0p68 BJT")
cls = extract_devices(bjt3("sky130_fd_pr__pnp_05v5_W0p68L0p68"), { "C" => pnp_5v0_0p68x0p68_c.extents , "B" => pnp_5v0_0p68x0p68_b.extents , "E" => pnp_5v0_0p68x0p68_e,
"tC" => pnp_5v0_0p68x0p68_c , "tB" => pnp_5v0_0p68x0p68_b, "tE" => pnp_5v0_0p68x0p68_e })
ignore_parameter("sky130_fd_pr__pnp_05v5_W0p68L0p68","AE")
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# sky130_fd_pr__pnp_05v5_W3p40L3p40 BJT
logger.info("Extracting sky130_fd_pr__pnp_05v5_W3p40L3p40 BJT")
cls = extract_devices(bjt3("sky130_fd_pr__pnp_05v5_W3p40L3p40"), { "C" => pnp_5v0_3p4x3p4_c.extents , "B" => pnp_5v0_3p4x3p4_b.extents , "E" => pnp_5v0_3p4x3p4_e,
"tC" => pnp_5v0_3p4x3p4_c , "tB" => pnp_5v0_3p4x3p4_b, "tE" => pnp_5v0_3p4x3p4_e })
ignore_parameter("sky130_fd_pr__pnp_05v5_W3p40L3p40","AE")
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
#================================
# ------ DIODE EXTRACTION -------
#================================
logger.info("Starting DIODE EXTRACTION")
# 5V N+ diffusion diode
logger.info("Extracting 5V N+ diffusion diode")
extract_devices(diode("sky130_fd_pr__diode_pw2nd_05v5", Diode), { "P" => ndiode_5v0_terminal_p, "N" => ndiode_5v0_terminal_n, "tA" => ndiode_terminal_p , "tC" => ndiode_terminal_n})
# 5V N+ diffusion diode low threshold voltage
logger.info("Extracting 5V N+ diffusion diode low threshold voltage")
extract_devices(diode("sky130_fd_pr__diode_pw2nd_05v5_lvt", Diode), { "N" => ndiode_5v0_lvt_terminal_n , "P" => ndiode_5v0_lvt_terminal_p, "tA" => ndiode_terminal_n , "tC" => ndiode_terminal_p})
# 5V N+ diffusion diode native threshold voltage
logger.info("Extracting 5V N+ diffusion diode native threshold voltage")
extract_devices(diode("sky130_fd_pr__diode_pw2nd_05v5_nvt", Diode), { "N" => ndiode_5v0_nvt_terminal_n , "P" => ndiode_5v0_nvt_terminal_p, "tA" => ndiode_terminal_n , "tC" => ndiode_terminal_p})
# 11V N+ diffusion diode
logger.info("Extracting 11V N+ diffusion diode")
extract_devices(diode("sky130_fd_pr__diode_pw2nd_11v0", Diode), { "N" => ndiode_11v0_terminal_n , "P" => ndiode_11v0_terminal_p, "tA" => ndiode_terminal_n , "tC" => ndiode_terminal_p})
# 5V P+ diffusion diode
logger.info("Extracting 5V P+ diffusion diode")
extract_devices(diode("sky130_fd_pr__diode_pd2nw_05v5", Diode), { "N" => pdiode_5v0_terminal_n , "P" => pdiode_5v0_terminal_p, "tA" => pdiode_terminal_n, "tC" => pdiode_terminal_p})
# 5V P+ diffusion diode low threshold voltage
logger.info("Extracting5V P+ diffusion diode low threshold voltage")
extract_devices(diode("sky130_fd_pr__diode_pd2nw_05v5_lvt", Diode), { "N" => pdiode_5v0_lvt_terminal_n , "P" => pdiode_5v0_lvt_terminal_p, "tA" => pdiode_terminal_n, "tC" => pdiode_terminal_p})
# 5V P+ diffusion diode high threshold voltage
logger.info("Extracting 5V P+ diffusion diode high threshold voltage")
extract_devices(diode("sky130_fd_pr__diode_pd2nw_05v5_hvt", Diode), { "N" => pdiode_5v0_hvt_terminal_n , "P" => pdiode_5v0_hvt_terminal_p, "tA" => pdiode_terminal_n, "tC" => pdiode_terminal_p})
# 11V P+ diffusion diode
logger.info("Extracting 11V P+ diffusion diode")
extract_devices(diode("sky130_fd_pr__diode_pd2nw_11v0", Diode), { "N" => pdiode_11v0_terminal_n , "P" => pdiode_11v0_terminal_p, "tA" => pdiode_terminal_n, "tC" => pdiode_terminal_p})
#================================
#---- PHOTODIODE EXTRACTIONS ----
#================================
logger.info("Starting PHOTODIODE EXTRACTION")
# Photodiode
logger.info("Extracting Photodiode")
cls = extract_devices(diode("sky130_fd_pr__photodiode"), { "P" => photodiode_p, "N" => photodiode_n})
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
ignore_parameter("sky130_fd_pr__photodiode","A")
ignore_parameter("sky130_fd_pr__photodiode","p")
#================================
# ---- RESISTOR EXTRACTIONS -----
#================================
logger.info("Starting RESISTOR EXTRACTION")
# ===============
# --DIFF & WELL--
# ===============
# sky130_fd_pr__res_generic_nd
logger.info("Extracting sky130_fd_pr__res_generic_nd device")
extract_devices(resistor_with_bulk("sky130_fd_pr__res_generic_nd", 120, BResistor), { "R" => nplus_res, "C" => nplus_cont, "W" => sub})
# sky130_fd_pr__res_generic_nd
logger.info("Extracting sky130_fd_pr__res_generic_nd device")
extract_devices(resistor_with_bulk("sky130_fd_pr__res_generic_nd_hv", 120, BResistor), { "R" => nplus_hv_res, "C" => nplus_hv_cont, "W" => sub})
# sky130_fd_pr__res_generic_pd
logger.info("Extracting sky130_fd_pr__res_generic_pd device")
extract_devices(resistor_with_bulk("sky130_fd_pr__res_generic_pd", 197, BResistor), { "R" => pplus_res, "C" => pplus_cont, "W" => nwell})
# sky130_fd_pr__res_generic_pd
logger.info("Extracting sky130_fd_pr__res_generic_pd device")
extract_devices(resistor_with_bulk("sky130_fd_pr__res_generic_pd_hv", 197, BResistor), { "R" => pplus_hv_res, "C" => pplus_hv_cont, "W" => nwell})
# sky130_fd_pr__res_iso_pw
logger.info("Extracting sky130_fd_pr__res_iso_pw device")
extract_devices(resistor_with_bulk("sky130_fd_pr__res_iso_pw", 3050, BResistor), { "R" => pwell_resistor, "C" => pwell_cont, "W" => dnwell, "tA" => pwell_term, "tB" => pwell_term, "tW" => dnwell})
# ==============
# ---- POLY ----
# ==============
# sky130_fd_pr__res_generic_po
logger.info("Extracting sky130_fd_pr__res_generic_po device")
extract_devices(resistor("sky130_fd_pr__res_generic_po", 48.2, NResistor), { "R" => poly_res_generic, "C" => poly_con })
# sky130_fd_pr__res_high_po_0p35
logger.info("Extracting sky130_fd_pr__res_high_po_0p35 device")
extract_devices(resistor_with_bulk("sky130_fd_pr__res_high_po_0p35", 319.8, BResistor), { "R" => poly_high_0p35, "C" => poly_con, "W" => sub})
# sky130_fd_pr__res_high_po_0p69
logger.info("Extracting sky130_fd_pr__res_high_po_0p69 device")
extract_devices(resistor_with_bulk("sky130_fd_pr__res_high_po_0p69", 319.8, BResistor), { "R" => poly_high_0p69, "C" => poly_con, "W" => sub})
# sky130_fd_pr__res_high_po_1p41
logger.info("Extracting sky130_fd_pr__res_high_po_1p41 device")
extract_devices(resistor_with_bulk("sky130_fd_pr__res_high_po_1p41", 319.8, BResistor), { "R" => poly_high_1p41, "C" => poly_con, "W" => sub})
# sky130_fd_pr__res_high_po_2p85
logger.info("Extracting sky130_fd_pr__res_high_po_2p85 device")
extract_devices(resistor_with_bulk("sky130_fd_pr__res_high_po_2p85", 319.8, BResistor), { "R" => poly_high_2p85, "C" => poly_con, "W" => sub})
# sky130_fd_pr__res_high_po_5p73
logger.info("Extracting sky130_fd_pr__res_high_po_5p73 device")
extract_devices(resistor_with_bulk("sky130_fd_pr__res_high_po_5p73", 319.8, BResistor), { "R" => poly_high_5p73, "C" => poly_con, "W" => sub})
# sky130_fd_pr__res_xhigh_po_0p35
logger.info("Extracting sky130_fd_pr__res_xhigh_po_0p35 device")
extract_devices(resistor_with_bulk("sky130_fd_pr__res_xhigh_po_0p35", 2000, BResistor), { "R" => poly_xhigh_0p35, "C" => poly_con, "W" => sub})
# sky130_fd_pr__res_xhigh_po_0p69
logger.info("Extracting sky130_fd_pr__res_xhigh_po_0p69 device")
extract_devices(resistor_with_bulk("sky130_fd_pr__res_xhigh_po_0p69", 2000, BResistor), { "R" => poly_xhigh_0p69, "C" => poly_con, "W" => sub})
# sky130_fd_pr__res_xhigh_po_1p41
logger.info("Extracting sky130_fd_pr__res_xhigh_po_1p41 device")
extract_devices(resistor_with_bulk("sky130_fd_pr__res_xhigh_po_1p41", 2000, BResistor), { "R" => poly_xhigh_1p41, "C" => poly_con, "W" => sub})
# sky130_fd_pr__res_xhigh_po_2p85
logger.info("Extracting sky130_fd_pr__res_xhigh_po_2p85 device")
extract_devices(resistor_with_bulk("sky130_fd_pr__res_xhigh_po_2p85", 2000, BResistor), { "R" => poly_xhigh_2p85, "C" => poly_con, "W" => sub})
# sky130_fd_pr__res_xhigh_po_5p73
logger.info("Extracting sky130_fd_pr__res_xhigh_po_5p73 device")
extract_devices(resistor_with_bulk("sky130_fd_pr__res_xhigh_po_5p73", 2000, BResistor), { "R" => poly_xhigh_5p73, "C" => poly_con, "W" => sub})
# ===============
# ---- METAL ----
# ===============
# sky130_fd_pr__res_generic_l1
logger.info("Extracting sky130_fd_pr__res_generic_l1 device")
extract_devices(resistor("sky130_fd_pr__res_generic_l1", 12.2, NResistor), { "R" => li_resistor, "C" => li_con })
# sky130_fd_pr__res_generic_m1
logger.info("Extracting sky130_fd_pr__res_generic_m1 device")
extract_devices(resistor("sky130_fd_pr__res_generic_m1", 120, NResistor), { "R" => met1_resistor, "C" => met1_con })
# sky130_fd_pr__res_generic_m2
logger.info("Extracting sky130_fd_pr__res_generic_m2 device")
extract_devices(resistor("sky130_fd_pr__res_generic_m2", 120, NResistor), { "R" => met2_resistor, "C" => met2_con })
# sky130_fd_pr__res_generic_m3
logger.info("Extracting sky130_fd_pr__res_generic_m3 device")
extract_devices(resistor("sky130_fd_pr__res_generic_m3", 47, NResistor), { "R" => met3_resistor, "C" => met3_con })
# sky130_fd_pr__res_generic_m4
logger.info("Extracting sky130_fd_pr__res_generic_m4 device")
extract_devices(resistor("sky130_fd_pr__res_generic_m4", 47, NResistor), { "R" => met4_resistor, "C" => met4_con })
# sky130_fd_pr__res_generic_m5
logger.info("Extracting sky130_fd_pr__res_generic_m5 device")
extract_devices(resistor("sky130_fd_pr__res_generic_m5", 29, NResistor), { "R" => met5_resistor, "C" => met5_con })
#==================================
# ------- FUSE EXTRACTION -------
#==================================
logger.info("Starting FUSE EXTRACTION")
if FUSE == "m2"
# sky130_fd_pr__fuse_m2
logger.info("Extracting sky130_fd_pr__fuse_m2 device")
extract_devices(resistor("sky130_fd_pr__fuse_m2", 120, NResistor), { "R" => met2_fuse_res_layer, "C" => met2_con })
elsif FUSE == "m3"
# sky130_fd_pr__fuse_m3
logger.info("Extracting sky130_fd_pr__fuse_m3 device")
extract_devices(resistor("sky130_fd_pr__fuse_m3", 47, NResistor), { "R" => met3_fuse_res_layer, "C" => met3_ncap })
else
# sky130_fd_pr__fuse_m4
logger.info("Extracting sky130_fd_pr__fuse_m4 device")
extract_devices(resistor("sky130_fd_pr__fuse_m4", 47, NResistor), { "R" => met4_fuse_res_layer, "C" => met4_ncap })
end
#==================================
# ------- MIMCAP EXTRACTION -------
#==================================
logger.info("Starting MIMCAP EXTRACTION")
# sky130_fd_pr__model__cap_mim capacitor
logger.info("Extracting sky130_fd_pr__model__cap_mim device")
extract_devices(capacitor("sky130_fd_pr__model__cap_mim", 2e-15, MIMCap), { "P1" => met3_con, "P2" => capm })
# sky130_fd_pr__model__cap_mim_m4 capacitor
logger.info("Extracting sky130_fd_pr__model__cap_mim_m4 device")
extract_devices(capacitor("sky130_fd_pr__model__cap_mim_m4", 2e-15, MIMCap), { "P1" => met4_con, "P2" => capm2 })
#==================================
# ------- VARACTOR EXTRACTION -----
#==================================
logger.info("Starting VARACTOR EXTRACTION")
# Low threshold voltage varactor
logger.info("Extracting low threshold voltage varactor")
extract_devices(capacitor_with_bulk("sky130_fd_pr__cap_var_lvt", 4.4e-15, VarCap), { "P1" => varactor_gate_lvt, "P2" => varactor_nsd_lvt, "W" => varactor_bulk_lvt, "tA" => poly_con, "tB" => ntap_conn})
# High threshold voltage varactor
logger.info("Extracting high threshold voltage varactor")
extract_devices(capacitor_with_bulk("sky130_fd_pr__cap_var_hvt", 4.4e-15, VarCap), { "P1" => varactor_gate_hvt, "P2" => varactor_nsd_hvt, "W" => varactor_bulk_hvt, "tA" => poly_con, "tB" => ntap_conn})
#==================================
# ------ INDUCTOR EXTRACTION ------
#==================================
logger.info("Starting INDUCTOR EXTRACTION")
# RF Inductor with 3 turns and internal diameter of 90um
logger.info("Extracting RF Inductor with 3 turns and internal diameter of 90um")
cls = extract_devices(InductorExtractor::new("sky130_fd_pr__rf_ind_03_90"), {"C1" => met3_ind, "C2" => met2_con, "M" => coil_1 })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# RF Inductor with 5 turns and internal diameter of 125um
logger.info("Extracting RF Inductor with 5 turns and internal diameter of 125um")
cls = extract_devices(InductorExtractor::new("sky130_fd_pr__rf_ind_05_125"), {"C1" => met3_ind, "C2" => met2_con, "M" => coil_2 })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# RF Inductor with 5 turns and internal diameter of 220um
logger.info("Extracting RF Inductor with 5 turns and internal diameter of 220um")
cls = extract_devices(InductorExtractor::new("sky130_fd_pr__rf_ind_05_220"), {"C1" => met3_ind, "C2" => met2_con, "M" => coil_3 })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
#==================================
# ---------- VPP EXTRACTION -------
#==================================
logger.info("Starting VARACTOR EXTRACTION")
# VPP capacitor with dimensions of 2.4um x 4.6um and with layers of m1m2 and noshield
logger.info("Extracting sky130_fd_pr__cap_vpp_02p4x04p6_m1m2_noshield")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_02p4x04p6_m1m2_noshield"), {"C" => met2_vpp, "M" => vpp_02p4x04p6_m1m2_noshield, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 2.7um x 6.1um and with layers of m1m2m3m4 and shieldl1
logger.info("Extracting sky130_fd_pr__cap_vpp_02p7x06p1_m1m2m3m4_shieldl1_fingercap")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_02p7x06p1_m1m2m3m4_shieldl1_fingercap"), {"C" => met2_vpp, "M" => vpp_02p7x06p1_m1m2m3m4_shieldl1_fingercap, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 2.7um x 11.1um and with layers of m1m2m3m4 and shieldl1
logger.info("Extracting sky130_fd_pr__cap_vpp_02p7x11p1_m1m2m3m4_shieldl1_fingercap")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_02p7x11p1_m1m2m3m4_shieldl1_fingercap"), {"C" => met2_vpp, "M" => vpp_02p7x11p1_m1m2m3m4_shieldl1_fingercap, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 2.7um x 21.1um and with layers of m1m2m3m4 and shieldl1
logger.info("Extracting sky130_fd_pr__cap_vpp_02p7x21p1_m1m2m3m4_shieldl1_fingercap")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_02p7x21p1_m1m2m3m4_shieldl1_fingercap"), {"C" => met2_vpp, "M" => vpp_02p7x21p1_m1m2m3m4_shieldl1_fingercap, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 2.7um x 41.1um and with layers of m1m2m3m4 and shieldl1
logger.info("Extracting sky130_fd_pr__cap_vpp_02p7x41p1_m1m2m3m4_shieldl1_fingercap")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_02p7x41p1_m1m2m3m4_shieldl1_fingercap"), {"C" => met2_vpp, "M" => vpp_02p7x41p1_m1m2m3m4_shieldl1_fingercap, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 2.9um x 6.1um and with layers of m1m2m3m4 and shieldl1
logger.info("Extracting sky130_fd_pr__cap_vpp_02p9x06p1_m1m2m3m4_shieldl1_fingercap2")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_02p9x06p1_m1m2m3m4_shieldl1_fingercap2"), {"C" => met2_vpp, "M" => vpp_02p9x06p1_m1m2m3m4_shieldl1_fingercap2, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 3.9um x 3.9um and with layers of m1m2 and shieldl1 with floatm3
logger.info("Extracting sky130_fd_pr__cap_vpp_03p9x03p9_m1m2_shieldl1_floatm3")
cls = extract_devices(VPP4Extractor::new("sky130_fd_pr__cap_vpp_03p9x03p9_m1m2_shieldl1_floatm3"), {"C1" => met2_vpp, "C2" => met3_vpp, "M" => vpp_03p9x03p9_m1m2_shieldl1_floatm3, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 4.4um x 4.6um and with layers of l1m1m2 and noshield
logger.info("Extracting sky130_fd_pr__cap_vpp_04p4x04p6_l1m1m2_noshield")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_04p4x04p6_l1m1m2_noshield"), {"C" => met2_vpp, "M" => vpp_04p4x04p6_l1m1m2_noshield, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 4.4um x 4.6um and with layers of l1m1m2 and noshield
logger.info("Extracting sky130_fd_pr__cap_vpp_04p4x04p6_l1m1m2_noshield_o2subcell")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_04p4x04p6_l1m1m2_noshield_o2subcell"), {"C" => met2_vpp, "M" => vpp_04p4x04p6_l1m1m2_noshield_o2subcell, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 4.4um x 4.6um and with layers of l1m1m2 and shieldpo with floatm3
logger.info("Extracting sky130_fd_pr__cap_vpp_04p4x04p6_l1m1m2_shieldpo_floatm3")
cls = extract_devices(VPP4Extractor::new("sky130_fd_pr__cap_vpp_04p4x04p6_l1m1m2_shieldpo_floatm3"), {"C1" => met2_vpp, "C2" => met3_vpp, "M" => vpp_04p4x04p6_l1m1m2_shieldpo_floatm3, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 4.4um x 4.6um and with layers of m1m2m3 and shieldl1
logger.info("Extracting sky130_fd_pr__cap_vpp_04p4x04p6_m1m2m3_shieldl1")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_04p4x04p6_m1m2m3_shieldl1"), {"C" => met2_vpp, "M" => vpp_04p4x04p6_m1m2m3_shieldl1, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 4.4um x 4.6um and with layers of m1m2m3 and shieldl1m5 with floatm4
logger.info("Extracting sky130_fd_pr__cap_vpp_04p4x04p6_m1m2m3_shieldl1m5_floatm4")
cls = extract_devices(VPP4Extractor::new("sky130_fd_pr__cap_vpp_04p4x04p6_m1m2m3_shieldl1m5_floatm4"), {"C1" => met2_vpp, "C2" => met5_vpp, "M" => vpp_04p4x04p6_m1m2m3_shieldl1m5_floatm4, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 4.4um x 4.6um and with layers of m1m2 and noshield
logger.info("Extracting sky130_fd_pr__cap_vpp_04p4x04p6_m1m2_noshield")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_04p4x04p6_m1m2_noshield"), {"C" => met2_vpp, "M" => vpp_04p4x04p6_m1m2_noshield, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 4.4um x 4.6um and with layers of m1m2 and noshield
logger.info("Extracting sky130_fd_pr__cap_vpp_04p4x04p6_m1m2_noshield_o2")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_04p4x04p6_m1m2_noshield_o2"), {"C" => met2_vpp, "M" => vpp_04p4x04p6_m1m2_noshield_o2, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 4.4um x 4.6um and with layers of m1m2 and shieldl1
logger.info("Extracting sky130_fd_pr__cap_vpp_04p4x04p6_m1m2_shieldl1")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_04p4x04p6_m1m2_shieldl1"), {"C" => met2_vpp, "M" => vpp_04p4x04p6_m1m2_shieldl1, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 5.9um x 5.9um and with layers of m1m2m3m4 and shieldl1
logger.info("Extracting sky130_fd_pr__cap_vpp_05p9x05p9_m1m2m3m4_shieldl1_wafflecap")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_05p9x05p9_m1m2m3m4_shieldl1_wafflecap"), {"C" => met2_vpp, "M" => vpp_05p9x05p9_m1m2m3m4_shieldl1_wafflecap, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 6.8um x 6.1um and with layers of l1m1m2m3 and shieldpom4
logger.info("Extracting sky130_fd_pr__cap_vpp_06p8x06p1_l1m1m2m3_shieldpom4")
cls = extract_devices(VPP4Extractor::new("sky130_fd_pr__cap_vpp_06p8x06p1_l1m1m2m3_shieldpom4"), {"C1" => met2_vpp, "C2" => met4_vpp, "M" => vpp_06p8x06p1_l1m1m2m3_shieldpom4, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 6.8um x 6.1um and with layers of m1m2m3 and shieldl1m4
logger.info("Extracting sky130_fd_pr__cap_vpp_06p8x06p1_m1m2m3_shieldl1m4")
cls = extract_devices(VPP4Extractor::new("sky130_fd_pr__cap_vpp_06p8x06p1_m1m2m3_shieldl1m4"), {"C1" => met2_vpp, "C2" => met4_vpp, "M" => vpp_06p8x06p1_m1m2m3_shieldl1m4, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 8.6um x 7.8um and with layers of l1m1m2 and noshield
logger.info("Extracting sky130_fd_pr__cap_vpp_08p6x07p8_l1m1m2_noshield")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_08p6x07p8_l1m1m2_noshield"), {"C" => met2_vpp, "M" => vpp_08p6x07p8_l1m1m2_noshield, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 8.6um x 7.8um and with layers of l1m1m2 and noshield
logger.info("Extracting sky130_fd_pr__cap_vpp_08p6x07p8_l1m1m2_noshield_o2subcell")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_08p6x07p8_l1m1m2_noshield_o2subcell"), {"C" => met2_vpp, "M" => vpp_08p6x07p8_l1m1m2_noshield_o2subcell, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 8.6um x 7.8um and with layers of l1m1m2 and shieldpo with floatm3
logger.info("Extracting sky130_fd_pr__cap_vpp_08p6x07p8_l1m1m2_shieldpo_floatm3")
cls = extract_devices(VPP4Extractor::new("sky130_fd_pr__cap_vpp_08p6x07p8_l1m1m2_shieldpo_floatm3"), {"C1" => met2_vpp, "C2" => met3_vpp, "M" => vpp_08p6x07p8_l1m1m2_shieldpo_floatm3, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 8.6um x 7.8um and with layers of m1m2m3 and shieldl1
logger.info("Extracting sky130_fd_pr__cap_vpp_08p6x07p8_m1m2m3_shieldl1")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_08p6x07p8_m1m2m3_shieldl1"), {"C" => met2_vpp, "M" => vpp_08p6x07p8_m1m2m3_shieldl1, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 8.6um x 7.8um and with layers of m1m2m3 and shieldl1m5 with floatm4
logger.info("Extracting sky130_fd_pr__cap_vpp_08p6x07p8_m1m2m3_shieldl1m5_floatm4")
cls = extract_devices(VPP4Extractor::new("sky130_fd_pr__cap_vpp_08p6x07p8_m1m2m3_shieldl1m5_floatm4"), {"C1" => met2_vpp, "C2" => met5_vpp, "M" => vpp_08p6x07p8_m1m2m3_shieldl1m5_floatm4, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 8.6um x 7.8um and with layers of m1m2 and noshield
logger.info("Extracting sky130_fd_pr__cap_vpp_08p6x07p8_m1m2_noshield")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_08p6x07p8_m1m2_noshield"), {"C" => met2_vpp, "M" => vpp_08p6x07p8_m1m2_noshield, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 8.6um x 7.8um and with layers of m1m2 and shieldl1
logger.info("Extracting sky130_fd_pr__cap_vpp_08p6x07p8_m1m2_shieldl1")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_08p6x07p8_m1m2_shieldl1"), {"C" => met2_vpp, "M" => vpp_08p6x07p8_m1m2_shieldl1, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 11.3um x 11.3um and with layers of m1m2m3m4 and shieldl1
logger.info("Extracting sky130_fd_pr__cap_vpp_11p3x11p3_m1m2m3m4_shieldl1_wafflecap")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_11p3x11p3_m1m2m3m4_shieldl1_wafflecap"), {"C" => met2_vpp, "M" => vpp_11p3x11p3_m1m2m3m4_shieldl1_wafflecap, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 11.3um x 11.8um and with layers of l1m1m2m3m4 and shieldm5
logger.info("Extracting vpp cap sky130_fd_pr__cap_vpp_11p3x11p8_l1m1m2m3m4_shieldm5_nhv")
cls = extract_devices(VPP3NHVExtractor::new("sky130_fd_pr__cap_vpp_11p3x11p8_l1m1m2m3m4_shieldm5_nhv"),
{ "MARKER" => vpp_11p3x11p8_l1m1m2m3m4_shieldm5_nhv, "tA" => met2_vpp, "tB" => met1_vpp, "tW" => met5_vpp })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 11.5um x 11.7um and with layers of l1m1m2m3m4 and shieldm5
logger.info("Extracting sky130_fd_pr__cap_vpp_11p5x11p7_l1m1m2m3m4_shieldm5")
cls = extract_devices(VPP4Extractor::new("sky130_fd_pr__cap_vpp_11p5x11p7_l1m1m2m3m4_shieldm5"), {"C1" => met2_vpp, "C2" => met5_vpp, "M" => vpp_11p5x11p7_l1m1m2m3m4_shieldm5, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 11.5um x 11.7um and with layers of l1m1m2m3m4 and shieldpom5
logger.info("Extracting sky130_fd_pr__cap_vpp_11p5x11p7_l1m1m2m3m4_shieldpom5")
cls = extract_devices(VPP4Extractor::new("sky130_fd_pr__cap_vpp_11p5x11p7_l1m1m2m3m4_shieldpom5"), {"C1" => met2_vpp, "C2" => met5_vpp, "M" => vpp_11p5x11p7_l1m1m2m3m4_shieldpom5, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# # VPP capacitor with dimensions of 11.5um x 11.7um and with layers of l1m1m2m3m4 and shieldpom5
# logger.info("Extracting sky130_fd_pr__cap_vpp_11p5x11p7_l1m1m2m3m4_shieldpom5_x6")
# cls = extract_devices(VPP4Extractor::new("sky130_fd_pr__cap_vpp_11p5x11p7_l1m1m2m3m4_shieldpom5_x6"), {"C1" => met2_vpp, "C2" => met5_vpp, "M" => vpp_11p5x11p7_l1m1m2m3m4_shieldpom5_x6, "B" => vpp_sub })
# cls.supports_serial_combination = false
# cls.supports_parallel_combination = false
# # VPP capacitor with dimensions of 11.5um x 11.7um and with layers of l1m1m2m3m4 and shieldpom5
# logger.info("Extracting sky130_fd_pr__cap_vpp_11p5x11p7_l1m1m2m3m4_shieldpom5_x7")
# cls = extract_devices(VPP4Extractor::new("sky130_fd_pr__cap_vpp_11p5x11p7_l1m1m2m3m4_shieldpom5_x7"), {"C1" => met2_vpp, "C2" => met5_vpp, "M" => vpp_11p5x11p7_l1m1m2m3m4_shieldpom5_x7, "B" => vpp_sub })
# cls.supports_serial_combination = false
# cls.supports_parallel_combination = false
# # VPP capacitor with dimensions of 11.5um x 11.7um and with layers of l1m1m2m3m4 and shieldpom5
# logger.info("Extracting sky130_fd_pr__cap_vpp_11p5x11p7_l1m1m2m3m4_shieldpom5_x8")
# cls = extract_devices(VPP4Extractor::new("sky130_fd_pr__cap_vpp_11p5x11p7_l1m1m2m3m4_shieldpom5_x8"), {"C1" => met2_vpp, "C2" => met5_vpp, "M" => vpp_11p5x11p7_l1m1m2m3m4_shieldpom5_x8, "B" => vpp_sub })
# cls.supports_serial_combination = false
# cls.supports_parallel_combination = false
# # VPP capacitor with dimensions of 11.5um x 11.7um and with layers of l1m1m2m3m4 and shieldpom5
# logger.info("Extracting sky130_fd_pr__cap_vpp_11p5x11p7_l1m1m2m3m4_shieldpom5_x9")
# cls = extract_devices(VPP4Extractor::new("sky130_fd_pr__cap_vpp_11p5x11p7_l1m1m2m3m4_shieldpom5_x9"), {"C1" => met2_vpp, "C2" => met5_vpp, "M" => vpp_11p5x11p7_l1m1m2m3m4_shieldpom5_x9, "B" => vpp_sub })
# cls.supports_serial_combination = false
# cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 11.5um x 11.7um and with layers of l1m1m2m3m4 and shieldpom5
logger.info("Extracting sky130_fd_pr__cap_vpp_11p5x11p7_l1m1m2m3m4_shieldpom5_x")
cls = extract_devices(VPP4Extractor::new("sky130_fd_pr__cap_vpp_11p5x11p7_l1m1m2m3m4_shieldpom5_x"), {"C1" => met2_vpp, "C2" => met5_vpp, "M" => vpp_11p5x11p7_l1m1m2m3m4_shieldpom5_x, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 11.5um x 11.7um and with layers of l1m1m2m3 and shieldm4
logger.info("Extracting sky130_fd_pr__cap_vpp_11p5x11p7_l1m1m2m3_shieldm4")
cls = extract_devices(VPP4Extractor::new("sky130_fd_pr__cap_vpp_11p5x11p7_l1m1m2m3_shieldm4"), {"C1" => met2_vpp, "C2" => met4_vpp, "M" => vpp_11p5x11p7_l1m1m2m3_shieldm4, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 11.5um x 11.7um and with layers of l1m1m2m3 and shieldpom4
logger.info("Extracting sky130_fd_pr__cap_vpp_11p5x11p7_l1m1m2m3_shieldpom4")
cls = extract_devices(VPP4Extractor::new("sky130_fd_pr__cap_vpp_11p5x11p7_l1m1m2m3_shieldpom4"), {"C1" => met2_vpp, "C2" => met4_vpp, "M" => vpp_11p5x11p7_l1m1m2m3_shieldpom4, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 11.5um x 11.7um and with layers of l1m1m2 and noshield
logger.info("Extracting sky130_fd_pr__cap_vpp_11p5x11p7_l1m1m2_noshield")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_11p5x11p7_l1m1m2_noshield"), {"C" => met2_vpp, "M" => vpp_11p5x11p7_l1m1m2_noshield, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 11.5um x 11.7um and with layers of l1m1m2 and shieldpom3
logger.info("Extracting sky130_fd_pr__cap_vpp_11p5x11p7_l1m1m2_shieldpom3")
cls = extract_devices(VPP4Extractor::new("sky130_fd_pr__cap_vpp_11p5x11p7_l1m1m2_shieldpom3"), {"C1" => met2_vpp, "C2" => met3_vpp, "M" => vpp_11p5x11p7_l1m1m2_shieldpom3, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 11.5um x 11.7um and with layers of m1m2m3m4 and shieldl1m5
logger.info("Extracting sky130_fd_pr__cap_vpp_11p5x11p7_m1m2m3m4_shieldl1m5")
cls = extract_devices(VPP4Extractor::new("sky130_fd_pr__cap_vpp_11p5x11p7_m1m2m3m4_shieldl1m5"), {"C1" => met2_vpp, "C2" => met5_vpp, "M" => vpp_11p5x11p7_m1m2m3m4_shieldl1m5, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 11.5um x 11.7um and with layers of m1m2m3m4 and shieldm5
logger.info("Extracting sky130_fd_pr__cap_vpp_11p5x11p7_m1m2m3m4_shieldm5")
cls = extract_devices(VPP4Extractor::new("sky130_fd_pr__cap_vpp_11p5x11p7_m1m2m3m4_shieldm5"), {"C1" => met2_vpp, "C2" => met5_vpp, "M" => vpp_11p5x11p7_m1m2m3m4_shieldm5, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 11.5um x 11.7um and with layers of m1m2m3 and shieldl1
logger.info("Extracting sky130_fd_pr__cap_vpp_11p5x11p7_m1m2m3_shieldl1")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_11p5x11p7_m1m2m3_shieldl1"), {"C" => met2_vpp, "M" => vpp_11p5x11p7_m1m2m3_shieldl1, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 11.5um x 11.7um and with layers of m1m2m3 and shieldl1m5 with floatm4
logger.info("Extracting sky130_fd_pr__cap_vpp_11p5x11p7_m1m2m3_shieldl1m5_floatm4")
cls = extract_devices(VPP4Extractor::new("sky130_fd_pr__cap_vpp_11p5x11p7_m1m2m3_shieldl1m5_floatm4"), {"C1" => met2_vpp, "C2" => met5_vpp, "M" => vpp_11p5x11p7_m1m2m3_shieldl1m5_floatm4, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 11.5um x 11.7um and with layers of m1m2 and noshield
logger.info("Extracting sky130_fd_pr__cap_vpp_11p5x11p7_m1m2_noshield")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_11p5x11p7_m1m2_noshield"), {"C" => met2_vpp, "M" => vpp_11p5x11p7_m1m2_noshield, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 11.5um x 11.7um and with layers of m1m2 and shieldl1
logger.info("Extracting sky130_fd_pr__cap_vpp_11p5x11p7_m1m2_shieldl1")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_11p5x11p7_m1m2_shieldl1"), {"C" => met2_vpp, "M" => vpp_11p5x11p7_m1m2_shieldl1, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 11.5um x 11.7um and with layers of m1m4 and noshield
logger.info("Extracting sky130_fd_pr__cap_vpp_11p5x11p7_m1m4_noshield")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_11p5x11p7_m1m4_noshield"), {"C" => met2_vpp, "M" => vpp_11p5x11p7_m1m4_noshield, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 11.5um x 11.7um and with layers of pol1m1m2m3m4m5 and noshield
logger.info("Extracting sky130_fd_pr__cap_vpp_11p5x11p7_pol1m1m2m3m4m5_noshield")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_11p5x11p7_pol1m1m2m3m4m5_noshield"), {"C" => met2_vpp, "M" => vpp_11p5x11p7_pol1m1m2m3m4m5_noshield, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 11.5um x 23.1um and with layers of pol1m1m2m3m4m5 and noshield
logger.info("Extracting sky130_fd_pr__cap_vpp_11p5x23p1_pol1m1m2m3m4m5_noshield")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_11p5x23p1_pol1m1m2m3m4m5_noshield"), {"C" => met2_vpp, "M" => vpp_11p5x23p1_pol1m1m2m3m4m5_noshield, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 22.5um x 11.7um and with layers of pol1m1m2m3m4m5 and noshield
logger.info("Extracting sky130_fd_pr__cap_vpp_22p5x11p7_pol1m1m2m3m4m5_noshield")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_22p5x11p7_pol1m1m2m3m4m5_noshield"), {"C" => met2_vpp, "M" => vpp_22p5x11p7_pol1m1m2m3m4m5_noshield, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 22.5um x 23.1um and with layers of pol1m1m2m3m4m5 and noshield
logger.info("Extracting sky130_fd_pr__cap_vpp_22p5x23p1_pol1m1m2m3m4m5_noshield")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_22p5x23p1_pol1m1m2m3m4m5_noshield"), {"C" => met2_vpp, "M" => vpp_22p5x23p1_pol1m1m2m3m4m5_noshield, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 33.6um x 11.7um and with layers of pol1m1m2m3m4m5 and noshield
logger.info("Extracting sky130_fd_pr__cap_vpp_33p6x11p7_pol1m1m2m3m4m5_noshield")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_33p6x11p7_pol1m1m2m3m4m5_noshield"), {"C" => met2_vpp, "M" => vpp_33p6x11p7_pol1m1m2m3m4m5_noshield, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 33.6um x 23.1um and with layers of pol1m1m2m3m4m5 and noshield
logger.info("Extracting sky130_fd_pr__cap_vpp_33p6x23p1_pol1m1m2m3m4m5_noshield")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_33p6x23p1_pol1m1m2m3m4m5_noshield"), {"C" => met2_vpp, "M" => vpp_33p6x23p1_pol1m1m2m3m4m5_noshield, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 44.7um x 11.7um and with layers of pol1m1m2m3m4m5 and noshield
logger.info("Extracting sky130_fd_pr__cap_vpp_44p7x11p7_pol1m1m2m3m4m5_noshield")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_44p7x11p7_pol1m1m2m3m4m5_noshield"), {"C" => met2_vpp, "M" => vpp_44p7x11p7_pol1m1m2m3m4m5_noshield, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 44.7um x 23.1um and with layers of pol1m1m2m3m4m5 and noshield
logger.info("Extracting sky130_fd_pr__cap_vpp_44p7x23p1_pol1m1m2m3m4m5_noshield")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_44p7x23p1_pol1m1m2m3m4m5_noshield"), {"C" => met2_vpp, "M" => vpp_44p7x23p1_pol1m1m2m3m4m5_noshield, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 55.8um x 11.7um and with layers of pol1m1m2m3m4m5 and noshield
logger.info("Extracting sky130_fd_pr__cap_vpp_55p8x11p7_pol1m1m2m3m4m5_noshield")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_55p8x11p7_pol1m1m2m3m4m5_noshield"), {"C" => met2_vpp, "M" => vpp_55p8x11p7_pol1m1m2m3m4m5_noshield, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 55.8um x 11.7um and with layers of pol1m1m2m3m4m5 and noshield
logger.info("Extracting sky130_fd_pr__cap_vpp_55p8x11p7_pol1m1m2m3m4m5_noshield_m5pullin")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_55p8x11p7_pol1m1m2m3m4m5_noshield_m5pullin"), {"C" => met2_vpp, "M" => vpp_55p8x11p7_pol1m1m2m3m4m5_noshield_m5pullin, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 55.8um x 23.1um and with layers of pol1m1m2m3m4m5 and noshield
logger.info("Extracting sky130_fd_pr__cap_vpp_55p8x23p1_pol1m1m2m3m4m5_noshield")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_55p8x23p1_pol1m1m2m3m4m5_noshield"), {"C" => met2_vpp, "M" => vpp_55p8x23p1_pol1m1m2m3m4m5_noshield, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 55.8um x 23.1um and with layers of pol1m1m2m3m4m5 and noshield
logger.info("Extracting sky130_fd_pr__cap_vpp_55p8x23p1_pol1m1m2m3m4m5_noshield_m5pullin")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_55p8x23p1_pol1m1m2m3m4m5_noshield_m5pullin"), {"C" => met2_vpp, "M" => vpp_55p8x23p1_pol1m1m2m3m4m5_noshield_m5pullin, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
# VPP capacitor with dimensions of 55.8um x 23.1um and with layers of pol1m1m2m3m4m5 and noshield
logger.info("Extracting sky130_fd_pr__cap_vpp_55p8x23p1_pol1m1m2m3m4m5_noshield_test")
cls = extract_devices(VPP3Extractor::new("sky130_fd_pr__cap_vpp_55p8x23p1_pol1m1m2m3m4m5_noshield_test"), {"C" => met2_vpp, "M" => vpp_55p8x23p1_pol1m1m2m3m4m5_noshield_test, "B" => vpp_sub })
cls.supports_serial_combination = false
cls.supports_parallel_combination = false
#==================================
# ------- SONOS EXTRACTION --------
#==================================
logger.info("Starting SONOS EXTRACTION")
# Build space flash special SONOSFET star
logger.info("Extracting Build space flash special SONOSFET star")
extract_devices(mos4("sky130_fd_bs_flash__special_sonosfet_star"), { "SD" => sonos_nsd, "G" => sonos_gate, "tS" => sonos_nsd, "tD" => sonos_nsd, "tG" => poly_con, "W" => sub })
#================================================
#------------- COMPARISON OPTIONS ---------------
#================================================
logger.info("Starting SKY130 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(1e9)
min_caps(1e-16)
#=== COMPARE ===
compare
#=== TIME ESTIMATE ===
exec_end_time = Time.now
run_time = exec_end_time - exec_start_time
logger.info("LVS Total Run time %f seconds" % [run_time])
#=== DECISION ===
if ! compare
logger.info("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
logger.error("ERROR : Netlists don't match")
logger.info("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
exit(1)
else
logger.info("==========================================")
logger.info("INFO : Congratulations! Netlists match.")
logger.info("==========================================")
end