mirror of https://github.com/VLSIDA/OpenRAM.git
Fix run-time bug in combine adjacent pins for supply router
This commit is contained in:
parent
2f6300c7a0
commit
3cfefa784f
|
|
@ -495,6 +495,16 @@ class pin_group:
|
|||
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
|
||||
|
||||
def add_enclosure(self, cell):
|
||||
"""
|
||||
Add the enclosure shape to the given cell.
|
||||
|
|
|
|||
|
|
@ -9,9 +9,10 @@ from pin_layout import pin_layout
|
|||
from pin_group import pin_group
|
||||
from vector import vector
|
||||
from vector3d import vector3d
|
||||
from globals import OPTS
|
||||
from globals import OPTS,print_time
|
||||
from pprint import pformat
|
||||
import grid_utils
|
||||
from datetime import datetime
|
||||
|
||||
class router(router_tech):
|
||||
"""
|
||||
|
|
@ -31,16 +32,18 @@ class router(router_tech):
|
|||
|
||||
# If didn't specify a gds blockage file, write it out to read the gds
|
||||
# This isn't efficient, but easy for now
|
||||
#start_time = datetime.now()
|
||||
if not gds_filename:
|
||||
gds_filename = OPTS.openram_temp+"temp.gds"
|
||||
self.cell.gds_write(gds_filename)
|
||||
|
||||
|
||||
# Load the gds file and read in all the shapes
|
||||
self.layout = gdsMill.VlsiLayout(units=GDS["unit"])
|
||||
self.reader = gdsMill.Gds2reader(self.layout)
|
||||
self.reader.loadFromFile(gds_filename)
|
||||
self.top_name = self.layout.rootStructureName
|
||||
|
||||
#print_time("GDS read",datetime.now(), start_time)
|
||||
|
||||
### The pin data structures
|
||||
# A map of pin names to a set of pin_layout structures
|
||||
self.pins = {}
|
||||
|
|
@ -127,8 +130,12 @@ class router(router_tech):
|
|||
Pin can either be a label or a location,layer pair: [[x,y],layer].
|
||||
"""
|
||||
debug.info(1,"Finding pins for {}.".format(pin_name))
|
||||
#start_time = datetime.now()
|
||||
self.retrieve_pins(pin_name)
|
||||
#print_time("Retrieved pins",datetime.now(), start_time)
|
||||
#start_time = datetime.now()
|
||||
self.analyze_pins(pin_name)
|
||||
#print_time("Analyzed pins",datetime.now(), start_time)
|
||||
|
||||
def find_blockages(self):
|
||||
"""
|
||||
|
|
@ -152,97 +159,98 @@ class router(router_tech):
|
|||
self.find_pins(pin)
|
||||
|
||||
# This will get all shapes as blockages and convert to grid units
|
||||
# This ignores shapes that were pins
|
||||
# This ignores shapes that were pins
|
||||
#start_time = datetime.now()
|
||||
self.find_blockages()
|
||||
#print_time("Find blockags",datetime.now(), start_time)
|
||||
|
||||
# Convert the blockages to grid units
|
||||
#start_time = datetime.now()
|
||||
self.convert_blockages()
|
||||
#print_time("Find blockags",datetime.now(), start_time)
|
||||
|
||||
# This will convert the pins to grid units
|
||||
# It must be done after blockages to ensure no DRCs between expanded pins and blocked grids
|
||||
#start_time = datetime.now()
|
||||
for pin in pin_list:
|
||||
self.convert_pins(pin)
|
||||
|
||||
#print_time("Convert pins",datetime.now(), start_time)
|
||||
|
||||
#start_time = datetime.now()
|
||||
for pin in pin_list:
|
||||
self.combine_adjacent_pins(pin)
|
||||
#print_time("Combine pins",datetime.now(), start_time)
|
||||
#self.write_debug_gds("debug_combine_pins.gds",stop_program=True)
|
||||
|
||||
# Separate any adjacent grids of differing net names to prevent wide metal DRC violations
|
||||
# Must be done before enclosing pins
|
||||
#start_time = datetime.now()
|
||||
self.separate_adjacent_pins(self.supply_rail_space_width)
|
||||
#print_time("Separate pins",datetime.now(), start_time)
|
||||
# For debug
|
||||
#self.separate_adjacent_pins(1)
|
||||
|
||||
# Enclose the continguous grid units in a metal rectangle to fix some DRCs
|
||||
#start_time = datetime.now()
|
||||
self.enclose_pins()
|
||||
#print_time("Enclose pins",datetime.now(), start_time)
|
||||
#self.write_debug_gds("debug_enclose_pins.gds",stop_program=True)
|
||||
|
||||
|
||||
def combine_adjacent_pins_pass(self, 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_pis in the next step will ensure they are touching.
|
||||
"""
|
||||
|
||||
# Make a copy since we are going to add to (and then reduce) this list
|
||||
pin_groups = self.pin_groups[pin_name].copy()
|
||||
|
||||
# Start as None to signal the first iteration
|
||||
remove_indices = set()
|
||||
|
||||
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]):
|
||||
# Cannot combine more than once
|
||||
if index1 in remove_indices:
|
||||
continue
|
||||
for index2,pg2 in enumerate(self.pin_groups[pin_name]):
|
||||
# Cannot combine with yourself
|
||||
if index1==index2:
|
||||
# Cannot combine with yourself, also don't repeat
|
||||
if index1<=index2:
|
||||
continue
|
||||
# Cannot combine more than once
|
||||
if index2 in remove_indices:
|
||||
continue
|
||||
|
||||
# Combine if at least 1 grid cell is adjacent
|
||||
if pg1.adjacent(pg2):
|
||||
combined = pin_group(pin_name, [], self)
|
||||
combined.combine_groups(pg1, pg2)
|
||||
debug.info(3,"Combining {0} {1} {2}:".format(pin_name, index1, index2))
|
||||
debug.info(3, " {0}\n {1}".format(pg1.pins, pg2.pins))
|
||||
debug.info(3," --> {0}\n {1}".format(combined.pins,combined.grids))
|
||||
remove_indices.update([index1,index2])
|
||||
pin_groups.append(combined)
|
||||
break
|
||||
if not index1 in adjacent_pins.keys():
|
||||
adjacent_pins[index1] = set([index2])
|
||||
else:
|
||||
adjacent_pins[index1].add(index2)
|
||||
|
||||
# Remove them in decreasing order to not invalidate the indices
|
||||
debug.info(4,"Removing {}".format(sorted(remove_indices)))
|
||||
for i in sorted(remove_indices, reverse=True):
|
||||
del pin_groups[i]
|
||||
|
||||
# Use the new pin group!
|
||||
self.pin_groups[pin_name] = pin_groups
|
||||
# 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]))])
|
||||
|
||||
removed_pairs = int(len(remove_indices)/2)
|
||||
debug.info(1, "Combined {0} pin pairs 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
|
||||
|
||||
def combine_adjacent_pins(self, pin_name):
|
||||
"""
|
||||
Make multiple passes of the combine adjacent pins until we have no
|
||||
more combinations or hit an iteration limit.
|
||||
"""
|
||||
debug.info(1,"Combining adjacent pins for {}.".format(pin_name))
|
||||
# Start as None to signal the first iteration
|
||||
num_removed_pairs = None
|
||||
|
||||
# Just used in case there's a circular combination or something weird
|
||||
for iteration_count in range(10):
|
||||
num_removed_pairs = self.combine_adjacent_pins_pass(pin_name)
|
||||
if num_removed_pairs==0:
|
||||
break
|
||||
else:
|
||||
debug.warning("Did not converge combining adjacent pins in supply router.")
|
||||
|
||||
def separate_adjacent_pins(self, separation):
|
||||
"""
|
||||
|
|
@ -271,7 +279,7 @@ class router(router_tech):
|
|||
debug.info(1,"Comparing {0} and {1} adjacency".format(pin_name1, pin_name2))
|
||||
for index1,pg1 in enumerate(self.pin_groups[pin_name1]):
|
||||
for index2,pg2 in enumerate(self.pin_groups[pin_name2]):
|
||||
# FIXME: Use separation distance and edge grids only
|
||||
# FIgXME: Use separation distance and edge grids only
|
||||
grids_g1, grids_g2 = pg1.adjacent_grids(pg2, separation)
|
||||
# These should have the same length, so...
|
||||
if len(grids_g1)>0:
|
||||
|
|
|
|||
|
|
@ -2,13 +2,14 @@ import gdsMill
|
|||
import tech
|
||||
import math
|
||||
import debug
|
||||
from globals import OPTS
|
||||
from globals import OPTS,print_time
|
||||
from contact import contact
|
||||
from pin_group import pin_group
|
||||
from pin_layout import pin_layout
|
||||
from vector3d import vector3d
|
||||
from router import router
|
||||
from direction import direction
|
||||
from datetime import datetime
|
||||
import grid
|
||||
import grid_utils
|
||||
|
||||
|
|
@ -68,10 +69,13 @@ class supply_router(router):
|
|||
self.compute_supply_rail_dimensions()
|
||||
|
||||
# Get the pin shapes
|
||||
#start_time = datetime.now()
|
||||
self.find_pins_and_blockages([self.vdd_name, self.gnd_name])
|
||||
#print_time("Pins and blockages",datetime.now(), start_time)
|
||||
#self.write_debug_gds("pin_enclosures.gds",stop_program=True)
|
||||
|
||||
# Add the supply rails in a mesh network and connect H/V with vias
|
||||
#start_time = datetime.now()
|
||||
# Block everything
|
||||
self.prepare_blockages(self.gnd_name)
|
||||
# Determine the rail locations
|
||||
|
|
@ -82,15 +86,20 @@ class supply_router(router):
|
|||
# Determine the rail locations
|
||||
self.route_supply_rails(self.vdd_name,1)
|
||||
#self.write_debug_gds("debug_rails.gds",stop_program=True)
|
||||
|
||||
#print_time("Supply rails",datetime.now(), start_time)
|
||||
|
||||
#start_time = datetime.now()
|
||||
self.route_simple_overlaps(vdd_name)
|
||||
self.route_simple_overlaps(gnd_name)
|
||||
#print_time("Simple overlaps",datetime.now(), start_time)
|
||||
#self.write_debug_gds("debug_simple_route.gds",stop_program=False)
|
||||
|
||||
# Route the supply pins to the supply rails
|
||||
# Route vdd first since we want it to be shorter
|
||||
#start_time = datetime.now()
|
||||
self.route_pins_to_rails(vdd_name)
|
||||
self.route_pins_to_rails(gnd_name)
|
||||
#print_time("Routing",datetime.now(), start_time)
|
||||
#self.write_debug_gds("debug_pin_routes.gds",stop_program=True)
|
||||
|
||||
#self.write_debug_gds("final.gds",False)
|
||||
|
|
|
|||
Loading…
Reference in New Issue