mirror of https://github.com/VLSIDA/OpenRAM.git
Fix unconnected supply pin bug in supply router.
Simplified some of the supply router pin groups so that it assumes each group is fully connected. When computing enclosures of the pins on the routing grid, it will remove disconnected enclosure shapes to keep things connected.
This commit is contained in:
parent
2e353639f7
commit
7f5e6dd6f8
|
|
@ -25,7 +25,7 @@ class pin_group:
|
|||
|
||||
# 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 = [set(irredundant_pin_set)]
|
||||
self.pins = set(irredundant_pin_set)
|
||||
|
||||
self.router = router
|
||||
# These are the corresponding pin grids for each pin group.
|
||||
|
|
@ -55,7 +55,7 @@ class pin_group:
|
|||
total_string += grids_string
|
||||
|
||||
if self.enclosed:
|
||||
enlosure_string = "\n enclose={}".format(self.enclosures)
|
||||
enclosure_string = "\n enclose={}".format(self.enclosures)
|
||||
total_string += enclosure_string
|
||||
|
||||
total_string += ")"
|
||||
|
|
@ -74,25 +74,6 @@ class pin_group:
|
|||
def is_routed(self):
|
||||
return self.routed
|
||||
|
||||
def pins_enclosed(self):
|
||||
"""
|
||||
Check if all of the pin shapes are enclosed.
|
||||
Does not check if the DRC is correct, but just touching.
|
||||
"""
|
||||
for pin_list in self.pins:
|
||||
pin_is_enclosed=False
|
||||
for pin in pin_list:
|
||||
if pin_is_enclosed:
|
||||
break
|
||||
for encosure in self.enclosures:
|
||||
if pin.overlaps(enclosure):
|
||||
pin_is_enclosed=True
|
||||
break
|
||||
else:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def remove_redundant_shapes(self, pin_list):
|
||||
"""
|
||||
Remove any pin layout that is contained within another.
|
||||
|
|
@ -135,7 +116,6 @@ class pin_group:
|
|||
|
||||
return new_pin_list
|
||||
|
||||
# FIXME: This relies on some technology parameters from router which is not clean.
|
||||
def compute_enclosures(self):
|
||||
"""
|
||||
Find the minimum rectangle enclosures of the given tracks.
|
||||
|
|
@ -406,8 +386,8 @@ class pin_group:
|
|||
def enclose_pin_grids(self, ll, dir1=direction.NORTH, dir2=direction.EAST):
|
||||
"""
|
||||
This encloses a single pin component with a rectangle
|
||||
starting with the seed and expanding right until blocked
|
||||
and then up until blocked.
|
||||
starting with the seed and expanding dir1 until blocked
|
||||
and then dir2 until blocked.
|
||||
dir1 and dir2 should be two orthogonal directions.
|
||||
"""
|
||||
|
||||
|
|
@ -458,61 +438,86 @@ class pin_group:
|
|||
# Compute the enclosure pin_layout list of the set of tracks
|
||||
self.enclosures = self.compute_enclosures()
|
||||
|
||||
for pin_list in self.pins:
|
||||
for pin in pin_list:
|
||||
# Find a connector to every pin and add it to the enclosures
|
||||
for pin in self.pins:
|
||||
|
||||
# If it is contained, it won't need a connector
|
||||
if pin.contained_by_any(self.enclosures):
|
||||
continue
|
||||
# If it is contained, it won't need a connector
|
||||
if pin.contained_by_any(self.enclosures):
|
||||
continue
|
||||
|
||||
# Find a connector in the cardinal directions
|
||||
# If there is overlap, but it isn't contained, these could all be None
|
||||
# These could also be none if the pin is diagonal from the enclosure
|
||||
left_connector = self.find_left_connector(pin, self.enclosures)
|
||||
right_connector = self.find_right_connector(pin, self.enclosures)
|
||||
above_connector = self.find_above_connector(pin, self.enclosures)
|
||||
below_connector = self.find_below_connector(pin, self.enclosures)
|
||||
connector_list = [left_connector, right_connector, above_connector, below_connector]
|
||||
filtered_list = list(filter(lambda x: x!=None, connector_list))
|
||||
if (len(filtered_list)>0):
|
||||
import copy
|
||||
bbox_connector = copy.copy(pin)
|
||||
bbox_connector.bbox(filtered_list)
|
||||
self.enclosures.append(bbox_connector)
|
||||
# Find a connector in the cardinal directions
|
||||
# If there is overlap, but it isn't contained, these could all be None
|
||||
# These could also be none if the pin is diagonal from the enclosure
|
||||
left_connector = self.find_left_connector(pin, self.enclosures)
|
||||
right_connector = self.find_right_connector(pin, self.enclosures)
|
||||
above_connector = self.find_above_connector(pin, self.enclosures)
|
||||
below_connector = self.find_below_connector(pin, self.enclosures)
|
||||
connector_list = [left_connector, right_connector, above_connector, below_connector]
|
||||
filtered_list = list(filter(lambda x: x!=None, connector_list))
|
||||
if (len(filtered_list)>0):
|
||||
import copy
|
||||
bbox_connector = copy.copy(pin)
|
||||
bbox_connector.bbox(filtered_list)
|
||||
self.enclosures.append(bbox_connector)
|
||||
|
||||
# Now, make sure each pin touches an enclosure. If not, add another (diagonal) connector.
|
||||
# This could only happen when there was no enclosure in any cardinal direction from a pin
|
||||
for pin_list in self.pins:
|
||||
if not self.overlap_any_shape(pin_list, self.enclosures):
|
||||
connector = self.find_smallest_connector(pin_list, self.enclosures)
|
||||
if connector==None:
|
||||
debug.error("Could not find a connector for {} with {}".format(pin_list, self.enclosures))
|
||||
self.router.write_debug_gds("no_connector.gds")
|
||||
self.enclosures.append(connector)
|
||||
|
||||
if not self.overlap_any_shape(self.pins, self.enclosures):
|
||||
connector = self.find_smallest_connector(pin_list, self.enclosures)
|
||||
if connector==None:
|
||||
debug.error("Could not find a connector for {} with {}".format(pin_list, self.enclosures))
|
||||
self.router.write_debug_gds("no_connector.gds")
|
||||
self.enclosures.append(connector)
|
||||
|
||||
# At this point, the pins are overlapping, but there might be more than one!
|
||||
overlap_set = set()
|
||||
for pin in self.pins:
|
||||
overlap_set.update(self.transitive_overlap(pin, self.enclosures))
|
||||
# Use the new enclosures and recompute the grids that correspond to them
|
||||
if len(overlap_set)<len(self.enclosures):
|
||||
self.enclosures = overlap_set
|
||||
self.grids=set()
|
||||
# Also update the grid locations with the new (possibly pruned) enclosures
|
||||
for enclosure in self.enclosures:
|
||||
(sufficient,insufficient) = self.router.convert_pin_to_tracks(self.name,enclosure)
|
||||
self.grids.update(sufficient)
|
||||
|
||||
|
||||
debug.info(3,"Computed enclosure(s) {0}\n {1}\n {2}\n {3}".format(self.name,
|
||||
self.pins,
|
||||
self.grids,
|
||||
self.enclosures))
|
||||
|
||||
def combine_groups(self, pg1, pg2):
|
||||
def transitive_overlap(self, shape, shape_list):
|
||||
"""
|
||||
Combine two pin groups into one.
|
||||
Given shape, find the elements in shape_list that overlap transitively.
|
||||
I.e. if shape overlaps A and A overlaps B, return both A and B.
|
||||
"""
|
||||
self.pins = [*pg1.pins, *pg2.pins] # Join the two lists of pins
|
||||
self.grids = pg1.grids | pg2.grids # OR the set of grid locations
|
||||
self.secondary_grids = pg1.secondary_grids | pg2.secondary_grids
|
||||
|
||||
def add_group(self, pg):
|
||||
"""
|
||||
Combine the pin group into this one. This will add to the first item in the pins
|
||||
so this should be used before there are disconnected pins.
|
||||
"""
|
||||
debug.check(len(self.pins)==1,"Don't know which group to add pins to.")
|
||||
self.pins[0].update(*pg.pins) # Join the two lists of pins
|
||||
self.grids |= pg.grids # OR the set of grid locations
|
||||
self.secondary_grids |= pg.secondary_grids
|
||||
augmented_shape_list = set(shape_list)
|
||||
old_connected_set = set()
|
||||
connected_set = set([shape])
|
||||
# Repeat as long as we expand the set
|
||||
while len(connected_set) > len(old_connected_set):
|
||||
old_connected_set = connected_set
|
||||
connected_set = set([shape])
|
||||
for old_shape in old_connected_set:
|
||||
for cur_shape in augmented_shape_list:
|
||||
if old_shape.overlaps(cur_shape):
|
||||
connected_set.add(cur_shape)
|
||||
|
||||
|
||||
# Remove the original shape
|
||||
connected_set.remove(shape)
|
||||
|
||||
# if len(connected_set)<len(shape_list):
|
||||
# import pprint
|
||||
# print("S: ",shape)
|
||||
# pprint.pprint(shape_list)
|
||||
# pprint.pprint(connected_set)
|
||||
|
||||
return connected_set
|
||||
|
||||
|
||||
def add_enclosure(self, cell):
|
||||
"""
|
||||
|
|
@ -579,17 +584,16 @@ class pin_group:
|
|||
partial_set = set()
|
||||
blockage_set = set()
|
||||
|
||||
for pin_list in self.pins:
|
||||
for pin in pin_list:
|
||||
debug.info(2," Converting {0}".format(pin))
|
||||
# Determine which tracks the pin overlaps
|
||||
(sufficient,insufficient)=self.router.convert_pin_to_tracks(self.name, pin)
|
||||
pin_set.update(sufficient)
|
||||
partial_set.update(insufficient)
|
||||
for pin in self.pins:
|
||||
debug.info(2," Converting {0}".format(pin))
|
||||
# Determine which tracks the pin overlaps
|
||||
(sufficient,insufficient)=self.router.convert_pin_to_tracks(self.name, pin)
|
||||
pin_set.update(sufficient)
|
||||
partial_set.update(insufficient)
|
||||
|
||||
# Blockages will be a super-set of pins since it uses the inflated pin shape.
|
||||
blockage_in_tracks = self.router.convert_blockage(pin)
|
||||
blockage_set.update(blockage_in_tracks)
|
||||
# Blockages will be a super-set of pins since it uses the inflated pin shape.
|
||||
blockage_in_tracks = self.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
|
||||
|
|
@ -610,13 +614,12 @@ class pin_group:
|
|||
if (len(pin_set)==0 and len(partial_set)==0 and len(blockage_set)==0):
|
||||
#debug.warning("Pin is very close to metal blockage.\nAttempting to expand blocked pin {}".format(self.pins))
|
||||
|
||||
for pin_list in self.pins:
|
||||
for pin in pin_list:
|
||||
debug.warning(" Expanding conversion {0}".format(pin))
|
||||
# Determine which tracks the pin overlaps
|
||||
(sufficient,insufficient)=self.router.convert_pin_to_tracks(self.name, pin, expansion=1)
|
||||
pin_set.update(sufficient)
|
||||
partial_set.update(insufficient)
|
||||
for pin in self.pins:
|
||||
debug.warning(" Expanding conversion {0}".format(pin))
|
||||
# Determine which tracks the pin overlaps
|
||||
(sufficient,insufficient)=self.router.convert_pin_to_tracks(self.name, pin, expansion=1)
|
||||
pin_set.update(sufficient)
|
||||
partial_set.update(insufficient)
|
||||
|
||||
if len(pin_set)==0 and len(partial_set)==0:
|
||||
debug.error("Unable to find unblocked pin {} {}".format(self.name, self.pins))
|
||||
|
|
@ -630,62 +633,5 @@ class pin_group:
|
|||
debug.info(2," pins {}".format(self.grids))
|
||||
debug.info(2," secondary {}".format(self.secondary_grids))
|
||||
|
||||
# def recurse_simple_overlap_enclosure(self, start_set, direct):
|
||||
# """
|
||||
# Recursive function to return set of tracks that connects to
|
||||
# the actual supply rail wire in a given direction (or terminating
|
||||
# when any track is no longer in the supply rail.
|
||||
# """
|
||||
# next_set = grid_utils.expand_border(start_set, direct)
|
||||
|
||||
# supply_tracks = self.router.supply_rail_tracks[self.name]
|
||||
# supply_wire_tracks = self.router.supply_rail_wire_tracks[self.name]
|
||||
|
||||
# supply_overlap = next_set & supply_tracks
|
||||
# wire_overlap = next_set & supply_wire_tracks
|
||||
|
||||
# # If the rail overlap is the same, we are done, since we connected to the actual wire
|
||||
# if len(wire_overlap)==len(start_set):
|
||||
# new_set = start_set | wire_overlap
|
||||
# # If the supply overlap is the same, keep expanding unti we hit the wire or move out of the rail region
|
||||
# elif len(supply_overlap)==len(start_set):
|
||||
# recurse_set = self.recurse_simple_overlap_enclosure(supply_overlap, direct)
|
||||
# new_set = start_set | supply_overlap | recurse_set
|
||||
# else:
|
||||
# # If we got no next set, we are done, can't expand!
|
||||
# new_set = set()
|
||||
|
||||
# return new_set
|
||||
|
||||
# def create_simple_overlap_enclosure(self, start_set):
|
||||
# """
|
||||
# This takes a set of tracks that overlap a supply rail and creates an enclosure
|
||||
# that is ensured to overlap the supply rail wire.
|
||||
# It then adds rectangle(s) for the enclosure.
|
||||
# """
|
||||
# additional_set = set()
|
||||
# # Check the layer of any element in the pin to determine which direction to route it
|
||||
# e = next(iter(start_set))
|
||||
# new_set = start_set.copy()
|
||||
# if e.z==0:
|
||||
# new_set = self.recurse_simple_overlap_enclosure(start_set, direction.NORTH)
|
||||
# if not new_set:
|
||||
# new_set = self.recurse_simple_overlap_enclosure(start_set, direction.SOUTH)
|
||||
# else:
|
||||
# new_set = self.recurse_simple_overlap_enclosure(start_set, direction.EAST)
|
||||
# if not new_set:
|
||||
# new_set = self.recurse_simple_overlap_enclosure(start_set, direction.WEST)
|
||||
|
||||
# # Expand the pin grid set to include some extra grids that connect the supply rail
|
||||
# self.grids.update(new_set)
|
||||
|
||||
# # Block the grids
|
||||
# self.blockages.update(new_set)
|
||||
|
||||
# # Add the polygon enclosures and set this pin group as routed
|
||||
# self.set_routed()
|
||||
# self.enclosures = self.compute_enclosures()
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -187,60 +187,64 @@ class router(router_tech):
|
|||
start_time = datetime.now()
|
||||
self.enclose_pins()
|
||||
print_time("Enclosing pins",datetime.now(), start_time, 4)
|
||||
|
||||
|
||||
# MRG: Removing this code for now. The later compute enclosure code
|
||||
# assumes that all pins are touching and this may produce sets of pins
|
||||
# that are not connected.
|
||||
# def combine_adjacent_pins(self, pin_name):
|
||||
# """
|
||||
# Find pins that have adjacent routing tracks and merge them into a
|
||||
# single pin_group. The pins themselves may not be touching, but
|
||||
# enclose_pins in the next step will ensure they are touching.
|
||||
# """
|
||||
# debug.info(1,"Combining adjacent pins for {}.".format(pin_name))
|
||||
# # Find all adjacencies
|
||||
# adjacent_pins = {}
|
||||
# for index1,pg1 in enumerate(self.pin_groups[pin_name]):
|
||||
# for index2,pg2 in enumerate(self.pin_groups[pin_name]):
|
||||
# # Cannot combine with yourself, also don't repeat
|
||||
# if index1<=index2:
|
||||
# continue
|
||||
# # Combine if at least 1 grid cell is adjacent
|
||||
# if pg1.adjacent(pg2):
|
||||
# if not index1 in adjacent_pins:
|
||||
# adjacent_pins[index1] = set([index2])
|
||||
# else:
|
||||
# adjacent_pins[index1].add(index2)
|
||||
|
||||
# # Make a list of indices to ensure every group gets in the new set
|
||||
# all_indices = set([x for x in range(len(self.pin_groups[pin_name]))])
|
||||
|
||||
def combine_adjacent_pins(self, pin_name):
|
||||
"""
|
||||
Find pins that have adjacent routing tracks and merge them into a
|
||||
single pin_group. The pins themselves may not be touching, but
|
||||
enclose_pins in the next step will ensure they are touching.
|
||||
"""
|
||||
debug.info(1,"Combining adjacent pins for {}.".format(pin_name))
|
||||
# Find all adjacencies
|
||||
adjacent_pins = {}
|
||||
for index1,pg1 in enumerate(self.pin_groups[pin_name]):
|
||||
for index2,pg2 in enumerate(self.pin_groups[pin_name]):
|
||||
# Cannot combine with yourself, also don't repeat
|
||||
if index1<=index2:
|
||||
continue
|
||||
# Combine if at least 1 grid cell is adjacent
|
||||
if pg1.adjacent(pg2):
|
||||
if not index1 in adjacent_pins:
|
||||
adjacent_pins[index1] = set([index2])
|
||||
else:
|
||||
adjacent_pins[index1].add(index2)
|
||||
# # Now reconstruct the new groups
|
||||
# new_pin_groups = []
|
||||
# for index1,index2_set in adjacent_pins.items():
|
||||
# # Remove the indices if they are added to the new set
|
||||
# all_indices.discard(index1)
|
||||
# all_indices.difference_update(index2_set)
|
||||
|
||||
# Make a list of indices to ensure every group gets in the new set
|
||||
all_indices = set([x for x in range(len(self.pin_groups[pin_name]))])
|
||||
# # Create the combined group starting with the first item
|
||||
# combined = self.pin_groups[pin_name][index1]
|
||||
# # Add all of the other items that overlapped
|
||||
# for index2 in index2_set:
|
||||
# pg = self.pin_groups[pin_name][index2]
|
||||
# combined.add_group(pg)
|
||||
# debug.info(3,"Combining {0} {1}:".format(pin_name, index2))
|
||||
# debug.info(3, " {0}\n {1}".format(combined.pins, pg.pins))
|
||||
# debug.info(3," --> {0}\n {1}".format(combined.pins,combined.grids))
|
||||
# new_pin_groups.append(combined)
|
||||
|
||||
# # Add the pin groups that weren't added to the new set
|
||||
# for index in all_indices:
|
||||
# new_pin_groups.append(self.pin_groups[pin_name][index])
|
||||
|
||||
# old_size = len(self.pin_groups[pin_name])
|
||||
# # Use the new pin group!
|
||||
# self.pin_groups[pin_name] = new_pin_groups
|
||||
# removed_pairs = old_size - len(new_pin_groups)
|
||||
# debug.info(1, "Combined {0} pin groups for {1}".format(removed_pairs,pin_name))
|
||||
|
||||
# Now reconstruct the new groups
|
||||
new_pin_groups = []
|
||||
for index1,index2_set in adjacent_pins.items():
|
||||
# Remove the indices if they are added to the new set
|
||||
all_indices.discard(index1)
|
||||
all_indices.difference_update(index2_set)
|
||||
|
||||
# Create the combined group starting with the first item
|
||||
combined = self.pin_groups[pin_name][index1]
|
||||
# Add all of the other items that overlapped
|
||||
for index2 in index2_set:
|
||||
pg = self.pin_groups[pin_name][index2]
|
||||
combined.add_group(pg)
|
||||
debug.info(3,"Combining {0} {1}:".format(pin_name, index2))
|
||||
debug.info(3, " {0}\n {1}".format(combined.pins, pg.pins))
|
||||
debug.info(3," --> {0}\n {1}".format(combined.pins,combined.grids))
|
||||
new_pin_groups.append(combined)
|
||||
|
||||
# Add the pin groups that weren't added to the new set
|
||||
for index in all_indices:
|
||||
new_pin_groups.append(self.pin_groups[pin_name][index])
|
||||
|
||||
old_size = len(self.pin_groups[pin_name])
|
||||
# Use the new pin group!
|
||||
self.pin_groups[pin_name] = new_pin_groups
|
||||
removed_pairs = old_size - len(new_pin_groups)
|
||||
debug.info(1, "Combined {0} pin groups for {1}".format(removed_pairs,pin_name))
|
||||
|
||||
return removed_pairs
|
||||
# return removed_pairs
|
||||
|
||||
|
||||
def separate_adjacent_pins(self, separation):
|
||||
|
|
@ -748,44 +752,10 @@ class router(router_tech):
|
|||
if gid not in group_map:
|
||||
group_map[gid] = pin_group(name=pin_name, pin_set=[], router=self)
|
||||
# We always add it to the first set since they are touching
|
||||
group_map[gid].pins[0].add(pin)
|
||||
group_map[gid].pins.add(pin)
|
||||
|
||||
self.pin_groups[pin_name] = list(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):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ class supply_router(router):
|
|||
# Determine the rail locations
|
||||
self.route_supply_rails(self.vdd_name,1)
|
||||
print_time("Routing supply rails",datetime.now(), start_time, 3)
|
||||
|
||||
|
||||
start_time = datetime.now()
|
||||
self.route_simple_overlaps(vdd_name)
|
||||
self.route_simple_overlaps(gnd_name)
|
||||
|
|
@ -94,10 +94,23 @@ class supply_router(router):
|
|||
self.route_pins_to_rails(gnd_name)
|
||||
print_time("Maze routing supplies",datetime.now(), start_time, 3)
|
||||
#self.write_debug_gds("final.gds",False)
|
||||
|
||||
# Did we route everything??
|
||||
if not self.check_all_routed(vdd_name):
|
||||
return False
|
||||
if not self.check_all_routed(gnd_name):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def check_all_routed(self, pin_name):
|
||||
"""
|
||||
Check that all pin groups are routed.
|
||||
"""
|
||||
for pg in self.pin_groups[pin_name]:
|
||||
if not pg.is_routed():
|
||||
return False
|
||||
|
||||
def route_simple_overlaps(self, pin_name):
|
||||
"""
|
||||
|
|
@ -146,7 +159,7 @@ class supply_router(router):
|
|||
# We need to move this rail to the other layer for the z indices to match
|
||||
# during the intersection. This also makes a copy.
|
||||
new_r1 = {vector3d(i.x,i.y,1) for i in r1}
|
||||
|
||||
|
||||
for i2,r2 in enumerate(all_rails):
|
||||
# Never compare to yourself
|
||||
if i1==i2:
|
||||
|
|
@ -202,7 +215,7 @@ class supply_router(router):
|
|||
ur = grid_utils.get_upper_right(rail)
|
||||
z = ll.z
|
||||
pin = self.compute_pin_enclosure(ll, ur, z, name)
|
||||
debug.info(2,"Adding supply rail {0} {1}->{2} {3}".format(name,ll,ur,pin))
|
||||
debug.info(3,"Adding supply rail {0} {1}->{2} {3}".format(name,ll,ur,pin))
|
||||
self.cell.add_layout_pin(text=name,
|
||||
layer=pin.layer,
|
||||
offset=pin.ll(),
|
||||
|
|
@ -379,7 +392,10 @@ class supply_router(router):
|
|||
|
||||
# Actually run the A* router
|
||||
if not self.run_router(detour_scale=5):
|
||||
self.write_debug_gds()
|
||||
self.write_debug_gds("debug_route.gds",False)
|
||||
|
||||
#if index==3 and pin_name=="vdd":
|
||||
# self.write_debug_gds("route.gds",False)
|
||||
|
||||
|
||||
def add_supply_rail_target(self, pin_name):
|
||||
|
|
|
|||
Loading…
Reference in New Issue