OpenRAM/compiler/gdsMill/gdsMill/gds2reader.py

836 lines
40 KiB
Python

#!/usr/bin/env python
import struct
from .gdsPrimitives import *
class Gds2reader:
"""Class to read in a file in GDSII format and populate a layout class with it"""
## Based on info from http://www.rulabinsky.com/cavd/text/chapc.html
global offset
offset=0
def __init__(self,layoutObject,debugToTerminal = 0):
self.fileHandle = None
self.layoutObject = layoutObject
self.debugToTerminal=debugToTerminal
#do we dump debug data to the screen
def print64AsBinary(self,number):
for index in range(0,64):
print((number>>(63-index))&0x1,eol='')
print("\n")
def stripNonASCII(self,bytestring):
string = bytestring.decode('utf-8')
return string
def ieeeDoubleFromIbmData(self,ibmData):
#the GDS double is in IBM 370 format like this:
#(1)sign (7)exponent (56)mantissa
#exponent is excess 64, mantissa has no implied 1
#a normal IEEE double is like this:
#(1)sign (11)exponent (52)mantissa
data = struct.unpack('>q',ibmData)[0]
sign = (data >> 63)&0x01
exponent = (data >> 56) & 0x7f
mantissa = data<<8 #chop off sign and exponent
if mantissa == 0:
newFloat = 0.0
else:
exponent = ((exponent-64)*4)+1023 #convert to double exponent
#re normalize
while mantissa & 0x8000000000000000 == 0:
mantissa<<=1
exponent-=1
mantissa<<=1 #remove the assumed high bit
exponent-=1
#check for underflow error -- should handle these properly!
if(exponent<=0):
print("Underflow Error")
elif(exponent == 2047):
print("Overflow Error")
#re assemble
newFloat=(sign<<63)|(exponent<<52)|((mantissa>>12)&0xfffffffffffff)
asciiDouble = struct.pack('>q',newFloat)
#convert back to double
newFloat = struct.unpack('>d',asciiDouble)[0]
return newFloat
def ieeeFloatCheck(self,aFloat):
asciiDouble = struct.pack('>d',aFloat)
data = struct.unpack('>q',asciiDouble)[0]
sign = data >> 63
exponent = ((data >> 52) & 0x7ff)-1023
# BINWU: Cleanup
#print(exponent+1023)
mantissa = data << 12 #chop off sign and exponent
# BINWU: Cleanup
#self.print64AsBinary((sign<<63)|((exponent+1023)<<52)|(mantissa>>12))
asciiDouble = struct.pack('>q',(sign<<63)|(exponent+1023<<52)|(mantissa>>12))
newFloat = struct.unpack('>d',asciiDouble)[0]
print("Check:"+str(newFloat))
def readNextRecord(self):
global offset
recordLengthAscii = self.fileHandle.read(2) #first 2 bytes tell us the length of the record
if len(recordLengthAscii)==0:
return
recordLength = struct.unpack(">h",recordLengthAscii) #gives us a tuple with a short int inside
offset_int = int(recordLength[0]) # extract length
offset += offset_int # count offset
#print(offset) #print out the record numbers for de-bugging
record = self.fileHandle.read(recordLength[0]-2) #read the rest of it (first 2 bytes were already read)
return record
def readHeader(self):
self.layoutObject.info.clear()
## Header
record = self.readNextRecord()
idBits = record[0:2]
if(idBits==b'\x00\x02' and len(record)==4):
gdsVersion = struct.unpack(">h",record[2:4])[0]
self.layoutObject.info["gdsVersion"]=gdsVersion
if(self.debugToTerminal==1):
print("GDS II Version "+str(gdsVersion))
else:
print("Invalid GDSII Header")
return -1
#read records until we hit the UNITS section... this is the last part of the header
while 1:
record = self.readNextRecord()
idBits = record[0:2]
## Modified Date
if idBits==b'\x01\x02' and len(record)==26:
modYear = struct.unpack(">h",record[2:4])[0]
modMonth = struct.unpack(">h",record[4:6])[0]
modDay = struct.unpack(">h",record[6:8])[0]
modHour = struct.unpack(">h",record[8:10])[0]
modMinute = struct.unpack(">h",record[10:12])[0]
modSecond = struct.unpack(">h",record[12:14])[0]
lastAccessYear = struct.unpack(">h",record[14:16])[0]
lastAccessMonth = struct.unpack(">h",record[16:18])[0]
lastAccessDay = struct.unpack(">h",record[18:20])[0]
lastAccessHour = struct.unpack(">h",record[20:22])[0]
lastAccessMinute = struct.unpack(">h",record[22:24])[0]
lastAccessSecond = struct.unpack(">h",record[24:26])[0]
self.layoutObject.info["dates"]=(modYear,modMonth,modDay,modHour,modMinute,modSecond,\
lastAccessYear,lastAccessMonth,lastAccessDay,lastAccessHour,lastAccessMinute,lastAccessSecond)
if(self.debugToTerminal==1):
print("Date Modified:"+str(modYear)+","+str(modMonth)+","+str(modDay)+","+str(modHour)+","+str(modMinute)+","+str(modSecond))
print("Date Last Accessed:"+str(lastAccessYear)+","+str(lastAccessMonth)+","+str(lastAccessDay)+\
","+str(lastAccessHour)+","+str(lastAccessMinute)+","+str(lastAccessSecond))
## LibraryName
elif(idBits==b'\x02\x06'):
libraryName = record[2::].decode("utf-8")
self.layoutObject.info["libraryName"]=libraryName
if(self.debugToTerminal==1):
print("Library: "+libraryName)
## reference libraries
elif(idBits==b'\x1F\x06'):
referenceLibraryA = record[2:46]
referenceLibraryB = record[47:91]
self.layoutObject.info["referenceLibraries"]=(referenceLibraryA,referenceLibraryB)
if(self.debugToTerminal==1):
print( "Reference Libraries:"+referenceLibraryA+","+referenceLibraryB)
elif(idBits==b'\x20\x06'):
fontA = record[2:45]
fontB = record[46:89]
fontC = record[90:133]
fontD = record[134:177]
self.layoutObject.info["fonts"]=(fontA,fontB,fontC,fontD)
if(self.debugToTerminal==1):
print("Fonts:"+fontA+","+fontB+","+fontC+","+fontD)
elif(idBits==b'\x23\x06'):
attributeTable = record[2:45]
self.layoutObject.info["attributeTable"]=attributeTable
if(self.debugToTerminal==1):
print("Attributes:"+attributeTable)
elif(idBits==b'\x22\x02'):
generations = struct.unpack(">h",record[2]+record[3])
self.layoutObject.info["generations"]=generations
if(self.debugToTerminal==1):
print("Generations:"+generations )
elif(idBits==b'\x36\x02'):
fileFormat = struct.unpack(">h",record[2]+record[3])
self.layoutObject.info["fileFormat"]=fileFormat
if(self.debugToTerminal==1):
print("File Format:"+fileFormat)
elif(idBits==b'\x37\x06'):
mask = record[2::]
self.layoutObject.info["mask"] = mask
if(self.debugToTerminal==1):
print("Mask: "+mask)
elif(idBits==b'\x03\x05'): #this is also wrong b/c python doesn't natively have an 8 byte float
userUnits=self.ieeeDoubleFromIbmData(record[2:10])
dbUnits=self.ieeeDoubleFromIbmData(record[10:18])
self.layoutObject.info["units"] = (userUnits,dbUnits)
if(self.debugToTerminal==1):
print("Units: 1 user unit="+str(userUnits)+" database units, 1 database unit="+str(dbUnits)+" meters.")
break;
if(self.debugToTerminal==1):
print("End of GDSII Header Found")
return 1
def readBoundary(self):
##reads in a boundary type structure = a filled polygon
if(self.debugToTerminal==1):
print("\t\t\tBeginBoundary")
thisBoundary=GdsBoundary()
while 1:
record = self.readNextRecord()
idBits = record[0:2]
if(idBits==b'\x26\x01'): #ELFLAGS
elementFlags = struct.unpack(">h",record[2:4])[0]
thisBoundary.elementFlags=elementFlags
if(self.debugToTerminal==1):
print("\t\tElement Flags: "+str(elementFlags))
elif(idBits==b'\x2F\x03'): #PLEX
plex = struct.unpack(">i",record[2:6])[0]
thisBoundary.plex=plex
if(self.debugToTerminal==1):
print("\t\tPLEX: "+str(plex))
elif(idBits==b'\x0D\x02'): #Layer
drawingLayer = struct.unpack(">h",record[2:4])[0]
thisBoundary.drawingLayer=drawingLayer
if drawingLayer not in self.layoutObject.layerNumbersInUse:
self.layoutObject.layerNumbersInUse += [drawingLayer]
if(self.debugToTerminal==1):
print("\t\tDrawing Layer: "+str(drawingLayer))
elif(idBits==b'\x0E\x02'): #Purpose DATATYPE
purposeLayer = struct.unpack(">h",record[2:4])[0]
thisBoundary.purposeLayer=purposeLayer
if(self.debugToTerminal==1):
print("\t\tPurpose Layer: "+str(purposeLayer))
elif(idBits==b'\x10\x03'): #XY Data Points
numDataPoints = len(record)-2 #packed as XY coordinates 4 bytes each
thisBoundary.coordinates=[]
for index in range(2,numDataPoints+2,8): #incorporate the 2 byte offset
x=struct.unpack(">i",record[index:index+4])[0]
y=struct.unpack(">i",record[index+4:index+8])[0]
thisBoundary.coordinates+=[(x,y)]
if(self.debugToTerminal==1):
print("\t\t\tXY Point: "+str(x)+","+str(y))
elif(idBits==b'\x11\x00'): #End Of Element
if(self.debugToTerminal==1):
print("\t\t\tEndBoundary")
break;
return thisBoundary
def readPath(self): #reads in a path structure
if(self.debugToTerminal==1):
print("\t\t\tBeginPath")
thisPath=GdsPath()
while 1:
record = self.readNextRecord()
idBits = record[0:2]
if(idBits==b'\x26\x01'): #ELFLAGS
elementFlags = struct.unpack(">h",record[2:4])[0]
thisPath.elementFlags=elementFlags
if(self.debugToTerminal==1):
print("\t\tElement Flags: "+str(elementFlags))
elif(idBits==b'\x2F\x03'): #PLEX
plex = struct.unpack(">i",record[2:6])[0]
thisPath.plex=plex
if(self.debugToTerminal==1):
print("\t\tPLEX: "+str(plex))
elif(idBits==b'\x0D\x02'): #Layer
drawingLayer = struct.unpack(">h",record[2:4])[0]
thisPath.drawingLayer=drawingLayer
if drawingLayer not in self.layoutObject.layerNumbersInUse:
self.layoutObject.layerNumbersInUse += [drawingLayer]
if(self.debugToTerminal==1):
print("\t\t\tDrawing Layer: "+str(drawingLayer))
elif(idBits==b'\x16\x02'): #Purpose
purposeLayer = struct.unpack(">h",record[2:4])[0]
thisPath.purposeLayer=purposeLayer
if(self.debugToTerminal==1):
print("\t\tPurpose Layer: "+str(purposeLayer))
elif(idBits==b'\x21\x02'): #Path type
pathType = struct.unpack(">h",record[2:4])[0]
thisPath.pathType=pathType
if(self.debugToTerminal==1):
print("\t\t\tPath Type: "+str(pathType))
elif(idBits==b'\x0E\x02'): #Data type
dataType = struct.unpack(">h",record[2:4])[0]
thisPath.dataType=dataType
if(self.debugToTerminal==1):
print("\t\t\tData Type: "+str(dataType))
elif(idBits==b'\x0F\x03'): #Path width
pathWidth = struct.unpack(">i",record[2:6])[0]
thisPath.pathWidth=pathWidth
if(self.debugToTerminal==1):
print("\t\t\tPath Width: "+str(pathWidth))
elif(idBits==b'\x10\x03'): #XY Data Points
numDataPoints = len(record)-2 #packed nas XY coordinates 4 bytes each
thisPath.coordinates=[]
for index in range(2,numDataPoints+2,8): #incorporate the 2 byte offset
x=struct.unpack(">i",record[index:index+4])[0]
y=struct.unpack(">i",record[index+4:index+8])[0]
thisPath.coordinates+=[(x,y)]
if(self.debugToTerminal==1):
print("\t\t\tXY Point: "+str(x)+","+str(y))
elif(idBits==b'\x11\x00'): #End Of Element
if(self.debugToTerminal==1):
print("\t\t\tEndPath")
break;
return thisPath
def readSref(self): #reads in a reference to another structure
if(self.debugToTerminal==1):
print("\t\t\tBeginSref")
thisSref=GdsSref()
while 1:
record = self.readNextRecord()
idBits = record[0:2]
if(idBits==b'\x26\x01'): #ELFLAGS
elementFlags = struct.unpack(">h",record[2:4])[0]
thisSref.elementFlags=elementFlags
if(self.debugToTerminal==1):
print("\t\tElement Flags: "+str(elementFlags))
elif(idBits==b'\x2F\x03'): #PLEX
plex = struct.unpack(">i",record[2:6])[0]
thisSref.plex=plex
if(self.debugToTerminal==1):
print("\t\tPLEX: "+str(plex))
elif(idBits==b'\x12\x06'): #Reference Name
sName = self.stripNonASCII(record[2::])
thisSref.sName=sName.rstrip()
if(self.debugToTerminal==1):
print("\t\tReference Name:"+sName)
elif(idBits==b'\x1A\x01'): #Transformation
transFlags = struct.unpack(">H",record[2:4])[0]
mirrorFlag = bool(transFlags&0x8000) ##these flags are a bit sketchy
rotateFlag = bool(transFlags&0x0002)
magnifyFlag = bool(transFlags&0x0004)
thisSref.transFlags=[mirrorFlag,magnifyFlag,rotateFlag]
if(self.debugToTerminal==1):
print("\t\t\tMirror X:"+str(mirrorFlag))
print( "\t\t\tRotate:"+str(rotateFlag))
print("\t\t\tMagnify:"+str(magnifyFlag))
elif(idBits==b'\x1B\x05'): #Magnify
magFactor=self.ieeeDoubleFromIbmData(record[2:10])
thisSref.magFactor=magFactor
if(self.debugToTerminal==1):
print("\t\t\tMagnification:"+str(magFactor))
elif(idBits==b'\x1C\x05'): #Rotate Angle
rotateAngle=self.ieeeDoubleFromIbmData(record[2:10])
thisSref.rotateAngle=rotateAngle
if(self.debugToTerminal==1):
print("\t\t\tRotate Angle (CCW):"+str(rotateAngle))
elif(idBits==b'\x10\x03'): #XY Data Points
index=2
x=struct.unpack(">i",record[index:index+4])[0]
y=struct.unpack(">i",record[index+4:index+8])[0]
thisSref.coordinates=(x,y)
if(self.debugToTerminal==1):
print("\t\t\tXY Point: "+str(x)+","+str(y))
elif(idBits==b'\x11\x00'): #End Of Element
if(self.debugToTerminal==1):
print("\t\t\tEndSref")
break;
return thisSref
def readAref(self): #an array of references
if(self.debugToTerminal==1):
print("\t\t\tBeginAref")
thisAref = GdsAref()
while 1:
record = self.readNextRecord()
idBits = record[0:2]
if(idBits==b'\x26\x01'): #ELFLAGS
elementFlags = struct.unpack(">h",record[2:4])[0]
thisAref.elementFlags=elementFlags
if(self.debugToTerminal==1):
print("\t\tElement Flags: "+str(elementFlags))
elif(idBits==b'\x2F\x03'): #PLEX
plex = struct.unpack(">i",record[2:6])[0]
thisAref.plex=plex
if(self.debugToTerminal==1):
print("\t\tPLEX: "+str(plex))
elif(idBits==b'\x12\x06'): #Reference Name
aName = record[2::]
thisAref.aName=aName
if(self.debugToTerminal==1):
print("\t\tReference Name:"+aName)
elif(idBits==b'\x1A\x01'): #Transformation
transFlags = struct.unpack(">H",record[2:4])[0]
mirrorFlag = bool(transFlags&0x8000) ##these flags are a bit sketchy
rotateFlag = bool(transFlags&0x0002)
magnifyFlag = bool(transFlags&0x0004)
thisAref.transFlags=[mirrorFlag,magnifyFlag,rotateFlag]
if(self.debugToTerminal==1):
print("\t\t\tMirror X:"+str(mirrorFlag))
print("\t\t\tRotate:"+str(rotateFlag))
print("\t\t\tMagnify:"+str(magnifyFlag))
elif(idBits==b'\x1B\x05'): #Magnify
magFactor=self.ieeeDoubleFromIbmData(record[2:10])
thisAref.magFactor=magFactor
if(self.debugToTerminal==1):
print("\t\t\tMagnification:"+str(magFactor))
elif(idBits==b'\x1C\x05'): #Rotate Angle
rotateAngle=self.ieeeDoubleFromIbmData(record[2:10])
thisAref.rotateAngle=rotateAngle
if(self.debugToTerminal==1):
print("\t\t\tRotate Angle (CCW):"+str(rotateAngle))
elif(idBits==b'\x10\x03'): #XY Data Points
index=2
topLeftX=struct.unpack(">i",record[index:index+4])[0]
topLeftY=struct.unpack(">i",record[index+4:index+8])[0]
rightMostX=struct.unpack(">i",record[index+8:index+12])[0]
bottomMostY=struct.unpack(">i",record[index+12:index+16])[0]
thisAref.coordinates=[(topLeftX,topLeftY),(rightMostX,topLeftY),(topLeftX,bottomMostY)]
if(self.debugToTerminal==1):
print("\t\t\tTop Left Point: "+str(topLeftX)+","+str(topLeftY))
print("\t\t\t\tArray Width: "+str(rightMostX-topLeftX))
print("\t\t\t\tArray Height: "+str(topLeftY-bottomMostY))
elif(idBits==b'\x11\x00'): #End Of Element
if(self.debugToTerminal==1):
print("\t\t\tEndAref")
break;
return thisAref
def readText(self):
if(self.debugToTerminal==1):
print("\t\t\tBeginText")
thisText=GdsText()
while 1:
record = self.readNextRecord()
idBits = record[0:2]
if(idBits==b'\x26\x01'): #ELFLAGS
elementFlags = struct.unpack(">h",record[2:4])[0]
thisText.elementFlags=elementFlags
if(self.debugToTerminal==1):
print("\t\tElement Flags: "+str(elementFlags))
elif(idBits==b'\x2F\x03'): #PLEX
plex = struct.unpack(">i",record[2:6])[0]
thisText.plex=plex
if(self.debugToTerminal==1):
print("\t\tPLEX: "+str(plex))
elif(idBits==b'\x0D\x02'): #Layer
drawingLayer = struct.unpack(">h",record[2:4])[0]
thisText.drawingLayer=drawingLayer
if drawingLayer not in self.layoutObject.layerNumbersInUse:
self.layoutObject.layerNumbersInUse += [drawingLayer]
if(self.debugToTerminal==1):
print("\t\tDrawing Layer: "+str(drawingLayer))
elif(idBits==b'\x16\x02'): #Purpose TEXTTYPE
purposeLayer = struct.unpack(">h",record[2:4])[0]
thisText.purposeLayer=purposeLayer
if(self.debugToTerminal==1):
print("\t\tPurpose Layer: "+str(purposeLayer))
elif(idBits==b'\x1A\x01'): #Transformation
transFlags = struct.unpack(">H",record[2:4])[0]
mirrorFlag = bool(transFlags&0x8000) ##these flags are a bit sketchy
rotateFlag = bool(transFlags&0x0002)
magnifyFlag = bool(transFlags&0x0004)
thisText.transFlags=[mirrorFlag,magnifyFlag,rotateFlag]
if(self.debugToTerminal==1):
print("\t\t\tMirror X:"+str(mirrorFlag))
print("\t\t\tRotate:"+str(rotateFlag))
print("\t\t\tMagnify:"+str(magnifyFlag))
elif(idBits==b'\x1B\x05'): #Magnify
magFactor=self.ieeeDoubleFromIbmData(record[2:10])
thisText.magFactor=magFactor
if(self.debugToTerminal==1):
print("\t\t\tMagnification:"+str(magFactor))
elif(idBits==b'\x1C\x05'): #Rotate Angle
rotateAngle=self.ieeeDoubleFromIbmData(record[2:10])
thisText.rotateAngle=rotateAngle
if(self.debugToTerminal==1):
print("\t\t\tRotate Angle (CCW):"+str(rotateAngle))
elif(idBits==b'\x21\x02'): #Path type
pathType = struct.unpack(">h",record[2:4])[0]
thisText.pathType=pathType
if(self.debugToTerminal==1):
print("\t\t\tPath Type: "+str(pathType))
elif(idBits==b'\x0F\x03'): #Path width
pathWidth = struct.unpack(">i",record[2:6])[0]
thisText.pathWidth=pathWidth
if(self.debugToTerminal==1):
print("\t\t\tPath Width: "+str(pathWidth))
elif(idBits==b'\x1A\x01'): #Text Presentation
presentationFlags = struct.unpack(">H",record[2:4])[0]
font = (presentationFlags&0x0030)>>4 ##these flags are a bit sketchy
verticalFlags = (presentationFlags&0x000C)
horizontalFlags = (presentationFlags&0x0003)
thisText.presentationFlags=(font,verticalFlags,horizontalFlags)
if(self.debugToTerminal==1):
print("\t\t\tFont:"+str(font))
if(verticalFlags==0):
if(self.debugToTerminal==1):
print("\t\t\tVertical: Top")
elif(verticalFlags==1):
if(self.debugToTerminal==1):
print("\t\t\tVertical: Middle")
elif(verticalFlags==2):
if(self.debugToTerminal==1):
print("\t\t\tVertical: Bottom")
if(horizontalFlags==0):
if(self.debugToTerminal==1):
print("\t\t\tHorizontal: Left")
elif(horizontalFlags==1):
if(self.debugToTerminal==1):
print("\t\t\tHorizontal: Center")
elif(horizontalFlags==2):
if(self.debugToTerminal==1):
print("\t\t\tHorizontal: Right")
elif(idBits==b'\x10\x03'): #XY Data Points
index=2
x=struct.unpack(">i",record[index:index+4])[0]
y=struct.unpack(">i",record[index+4:index+8])[0]
thisText.coordinates=[(x,y)]
if(self.debugToTerminal==1):
print("\t\t\tXY Point: "+str(x)+","+str(y))
elif(idBits==b'\x19\x06'): #Text String - also the last record in this element
textString = record[2::].decode('utf-8')
thisText.textString=textString
if(self.debugToTerminal==1):
print("\t\t\tText String: "+textString)
elif(idBits==b'\x11\x00'): #End Of Element
if(self.debugToTerminal==1):
print("\t\t\tEndText")
break;
return thisText
def readNode(self):
if(self.debugToTerminal==1):
print("\t\t\tBeginNode")
##reads in a node type structure = an electrical net
thisNode = GdsNode()
while 1:
record = self.readNextRecord()
idBits = record[0:2]
if(idBits==b'\x26\x01'): #ELFLAGS
elementFlags = struct.unpack(">h",record[2:4])[0]
thisNode.elementFlags=elementFlags
if(self.debugToTerminal==1):
print("\t\tElement Flags: "+str(elementFlags))
elif(idBits==b'\x2F\x03'): #PLEX
plex = struct.unpack(">i",record[2:6])[0]
thisNode.plex=plex
if(self.debugToTerminal==1):
print("\t\tPLEX: "+str(plex))
elif(idBits==b'\x0D\x02'): #Layer
drawingLayer = struct.unpack(">h",record[2:4])[0]
thisNode.drawingLayer=drawingLayer
if drawingLayer not in self.layoutObject.layerNumbersInUse:
self.layoutObject.layerNumbersInUse += [drawingLayer]
if(self.debugToTerminal==1):
print("\t\tDrawing Layer: "+str(drawingLayer))
elif(idBits==b'\x2A\x02'): #Node Type
nodeType = struct.unpack(">h",record[2:4])[0]
thisNode.nodeType=nodeType
if(self.debugToTerminal==1):
print("\t\tNode Type: "+str(nodeType))
elif(idBits==b'\x10\x03'): #XY Data Points
numDataPoints = len(record)-2 #packed as XY coordinates 4 bytes each
thisNode.coordinates=[]
for index in range(2,numDataPoints+2,8): #incorporate the 2 byte offset
x=struct.unpack(">i",record[index:index+4])[0]
y=struct.unpack(">i",record[index+4:index+8])[0]
thisNode.coordinates+=[(x,y)]
if(self.debugToTerminal==1):
print("\t\t\tXY Point: "+str(x)+","+str(y))
elif(idBits==b'\x11\x00'): #End Of Element
if(self.debugToTerminal==1):
print("\t\t\tEndNode")
break;
return thisNode
def readBox(self):
if(self.debugToTerminal==1):
print("\t\t\tBeginBox")
##reads in a gds BOX structure
thisBox = GdsBox()
while 1:
record = self.readNextRecord()
idBits = record[0:2]
if(idBits==b'\x26\x01'): #ELFLAGS
elementFlags = struct.unpack(">h",record[2:4])
thisBox.elementFlags=elementFlags
if(self.debugToTerminal==1):
print("\t\tElement Flags: "+str(elementFlags))
elif(idBits==b'\x2F\x03'): #PLEX
plex = struct.unpack(">i",record[2:6])[0]
thisBox.plex=plex
if(self.debugToTerminal==1):
print("\t\tPLEX: "+str(plex))
elif(idBits==b'\x0D\x02'): #Layer
drawingLayer = struct.unpack(">h",record[2:4])[0]
thisBox.drawingLayer=drawingLayer
if drawingLayer not in self.layoutObject.layerNumbersInUse:
self.layoutObject.layerNumbersInUse += [drawingLayer]
if(self.debugToTerminal==1):
print("\t\tDrawing Layer: "+str(drawingLayer))
elif(idBits==b'\x16\x02'): #Purpose TEXTYPE
purposeLayer = struct.unpack(">h",record[2:4])[0]
thisBox.purposeLayer=purposeLayer
if(self.debugToTerminal==1):
print("\t\tPurpose Layer: "+str(purposeLayer))
elif(idBits==b'\x2D\x00'): #Box
boxValue = struct.unpack(">h",record[2:4])[0]
thisBox.boxValue=boxValue
if(self.debugToTerminal==1):
print("\t\tBox Value: "+str(boxValue))
elif(idBits==b'\x10\x03'): #XY Data Points that form a closed box
numDataPoints = len(record)-2 #packed as XY coordinates 4 bytes each
thisBox.coordinates=[]
for index in range(2,numDataPoints+2,8): #incorporate the 2 byte offset
x=struct.unpack(">i",record[index:index+4])[0]
y=struct.unpack(">i",record[index+4:index+8])[0]
thisBox.coordinates+=[(x,y)]
if(self.debugToTerminal==1):
print("\t\t\tXY Point: "+str(x)+","+str(y))
elif(idBits==b'\x11\x00'): #End Of Element
if(self.debugToTerminal==1):
print("\t\t\tEndBox")
break;
return thisBox
def readNextStructure(self):
thisStructure = GdsStructure()
record = self.readNextRecord()
idBits = record[0:2]
# Begin structure
if(idBits==b'\x05\x02' and len(record)==26):
createYear = struct.unpack(">h",record[2:4])[0]
createMonth = struct.unpack(">h",record[4:6])[0]
createDay = struct.unpack(">h",record[6:8])[0]
createHour = struct.unpack(">h",record[8:10])[0]
createMinute = struct.unpack(">h",record[10:12])[0]
createSecond = struct.unpack(">h",record[12:14])[0]
modYear = struct.unpack(">h",record[14:16])[0]
modMonth = struct.unpack(">h",record[16:18])[0]
modDay = struct.unpack(">h",record[18:20])[0]
modHour = struct.unpack(">h",record[20:22])[0]
modMinute = struct.unpack(">h",record[22:24])[0]
modSecond = struct.unpack(">h",record[24:26])[0]
thisStructure.createDate=(createYear,createMonth,createDay,createHour,createMinute,createSecond)
thisStructure.modDate=(modYear,modMonth,modDay,modHour,modMinute,modSecond)
if(self.debugToTerminal==1):
print("Date Created:"+str(createYear)+","+str(createMonth)+","+str(createDay)+\
","+str(createHour)+","+str(createMinute)+","+str(createSecond))
print("Date Modified:"+str(modYear)+","+str(modMonth)+","+str(modDay)+","+str(modHour)+","+str(modMinute)+","+str(modSecond))
else:
#means we have hit the last structure, so return the record
#to whoever called us to do something with it
return record
while 1:
record = self.readNextRecord()
idBits = record[0:2]
if idBits==b'\x07\x00': break; #we've reached the end of the structure
elif(idBits==b'\x06\x06'):
structName = self.stripNonASCII(record[2::])
thisStructure.name = structName
if(self.debugToTerminal==1):
print("\tStructure Name: "+structName)
elif(idBits==b'\x08\x00'):
thisStructure.boundaries+=[self.readBoundary()]
elif(idBits==b'\x09\x00'):
thisStructure.paths+=[self.readPath()]
elif(idBits==b'\x0A\x00'):
thisStructure.srefs+=[self.readSref()]
elif(idBits==b'\x0B\x00'):
thisStructure.arefs+=[self.readAref()]
elif(idBits==b'\x0C\x00'):
thisStructure.texts+=[self.readText()]
elif(idBits==b'\x15\x00'):
thisStructure.nodes+=[self.readNode()]
elif(idBits==b'\x2E\x02'):
thisStructure.boxes+=[self.readBox()]
if(self.debugToTerminal==1):
print("\tEnd of Structure.")
self.layoutObject.structures[structName]=thisStructure #add this structure to the layout object
return 1
def readGds2(self):
if(self.readHeader()): #did the header read ok?
record = self.readNextStructure()
while(record == 1):
record = self.readNextStructure()
#now we have fallen out of the while, which means we are out of structures
#so test for end of library
if(len(record)>1):
idBits = record[0:2]
if idBits==b'\x04\x00': #we've reached the end of the library
if(self.debugToTerminal==1):
print("End of GDS Library.")
else:
print("There was an error reading the structure list.")
else:
print("There was an error parsing the GDS header. Aborting...")
def loadFromFile(self, fileName):
self.fileHandle = open(fileName,"rb")
self.readGds2()
self.fileHandle.close()
self.layoutObject.initialize()
##############################################
def findStruct(self,fileName,findStructName):
#print("find struct")
self.fileHandle = open(fileName,"rb")
self.debugToTerminal=0
if(self.readHeader()): #did the header read ok?
record = self.findStruct_readNextStruct(findStructName)
while(record == 1):
record = self.findStruct_readNextStruct(findStructName)
#now we have fallen out of the while, which means we are out of structures
#so test for end of library
else:
print("There was an error parsing the GDS header. Aborting...")
self.fileHandle.close()
#print("End the search of",findStructName)
#self.layoutObject.initialize()
return record
def findStruct_readNextStruct(self,findStructName):
self.debugToTerminal=0
thisStructure = GdsStructure()
record = self.readNextRecord()
idBits = record[0:2]
if(idBits==('\x05','\x02') and len(record)==26):
createYear = struct.unpack(">h",record[2]+record[3])[0]
createMonth = struct.unpack(">h",record[4]+record[5])[0]
createDay = struct.unpack(">h",record[6]+record[7])[0]
createHour = struct.unpack(">h",record[8]+record[9])[0]
createMinute = struct.unpack(">h",record[10]+record[11])[0]
createSecond = struct.unpack(">h",record[12]+record[13])[0]
modYear = struct.unpack(">h",record[14]+record[15])[0]
modMonth = struct.unpack(">h",record[16]+record[17])[0]
modDay = struct.unpack(">h",record[18]+record[19])[0]
modHour = struct.unpack(">h",record[20]+record[21])[0]
modMinute = struct.unpack(">h",record[22]+record[23])[0]
modSecond = struct.unpack(">h",record[24]+record[25])[0]
thisStructure.createDate=(createYear,createMonth,createDay,createHour,createMinute,createSecond)
thisStructure.modDate=(modYear,modMonth,modDay,modHour,modMinute,modSecond)
else:
#means we have hit the last structure, so return the record
#to whoever called us to do something with it
return record
wantedStruct=0
while 1:
record = self.readNextRecord()
idBits = record[0:2]
if idBits==('\x07','\x00'): break; #we've reached the end of the structure
elif(idBits==('\x06','\x06')):
structName = self.stripNonASCII(record[2::]) #(record[2:1] + record[1::]).rstrip()
thisStructure.name = structName
if(findStructName==thisStructure.name):
wantedStruct=1
if(self.debugToTerminal==1):
print("\tStructure Name: "+structName)
elif(idBits==('\x08','\x00')):
thisStructure.boundaries+=[self.readBoundary()]
elif(idBits==('\x09','\x00')):
thisStructure.paths+=[self.readPath()]
elif(idBits==('\x0A','\x00')):
thisStructure.srefs+=[self.readSref()]
elif(idBits==('\x0B','\x00')):
thisStructure.arefs+=[self.readAref()]
elif(idBits==('\x0C','\x00')):
thisStructure.texts+=[self.readText()]
elif(idBits==('\x15','\x00')):
thisStructure.nodes+=[self.readNode()]
elif(idBits==('\x2E','\x02')):
thisStructure.boxes+=[self.readBox()]
if(self.debugToTerminal==1):
print("\tEnd of Structure.")
self.layoutObject.structures[structName]=thisStructure #add this structure to the layout object
if(wantedStruct == 0):
return 1
else:
#print("\tDone with collectting bound. Return")
return [0,thisStructure.boundaries]
def findLabel(self,fileName,findLabelName):
#print("find Label")
self.fileHandle = open(fileName,"rb")
self.debugToTerminal=0
if(self.readHeader()): #did the header read ok?
record = self.findLabel_readNextStruct(findLabelName)
while(record == 1):
record = self.findLabel_readNextStruct(findLabelName)
#now we have fallen out of the while, which means we are out of structures
#so test for end of library
else:
print("There was an error parsing the GDS header. Aborting...")
self.fileHandle.close()
#print("End the search of",findStructName)
#self.layoutObject.initialize()
return record
def findLabel_readNextStruct(self,findLabelName):
self.debugToTerminal=0
thisStructure = GdsStructure()
record = self.readNextRecord()
idBits = record[0:2]
if(idBits==('\x05','\x02') and len(record)==26):
createYear = struct.unpack(">h",record[2]+record[3])[0]
createMonth = struct.unpack(">h",record[4]+record[5])[0]
createDay = struct.unpack(">h",record[6]+record[7])[0]
createHour = struct.unpack(">h",record[8]+record[9])[0]
createMinute = struct.unpack(">h",record[10]+record[11])[0]
createSecond = struct.unpack(">h",record[12]+record[13])[0]
modYear = struct.unpack(">h",record[14]+record[15])[0]
modMonth = struct.unpack(">h",record[16]+record[17])[0]
modDay = struct.unpack(">h",record[18]+record[19])[0]
modHour = struct.unpack(">h",record[20]+record[21])[0]
modMinute = struct.unpack(">h",record[22]+record[23])[0]
modSecond = struct.unpack(">h",record[24]+record[25])[0]
thisStructure.createDate=(createYear,createMonth,createDay,createHour,createMinute,createSecond)
thisStructure.modDate=(modYear,modMonth,modDay,modHour,modMinute,modSecond)
else:
#means we have hit the last structure, so return the record
#to whoever called us to do something with it
return record
wantedLabel=0
wantedtexts=[GdsText()]
while 1:
record = self.readNextRecord()
idBits = record[0:2]
if idBits==('\x07','\x00'): break; #we've reached the end of the structure
elif(idBits==('\x06','\x06')):
structName = self.stripNonASCII(record[2::]) #(record[2:1] + record[1::]).rstrip()
thisStructure.name = structName
if(self.debugToTerminal==1):
print("\tStructure Name: "+structName)
elif(idBits==('\x08','\x00')):
thisStructure.boundaries+=[self.readBoundary()]
elif(idBits==('\x09','\x00')):
thisStructure.paths+=[self.readPath()]
elif(idBits==('\x0A','\x00')):
thisStructure.srefs+=[self.readSref()]
elif(idBits==('\x0B','\x00')):
thisStructure.arefs+=[self.readAref()]
elif(idBits==('\x0C','\x00')):
label=self.readText()
#Be careful: label.textString contains one space string in it. Delete that one before use it
if( findLabelName == label.textString[0:(len(label.textString)-1)] ):
wantedLabel=1
wantedtexts+=[label]
thisStructure.texts+=[label]
if(self.debugToTerminal == 1):
print(label.textString[0:(len(label.textString)-1)],findLabelName,( findLabelName == label.textString[0:(len(label.textString)-1)] ))
elif(idBits==('\x15','\x00')):
thisStructure.nodes+=[self.readNode()]
elif(idBits==('\x2E','\x02')):
thisStructure.boxes+=[self.readBox()]
if(self.debugToTerminal==1):
print("\tEnd of Structure.")
self.layoutObject.structures[structName]=thisStructure #add this structure to the layout object
if(wantedLabel == 0):
return 1
else:
#print("\tDone with collectting bound. Return")
return [0,wantedtexts]