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.place_top_level_pins()
self.route_output_buffers() 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 # Route the pins to the perimeter
if OPTS.perimeter_pins: if OPTS.perimeter_pins:
# We now route the escape routes far enough out so that they will # We now route the escape routes far enough out so that they will
# reach past the power ring or stripes on the sides # 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): def setup_layout_constants(self):
@ -441,7 +444,7 @@ class rom_bank(design,rom_verilog):
pin_num = msb - self.col_bits pin_num = msb - self.col_bits
self.add_io_pin(self.decode_inst, "A{}".format(pin_num), name) 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 pin_name in ["vdd", "gnd"]:
for inst in self.insts: for inst in self.insts:
@ -454,6 +457,7 @@ class rom_bank(design,rom_verilog):
from openram.router import supply_router as router from openram.router import supply_router as router
rtr = router(layers=self.supply_stack, rtr = router(layers=self.supply_stack,
design=self, design=self,
bbox=bbox,
pin_type=OPTS.supply_pin_type) pin_type=OPTS.supply_pin_type)
rtr.route() rtr.route()
@ -479,7 +483,7 @@ class rom_bank(design,rom_verilog):
pin.width(), pin.width(),
pin.height()) pin.height())
def route_escape_pins(self): def route_escape_pins(self, bbox):
pins_to_route = [] pins_to_route = []
for bit in range(self.col_bits): for bit in range(self.col_bits):
@ -495,5 +499,6 @@ class rom_bank(design,rom_verilog):
pins_to_route.append("cs") pins_to_route.append("cs")
from openram.router import signal_escape_router as router from openram.router import signal_escape_router as router
rtr = router(layers=self.m3_stack, rtr = router(layers=self.m3_stack,
bbox=bbox,
design=self) design=self)
rtr.route(pins_to_route) rtr.route(pins_to_route)

View File

@ -243,7 +243,7 @@ class sram_1bank(design, verilog, lef):
def create_modules(self): def create_modules(self):
debug.error("Must override pure virtual function.", -1) 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. """ """ Route the supply grid and connect the pins to them. """
# Copy the pins to the top level # 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 from openram.router import supply_router as router
rtr = router(layers=self.supply_stack, rtr = router(layers=self.supply_stack,
design=self, design=self,
bbox=bbox,
pin_type=OPTS.supply_pin_type) pin_type=OPTS.supply_pin_type)
rtr.route() rtr.route()
@ -322,7 +323,7 @@ class sram_1bank(design, verilog, lef):
# Grid is left with many top level pins # Grid is left with many top level pins
pass 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. 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 from openram.router import signal_escape_router as router
rtr = router(layers=self.m3_stack, rtr = router(layers=self.m3_stack,
bbox=bbox,
design=self) design=self)
rtr.route(pins_to_route) rtr.route(pins_to_route)
@ -1072,14 +1074,15 @@ class sram_1bank(design, verilog, lef):
# Some technologies have an isolation # Some technologies have an isolation
self.add_dnwell(inflate=2.5) self.add_dnwell(inflate=2.5)
init_bbox = self.get_bbox()
# Route the supplies together and/or to the ring/stripes. # Route the supplies together and/or to the ring/stripes.
# Route the pins to the perimeter # Route the pins to the perimeter
if OPTS.perimeter_pins: if OPTS.perimeter_pins:
# We now route the escape routes far enough out so that they will # We now route the escape routes far enough out so that they will
# reach past the power ring or stripes on the sides # 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): 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. 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` contains tech constants for the router
router_tech.__init__(self, layers, route_track_width=1) 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 # Temporary GDSII file name to find pins and blockages
self.gds_filename = OPTS.openram_temp + "temp.gds" self.gds_filename = OPTS.openram_temp + "temp.gds"
# Calculate the bounding box for routing around the perimeter # 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 # Dictionary for vdd and gnd pins
self.pins = {} self.pins = {}
# Set of all the 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. 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_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 # New pins are the side supply pins
self.new_pins = {} self.new_pins = {}
@ -53,7 +53,6 @@ class signal_escape_router(router):
self.blockages.append(self.inflate_shape(pin)) self.blockages.append(self.inflate_shape(pin))
# Route vdd and gnd # Route vdd and gnd
i = 0
for source, target, _ in self.get_route_pairs(pin_names): for source, target, _ in self.get_route_pairs(pin_names):
# Change fake pin's name so the graph will treat it as routable # Change fake pin's name so the graph will treat it as routable
target.name = source.name 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. 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_tech` contains tech constants for the router
router.__init__(self, layers, design) router.__init__(self, layers, design, bbox)
# Side supply pin type # Side supply pin type
# (can be "top", "bottom", "right", "left", and "ring") # (can be "top", "bottom", "right", "left", and "ring")
@ -52,7 +52,6 @@ class supply_router(router):
self.convert_blockages() self.convert_blockages()
# Add side pins # Add side pins
self.calculate_ring_bbox()
if self.pin_type in ["top", "bottom", "right", "left"]: if self.pin_type in ["top", "bottom", "right", "left"]:
self.add_side_pin(vdd_name) self.add_side_pin(vdd_name)
self.add_side_pin(gnd_name) self.add_side_pin(gnd_name)
@ -84,7 +83,7 @@ class supply_router(router):
# larger routing region # larger routing region
if path is None: if path is None:
rll, rur = region rll, rur = region
bll, bur = self.ring_bbox bll, bur = self.bbox
# Stop scaling the region and throw an error # Stop scaling the region and throw an error
if rll.x < bll.x and rll.y < bll.y and \ if rll.x < bll.x and rll.y < bll.y and \
rur.x > bur.x and rur.y > bur.y: rur.x > bur.x and rur.y > bur.y:
@ -103,38 +102,10 @@ class supply_router(router):
break 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): def add_side_pin(self, pin_name, side, num_vias=3, num_fake_pins=4):
""" Add supply pin to one side of the layout. """ """ Add supply pin to one side of the layout. """
ll, ur = self.ring_bbox ll, ur = self.bbox
vertical = side in ["left", "right"] vertical = side in ["left", "right"]
inner = pin_name == self.gnd_name inner = pin_name == self.gnd_name