mirror of https://github.com/VLSIDA/OpenRAM.git
Cleanup graph router
This commit is contained in:
parent
54f2e73214
commit
947e94323d
|
|
@ -128,24 +128,20 @@ class graph:
|
||||||
# Find the blockages that are in the routing area
|
# Find the blockages that are in the routing area
|
||||||
self.graph_blockages = []
|
self.graph_blockages = []
|
||||||
self.find_graph_blockages(region)
|
self.find_graph_blockages(region)
|
||||||
for shape in [source, target]:
|
|
||||||
if shape not in self.graph_blockages:
|
|
||||||
self.graph_blockages.append(shape)
|
|
||||||
|
|
||||||
# Find the vias that are in the routing area
|
# Find the vias that are in the routing area
|
||||||
self.graph_vias = []
|
self.graph_vias = []
|
||||||
for via in self.router.vias:
|
self.find_graph_vias(region)
|
||||||
# Set the regions's lpp to current via's lpp so that the
|
|
||||||
# overlaps method works
|
|
||||||
region.lpp = via.lpp
|
|
||||||
if region.overlaps(via):
|
|
||||||
self.graph_vias.append(via)
|
|
||||||
|
|
||||||
# Create the graph
|
# Generate the cartesian values from shapes in the area
|
||||||
x_values, y_values = self.generate_cartesian_values()
|
x_values, y_values = self.generate_cartesian_values()
|
||||||
|
# Adjust the routing region to include "edge" shapes
|
||||||
region.bbox(self.graph_blockages)
|
region.bbox(self.graph_blockages)
|
||||||
|
# Find and include edge shapes to prevent DRC errors
|
||||||
self.find_graph_blockages(region)
|
self.find_graph_blockages(region)
|
||||||
|
# Generate the graph nodes from cartesian values
|
||||||
self.generate_graph_nodes(x_values, y_values)
|
self.generate_graph_nodes(x_values, y_values)
|
||||||
|
# Save the graph nodes that lie in source and target shapes
|
||||||
self.save_end_nodes()
|
self.save_end_nodes()
|
||||||
debug.info(3, "Number of blockages detected in the routing region: {}".format(len(self.graph_blockages)))
|
debug.info(3, "Number of blockages detected in the routing region: {}".format(len(self.graph_blockages)))
|
||||||
debug.info(3, "Number of vias detected in the routing region: {}".format(len(self.graph_vias)))
|
debug.info(3, "Number of vias detected in the routing region: {}".format(len(self.graph_vias)))
|
||||||
|
|
@ -156,13 +152,33 @@ class graph:
|
||||||
""" Find blockages that overlap the routing region. """
|
""" Find blockages that overlap the routing region. """
|
||||||
|
|
||||||
for blockage in self.router.blockages:
|
for blockage in self.router.blockages:
|
||||||
# Set the region's lpp to current blockage's lpp so that the
|
# Skip if already included
|
||||||
# overlaps method works
|
|
||||||
if blockage in self.graph_blockages:
|
if blockage in self.graph_blockages:
|
||||||
continue
|
continue
|
||||||
|
# Set the region's lpp to current blockage's lpp so that the
|
||||||
|
# overlaps method works
|
||||||
region.lpp = blockage.lpp
|
region.lpp = blockage.lpp
|
||||||
if region.overlaps(blockage):
|
if region.overlaps(blockage):
|
||||||
self.graph_blockages.append(blockage)
|
self.graph_blockages.append(blockage)
|
||||||
|
# FIXME: Don't include source and target if they're already included
|
||||||
|
# in inflated form
|
||||||
|
for shape in [self.source, self.target]:
|
||||||
|
if shape not in self.graph_blockages:
|
||||||
|
self.graph_blockages.append(shape)
|
||||||
|
|
||||||
|
|
||||||
|
def find_graph_vias(self, region):
|
||||||
|
""" Find vias that overlap the routing region. """
|
||||||
|
|
||||||
|
for via in self.router.vias:
|
||||||
|
# Skip if already included
|
||||||
|
if via in self.graph_vias:
|
||||||
|
continue
|
||||||
|
# Set the regions's lpp to current via's lpp so that the
|
||||||
|
# overlaps method works
|
||||||
|
region.lpp = via.lpp
|
||||||
|
if region.overlaps(via):
|
||||||
|
self.graph_vias.append(via)
|
||||||
|
|
||||||
|
|
||||||
def generate_cartesian_values(self):
|
def generate_cartesian_values(self):
|
||||||
|
|
|
||||||
|
|
@ -97,10 +97,10 @@ class graph_router(router_tech):
|
||||||
# Route closest pins according to the minimum spanning tree
|
# Route closest pins according to the minimum spanning tree
|
||||||
for source, target in self.get_mst_pairs(list(pins)):
|
for source, target in self.get_mst_pairs(list(pins)):
|
||||||
# Create the graph
|
# Create the graph
|
||||||
hg = graph(self)
|
g = graph(self)
|
||||||
hg.create_graph(source, target)
|
g.create_graph(source, target)
|
||||||
# Find the shortest path from source to target
|
# Find the shortest path from source to target
|
||||||
path = hg.find_shortest_path()
|
path = g.find_shortest_path()
|
||||||
# TODO: Exponentially increase the routing area and retry if no
|
# TODO: Exponentially increase the routing area and retry if no
|
||||||
# path was found
|
# path was found
|
||||||
debug.check(path is not None, "Couldn't route from {} to {}".format(source, target))
|
debug.check(path is not None, "Couldn't route from {} to {}".format(source, target))
|
||||||
|
|
@ -130,7 +130,6 @@ class graph_router(router_tech):
|
||||||
for shape in shape_list:
|
for shape in shape_list:
|
||||||
layer, boundary = shape
|
layer, boundary = shape
|
||||||
# gdsMill boundaries are in (left, bottom, right, top) order
|
# gdsMill boundaries are in (left, bottom, right, top) order
|
||||||
# so repack and snap to the grid
|
|
||||||
ll = vector(boundary[0], boundary[1])
|
ll = vector(boundary[0], boundary[1])
|
||||||
ur = vector(boundary[2], boundary[3])
|
ur = vector(boundary[2], boundary[3])
|
||||||
rect = [ll, ur]
|
rect = [ll, ur]
|
||||||
|
|
@ -163,7 +162,6 @@ class graph_router(router_tech):
|
||||||
shapes = self.layout.getAllShapes(lpp)
|
shapes = self.layout.getAllShapes(lpp)
|
||||||
for boundary in shapes:
|
for boundary in shapes:
|
||||||
# gdsMill boundaries are in (left, bottom, right, top) order
|
# gdsMill boundaries are in (left, bottom, right, top) order
|
||||||
# so repack and snap to the grid
|
|
||||||
ll = vector(boundary[0], boundary[1])
|
ll = vector(boundary[0], boundary[1])
|
||||||
ur = vector(boundary[2], boundary[3])
|
ur = vector(boundary[2], boundary[3])
|
||||||
rect = [ll, ur]
|
rect = [ll, ur]
|
||||||
|
|
@ -224,7 +222,6 @@ class graph_router(router_tech):
|
||||||
shapes = self.layout.getAllShapes(via_lpp)
|
shapes = self.layout.getAllShapes(via_lpp)
|
||||||
for boundary in shapes:
|
for boundary in shapes:
|
||||||
# gdsMill boundaries are in (left, bottom, right, top) order
|
# gdsMill boundaries are in (left, bottom, right, top) order
|
||||||
# so repack and snap to the grid
|
|
||||||
ll = vector(boundary[0], boundary[1])
|
ll = vector(boundary[0], boundary[1])
|
||||||
ur = vector(boundary[2], boundary[3])
|
ur = vector(boundary[2], boundary[3])
|
||||||
rect = [ll, ur]
|
rect = [ll, ur]
|
||||||
|
|
@ -486,30 +483,32 @@ class graph_router(router_tech):
|
||||||
|
|
||||||
|
|
||||||
def get_new_pins(self, name):
|
def get_new_pins(self, name):
|
||||||
""" """
|
""" Return the new supply pins added by this router. """
|
||||||
|
|
||||||
return self.new_pins[name]
|
return self.new_pins[name]
|
||||||
|
|
||||||
|
|
||||||
def write_debug_gds(self, gds_name="debug_route.gds", hg=None, source=None, target=None):
|
def write_debug_gds(self, gds_name="debug_route.gds", g=None, source=None, target=None):
|
||||||
""" """
|
""" Write the debug GDSII file for the router. """
|
||||||
|
|
||||||
self.add_router_info(hg, source, target)
|
self.add_router_info(g, source, target)
|
||||||
self.design.gds_write(gds_name)
|
self.design.gds_write(gds_name)
|
||||||
self.del_router_info()
|
self.del_router_info()
|
||||||
|
|
||||||
|
|
||||||
def add_router_info(self, hg=None, source=None, target=None):
|
def add_router_info(self, g=None, source=None, target=None):
|
||||||
""" """
|
"""
|
||||||
|
Add debug information to the text layer about the graph and router.
|
||||||
|
"""
|
||||||
|
|
||||||
# Display the inflated blockage
|
# Display the inflated blockage
|
||||||
if hg:
|
if g:
|
||||||
for blockage in self.blockages:
|
for blockage in self.blockages:
|
||||||
if blockage in hg.graph_blockages:
|
if blockage in g.graph_blockages:
|
||||||
self.add_object_info(blockage, "blockage{}++[{}]".format(self.get_zindex(blockage.lpp), blockage.name))
|
self.add_object_info(blockage, "blockage{}++[{}]".format(self.get_zindex(blockage.lpp), blockage.name))
|
||||||
else:
|
else:
|
||||||
self.add_object_info(blockage, "blockage{}[{}]".format(self.get_zindex(blockage.lpp), blockage.name))
|
self.add_object_info(blockage, "blockage{}[{}]".format(self.get_zindex(blockage.lpp), blockage.name))
|
||||||
for node in hg.nodes:
|
for node in g.nodes:
|
||||||
offset = (node.center.x, node.center.y)
|
offset = (node.center.x, node.center.y)
|
||||||
self.design.add_label(text="n{}".format(node.center.z),
|
self.design.add_label(text="n{}".format(node.center.z),
|
||||||
layer="text",
|
layer="text",
|
||||||
|
|
@ -526,14 +525,14 @@ class graph_router(router_tech):
|
||||||
|
|
||||||
|
|
||||||
def del_router_info(self):
|
def del_router_info(self):
|
||||||
""" """
|
""" Delete router information from the text layer. """
|
||||||
|
|
||||||
lpp = tech_layer["text"]
|
lpp = tech_layer["text"]
|
||||||
self.design.objs = [x for x in self.design.objs if x.lpp != lpp]
|
self.design.objs = [x for x in self.design.objs if x.lpp != lpp]
|
||||||
|
|
||||||
|
|
||||||
def add_object_info(self, obj, label):
|
def add_object_info(self, obj, label):
|
||||||
""" """
|
""" Add debug information to the text layer about an object. """
|
||||||
|
|
||||||
ll, ur = obj.rect
|
ll, ur = obj.rect
|
||||||
self.design.add_rect(layer="text",
|
self.design.add_rect(layer="text",
|
||||||
|
|
|
||||||
|
|
@ -124,14 +124,14 @@ class router_tech:
|
||||||
return (min_width, min_spacing)
|
return (min_width, min_spacing)
|
||||||
|
|
||||||
def get_layer_width(self, zindex):
|
def get_layer_width(self, zindex):
|
||||||
""" """
|
""" Return the minimum width of a layer. """
|
||||||
layer_name = self.get_layer(zindex)
|
layer_name = self.get_layer(zindex)
|
||||||
min_wire_width = drc("minwidth_{0}".format(layer_name), 0, math.inf)
|
min_wire_width = drc("minwidth_{0}".format(layer_name), 0, math.inf)
|
||||||
min_width = self.route_track_width * drc("minwidth_{0}".format(layer_name), self.route_track_width * min_wire_width, math.inf)
|
min_width = self.route_track_width * drc("minwidth_{0}".format(layer_name), self.route_track_width * min_wire_width, math.inf)
|
||||||
return min_width
|
return min_width
|
||||||
|
|
||||||
def get_layer_space(self, zindex, width):
|
def get_layer_space(self, zindex, width):
|
||||||
""" """
|
""" Return the minimum spacing of a layer given wire width. """
|
||||||
if width is None:
|
if width is None:
|
||||||
width = self.get_layer_width(zindex)
|
width = self.get_layer_width(zindex)
|
||||||
layer_name = self.get_layer(zindex)
|
layer_name = self.get_layer(zindex)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue