Fix DRC spacing in Hanan router

This commit is contained in:
Eren Dogan 2023-06-05 19:33:45 -07:00
parent 48a148003a
commit 15b4e4dbe8
3 changed files with 40 additions and 42 deletions

View File

@ -8,6 +8,7 @@ from copy import deepcopy
from openram import debug from openram import debug
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
from .direction import direction from .direction import direction
from .hanan_node import hanan_node from .hanan_node import hanan_node
from .hanan_probe import hanan_probe from .hanan_probe import hanan_probe
@ -90,11 +91,12 @@ class hanan_graph:
# Create a copy of blockages # Create a copy of blockages
blockages = self.router.blockages[:] blockages = self.router.blockages[:]
# Create a copy of pins with different name than the routed pins # Create a copy of pins with different name than the routed pins
for name, pins, in self.router.pins.items(): offset = self.router.layer_widths[0] / 2
for name, pins in self.router.pins.items():
if name == pin_name: if name == pin_name:
continue continue
for pin in pins: for pin in pins:
blockages.append(deepcopy(pin).inflated_pin(multiple=1)) blockages.append(deepcopy(pin).inflated_pin(spacing=offset, multiple=1))
return blockages return blockages
@ -106,34 +108,26 @@ class hanan_graph:
x_values = set() x_values = set()
y_values = set() y_values = set()
offset = max(self.router.horiz_track_width, self.router.vert_track_width) / 2
# Add the source and target values # Add the source and target values
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
uc = shape.uc() points = [shape.uc(), shape.bc()]
bc = shape.bc()
points = [vector(uc.x, uc.y - offset),
vector(bc.x, bc.y + offset)]
elif aspect_ratio >= 2: # Fat pin elif aspect_ratio >= 2: # Fat pin
lc = shape.lc() points = [shape.lc(), shape.rc()]
rc = shape.rc()
points = [vector(lc.x + offset, lc.y),
vector(rc.x - offset, rc.y)]
else: # Square-like pin else: # Square-like pin
center = shape.center() points = [shape.center()]
x_values.add(center.x)
y_values.add(center.y)
continue
for p in points: for p in points:
x_values.add(p.x) x_values.add(p.x)
y_values.add(p.y) y_values.add(p.y)
# Add corners for blockages # Add corners for blockages
offset = drc["grid"]
for blockage in self.graph_blockages: for blockage in self.graph_blockages:
ll, ur = blockage.rect ll, ur = blockage.rect
# Add minimum offset to the blockage corner nodes to prevent overlaps
x_values.update([ll.x - offset, ur.x + offset]) x_values.update([ll.x - offset, ur.x + offset])
y_values.update([ll.y - offset, ur.y + offset]) y_values.update([ll.y - offset, ur.y + offset])

View File

@ -109,6 +109,7 @@ class hanan_router(router_tech):
""" """ """ """
debug.info(1, "Finding all blockages...") debug.info(1, "Finding all blockages...")
blockages = []
for lpp in [self.vert_lpp, self.horiz_lpp]: for lpp in [self.vert_lpp, self.horiz_lpp]:
shapes = self.layout.getAllShapes(lpp) shapes = self.layout.getAllShapes(lpp)
for boundary in shapes: for boundary in shapes:
@ -117,37 +118,31 @@ class hanan_router(router_tech):
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]
new_shape = hanan_shape("blockage{}".format(len(self.blockages)), new_shape = hanan_shape("blockage{}".format(len(blockages)),
rect, rect,
lpp) lpp)
# If there is a rectangle that is the same in the pins, # If there is a rectangle that is the same in the pins,
# it isn't a blockage # it isn't a blockage
if new_shape not in self.all_pins and not new_shape.contained_by_any(self.all_pins) and not self.blockage_contains(new_shape): if new_shape.contained_by_any(self.all_pins) or new_shape.contained_by_any(blockages):
new_shape = new_shape.inflated_pin(multiple=1) continue
# Remove blockages contained by this new blockage # Remove blockages contained by this new blockage
for i in range(len(self.blockages) - 1, -1, -1): for i in range(len(blockages) - 1, -1, -1):
blockage = self.blockages[i] blockage = blockages[i]
# Remove the previous blockage contained by this new # Remove the previous blockage contained by this new
# blockage # blockage
if new_shape.contains(blockage): if new_shape.contains(blockage):
self.blockages.remove(blockage) blockages.remove(blockage)
# Merge the previous blockage into this new blockage if # Merge the previous blockage into this new blockage if
# they are aligning # they are aligning
elif new_shape.aligns(blockage): elif new_shape.aligns(blockage):
new_shape.bbox([blockage]) new_shape.bbox([blockage])
self.blockages.remove(blockage) blockages.remove(blockage)
self.blockages.append(new_shape) blockages.append(new_shape)
# Inflate the shapes to prevent DRC errors
def blockage_contains(self, shape): offset = self.layer_widths[0] / 2
""" for blockage in blockages:
Return if this shape is contained by a blockage. self.blockages.append(blockage.inflated_pin(spacing=offset, multiple=1))
"""
for blockage in self.blockages:
if blockage.contains(shape):
return True
return False
def add_path(self, path): def add_path(self, path):

View File

@ -4,6 +4,8 @@
# All rights reserved. # All rights reserved.
# #
from openram.base.pin_layout import pin_layout from openram.base.pin_layout import pin_layout
from openram.base.vector import vector
from openram.tech import drc
class hanan_shape(pin_layout): class hanan_shape(pin_layout):
@ -20,7 +22,14 @@ class hanan_shape(pin_layout):
def inflated_pin(self, spacing=None, multiple=0.5): def inflated_pin(self, spacing=None, multiple=0.5):
""" Override the default inflated_pin behavior. """ """ Override the default inflated_pin behavior. """
inflated_area = self.inflate(spacing, multiple) 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
inflated_area = (newll, newur)
return hanan_shape(self.name, inflated_area, self.layer) return hanan_shape(self.name, inflated_area, self.layer)