From d6987ac584b188f765c5ba8a129fae17ddf50bfe Mon Sep 17 00:00:00 2001 From: Joey Kunzler Date: Wed, 19 Feb 2020 16:26:52 -0800 Subject: [PATCH 1/2] added purposes to addText(), removed reference to specific tech from gdsMill --- compiler/base/geometry.py | 55 +++++----- compiler/base/pin_layout.py | 77 +++++++------- compiler/gdsMill/gdsMill/gdsPrimitives.py | 9 +- compiler/gdsMill/gdsMill/vlsiLayout.py | 124 +++++++++++----------- 4 files changed, 130 insertions(+), 135 deletions(-) diff --git a/compiler/base/geometry.py b/compiler/base/geometry.py index f354cf02..0041d3c9 100644 --- a/compiler/base/geometry.py +++ b/compiler/base/geometry.py @@ -51,7 +51,7 @@ class geometry: y = item[0] * math.sin(angle) + item[1] * mirr * math.cos(angle) + offset[1] coordinate += [[x, y]] return coordinate - + def normalize(self): """ Re-find the LL and UR points after a transform """ (first, second) = self.boundary @@ -64,14 +64,14 @@ class geometry: def update_boundary(self): """ Update the boundary with a new placement. """ self.compute_boundary(self.offset, self.mirror, self.rotate) - + def compute_boundary(self, offset=vector(0, 0), mirror="", rotate=0): """ Transform with offset, mirror and rotation to get the absolute pin location. We must then re-find the ll and ur. The master is the cell instance. """ if OPTS.netlist_only: self.boundary = [vector(0,0), vector(0,0)] return - + (ll, ur) = [vector(0, 0), vector(self.width, self.height)] if mirror == "MX": @@ -83,7 +83,7 @@ class geometry: elif mirror == "XY": ll = ll.scale(-1, -1) ur = ur.scale(-1, -1) - + if rotate == 90: ll = ll.rotate_scale(-1, 1) ur = ur.rotate_scale(-1, 1) @@ -96,19 +96,19 @@ class geometry: self.boundary = [offset + ll, offset + ur] self.normalize() - + def ll(self): """ Return the lower left corner """ return self.boundary[0] - + def ur(self): """ Return the upper right corner """ return self.boundary[1] - + def lr(self): """ Return the lower right corner """ return vector(self.boundary[1].x, self.boundary[0].y) - + def ul(self): """ Return the upper left corner """ return vector(self.boundary[0].x, self.boundary[1].y) @@ -132,12 +132,12 @@ class geometry: def cx(self): """ Return the center x """ return 0.5 * (self.boundary[0].x + self.boundary[1].x) - + def cy(self): """ Return the center y """ return 0.5 * (self.boundary[0].y + self.boundary[1].y) - - + + class instance(geometry): """ An instance of an instance/module with a specified location and @@ -148,7 +148,7 @@ class instance(geometry): geometry.__init__(self) debug.check(mirror not in ["R90", "R180", "R270"], "Please use rotation and not mirroring during instantiation.") - + self.name = name self.mod = mod self.gds = mod.gds @@ -166,7 +166,7 @@ class instance(geometry): self.width = round_to_grid(mod.width) self.height = round_to_grid(mod.height) self.compute_boundary(offset, mirror, rotate) - + debug.info(4, "creating instance: " + self.name) def get_blockages(self, lpp, top=False): @@ -202,11 +202,11 @@ class instance(geometry): new_blockages.append(self.transform_coords(b,self.offset, mirr, angle)) return new_blockages - + def gds_write_file(self, new_layout): """Recursively writes all the sub-modules in this instance""" debug.info(4, "writing instance: " + self.name) - # make sure to write out my module/structure + # make sure to write out my module/structure # (it will only be written the first time though) self.mod.gds_write_file(self.gds) # now write an instance of my module/structure @@ -215,7 +215,7 @@ class instance(geometry): offsetInMicrons=self.offset, mirror=self.mirror, rotate=self.rotate) - + def place(self, offset, mirror="R0", rotate=0): """ This updates the placement of an instance. """ # Update the placement of an already added instance @@ -224,8 +224,8 @@ class instance(geometry): self.rotate = rotate self.update_boundary() debug.info(3, "placing instance {}".format(self)) - - + + def get_pin(self,name,index=-1): """ Return an absolute pin that is offset and transformed based on this instance location. Index will return one of several pins.""" @@ -243,20 +243,20 @@ class instance(geometry): def get_num_pins(self, name): """ Return the number of pins of a given name """ return len(self.mod.get_pins(name)) - + def get_pins(self,name): """ Return an absolute pin that is offset and transformed based on this instance location. """ - + import copy pin = copy.deepcopy(self.mod.get_pins(name)) - + new_pins = [] for p in pin: - p.transform(self.offset,self.mirror,self.rotate) + p.transform(self.offset,self.mirror,self.rotate) new_pins.append(p) return new_pins - + def __str__(self): """ override print function output """ return "( inst: " + self.name + " @" + str(self.offset) + " mod=" + self.mod.name + " " + self.mirror + " R=" + str(self.rotate) + ")" @@ -293,7 +293,7 @@ class path(geometry): def get_blockages(self, layer): """ Fail since we don't support paths yet. """ assert(0) - + def __str__(self): """ override print function output """ return "path: layer=" + self.layerNumber + " w=" + self.width @@ -329,6 +329,7 @@ class label(geometry): debug.info(4, "writing label (" + str(self.layerNumber) + "): " + self.text) new_layout.addText(text=self.text, layerNumber=self.layerNumber, + layerPurpose=self.layerPurpose, offsetInMicrons=self.offset, magnification=self.zoom, rotate=None) @@ -336,7 +337,7 @@ class label(geometry): def get_blockages(self, layer): """ Returns an empty list since text cannot be blockages. """ return [] - + def __str__(self): """ override print function output """ return "label: " + self.text + " layer=" + str(self.layerNumber) @@ -345,7 +346,7 @@ class label(geometry): """ override print function output """ return "( label: " + self.text + " @" + str(self.offset) + " layer=" + str(self.layerNumber) + " )" - + class rectangle(geometry): """Represents a rectangular shape""" @@ -363,7 +364,7 @@ class rectangle(geometry): debug.info(4, "creating rectangle (" + str(self.layerNumber) + "): " + str(self.width) + "x" + str(self.height) + " @ " + str(self.offset)) - + def get_blockages(self, layer): """ Returns a list of one rectangle if it is on this layer""" if self.layerNumber == layer: diff --git a/compiler/base/pin_layout.py b/compiler/base/pin_layout.py index a057f3e0..f18956a8 100644 --- a/compiler/base/pin_layout.py +++ b/compiler/base/pin_layout.py @@ -30,7 +30,7 @@ class pin_layout: debug.check(self.width() > 0, "Zero width pin.") debug.check(self.height() > 0, "Zero height pin.") - + # if it's a string, use the name if type(layer_name_pp) == str: self._layer = layer_name_pp @@ -93,17 +93,17 @@ class pin_layout: is a major speedup, if pin_layout is used as a key for dicts. """ return self._hash - + def __lt__(self, other): """ Provide a function for ordering items by the ll point """ (ll, ur) = self.rect (oll, our) = other.rect - + if ll.x < oll.x and ll.y < oll.y: return True - + return False - + def __eq__(self, other): """ Check if these are the same pins for duplicate checks """ if isinstance(other, self.__class__): @@ -128,14 +128,14 @@ class pin_layout: max_y = max(max_y, pin.ur().y) self.rect = [vector(min_x, min_y), vector(max_x, max_y)] - + def fix_minarea(self): """ Try to fix minimum area rule. """ min_area = drc("{}_minarea".format(self.layer)) pass - + def inflate(self, spacing=None): """ Inflate the rectangle by the spacing (or other rule) @@ -143,12 +143,12 @@ class pin_layout: """ if not spacing: spacing = 0.5*drc("{0}_to_{0}".format(self.layer)) - + (ll, ur) = self.rect spacing = vector(spacing, spacing) newll = ll - spacing newur = ur + spacing - + return (newll, newur) def intersection(self, other): @@ -191,7 +191,7 @@ class pin_layout: y_overlaps = True return y_overlaps - + def xcontains(self, other): """ Check if shape contains the x overlap """ (ll, ur) = self.rect @@ -205,13 +205,13 @@ class pin_layout: (oll, our) = other.rect return (oll.y >= ll.y and our.y <= ur.y) - + def contains(self, other): """ Check if a shape contains another rectangle """ # If it is the same shape entirely, it is contained! if self == other: return True - + # Can only overlap on the same layer if not self.same_lpp(self.lpp, other.lpp): return False @@ -230,13 +230,13 @@ class pin_layout: if shape.contains(self): return True return False - + def overlaps(self, other): """ Check if a shape overlaps with a rectangle """ # Can only overlap on the same layer if not self.same_lpp(self.lpp, other.lpp): return False - + x_overlaps = self.xoverlaps(other) y_overlaps = self.yoverlaps(other) @@ -245,11 +245,11 @@ class pin_layout: def area(self): """ Return the area. """ return self.height()*self.width() - + def height(self): """ Return height. Abs is for pre-normalized value.""" return abs(self.rect[1].y-self.rect[0].y) - + def width(self): """ Return width. Abs is for pre-normalized value.""" return abs(self.rect[1].x-self.rect[0].x) @@ -260,7 +260,7 @@ class pin_layout: ll = vector(min(first[0], second[0]), min(first[1], second[1])) ur = vector(max(first[0], second[0]), max(first[1], second[1])) self.rect=[ll, ur] - + def transform(self, offset, mirror, rotate): """ Transform with offset, mirror and rotation @@ -278,7 +278,7 @@ class pin_layout: elif mirror == "XY": ll = ll.scale(-1, -1) ur = ur.scale(-1, -1) - + if rotate == 90: ll = ll.rotate_scale(-1, 1) ur = ur.rotate_scale(-1, 1) @@ -303,7 +303,7 @@ class pin_layout: def cy(self): """ Center y """ return 0.5*(self.rect[0].y+self.rect[1].y) - + # The four possible corners def ll(self): """ Lower left point """ @@ -320,7 +320,7 @@ class pin_layout: def ur(self): """ Upper right point """ return self.rect[1] - + # The possible y edge values def uy(self): """ Upper y value """ @@ -331,15 +331,15 @@ class pin_layout: return self.rect[0].y # The possible x edge values - + def lx(self): """ Left x value """ return self.rect[0].x - + def rx(self): """ Right x value """ return self.rect[1].x - + # The edge centers def rc(self): """ Right center point """ @@ -350,7 +350,7 @@ class pin_layout: """ Left center point """ return vector(self.rect[0].x, 0.5*(self.rect[0].y+self.rect[1].y)) - + def uc(self): """ Upper center point """ return vector(0.5*(self.rect[0].x+self.rect[1].x), @@ -378,6 +378,7 @@ class pin_layout: # imported into Magic. newLayout.addText(text=self.name, layerNumber=layer_num, + purposeNumber=purpose, offsetInMicrons=self.center(), magnification=GDS["zoom"], rotate=None) @@ -392,7 +393,7 @@ class pin_layout: dy = min(r1_ur.y, r2_ur.y) - max(r1_ll.y, r2_ll.y) dx = min(r1_ur.x, r2_ur.x) - max(r1_ll.x, r2_ll.x) - + if dx >= 0 and dy >= 0: return [dx, dy] else: @@ -407,7 +408,7 @@ class pin_layout: def dist(x1, y1, x2, y2): return math.sqrt((x2-x1)**2 + (y2-y1)**2) - + left = r2_ur.x < r1_ll.x right = r1_ur.x < r2_ll.x bottom = r2_ur.y < r1_ll.y @@ -432,7 +433,7 @@ class pin_layout: else: # rectangles intersect return 0 - + def overlap_length(self, other): """ Calculate the intersection segment and determine its length @@ -453,7 +454,7 @@ class pin_layout: # This is where we had a corner intersection or none return 0 - + def compute_overlap_segment(self, other): """ Calculate the intersection segment of two rectangles @@ -469,19 +470,19 @@ class pin_layout: r2_lr = vector(r2_ur.x, r2_ll.y) from itertools import tee - + def pairwise(iterable): "s -> (s0,s1), (s1,s2), (s2, s3), ..." a, b = tee(iterable) next(b, None) return zip(a, b) - + # R1 edges CW r1_cw_points = [r1_ll, r1_ul, r1_ur, r1_lr, r1_ll] r1_edges = [] for (p, q) in pairwise(r1_cw_points): r1_edges.append([p, q]) - + # R2 edges CW r2_cw_points = [r2_ll, r2_ul, r2_ur, r2_lr, r2_ll] r2_edges = [] @@ -509,9 +510,9 @@ class pin_layout: q.y <= max(p.y, r.y) and \ q.y >= min(p.y, r.y): return True - + return False - + def segment_intersection(self, s1, s2): """ Determine the intersection point of two segments @@ -524,22 +525,22 @@ class pin_layout: a1 = b.y - a.y b1 = a.x - b.x c1 = a1*a.x + b1*a.y - + # Line CD represented as a2x + b2y = c2 a2 = d.y - c.y b2 = c.x - d.x c2 = a2*c.x + b2*c.y - + determinant = a1*b2 - a2*b1 if determinant != 0: x = (b2*c1 - b1*c2)/determinant y = (a1*c2 - a2*c1)/determinant - + r = vector(x, y).snap_to_grid() if self.on_segment(a, r, b) and self.on_segment(c, r, d): return r - + return None def same_lpp(self, lpp1, lpp2): @@ -549,5 +550,5 @@ class pin_layout: """ if lpp1[1] == None or lpp2[1] == None: return lpp1[0] == lpp2[0] - + return lpp1[0] == lpp2[0] and lpp1[1] == lpp2[1] diff --git a/compiler/gdsMill/gdsMill/gdsPrimitives.py b/compiler/gdsMill/gdsMill/gdsPrimitives.py index 13b8acf9..8e07524c 100644 --- a/compiler/gdsMill/gdsMill/gdsPrimitives.py +++ b/compiler/gdsMill/gdsMill/gdsPrimitives.py @@ -1,12 +1,5 @@ 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 represent a GDS Structure Object""" def __init__(self): @@ -147,7 +140,7 @@ class GdsText: self.elementFlags="" self.plex="" self.drawingLayer="" - self.purposeLayer=purposeLayer + self.purposeLayer=0 self.transFlags=[0,0,0] self.magFactor="" self.rotateAngle="" diff --git a/compiler/gdsMill/gdsMill/vlsiLayout.py b/compiler/gdsMill/gdsMill/vlsiLayout.py index 412a430c..979180cd 100644 --- a/compiler/gdsMill/gdsMill/vlsiLayout.py +++ b/compiler/gdsMill/gdsMill/vlsiLayout.py @@ -35,7 +35,7 @@ class VlsiLayout: modDate.hour, modDate.minute, modDate.second) - + self.info = dict() #information gathered from the GDSII header self.info['units']=self.units self.info['dates']=(modDate.year, @@ -52,12 +52,12 @@ class VlsiLayout: modDate.second) 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. - + #temp variables used in delegate functions self.tempCoordinates=None self.tempPassFail = True @@ -73,14 +73,14 @@ class VlsiLayout: 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) newY = coordinate[0]*math.sin(angle) + coordinate[1]*math.cos(angle) coordinatesRotate.extend((newX,newY)) return coordinatesRotate - + def rename(self,newName): #take the root structure and copy it to a new structure with the new name self.structures[newName] = self.structures[self.rootStructureName] @@ -129,8 +129,8 @@ class VlsiLayout: modDate.hour, modDate.minute, modDate.second) - - + + #repopulate the 2d map so drawing occurs correctly self.prepareForWrite() @@ -155,15 +155,15 @@ 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, + + 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 + #parameters explicitly if startingStructureName == None: - startingStructureName = self.rootStructureName + startingStructureName = self.rootStructureName - #set up the rotation matrix + #set up the rotation matrix if(rotateAngle == None or rotateAngle == ""): angle = 0 else: @@ -193,10 +193,10 @@ class VlsiLayout: 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 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 - self.traverseTheHierarchy(startingStructureName = sref.sName, + #here, we are going to modify the sref coordinates based on the parent objects rotation + self.traverseTheHierarchy(startingStructureName = sref.sName, delegateFunction = delegateFunction, transformPath = transformPath, rotateAngle = sref.rotateAngle, @@ -204,12 +204,12 @@ class VlsiLayout: coordinates = sref.coordinates) 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 del transformPath[-1] return - + def initialize(self): self.deduceHierarchy() # self.traverseTheHierarchy() @@ -217,17 +217,17 @@ 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 vVector = np.array([[0.0],[1.0],[0.0]]) origin = np.array([[0.0],[0.0],[1.0]]) #and an origin (Z component is 1.0 to indicate position instead of vector) - #make a copy of all the transforms and reverse it + #make a copy of all the transforms and reverse it reverseTransformPath = transformPath[:] if len(reverseTransformPath) > 1: - reverseTransformPath.reverse() + reverseTransformPath.reverse() #now go through each transform and apply them to our basis and origin in succession for transform in reverseTransformPath: origin = np.dot(transform[0], origin) #rotate @@ -237,20 +237,20 @@ class VlsiLayout: uVector = np.dot(transform[1], uVector) #scale vVector = np.dot(transform[1], vVector) #scale origin = np.dot(transform[2], origin) #translate - #we don't need to do a translation on the basis vectors + #we don't need to do a translation on the basis vectors #uVector = transform[2] * uVector #translate #vVector = transform[2] * vVector #translate #populate the xyTree with each structureName and coordinate space self.xyTree.append((startingStructureName,origin,uVector,vVector)) self.traverseTheHierarchy(delegateFunction = addToXyTree) - + def microns(self, userUnits): """Utility function to convert user units to microns""" userUnit = self.units[1]/self.units[0] userUnitsPerMicron = userUnit / userunit layoutUnitsPerMicron = userUnitsPerMicron / self.units[0] return userUnits / layoutUnitsPerMicron - + def userUnits(self, microns): """Utility function to convert microns to user units""" userUnit = self.units[1]/self.units[0] @@ -270,7 +270,7 @@ class VlsiLayout: if self.debug: debug.info(0,"DEBUG: GdsMill vlsiLayout: changeRoot: %s "%newRoot) - + # Determine if newRoot exists # layoutToAdd (default) or nameOfLayout if (newRoot == 0 | ((newRoot not in self.structures) & ~create)): @@ -282,19 +282,19 @@ class VlsiLayout: 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. """ offsetInLayoutUnits = (self.userUnits(offsetInMicrons[0]),self.userUnits(offsetInMicrons[1])) - if self.debug: + if self.debug: debug.info(0,"DEBUG: GdsMill vlsiLayout: addInstance: type {0}, nameOfLayout {1}".format(type(layoutToAdd),nameOfLayout)) debug.info(0,"DEBUG: name={0} offset={1} mirror={2} rotate={3}".format(layoutToAdd.rootStructureName,offsetInMicrons, mirror, rotate)) - # Determine if we are instantiating the root design of + # Determine if we are instantiating the root design of # layoutToAdd (default) or nameOfLayout if nameOfLayout == 0: StructureFound = True @@ -303,7 +303,7 @@ class VlsiLayout: StructureName = nameOfLayout #layoutToAdd StructureFound = False for structure in layoutToAdd.structures: - if StructureName in structure: + if StructureName in structure: if self.debug: debug.info(1,"DEBUG: Structure %s Found"%StructureName) StructureFound = True @@ -311,7 +311,7 @@ class VlsiLayout: debug.check(StructureFound,"Could not find layout to instantiate {}".format(StructureName)) - # If layoutToAdd is a unique object (not this), then copy hierarchy, + # If layoutToAdd is a unique object (not this), then copy hierarchy, # otherwise, if it is a text name of an internal structure, use it. if layoutToAdd != self: @@ -330,7 +330,7 @@ class VlsiLayout: layoutToAddSref.coordinates = offsetInLayoutUnits if mirror or rotate: - + layoutToAddSref.transFlags = [0,0,0] # transFlags = (mirror around x-axis, magnification, rotation) # If magnification or rotation is true, it is the flags are then @@ -356,7 +356,7 @@ class VlsiLayout: #add the sref to the root structure self.structures[self.rootStructureName].srefs.append(layoutToAddSref) - + def addBox(self,layerNumber=0, purposeNumber=0, offsetInMicrons=(0,0), width=1.0, height=1.0,center=False): """ Method to add a box to a layout @@ -373,7 +373,7 @@ class VlsiLayout: (offsetInLayoutUnits[0],offsetInLayoutUnits[1]+heightInLayoutUnits), offsetInLayoutUnits] else: - startPoint = (offsetInLayoutUnits[0]-widthInLayoutUnits/2.0, offsetInLayoutUnits[1]-heightInLayoutUnits/2.0) + startPoint = (offsetInLayoutUnits[0]-widthInLayoutUnits/2.0, offsetInLayoutUnits[1]-heightInLayoutUnits/2.0) coordinates=[startPoint, (startPoint[0]+widthInLayoutUnits,startPoint[1]), (startPoint[0]+widthInLayoutUnits,startPoint[1]+heightInLayoutUnits), @@ -386,7 +386,7 @@ class VlsiLayout: boundaryToAdd.purposeLayer = purposeNumber #add the sref to the root structure self.structures[self.rootStructureName].boundaries.append(boundaryToAdd) - + def addPath(self, layerNumber=0, purposeNumber=0, coordinates=[(0,0)], width=1.0): """ Method to add a path to a layout @@ -405,11 +405,12 @@ class VlsiLayout: pathToAdd.coordinates = layoutUnitCoordinates #add the sref to the root structure self.structures[self.rootStructureName].paths.append(pathToAdd) - - def addText(self, text, layerNumber=0, offsetInMicrons=(0,0), magnification=0.1, rotate = None): + + def addText(self, text, layerNumber=0, purposeNumber=0, offsetInMicrons=(0,0), magnification=0.1, rotate = None): offsetInLayoutUnits = (self.userUnits(offsetInMicrons[0]),self.userUnits(offsetInMicrons[1])) textToAdd = GdsText() textToAdd.drawingLayer = layerNumber + textToAdd.purposeLayer = purposeNumber textToAdd.coordinates = [offsetInLayoutUnits] textToAdd.transFlags = [0,0,0] textToAdd.textString = self.padText(text) @@ -438,7 +439,7 @@ class VlsiLayout: return 1 else: return 0 - + def intersectionPoint(self,startPoint1,endPoint1,startPoint2,endPoint2): if((endPoint1[0]-startPoint1[0])!=0 and (endPoint2[0]-startPoint2[0])!=0): pSlope = (endPoint1[1]-startPoint1[1])/(endPoint1[0]-startPoint1[0]) @@ -458,7 +459,7 @@ class VlsiLayout: newY = None elif((endPoint1[0]-startPoint1[0])==0 and (endPoint2[0]-startPoint2[0])!=0): qSlope = (endPoint2[1]-startPoint2[1])/(endPoint2[0]-startPoint2[0]) - qIntercept = startPoint2[1]-qSlope*startPoint2[0] + qIntercept = startPoint2[1]-qSlope*startPoint2[0] newX=endPoint1[0] newY=qSlope*newX+qIntercept elif((endPoint1[0]-startPoint1[0])!=0 and (endPoint2[0]-startPoint2[0])==0): @@ -467,14 +468,14 @@ class VlsiLayout: newX=endPoint2[0] newY=pSlope*newX+pIntercept return (newX,newY) - + def isCollinear(self,testPoint,point1,point2): slope1 = (testPoint[1]-point1[1])/(testPoint[0]-point1[0]) slope2 = (point2[1]-point1[1])/(point2[0]-point1[0]) if slope1 == slope2: return True return False - + def doShapesIntersect(self,shape1Coordinates, shape2Coordinates): """ Utility function to determine if 2 arbitrary shapes intersect. @@ -491,7 +492,7 @@ class VlsiLayout: if(self.isBounded(intersect,startPoint1,endPoint1) and self.isBounded(intersect,startPoint2,endPoint2)): return True #these shapes overlap! return False #these shapes are ok - + def isPointInsideOfBox(self,pointCoordinates,boxCoordinates): """ Check if a point is contained in the shape @@ -516,7 +517,7 @@ class VlsiLayout: pointCoordinates[1] Date: Thu, 20 Feb 2020 18:35:54 -0800 Subject: [PATCH 2/2] fixed variable typo --- compiler/base/geometry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/base/geometry.py b/compiler/base/geometry.py index 0041d3c9..cfda3553 100644 --- a/compiler/base/geometry.py +++ b/compiler/base/geometry.py @@ -329,7 +329,7 @@ class label(geometry): debug.info(4, "writing label (" + str(self.layerNumber) + "): " + self.text) new_layout.addText(text=self.text, layerNumber=self.layerNumber, - layerPurpose=self.layerPurpose, + purposeNumber=self.layerPurpose, offsetInMicrons=self.offset, magnification=self.zoom, rotate=None)