blob: e9a6bddd5a6c683ed461d070d19c072b9a9123c9 [file] [log] [blame]
# Copyright 2022 GlobalFoundries PDK Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://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.
"""Run GlobalFoundries 180nm MCU LVS.
Usage:
run_lvs.py (--help| -h)
run_lvs.py (--design=<layout_path>) (--net=<netlist_path>) (--gf180mcu=<combined_options>) [--thr=<thr>] [--run_mode=<run_mode>] [--lvs_sub=<sub_name>] [--no_net_names] [--set_spice_comments] [--set_scale] [--set_verbose] [--set_schematic_simplify] [--set_net_only] [--set_top_lvl_pins] [--set_combine] [--set_purge] [--set_purge_nets]
Options:
--help -h Print this help message.
--design=<layout_path> The input GDS file path.
--net=<netlist_path> The input netlist file path.
--gf180mcu=<combined_options> Select combined options of metal_top, mim_option, and metal_level. Allowed values (A, B, C).
gf180mcu=A: Select metal_top=30K mim_option=A metal_level=3LM poly_res=1K, and mim_cap=2
gf180mcu=B: Select metal_top=11K mim_option=B metal_level=4LM poly_res=1K, and mim_cap=2
gf180mcu=C: Select metal_top=9K mim_option=B metal_level=5LM poly_res=1K, and mim_cap=2
--thr=<thr> Number of cores to be used by LVS checker
--run_mode=<run_mode> Select klayout mode Allowed modes (flat , deep, tiling). [default: deep]
--lvs_sub=<sub_name> Assign the substrate name used in design.
--no_net_names Discard net names in extracted netlist.
--set_spice_comments Set netlist comments in extracted netlist.
--set_scale Set scale of 1e6 in extracted netlist.
--set_verbose Set verbose mode.
--set_schematic_simplify Set schematic simplification in input netlist.
--set_net_only Set netlist object creation only in extracted netlist.
--set_top_lvl_pins Set top level pins only in extracted netlist.
--set_combine Set netlist combine only in extracted netlist.
--set_purge Set netlist purge all only in extracted netlist.
--set_purge_nets Set netlist purge nets only in extracted netlist.
"""
from docopt import docopt
import os
import logging
def main():
# Switches used in run
switches = ''
if args["--run_mode"] in ["flat" , "deep", "tiling"]:
switches = switches + f'-rd run_mode={args["--run_mode"]} '
else:
logging.error("Allowed klayout modes are (flat , deep , tiling) only")
exit()
if args["--gf180mcu"] == "A":
switches = switches + f'-rd metal_top=30K -rd mim_option=A -rd metal_level=3LM -rd poly_res=1K -rd mim_cap=2 '
elif args["--gf180mcu"] == "B":
switches = switches + f'-rd metal_top=11K -rd mim_option=B -rd metal_level=4LM -rd poly_res=1K -rd mim_cap=2 '
elif args["--gf180mcu"] == "C":
switches = switches + f'-rd metal_top=9K -rd mim_option=B -rd metal_level=5LM -rd poly_res=1K -rd mim_cap=2 '
else:
print("gf180mcu switch allowed values are (A , B, C) only")
exit()
switches = switches + '-rd spice_net_names=false ' if args["--no_net_names"] else switches + '-rd spice_net_names=true '
switches = switches + '-rd spice_comments=true ' if args["--set_spice_comments"] else switches + '-rd spice_comments=false '
switches = switches + '-rd scale=true ' if args["--set_scale"] else switches + '-rd scale=false '
switches = switches + '-rd verbose=true ' if args["--set_verbose"] else switches + '-rd verbose=false '
switches = switches + '-rd schematic_simplify=true ' if args["--set_schematic_simplify"] else switches + '-rd schematic_simplify=false '
switches = switches + '-rd net_only=true ' if args["--set_net_only"] else switches + '-rd net_only=false '
switches = switches + '-rd top_lvl_pins=true ' if args["--set_top_lvl_pins"] else switches + '-rd top_lvl_pins=false '
switches = switches + '-rd combine=true ' if args["--set_combine"] else switches + '-rd combine=false '
switches = switches + '-rd purge=true ' if args["--set_purge"] else switches + '-rd purge=false '
switches = switches + '-rd purge_nets=true ' if args["--set_purge_nets"] else switches + '-rd purge_nets=false '
switches = switches + f'-rd lvs_sub={args["--lvs_sub"]} ' if args["--lvs_sub"] else switches
# Generate databases
if args["--design"]:
path = args["--design"]
if args["--design"]:
file_name = args["--net"].split('.')
else:
print("The script must be given a netlist file or a path to be able to run LVS")
exit()
os.system(f"klayout -b -r gf180mcu.lvs -rd input={path} -rd report={file_name[0]}.lyrdb -rd schematic={args['--net']} -rd target_netlist=extracted_netlist_{file_name[0]}.cir -rd thr={workers_count} {switches}")
else:
print("The script must be given a layout file or a path to be able to run LVS")
exit()
if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG, format=f"%(asctime)s | %(levelname)-7s | %(message)s", datefmt='%d-%b-%Y %H:%M:%S')
# Args
args = docopt(__doc__, version='LVS Checker: 0.1')
workers_count = os.cpu_count()*2 if args["--thr"] == None else int(args["--thr"])
# Env. variables
pdk_root = os.environ['PDK_ROOT']
pdk = os.environ['PDK']
# ========= Checking Klayout version =========
klayout_v_ = os.popen("klayout -v").read()
klayout_v_ = klayout_v_.split("\n")[0]
klayout_v = int (klayout_v_.split(".") [-1])
if klayout_v < 8:
logging.warning("Using this klayout version has not been assesed in this development. Limits are unknown")
logging.info(f"Your version is: {klayout_v_}" )
logging.info(f"Prerequisites at a minimum: KLayout 0.27.8")
# Calling main function
main()