Found rotate bug in transformCoordinate. Cleaned up transFlags.

This commit is contained in:
Matt Guthaus 2018-09-04 16:35:40 -07:00
parent 763f1e8dee
commit 378993ca22
15 changed files with 156 additions and 166 deletions

View File

@ -15,22 +15,27 @@ class contact(hierarchy_design.hierarchy_design):
necessary to import layouts into Magic which requires the select to be in the same GDS necessary to import layouts into Magic which requires the select to be in the same GDS
hierarchy as the contact. hierarchy as the contact.
""" """
unique_id = 1
def __init__(self, layer_stack, dimensions=[1,1], implant_type=None, well_type=None): def __init__(self, layer_stack, dimensions=[1,1], implant_type=None, well_type=None):
if implant_type or well_type: if implant_type or well_type:
name = "{0}_{1}_{2}_{3}x{4}_{5}{6}".format(layer_stack[0], name = "{0}_{1}_{2}_{3}x{4}_{5}{6}_{7}".format(layer_stack[0],
layer_stack[1], layer_stack[1],
layer_stack[2], layer_stack[2],
dimensions[0], dimensions[0],
dimensions[1], dimensions[1],
implant_type, implant_type,
well_type) well_type,
contact.unique_id)
else: else:
name = "{0}_{1}_{2}_{3}x{4}".format(layer_stack[0], name = "{0}_{1}_{2}_{3}x{4}_{5}".format(layer_stack[0],
layer_stack[1], layer_stack[1],
layer_stack[2], layer_stack[2],
dimensions[0], dimensions[0],
dimensions[1]) dimensions[1],
contact.unique_id)
contact.unique_id += 1
hierarchy_design.hierarchy_design.__init__(self, name) hierarchy_design.hierarchy_design.__init__(self, name)
debug.info(4, "create contact object {0}".format(name)) debug.info(4, "create contact object {0}".format(name))

View File

@ -34,14 +34,14 @@ class geometry:
# coordinate += [(x, y)] # coordinate += [(x, y)]
# return coordinate # return coordinate
def transform_coords(self, coords, offset, mirr, angle): # def transform_coords(self, coords, offset, mirr, angle):
"""Calculate coordinates after flip, rotate, and shift""" # """Calculate coordinates after flip, rotate, and shift"""
coordinate = [] # coordinate = []
for item in coords: # for item in coords:
x = item[0]*math.cos(angle) - item[1]*mirr*math.sin(angle) + offset[0] # x = item[0]*math.cos(angle) - item[1]*mirr*math.sin(angle) + offset[0]
y = item[0]*math.sin(angle) + item[1]*mirr*math.cos(angle) + offset[1] # y = item[0]*math.sin(angle) + item[1]*mirr*math.cos(angle) + offset[1]
coordinate += [[x, y]] # coordinate += [[x, y]]
return coordinate # return coordinate
def normalize(self): def normalize(self):
""" Re-find the LL and UR points after a transform """ """ Re-find the LL and UR points after a transform """
@ -148,40 +148,40 @@ class instance(geometry):
debug.info(4, "creating instance: " + self.name) debug.info(4, "creating instance: " + self.name)
def get_blockages(self, layer, top=False): # def get_blockages(self, layer, top=False):
""" Retrieve rectangular blockages of all modules in this instance. # """ Retrieve rectangular blockages of all modules in this instance.
Apply the transform of the instance placement to give absolute blockages.""" # Apply the transform of the instance placement to give absolute blockages."""
angle = math.radians(float(self.rotate)) # angle = math.radians(float(self.rotate))
mirr = 1 # mirr = 1
if self.mirror=="R90": # if self.mirror=="R90":
angle += math.radians(90.0) # angle += math.radians(90.0)
elif self.mirror=="R180": # elif self.mirror=="R180":
angle += math.radians(180.0) # angle += math.radians(180.0)
elif self.mirror=="R270": # elif self.mirror=="R270":
angle += math.radians(270.0) # angle += math.radians(270.0)
elif self.mirror=="MX": # elif self.mirror=="MX":
mirr = -1 # mirr = -1
elif self.mirror=="MY": # elif self.mirror=="MY":
mirr = -1 # mirr = -1
angle += math.radians(180.0) # angle += math.radians(180.0)
elif self.mirror=="XY": # elif self.mirror=="XY":
mirr = 1 # mirr = 1
angle += math.radians(180.0) # angle += math.radians(180.0)
if self.mod.is_library_cell: # if self.mod.is_library_cell:
# For lib cells, block the whole thing except on metal3 # # For lib cells, block the whole thing except on metal3
# since they shouldn't use metal3 # # since they shouldn't use metal3
if layer==tech.layer["metal1"] or layer==tech.layer["metal2"]: # if layer==tech.layer["metal1"] or layer==tech.layer["metal2"]:
return [self.transform_coords(self.mod.get_boundary(), self.offset, mirr, angle)] # return [self.transform_coords(self.mod.get_boundary(), self.offset, mirr, angle)]
else: # else:
return [] # return []
else: # else:
blockages = self.mod.get_blockages(layer) # blockages = self.mod.get_blockages(layer)
new_blockages = [] # new_blockages = []
for b in blockages: # for b in blockages:
new_blockages.append(self.transform_coords(b,self.offset, mirr, angle)) # new_blockages.append(self.transform_coords(b,self.offset, mirr, angle))
return new_blockages # return new_blockages
def gds_write_file(self, new_layout): def gds_write_file(self, new_layout):
"""Recursively writes all the sub-modules in this instance""" """Recursively writes all the sub-modules in this instance"""

View File

@ -379,12 +379,10 @@ class layout(lef.lef):
dimensions=size, dimensions=size,
implant_type=implant_type, implant_type=implant_type,
well_type=well_type) well_type=well_type)
debug.check(mirror=="R0","Use rotate to rotate vias instead of mirror.")
height = via.height height = via.height
width = via.width width = via.width
debug.check(mirror=="R0","Use rotate to rotate vias instead of mirror.")
if rotate==0: if rotate==0:
corrected_offset = offset + vector(-0.5*width,-0.5*height) corrected_offset = offset + vector(-0.5*width,-0.5*height)
elif rotate==90: elif rotate==90:
@ -847,6 +845,7 @@ class layout(lef.lef):
""" """
Add a single power pin from M3 down to M1 at the given center location Add a single power pin from M3 down to M1 at the given center location
""" """
debug.info(0,"Adding power pin {0} at {1} rotate={2}".format(name, loc, rotate))
self.add_via_center(layers=("metal1", "via1", "metal2"), self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=loc, offset=loc,
rotate=rotate) rotate=rotate)

View File

@ -36,16 +36,14 @@ class pin_layout:
def __eq__(self, other): def __eq__(self, other):
""" Check if these are the same pins for duplicate checks """ """ Check if these are the same pins for duplicate checks """
if isinstance(other, self.__class__): if isinstance(other, self.__class__):
return (self.name==other.name and self.layer==other.layer and self.rect == other.rect) return (self.layer==other.layer and self.rect == other.rect)
else: else:
return False return False
def overlaps(self, other): def overlaps(self, other):
""" Check if a shape overlaps with a rectangle """ """ Check if a shape overlaps with a rectangle """
ll = self.rect[0] (ll,ur) = self.rect
ur = self.rect[1] (oll,our) = other.rect
oll = other.rect[0]
our = other.rect[1]
# Start assuming no overlaps # Start assuming no overlaps
x_overlaps = False x_overlaps = False
y_overlaps = False y_overlaps = False

View File

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

View File

@ -280,15 +280,15 @@ class Gds2writer:
if(thisSref.transFlags!=""): if(thisSref.transFlags!=""):
idBits=b'\x1A\x01' idBits=b'\x1A\x01'
mirrorFlag = int(thisSref.transFlags[0])<<15 mirrorFlag = int(thisSref.transFlags[0])<<15
rotateFlag = int(thisSref.transFlags[1])<<1 rotateFlag = int(thisSref.transFlags[2])<<1
magnifyFlag = int(thisSref.transFlags[2])<<3 magnifyFlag = int(thisSref.transFlags[1])<<3
transFlags = struct.pack(">H",mirrorFlag|rotateFlag|magnifyFlag) transFlags = struct.pack(">H",mirrorFlag|rotateFlag|magnifyFlag)
self.writeRecord(idBits+transFlags) self.writeRecord(idBits+transFlags)
if(thisSref.magFactor!=""): if(thisSref.transFlags[1]):
idBits=b'\x1B\x05' idBits=b'\x1B\x05'
magFactor=self.ibmDataFromIeeeDouble(thisSref.magFactor) magFactor=self.ibmDataFromIeeeDouble(thisSref.magFactor)
self.writeRecord(idBits+magFactor) self.writeRecord(idBits+magFactor)
if(thisSref.rotateAngle!=""): if(thisSref.transFlags[2]):
idBits=b'\x1C\x05' idBits=b'\x1C\x05'
rotateAngle=self.ibmDataFromIeeeDouble(thisSref.rotateAngle) rotateAngle=self.ibmDataFromIeeeDouble(thisSref.rotateAngle)
self.writeRecord(idBits+rotateAngle) self.writeRecord(idBits+rotateAngle)
@ -327,15 +327,15 @@ class Gds2writer:
if(thisAref.transFlags): if(thisAref.transFlags):
idBits=b'\x1A\x01' idBits=b'\x1A\x01'
mirrorFlag = int(thisAref.transFlags[0])<<15 mirrorFlag = int(thisAref.transFlags[0])<<15
rotateFlag = int(thisAref.transFlags[1])<<1 rotateFlag = int(thisAref.transFlags[2])<<1
magnifyFlag = int(thisAref.transFlags[0])<<3 magnifyFlag = int(thisAref.transFlags[1])<<3
transFlags = struct.pack(">H",mirrorFlag|rotateFlag|magnifyFlag) transFlags = struct.pack(">H",mirrorFlag|rotateFlag|magnifyFlag)
self.writeRecord(idBits+transFlags) self.writeRecord(idBits+transFlags)
if(thisAref.magFactor): if(thisAref.transFlags[1]):
idBits=b'\x1B\x05' idBits=b'\x1B\x05'
magFactor=self.ibmDataFromIeeeDouble(thisAref.magFactor) magFactor=self.ibmDataFromIeeeDouble(thisAref.magFactor)
self.writeRecord(idBits+magFactor) self.writeRecord(idBits+magFactor)
if(thisAref.rotateAngle): if(thisAref.transFlags[2]):
idBits=b'\x1C\x05' idBits=b'\x1C\x05'
rotateAngle=self.ibmDataFromIeeeDouble(thisAref.rotateAngle) rotateAngle=self.ibmDataFromIeeeDouble(thisAref.rotateAngle)
self.writeRecord(idBits+rotateAngle) self.writeRecord(idBits+rotateAngle)
@ -374,15 +374,15 @@ class Gds2writer:
if(thisText.transFlags != ""): if(thisText.transFlags != ""):
idBits=b'\x1A\x01' idBits=b'\x1A\x01'
mirrorFlag = int(thisText.transFlags[0])<<15 mirrorFlag = int(thisText.transFlags[0])<<15
rotateFlag = int(thisText.transFlags[1])<<1 rotateFlag = int(thisText.transFlags[2])<<1
magnifyFlag = int(thisText.transFlags[0])<<3 magnifyFlag = int(thisText.transFlags[1])<<3
transFlags = struct.pack(">H",mirrorFlag|rotateFlag|magnifyFlag) transFlags = struct.pack(">H",mirrorFlag|rotateFlag|magnifyFlag)
self.writeRecord(idBits+transFlags) self.writeRecord(idBits+transFlags)
if(thisText.magFactor != ""): if(thisText.transFlags[1]):
idBits=b'\x1B\x05' idBits=b'\x1B\x05'
magFactor=self.ibmDataFromIeeeDouble(thisText.magFactor) magFactor=self.ibmDataFromIeeeDouble(thisText.magFactor)
self.writeRecord(idBits+magFactor) self.writeRecord(idBits+magFactor)
if(thisText.rotateAngle != ""): if(thisText.transFlags[2]):
idBits=b'\x1C\x05' idBits=b'\x1C\x05'
rotateAngle=self.ibmDataFromIeeeDouble(thisText.rotateAngle) rotateAngle=self.ibmDataFromIeeeDouble(thisText.rotateAngle)
self.writeRecord(idBits+rotateAngle) self.writeRecord(idBits+rotateAngle)

View File

@ -141,7 +141,7 @@ class GdsText:
self.plex="" self.plex=""
self.drawingLayer="" self.drawingLayer=""
self.purposeLayer = None self.purposeLayer = None
self.transFlags=[0,00] self.transFlags=[0,0,0]
self.magFactor="" self.magFactor=""
self.rotateAngle="" self.rotateAngle=""
self.pathType="" self.pathType=""

View File

@ -64,10 +64,11 @@ class VlsiLayout:
#helper method to rotate a list of coordinates #helper method to rotate a list of coordinates
angle=math.radians(float(0)) angle=math.radians(float(0))
if(rotateAngle): if(rotateAngle):
angle = math.radians(float(repr(rotateAngle))) angle = math.radians(float(rotateAngle))
coordinatesRotate = [] #this will hold the rotated values coordinatesRotate = [] #this will hold the rotated values
for coordinate in coordinatesToRotate: for coordinate in coordinatesToRotate:
# This is the CCW rotation matrix
newX = coordinate[0]*math.cos(angle) - coordinate[1]*math.sin(angle) newX = coordinate[0]*math.cos(angle) - coordinate[1]*math.sin(angle)
newY = coordinate[0]*math.sin(angle) + coordinate[1]*math.cos(angle) newY = coordinate[0]*math.sin(angle) + coordinate[1]*math.cos(angle)
coordinatesRotate.extend((newX,newY)) coordinatesRotate.extend((newX,newY))
@ -274,8 +275,9 @@ class VlsiLayout:
Method to insert one layout into another at a particular offset. Method to insert one layout into another at a particular offset.
""" """
offsetInLayoutUnits = (self.userUnits(offsetInMicrons[0]),self.userUnits(offsetInMicrons[1])) offsetInLayoutUnits = (self.userUnits(offsetInMicrons[0]),self.userUnits(offsetInMicrons[1]))
if self.debug==1: if self.debug:
debug.info(0,"DEBUG: GdsMill vlsiLayout: addInstance: type %s, nameOfLayout "%type(layoutToAdd),nameOfLayout) debug.info(0,"DEBUG: GdsMill vlsiLayout: addInstance: type {0}, nameOfLayout {1}".format(type(layoutToAdd),nameOfLayout))
debug.info(0,"DEBUG: name={0} offset={1} mirror={2} rotate={3}".format(layoutToAdd.rootStructureName,offsetInMicrons, mirror, rotate))
@ -295,7 +297,7 @@ class VlsiLayout:
# If layoutToAdd is a unique object (not this), then copy heirarchy, # If layoutToAdd is a unique object (not this), then copy hierarchy,
# otherwise, if it is a text name of an internal structure, use it. # otherwise, if it is a text name of an internal structure, use it.
if layoutToAdd != self: if layoutToAdd != self:
@ -316,9 +318,7 @@ class VlsiLayout:
if mirror or rotate: if mirror or rotate:
layoutToAddSref.transFlags = [0,0,0] layoutToAddSref.transFlags = [0,0,0]
# This is NOT the same as the order in the GDS spec! # transFlags = (mirror around x-axis, magnification, rotation)
# It gets written out in gds2writer in the right order though.
# transFlags = (mirror around x-axis, rotation, magnification)
# If magnification or rotation is true, it is the flags are then # If magnification or rotation is true, it is the flags are then
# followed by an amount in the record # followed by an amount in the record
if mirror=="R90": if mirror=="R90":
@ -328,17 +328,16 @@ class VlsiLayout:
if mirror=="R270": if mirror=="R270":
rotate = 270.0 rotate = 270.0
if rotate: if rotate:
#layoutToAddSref.transFlags = [0,1,0] layoutToAddSref.transFlags[2] = 1
layoutToAddSref.rotateAngle = rotate layoutToAddSref.rotateAngle = rotate
if mirror == "x" or mirror == "MX": if mirror == "x" or mirror == "MX":
layoutToAddSref.transFlags = [1,0,0] layoutToAddSref.transFlags[0] = 1
if mirror == "y" or mirror == "MY": #NOTE: "MY" option will override specified rotate angle if mirror == "y" or mirror == "MY": #NOTE: "MY" option will override specified rotate angle
#layoutToAddSref.transFlags = [1,1,0] layoutToAddSref.transFlags[0] = 1
layoutToAddSref.transFlags = [1,0,0] layoutToAddSref.transFlags[2] = 1
layoutToAddSref.rotateAngle = 180.0 layoutToAddSref.rotateAngle = 180.0
if mirror == "xy" or mirror == "XY": #NOTE: "XY" option will override specified rotate angle if mirror == "xy" or mirror == "XY": #NOTE: "XY" option will override specified rotate angle
#layoutToAddSref.transFlags = [0,1,0] layoutToAddSref.transFlags[2] = 1
layoutToAddSref.transFlags = [0,0,0]
layoutToAddSref.rotateAngle = 180.0 layoutToAddSref.rotateAngle = 180.0
#add the sref to the root structure #add the sref to the root structure
@ -405,10 +404,10 @@ class VlsiLayout:
if(len(text)%2 == 1): if(len(text)%2 == 1):
text = text + '\x00' text = text + '\x00'
textToAdd.textString = text textToAdd.textString = text
textToAdd.transFlags = [0,0,1] textToAdd.transFlags[1] = 1
textToAdd.magFactor = magnification textToAdd.magFactor = magnification
if rotate: if rotate:
textToAdd.transFlags = [0,1,1] textToAdd.transFlags[2] = 1
textToAdd.rotateAngle = rotate textToAdd.rotateAngle = rotate
#add the sref to the root structure #add the sref to the root structure
self.structures[self.rootStructureName].texts.append(textToAdd) self.structures[self.rootStructureName].texts.append(textToAdd)
@ -816,10 +815,10 @@ class VlsiLayout:
""" """
(structureName,structureOrigin,structureuVector,structurevVector)=structure (structureName,structureOrigin,structureuVector,structurevVector)=structure
#print(structureName,"u",structureuVector.transpose(),"v",structurevVector.transpose(),"o",structureOrigin.transpose())
boundaries = [] boundaries = []
for boundary in self.structures[str(structureName)].boundaries: for boundary in self.structures[str(structureName)].boundaries:
# Pin enclosures only work on rectangular pins so ignore any non rectangle # FIXME: Right now, this only supports rectangular shapes!
# This may report not finding pins, but the user should fix this by adding a rectangle.
if len(boundary.coordinates)!=5: if len(boundary.coordinates)!=5:
continue continue
if layer==boundary.drawingLayer: if layer==boundary.drawingLayer:
@ -827,10 +826,11 @@ class VlsiLayout:
right_top=boundary.coordinates[2] right_top=boundary.coordinates[2]
# Rectangle is [leftx, bottomy, rightx, topy]. # Rectangle is [leftx, bottomy, rightx, topy].
boundaryRect=[left_bottom[0],left_bottom[1],right_top[0],right_top[1]] boundaryRect=[left_bottom[0],left_bottom[1],right_top[0],right_top[1]]
# perform the rotation
boundaryRect=self.transformRectangle(boundaryRect,structureuVector,structurevVector) boundaryRect=self.transformRectangle(boundaryRect,structureuVector,structurevVector)
# add the offset
boundaryRect=[boundaryRect[0]+structureOrigin[0].item(),boundaryRect[1]+structureOrigin[1].item(), boundaryRect=[boundaryRect[0]+structureOrigin[0].item(),boundaryRect[1]+structureOrigin[1].item(),
boundaryRect[2]+structureOrigin[0].item(),boundaryRect[3]+structureOrigin[1].item()] boundaryRect[2]+structureOrigin[0].item(),boundaryRect[3]+structureOrigin[1].item()]
boundaries.append(boundaryRect) boundaries.append(boundaryRect)
return boundaries return boundaries
@ -858,8 +858,12 @@ class VlsiLayout:
""" """
Rotate a coordinate in space. Rotate a coordinate in space.
""" """
x=coordinate[0]*uVector[0].item()+coordinate[1]*uVector[1].item() # MRG: 9/3/18 Incorrect matrixi multiplication!
y=coordinate[1]*vVector[1].item()+coordinate[0]*vVector[0].item() # This is fixed to be:
# |u[0] v[0]| |x| |x'|
# |u[1] v[1]|x|y|=|y'|
x=coordinate[0]*uVector[0].item()+coordinate[1]*vVector[0].item()
y=coordinate[0]*uVector[1].item()+coordinate[1]*vVector[1].item()
transformCoordinate=[x,y] transformCoordinate=[x,y]
return transformCoordinate return transformCoordinate

View File

@ -115,11 +115,11 @@ class dff_inv_array(design.design):
def add_layout_pins(self): def add_layout_pins(self):
for row in range(self.rows): for row in range(self.rows):
for col in range(self.columns): for col in range(self.columns):
# Continous vdd rail along with label. # Adds power pin on left of row
vdd_pin=self.dff_insts[row,col].get_pin("vdd") vdd_pin=self.dff_insts[row,col].get_pin("vdd")
self.add_power_pin("vdd", vdd_pin.lc()) self.add_power_pin("vdd", vdd_pin.lc())
# Continous gnd rail along with label. # Adds gnd pin on left of row
gnd_pin=self.dff_insts[row,col].get_pin("gnd") gnd_pin=self.dff_insts[row,col].get_pin("gnd")
self.add_power_pin("gnd", gnd_pin.lc()) self.add_power_pin("gnd", gnd_pin.lc())

View File

@ -171,6 +171,8 @@ class pinv(pgate.pgate):
offset=vector(0.5*self.width,self.height), offset=vector(0.5*self.width,self.height),
width=self.width) width=self.width)
def create_ptx(self): def create_ptx(self):
""" """
Create the PMOS and NMOS netlist. Create the PMOS and NMOS netlist.

View File

@ -36,9 +36,6 @@ class grid:
def add_blockage_shape(self,ll,ur,z): 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)) 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 = [] block_list = []
for x in range(int(ll[0]),int(ur[0])+1): for x in range(int(ll[0]),int(ur[0])+1):
for y in range(int(ll[1]),int(ur[1])+1): for y in range(int(ll[1]),int(ur[1])+1):

View File

@ -49,6 +49,12 @@ class router:
""" If we want to route something besides the top-level cell.""" """ If we want to route something besides the top-level cell."""
self.top_name = top_name self.top_name = top_name
def get_zindex(self,layer_num):
if layer_num==self.horiz_layer_number:
return 0
else:
return 1
def set_layers(self, layers): def set_layers(self, layers):
"""Allows us to change the layers that we are routing on. First layer """Allows us to change the layers that we are routing on. First layer
is always horizontal, middle is via, and last is always is always horizontal, middle is via, and last is always
@ -203,15 +209,20 @@ class router:
def add_blockages(self): def add_blockages(self):
""" Add the blockages except the pin shapes """ """ Add the blockages except the pin shapes """
# Skip pin shapes
all_pins = [x[0] for x in list(self.pins.values())]
for blockage in self.blockages: for blockage in self.blockages:
# Skip pin shapes
all_pins = [x[0] for x in list(self.pins.values())]
for pin in all_pins: for pin in all_pins:
if blockage.overlaps(pin): # If the blockage overlaps the pin and is on the same layer,
# it must be connected, so skip it.
if blockage==pin:
debug.info(1,"Skipping blockage for pin {}".format(str(pin)))
break break
else: else:
debug.info(2,"Adding blockage {}".format(str(blockage)))
[ll,ur]=self.convert_blockage_to_tracks(blockage.rect) [ll,ur]=self.convert_blockage_to_tracks(blockage.rect)
zlayer = 0 if blockage.layer_num==self.horiz_layer_number else 1 zlayer = self.get_zindex(blockage.layer_num)
self.rg.add_blockage_shape(ll,ur,zlayer) self.rg.add_blockage_shape(ll,ur,zlayer)
@ -227,37 +238,6 @@ class router:
rect = [ll,ur] rect = [ll,ur]
new_pin = pin_layout("blockage{}".format(len(self.blockages)),rect,layer_num) new_pin = pin_layout("blockage{}".format(len(self.blockages)),rect,layer_num)
self.blockages.append(new_pin) 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)
# self.get_blockages(cur_sref.sName, sMirr, sAngle, sxyShift)
def convert_point_to_units(self,p): def convert_point_to_units(self,p):
@ -282,9 +262,11 @@ class router:
old_ur = ur old_ur = ur
ll=ll.scale(self.track_factor) ll=ll.scale(self.track_factor)
ur=ur.scale(self.track_factor) ur=ur.scale(self.track_factor)
if ll[0]<45 and ll[0]>35 and ll[1]<46 and ll[1]>39:
print(ll,ur)
ll = ll.floor() ll = ll.floor()
ur = ur.ceil() ur = ur.ceil()
if ll[0]<45 and ll[0]>35 and ll[1]<10 and ll[1]>0: if ll[0]<45 and ll[0]>35 and ll[1]<46 and ll[1]>39:
debug.info(0,"Converting [ {0} , {1} ]".format(old_ll,old_ur)) debug.info(0,"Converting [ {0} , {1} ]".format(old_ll,old_ur))
debug.info(0,"Converted [ {0} , {1} ]".format(ll,ur)) debug.info(0,"Converted [ {0} , {1} ]".format(ll,ur))
return [ll,ur] return [ll,ur]
@ -296,9 +278,6 @@ 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
#ll = snap_to_grid(ll)
#ur = snap_to_grid(ur)
#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
@ -306,37 +285,40 @@ class router:
ur=ur.scale(self.track_factor).ceil() ur=ur.scale(self.track_factor).ceil()
# width depends on which layer it is # width depends on which layer it is
zindex = 0 if pin.layer_num==self.horiz_layer_number else 1 zindex=self.get_zindex(pin.layer_num)
if zindex==0: if zindex:
width = self.horiz_layer_width
else:
width = self.vert_layer_width width = self.vert_layer_width
else:
width = self.horiz_layer_width
track_list = [] track_list = []
block_list = [] block_list = []
# include +- 1 so when a shape is less than one grid
for x in range(ll[0]-1,ur[0]+1): track_area = self.track_width*self.track_width
for y in range(ll[1]-1,ur[1]+1): 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))
# get the rectangular pin at a track location
# if dimension of overlap is greater than min width in any dimension,
# it will be an on-grid pin
rect = self.convert_track_to_pin(vector3d(x,y,zindex))
max_overlap=max(self.compute_overlap(pin.rect,rect))
# 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_full_track_to_shape(vector3d(x,y,zindex)) full_rect = self.convert_track_to_shape(vector3d(x,y,zindex))
full_overlap=max(self.compute_overlap(pin.rect,full_rect)) 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(shape,rect,max_overlap))
if max_overlap >= width:
# Assume if more than half the area, it is occupied
overlap_ratio = overlap_area/track_area
if overlap_ratio > 0.5:
track_list.append(vector3d(x,y,zindex)) track_list.append(vector3d(x,y,zindex))
elif full_overlap>0: # otherwise, the pin may not be accessible, so block it
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,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.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)
@ -381,7 +363,7 @@ class router:
return [ll,ur] return [ll,ur]
def convert_full_track_to_shape(self,track): def convert_track_to_shape(self,track):
""" """
Convert a grid point into a rectangle shape that occupies the entire centered Convert a grid point into a rectangle shape that occupies the entire centered
track. track.
@ -447,9 +429,8 @@ class router:
grid_keys=self.rg.map.keys() grid_keys=self.rg.map.keys()
partial_track=vector(0,self.track_width/6.0) partial_track=vector(0,self.track_width/6.0)
for g in grid_keys: for g in grid_keys:
continue # for now... shape = self.convert_track_to_shape(g)
shape = self.convert_full_track_to_shape(g) self.cell.add_rect(layer="text",
self.cell.add_rect(layer="boundary",
offset=shape[0], offset=shape[0],
width=shape[1].x-shape[0].x, width=shape[1].x-shape[0].x,
height=shape[1].y-shape[0].y) height=shape[1].y-shape[0].y)
@ -481,7 +462,7 @@ class router:
zoom=0.05) zoom=0.05)
for blockage in self.blockages: for blockage in self.blockages:
self.cell.add_rect(layer="boundary", self.cell.add_rect(layer="blockage",
offset=blockage.ll(), offset=blockage.ll(),
width=blockage.width(), width=blockage.width(),
height=blockage.height()) height=blockage.height())

View File

@ -32,12 +32,14 @@ class no_blockages_test(openram_test):
globals.setup_paths() globals.setup_paths()
from control_logic import control_logic from control_logic import control_logic
cell = control_logic(16) cell = control_logic(16)
#from pinv import pinv
#cell = pinv()
#gds_file = "{0}/{1}.gds".format(os.path.dirname(os.path.realpath(__file__)),"control_logic") #gds_file = "{0}/{1}.gds".format(os.path.dirname(os.path.realpath(__file__)),"control_logic")
#cell = gds_cell(name, gds_file) #cell = gds_cell(name, gds_file)
self.add_inst(name=name, self.add_inst(name=name,
mod=cell, mod=cell,
offset=[0,0]) offset=[0,0])
self.connect_inst(["csb","web","clk","s_en","w_en","clk_buf_bar","clk_buf","vdd","gnd"]) self.connect_inst(cell.pin_map.keys())
r=router(module=cell) r=router(module=cell)
layer_stack =("metal3","via2","metal2") layer_stack =("metal3","via2","metal2")

View File

@ -56,6 +56,7 @@ layer["via9"] = 28
layer["metal10"] = 29 layer["metal10"] = 29
layer["text"] = 239 layer["text"] = 239
layer["boundary"]= 239 layer["boundary"]= 239
layer["blockage"]= 239
################################################### ###################################################
##END GDS Layer Map ##END GDS Layer Map

View File

@ -41,6 +41,7 @@ layer["via2"] = 61
layer["metal3"] = 62 layer["metal3"] = 62
layer["text"] = 63 layer["text"] = 63
layer["boundary"] = 63 layer["boundary"] = 63
layer["blockage"] = 83
################################################### ###################################################
##END GDS Layer Map ##END GDS Layer Map