mirror of https://github.com/VLSIDA/OpenRAM.git
Rewrite blockage routines in router. Clean up GdsMill code.
This commit is contained in:
parent
0dbc88dab2
commit
95a8688506
|
|
@ -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):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue