#!/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" def stripNonASCII(self,string): #''' 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 sName = self.stripNonASCII(record[2::]) 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')): structName = self.stripNonASCII(record[2::]) #(record[2:1] + record[1::]).rstrip() # print ''.[x for x in structName if ord(x) < 128] # stripped = (c for c in structName if 0 < ord(c) < 127) # structName = "".join(stripped) # print self.stripNonASCII(structName) ##FIXME: trimming by Tom g. ##could be an issue here with string trimming! 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')): structName = self.stripNonASCII(record[2::]) #(record[2:1] + record[1::]).rstrip() # print ''.[x for x in structName if ord(x) < 128] # stripped = (c for c in structName if 0 < ord(c) < 127) # structName = "".join(stripped) # print self.stripNonASCII(structName) ##FIXME: trimming by Tom g. ##could be an issue here with string trimming! 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')): structName = self.stripNonASCII(record[2::]) #(record[2:1] + record[1::]).rstrip() # print ''.[x for x in structName if ord(x) < 128] # stripped = (c for c in structName if 0 < ord(c) < 127) # structName = "".join(stripped) # print self.stripNonASCIIx(structName) ##FIXME: trimming by Tom g. ##could be an issue here with string trimming! 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]