Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: expand synthesis options, initial state elements in cli #604

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
17 changes: 17 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
23 changes: 11 additions & 12 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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";
kareefardi marked this conversation as resolved.
Show resolved Hide resolved
inputs.volare.inputs.nixpkgs.follows = "nix-eda/nixpkgs";
inputs.devshell.inputs.nixpkgs.follows = "nix-eda/nixpkgs";

Expand Down
5 changes: 3 additions & 2 deletions nix/create-shell.nix
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@
{
extra-packages ? [],
extra-python-packages ? [],
extra-env ? [],
openlane-plugins ? [],
include-openlane ? true
include-openlane ? true,
}: ({
lib,
git,
Expand Down Expand Up @@ -62,7 +63,7 @@ in
name = "NIX_PYTHONPATH";
value = "${openlane-env-sitepackages}";
}
];
] ++ extra-env;
devshell.interactive.PS1 = {
text = ''PS1="${prompt}"'';
};
Expand Down
52 changes: 35 additions & 17 deletions openlane/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -40,7 +35,7 @@


from .__version__ import __version__
from .state import State
from .state import State, DesignFormat
from .logging import (
debug,
err,
Expand All @@ -56,7 +51,7 @@


def run(
ctx: Context,
ctx: click.Context,
flow_name: Optional[str],
pdk_root: Optional[str],
pdk: str,
Expand All @@ -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,
):
Expand All @@ -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):
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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:
Expand All @@ -209,7 +226,7 @@ def print_bare_version(


def run_included_example(
ctx: Context,
ctx: click.Context,
smoke_test: bool,
example: Optional[str],
**kwargs,
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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.",
),
Expand Down Expand Up @@ -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
Expand Down
12 changes: 11 additions & 1 deletion openlane/flows/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down
44 changes: 35 additions & 9 deletions openlane/scripts/pyosys/synthesize.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"
donn marked this conversation as resolved.
Show resolved Hide resolved
) # 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
Expand All @@ -111,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))
Expand Down Expand Up @@ -150,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"],
Expand Down Expand Up @@ -203,10 +219,13 @@ 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",
Expand All @@ -232,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"],
Expand Down Expand Up @@ -305,7 +324,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",
Expand Down Expand Up @@ -336,9 +358,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",
Expand All @@ -349,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)
Expand Down
Loading
Loading