From cf30e0d1ae308db9d71252455e1dfe605d35ec27 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Fri, 3 Nov 2023 16:11:17 -0700 Subject: [PATCH] Add bottom_via_layer api for power_straps.by_tracks (#815) The default setting "rail" uses the stdcell rail layer. This can be set to a different metal layer if desired --- hammer/config/defaults.yml | 5 +++++ hammer/config/defaults_types.yml | 4 ++++ hammer/vlsi/hammer_vlsi_impl.py | 16 +++++++++++----- tests/test_power_straps.py | 8 ++++++-- 4 files changed, 26 insertions(+), 7 deletions(-) diff --git a/hammer/config/defaults.yml b/hammer/config/defaults.yml index 4fa1a0c89..7ad50b127 100644 --- a/hammer/config/defaults.yml +++ b/hammer/config/defaults.yml @@ -616,6 +616,11 @@ par: generate_rail_layer: true # If true, generates straps on the stdcell rail layer - technology.core.std_cell_rail_layer # type: bool + bottom_via_layer: "rail" # Sets what the lowest power strap layer should generate vias to + # Usually should be set to rail, which will use technology.core.std_cell_rail_layer as this setting + # Otherwise should be set to some layer name + # type: str + # DRC settings drc.inputs: # DRC settings diff --git a/hammer/config/defaults_types.yml b/hammer/config/defaults_types.yml index efe311574..d7227e78d 100644 --- a/hammer/config/defaults_types.yml +++ b/hammer/config/defaults_types.yml @@ -330,6 +330,10 @@ par: # type: bool generate_rail_layer: bool + # Indicates bottom layer to via to during power strap generation + # type: str + bottom_via_layer: str + # DRC settings drc.inputs: # Top RTL module. diff --git a/hammer/vlsi/hammer_vlsi_impl.py b/hammer/vlsi/hammer_vlsi_impl.py index 551881451..763682dcd 100644 --- a/hammer/vlsi/hammer_vlsi_impl.py +++ b/hammer/vlsi/hammer_vlsi_impl.py @@ -649,13 +649,19 @@ def generate_power_straps_tcl(self) -> List[str]: generate_rail_layer = self.get_setting("{}.generate_rail_layer".format(namespace)) ground_net_names = list(map(lambda x: x.name, self.get_independent_ground_nets())) # type: List[str] power_net_names = list(map(lambda x: x.name, self.get_independent_power_nets())) # type: List[str] + bottom_via_option = self.get_setting("{}.bottom_via_layer".format(namespace)) + if bottom_via_option == "rail": + bottom_via_layer = self.get_setting("technology.core.std_cell_rail_layer") + else: + bottom_via_layer = bottom_via_option + def get_weight(s: Supply) -> int: # Check that it's not None assert isinstance(s.weight, int) return s.weight weights = list(map(get_weight, self.get_independent_power_nets())) # type: List[int] assert len(ground_net_names) == 1, "FIXME, I am assuming there's only 1 ground net" - return self.specify_all_power_straps_by_tracks(layers, ground_net_names[0], power_net_names, weights, bbox, pin_layers, generate_rail_layer) + return self.specify_all_power_straps_by_tracks(layers, bottom_via_layer, ground_net_names[0], power_net_names, weights, bbox, pin_layers, generate_rail_layer) else: raise NotImplementedError("Power strap generation method %s is not implemented" % method) @@ -706,7 +712,7 @@ def specify_power_straps_by_tracks(self, layer_name: str, bottom_via_layer: str, self._get_power_straps_for_hardmacros(layer_name, pitch, width, spacing, offset, bbox, nets) return self.specify_power_straps(layer_name, bottom_via_layer, blockage_spacing, pitch, width, spacing, offset, bbox, nets, add_pins, antenna_trim_shape) - def specify_all_power_straps_by_tracks(self, layer_names: List[str], ground_net: str, power_nets: List[str], power_weights: List[int], bbox: Optional[List[Decimal]], pin_layers: List[str], generate_rail_layer: bool) -> List[str]: + def specify_all_power_straps_by_tracks(self, layer_names: List[str], bottom_via_layer: str, ground_net: str, power_nets: List[str], power_weights: List[int], bbox: Optional[List[Decimal]], pin_layers: List[str], generate_rail_layer: bool) -> List[str]: """ Generate a list of TCL commands that will create power straps on a given set of layers by specifying the desired per-track track consumption and utilization. This will build standard cell power strap rails first. Layer-specific parameters are read from the hammer config: @@ -717,6 +723,7 @@ def specify_all_power_straps_by_tracks(self, layer_names: List[str], ground_net: These settings are all overridable by appending an underscore followed by the metal name (e.g. power_utilization_M3). :param layer_names: The list of metal layer names on which to create straps. + :param bottom_via_layer: The layer the lowest-strap layer will via down to. Usually the stdcell rail layer :param ground_net: The name of the ground net in this design. Only 1 ground net is supported. :param power_nets: A list of power nets to create (not ground). :param power_weights: Specifies the power strap placement pattern for multiple-domain designs (e.g. ["VDDA", "VDDB"] with [2, 1] will produce 2 VDDA straps for ever 1 VDDB strap). @@ -737,10 +744,9 @@ def specify_all_power_straps_by_tracks(self, layer_names: List[str], ground_net: blockage_spacing = coerce_to_grid(float(self._get_by_tracks_metal_setting("blockage_spacing", rail_layer_name)), rail_layer.grid_unit) # TODO does the CPF help this, or do we need to be more explicit about the bbox for each domain output.extend(self.specify_std_cell_power_straps(blockage_spacing, bbox, [ground_net] + power_nets)) - # The layer to via down to - bottom_via_layer = rail_layer_name + # The last layer we used - last = rail_layer + last = self.get_stackup().get_metal(bottom_via_layer) substrate_json = [] # type: List[Dict[str, Any]] diff --git a/tests/test_power_straps.py b/tests/test_power_straps.py index eb1790960..af9e46751 100644 --- a/tests/test_power_straps.py +++ b/tests/test_power_straps.py @@ -86,6 +86,7 @@ def simple_straps_options() -> Dict[str, Any]: power_utilization_M8 = 1.0 track_start_M5 = 1 track_offset_M5 = 1.2 + bottom_via_layer = "rail" # VSS comes before VDD nets = ["VSS", "VDD"] @@ -110,7 +111,8 @@ def simple_straps_options() -> Dict[str, Any]: "power_utilization": power_utilization, "power_utilization_M8": power_utilization_M8, "track_start_M5": track_start_M5, - "track_offset_M5": track_offset_M5 + "track_offset_M5": track_offset_M5, + "bottom_via_layer": bottom_via_layer } } return straps_options @@ -123,6 +125,7 @@ def multiple_domains_straps_options() -> Dict[str, Any]: track_spacing = 0 power_utilization = 0.2 power_utilization_M8 = 1.0 + bottom_via_layer = "rail" straps_options = { "vlsi.inputs.supplies": { @@ -139,7 +142,8 @@ def multiple_domains_straps_options() -> Dict[str, Any]: "track_width": track_width, "track_spacing": track_spacing, "power_utilization": power_utilization, - "power_utilization_M8": power_utilization_M8 + "power_utilization_M8": power_utilization_M8, + "bottom_via_layer": bottom_via_layer } } return straps_options