Perform signal escape routing in smaller regions

This commit is contained in:
Eren Dogan 2023-08-27 21:16:34 -07:00
parent 9df3c2ac59
commit 53cc99f5c1
1 changed files with 81 additions and 11 deletions

View File

@ -5,6 +5,7 @@
#
from openram import debug
from openram.base.vector import vector
from openram.base.vector3d import vector3d
from openram import OPTS
from .graph import graph
from .graph_shape import graph_shape
@ -75,9 +76,51 @@ class signal_escape_router(router):
self.replace_layout_pins()
def prepare_path(self, path):
"""
Override the `prepare_path` method from the `router` class to prevent
overflows from the SRAM layout area.
"""
ll, ur = self.bbox
nodes = super().prepare_path(path)
new_nodes = []
for i in range(len(nodes)):
node = nodes[i]
c = node.center
# Haven't overflown yet
if ll.x < c.x and c.x < ur.x and ll.y < c.y and c.y < ur.y:
new_nodes.append(node)
continue
# Snap the pin to the perimeter and break the iteration
ll_diff_x = abs(c.x - ll.x)
ll_diff_y = abs(c.y - ll.y)
ur_diff_x = abs(c.x - ur.x)
ur_diff_y = abs(c.y - ur.y)
min_diff = min(ll_diff_x, ll_diff_y, ur_diff_x, ur_diff_y)
if min_diff == ll_diff_x:
fake_center = vector3d(ll.x + self.half_wire, c.y, c.z)
if min_diff == ll_diff_y:
fake_center = vector3d(c.x, ll.y + self.half_wire, c.z)
if min_diff == ur_diff_x:
fake_center = vector3d(ur.x - self.half_wire, c.y, c.z)
if min_diff == ur_diff_y:
fake_center = vector3d(c.x, ur.y - self.half_wire, c.z)
node.center = fake_center
new_nodes.append(node)
break
return new_nodes
def add_perimeter_fake_pins(self):
"""
Add the fake pins on the perimeter to where the signals will be routed.
These perimeter fake pins are only used to replace layout pins at the
end of routing.
"""
ll, ur = self.bbox
@ -118,17 +161,44 @@ class signal_escape_router(router):
self.fake_pins.append(pin)
def get_closest_perimeter_fake_pin(self, pin):
""" Return the closest fake pin for the given pin. """
def create_fake_pin(self, pin):
""" Create a fake pin on the perimeter orthogonal to the given pin. """
min_dist = float("inf")
close_fake = None
for fake in self.fake_pins:
dist = pin.distance(fake)
if dist < min_dist:
min_dist = dist
close_fake = fake
return close_fake
ll, ur = self.bbox
c = pin.center()
# Find the closest edge
ll_diff_x = abs(c.x - ll.x)
ll_diff_y = abs(c.y - ll.y)
ur_diff_x = abs(c.x - ur.x)
ur_diff_y = abs(c.y - ur.y)
min_diff = min(ll_diff_x, ll_diff_y, ur_diff_x, ur_diff_y)
# Keep the fake pin out of the SRAM layout are so that they won't be
# blocked by previous signals if they're on the same orthogonal line
if min_diff == ll_diff_x:
fake_center = vector(ll.x - self.track_wire * 2, c.y)
vertical = True
if min_diff == ll_diff_y:
fake_center = vector(c.x, ll.y - self.track_wire * 2)
vertical = False
if min_diff == ur_diff_x:
fake_center = vector(ur.x + self.track_wire * 2, c.y)
vertical = True
if min_diff == ur_diff_y:
fake_center = vector(c.x, ur.y + self.track_wire * 2)
vertical = False
# Create the fake pin shape
layer = self.get_layer(int(not vertical))
half_wire_vector = vector([self.half_wire] * 2)
nll = fake_center - half_wire_vector
nur = fake_center + half_wire_vector
rect = [nll, nur]
pin = graph_shape(name="fake",
rect=rect,
layer_name_pp=layer)
return pin
def get_route_pairs(self, pin_names):
@ -137,7 +207,7 @@ class signal_escape_router(router):
to_route = []
for name in pin_names:
pin = next(iter(self.pins[name]))
fake = self.get_closest_perimeter_fake_pin(pin)
fake = self.create_fake_pin(pin)
to_route.append((pin, fake, pin.distance(fake)))
return sorted(to_route, key=lambda x: x[2])