Cleanup graph router

This commit is contained in:
Eren Dogan 2023-07-24 08:03:08 -07:00
parent 54f2e73214
commit 947e94323d
3 changed files with 46 additions and 31 deletions

View File

@ -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):

View File

@ -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",

View File

@ -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)