mirror of https://github.com/efabless/caravel.git
803 lines
28 KiB
Python
803 lines
28 KiB
Python
#!/usr/local/bin/python
|
|
|
|
import argparse
|
|
from cmath import log
|
|
import logging
|
|
import os
|
|
import subprocess
|
|
from sys import stdout
|
|
import count_lvs
|
|
import glob
|
|
import time
|
|
import shutil
|
|
|
|
|
|
def build_caravel_caravan(caravel_root, mcw_root, pdk_root, log_dir, pdk_env, design):
|
|
os.environ["CARAVEL_ROOT"] = caravel_root
|
|
os.environ["MCW_ROOT"] = mcw_root
|
|
os.environ["PDK_ROOT"] = pdk_root
|
|
os.environ["PDK"] = pdk_envg
|
|
os.environ["DESIGN"] = design
|
|
|
|
gpio_defaults_cmd = ["python3", f"scripts/gen_gpio_defaults.py"]
|
|
build_cmd = [
|
|
"magic",
|
|
"-noconsole",
|
|
"-dnull",
|
|
"-rcfile",
|
|
f"{pdk_root}/{pdk_env}/libs.tech/magic/{pdk_env}.magicrc",
|
|
"tech-files/build.tcl",
|
|
]
|
|
log_file_path = f"{log_dir}/build_{design}.log"
|
|
with open(log_file_path, "w") as build_log:
|
|
subprocess.run(
|
|
gpio_defaults_cmd, cwd=caravel_root, stderr=build_log, stdout=build_log
|
|
)
|
|
subprocess.run(build_cmd, stderr=build_log, stdout=build_log)
|
|
|
|
def run_drc(design_root, timestr, signoff_dir, pdk_path, design):
|
|
log_dir = f"{signoff_dir}/{design}/standalone_pvr/{timestr}/logs"
|
|
if "sky130" in os.getenv('PDK'):
|
|
klayout_drc_cmd = [
|
|
"python3",
|
|
"klayout_drc.py",
|
|
"-g",
|
|
f"{design_root}/gds/{design}.gds",
|
|
"-l",
|
|
f"{log_dir}",
|
|
"-s",
|
|
f"{signoff_dir}/{design}/standalone_pvr/{timestr}",
|
|
"-d",
|
|
f"{design}",
|
|
]
|
|
elif "gf180" in os.getenv('PDK'):
|
|
klayout_drc_cmd = [
|
|
"python3",
|
|
f"{pdk_path}/libs.tech/klayout/drc/run_drc.py",
|
|
"--variant=C",
|
|
f"--path={design_root}/gds/{design}.gds",
|
|
f"--run_dir={signoff_dir}/{design}/standalone_pvr/{timestr}",
|
|
]
|
|
|
|
p1 = subprocess.Popen(klayout_drc_cmd)
|
|
return p1
|
|
|
|
|
|
def run_lvs(
|
|
caravel_root, mcw_root, log_dir, signoff_dir, pdk_root, lvs_root, pdk_env, design
|
|
):
|
|
myenv = os.environ.copy()
|
|
myenv["PDK_ROOT"] = pdk_root
|
|
myenv["PDK"] = pdk_env
|
|
myenv["LVS_ROOT"] = lvs_root
|
|
myenv["LOG_ROOT"] = log_dir
|
|
myenv["CARAVEL_ROOT"] = caravel_root
|
|
myenv["MCW_ROOT"] = mcw_root
|
|
myenv["SIGNOFF_ROOT"] = os.path.join(signoff_dir, f"{design}/standalone_pvr")
|
|
myenv["WORK_DIR"] = os.path.join(caravel_root, "extra_be_checks")
|
|
|
|
if not os.path.exists(f"{lvs_root}"):
|
|
subprocess.run(
|
|
[
|
|
"git",
|
|
"clone",
|
|
"https://github.com/d-m-bailey/extra_be_checks.git",
|
|
"-b",
|
|
f"caravel",
|
|
],
|
|
cwd=f"{caravel_root}/scripts",
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE,
|
|
)
|
|
if (design == "mgmt_core_wrapper" or design == "RAM128" or design == "RAM256"):
|
|
lvs_cmd = [
|
|
"bash",
|
|
"./run_full_lvs",
|
|
f"{design}",
|
|
f"{mcw_root}/verilog/gl/{design}.v",
|
|
f"{design}",
|
|
f"{mcw_root}/gds/{design}.gds",
|
|
]
|
|
else:
|
|
lvs_cmd = [
|
|
"bash",
|
|
"./run_full_lvs",
|
|
f"{design}",
|
|
f"{caravel_root}/verilog/gl/{design}.v",
|
|
f"{design}",
|
|
f"{caravel_root}/gds/{design}.gds",
|
|
]
|
|
p1 = subprocess.Popen(
|
|
lvs_cmd,
|
|
env=myenv,
|
|
cwd=f"{caravel_root}/scripts/extra_be_checks",
|
|
universal_newlines=True,
|
|
)
|
|
return p1
|
|
|
|
|
|
def run_verification(caravel_root, pdk_root, pdk_env, sim, simulator="vcs"):
|
|
myenv = os.environ.copy()
|
|
myenv["PDK_ROOT"] = pdk_root
|
|
myenv["PDK"] = pdk_env
|
|
if simulator == "vcs":
|
|
ver_cmd = [
|
|
"python3",
|
|
"verify_cocotb.py",
|
|
"-tag",
|
|
f"CI_{sim}",
|
|
"-r",
|
|
f"r_{sim}",
|
|
"-v",
|
|
]
|
|
else:
|
|
ver_cmd = [
|
|
"python3",
|
|
"verify_cocotb.py",
|
|
"-tag",
|
|
f"CI_{sim}",
|
|
"-r",
|
|
f"r_{sim}",
|
|
]
|
|
p1 = subprocess.Popen(
|
|
ver_cmd,
|
|
cwd=f"{caravel_root}/verilog/dv/cocotb",
|
|
env=myenv,
|
|
universal_newlines=True,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE,
|
|
)
|
|
return p1
|
|
|
|
|
|
def run_sta(root, pt_lib_root, log_dir, signoff_dir, design, timestr, upw):
|
|
myenv = os.environ.copy()
|
|
myenv["PT_LIB_ROOT"] = pt_lib_root
|
|
if "sky130" in os.getenv('PDK'):
|
|
if not os.path.exists(f"{pt_lib_root}"):
|
|
subprocess.run(
|
|
[
|
|
"git",
|
|
"clone",
|
|
"git@github.com:efabless/pt_libs.git",
|
|
],
|
|
cwd=f"{caravel_root}/scripts",
|
|
stdout=subprocess.PIPE,
|
|
)
|
|
sta_cmd = [
|
|
"python3",
|
|
"run_pt_sta.py",
|
|
"-a",
|
|
"-d",
|
|
f"{design}",
|
|
"-o",
|
|
f"{signoff_dir}/{design}/primetime/{timestr}",
|
|
"-l",
|
|
f"{log_dir}",
|
|
"-r",
|
|
f"{root}",
|
|
"-upw",
|
|
f"{upw}",
|
|
]
|
|
p1 = subprocess.Popen(
|
|
sta_cmd,
|
|
cwd=f"{caravel_root}/scripts",
|
|
env=myenv,
|
|
universal_newlines=True,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE,
|
|
)
|
|
return p1
|
|
|
|
def run_starxt (design_root, log_dir, signoff_dir, design, timestr):
|
|
myenv = os.environ.copy()
|
|
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
if not os.path.exists(f"{SCRIPT_DIR}/gf180mcu-tech/"):
|
|
subprocess.run(
|
|
[
|
|
"git",
|
|
"clone",
|
|
"git@github.com:efabless/gf180mcu-tech.git",
|
|
],
|
|
cwd=f"{caravel_root}/scripts",
|
|
stdout=subprocess.PIPE,
|
|
)
|
|
starxt_cmd = [
|
|
"python3",
|
|
"extract_StarRC.py",
|
|
"-a",
|
|
"-d",
|
|
f"{design}",
|
|
"-o",
|
|
f"{signoff_dir}/{design}/StarRC/{timestr}",
|
|
"-r",
|
|
f"{design_root}",
|
|
"-l",
|
|
f"{log_dir}",
|
|
]
|
|
p1 = subprocess.Popen(
|
|
starxt_cmd,
|
|
cwd=f"{caravel_root}/scripts",
|
|
env=myenv,
|
|
universal_newlines=True,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE,
|
|
)
|
|
return p1
|
|
|
|
def run_antenna(design_root, timestr, signoff_dir, pdk_path, design):
|
|
klayout_antenna_cmd = [
|
|
"python3",
|
|
f"{pdk_path}/libs.tech/klayout/drc/run_drc.py",
|
|
"--variant=C",
|
|
"--antenna_only",
|
|
f"--path={design_root}/gds/{design}.gds",
|
|
f"--run_dir={signoff_dir}/{design}/standalone_pvr/{timestr}/",
|
|
]
|
|
p1 = subprocess.Popen(klayout_antenna_cmd)
|
|
return p1
|
|
|
|
|
|
def check_errors(
|
|
caravel_root, log_dir, signoff_dir, drc, lvs, verification, sta, design, antenna
|
|
):
|
|
f = open(os.path.join(signoff_dir, f"{design}/signoff.rpt"), "w")
|
|
if drc:
|
|
if "sky130" in os.getenv('PDK'):
|
|
drc_count_klayout = os.path.join(log_dir, f"{design}_klayout_drc.total")
|
|
with open(drc_count_klayout) as rep:
|
|
if rep.readline().strip() != "0":
|
|
logging.error(f"klayout DRC failed")
|
|
f.write("Klayout MR DRC: Failed\n")
|
|
else:
|
|
logging.info("Klayout MR DRC: Passed")
|
|
f.write("Klayout MR DRC: Passed\n")
|
|
elif "gf180" in os.getenv('PDK'):
|
|
drc_output_dir = f"{signoff_dir}/{design}/standalone_pvr/{timestr}"
|
|
log_drc_file = glob.glob(f"{drc_output_dir}/drc_run_*.log")[0]
|
|
os.remove(f"{drc_output_dir}/main.drc")
|
|
with open(log_drc_file) as rep:
|
|
for lines in rep:
|
|
if "not clean" in lines:
|
|
logging.error(f"klayout DRC failed")
|
|
f.write("Klayout MR DRC: Failed\n")
|
|
elif "clean" in lines:
|
|
logging.info("Klayout MR DRC: Passed")
|
|
f.write("Klayout MR DRC: Passed\n")
|
|
if lvs:
|
|
lvs_summary_report = open(
|
|
os.path.join(signoff_dir, f"{design}/standalone_pvr/lvs_summary.rpt"), "w"
|
|
)
|
|
lvs_sum_rep = os.path.join(signoff_dir, f"{design}/standalone_pvr/lvs_summary.rpt")
|
|
lvs_report = os.path.join(signoff_dir, f"{design}/standalone_pvr/{design}.lvs.json")
|
|
failures = count_lvs.count_LVS_failures(lvs_report)
|
|
if failures[0] > 0:
|
|
lvs_summary_report.write("LVS reports:\n")
|
|
lvs_summary_report.write(" net count difference = " + str(failures[5]) + "\n")
|
|
lvs_summary_report.write(
|
|
" device count difference = " + str(failures[6]) + "\n"
|
|
)
|
|
lvs_summary_report.write(" unmatched nets = " + str(failures[1]) + "\n")
|
|
lvs_summary_report.write(" unmatched devices = " + str(failures[2]) + "\n")
|
|
lvs_summary_report.write(" unmatched pins = " + str(failures[3]) + "\n")
|
|
lvs_summary_report.write(" property failures = " + str(failures[4]) + "\n")
|
|
logging.error(f"LVS on {design} failed")
|
|
logging.info(f"Find full report at {lvs_report}")
|
|
logging.info(f"Find summary report at {lvs_sum_rep}")
|
|
f.write("Layout Vs Schematic: Failed\n")
|
|
else:
|
|
lvs_summary_report.write("Layout Vs Schematic Passed")
|
|
logging.info("Layout Vs Schematic: Passed")
|
|
f.write("Layout Vs Schematic: Passed\n")
|
|
|
|
if verification:
|
|
for sim in ["rtl", "gl", "sdf"]:
|
|
verification_report = os.path.join(
|
|
caravel_root, f"/verilog/dv/cocotb/sim/CI_{sim}/runs.log"
|
|
)
|
|
with open(verification_report) as rep:
|
|
if "(0)failed" in rep.read():
|
|
logging.info(f"{sim} simulations: Passed")
|
|
f.write(f"{sim} simulations: Passed\n")
|
|
else:
|
|
logging.error(
|
|
f"{sim} simulations failed, find report at {verification_report}"
|
|
)
|
|
f.write(f"{sim} simulations: Failed\n")
|
|
|
|
if sta:
|
|
sta_logs = glob.glob(f"{sta_log_dir}/{design}-*sta.log")
|
|
for l in sta_logs:
|
|
with open(l) as rep:
|
|
log_name = l.split("/")[-1]
|
|
log_name = log_name.split(".")[0]
|
|
data = rep.read()
|
|
if "The following spefs are missing:" in data:
|
|
logging.warning(f"Missing spefs. check: {l}")
|
|
rep.seek(0)
|
|
lines = rep.readlines()
|
|
if "Passed" in lines[-1]:
|
|
logging.info(f"{log_name} STA: Passed")
|
|
f.write(f"{log_name} STA: Passed\n")
|
|
elif "max_transition and max_capacitance" in lines[-1]:
|
|
logging.warning(lines[-1])
|
|
logging.info(f"{log_name} STA: Passed (except: max_tran & max_cap)")
|
|
f.write(f"{log_name} STA: Passed (except: max_tran & max_cap)\n")
|
|
elif "max_transition" in lines[-1]:
|
|
logging.warning(lines[-1])
|
|
logging.info(f"{log_name} STA: Passed (except: max_tran)")
|
|
f.write(f"{log_name} STA: Passed (except: max_tran)\n")
|
|
elif "max_capacitance" in lines[-1]:
|
|
logging.warning(lines[-1])
|
|
logging.info(f"{log_name} STA: Passed (except: max_cap)")
|
|
f.write(f"{log_name} STA: Passed (except: max_cap)\n")
|
|
elif "other violations" in lines[-1]:
|
|
logging.warning(lines[-1])
|
|
logging.info(f"{log_name} STA: Passed")
|
|
f.write(f"{log_name} STA: Passed\n")
|
|
else:
|
|
logging.error(lines[-1])
|
|
if "setup" in lines[-1]:
|
|
f.write(f"{log_name} STA: Failed (setup)\n")
|
|
logging.error(f"{log_name} STA: Failed (setup)")
|
|
elif "hold" in lines[-1]:
|
|
f.write(f"{log_name} STA: Failed (hold)\n")
|
|
logging.error(f"{log_name} STA: Failed (hold)")
|
|
else:
|
|
logging.error(f"{log_name} STA: Failed")
|
|
f.write(f"{log_name} STA: Failed (" + lines[-1].split(" failed")[0] + ")\n")
|
|
|
|
if antenna:
|
|
antenna_report = os.path.join(signoff_dir, f"{design}/standalone_pvr/{timestr}/antenna-vios.report")
|
|
xml_report = open(os.path.join(signoff_dir, f"{design}/standalone_pvr/{timestr}/{design}_antenna.lyrdb"))
|
|
antenna_count = xml_report.read().count('<item>')
|
|
antenna_count_log = open(os.path.join(signoff_dir, f"{design}/standalone_pvr/{timestr}/antenna_count.log"), "w")
|
|
antenna_count_log.write(str(antenna_count))
|
|
antenna_count_log.close()
|
|
if antenna_count == 0:
|
|
logging.info("Antenna checks: Passed")
|
|
f.write("Antenna checks: Passed\n")
|
|
else:
|
|
logging.error(f"Antenna checks failed find report at {antenna_report}")
|
|
f.write("Antenna checks: Failed\n")
|
|
|
|
def save_latest_run (lvs, drc, antenna, sta, spef, run_dir):
|
|
if spef:
|
|
if os.path.exists(f"{run_dir}/../logs"):
|
|
shutil.rmtree(f"{run_dir}/../logs")
|
|
shutil.copytree(f"{run_dir}/logs", f"{run_dir}/../logs")
|
|
spef_files = glob.glob(f"{run_dir}/*.spef")
|
|
for spef_f in spef_files:
|
|
spef_name =spef_f.split("/")[-1]
|
|
shutil.copyfile(spef_f,f"{run_dir}/../{spef_name}")
|
|
|
|
elif sta:
|
|
dirs = ['lib', 'sdf', 'reports', 'logs']
|
|
for dir in dirs:
|
|
if os.path.exists(f"{run_dir}/../{dir}"):
|
|
shutil.rmtree(f"{run_dir}/../{dir}")
|
|
shutil.copytree(f"{run_dir}/{dir}", f"{run_dir}/../{dir}")
|
|
cmd = f"sed -i -E 's#original_pin :.*##g' {run_dir}/../lib/*/*.lib"
|
|
os.system(cmd)
|
|
# if lvs or drc or antenna :
|
|
# if os.path.exists(f"{run_dir}/../logs"):
|
|
# shutil.rmtree(f"{run_dir}/../logs")
|
|
# shutil.copytree(f"{run_dir}/logs", f"{run_dir}/../logs")
|
|
# files = glob.glob(f"{run_dir}/*")
|
|
# for f in files:
|
|
# f_name = f.split("/")[-1]
|
|
# shutil.copyfile(spef_f,f"{run_dir}/../{f_name}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
logging.basicConfig(
|
|
level=logging.DEBUG,
|
|
format=f"%(asctime)s | %(levelname)-7s | %(message)s",
|
|
datefmt="%d-%b-%Y %H:%M:%S",
|
|
)
|
|
parser = argparse.ArgumentParser(description="CI wrapper")
|
|
parser.add_argument(
|
|
"-drc",
|
|
"--drc_check",
|
|
help="run drc check",
|
|
action="store_true",
|
|
)
|
|
parser.add_argument(
|
|
"-l",
|
|
"--lvs_check",
|
|
help="run lvs check",
|
|
action="store_true",
|
|
)
|
|
parser.add_argument(
|
|
"-v",
|
|
"--vcs",
|
|
help="run verification using vcs",
|
|
action="store_true",
|
|
)
|
|
parser.add_argument(
|
|
"-rtl",
|
|
"--rtl",
|
|
help="run rtl verification",
|
|
action="store_true",
|
|
)
|
|
parser.add_argument(
|
|
"-gl",
|
|
"--gl",
|
|
help="run gl verification",
|
|
action="store_true",
|
|
)
|
|
parser.add_argument(
|
|
"-sdf",
|
|
"--sdf",
|
|
help="run sdf verification",
|
|
action="store_true",
|
|
)
|
|
parser.add_argument(
|
|
"-iv",
|
|
"--iverilog",
|
|
help="run verification using iverilog",
|
|
action="store_true",
|
|
)
|
|
parser.add_argument(
|
|
"-sta",
|
|
"--primetime_sta",
|
|
help="run sta using primetime",
|
|
action="store_true",
|
|
)
|
|
parser.add_argument(
|
|
"-upw",
|
|
"--upw",
|
|
help="Specify to run STA with non-empty user project wrapper",
|
|
action="store_true",
|
|
)
|
|
parser.add_argument(
|
|
"-spef",
|
|
"--starRC_extract",
|
|
help="run spef extraction using StarRC (gf180)",
|
|
action="store_true",
|
|
)
|
|
parser.add_argument(
|
|
"-ant",
|
|
"--antenna",
|
|
help="run antenna checks",
|
|
action="store_true",
|
|
)
|
|
parser.add_argument(
|
|
"-d",
|
|
"--design",
|
|
help="design under test",
|
|
required=True,
|
|
)
|
|
parser.add_argument(
|
|
"-a",
|
|
"--all",
|
|
help="run all checks",
|
|
action="store_true",
|
|
)
|
|
args = parser.parse_args()
|
|
|
|
if not os.getenv("PDK_ROOT"):
|
|
logging.error("Please export PDK_ROOT")
|
|
exit(1)
|
|
if not os.getenv("PDK"):
|
|
logging.error("Please export PDK")
|
|
exit(1)
|
|
caravel_redesign_root = os.path.dirname(
|
|
os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
)
|
|
if os.getenv("CARAVEL_ROOT") == None:
|
|
caravel_root = os.path.join(caravel_redesign_root, "caravel")
|
|
logging.warning(f"CARAVEL_ROOT is not defined, defaulting to {caravel_root}")
|
|
else:
|
|
caravel_root = os.getenv("CARAVEL_ROOT")
|
|
|
|
if os.getenv("MCW_ROOT") == None:
|
|
mcw_root = os.path.join(caravel_redesign_root, "caravel_mgmt_soc_litex")
|
|
logging.warning(f"MCW_ROOT is not defined, defaulting to {mcw_root}")
|
|
else:
|
|
mcw_root = os.getenv("MCW_ROOT")
|
|
|
|
if not os.path.exists(f"{caravel_root}"):
|
|
logging.error(f"{caravel_root} does not exist!")
|
|
exit(1)
|
|
if not os.path.exists(f"{mcw_root}"):
|
|
logging.error(f"{mcw_root} does not exist!")
|
|
exit(1)
|
|
|
|
pdk_root = os.getenv("PDK_ROOT")
|
|
pdk_env = os.getenv("PDK")
|
|
signoff_dir = os.path.join(caravel_root, "signoff")
|
|
lvs_root = os.path.join(caravel_root, "scripts/extra_be_checks")
|
|
drc = args.drc_check
|
|
lvs = args.lvs_check
|
|
rtl = args.rtl
|
|
gl = args.gl
|
|
sdf = args.sdf
|
|
iverilog = args.iverilog
|
|
verification = args.vcs
|
|
sta = args.primetime_sta
|
|
if args.upw: upw = True
|
|
else: upw = False
|
|
spef = args.starRC_extract
|
|
if spef and "sky130" in pdk_env:
|
|
logging.erro(f"Spef extraction is available for gf180mcu only")
|
|
spef = False
|
|
design = args.design
|
|
antenna = args.antenna
|
|
|
|
if sta:
|
|
if not os.getenv("CHIP"):
|
|
os.environ["CHIP"] = "caravel"
|
|
if not os.getenv("CHIP_CORE"):
|
|
os.environ["CHIP_CORE"] = "caravel_core"
|
|
os.environ["DEBUG"] = "0"
|
|
|
|
if (design == "mgmt_core_wrapper" or design == "RAM128" or design == "RAM256" or design == "gf180_ram_512x8_wrapper"):
|
|
signoff_dir = os.path.join(mcw_root, "signoff")
|
|
elif (design == "user_project_wrapper" or design == "user_proj_example" or design == "user_project" or design == "user_analog_project_wrapper"):
|
|
uprj_root = os.getenv("UPRJ_ROOT")
|
|
signoff_dir = os.path.join(uprj_root, "signoff")
|
|
|
|
timestr = time.strftime("%Y_%m_%d_%H_%M_%S")
|
|
log_dir = os.path.join(signoff_dir, f"{design}/standalone_pvr/{timestr}/logs")
|
|
|
|
if not os.path.exists(f"{signoff_dir}/{design}"):
|
|
os.makedirs(f"{signoff_dir}/{design}")
|
|
|
|
if lvs or drc or antenna:
|
|
if not os.path.exists(f"{signoff_dir}/{design}/standalone_pvr"):
|
|
os.makedirs(f"{signoff_dir}/{design}/standalone_pvr")
|
|
if not os.path.exists(f"{signoff_dir}/{design}/standalone_pvr/{timestr}"):
|
|
os.makedirs(f"{signoff_dir}/{design}/standalone_pvr/{timestr}")
|
|
if not os.path.exists(f"{log_dir}"):
|
|
os.makedirs(f"{log_dir}")
|
|
if glob.glob(f"{caravel_root}/gds/*.gz"):
|
|
logging.error(
|
|
f"Compressed gds files in {caravel_root}. Please uncompress first."
|
|
)
|
|
exit(1)
|
|
|
|
if glob.glob(f"{mcw_root}/gds/*.gz"):
|
|
logging.error(
|
|
f"Compressed gds files in {mcw_root}. Please uncompress first."
|
|
)
|
|
exit(1)
|
|
|
|
design_root = os.path.join(caravel_root, f"gds/{design}.gds")
|
|
if not os.path.exists(design_root):
|
|
design_root = os.path.join(mcw_root, f"gds/{design}.gds")
|
|
if not os.path.exists(design_root):
|
|
logging.error(f"can't find {design}.gds file")
|
|
|
|
# if design == "caravel" or design == "caravan":
|
|
# logging.info(f"Building {design} ...")
|
|
# build_caravel_caravan(caravel_root, mcw_root, pdk_root, log_dir, pdk_env, design)
|
|
# else:
|
|
# logging.info(f"running checks on {design}")
|
|
|
|
if args.all:
|
|
drc = True
|
|
lvs = True
|
|
sta = True
|
|
spef = True
|
|
antenna = True
|
|
|
|
pdk_path = pdk_root + "/" + pdk_env
|
|
|
|
if drc:
|
|
if (design == "mgmt_core_wrapper" or design == "RAM128" or design == "RAM256" or design == "gf180_ram_512x8_wrapper"):
|
|
drc_p1 = run_drc(mcw_root, timestr, signoff_dir, pdk_path, design)
|
|
else:
|
|
drc_p1 = run_drc(caravel_root, timestr, signoff_dir, pdk_path, design)
|
|
logging.info(f"Running klayout DRC on {design}")
|
|
if lvs:
|
|
lvs_p1 = run_lvs(
|
|
caravel_root,
|
|
mcw_root,
|
|
log_dir,
|
|
signoff_dir,
|
|
pdk_root,
|
|
lvs_root,
|
|
pdk_env,
|
|
design,
|
|
)
|
|
logging.info(f"Running LVS on {design}")
|
|
|
|
if spef:
|
|
if not os.path.exists(f"{signoff_dir}/{design}/StarRC"):
|
|
os.makedirs(f"{signoff_dir}/{design}/StarRC")
|
|
if not os.path.exists(f"{signoff_dir}/{design}/StarRC/{timestr}"):
|
|
os.makedirs(f"{signoff_dir}/{design}/StarRC/{timestr}")
|
|
spef_log_dir = os.path.join(signoff_dir, f"{design}/StarRC/{timestr}/logs")
|
|
if not os.path.exists(f"{spef_log_dir}"):
|
|
os.makedirs(f"{spef_log_dir}")
|
|
|
|
if (design == "mgmt_core_wrapper" or design == "RAM128" or design == "RAM256" or design == "gf180_ram_512x8_wrapper"):
|
|
spef_p = run_starxt(
|
|
mcw_root,
|
|
spef_log_dir,
|
|
signoff_dir,
|
|
design,
|
|
timestr,
|
|
)
|
|
elif (design == "user_project_wrapper" or design == "user_proj_example"):
|
|
spef_p = run_starxt(
|
|
uprj_root,
|
|
spef_log_dir,
|
|
signoff_dir,
|
|
design,
|
|
timestr,
|
|
)
|
|
else:
|
|
spef_p = run_starxt(
|
|
caravel_root,
|
|
spef_log_dir,
|
|
signoff_dir,
|
|
design,
|
|
timestr,
|
|
)
|
|
logging.info(f"Running StarRC all corners extraction on {design}")
|
|
|
|
if sta and spef:
|
|
out, err = spef_p.communicate()
|
|
spef_log = open(f"{spef_log_dir}/{design}-error.log", "w")
|
|
if err:
|
|
if "ERROR" in err:
|
|
logging.error(err[err.find("ERROR"):].split(')',1)[0]+")")
|
|
spef_log.write(err[err.find("ERROR"):].split(')',1)[0]+")")
|
|
spef_log.close()
|
|
else:
|
|
logging.info(f"StarRC spef extraction done")
|
|
os.remove(f"{spef_log_dir}/{design}-error.log")
|
|
save_latest_run (lvs, drc, antenna, sta, spef, f"{signoff_dir}/{design}/StarRC/{timestr}")
|
|
spef = False
|
|
if not os.path.exists(f"{signoff_dir}/{design}/primetime"):
|
|
os.makedirs(f"{signoff_dir}/{design}/primetime")
|
|
if not os.path.exists(f"{signoff_dir}/{design}/primetime/{timestr}"):
|
|
os.makedirs(f"{signoff_dir}/{design}/primetime/{timestr}")
|
|
sta_log_dir = os.path.join(signoff_dir, f"{design}/primetime/{timestr}/logs")
|
|
if not os.path.exists(f"{sta_log_dir}"):
|
|
os.makedirs(f"{sta_log_dir}")
|
|
|
|
logging.info(f"Running PrimeTime STA all corners on {design}")
|
|
if (design == "mgmt_core_wrapper" or design == "RAM128" or design == "RAM256" or design == "gf180_ram_512x8_wrapper"):
|
|
sta_p = run_sta(
|
|
mcw_root,
|
|
f"{caravel_root}/scripts/pt_libs",
|
|
sta_log_dir,
|
|
signoff_dir,
|
|
design,
|
|
timestr,
|
|
upw
|
|
)
|
|
elif (design == "user_project_wrapper" or design == "user_proj_example" or design == "user_project" or design == "user_analog_project_wrapper"):
|
|
sta_p = run_sta(
|
|
uprj_root,
|
|
f"{caravel_root}/scripts/pt_libs",
|
|
sta_log_dir,
|
|
signoff_dir,
|
|
design,
|
|
timestr,
|
|
upw
|
|
)
|
|
else:
|
|
sta_p = run_sta(
|
|
caravel_root,
|
|
f"{caravel_root}/scripts/pt_libs",
|
|
sta_log_dir,
|
|
signoff_dir,
|
|
design,
|
|
timestr,
|
|
upw
|
|
)
|
|
elif spef:
|
|
out, err = spef_p.communicate()
|
|
spef_log = open(f"{spef_log_dir}/{design}-error.log", "w")
|
|
if err:
|
|
if "ERROR" in err:
|
|
logging.error(err[err.find("ERROR"):].split(')',1)[0]+")")
|
|
spef_log.write(err[err.find("ERROR"):].split(')',1)[0]+")")
|
|
spef_log.close()
|
|
else:
|
|
logging.info(f"StarRC spef extraction done")
|
|
os.remove(f"{spef_log_dir}/{design}-error.log")
|
|
save_latest_run (lvs, drc, antenna, sta, spef, f"{signoff_dir}/{design}/StarRC/{timestr}")
|
|
elif sta:
|
|
if not os.path.exists(f"{signoff_dir}/{design}/primetime"):
|
|
os.makedirs(f"{signoff_dir}/{design}/primetime")
|
|
if not os.path.exists(f"{signoff_dir}/{design}/primetime/{timestr}"):
|
|
os.makedirs(f"{signoff_dir}/{design}/primetime/{timestr}")
|
|
sta_log_dir = os.path.join(signoff_dir, f"{design}/primetime/{timestr}/logs")
|
|
if not os.path.exists(f"{sta_log_dir}"):
|
|
os.makedirs(f"{sta_log_dir}")
|
|
|
|
logging.info(f"Running PrimeTime STA all corners on {design}")
|
|
if (design == "mgmt_core_wrapper" or design == "RAM128" or design == "RAM256" or design == "gf180_ram_512x8_wrapper"):
|
|
sta_p = run_sta(
|
|
mcw_root,
|
|
f"{caravel_root}/scripts/pt_libs",
|
|
sta_log_dir,
|
|
signoff_dir,
|
|
design,
|
|
timestr,
|
|
upw
|
|
)
|
|
elif (design == "user_project_wrapper" or design == "user_proj_example" or design == "user_project" or design == "user_analog_project_wrapper"):
|
|
sta_p = run_sta(
|
|
uprj_root,
|
|
f"{caravel_root}/scripts/pt_libs",
|
|
sta_log_dir,
|
|
signoff_dir,
|
|
design,
|
|
timestr,
|
|
upw
|
|
)
|
|
else:
|
|
sta_p = run_sta(
|
|
caravel_root,
|
|
f"{caravel_root}/scripts/pt_libs",
|
|
sta_log_dir,
|
|
signoff_dir,
|
|
design,
|
|
timestr,
|
|
upw
|
|
)
|
|
|
|
if antenna:
|
|
logging.info(f"Running antenna checks on {design}")
|
|
if (design == "mgmt_core_wrapper" or design == "RAM128" or design == "RAM256"):
|
|
ant = run_antenna(mcw_root, timestr, signoff_dir, pdk_path, design)
|
|
else:
|
|
ant = run_antenna(caravel_root, timestr, signoff_dir, pdk_path, design)
|
|
|
|
if verification or iverilog:
|
|
verify_p = []
|
|
sim = []
|
|
if rtl:
|
|
sim.append("rtl")
|
|
if gl:
|
|
sim.append("gl")
|
|
if sdf:
|
|
sim.append("sdf")
|
|
if not rtl and not gl and not sdf:
|
|
sim = ["rtl", "gl", "sdf"]
|
|
if verification:
|
|
simulator = "vcs"
|
|
elif iverilog:
|
|
simulator = "iverilog"
|
|
for sim_type in sim:
|
|
logging.info(f"Running all {sim_type} verification on caravel")
|
|
verify_p.append(
|
|
run_verification(caravel_root, pdk_root, pdk_env, sim_type, simulator)
|
|
)
|
|
for i in range(len(verify_p)):
|
|
out, err = verify_p[i].communicate()
|
|
ver_log = open(f"{log_dir}/{sim[i]}_caravel.log", "w")
|
|
if err:
|
|
logging.error(err)
|
|
ver_log.write(err)
|
|
if out:
|
|
ver_log.write(out)
|
|
|
|
if sta:
|
|
out, err = sta_p.communicate()
|
|
sta_log = open(f"{sta_log_dir}/PT_STA_{design}.log", "w")
|
|
if err:
|
|
logging.error(err)
|
|
sta_log.write(err)
|
|
sta_log.close()
|
|
else:
|
|
os.remove(f"{sta_log_dir}/PT_STA_{design}.log")
|
|
save_latest_run (lvs, drc, antenna, sta, spef, f"{signoff_dir}/{design}/primetime/{timestr}")
|
|
|
|
if lvs:
|
|
lvs_p1.wait()
|
|
if drc:
|
|
drc_p1.wait()
|
|
if antenna:
|
|
ant.wait()
|
|
|
|
check_errors(
|
|
caravel_root, log_dir, signoff_dir, drc, lvs, verification, sta, design, antenna
|
|
)
|