fixed purposes for gdsMill

This commit is contained in:
Joey Kunzler 2020-02-15 15:00:30 -08:00
parent 87b5a48f9e
commit 125bcafb3e
3 changed files with 114 additions and 109 deletions

View File

@ -12,14 +12,14 @@ class Gds2reader:
self.fileHandle = None self.fileHandle = None
self.layoutObject = layoutObject self.layoutObject = layoutObject
self.debugToTerminal=debugToTerminal self.debugToTerminal=debugToTerminal
#do we dump debug data to the screen #do we dump debug data to the screen
def print64AsBinary(self,number): def print64AsBinary(self,number):
for index in range(0,64): for index in range(0,64):
print((number>>(63-index))&0x1,eol='') print((number>>(63-index))&0x1,eol='')
print("\n") print("\n")
def stripNonASCII(self,bytestring): def stripNonASCII(self,bytestring):
string = bytestring.decode('utf-8') string = bytestring.decode('utf-8')
return string return string
@ -29,20 +29,20 @@ class Gds2reader:
#(1)sign (7)exponent (56)mantissa #(1)sign (7)exponent (56)mantissa
#exponent is excess 64, mantissa has no implied 1 #exponent is excess 64, mantissa has no implied 1
#a normal IEEE double is like this: #a normal IEEE double is like this:
#(1)sign (11)exponent (52)mantissa #(1)sign (11)exponent (52)mantissa
data = struct.unpack('>q',ibmData)[0] data = struct.unpack('>q',ibmData)[0]
sign = (data >> 63)&0x01 sign = (data >> 63)&0x01
exponent = (data >> 56) & 0x7f exponent = (data >> 56) & 0x7f
mantissa = data<<8 #chop off sign and exponent mantissa = data<<8 #chop off sign and exponent
if mantissa == 0: if mantissa == 0:
newFloat = 0.0 newFloat = 0.0
else: else:
exponent = ((exponent-64)*4)+1023 #convert to double exponent exponent = ((exponent-64)*4)+1023 #convert to double exponent
#re normalize #re normalize
while mantissa & 0x8000000000000000 == 0: while mantissa & 0x8000000000000000 == 0:
mantissa<<=1 mantissa<<=1
exponent-=1 exponent-=1
mantissa<<=1 #remove the assumed high bit mantissa<<=1 #remove the assumed high bit
exponent-=1 exponent-=1
#check for underflow error -- should handle these properly! #check for underflow error -- should handle these properly!
@ -56,7 +56,7 @@ class Gds2reader:
#convert back to double #convert back to double
newFloat = struct.unpack('>d',asciiDouble)[0] newFloat = struct.unpack('>d',asciiDouble)[0]
return newFloat return newFloat
def ieeeFloatCheck(self,aFloat): def ieeeFloatCheck(self,aFloat):
asciiDouble = struct.pack('>d',aFloat) asciiDouble = struct.pack('>d',aFloat)
data = struct.unpack('>q',asciiDouble)[0] data = struct.unpack('>q',asciiDouble)[0]
@ -70,12 +70,12 @@ class Gds2reader:
asciiDouble = struct.pack('>q',(sign<<63)|(exponent+1023<<52)|(mantissa>>12)) asciiDouble = struct.pack('>q',(sign<<63)|(exponent+1023<<52)|(mantissa>>12))
newFloat = struct.unpack('>d',asciiDouble)[0] newFloat = struct.unpack('>d',asciiDouble)[0]
print("Check:"+str(newFloat)) print("Check:"+str(newFloat))
def readNextRecord(self): def readNextRecord(self):
global offset global offset
recordLengthAscii = self.fileHandle.read(2) #first 2 bytes tell us the length of the record recordLengthAscii = self.fileHandle.read(2) #first 2 bytes tell us the length of the record
if len(recordLengthAscii)==0: if len(recordLengthAscii)==0:
return return
recordLength = struct.unpack(">h",recordLengthAscii) #gives us a tuple with a short int inside recordLength = struct.unpack(">h",recordLengthAscii) #gives us a tuple with a short int inside
offset_int = int(recordLength[0]) # extract length offset_int = int(recordLength[0]) # extract length
offset += offset_int # count offset offset += offset_int # count offset
@ -96,20 +96,20 @@ class Gds2reader:
else: else:
print("Invalid GDSII Header") print("Invalid GDSII Header")
return -1 return -1
#read records until we hit the UNITS section... this is the last part of the header #read records until we hit the UNITS section... this is the last part of the header
while 1: while 1:
record = self.readNextRecord() record = self.readNextRecord()
idBits = record[0:2] idBits = record[0:2]
## Modified Date ## Modified Date
if idBits==b'\x01\x02' and len(record)==26: if idBits==b'\x01\x02' and len(record)==26:
modYear = struct.unpack(">h",record[2:4])[0] modYear = struct.unpack(">h",record[2:4])[0]
modMonth = struct.unpack(">h",record[4:6])[0] modMonth = struct.unpack(">h",record[4:6])[0]
modDay = struct.unpack(">h",record[6:8])[0] modDay = struct.unpack(">h",record[6:8])[0]
modHour = struct.unpack(">h",record[8:10])[0] modHour = struct.unpack(">h",record[8:10])[0]
modMinute = struct.unpack(">h",record[10:12])[0] modMinute = struct.unpack(">h",record[10:12])[0]
modSecond = struct.unpack(">h",record[12:14])[0] modSecond = struct.unpack(">h",record[12:14])[0]
lastAccessYear = struct.unpack(">h",record[14:16])[0] lastAccessYear = struct.unpack(">h",record[14:16])[0]
lastAccessMonth = struct.unpack(">h",record[16:18])[0] lastAccessMonth = struct.unpack(">h",record[16:18])[0]
lastAccessDay = struct.unpack(">h",record[18:20])[0] lastAccessDay = struct.unpack(">h",record[18:20])[0]
lastAccessHour = struct.unpack(">h",record[20:22])[0] lastAccessHour = struct.unpack(">h",record[20:22])[0]
@ -169,14 +169,14 @@ class Gds2reader:
if(self.debugToTerminal==1): if(self.debugToTerminal==1):
print("Units: 1 user unit="+str(userUnits)+" database units, 1 database unit="+str(dbUnits)+" meters.") print("Units: 1 user unit="+str(userUnits)+" database units, 1 database unit="+str(dbUnits)+" meters.")
break; break;
if(self.debugToTerminal==1): if(self.debugToTerminal==1):
print("End of GDSII Header Found") print("End of GDSII Header Found")
return 1 return 1
def readBoundary(self): def readBoundary(self):
##reads in a boundary type structure = a filled polygon ##reads in a boundary type structure = a filled polygon
if(self.debugToTerminal==1): if(self.debugToTerminal==1):
print("\t\t\tBeginBoundary") print("\t\t\tBeginBoundary")
thisBoundary=GdsBoundary() thisBoundary=GdsBoundary()
while 1: while 1:
record = self.readNextRecord() record = self.readNextRecord()
@ -198,9 +198,9 @@ class Gds2reader:
self.layoutObject.layerNumbersInUse += [drawingLayer] self.layoutObject.layerNumbersInUse += [drawingLayer]
if(self.debugToTerminal==1): if(self.debugToTerminal==1):
print("\t\tDrawing Layer: "+str(drawingLayer)) print("\t\tDrawing Layer: "+str(drawingLayer))
elif(idBits==b'\x16\x02'): #Purpose elif(idBits==b'\x0E\x02'): #Purpose DATATYPE
purposeLayer = struct.unpack(">h",record[2:4])[0] purposeLayer = struct.unpack(">h",record[2:4])[0]
thisBoundary.purposeLayer=purposeLayer thisBoundary.purposeLayer=purposeLayer
if(self.debugToTerminal==1): if(self.debugToTerminal==1):
print("\t\tPurpose Layer: "+str(purposeLayer)) print("\t\tPurpose Layer: "+str(purposeLayer))
elif(idBits==b'\x10\x03'): #XY Data Points elif(idBits==b'\x10\x03'): #XY Data Points
@ -217,11 +217,11 @@ class Gds2reader:
print("\t\t\tEndBoundary") print("\t\t\tEndBoundary")
break; break;
return thisBoundary return thisBoundary
def readPath(self): #reads in a path structure def readPath(self): #reads in a path structure
if(self.debugToTerminal==1): if(self.debugToTerminal==1):
print("\t\t\tBeginPath") print("\t\t\tBeginPath")
thisPath=GdsPath() thisPath=GdsPath()
while 1: while 1:
record = self.readNextRecord() record = self.readNextRecord()
@ -245,7 +245,7 @@ class Gds2reader:
print("\t\t\tDrawing Layer: "+str(drawingLayer)) print("\t\t\tDrawing Layer: "+str(drawingLayer))
elif(idBits==b'\x16\x02'): #Purpose elif(idBits==b'\x16\x02'): #Purpose
purposeLayer = struct.unpack(">h",record[2:4])[0] purposeLayer = struct.unpack(">h",record[2:4])[0]
thisPath.purposeLayer=purposeLayer thisPath.purposeLayer=purposeLayer
if(self.debugToTerminal==1): if(self.debugToTerminal==1):
print("\t\tPurpose Layer: "+str(purposeLayer)) print("\t\tPurpose Layer: "+str(purposeLayer))
elif(idBits==b'\x21\x02'): #Path type elif(idBits==b'\x21\x02'): #Path type
@ -277,7 +277,7 @@ class Gds2reader:
print("\t\t\tEndPath") print("\t\t\tEndPath")
break; break;
return thisPath return thisPath
def readSref(self): #reads in a reference to another structure def readSref(self): #reads in a reference to another structure
if(self.debugToTerminal==1): if(self.debugToTerminal==1):
print("\t\t\tBeginSref") print("\t\t\tBeginSref")
@ -318,7 +318,7 @@ class Gds2reader:
print("\t\t\tMagnification:"+str(magFactor)) print("\t\t\tMagnification:"+str(magFactor))
elif(idBits==b'\x1C\x05'): #Rotate Angle elif(idBits==b'\x1C\x05'): #Rotate Angle
rotateAngle=self.ieeeDoubleFromIbmData(record[2:10]) rotateAngle=self.ieeeDoubleFromIbmData(record[2:10])
thisSref.rotateAngle=rotateAngle thisSref.rotateAngle=rotateAngle
if(self.debugToTerminal==1): if(self.debugToTerminal==1):
print("\t\t\tRotate Angle (CCW):"+str(rotateAngle)) print("\t\t\tRotate Angle (CCW):"+str(rotateAngle))
elif(idBits==b'\x10\x03'): #XY Data Points elif(idBits==b'\x10\x03'): #XY Data Points
@ -333,11 +333,11 @@ class Gds2reader:
print("\t\t\tEndSref") print("\t\t\tEndSref")
break; break;
return thisSref return thisSref
def readAref(self): #an array of references def readAref(self): #an array of references
if(self.debugToTerminal==1): if(self.debugToTerminal==1):
print("\t\t\tBeginAref") print("\t\t\tBeginAref")
thisAref = GdsAref() thisAref = GdsAref()
while 1: while 1:
record = self.readNextRecord() record = self.readNextRecord()
@ -374,7 +374,7 @@ class Gds2reader:
print("\t\t\tMagnification:"+str(magFactor)) print("\t\t\tMagnification:"+str(magFactor))
elif(idBits==b'\x1C\x05'): #Rotate Angle elif(idBits==b'\x1C\x05'): #Rotate Angle
rotateAngle=self.ieeeDoubleFromIbmData(record[2:10]) rotateAngle=self.ieeeDoubleFromIbmData(record[2:10])
thisAref.rotateAngle=rotateAngle thisAref.rotateAngle=rotateAngle
if(self.debugToTerminal==1): if(self.debugToTerminal==1):
print("\t\t\tRotate Angle (CCW):"+str(rotateAngle)) print("\t\t\tRotate Angle (CCW):"+str(rotateAngle))
elif(idBits==b'\x10\x03'): #XY Data Points elif(idBits==b'\x10\x03'): #XY Data Points
@ -393,11 +393,11 @@ class Gds2reader:
print("\t\t\tEndAref") print("\t\t\tEndAref")
break; break;
return thisAref return thisAref
def readText(self): def readText(self):
if(self.debugToTerminal==1): if(self.debugToTerminal==1):
print("\t\t\tBeginText") print("\t\t\tBeginText")
thisText=GdsText() thisText=GdsText()
while 1: while 1:
record = self.readNextRecord() record = self.readNextRecord()
@ -419,9 +419,9 @@ class Gds2reader:
self.layoutObject.layerNumbersInUse += [drawingLayer] self.layoutObject.layerNumbersInUse += [drawingLayer]
if(self.debugToTerminal==1): if(self.debugToTerminal==1):
print("\t\tDrawing Layer: "+str(drawingLayer)) print("\t\tDrawing Layer: "+str(drawingLayer))
elif(idBits==b'\x16\x02'): #Purpose elif(idBits==b'\x16\x02'): #Purpose TEXTTYPE
purposeLayer = struct.unpack(">h",record[2:4])[0] purposeLayer = struct.unpack(">h",record[2:4])[0]
thisText.purposeLayer=purposeLayer thisText.purposeLayer=purposeLayer
if(self.debugToTerminal==1): if(self.debugToTerminal==1):
print("\t\tPurpose Layer: "+str(purposeLayer)) print("\t\tPurpose Layer: "+str(purposeLayer))
elif(idBits==b'\x1A\x01'): #Transformation elif(idBits==b'\x1A\x01'): #Transformation
@ -497,11 +497,11 @@ class Gds2reader:
print("\t\t\tEndText") print("\t\t\tEndText")
break; break;
return thisText return thisText
def readNode(self): def readNode(self):
if(self.debugToTerminal==1): if(self.debugToTerminal==1):
print("\t\t\tBeginNode") print("\t\t\tBeginNode")
##reads in a node type structure = an electrical net ##reads in a node type structure = an electrical net
thisNode = GdsNode() thisNode = GdsNode()
while 1: while 1:
@ -543,11 +543,11 @@ class Gds2reader:
print("\t\t\tEndNode") print("\t\t\tEndNode")
break; break;
return thisNode return thisNode
def readBox(self): def readBox(self):
if(self.debugToTerminal==1): if(self.debugToTerminal==1):
print("\t\t\tBeginBox") print("\t\t\tBeginBox")
##reads in a gds BOX structure ##reads in a gds BOX structure
thisBox = GdsBox() thisBox = GdsBox()
while 1: while 1:
@ -570,9 +570,9 @@ class Gds2reader:
self.layoutObject.layerNumbersInUse += [drawingLayer] self.layoutObject.layerNumbersInUse += [drawingLayer]
if(self.debugToTerminal==1): if(self.debugToTerminal==1):
print("\t\tDrawing Layer: "+str(drawingLayer)) print("\t\tDrawing Layer: "+str(drawingLayer))
elif(idBits==b'\x16\x02'): #Purpose elif(idBits==b'\x16\x02'): #Purpose TEXTYPE
purposeLayer = struct.unpack(">h",record[2:4])[0] purposeLayer = struct.unpack(">h",record[2:4])[0]
thisBox.purposeLayer=purposeLayer thisBox.purposeLayer=purposeLayer
if(self.debugToTerminal==1): if(self.debugToTerminal==1):
print("\t\tPurpose Layer: "+str(purposeLayer)) print("\t\tPurpose Layer: "+str(purposeLayer))
elif(idBits==b'\x2D\x00'): #Box elif(idBits==b'\x2D\x00'): #Box
@ -594,14 +594,14 @@ class Gds2reader:
print("\t\t\tEndBox") print("\t\t\tEndBox")
break; break;
return thisBox return thisBox
def readNextStructure(self): def readNextStructure(self):
thisStructure = GdsStructure() thisStructure = GdsStructure()
record = self.readNextRecord() record = self.readNextRecord()
idBits = record[0:2] idBits = record[0:2]
# Begin structure # Begin structure
if(idBits==b'\x05\x02' and len(record)==26): if(idBits==b'\x05\x02' and len(record)==26):
createYear = struct.unpack(">h",record[2:4])[0] createYear = struct.unpack(">h",record[2:4])[0]
createMonth = struct.unpack(">h",record[4:6])[0] createMonth = struct.unpack(">h",record[4:6])[0]
createDay = struct.unpack(">h",record[6:8])[0] createDay = struct.unpack(">h",record[6:8])[0]
createHour = struct.unpack(">h",record[8:10])[0] createHour = struct.unpack(">h",record[8:10])[0]
@ -628,7 +628,7 @@ class Gds2reader:
idBits = record[0:2] idBits = record[0:2]
if idBits==b'\x07\x00': break; #we've reached the end of the structure if idBits==b'\x07\x00': break; #we've reached the end of the structure
elif(idBits==b'\x06\x06'): elif(idBits==b'\x06\x06'):
structName = self.stripNonASCII(record[2::]) structName = self.stripNonASCII(record[2::])
thisStructure.name = structName thisStructure.name = structName
if(self.debugToTerminal==1): if(self.debugToTerminal==1):
print("\tStructure Name: "+structName) print("\tStructure Name: "+structName)
@ -646,11 +646,11 @@ class Gds2reader:
thisStructure.nodes+=[self.readNode()] thisStructure.nodes+=[self.readNode()]
elif(idBits==b'\x2E\x02'): elif(idBits==b'\x2E\x02'):
thisStructure.boxes+=[self.readBox()] thisStructure.boxes+=[self.readBox()]
if(self.debugToTerminal==1): if(self.debugToTerminal==1):
print("\tEnd of Structure.") print("\tEnd of Structure.")
self.layoutObject.structures[structName]=thisStructure #add this structure to the layout object self.layoutObject.structures[structName]=thisStructure #add this structure to the layout object
return 1 return 1
def readGds2(self): def readGds2(self):
if(self.readHeader()): #did the header read ok? if(self.readHeader()): #did the header read ok?
record = self.readNextStructure() record = self.readNextStructure()
@ -667,7 +667,7 @@ class Gds2reader:
print("There was an error reading the structure list.") print("There was an error reading the structure list.")
else: else:
print("There was an error parsing the GDS header. Aborting...") print("There was an error parsing the GDS header. Aborting...")
def loadFromFile(self, fileName): def loadFromFile(self, fileName):
self.fileHandle = open(fileName,"rb") self.fileHandle = open(fileName,"rb")
self.readGds2() self.readGds2()
@ -695,11 +695,11 @@ class Gds2reader:
def findStruct_readNextStruct(self,findStructName): def findStruct_readNextStruct(self,findStructName):
self.debugToTerminal=0 self.debugToTerminal=0
thisStructure = GdsStructure() thisStructure = GdsStructure()
record = self.readNextRecord() record = self.readNextRecord()
idBits = record[0:2] idBits = record[0:2]
if(idBits==('\x05','\x02') and len(record)==26): if(idBits==('\x05','\x02') and len(record)==26):
createYear = struct.unpack(">h",record[2]+record[3])[0] createYear = struct.unpack(">h",record[2]+record[3])[0]
createMonth = struct.unpack(">h",record[4]+record[5])[0] createMonth = struct.unpack(">h",record[4]+record[5])[0]
createDay = struct.unpack(">h",record[6]+record[7])[0] createDay = struct.unpack(">h",record[6]+record[7])[0]
createHour = struct.unpack(">h",record[8]+record[9])[0] createHour = struct.unpack(">h",record[8]+record[9])[0]
@ -743,7 +743,7 @@ class Gds2reader:
thisStructure.nodes+=[self.readNode()] thisStructure.nodes+=[self.readNode()]
elif(idBits==('\x2E','\x02')): elif(idBits==('\x2E','\x02')):
thisStructure.boxes+=[self.readBox()] thisStructure.boxes+=[self.readBox()]
if(self.debugToTerminal==1): if(self.debugToTerminal==1):
print("\tEnd of Structure.") print("\tEnd of Structure.")
self.layoutObject.structures[structName]=thisStructure #add this structure to the layout object self.layoutObject.structures[structName]=thisStructure #add this structure to the layout object
if(wantedStruct == 0): if(wantedStruct == 0):
@ -771,11 +771,11 @@ class Gds2reader:
def findLabel_readNextStruct(self,findLabelName): def findLabel_readNextStruct(self,findLabelName):
self.debugToTerminal=0 self.debugToTerminal=0
thisStructure = GdsStructure() thisStructure = GdsStructure()
record = self.readNextRecord() record = self.readNextRecord()
idBits = record[0:2] idBits = record[0:2]
if(idBits==('\x05','\x02') and len(record)==26): if(idBits==('\x05','\x02') and len(record)==26):
createYear = struct.unpack(">h",record[2]+record[3])[0] createYear = struct.unpack(">h",record[2]+record[3])[0]
createMonth = struct.unpack(">h",record[4]+record[5])[0] createMonth = struct.unpack(">h",record[4]+record[5])[0]
createDay = struct.unpack(">h",record[6]+record[7])[0] createDay = struct.unpack(">h",record[6]+record[7])[0]
createHour = struct.unpack(">h",record[8]+record[9])[0] createHour = struct.unpack(">h",record[8]+record[9])[0]
@ -825,7 +825,7 @@ class Gds2reader:
thisStructure.nodes+=[self.readNode()] thisStructure.nodes+=[self.readNode()]
elif(idBits==('\x2E','\x02')): elif(idBits==('\x2E','\x02')):
thisStructure.boxes+=[self.readBox()] thisStructure.boxes+=[self.readBox()]
if(self.debugToTerminal==1): if(self.debugToTerminal==1):
print("\tEnd of Structure.") print("\tEnd of Structure.")
self.layoutObject.structures[structName]=thisStructure #add this structure to the layout object self.layoutObject.structures[structName]=thisStructure #add this structure to the layout object
if(wantedLabel == 0): if(wantedLabel == 0):
@ -833,4 +833,3 @@ class Gds2reader:
else: else:
#print("\tDone with collectting bound. Return") #print("\tDone with collectting bound. Return")
return [0,wantedtexts] return [0,wantedtexts]

View File

@ -5,37 +5,37 @@ from .gdsPrimitives import *
class Gds2writer: class Gds2writer:
"""Class to take a populated layout class and write it to a file in GDSII format""" """Class to take a populated layout class and write it to a file in GDSII format"""
## Based on info from http://www.rulabinsky.com/cavd/text/chapc.html ## Based on info from http://www.rulabinsky.com/cavd/text/chapc.html
def __init__(self,layoutObject): def __init__(self,layoutObject):
self.fileHandle = 0 self.fileHandle = 0
self.layoutObject = layoutObject self.layoutObject = layoutObject
self.debugToTerminal=0 #do we dump debug data to the screen self.debugToTerminal=0 #do we dump debug data to the screen
def print64AsBinary(self,number): def print64AsBinary(self,number):
#debugging method for binary inspection #debugging method for binary inspection
for index in range(0,64): for index in range(0,64):
print((number>>(63-index))&0x1,eol='') print((number>>(63-index))&0x1,eol='')
print("\n") print("\n")
def ieeeDoubleFromIbmData(self,ibmData): def ieeeDoubleFromIbmData(self,ibmData):
#the GDS double is in IBM 370 format like this: #the GDS double is in IBM 370 format like this:
#(1)sign (7)exponent (56)mantissa #(1)sign (7)exponent (56)mantissa
#exponent is excess 64, mantissa has no implied 1 #exponent is excess 64, mantissa has no implied 1
#a normal IEEE double is like this: #a normal IEEE double is like this:
#(1)sign (11)exponent (52)mantissa #(1)sign (11)exponent (52)mantissa
data = struct.unpack('>q',ibmData)[0] data = struct.unpack('>q',ibmData)[0]
sign = (data >> 63)&0x01 sign = (data >> 63)&0x01
exponent = (data >> 56) & 0x7f exponent = (data >> 56) & 0x7f
mantissa = data<<8 #chop off sign and exponent mantissa = data<<8 #chop off sign and exponent
if mantissa == 0: if mantissa == 0:
newFloat = 0.0 newFloat = 0.0
else: else:
exponent = ((exponent-64)*4)+1023 #convert to double exponent exponent = ((exponent-64)*4)+1023 #convert to double exponent
#re normalize #re normalize
while mantissa & 0x8000000000000000 == 0: while mantissa & 0x8000000000000000 == 0:
mantissa<<=1 mantissa<<=1
exponent-=1 exponent-=1
mantissa<<=1 #remove the assumed high bit mantissa<<=1 #remove the assumed high bit
exponent-=1 exponent-=1
#check for underflow error -- should handle these properly! #check for underflow error -- should handle these properly!
@ -49,12 +49,12 @@ class Gds2writer:
#convert back to double #convert back to double
newFloat = struct.unpack('>d',asciiDouble)[0] newFloat = struct.unpack('>d',asciiDouble)[0]
return newFloat return newFloat
def ibmDataFromIeeeDouble(self,ieeeDouble): def ibmDataFromIeeeDouble(self,ieeeDouble):
asciiDouble = struct.pack('>d',ieeeDouble) asciiDouble = struct.pack('>d',ieeeDouble)
data = struct.unpack('>q',asciiDouble)[0] data = struct.unpack('>q',asciiDouble)[0]
sign = (data >> 63) & 0x01 sign = (data >> 63) & 0x01
exponent = ((data >> 52) & 0x7ff)-1023 exponent = ((data >> 52) & 0x7ff)-1023
mantissa = data << 12 #chop off sign and exponent mantissa = data << 12 #chop off sign and exponent
if(ieeeDouble == 0): if(ieeeDouble == 0):
mantissa = 0 mantissa = 0
@ -70,14 +70,14 @@ class Gds2writer:
for index in range (0,-exponent&3): for index in range (0,-exponent&3):
mantissa >>= 1 mantissa >>= 1
mantissa = mantissa & 0x7fffffffffffffff mantissa = mantissa & 0x7fffffffffffffff
exponent = (exponent+3) >> 2 exponent = (exponent+3) >> 2
exponent+=64 exponent+=64
newFloat =(sign<<63)|(exponent<<56)|((mantissa>>8)&0xffffffffffffff) newFloat =(sign<<63)|(exponent<<56)|((mantissa>>8)&0xffffffffffffff)
asciiDouble = struct.pack('>q',newFloat) asciiDouble = struct.pack('>q',newFloat)
return asciiDouble return asciiDouble
def ieeeFloatCheck(self,aFloat): def ieeeFloatCheck(self,aFloat):
#debugging method for float construction #debugging method for float construction
asciiDouble = struct.pack('>d',aFloat) asciiDouble = struct.pack('>d',aFloat)
@ -90,7 +90,7 @@ class Gds2writer:
asciiDouble = struct.pack('>q',(sign<<63)|(exponent+1023<<52)|(mantissa>>12)) asciiDouble = struct.pack('>q',(sign<<63)|(exponent+1023<<52)|(mantissa>>12))
newFloat = struct.unpack('>d',asciiDouble)[0] newFloat = struct.unpack('>d',asciiDouble)[0]
print("Check:"+str(newFloat)) print("Check:"+str(newFloat))
def writeRecord(self,record): def writeRecord(self,record):
recordLength = len(record)+2 #make sure to include this in the length recordLength = len(record)+2 #make sure to include this in the length
recordLengthAscii=struct.pack(">h",recordLength) recordLengthAscii=struct.pack(">h",recordLength)
@ -127,7 +127,7 @@ class Gds2writer:
libraryName = self.layoutObject.info["libraryName"].encode() + "\0" libraryName = self.layoutObject.info["libraryName"].encode() + "\0"
else: else:
libraryName = self.layoutObject.info["libraryName"].encode() libraryName = self.layoutObject.info["libraryName"].encode()
self.writeRecord(idBits+libraryName) self.writeRecord(idBits+libraryName)
## reference libraries ## reference libraries
if("referenceLibraries" in self.layoutObject.info): if("referenceLibraries" in self.layoutObject.info):
idBits=b'\x1F\x06' idBits=b'\x1F\x06'
@ -158,11 +158,11 @@ class Gds2writer:
mask = self.layoutObject.info["mask"] mask = self.layoutObject.info["mask"]
self.writeRecord(idBits+mask) self.writeRecord(idBits+mask)
if("units" in self.layoutObject.info): if("units" in self.layoutObject.info):
idBits=b'\x03\x05' idBits=b'\x03\x05'
userUnits=self.ibmDataFromIeeeDouble(self.layoutObject.info["units"][0]) userUnits=self.ibmDataFromIeeeDouble(self.layoutObject.info["units"][0])
dbUnits=self.ibmDataFromIeeeDouble((self.layoutObject.info["units"][0]*1e-6/self.layoutObject.info["units"][1])*self.layoutObject.info["units"][1]) dbUnits=self.ibmDataFromIeeeDouble((self.layoutObject.info["units"][0]*1e-6/self.layoutObject.info["units"][1])*self.layoutObject.info["units"][1])
#User Units are hardcoded, since the floating point implementation of gdsMill is not adequate, #User Units are hardcoded, since the floating point implementation of gdsMill is not adequate,
#resulting in a different value being written in output stream. Hardcoded to sram compiler's outputed gds units. #resulting in a different value being written in output stream. Hardcoded to sram compiler's outputed gds units.
#db="39225c17d04dad2a" #db="39225c17d04dad2a"
#uu="3e20c49ba5e353f8" #uu="3e20c49ba5e353f8"
@ -172,17 +172,17 @@ class Gds2writer:
#dbUnits="39225c17d04dad2a".decode("hex") #dbUnits="39225c17d04dad2a".decode("hex")
#db=39225c17d04dad2a #db=39225c17d04dad2a
self.writeRecord(idBits+userUnits+dbUnits) self.writeRecord(idBits+userUnits+dbUnits)
if(self.debugToTerminal==1): if(self.debugToTerminal==1):
print("writer: userUnits %s"%(userUnits.encode("hex"))) print("writer: userUnits %s"%(userUnits.encode("hex")))
print("writer: dbUnits %s"%(dbUnits.encode("hex"))) print("writer: dbUnits %s"%(dbUnits.encode("hex")))
#self.ieeeFloatCheck(1.3e-6) #self.ieeeFloatCheck(1.3e-6)
print("End of GDSII Header Written") print("End of GDSII Header Written")
return 1 return 1
def writeBoundary(self,thisBoundary): def writeBoundary(self,thisBoundary):
idBits=b'\x08\x00' #record Type idBits=b'\x08\x00' #record Type
self.writeRecord(idBits) self.writeRecord(idBits)
@ -216,7 +216,7 @@ class Gds2writer:
idBits=b'\x11\x00' #End Of Element idBits=b'\x11\x00' #End Of Element
coordinateRecord = idBits coordinateRecord = idBits
self.writeRecord(coordinateRecord) self.writeRecord(coordinateRecord)
def writePath(self,thisPath): #writes out a path structure def writePath(self,thisPath): #writes out a path structure
idBits=b'\x09\x00' #record Type idBits=b'\x09\x00' #record Type
self.writeRecord(idBits) self.writeRecord(idBits)
@ -260,7 +260,7 @@ class Gds2writer:
idBits=b'\x11\x00' #End Of Element idBits=b'\x11\x00' #End Of Element
coordinateRecord = idBits coordinateRecord = idBits
self.writeRecord(coordinateRecord) self.writeRecord(coordinateRecord)
def writeSref(self,thisSref): #reads in a reference to another structure def writeSref(self,thisSref): #reads in a reference to another structure
idBits=b'\x0A\x00' #record Type idBits=b'\x0A\x00' #record Type
self.writeRecord(idBits) self.writeRecord(idBits)
@ -296,7 +296,7 @@ class Gds2writer:
magFactor=self.ibmDataFromIeeeDouble(thisSref.magFactor) magFactor=self.ibmDataFromIeeeDouble(thisSref.magFactor)
self.writeRecord(idBits+magFactor) self.writeRecord(idBits+magFactor)
if(thisSref.rotateAngle!=""): if(thisSref.rotateAngle!=""):
idBits=b'\x1C\x05' idBits=b'\x1C\x05'
rotateAngle=self.ibmDataFromIeeeDouble(thisSref.rotateAngle) rotateAngle=self.ibmDataFromIeeeDouble(thisSref.rotateAngle)
self.writeRecord(idBits+rotateAngle) self.writeRecord(idBits+rotateAngle)
if(thisSref.coordinates!=""): if(thisSref.coordinates!=""):
@ -312,7 +312,7 @@ class Gds2writer:
idBits=b'\x11\x00' #End Of Element idBits=b'\x11\x00' #End Of Element
coordinateRecord = idBits coordinateRecord = idBits
self.writeRecord(coordinateRecord) self.writeRecord(coordinateRecord)
def writeAref(self,thisAref): #an array of references def writeAref(self,thisAref): #an array of references
idBits=b'\x0B\x00' #record Type idBits=b'\x0B\x00' #record Type
self.writeRecord(idBits) self.writeRecord(idBits)
@ -348,7 +348,7 @@ class Gds2writer:
magFactor=self.ibmDataFromIeeeDouble(thisAref.magFactor) magFactor=self.ibmDataFromIeeeDouble(thisAref.magFactor)
self.writeRecord(idBits+magFactor) self.writeRecord(idBits+magFactor)
if(thisAref.rotateAngle!=""): if(thisAref.rotateAngle!=""):
idBits=b'\x1C\x05' idBits=b'\x1C\x05'
rotateAngle=self.ibmDataFromIeeeDouble(thisAref.rotateAngle) rotateAngle=self.ibmDataFromIeeeDouble(thisAref.rotateAngle)
self.writeRecord(idBits+rotateAngle) self.writeRecord(idBits+rotateAngle)
if(thisAref.coordinates): if(thisAref.coordinates):
@ -363,7 +363,7 @@ class Gds2writer:
idBits=b'\x11\x00' #End Of Element idBits=b'\x11\x00' #End Of Element
coordinateRecord = idBits coordinateRecord = idBits
self.writeRecord(coordinateRecord) self.writeRecord(coordinateRecord)
def writeText(self,thisText): def writeText(self,thisText):
idBits=b'\x0C\x00' #record Type idBits=b'\x0C\x00' #record Type
self.writeRecord(idBits) self.writeRecord(idBits)
@ -379,9 +379,8 @@ class Gds2writer:
idBits=b'\x0D\x02' #drawing layer idBits=b'\x0D\x02' #drawing layer
drawingLayer = struct.pack(">h",thisText.drawingLayer) drawingLayer = struct.pack(">h",thisText.drawingLayer)
self.writeRecord(idBits+drawingLayer) self.writeRecord(idBits+drawingLayer)
# TextType is always a 0 per GDS specification idBits=b'\x16\x02' #purpose layer TEXTTYPE
idBits=b'\x16\x02' #purpose layer purposeLayer = struct.pack(">h",thisText.purposeLayer)
purposeLayer = struct.pack(">h",0)
self.writeRecord(idBits+purposeLayer) self.writeRecord(idBits+purposeLayer)
if(thisText.transFlags != ""): if(thisText.transFlags != ""):
idBits=b'\x1A\x01' idBits=b'\x1A\x01'
@ -400,7 +399,7 @@ class Gds2writer:
magFactor=self.ibmDataFromIeeeDouble(thisText.magFactor) magFactor=self.ibmDataFromIeeeDouble(thisText.magFactor)
self.writeRecord(idBits+magFactor) self.writeRecord(idBits+magFactor)
if(thisText.rotateAngle!=""): if(thisText.rotateAngle!=""):
idBits=b'\x1C\x05' idBits=b'\x1C\x05'
rotateAngle=self.ibmDataFromIeeeDouble(thisText.rotateAngle) rotateAngle=self.ibmDataFromIeeeDouble(thisText.rotateAngle)
self.writeRecord(idBits+rotateAngle) self.writeRecord(idBits+rotateAngle)
if(thisText.pathType !=""): if(thisText.pathType !=""):
@ -412,12 +411,12 @@ class Gds2writer:
pathWidth = struct.pack(">i",thisText.pathWidth) pathWidth = struct.pack(">i",thisText.pathWidth)
self.writeRecord(idBits+pathWidth) self.writeRecord(idBits+pathWidth)
if(thisText.presentationFlags!=""): if(thisText.presentationFlags!=""):
idBits=b'\x1A\x01' idBits=b'\x1A\x01'
font = thisText.presentationFlags[0]<<4 font = thisText.presentationFlags[0]<<4
verticalFlags = int(thisText.presentationFlags[1])<<2 verticalFlags = int(thisText.presentationFlags[1])<<2
horizontalFlags = int(thisText.presentationFlags[2]) horizontalFlags = int(thisText.presentationFlags[2])
presentationFlags = struct.pack(">H",font|verticalFlags|horizontalFlags) presentationFlags = struct.pack(">H",font|verticalFlags|horizontalFlags)
self.writeRecord(idBits+transFlags) self.writeRecord(idBits+transFlags)
if(thisText.coordinates!=""): if(thisText.coordinates!=""):
idBits=b'\x10\x03' #XY Data Points idBits=b'\x10\x03' #XY Data Points
coordinateRecord = idBits coordinateRecord = idBits
@ -431,11 +430,11 @@ class Gds2writer:
idBits=b'\x19\x06' idBits=b'\x19\x06'
textString = thisText.textString textString = thisText.textString
self.writeRecord(idBits+textString.encode()) self.writeRecord(idBits+textString.encode())
idBits=b'\x11\x00' #End Of Element idBits=b'\x11\x00' #End Of Element
coordinateRecord = idBits coordinateRecord = idBits
self.writeRecord(coordinateRecord) self.writeRecord(coordinateRecord)
def writeNode(self,thisNode): def writeNode(self,thisNode):
idBits=b'\x15\x00' #record Type idBits=b'\x15\x00' #record Type
self.writeRecord(idBits) self.writeRecord(idBits)
@ -450,11 +449,11 @@ class Gds2writer:
if(thisNode.drawingLayer!=""): if(thisNode.drawingLayer!=""):
idBits=b'\x0D\x02' #drawig layer idBits=b'\x0D\x02' #drawig layer
drawingLayer = struct.pack(">h",thisNode.drawingLayer) drawingLayer = struct.pack(">h",thisNode.drawingLayer)
self.writeRecord(idBits+drawingLayer) self.writeRecord(idBits+drawingLayer)
if(thisNode.nodeType!=""): if(thisNode.nodeType!=""):
idBits=b'\x2A\x02' idBits=b'\x2A\x02'
nodeType = struct.pack(">h",thisNode.nodeType) nodeType = struct.pack(">h",thisNode.nodeType)
self.writeRecord(idBits+nodeType) self.writeRecord(idBits+nodeType)
if(thisText.coordinates!=""): if(thisText.coordinates!=""):
idBits=b'\x10\x03' #XY Data Points idBits=b'\x10\x03' #XY Data Points
coordinateRecord = idBits coordinateRecord = idBits
@ -464,11 +463,11 @@ class Gds2writer:
coordinateRecord+=x coordinateRecord+=x
coordinateRecord+=y coordinateRecord+=y
self.writeRecord(coordinateRecord) self.writeRecord(coordinateRecord)
idBits=b'\x11\x00' #End Of Element idBits=b'\x11\x00' #End Of Element
coordinateRecord = idBits coordinateRecord = idBits
self.writeRecord(coordinateRecord) self.writeRecord(coordinateRecord)
def writeBox(self,thisBox): def writeBox(self,thisBox):
idBits=b'\x2E\x02' #record Type idBits=b'\x2E\x02' #record Type
self.writeRecord(idBits) self.writeRecord(idBits)
@ -491,7 +490,7 @@ class Gds2writer:
if(thisBox.boxValue!=""): if(thisBox.boxValue!=""):
idBits=b'\x2D\x00' idBits=b'\x2D\x00'
boxValue = struct.pack(">h",thisBox.boxValue) boxValue = struct.pack(">h",thisBox.boxValue)
self.writeRecord(idBits+boxValue) self.writeRecord(idBits+boxValue)
if(thisBox.coordinates!=""): if(thisBox.coordinates!=""):
idBits=b'\x10\x03' #XY Data Points idBits=b'\x10\x03' #XY Data Points
coordinateRecord = idBits coordinateRecord = idBits
@ -501,11 +500,11 @@ class Gds2writer:
coordinateRecord+=x coordinateRecord+=x
coordinateRecord+=y coordinateRecord+=y
self.writeRecord(coordinateRecord) self.writeRecord(coordinateRecord)
idBits=b'\x11\x00' #End Of Element idBits=b'\x11\x00' #End Of Element
coordinateRecord = idBits coordinateRecord = idBits
self.writeRecord(coordinateRecord) self.writeRecord(coordinateRecord)
def writeNextStructure(self,structureName): def writeNextStructure(self,structureName):
#first put in the structure head #first put in the structure head
thisStructure = self.layoutObject.structures[structureName] thisStructure = self.layoutObject.structures[structureName]
@ -532,7 +531,7 @@ class Gds2writer:
structureName = structureName + '\x00' structureName = structureName + '\x00'
self.writeRecord(idBits+structureName.encode()) self.writeRecord(idBits+structureName.encode())
#now go through all the structure elements and write them in #now go through all the structure elements and write them in
for boundary in thisStructure.boundaries: for boundary in thisStructure.boundaries:
self.writeBoundary(boundary) self.writeBoundary(boundary)
for path in thisStructure.paths: for path in thisStructure.paths:
@ -550,7 +549,7 @@ class Gds2writer:
#put in the structure tail #put in the structure tail
idBits=b'\x07\x00' idBits=b'\x07\x00'
self.writeRecord(idBits) self.writeRecord(idBits)
def writeGds2(self): def writeGds2(self):
self.writeHeader(); #first, put the header in self.writeHeader(); #first, put the header in
#go through each structure in the layout and write it to the file #go through each structure in the layout and write it to the file
@ -559,7 +558,7 @@ class Gds2writer:
#at the end, put in the END LIB record #at the end, put in the END LIB record
idBits=b'\x04\x00' idBits=b'\x04\x00'
self.writeRecord(idBits) self.writeRecord(idBits)
def writeToFile(self,fileName): def writeToFile(self,fileName):
self.fileHandle = open(fileName,"wb") self.fileHandle = open(fileName,"wb")
self.writeGds2() self.writeGds2()

View File

@ -1,5 +1,12 @@
import math import math
from globals import OPTS
# default purpose layer is used for addText() in vlsiLayout.py
if OPTS.tech_name == "s8":
purposeLayer=20
else:
purposeLayer=0
class GdsStructure: class GdsStructure:
"""Class represent a GDS Structure Object""" """Class represent a GDS Structure Object"""
def __init__(self): def __init__(self):
@ -9,7 +16,7 @@ class GdsStructure:
#these are the primitives defined in GDS2, and we will maintain lists of them all #these are the primitives defined in GDS2, and we will maintain lists of them all
self.boundaries=[] self.boundaries=[]
self.paths=[] self.paths=[]
self.srefs=[] self.srefs=[]
self.arefs=[] self.arefs=[]
self.texts=[] self.texts=[]
self.nodes=[] self.nodes=[]
@ -23,7 +30,7 @@ class GdsBoundary:
self.drawingLayer="" self.drawingLayer=""
self.purposeLayer=0 self.purposeLayer=0
self.coordinates="" self.coordinates=""
class GdsPath: class GdsPath:
"""Class represent a GDS Path Object""" """Class represent a GDS Path Object"""
def __init__(self): def __init__(self):
@ -35,7 +42,7 @@ class GdsPath:
self.dataType=None self.dataType=None
self.pathWidth="" self.pathWidth=""
self.coordinates="" self.coordinates=""
def equivalentBoundaryCoordinates(self): def equivalentBoundaryCoordinates(self):
"""Convert the path to a set of boundary coordinates that define it""" """Convert the path to a set of boundary coordinates that define it"""
halfWidth = (self.pathWidth/2) halfWidth = (self.pathWidth/2)
@ -62,7 +69,7 @@ class GdsPath:
nextX = None; nextX = None;
nextY = None; nextY = None;
if lastX==None: #start of the path if lastX==None: #start of the path
if nextX>x:#moving right if nextX>x:#moving right
boundaryEquivalent+=[(x,y+halfWidth)] boundaryEquivalent+=[(x,y+halfWidth)]
if nextX<x:#moving left if nextX<x:#moving left
boundaryEquivalent+=[(x,y-halfWidth)] boundaryEquivalent+=[(x,y-halfWidth)]
@ -96,9 +103,9 @@ class GdsPath:
boundaryEquivalent+=[(x-halfWidth,y+halfWidth)] boundaryEquivalent+=[(x-halfWidth,y+halfWidth)]
if(y < lastY and x > nextX): if(y < lastY and x > nextX):
boundaryEquivalent+=[(x+halfWidth,y-halfWidth)] boundaryEquivalent+=[(x+halfWidth,y-halfWidth)]
if nextX == None: #end of path, put in the last 2 points if nextX == None: #end of path, put in the last 2 points
if lastX<x:#moving right if lastX<x:#moving right
boundaryEquivalent+=[(x,y+halfWidth)] boundaryEquivalent+=[(x,y+halfWidth)]
if lastX>x:#moving left if lastX>x:#moving left
boundaryEquivalent+=[(x,y-halfWidth)] boundaryEquivalent+=[(x,y-halfWidth)]
@ -140,7 +147,7 @@ class GdsText:
self.elementFlags="" self.elementFlags=""
self.plex="" self.plex=""
self.drawingLayer="" self.drawingLayer=""
self.purposeLayer=0 self.purposeLayer=purposeLayer
self.transFlags=[0,0,0] self.transFlags=[0,0,0]
self.magFactor="" self.magFactor=""
self.rotateAngle="" self.rotateAngle=""
@ -149,7 +156,7 @@ class GdsText:
self.presentationFlags="" self.presentationFlags=""
self.coordinates="" self.coordinates=""
self.textString = "" self.textString = ""
class GdsNode: class GdsNode:
"""Class represent a GDS Node Object""" """Class represent a GDS Node Object"""
def __init__(self): def __init__(self):
@ -158,7 +165,7 @@ class GdsNode:
self.drawingLayer="" self.drawingLayer=""
self.nodeType="" self.nodeType=""
self.coordinates="" self.coordinates=""
class GdsBox: class GdsBox:
"""Class represent a GDS Box Object""" """Class represent a GDS Box Object"""
def __init__(self): def __init__(self):