mirror of https://github.com/VLSIDA/OpenRAM.git
Update signal routing for new blockage and pins.
This commit is contained in:
parent
7ead566154
commit
59956f1446
|
|
@ -713,9 +713,9 @@ class VlsiLayout:
|
|||
# Convert to user units
|
||||
new_boundaries = []
|
||||
for pin_boundary in pin_boundaries:
|
||||
new_boundaries.append([pin_boundary[0]*self.units[0],pin_boundary[1]*self.units[0],
|
||||
pin_boundary[2]*self.units[0],pin_boundary[3]*self.units[0]])
|
||||
|
||||
new_pin_boundary = [pin_boundary[0]*self.units[0],pin_boundary[1]*self.units[0],
|
||||
pin_boundary[2]*self.units[0],pin_boundary[3]*self.units[0]]
|
||||
new_boundaries.append(["p"+str(coordinate)+"_"+str(layer), layer, new_pin_boundary])
|
||||
return new_boundaries
|
||||
|
||||
def getPinShapeByLabel(self,label_name):
|
||||
|
|
|
|||
|
|
@ -34,15 +34,15 @@ class astar_grid(grid.grid):
|
|||
def add_source(self,track_list):
|
||||
debug.info(2,"Adding source list={0}".format(str(track_list)))
|
||||
for n in track_list:
|
||||
if not self.is_blocked(n):
|
||||
debug.info(3,"Adding source ={0}".format(str(n)))
|
||||
self.set_source(n)
|
||||
debug.info(3,"Adding source ={0}".format(str(n)))
|
||||
self.set_source(n)
|
||||
|
||||
|
||||
def add_target(self,track_list):
|
||||
debug.info(2,"Adding target list={0}".format(str(track_list)))
|
||||
for n in track_list:
|
||||
if not self.is_blocked(n):
|
||||
self.set_target(n)
|
||||
debug.info(3,"Adding target ={0}".format(str(n)))
|
||||
self.set_target(n)
|
||||
|
||||
def is_target(self,point):
|
||||
"""
|
||||
|
|
@ -73,18 +73,14 @@ class astar_grid(grid.grid):
|
|||
We will use an A* search, so this cost must be pessimistic.
|
||||
Cost so far will be the length of the path.
|
||||
"""
|
||||
debug.info(4,"Initializing queue.")
|
||||
|
||||
# uniquify the source (and target while we are at it)
|
||||
self.source = list(set(self.source))
|
||||
self.target = list(set(self.target))
|
||||
debug.info(1,"Initializing queue.")
|
||||
|
||||
# Counter is used to not require data comparison in Python 3.x
|
||||
# Items will be returned in order they are added during cost ties
|
||||
self.counter = 0
|
||||
for s in self.source:
|
||||
cost = self.cost_to_target(s)
|
||||
debug.info(1,"Init: cost=" + str(cost) + " " + str([s]))
|
||||
debug.info(2,"Init: cost=" + str(cost) + " " + str([s]))
|
||||
heappush(self.q,(cost,self.counter,[s]))
|
||||
self.counter+=1
|
||||
|
||||
|
|
|
|||
|
|
@ -63,6 +63,15 @@ class grid:
|
|||
for p in path:
|
||||
self.map[p].path=True
|
||||
|
||||
def block_path(self,path):
|
||||
"""
|
||||
Mark the path in the routing grid as blocked.
|
||||
Also unsets the path flag.
|
||||
"""
|
||||
for p in path:
|
||||
self.map[p].path=False
|
||||
self.map[p].blocked=True
|
||||
|
||||
def cost(self,path):
|
||||
"""
|
||||
The cost of the path is the length plus a penalty for the number
|
||||
|
|
|
|||
|
|
@ -96,12 +96,13 @@ class router:
|
|||
Pin can either be a label or a location,layer pair: [[x,y],layer].
|
||||
"""
|
||||
|
||||
shape_list=self.layout.getPinShapeByLabel(str(pin_name))
|
||||
shape_list=self.layout.getAllPinShapesByLabel(str(pin_name))
|
||||
pin_list = []
|
||||
for shape in shape_list:
|
||||
(name,layer,boundary)=shape
|
||||
rect = [vector(boundary[0],boundary[1]),vector(boundary[2],boundary[3])]
|
||||
pin = pin_layout(pin_name, rect, layer)
|
||||
debug.info(2,"Found pin {}".format(str(pin)))
|
||||
pin_list.append(pin)
|
||||
|
||||
debug.check(len(pin_list)>0,"Did not find any pin shapes for {0}.".format(str(pin)))
|
||||
|
|
@ -219,7 +220,7 @@ class router:
|
|||
for pin in all_pins:
|
||||
# If the blockage overlaps the pin and is on the same layer,
|
||||
# it must be connected, so skip it.
|
||||
if blockage==pin:
|
||||
if blockage.overlaps(pin):
|
||||
debug.info(1,"Removing blockage for pin {}".format(str(pin)))
|
||||
break
|
||||
else:
|
||||
|
|
@ -288,7 +289,7 @@ class router:
|
|||
If a pin has insufficent overlap, it returns the blockage list to avoid it.
|
||||
"""
|
||||
(ll,ur) = pin.rect
|
||||
#debug.info(1,"Converting [ {0} , {1} ]".format(ll,ur))
|
||||
debug.info(1,"Converting [ {0} , {1} ]".format(ll,ur))
|
||||
|
||||
# scale the size bigger to include neaby tracks
|
||||
ll=ll.scale(self.track_factor).floor()
|
||||
|
|
@ -304,31 +305,31 @@ class router:
|
|||
track_list = []
|
||||
block_list = []
|
||||
|
||||
track_area = self.track_width*self.track_width
|
||||
for x in range(ll[0],ur[0]):
|
||||
for y in range(ll[1],ur[1]):
|
||||
#debug.info(1,"Converting [ {0} , {1} ]".format(x,y))
|
||||
debug.info(1,"Converting [ {0} , {1} ]".format(x,y))
|
||||
|
||||
# however, if there is not enough overlap, then if there is any overlap at all,
|
||||
# we need to block it to prevent routes coming in on that grid
|
||||
full_rect = self.convert_track_to_shape(vector3d(x,y,zindex))
|
||||
track_area = (full_rect[1].x-full_rect[0].x)*(full_rect[1].y-full_rect[0].y)
|
||||
overlap_rect=self.compute_overlap(pin.rect,full_rect)
|
||||
overlap_area = overlap_rect[0]*overlap_rect[1]
|
||||
#debug.info(1,"Check overlap: {0} {1} max={2}".format(shape,rect,max_overlap))
|
||||
debug.info(1,"Check overlap: {0} {1} max={2}".format(pin.rect,overlap_rect,overlap_area))
|
||||
|
||||
# Assume if more than half the area, it is occupied
|
||||
overlap_ratio = overlap_area/track_area
|
||||
if overlap_ratio > 0.5:
|
||||
if overlap_ratio > 0.25:
|
||||
track_list.append(vector3d(x,y,zindex))
|
||||
# otherwise, the pin may not be accessible, so block it
|
||||
elif overlap_ratio > 0:
|
||||
block_list.append(vector3d(x,y,zindex))
|
||||
else:
|
||||
debug.info(4,"No overlap: {0} {1} max={2}".format(pin.rect,rect,max_overlap))
|
||||
print("H:",x,y)
|
||||
if x>38 and x<42 and y>42 and y<45:
|
||||
print(pin)
|
||||
print(full_rect, overlap_rect, overlap_ratio)
|
||||
debug.info(4,"No overlap: {0} {1} max={2}".format(pin.rect,overlap_rect,overlap_area))
|
||||
# print("H:",x,y)
|
||||
# if x>38 and x<42 and y>42 and y<45:
|
||||
# print(pin)
|
||||
# print(full_rect, overlap_rect, overlap_ratio)
|
||||
#debug.warning("Off-grid pin for {0}.".format(str(pin)))
|
||||
#debug.info(1,"Converted [ {0} , {1} ]".format(ll,ur))
|
||||
return (track_list,block_list)
|
||||
|
|
@ -480,6 +481,74 @@ class router:
|
|||
height=ur.y-ll.y)
|
||||
|
||||
|
||||
def add_route(self,path):
|
||||
"""
|
||||
Add the current wire route to the given design instance.
|
||||
"""
|
||||
debug.info(3,"Set path: " + str(path))
|
||||
|
||||
# Keep track of path for future blockages
|
||||
self.paths.append(path)
|
||||
|
||||
# This is marked for debug
|
||||
self.rg.add_path(path)
|
||||
|
||||
# For debugging... if the path failed to route.
|
||||
if False or path==None:
|
||||
self.write_debug_gds()
|
||||
|
||||
|
||||
# First, simplify the path for
|
||||
#debug.info(1,str(self.path))
|
||||
contracted_path = self.contract_path(path)
|
||||
debug.info(1,str(contracted_path))
|
||||
|
||||
# convert the path back to absolute units from tracks
|
||||
abs_path = map(self.convert_point_to_units,contracted_path)
|
||||
debug.info(1,str(abs_path))
|
||||
self.cell.add_route(self.layers,abs_path)
|
||||
|
||||
|
||||
def get_inertia(self,p0,p1):
|
||||
"""
|
||||
Sets the direction based on the previous direction we came from.
|
||||
"""
|
||||
# direction (index) of movement
|
||||
if p0.x!=p1.x:
|
||||
return 0
|
||||
elif p0.y!=p1.y:
|
||||
return 1
|
||||
else:
|
||||
# z direction
|
||||
return 2
|
||||
|
||||
def contract_path(self,path):
|
||||
"""
|
||||
Remove intermediate points in a rectilinear path.
|
||||
"""
|
||||
newpath = [path[0]]
|
||||
for i in range(1,len(path)-1):
|
||||
prev_inertia=self.get_inertia(path[i-1],path[i])
|
||||
next_inertia=self.get_inertia(path[i],path[i+1])
|
||||
# if we switch directions, add the point, otherwise don't
|
||||
if prev_inertia!=next_inertia:
|
||||
newpath.append(path[i])
|
||||
|
||||
# always add the last path
|
||||
newpath.append(path[-1])
|
||||
return newpath
|
||||
|
||||
|
||||
def add_path_blockages(self):
|
||||
"""
|
||||
Go through all of the past paths and add them as blockages.
|
||||
This is so we don't have to write/reload the GDS.
|
||||
"""
|
||||
for path in self.paths:
|
||||
self.rg.block_path(path)
|
||||
|
||||
|
||||
|
||||
# FIXME: This should be replaced with vector.snap_to_grid at some point
|
||||
|
||||
def snap_to_grid(offset):
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ class signal_router(router):
|
|||
"""
|
||||
router.__init__(self, gds_name, module)
|
||||
|
||||
self.pins = {}
|
||||
|
||||
# all the paths we've routed so far (to supplement the blockages)
|
||||
self.paths = []
|
||||
|
||||
|
|
@ -45,8 +47,9 @@ class signal_router(router):
|
|||
"""
|
||||
debug.info(1,"Running signal router from {0} to {1}...".format(src,dest))
|
||||
self.cell = cell
|
||||
self.source_pin_name = src
|
||||
self.target_pin_name = dest
|
||||
|
||||
self.pins[src] = []
|
||||
self.pins[dest] = []
|
||||
|
||||
# Clear the pins if we have previously routed
|
||||
if (hasattr(self,'rg')):
|
||||
|
|
@ -61,15 +64,16 @@ class signal_router(router):
|
|||
# This will get all shapes as blockages
|
||||
self.find_blockages()
|
||||
|
||||
# Get the pin shapes
|
||||
# Now add the blockages (all shapes except the pins)
|
||||
self.get_pin(src)
|
||||
self.get_pin(dest)
|
||||
|
||||
# Now add the blockages (all shapes except the src/tgt pins)
|
||||
# Now add the blockages
|
||||
self.add_blockages()
|
||||
# Add blockages from previous paths
|
||||
self.add_path_blockages()
|
||||
|
||||
|
||||
# Now add the src/tgt if they are not blocked by other shapes
|
||||
self.add_pin(src,True)
|
||||
self.add_pin(dest,False)
|
||||
|
|
@ -91,72 +95,6 @@ class signal_router(router):
|
|||
return False
|
||||
|
||||
|
||||
def add_route(self,path):
|
||||
"""
|
||||
Add the current wire route to the given design instance.
|
||||
"""
|
||||
debug.info(3,"Set path: " + str(path))
|
||||
|
||||
# Keep track of path for future blockages
|
||||
self.paths.append(path)
|
||||
|
||||
# This is marked for debug
|
||||
self.rg.add_path(path)
|
||||
|
||||
# For debugging... if the path failed to route.
|
||||
if False or path==None:
|
||||
self.write_debug_gds()
|
||||
|
||||
|
||||
# First, simplify the path for
|
||||
#debug.info(1,str(self.path))
|
||||
contracted_path = self.contract_path(path)
|
||||
debug.info(1,str(contracted_path))
|
||||
|
||||
# convert the path back to absolute units from tracks
|
||||
abs_path = map(self.convert_point_to_units,contracted_path)
|
||||
debug.info(1,str(abs_path))
|
||||
self.cell.add_route(self.layers,abs_path)
|
||||
|
||||
|
||||
def get_inertia(self,p0,p1):
|
||||
"""
|
||||
Sets the direction based on the previous direction we came from.
|
||||
"""
|
||||
# direction (index) of movement
|
||||
if p0.x!=p1.x:
|
||||
return 0
|
||||
elif p0.y!=p1.y:
|
||||
return 1
|
||||
else:
|
||||
# z direction
|
||||
return 2
|
||||
|
||||
def contract_path(self,path):
|
||||
"""
|
||||
Remove intermediate points in a rectilinear path.
|
||||
"""
|
||||
newpath = [path[0]]
|
||||
for i in range(1,len(path)-1):
|
||||
prev_inertia=self.get_inertia(path[i-1],path[i])
|
||||
next_inertia=self.get_inertia(path[i],path[i+1])
|
||||
# if we switch directions, add the point, otherwise don't
|
||||
if prev_inertia!=next_inertia:
|
||||
newpath.append(path[i])
|
||||
|
||||
# always add the last path
|
||||
newpath.append(path[-1])
|
||||
return newpath
|
||||
|
||||
|
||||
def add_path_blockages(self):
|
||||
"""
|
||||
Go through all of the past paths and add them as blockages.
|
||||
This is so we don't have to write/reload the GDS.
|
||||
"""
|
||||
for path in self.paths:
|
||||
for grid in path:
|
||||
self.rg.set_blocked(grid)
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -34,10 +34,10 @@ class supply_router(router):
|
|||
self.rg.reinit()
|
||||
|
||||
|
||||
|
||||
def route(self, cell, layers, vdd_name="vdd", gnd_name="gnd"):
|
||||
"""
|
||||
Route a single source-destination net and return
|
||||
the simplified rectilinear path.
|
||||
Add power supply rails and connect all pins to these rails.
|
||||
"""
|
||||
debug.info(1,"Running supply router on {0} and {1}...".format(vdd_name, gnd_name))
|
||||
self.cell = cell
|
||||
|
|
@ -61,10 +61,12 @@ class supply_router(router):
|
|||
self.get_pin(vdd_name)
|
||||
self.get_pin(gnd_name)
|
||||
|
||||
# Now add the blockages (all shapes except the src/tgt pins)
|
||||
# Now add the blockages (all shapes except the pins)
|
||||
self.add_blockages()
|
||||
# Add blockages from previous routes
|
||||
self.add_path_blockages()
|
||||
|
||||
#self.route_supply_rails()
|
||||
|
||||
#self.route_supply_pins()
|
||||
|
||||
# source pin will be a specific layout pin
|
||||
# target pin will be the rails only
|
||||
|
|
@ -84,6 +86,37 @@ class supply_router(router):
|
|||
self.write_debug_gds()
|
||||
return False
|
||||
|
||||
def route_supply_rails(self):
|
||||
"""
|
||||
Add supply rails for vdd and gnd alternating in both layers.
|
||||
Connect cross-over points with vias.
|
||||
"""
|
||||
# vdd will be the even grids
|
||||
|
||||
# gnd will be the odd grids
|
||||
|
||||
|
||||
pass
|
||||
|
||||
def route_supply_pins(self, pin):
|
||||
"""
|
||||
This will route all the supply pins to supply rails one at a time.
|
||||
After each one, it adds the cells to the blockage list.
|
||||
"""
|
||||
for pin_name in self.pins.keys():
|
||||
for pin in self.pins[pin_name]:
|
||||
route_supply_pin(pin)
|
||||
|
||||
|
||||
|
||||
def route_supply_pin(self, pin):
|
||||
"""
|
||||
This will take a single pin and route it to the appropriate supply rail.
|
||||
Do not allow other pins to be destinations so that everything is connected
|
||||
to the rails.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def add_route(self,path):
|
||||
"""
|
||||
|
|
@ -125,22 +158,4 @@ class supply_router(router):
|
|||
self.rg = supply_grid.supply_grid()
|
||||
|
||||
|
||||
##########################
|
||||
# Gridded supply route functions
|
||||
##########################
|
||||
def create_grid(self, ll, ur):
|
||||
""" Create alternating vdd/gnd lines horizontally """
|
||||
|
||||
self.create_horizontal_grid()
|
||||
self.create_vertical_grid()
|
||||
|
||||
|
||||
def create_horizontal_grid(self):
|
||||
""" Create alternating vdd/gnd lines horizontally """
|
||||
|
||||
pass
|
||||
|
||||
def create_vertical_grid(self):
|
||||
""" Create alternating vdd/gnd lines horizontally """
|
||||
pass
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue