mirror of https://github.com/VLSIDA/OpenRAM.git
Combine adjacent power supply pins finished
This commit is contained in:
parent
0544d02ca2
commit
3407163cf1
|
|
@ -12,7 +12,7 @@ class pin_group:
|
||||||
self.name = name
|
self.name = name
|
||||||
# Flag for when it is routed
|
# Flag for when it is routed
|
||||||
self.routed = False
|
self.routed = False
|
||||||
self.shapes = pin_shapes
|
self.pins = pin_shapes
|
||||||
self.router = router
|
self.router = router
|
||||||
# These are the corresponding pin grids for each pin group.
|
# These are the corresponding pin grids for each pin group.
|
||||||
self.grids = set()
|
self.grids = set()
|
||||||
|
|
@ -115,7 +115,7 @@ class pin_group:
|
||||||
Return the smallest.
|
Return the smallest.
|
||||||
"""
|
"""
|
||||||
smallest = None
|
smallest = None
|
||||||
for pin in self.shapes:
|
for pin in self.pins:
|
||||||
for enclosure in enclosure_list:
|
for enclosure in enclosure_list:
|
||||||
new_enclosure = self.compute_enclosure(pin, enclosure)
|
new_enclosure = self.compute_enclosure(pin, enclosure)
|
||||||
if smallest == None or new_enclosure.area()<smallest.area():
|
if smallest == None or new_enclosure.area()<smallest.area():
|
||||||
|
|
@ -130,7 +130,7 @@ class pin_group:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
smallest_shape = None
|
smallest_shape = None
|
||||||
for pin in self.shapes:
|
for pin in self.pins:
|
||||||
# They may not be all on the same layer... in the future.
|
# They may not be all on the same layer... in the future.
|
||||||
zindex=self.router.get_zindex(pin.layer_num)
|
zindex=self.router.get_zindex(pin.layer_num)
|
||||||
(min_width,min_space) = self.router.get_layer_width_space(zindex)
|
(min_width,min_space) = self.router.get_layer_width_space(zindex)
|
||||||
|
|
@ -221,18 +221,77 @@ class pin_group:
|
||||||
self.enclosure = self.find_smallest_overlapping(enclosure_list)
|
self.enclosure = self.find_smallest_overlapping(enclosure_list)
|
||||||
if not self.enclosure:
|
if not self.enclosure:
|
||||||
self.enclosure = self.find_smallest_connector(enclosure_list)
|
self.enclosure = self.find_smallest_connector(enclosure_list)
|
||||||
debug.info(2,"Computed enclosure {0} {1}".format(self.name, self.enclosure))
|
debug.info(2,"Computed enclosure {0}\n {1}\n {2}\n {3}".format(self.name, self.pins, self.grids, self.enclosure))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def add_enclosure(self, cell):
|
def add_enclosure(self, cell):
|
||||||
"""
|
"""
|
||||||
Add the enclosure shape to the given cell.
|
Add the enclosure shape to the given cell.
|
||||||
"""
|
"""
|
||||||
debug.info(2,"Adding enclosure {0} {1}".format(self.name, self.enclosure))
|
debug.info(2,"Adding enclosure {0} {1}".format(self.name, self.enclosure))
|
||||||
self.router.cell.add_rect(layer=self.enclosure.layer,
|
cell.add_rect(layer=self.enclosure.layer,
|
||||||
offset=self.enclosure.ll(),
|
offset=self.enclosure.ll(),
|
||||||
width=self.enclosure.width(),
|
width=self.enclosure.width(),
|
||||||
height=self.enclosure.height())
|
height=self.enclosure.height())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def adjacent(self, other):
|
||||||
|
"""
|
||||||
|
Chck if the two pin groups have at least one adjacent pin grid.
|
||||||
|
"""
|
||||||
|
# We could optimize this to just check the boundaries
|
||||||
|
for g1 in self.grids:
|
||||||
|
for g2 in other.grids:
|
||||||
|
if g1.adjacent(g2):
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
def convert_pin(self, router):
|
||||||
|
#print("PG ",pg)
|
||||||
|
# Keep the same groups for each pin
|
||||||
|
pin_set = set()
|
||||||
|
blockage_set = set()
|
||||||
|
for pin in self.pins:
|
||||||
|
debug.info(2," Converting {0}".format(pin))
|
||||||
|
# Determine which tracks the pin overlaps
|
||||||
|
pin_in_tracks=router.convert_pin_to_tracks(self.name, pin)
|
||||||
|
pin_set.update(pin_in_tracks)
|
||||||
|
# Blockages will be a super-set of pins since it uses the inflated pin shape.
|
||||||
|
blockage_in_tracks = router.convert_blockage(pin)
|
||||||
|
blockage_set.update(blockage_in_tracks)
|
||||||
|
|
||||||
|
# If we have a blockage, we must remove the grids
|
||||||
|
# Remember, this excludes the pin blockages already
|
||||||
|
shared_set = pin_set & router.blocked_grids
|
||||||
|
if shared_set:
|
||||||
|
debug.info(2,"Removing pins {}".format(shared_set))
|
||||||
|
shared_set = blockage_set & router.blocked_grids
|
||||||
|
if shared_set:
|
||||||
|
debug.info(2,"Removing blocks {}".format(shared_set))
|
||||||
|
pin_set.difference_update(router.blocked_grids)
|
||||||
|
blockage_set.difference_update(router.blocked_grids)
|
||||||
|
debug.info(2," pins {}".format(pin_set))
|
||||||
|
debug.info(2," blocks {}".format(blockage_set))
|
||||||
|
|
||||||
|
# At least one of the groups must have some valid tracks
|
||||||
|
if (len(pin_set)==0 and len(blockage_set)==0):
|
||||||
|
self.write_debug_gds("blocked_pin.gds")
|
||||||
|
debug.error("Unable to find unblocked pin on grid.")
|
||||||
|
|
||||||
|
# We need to route each of the components, so don't combine the groups
|
||||||
|
self.grids = pin_set | blockage_set
|
||||||
|
|
||||||
|
# Add all of the partial blocked grids to the set for the design
|
||||||
|
# if they are not blocked by other metal
|
||||||
|
#partial_set = blockage_set - pin_set
|
||||||
|
#self.blockages = partial_set
|
||||||
|
|
||||||
|
# We should not have added the pins to the blockages,
|
||||||
|
# but remove them just in case
|
||||||
|
# Partial set may still be in the blockages if there were
|
||||||
|
# other shapes disconnected from the pins that were also overlapping
|
||||||
|
#route.blocked_grids.difference_update(pin_set)
|
||||||
|
|
|
||||||
|
|
@ -152,9 +152,44 @@ class router(router_tech):
|
||||||
for pin in pin_list:
|
for pin in pin_list:
|
||||||
self.convert_pins(pin)
|
self.convert_pins(pin)
|
||||||
|
|
||||||
|
for pin in pin_list:
|
||||||
|
self.combine_adjacent_pins(pin)
|
||||||
|
#self.write_debug_gds("debug_combine_pins.gds",stop_program=True)
|
||||||
|
|
||||||
# Enclose the continguous grid units in a metal rectangle to fix some DRCs
|
# Enclose the continguous grid units in a metal rectangle to fix some DRCs
|
||||||
self.enclose_pins()
|
self.enclose_pins()
|
||||||
|
|
||||||
|
def combine_adjacent_pins(self, pin_name):
|
||||||
|
"""
|
||||||
|
This checks for simple cases where a pin component already overlaps a supply rail.
|
||||||
|
It will add an enclosure to ensure the overlap in wide DRC rule cases.
|
||||||
|
"""
|
||||||
|
# Make a copy since we are going to reduce this list
|
||||||
|
pin_groups = self.pin_groups[pin_name].copy()
|
||||||
|
|
||||||
|
remove_indices = []
|
||||||
|
for index1,pg1 in enumerate(self.pin_groups[pin_name]):
|
||||||
|
for index2,pg2 in enumerate(self.pin_groups[pin_name]):
|
||||||
|
|
||||||
|
if index1==index2:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if pg1.adjacent(pg2):
|
||||||
|
debug.info(2,"Combing {0}:\n {1}\n {2}".format(pin_name, pg1.pins, pg2.pins))
|
||||||
|
combined = pin_group(pin_name, pg1.pins | pg2.pins, self)
|
||||||
|
combined.grids = pg1.grids | pg2.grids
|
||||||
|
|
||||||
|
# check if there are any blockage problems??
|
||||||
|
remove_indices.append(index1)
|
||||||
|
remove_indices.append(index2)
|
||||||
|
pin_groups.append(combined)
|
||||||
|
|
||||||
|
# Remove them in decreasing order to not invalidate the indices
|
||||||
|
for i in sorted(remove_indices, reverse=True):
|
||||||
|
del pin_groups[i]
|
||||||
|
|
||||||
|
self.pin_groups[pin_name] = pin_groups
|
||||||
|
|
||||||
def prepare_blockages(self, pin_name):
|
def prepare_blockages(self, pin_name):
|
||||||
"""
|
"""
|
||||||
Reset and add all of the blockages in the design.
|
Reset and add all of the blockages in the design.
|
||||||
|
|
@ -539,50 +574,7 @@ class router(router_tech):
|
||||||
Convert the pin groups into pin tracks and blockage tracks.
|
Convert the pin groups into pin tracks and blockage tracks.
|
||||||
"""
|
"""
|
||||||
for pg in self.pin_groups[pin_name]:
|
for pg in self.pin_groups[pin_name]:
|
||||||
#print("PG ",pg)
|
pg.convert_pin(self)
|
||||||
# Keep the same groups for each pin
|
|
||||||
pin_set = set()
|
|
||||||
blockage_set = set()
|
|
||||||
for pin in pg.shapes:
|
|
||||||
debug.info(2," Converting {0}".format(pin))
|
|
||||||
# Determine which tracks the pin overlaps
|
|
||||||
pin_in_tracks=self.convert_pin_to_tracks(pin_name, pin)
|
|
||||||
pin_set.update(pin_in_tracks)
|
|
||||||
# Blockages will be a super-set of pins since it uses the inflated pin shape.
|
|
||||||
blockage_in_tracks = self.convert_blockage(pin)
|
|
||||||
blockage_set.update(blockage_in_tracks)
|
|
||||||
|
|
||||||
# If we have a blockage, we must remove the grids
|
|
||||||
# Remember, this excludes the pin blockages already
|
|
||||||
shared_set = pin_set & self.blocked_grids
|
|
||||||
if shared_set:
|
|
||||||
debug.info(2,"Removing pins {}".format(shared_set))
|
|
||||||
shared_set = blockage_set & self.blocked_grids
|
|
||||||
if shared_set:
|
|
||||||
debug.info(2,"Removing blocks {}".format(shared_set))
|
|
||||||
pin_set.difference_update(self.blocked_grids)
|
|
||||||
blockage_set.difference_update(self.blocked_grids)
|
|
||||||
debug.info(2," pins {}".format(pin_set))
|
|
||||||
debug.info(2," blocks {}".format(blockage_set))
|
|
||||||
|
|
||||||
# At least one of the groups must have some valid tracks
|
|
||||||
if (len(pin_set)==0 and len(blockage_set)==0):
|
|
||||||
self.write_debug_gds("blocked_pin.gds")
|
|
||||||
debug.error("Unable to find unblocked pin on grid.")
|
|
||||||
|
|
||||||
# We need to route each of the components, so don't combine the groups
|
|
||||||
pg.grids = pin_set | blockage_set
|
|
||||||
|
|
||||||
# Add all of the partial blocked grids to the set for the design
|
|
||||||
# if they are not blocked by other metal
|
|
||||||
#partial_set = blockage_set - pin_set
|
|
||||||
#self.pin_blockages[pin_name].append(partial_set)
|
|
||||||
|
|
||||||
# We should not have added the pins to the blockages,
|
|
||||||
# but remove them just in case
|
|
||||||
# Partial set may still be in the blockages if there were
|
|
||||||
# other shapes disconnected from the pins that were also overlapping
|
|
||||||
#self.blocked_grids.difference_update(pin_set)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ class supply_router(router):
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def route_simple_overlaps(self, pin_name):
|
def route_simple_overlaps(self, pin_name):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -163,3 +163,17 @@ class vector3d():
|
||||||
""" Min of both values """
|
""" Min of both values """
|
||||||
return vector3d(min(self.x,other.x),min(self.y,other.y),min(self.z,other.z))
|
return vector3d(min(self.x,other.x),min(self.y,other.y),min(self.z,other.z))
|
||||||
|
|
||||||
|
|
||||||
|
def adjacent(self, other):
|
||||||
|
""" Is the one grid adjacent in any planar direction to the other """
|
||||||
|
if self == other + vector3d(1,0,0):
|
||||||
|
return True
|
||||||
|
elif self == other + vector3d(-1,0,0):
|
||||||
|
return True
|
||||||
|
elif self == other + vector3d(0,1,0):
|
||||||
|
return True
|
||||||
|
elif self == other + vector3d(0,-1,0):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue