mirror of https://github.com/VLSIDA/OpenRAM.git
Merge branch 'dev' of https://github.com/VLSIDA/PrivateRAM into multiport
This commit is contained in:
commit
c91735b23b
|
|
@ -15,6 +15,7 @@ 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.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
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}".format(layer_stack[0],
|
||||||
|
|
@ -24,12 +25,13 @@ class contact(hierarchy_design.hierarchy_design):
|
||||||
dimensions[1],
|
dimensions[1],
|
||||||
implant_type,
|
implant_type,
|
||||||
well_type)
|
well_type)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
name = "{0}_{1}_{2}_{3}x{4}".format(layer_stack[0],
|
name = "{0}_{1}_{2}_{3}x{4}".format(layer_stack[0],
|
||||||
layer_stack[1],
|
layer_stack[1],
|
||||||
layer_stack[2],
|
layer_stack[2],
|
||||||
dimensions[0],
|
dimensions[0],
|
||||||
dimensions[1])
|
dimensions[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))
|
||||||
|
|
|
||||||
|
|
@ -379,11 +379,9 @@ 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)
|
||||||
|
|
@ -849,10 +847,10 @@ class layout(lef.lef):
|
||||||
"""
|
"""
|
||||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||||
offset=loc,
|
offset=loc,
|
||||||
rotate=rotate)
|
rotate=float(rotate))
|
||||||
via=self.add_via_center(layers=("metal2", "via2", "metal3"),
|
via=self.add_via_center(layers=("metal2", "via2", "metal3"),
|
||||||
offset=loc,
|
offset=loc,
|
||||||
rotate=rotate)
|
rotate=float(rotate))
|
||||||
self.add_layout_pin_rect_center(text=name,
|
self.add_layout_pin_rect_center(text=name,
|
||||||
layer="metal3",
|
layer="metal3",
|
||||||
offset=loc,
|
offset=loc,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import debug
|
import debug
|
||||||
from tech import GDS
|
from tech import GDS, drc
|
||||||
from vector import vector
|
from vector import vector
|
||||||
from tech import layer
|
from tech import layer
|
||||||
|
|
||||||
|
|
@ -36,16 +36,29 @@ 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 inflate(self, spacing=None):
|
||||||
|
"""
|
||||||
|
Inflate the rectangle by the spacing (or other rule)
|
||||||
|
and return the new rectangle.
|
||||||
|
"""
|
||||||
|
if not spacing:
|
||||||
|
spacing = drc["{0}_to_{0}".format(self.layer)]
|
||||||
|
|
||||||
|
(ll,ur) = self.rect
|
||||||
|
spacing = vector(spacing, spacing)
|
||||||
|
newll = ll - spacing
|
||||||
|
newur = ur + spacing
|
||||||
|
|
||||||
|
return (newll, newur)
|
||||||
|
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -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))
|
||||||
|
|
|
||||||
|
|
@ -280,8 +280,13 @@ 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
|
# The rotate and magnify flags specify "absolute" rotate and magnify.
|
||||||
magnifyFlag = int(thisSref.transFlags[2])<<3
|
# It is unclear what that is (ignore all further rotates/mags in the
|
||||||
|
# hierarchy? But anyway, calibre doesn't support it.
|
||||||
|
rotateFlag=0
|
||||||
|
magnifyFlag = 0
|
||||||
|
#rotateFlag = int(thisSref.transFlags[2])<<1
|
||||||
|
#magnifyFlag = int(thisSref.transFlags[1])<<2
|
||||||
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.magFactor!=""):
|
||||||
|
|
@ -327,15 +332,20 @@ 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
|
# The rotate and magnify flags specify "absolute" rotate and magnify.
|
||||||
magnifyFlag = int(thisAref.transFlags[0])<<3
|
# It is unclear what that is (ignore all further rotates/mags in the
|
||||||
|
# hierarchy? But anyway, calibre doesn't support it.
|
||||||
|
rotateFlag=0
|
||||||
|
magnifyFlag = 0
|
||||||
|
#rotateFlag = int(thisAref.transFlags[2])<<1
|
||||||
|
#magnifyFlag = int(thisAref.transFlags[1])<<2
|
||||||
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.magFactor!=""):
|
||||||
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.rotateAngle!=""):
|
||||||
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 +384,20 @@ 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
|
# The rotate and magnify flags specify "absolute" rotate and magnify.
|
||||||
magnifyFlag = int(thisText.transFlags[0])<<3
|
# It is unclear what that is (ignore all further rotates/mags in the
|
||||||
|
# hierarchy? But anyway, calibre doesn't support it.
|
||||||
|
rotateFlag=0
|
||||||
|
magnifyFlag = 0
|
||||||
|
#rotateFlag = int(thisText.transFlags[2])<<1
|
||||||
|
#magnifyFlag = int(thisText.transFlags[1])<<2
|
||||||
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.magFactor!=""):
|
||||||
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.rotateAngle!=""):
|
||||||
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)
|
||||||
|
|
|
||||||
|
|
@ -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=""
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -118,9 +118,6 @@ def init_openram(config_file, is_unit_test=True):
|
||||||
|
|
||||||
init_paths()
|
init_paths()
|
||||||
|
|
||||||
# This depends on the tech, so do it after tech is loaded
|
|
||||||
init_config()
|
|
||||||
|
|
||||||
# Reset the static duplicate name checker for unit tests.
|
# Reset the static duplicate name checker for unit tests.
|
||||||
import hierarchy_design
|
import hierarchy_design
|
||||||
hierarchy_design.hierarchy_design.name_map=[]
|
hierarchy_design.hierarchy_design.name_map=[]
|
||||||
|
|
@ -257,7 +254,8 @@ def cleanup_paths():
|
||||||
if not OPTS.purge_temp:
|
if not OPTS.purge_temp:
|
||||||
debug.info(0,"Preserving temp directory: {}".format(OPTS.openram_temp))
|
debug.info(0,"Preserving temp directory: {}".format(OPTS.openram_temp))
|
||||||
return
|
return
|
||||||
if os.path.exists(OPTS.openram_temp):
|
elif os.path.exists(OPTS.openram_temp):
|
||||||
|
debug.info(1,"Purging temp directory: {}".format(OPTS.openram_temp))
|
||||||
# This annoyingly means you have to re-cd into the directory each debug iteration
|
# This annoyingly means you have to re-cd into the directory each debug iteration
|
||||||
#shutil.rmtree(OPTS.openram_temp, ignore_errors=True)
|
#shutil.rmtree(OPTS.openram_temp, ignore_errors=True)
|
||||||
contents = [os.path.join(OPTS.openram_temp, i) for i in os.listdir(OPTS.openram_temp)]
|
contents = [os.path.join(OPTS.openram_temp, i) for i in os.listdir(OPTS.openram_temp)]
|
||||||
|
|
@ -293,8 +291,6 @@ def setup_paths():
|
||||||
OPTS.openram_temp += "/"
|
OPTS.openram_temp += "/"
|
||||||
debug.info(1, "Temporary files saved in " + OPTS.openram_temp)
|
debug.info(1, "Temporary files saved in " + OPTS.openram_temp)
|
||||||
|
|
||||||
cleanup_paths()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def is_exe(fpath):
|
def is_exe(fpath):
|
||||||
|
|
@ -316,6 +312,7 @@ def init_paths():
|
||||||
|
|
||||||
# make the directory if it doesn't exist
|
# make the directory if it doesn't exist
|
||||||
try:
|
try:
|
||||||
|
debug.info(1,"Creating temp directory: {}".format(OPTS.openram_temp))
|
||||||
os.makedirs(OPTS.openram_temp, 0o750)
|
os.makedirs(OPTS.openram_temp, 0o750)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
if e.errno == 17: # errno.EEXIST
|
if e.errno == 17: # errno.EEXIST
|
||||||
|
|
@ -331,15 +328,6 @@ def init_paths():
|
||||||
except:
|
except:
|
||||||
debug.error("Unable to make output directory.",-1)
|
debug.error("Unable to make output directory.",-1)
|
||||||
|
|
||||||
def init_config():
|
|
||||||
""" Initialize the SRAM configurations. """
|
|
||||||
# Create the SRAM configuration
|
|
||||||
from sram_config import sram_config
|
|
||||||
OPTS.sram_config = sram_config(OPTS.word_size,
|
|
||||||
OPTS.num_words,
|
|
||||||
OPTS.num_banks)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# imports correct technology directories for testing
|
# imports correct technology directories for testing
|
||||||
def import_tech():
|
def import_tech():
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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):
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -84,19 +90,19 @@ class router:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def find_pin(self,pin):
|
def find_pin(self,pin_name):
|
||||||
"""
|
"""
|
||||||
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].
|
Pin can either be a label or a location,layer pair: [[x,y],layer].
|
||||||
"""
|
"""
|
||||||
|
|
||||||
label_list=self.layout.getPinShapeByLabel(str(pin))
|
shape_list=self.layout.getPinShapeByLabel(str(pin_name))
|
||||||
pin_list = []
|
pin_list = []
|
||||||
for label in label_list:
|
for shape in shape_list:
|
||||||
(name,layer,boundary)=label
|
(name,layer,boundary)=shape
|
||||||
rect = [vector(boundary[0],boundary[1]),vector(boundary[2],boundary[3])]
|
rect = [vector(boundary[0],boundary[1]),vector(boundary[2],boundary[3])]
|
||||||
# this is a list because other cells/designs may have must-connect pins
|
pin = pin_layout(pin_name, rect, layer)
|
||||||
pin_list.append(pin_layout(pin, rect, layer))
|
pin_list.append(pin)
|
||||||
|
|
||||||
debug.check(len(pin_list)>0,"Did not find any pin shapes for {0}.".format(str(pin)))
|
debug.check(len(pin_list)>0,"Did not find any pin shapes for {0}.".format(str(pin)))
|
||||||
|
|
||||||
|
|
@ -202,17 +208,30 @@ class router:
|
||||||
|
|
||||||
|
|
||||||
def add_blockages(self):
|
def add_blockages(self):
|
||||||
""" Add the blockages except the pin shapes """
|
""" Add the blockages except the pin shapes. Also remove the pin shapes from the blockages list. """
|
||||||
|
# Join all the pin shapes into one big list
|
||||||
|
all_pins = [item for sublist in list(self.pins.values()) for item in sublist]
|
||||||
|
|
||||||
|
# Do an n^2 check to see if any shapes are the same, otherwise add them
|
||||||
|
# FIXME: Make faster, but number of pins won't be *that* large
|
||||||
|
real_blockages = []
|
||||||
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,"Removing blockage for pin {}".format(str(pin)))
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
[ll,ur]=self.convert_blockage_to_tracks(blockage.rect)
|
debug.info(2,"Adding blockage {}".format(str(blockage)))
|
||||||
zlayer = 0 if blockage.layer_num==self.horiz_layer_number else 1
|
# Inflate the blockage by spacing rule
|
||||||
|
[ll,ur]=self.convert_blockage_to_tracks(blockage.inflate())
|
||||||
|
zlayer = self.get_zindex(blockage.layer_num)
|
||||||
self.rg.add_blockage_shape(ll,ur,zlayer)
|
self.rg.add_blockage_shape(ll,ur,zlayer)
|
||||||
|
real_blockages.append(blockage)
|
||||||
|
|
||||||
|
# Remember the filtered blockages
|
||||||
|
self.blockages = real_blockages
|
||||||
|
|
||||||
|
|
||||||
def get_blockages(self, layer_num):
|
def get_blockages(self, layer_num):
|
||||||
|
|
@ -228,37 +247,6 @@ class router:
|
||||||
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,11 +270,15 @@ 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)
|
||||||
ll = ll.floor()
|
# We can round since we are using inflated shapes
|
||||||
ur = ur.ceil()
|
# and the track points are at the center
|
||||||
if ll[0]<45 and ll[0]>35 and ll[1]<10 and ll[1]>0:
|
ll = ll.round()
|
||||||
debug.info(0,"Converting [ {0} , {1} ]".format(old_ll,old_ur))
|
ur = ur.round()
|
||||||
debug.info(0,"Converted [ {0} , {1} ]".format(ll,ur))
|
# if ll[0]<45 and ll[0]>35 and ll[1]<5 and ll[1]>-5:
|
||||||
|
# debug.info(0,"Converting [ {0} , {1} ]".format(old_ll,old_ur))
|
||||||
|
# debug.info(0,"Converted [ {0} , {1} ]".format(ll,ur))
|
||||||
|
# pin=self.convert_track_to_shape(ll)
|
||||||
|
# debug.info(0,"Pin {}".format(pin))
|
||||||
return [ll,ur]
|
return [ll,ur]
|
||||||
|
|
||||||
def convert_pin_to_tracks(self, pin):
|
def convert_pin_to_tracks(self, pin):
|
||||||
|
|
@ -296,9 +288,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 +295,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 +373,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 +439,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,10 +472,12 @@ class router:
|
||||||
zoom=0.05)
|
zoom=0.05)
|
||||||
|
|
||||||
for blockage in self.blockages:
|
for blockage in self.blockages:
|
||||||
self.cell.add_rect(layer="boundary",
|
# Display the inflated blockage
|
||||||
offset=blockage.ll(),
|
(ll,ur) = blockage.inflate()
|
||||||
width=blockage.width(),
|
self.cell.add_rect(layer="blockage",
|
||||||
height=blockage.height())
|
offset=ll,
|
||||||
|
width=ur.x-ll.x,
|
||||||
|
height=ur.y-ll.y)
|
||||||
|
|
||||||
|
|
||||||
# FIXME: This should be replaced with vector.snap_to_grid at some point
|
# FIXME: This should be replaced with vector.snap_to_grid at some point
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -625,7 +625,7 @@ drDefinePacket(
|
||||||
( display deviceAnt stipple0 solid yellow yellow solid )
|
( display deviceAnt stipple0 solid yellow yellow solid )
|
||||||
( display winBottomShadow solid solid winColor1 winColor1 solid )
|
( display winBottomShadow solid solid winColor1 winColor1 solid )
|
||||||
( display PselectNet dots4 solid brown brown outlineStipple)
|
( display PselectNet dots4 solid brown brown outlineStipple)
|
||||||
( display comment stipple0 lineStyle0 winBack winBack solid )
|
( display comment stipple0 lineStyle0 winBack winBack outline )
|
||||||
( display Poly1 dots lineStyle0 red red outlineStipple)
|
( display Poly1 dots lineStyle0 red red outlineStipple)
|
||||||
( display Unrouted stipple0 lineStyle1 winColor5 winColor5 solid )
|
( display Unrouted stipple0 lineStyle1 winColor5 winColor5 solid )
|
||||||
( display stretch stipple0 solid yellow yellow solid )
|
( display stretch stipple0 solid yellow yellow solid )
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue