Skip to content

Commit

Permalink
Add antenna report summary table (#328)
Browse files Browse the repository at this point in the history
* `OpenROAD.CheckAntennas`:
  * Added new `antenna_summary.rpt` file with a summary table for antennas matching that of OpenLane 1
  • Loading branch information
kareefardi authored Jan 8, 2024
1 parent 87dbf39 commit 056badd
Showing 1 changed file with 103 additions and 1 deletion.
104 changes: 103 additions & 1 deletion openlane/steps/openroad.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ class OpenROADStep(TclStep):
]

@abstractmethod
def get_script_path(self):
def get_script_path(self) -> str:
pass

def prepare_env(self, env: dict, state: State) -> dict:
Expand Down Expand Up @@ -1077,13 +1077,115 @@ class CheckAntennas(OpenROADStep):
def get_script_path(self):
return os.path.join(get_script_dir(), "openroad", "antenna_check.tcl")

def __summarize_antenna_report(self, report_file: str, output_file: str):
"""
Extracts the list of violating nets from an ARC report file"
"""

class AntennaViolation:
def __init__(self, net, pin, required_ratio, partial_ratio, layer):
self.net = net
self.pin = pin
self.required_ratio = float(required_ratio)
self.partial_ratio = float(partial_ratio)
self.layer = layer
self.partial_to_required = self.partial_ratio / self.required_ratio

def __lt__(self, other):
return self.partial_to_required < other.partial_to_required

net_pattern = re.compile(r"\s*Net:\s*(\S+)")
required_ratio_pattern = re.compile(r"\s*Required ratio:\s+([\d.]+)")
partial_ratio_pattern = re.compile(r"\s*Partial area ratio:\s+([\d.]+)")
layer_pattern = re.compile(r"\s*Layer:\s+(\S+)")
pin_pattern = re.compile(r"\s*Pin:\s+(\S+)")

required_ratio = None
layer = None
partial_ratio = None
required_ratio = None
pin = None
net = None
violations: List[AntennaViolation] = []

net_pattern = re.compile(r"\s*Net:\s*(\S+)")
required_ratio_pattern = re.compile(r"\s*Required ratio:\s+([\d.]+)")
partial_ratio_pattern = re.compile(r"\s*Partial area ratio:\s+([\d.]+)")
layer_pattern = re.compile(r"\s*Layer:\s+(\S+)")
pin_pattern = re.compile(r"\s*Pin:\s+(\S+)")

with open(report_file, "r") as f:
for line in f:
pin_new = pin_pattern.match(line)
required_ratio_new = required_ratio_pattern.match(line)
partial_ratio_new = partial_ratio_pattern.match(line)
layer_new = layer_pattern.match(line)
net_new = net_pattern.match(line)
required_ratio = (
required_ratio_new.group(1)
if required_ratio_new is not None
else required_ratio
)
partial_ratio = (
partial_ratio_new.group(1)
if partial_ratio_new is not None
else partial_ratio
)
layer = layer_new.group(1) if layer_new is not None else layer
pin = pin_new.group(1) if pin_new is not None else pin
net = net_new.group(1) if net_new is not None else net

if "VIOLATED" in line:
violations.append(
AntennaViolation(
net=net,
pin=pin,
partial_ratio=partial_ratio,
layer=layer,
required_ratio=required_ratio,
)
)

violations.sort(reverse=True)

# Partial/Required: 2.36, Required: 3091.96, Partial: 7298.29,
# Net: net384, Pin: _22354_/A, Layer: met5
table = rich.table.Table()
decimal_places = 2
row = []
table.add_column("Partial/Required")
table.add_column("Required")
table.add_column("Partial")
table.add_column("Net")
table.add_column("Pin")
table.add_column("Layer")
for violation in violations:
row = [
f"{violation.partial_to_required:.{decimal_places}f}",
f"{violation.required_ratio:.{decimal_places}f}",
f"{violation.partial_ratio:.{decimal_places}f}",
f"{violation.net}",
f"{violation.pin}",
f"{violation.layer}",
]
table.add_row(*row)

if not options.get_condensed_mode():
console.print(table)
with open(output_file, "w") as f:
rich.print(table, file=f)

def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]:
views_updates, metrics_updates = super().run(state_in, **kwargs)

metrics_updates["route__antenna_violations__count"] = get_antenna_nets(
open(os.path.join(self.step_dir, "antenna.rpt")),
open(os.path.join(self.step_dir, "antenna_net_list.txt"), "w"),
)
self.__summarize_antenna_report(
os.path.join(self.step_dir, "antenna.rpt"),
os.path.join(self.step_dir, "antenna_summary.rpt"),
)

return views_updates, metrics_updates

Expand Down

0 comments on commit 056badd

Please sign in to comment.