From 378993ca22848d4e1327206915bebef6b354b237 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Tue, 4 Sep 2018 16:35:40 -0700 Subject: [PATCH] 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