Use the initial bbox to route supply and signals

This commit is contained in:
Eren Dogan 2023-08-02 18:01:09 -07:00
parent 08dad81214
commit 87eca6b7db
5 changed files with 30 additions and 46 deletions

View File

@ -111,12 +111,15 @@ class rom_bank(design,rom_verilog):
self.place_top_level_pins()
self.route_output_buffers()
self.route_supplies()
# FIXME: Somehow ROM layout behaves weird and doesn't add all the pin
# shapes before routing supplies
init_bbox = self.get_bbox()
self.route_supplies(init_bbox)
# Route the pins to the perimeter
if OPTS.perimeter_pins:
# We now route the escape routes far enough out so that they will
# reach past the power ring or stripes on the sides
self.route_escape_pins()
self.route_escape_pins(init_bbox)
def setup_layout_constants(self):
@ -441,7 +444,7 @@ class rom_bank(design,rom_verilog):
pin_num = msb - self.col_bits
self.add_io_pin(self.decode_inst, "A{}".format(pin_num), name)
def route_supplies(self):
def route_supplies(self, bbox):
for pin_name in ["vdd", "gnd"]:
for inst in self.insts:
@ -454,6 +457,7 @@ class rom_bank(design,rom_verilog):
from openram.router import supply_router as router
rtr = router(layers=self.supply_stack,
design=self,
bbox=bbox,
pin_type=OPTS.supply_pin_type)
rtr.route()
@ -479,7 +483,7 @@ class rom_bank(design,rom_verilog):
pin.width(),
pin.height())
def route_escape_pins(self):
def route_escape_pins(self, bbox):
pins_to_route = []
for bit in range(self.col_bits):
@ -495,5 +499,6 @@ class rom_bank(design,rom_verilog):
pins_to_route.append("cs")
from openram.router import signal_escape_router as router
rtr = router(layers=self.m3_stack,
bbox=bbox,
design=self)
rtr.route(pins_to_route)

View File

@ -243,7 +243,7 @@ class sram_1bank(design, verilog, lef):
def create_modules(self):
debug.error("Must override pure virtual function.", -1)
def route_supplies(self):
def route_supplies(self, bbox=None):
""" Route the supply grid and connect the pins to them. """
# Copy the pins to the top level
@ -259,6 +259,7 @@ class sram_1bank(design, verilog, lef):
from openram.router import supply_router as router
rtr = router(layers=self.supply_stack,
design=self,
bbox=bbox,
pin_type=OPTS.supply_pin_type)
rtr.route()
@ -322,7 +323,7 @@ class sram_1bank(design, verilog, lef):
# Grid is left with many top level pins
pass
def route_escape_pins(self):
def route_escape_pins(self, bbox=None):
"""
Add the top-level pins for a single bank SRAM with control.
"""
@ -367,6 +368,7 @@ class sram_1bank(design, verilog, lef):
from openram.router import signal_escape_router as router
rtr = router(layers=self.m3_stack,
bbox=bbox,
design=self)
rtr.route(pins_to_route)
@ -1072,14 +1074,15 @@ class sram_1bank(design, verilog, lef):
# Some technologies have an isolation
self.add_dnwell(inflate=2.5)
init_bbox = self.get_bbox()
# Route the supplies together and/or to the ring/stripes.
# Route the pins to the perimeter
if OPTS.perimeter_pins:
# We now route the escape routes far enough out so that they will
# reach past the power ring or stripes on the sides
self.route_escape_pins()
self.route_escape_pins(init_bbox)
self.route_supplies()
self.route_supplies(init_bbox)
def route_dffs(self, add_routes=True):

View File

@ -20,7 +20,7 @@ class router(router_tech):
This is the base class for routers that use the Hanan grid graph method.
"""
def __init__(self, layers, design):
def __init__(self, layers, design, bbox=None):
# `router_tech` contains tech constants for the router
router_tech.__init__(self, layers, route_track_width=1)
@ -32,7 +32,13 @@ class router(router_tech):
# Temporary GDSII file name to find pins and blockages
self.gds_filename = OPTS.openram_temp + "temp.gds"
# Calculate the bounding box for routing around the perimeter
self.bbox = self.design.get_bbox(margin=11 * self.track_width)
# FIXME: We wouldn't do this if `rom_bank` wasn't behaving weird
if bbox is None:
self.bbox = self.design.get_bbox(margin=11 * self.track_width)
else:
ll, ur = bbox
margin = vector([11 * self.track_width] * 2)
self.bbox = [ll - margin, ur + margin]
# Dictionary for vdd and gnd pins
self.pins = {}
# Set of all the pins

View File

@ -16,10 +16,10 @@ class signal_escape_router(router):
This is the signal escape router that uses the Hanan grid graph method.
"""
def __init__(self, layers, design):
def __init__(self, layers, design, bbox=None):
# `router_tech` contains tech constants for the router
router.__init__(self, layers, design)
router.__init__(self, layers, design, bbox)
# New pins are the side supply pins
self.new_pins = {}
@ -53,7 +53,6 @@ class signal_escape_router(router):
self.blockages.append(self.inflate_shape(pin))
# Route vdd and gnd
i = 0
for source, target, _ in self.get_route_pairs(pin_names):
# Change fake pin's name so the graph will treat it as routable
target.name = source.name

View File

@ -16,10 +16,10 @@ class supply_router(router):
This is the supply router that uses the Hanan grid graph method.
"""
def __init__(self, layers, design, pin_type=None):
def __init__(self, layers, design, bbox=None, pin_type=None):
# `router_tech` contains tech constants for the router
router.__init__(self, layers, design)
router.__init__(self, layers, design, bbox)
# Side supply pin type
# (can be "top", "bottom", "right", "left", and "ring")
@ -52,7 +52,6 @@ class supply_router(router):
self.convert_blockages()
# Add side pins
self.calculate_ring_bbox()
if self.pin_type in ["top", "bottom", "right", "left"]:
self.add_side_pin(vdd_name)
self.add_side_pin(gnd_name)
@ -84,7 +83,7 @@ class supply_router(router):
# larger routing region
if path is None:
rll, rur = region
bll, bur = self.ring_bbox
bll, bur = self.bbox
# Stop scaling the region and throw an error
if rll.x < bll.x and rll.y < bll.y and \
rur.x > bur.x and rur.y > bur.y:
@ -103,38 +102,10 @@ class supply_router(router):
break
def calculate_ring_bbox(self, num_vias=3):
""" Calculate the ring-safe bounding box of the layout. """
ll, ur = self.bbox
# Calculate the "wideness" of a side supply pin
wideness = self.track_wire * num_vias + self.track_space * (num_vias - 1)
# Total wideness is used to find it any pin overlaps in this region. If
# so, the bbox is shifted to prevent this overlap.
total_wideness = wideness * 4
for blockage in self.blockages:
bll, bur = blockage.rect
if self.get_zindex(blockage.lpp) == 1: # Vertical
diff = ll.x + total_wideness - bll.x
if diff > 0:
ll = vector(ll.x - diff, ll.y)
diff = ur.x - total_wideness - bur.x
if diff < 0:
ur = vector(ur.x - diff, ur.y)
else: # Horizontal
diff = ll.y + total_wideness - bll.y
if diff > 0:
ll = vector(ll.x, ll.y - diff)
diff = ur.y - total_wideness - bur.y
if diff < 0:
ur = vector(ur.x, ur.y - diff)
self.ring_bbox = [ll, ur]
def add_side_pin(self, pin_name, side, num_vias=3, num_fake_pins=4):
""" Add supply pin to one side of the layout. """
ll, ur = self.ring_bbox
ll, ur = self.bbox
vertical = side in ["left", "right"]
inner = pin_name == self.gnd_name