From fa02faa76e5feefc5d71903b2ad63295904f516e Mon Sep 17 00:00:00 2001 From: Mohamed Gaber Date: Sun, 27 Oct 2024 20:03:17 +0300 Subject: [PATCH 01/14] more synthesis options (wip) --- openlane/scripts/pyosys/synthesize.py | 25 ++++++++++++++++++++----- openlane/steps/pyosys.py | 12 ++++++++++++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/openlane/scripts/pyosys/synthesize.py b/openlane/scripts/pyosys/synthesize.py index 39308d67f..6bc8a114d 100644 --- a/openlane/scripts/pyosys/synthesize.py +++ b/openlane/scripts/pyosys/synthesize.py @@ -86,11 +86,15 @@ def openlane_synth(d, top, flatten, report_dir, *, booth=False, abc_dff=False): d.run_pass("opt_clean") # Clean up after memory analysis # Perform more aggressive optimization with faster runtime - d.run_pass("opt", "-fast", "-full") # Fast and comprehensive optimization + d.run_pass( + "opt", "-fast", "-mux_undef", "-mux_bool", "-fine" + ) # Fast and comprehensive optimization # Technology mapping d.run_pass("memory_map") # Map memories to standard cells - d.run_pass("opt", "-full") # More optimization after memory mapping + d.run_pass( + "opt", "-mux_undef", "-mux_bool", "-fine" + ) # More optimization after memory mapping d.run_pass("techmap") # Map logic to standard cells from the technology library d.run_pass("opt", "-fast") # Fast optimization after technology mapping d.run_pass("opt", "-fast") # More fast optimization @@ -203,10 +207,14 @@ def synthesize( d.tee("stat", "-json", *lib_arguments, o=os.path.join(report_dir, "stat.json")) d.tee("stat", *lib_arguments, o=os.path.join(report_dir, "stat.rpt")) + noattr_flag = [] + if config["SYNTH_WRITE_NOATTR"]: + noattr_flag.append("-noattr") + d.run_pass( "write_verilog", "-noattr", - "-noexpr", + *noattr_flag, "-nohex", "-nodec", "-defparam", @@ -305,7 +313,10 @@ def run_strategy(d): *(["-dff"] if config["SYNTH_ABC_DFF"] else []), ) - d.run_pass("setundef", "-zero") + if value := config.get("SYNTH_SET_UNDEFINED"): + flag = "zero" if value == "low" else "high" + d.run_pass("setundef", flag) + d.run_pass( "hilomap", "-hicell", @@ -336,9 +347,13 @@ def run_strategy(d): # sc_mcu7t5v0__and3_1_A3_Z_gf180mcu_fd_sc_mcu7t5v0__buf_1_I_Z d.run_pass("autoname") + noattr_flag = [] + if config["SYNTH_WRITE_NOATTR"]: + noattr_flag.append("-noattr") + d.run_pass( "write_verilog", - "-noattr", + *noattr_flag, "-noexpr", "-nohex", "-nodec", diff --git a/openlane/steps/pyosys.py b/openlane/steps/pyosys.py index 5b2935358..7690c8687 100644 --- a/openlane/steps/pyosys.py +++ b/openlane/steps/pyosys.py @@ -491,6 +491,18 @@ class SynthesisCommon(VerilogStep): "Runs the booth pass as part of synthesis: See https://yosyshq.readthedocs.io/projects/yosys/en/latest/cmd/booth.html", default=False, ), + Variable( + "SYNTH_TIE_UNDEFINED", + Optional[Literal["high", "low"]], + "Whether to tie undefined values low or high. Explicitly provide null if you wish to simply leave them undriven.", + default="high", + ), + Variable( + "SYNTH_WRITE_NOATTR", + bool, + "If true, Verilog-2001 attributes are omitted from output netlists. Some utilities do not support attributes.", + default=True, + ), # Variable( # "SYNTH_SDC_FILE", # Optional[Path], From acb8e2b9d012f25470ecf0732ac77f24e048b3fc Mon Sep 17 00:00:00 2001 From: Mohamed Gaber Date: Mon, 28 Oct 2024 11:34:56 +0300 Subject: [PATCH 02/14] extra env --- nix/create-shell.nix | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/nix/create-shell.nix b/nix/create-shell.nix index 57f5fc49e..f3549551f 100644 --- a/nix/create-shell.nix +++ b/nix/create-shell.nix @@ -14,8 +14,9 @@ { extra-packages ? [], extra-python-packages ? [], + extra-env ? [], openlane-plugins ? [], - include-openlane ? true + include-openlane ? true, }: ({ lib, git, @@ -62,7 +63,7 @@ in name = "NIX_PYTHONPATH"; value = "${openlane-env-sitepackages}"; } - ]; + ] ++ extra-env; devshell.interactive.PS1 = { text = ''PS1="${prompt}"''; }; From 04ea84a014ab394792fe000ceed8ad979fc408f0 Mon Sep 17 00:00:00 2001 From: Mohamed Gaber Date: Wed, 6 Nov 2024 14:18:13 +0200 Subject: [PATCH 03/14] fix synth elab only bug --- openlane/scripts/pyosys/synthesize.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openlane/scripts/pyosys/synthesize.py b/openlane/scripts/pyosys/synthesize.py index 6bc8a114d..ee4a0bcc3 100644 --- a/openlane/scripts/pyosys/synthesize.py +++ b/openlane/scripts/pyosys/synthesize.py @@ -213,7 +213,6 @@ def synthesize( d.run_pass( "write_verilog", - "-noattr", *noattr_flag, "-nohex", "-nodec", From 05312812be6c7b67fdc8e3244efeac352b957e9a Mon Sep 17 00:00:00 2001 From: Mohamed Gaber Date: Thu, 7 Nov 2024 12:02:17 +0200 Subject: [PATCH 04/14] update nix-eda, ioplace parser --- flake.lock | 23 +++++++++++------------ flake.nix | 2 +- pyproject.toml | 2 +- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/flake.lock b/flake.lock index a7eaab0ff..700f92bbb 100644 --- a/flake.lock +++ b/flake.lock @@ -37,17 +37,16 @@ }, "ioplace-parser": { "inputs": { - "nixpkgs": [ - "nix-eda", - "nixpkgs" + "nix-eda": [ + "nix-eda" ] }, "locked": { - "lastModified": 1719837045, - "narHash": "sha256-ya2KEXKAIn8oYUi9G9TaUcQAEfGkbENCgXF/V0d/kws=", + "lastModified": 1730973673, + "narHash": "sha256-F7jux5RLKTFEcXEQ2mRIH83zlSAT+uffYsf/XnKgoiU=", "owner": "efabless", "repo": "ioplace_parser", - "rev": "570fd3e352926f57e6eecbb8bd3892a5dec375b7", + "rev": "e31eb8553caba31c08416d89e31b6aec58002755", "type": "github" }, "original": { @@ -82,11 +81,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1728905391, - "narHash": "sha256-iox9yGNG4MwSKhQuwegLcDW6wVGzfdBPrh8SrhSLA8c=", + "lastModified": 1730973643, + "narHash": "sha256-8ZeUxluUbUD3IF0thq4Alioy3JaEVR0AY5+7PuFypBE=", "owner": "efabless", "repo": "nix-eda", - "rev": "0814aa6c1c7d556aa08212cc875063cff62cb9b0", + "rev": "1f8771758e26ad96da4947ed1b17e3942f978cfa", "type": "github" }, "original": { @@ -129,11 +128,11 @@ ] }, "locked": { - "lastModified": 1724178650, - "narHash": "sha256-p+Li/z3l7ShRSIKUrxVK+7uGhSvqPE7jOW4FA4k3SIw=", + "lastModified": 1728904439, + "narHash": "sha256-e6QXMol9kbrJplYamSDfz+X/BDhgP66rHmjkeIZlaNI=", "owner": "efabless", "repo": "volare", - "rev": "0090420799258d29adca54c8951d38bb8b605aeb", + "rev": "7458169adc63dfac4ecfcb1c967972c6d8cd888f", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 67dfd2d9a..a4f2c7584 100644 --- a/flake.nix +++ b/flake.nix @@ -33,7 +33,7 @@ }; inputs.libparse.inputs.nixpkgs.follows = "nix-eda/nixpkgs"; - inputs.ioplace-parser.inputs.nixpkgs.follows = "nix-eda/nixpkgs"; + inputs.ioplace-parser.inputs.nix-eda.follows = "nix-eda"; inputs.volare.inputs.nixpkgs.follows = "nix-eda/nixpkgs"; inputs.devshell.inputs.nixpkgs.follows = "nix-eda/nixpkgs"; diff --git a/pyproject.toml b/pyproject.toml index 17f1b7128..2ab150e05 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,7 +24,7 @@ psutil = ">=5.9.0" httpx = ">=0.22.0,<0.28" klayout = ">=0.29.0,<0.30.0" rapidfuzz = ">=3.9.0,<4" -ioplace-parser = "0.3.0" +ioplace-parser = ">=0.3.0,<0.5.0" yamlcore = "^0.0.2" From e294b241f8a9c35b99853b32d7c78e3cd8bc3a0d Mon Sep 17 00:00:00 2001 From: Mohamed Gaber Date: Tue, 19 Nov 2024 22:25:19 +0200 Subject: [PATCH 05/14] add --initial-state-element-override/-e option --- openlane/__main__.py | 52 +++++++++++++++++++++++++++++-------------- openlane/flows/cli.py | 12 +++++++++- 2 files changed, 46 insertions(+), 18 deletions(-) diff --git a/openlane/__main__.py b/openlane/__main__.py index 86780f0e5..a1dcef55b 100644 --- a/openlane/__main__.py +++ b/openlane/__main__.py @@ -23,12 +23,7 @@ from functools import partial from typing import Any, Dict, Sequence, Tuple, Type, Optional, List, Union -from click import ( - Parameter, - Context, - Path, - pass_context, -) +import click from cloup import ( option, option_group, @@ -40,7 +35,7 @@ from .__version__ import __version__ -from .state import State +from .state import State, DesignFormat from .logging import ( debug, err, @@ -56,7 +51,7 @@ def run( - ctx: Context, + ctx: click.Context, flow_name: Optional[str], pdk_root: Optional[str], pdk: str, @@ -73,6 +68,7 @@ def run( config_override_strings: List[str], _force_run_dir: Optional[str], design_dir: Optional[str], + initial_state_element_override: Sequence[str], view_save_path: Optional[str] = None, ef_view_save_path: Optional[str] = None, ): @@ -97,6 +93,27 @@ def run( if flow_description is None: flow_description = "Classic" + if len(initial_state_element_override): + if with_initial_state is None: + with_initial_state = State() + overrides = {} + for element in initial_state_element_override: + element_split = element.split("=", maxsplit=1) + if len(element_split) < 2: + err(f"Invalid initial state element override: '{element}'.") + ctx.exit(1) + df_id, path = element_split + design_format = DesignFormat.by_id(df_id) + if design_format is None: + err(f"Invalid design format ID: '{df_id}'.") + ctx.exit(1) + overrides[design_format] = common.Path(path) + + with_initial_state = with_initial_state.__class__( + with_initial_state, + overrides=overrides, + ) + TargetFlow: Type[Flow] if isinstance(flow_description, str): @@ -170,7 +187,7 @@ def run( flow._save_snapshot_ef(evsp) -def print_version(ctx: Context, param: Parameter, value: bool): +def print_version(ctx: click.Context, param: click.Parameter, value: bool): if not value: return @@ -198,8 +215,8 @@ def print_version(ctx: Context, param: Parameter, value: bool): def print_bare_version( - ctx: Context, - param: Parameter, + ctx: click.Context, + param: click.Parameter, value: bool, ): if not value: @@ -209,7 +226,7 @@ def print_bare_version( def run_included_example( - ctx: Context, + ctx: click.Context, smoke_test: bool, example: Optional[str], **kwargs, @@ -285,8 +302,8 @@ def run_included_example( def cli_in_container( - ctx: Context, - param: Parameter, + ctx: click.Context, + param: click.Parameter, value: bool, ): if not value: @@ -331,14 +348,14 @@ def cli_in_container( o( "--save-views-to", "view_save_path", - type=Path(file_okay=False, dir_okay=True), + type=click.Path(file_okay=False, dir_okay=True), default=None, help="A directory to copy the final views to, where each format is saved under a directory named after the corner ID (much like the 'final' directory after running a flow.)", ), o( "--ef-save-views-to", "ef_view_save_path", - type=Path(file_okay=False, dir_okay=True), + type=click.Path(file_okay=False, dir_okay=True), default=None, help="A directory to copy the final views to in the Efabless format, compatible with Caravel User Project.", ), @@ -401,8 +418,9 @@ def cli_in_container( _enable_debug_flags=True, sequential_flow_reproducible=True, enable_overwrite_flag=True, + enable_initial_state_element=True, ) -@pass_context +@click.pass_context def cli(ctx, /, **kwargs): """ Runs an OpenLane flow via the commandline using a design configuration diff --git a/openlane/flows/cli.py b/openlane/flows/cli.py index 09e1b8d0d..6378c83d2 100644 --- a/openlane/flows/cli.py +++ b/openlane/flows/cli.py @@ -139,6 +139,7 @@ def cloup_flow_opts( volare_pdk_override: Optional[str] = None, _enable_debug_flags: bool = False, enable_overwrite_flag: bool = False, + enable_initial_state_element: bool = False, ) -> Decorator: """ Creates a wrapper that appends a number of OpenLane flow-related flags to a @@ -214,7 +215,7 @@ def decorate(f): ), default=None, callback=initial_state_cb, - help="Use this JSON file as an initial state. If this is not specified, the latest `state_out.json` of the run directory will be used if available.", + help="Use this JSON file as an initial state. If this is not specified, the latest `state_out.json` of the run directory will be used. If none exist, an empty initial state is created.", )(f) f = o( "--design-dir", @@ -381,6 +382,15 @@ def decorate(f): callback=set_worker_count_cb, expose_value=False, )(f) + if enable_initial_state_element: + f = o( + "-e", + "--initial-state-element-override", + type=str, + multiple=True, + default=(), + help="Elements to override in the used initial state in the format DESIGN_FORMAT_ID=PATH", + )(f) if accept_config_files: f = argument( "config_files", From 4ef5756d8204699fe966b718dd37785f2be7be66 Mon Sep 17 00:00:00 2001 From: Mohamed Gaber Date: Wed, 20 Nov 2024 12:53:17 +0200 Subject: [PATCH 06/14] add `yosys.resynthesis` --- openlane/scripts/pyosys/synthesize.py | 14 +++++++++++++- openlane/steps/pyosys.py | 24 ++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/openlane/scripts/pyosys/synthesize.py b/openlane/scripts/pyosys/synthesize.py index ee4a0bcc3..911e64f15 100644 --- a/openlane/scripts/pyosys/synthesize.py +++ b/openlane/scripts/pyosys/synthesize.py @@ -115,11 +115,13 @@ def openlane_synth(d, top, flatten, report_dir, *, booth=False, abc_dff=False): @click.option("--config-in", type=click.Path(exists=True), required=True) @click.option("--extra-in", type=click.Path(exists=True), required=True) @click.option("--lighter-dff-map", type=click.Path(exists=True), required=False) +@click.argument("inputs", nargs=-1) def synthesize( output, config_in, extra_in, lighter_dff_map, + inputs, ): config = json.load(open(config_in)) extra = json.load(open(extra_in)) @@ -154,7 +156,17 @@ def synthesize( ys.log(f"[INFO] Using SDC file '{sdc_path}' for ABC…") - if verilog_files := config.get("VERILOG_FILES"): + if len(inputs): + d.read_verilog_files( + inputs, + top=config["DESIGN_NAME"], + synth_parameters=[], + includes=includes, + defines=defines, + use_synlig=False, + synlig_defer=False, + ) + elif verilog_files := config.get("VERILOG_FILES"): d.read_verilog_files( verilog_files, top=config["DESIGN_NAME"], diff --git a/openlane/steps/pyosys.py b/openlane/steps/pyosys.py index 7690c8687..eed8abdb2 100644 --- a/openlane/steps/pyosys.py +++ b/openlane/steps/pyosys.py @@ -597,6 +597,30 @@ class Synthesis(SynthesisCommon): config_vars = SynthesisCommon.config_vars + verilog_rtl_cfg_vars +@Step.factory.register() +class Resynthesize(SynthesisCommon): + """ + Like ``Synthesis``, but operates on the input netlist instead of RTL files. + Useful to process/elaborate on netlists generated by tools other than Yosys. + + Some metrics will also be extracted and updated, namely: + + * ``design__instance__count`` + * ``design__instance_unmapped__count`` + * ``design__instance__area`` + """ + + id = "Yosys.Resynthesis" + name = "Resynthesis" + + config_vars = SynthesisCommon.config_vars + + inputs = [DesignFormat.NETLIST] + + def get_command(self, state_in): + return super().get_command(state_in) + [state_in[DesignFormat.NETLIST]] + + @Step.factory.register() class VHDLSynthesis(SynthesisCommon): """ From 9720e82b03ed343e24599c0bc507feb7394ad432 Mon Sep 17 00:00:00 2001 From: Mohamed Gaber Date: Wed, 20 Nov 2024 07:54:02 -0800 Subject: [PATCH 07/14] SYNTH_HIERARCHY_MODE --- openlane/scripts/pyosys/synthesize.py | 4 ++-- openlane/steps/pyosys.py | 14 ++++++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/openlane/scripts/pyosys/synthesize.py b/openlane/scripts/pyosys/synthesize.py index 911e64f15..f5f110ff3 100644 --- a/openlane/scripts/pyosys/synthesize.py +++ b/openlane/scripts/pyosys/synthesize.py @@ -251,7 +251,7 @@ def synthesize( openlane_synth( d, config["DESIGN_NAME"], - not config["SYNTH_NO_FLAT"], + config["SYNTH_HIERARCHY_MODE"] == "flatten", report_dir, booth=config["SYNTH_MUL_BOOTH"], abc_dff=config["SYNTH_ABC_DFF"], @@ -375,7 +375,7 @@ def run_strategy(d): run_strategy(d) - if config["SYNTH_NO_FLAT"]: + if config["SYNTH_HIERARCHY_MODE"] == "deferred_flatten": # Resynthesize, flattening d_flat = ys.Design() d_flat.add_blackbox_models(blackbox_models) diff --git a/openlane/steps/pyosys.py b/openlane/steps/pyosys.py index eed8abdb2..a924c1304 100644 --- a/openlane/steps/pyosys.py +++ b/openlane/steps/pyosys.py @@ -450,10 +450,16 @@ class SynthesisCommon(VerilogStep): default=False, ), Variable( - "SYNTH_NO_FLAT", - bool, - "A flag that disables flattening the hierarchy during synthesis, only flattening it after synthesis, mapping and optimizations.", - default=False, + "SYNTH_HIERARCHY_MODE", + Literal["flatten", "deferred_flatten", "keep"], + "Affects how hierarchy is maintained throughout and after synthesis. 'flatten' flattens it during and after synthesis. 'deferred_flatten' flattens it after synthesis. 'keep' never flattens it.", + default="flatten", + deprecated_names=[ + ( + "SYNTH_NO_FLAT", + lambda x: "deferred_flatten" if x else "flatten", + ) + ], ), Variable( "SYNTH_SHARE_RESOURCES", From 22547b12a77f22ee362e8af9445d16c755547bcf Mon Sep 17 00:00:00 2001 From: Mohamed Gaber Date: Mon, 25 Nov 2024 11:17:26 +0200 Subject: [PATCH 08/14] fix resynthesis class name --- openlane/steps/pyosys.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlane/steps/pyosys.py b/openlane/steps/pyosys.py index 87caddd60..c2b775602 100644 --- a/openlane/steps/pyosys.py +++ b/openlane/steps/pyosys.py @@ -604,7 +604,7 @@ class Synthesis(SynthesisCommon): @Step.factory.register() -class Resynthesize(SynthesisCommon): +class Resynthesis(SynthesisCommon): """ Like ``Synthesis``, but operates on the input netlist instead of RTL files. Useful to process/elaborate on netlists generated by tools other than Yosys. From f8ca843558a1bbca8da2d1f38a2b4183ab393c4b Mon Sep 17 00:00:00 2001 From: Mohamed Gaber Date: Mon, 25 Nov 2024 11:20:39 +0200 Subject: [PATCH 09/14] changelog & version --- Changelog.md | 17 +++++++++++++++++ pyproject.toml | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 4fcc82ada..e4b2cb899 100644 --- a/Changelog.md +++ b/Changelog.md @@ -13,6 +13,23 @@ ## API Breaks ## Documentation --> + +# 2.3.0 + +## Steps + +* `Yosys.*Synthesis` + * Created new variable `SYNTH_HIERARCHY_MODE`, replacing `SYNTH_NO_FLAT`. There are three options, `flatten`, `deferred_flatten` and `keep`. The first two correspond to `SYNTH_NO_FLAT` being false and true respectively. The third keeps the hierarchy in the final netlist. + * Created new variable `SYNTH_TIE_UNDEFINED` to customize whether undefined and undriven values are tied low, high, or left as-is. + * Created new variable `SYNTH_WRITE_NOATTR` to allow attributes to be propagated to the final netlist. + +* Created `Yosys.Resynthesis` + * Like `Yosys.Synthesis`, but uses the current input state netlist as an input instead of RTL files + +## CLI + +* Added new option: `-e`/`--initial-state-element-override`: allows an element in the initial state to be overridden straight from the commandline. + # 2.2.7 ## Steps diff --git a/pyproject.toml b/pyproject.toml index 88938e0ad..6eaf08819 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "openlane" -version = "2.2.7" +version = "2.3.0" description = "An infrastructure for implementing chip design flows" authors = ["Efabless Corporation and Contributors "] readme = "Readme.md" From 1310eb761633247c5b75a2d5f16c26d4d65e6d44 Mon Sep 17 00:00:00 2001 From: Mohamed Gaber Date: Wed, 4 Dec 2024 18:23:29 +0200 Subject: [PATCH 10/14] gpl: add `PL_ROUTABILITY_OVERFLOW_THRESHOLD` --- Changelog.md | 25 ++++++++++++++++++++----- openlane/scripts/openroad/gpl.tcl | 4 ++++ openlane/steps/openroad.py | 5 +++++ 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/Changelog.md b/Changelog.md index 10c976a7d..53e1d64c4 100644 --- a/Changelog.md +++ b/Changelog.md @@ -18,17 +18,32 @@ ## Steps +* `OpenROAD.GlobalPlacement` + + * Exposed `-routability_check_overflow` argument as new variable + `PL_ROUTABILITY_OVERFLOW_THRESHOLD`. + * `Yosys.*Synthesis` - * Created new variable `SYNTH_HIERARCHY_MODE`, replacing `SYNTH_NO_FLAT`. There are three options, `flatten`, `deferred_flatten` and `keep`. The first two correspond to `SYNTH_NO_FLAT` being false and true respectively. The third keeps the hierarchy in the final netlist. - * Created new variable `SYNTH_TIE_UNDEFINED` to customize whether undefined and undriven values are tied low, high, or left as-is. - * Created new variable `SYNTH_WRITE_NOATTR` to allow attributes to be propagated to the final netlist. + + * Created new variable `SYNTH_HIERARCHY_MODE`, replacing `SYNTH_NO_FLAT`. + There are three options, `flatten`, `deferred_flatten` and `keep`. The first + two correspond to `SYNTH_NO_FLAT` being false and true respectively. The + third keeps the hierarchy in the final netlist. + * Created new variable `SYNTH_TIE_UNDEFINED` to customize whether undefined + and undriven values are tied low, high, or left as-is. + * Created new variable `SYNTH_WRITE_NOATTR` to allow attributes to be + propagated to the final netlist. * Created `Yosys.Resynthesis` - * Like `Yosys.Synthesis`, but uses the current input state netlist as an input instead of RTL files + + * Like `Yosys.Synthesis`, but uses the current input state netlist as an input + instead of RTL files ## CLI -* Added new option: `-e`/`--initial-state-element-override`: allows an element in the initial state to be overridden straight from the commandline. +* Added new option: `-e`/`--initial-state-element-override`: allows an element + in the initial state to be overridden straight from the commandline. + # 2.2.9 ## Steps diff --git a/openlane/scripts/openroad/gpl.tcl b/openlane/scripts/openroad/gpl.tcl index 1652456d3..ad1015e6a 100755 --- a/openlane/scripts/openroad/gpl.tcl +++ b/openlane/scripts/openroad/gpl.tcl @@ -47,6 +47,9 @@ if { [info exists ::env(PL_ROUTABILITY_DRIVEN)] && $::env(PL_ROUTABILITY_DRIVEN) set_macro_extension $::env(GRT_MACRO_EXTENSION) source $::env(SCRIPTS_DIR)/openroad/common/set_layer_adjustments.tcl lappend arg_list -routability_driven + if { [info exists ::env(PL_ROUTABILITY_OVERFLOW_THRESHOLD)] } { + lappend arg_list -routability_check_overflow $::env(PL_ROUTABILITY_OVERFLOW_THRESHOLD) + } } if { $::env(PL_SKIP_INITIAL_PLACEMENT) } { @@ -72,6 +75,7 @@ lappend arg_list -pad_right $cell_pad_side lappend arg_list -pad_left $cell_pad_side lappend arg_list -init_wirelength_coef $::env(PL_WIRE_LENGTH_COEF) +puts "+ global_placement $arg_list" global_placement {*}$arg_list diff --git a/openlane/steps/openroad.py b/openlane/steps/openroad.py index 11cd6efe3..a5101cc9f 100644 --- a/openlane/steps/openroad.py +++ b/openlane/steps/openroad.py @@ -1287,6 +1287,11 @@ class GlobalPlacement(_GlobalPlacement): "Specifies whether the placer should use routability driven placement.", default=True, ), + Variable( + "PL_ROUTABILITY_OVERFLOW_THRESHOLD", + Optional[Decimal], + "Sets overflow threshold for routability mode.", + ), ] From 9c6b80f67b071077dc81f69c1d4d41069c88e13e Mon Sep 17 00:00:00 2001 From: Kareem Farid Date: Mon, 9 Dec 2024 14:21:47 +0200 Subject: [PATCH 11/14] correctly utilize SYNTH_TIE_UNDEFINED Signed-off-by: Kareem Farid --- openlane/scripts/pyosys/synthesize.py | 32 +++++++++++++++++++-------- openlane/steps/pyosys.py | 2 +- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/openlane/scripts/pyosys/synthesize.py b/openlane/scripts/pyosys/synthesize.py index 75598f079..843205ff8 100644 --- a/openlane/scripts/pyosys/synthesize.py +++ b/openlane/scripts/pyosys/synthesize.py @@ -57,7 +57,9 @@ def openlane_proc(d: ys.Design, report_dir: str): d.run_pass("opt_expr") # Optimize expressions -def openlane_synth(d, top, flatten, report_dir, *, booth=False, abc_dff=False): +def openlane_synth( + d, top, flatten, report_dir, *, booth=False, abc_dff=False, undriven=True +): d.run_pass("hierarchy", "-check", "-top", top, "-nokeep_prints", "-nokeep_asserts") openlane_proc(d, report_dir) @@ -86,15 +88,26 @@ def openlane_synth(d, top, flatten, report_dir, *, booth=False, abc_dff=False): d.run_pass("opt_clean") # Clean up after memory analysis # Perform more aggressive optimization with faster runtime - d.run_pass( - "opt", "-fast", "-mux_undef", "-mux_bool", "-fine" - ) # Fast and comprehensive optimization + # Fast and comprehensive optimization + if undriven: + d.run_pass("opt", "-fast", "-full") + else: + d.run_pass("opt", "-fast", "-mux_undef", "-mux_bool", "-fine") # Technology mapping d.run_pass("memory_map") # Map memories to standard cells - d.run_pass( - "opt", "-mux_undef", "-mux_bool", "-fine" - ) # More optimization after memory mapping + d.run_pass("opt_muxtree") + d.run_pass("opt_reduce", "-fine", "-full") + d.run_pass("opt_merge", "-share_all") + d.run_pass("opt_share") + d.run_pass("opt_dff") + d.run_pass("opt_clean") + if undriven: + d.run_pass("opt", "-fast", "-full") + else: + d.run_pass( + "opt_expr", "-mux_undef", "-mux_bool", "-fine" + ) # More optimization after memory mapping d.run_pass("techmap") # Map logic to standard cells from the technology library d.run_pass("opt", "-fast") # Fast optimization after technology mapping d.run_pass("opt", "-fast") # More fast optimization @@ -255,6 +268,7 @@ def synthesize( report_dir, booth=config["SYNTH_MUL_BOOTH"], abc_dff=config["SYNTH_ABC_DFF"], + undriven=config.get("SYNTH_TIE_UNDEFINED") is not None, ) d.run_pass("delete", "t:$print") @@ -324,8 +338,8 @@ def run_strategy(d): *(["-dff"] if config["SYNTH_ABC_DFF"] else []), ) - if value := config.get("SYNTH_SET_UNDEFINED"): - flag = "zero" if value == "low" else "high" + if value := config.get("SYNTH_TIE_UNDEFINED"): + flag = "-zero" if value == "low" else "-one" d.run_pass("setundef", flag) d.run_pass( diff --git a/openlane/steps/pyosys.py b/openlane/steps/pyosys.py index ee4f54ab5..353fbab1f 100644 --- a/openlane/steps/pyosys.py +++ b/openlane/steps/pyosys.py @@ -463,7 +463,7 @@ class SynthesisCommon(VerilogStep): "SYNTH_TIE_UNDEFINED", Optional[Literal["high", "low"]], "Whether to tie undefined values low or high. Explicitly provide null if you wish to simply leave them undriven.", - default="high", + default="low", ), Variable( "SYNTH_WRITE_NOATTR", From 2a9bf55c2e80882e078852b8cc2abcb44b199035 Mon Sep 17 00:00:00 2001 From: Mohamed Gaber Date: Sun, 15 Dec 2024 17:14:06 +0200 Subject: [PATCH 12/14] unpack `opt` pass for consistency without `-full` being passed --- openlane/scripts/pyosys/synthesize.py | 135 +++++++++++++++++++++----- 1 file changed, 111 insertions(+), 24 deletions(-) diff --git a/openlane/scripts/pyosys/synthesize.py b/openlane/scripts/pyosys/synthesize.py index 843205ff8..600dffed1 100644 --- a/openlane/scripts/pyosys/synthesize.py +++ b/openlane/scripts/pyosys/synthesize.py @@ -12,7 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Parts of this file adapted from https://github.com/YosysHQ/yosys/blob/master/techlibs/common/synth.cc +# Parts of this file adapted from: +# +# * https://github.com/YosysHQ/yosys/blob/master/techlibs/common/synth.cc +# * https://github.com/YosysHQ/yosys/blob/master/passes/opt/opt.cc # # Copyright (C) 2012 Claire Xenia Wolf # @@ -57,6 +60,88 @@ def openlane_proc(d: ys.Design, report_dir: str): d.run_pass("opt_expr") # Optimize expressions +def openlane_opt( + d, + fast=False, + mux_undef=False, + mux_bool=False, + undriven=False, + fine=False, + purge=False, + noclkinv=False, + keepdc=False, + share_all=False, + nodffe=False, + nosdff=False, + sat=False, + opt_share=False, + noff=False, +): + expr_args = [] + merge_args = [] + reduce_args = [] + clean_args = [] + dff_args = [] + if purge: + clean_args.append("-purge") + if mux_undef: + expr_args.append("-mux_undef") + if mux_bool: + expr_args.append("-mux_bool") + if undriven: + expr_args.append("-undriven") + if fine: + expr_args.append("-fine") + reduce_args.append("-fine") + if noclkinv: + expr_args.append("-noclkinv") + if keepdc: + expr_args.append("-keepdc") + dff_args.append("-keepdc") + merge_args.append("-keepdc") + if nodffe: + dff_args.append("-nodffe") + if nosdff: + dff_args.append("-nosdff") + if sat: + dff_args.append("-sat") + if share_all: + merge_args.append("-share_all") + if fast: + while True: + d.run_pass("opt_expr", *expr_args) + d.run_pass("opt_merge", *merge_args) + d.scratchpad_unset("opt.did_something") + if not noff: + d.run_pass("opt_dff", *dff_args) + if not d.scratchpad_get_bool("opt.did_something"): + break + d.run_pass("opt_clean", *clean_args) + ys.log_header(d, "Rerunning OPT passes (Removed registers in this run.)") + d.run_pass("opt_clean", *clean_args) + else: + d.run_pass("opt_expr", *expr_args) + d.run_pass("opt_merge", "-nomux", *merge_args) + while True: + d.scratchpad_unset("opt.did_something") + d.run_pass("opt_muxtree") + d.run_pass("opt_reduce", *reduce_args) + d.run_pass("opt_merge", *merge_args) + if opt_share: + d.run_pass("opt_share") + if not noff: + d.run_pass("opt_dff", *dff_args) + d.run_pass("opt_clean", *clean_args) + d.run_pass("opt_expr", *expr_args) + if not d.scratchpad_get_bool("opt.did_something"): + break + ys.log_header(d, "Rerunning OPT passes. (Maybe there is more to do…)") + + d.optimize() + d.sort() + d.check() + + def openlane_synth( d, top, flatten, report_dir, *, booth=False, abc_dff=False, undriven=True ): @@ -71,9 +156,9 @@ def openlane_synth( d.run_pass("opt_clean") # Clean up after optimization # Perform various logic optimization passes - d.run_pass("opt", "-nodffe", "-nosdff") # Optimize logic excluding flip-flops + openlane_opt(d, nodffe=True, nosdff=True) d.run_pass("fsm") # Identify and optimize finite state machines - d.run_pass("opt") # Additional logic optimization + openlane_opt(d) d.run_pass("wreduce") # Reduce logic using algebraic rewriting d.run_pass("peepopt") # Perform local peephole optimization d.run_pass("opt_clean") # Clean up after optimization @@ -81,36 +166,38 @@ def openlane_synth( d.run_pass("booth") d.run_pass("alumacc") # Optimize arithmetic logic unitsb d.run_pass("share") # Share logic across the design - d.run_pass("opt") # More logic optimization + openlane_opt(d) # Memory optimization d.run_pass("memory", "-nomap") # Analyze memories but don't map them yet d.run_pass("opt_clean") # Clean up after memory analysis # Perform more aggressive optimization with faster runtime - # Fast and comprehensive optimization - if undriven: - d.run_pass("opt", "-fast", "-full") - else: - d.run_pass("opt", "-fast", "-mux_undef", "-mux_bool", "-fine") + openlane_opt( + d, + fast=True, + opt_share=True, # affects opt_share + mux_undef=True, # affects opt_expr + mux_bool=True, # affects opt_expr + undriven=undriven, # affects opt_expr + fine=True, # affects opt_expr, opt_reduce + ) # Technology mapping d.run_pass("memory_map") # Map memories to standard cells - d.run_pass("opt_muxtree") - d.run_pass("opt_reduce", "-fine", "-full") - d.run_pass("opt_merge", "-share_all") - d.run_pass("opt_share") - d.run_pass("opt_dff") - d.run_pass("opt_clean") - if undriven: - d.run_pass("opt", "-fast", "-full") - else: - d.run_pass( - "opt_expr", "-mux_undef", "-mux_bool", "-fine" - ) # More optimization after memory mapping - d.run_pass("techmap") # Map logic to standard cells from the technology library - d.run_pass("opt", "-fast") # Fast optimization after technology mapping - d.run_pass("opt", "-fast") # More fast optimization + openlane_opt( + d, + opt_share=True, # affects opt_share + mux_undef=True, # affects opt_expr + mux_bool=True, # affects opt_expr + undriven=undriven, # affects opt_expr + fine=True, # affects opt_expr, opt_reduce + ) + d.run_pass("techmap") + + # Couple more fast opt iterations + openlane_opt(d, fast=True) + openlane_opt(d, fast=True) d.run_pass( "abc", "-fast", *(["-dff"] if abc_dff else []) From 224d7d7937ff4cc8b2452dd1d4556a4100fab35f Mon Sep 17 00:00:00 2001 From: Mohamed Gaber Date: Sun, 15 Dec 2024 18:26:05 +0200 Subject: [PATCH 13/14] add experimental feature to fix hold first --- .../scripts/openroad/rsz_timing_postcts.tcl | 42 +++++++++++-------- .../scripts/openroad/rsz_timing_postgrt.tcl | 36 +++++++++------- openlane/steps/openroad.py | 12 ++++++ 3 files changed, 57 insertions(+), 33 deletions(-) diff --git a/openlane/scripts/openroad/rsz_timing_postcts.tcl b/openlane/scripts/openroad/rsz_timing_postcts.tcl index 5cc82b427..1de9f47f0 100644 --- a/openlane/scripts/openroad/rsz_timing_postcts.tcl +++ b/openlane/scripts/openroad/rsz_timing_postcts.tcl @@ -29,26 +29,32 @@ source $::env(SCRIPTS_DIR)/openroad/common/set_rc.tcl estimate_parasitics -placement # Resize -set arg_list [list] -lappend arg_list -verbose -lappend arg_list -setup -lappend arg_list -setup_margin $::env(PL_RESIZER_SETUP_SLACK_MARGIN) -lappend arg_list -max_buffer_percent $::env(PL_RESIZER_SETUP_MAX_BUFFER_PCT) -if { $::env(PL_RESIZER_GATE_CLONING) != 1 } { - lappend arg_list -skip_gate_cloning +set setup_args [list] +lappend setup_args -verbose +lappend setup_args -setup +lappend setup_args -setup_margin $::env(GRT_RESIZER_SETUP_SLACK_MARGIN) +lappend setup_args -max_buffer_percent $::env(GRT_RESIZER_SETUP_MAX_BUFFER_PCT) +if { $::env(GRT_RESIZER_GATE_CLONING) != 1 } { + lappend setup_args -skip_gate_cloning } -repair_timing {*}$arg_list - -set arg_list [list] -lappend arg_list -verbose -lappend arg_list -hold -lappend arg_list -setup_margin $::env(PL_RESIZER_SETUP_SLACK_MARGIN) -lappend arg_list -hold_margin $::env(PL_RESIZER_HOLD_SLACK_MARGIN) -lappend arg_list -max_buffer_percent $::env(PL_RESIZER_HOLD_MAX_BUFFER_PCT) -if { $::env(PL_RESIZER_ALLOW_SETUP_VIOS) == 1 } { - lappend arg_list -allow_setup_violations + +set hold_args [list] +lappend hold_args -verbose +lappend hold_args -hold +lappend hold_args -setup_margin $::env(GRT_RESIZER_SETUP_SLACK_MARGIN) +lappend hold_args -hold_margin $::env(GRT_RESIZER_HOLD_SLACK_MARGIN) +lappend hold_args -max_buffer_percent $::env(GRT_RESIZER_HOLD_MAX_BUFFER_PCT) +if { $::env(GRT_RESIZER_ALLOW_SETUP_VIOS) == 1 } { + lappend hold_args -allow_setup_violations +} + +if { $::env(PL_RESIZER_FIX_HOLD_FIRST) == 1 } { + repair_timing {*}$hold_args + repair_timing {*}$setup_args +} else { + repair_timing {*}$setup_args + repair_timing {*}$hold_args } -repair_timing {*}$arg_list # Legalize source $::env(SCRIPTS_DIR)/openroad/common/dpl.tcl diff --git a/openlane/scripts/openroad/rsz_timing_postgrt.tcl b/openlane/scripts/openroad/rsz_timing_postgrt.tcl index aa85a38a3..2ad629281 100644 --- a/openlane/scripts/openroad/rsz_timing_postgrt.tcl +++ b/openlane/scripts/openroad/rsz_timing_postgrt.tcl @@ -32,26 +32,32 @@ source $::env(SCRIPTS_DIR)/openroad/common/grt.tcl estimate_parasitics -global_routing # Resize -set arg_list [list] -lappend arg_list -verbose -lappend arg_list -setup -lappend arg_list -setup_margin $::env(GRT_RESIZER_SETUP_SLACK_MARGIN) -lappend arg_list -max_buffer_percent $::env(GRT_RESIZER_SETUP_MAX_BUFFER_PCT) +set setup_args [list] +lappend setup_args -verbose +lappend setup_args -setup +lappend setup_args -setup_margin $::env(GRT_RESIZER_SETUP_SLACK_MARGIN) +lappend setup_args -max_buffer_percent $::env(GRT_RESIZER_SETUP_MAX_BUFFER_PCT) if { $::env(GRT_RESIZER_GATE_CLONING) != 1 } { - lappend arg_list -skip_gate_cloning + lappend setup_args -skip_gate_cloning } -repair_timing {*}$arg_list -set arg_list [list] -lappend arg_list -verbose -lappend arg_list -hold -lappend arg_list -setup_margin $::env(GRT_RESIZER_SETUP_SLACK_MARGIN) -lappend arg_list -hold_margin $::env(GRT_RESIZER_HOLD_SLACK_MARGIN) -lappend arg_list -max_buffer_percent $::env(GRT_RESIZER_HOLD_MAX_BUFFER_PCT) +set hold_args [list] +lappend hold_args -verbose +lappend hold_args -hold +lappend hold_args -setup_margin $::env(GRT_RESIZER_SETUP_SLACK_MARGIN) +lappend hold_args -hold_margin $::env(GRT_RESIZER_HOLD_SLACK_MARGIN) +lappend hold_args -max_buffer_percent $::env(GRT_RESIZER_HOLD_MAX_BUFFER_PCT) if { $::env(GRT_RESIZER_ALLOW_SETUP_VIOS) == 1 } { - lappend arg_list -allow_setup_violations + lappend hold_args -allow_setup_violations +} + +if { $::env(GRT_RESIZER_FIX_HOLD_FIRST) == 1 } { + repair_timing {*}$hold_args + repair_timing {*}$setup_args +} else { + repair_timing {*}$setup_args + repair_timing {*}$hold_args } -repair_timing {*}$arg_list # Re-DPL and GRT source $::env(SCRIPTS_DIR)/openroad/common/dpl.tcl diff --git a/openlane/steps/openroad.py b/openlane/steps/openroad.py index a5101cc9f..6e687cc2a 100644 --- a/openlane/steps/openroad.py +++ b/openlane/steps/openroad.py @@ -2293,6 +2293,12 @@ class ResizerTimingPostCTS(ResizerStep): "Enables gate cloning when attempting to fix setup violations", default=True, ), + Variable( + "PL_RESIZER_FIX_HOLD_FIRST", + bool, + "Experimental: attempt to fix hold violations before setup violations, which may lead to better timing results.", + default=False, + ), ] def get_script_path(self): @@ -2366,6 +2372,12 @@ class ResizerTimingPostGRT(ResizerStep): "Gates running global routing after resizer steps. May be useful to disable for designs where global routing takes non-trivial time.", default=True, ), + Variable( + "GRT_RESIZER_FIX_HOLD_FIRST", + bool, + "Experimental: attempt to fix hold violations before setup violations, which may lead to better timing results.", + default=False, + ), ] def get_script_path(self): From ebafa8eb1dd474fc39a25a68bc4d74402c851e3c Mon Sep 17 00:00:00 2001 From: Mohamed Gaber Date: Sun, 15 Dec 2024 18:37:37 +0200 Subject: [PATCH 14/14] oops --- openlane/scripts/openroad/rsz_timing_postcts.tcl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/openlane/scripts/openroad/rsz_timing_postcts.tcl b/openlane/scripts/openroad/rsz_timing_postcts.tcl index 1de9f47f0..be22825ea 100644 --- a/openlane/scripts/openroad/rsz_timing_postcts.tcl +++ b/openlane/scripts/openroad/rsz_timing_postcts.tcl @@ -32,19 +32,19 @@ estimate_parasitics -placement set setup_args [list] lappend setup_args -verbose lappend setup_args -setup -lappend setup_args -setup_margin $::env(GRT_RESIZER_SETUP_SLACK_MARGIN) -lappend setup_args -max_buffer_percent $::env(GRT_RESIZER_SETUP_MAX_BUFFER_PCT) -if { $::env(GRT_RESIZER_GATE_CLONING) != 1 } { +lappend setup_args -setup_margin $::env(PL_RESIZER_SETUP_SLACK_MARGIN) +lappend setup_args -max_buffer_percent $::env(PL_RESIZER_SETUP_MAX_BUFFER_PCT) +if { $::env(PL_RESIZER_GATE_CLONING) != 1 } { lappend setup_args -skip_gate_cloning } set hold_args [list] lappend hold_args -verbose lappend hold_args -hold -lappend hold_args -setup_margin $::env(GRT_RESIZER_SETUP_SLACK_MARGIN) -lappend hold_args -hold_margin $::env(GRT_RESIZER_HOLD_SLACK_MARGIN) -lappend hold_args -max_buffer_percent $::env(GRT_RESIZER_HOLD_MAX_BUFFER_PCT) -if { $::env(GRT_RESIZER_ALLOW_SETUP_VIOS) == 1 } { +lappend hold_args -setup_margin $::env(PL_RESIZER_SETUP_SLACK_MARGIN) +lappend hold_args -hold_margin $::env(PL_RESIZER_HOLD_SLACK_MARGIN) +lappend hold_args -max_buffer_percent $::env(PL_RESIZER_HOLD_MAX_BUFFER_PCT) +if { $::env(PL_RESIZER_ALLOW_SETUP_VIOS) == 1 } { lappend hold_args -allow_setup_violations }