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
|
# Convert to user units
|
||||||
new_boundaries = []
|
new_boundaries = []
|
||||||
for pin_boundary in pin_boundaries:
|
for pin_boundary in pin_boundaries:
|
||||||
new_boundaries.append([pin_boundary[0]*self.units[0],pin_boundary[1]*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]])
|
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
|
return new_boundaries
|
||||||
|
|
||||||
def getPinShapeByLabel(self,label_name):
|
def getPinShapeByLabel(self,label_name):
|
||||||
|
|
|
||||||
|
|
@ -34,14 +34,14 @@ class astar_grid(grid.grid):
|
||||||
def add_source(self,track_list):
|
def add_source(self,track_list):
|
||||||
debug.info(2,"Adding source list={0}".format(str(track_list)))
|
debug.info(2,"Adding source list={0}".format(str(track_list)))
|
||||||
for n in track_list:
|
for n in track_list:
|
||||||
if not self.is_blocked(n):
|
|
||||||
debug.info(3,"Adding source ={0}".format(str(n)))
|
debug.info(3,"Adding source ={0}".format(str(n)))
|
||||||
self.set_source(n)
|
self.set_source(n)
|
||||||
|
|
||||||
|
|
||||||
def add_target(self,track_list):
|
def add_target(self,track_list):
|
||||||
debug.info(2,"Adding target list={0}".format(str(track_list)))
|
debug.info(2,"Adding target list={0}".format(str(track_list)))
|
||||||
for n in track_list:
|
for n in track_list:
|
||||||
if not self.is_blocked(n):
|
debug.info(3,"Adding target ={0}".format(str(n)))
|
||||||
self.set_target(n)
|
self.set_target(n)
|
||||||
|
|
||||||
def is_target(self,point):
|
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.
|
We will use an A* search, so this cost must be pessimistic.
|
||||||
Cost so far will be the length of the path.
|
Cost so far will be the length of the path.
|
||||||
"""
|
"""
|
||||||
debug.info(4,"Initializing queue.")
|
debug.info(1,"Initializing queue.")
|
||||||
|
|
||||||
# uniquify the source (and target while we are at it)
|
|
||||||
self.source = list(set(self.source))
|
|
||||||
self.target = list(set(self.target))
|
|
||||||
|
|
||||||
# Counter is used to not require data comparison in Python 3.x
|
# Counter is used to not require data comparison in Python 3.x
|
||||||
# Items will be returned in order they are added during cost ties
|
# Items will be returned in order they are added during cost ties
|
||||||
self.counter = 0
|
self.counter = 0
|
||||||
for s in self.source:
|
for s in self.source:
|
||||||
cost = self.cost_to_target(s)
|
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]))
|
heappush(self.q,(cost,self.counter,[s]))
|
||||||
self.counter+=1
|
self.counter+=1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,15 @@ class grid:
|
||||||
for p in path:
|
for p in path:
|
||||||
self.map[p].path=True
|
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):
|
def cost(self,path):
|
||||||
"""
|
"""
|
||||||
The cost of the path is the length plus a penalty for the number
|
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].
|
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 = []
|
pin_list = []
|
||||||
for shape in shape_list:
|
for shape in shape_list:
|
||||||
(name,layer,boundary)=shape
|
(name,layer,boundary)=shape
|
||||||
rect = [vector(boundary[0],boundary[1]),vector(boundary[2],boundary[3])]
|
rect = [vector(boundary[0],boundary[1]),vector(boundary[2],boundary[3])]
|
||||||
pin = pin_layout(pin_name, rect, layer)
|
pin = pin_layout(pin_name, rect, layer)
|
||||||
|
debug.info(2,"Found pin {}".format(str(pin)))
|
||||||
pin_list.append(pin)
|
pin_list.append(pin)
|
||||||
|
|
||||||
debug.check(len(pin_list)>0,"Did not find any pin shapes for {0}.".format(str(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:
|
for pin in all_pins:
|
||||||
# If the blockage overlaps the pin and is on the same layer,
|
# If the blockage overlaps the pin and is on the same layer,
|
||||||
# it must be connected, so skip it.
|
# it must be connected, so skip it.
|
||||||
if blockage==pin:
|
if blockage.overlaps(pin):
|
||||||
debug.info(1,"Removing blockage for pin {}".format(str(pin)))
|
debug.info(1,"Removing blockage for pin {}".format(str(pin)))
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
|
|
@ -288,7 +289,7 @@ class router:
|
||||||
If a pin has insufficent overlap, it returns the blockage list to avoid it.
|
If a pin has insufficent overlap, it returns the blockage list to avoid it.
|
||||||
"""
|
"""
|
||||||
(ll,ur) = pin.rect
|
(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
|
# scale the size bigger to include neaby tracks
|
||||||
ll=ll.scale(self.track_factor).floor()
|
ll=ll.scale(self.track_factor).floor()
|
||||||
|
|
@ -304,31 +305,31 @@ class router:
|
||||||
track_list = []
|
track_list = []
|
||||||
block_list = []
|
block_list = []
|
||||||
|
|
||||||
track_area = self.track_width*self.track_width
|
|
||||||
for x in range(ll[0],ur[0]):
|
for x in range(ll[0],ur[0]):
|
||||||
for y in range(ll[1],ur[1]):
|
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,
|
# 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
|
# we need to block it to prevent routes coming in on that grid
|
||||||
full_rect = self.convert_track_to_shape(vector3d(x,y,zindex))
|
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_rect=self.compute_overlap(pin.rect,full_rect)
|
||||||
overlap_area = overlap_rect[0]*overlap_rect[1]
|
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
|
# Assume if more than half the area, it is occupied
|
||||||
overlap_ratio = overlap_area/track_area
|
overlap_ratio = overlap_area/track_area
|
||||||
if overlap_ratio > 0.5:
|
if overlap_ratio > 0.25:
|
||||||
track_list.append(vector3d(x,y,zindex))
|
track_list.append(vector3d(x,y,zindex))
|
||||||
# otherwise, the pin may not be accessible, so block it
|
# otherwise, the pin may not be accessible, so block it
|
||||||
elif overlap_ratio > 0:
|
elif overlap_ratio > 0:
|
||||||
block_list.append(vector3d(x,y,zindex))
|
block_list.append(vector3d(x,y,zindex))
|
||||||
else:
|
else:
|
||||||
debug.info(4,"No overlap: {0} {1} max={2}".format(pin.rect,rect,max_overlap))
|
debug.info(4,"No overlap: {0} {1} max={2}".format(pin.rect,overlap_rect,overlap_area))
|
||||||
print("H:",x,y)
|
# print("H:",x,y)
|
||||||
if x>38 and x<42 and y>42 and y<45:
|
# if x>38 and x<42 and y>42 and y<45:
|
||||||
print(pin)
|
# print(pin)
|
||||||
print(full_rect, overlap_rect, overlap_ratio)
|
# print(full_rect, overlap_rect, overlap_ratio)
|
||||||
#debug.warning("Off-grid pin for {0}.".format(str(pin)))
|
#debug.warning("Off-grid pin for {0}.".format(str(pin)))
|
||||||
#debug.info(1,"Converted [ {0} , {1} ]".format(ll,ur))
|
#debug.info(1,"Converted [ {0} , {1} ]".format(ll,ur))
|
||||||
return (track_list,block_list)
|
return (track_list,block_list)
|
||||||
|
|
@ -480,6 +481,74 @@ class router:
|
||||||
height=ur.y-ll.y)
|
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
|
# FIXME: This should be replaced with vector.snap_to_grid at some point
|
||||||
|
|
||||||
def snap_to_grid(offset):
|
def snap_to_grid(offset):
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,8 @@ class signal_router(router):
|
||||||
"""
|
"""
|
||||||
router.__init__(self, gds_name, module)
|
router.__init__(self, gds_name, module)
|
||||||
|
|
||||||
|
self.pins = {}
|
||||||
|
|
||||||
# all the paths we've routed so far (to supplement the blockages)
|
# all the paths we've routed so far (to supplement the blockages)
|
||||||
self.paths = []
|
self.paths = []
|
||||||
|
|
||||||
|
|
@ -45,8 +47,9 @@ class signal_router(router):
|
||||||
"""
|
"""
|
||||||
debug.info(1,"Running signal router from {0} to {1}...".format(src,dest))
|
debug.info(1,"Running signal router from {0} to {1}...".format(src,dest))
|
||||||
self.cell = cell
|
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
|
# Clear the pins if we have previously routed
|
||||||
if (hasattr(self,'rg')):
|
if (hasattr(self,'rg')):
|
||||||
|
|
@ -61,15 +64,16 @@ class signal_router(router):
|
||||||
# This will get all shapes as blockages
|
# This will get all shapes as blockages
|
||||||
self.find_blockages()
|
self.find_blockages()
|
||||||
|
|
||||||
# Get the pin shapes
|
# Now add the blockages (all shapes except the pins)
|
||||||
self.get_pin(src)
|
self.get_pin(src)
|
||||||
self.get_pin(dest)
|
self.get_pin(dest)
|
||||||
|
|
||||||
# Now add the blockages (all shapes except the src/tgt pins)
|
# Now add the blockages
|
||||||
self.add_blockages()
|
self.add_blockages()
|
||||||
# Add blockages from previous paths
|
# Add blockages from previous paths
|
||||||
self.add_path_blockages()
|
self.add_path_blockages()
|
||||||
|
|
||||||
|
|
||||||
# Now add the src/tgt if they are not blocked by other shapes
|
# Now add the src/tgt if they are not blocked by other shapes
|
||||||
self.add_pin(src,True)
|
self.add_pin(src,True)
|
||||||
self.add_pin(dest,False)
|
self.add_pin(dest,False)
|
||||||
|
|
@ -91,72 +95,6 @@ class signal_router(router):
|
||||||
return False
|
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()
|
self.rg.reinit()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def route(self, cell, layers, vdd_name="vdd", gnd_name="gnd"):
|
def route(self, cell, layers, vdd_name="vdd", gnd_name="gnd"):
|
||||||
"""
|
"""
|
||||||
Route a single source-destination net and return
|
Add power supply rails and connect all pins to these rails.
|
||||||
the simplified rectilinear path.
|
|
||||||
"""
|
"""
|
||||||
debug.info(1,"Running supply router on {0} and {1}...".format(vdd_name, gnd_name))
|
debug.info(1,"Running supply router on {0} and {1}...".format(vdd_name, gnd_name))
|
||||||
self.cell = cell
|
self.cell = cell
|
||||||
|
|
@ -61,10 +61,12 @@ class supply_router(router):
|
||||||
self.get_pin(vdd_name)
|
self.get_pin(vdd_name)
|
||||||
self.get_pin(gnd_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()
|
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
|
# source pin will be a specific layout pin
|
||||||
# target pin will be the rails only
|
# target pin will be the rails only
|
||||||
|
|
@ -84,6 +86,37 @@ class supply_router(router):
|
||||||
self.write_debug_gds()
|
self.write_debug_gds()
|
||||||
return False
|
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):
|
def add_route(self,path):
|
||||||
"""
|
"""
|
||||||
|
|
@ -125,22 +158,4 @@ class supply_router(router):
|
||||||
self.rg = supply_grid.supply_grid()
|
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