fix(configure): fails due to missing args.pdk

slightly refactor project.py to make the code more extensible to future PDK support
This commit is contained in:
Uri Shaked
2025-09-02 17:42:28 +03:00
parent 9519fa87fd
commit ef2b0de84b
3 changed files with 25 additions and 28 deletions
+1 -1
View File
@@ -66,7 +66,7 @@ class Projects:
index, index,
commit_id_data["repo"], commit_id_data["repo"],
project_dir, project_dir,
args, pdk=config["pdk"],
is_user_project=False, is_user_project=False,
) )
project.commit_id = commit_id_data["commit"] project.commit_id = commit_id_data["commit"]
+18 -25
View File
@@ -64,13 +64,6 @@ PINOUT_KEYS = [
SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
class Args:
openlane2: bool
ihp: bool
print_cell_summary: bool
print_cell_category: bool
class Project: class Project:
top_verilog_filename: str top_verilog_filename: str
mux_address: int mux_address: int
@@ -83,11 +76,11 @@ class Project:
index: int, index: int,
git_url: str, git_url: str,
local_dir: str, local_dir: str,
args: Args, pdk: str,
is_user_project: bool, is_user_project: bool,
): ):
self.git_url = git_url self.git_url = git_url
self.args = args self.ihp = pdk == "ihp-sg13g2"
self.index = index self.index = index
self.local_dir = os.path.realpath(local_dir) self.local_dir = os.path.realpath(local_dir)
self.is_user_project = is_user_project self.is_user_project = is_user_project
@@ -364,7 +357,7 @@ class Project:
return os.path.join(self.local_dir, f"{self.info.top_module}.v") return os.path.join(self.local_dir, f"{self.info.top_module}.v")
def get_tile_sizes(self): def get_tile_sizes(self):
if self.args.ihp: if self.ihp:
tile_sizes_yaml = "ihp/tile_sizes.yaml" tile_sizes_yaml = "ihp/tile_sizes.yaml"
else: else:
tile_sizes_yaml = "tile_sizes.yaml" tile_sizes_yaml = "tile_sizes.yaml"
@@ -494,7 +487,7 @@ class Project:
tiles = self.info.tiles tiles = self.info.tiles
tile_sizes = self.get_tile_sizes() tile_sizes = self.get_tile_sizes()
die_area = tile_sizes[tiles] die_area = tile_sizes[tiles]
if self.args.ihp: if self.ihp:
def_template = f"dir::../tt/ihp/def/tt_block_{tiles}_pgvdd.def" def_template = f"dir::../tt/ihp/def/tt_block_{tiles}_pgvdd.def"
else: else:
def_template = f"dir::../tt/def/tt_block_{tiles}_pg.def" def_template = f"dir::../tt/def/tt_block_{tiles}_pg.def"
@@ -529,7 +522,7 @@ class Project:
os.makedirs("runs/wokwi", exist_ok=True) os.makedirs("runs/wokwi", exist_ok=True)
arg_progress = "--hide-progress-bar" if "CI" in os.environ else "" arg_progress = "--hide-progress-bar" if "CI" in os.environ else ""
arg_pdk_root = '--pdk-root "$PDK_ROOT"' if "PDK_ROOT" in os.environ else "" arg_pdk_root = '--pdk-root "$PDK_ROOT"' if "PDK_ROOT" in os.environ else ""
arg_pdk = "--manual-pdk --pdk ihp-sg13g2" if self.args.ihp else "" arg_pdk = "--manual-pdk --pdk ihp-sg13g2" if self.ihp else ""
harden_cmd = f"python -m openlane {arg_pdk_root} --docker-no-tty --dockerized {arg_pdk_root} {arg_pdk} --run-tag wokwi --force-run-dir runs/wokwi {arg_progress} src/config_merged.json" harden_cmd = f"python -m openlane {arg_pdk_root} --docker-no-tty --dockerized {arg_pdk_root} {arg_pdk} --run-tag wokwi --force-run-dir runs/wokwi {arg_progress} src/config_merged.json"
env = os.environ.copy() env = os.environ.copy()
logging.debug(harden_cmd) logging.debug(harden_cmd)
@@ -556,7 +549,7 @@ class Project:
resolved_json_path = "runs/wokwi/resolved.json" resolved_json_path = "runs/wokwi/resolved.json"
config = json.load(open(os.path.join(self.local_dir, resolved_json_path))) config = json.load(open(os.path.join(self.local_dir, resolved_json_path)))
openlane_version = config["meta"]["openlane_version"] openlane_version = config["meta"]["openlane_version"]
if self.args.ihp: if self.ihp:
pdk_repo = Repo(env["PDK_ROOT"]) pdk_repo = Repo(env["PDK_ROOT"])
pdk_repo_name = list(pdk_repo.remotes[0].urls)[0].split("/")[-1] pdk_repo_name = list(pdk_repo.remotes[0].urls)[0].split("/")[-1]
pdk_commit = pdk_repo.commit().hexsha pdk_commit = pdk_repo.commit().hexsha
@@ -570,7 +563,7 @@ class Project:
f"OpenLane2 {openlane_version}\n" f"OpenLane2 {openlane_version}\n"
) )
open("runs/wokwi/PDK_SOURCES", "w").write(pdk_sources) open("runs/wokwi/PDK_SOURCES", "w").write(pdk_sources)
if not self.args.ihp: if not self.ihp:
volare.enable( volare.enable(
volare.get_volare_home(), # uses PDK_ROOT if set, ~/.volare otherwise volare.get_volare_home(), # uses PDK_ROOT if set, ~/.volare otherwise
{"sky130A": "sky130"}[config["PDK"]], {"sky130A": "sky130"}[config["PDK"]],
@@ -757,7 +750,7 @@ class Project:
(67, 25), # 67/25 - Metal5.text (67, 25), # 67/25 - Metal5.text
(126, 25), # 126/25 - TopMetal1.text (126, 25), # 126/25 - TopMetal1.text
] ]
if self.args.ihp: if self.ihp:
label_layers = ihp_label_layers label_layers = ihp_label_layers
else: else:
label_layers = sky130_label_layers label_layers = sky130_label_layers
@@ -812,7 +805,7 @@ class Project:
(51, 0), # 51/0 - HeatTrans.drawing (51, 0), # 51/0 - HeatTrans.drawing
(189, 4), # 189/4 - prBoundary.boundary (189, 4), # 189/4 - prBoundary.boundary
] ]
if self.args.ihp: if self.ihp:
buried_layers = ihp_buried_layers buried_layers = ihp_buried_layers
else: else:
buried_layers = sky130_buried_layers buried_layers = sky130_buried_layers
@@ -884,7 +877,7 @@ class Project:
if "WIDTHLABEL" not in line: if "WIDTHLABEL" not in line:
warnings.append(line.strip()) warnings.append(line.strip())
if self.args.ihp: if self.ihp:
tt_corner = "nom_typ_1p20V_25C" tt_corner = "nom_typ_1p20V_25C"
else: else:
tt_corner = "nom_tt_025C_1v80" tt_corner = "nom_tt_025C_1v80"
@@ -920,33 +913,33 @@ class Project:
print("| {} | {} |".format(util, wire_length)) print("| {} | {} |".format(util, wire_length))
# Print the summaries # Print the summaries
def summarize(self): def summarize(self, print_cell_category: bool, print_cell_summary: bool):
cell_count = self.get_cell_counts_from_gl() cell_count = self.get_cell_counts_from_gl()
Categories = typing.TypedDict( Categories = typing.TypedDict(
"Categories", {"categories": typing.List[str], "map": typing.Dict[str, int]} "Categories", {"categories": typing.List[str], "map": typing.Dict[str, int]}
) )
if self.args.ihp: if self.ihp:
categories_file = "ihp/categories.json" categories_file = "ihp/categories.json"
else: else:
categories_file = "categories.json" categories_file = "categories.json"
with open(os.path.join(SCRIPT_DIR, categories_file)) as fh: with open(os.path.join(SCRIPT_DIR, categories_file)) as fh:
categories: Categories = json.load(fh) categories: Categories = json.load(fh)
if self.args.ihp: if self.ihp:
ihp_defs = load_ihp_cells() ihp_defs = load_ihp_cells()
else: else:
sky130_defs = load_sky130_cells() sky130_defs = load_sky130_cells()
def _cell_url(name): def _cell_url(name):
if self.args.ihp: if self.ihp:
return _ihp_cell_url(ihp_defs[name]["doc_ref"]) return _ihp_cell_url(ihp_defs[name]["doc_ref"])
else: else:
return _sky130_cell_url(name) return _sky130_cell_url(name)
# print all used cells, sorted by frequency # print all used cells, sorted by frequency
total = 0 total = 0
if self.args.print_cell_summary: if print_cell_summary:
print("# Cell usage") print("# Cell usage")
print() print()
print("| Cell Name | Description | Count |") print("| Cell Name | Description | Count |")
@@ -957,7 +950,7 @@ class Project:
if count > 0: if count > 0:
total += count total += count
cell_link = _cell_url(name) cell_link = _cell_url(name)
if self.args.ihp: if self.ihp:
description = ihp_defs[name]["description"] description = ihp_defs[name]["description"]
else: else:
description = sky130_defs[name]["description"] description = sky130_defs[name]["description"]
@@ -965,7 +958,7 @@ class Project:
print(f"| | Total | {total} |") print(f"| | Total | {total} |")
if self.args.print_cell_category: if print_cell_category:
CategoryInfo = typing.TypedDict( CategoryInfo = typing.TypedDict(
"CategoryInfo", {"count": int, "examples": typing.List[str]} "CategoryInfo", {"count": int, "examples": typing.List[str]}
) )
@@ -1020,7 +1013,7 @@ class Project:
def get_cell_counts_from_gl(self): def get_cell_counts_from_gl(self):
cell_count: typing.Dict[str, int] = {} cell_count: typing.Dict[str, int] = {}
total = 0 total = 0
if self.args.ihp: if self.ihp:
cell_re = r"sg13g2_(?P<cell_name>\S+)_(?P<cell_drive>\d+)" cell_re = r"sg13g2_(?P<cell_name>\S+)_(?P<cell_drive>\d+)"
else: else:
cell_re = ( cell_re = (
+6 -2
View File
@@ -147,7 +147,8 @@ if __name__ == "__main__":
ch.setFormatter(log_format) ch.setFormatter(log_format)
log.addHandler(ch) log.addHandler(ch)
project = Project(0, "unknown", args.project_dir, args, is_user_project=True) pdk = "ihp-sg13g2" if args.ihp else "sky130A"
project = Project(0, "unknown", args.project_dir, pdk, is_user_project=True)
project.post_clone_setup() project.post_clone_setup()
# handle the options # handle the options
@@ -155,7 +156,10 @@ if __name__ == "__main__":
project.check_docs() project.check_docs()
if args.print_cell_summary or args.print_cell_category: if args.print_cell_summary or args.print_cell_category:
project.summarize() project.summarize(
print_cell_category=args.print_cell_category,
print_cell_summary=args.print_cell_summary,
)
if args.print_stats: if args.print_stats:
project.print_stats() project.print_stats()