diff --git a/chipcompiler/data/pdk.py b/chipcompiler/data/pdk.py index 64a6bda2..788c4800 100644 --- a/chipcompiler/data/pdk.py +++ b/chipcompiler/data/pdk.py @@ -34,6 +34,8 @@ class PDK: tie_low_cell : str = "" tie_low_port : str = "" dont_use : list = field(default_factory=list) # don't use cell list + abc_driver_cell : str = "" # ABC driving cell + abc_load : float = 0.015 # ABC output load def validate(self) -> None: """Check that critical PDK paths exist. Raises ValueError if not.""" @@ -158,6 +160,8 @@ def PDK_ICS55(pdk_root: str = "") -> PDK: tie_high_port = "Z", tie_low_cell = "TIELOH7R", tie_low_port = "Z", + abc_driver_cell = "BUFX0P5H7R", + abc_load = 0.015, dont_use=[ "DFFSRQX*", "DFFSRX*", diff --git a/chipcompiler/tools/yosys/builder.py b/chipcompiler/tools/yosys/builder.py index 1e278b03..7b094024 100644 --- a/chipcompiler/tools/yosys/builder.py +++ b/chipcompiler/tools/yosys/builder.py @@ -22,6 +22,21 @@ def _abspath(path: str) -> str: return os.path.abspath(path) +def _split_stdcell_macro_libs(lib_files: list[str]) -> tuple[list[str], list[str]]: + """Split known ICS55 stdcell libraries from macro libraries.""" + stdcell_libs = [] + macro_libs = [] + + for lib in lib_files: + name = os.path.basename(lib) + if name.startswith("ICS55_"): + macro_libs.append(lib) + else: + stdcell_libs.append(lib) + + return stdcell_libs, macro_libs + + def generate_global_var_tcl(workspace: Workspace, step: WorkspaceStep) -> str: """Generate global_var.tcl content dynamically from workspace configuration.""" @@ -66,11 +81,12 @@ def generate_global_var_tcl(workspace: Workspace, tie_low_port = pdk.tie_low_port if pdk.tie_low_port else "" tie_high_cell = pdk.tie_high_cell if pdk.tie_high_cell else "" tie_high_port = pdk.tie_high_port if pdk.tie_high_port else "" + abc_driver_cell = pdk.abc_driver_cell if pdk.abc_driver_cell else "BUFX4H7L" + abc_load = pdk.abc_load if pdk.abc_load else 0.015 lib_files = workspace.pdk.libs if workspace.pdk.libs else [] - lib_files_all = " ".join(lib_files) if lib_files else "" - - lib_stdcell = lib_files.copy() #TODO: Distinguish between stdcell and other libraries? + lib_stdcell, lib_macro = _split_stdcell_macro_libs(lib_files) + lib_files_all = " ".join(lib_stdcell + lib_macro) if lib_files else "" lib_stdcell_all = " ".join(lib_stdcell) if lib_stdcell else "" filelist = workspace.design.input_filelist if workspace.design.input_filelist else workspace.parameters.data.get("File list", "") @@ -112,6 +128,8 @@ def generate_global_var_tcl(workspace: Workspace, set tie_low_port {_tcl_quote(tie_low_port) if tie_low_port else '""'} set tie_high_cell {_tcl_quote(tie_high_cell) if tie_high_cell else '""'} set tie_high_port {_tcl_quote(tie_high_port) if tie_high_port else '""'} +set abc_driver_cell {_tcl_quote(abc_driver_cell)} +set abc_load {abc_load} # Library files set lib_stdcell_list [split {_tcl_quote(lib_stdcell_all) if lib_stdcell_all else '""'}] @@ -172,6 +190,7 @@ def build_step(workspace: Workspace, "dir": f"{step.directory}/output", "def": output_def, "verilog": output_verilog, + "fixed_verilog": f"{step.directory}/output/{workspace.design.name}_{step.name}_fixed.v", "json": f"{step.directory}/output/{workspace.design.name}_{step.name}.json", "report": f"{step.directory}/output/{workspace.design.name}_{step.name}.rpt", "image": f"{step.directory}/output/{workspace.design.name}_{step.name}.png" diff --git a/chipcompiler/tools/yosys/runner.py b/chipcompiler/tools/yosys/runner.py index 7ecd2461..6311c1d4 100644 --- a/chipcompiler/tools/yosys/runner.py +++ b/chipcompiler/tools/yosys/runner.py @@ -9,6 +9,52 @@ from chipcompiler.tools.yosys.utility import check_slang_plugin, get_yosys_runtime +def _remove_parameter_overrides(text: str) -> str: + """Remove Verilog parameter override blocks of the form #( ... ).""" + out = [] + i = 0 + length = len(text) + + while i < length: + if text[i] == "#" and i + 1 < length and text[i + 1] == "(": + depth = 0 + j = i + 1 + while j < length: + if text[j] == "(": + depth += 1 + elif text[j] == ")": + depth -= 1 + if depth == 0: + j += 1 + break + j += 1 + + if depth == 0: + i = j + continue + + out.append(text[i]) + i += 1 + + return "".join(out) + + +def _write_fixed_netlist(src_path: str, dst_path: str) -> bool: + """Write an extra netlist with parameter override blocks removed.""" + if not src_path or not dst_path or not os.path.exists(src_path): + return False + + with open(src_path, "r", encoding="utf-8", errors="ignore") as src: + text = src.read() + + fixed = _remove_parameter_overrides(text) + + with open(dst_path, "w", encoding="utf-8") as dst: + dst.write(fixed) + + return True + + def run_step(workspace: Workspace, step: WorkspaceStep, ecc_module=None) -> bool: @@ -77,6 +123,10 @@ def run_step(workspace: Workspace, if os.path.exists(step.output["verilog"]): sub_flow.update_step(step_name="run yosys", state=StateEnum.Success) + + fixed_netlist = step.output.get("fixed_verilog", "") + if fixed_netlist: + _write_fixed_netlist(step.output["verilog"], fixed_netlist) build_step_metrics(workspace=workspace, step=step) diff --git a/chipcompiler/tools/yosys/scripts/abc-opt.script b/chipcompiler/tools/yosys/scripts/abc-opt.script index 12d8aaf0..76317190 100644 --- a/chipcompiler/tools/yosys/scripts/abc-opt.script +++ b/chipcompiler/tools/yosys/scripts/abc-opt.script @@ -59,7 +59,7 @@ topo stime echo "buffering for delay and fanout..." -buffer -p +buffer -c -N 32 echo "resizing cells..." upsize {D} dnsize {D} diff --git a/chipcompiler/tools/yosys/scripts/yosys_synthesis.tcl b/chipcompiler/tools/yosys/scripts/yosys_synthesis.tcl index feab4834..8ddbeb92 100644 --- a/chipcompiler/tools/yosys/scripts/yosys_synthesis.tcl +++ b/chipcompiler/tools/yosys/scripts/yosys_synthesis.tcl @@ -53,15 +53,19 @@ if {[info exists filelist] && $filelist ne ""} { puts "Reading SystemVerilog sources from filelist: $filelist" yosys read_slang -F $filelist --top $top_design \ --compat-mode --keep-hierarchy \ - --allow-use-before-declare --ignore-unknown-modules \ - --ignore-timing --ignore-initial + +define+SYNTHESIS \ + --allow-use-before-declare \ + --ignore-timing \ + -Wduplicate-definition } else { # Fall back to individual Verilog files puts "Reading Verilog sources from rtl files: $rtl_file" yosys read_slang {*}$rtl_file --top $top_design \ --compat-mode --keep-hierarchy \ - --allow-use-before-declare --ignore-unknown-modules \ - --ignore-timing --ignore-initial + +define+SYNTHESIS \ + --allow-use-before-declare \ + --ignore-timing \ + -Wduplicate-definition } # preserve hierarchy of selected modules/instances @@ -117,17 +121,17 @@ if {$keep_hierarchy == "false"} { # ----------------------------------------------------------------------------- # Preserve flip-flop names as far as possible # split internal nets +yosys splitnets -driver yosys splitnets -format __v # rename DFFs from the driven signal -yosys rename -wire -suffix _reg_p t:*DFF*_P* -yosys rename -wire -suffix _reg_n t:*DFF*_N* +yosys rename -wire -suffix _reg t:*DFF* # rename all other cells +yosys select -write ${timing_cell_stat_rpt} t:*DFF* yosys autoname t:*DFF* %n yosys clean -purge yosys select -write ${timing_cell_stat_rpt} t:*DFF* -yosys tee -q -o ${timing_cell_count_rpt} select -count t:*DFF*_P* -yosys tee -q -a ${timing_cell_count_rpt} select -count t:*DFF*_N* +yosys tee -q -o ${timing_cell_count_rpt} select -count t:*DFF* yosys tee -q -a ${timing_cell_count_rpt} select -count */t:*_DLATCH*_ */t:*_SR*_ # yosys tee -q -o "${generic_stat_json}" stat -json -tech cmos @@ -158,9 +162,8 @@ set abc_comb_script [processAbcScript abc-opt.script] # Generate abc.constr file dynamically set abc_constr_path "${tmp_dir}/abc.constr" set abc_constr_file [open $abc_constr_path w] -set driver_cell {BUFX4H7L} -puts $abc_constr_file "set_driving_cell ${driver_cell}" -puts $abc_constr_file "set_load 0.015" +puts $abc_constr_file "set_driving_cell ${abc_driver_cell}" +puts $abc_constr_file "set_load ${abc_load}" close $abc_constr_file # call ABC @@ -172,15 +175,14 @@ yosys clean -purge # prep for openROAD # yosys write_verilog -norename -noexpr -attr2comment ${tmp_dir}/${top_design}_yosys_debug.v -# yosys splitnets -driver -yosys splitnets -ports +yosys splitnets -ports -format __v yosys setundef -zero yosys clean -purge # map constants to tie cells yosys hilomap -singleton -hicell {*}$tech_cell_tiehi -locell {*}$tech_cell_tielo # final reports -yosys tee -q -o "${synth_stat_json}" stat -json {*}$liberty_args +yosys tee -q -o "${synth_stat_json}" stat -json -top $top_design {*}$liberty_args # yosys tee -q -o "${synth_stat_json}.rpt" stat {*}$liberty_args yosys tee -q -o "${synth_check_rpt}" check