Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/dev' into synthesis-adjustments
Browse files Browse the repository at this point in the history
  • Loading branch information
donn committed Sep 8, 2024
2 parents 7ce96c0 + b961029 commit 9ffacf5
Show file tree
Hide file tree
Showing 12 changed files with 145 additions and 18 deletions.
22 changes: 22 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,28 @@
## Documentation
-->

# 2.1.3

## Tool Updates

* Bundled an downgraded OpenSTA bundled with OpenLane to work around critical
bug for hierarchical static timing analysis:
https://github.com/parallaxsw/OpenSTA/issues/82
* Version of OpenSTA linked against OpenROAD unchanged.

## Testing

* CI now uses DeterminateSystems Nix Installer for all Nix installations as well
as the Magic Nix Cache Action instead of the nonfunctional attempt at local
file-based substituters

## Documentation

* Installation documents now use the less-brittle Determinate Systems Nix
installer, as well as adding warnings about the `apt` version of Nix.

* Added an OpenROAD Flow Scripts-inspired Diagram to the Readme.

# 2.1.2

## Steps
Expand Down
4 changes: 2 additions & 2 deletions default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
libparse,
magic-vlsi,
netgen,
opensta,
opensta-stable,
openroad,
ruby,
surelog,
Expand Down Expand Up @@ -84,8 +84,8 @@
];

includedTools = [
opensta-stable
yosys-env
opensta
openroad-env
klayout
netgen
Expand Down
4 changes: 4 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@
});
colab-env = callPackage ./nix/colab-env.nix {};
opensta = callPackage ./nix/opensta.nix {};
opensta-stable = callPackage ./nix/opensta.nix {
rev = "cc9eb1f12a0d5030aebc1f1428e4300480e30b40";
sha256 = "sha256-/ShPD4xWq3lkN0Z3uONKm7i9eqbT+IU41UF7yIvDJy4=";
};
openroad-abc = callPackage ./nix/openroad-abc.nix {};
openroad = callPythonPackage ./nix/openroad.nix {
inherit (nix-eda) buildPythonEnvForInterpreter;
Expand Down
1 change: 1 addition & 0 deletions nix/opensta.nix
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ clangStdenv.mkDerivation (finalAttrs: {
meta = with lib; {
description = "Gate-level static timing verifier";
homepage = "https://parallaxsw.com";
mainProgram = "sta";
license = licenses.gpl3Plus;
platforms = platforms.darwin ++ platforms.linux;
};
Expand Down
8 changes: 4 additions & 4 deletions openlane/config/variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,11 @@ def __str__(self) -> str:
@dataclass
class Instance:
"""
Location information for an instance of a Macro.
Location information for an instance of a cell or macro.
:param location: The physical co-ordinates of the Macro's origin. Leave
:param location: The physical co-ordinates of the object's origin. Leave
empty for automatic placement.
:param orientation: The orientation of the macro's placement. 'N'/'R0' by default.
:param orientation: The orientation of the object's placement. 'N'/'R0' by default.
"""

location: Optional[Tuple[Decimal, Decimal]]
Expand Down Expand Up @@ -549,7 +549,7 @@ def __process(
raw = value
if not isinstance(raw, dict):
raise ValueError(
f"Value provided for deserializable path {validating_type} at '{key_path}' is not a dictionary."
f"Value provided for deserializable class {validating_type} at '{key_path}' is not a dictionary."
)
raw = value.copy()
kwargs_dict = {}
Expand Down
1 change: 1 addition & 0 deletions openlane/flows/classic.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class Classic(SequentialFlow):
Checker.PowerGridViolations,
OpenROAD.STAMidPNR,
OpenROAD.RepairDesignPostGPL,
Odb.ManualGlobalPlacement,
OpenROAD.DetailedPlacement,
OpenROAD.CTS,
OpenROAD.STAMidPNR,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,16 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import sys
from decimal import Decimal

from reader import click_odb, click


@click.group
def cli():
pass


LEF2OA_MAP = {
"N": "R0",
"S": "R180",
Expand Down Expand Up @@ -52,7 +60,7 @@ def gridify(n, f):
help="A flag to signal whether the placement should be fixed or not",
)
@click_odb
def manual_macro_place(reader, config, fixed):
def manual_macro_placement(reader, config, fixed):
"""
Places macros in positions and orientations specified by a config file
"""
Expand All @@ -71,8 +79,8 @@ def manual_macro_place(reader, config, fixed):
name, x, y, orientation = line
macro_data = [
name,
int(float(x) * db_units_per_micron),
int(float(y) * db_units_per_micron),
int(Decimal(x) * db_units_per_micron),
int(Decimal(y) * db_units_per_micron),
orientation,
]
name_escaped = reader.escape_verilog_name(name)
Expand Down Expand Up @@ -112,5 +120,43 @@ def manual_macro_place(reader, config, fixed):
print(f"Successfully placed {macros_cnt} instances.")


cli.add_command(manual_macro_placement)


@click.command()
@click_odb
def manual_global_placement(reader):
db_units_per_micron = reader.block.getDbUnitsPerMicron()

data = reader.config["MANUAL_GLOBAL_PLACEMENTS"]
not_found = []
for instance, info in data.items():
name_escaped = reader.escape_verilog_name(instance)
x, y = info["location"]
orientation = lef_rot_to_oa_rot(info["orientation"])
found = False
for inst in reader.block.getInsts():
if inst.getName() == name_escaped:
found = True
x_dbu = int(x * db_units_per_micron)
y_dbu = int(y * db_units_per_micron)
inst.setOrient(lef_rot_to_oa_rot(orientation))
inst.setLocation(x_dbu, y_dbu)
inst.setPlacementStatus("PLACED")
break
if not found:
not_found.append(instance)

if len(not_found):
print(
"[ERROR] One or more instances not found. Make sure you use their Verilog and not their LEF names."
)
for instance in not_found:
print(f"* {instance}")
exit(1)


cli.add_command(manual_global_placement)

if __name__ == "__main__":
manual_macro_place()
cli()
8 changes: 6 additions & 2 deletions openlane/scripts/odbpy/reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@
# limitations under the License.
# flake8: noqa E402
import odb
import json
from openroad import Tech, Design

import re
import sys
import json
import locale
import inspect
import functools
from decimal import Decimal
from fnmatch import fnmatch
from typing import Callable, Dict

Expand Down Expand Up @@ -68,7 +69,10 @@ def __init__(self, *args, **kwargs):

self.config = None
if "config_path" in kwargs and kwargs["config_path"] is not None:
self.config = json.load(open(kwargs["config_path"], encoding="utf8"))
self.config = json.load(
open(kwargs["config_path"], encoding="utf8"),
parse_float=Decimal,
)

self.db = self.ord_tech.getDB()
self.tech = self.db.getTech()
Expand Down
2 changes: 1 addition & 1 deletion openlane/scripts/pyosys/ys_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ def _Design_read_verilog_files(
else:
for file in files:
self.run_pass(
"read_verilog", "-noautowire", "-sv", *include_args, *define_args, file
"read_verilog", "-defer", "-noautowire", "-sv", *include_args, *define_args, file,
)
for param, value in chparams.items():
self.run_pass("chparam", "-set", param, value, top)
Expand Down
47 changes: 44 additions & 3 deletions openlane/steps/odb.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from decimal import Decimal
from functools import reduce
from abc import abstractmethod
from typing import List, Literal, Optional, Tuple
from typing import Dict, List, Literal, Optional, Tuple


from .common_variables import io_layer_variables
Expand All @@ -37,7 +37,7 @@
DefaultOutputProcessor,
)
from ..logging import info, verbose
from ..config import Variable, Macro
from ..config import Variable, Macro, Instance
from ..state import State, DesignFormat
from ..common import Path, get_script_dir

Expand Down Expand Up @@ -356,7 +356,10 @@ class ManualMacroPlacement(OdbpyStep):
]

def get_script_path(self):
return os.path.join(get_script_dir(), "odbpy", "manual_macro_place.py")
return os.path.join(get_script_dir(), "odbpy", "placers.py")

def get_subcommand(self) -> List[str]:
return ["manual-macro-placement"]

def get_command(self) -> List[str]:
return super().get_command() + [
Expand Down Expand Up @@ -847,3 +850,41 @@ class HeuristicDiodeInsertion(CompositeStep):
DetailedPlacement,
GlobalRouting,
]


@Step.factory.register()
class ManualGlobalPlacement(OdbpyStep):
"""
This is an step to override the placement of one or more instances at
user-specified locations.
Alternatively, if this is a custom design with a few cells, this can be used
in place of the global placement entirely.
"""

id = "Odb.ManualGlobalPlacement"
name = "Manual Global Placement"

config_vars = OdbpyStep.config_vars + [
Variable(
"MANUAL_GLOBAL_PLACEMENTS",
Optional[Dict[str, Instance]],
description="A dictionary of instances to their global (non-legalized and unfixed) placement location.",
)
]

def get_script_path(self) -> str:
return os.path.join(get_script_dir(), "odbpy", "placers.py")

def get_subcommand(self) -> List[str]:
return ["manual-global-placement"]

def get_command(self) -> List[str]:
assert self.config_path is not None, "get_command called before start()"
return super().get_command() + ["--step-config", self.config_path]

def run(self, state_in, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]:
if self.config["MANUAL_GLOBAL_PLACEMENTS"] is None:
info("'MANUAL_GLOBAL_PLACEMENTS' not set, skipping…")
return {}, {}
return super().run(state_in, **kwargs)
10 changes: 9 additions & 1 deletion openlane/steps/step.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,12 @@ class Step(ABC):
If :meth:`start` is called again, the reference is destroyed.
:ivar config_path:
Path to the last step-specific `config.json` generated while running
this step object, if it exists.
If :meth:`start` is called again, the path will be replaced.
:ivar toolbox:
The last :class:`Toolbox` used while running this step object, if it
exists.
Expand All @@ -461,6 +467,7 @@ class Step(ABC):
state_out: Optional[State] = None
start_time: Optional[float] = None
end_time: Optional[float] = None
config_path: Optional[str] = None

# These are mutable class variables. However, they will only be used
# when steps are run outside of a Flow, pretty much.
Expand Down Expand Up @@ -1120,7 +1127,8 @@ def start(
with open(os.path.join(self.step_dir, "state_in.json"), "w") as f:
f.write(state_in_result.dumps())

with open(os.path.join(self.step_dir, "config.json"), "w") as f:
self.config_path = os.path.join(self.step_dir, "config.json")
with open(self.config_path, "w") as f:
config_mut = self.config.to_raw_dict()
config_mut["meta"] = {
"openlane_version": __version__,
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "openlane"
version = "2.1.2"
version = "2.1.3"
description = "An infrastructure for implementing chip design flows"
authors = ["Efabless Corporation and Contributors <[email protected]>"]
readme = "Readme.md"
Expand Down

0 comments on commit 9ffacf5

Please sign in to comment.