Skip to content

Commit

Permalink
Fix support for hybrid height technologies in place_and_route rule.
Browse files Browse the repository at this point in the history
  • Loading branch information
mikesinouye committed Mar 15, 2024
1 parent eb7f96f commit 801a85d
Show file tree
Hide file tree
Showing 5 changed files with 578 additions and 566 deletions.
247 changes: 105 additions & 142 deletions pdk/open_road_configuration.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -12,158 +12,121 @@
# See the License for the specific language governing permissions and
# limitations under the License.

"""Rules for defining OpenROAD configuration for various PDKs"""
"""Floorplaning openROAD commands"""

OpenRoadPdkInfo = provider(
"provider for openROAD configuration for a pdk",
fields = {
"cell_site": "LEF standard cell site name to use for floorplanning",
"tracks_file": "Track setup script",
"endcap_cell": "The endcap cell to use in place and route",
"tap_cell": "The tap cell to use in the place and route.",
"pin_horizontal_metal_layer": "",
"pin_vertical_metal_layer": "",
"tapcell_distance": "Number of sites ",
"wire_rc_signal_metal_layer": "The metal layer to pull RC information for signal nets",
"wire_rc_clock_metal_layer": "The metal layer to pull RC information for clock nets",
"pdn_config": "PDN config",
"global_placement_cell_pad": "Global placement cell padding to aide in routing",
"do_not_use_cell_list": "Do not use cells in timing repair. This supports wild card * cell names",
"cts_buffer_cell": "Clock Tree Buffer cell",
"fill_cells": "Metal fill cells",
"ha_fa_mapping": "HA/FA techmapping file",
"global_routing_layer_adjustments": "Global routing adjustment layers",
"global_routing_clock_layers": "Clock routing layers",
"global_routing_signal_layers": "Signal routing layers",
"tie_low_port": "Tie low port",
"tie_high_port": "Tie high port",
"tie_separation": "Tie sepearation value",
"rc_script_configuration": "RC script for the various metal layers",
"tapcell_tcl": "TCL file that sets tapcell options. This overrides other tapcell attributes in this rule.",
"placement_padding_tcl": "TCL Script for handling the placement padding of cells",
"check_placement": "Check the placement in the placement script",
"detailed_routing_configuration": "optional detailed routing configuration",
"density_fill_config": "optional path to file with metal fill configuration",
"klayout_tech_file": "KLayout technology file for GDS write",
},
)
load("//third_party/bazel_rules_hdl/pdk:open_road_configuration.bzl", "get_open_road_configuration")
load("//third_party/bazel_rules_hdl/place_and_route:open_road.bzl", "OpenRoadInfo", "openroad_command")
load("//third_party/bazel_rules_hdl/place_and_route:private/report_area.bzl", "generate_area_results")
load("//third_party/bazel_rules_hdl/place_and_route:private/report_power.bzl", "generate_power_results")
load("//third_party/bazel_rules_hdl/synthesis:build_defs.bzl", "SynthesisInfo")

DetailedRoutingInfo = provider(
"Detailed routing info params for OpenROAD",
fields = ["bottom_routing_layer", "top_routing_layer", "via_in_pin_bottom_layer", "via_in_pin_top_layer", "enable_via_gen"],
)
def _initialize_floorplan_command(ctx):
open_road_configuration = get_open_road_configuration(ctx.attr.synthesized_rtl[SynthesisInfo])

def _open_road_pdk_configuration_impl(ctx):
return [
OpenRoadPdkInfo(
cell_site = ctx.attr.cell_site,
tracks_file = ctx.file.tracks_file,
tap_cell = ctx.attr.tap_cell,
pin_vertical_metal_layer = ctx.attr.pin_vertical_metal_layer,
pin_horizontal_metal_layer = ctx.attr.pin_horizontal_metal_layer,
tapcell_distance = ctx.attr.tapcell_distance,
endcap_cell = ctx.attr.endcap_cell,
pdn_config = ctx.file.pdn_config,
wire_rc_signal_metal_layer = ctx.attr.wire_rc_signal_metal_layer,
wire_rc_clock_metal_layer = ctx.attr.wire_rc_clock_metal_layer,
global_placement_cell_pad = ctx.attr.global_placement_cell_pad,
do_not_use_cell_list = ctx.attr.do_not_use_cell_list,
cts_buffer_cell = ctx.attr.cts_buffer_cell,
fill_cells = ctx.attr.fill_cells,
ha_fa_mapping = ctx.attr.ha_fa_mapping,
global_routing_layer_adjustments = ctx.attr.global_routing_layer_adjustments,
global_routing_clock_layers = ctx.attr.global_routing_clock_layers,
global_routing_signal_layers = ctx.attr.global_routing_signal_layers,
tie_low_port = ctx.attr.tie_low_port,
tie_high_port = ctx.attr.tie_high_port,
tie_separation = ctx.attr.tie_separation,
rc_script_configuration = ctx.file.rc_script_configuration,
tapcell_tcl = ctx.file.tapcell_tcl,
placement_padding_tcl = ctx.file.placement_padding_tcl,
check_placement = ctx.attr.check_placement,
detailed_routing_configuration = ctx.attr.detailed_routing_configuration,
density_fill_config = ctx.attr.density_fill_config,
klayout_tech_file = ctx.attr.klayout_tech_file,
),
]

open_road_pdk_configuration = rule(
implementation = _open_road_pdk_configuration_impl,
attrs = {
"cell_site": attr.string(mandatory = True, doc = "LEF standard cell site name."),
"tracks_file": attr.label(mandatory = True, allow_single_file = True, doc = "Track setup script."),
"pdn_config": attr.label(mandatory = True, allow_single_file = True, doc = "PDN Config."),
"tap_cell": attr.string(),
"pin_horizontal_metal_layer": attr.string(mandatory = True),
"pin_vertical_metal_layer": attr.string(mandatory = True),
"tapcell_distance": attr.int(),
"endcap_cell": attr.string(),
"wire_rc_signal_metal_layer": attr.string(mandatory = True),
"wire_rc_clock_metal_layer": attr.string(mandatory = True),
"global_placement_cell_pad": attr.int(mandatory = True),
"do_not_use_cell_list": attr.string_list(mandatory = True, doc = "This value can be an empty list if all cells should be used in P&R"),
"cts_buffer_cell": attr.string(mandatory = True, doc = "Clock Tree Buffer cell"),
"fill_cells": attr.string_list(mandatory = True),
"ha_fa_mapping": attr.label(allow_single_file = True, doc = "Yosys specific HA/FA techmapping file"),
"global_routing_layer_adjustments": attr.string_dict(mandatory = True),
"global_routing_clock_layers": attr.string(mandatory = True),
"global_routing_signal_layers": attr.string(mandatory = True),
"tie_low_port": attr.string(mandatory = True),
"tie_high_port": attr.string(mandatory = True),
"tie_separation": attr.int(mandatory = True),
"rc_script_configuration": attr.label(allow_single_file = True),
"tapcell_tcl": attr.label(allow_single_file = True, doc = "TCL file that sets tapcell options. This overrides other tapcell attributes in this rule."),
"placement_padding_tcl": attr.label(allow_single_file = True, doc = "TCL Script for handling the placement padding of cells"),
"check_placement": attr.bool(mandatory = False, default = True),
"detailed_routing_configuration": attr.label(providers = [DetailedRoutingInfo]),
"density_fill_config": attr.label(allow_single_file = True),
"klayout_tech_file": attr.label(mandatory = True, allow_single_file = True),
},
)
if ctx.attr.die_width_microns and ctx.attr.die_height_microns:
return "initialize_floorplan -site \"{site}\" -additional_sites \"{additional_cell_sites}\" -die_area {die_area} -core_area {core_area}".format(
die_area = "\"0 0 {width} {height}\"".format(
width = ctx.attr.die_width_microns,
height = ctx.attr.die_height_microns,
),
core_area = "\"{lx} {ly} {ux} {uy}\"".format(
lx = ctx.attr.core_padding_microns,
ly = ctx.attr.core_padding_microns,
ux = ctx.attr.die_width_microns - ctx.attr.core_padding_microns,
uy = ctx.attr.die_height_microns - ctx.attr.core_padding_microns,
),
site = open_road_configuration.cell_site,
additional_cell_sites = " ".join(open_road_configuration.additional_cell_sites),
)

def detailed_routing_configuration_impl(ctx):
return [DetailedRoutingInfo(
bottom_routing_layer = ctx.attr.bottom_routing_layer,
top_routing_layer = ctx.attr.top_routing_layer,
via_in_pin_bottom_layer = ctx.attr.via_in_pin_bottom_layer,
via_in_pin_top_layer = ctx.attr.via_in_pin_top_layer,
enable_via_gen = ctx.attr.enable_via_gen,
)]
if ctx.attr.target_die_utilization_percentage:
utilization = ctx.attr.target_die_utilization_percentage #TODO(bazel): When bazel 4.0.0 is avaliable use float command
return "initialize_floorplan -site \"{site}\" -additional_sites \"{additional_cell_sites}\" -utilization {utilization} -core_space {core_space}".format(
utilization = utilization,
core_space = ctx.attr.core_padding_microns,
site = open_road_configuration.cell_site,
additional_cell_sites = " ".join(open_road_configuration.additional_cell_sites),
)

detailed_routing_configuration = rule(
implementation = detailed_routing_configuration_impl,
attrs = {
"bottom_routing_layer": attr.string(mandatory = True, doc = "Minimum routing layer name"),
"top_routing_layer": attr.string(mandatory = True, doc = "Maximum routing layer name"),
"via_in_pin_bottom_layer": attr.string(doc = "via in pin bottom layer"),
"via_in_pin_top_layer": attr.string(doc = "via in pin top layer"),
"enable_via_gen": attr.bool(default = True),
},
provides = [DetailedRoutingInfo],
)
fail("either (die_width_microns and die_height_microns) or `utilization` must be set")

def assert_has_open_road_configuration(synthesis_info):
"""Asserts if PDK is missing openROAD configuration.
Args:
synthesis_info: bazel rule context.
"""
if not get_open_road_configuration(synthesis_info):
fail("The PDK used for synthesis does not have an OpenROAD configuration.")

def get_open_road_configuration(synthesis_info):
"""Returns the openROAD configuration for the synthesized netlist.
def init_floor_plan(ctx):
"""Initializes the floor plan based on user ctx args.
Returns:
OpenRoadInfo: the openROAD info provider containing required input files and
and commands run.
Args:
synthesis_info: SynthesisInfo provider to extract openROAD configuration from.
ctx: Bazel rule ctx
Returns:
OpenRoadPdkInfo: The openroad pdk information.
"""
netlist_target = ctx.attr.synthesized_rtl
open_road_configuration = get_open_road_configuration(netlist_target[SynthesisInfo])
netlist = netlist_target[SynthesisInfo].synthesized_netlist
top_module = netlist_target[SynthesisInfo].top_module
liberty = netlist_target[SynthesisInfo].standard_cell_info.default_corner.liberty
additional_liberties = [corner.liberty for corner in netlist_target[SynthesisInfo].standard_cell_info.corners]
tech_lef = netlist_target[SynthesisInfo].standard_cell_info.tech_lef
std_cell_lef = netlist_target[SynthesisInfo].standard_cell_info.cell_lef_definitions
verilog_based_power_results = ctx.actions.declare_file("{}_verilog_based_power_results.textproto".format(ctx.attr.name))
verilog_based_area_results = ctx.actions.declare_file("{}_verilog_based_area_results.textproto".format(ctx.attr.name))
tieoneport = open_road_configuration.tie_high_port
tiezeroport = open_road_configuration.tie_low_port

open_road_commands = [
"read_lef {tech_lef}".format(
tech_lef = tech_lef.path,
),
]
for file in std_cell_lef:
open_road_commands.append("read_lef {}".format(file.path))
for file in [liberty] + additional_liberties:
open_road_commands.append("read_liberty {liberty}".format(liberty = file.path))
open_road_commands.extend([
"read_verilog {verilog}".format(
verilog = netlist.path,
),
"link_design {top_module}".format(
top_module = top_module,
),
_initialize_floorplan_command(ctx),
"source {tracks_file}".format(
tracks_file = open_road_configuration.tracks_file.path,
),
"remove_buffers",
"insert_tiecells {port} -prefix \"TIE_ONE_\"".format(
port = tieoneport,
),
"insert_tiecells {port} -prefix \"TIE_ZERO_\"".format(
port = tiezeroport,
),
])
open_road_commands.extend(generate_power_results(ctx, verilog_based_power_results))
open_road_commands.extend(generate_area_results(verilog_based_area_results))

standard_cell_info = synthesis_info.standard_cell_info
input_open_road_files = [
netlist,
liberty,
tech_lef,
open_road_configuration.tracks_file,
] + std_cell_lef + additional_liberties

if not standard_cell_info:
fail("This rule is missing the standard cell info attached to the synthesized verilog.")
command_output = openroad_command(
ctx,
commands = open_road_commands,
inputs = input_open_road_files,
step_name = "floorplan",
outputs = [
verilog_based_power_results,
verilog_based_area_results,
],
)

return standard_cell_info.open_road_configuration
return OpenRoadInfo(
commands = open_road_commands,
output_db = command_output.db,
logs = depset([command_output.log_file]),
input_files = depset(direct = input_open_road_files),
verilog_based_power_results = verilog_based_power_results,
verilog_based_area_results = verilog_based_area_results,
)
Loading

0 comments on commit 801a85d

Please sign in to comment.