2016-11-08 18:57:35 +01:00
|
|
|
#!/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,
|
|
|
|
|
print "\n"
|
|
|
|
|
|
2017-05-17 23:27:14 +02:00
|
|
|
def stripNonASCII(self,string):
|
2016-11-08 18:57:35 +01:00
|
|
|
#''' Returns the string without non ASCII characters'''
|
|
|
|
|
stripped = (c for c in string if 0 < ord(c) < 127)
|
|
|
|
|
return "".join(stripped)
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
recordLength = struct.unpack(">h",recordLengthAscii) #gives us a tuple with a short int inside
|
|
|
|
|
offlist = list(recordLength) #change tuple to a list
|
|
|
|
|
offset += float(offlist[0]) #count offset
|
|
|
|
|
#print float(offlist[0])
|
|
|
|
|
#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],record[1])
|
|
|
|
|
if(idBits==('\x00','\x02') and len(record)==4):
|
|
|
|
|
gdsVersion = struct.unpack(">h",record[2]+record[3])[0]
|
|
|
|
|
self.layoutObject.info["gdsVersion"]=gdsVersion
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "GDS II Version "+str(gdsVersion)
|
|
|
|
|
else:
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
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],record[1])
|
|
|
|
|
## Modified Date
|
|
|
|
|
if(idBits==('\x01','\x02') and len(record)==26):
|
|
|
|
|
modYear = struct.unpack(">h",record[2]+record[3])[0]
|
|
|
|
|
modMonth = struct.unpack(">h",record[4]+record[5])[0]
|
|
|
|
|
modDay = struct.unpack(">h",record[6]+record[7])[0]
|
|
|
|
|
modHour = struct.unpack(">h",record[8]+record[9])[0]
|
|
|
|
|
modMinute = struct.unpack(">h",record[10]+record[11])[0]
|
|
|
|
|
modSecond = struct.unpack(">h",record[12]+record[13])[0]
|
|
|
|
|
lastAccessYear = struct.unpack(">h",record[14]+record[15])[0]
|
|
|
|
|
lastAccessMonth = struct.unpack(">h",record[16]+record[17])[0]
|
|
|
|
|
lastAccessDay = struct.unpack(">h",record[18]+record[19])[0]
|
|
|
|
|
lastAccessHour = struct.unpack(">h",record[20]+record[21])[0]
|
|
|
|
|
lastAccessMinute = struct.unpack(">h",record[22]+record[23])[0]
|
|
|
|
|
lastAccessSecond = struct.unpack(">h",record[24]+record[25])[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==('\x02','\x06')):
|
|
|
|
|
libraryName = record[2::]
|
|
|
|
|
self.layoutObject.info["libraryName"]=libraryName
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "Library: "+libraryName
|
|
|
|
|
## reference libraries
|
|
|
|
|
elif(idBits==('\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==('\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==('\x23','\x06')):
|
|
|
|
|
attributeTable = record[2:45]
|
|
|
|
|
self.layoutObject.info["attributeTable"]=attributeTable
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "Attributes:"+attributeTable
|
|
|
|
|
elif(idBits==('\x22','\x02')):
|
|
|
|
|
generations = struct.unpack(">h",record[2]+record[3])
|
|
|
|
|
self.layoutObject.info["generations"]=generations
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "Generations:"+generations
|
|
|
|
|
elif(idBits==('\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==('\x37','\x06')):
|
|
|
|
|
mask = record[2::]
|
|
|
|
|
self.layoutObject.info["mask"] = mask
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "Mask: "+mask
|
|
|
|
|
elif(idBits==('\x03','\x05')): #this is also wrong b/c python doesn't natively have an 8 byte float
|
|
|
|
|
userUnits=self.ieeeDoubleFromIbmData(record[2]+record[3]+record[4]+record[5]+record[6]+record[7]+record[8]+record[9])
|
|
|
|
|
dbUnits=self.ieeeDoubleFromIbmData
|
|
|
|
|
self.layoutObject.info["units"] = (userUnits,dbUnits)
|
|
|
|
|
|
|
|
|
|
#print "userUnits %s"%((record[2]+record[3]+record[4]+record[5]+record[6]+record[7]+record[8]+record[9])).encode("hex")
|
|
|
|
|
#print "dbUnits %s"%(record[10]+record[11]+record[12]+record[13]+record[14]+record[15]+record[16]+record[17]).encode("hex")
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
thisBoundary=GdsBoundary()
|
|
|
|
|
while 1:
|
|
|
|
|
record = self.readNextRecord()
|
|
|
|
|
idBits = (record[0],record[1])
|
|
|
|
|
if(idBits==('\x26','\x01')): #ELFLAGS
|
|
|
|
|
elementFlags = struct.unpack(">h",record[2]+record[3])[0]
|
|
|
|
|
thisBoundary.elementFlags=elementFlags
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\tElement Flags: "+str(elementFlags)
|
|
|
|
|
elif(idBits==('\x2F','\x03')): #PLEX
|
|
|
|
|
plex = struct.unpack(">i",record[2]+record[3]+record[4]+record[5])[0]
|
|
|
|
|
thisBoundary.plex=plex
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\tPLEX: "+str(plex)
|
|
|
|
|
elif(idBits==('\x0D','\x02')): #Layer
|
|
|
|
|
drawingLayer = struct.unpack(">h",record[2]+record[3])[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==('\x16','\x02')): #Purpose
|
|
|
|
|
purposeLayer = struct.unpack(">h",record[2]+record[3])[0]
|
|
|
|
|
thisBoundary.purposeLayer=purposeLayer
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\tPurpose Layer: "+str(purposeLayer)
|
|
|
|
|
elif(idBits==('\x0E','\x02')): #DataType
|
|
|
|
|
dataType = struct.unpack(">h",record[2]+record[3])[0]
|
|
|
|
|
thisBoundary.dataType=dataType
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\t\tData Type: "+str(dataType)
|
|
|
|
|
elif(idBits==('\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]+record[index+1]+record[index+2]+record[index+3])[0]
|
|
|
|
|
y=struct.unpack(">i",record[index+4]+record[index+5]+record[index+6]+record[index+7])[0]
|
|
|
|
|
thisBoundary.coordinates+=[(x,y)]
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\t\tXY Point: "+str(x)+","+str(y)
|
|
|
|
|
elif(idBits==('\x11','\x00')): #End Of Element
|
|
|
|
|
break;
|
|
|
|
|
return thisBoundary
|
|
|
|
|
|
|
|
|
|
def readPath(self): #reads in a path structure
|
|
|
|
|
thisPath=GdsPath()
|
|
|
|
|
while 1:
|
|
|
|
|
record = self.readNextRecord()
|
|
|
|
|
idBits = (record[0],record[1])
|
|
|
|
|
if(idBits==('\x26','\x01')): #ELFLAGS
|
|
|
|
|
elementFlags = struct.unpack(">h",record[2]+record[3])[0]
|
|
|
|
|
thisPath.elementFlags=elementFlags
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\tElement Flags: "+str(elementFlags)
|
|
|
|
|
elif(idBits==('\x2F','\x03')): #PLEX
|
|
|
|
|
plex = struct.unpack(">i",record[2]+record[3]+record[4]+record[5])[0]
|
|
|
|
|
thisPath.plex=plex
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\tPLEX: "+str(plex)
|
|
|
|
|
elif(idBits==('\x0D','\x02')): #Layer
|
|
|
|
|
drawingLayer = struct.unpack(">h",record[2]+record[3])[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==('\x16','\x02')): #Purpose
|
|
|
|
|
purposeLayer = struct.unpack(">h",record[2]+record[3])[0]
|
|
|
|
|
thisPath.purposeLayer=purposeLayer
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\tPurpose Layer: "+str(purposeLayer)
|
|
|
|
|
elif(idBits==('\x21','\x02')): #Path type
|
|
|
|
|
pathType = struct.unpack(">h",record[2]+record[3])[0]
|
|
|
|
|
thisPath.pathType=pathType
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\t\tPath Type: "+str(pathType)
|
|
|
|
|
elif(idBits==('\x0F','\x03')): #Path width
|
|
|
|
|
pathWidth = struct.unpack(">i",record[2]+record[3]+record[4]+record[5])[0]
|
|
|
|
|
thisPath.pathWidth=pathWidth
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\t\tPath Width: "+str(pathWidth)
|
|
|
|
|
elif(idBits==('\x10','\x03')): #XY Data Points
|
|
|
|
|
numDataPoints = len(record)-2 #packed as 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]+record[index+1]+record[index+2]+record[index+3])[0]
|
|
|
|
|
y=struct.unpack(">i",record[index+4]+record[index+5]+record[index+6]+record[index+7])[0]
|
|
|
|
|
thisPath.coordinates+=[(x,y)]
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\t\tXY Point: "+str(x)+","+str(y)
|
|
|
|
|
elif(idBits==('\x11','\x00')): #End Of Element
|
|
|
|
|
break;
|
|
|
|
|
return thisPath
|
|
|
|
|
|
|
|
|
|
def readSref(self): #reads in a reference to another structure
|
|
|
|
|
thisSref=GdsSref()
|
|
|
|
|
while 1:
|
|
|
|
|
record = self.readNextRecord()
|
|
|
|
|
idBits = (record[0],record[1])
|
|
|
|
|
if(idBits==('\x26','\x01')): #ELFLAGS
|
|
|
|
|
elementFlags = struct.unpack(">h",record[2]+record[3])[0]
|
|
|
|
|
thisSref.elementFlags=elementFlags
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\tElement Flags: "+str(elementFlags)
|
|
|
|
|
elif(idBits==('\x2F','\x03')): #PLEX
|
|
|
|
|
plex = struct.unpack(">i",record[2]+record[3]+record[4]+record[5])[0]
|
|
|
|
|
thisSref.plex=plex
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\tPLEX: "+str(plex)
|
|
|
|
|
elif(idBits==('\x12','\x06')): #Reference Name
|
2017-05-17 23:27:14 +02:00
|
|
|
sName = self.stripNonASCII(record[2::])
|
2016-11-08 18:57:35 +01:00
|
|
|
thisSref.sName=sName.rstrip()
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\tReference Name:"+sName
|
|
|
|
|
elif(idBits==('\x1A','\x01')): #Transformation
|
|
|
|
|
transFlags = struct.unpack(">H",record[2]+record[3])[0]
|
|
|
|
|
mirrorFlag = bool(transFlags&0x8000) ##these flags are a bit sketchy
|
|
|
|
|
rotateFlag = bool(transFlags&0x0002)
|
|
|
|
|
magnifyFlag = bool(transFlags&0x0004)
|
|
|
|
|
thisSref.transFlags=(mirrorFlag,rotateFlag,magnifyFlag)
|
|
|
|
|
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==('\x1B','\x05')): #Magnify
|
|
|
|
|
magFactor=self.ieeeDoubleFromIbmData(record[2]+record[3]+record[4]+record[5]+record[6]+record[7]+record[8]+record[9])
|
|
|
|
|
thisSref.magFactor=magFactor
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\t\tMagnification:"+str(magFactor)
|
|
|
|
|
elif(idBits==('\x1C','\x05')): #Rotate Angle
|
|
|
|
|
rotateAngle=self.ieeeDoubleFromIbmData(record[2]+record[3]+record[4]+record[5]+record[6]+record[7]+record[8]+record[9])
|
|
|
|
|
thisSref.rotateAngle=rotateAngle
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\t\tRotate Angle (CCW):"+str(rotateAngle)
|
|
|
|
|
elif(idBits==('\x10','\x03')): #XY Data Points
|
|
|
|
|
index=2
|
|
|
|
|
x=struct.unpack(">i",record[index]+record[index+1]+record[index+2]+record[index+3])[0]
|
|
|
|
|
y=struct.unpack(">i",record[index+4]+record[index+5]+record[index+6]+record[index+7])[0]
|
|
|
|
|
thisSref.coordinates=(x,y)
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\t\tXY Point: "+str(x)+","+str(y)
|
|
|
|
|
elif(idBits==('\x11','\x00')): #End Of Element
|
|
|
|
|
break;
|
|
|
|
|
return thisSref
|
|
|
|
|
|
|
|
|
|
def readAref(self): #an array of references
|
|
|
|
|
thisAref = GdsAref()
|
|
|
|
|
while 1:
|
|
|
|
|
record = self.readNextRecord()
|
|
|
|
|
idBits = (record[0],record[1])
|
|
|
|
|
if(idBits==('\x26','\x01')): #ELFLAGS
|
|
|
|
|
elementFlags = struct.unpack(">h",record[2]+record[3])[0]
|
|
|
|
|
thisAref.elementFlags=elementFlags
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\tElement Flags: "+str(elementFlags)
|
|
|
|
|
elif(idBits==('\x2F','\x03')): #PLEX
|
|
|
|
|
plex = struct.unpack(">i",record[2]+record[3]+record[4]+record[5])[0]
|
|
|
|
|
thisAref.plex=plex
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\tPLEX: "+str(plex)
|
|
|
|
|
elif(idBits==('\x12','\x06')): #Reference Name
|
|
|
|
|
aName = record[2::]
|
|
|
|
|
thisAref.aName=aName
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\tReference Name:"+aName
|
|
|
|
|
elif(idBits==('\x1A','\x01')): #Transformation
|
|
|
|
|
transFlags = struct.unpack(">H",record[2]+record[3])[0]
|
|
|
|
|
mirrorFlag = bool(transFlags&0x8000) ##these flags are a bit sketchy
|
|
|
|
|
rotateFlag = bool(transFlags&0x0002)
|
|
|
|
|
magnifyFlag = bool(transFlags&0x0004)
|
|
|
|
|
thisAref.transFlags=(mirrorFlag,rotateFlag,magnifyFlag)
|
|
|
|
|
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==('\x1B','\x05')): #Magnify
|
|
|
|
|
magFactor=self.ieeeDoubleFromIbmData(record[2]+record[3]+record[4]+record[5]+record[6]+record[7]+record[8]+record[9])
|
|
|
|
|
thisAref.magFactor=magFactor
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\t\tMagnification:"+str(magFactor)
|
|
|
|
|
elif(idBits==('\x1C','\x05')): #Rotate Angle
|
|
|
|
|
rotateAngle=self.ieeeDoubleFromIbmData(record[2]+record[3]+record[4]+record[5]+record[6]+record[7]+record[8]+record[9])
|
|
|
|
|
thisAref.rotateAngle=rotateAngle
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\t\tRotate Angle (CCW):"+str(rotateAngle)
|
|
|
|
|
elif(idBits==('\x10','\x03')): #XY Data Points
|
|
|
|
|
index=2
|
|
|
|
|
topLeftX=struct.unpack(">i",record[index]+record[index+1]+record[index+2]+record[index+3])[0]
|
|
|
|
|
topLeftY=struct.unpack(">i",record[index+4]+record[index+5]+record[index+6]+record[index+7])[0]
|
|
|
|
|
rightMostX=struct.unpack(">i",record[index+8]+record[index+9]+record[index+10]+record[index+11])[0]
|
|
|
|
|
bottomMostY=struct.unpack(">i",record[index+12]+record[index+13]+record[index+14]+record[index+15])[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==('\x11','\x00')): #End Of Element
|
|
|
|
|
break;
|
|
|
|
|
return thisAref
|
|
|
|
|
|
|
|
|
|
def readText(self):
|
|
|
|
|
##reads in a text structure
|
|
|
|
|
thisText=GdsText()
|
|
|
|
|
while 1:
|
|
|
|
|
record = self.readNextRecord()
|
|
|
|
|
idBits = (record[0],record[1])
|
|
|
|
|
if(idBits==('\x26','\x01')): #ELFLAGS
|
|
|
|
|
elementFlags = struct.unpack(">h",record[2]+record[3])[0]
|
|
|
|
|
thisText.elementFlags=elementFlags
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\tElement Flags: "+str(elementFlags)
|
|
|
|
|
elif(idBits==('\x2F','\x03')): #PLEX
|
|
|
|
|
plex = struct.unpack(">i",record[2]+record[3]+record[4]+record[5])[0]
|
|
|
|
|
thisText.plex=plex
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\tPLEX: "+str(plex)
|
|
|
|
|
elif(idBits==('\x0D','\x02')): #Layer
|
|
|
|
|
drawingLayer = struct.unpack(">h",record[2]+record[3])[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==('\x16','\x02')): #Purpose
|
|
|
|
|
purposeLayer = struct.unpack(">h",record[2]+record[3])[0]
|
|
|
|
|
thisText.purposeLayer=purposeLayer
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\tPurpose Layer: "+str(purposeLayer)
|
|
|
|
|
elif(idBits==('\x1A','\x01')): #Transformation
|
|
|
|
|
transFlags = struct.unpack(">H",record[2]+record[3])[0]
|
|
|
|
|
mirrorFlag = bool(transFlags&0x8000) ##these flags are a bit sketchy
|
|
|
|
|
rotateFlag = bool(transFlags&0x0002)
|
|
|
|
|
magnifyFlag = bool(transFlags&0x0004)
|
|
|
|
|
thisText.transFlags=(mirrorFlag,rotateFlag,magnifyFlag)
|
|
|
|
|
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==('\x1B','\x05')): #Magnify
|
|
|
|
|
magFactor=self.ieeeDoubleFromIbmData(record[2]+record[3]+record[4]+record[5]+record[6]+record[7]+record[8]+record[9])
|
|
|
|
|
thisText.magFactor=magFactor
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\t\tMagnification:"+str(magFactor)
|
|
|
|
|
elif(idBits==('\x1C','\x05')): #Rotate Angle
|
|
|
|
|
rotateAngle=self.ieeeDoubleFromIbmData(record[2]+record[3]+record[4]+record[5]+record[6]+record[7]+record[8]+record[9])
|
|
|
|
|
thisText.rotateAngle=rotateAngle
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\t\tRotate Angle (CCW):"+str(rotateAngle)
|
|
|
|
|
elif(idBits==('\x21','\x02')): #Path type
|
|
|
|
|
pathType = struct.unpack(">h",record[2]+record[3])[0]
|
|
|
|
|
thisText.pathType=pathType
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\t\tPath Type: "+str(pathType)
|
|
|
|
|
elif(idBits==('\x0F','\x03')): #Path width
|
|
|
|
|
pathWidth = struct.unpack(">i",record[2]+record[3]+record[4]+record[5])[0]
|
|
|
|
|
thisText.pathWidth=pathWidth
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\t\tPath Width: "+str(pathWidth)
|
|
|
|
|
elif(idBits==('\x1A','\x01')): #Text Presentation
|
|
|
|
|
presentationFlags = struct.unpack(">H",record[2]+record[3])[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==('\x10','\x03')): #XY Data Points
|
|
|
|
|
index=2
|
|
|
|
|
x=struct.unpack(">i",record[index]+record[index+1]+record[index+2]+record[index+3])[0]
|
|
|
|
|
y=struct.unpack(">i",record[index+4]+record[index+5]+record[index+6]+record[index+7])[0]
|
|
|
|
|
thisText.coordinates=[(x,y)]
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\t\tXY Point: "+str(x)+","+str(y)
|
|
|
|
|
elif(idBits==('\x19','\x06')): #Text String - also the last record in this element
|
|
|
|
|
textString = record[2::]
|
|
|
|
|
thisText.textString=textString
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\t\tText String: "+textString
|
|
|
|
|
elif(idBits==('\x11','\x00')): #End Of Element
|
|
|
|
|
break;
|
|
|
|
|
return thisText
|
|
|
|
|
|
|
|
|
|
def readNode(self):
|
|
|
|
|
##reads in a node type structure = an electrical net
|
|
|
|
|
thisNode = GdsNode()
|
|
|
|
|
while 1:
|
|
|
|
|
record = self.readNextRecord()
|
|
|
|
|
idBits = (record[0],record[1])
|
|
|
|
|
if(idBits==('\x26','\x01')): #ELFLAGS
|
|
|
|
|
elementFlags = struct.unpack(">h",record[2]+record[3])[0]
|
|
|
|
|
thisNode.elementFlags=elementFlags
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\tElement Flags: "+str(elementFlags)
|
|
|
|
|
elif(idBits==('\x2F','\x03')): #PLEX
|
|
|
|
|
plex = struct.unpack(">i",record[2]+record[3]+record[4]+record[5])[0]
|
|
|
|
|
thisNode.plex=plex
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\tPLEX: "+str(plex)
|
|
|
|
|
elif(idBits==('\x0D','\x02')): #Layer
|
|
|
|
|
drawingLayer = struct.unpack(">h",record[2]+record[3])[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==('\x2A','\x02')): #Node Type
|
|
|
|
|
nodeType = struct.unpack(">h",record[2]+record[3])[0]
|
|
|
|
|
thisNode.nodeType=nodeType
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\tNode Type: "+str(nodeType)
|
|
|
|
|
elif(idBits==('\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]+record[index+1]+record[index+2]+record[index+3])[0]
|
|
|
|
|
y=struct.unpack(">i",record[index+4]+record[index+5]+record[index+6]+record[index+7])[0]
|
|
|
|
|
thisNode.coordinates+=[(x,y)]
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\t\tXY Point: "+str(x)+","+str(y)
|
|
|
|
|
elif(idBits==('\x11','\x00')): #End Of Element
|
|
|
|
|
break;
|
|
|
|
|
return thisNode
|
|
|
|
|
|
|
|
|
|
def readBox(self):
|
|
|
|
|
##reads in a gds BOX structure
|
|
|
|
|
thisBox = GdsBox()
|
|
|
|
|
while 1:
|
|
|
|
|
record = self.readNextRecord()
|
|
|
|
|
idBits = (record[0],record[1])
|
|
|
|
|
if(idBits==('\x26','\x01')): #ELFLAGS
|
|
|
|
|
elementFlags = struct.unpack(">h",record[2]+record[3])
|
|
|
|
|
thisBox.elementFlags=elementFlags
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\tElement Flags: "+str(elementFlags)
|
|
|
|
|
elif(idBits==('\x2F','\x03')): #PLEX
|
|
|
|
|
plex = struct.unpack(">i",record[2]+record[3]+record[4]+record[5])[0]
|
|
|
|
|
thisBox.plex=plex
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\tPLEX: "+str(plex)
|
|
|
|
|
elif(idBits==('\x0D','\x02')): #Layer
|
|
|
|
|
drawingLayer = struct.unpack(">h",record[2]+record[3])[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==('\x16','\x02')): #Purpose
|
|
|
|
|
purposeLayer = struct.unpack(">h",record[2]+record[3])[0]
|
|
|
|
|
thisBox.purposeLayer=purposeLayer
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\tPurpose Layer: "+str(purposeLayer)
|
|
|
|
|
elif(idBits==('\x2D','\x00')): #Box
|
|
|
|
|
boxValue = struct.unpack(">h",record[2]+record[3])[0]
|
|
|
|
|
thisBox.boxValue=boxValue
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\tBox Value: "+str(boxValue)
|
|
|
|
|
elif(idBits==('\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]+record[index+1]+record[index+2]+record[index+3])[0]
|
|
|
|
|
y=struct.unpack(">i",record[index+4]+record[index+5]+record[index+6]+record[index+7])[0]
|
|
|
|
|
thisBox.coordinates+=[(x,y)]
|
|
|
|
|
if(self.debugToTerminal==1):
|
|
|
|
|
print "\t\t\tXY Point: "+str(x)+","+str(y)
|
|
|
|
|
elif(idBits==('\x11','\x00')): #End Of Element
|
|
|
|
|
break;
|
|
|
|
|
return thisBox
|
|
|
|
|
|
|
|
|
|
def readNextStructure(self):
|
|
|
|
|
thisStructure = GdsStructure()
|
|
|
|
|
record = self.readNextRecord()
|
|
|
|
|
idBits = (record[0],record[1])
|
|
|
|
|
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
|
|
|
|
|
while 1:
|
|
|
|
|
record = self.readNextRecord()
|
|
|
|
|
idBits = (record[0],record[1])
|
|
|
|
|
if idBits==('\x07','\x00'): break; #we've reached the end of the structure
|
|
|
|
|
elif(idBits==('\x06','\x06')):
|
2017-05-17 23:27:14 +02:00
|
|
|
structName = self.stripNonASCII(record[2::]) #(record[2:1] + record[1::]).rstrip()
|
2016-11-08 18:57:35 +01:00
|
|
|
# print ''.[x for x in structName if ord(x) < 128]
|
|
|
|
|
# stripped = (c for c in structName if 0 < ord(c) < 127)
|
|
|
|
|
# structName = "".join(stripped)
|
2017-05-17 23:27:14 +02:00
|
|
|
# print self.stripNonASCII(structName) ##FIXME: trimming by Tom g. ##could be an issue here with string trimming!
|
2016-11-08 18:57:35 +01:00
|
|
|
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')):
|
|
|
|
|
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
|
|
|
|
|
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],record[1])
|
|
|
|
|
if idBits==('\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],record[1])
|
|
|
|
|
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],record[1])
|
|
|
|
|
if idBits==('\x07','\x00'): break; #we've reached the end of the structure
|
|
|
|
|
elif(idBits==('\x06','\x06')):
|
2017-05-17 23:27:14 +02:00
|
|
|
structName = self.stripNonASCII(record[2::]) #(record[2:1] + record[1::]).rstrip()
|
2016-11-08 18:57:35 +01:00
|
|
|
# print ''.[x for x in structName if ord(x) < 128]
|
|
|
|
|
# stripped = (c for c in structName if 0 < ord(c) < 127)
|
|
|
|
|
# structName = "".join(stripped)
|
2017-05-17 23:27:14 +02:00
|
|
|
# print self.stripNonASCII(structName) ##FIXME: trimming by Tom g. ##could be an issue here with string trimming!
|
2016-11-08 18:57:35 +01:00
|
|
|
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],record[1])
|
|
|
|
|
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],record[1])
|
|
|
|
|
if idBits==('\x07','\x00'): break; #we've reached the end of the structure
|
|
|
|
|
elif(idBits==('\x06','\x06')):
|
2017-05-17 23:27:14 +02:00
|
|
|
structName = self.stripNonASCII(record[2::]) #(record[2:1] + record[1::]).rstrip()
|
2016-11-08 18:57:35 +01:00
|
|
|
# print ''.[x for x in structName if ord(x) < 128]
|
|
|
|
|
# stripped = (c for c in structName if 0 < ord(c) < 127)
|
|
|
|
|
# structName = "".join(stripped)
|
2017-05-17 23:27:14 +02:00
|
|
|
# print self.stripNonASCIIx(structName) ##FIXME: trimming by Tom g. ##could be an issue here with string trimming!
|
2016-11-08 18:57:35 +01:00
|
|
|
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
|
|
|
|
|
# BINWU: Cleanup
|
|
|
|
|
#print"Find the Label",findLabelName
|
|
|
|
|
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)] )
|
|
|
|
|
# BINWU: Cleanup
|
|
|
|
|
#print thisStructure.name
|
|
|
|
|
#print thisStructure.texts
|
|
|
|
|
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]
|
|
|
|
|
|