feat: add DRC & LVS for ORFS (#72)

Co-authored-by: htfab <mpw@htamas.net>
This commit is contained in:
htfab
2024-10-14 15:04:43 +03:00
committed by GitHub
co-authored by htfab
parent 30dbb0cd1b
commit dcab9fc353
2 changed files with 136 additions and 1 deletions
+46
View File
@@ -0,0 +1,46 @@
diff --git a/ihp-sg13g2/libs.tech/klayout/tech/lvs/sg13g2_full.lylvs b/ihp-sg13g2/libs.tech/klayout/tech/lvs/sg13g2_full.lylvs
index 86c8955..8a9614d 100644
--- a/ihp-sg13g2/libs.tech/klayout/tech/lvs/sg13g2_full.lylvs
+++ b/ihp-sg13g2/libs.tech/klayout/tech/lvs/sg13g2_full.lylvs
@@ -4657,6 +4657,41 @@ schematic.purge_nets if PURGE_NETS
max_res(1e9)
min_caps(1e-18)
+# === EQUIVALENT STANDARD CELL PINS ===
+equivalent_pins("sg13g2_a21o_1", "A1", "A2")
+equivalent_pins("sg13g2_a21o_2", "A1", "A2")
+equivalent_pins("sg13g2_a21oi_1", "A1", "A2")
+equivalent_pins("sg13g2_a21oi_2", "A1", "A2")
+equivalent_pins("sg13g2_a221oi_1", "A1", "A2")
+equivalent_pins("sg13g2_a221oi_1", "B1", "B2")
+equivalent_pins("sg13g2_a22oi_1", "A1", "A2")
+equivalent_pins("sg13g2_a22oi_1", "B1", "B2")
+equivalent_pins("sg13g2_and2_1", "A", "B")
+equivalent_pins("sg13g2_and2_2", "A", "B")
+equivalent_pins("sg13g2_and3_1", "A", "B", "C")
+equivalent_pins("sg13g2_and3_2", "A", "B", "C")
+equivalent_pins("sg13g2_and4_1", "A", "B", "C", "D")
+equivalent_pins("sg13g2_and4_2", "A", "B", "C", "D")
+equivalent_pins("sg13g2_nand2_1", "A", "B")
+equivalent_pins("sg13g2_nand2_2", "A", "B")
+equivalent_pins("sg13g2_nand3_1", "A", "B", "C")
+equivalent_pins("sg13g2_nand4_1", "A", "B", "C", "D")
+equivalent_pins("sg13g2_nor2_1", "A", "B")
+equivalent_pins("sg13g2_nor2_2", "A", "B")
+equivalent_pins("sg13g2_nor3_1", "A", "B", "C")
+equivalent_pins("sg13g2_nor3_2", "A", "B", "C")
+equivalent_pins("sg13g2_nor4_1", "A", "B", "C", "D")
+equivalent_pins("sg13g2_nor4_2", "A", "B", "C", "D")
+equivalent_pins("sg13g2_o21ai_1", "A1", "A2")
+equivalent_pins("sg13g2_or2_1", "A", "B")
+equivalent_pins("sg13g2_or2_2", "A", "B")
+equivalent_pins("sg13g2_or3_1", "A", "B", "C")
+equivalent_pins("sg13g2_or3_2", "A", "B", "C")
+equivalent_pins("sg13g2_or4_1", "A", "B", "C", "D")
+equivalent_pins("sg13g2_or4_2", "A", "B", "C", "D")
+equivalent_pins("sg13g2_xnor2_1", "A", "B")
+equivalent_pins("sg13g2_xor2_1", "A", "B")
+
# === COMPARISON ===
logger.info('Starting SG13G2 LVS Comparison')
compare
+90 -1
View File
@@ -562,7 +562,11 @@ class Project:
if self.args.orfs: if self.args.orfs:
shutil.rmtree("runs/wokwi", ignore_errors=True) shutil.rmtree("runs/wokwi", ignore_errors=True)
os.makedirs("runs/wokwi", exist_ok=True) os.makedirs("runs/wokwi", exist_ok=True)
harden_cmd = f"make -B -C $ORFS_ROOT/flow all generate_abstract" cdl = os.path.join(
self.local_dir,
"runs/wokwi/objects/ihp-sg13g2/tt-submission/base/6_final_concat.cdl",
)
harden_cmd = f"make -B -C $ORFS_ROOT/flow all generate_abstract {cdl}"
env = os.environ.copy() env = os.environ.copy()
if "ORFS_ROOT" not in env: if "ORFS_ROOT" not in env:
env["ORFS_ROOT"] = os.path.join(self.local_dir, "OpenROAD-flow-scripts") env["ORFS_ROOT"] = os.path.join(self.local_dir, "OpenROAD-flow-scripts")
@@ -602,6 +606,11 @@ class Project:
logging.error("harden failed") logging.error("harden failed")
exit(1) exit(1)
# DRC & LVS aren't included in the default ORFS flow
if self.args.orfs:
self.run_drc()
self.run_lvs()
# Write commit information # Write commit information
if self.args.orfs: if self.args.orfs:
commit_id_json_path = ( commit_id_json_path = (
@@ -685,6 +694,86 @@ class Project:
os.chdir(cwd) os.chdir(cwd)
def run_drc(self):
if self.args.orfs:
gds_path = os.path.join(
self.local_dir,
"runs/wokwi/results/ihp-sg13g2/tt-submission/base/6_final.gds",
)
drc_script = os.path.join(
os.environ["IHP_PDK_ROOT"],
"ihp-sg13g2/libs.tech/klayout/tech/drc/sg13g2_maximal.lydrc",
)
drc_report = os.path.join(
self.local_dir,
"runs/wokwi/reports/ihp-sg13g2/tt-submission/base/6_drc.lyrdb",
)
drc_log = os.path.join(
self.local_dir,
"runs/wokwi/logs/ihp-sg13g2/tt-submission/base/6_drc.log",
)
drc_cmd = f"klayout -b -rd in_gds={gds_path} -rd report_file={drc_report} -rd density=false -r {drc_script} | tee {drc_log}"
p = subprocess.run(drc_cmd, shell=True)
if p.returncode != 0:
logging.error("DRC job exited abnormally")
exit(1)
with open(drc_report) as f:
drc_ok = True
for line in f:
line = line.strip()
if m := re.match("<category>'([^']*)'</category>", line):
if m[1] != "Pin.f.M5":
drc_ok = False
break
if drc_ok:
logging.info("DRC passed")
else:
logging.error("DRC failed")
exit(1)
else:
logging.warning(
"DRC is already included in OpenLane hardening job, skipping"
)
def run_lvs(self):
if self.args.orfs:
gds_path = os.path.join(
self.local_dir,
"runs/wokwi/results/ihp-sg13g2/tt-submission/base/6_final.gds",
)
cdl_path = os.path.join(
self.local_dir,
"runs/wokwi/objects/ihp-sg13g2/tt-submission/base/6_final_concat.cdl",
)
lvs_script = os.path.join(
os.environ["IHP_PDK_ROOT"],
"ihp-sg13g2/libs.tech/klayout/tech/lvs/sg13g2_full.lylvs",
)
lvs_report = os.path.join(
self.local_dir,
"runs/wokwi/reports/ihp-sg13g2/tt-submission/base/6_lvs.lvsdb",
)
lvs_log = os.path.join(
self.local_dir,
"runs/wokwi/logs/ihp-sg13g2/tt-submission/base/6_lvs.log",
)
lvs_cmd = f"klayout -b -rd in_gds={gds_path} -rd cdl_file={cdl_path} -rd report_file={lvs_report} -rd run_mode=deep -r {lvs_script} | tee {lvs_log}"
p = subprocess.run(lvs_cmd, shell=True)
if p.returncode != 0:
logging.error("LVS job exited abnormally")
exit(1)
with open(lvs_log) as f:
ok_msg = "Congratulations! Netlists match."
if any(ok_msg in line for line in f):
logging.info("LVS passed")
else:
logging.error("LVS failed")
exit(1)
else:
logging.warning(
"LVS is already included in OpenLane hardening job, skipping"
)
def create_fpga_bitstream(self): def create_fpga_bitstream(self):
logging.info(f"Creating FPGA bitstream for {self}") logging.info(f"Creating FPGA bitstream for {self}")