Debugged and tested route by pin location,layer

This commit is contained in:
mguthaus 2017-05-17 15:58:29 -07:00
parent a1496e70a8
commit 68ce3843fe
4 changed files with 138 additions and 56 deletions

View File

@ -656,7 +656,7 @@ class VlsiLayout:
for Text in self.structures[self.rootStructureName].texts:
if Text.textString == label_name or Text.textString == label_name+"\x00":
label_layer = Text.drawingLayer
label_coordinate = Text.coordinates
label_coordinate = Text.coordinates[0]
return (label_coordinate, label_layer)
@ -665,22 +665,22 @@ class VlsiLayout:
"""
Return the coordinates in USER units and layer of a label
"""
(label_coordinate,label_layer)=getLabelDBInfo(label_name)
user_coordinates = [x*self.units[0] for x in label_coordinates]
return (user_coordinates,layer)
(label_coordinate,label_layer)=self.getLabelDBInfo(label_name)
user_coordinates = [x*self.units[0] for x in label_coordinate]
return (user_coordinates,label_layer)
def getPinShapeByLocLayer(self, coordinate, layer):
"""
Return the largest enclosing rectangle on a layer and at a location.
Coordinates should be in user units.
Coordinates should be in USER units.
"""
db_coordinates = [x/self.units[0] for x in coordinate]
db_coordinate = [x/self.units[0] for x in coordinate]
return self.getPinShapeByDBLocLayer(db_coordinate, layer)
def getPinShapeByDBLocLayer(self, coordinate, layer):
"""
Return the largest enclosing rectangle on a layer and at a location.
Coordinates should be in db units.
Coordinates should be in DB units.
"""
pin_boundaries=self.getAllPinShapesInStructureList(coordinate, layer)
@ -688,24 +688,25 @@ class VlsiLayout:
pin_boundaries.sort(cmpBoundaryAreas,reverse=True)
pin_boundary=pin_boundaries[0]
# Convert to user units
# Convert to USER units
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]]
return [None, layer, pin_boundary]
# Make a name if we don't have the pin name
return ["p"+str(coordinate)+"_"+str(layer), layer, pin_boundary]
def getAllPinShapesByLocLayer(self, coordinate, layer):
"""
Return ALL the enclosing rectangles on the same layer
at the given coordinate. Coordinates should be in user units.
at the given coordinate. Coordinates should be in USER units.
"""
db_coordinates = [x/self.units[0] for x in coordinate]
db_coordinate = [int(x/self.units[0]) for x in coordinate]
return self.getAllPinShapesByDBLocLayer(db_coordinate, layer)
def getAllPinShapesByDBLocLayer(self, coordinate, layer):
"""
Return ALL the enclosing rectangles on the same layer
at the given coordinate. Coordinates should be in db units.
at the given coordinate. Coordinates should be in DB units.
"""
pin_boundaries=self.getAllPinShapesInStructureList(coordinate, layer)
@ -714,7 +715,9 @@ class VlsiLayout:
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]])
# Make a name if we don't have the pin name
return ["p"+str(coordinate)+"_"+str(layer), layer, new_boundaries]
def getPinShapeByLabel(self,label_name):
"""
@ -766,7 +769,7 @@ class VlsiLayout:
MetalBoundary=[MetalBoundary[0]+StructureOrigin[0],MetalBoundary[1]+StructureOrigin[1],
MetalBoundary[2]+StructureOrigin[0],MetalBoundary[3]+StructureOrigin[1]]
if self.labelInRectangle(coordinates[0],MetalBoundary):
if self.labelInRectangle(coordinates,MetalBoundary):
boundaries.append(MetalBoundary)
return boundaries

View File

@ -198,14 +198,14 @@ class grid:
for p in path:
self.map[p].path=True
def route(self,factor):
def route(self,cost_bound_factor):
"""
This does the A* maze routing with preferred direction routing.
"""
# We set a cost bound of the HPWL for run-time. This can be
# over-ridden if the route fails due to pruning a feasible solution.
cost_bound = factor*self.cost_to_target(self.source[0])*self.NONPREFERRED_COST
cost_bound = cost_bound_factor*self.cost_to_target(self.source[0])*self.NONPREFERRED_COST
# Make sure the queue is empty if we run another route
while not self.q.empty():

View File

@ -24,12 +24,10 @@ class router:
self.reader.loadFromFile(gds_name)
self.top_name = self.layout.rootStructureName
# A list of pin names for source and dest
self.pin_names = []
# The map of pin names to list of all pin shapes for a pin.
self.pin_shapes = {}
# The corresponding layers of the above pin shapes
self.pin_layers = {}
self.source_pin_shapes = []
self.source_pin_zindex = None
self.target_pin_shapes = []
self.target_pin_zindex = None
# The boundary will determine the limits to the size of the routing grid
self.boundary = self.layout.measureBoundary(self.top_name)
@ -86,24 +84,22 @@ class router:
def find_pin(self,pin):
"""
Finds the pin shapes and converts to tracks
Finds the pin shapes and converts to tracks.
Pin can either be a label or a location,layer pair: [[x,y],layer].
"""
# Returns all the shapes that enclose a pin on a given layer
(pin_name,pin_layer,pin_shapes) = self.layout.getAllPinShapes(str(pin))
if type(pin)==str:
(pin_name,pin_layer,pin_shapes) = self.layout.getAllPinShapesByLabel(str(pin))
else:
(pin_name,pin_layer,pin_shapes) = self.layout.getAllPinShapesByLocLayer(pin[0],pin[1])
self.pin_shapes[str(pin)]=[]
self.pin_names.append(pin_name)
self.pin_layers[str(pin)] = pin_layer
new_pin_shapes = []
for pin_shape in pin_shapes:
debug.info(2,"Find pin {0} layer {1} shape {2}".format(pin_name,str(pin_layer),str(pin_shape)))
# repack the shape as a pair of vectors rather than four values
shape=[vector(pin_shape[0],pin_shape[1]),vector(pin_shape[2],pin_shape[3])]
# convert the pin coordinates to tracks and round the sizes down
self.pin_shapes[str(pin)].append(shape)
new_pin_shapes.append([vector(pin_shape[0],pin_shape[1]),vector(pin_shape[2],pin_shape[3])])
return self.pin_shapes[str(pin)]
return (pin_layer,new_pin_shapes)
def find_blockages(self):
"""
@ -122,15 +118,14 @@ class router:
Convert the routed path to blockages.
Keep the other blockages unchanged.
"""
self.pin_names = []
self.pin_shapes = {}
self.pin_layers = {}
self.source_pin_shapes = []
self.source_pin_zindex = None
self.target_pin_shapes = []
self.target_pin_zindex = None
self.rg.reinit()
def route(self, layers, src, dest, cost_factor=1):
def route(self, layers, src, dest, cost_bound_scale=1):
"""
Route a single source-destination net and return
the simplified rectilinear path. Cost factor is how sub-optimal to explore for a feasible route.
@ -158,7 +153,7 @@ class router:
#self.rg.view()
# returns the path in tracks
(self.path,cost) = self.rg.route(cost_factor)
(self.path,cost) = self.rg.route(cost_bound_scale)
debug.info(1,"Found path: cost={0} ".format(cost))
debug.info(2,str(self.path))
self.set_path(self.path)
@ -196,14 +191,14 @@ class router:
cell.add_route(self.layers,abs_path)
# Check if a via is needed at the start point
if (contracted_path[0].z!=self.source_pin_layer):
if (contracted_path[0].z!=self.source_pin_zindex):
# offset this by 1/2 the via size
c=contact(self.layers, (1, 1))
via_offset = vector(-0.5*c.width,-0.5*c.height)
cell.add_via(self.layers,abs_path[0]+via_offset)
# Check if a via is needed at the end point
if (contracted_path[-1].z!=self.target_pin_layer):
if (contracted_path[-1].z!=self.target_pin_zindex):
# offset this by 1/2 the via size
c=contact(self.layers, (1, 1))
via_offset = vector(-0.5*c.width,-0.5*c.height)
@ -295,31 +290,29 @@ class router:
debug.info(3,"Set path: " + str(path))
self.rg.set_path(path)
def set_source(self,name):
def set_source(self,src):
"""
Mark the grids that are in the pin rectangle ranges to have the source property.
"""
self.source_pin_name = name
shapes = self.find_pin(name)
zindex = 0 if self.pin_layers[name]==self.horiz_layer_number else 1
self.source_pin_layer = zindex
for shape in shapes:
(pin_layer,self.source_pin_shapes) = self.find_pin(src)
zindex = 0 if pin_layer==self.horiz_layer_number else 1
self.source_pin_zindex = zindex
for shape in self.source_pin_shapes:
shape_in_tracks=self.convert_shape_to_tracks(shape)
debug.info(1,"Set source: " + str(name) + " " + str(shape_in_tracks) + " z=" + str(zindex))
debug.info(1,"Set source: " + str(src) + " " + str(shape_in_tracks) + " z=" + str(zindex))
self.rg.set_source(shape_in_tracks[0],shape_in_tracks[1],zindex)
def set_target(self,name):
def set_target(self,src):
"""
Mark the grids that are in the pin rectangle ranges to have the target property.
"""
self.target_pin_name = name
shapes = self.find_pin(name)
zindex = 0 if self.pin_layers[name]==self.horiz_layer_number else 1
self.target_pin_layer = zindex
for shape in shapes:
(pin_layer,self.target_pin_shapes) = self.find_pin(src)
zindex = 0 if pin_layer==self.horiz_layer_number else 1
self.target_pin_zindex = zindex
for shape in self.target_pin_shapes:
shape_in_tracks=self.convert_shape_to_tracks(shape)
debug.info(1,"Set target: " + str(name) + " " + str(shape_in_tracks) + " z=" + str(zindex))
debug.info(1,"Set target: " + str(src) + " " + str(shape_in_tracks) + " z=" + str(zindex))
self.rg.set_target(shape_in_tracks[0],shape_in_tracks[1],zindex)
def write_obstacle(self, sref, mirr = 1, angle = math.radians(float(0)), xyShift = (0, 0)):

View File

@ -0,0 +1,86 @@
#!/usr/bin/env python2.7
"Run a regresion test the library cells for DRC"
import unittest
from testutils import header
import sys,os
sys.path.append(os.path.join(sys.path[0],"../.."))
sys.path.append(os.path.join(sys.path[0],".."))
import globals
import debug
import calibre
OPTS = globals.OPTS
class pin_location_test(unittest.TestCase):
"""
Simplest two pin route test with no blockages using the pin locations instead of labels.
"""
def runTest(self):
globals.init_openram("config_{0}".format(OPTS.tech_name))
import design
import router
class gdscell(design.design):
"""
A generic GDS design that we can route on.
"""
def __init__(self, name):
#design.design.__init__(self, name)
debug.info(2, "Create {0} object".format(name))
self.name = name
self.gds_file = "{0}/{1}.gds".format(os.path.dirname(os.path.realpath(__file__)),name)
self.sp_file = "{0}/{1}.sp".format(os.path.dirname(os.path.realpath(__file__)),name)
design.hierarchy_layout.layout.__init__(self, name)
design.hierarchy_spice.spice.__init__(self, name)
class routing(design.design):
"""
A generic GDS design that we can route on.
"""
def __init__(self, name, gdsname):
design.design.__init__(self, name)
debug.info(2, "Create {0} object".format(name))
cell = gdscell(gdsname)
self.add_inst(name=gdsname,
mod=cell,
offset=[0,0])
self.connect_inst([])
self.gdsname = "{0}/{1}.gds".format(os.path.dirname(os.path.realpath(__file__)),gdsname)
r=router.router(self.gdsname)
layer_stack =("metal1","via1","metal2")
# these are user coordinates and layers
src_pin = [[0.52, 4.099],11]
tgt_pin = [[3.533, 1.087],11]
r.route(layer_stack,src=src_pin,dest=tgt_pin)
#r.route(layer_stack,src="A",dest="B")
r.add_route(self)
r = routing("test1", "01_no_blockages_test")
self.local_check(r)
# fails if there are any DRC errors on any cells
globals.end_openram()
def local_check(self, r):
tempgds = OPTS.openram_temp + "temp.gds"
r.gds_write(tempgds)
self.assertFalse(calibre.run_drc(r.name, tempgds))
os.remove(tempgds)
# instantiate a copy of the class to actually run the test
if __name__ == "__main__":
(OPTS, args) = globals.parse_args()
del sys.argv[1:]
header(__file__, OPTS.tech_name)
unittest.main()