From 378993ca22848d4e1327206915bebef6b354b237 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Tue, 4 Sep 2018 16:35:40 -0700 Subject: [PATCH 1/8] Found rotate bug in transformCoordinate. Cleaned up transFlags. --- compiler/base/contact.py | 31 +++--- compiler/base/geometry.py | 80 +++++++------- compiler/base/hierarchy_layout.py | 7 +- compiler/base/pin_layout.py | 8 +- compiler/gdsMill/gdsMill/gds2reader.py | 6 +- compiler/gdsMill/gdsMill/gds2writer.py | 24 ++--- compiler/gdsMill/gdsMill/gdsPrimitives.py | 2 +- compiler/gdsMill/gdsMill/vlsiLayout.py | 44 ++++---- compiler/modules/dff_inv_array.py | 4 +- compiler/pgates/pinv.py | 2 + compiler/router/grid.py | 3 - compiler/router/router.py | 105 ++++++++----------- compiler/router/tests/10_supply_grid_test.py | 4 +- technology/freepdk45/tech/tech.py | 1 + technology/scn3me_subm/tech/tech.py | 1 + 15 files changed, 156 insertions(+), 166 deletions(-) diff --git a/compiler/base/contact.py b/compiler/base/contact.py index 5c300033..9ffae803 100644 --- a/compiler/base/contact.py +++ b/compiler/base/contact.py @@ -15,22 +15,27 @@ class contact(hierarchy_design.hierarchy_design): necessary to import layouts into Magic which requires the select to be in the same GDS hierarchy as the contact. """ + + unique_id = 1 + def __init__(self, layer_stack, dimensions=[1,1], implant_type=None, well_type=None): if implant_type or well_type: - name = "{0}_{1}_{2}_{3}x{4}_{5}{6}".format(layer_stack[0], - layer_stack[1], - layer_stack[2], - dimensions[0], - dimensions[1], - implant_type, - well_type) + name = "{0}_{1}_{2}_{3}x{4}_{5}{6}_{7}".format(layer_stack[0], + layer_stack[1], + layer_stack[2], + dimensions[0], + dimensions[1], + implant_type, + well_type, + contact.unique_id) else: - name = "{0}_{1}_{2}_{3}x{4}".format(layer_stack[0], - layer_stack[1], - layer_stack[2], - dimensions[0], - dimensions[1]) - + name = "{0}_{1}_{2}_{3}x{4}_{5}".format(layer_stack[0], + layer_stack[1], + layer_stack[2], + dimensions[0], + dimensions[1], + contact.unique_id) + contact.unique_id += 1 hierarchy_design.hierarchy_design.__init__(self, name) debug.info(4, "create contact object {0}".format(name)) diff --git a/compiler/base/geometry.py b/compiler/base/geometry.py index 7144a2cf..682b783b 100644 --- a/compiler/base/geometry.py +++ b/compiler/base/geometry.py @@ -34,14 +34,14 @@ class geometry: # coordinate += [(x, y)] # return coordinate - def transform_coords(self, coords, offset, mirr, angle): - """Calculate coordinates after flip, rotate, and shift""" - coordinate = [] - for item in coords: - x = item[0]*math.cos(angle) - item[1]*mirr*math.sin(angle) + offset[0] - y = item[0]*math.sin(angle) + item[1]*mirr*math.cos(angle) + offset[1] - coordinate += [[x, y]] - return coordinate + # def transform_coords(self, coords, offset, mirr, angle): + # """Calculate coordinates after flip, rotate, and shift""" + # coordinate = [] + # for item in coords: + # x = item[0]*math.cos(angle) - item[1]*mirr*math.sin(angle) + offset[0] + # 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 """ @@ -148,40 +148,40 @@ class instance(geometry): debug.info(4, "creating instance: " + self.name) - def get_blockages(self, layer, top=False): - """ Retrieve rectangular blockages of all modules in this instance. - Apply the transform of the instance placement to give absolute blockages.""" - angle = math.radians(float(self.rotate)) - mirr = 1 - if self.mirror=="R90": - angle += math.radians(90.0) - elif self.mirror=="R180": - angle += math.radians(180.0) - elif self.mirror=="R270": - angle += math.radians(270.0) - elif self.mirror=="MX": - mirr = -1 - elif self.mirror=="MY": - mirr = -1 - angle += math.radians(180.0) - elif self.mirror=="XY": - mirr = 1 - angle += math.radians(180.0) + # def get_blockages(self, layer, top=False): + # """ Retrieve rectangular blockages of all modules in this instance. + # Apply the transform of the instance placement to give absolute blockages.""" + # angle = math.radians(float(self.rotate)) + # mirr = 1 + # if self.mirror=="R90": + # angle += math.radians(90.0) + # elif self.mirror=="R180": + # angle += math.radians(180.0) + # elif self.mirror=="R270": + # angle += math.radians(270.0) + # elif self.mirror=="MX": + # mirr = -1 + # elif self.mirror=="MY": + # mirr = -1 + # angle += math.radians(180.0) + # elif self.mirror=="XY": + # mirr = 1 + # angle += math.radians(180.0) - if self.mod.is_library_cell: - # For lib cells, block the whole thing except on metal3 - # since they shouldn't use metal3 - if layer==tech.layer["metal1"] or layer==tech.layer["metal2"]: - return [self.transform_coords(self.mod.get_boundary(), self.offset, mirr, angle)] - else: - return [] - else: + # if self.mod.is_library_cell: + # # For lib cells, block the whole thing except on metal3 + # # since they shouldn't use metal3 + # if layer==tech.layer["metal1"] or layer==tech.layer["metal2"]: + # return [self.transform_coords(self.mod.get_boundary(), self.offset, mirr, angle)] + # else: + # return [] + # else: - blockages = self.mod.get_blockages(layer) - new_blockages = [] - for b in blockages: - new_blockages.append(self.transform_coords(b,self.offset, mirr, angle)) - return new_blockages + # blockages = self.mod.get_blockages(layer) + # new_blockages = [] + # for b in blockages: + # 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""" diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index 01a48f89..83a8420b 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -379,12 +379,10 @@ class layout(lef.lef): dimensions=size, implant_type=implant_type, well_type=well_type) - - debug.check(mirror=="R0","Use rotate to rotate vias instead of mirror.") - height = via.height width = via.width - + debug.check(mirror=="R0","Use rotate to rotate vias instead of mirror.") + if rotate==0: corrected_offset = offset + vector(-0.5*width,-0.5*height) elif rotate==90: @@ -847,6 +845,7 @@ class layout(lef.lef): """ Add a single power pin from M3 down to M1 at the given center location """ + debug.info(0,"Adding power pin {0} at {1} rotate={2}".format(name, loc, rotate)) self.add_via_center(layers=("metal1", "via1", "metal2"), offset=loc, rotate=rotate) diff --git a/compiler/base/pin_layout.py b/compiler/base/pin_layout.py index aa6bacfc..7e454df4 100644 --- a/compiler/base/pin_layout.py +++ b/compiler/base/pin_layout.py @@ -36,16 +36,14 @@ class pin_layout: def __eq__(self, other): """ Check if these are the same pins for duplicate checks """ if isinstance(other, self.__class__): - return (self.name==other.name and self.layer==other.layer and self.rect == other.rect) + return (self.layer==other.layer and self.rect == other.rect) else: return False def overlaps(self, other): """ Check if a shape overlaps with a rectangle """ - ll = self.rect[0] - ur = self.rect[1] - oll = other.rect[0] - our = other.rect[1] + (ll,ur) = self.rect + (oll,our) = other.rect # Start assuming no overlaps x_overlaps = False y_overlaps = False diff --git a/compiler/gdsMill/gdsMill/gds2reader.py b/compiler/gdsMill/gdsMill/gds2reader.py index 3d63cf53..85fc0c66 100644 --- a/compiler/gdsMill/gdsMill/gds2reader.py +++ b/compiler/gdsMill/gdsMill/gds2reader.py @@ -294,7 +294,7 @@ class Gds2reader: mirrorFlag = bool(transFlags&0x8000) ##these flags are a bit sketchy rotateFlag = bool(transFlags&0x0002) magnifyFlag = bool(transFlags&0x0004) - thisSref.transFlags=[mirrorFlag,rotateFlag,magnifyFlag] + thisSref.transFlags=[mirrorFlag,magnifyFlag,rotateFlag] if(self.debugToTerminal==1): print("\t\t\tMirror X:"+str(mirrorFlag)) print( "\t\t\tRotate:"+str(rotateFlag)) @@ -345,7 +345,7 @@ class Gds2reader: mirrorFlag = bool(transFlags&0x8000) ##these flags are a bit sketchy rotateFlag = bool(transFlags&0x0002) magnifyFlag = bool(transFlags&0x0004) - thisAref.transFlags=[mirrorFlag,rotateFlag,magnifyFlag] + thisAref.transFlags=[mirrorFlag,magnifyFlag,rotateFlag] if(self.debugToTerminal==1): print("\t\t\tMirror X:"+str(mirrorFlag)) print("\t\t\tRotate:"+str(rotateFlag)) @@ -408,7 +408,7 @@ class Gds2reader: mirrorFlag = bool(transFlags&0x8000) ##these flags are a bit sketchy rotateFlag = bool(transFlags&0x0002) magnifyFlag = bool(transFlags&0x0004) - thisText.transFlags=[mirrorFlag,rotateFlag,magnifyFlag] + thisText.transFlags=[mirrorFlag,magnifyFlag,rotateFlag] if(self.debugToTerminal==1): print("\t\t\tMirror X:"+str(mirrorFlag)) print("\t\t\tRotate:"+str(rotateFlag)) diff --git a/compiler/gdsMill/gdsMill/gds2writer.py b/compiler/gdsMill/gdsMill/gds2writer.py index ce9d27e2..3ab1c0b7 100644 --- a/compiler/gdsMill/gdsMill/gds2writer.py +++ b/compiler/gdsMill/gdsMill/gds2writer.py @@ -280,15 +280,15 @@ class Gds2writer: if(thisSref.transFlags!=""): idBits=b'\x1A\x01' mirrorFlag = int(thisSref.transFlags[0])<<15 - rotateFlag = int(thisSref.transFlags[1])<<1 - magnifyFlag = int(thisSref.transFlags[2])<<3 + rotateFlag = int(thisSref.transFlags[2])<<1 + magnifyFlag = int(thisSref.transFlags[1])<<3 transFlags = struct.pack(">H",mirrorFlag|rotateFlag|magnifyFlag) self.writeRecord(idBits+transFlags) - if(thisSref.magFactor!=""): + if(thisSref.transFlags[1]): idBits=b'\x1B\x05' magFactor=self.ibmDataFromIeeeDouble(thisSref.magFactor) self.writeRecord(idBits+magFactor) - if(thisSref.rotateAngle!=""): + if(thisSref.transFlags[2]): idBits=b'\x1C\x05' rotateAngle=self.ibmDataFromIeeeDouble(thisSref.rotateAngle) self.writeRecord(idBits+rotateAngle) @@ -327,15 +327,15 @@ class Gds2writer: if(thisAref.transFlags): idBits=b'\x1A\x01' mirrorFlag = int(thisAref.transFlags[0])<<15 - rotateFlag = int(thisAref.transFlags[1])<<1 - magnifyFlag = int(thisAref.transFlags[0])<<3 + rotateFlag = int(thisAref.transFlags[2])<<1 + magnifyFlag = int(thisAref.transFlags[1])<<3 transFlags = struct.pack(">H",mirrorFlag|rotateFlag|magnifyFlag) self.writeRecord(idBits+transFlags) - if(thisAref.magFactor): + if(thisAref.transFlags[1]): idBits=b'\x1B\x05' magFactor=self.ibmDataFromIeeeDouble(thisAref.magFactor) self.writeRecord(idBits+magFactor) - if(thisAref.rotateAngle): + if(thisAref.transFlags[2]): idBits=b'\x1C\x05' rotateAngle=self.ibmDataFromIeeeDouble(thisAref.rotateAngle) self.writeRecord(idBits+rotateAngle) @@ -374,15 +374,15 @@ class Gds2writer: if(thisText.transFlags != ""): idBits=b'\x1A\x01' mirrorFlag = int(thisText.transFlags[0])<<15 - rotateFlag = int(thisText.transFlags[1])<<1 - magnifyFlag = int(thisText.transFlags[0])<<3 + rotateFlag = int(thisText.transFlags[2])<<1 + magnifyFlag = int(thisText.transFlags[1])<<3 transFlags = struct.pack(">H",mirrorFlag|rotateFlag|magnifyFlag) self.writeRecord(idBits+transFlags) - if(thisText.magFactor != ""): + if(thisText.transFlags[1]): idBits=b'\x1B\x05' magFactor=self.ibmDataFromIeeeDouble(thisText.magFactor) self.writeRecord(idBits+magFactor) - if(thisText.rotateAngle != ""): + if(thisText.transFlags[2]): idBits=b'\x1C\x05' rotateAngle=self.ibmDataFromIeeeDouble(thisText.rotateAngle) self.writeRecord(idBits+rotateAngle) diff --git a/compiler/gdsMill/gdsMill/gdsPrimitives.py b/compiler/gdsMill/gdsMill/gdsPrimitives.py index 9b148dce..dc43fea6 100644 --- a/compiler/gdsMill/gdsMill/gdsPrimitives.py +++ b/compiler/gdsMill/gdsMill/gdsPrimitives.py @@ -141,7 +141,7 @@ class GdsText: self.plex="" self.drawingLayer="" self.purposeLayer = None - self.transFlags=[0,00] + self.transFlags=[0,0,0] self.magFactor="" self.rotateAngle="" self.pathType="" diff --git a/compiler/gdsMill/gdsMill/vlsiLayout.py b/compiler/gdsMill/gdsMill/vlsiLayout.py index b9813149..431d7d23 100644 --- a/compiler/gdsMill/gdsMill/vlsiLayout.py +++ b/compiler/gdsMill/gdsMill/vlsiLayout.py @@ -64,10 +64,11 @@ class VlsiLayout: #helper method to rotate a list of coordinates angle=math.radians(float(0)) if(rotateAngle): - angle = math.radians(float(repr(rotateAngle))) + angle = math.radians(float(rotateAngle)) 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)) @@ -274,8 +275,9 @@ class VlsiLayout: Method to insert one layout into another at a particular offset. """ offsetInLayoutUnits = (self.userUnits(offsetInMicrons[0]),self.userUnits(offsetInMicrons[1])) - if self.debug==1: - debug.info(0,"DEBUG: GdsMill vlsiLayout: addInstance: type %s, nameOfLayout "%type(layoutToAdd),nameOfLayout) + 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)) @@ -295,7 +297,7 @@ class VlsiLayout: - # If layoutToAdd is a unique object (not this), then copy heirarchy, + # 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: @@ -316,9 +318,7 @@ class VlsiLayout: if mirror or rotate: layoutToAddSref.transFlags = [0,0,0] - # This is NOT the same as the order in the GDS spec! - # It gets written out in gds2writer in the right order though. - # transFlags = (mirror around x-axis, rotation, magnification) + # transFlags = (mirror around x-axis, magnification, rotation) # If magnification or rotation is true, it is the flags are then # followed by an amount in the record if mirror=="R90": @@ -328,17 +328,16 @@ class VlsiLayout: if mirror=="R270": rotate = 270.0 if rotate: - #layoutToAddSref.transFlags = [0,1,0] + layoutToAddSref.transFlags[2] = 1 layoutToAddSref.rotateAngle = rotate if mirror == "x" or mirror == "MX": - layoutToAddSref.transFlags = [1,0,0] + layoutToAddSref.transFlags[0] = 1 if mirror == "y" or mirror == "MY": #NOTE: "MY" option will override specified rotate angle - #layoutToAddSref.transFlags = [1,1,0] - layoutToAddSref.transFlags = [1,0,0] + layoutToAddSref.transFlags[0] = 1 + layoutToAddSref.transFlags[2] = 1 layoutToAddSref.rotateAngle = 180.0 if mirror == "xy" or mirror == "XY": #NOTE: "XY" option will override specified rotate angle - #layoutToAddSref.transFlags = [0,1,0] - layoutToAddSref.transFlags = [0,0,0] + layoutToAddSref.transFlags[2] = 1 layoutToAddSref.rotateAngle = 180.0 #add the sref to the root structure @@ -405,10 +404,10 @@ class VlsiLayout: if(len(text)%2 == 1): text = text + '\x00' textToAdd.textString = text - textToAdd.transFlags = [0,0,1] + textToAdd.transFlags[1] = 1 textToAdd.magFactor = magnification if rotate: - textToAdd.transFlags = [0,1,1] + textToAdd.transFlags[2] = 1 textToAdd.rotateAngle = rotate #add the sref to the root structure self.structures[self.rootStructureName].texts.append(textToAdd) @@ -816,10 +815,10 @@ class VlsiLayout: """ (structureName,structureOrigin,structureuVector,structurevVector)=structure + #print(structureName,"u",structureuVector.transpose(),"v",structurevVector.transpose(),"o",structureOrigin.transpose()) boundaries = [] for boundary in self.structures[str(structureName)].boundaries: - # Pin enclosures only work on rectangular pins so ignore any non rectangle - # This may report not finding pins, but the user should fix this by adding a rectangle. + # FIXME: Right now, this only supports rectangular shapes! if len(boundary.coordinates)!=5: continue if layer==boundary.drawingLayer: @@ -827,10 +826,11 @@ class VlsiLayout: right_top=boundary.coordinates[2] # Rectangle is [leftx, bottomy, rightx, topy]. boundaryRect=[left_bottom[0],left_bottom[1],right_top[0],right_top[1]] + # perform the rotation boundaryRect=self.transformRectangle(boundaryRect,structureuVector,structurevVector) + # add the offset boundaryRect=[boundaryRect[0]+structureOrigin[0].item(),boundaryRect[1]+structureOrigin[1].item(), boundaryRect[2]+structureOrigin[0].item(),boundaryRect[3]+structureOrigin[1].item()] - boundaries.append(boundaryRect) return boundaries @@ -858,8 +858,12 @@ class VlsiLayout: """ Rotate a coordinate in space. """ - x=coordinate[0]*uVector[0].item()+coordinate[1]*uVector[1].item() - y=coordinate[1]*vVector[1].item()+coordinate[0]*vVector[0].item() + # MRG: 9/3/18 Incorrect matrixi multiplication! + # This is fixed to be: + # |u[0] v[0]| |x| |x'| + # |u[1] v[1]|x|y|=|y'| + x=coordinate[0]*uVector[0].item()+coordinate[1]*vVector[0].item() + y=coordinate[0]*uVector[1].item()+coordinate[1]*vVector[1].item() transformCoordinate=[x,y] return transformCoordinate diff --git a/compiler/modules/dff_inv_array.py b/compiler/modules/dff_inv_array.py index c88fabd3..c2455821 100644 --- a/compiler/modules/dff_inv_array.py +++ b/compiler/modules/dff_inv_array.py @@ -115,11 +115,11 @@ class dff_inv_array(design.design): def add_layout_pins(self): for row in range(self.rows): for col in range(self.columns): - # Continous vdd rail along with label. + # Adds power pin on left of row vdd_pin=self.dff_insts[row,col].get_pin("vdd") self.add_power_pin("vdd", vdd_pin.lc()) - # Continous gnd rail along with label. + # Adds gnd pin on left of row gnd_pin=self.dff_insts[row,col].get_pin("gnd") self.add_power_pin("gnd", gnd_pin.lc()) diff --git a/compiler/pgates/pinv.py b/compiler/pgates/pinv.py index f0df378d..e39f95bc 100644 --- a/compiler/pgates/pinv.py +++ b/compiler/pgates/pinv.py @@ -171,6 +171,8 @@ class pinv(pgate.pgate): offset=vector(0.5*self.width,self.height), width=self.width) + + def create_ptx(self): """ Create the PMOS and NMOS netlist. diff --git a/compiler/router/grid.py b/compiler/router/grid.py index 5f60da4e..8eb063cf 100644 --- a/compiler/router/grid.py +++ b/compiler/router/grid.py @@ -36,9 +36,6 @@ class grid: def add_blockage_shape(self,ll,ur,z): debug.info(3,"Adding blockage ll={0} ur={1} z={2}".format(str(ll),str(ur),z)) - if ll[0]<42 and ll[0]>38 and ll[1]<3 and ll[1]>0: - debug.info(0,"Adding blockage ll={0} ur={1} z={2}".format(str(ll),str(ur),z)) - block_list = [] for x in range(int(ll[0]),int(ur[0])+1): for y in range(int(ll[1]),int(ur[1])+1): diff --git a/compiler/router/router.py b/compiler/router/router.py index bb784b3c..20b8a612 100644 --- a/compiler/router/router.py +++ b/compiler/router/router.py @@ -49,6 +49,12 @@ class router: """ If we want to route something besides the top-level cell.""" self.top_name = top_name + def get_zindex(self,layer_num): + if layer_num==self.horiz_layer_number: + return 0 + else: + return 1 + def set_layers(self, layers): """Allows us to change the layers that we are routing on. First layer is always horizontal, middle is via, and last is always @@ -203,15 +209,20 @@ class router: def add_blockages(self): """ Add the blockages except the pin shapes """ + # Skip pin shapes + all_pins = [x[0] for x in list(self.pins.values())] + for blockage in self.blockages: - # Skip pin shapes - all_pins = [x[0] for x in list(self.pins.values())] for pin in all_pins: - if blockage.overlaps(pin): + # If the blockage overlaps the pin and is on the same layer, + # it must be connected, so skip it. + if blockage==pin: + debug.info(1,"Skipping blockage for pin {}".format(str(pin))) break else: + debug.info(2,"Adding blockage {}".format(str(blockage))) [ll,ur]=self.convert_blockage_to_tracks(blockage.rect) - zlayer = 0 if blockage.layer_num==self.horiz_layer_number else 1 + zlayer = self.get_zindex(blockage.layer_num) self.rg.add_blockage_shape(ll,ur,zlayer) @@ -227,37 +238,6 @@ class router: rect = [ll,ur] new_pin = pin_layout("blockage{}".format(len(self.blockages)),rect,layer_num) self.blockages.append(new_pin) - - # for boundary in self.layout.structures[sref].boundaries: - # coord_trans = self.translate_coordinates(boundary.coordinates, mirr, angle, xyShift) - # shape_coords = self.min_max_coord(coord_trans) - # shape = self.convert_shape_to_units(shape_coords) - - # # only consider the two layers that we are routing on - # if boundary.drawingLayer in [self.vert_layer_number,self.horiz_layer_number]: - # # store the blockages as pin layouts so they are easy to compare etc. - # new_pin = pin_layout("blockage",shape,boundary.drawingLayer) - # # avoid repeated blockage pins - # if new_pin not in self.blockages: - # self.blockages.append(new_pin) - - - # # recurse given the mirror, angle, etc. - # for cur_sref in self.layout.structures[sref].srefs: - # sMirr = 1 - # if cur_sref.transFlags[0] == True: - # sMirr = -1 - # sAngle = math.radians(float(0)) - # if cur_sref.rotateAngle: - # sAngle = math.radians(float(cur_sref.rotateAngle)) - # sAngle += angle - # x = cur_sref.coordinates[0] - # y = cur_sref.coordinates[1] - # newX = (x)*math.cos(angle) - mirr*(y)*math.sin(angle) + xyShift[0] - # newY = (x)*math.sin(angle) + mirr*(y)*math.cos(angle) + xyShift[1] - # sxyShift = (newX, newY) - - # self.get_blockages(cur_sref.sName, sMirr, sAngle, sxyShift) def convert_point_to_units(self,p): @@ -282,9 +262,11 @@ class router: old_ur = ur ll=ll.scale(self.track_factor) ur=ur.scale(self.track_factor) + if ll[0]<45 and ll[0]>35 and ll[1]<46 and ll[1]>39: + print(ll,ur) ll = ll.floor() ur = ur.ceil() - if ll[0]<45 and ll[0]>35 and ll[1]<10 and ll[1]>0: + if ll[0]<45 and ll[0]>35 and ll[1]<46 and ll[1]>39: debug.info(0,"Converting [ {0} , {1} ]".format(old_ll,old_ur)) debug.info(0,"Converted [ {0} , {1} ]".format(ll,ur)) return [ll,ur] @@ -296,9 +278,6 @@ class router: If a pin has insufficent overlap, it returns the blockage list to avoid it. """ (ll,ur) = pin.rect - #ll = snap_to_grid(ll) - #ur = snap_to_grid(ur) - #debug.info(1,"Converting [ {0} , {1} ]".format(ll,ur)) # scale the size bigger to include neaby tracks @@ -306,37 +285,40 @@ class router: ur=ur.scale(self.track_factor).ceil() # width depends on which layer it is - zindex = 0 if pin.layer_num==self.horiz_layer_number else 1 - if zindex==0: - width = self.horiz_layer_width - else: + zindex=self.get_zindex(pin.layer_num) + if zindex: width = self.vert_layer_width + else: + width = self.horiz_layer_width track_list = [] block_list = [] - # include +- 1 so when a shape is less than one grid - for x in range(ll[0]-1,ur[0]+1): - for y in range(ll[1]-1,ur[1]+1): + + track_area = self.track_width*self.track_width + for x in range(ll[0],ur[0]): + for y in range(ll[1],ur[1]): #debug.info(1,"Converting [ {0} , {1} ]".format(x,y)) - # get the rectangular pin at a track location - # if dimension of overlap is greater than min width in any dimension, - # it will be an on-grid pin - rect = self.convert_track_to_pin(vector3d(x,y,zindex)) - max_overlap=max(self.compute_overlap(pin.rect,rect)) # however, if there is not enough overlap, then if there is any overlap at all, # we need to block it to prevent routes coming in on that grid - full_rect = self.convert_full_track_to_shape(vector3d(x,y,zindex)) - full_overlap=max(self.compute_overlap(pin.rect,full_rect)) - + full_rect = self.convert_track_to_shape(vector3d(x,y,zindex)) + overlap_rect=self.compute_overlap(pin.rect,full_rect) + overlap_area = overlap_rect[0]*overlap_rect[1] #debug.info(1,"Check overlap: {0} {1} max={2}".format(shape,rect,max_overlap)) - if max_overlap >= width: + + # Assume if more than half the area, it is occupied + overlap_ratio = overlap_area/track_area + if overlap_ratio > 0.5: track_list.append(vector3d(x,y,zindex)) - elif full_overlap>0: + # otherwise, the pin may not be accessible, so block it + elif overlap_ratio > 0: block_list.append(vector3d(x,y,zindex)) else: debug.info(4,"No overlap: {0} {1} max={2}".format(pin.rect,rect,max_overlap)) - + print("H:",x,y) + if x>38 and x<42 and y>42 and y<45: + print(pin) + print(full_rect, overlap_rect, overlap_ratio) #debug.warning("Off-grid pin for {0}.".format(str(pin))) #debug.info(1,"Converted [ {0} , {1} ]".format(ll,ur)) return (track_list,block_list) @@ -381,7 +363,7 @@ class router: return [ll,ur] - def convert_full_track_to_shape(self,track): + def convert_track_to_shape(self,track): """ Convert a grid point into a rectangle shape that occupies the entire centered track. @@ -447,9 +429,8 @@ class router: grid_keys=self.rg.map.keys() partial_track=vector(0,self.track_width/6.0) for g in grid_keys: - continue # for now... - shape = self.convert_full_track_to_shape(g) - self.cell.add_rect(layer="boundary", + shape = self.convert_track_to_shape(g) + self.cell.add_rect(layer="text", offset=shape[0], width=shape[1].x-shape[0].x, height=shape[1].y-shape[0].y) @@ -481,7 +462,7 @@ class router: zoom=0.05) for blockage in self.blockages: - self.cell.add_rect(layer="boundary", + self.cell.add_rect(layer="blockage", offset=blockage.ll(), width=blockage.width(), height=blockage.height()) diff --git a/compiler/router/tests/10_supply_grid_test.py b/compiler/router/tests/10_supply_grid_test.py index 485d925c..2fa5cb7b 100755 --- a/compiler/router/tests/10_supply_grid_test.py +++ b/compiler/router/tests/10_supply_grid_test.py @@ -32,12 +32,14 @@ class no_blockages_test(openram_test): globals.setup_paths() from control_logic import control_logic cell = control_logic(16) + #from pinv import pinv + #cell = pinv() #gds_file = "{0}/{1}.gds".format(os.path.dirname(os.path.realpath(__file__)),"control_logic") #cell = gds_cell(name, gds_file) self.add_inst(name=name, mod=cell, offset=[0,0]) - self.connect_inst(["csb","web","clk","s_en","w_en","clk_buf_bar","clk_buf","vdd","gnd"]) + self.connect_inst(cell.pin_map.keys()) r=router(module=cell) layer_stack =("metal3","via2","metal2") diff --git a/technology/freepdk45/tech/tech.py b/technology/freepdk45/tech/tech.py index 50d8977c..3c28fab5 100644 --- a/technology/freepdk45/tech/tech.py +++ b/technology/freepdk45/tech/tech.py @@ -56,6 +56,7 @@ layer["via9"] = 28 layer["metal10"] = 29 layer["text"] = 239 layer["boundary"]= 239 +layer["blockage"]= 239 ################################################### ##END GDS Layer Map diff --git a/technology/scn3me_subm/tech/tech.py b/technology/scn3me_subm/tech/tech.py index 4998c5b6..a3f51604 100755 --- a/technology/scn3me_subm/tech/tech.py +++ b/technology/scn3me_subm/tech/tech.py @@ -41,6 +41,7 @@ layer["via2"] = 61 layer["metal3"] = 62 layer["text"] = 63 layer["boundary"] = 63 +layer["blockage"] = 83 ################################################### ##END GDS Layer Map From 9d40cd4a0385d5dd796b2323b486b64e694a2aec Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Tue, 4 Sep 2018 16:39:13 -0700 Subject: [PATCH 2/8] Remove verbose print statement in add_power_pin --- compiler/base/hierarchy_layout.py | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index 83a8420b..28991826 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -845,7 +845,6 @@ class layout(lef.lef): """ Add a single power pin from M3 down to M1 at the given center location """ - debug.info(0,"Adding power pin {0} at {1} rotate={2}".format(name, loc, rotate)) self.add_via_center(layers=("metal1", "via1", "metal2"), offset=loc, rotate=rotate) From 5395f21be9616633b517c0b66bce809db4fc7333 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Tue, 4 Sep 2018 16:40:52 -0700 Subject: [PATCH 3/8] Remove unique id in contact that was used for debugging --- compiler/base/contact.py | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/compiler/base/contact.py b/compiler/base/contact.py index 9ffae803..1d4beb11 100644 --- a/compiler/base/contact.py +++ b/compiler/base/contact.py @@ -16,26 +16,23 @@ class contact(hierarchy_design.hierarchy_design): hierarchy as the contact. """ - unique_id = 1 - def __init__(self, layer_stack, dimensions=[1,1], implant_type=None, well_type=None): if implant_type or well_type: - name = "{0}_{1}_{2}_{3}x{4}_{5}{6}_{7}".format(layer_stack[0], - layer_stack[1], - layer_stack[2], - dimensions[0], - dimensions[1], - implant_type, - well_type, - contact.unique_id) + name = "{0}_{1}_{2}_{3}x{4}_{5}{6}".format(layer_stack[0], + layer_stack[1], + layer_stack[2], + dimensions[0], + dimensions[1], + implant_type, + well_type) + else: - name = "{0}_{1}_{2}_{3}x{4}_{5}".format(layer_stack[0], - layer_stack[1], - layer_stack[2], - dimensions[0], - dimensions[1], - contact.unique_id) - contact.unique_id += 1 + name = "{0}_{1}_{2}_{3}x{4}".format(layer_stack[0], + layer_stack[1], + layer_stack[2], + dimensions[0], + dimensions[1]) + hierarchy_design.hierarchy_design.__init__(self, name) debug.info(4, "create contact object {0}".format(name)) From 73e2bd2653516a0cb1d90bbde4a1a009703bbd9d Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Tue, 4 Sep 2018 16:43:59 -0700 Subject: [PATCH 4/8] Removed solid display format for comments to allow grid/blockage visibility. --- technology/scn3me_subm/tf/display.drf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/technology/scn3me_subm/tf/display.drf b/technology/scn3me_subm/tf/display.drf index e9a22348..047879b6 100644 --- a/technology/scn3me_subm/tf/display.drf +++ b/technology/scn3me_subm/tf/display.drf @@ -625,7 +625,7 @@ drDefinePacket( ( display deviceAnt stipple0 solid yellow yellow solid ) ( display winBottomShadow solid solid winColor1 winColor1 solid ) ( display PselectNet dots4 solid brown brown outlineStipple) - ( display comment stipple0 lineStyle0 winBack winBack solid ) + ( display comment stipple0 lineStyle0 winBack winBack outline ) ( display Poly1 dots lineStyle0 red red outlineStipple) ( display Unrouted stipple0 lineStyle1 winColor5 winColor5 solid ) ( display stretch stipple0 solid yellow yellow solid ) From 8ffdcdf277f40801aa234e2086a19b7e1c96589f Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Tue, 4 Sep 2018 17:27:50 -0700 Subject: [PATCH 5/8] Fixed bit shift amount error. Removed rotate flag for Calibre. --- compiler/base/hierarchy_layout.py | 4 ++-- compiler/gdsMill/gdsMill/gds2writer.py | 11 +++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index 28991826..3ac5ea63 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -847,10 +847,10 @@ class layout(lef.lef): """ self.add_via_center(layers=("metal1", "via1", "metal2"), offset=loc, - rotate=rotate) + rotate=float(rotate)) via=self.add_via_center(layers=("metal2", "via2", "metal3"), offset=loc, - rotate=rotate) + rotate=float(rotate)) self.add_layout_pin_rect_center(text=name, layer="metal3", offset=loc, diff --git a/compiler/gdsMill/gdsMill/gds2writer.py b/compiler/gdsMill/gdsMill/gds2writer.py index 3ab1c0b7..1a3d75af 100644 --- a/compiler/gdsMill/gdsMill/gds2writer.py +++ b/compiler/gdsMill/gdsMill/gds2writer.py @@ -280,8 +280,11 @@ class Gds2writer: if(thisSref.transFlags!=""): idBits=b'\x1A\x01' mirrorFlag = int(thisSref.transFlags[0])<<15 - rotateFlag = int(thisSref.transFlags[2])<<1 - magnifyFlag = int(thisSref.transFlags[1])<<3 + # FIXME: For some reason, Calibre doesn't like when this flag is set + # but it will still pay attention to the rotate value! + #rotateFlag = int(thisSref.transFlags[2])<<1 + rotateFlag=0 + magnifyFlag = int(thisSref.transFlags[1])<<2 transFlags = struct.pack(">H",mirrorFlag|rotateFlag|magnifyFlag) self.writeRecord(idBits+transFlags) if(thisSref.transFlags[1]): @@ -328,7 +331,7 @@ class Gds2writer: idBits=b'\x1A\x01' mirrorFlag = int(thisAref.transFlags[0])<<15 rotateFlag = int(thisAref.transFlags[2])<<1 - magnifyFlag = int(thisAref.transFlags[1])<<3 + magnifyFlag = int(thisAref.transFlags[1])<<2 transFlags = struct.pack(">H",mirrorFlag|rotateFlag|magnifyFlag) self.writeRecord(idBits+transFlags) if(thisAref.transFlags[1]): @@ -375,7 +378,7 @@ class Gds2writer: idBits=b'\x1A\x01' mirrorFlag = int(thisText.transFlags[0])<<15 rotateFlag = int(thisText.transFlags[2])<<1 - magnifyFlag = int(thisText.transFlags[1])<<3 + magnifyFlag = int(thisText.transFlags[1])<<2 transFlags = struct.pack(">H",mirrorFlag|rotateFlag|magnifyFlag) self.writeRecord(idBits+transFlags) if(thisText.transFlags[1]): From 0f87ba742f5cfd258d86db9d9da34689f3fb6af5 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 5 Sep 2018 09:28:43 -0700 Subject: [PATCH 6/8] Add back LEF blockages. Remove "absolute" flags from GDS output --- compiler/base/geometry.py | 80 +++++++++++++------------- compiler/gdsMill/gdsMill/gds2writer.py | 40 ++++++++----- compiler/gdsMill/gdsMill/vlsiLayout.py | 10 ++-- 3 files changed, 71 insertions(+), 59 deletions(-) diff --git a/compiler/base/geometry.py b/compiler/base/geometry.py index 682b783b..7144a2cf 100644 --- a/compiler/base/geometry.py +++ b/compiler/base/geometry.py @@ -34,14 +34,14 @@ class geometry: # coordinate += [(x, y)] # return coordinate - # def transform_coords(self, coords, offset, mirr, angle): - # """Calculate coordinates after flip, rotate, and shift""" - # coordinate = [] - # for item in coords: - # x = item[0]*math.cos(angle) - item[1]*mirr*math.sin(angle) + offset[0] - # y = item[0]*math.sin(angle) + item[1]*mirr*math.cos(angle) + offset[1] - # coordinate += [[x, y]] - # return coordinate + def transform_coords(self, coords, offset, mirr, angle): + """Calculate coordinates after flip, rotate, and shift""" + coordinate = [] + for item in coords: + x = item[0]*math.cos(angle) - item[1]*mirr*math.sin(angle) + offset[0] + 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 """ @@ -148,40 +148,40 @@ class instance(geometry): debug.info(4, "creating instance: " + self.name) - # def get_blockages(self, layer, top=False): - # """ Retrieve rectangular blockages of all modules in this instance. - # Apply the transform of the instance placement to give absolute blockages.""" - # angle = math.radians(float(self.rotate)) - # mirr = 1 - # if self.mirror=="R90": - # angle += math.radians(90.0) - # elif self.mirror=="R180": - # angle += math.radians(180.0) - # elif self.mirror=="R270": - # angle += math.radians(270.0) - # elif self.mirror=="MX": - # mirr = -1 - # elif self.mirror=="MY": - # mirr = -1 - # angle += math.radians(180.0) - # elif self.mirror=="XY": - # mirr = 1 - # angle += math.radians(180.0) + def get_blockages(self, layer, top=False): + """ Retrieve rectangular blockages of all modules in this instance. + Apply the transform of the instance placement to give absolute blockages.""" + angle = math.radians(float(self.rotate)) + mirr = 1 + if self.mirror=="R90": + angle += math.radians(90.0) + elif self.mirror=="R180": + angle += math.radians(180.0) + elif self.mirror=="R270": + angle += math.radians(270.0) + elif self.mirror=="MX": + mirr = -1 + elif self.mirror=="MY": + mirr = -1 + angle += math.radians(180.0) + elif self.mirror=="XY": + mirr = 1 + angle += math.radians(180.0) - # if self.mod.is_library_cell: - # # For lib cells, block the whole thing except on metal3 - # # since they shouldn't use metal3 - # if layer==tech.layer["metal1"] or layer==tech.layer["metal2"]: - # return [self.transform_coords(self.mod.get_boundary(), self.offset, mirr, angle)] - # else: - # return [] - # else: + if self.mod.is_library_cell: + # For lib cells, block the whole thing except on metal3 + # since they shouldn't use metal3 + if layer==tech.layer["metal1"] or layer==tech.layer["metal2"]: + return [self.transform_coords(self.mod.get_boundary(), self.offset, mirr, angle)] + else: + return [] + else: - # blockages = self.mod.get_blockages(layer) - # new_blockages = [] - # for b in blockages: - # new_blockages.append(self.transform_coords(b,self.offset, mirr, angle)) - # return new_blockages + blockages = self.mod.get_blockages(layer) + new_blockages = [] + for b in blockages: + 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""" diff --git a/compiler/gdsMill/gdsMill/gds2writer.py b/compiler/gdsMill/gdsMill/gds2writer.py index 1a3d75af..402416cd 100644 --- a/compiler/gdsMill/gdsMill/gds2writer.py +++ b/compiler/gdsMill/gdsMill/gds2writer.py @@ -280,18 +280,20 @@ class Gds2writer: if(thisSref.transFlags!=""): idBits=b'\x1A\x01' mirrorFlag = int(thisSref.transFlags[0])<<15 - # FIXME: For some reason, Calibre doesn't like when this flag is set - # but it will still pay attention to the rotate value! - #rotateFlag = int(thisSref.transFlags[2])<<1 + # The rotate and magnify flags specify "absolute" rotate and magnify. + # It is unclear what that is (ignore all further rotates/mags in the + # hierarchy? But anyway, calibre doesn't support it. rotateFlag=0 - magnifyFlag = int(thisSref.transFlags[1])<<2 + magnifyFlag = 0 + #rotateFlag = int(thisSref.transFlags[2])<<1 + #magnifyFlag = int(thisSref.transFlags[1])<<2 transFlags = struct.pack(">H",mirrorFlag|rotateFlag|magnifyFlag) self.writeRecord(idBits+transFlags) - if(thisSref.transFlags[1]): + if(thisSref.magFactor!=""): idBits=b'\x1B\x05' magFactor=self.ibmDataFromIeeeDouble(thisSref.magFactor) self.writeRecord(idBits+magFactor) - if(thisSref.transFlags[2]): + if(thisSref.rotateAngle!=""): idBits=b'\x1C\x05' rotateAngle=self.ibmDataFromIeeeDouble(thisSref.rotateAngle) self.writeRecord(idBits+rotateAngle) @@ -330,15 +332,20 @@ class Gds2writer: if(thisAref.transFlags): idBits=b'\x1A\x01' mirrorFlag = int(thisAref.transFlags[0])<<15 - rotateFlag = int(thisAref.transFlags[2])<<1 - magnifyFlag = int(thisAref.transFlags[1])<<2 + # The rotate and magnify flags specify "absolute" rotate and magnify. + # It is unclear what that is (ignore all further rotates/mags in the + # hierarchy? But anyway, calibre doesn't support it. + rotateFlag=0 + magnifyFlag = 0 + #rotateFlag = int(thisAref.transFlags[2])<<1 + #magnifyFlag = int(thisAref.transFlags[1])<<2 transFlags = struct.pack(">H",mirrorFlag|rotateFlag|magnifyFlag) self.writeRecord(idBits+transFlags) - if(thisAref.transFlags[1]): + if(thisAref.magFactor!=""): idBits=b'\x1B\x05' magFactor=self.ibmDataFromIeeeDouble(thisAref.magFactor) self.writeRecord(idBits+magFactor) - if(thisAref.transFlags[2]): + if(thisAref.rotateAngle!=""): idBits=b'\x1C\x05' rotateAngle=self.ibmDataFromIeeeDouble(thisAref.rotateAngle) self.writeRecord(idBits+rotateAngle) @@ -377,15 +384,20 @@ class Gds2writer: if(thisText.transFlags != ""): idBits=b'\x1A\x01' mirrorFlag = int(thisText.transFlags[0])<<15 - rotateFlag = int(thisText.transFlags[2])<<1 - magnifyFlag = int(thisText.transFlags[1])<<2 + # The rotate and magnify flags specify "absolute" rotate and magnify. + # It is unclear what that is (ignore all further rotates/mags in the + # hierarchy? But anyway, calibre doesn't support it. + rotateFlag=0 + magnifyFlag = 0 + #rotateFlag = int(thisText.transFlags[2])<<1 + #magnifyFlag = int(thisText.transFlags[1])<<2 transFlags = struct.pack(">H",mirrorFlag|rotateFlag|magnifyFlag) self.writeRecord(idBits+transFlags) - if(thisText.transFlags[1]): + if(thisText.magFactor!=""): idBits=b'\x1B\x05' magFactor=self.ibmDataFromIeeeDouble(thisText.magFactor) self.writeRecord(idBits+magFactor) - if(thisText.transFlags[2]): + if(thisText.rotateAngle!=""): idBits=b'\x1C\x05' rotateAngle=self.ibmDataFromIeeeDouble(thisText.rotateAngle) self.writeRecord(idBits+rotateAngle) diff --git a/compiler/gdsMill/gdsMill/vlsiLayout.py b/compiler/gdsMill/gdsMill/vlsiLayout.py index 431d7d23..5e12619c 100644 --- a/compiler/gdsMill/gdsMill/vlsiLayout.py +++ b/compiler/gdsMill/gdsMill/vlsiLayout.py @@ -328,16 +328,16 @@ class VlsiLayout: if mirror=="R270": rotate = 270.0 if rotate: - layoutToAddSref.transFlags[2] = 1 + #layoutToAddSref.transFlags[2] = 1 layoutToAddSref.rotateAngle = rotate if mirror == "x" or mirror == "MX": layoutToAddSref.transFlags[0] = 1 if mirror == "y" or mirror == "MY": #NOTE: "MY" option will override specified rotate angle layoutToAddSref.transFlags[0] = 1 - layoutToAddSref.transFlags[2] = 1 + #layoutToAddSref.transFlags[2] = 1 layoutToAddSref.rotateAngle = 180.0 if mirror == "xy" or mirror == "XY": #NOTE: "XY" option will override specified rotate angle - layoutToAddSref.transFlags[2] = 1 + #layoutToAddSref.transFlags[2] = 1 layoutToAddSref.rotateAngle = 180.0 #add the sref to the root structure @@ -404,10 +404,10 @@ class VlsiLayout: if(len(text)%2 == 1): text = text + '\x00' textToAdd.textString = text - textToAdd.transFlags[1] = 1 + #textToAdd.transFlags[1] = 1 textToAdd.magFactor = magnification if rotate: - textToAdd.transFlags[2] = 1 + #textToAdd.transFlags[2] = 1 textToAdd.rotateAngle = rotate #add the sref to the root structure self.structures[self.rootStructureName].texts.append(textToAdd) From 2a27fbc98e866954da847e59b13361ca1d3de14b Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 5 Sep 2018 10:02:12 -0700 Subject: [PATCH 7/8] Fix temp directory preservation option. Make labels in freepdk45 replica bitcell lower case. --- compiler/globals.py | 18 +++--------------- compiler/router/router.py | 6 ++++-- .../freepdk45/gds_lib/replica_cell_6t.gds | Bin 20480 -> 20480 bytes 3 files changed, 7 insertions(+), 17 deletions(-) diff --git a/compiler/globals.py b/compiler/globals.py index 3bdc5f92..7a7d0098 100644 --- a/compiler/globals.py +++ b/compiler/globals.py @@ -118,9 +118,6 @@ def init_openram(config_file, is_unit_test=True): init_paths() - # This depends on the tech, so do it after tech is loaded - init_config() - # Reset the static duplicate name checker for unit tests. import hierarchy_design hierarchy_design.hierarchy_design.name_map=[] @@ -257,7 +254,8 @@ def cleanup_paths(): if not OPTS.purge_temp: debug.info(0,"Preserving temp directory: {}".format(OPTS.openram_temp)) return - if os.path.exists(OPTS.openram_temp): + elif os.path.exists(OPTS.openram_temp): + debug.info(1,"Purging temp directory: {}".format(OPTS.openram_temp)) # This annoyingly means you have to re-cd into the directory each debug iteration #shutil.rmtree(OPTS.openram_temp, ignore_errors=True) contents = [os.path.join(OPTS.openram_temp, i) for i in os.listdir(OPTS.openram_temp)] @@ -293,8 +291,6 @@ def setup_paths(): OPTS.openram_temp += "/" debug.info(1, "Temporary files saved in " + OPTS.openram_temp) - cleanup_paths() - def is_exe(fpath): @@ -316,6 +312,7 @@ def init_paths(): # make the directory if it doesn't exist try: + debug.info(1,"Creating temp directory: {}".format(OPTS.openram_temp)) os.makedirs(OPTS.openram_temp, 0o750) except OSError as e: if e.errno == 17: # errno.EEXIST @@ -330,16 +327,7 @@ def init_paths(): os.chmod(OPTS.output_path, 0o750) except: debug.error("Unable to make output directory.",-1) - -def init_config(): - """ Initialize the SRAM configurations. """ - # Create the SRAM configuration - from sram_config import sram_config - OPTS.sram_config = sram_config(OPTS.word_size, - OPTS.num_words, - OPTS.num_banks) - # imports correct technology directories for testing def import_tech(): diff --git a/compiler/router/router.py b/compiler/router/router.py index 20b8a612..c3ce007d 100644 --- a/compiler/router/router.py +++ b/compiler/router/router.py @@ -262,13 +262,15 @@ class router: old_ur = ur ll=ll.scale(self.track_factor) ur=ur.scale(self.track_factor) - if ll[0]<45 and ll[0]>35 and ll[1]<46 and ll[1]>39: + if ll[0]<45 and ll[0]>35 and ll[1]<5 and ll[1]>-5: print(ll,ur) ll = ll.floor() ur = ur.ceil() - if ll[0]<45 and ll[0]>35 and ll[1]<46 and ll[1]>39: + if ll[0]<45 and ll[0]>35 and ll[1]<5 and ll[1]>-5: debug.info(0,"Converting [ {0} , {1} ]".format(old_ll,old_ur)) debug.info(0,"Converted [ {0} , {1} ]".format(ll,ur)) + pin=self.convert_track_to_shape(ll) + debug.info(0,"Pin {}".format(pin)) return [ll,ur] def convert_pin_to_tracks(self, pin): diff --git a/technology/freepdk45/gds_lib/replica_cell_6t.gds b/technology/freepdk45/gds_lib/replica_cell_6t.gds index 9b301c08ae8f2b857d6cbdef1795cc73b82ea61a..1316c276cdb156fc0f599093fabe56a5310d8684 100644 GIT binary patch delta 961 zcmYLGPe>eB9G*AMj1KrKPE=0P0RjKcQx+1&b%2X5`<_+KpozH^6Q_M{w%9l1cMI=(#?k2EunFyM7k2j+2D``64s$fZ zD&%ktjjkoItWXW@po>P3d_fc8UN{Q6^)1rD>9F}!ATtT(foZ?C~^U7i7MY`jnMQTI z`byiCPcv9&=mEZTk9mDe^`tLq%=5<>!>dsZ)~Jj6Nb`SdeOQH`x`o3O$FpP%o2N*0 zisI55{F6F1Ptw1oGsnG7;{Fi*M>=<`KTHlHG*rfZnq!0Zis@d^cLN8T^yW;FsBucy$Gt*@}4eHvTGGcv|MTUA_#fOcyR2@Jn=fiH0dr zU7~u1>KWa$C+O1FbQAJ4_xwC#-e%zr?G#kcoDfCG6Dl@lOwZ2WWOUR5o^y^>z68z< zh+IWeGf>kw3{8DNw56(WRRe~~Are}1)S7eAs<^0Ch*u1ldc|w%E`zI^Fz2}^E&RvO zvQ&?stFhgd&LEm3n}6xGbQ;gqDUTrOU*m<7#o6UJ{OXVRy=vknVT|yHGmdrV0&;{8 YOBZmTkaJGp+oj_1I%_D6t zu4`#+L^HLdHmTX#1eO14_cmXKsh`22=%6oJxFDK)(Z_o`HdbO1Pj%kvxA8D$qaAaR zj4M1aByJmZct#5eqk&;;^`G*?afut_9eCtuY!`2hZNVH(i(GOWQNlqlq2MLxXVK5vhGj86CebIXW4rjw+(tkC zJ60w*YGwmJW*X>a=%4uzPkDDZ(Loe{1vl~%EBV(jny(|8p?=1NKU0UrILi6>Bv*r% zqbK8s(>3&`CA?`LS;o;6>!*BNnX18>YGG&cCag)$on?LY2+?uA6W($5DP-_dsf@#X z3cZqp;anP*OE!!W|FL)#wbRS`n?9Zt+qhP^f_~9~S?nTO;#Zfrszq*esfnn-HiafU za)N9X1IpQMk!xB|VKo1dK=0H5)+x^Mk_^4)ga|L3yeVLvbi(0_F@c>E9P>o5AI%Fy z3mkFb|Jr%ZGfzVznq%`h=46u`&9Zow#k1Tad6+N3E*J4=Wfp&yQeoF-b7?E+HMu`H ztD}3?IauzB{jM!As7c-*{a56|u$#DFZK7LsAgdHrTex3gUSVEgUMbSOfX&k;9+$_T zb^4;5)YWAa%XMA(_^s5&xAHu$%U9t_2ZLq+Md(e5fg{l+6rno~jv5Nx2A#=zgYR_* zL0v)BoxAlj`0nC4Y+ZZ1)oxs;*<8C{%7}v_23R zc8XZu$l>;Y;GqdKO!L Date: Wed, 5 Sep 2018 11:06:17 -0700 Subject: [PATCH 8/8] Add inflate blockages and remove pins from blockages. --- compiler/base/pin_layout.py | 17 ++++++++++- compiler/router/router.py | 58 ++++++++++++++++++++++--------------- 2 files changed, 50 insertions(+), 25 deletions(-) diff --git a/compiler/base/pin_layout.py b/compiler/base/pin_layout.py index 7e454df4..bb65f771 100644 --- a/compiler/base/pin_layout.py +++ b/compiler/base/pin_layout.py @@ -1,5 +1,5 @@ import debug -from tech import GDS +from tech import GDS, drc from vector import vector from tech import layer @@ -40,6 +40,21 @@ class pin_layout: else: return False + def inflate(self, spacing=None): + """ + Inflate the rectangle by the spacing (or other rule) + and return the new rectangle. + """ + if not spacing: + spacing = 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 overlaps(self, other): """ Check if a shape overlaps with a rectangle """ (ll,ur) = self.rect diff --git a/compiler/router/router.py b/compiler/router/router.py index c3ce007d..73c0681d 100644 --- a/compiler/router/router.py +++ b/compiler/router/router.py @@ -90,19 +90,19 @@ class router: - def find_pin(self,pin): + def find_pin(self,pin_name): """ Finds the pin shapes and converts to tracks. Pin can either be a label or a location,layer pair: [[x,y],layer]. """ - label_list=self.layout.getPinShapeByLabel(str(pin)) + shape_list=self.layout.getPinShapeByLabel(str(pin_name)) pin_list = [] - for label in label_list: - (name,layer,boundary)=label + for shape in shape_list: + (name,layer,boundary)=shape rect = [vector(boundary[0],boundary[1]),vector(boundary[2],boundary[3])] - # this is a list because other cells/designs may have must-connect pins - pin_list.append(pin_layout(pin, rect, layer)) + pin = pin_layout(pin_name, rect, layer) + pin_list.append(pin) debug.check(len(pin_list)>0,"Did not find any pin shapes for {0}.".format(str(pin))) @@ -208,22 +208,30 @@ class router: def add_blockages(self): - """ Add the blockages except the pin shapes """ - # Skip pin shapes - all_pins = [x[0] for x in list(self.pins.values())] - + """ Add the blockages except the pin shapes. Also remove the pin shapes from the blockages list. """ + # Join all the pin shapes into one big list + all_pins = [item for sublist in list(self.pins.values()) for item in sublist] + + # Do an n^2 check to see if any shapes are the same, otherwise add them + # FIXME: Make faster, but number of pins won't be *that* large + real_blockages = [] for blockage in self.blockages: for pin in all_pins: # If the blockage overlaps the pin and is on the same layer, # it must be connected, so skip it. if blockage==pin: - debug.info(1,"Skipping blockage for pin {}".format(str(pin))) + debug.info(1,"Removing blockage for pin {}".format(str(pin))) break else: debug.info(2,"Adding blockage {}".format(str(blockage))) - [ll,ur]=self.convert_blockage_to_tracks(blockage.rect) + # Inflate the blockage by spacing rule + [ll,ur]=self.convert_blockage_to_tracks(blockage.inflate()) zlayer = self.get_zindex(blockage.layer_num) self.rg.add_blockage_shape(ll,ur,zlayer) + real_blockages.append(blockage) + + # Remember the filtered blockages + self.blockages = real_blockages def get_blockages(self, layer_num): @@ -262,15 +270,15 @@ class router: old_ur = ur ll=ll.scale(self.track_factor) ur=ur.scale(self.track_factor) - if ll[0]<45 and ll[0]>35 and ll[1]<5 and ll[1]>-5: - print(ll,ur) - ll = ll.floor() - ur = ur.ceil() - if ll[0]<45 and ll[0]>35 and ll[1]<5 and ll[1]>-5: - debug.info(0,"Converting [ {0} , {1} ]".format(old_ll,old_ur)) - debug.info(0,"Converted [ {0} , {1} ]".format(ll,ur)) - pin=self.convert_track_to_shape(ll) - debug.info(0,"Pin {}".format(pin)) + # We can round since we are using inflated shapes + # and the track points are at the center + ll = ll.round() + ur = ur.round() + # if ll[0]<45 and ll[0]>35 and ll[1]<5 and ll[1]>-5: + # debug.info(0,"Converting [ {0} , {1} ]".format(old_ll,old_ur)) + # debug.info(0,"Converted [ {0} , {1} ]".format(ll,ur)) + # pin=self.convert_track_to_shape(ll) + # debug.info(0,"Pin {}".format(pin)) return [ll,ur] def convert_pin_to_tracks(self, pin): @@ -464,10 +472,12 @@ class router: zoom=0.05) for blockage in self.blockages: + # Display the inflated blockage + (ll,ur) = blockage.inflate() self.cell.add_rect(layer="blockage", - offset=blockage.ll(), - width=blockage.width(), - height=blockage.height()) + offset=ll, + width=ur.x-ll.x, + height=ur.y-ll.y) # FIXME: This should be replaced with vector.snap_to_grid at some point