mirror of https://github.com/VLSIDA/OpenRAM.git
Debugging missing enclosures
This commit is contained in:
parent
9e5d78cfc2
commit
4ce6b040fd
|
|
@ -1,10 +1,12 @@
|
||||||
|
from pin_layout import pin_layout
|
||||||
from vector3d import vector3d
|
from vector3d import vector3d
|
||||||
|
from vector import vector
|
||||||
from tech import drc
|
from tech import drc
|
||||||
import debug
|
import debug
|
||||||
|
|
||||||
class pin_group:
|
class pin_group:
|
||||||
"""
|
"""
|
||||||
A class to represent a group of touching rectangular design pin.
|
A class to represent a group of rectangular design pin.
|
||||||
It requires a router to define the track widths and blockages which
|
It requires a router to define the track widths and blockages which
|
||||||
determine how pin shapes get mapped to tracks.
|
determine how pin shapes get mapped to tracks.
|
||||||
"""
|
"""
|
||||||
|
|
@ -12,7 +14,9 @@ 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.pins = pin_shapes
|
# This is a list because we can have a pin group of disconnected sets of pins
|
||||||
|
# and these are represented by separate lists
|
||||||
|
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()
|
||||||
|
|
@ -52,7 +56,7 @@ class pin_group:
|
||||||
debug.info(0,"FINAL :",new_pin_list)
|
debug.info(0,"FINAL :",new_pin_list)
|
||||||
return new_pin_list
|
return new_pin_list
|
||||||
|
|
||||||
# FIXME: This relies on some technology parameters from router which is not clearn.
|
# FIXME: This relies on some technology parameters from router which is not clean.
|
||||||
def compute_enclosures(self):
|
def compute_enclosures(self):
|
||||||
"""
|
"""
|
||||||
Find the minimum rectangle enclosures of the given tracks.
|
Find the minimum rectangle enclosures of the given tracks.
|
||||||
|
|
@ -64,6 +68,7 @@ class pin_group:
|
||||||
enclosure = self.router.compute_pin_enclosure(ll, ur, ll.z)
|
enclosure = self.router.compute_pin_enclosure(ll, ur, ll.z)
|
||||||
pin_list.append(enclosure)
|
pin_list.append(enclosure)
|
||||||
|
|
||||||
|
print("ENCLOS",pin_list)
|
||||||
#return pin_list
|
#return pin_list
|
||||||
# We used to do this, but smaller enclosures can be
|
# We used to do this, but smaller enclosures can be
|
||||||
return self.remove_redundant_shapes(pin_list)
|
return self.remove_redundant_shapes(pin_list)
|
||||||
|
|
@ -115,32 +120,48 @@ class pin_group:
|
||||||
Return the smallest.
|
Return the smallest.
|
||||||
"""
|
"""
|
||||||
smallest = None
|
smallest = None
|
||||||
for pin in self.pins:
|
for pin_list in self.pins:
|
||||||
for enclosure in enclosure_list:
|
for pin in pin_list:
|
||||||
new_enclosure = self.compute_enclosure(pin, enclosure)
|
for enclosure in enclosure_list:
|
||||||
if smallest == None or new_enclosure.area()<smallest.area():
|
new_enclosure = self.compute_enclosure(pin, enclosure)
|
||||||
smallest = new_enclosure
|
if smallest == None or new_enclosure.area()<smallest.area():
|
||||||
|
smallest = new_enclosure
|
||||||
|
|
||||||
return smallest
|
return smallest
|
||||||
|
|
||||||
def find_smallest_overlapping(self, shape_list):
|
def find_smallest_overlapping(self, pin_list, shape_list):
|
||||||
"""
|
"""
|
||||||
Find the smallest area shape in shape_list that overlaps with any
|
Find the smallest area shape in shape_list that overlaps with any
|
||||||
pin in pin_list by a min width.
|
pin in pin_list by a min width.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
smallest_shape = None
|
smallest_shape = None
|
||||||
for pin in self.pins:
|
for pin in pin_list:
|
||||||
# They may not be all on the same layer... in the future.
|
overlap_shape = self.find_smallest_overlapping_pin(pin,shape_list)
|
||||||
zindex=self.router.get_zindex(pin.layer_num)
|
if overlap_shape:
|
||||||
(min_width,min_space) = self.router.get_layer_width_space(zindex)
|
overlap_length = pin.overlap_length(overlap_shape)
|
||||||
|
if smallest_shape == None or overlap_shape.area()<smallest_shape.area():
|
||||||
|
smallest_shape = overlap_shape
|
||||||
|
|
||||||
|
return smallest_shape
|
||||||
|
|
||||||
# Now compare it with every other shape to check how much they overlap
|
|
||||||
for other in shape_list:
|
def find_smallest_overlapping_pin(self, pin, shape_list):
|
||||||
overlap_length = pin.overlap_length(other)
|
"""
|
||||||
if overlap_length > min_width:
|
Find the smallest area shape in shape_list that overlaps with any
|
||||||
if smallest_shape == None or other.area()<smallest_shape.area():
|
pin in pin_list by a min width.
|
||||||
smallest_shape = other
|
"""
|
||||||
|
|
||||||
|
smallest_shape = None
|
||||||
|
zindex=self.router.get_zindex(pin.layer_num)
|
||||||
|
(min_width,min_space) = self.router.get_layer_width_space(zindex)
|
||||||
|
|
||||||
|
# Now compare it with every other shape to check how much they overlap
|
||||||
|
for other in shape_list:
|
||||||
|
overlap_length = pin.overlap_length(other)
|
||||||
|
if overlap_length > min_width:
|
||||||
|
if smallest_shape == None or other.area()<smallest_shape.area():
|
||||||
|
smallest_shape = other
|
||||||
|
|
||||||
return smallest_shape
|
return smallest_shape
|
||||||
|
|
||||||
|
|
@ -167,7 +188,7 @@ class pin_group:
|
||||||
|
|
||||||
return pin
|
return pin
|
||||||
|
|
||||||
def enclose_pin_grids(self, seed):
|
def enclose_pin_grids(self, ll):
|
||||||
"""
|
"""
|
||||||
This encloses a single pin component with a rectangle
|
This encloses a single pin component with a rectangle
|
||||||
starting with the seed and expanding right until blocked
|
starting with the seed and expanding right until blocked
|
||||||
|
|
@ -178,9 +199,6 @@ class pin_group:
|
||||||
if not self.grids:
|
if not self.grids:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Start with the seed
|
|
||||||
ll = seed
|
|
||||||
|
|
||||||
# Start with the ll and make the widest row
|
# Start with the ll and make the widest row
|
||||||
row = [ll]
|
row = [ll]
|
||||||
# Move right while we can
|
# Move right while we can
|
||||||
|
|
@ -218,22 +236,36 @@ class pin_group:
|
||||||
"""
|
"""
|
||||||
# Compute the enclosure pin_layout list of the set of tracks
|
# Compute the enclosure pin_layout list of the set of tracks
|
||||||
enclosure_list = self.compute_enclosures()
|
enclosure_list = self.compute_enclosures()
|
||||||
self.enclosure = self.find_smallest_overlapping(enclosure_list)
|
|
||||||
if not self.enclosure:
|
|
||||||
self.enclosure = self.find_smallest_connector(enclosure_list)
|
|
||||||
debug.info(2,"Computed enclosure {0}\n {1}\n {2}\n {3}".format(self.name, self.pins, self.grids, self.enclosure))
|
|
||||||
|
|
||||||
|
# A single set of connected pins is easy, so use the optimized set
|
||||||
|
if len(self.pins)==1:
|
||||||
|
smallest = self.find_smallest_overlapping(self.pins[0],enclosure_list)
|
||||||
|
if smallest:
|
||||||
|
self.enclosures=[smallest]
|
||||||
|
else:
|
||||||
|
connector=self.find_smallest_connector(enclosure_list)
|
||||||
|
if connector:
|
||||||
|
self.enclosures=[connector]
|
||||||
|
else:
|
||||||
|
debug.error("Unable to enclose pin {}".format(self.pins),-1)
|
||||||
|
else:
|
||||||
|
# Multiple pins is hard, so just use all of the enclosure shapes!
|
||||||
|
# FIXME: Find the minimum set of enclosures to reduce number of shapes.
|
||||||
|
self.enclosures = enclosure_list
|
||||||
|
|
||||||
|
debug.info(2,"Computed enclosure(s) {0}\n {1}\n {2}\n {3}".format(self.name, self.pins, self.grids, self.enclosures))
|
||||||
|
|
||||||
|
|
||||||
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))
|
for enclosure in self.enclosures:
|
||||||
cell.add_rect(layer=self.enclosure.layer,
|
debug.info(2,"Adding enclosure {0} {1}".format(self.name, enclosure))
|
||||||
offset=self.enclosure.ll(),
|
cell.add_rect(layer=enclosure.layer,
|
||||||
width=self.enclosure.width(),
|
offset=enclosure.ll(),
|
||||||
height=self.enclosure.height())
|
width=enclosure.width(),
|
||||||
|
height=enclosure.height())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -255,14 +287,15 @@ class pin_group:
|
||||||
# Keep the same groups for each pin
|
# Keep the same groups for each pin
|
||||||
pin_set = set()
|
pin_set = set()
|
||||||
blockage_set = set()
|
blockage_set = set()
|
||||||
for pin in self.pins:
|
for pin_list in self.pins:
|
||||||
debug.info(2," Converting {0}".format(pin))
|
for pin in pin_list:
|
||||||
# Determine which tracks the pin overlaps
|
debug.info(2," Converting {0}".format(pin))
|
||||||
pin_in_tracks=router.convert_pin_to_tracks(self.name, pin)
|
# Determine which tracks the pin overlaps
|
||||||
pin_set.update(pin_in_tracks)
|
pin_in_tracks=router.convert_pin_to_tracks(self.name, pin)
|
||||||
# Blockages will be a super-set of pins since it uses the inflated pin shape.
|
pin_set.update(pin_in_tracks)
|
||||||
blockage_in_tracks = router.convert_blockage(pin)
|
# Blockages will be a super-set of pins since it uses the inflated pin shape.
|
||||||
blockage_set.update(blockage_in_tracks)
|
blockage_in_tracks = router.convert_blockage(pin)
|
||||||
|
blockage_set.update(blockage_in_tracks)
|
||||||
|
|
||||||
# If we have a blockage, we must remove the grids
|
# If we have a blockage, we must remove the grids
|
||||||
# Remember, this excludes the pin blockages already
|
# Remember, this excludes the pin blockages already
|
||||||
|
|
|
||||||
|
|
@ -175,13 +175,15 @@ class router(router_tech):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if pg1.adjacent(pg2):
|
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, [], self)
|
||||||
combined = pin_group(pin_name, pg1.pins | pg2.pins, self)
|
combined.pins = [pg1.pins, pg2.pins]
|
||||||
combined.grids = pg1.grids | pg2.grids
|
combined.grids = pg1.grids | pg2.grids
|
||||||
|
blocked_grids = combined.grids & self.blocked_grids
|
||||||
# check if there are any blockage problems??
|
# Only add this if we can
|
||||||
remove_indices.update([index1,index2])
|
if len(blocked_grids)==0:
|
||||||
pin_groups.append(combined)
|
debug.info(2,"Combing {0}:\n {1}\n {2}".format(pin_name, pg1.pins, pg2.pins))
|
||||||
|
remove_indices.update([index1,index2])
|
||||||
|
pin_groups.append(combined)
|
||||||
|
|
||||||
# Remove them in decreasing order to not invalidate the indices
|
# Remove them in decreasing order to not invalidate the indices
|
||||||
for i in sorted(remove_indices, reverse=True):
|
for i in sorted(remove_indices, reverse=True):
|
||||||
|
|
@ -884,10 +886,10 @@ class router(router_tech):
|
||||||
self.cell.add_label(text=str(t),
|
self.cell.add_label(text=str(t),
|
||||||
layer="text",
|
layer="text",
|
||||||
offset=type_off)
|
offset=type_off)
|
||||||
self.cell.add_label(text="{0},{1}".format(g[0],g[1]),
|
self.cell.add_label(text="{0},{1}".format(g[0],g[1]),
|
||||||
layer="text",
|
layer="text",
|
||||||
offset=shape[0],
|
offset=shape[0],
|
||||||
zoom=0.05)
|
zoom=0.05)
|
||||||
|
|
||||||
def add_router_info(self):
|
def add_router_info(self):
|
||||||
"""
|
"""
|
||||||
|
|
@ -899,8 +901,7 @@ class router(router_tech):
|
||||||
|
|
||||||
show_blockages = True
|
show_blockages = True
|
||||||
show_blockage_grids = True
|
show_blockage_grids = True
|
||||||
show_enclosures = False
|
show_enclosures = True
|
||||||
show_connectors = False
|
|
||||||
show_all_grids = True
|
show_all_grids = True
|
||||||
|
|
||||||
if show_all_grids:
|
if show_all_grids:
|
||||||
|
|
@ -923,20 +924,15 @@ class router(router_tech):
|
||||||
for g in grid_keys:
|
for g in grid_keys:
|
||||||
self.annotate_grid(g)
|
self.annotate_grid(g)
|
||||||
|
|
||||||
if show_connectors:
|
|
||||||
for pin in self.connector_enclosure:
|
|
||||||
#print("connector: ",str(pin))
|
|
||||||
self.cell.add_rect(layer="text",
|
|
||||||
offset=pin.ll(),
|
|
||||||
width=pin.width(),
|
|
||||||
height=pin.height())
|
|
||||||
if show_enclosures:
|
if show_enclosures:
|
||||||
for pin in self.enclosures:
|
for key in self.pin_groups.keys():
|
||||||
#print("enclosure: ",pin.name,pin.ll(),pin.width(),pin.height())
|
for pg in self.pin_groups[key]:
|
||||||
self.cell.add_rect(layer="text",
|
for pin in pg.enclosures:
|
||||||
offset=pin.ll(),
|
#print("enclosure: ",pin.name,pin.ll(),pin.width(),pin.height())
|
||||||
width=pin.width(),
|
self.cell.add_rect(layer="text",
|
||||||
height=pin.height())
|
offset=pin.ll(),
|
||||||
|
width=pin.width(),
|
||||||
|
height=pin.height())
|
||||||
|
|
||||||
# FIXME: This should be replaced with vector.snap_to_grid at some point
|
# FIXME: This should be replaced with vector.snap_to_grid at some point
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ class supply_router(router):
|
||||||
|
|
||||||
# Get the pin shapes
|
# Get the pin shapes
|
||||||
self.find_pins_and_blockages([self.vdd_name, self.gnd_name])
|
self.find_pins_and_blockages([self.vdd_name, self.gnd_name])
|
||||||
#self.write_debug_gds("pin_enclosures.gds",stop_program=False)
|
self.write_debug_gds("pin_enclosures.gds",stop_program=True)
|
||||||
|
|
||||||
# Add the supply rails in a mesh network and connect H/V with vias
|
# Add the supply rails in a mesh network and connect H/V with vias
|
||||||
# Block everything
|
# Block everything
|
||||||
|
|
@ -226,9 +226,8 @@ class supply_router(router):
|
||||||
# the overlap area for placement of a via
|
# the overlap area for placement of a via
|
||||||
overlap = new_r1 & new_r2
|
overlap = new_r1 & new_r2
|
||||||
if len(overlap) >= self.supply_rail_wire_width**2:
|
if len(overlap) >= self.supply_rail_wire_width**2:
|
||||||
debug.info(2,"Via overlap {0} {1} {2}".format(len(overlap),self.supply_rail_wire_width**2,overlap))
|
debug.info(3,"Via overlap {0} {1} {2}".format(len(overlap),self.supply_rail_wire_width**2,overlap))
|
||||||
connections.add(i1)
|
connections.update([i1,i2])
|
||||||
connections.add(i2)
|
|
||||||
via_areas.append(overlap)
|
via_areas.append(overlap)
|
||||||
|
|
||||||
# Go through and add the vias at the center of the intersection
|
# Go through and add the vias at the center of the intersection
|
||||||
|
|
@ -239,11 +238,12 @@ class supply_router(router):
|
||||||
self.add_via(center,self.rail_track_width)
|
self.add_via(center,self.rail_track_width)
|
||||||
|
|
||||||
# Determien which indices were not connected to anything above
|
# Determien which indices were not connected to anything above
|
||||||
all_indices = set([x for x in range(len(self.supply_rails[name]))])
|
missing_indices = set([x for x in range(len(self.supply_rails[name]))])
|
||||||
missing_indices = all_indices ^ connections
|
missing_indices.difference_update(connections)
|
||||||
|
|
||||||
# Go through and remove those disconnected indices
|
# Go through and remove those disconnected indices
|
||||||
# (No via was added, so that doesn't need to be removed)
|
# (No via was added, so that doesn't need to be removed)
|
||||||
for rail_index in missing_indices:
|
for rail_index in sorted(missing_indices, reverse=True):
|
||||||
ll = grid_utils.get_lower_left(all_rails[rail_index])
|
ll = grid_utils.get_lower_left(all_rails[rail_index])
|
||||||
ur = grid_utils.get_upper_right(all_rails[rail_index])
|
ur = grid_utils.get_upper_right(all_rails[rail_index])
|
||||||
debug.info(1,"Removing disconnected supply rail {0} .. {1}".format(ll,ur))
|
debug.info(1,"Removing disconnected supply rail {0} .. {1}".format(ll,ur))
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue