diff --git a/compiler/base/contact.py b/compiler/base/contact.py index 5c300033..1d4beb11 100644 --- a/compiler/base/contact.py +++ b/compiler/base/contact.py @@ -15,6 +15,7 @@ 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. """ + 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], @@ -24,13 +25,14 @@ class contact(hierarchy_design.hierarchy_design): dimensions[1], implant_type, well_type) + else: name = "{0}_{1}_{2}_{3}x{4}".format(layer_stack[0], - layer_stack[1], - layer_stack[2], - dimensions[0], - dimensions[1]) - + 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)) diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index 01a48f89..3ac5ea63 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: @@ -849,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/base/pin_layout.py b/compiler/base/pin_layout.py index aa6bacfc..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 @@ -36,16 +36,29 @@ 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 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 = 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..402416cd 100644 --- a/compiler/gdsMill/gdsMill/gds2writer.py +++ b/compiler/gdsMill/gdsMill/gds2writer.py @@ -280,8 +280,13 @@ 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 + # 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(thisSref.transFlags[2])<<1 + #magnifyFlag = int(thisSref.transFlags[1])<<2 transFlags = struct.pack(">H",mirrorFlag|rotateFlag|magnifyFlag) self.writeRecord(idBits+transFlags) if(thisSref.magFactor!=""): @@ -327,15 +332,20 @@ 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 + # 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.magFactor): + if(thisAref.magFactor!=""): idBits=b'\x1B\x05' magFactor=self.ibmDataFromIeeeDouble(thisAref.magFactor) self.writeRecord(idBits+magFactor) - if(thisAref.rotateAngle): + if(thisAref.rotateAngle!=""): idBits=b'\x1C\x05' rotateAngle=self.ibmDataFromIeeeDouble(thisAref.rotateAngle) self.writeRecord(idBits+rotateAngle) @@ -374,15 +384,20 @@ 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 + # 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.magFactor != ""): + if(thisText.magFactor!=""): idBits=b'\x1B\x05' magFactor=self.ibmDataFromIeeeDouble(thisText.magFactor) self.writeRecord(idBits+magFactor) - if(thisText.rotateAngle != ""): + if(thisText.rotateAngle!=""): 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..5e12619c 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/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/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..73c0681d 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 @@ -84,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))) @@ -202,17 +208,30 @@ class router: def add_blockages(self): - """ Add the blockages except the pin shapes """ + """ 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: - # 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,"Removing blockage for pin {}".format(str(pin))) break else: - [ll,ur]=self.convert_blockage_to_tracks(blockage.rect) - zlayer = 0 if blockage.layer_num==self.horiz_layer_number else 1 + debug.info(2,"Adding blockage {}".format(str(blockage))) + # 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): @@ -227,37 +246,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,11 +270,15 @@ class router: old_ur = ur ll=ll.scale(self.track_factor) ur=ur.scale(self.track_factor) - ll = ll.floor() - ur = ur.ceil() - if ll[0]<45 and ll[0]>35 and ll[1]<10 and ll[1]>0: - debug.info(0,"Converting [ {0} , {1} ]".format(old_ll,old_ur)) - debug.info(0,"Converted [ {0} , {1} ]".format(ll,ur)) + # 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): @@ -296,9 +288,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 +295,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 +373,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 +439,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,10 +472,12 @@ class router: zoom=0.05) for blockage in self.blockages: - self.cell.add_rect(layer="boundary", - offset=blockage.ll(), - width=blockage.width(), - height=blockage.height()) + # Display the inflated blockage + (ll,ur) = blockage.inflate() + self.cell.add_rect(layer="blockage", + 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 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 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 )