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

Many Genus + Innovus enhancements #843

Merged
merged 8 commits into from
Mar 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions hammer/common/cadence/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,10 +207,15 @@ def append_mmmc(cmd: str) -> None:

# Finally, apply the analysis view.
# TODO: should not need to analyze extra views as well. Defaulting to hold for now (min. runtime impact).
append_mmmc("set_analysis_view -setup {{ {setup_views} }} -hold {{ {hold_views} {extra_views} }}".format(
# First extra view is assumed to be for dynamic and leakage power calculation.
power_opts = ""
if len(extra_view_names) > 0:
power_opts = f"-dynamic {extra_view_names[0]} -leakage {extra_view_names[0]}"
append_mmmc("set_analysis_view -setup {{ {setup_views} }} -hold {{ {hold_views} {extra_views} }} {power}".format(
setup_views=" ".join(setup_view_names),
hold_views=" ".join(hold_view_names),
extra_views=" ".join(extra_view_names)
extra_views=" ".join(extra_view_names),
power=power_opts
))
else:
# First, create an Innovus library set.
Expand Down
3 changes: 2 additions & 1 deletion hammer/config/defaults.yml
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,8 @@ vlsi.inputs:
# - Required for all types
# - One of the following:
# - "dummy" (does nothing with this constraint)
# - "placement" (creates a placement constraint for an instance)
# - "placement" or "soft_placement" (creates a soft placement constraint for a hierarchical instance)
# - "hard_placement" (creates a hard placement constraint for a hierarchical instance)
# - "toplevel" (top-level chip dimensions; may only occur once, for the top-level module)
# - "hardmacro" (places this hard macro at a particular spot)
# - "hierarchical" (marks this instance as part of hierarchical place and route)
Expand Down
179 changes: 156 additions & 23 deletions hammer/par/innovus/__init__.py

Large diffs are not rendered by default.

12 changes: 11 additions & 1 deletion hammer/par/innovus/defaults.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ par.innovus:

# Innovus version to use.
# Used to locate the binary - e.g. the '221' in ${cadence.cadence_home}/DDI/DDI221/INNOVUS221/bin/innovus
version: "221"
version: "231"

# Design flow effort.
# Valid options: express (fastest), standard, and extreme (slowest).
Expand All @@ -35,3 +35,13 @@ par.innovus:
# Note that this requires an optional licence (enccco).
# type: bool
use_cco: true

# Route bumps with early global router (version >= 23.1 only).
# By default, bumps are ignored for routing. If true, turn on early bump routing.
# This is useful for RC delay estimation if you don't have IO cells routed to bumps via the flip-chip router.
early_route_bumps: false

# Perform signoff timing, then timing/DRV/power optimization with opt_signoff.
# Should only be run at the very end, as runtime impact is significant.
# Requires the same version of Tempus to be installed at ${cadence.cadence_home}/SSV/SSV${par.innovus.bin}/bin
signoff: false
2 changes: 1 addition & 1 deletion hammer/par/openroad/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1814,7 +1814,7 @@ def generate_floorplan_tcl(self) -> List[str]:
pass
if constraint.type == PlacementConstraintType.Dummy:
pass
elif constraint.type == PlacementConstraintType.Placement:
elif constraint.type in [PlacementConstraintType.SoftPlacement, PlacementConstraintType.HardPlacement]:
pass
# for OpenROAD
elif constraint.type in [PlacementConstraintType.HardMacro, PlacementConstraintType.Hierarchical]:
Expand Down
2 changes: 1 addition & 1 deletion hammer/power/joules/defaults.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ power.joules:

# Joules version to use.
# Used to locate the binary - e.g. the '221' in ${cadence.cadence_home}/DDI/DDI221/JLS221/bin/joules
version: "221"
version: "231"
16 changes: 10 additions & 6 deletions hammer/synthesis/genus/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,9 @@ def init_environment(self) -> bool:
verbose_append("set_db module:{top}/{mod} .preserve true".format(top=self.top_module, mod=ilm.module))
verbose_append("init_design -top {}".format(self.top_module))

# Report timing constraint issues
verbose_append("report_timing -lint -verbose")

# Setup power settings from cpf/upf
# Difference from other tools: apply_power_intent after read
power_cmds = self.generate_power_spec_commands()
Expand Down Expand Up @@ -357,12 +360,13 @@ def add_tieoffs(self) -> bool:
self.verbose_append("set_db message:WSDF-201 .max_print 20")
self.verbose_append("set_db use_tiehilo_for_const duplicate")

# If there is more than 1 corner or a certain type, use lib cells for only the active analysis view
corner_counts = Counter(list(map(lambda c: c.type, self.get_mmmc_corners())))
if any(cnt>1 for cnt in corner_counts.values()):
self.verbose_append("set ACTIVE_VIEW [string map { .setup_view {} .hold_view {} .extra_view {} } [get_db analysis_view:[get_analysis_views] .name]]")
self.verbose_append("set HI_TIEOFF [get_db base_cell:{TIE_HI_CELL} .lib_cells -if {{ .library.default_opcond == $ACTIVE_VIEW }}]".format(TIE_HI_CELL=tie_hi_cell))
self.verbose_append("set LO_TIEOFF [get_db base_cell:{TIE_LO_CELL} .lib_cells -if {{ .library.default_opcond == $ACTIVE_VIEW }}]".format(TIE_LO_CELL=tie_lo_cell))
# If MMMC corners specified, get the single lib cell for the active analysis view
# Else, Genus will complain that multiple objects match for the cell name
corners = self.get_mmmc_corners()
if corners:
self.verbose_append("set ACTIVE_SET [string map { .setup_view .setup_set .hold_view .hold_set .extra_view .extra_set } [get_db [get_analysis_views] .name]]")
self.verbose_append("set HI_TIEOFF [get_db base_cell:{TIE_HI_CELL} .lib_cells -if {{ .library.library_set.name == $ACTIVE_SET }}]".format(TIE_HI_CELL=tie_hi_cell))
self.verbose_append("set LO_TIEOFF [get_db base_cell:{TIE_LO_CELL} .lib_cells -if {{ .library.library_set.name == $ACTIVE_SET }}]".format(TIE_LO_CELL=tie_lo_cell))
self.verbose_append("add_tieoffs -high $HI_TIEOFF -low $LO_TIEOFF -max_fanout 1 -verbose")
else:
self.verbose_append("add_tieoffs -high {HI_TIEOFF} -low {LO_TIEOFF} -max_fanout 1 -verbose".format(HI_TIEOFF=tie_hi_cell, LO_TIEOFF=tie_lo_cell))
Expand Down
2 changes: 1 addition & 1 deletion hammer/synthesis/genus/defaults.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ synthesis.genus:

# Genus version to use.
# Used to locate the binary - e.g. the '221' in ${cadence.cadence_home}/DDI/DDI221/GENUS221/bin/genus
version: "221"
version: "231"

# Generate the TCL file but do not run it yet.
generate_only: false
19 changes: 11 additions & 8 deletions hammer/vlsi/constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -530,18 +530,21 @@ def __str__(self) -> str:

class PlacementConstraintType(Enum):
Dummy = 1
Placement = 2
TopLevel = 3
HardMacro = 4
Hierarchical = 5
Obstruction = 6
Overlap = 7
SoftPlacement = 2
HardPlacement = 3
TopLevel = 4
HardMacro = 5
Hierarchical = 6
Obstruction = 7
Overlap = 8

@classmethod
def __mapping(cls) -> Dict[str, "PlacementConstraintType"]:
return {
"dummy": PlacementConstraintType.Dummy,
"placement": PlacementConstraintType.Placement,
"placement": PlacementConstraintType.SoftPlacement,
"soft_placement": PlacementConstraintType.SoftPlacement,
"hard_placement": PlacementConstraintType.HardPlacement,
"toplevel": PlacementConstraintType.TopLevel,
"hardmacro": PlacementConstraintType.HardMacro,
"hierarchical": PlacementConstraintType.Hierarchical,
Expand Down Expand Up @@ -781,7 +784,7 @@ def from_dict(constraint: dict) -> "PlacementConstraint":
assert isinstance(create_physical, bool)

### Width & height ###
# These fields are mandatory for Hierarchical, Dummy, Placement, TopLevel, and Obstruction constraints
# These fields are mandatory for Hierarchical, Dummy, Soft/HardPlacement, TopLevel, and Obstruction constraints
# These fields are optional for HardMacro and Overlap constraints
# TODO(ucb-bar/hammer#414) make them mandatory for HardMacro and Overlap once there's a more robust way of automatically getting that data into hammer
# This is not None because we don't want to make width optional for the reason above
Expand Down
2 changes: 1 addition & 1 deletion hammer/vlsi/hammer_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -1268,7 +1268,7 @@ def get_macro_wh(macro: Optional[str]) -> Tuple[Decimal, Decimal]:
if viz_mode in ["all", "floorplan"]:
macro_rects = macro_text = obs_rects = obs_text = orient_lines = '<g transform="{}">\n'.format(translate)
for c in fp_consts:
if c.type in [PlacementConstraintType.Placement, PlacementConstraintType.HardMacro, PlacementConstraintType.Hierarchical]:
if c.type in [PlacementConstraintType.SoftPlacement, PlacementConstraintType.HardPlacement, PlacementConstraintType.HardMacro, PlacementConstraintType.Hierarchical]:
# macros & hierarchical not required to have width/height, will resolve to 0
(width, height) = (c.width, c.height)
if width == 0 or height == 0:
Expand Down
8 changes: 7 additions & 1 deletion tests/test_constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,13 @@ def test_placement(self) -> None:
"height": Decimal(20),
"orientation": "r0"}
tc = PlacementConstraint.from_dict(d)
assert tc.type == PlacementConstraintType.Placement
assert tc.type == PlacementConstraintType.SoftPlacement
d["type"] = "soft_placement"
tc = PlacementConstraint.from_dict(d)
assert tc.type == PlacementConstraintType.SoftPlacement
d["type"] = "hard_placement"
tc = PlacementConstraint.from_dict(d)
assert tc.type == PlacementConstraintType.HardPlacement
assert tc.path == "path/to/placement"
assert tc.x == Decimal(4)
assert tc.y == Decimal(6)
Expand Down
Loading