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:
|
if name == pin_name:
|
||||||
continue
|
continue
|
||||||
for pin in pins:
|
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
|
return blockages
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -110,13 +110,16 @@ class hanan_graph:
|
||||||
y_values = set()
|
y_values = set()
|
||||||
|
|
||||||
# Add the source and target values
|
# 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]:
|
for shape in [self.source, self.target]:
|
||||||
aspect_ratio = shape.width() / shape.height()
|
aspect_ratio = shape.width() / shape.height()
|
||||||
# If the pin is tall or fat, add two points on the ends
|
# If the pin is tall or fat, add two points on the ends
|
||||||
if aspect_ratio <= 0.5: # Tall pin
|
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
|
elif aspect_ratio >= 2: # Fat pin
|
||||||
points = [shape.lc(), shape.rc()]
|
points = [shape.lc() + x_offset, shape.rc() - x_offset]
|
||||||
else: # Square-like pin
|
else: # Square-like pin
|
||||||
points = [shape.center()]
|
points = [shape.center()]
|
||||||
for p in points:
|
for p in points:
|
||||||
|
|
@ -251,9 +254,14 @@ class hanan_graph:
|
||||||
path.append(current)
|
path.append(current)
|
||||||
return path
|
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
|
# Update neighbor scores
|
||||||
for node in current.neighbors:
|
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]:
|
if node.id not in g_scores or tentative_score < g_scores[node.id]:
|
||||||
came_from[node.id] = current
|
came_from[node.id] = current
|
||||||
g_scores[node.id] = tentative_score
|
g_scores[node.id] = tentative_score
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#
|
#
|
||||||
from openram.base.vector import vector
|
from openram.base.vector import vector
|
||||||
from openram.base.vector3d import vector3d
|
from openram.base.vector3d import vector3d
|
||||||
|
from openram.tech import drc
|
||||||
|
|
||||||
|
|
||||||
class hanan_node:
|
class hanan_node:
|
||||||
|
|
@ -48,14 +49,28 @@ class hanan_node:
|
||||||
neighbor.neighbors.remove(self)
|
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. """
|
""" Get the cost of going from this node to the other node. """
|
||||||
|
|
||||||
if other in self.neighbors:
|
if other in self.neighbors:
|
||||||
is_vertical = self.center.x == other.center.x
|
is_vertical = self.center.x == other.center.x
|
||||||
layer_dist = self.center.distance(other.center)
|
layer_dist = self.center.distance(other.center)
|
||||||
|
# Edge is on non-preferred direction
|
||||||
if is_vertical != bool(self.center.z):
|
if is_vertical != bool(self.center.z):
|
||||||
layer_dist *= 2
|
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
|
via_dist = abs(self.center.z - other.center.z) * 2
|
||||||
return layer_dist + via_dist
|
return layer_dist + via_dist
|
||||||
return float("inf")
|
return float("inf")
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,7 @@ class hanan_router(router_tech):
|
||||||
# Inflate the shapes to prevent DRC errors
|
# Inflate the shapes to prevent DRC errors
|
||||||
offset = self.layer_widths[0] / 2
|
offset = self.layer_widths[0] / 2
|
||||||
for blockage in blockages:
|
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):
|
def add_path(self, path):
|
||||||
|
|
@ -160,19 +160,13 @@ class hanan_router(router_tech):
|
||||||
the layout.
|
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]
|
last_added = path[0]
|
||||||
coordinates = [path[0].center]
|
coordinates = [path[0].center]
|
||||||
direction = get_direction(path[0], path[1])
|
direction = path[0].get_direction(path[1])
|
||||||
candidate = path[1]
|
candidate = path[1]
|
||||||
for i in range(2, len(path)):
|
for i in range(2, len(path)):
|
||||||
node = path[i]
|
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
|
# Skip the previous candidate since the current node follows the
|
||||||
# same direction
|
# same direction
|
||||||
if direction == current_direction:
|
if direction == current_direction:
|
||||||
|
|
|
||||||
|
|
@ -19,16 +19,13 @@ class hanan_shape(pin_layout):
|
||||||
pin_layout.__init__(self, name, rect, layer_name_pp)
|
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. """
|
""" Override the default inflated_pin behavior. """
|
||||||
|
|
||||||
if not spacing:
|
ll, ur = self.inflate(spacing, multiple)
|
||||||
spacing = 0
|
extra = vector([extra_spacing] * 2)
|
||||||
drc_spacing = multiple * drc("{0}_to_{0}".format(self.layer))
|
newll = ll - extra
|
||||||
spacing = vector([spacing + drc_spacing] * 2)
|
newur = ur + extra
|
||||||
(ll, ur) = self.rect
|
|
||||||
newll = ll - spacing
|
|
||||||
newur = ur + spacing
|
|
||||||
inflated_area = (newll, newur)
|
inflated_area = (newll, newur)
|
||||||
return hanan_shape(self.name, inflated_area, self.layer)
|
return hanan_shape(self.name, inflated_area, self.layer)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue