blob: 4f6b68c8e8b34a9984322ac0d48bcdabf287a646 [file] [log] [blame]
################################################################################################
# Copyright 2023 GlobalFoundries PDK Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
################################################################################################
#=======================================================================================================================
#--------------------------------------------- GF 0.18um ULL LVS RULE DECK ---------------------------------------------
#=======================================================================================================================
require 'time'
require 'logger'
require 'etc'
exec_start_time = Time.now
logger = Logger.new($stdout)
logger.formatter = proc do |_severity, datetime, _progname, msg|
"#{datetime}: Memory Usage (" + `pmap #{Process.pid} | tail -1`[10, 40].strip + ") : #{msg}
"
end
#================================================
#----------------- FILE SETUP -------------------
#================================================
logger.info("Starting running GF180ULL Klayout LVS runset on #{$input}")
logger.info("Ruby Version for klayout: #{RUBY_VERSION}")
if $input
if $topcell
source($input, $topcell)
else
source($input)
end
end
logger.info('Loading database to memory is complete.')
if $report
logger.info("GF180ULL Klayout LVS runset output at: #{$report}")
report_lvs($report)
else
layout_dir = Pathname.new(RBA::CellView.active.filename).parent.realpath
report_path = layout_dir.join("#{source.cell_name}.lvsdb").to_s
logger.info("GF180ULL Klayout LVS runset output at default location: #{source.cell_name}.lvsdb")
report_lvs($report_path)
end
if $target_netlist
logger.info("LVS extracted netlist at: #{$target_netlist}")
target_netlist($target_netlist)
else
layout_dir = Pathname.new(RBA::CellView.active.filename).parent.realpath
netlist_path = layout_dir.join("#{source.cell_name}_extracted.cir").to_s
logger.info("GF180ULL Klayout LVS extracted netlist file at: #{source.cell_name}_extracted.cir")
target_netlist($netlist_path,
write_spice(spice_with_net_names, spice_with_comments), 'Extracted by KLayout with GF180 LVS runset')
end
#================================================
#------------------ SWITCHES --------------------
#================================================
logger.info('Evaluate switches.')
def bool_check?(obj)
obj.to_s.downcase == 'true'
end
#=== GET SUBSTRATE NAME ===
substrate_name = $lvs_sub || 'gf180ull_gnd'
logger.info("Substrate name used: #{$lvs_sub}")
#=== NET NAMES OPTION ===
# true: use net names instead of numbers
# false: use numbers for nets
SPICE_WITH_NET_NAMES = bool_check?($spice_net_names)
logger.info("Extracted netlist with net names: #{SPICE_WITH_NET_NAMES}")
#=== COMMENTS OPTION ===
# true: put in comments with details
# false: no comments
SPICE_WITH_COMMENTS = bool_check?($spice_comments)
logger.info("Extracted netlist with comments in details: #{SPICE_WITH_COMMENTS}")
#=== EXTRACTION SCALE ===
DEV_SCALE = bool_check?($scale)
device_scaling(1_000_000) if $DEV_SCALE
logger.info("LVS device_scaling option: #{DEV_SCALE}")
# SCH_SIMPLE
SCH_SIMPLE = bool_check?($schematic_simplify)
logger.info("Selected SCH_SIMPLE option: #{SCH_SIMPLE}")
# NET_ONLY
NET_ONLY = bool_check?($net_only)
logger.info("Selected NET_ONLY option: #{NET_ONLY}")
# TOP_LVL_PINS
TOP_LVL_PINS = bool_check?($top_lvl_pins)
logger.info("Selected TOP_LVL_PINS option: #{TOP_LVL_PINS}")
# COMBINE
COMBINE = bool_check?($combine)
logger.info("Selected COMBINE option: #{COMBINE}")
# PURGE
PURGE = bool_check?($purge)
logger.info("Selected PURGE option: #{PURGE}")
# PURGE_NETS
PURGE_NETS = bool_check?($purge_nets)
logger.info("Selected PURGE_NETS option: #{PURGE_NETS}")
# SIMPLIFY
SIMPLIFY = if NET_ONLY || TOP_LVL_PINS || COMBINE || PURGE || PURGE_NETS
false
else
true
end
logger.info("Selected SIMPLIFY option: #{SIMPLIFY}")
#=== PRINT DETAILS ===
logger.info("Verbose mode: #{$verbose}")
if $verbose == 'true'
verbose(true)
else
verbose(false)
end
# === TILING MODE ===
case $run_mode
when 'tiling'
tiles(500.um)
tile_borders(10.um)
logger.info('Tiling mode is enabled.')
when 'deep'
#=== HIER MODE ===
deep
logger.info('deep mode is enabled.')
else
#=== FLAT MODE ===
flat
logger.info('flat mode is enabled.')
end
# METAL_TOP
METAL_TOP = $metal_top || '9K'
logger.info("METAL_TOP Selected is #{METAL_TOP}")
# METAL_LEVEL
METAL_LEVEL = $metal_level || '6LM'
logger.info("METAL_STACK Selected is #{METAL_LEVEL}")
# POLY_RES
POLY_RES = $poly_res || '1k'
logger.info("POLY_RES Selected is #{POLY_RES}")
# MIM
MIM_OPTION = $mim_option || 'B'
logger.info("MIM Option selected: #{MIM_OPTION}")
# MIM
MIM_CAP = $mim_cap || '2'
logger.info("MIM CAP selected: #{MIM_CAP}")
#================================================
# --------------- CUSTOM CLASSES ----------------
#================================================
# %include 'rule_decks/custom_classes.lvs'
# 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
exts = ["spice", "cdl"]
candidates = exts.map{|ext| "#{source.cell_name}.#{ext}"}
netlists = candidates.select{|f| File.exist?(f)}
if netlists.empty?
error("Netlist not found, tried: #{candidates}")
else
schematic(netlists[0], reader)
logger.info("Netlist file: #{netlists[0]}")
end
end
#================================================
#------------- LAYERS DERIVATIONS ---------------
#================================================
# %include 'rule_decks/layers_definition.lvs'
#================================================================
#------------------------- MAIN RUNSET --------------------------
#================================================================
logger.info('GF180 LVS rules started')
#================================================
#------------- LAYERS DERIVATIONS ---------------
#================================================
logger.info('Starting deriving base layers.')
#==================================
# ------ GENERAL DERIVATIONS ------
#==================================
# %include 'rule_decks/general_derivations.lvs'
#================================
# ------ BJT DERIVATIONS --------
#================================
# %include 'rule_decks/bjt_derivations.lvs'
#================================
# ------ MOS DERIVATIONS --------
#================================
# %include 'rule_decks/mos_derivations.lvs'
#================================
# ------ DIODE DERIVATIONS --------
#================================
# %include 'rule_decks/diode_derivations.lvs'
#================================
# ------ MOSCAP DERIVATIONS -----
#================================
# %include 'rule_decks/moscap_derivations.lvs'
#===================================
# ------ Varactor DERIVATIONS ------
#===================================
# %include 'rule_decks/varactor_derivations.lvs'
#===================================
# ------ PISCAP DERIVATIONS ------
#===================================
# %include 'rule_decks/piscap_derivations.lvs'
#===================================
# ------ MIMCAP DERIVATIONS ------
#===================================
# %include 'rule_decks/mimcap_derivations.lvs'
#================================================
#------------ DEVICES CONNECTIVITY --------------
#================================================
# %include 'rule_decks/devices_connections.lvs'
#================================================
#------------- DEVICES EXTRACTION ---------------
#================================================
logger.info('Starting GF180 LVS DEVICES EXTRACTION')
#================================
# ------- BJT EXTRACTION --------
#================================
# %include 'rule_decks/bjt_extraction.lvs'
#================================
# ------- MOS EXTRACTION --------
#================================
# %include 'rule_decks/mos_extraction.lvs'
#================================
# ------- Diode EXTRACTION ------
#================================
# %include 'rule_decks/diode_extraction.lvs'
#================================
# ------- MOSCAP EXTRACTION -----
#================================
# %include 'rule_decks/moscap_extraction.lvs'
#================================
# ----- Varactor EXTRACTION ----
#================================
# %include 'rule_decks/varactor_extraction.lvs'
#================================
# ------ PISCAP EXTRACTION -----
#================================
# %include 'rule_decks/piscap_extraction.lvs'
#================================
# ------ MIMCAP EXTRACTION -----
#================================
# %include 'rule_decks/mimcap_extraction.lvs'
#================================================
#------------- COMPARISON OPTIONS ---------------
#================================================
logger.info('Starting GF180 LVS comparison section')
#=== FLATTEN CELLS ===
align
#=== NETLIST EXTRACTION ===
netlist.simplify if SIMPLIFY
#=== NETLIST OPTIONS ===
netlist if NET_ONLY
netlist.make_top_level_pins if TOP_LVL_PINS
netlist.combine_devices if COMBINE
netlist.purge if PURGE
netlist.purge_nets if PURGE_NETS
#=== SCHEMATIC OPTIONS ===
schematic.simplify if SCH_SIMPLE
#=== IGNORE EXTREME VALUES ===
max_res(1e7)
min_caps(1e-16)
compare
exec_end_time = Time.now
run_time = exec_end_time - exec_start_time
logger.info(format('LVS Total Run time %f seconds', run_time))
if !compare
logger.info('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
logger.error("ERROR : Netlists don't match")
logger.info('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
else
logger.info('==========================================')
logger.info('INFO : Congratulations! Netlists match.')
logger.info('==========================================')
end