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

Updates for DDI221 #798

Merged
merged 7 commits into from
Sep 28, 2023
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
2 changes: 1 addition & 1 deletion doc/Technology/Tech-json.rst
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ The example below shows a subset of the ASAP7 tech plugin for 2 types of cells:
{"cell_type": "tapcell", "name": ["TAPCELL_ASAP7_75t_L"]},
{"cell_type": "stdfiller", "name": ["FILLER_ASAP7_75t_R", "FILLER_ASAP7_75t_L", "FILLER_ASAP7_75t_SL", "FILLER_ASAP7_75t_SRAM", "FILLERxp5_ASAP7_75t_R", "FILLERxp5_ASAP7_75t_L", "FILLERxp5_ASAP7_75t_SL", "FILLERxp5_ASAP7_75t_SRAM"]},

There are 8 ``cell_type`` s supported: ``tiehicell``, ``tielocell``, ``tiehilocell``, ``endcap``, ``iofiller``, ``stdfiller``, ``decap``, and ``tapcell``. Depending on the tech/tool, some of these cell types can only have 1 cell in the ``name`` list.
See the ``SpecialCell`` subsection in the :ref:`full_schema` for a list of special cell types. Depending on the tech/tool, some of these cell types can only have 1 cell in the ``name`` list.

There is an optional ``size`` list. For each element in its corresponding ``name`` list, a size (type: str) can be given. An example of how this is used is for ``decap`` cells, where each listed cell has a typical capacitance, which a place and route tool can then use to place decaps to hit a target total decapacitance value. After characterizing the ASAP7 decaps using Voltus, the nominal capacitance is filled into the ``size`` list:

Expand Down
8 changes: 4 additions & 4 deletions hammer/config/defaults.yml
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ vlsi.inputs:

constraints: [] # Manual hierarchical constraints. Overrides generic constraints on a per module basis.
# Should be a list along the lines of [{"module1": <list of other hammer constraints>}].
# For example [{"mod1": [vlsi.inputs.default_output_load: 2], "mod2": [vlsi.inputs.clocks:<clock constraints>] }].
# For example [{"mod1": [vlsi.inputs.default_output_load: "2 pF"], "mod2": [vlsi.inputs.clocks:<clock constraints>] }].

ilms: [] # ILMs for hierarchical mode.
# ILM struct (ILMStruct) members:
Expand Down Expand Up @@ -188,13 +188,13 @@ vlsi.inputs:
# group (str) - Optional. The name of the clock group this clock belongs to. Clocks in the same group will not be marked as asynchronous.
# Clocks with no group specified will all be placed in separate groups and thus marked as asynchronous to each other and all other groups.

default_output_load: 1 # Default output pin load capacitance.
# Default: 1pF
default_output_load: "1 pF" # Default output pin load capacitance.
# type: CapacitanceValue

output_loads: [] # List of output load constraints.
# Each item in the list should be a struct with the following members:
# name (str) - Name of the output load (e.g. io_out)
# load (float) - Output load capacitance in pF.
# load (CapacitanceValue) - Output load capacitance (e.g. "1 pF").

delays: [] # List of delay constraints.
# These either constrain inputs to arrive after a certain delay relative
Expand Down
2 changes: 1 addition & 1 deletion hammer/config/defaults_types.yml
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ vlsi.inputs:
clocks: list[dict[str, Any]]

# Default output pin load capacitance.
default_output_load: int
default_output_load: str

# List of output load constraints.
output_loads: list[dict[str, str]]
Expand Down
20 changes: 18 additions & 2 deletions hammer/par/innovus/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ def output_ilm_sdcs(self) -> List[str]:
def env_vars(self) -> Dict[str, str]:
v = dict(super().env_vars)
v["INNOVUS_BIN"] = self.get_setting("par.innovus.innovus_bin")
if self.version() >= self.version_number("221"): # support critical region resynthesis with DDI
v["PATH"] = f'{os.environ.copy()["PATH"]}:{os.path.dirname(self.get_setting("par.innovus.innovus_bin").replace("INNOVUS", "GENUS"))}'
return v

@property
Expand Down Expand Up @@ -327,7 +329,8 @@ def init_design(self) -> bool:
verbose_append(f"set_db route_design_top_layer {layers[1]}")

# Set design effort.
verbose_append("set_db design_flow_effort {}".format(self.get_setting("par.innovus.design_flow_effort")))
verbose_append(f"set_db design_flow_effort {self.get_setting('par.innovus.design_flow_effort')}")
verbose_append(f"set_db design_power_effort {self.get_setting('par.innovus.design_power_effort')}")

# Set "don't use" cells.
for l in self.generate_dont_use_commands():
Expand Down Expand Up @@ -362,7 +365,7 @@ def place_bumps(self) -> bool:
# TODO: Fix this once the stackup supports vias ucb-bar/hammer#354
block_layer = self.get_setting("vlsi.technology.bump_block_cut_layer") # type: str
for bump in bumps.assignments:
self.append("create_bump -cell {cell} -location_type cell_center -name_format \"Bump_{c}.{r}\" -orient r0 -location \"{x} {y}\"".format(
self.append("create_bump -allow_overlap_control keep_all -cell {cell} -location_type cell_center -name_format \"Bump_{c}.{r}\" -orient r0 -location \"{x} {y}\"".format(
cell = bump.custom_cell if bump.custom_cell is not None else bumps.cell,
c = bump.x,
r = bump.y,
Expand Down Expand Up @@ -523,6 +526,19 @@ def clock_tree(self) -> bool:
'''.format(sdc=self.post_synth_sdc), clean=True)
if len(self.get_clock_ports()) > 0:
# Ignore clock tree when there are no clocks
# If special cells are specified, explicitly set them instead of letting tool infer from libs
buffers = self.technology.get_special_cell_by_type(CellType.CTSBuffer)[0].name
if len(buffers) > 0:
self.append(f"set_db cts_buffer_cells {{{' '.join(buffers)}}}")
inverters = self.technology.get_special_cell_by_type(CellType.CTSInverter)[0].name
if len(inverters) > 0:
self.append(f"set_db cts_inverter_cells {{{' '.join(inverters)}}}")
gates = self.technology.get_special_cell_by_type(CellType.CTSGate)[0].name
if len(gates) > 0:
self.append(f"set_db cts_clock_gating_cells {{{' '.join(gates)}}}")
logics = self.technology.get_special_cell_by_type(CellType.CTSLogic)[0].name
if len(logics) > 0:
self.append(f"set_db cts_logic_cells {{{' '.join(logics)}}}")
self.verbose_append("create_clock_tree_spec")
if bool(self.get_setting("par.innovus.use_cco")):
# -hold is a secret flag for ccopt_design (undocumented anywhere)
Expand Down
14 changes: 8 additions & 6 deletions hammer/par/innovus/defaults.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,20 @@

par.innovus:
# Location of the binary.
innovus_bin: "${cadence.cadence_home}/INNOVUS/INNOVUS${par.innovus.version}/bin/innovus"
innovus_bin: "${cadence.cadence_home}/DDI/DDI${par.innovus.version}/INNOVUS${par.innovus.version}/bin/innovus"
innovus_bin_meta: lazysubst # we want later overrides to be able to affect this

# Innovus version to use.
# Used to locate the binary - e.g. the '171' in ${cadence.cadence_home}/INNOVUS/INNOVUS171/bin/innovus
# 171_ISR3 supports ILMs properly in contrast to 171.
version: "171_ISR3"
# Used to locate the binary - e.g. the '221' in ${cadence.cadence_home}/DDI/DDI221/INNOVUS2211/bin/innovus
version: "221"

# Design flow effort.
# Valid options: express (fastest), standard, and extreme (slowest).
# Default: express to increase turnaround speed.
design_flow_effort: "express"
design_flow_effort: "standard"

# Design power effort.
# Valid options: none, low, high.
design_power_effort: "low"

# Floorplanning SDC constraints to use.
# Valid options are:
Expand Down
30 changes: 22 additions & 8 deletions hammer/synthesis/genus/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,7 @@ def do_pre_steps(self, first_step: HammerToolStep) -> bool:
def do_between_steps(self, prev: HammerToolStep, next: HammerToolStep) -> bool:
assert super().do_between_steps(prev, next)
# Write a checkpoint to disk.
if self.version() >= self.version_number("221"):
# -common now enables database reading in Innovus
self.verbose_append("write_db -common -to_file pre_{step}".format(step=next.name))
else:
self.verbose_append("write_db -to_file pre_{step}".format(step=next.name))
self.verbose_append("write_db -to_file pre_{step}".format(step=next.name))
return True

def do_post_steps(self) -> bool:
Expand Down Expand Up @@ -198,10 +194,9 @@ def init_environment(self) -> bool:
# Clock gating setup
if self.get_setting("synthesis.clock_gating_mode") == "auto":
verbose_append("set_db lp_clock_gating_infer_enable true")
# Innovus will create instances named CLKGATE_foo, CLKGATE_bar, etc.
# Genus will create instances named CLKGATE_foo, CLKGATE_bar, etc.
verbose_append("set_db lp_clock_gating_prefix {CLKGATE}")
verbose_append("set_db lp_insert_clock_gating true")
verbose_append("set_db lp_insert_clock_gating_incremental true")
verbose_append("set_db lp_clock_gating_register_aware true")

# Set up libraries.
Expand Down Expand Up @@ -287,6 +282,22 @@ def retime_modules(self) -> bool:
return True

def syn_generic(self) -> bool:
# Add clock mapping flow if special cells are specified
if self.version() >= self.version_number("211"):
buffers = self.technology.get_special_cell_by_type(CellType.CTSBuffer)[0].name
if len(buffers) > 0:
self.append(f"set_db cts_buffer_cells {{{' '.join(buffers)}}}")
inverters = self.technology.get_special_cell_by_type(CellType.CTSInverter)[0].name
if len(inverters) > 0:
self.append(f"set_db cts_inverter_cells {{{' '.join(inverters)}}}")
gates = self.technology.get_special_cell_by_type(CellType.CTSGate)[0].name
if len(gates) > 0:
self.append(f"set_db cts_clock_gating_cells {{{' '.join(gates)}}}")
logics = self.technology.get_special_cell_by_type(CellType.CTSLogic)[0].name
if len(logics) > 0:
self.append(f"set_db cts_logic_cells {{{' '.join(logics)}}}")
if any(c > 0 for c in [len(buffers), len(inverters), len(gates), len(logics)]):
self.append("set_db map_clock_tree true")
self.verbose_append("syn_generic")
return True

Expand Down Expand Up @@ -348,7 +359,10 @@ def write_outputs(self) -> bool:
verbose_append("write_hdl > {}".format(self.mapped_v_path))
if self.hierarchical_mode.is_nonleaf_hierarchical() and self.version() >= self.version_number("191"):
verbose_append("write_hdl -exclude_ilm > {}".format(self.mapped_hier_v_path))
verbose_append("write_script > {}.mapped.scr".format(top))
if self.version() >= self.version_number("221"):
verbose_append("write_template -full -outfile {}.mapped.scr".format(top))
else:
verbose_append("write_script > {}.mapped.scr".format(top))
corners = self.get_mmmc_corners()
if corners:
# First setup corner is default view
Expand Down
6 changes: 3 additions & 3 deletions hammer/synthesis/genus/defaults.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Default settings for synthesis in Genus, for project/technology configuration and overriding.
synthesis.genus:
# Location of the binary.
genus_bin: "${cadence.cadence_home}/GENUS/GENUS${synthesis.genus.version}/bin/genus"
genus_bin: "${cadence.cadence_home}/DDI/DDI${synthesis.genus.version}/GENUS${synthesis.genus.version}/bin/genus"
genus_bin_meta: lazysubst # we want later overrides to be able to affect this

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

# Generate the TCL file but do not run it yet.
generate_only: false
3 changes: 3 additions & 0 deletions hammer/tech/specialcells.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ class CellType(str, Enum):
TapCell = "tapcell"
Driver = "driver"
CTSBuffer = "ctsbuffer"
CTSInverter = "ctsinverter"
CTSGate = "ctsgate"
CTSLogic = "ctslogic"


class SpecialCell(BaseModel):
Expand Down
2 changes: 1 addition & 1 deletion hammer/vlsi/constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ def name_bump(self, definition: BumpsDefinition, assignment: BumpAssignment) ->

OutputLoadConstraint = NamedTuple('OutputLoadConstraint', [
('name', str),
('load', float)
('load', CapacitanceValue)
])


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 @@ -1558,7 +1558,7 @@ def get_output_load_constraints(self) -> List[OutputLoadConstraint]:
for load_src in output_loads:
load = OutputLoadConstraint(
name=str(load_src["name"]),
load=float(load_src["load"])
load=CapacitanceValue(load_src["load"])
)
output.append(load)
return output
Expand Down
10 changes: 6 additions & 4 deletions hammer/vlsi/hammer_vlsi_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -2170,7 +2170,9 @@ def sdc_pin_constraints(self) -> str:
"""Generate a fragment for I/O pin constraints."""
output = [] # type: List[str]

default_output_load = float(self.get_setting("vlsi.inputs.default_output_load"))
output.append("set_units -capacitance fF")

default_output_load = CapacitanceValue(self.get_setting("vlsi.inputs.default_output_load")).value_in_units("fF", round_zeroes = True)

# Specify default load.
output.append("set_load {load} [all_outputs]".format(
Expand All @@ -2179,14 +2181,14 @@ def sdc_pin_constraints(self) -> str:

# Also specify loads for specific pins.
for load in self.get_output_load_constraints():
output.append("set_load {load} [get_port \"{name}\"]".format(
load=load.load,
output.append("set_load {load} [get_port {name}]".format(
load=load.load.value_in_units("fF", round_zeroes = True),
name=load.name
))

# Also specify delays for specific pins.
for delay in self.get_delay_constraints():
output.append("set_{direction}_delay {delay} -clock {clock} [get_port \"{name}\"]".format(
output.append("set_{direction}_delay {delay} -clock {clock} [get_port {name}]".format(
delay=delay.delay.value_in_units(self.get_time_unit().value_prefix + self.get_time_unit().unit),
clock=delay.clock,
direction=delay.direction,
Expand Down