mirror of https://github.com/VLSIDA/OpenRAM.git
Include new wires while routing the pins
This commit is contained in:
parent
0938e7ec9a
commit
bb35ac2f90
|
|
@ -48,7 +48,7 @@ class hanan_graph:
|
|||
for blockage in self.graph_blockages:
|
||||
# Check if two shapes overlap
|
||||
# Inflated blockages of pins don't block probes
|
||||
if blockage.overlaps(probe_shape) and blockage.name != self.source.name:
|
||||
if blockage.overlaps(probe_shape) and (blockage.name != self.source.name or not blockage.inflated_from.overlaps(probe_shape)):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
|
@ -69,6 +69,9 @@ class hanan_graph:
|
|||
# Find the blockages that are in the routing area
|
||||
self.graph_blockages = []
|
||||
for blockage in self.router.blockages:
|
||||
# FIXME: Include pins as blockages as well to prevent DRC errors
|
||||
if blockage.name == self.source.name:
|
||||
continue
|
||||
# Set the region's lpp to current blockage's lpp so that the
|
||||
# overlaps method works
|
||||
region.lpp = blockage.lpp
|
||||
|
|
@ -92,10 +95,9 @@ class hanan_graph:
|
|||
x_values = set()
|
||||
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)
|
||||
# Add inner values for blockages of the routed type
|
||||
x_offset = vector(self.router.offset, 0)
|
||||
y_offset = vector(0, self.router.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
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@ class hanan_router(router_tech):
|
|||
self.all_pins = set()
|
||||
self.blockages = []
|
||||
|
||||
# Set the offset here
|
||||
self.offset = self.layer_widths[0] / 2
|
||||
|
||||
|
||||
def route(self, vdd_name="vdd", gnd_name="gnd"):
|
||||
""" Route the given pins in the given order. """
|
||||
|
|
@ -38,10 +41,7 @@ class hanan_router(router_tech):
|
|||
self.write_debug_gds(gds_name="before.gds")
|
||||
|
||||
# Prepare gdsMill to find pins and blockages
|
||||
self.design.gds_write(self.gds_filename)
|
||||
self.layout = gdsMill.VlsiLayout(units=GDS["unit"])
|
||||
self.reader = gdsMill.Gds2reader(self.layout)
|
||||
self.reader.loadFromFile(self.gds_filename)
|
||||
self.prepare_gds_reader()
|
||||
|
||||
# Find pins to be routed
|
||||
self.find_pins(vdd_name)
|
||||
|
|
@ -50,23 +50,40 @@ class hanan_router(router_tech):
|
|||
# Find blockages
|
||||
self.find_blockages()
|
||||
|
||||
# Add vdd and gnd pins as blockages as well
|
||||
# NOTE: This is done to make vdd and gnd pins DRC-safe
|
||||
for pin in self.all_pins:
|
||||
self.blockages.append(pin.inflated_pin(multiple=1, extra_spacing=self.offset, keep_link=True))
|
||||
|
||||
# Route vdd and gnd
|
||||
for pin_name in [vdd_name, gnd_name]:
|
||||
pins = self.pins[pin_name]
|
||||
# Create minimum spanning tree connecting all pins
|
||||
for source, target in self.get_mst_pairs(list(pins)):
|
||||
# Create the hanan graph
|
||||
# Create the Hanan graph
|
||||
hg = hanan_graph(self)
|
||||
hg.create_graph(source, target)
|
||||
# Find the shortest path from source to target
|
||||
path = hg.find_shortest_path()
|
||||
debug.check(path is not None, "Couldn't route {} to {}".format(source, target))
|
||||
debug.check(path is not None, "Couldn't route from {} to {}".format(source, target))
|
||||
# Create the path shapes on layout
|
||||
self.add_path(path)
|
||||
# Find the recently added shapes
|
||||
self.prepare_gds_reader()
|
||||
self.find_blockages(pin_name)
|
||||
|
||||
self.write_debug_gds(gds_name="after.gds")
|
||||
|
||||
|
||||
def prepare_gds_reader(self):
|
||||
""" """
|
||||
|
||||
self.design.gds_write(self.gds_filename)
|
||||
self.layout = gdsMill.VlsiLayout(units=GDS["unit"])
|
||||
self.reader = gdsMill.Gds2reader(self.layout)
|
||||
self.reader.loadFromFile(self.gds_filename)
|
||||
|
||||
|
||||
def find_pins(self, pin_name):
|
||||
""" """
|
||||
debug.info(1, "Finding all pins for {}".format(pin_name))
|
||||
|
|
@ -80,16 +97,28 @@ class hanan_router(router_tech):
|
|||
ll = vector(boundary[0], boundary[1])
|
||||
ur = vector(boundary[2], boundary[3])
|
||||
rect = [ll, ur]
|
||||
pin = hanan_shape(pin_name, rect, layer)
|
||||
pin_set.add(pin)
|
||||
new_pin = hanan_shape(pin_name, rect, layer)
|
||||
# Skip this pin if it's contained by another pin of the same type
|
||||
if new_pin.contained_by_any(pin_set):
|
||||
continue
|
||||
# Remove any previous pin of the same type contained by this new pin
|
||||
for pin in list(pin_set):
|
||||
if new_pin.contains(pin):
|
||||
pin_set.remove(pin)
|
||||
elif new_pin.aligns(pin):
|
||||
new_pin.bbox([pin])
|
||||
pin_set.remove(pin)
|
||||
pin_set.add(new_pin)
|
||||
# Add these pins to the 'pins' dict
|
||||
self.pins[pin_name] = pin_set
|
||||
self.all_pins.update(pin_set)
|
||||
|
||||
|
||||
def find_blockages(self):
|
||||
def find_blockages(self, shape_name=None):
|
||||
""" """
|
||||
debug.info(1, "Finding all blockages...")
|
||||
debug.info(1, "Finding blockages...")
|
||||
|
||||
prev_blockages = self.blockages[:]
|
||||
|
||||
blockages = []
|
||||
for lpp in [self.vert_lpp, self.horiz_lpp]:
|
||||
|
|
@ -100,12 +129,16 @@ class hanan_router(router_tech):
|
|||
ll = vector(boundary[0], boundary[1])
|
||||
ur = vector(boundary[2], boundary[3])
|
||||
rect = [ll, ur]
|
||||
new_shape = hanan_shape("blockage{}".format(len(blockages)),
|
||||
rect,
|
||||
lpp)
|
||||
if shape_name is None:
|
||||
name = "blockage{}".format(len(blockages))
|
||||
else:
|
||||
name = shape_name
|
||||
new_shape = hanan_shape(name, rect, lpp)
|
||||
# If there is a rectangle that is the same in the pins,
|
||||
# it isn't a blockage
|
||||
if new_shape.contained_by_any(self.all_pins) or new_shape.contained_by_any(blockages):
|
||||
if new_shape.contained_by_any(self.all_pins) or \
|
||||
new_shape.contained_by_any(prev_blockages) or \
|
||||
new_shape.contained_by_any(blockages):
|
||||
continue
|
||||
# Remove blockages contained by this new blockage
|
||||
for i in range(len(blockages) - 1, -1, -1):
|
||||
|
|
@ -122,14 +155,24 @@ class hanan_router(router_tech):
|
|||
blockages.append(new_shape)
|
||||
|
||||
# Inflate the shapes to prevent DRC errors
|
||||
offset = self.layer_widths[0] / 2
|
||||
for blockage in blockages:
|
||||
self.blockages.append(blockage.inflated_pin(multiple=1, extra_spacing=offset))
|
||||
|
||||
# Add vdd and gnd pins as blockages as well
|
||||
# NOTE: This is done to make vdd and gnd pins DRC-safe
|
||||
for pin in self.all_pins:
|
||||
self.blockages.append(pin.inflated_pin(multiple=1, extra_spacing=offset, keep_link=True))
|
||||
self.blockages.append(blockage.inflated_pin(multiple=1,
|
||||
extra_spacing=self.offset,
|
||||
keep_link=shape_name is not None))
|
||||
# Remove blockages contained by this new blockage
|
||||
for i in range(len(prev_blockages) - 1, -1, -1):
|
||||
prev_blockage = prev_blockages[i]
|
||||
# Remove the previous blockage contained by this new
|
||||
# blockage
|
||||
if blockage.contains(prev_blockage):
|
||||
prev_blockages.remove(prev_blockage)
|
||||
self.blockages.remove(prev_blockage)
|
||||
# Merge the previous blockage into this new blockage if
|
||||
# they are aligning
|
||||
elif blockage.aligns(prev_blockage):
|
||||
blockage.bbox([prev_blockage])
|
||||
prev_blockages.remove(prev_blockage)
|
||||
self.blockages.remove(prev_blockage)
|
||||
|
||||
|
||||
def get_mst_pairs(self, pins):
|
||||
|
|
@ -214,26 +257,32 @@ class hanan_router(router_tech):
|
|||
return coordinates
|
||||
|
||||
|
||||
def write_debug_gds(self, gds_name="debug_route.gds", source=None, target=None):
|
||||
def write_debug_gds(self, gds_name="debug_route.gds", hg=None, source=None, target=None):
|
||||
""" """
|
||||
|
||||
self.add_router_info(source, target)
|
||||
self.add_router_info(hg, source, target)
|
||||
self.design.gds_write(gds_name)
|
||||
self.del_router_info()
|
||||
|
||||
|
||||
def add_router_info(self, source=None, target=None):
|
||||
def add_router_info(self, hg=None, source=None, target=None):
|
||||
""" """
|
||||
|
||||
# Display the inflated blockage
|
||||
if "hg" in self.__dict__:
|
||||
for blockage in self.hg.graph_blockages:
|
||||
self.add_object_info(blockage, "blockage{}".format(self.get_zindex(blockage.lpp)))
|
||||
for node in self.hg.nodes:
|
||||
if hg:
|
||||
for blockage in self.blockages:
|
||||
if blockage in hg.graph_blockages:
|
||||
self.add_object_info(blockage, "blockage{}++[{}]".format(self.get_zindex(blockage.lpp), blockage.name))
|
||||
else:
|
||||
self.add_object_info(blockage, "blockage{}[{}]".format(self.get_zindex(blockage.lpp), blockage.name))
|
||||
for node in hg.nodes:
|
||||
offset = (node.center.x, node.center.y)
|
||||
self.design.add_label(text="n{}".format(node.center.z),
|
||||
layer="text",
|
||||
offset=offset)
|
||||
else:
|
||||
for blockage in self.blockages:
|
||||
self.add_object_info(blockage, "blockage{}".format(self.get_zindex(blockage.lpp)))
|
||||
if source:
|
||||
self.add_object_info(source, "source")
|
||||
if target:
|
||||
|
|
|
|||
Loading…
Reference in New Issue