mirror of https://github.com/VLSIDA/OpenRAM.git
Prevent multiple dog-legs in non-preferred direction
This commit is contained in:
parent
15b4e4dbe8
commit
a47bc7ebee
|
|
@ -96,7 +96,7 @@ class hanan_graph:
|
|||
if name == pin_name:
|
||||
continue
|
||||
for pin in pins:
|
||||
blockages.append(deepcopy(pin).inflated_pin(spacing=offset, multiple=1))
|
||||
blockages.append(deepcopy(pin).inflated_pin(multiple=1, extra_spacing=offset))
|
||||
return blockages
|
||||
|
||||
|
||||
|
|
@ -110,13 +110,16 @@ class hanan_graph:
|
|||
y_values = set()
|
||||
|
||||
# Add the source and target values
|
||||
offset = self.router.layer_widths[0] / 2
|
||||
x_offset = vector(offset, 0)
|
||||
y_offset = vector(0, offset)
|
||||
for shape in [self.source, self.target]:
|
||||
aspect_ratio = shape.width() / shape.height()
|
||||
# If the pin is tall or fat, add two points on the ends
|
||||
if aspect_ratio <= 0.5: # Tall pin
|
||||
points = [shape.uc(), shape.bc()]
|
||||
points = [shape.bc() + y_offset, shape.uc() - y_offset]
|
||||
elif aspect_ratio >= 2: # Fat pin
|
||||
points = [shape.lc(), shape.rc()]
|
||||
points = [shape.lc() + x_offset, shape.rc() - x_offset]
|
||||
else: # Square-like pin
|
||||
points = [shape.center()]
|
||||
for p in points:
|
||||
|
|
@ -251,9 +254,14 @@ class hanan_graph:
|
|||
path.append(current)
|
||||
return path
|
||||
|
||||
# Get the previous node to better calculate the next costs
|
||||
prev_node = None
|
||||
if current.id in came_from:
|
||||
prev_node = came_from[current.id]
|
||||
|
||||
# Update neighbor scores
|
||||
for node in current.neighbors:
|
||||
tentative_score = current.get_edge_cost(node) + g_scores[current.id]
|
||||
tentative_score = current.get_edge_cost(node, prev_node) + g_scores[current.id]
|
||||
if node.id not in g_scores or tentative_score < g_scores[node.id]:
|
||||
came_from[node.id] = current
|
||||
g_scores[node.id] = tentative_score
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#
|
||||
from openram.base.vector import vector
|
||||
from openram.base.vector3d import vector3d
|
||||
from openram.tech import drc
|
||||
|
||||
|
||||
class hanan_node:
|
||||
|
|
@ -48,14 +49,28 @@ class hanan_node:
|
|||
neighbor.neighbors.remove(self)
|
||||
|
||||
|
||||
def get_edge_cost(self, other):
|
||||
def get_direction(self, b):
|
||||
""" Return the direction of path from a to b. """
|
||||
|
||||
horiz = self.center.x == b.center.x
|
||||
vert = self.center.y == b.center.y
|
||||
return (horiz, vert)
|
||||
|
||||
|
||||
def get_edge_cost(self, other, prev_node=None):
|
||||
""" Get the cost of going from this node to the other node. """
|
||||
|
||||
if other in self.neighbors:
|
||||
is_vertical = self.center.x == other.center.x
|
||||
layer_dist = self.center.distance(other.center)
|
||||
# Edge is on non-preferred direction
|
||||
if is_vertical != bool(self.center.z):
|
||||
layer_dist *= 2
|
||||
# Wire bends towards non-preferred direction
|
||||
# NOTE: Adding a fixed cost prevents multiple dog-legs in
|
||||
# non-preferred direction
|
||||
if prev_node and self.get_direction(prev_node) != self.get_direction(other):
|
||||
layer_dist += drc["grid"]
|
||||
via_dist = abs(self.center.z - other.center.z) * 2
|
||||
return layer_dist + via_dist
|
||||
return float("inf")
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ class hanan_router(router_tech):
|
|||
# Inflate the shapes to prevent DRC errors
|
||||
offset = self.layer_widths[0] / 2
|
||||
for blockage in blockages:
|
||||
self.blockages.append(blockage.inflated_pin(spacing=offset, multiple=1))
|
||||
self.blockages.append(blockage.inflated_pin(multiple=1, extra_spacing=offset))
|
||||
|
||||
|
||||
def add_path(self, path):
|
||||
|
|
@ -160,19 +160,13 @@ class hanan_router(router_tech):
|
|||
the layout.
|
||||
"""
|
||||
|
||||
def get_direction(a, b):
|
||||
""" Return the direction of path from a to b. """
|
||||
horiz = a.center.x == b.center.x
|
||||
vert = a.center.y == b.center.y
|
||||
return (horiz, vert)
|
||||
|
||||
last_added = path[0]
|
||||
coordinates = [path[0].center]
|
||||
direction = get_direction(path[0], path[1])
|
||||
direction = path[0].get_direction(path[1])
|
||||
candidate = path[1]
|
||||
for i in range(2, len(path)):
|
||||
node = path[i]
|
||||
current_direction = get_direction(candidate, node)
|
||||
current_direction = node.get_direction(candidate)
|
||||
# Skip the previous candidate since the current node follows the
|
||||
# same direction
|
||||
if direction == current_direction:
|
||||
|
|
|
|||
|
|
@ -19,16 +19,13 @@ class hanan_shape(pin_layout):
|
|||
pin_layout.__init__(self, name, rect, layer_name_pp)
|
||||
|
||||
|
||||
def inflated_pin(self, spacing=None, multiple=0.5):
|
||||
def inflated_pin(self, spacing=None, multiple=0.5, extra_spacing=0):
|
||||
""" Override the default inflated_pin behavior. """
|
||||
|
||||
if not spacing:
|
||||
spacing = 0
|
||||
drc_spacing = multiple * drc("{0}_to_{0}".format(self.layer))
|
||||
spacing = vector([spacing + drc_spacing] * 2)
|
||||
(ll, ur) = self.rect
|
||||
newll = ll - spacing
|
||||
newur = ur + spacing
|
||||
ll, ur = self.inflate(spacing, multiple)
|
||||
extra = vector([extra_spacing] * 2)
|
||||
newll = ll - extra
|
||||
newur = ur + extra
|
||||
inflated_area = (newll, newur)
|
||||
return hanan_shape(self.name, inflated_area, self.layer)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue