mirror of https://github.com/VLSIDA/OpenRAM.git
Change analyze_pins to a heuristic algorithm less than O(n^2)
This commit is contained in:
parent
a96f492d0a
commit
dfb2cf3cbd
|
|
@ -46,12 +46,13 @@ class router(router_tech):
|
||||||
|
|
||||||
### The pin data structures
|
### The pin data structures
|
||||||
# A map of pin names to a set of pin_layout structures
|
# A map of pin names to a set of pin_layout structures
|
||||||
|
# (i.e. pins with a given label)
|
||||||
self.pins = {}
|
self.pins = {}
|
||||||
# This is a set of all pins (ignoring names) so that can quickly not create blockages for pins
|
# This is a set of all pins (ignoring names) so that can quickly not create blockages for pins
|
||||||
# (They will be blocked based on the names we are routing)
|
# (They will be blocked when we are routing other nets based on their name.)
|
||||||
self.all_pins = set()
|
self.all_pins = set()
|
||||||
|
|
||||||
# A map of pin names to a list of pin groups
|
# The labeled pins above categorized into pin groups that are touching/connected.
|
||||||
self.pin_groups = {}
|
self.pin_groups = {}
|
||||||
|
|
||||||
### The blockage data structures
|
### The blockage data structures
|
||||||
|
|
@ -673,37 +674,109 @@ class router(router_tech):
|
||||||
|
|
||||||
def analyze_pins(self, pin_name):
|
def analyze_pins(self, pin_name):
|
||||||
"""
|
"""
|
||||||
Analyze the shapes of a pin and combine them into groups which are connected.
|
Analyze the shapes of a pin and combine them into pin_groups which are connected.
|
||||||
"""
|
"""
|
||||||
debug.info(2,"Analyzing pin groups for {}.".format(pin_name))
|
debug.info(2,"Analyzing pin groups for {}.".format(pin_name))
|
||||||
|
|
||||||
pin_set = self.pins[pin_name]
|
pin_set = self.pins[pin_name]
|
||||||
|
|
||||||
# Put each pin in an equivalence class of it's own
|
# This will be a list of pin tuples that overlap
|
||||||
equiv_classes = [set([x]) for x in pin_set]
|
overlap_list = []
|
||||||
def combine_classes(equiv_classes):
|
|
||||||
for class1 in equiv_classes:
|
|
||||||
for class2 in equiv_classes:
|
|
||||||
if class1 == class2:
|
|
||||||
continue
|
|
||||||
# Compare each pin in each class,
|
|
||||||
# and if any overlap, update equiv_classes to include the combined the class
|
|
||||||
for p1 in class1:
|
|
||||||
for p2 in class2:
|
|
||||||
if p1.overlaps(p2):
|
|
||||||
combined_class = class1 | class2
|
|
||||||
equiv_classes.remove(class1)
|
|
||||||
equiv_classes.remove(class2)
|
|
||||||
equiv_classes.append(combined_class)
|
|
||||||
return(equiv_classes)
|
|
||||||
return(equiv_classes)
|
|
||||||
|
|
||||||
old_length = math.inf
|
# Sort the rectangles into a list with lower/upper y coordinates
|
||||||
while (len(equiv_classes)<old_length):
|
bottom_y_coordinates = [(x.by(), x, "bottom") for x in pin_set]
|
||||||
old_length = len(equiv_classes)
|
top_y_coordinates = [(x.uy(), x, "top") for x in pin_set]
|
||||||
equiv_classes = combine_classes(equiv_classes)
|
y_coordinates = bottom_y_coordinates + top_y_coordinates
|
||||||
|
y_coordinates.sort(key=lambda x: x[0])
|
||||||
|
|
||||||
self.pin_groups[pin_name] = [pin_group(name=pin_name, pin_set=x, router=self) for x in equiv_classes]
|
# Map the pins to the lower indices
|
||||||
|
bottom_index_map = {x[1]:i for i,x in enumerate(y_coordinates) if x[2]=="bottom"}
|
||||||
|
top_index_map = {x[1]:i for i,x in enumerate(y_coordinates) if x[2]=="bottom"}
|
||||||
|
|
||||||
|
# Sort the pin list by x coordinate
|
||||||
|
pin_list = list(pin_set)
|
||||||
|
pin_list.sort(key=lambda x: x.lx())
|
||||||
|
|
||||||
|
# for shapes in x order
|
||||||
|
for pin in pin_list:
|
||||||
|
# start at pin's lower y coordinate
|
||||||
|
bottom_index = bottom_index_map[pin]
|
||||||
|
compared_pins = set()
|
||||||
|
for i in range(bottom_index,len(y_coordinates)):
|
||||||
|
compare_pin = y_coordinates[i][1]
|
||||||
|
# Don't overlap yourself
|
||||||
|
if pin==compare_pin:
|
||||||
|
continue
|
||||||
|
# Done when we encounter any shape above the pin
|
||||||
|
if compare_pin.by() > pin.uy():
|
||||||
|
break
|
||||||
|
# Don't double compare the same pin twice
|
||||||
|
if compare_pin in compared_pins:
|
||||||
|
continue
|
||||||
|
compared_pins.add(compare_pin)
|
||||||
|
# If we overlap, add them to the list
|
||||||
|
if pin.overlaps(compare_pin):
|
||||||
|
overlap_list.append((pin,compare_pin))
|
||||||
|
|
||||||
|
# Initial unique group assignments
|
||||||
|
group_id = {}
|
||||||
|
gid = 1
|
||||||
|
for pin in pin_list:
|
||||||
|
group_id[pin] = gid
|
||||||
|
gid += 1
|
||||||
|
|
||||||
|
for p in overlap_list:
|
||||||
|
(p1,p2) = p
|
||||||
|
for pin in pin_list:
|
||||||
|
if group_id[pin] == group_id[p2]:
|
||||||
|
group_id[pin] = group_id[p1]
|
||||||
|
|
||||||
|
|
||||||
|
# For each pin add it to it's group
|
||||||
|
group_map = {}
|
||||||
|
for pin in pin_list:
|
||||||
|
gid = group_id[pin]
|
||||||
|
if gid not in group_map.keys():
|
||||||
|
group_map[gid] = pin_group(name=pin_name, pin_set=[], router=self)
|
||||||
|
group = group_map[gid]
|
||||||
|
# We always add it to the first set since they are touching
|
||||||
|
group.pins[0].add(pin)
|
||||||
|
|
||||||
|
self.pin_groups[pin_name] = group_map.values()
|
||||||
|
|
||||||
|
# This is the old O(n^2) implementation
|
||||||
|
# def analyze_pins(self, pin_name):
|
||||||
|
# """
|
||||||
|
# Analyze the shapes of a pin and combine them into pin_groups which are connected.
|
||||||
|
# """
|
||||||
|
# debug.info(2,"Analyzing pin groups for {}.".format(pin_name))
|
||||||
|
|
||||||
|
# pin_set = self.pins[pin_name]
|
||||||
|
|
||||||
|
# # Put each pin in an equivalence class of it's own
|
||||||
|
# equiv_classes = [set([x]) for x in pin_set]
|
||||||
|
# def combine_classes(equiv_classes):
|
||||||
|
# for class1 in equiv_classes:
|
||||||
|
# for class2 in equiv_classes:
|
||||||
|
# if class1 == class2:
|
||||||
|
# continue
|
||||||
|
# # Compare each pin in each class,
|
||||||
|
# # and if any overlap, update equiv_classes to include the combined the class
|
||||||
|
# for p1 in class1:
|
||||||
|
# for p2 in class2:
|
||||||
|
# if p1.overlaps(p2):
|
||||||
|
# combined_class = class1 | class2
|
||||||
|
# equiv_classes.remove(class1)
|
||||||
|
# equiv_classes.remove(class2)
|
||||||
|
# equiv_classes.append(combined_class)
|
||||||
|
# return(equiv_classes)
|
||||||
|
# return(equiv_classes)
|
||||||
|
|
||||||
|
# old_length = math.inf
|
||||||
|
# while (len(equiv_classes)<old_length):
|
||||||
|
# old_length = len(equiv_classes)
|
||||||
|
# equiv_classes = combine_classes(equiv_classes)
|
||||||
|
|
||||||
|
# self.pin_groups[pin_name] = [pin_group(name=pin_name, pin_set=x, router=self) for x in equiv_classes]
|
||||||
|
|
||||||
def convert_pins(self, pin_name):
|
def convert_pins(self, pin_name):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue