diff --git a/compiler/gdsMill/gdsMill/gdsPrimitives.py b/compiler/gdsMill/gdsMill/gdsPrimitives.py index 8e07524c..3b5dcee6 100644 --- a/compiler/gdsMill/gdsMill/gdsPrimitives.py +++ b/compiler/gdsMill/gdsMill/gdsPrimitives.py @@ -1,4 +1,4 @@ -import math + class GdsStructure: """Class represent a GDS Structure Object""" @@ -15,6 +15,7 @@ class GdsStructure: self.nodes=[] self.boxes=[] + class GdsBoundary: """Class represent a GDS Boundary Object""" def __init__(self): @@ -24,6 +25,7 @@ class GdsBoundary: self.purposeLayer=0 self.coordinates="" + class GdsPath: """Class represent a GDS Path Object""" def __init__(self): @@ -112,6 +114,7 @@ class GdsPath: lastY = y return boundaryEquivalent + class GdsSref: """Class represent a GDS structure reference Object""" def __init__(self): @@ -123,6 +126,7 @@ class GdsSref: self.rotateAngle="" self.coordinates="" + class GdsAref: """Class represent a GDS array reference Object""" def __init__(self): @@ -134,6 +138,7 @@ class GdsAref: self.rotateAngle="" self.coordinates="" + class GdsText: """Class represent a GDS text Object""" def __init__(self): @@ -150,6 +155,7 @@ class GdsText: self.coordinates="" self.textString = "" + class GdsNode: """Class represent a GDS Node Object""" def __init__(self): @@ -159,6 +165,7 @@ class GdsNode: self.nodeType="" self.coordinates="" + class GdsBox: """Class represent a GDS Box Object""" def __init__(self): diff --git a/compiler/gdsMill/gdsMill/vlsiLayout.py b/compiler/gdsMill/gdsMill/vlsiLayout.py index 68e32762..bd9968dc 100644 --- a/compiler/gdsMill/gdsMill/vlsiLayout.py +++ b/compiler/gdsMill/gdsMill/vlsiLayout.py @@ -1,26 +1,25 @@ from .gdsPrimitives import * from datetime import * -#from mpmath import matrix -#from numpy import matrix import numpy as np -#import gdsPrimitives +import math import debug + class VlsiLayout: """Class represent a hierarchical layout""" - def __init__(self, name=None, units=(0.001,1e-9), libraryName = "DEFAULT.DB", gdsVersion=5): - #keep a list of all the structures in this layout + def __init__(self, name=None, units=(0.001,1e-9), libraryName="DEFAULT.DB", gdsVersion=5): + # keep a list of all the structures in this layout self.units = units - #print(units) + # print(units) modDate = datetime.now() self.structures=dict() self.layerNumbersInUse = [] self.debug = False if name: - #take the root structure and copy it to a new structure with the new name + # take the root structure and copy it to a new structure with the new name self.rootStructureName=self.padText(name) - #create the ROOT structure + # create the ROOT structure self.structures[self.rootStructureName] = GdsStructure() self.structures[self.rootStructureName].name = name self.structures[self.rootStructureName].createDate = (modDate.year, @@ -36,7 +35,7 @@ class VlsiLayout: modDate.minute, modDate.second) - self.info = dict() #information gathered from the GDSII header + self.info = dict() # information gathered from the GDSII header self.info['units']=self.units self.info['dates']=(modDate.year, modDate.month, @@ -53,12 +52,13 @@ class VlsiLayout: self.info['libraryName']=libraryName self.info['gdsVersion']=gdsVersion - self.xyTree = [] #This will contain a list of all structure names - #expanded to include srefs / arefs separately. - #each structure will have an X,Y,offset, and rotate associated - #with it. Populate via traverseTheHierarchy method. + # This will contain a list of all structure names + # expanded to include srefs / arefs separately. + # each structure will have an X,Y,offset, and rotate associated + # with it. Populate via traverseTheHierarchy method. + self.xyTree = [] - #temp variables used in delegate functions + # temp variables used in delegate functions self.tempCoordinates=None self.tempPassFail = True @@ -68,12 +68,12 @@ class VlsiLayout: self.pins = {} def rotatedCoordinates(self,coordinatesToRotate,rotateAngle): - #helper method to rotate a list of coordinates + # helper method to rotate a list of coordinates angle=math.radians(float(0)) if(rotateAngle): angle = math.radians(float(rotateAngle)) - coordinatesRotate = [] #this will hold the rotated values + coordinatesRotate = [] # this will hold the rotated values for coordinate in coordinatesToRotate: # This is the CCW rotation matrix newX = coordinate[0]*math.cos(angle) - coordinate[1]*math.sin(angle) @@ -82,53 +82,51 @@ class VlsiLayout: return coordinatesRotate def rename(self,newName): - #take the root structure and copy it to a new structure with the new name + # take the root structure and copy it to a new structure with the new name self.structures[newName] = self.structures[self.rootStructureName] self.structures[newName].name = self.padText(newName) - #and delete the old root + # and delete the old root del self.structures[self.rootStructureName] self.rootStructureName = newName - #repopulate the 2d map so drawing occurs correctly + # repopulate the 2d map so drawing occurs correctly del self.xyTree[:] self.populateCoordinateMap() def newLayout(self,newName): - #if (newName == "" | newName == 0): - # print("ERROR: vlsiLayout.py:newLayout newName is null") + # if (newName == "" | newName == 0): + # print("ERROR: vlsiLayout.py:newLayout newName is null") - #make sure the newName is a multiple of 2 characters - #if(len(newName)%2 == 1): - #pad with a zero - #newName = newName + '\x00' - #take the root structure and copy it to a new structure with the new name - #self.structures[newName] = self.structures[self.rootStructureName] + # make sure the newName is a multiple of 2 characters + # if(len(newName)%2 == 1): + # pad with a zero + # newName = newName + '\x00' + # take the root structure and copy it to a new structure with the new name + # self.structures[newName] = self.structures[self.rootStructureName] modDate = datetime.now() self.structures[newName] = GdsStructure() self.structures[newName].name = newName - - self.rootStructureName = newName self.rootStructureName=newName - #create the ROOT structure + # create the ROOT structure self.structures[self.rootStructureName] = GdsStructure() - #self.structures[self.rootStructureName].name = name + # self.structures[self.rootStructureName].name = name self.structures[self.rootStructureName].createDate = (modDate.year, - modDate.month, - modDate.day, - modDate.hour, - modDate.minute, - modDate.second) + modDate.month, + modDate.day, + modDate.hour, + modDate.minute, + modDate.second) self.structures[self.rootStructureName].modDate = (modDate.year, - modDate.month, - modDate.day, - modDate.hour, - modDate.minute, - modDate.second) + modDate.month, + modDate.day, + modDate.hour, + modDate.minute, + modDate.second) #repopulate the 2d map so drawing occurs correctly @@ -155,47 +153,50 @@ class VlsiLayout: debug.check(len(structureNames)==1,"Multiple possible root structures in the layout: {}".format(str(structureNames))) self.rootStructureName = structureNames[0] - - def traverseTheHierarchy(self, startingStructureName=None, delegateFunction = None, - transformPath = [], rotateAngle = 0, transFlags = [0,0,0], coordinates = (0,0)): - #since this is a recursive function, must deal with the default - #parameters explicitly + def traverseTheHierarchy(self, startingStructureName=None, delegateFunction=None, + transformPath=[], rotateAngle=0, transFlags=[0, 0, 0], coordinates=(0, 0)): + # since this is a recursive function, must deal with the default + # parameters explicitly if startingStructureName == None: startingStructureName = self.rootStructureName - #set up the rotation matrix + # set up the rotation matrix if(rotateAngle == None or rotateAngle == ""): angle = 0 else: # MRG: Added negative to make CCW rotate 8/29/18 angle = math.radians(float(rotateAngle)) - mRotate = np.array([[math.cos(angle),-math.sin(angle),0.0], - [math.sin(angle),math.cos(angle),0.0], - [0.0,0.0,1.0]]) - #set up the translation matrix + mRotate = np.array([[math.cos(angle), -math.sin(angle), 0.0], + [math.sin(angle), math.cos(angle), 0.0], + [0.0, 0.0, 1.0]]) + # set up the translation matrix translateX = float(coordinates[0]) translateY = float(coordinates[1]) - mTranslate = np.array([[1.0,0.0,translateX],[0.0,1.0,translateY],[0.0,0.0,1.0]]) - #set up the scale matrix (handles mirror X) + mTranslate = np.array([[1.0, 0.0, translateX], + [0.0, 1.0, translateY], + [0.0, 0.0, 1.0]]) + # set up the scale matrix (handles mirror X) scaleX = 1.0 - if(transFlags[0]): + if (transFlags[0]): scaleY = -1.0 else: scaleY = 1.0 - mScale = np.array([[scaleX,0.0,0.0],[0.0,scaleY,0.0],[0.0,0.0,1.0]]) - #we need to keep track of all transforms in the hierarchy - #when we add an element to the xy tree, we apply all transforms from the bottom up + mScale = np.array([[scaleX, 0.0, 0.0], + [0.0, scaleY, 0.0], + [0.0, 0.0, 1.0]]) + # we need to keep track of all transforms in the hierarchy + # when we add an element to the xy tree, we apply all transforms from the bottom up transformPath.append((mRotate,mScale,mTranslate)) if delegateFunction != None: delegateFunction(startingStructureName, transformPath) - #starting with a particular structure, we will recursively traverse the tree - #********might have to set the recursion level deeper for big layouts! + # starting with a particular structure, we will recursively traverse the tree + # ********might have to set the recursion level deeper for big layouts! try: if(len(self.structures[startingStructureName].srefs)>0): #does this structure reference any others? - #if so, go through each and call this function again - #if not, return back to the caller (caller can be this function) + # if so, go through each and call this function again + # if not, return back to the caller (caller can be this function) for sref in self.structures[startingStructureName].srefs: - #here, we are going to modify the sref coordinates based on the parent objects rotation + # here, we are going to modify the sref coordinates based on the parent objects rotation self.traverseTheHierarchy(startingStructureName = sref.sName, delegateFunction = delegateFunction, transformPath = transformPath, @@ -205,8 +206,8 @@ class VlsiLayout: except KeyError: debug.error("Could not find structure {} in GDS file.".format(startingStructureName),-1) - #MUST HANDLE AREFs HERE AS WELL - #when we return, drop the last transform from the transformPath + # MUST HANDLE AREFs HERE AS WELL + # when we return, drop the last transform from the transformPath del transformPath[-1] return @@ -218,7 +219,6 @@ class VlsiLayout: for layerNumber in self.layerNumbersInUse: self.processLabelPins((layerNumber, None)) - def populateCoordinateMap(self): def addToXyTree(startingStructureName = None,transformPath = None): uVector = np.array([[1.0],[0.0],[0.0]]) #start with normal basis vectors @@ -281,8 +281,6 @@ class VlsiLayout: self.newLayout(newRoot) self.rootStructureName = newRoot - - def addInstance(self,layoutToAdd,nameOfLayout=0,offsetInMicrons=(0,0),mirror=None,rotate=None): """ Method to insert one layout into another at a particular offset. @@ -406,7 +404,7 @@ class VlsiLayout: #add the sref to the root structure self.structures[self.rootStructureName].paths.append(pathToAdd) - def addText(self, text, layerNumber=0, purposeNumber=0, offsetInMicrons=(0,0), magnification=0.1, rotate = None): + def addText(self, text, layerNumber=0, purposeNumber=0, offsetInMicrons=(0,0), magnification=None, rotate=None): offsetInLayoutUnits = (self.userUnits(offsetInMicrons[0]),self.userUnits(offsetInMicrons[1])) textToAdd = GdsText() textToAdd.drawingLayer = layerNumber @@ -415,7 +413,8 @@ class VlsiLayout: textToAdd.transFlags = [0,0,0] textToAdd.textString = self.padText(text) #textToAdd.transFlags[1] = 1 - textToAdd.magFactor = magnification + if magnification: + textToAdd.magFactor = magnification if rotate: #textToAdd.transFlags[2] = 1 textToAdd.rotateAngle = rotate diff --git a/compiler/processGDS.py b/compiler/processGDS.py new file mode 100755 index 00000000..6b1a7398 --- /dev/null +++ b/compiler/processGDS.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +import sys +from gdsMill import gdsMill + +if len(sys.argv) < 2: + print("Usage: {0} in.gds out.gds".format(sys.argv[0])) + sys.exit(1) + +in_gds_file = sys.argv[1] +out_gds_file = sys.argv[2] +layout = gdsMill.VlsiLayout() +reader = gdsMill.Gds2reader(layout) +reader.loadFromFile(in_gds_file) + + +struct = layout.structures[layout.rootStructureName] +# Do something to the structure +for text in struct.texts: + print(text.textString) + text.magFactor="" + +writer = gdsMill.Gds2writer(layout) +writer.writeToFile(out_gds_file) +