Rewrite blockage routines in router. Clean up GdsMill code.

This commit is contained in:
Matt Guthaus 2018-08-28 10:41:19 -07:00
parent 0dbc88dab2
commit 95a8688506
14 changed files with 256 additions and 176 deletions

View File

@ -261,7 +261,7 @@ class layout(lef.lef):
width=drc["minwidth_{0}".format(layer)]
if height==None:
height=drc["minwidth_{0}".format(layer)]
new_pin = pin_layout(text, [offset,offset+vector(width,height)], layer)
try:
@ -400,13 +400,14 @@ class layout(lef.lef):
elif rotate==90:
corrected_offset = offset + vector(0.5*height,-0.5*width)
elif rotate==180:
corrected_offset = offset + vector(-0.5*width,0.5*height)
corrected_offset = offset + vector(0.5*width,0.5*height)
elif rotate==270:
corrected_offset = offset + vector(-0.5*height,0.5*width)
else:
debug.error("Invalid rotation argument.",-1)
#print(rotate,offset,"->",corrected_offset)
self.add_mod(via)
inst=self.add_inst(name=via.name,
mod=via,
@ -848,19 +849,21 @@ class layout(lef.lef):
width=xmax-xmin,
height=ymax-ymin)
def add_power_pin(self, name, loc, rotate=True):
def add_power_pin(self, name, loc, rotate=90):
"""
Add a single power pin from M3 own to M1
Add a single power pin from M3 own to M1 at the given center location
"""
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=loc,
rotate=90 if rotate else 0)
self.add_via_center(layers=("metal2", "via2", "metal3"),
offset=loc,
rotate=90 if rotate else 0)
rotate=rotate)
via=self.add_via_center(layers=("metal2", "via2", "metal3"),
offset=loc,
rotate=rotate)
self.add_layout_pin_rect_center(text=name,
layer="metal3",
offset=loc)
offset=loc,
width=via.width,
height=via.height)
def add_power_ring(self, bbox):
"""

View File

@ -294,7 +294,7 @@ class Gds2reader:
mirrorFlag = bool(transFlags&0x8000) ##these flags are a bit sketchy
rotateFlag = bool(transFlags&0x0002)
magnifyFlag = bool(transFlags&0x0004)
thisSref.transFlags=(mirrorFlag,rotateFlag,magnifyFlag)
thisSref.transFlags=[mirrorFlag,rotateFlag,magnifyFlag]
if(self.debugToTerminal==1):
print("\t\t\tMirror X:"+str(mirrorFlag))
print( "\t\t\tRotate:"+str(rotateFlag))
@ -345,7 +345,7 @@ class Gds2reader:
mirrorFlag = bool(transFlags&0x8000) ##these flags are a bit sketchy
rotateFlag = bool(transFlags&0x0002)
magnifyFlag = bool(transFlags&0x0004)
thisAref.transFlags=(mirrorFlag,rotateFlag,magnifyFlag)
thisAref.transFlags=[mirrorFlag,rotateFlag,magnifyFlag]
if(self.debugToTerminal==1):
print("\t\t\tMirror X:"+str(mirrorFlag))
print("\t\t\tRotate:"+str(rotateFlag))
@ -408,7 +408,7 @@ class Gds2reader:
mirrorFlag = bool(transFlags&0x8000) ##these flags are a bit sketchy
rotateFlag = bool(transFlags&0x0002)
magnifyFlag = bool(transFlags&0x0004)
thisText.transFlags=(mirrorFlag,rotateFlag,magnifyFlag)
thisText.transFlags=[mirrorFlag,rotateFlag,magnifyFlag]
if(self.debugToTerminal==1):
print("\t\t\tMirror X:"+str(mirrorFlag))
print("\t\t\tRotate:"+str(rotateFlag))

View File

@ -152,7 +152,7 @@ class VlsiLayout:
self.rootStructureName = structureNames[0]
def traverseTheHierarchy(self, startingStructureName=None, delegateFunction = None,
transformPath = [], rotateAngle = 0, transFlags = (0,0,0), coordinates = (0,0)):
transformPath = [], rotateAngle = 0, transFlags = [0,0,0], coordinates = (0,0)):
#since this is a recursive function, must deal with the default
#parameters explicitly
if startingStructureName == None:
@ -160,11 +160,11 @@ class VlsiLayout:
#set up the rotation matrix
if(rotateAngle == None or rotateAngle == ""):
rotateAngle = 0
angle = 0
else:
rotateAngle = math.radians(float(rotateAngle))
mRotate = matrix([[math.cos(rotateAngle),-math.sin(rotateAngle),0.0],
[math.sin(rotateAngle),math.cos(rotateAngle),0.0],
angle = math.radians(float(rotateAngle))
mRotate = matrix([[math.cos(angle),-math.sin(angle),0.0],
[math.sin(angle),math.cos(angle),0.0],
[0.0,0.0,1.0]])
#set up the translation matrix
translateX = float(coordinates[0])
@ -190,15 +190,12 @@ class VlsiLayout:
#if not, return back to the caller (caller can be this function)
for sref in self.structures[startingStructureName].srefs:
#here, we are going to modify the sref coordinates based on the parent objects rotation
# if (sref.sName.count("via") == 0):
self.traverseTheHierarchy(startingStructureName = sref.sName,
delegateFunction = delegateFunction,
transformPath = transformPath,
rotateAngle = sref.rotateAngle,
transFlags = sref.transFlags,
coordinates = sref.coordinates)
# else:
# print("WARNING: via encountered, ignoring:", sref.sName)
#MUST HANDLE AREFs HERE AS WELL
#when we return, drop the last transform from the transformPath
del transformPath[-1]
@ -225,8 +222,8 @@ class VlsiLayout:
uVector = transform[0] * uVector #rotate
vVector = transform[0] * vVector #rotate
origin = transform[1] * origin #scale
uVector = transform[1] * uVector #rotate
vVector = transform[1] * vVector #rotate
uVector = transform[1] * uVector #scale
vVector = transform[1] * vVector #scale
origin = transform[2] * origin #translate
#we don't need to do a translation on the basis vectors
self.xyTree+=[(startingStructureName,origin,uVector,vVector)] #populate the xyTree with each
@ -307,18 +304,9 @@ class VlsiLayout:
for layerNumber in layoutToAdd.layerNumbersInUse:
if layerNumber not in self.layerNumbersInUse:
self.layerNumbersInUse += [layerNumber]
#Also, check if the user units / microns is the same as this Layout
#if (layoutToAdd.units != self.units):
#print("WARNING: VlsiLayout: Units from design to be added do not match target Layout")
# if debug: print("DEBUG: vlsilayout: Using %d layers")
# If we can't find the structure, error
#if StructureFound == False:
#print("ERROR: vlsiLayout.addInstance: [%s] Name not found in local structures, "%(nameOfLayout))
#return #FIXME: remove!
#exit(1)
#add a reference to the new layout structure in this layout's root
layoutToAddSref = GdsSref()
@ -326,24 +314,27 @@ class VlsiLayout:
layoutToAddSref.coordinates = offsetInLayoutUnits
if mirror or rotate:
########flags = (mirror around x-axis, absolute rotation, absolute magnification)
layoutToAddSref.transFlags = (False,False,False)
#Below angles are angular angles(relative), not absolute
# transFlags = (mirror around x-axis, magnification, rotation)
# If magnification or rotation is true, it is the flags are then
# followed by an amount in the record
if mirror=="R90":
rotate = 90.0
if mirror=="R180":
rotate = 180.0
if mirror=="R270":
rotate = 270.0
layoutToAddSref.transFlags = [0,0,0]
if rotate:
layoutToAddSref.transFlags = [0,0,1]
layoutToAddSref.rotateAngle = rotate
if mirror == "x" or mirror == "MX":
layoutToAddSref.transFlags = (True,False,False)
layoutToAddSref.transFlags = [1,0,0]
if mirror == "y" or mirror == "MY": #NOTE: "MY" option will override specified rotate angle
layoutToAddSref.transFlags = (True,False,False)
layoutToAddSref.transFlags = [1,0,1]
layoutToAddSref.rotateAngle = 180.0
if mirror == "xy" or mirror == "XY": #NOTE: "XY" option will override specified rotate angle
layoutToAddSref.transFlags = (False,False,False)
layoutToAddSref.transFlags = [0,0,1]
layoutToAddSref.rotateAngle = 180.0
#add the sref to the root structure
@ -410,14 +401,14 @@ class VlsiLayout:
textToAdd.purposeLayer = purposeNumber
textToAdd.dataType = 0
textToAdd.coordinates = [offsetInLayoutUnits]
textToAdd.transFlags = [0,0,0]
if(len(text)%2 == 1):
#pad with a zero
text = text + '\x00'
textToAdd.textString = text
textToAdd.transFlags = (False,False,True)
textToAdd.transFlags[1] = 1
textToAdd.magFactor = magnification
if rotate:
textToAdd.transFlags = (False,True,True)
textToAdd.transFlags[2] = 1
textToAdd.rotateAngle = rotate
#add the sref to the root structure
self.structures[self.rootStructureName].texts+=[textToAdd]
@ -620,10 +611,6 @@ class VlsiLayout:
StructureOrigin=[Structure[1][0],Structure[1][1]]
StructureuVector=[Structure[2][0],Structure[2][1],Structure[2][2]]
StructurevVector=[Structure[3][0],Structure[3][1],Structure[3][2]]
#debug.info(debug_level,"Checking Structure: "+str(StructureName))
#debug.info(debug_level,"-Structure Structure Origin:"+str(StructureOrigin))
#debug.info(debug_level,"-Structure direction: uVector["+str(StructureuVector)+"]")
#debug.info(debug_level,"-Structure direction: vVector["+str(StructurevVector)+"]")
for boundary in self.structures[str(StructureName)].boundaries:
left_bottom=boundary.coordinates[0]
@ -808,6 +795,63 @@ class VlsiLayout:
return boundaries
def getAllShapesInStructureList(self,layer):
"""
Return all pin shapes on a given layer.
"""
boundaries = []
for TreeUnit in self.xyTree:
#print(TreeUnit[0])
boundaries += self.getShapesInStructure(layer,TreeUnit)
# Remove duplicates without defining a hash
# (could be sped up by creating hash and using list(set())
new_boundaries = []
for boundary in boundaries:
if boundary not in new_boundaries:
new_boundaries.append(boundary)
# Convert to user units
boundaries = []
for boundary in new_boundaries:
boundaries.append([boundary[0]*self.units[0],boundary[1]*self.units[0],
boundary[2]*self.units[0],boundary[3]*self.units[0]])
return boundaries
def getShapesInStructure(self,layer,structure):
"""
Go through all the shapes in a structure and return the list of shapes.
"""
# check if this is a rectangle
structureName=structure[0]
structureOrigin=[structure[1][0],structure[1][1]]
structureuVector=[structure[2][0],structure[2][1],structure[2][2]]
structurevVector=[structure[3][0],structure[3][1],structure[3][2]]
boundaries = []
for boundary in self.structures[str(structureName)].boundaries:
# Pin enclosures only work on rectangular pins so ignore any non rectangle
# This may report not finding pins, but the user should fix this by adding a rectangle.
if len(boundary.coordinates)!=5:
continue
if layer==boundary.drawingLayer:
left_bottom=boundary.coordinates[0]
right_top=boundary.coordinates[2]
# Rectangle is [leftx, bottomy, rightx, topy].
boundaryRect=[left_bottom[0],left_bottom[1],right_top[0],right_top[1]]
boundaryRect=self.transformRectangle(boundaryRect,structureuVector,structurevVector)
boundaryRect=[boundaryRect[0]+structureOrigin[0].item(),boundaryRect[1]+structureOrigin[1].item(),
boundaryRect[2]+structureOrigin[0].item(),boundaryRect[3]+structureOrigin[1].item()]
boundaries.append(boundaryRect)
return boundaries
def transformRectangle(self,originalRectangle,uVector,vVector):
"""
Transforms the four coordinates of a rectangle in space
@ -849,6 +893,7 @@ class VlsiLayout:
else:
return False
def boundaryArea(A):
"""
Returns boundary area for sorting.

View File

@ -170,7 +170,7 @@ class delay_chain(design.design):
continue
for pin_name in ["vdd", "gnd"]:
pin = load.get_pin(pin_name)
self.add_power_pin(pin_name, pin.rc())
self.add_power_pin(pin_name, pin.rc(),rotate=0)
else:
# We have an even number of rows, so need to get the last gnd rail
inv = self.driver_inst_list[-1]
@ -179,7 +179,7 @@ class delay_chain(design.design):
continue
pin_name = "gnd"
pin = load.get_pin(pin_name)
self.add_power_pin(pin_name, pin.rc())
self.add_power_pin(pin_name, pin.rc(),rotate=0)
# input is A pin of first inverter

View File

@ -171,7 +171,7 @@ class replica_bitline(design.design):
# Replica bitcell needs to be routed up to M3
pin=self.rbc_inst.get_pin("vdd")
# Don't rotate this via to vit in FreePDK45
self.add_power_pin("vdd", pin.center(), False)
self.add_power_pin("vdd", pin.center(), rotate=0)
for pin in self.rbc_inst.get_pins("gnd"):
self.add_power_pin("gnd", pin.center())

View File

@ -89,7 +89,7 @@ class astar_grid(grid.grid):
self.counter+=1
def astar_route(self,detour_scale):
def route(self,detour_scale):
"""
This does the A* maze routing with preferred direction routing.
"""

View File

@ -36,6 +36,9 @@ class grid:
def add_blockage_shape(self,ll,ur,z):
debug.info(3,"Adding blockage ll={0} ur={1} z={2}".format(str(ll),str(ur),z))
if ll[0]<42 and ll[0]>38 and ll[1]<3 and ll[1]>0:
debug.info(0,"Adding blockage ll={0} ur={1} z={2}".format(str(ll),str(ur),z))
block_list = []
for x in range(int(ll[0]),int(ur[0])+1):
for y in range(int(ll[1]),int(ur[1])+1):

View File

@ -27,8 +27,7 @@ class router:
self.top_name = self.layout.rootStructureName
self.pins = {}
# the list of all blockage shapes
self.blockages = []
self.blockages=[]
# all the paths we've routed so far (to supplement the blockages)
self.paths = []
@ -101,9 +100,9 @@ class router:
This doesn't consider whether the obstacles will be pins or not. They get reset later
if they are not actually a blockage.
"""
for layer in self.layers:
self.get_blockages(self.top_name)
#for layer in [self.vert_layer_number,self.horiz_layer_number]:
# self.get_blockages(layer)
self.get_blockages(self.horiz_layer_number)
def clear_pins(self):
"""
@ -207,38 +206,50 @@ class router:
self.rg.add_blockage_shape(ll,ur,zlayer)
def get_blockages(self, sref, mirr = 1, angle = math.radians(float(0)), xyShift = (0, 0)):
def get_blockages(self, layer_num):
"""
Recursive find boundaries as blockages to the routing grid.
Recurses for each Structure in GDS.
"""
for boundary in self.layout.structures[sref].boundaries:
coord_trans = self.translate_coordinates(boundary.coordinates, mirr, angle, xyShift)
shape_coords = self.min_max_coord(coord_trans)
shape = self.convert_shape_to_units(shape_coords)
# only consider the two layers that we are routing on
if boundary.drawingLayer in [self.vert_layer_number,self.horiz_layer_number]:
# store the blockages as pin layouts so they are easy to compare etc.
self.blockages.append(pin_layout("blockage",shape,boundary.drawingLayer))
shapes = self.layout.getAllShapesInStructureList(layer_num)
for boundary in shapes:
rect = [vector(boundary[0],boundary[1]),vector(boundary[2],boundary[3])]
new_pin = pin_layout("blockage",rect,layer_num)
self.blockages.append(new_pin)
# for boundary in self.layout.structures[sref].boundaries:
# coord_trans = self.translate_coordinates(boundary.coordinates, mirr, angle, xyShift)
# shape_coords = self.min_max_coord(coord_trans)
# shape = self.convert_shape_to_units(shape_coords)
# # only consider the two layers that we are routing on
# if boundary.drawingLayer in [self.vert_layer_number,self.horiz_layer_number]:
# # store the blockages as pin layouts so they are easy to compare etc.
# new_pin = pin_layout("blockage",shape,boundary.drawingLayer)
# # avoid repeated blockage pins
# if new_pin not in self.blockages:
# self.blockages.append(new_pin)
# recurse given the mirror, angle, etc.
for cur_sref in self.layout.structures[sref].srefs:
sMirr = 1
if cur_sref.transFlags[0] == True:
sMirr = -1
sAngle = math.radians(float(0))
if cur_sref.rotateAngle:
sAngle = math.radians(float(cur_sref.rotateAngle))
sAngle += angle
x = cur_sref.coordinates[0]
y = cur_sref.coordinates[1]
newX = (x)*math.cos(angle) - mirr*(y)*math.sin(angle) + xyShift[0]
newY = (x)*math.sin(angle) + mirr*(y)*math.cos(angle) + xyShift[1]
sxyShift = (newX, newY)
# # recurse given the mirror, angle, etc.
# for cur_sref in self.layout.structures[sref].srefs:
# sMirr = 1
# if cur_sref.transFlags[0] == True:
# sMirr = -1
# sAngle = math.radians(float(0))
# if cur_sref.rotateAngle:
# sAngle = math.radians(float(cur_sref.rotateAngle))
# sAngle += angle
# x = cur_sref.coordinates[0]
# y = cur_sref.coordinates[1]
# newX = (x)*math.cos(angle) - mirr*(y)*math.sin(angle) + xyShift[0]
# newY = (x)*math.sin(angle) + mirr*(y)*math.cos(angle) + xyShift[1]
# sxyShift = (newX, newY)
self.get_blockages(cur_sref.sName, sMirr, sAngle, sxyShift)
# self.get_blockages(cur_sref.sName, sMirr, sAngle, sxyShift)
def convert_point_to_units(self,p):
"""
@ -248,21 +259,25 @@ class router:
pt=pt.scale(self.track_widths[0],self.track_widths[1],1)
return pt
def convert_blockage_to_tracks(self,shape,round_bigger=False):
def convert_blockage_to_tracks(self,shape):
"""
Convert a rectangular blockage shape into track units.
"""
[ll,ur] = shape
ll = snap_to_grid(ll)
ur = snap_to_grid(ur)
(ll,ur) = shape
# ll = snap_to_grid(ll)
# ur = snap_to_grid(ur)
# to scale coordinates to tracks
#debug.info(1,"Converting [ {0} , {1} ]".format(ll,ur))
debug.info(3,"Converting [ {0} , {1} ]".format(ll,ur))
old_ll = ll
old_ur = ur
ll=ll.scale(self.track_factor)
ur=ur.scale(self.track_factor)
ll = ll.floor() if round_bigger else ll.round()
ur = ur.ceil() if round_bigger else ur.round()
#debug.info(1,"Converted [ {0} , {1} ]".format(ll,ur))
ll = ll.floor()
ur = ur.ceil()
if ll[0]<45 and ll[0]>35 and ll[1]<10 and ll[1]>0:
debug.info(0,"Converting [ {0} , {1} ]".format(old_ll,old_ur))
debug.info(0,"Converted [ {0} , {1} ]".format(ll,ur))
return [ll,ur]
def convert_pin_to_tracks(self, pin):
@ -271,9 +286,9 @@ class router:
If no on-grid pins are found, it searches for the nearest off-grid pin(s).
If a pin has insufficent overlap, it returns the blockage list to avoid it.
"""
[ll,ur] = pin.rect
ll = snap_to_grid(ll)
ur = snap_to_grid(ur)
(ll,ur) = pin.rect
#ll = snap_to_grid(ll)
#ur = snap_to_grid(ur)
#debug.info(1,"Converting [ {0} , {1} ]".format(ll,ur))
@ -401,6 +416,68 @@ class router:
self.write_debug_gds()
debug.check(found_pin,"Unable to find pin on grid.")
def write_debug_gds(self):
"""
Write out a GDS file with the routing grid and search information annotated on it.
"""
# Only add the debug info to the gds file if we have any debugging on.
# This is because we may reroute a wire with detours and don't want the debug information.
if OPTS.debug_level==0: return
self.add_router_info()
debug.error("Writing debug_route.gds")
self.cell.gds_write("debug_route.gds")
def add_router_info(self):
"""
Write the routing grid and router cost, blockage, pins on
the boundary layer for debugging purposes. This can only be
called once or the labels will overlap.
"""
debug.info(0,"Adding router info")
grid_keys=self.rg.map.keys()
partial_track=vector(0,self.track_width/6.0)
for g in grid_keys:
continue # for now...
shape = self.convert_full_track_to_shape(g)
self.cell.add_rect(layer="boundary",
offset=shape[0],
width=shape[1].x-shape[0].x,
height=shape[1].y-shape[0].y)
# These are the on grid pins
#rect = self.convert_track_to_pin(g)
#self.cell.add_rect(layer="boundary",
# offset=rect[0],
# width=rect[1].x-rect[0].x,
# height=rect[1].y-rect[0].y)
t=self.rg.map[g].get_type()
# midpoint offset
off=vector((shape[1].x+shape[0].x)/2,
(shape[1].y+shape[0].y)/2)
if g[2]==1:
# Upper layer is upper right label
type_off=off+partial_track
else:
# Lower layer is lower left label
type_off=off-partial_track
if t!=None:
self.cell.add_label(text=str(t),
layer="text",
offset=type_off)
self.cell.add_label(text="{0},{1}".format(g[0],g[1]),
layer="text",
offset=shape[0],
zoom=0.05)
for blockage in self.blockages:
self.cell.add_rect(layer="boundary",
offset=blockage.ll(),
width=blockage.width(),
height=blockage.height())
# FIXME: This should be replaced with vector.snap_to_grid at some point
def snap_to_grid(offset):

View File

@ -26,7 +26,7 @@ class signal_router(router):
def create_routing_grid(self):
"""
Create a routing grid that spans given area. Wires cannot exist outside region.
Create a sprase routing grid with A* expansion functions.
"""
# We will add a halo around the boundary
# of this many tracks
@ -44,6 +44,8 @@ class signal_router(router):
This is used to speed up the routing when there is not much detouring needed.
"""
self.cell = cell
self.source_pin_name = src
self.target_pin_name = dest
# Clear the pins if we have previously routed
if (hasattr(self,'rg')):
@ -73,7 +75,7 @@ class signal_router(router):
# returns the path in tracks
(path,cost) = self.rg.astar_route(detour_scale)
(path,cost) = self.rg.route(detour_scale)
if path:
debug.info(1,"Found path: cost={0} ".format(cost))
debug.info(2,str(path))
@ -158,59 +160,3 @@ class signal_router(router):
def write_debug_gds(self):
"""
Write out a GDS file with the routing grid and search information annotated on it.
"""
# Only add the debug info to the gds file if we have any debugging on.
# This is because we may reroute a wire with detours and don't want the debug information.
if OPTS.debug_level==0: return
self.add_router_info()
pin_names = list(self.pins.keys())
debug.error("Writing debug_route.gds from {0} to {1}".format(self.source_pin_name,self.target_pin_name))
self.cell.gds_write("debug_route.gds")
def add_router_info(self):
"""
Write the routing grid and router cost, blockage, pins on
the boundary layer for debugging purposes. This can only be
called once or the labels will overlap.
"""
debug.info(0,"Adding router info for {0} to {1}".format(self.source_pin_name,self.target_pin_name))
grid_keys=self.rg.map.keys()
partial_track=vector(0,self.track_width/6.0)
for g in grid_keys:
shape = self.convert_full_track_to_shape(g)
self.cell.add_rect(layer="boundary",
offset=shape[0],
width=shape[1].x-shape[0].x,
height=shape[1].y-shape[0].y)
# These are the on grid pins
#rect = self.convert_track_to_pin(g)
#self.cell.add_rect(layer="boundary",
# offset=rect[0],
# width=rect[1].x-rect[0].x,
# height=rect[1].y-rect[0].y)
t=self.rg.map[g].get_type()
# midpoint offset
off=vector((shape[1].x+shape[0].x)/2,
(shape[1].y+shape[0].y)/2)
if g[2]==1:
# Upper layer is upper right label
type_off=off+partial_track
else:
# Lower layer is lower left label
type_off=off-partial_track
if t!=None:
self.cell.add_label(text=str(t),
layer="text",
offset=type_off)
self.cell.add_label(text="{0},{1}".format(g[0],g[1]),
layer="text",
offset=shape[0],
zoom=0.05)

View File

@ -66,24 +66,22 @@ class supply_router(router):
# Add blockages from previous routes
self.add_path_blockages()
# Now add the src/tgt if they are not blocked by other shapes
self.add_pin(vdd_name,True)
#self.add_pin()
# source pin will be a specific layout pin
# target pin will be the rails only
# returns the path in tracks
(path,cost) = self.rg.route(detour_scale)
if path:
debug.info(1,"Found path: cost={0} ".format(cost))
debug.info(2,str(path))
self.add_route(path)
return True
else:
self.write_debug_gds()
# clean up so we can try a reroute
self.clear_pins()
# (path,cost) = self.rg.route(detour_scale)
# if path:
# debug.info(1,"Found path: cost={0} ".format(cost))
# debug.info(2,str(path))
# self.add_route(path)
# return True
# else:
# self.write_debug_gds()
# # clean up so we can try a reroute
# self.clear_pins()
self.write_debug_gds()
return False
@ -114,6 +112,17 @@ class supply_router(router):
self.cell.add_route(self.layers,abs_path)
def create_routing_grid(self):
"""
Create a sprase routing grid with A* expansion functions.
"""
# We will add a halo around the boundary
# of this many tracks
size = self.ur - self.ll
debug.info(1,"Size: {0} x {1}".format(size.x,size.y))
import supply_grid
self.rg = supply_grid.supply_grid()
##########################
@ -135,6 +144,3 @@ class supply_router(router):
""" Create alternating vdd/gnd lines horizontally """
pass
def route(self):
#self.create_grid()
pass

View File

@ -38,7 +38,7 @@ class no_blockages_test(openram_test):
self.connect_inst([])
r=router(gds_file)
layer_stack =("metal3","via1","metal2")
layer_stack =("metal3","via2","metal2")
self.assertTrue(r.route(self,layer_stack))
r=routing("10_supply_grid_test_{0}".format(OPTS.tech_name))

View File

@ -20,7 +20,7 @@ class single_bank_test(openram_test):
debug.info(1, "No column mux")
a = bank(word_size=4, num_words=16, words_per_row=1, num_banks=1, name="bank1_single")
self.local_check(a)
debug.info(1, "Two way column mux")
a = bank(word_size=4, num_words=32, words_per_row=2, num_banks=1, name="bank2_single")
self.local_check(a)

View File

@ -21,17 +21,17 @@ class sram_1bank_test(openram_test):
a = sram(word_size=4, num_words=16, num_banks=1, name="sram1")
self.local_check(a, final_verification=True)
debug.info(1, "Single bank two way column mux with control logic")
a = sram(word_size=4, num_words=32, num_banks=1, name="sram2")
self.local_check(a, final_verification=True)
# debug.info(1, "Single bank two way column mux with control logic")
# a = sram(word_size=4, num_words=32, num_banks=1, name="sram2")
# self.local_check(a, final_verification=True)
debug.info(1, "Single bank, four way column mux with control logic")
a = sram(word_size=4, num_words=64, num_banks=1, name="sram3")
self.local_check(a, final_verification=True)
# debug.info(1, "Single bank, four way column mux with control logic")
# a = sram(word_size=4, num_words=64, num_banks=1, name="sram3")
# self.local_check(a, final_verification=True)
debug.info(1, "Single bank, eight way column mux with control logic")
a = sram(word_size=2, num_words=128, num_banks=1, name="sram4")
self.local_check(a, final_verification=True)
# debug.info(1, "Single bank, eight way column mux with control logic")
# a = sram(word_size=2, num_words=128, num_banks=1, name="sram4")
# self.local_check(a, final_verification=True)
globals.end_openram()