Skip to content

Commit

Permalink
make BoundingBox dataclass
Browse files Browse the repository at this point in the history
update regex to new openroad format

Signed-off-by: Kareem Farid <[email protected]>
  • Loading branch information
kareefardi committed Feb 12, 2025
1 parent 4893817 commit e8aaf69
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 51 deletions.
32 changes: 17 additions & 15 deletions openlane/common/drc.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,23 @@
from enum import IntEnum
from decimal import Decimal, InvalidOperation
from dataclasses import dataclass, field, asdict
from typing import List, Optional, Tuple, Dict, Union
from typing import List, Optional, Tuple, Dict


BoundingBox = Tuple[Decimal, Decimal, Decimal, Decimal] # microns
BoundingBoxWithDescription = Tuple[Decimal, Decimal, Decimal, Decimal, str] # microns
@dataclass
class BoundingBox:
llx: Decimal
lly: Decimal
urx: Decimal
ury: Decimal
info: Optional[str] = None


@dataclass
class Violation:
rules: List[Tuple[str, str]] # (layer, rule)
description: str
bounding_boxes: List[Union[BoundingBox, BoundingBoxWithDescription]] = field(
default_factory=list
)
bounding_boxes: List[BoundingBox] = field(default_factory=list)

@property
def layer(self) -> str:
Expand Down Expand Up @@ -72,7 +75,7 @@ class State(IntEnum):
re_violation = re.compile(r"violation type: (?P<type>.*)$")
re_src = re.compile(r"srcs: (?P<src1>\S+)( (?P<src2>\S+))?")
re_bbox = re.compile(
r"bbox = \( (?P<llx>\S+), (?P<lly>\S+) \) - \( (?P<urx>\S+), (?P<ury>\S+) \) on Layer (?P<layer>\S+)"
r"bbox = \((?P<llx>\S+), (?P<lly>\S+)\) - \((?P<urx>\S+), (?P<ury>\S+)\) on Layer (?P<layer>\S+)"
)
bbox_count = 0
violations: Dict[str, Violation] = {}
Expand Down Expand Up @@ -100,7 +103,7 @@ class State(IntEnum):
ury = bbox_match.group("ury")
layer = bbox_match.group("layer")
bbox_count += 1
bounding_box = (
bounding_box = BoundingBox(
Decimal(llx),
Decimal(lly),
Decimal(urx),
Expand Down Expand Up @@ -190,7 +193,7 @@ class State(IntEnum):
f"invalid bounding box at line {i}: bounding box has {len(coord_list)}/4 elements"
)

bounding_box = (
bounding_box = BoundingBox(
coord_list[0],
coord_list[1],
coord_list[2],
Expand Down Expand Up @@ -220,7 +223,7 @@ def from_magic_feedback(
"Invalid syntax: 'box' command has less than 4 arguments"
)
lx, ly, ux, uy = components[0:4]
last_bounding_box = (
last_bounding_box = BoundingBox(
Decimal(lx) * cif_scale,
Decimal(ly) * cif_scale,
Decimal(ux) * cif_scale,
Expand Down Expand Up @@ -305,9 +308,8 @@ def to_klayout_xml(self, out: io.BufferedIOBase):
xf.write(cell, category, visited, multiplicity)
with xf.element("values"):
value = ET.Element("value")
value.text = f"polygon: ({bounding_box[0]},{bounding_box[1]};{bounding_box[2]},{bounding_box[1]};{bounding_box[2]},{bounding_box[3]};{bounding_box[0]},{bounding_box[3]})"
value.text = f"polygon: ({bounding_box.llx},{bounding_box.lly};{bounding_box.urx},{bounding_box.lly};{bounding_box.urx},{bounding_box.ury};{bounding_box.llx},{bounding_box.ury})"
xf.write(value)
value = ET.Element("value")
value.text = f"text: '{bounding_box.info}'"
xf.write(value)
if len(bounding_box) == 5:
value = ET.Element("value")
value.text = f"text: '{bounding_box[4]}'"
xf.write(value)
22 changes: 11 additions & 11 deletions openlane/steps/openroad.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import subprocess
import tempfile
import textwrap
import pathlib
from abc import abstractmethod
from base64 import b64encode
from concurrent.futures import Future, ThreadPoolExecutor
Expand Down Expand Up @@ -1737,23 +1738,22 @@ def get_script_path(self):

def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]:
kwargs, env = self.extract_env(kwargs)
report_path = os.path.join(self.step_dir, "reports", "drc.rpt")
klayout_db_path = os.path.join(self.step_dir, "reports", "drc.xml")
mkdirp(os.path.join(self.step_dir, "reports"))
env["DRT_THREADS"] = env.get("DRT_THREADS", str(_get_process_limit()))
env["_DRC_REPORT_PATH"] = report_path
info(f"Running TritonRoute with {env['DRT_THREADS']} threads…")
views_updates, metrics_updates = super().run(state_in, env=env, **kwargs)
drc, violation_count = DRCObject.from_openroad(
open(report_path, encoding="utf8"), self.config["DESIGN_NAME"]
)

drc.to_klayout_xml(open(klayout_db_path, "wb"))
if violation_count > 0:
self.warn(
f"DRC errors found after routing. View the report file at {report_path}.\nView KLayout xml file at {klayout_db_path}"
drc_paths = list(pathlib.Path(self.step_dir).rglob("*.drc*"))
for path in drc_paths:
drc, _ = DRCObject.from_openroad(
open(path, encoding="utf8"), self.config["DESIGN_NAME"]
)

drc.to_klayout_xml(open(pathlib.Path(str(path) + ".xml"), "wb"))
# if violation_count > 0:
# self.warn(
# f"DRC errors found after routing. View the report file at {report_path}.\nView KLayout xml file at {klayout_db_path}"
# )

return views_updates, metrics_updates


Expand Down
52 changes: 27 additions & 25 deletions test/common/test_misc_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,26 +93,27 @@ def test_slugify():

def test_magic_drc():
from openlane.common import DRC, Violation
from openlane.common.drc import BoundingBox

drc_object, count = DRC.from_magic(io.StringIO(MAGIC_EXAMPLE))
violations = {
"LU.3": Violation(
rules=[("LU", "3")],
description="P-diff distance to N-tap must be < 15.0um (LU.3)",
bounding_boxes=[
(
BoundingBox(
Decimal("17.990"),
Decimal("21.995"),
Decimal("18.265"),
Decimal("22.995"),
),
(
BoundingBox(
Decimal("20.905"),
Decimal("22.935"),
Decimal("21.575"),
Decimal("22.995"),
),
(
BoundingBox(
Decimal("18.535"),
Decimal("21.995"),
Decimal("18.795"),
Expand Down Expand Up @@ -172,61 +173,62 @@ def test_magic_drc_exceptions():

def test_magic_feedback():
from openlane.common import DRC, Violation
from openlane.common.drc import BoundingBox

expected_violations = {
"obsm4-metal4.ILLEGAL_OVERLAP": Violation(
rules=[("obsm4-metal4", "ILLEGAL_OVERLAP")],
description="Illegal overlap between obsm4 and metal4 (types do not connect)",
bounding_boxes=[
(
BoundingBox(
Decimal("11137.80"),
Decimal("4449.70"),
Decimal("11153.80"),
Decimal("4458.80"),
),
(
BoundingBox(
Decimal("11137.80"),
Decimal("4437.90"),
Decimal("11139.90"),
Decimal("4449.70"),
),
(
BoundingBox(
Decimal("11151.70"),
Decimal("4437.90"),
Decimal("11153.80"),
Decimal("4449.70"),
),
(
BoundingBox(
Decimal("11137.80"),
Decimal("4433.70"),
Decimal("11153.80"),
Decimal("4437.90"),
),
(
BoundingBox(
Decimal("11137.80"),
Decimal("4421.90"),
Decimal("11139.90"),
Decimal("4433.70"),
),
(
BoundingBox(
Decimal("11151.70"),
Decimal("4421.90"),
Decimal("11153.80"),
Decimal("4433.70"),
),
(
BoundingBox(
Decimal("11137.80"),
Decimal("4417.70"),
Decimal("11153.80"),
Decimal("4421.90"),
),
(
BoundingBox(
Decimal("11137.80"),
Decimal("4412.80"),
Decimal("11139.90"),
Decimal("4417.70"),
),
(
BoundingBox(
Decimal("11151.70"),
Decimal("4412.80"),
Decimal("11153.80"),
Expand All @@ -238,19 +240,19 @@ def test_magic_feedback():
rules=[("obsm4-via4", "ILLEGAL_OVERLAP")],
description="Illegal overlap between obsm4 and via4 (types do not connect)",
bounding_boxes=[
(
BoundingBox(
Decimal("11139.90"),
Decimal("4437.90"),
Decimal("11151.70"),
Decimal("4449.70"),
),
(
BoundingBox(
Decimal("11139.90"),
Decimal("4421.90"),
Decimal("11151.70"),
Decimal("4433.70"),
),
(
BoundingBox(
Decimal("11139.90"),
Decimal("4412.80"),
Decimal("11151.70"),
Expand All @@ -262,31 +264,31 @@ def test_magic_feedback():
rules=[("UNKNOWN", "UNKNOWN2")],
description="device missing 1 terminal;\n connecting remainder to node VGND",
bounding_boxes=[
(
BoundingBox(
Decimal("8232.15"),
Decimal("8080.15"),
Decimal("8238.05"),
Decimal("8085.65"),
),
(
BoundingBox(
Decimal("8204.55"),
Decimal("8080.15"),
Decimal("8224.25"),
Decimal("8085.65"),
),
(
BoundingBox(
Decimal("8186.15"),
Decimal("8035.95"),
Decimal("8215.05"),
Decimal("8041.45"),
),
(
BoundingBox(
Decimal("8149.35"),
Decimal("8080.15"),
Decimal("8196.65"),
Decimal("8085.65"),
),
(
BoundingBox(
Decimal("393.75"),
Decimal("8025.75"),
Decimal("404.25"),
Expand All @@ -298,31 +300,31 @@ def test_magic_feedback():
rules=[("UNKNOWN", "UNKNOWN3")],
description="device missing 1 terminal;\n connecting remainder to node VPWR",
bounding_boxes=[
(
BoundingBox(
Decimal("8232.15"),
Decimal("8063.15"),
Decimal("8238.05"),
Decimal("8071.85"),
),
(
BoundingBox(
Decimal("8204.55"),
Decimal("8063.15"),
Decimal("8224.25"),
Decimal("8071.85"),
),
(
BoundingBox(
Decimal("8186.15"),
Decimal("8049.75"),
Decimal("8215.05"),
Decimal("8058.45"),
),
(
BoundingBox(
Decimal("8149.35"),
Decimal("8063.15"),
Decimal("8196.65"),
Decimal("8071.85"),
),
(
BoundingBox(
Decimal("393.75"),
Decimal("8008.75"),
Decimal("404.25"),
Expand Down

0 comments on commit e8aaf69

Please sign in to comment.