diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index 16229eb9..2e7a7761 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -251,7 +251,7 @@ class layout(lef.lef): width=drc["minwidth_{0}".format(layer)] if height==None: height=drc["minwidth_{0}".format(layer)] - + new_pin = pin_layout(text, [offset,offset+vector(width,height)], layer) try: @@ -390,13 +390,14 @@ class layout(lef.lef): elif rotate==90: corrected_offset = offset + vector(0.5*height,-0.5*width) elif rotate==180: - corrected_offset = offset + vector(-0.5*width,0.5*height) + corrected_offset = offset + vector(0.5*width,0.5*height) elif rotate==270: corrected_offset = offset + vector(-0.5*height,0.5*width) else: debug.error("Invalid rotation argument.",-1) + #print(rotate,offset,"->",corrected_offset) self.add_mod(via) inst=self.add_inst(name=via.name, mod=via, @@ -842,19 +843,21 @@ class layout(lef.lef): width=xmax-xmin, height=ymax-ymin) - def add_power_pin(self, name, loc, rotate=True): + def add_power_pin(self, name, loc, rotate=90): """ - Add a single power pin from M3 own to M1 + Add a single power pin from M3 own to M1 at the given center location """ self.add_via_center(layers=("metal1", "via1", "metal2"), offset=loc, - rotate=90 if rotate else 0) - self.add_via_center(layers=("metal2", "via2", "metal3"), - offset=loc, - rotate=90 if rotate else 0) + rotate=rotate) + via=self.add_via_center(layers=("metal2", "via2", "metal3"), + offset=loc, + rotate=rotate) self.add_layout_pin_rect_center(text=name, layer="metal3", - offset=loc) + offset=loc, + width=via.width, + height=via.height) def add_power_ring(self, bbox): """ diff --git a/compiler/gdsMill/gdsMill/gds2reader.py b/compiler/gdsMill/gdsMill/gds2reader.py index a162361e..3d63cf53 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,rotateFlag,magnifyFlag] 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,rotateFlag,magnifyFlag] 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,rotateFlag,magnifyFlag] if(self.debugToTerminal==1): print("\t\t\tMirror X:"+str(mirrorFlag)) print("\t\t\tRotate:"+str(rotateFlag)) diff --git a/compiler/gdsMill/gdsMill/vlsiLayout.py b/compiler/gdsMill/gdsMill/vlsiLayout.py index 076948bb..4b498bb8 100644 --- a/compiler/gdsMill/gdsMill/vlsiLayout.py +++ b/compiler/gdsMill/gdsMill/vlsiLayout.py @@ -152,7 +152,7 @@ class VlsiLayout: self.rootStructureName = structureNames[0] def traverseTheHierarchy(self, startingStructureName=None, delegateFunction = None, - transformPath = [], rotateAngle = 0, transFlags = (0,0,0), coordinates = (0,0)): + transformPath = [], rotateAngle = 0, transFlags = [0,0,0], coordinates = (0,0)): #since this is a recursive function, must deal with the default #parameters explicitly if startingStructureName == None: @@ -160,11 +160,11 @@ class VlsiLayout: #set up the rotation matrix if(rotateAngle == None or rotateAngle == ""): - rotateAngle = 0 + angle = 0 else: - rotateAngle = math.radians(float(rotateAngle)) - mRotate = matrix([[math.cos(rotateAngle),-math.sin(rotateAngle),0.0], - [math.sin(rotateAngle),math.cos(rotateAngle),0.0], + angle = math.radians(float(rotateAngle)) + mRotate = matrix([[math.cos(angle),-math.sin(angle),0.0], + [math.sin(angle),math.cos(angle),0.0], [0.0,0.0,1.0]]) #set up the translation matrix translateX = float(coordinates[0]) @@ -190,15 +190,12 @@ class VlsiLayout: #if not, return back to the caller (caller can be this function) for sref in self.structures[startingStructureName].srefs: #here, we are going to modify the sref coordinates based on the parent objects rotation -# if (sref.sName.count("via") == 0): self.traverseTheHierarchy(startingStructureName = sref.sName, delegateFunction = delegateFunction, transformPath = transformPath, rotateAngle = sref.rotateAngle, transFlags = sref.transFlags, coordinates = sref.coordinates) -# else: -# print("WARNING: via encountered, ignoring:", sref.sName) #MUST HANDLE AREFs HERE AS WELL #when we return, drop the last transform from the transformPath del transformPath[-1] @@ -225,8 +222,8 @@ class VlsiLayout: uVector = transform[0] * uVector #rotate vVector = transform[0] * vVector #rotate origin = transform[1] * origin #scale - uVector = transform[1] * uVector #rotate - vVector = transform[1] * vVector #rotate + uVector = transform[1] * uVector #scale + vVector = transform[1] * vVector #scale origin = transform[2] * origin #translate #we don't need to do a translation on the basis vectors self.xyTree+=[(startingStructureName,origin,uVector,vVector)] #populate the xyTree with each @@ -307,18 +304,9 @@ class VlsiLayout: for layerNumber in layoutToAdd.layerNumbersInUse: if layerNumber not in self.layerNumbersInUse: self.layerNumbersInUse += [layerNumber] - #Also, check if the user units / microns is the same as this Layout - #if (layoutToAdd.units != self.units): - #print("WARNING: VlsiLayout: Units from design to be added do not match target Layout") # if debug: print("DEBUG: vlsilayout: Using %d layers") - # If we can't find the structure, error - #if StructureFound == False: - #print("ERROR: vlsiLayout.addInstance: [%s] Name not found in local structures, "%(nameOfLayout)) - #return #FIXME: remove! - #exit(1) - #add a reference to the new layout structure in this layout's root layoutToAddSref = GdsSref() @@ -326,24 +314,27 @@ class VlsiLayout: layoutToAddSref.coordinates = offsetInLayoutUnits if mirror or rotate: - ########flags = (mirror around x-axis, absolute rotation, absolute magnification) - layoutToAddSref.transFlags = (False,False,False) - #Below angles are angular angles(relative), not absolute + # 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": rotate = 90.0 if mirror=="R180": rotate = 180.0 if mirror=="R270": rotate = 270.0 + + layoutToAddSref.transFlags = [0,0,0] if rotate: + layoutToAddSref.transFlags = [0,0,1] layoutToAddSref.rotateAngle = rotate if mirror == "x" or mirror == "MX": - layoutToAddSref.transFlags = (True,False,False) + layoutToAddSref.transFlags = [1,0,0] if mirror == "y" or mirror == "MY": #NOTE: "MY" option will override specified rotate angle - layoutToAddSref.transFlags = (True,False,False) + layoutToAddSref.transFlags = [1,0,1] layoutToAddSref.rotateAngle = 180.0 if mirror == "xy" or mirror == "XY": #NOTE: "XY" option will override specified rotate angle - layoutToAddSref.transFlags = (False,False,False) + layoutToAddSref.transFlags = [0,0,1] layoutToAddSref.rotateAngle = 180.0 #add the sref to the root structure @@ -410,14 +401,14 @@ class VlsiLayout: textToAdd.purposeLayer = purposeNumber textToAdd.dataType = 0 textToAdd.coordinates = [offsetInLayoutUnits] + textToAdd.transFlags = [0,0,0] if(len(text)%2 == 1): - #pad with a zero text = text + '\x00' textToAdd.textString = text - textToAdd.transFlags = (False,False,True) + textToAdd.transFlags[1] = 1 textToAdd.magFactor = magnification if rotate: - textToAdd.transFlags = (False,True,True) + textToAdd.transFlags[2] = 1 textToAdd.rotateAngle = rotate #add the sref to the root structure self.structures[self.rootStructureName].texts+=[textToAdd] @@ -620,10 +611,6 @@ class VlsiLayout: StructureOrigin=[Structure[1][0],Structure[1][1]] StructureuVector=[Structure[2][0],Structure[2][1],Structure[2][2]] StructurevVector=[Structure[3][0],Structure[3][1],Structure[3][2]] - #debug.info(debug_level,"Checking Structure: "+str(StructureName)) - #debug.info(debug_level,"-Structure Structure Origin:"+str(StructureOrigin)) - #debug.info(debug_level,"-Structure direction: uVector["+str(StructureuVector)+"]") - #debug.info(debug_level,"-Structure direction: vVector["+str(StructurevVector)+"]") for boundary in self.structures[str(StructureName)].boundaries: left_bottom=boundary.coordinates[0] @@ -808,6 +795,63 @@ class VlsiLayout: return boundaries + + def getAllShapesInStructureList(self,layer): + """ + Return all pin shapes on a given layer. + """ + boundaries = [] + for TreeUnit in self.xyTree: + #print(TreeUnit[0]) + boundaries += self.getShapesInStructure(layer,TreeUnit) + + # Remove duplicates without defining a hash + # (could be sped up by creating hash and using list(set()) + new_boundaries = [] + for boundary in boundaries: + if boundary not in new_boundaries: + new_boundaries.append(boundary) + + # Convert to user units + boundaries = [] + for boundary in new_boundaries: + boundaries.append([boundary[0]*self.units[0],boundary[1]*self.units[0], + boundary[2]*self.units[0],boundary[3]*self.units[0]]) + + return boundaries + + + def getShapesInStructure(self,layer,structure): + """ + Go through all the shapes in a structure and return the list of shapes. + """ + + # check if this is a rectangle + structureName=structure[0] + structureOrigin=[structure[1][0],structure[1][1]] + structureuVector=[structure[2][0],structure[2][1],structure[2][2]] + structurevVector=[structure[3][0],structure[3][1],structure[3][2]] + + 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. + if len(boundary.coordinates)!=5: + continue + if layer==boundary.drawingLayer: + left_bottom=boundary.coordinates[0] + right_top=boundary.coordinates[2] + # Rectangle is [leftx, bottomy, rightx, topy]. + boundaryRect=[left_bottom[0],left_bottom[1],right_top[0],right_top[1]] + boundaryRect=self.transformRectangle(boundaryRect,structureuVector,structurevVector) + 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 + def transformRectangle(self,originalRectangle,uVector,vVector): """ Transforms the four coordinates of a rectangle in space @@ -849,6 +893,7 @@ class VlsiLayout: else: return False + def boundaryArea(A): """ Returns boundary area for sorting. diff --git a/compiler/modules/delay_chain.py b/compiler/modules/delay_chain.py index b8a57f15..ff9878fb 100644 --- a/compiler/modules/delay_chain.py +++ b/compiler/modules/delay_chain.py @@ -186,7 +186,7 @@ class delay_chain(design.design): continue for pin_name in ["vdd", "gnd"]: pin = load.get_pin(pin_name) - self.add_power_pin(pin_name, pin.rc()) + self.add_power_pin(pin_name, pin.rc(),rotate=0) else: # We have an even number of rows, so need to get the last gnd rail inv = self.driver_inst_list[-1] @@ -195,7 +195,7 @@ class delay_chain(design.design): continue pin_name = "gnd" pin = load.get_pin(pin_name) - self.add_power_pin(pin_name, pin.rc()) + self.add_power_pin(pin_name, pin.rc(),rotate=0) # input is A pin of first inverter diff --git a/compiler/modules/replica_bitline.py b/compiler/modules/replica_bitline.py index ee3e89d4..b15f4515 100644 --- a/compiler/modules/replica_bitline.py +++ b/compiler/modules/replica_bitline.py @@ -192,7 +192,7 @@ class replica_bitline(design.design): # Replica bitcell needs to be routed up to M3 pin=self.rbc_inst.get_pin("vdd") # Don't rotate this via to vit in FreePDK45 - self.add_power_pin("vdd", pin.center(), False) + self.add_power_pin("vdd", pin.center(), rotate=0) for pin in self.rbc_inst.get_pins("gnd"): self.add_power_pin("gnd", pin.center()) diff --git a/compiler/router/astar_grid.py b/compiler/router/astar_grid.py index 5715663a..65d9e245 100644 --- a/compiler/router/astar_grid.py +++ b/compiler/router/astar_grid.py @@ -89,7 +89,7 @@ class astar_grid(grid.grid): self.counter+=1 - def astar_route(self,detour_scale): + def route(self,detour_scale): """ This does the A* maze routing with preferred direction routing. """ diff --git a/compiler/router/grid.py b/compiler/router/grid.py index 8eb063cf..5f60da4e 100644 --- a/compiler/router/grid.py +++ b/compiler/router/grid.py @@ -36,6 +36,9 @@ 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 b46acfd8..40e93df1 100644 --- a/compiler/router/router.py +++ b/compiler/router/router.py @@ -27,8 +27,7 @@ class router: self.top_name = self.layout.rootStructureName self.pins = {} - # the list of all blockage shapes - self.blockages = [] + self.blockages=[] # all the paths we've routed so far (to supplement the blockages) self.paths = [] @@ -101,9 +100,9 @@ class router: This doesn't consider whether the obstacles will be pins or not. They get reset later if they are not actually a blockage. """ - for layer in self.layers: - self.get_blockages(self.top_name) - + #for layer in [self.vert_layer_number,self.horiz_layer_number]: + # self.get_blockages(layer) + self.get_blockages(self.horiz_layer_number) def clear_pins(self): """ @@ -207,38 +206,50 @@ class router: self.rg.add_blockage_shape(ll,ur,zlayer) - def get_blockages(self, sref, mirr = 1, angle = math.radians(float(0)), xyShift = (0, 0)): + def get_blockages(self, layer_num): """ Recursive find boundaries as blockages to the routing grid. - Recurses for each Structure in GDS. """ - 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. - self.blockages.append(pin_layout("blockage",shape,boundary.drawingLayer)) + shapes = self.layout.getAllShapesInStructureList(layer_num) + + for boundary in shapes: + rect = [vector(boundary[0],boundary[1]),vector(boundary[2],boundary[3])] + new_pin = pin_layout("blockage",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) + # # 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) + # self.get_blockages(cur_sref.sName, sMirr, sAngle, sxyShift) + def convert_point_to_units(self,p): """ @@ -248,21 +259,25 @@ class router: pt=pt.scale(self.track_widths[0],self.track_widths[1],1) return pt - def convert_blockage_to_tracks(self,shape,round_bigger=False): + def convert_blockage_to_tracks(self,shape): """ Convert a rectangular blockage shape into track units. """ - [ll,ur] = shape - ll = snap_to_grid(ll) - ur = snap_to_grid(ur) + (ll,ur) = shape + # ll = snap_to_grid(ll) + # ur = snap_to_grid(ur) # to scale coordinates to tracks - #debug.info(1,"Converting [ {0} , {1} ]".format(ll,ur)) + debug.info(3,"Converting [ {0} , {1} ]".format(ll,ur)) + old_ll = ll + old_ur = ur ll=ll.scale(self.track_factor) ur=ur.scale(self.track_factor) - ll = ll.floor() if round_bigger else ll.round() - ur = ur.ceil() if round_bigger else ur.round() - #debug.info(1,"Converted [ {0} , {1} ]".format(ll,ur)) + 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)) return [ll,ur] def convert_pin_to_tracks(self, pin): @@ -271,9 +286,9 @@ class router: If no on-grid pins are found, it searches for the nearest off-grid pin(s). 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) + (ll,ur) = pin.rect + #ll = snap_to_grid(ll) + #ur = snap_to_grid(ur) #debug.info(1,"Converting [ {0} , {1} ]".format(ll,ur)) @@ -401,6 +416,68 @@ class router: self.write_debug_gds() debug.check(found_pin,"Unable to find pin on grid.") + def write_debug_gds(self): + """ + Write out a GDS file with the routing grid and search information annotated on it. + """ + # Only add the debug info to the gds file if we have any debugging on. + # This is because we may reroute a wire with detours and don't want the debug information. + if OPTS.debug_level==0: return + + self.add_router_info() + debug.error("Writing debug_route.gds") + self.cell.gds_write("debug_route.gds") + + def add_router_info(self): + """ + Write the routing grid and router cost, blockage, pins on + the boundary layer for debugging purposes. This can only be + called once or the labels will overlap. + """ + debug.info(0,"Adding router info") + 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", + offset=shape[0], + width=shape[1].x-shape[0].x, + height=shape[1].y-shape[0].y) + # These are the on grid pins + #rect = self.convert_track_to_pin(g) + #self.cell.add_rect(layer="boundary", + # offset=rect[0], + # width=rect[1].x-rect[0].x, + # height=rect[1].y-rect[0].y) + + t=self.rg.map[g].get_type() + + # midpoint offset + off=vector((shape[1].x+shape[0].x)/2, + (shape[1].y+shape[0].y)/2) + if g[2]==1: + # Upper layer is upper right label + type_off=off+partial_track + else: + # Lower layer is lower left label + type_off=off-partial_track + if t!=None: + self.cell.add_label(text=str(t), + layer="text", + offset=type_off) + self.cell.add_label(text="{0},{1}".format(g[0],g[1]), + layer="text", + offset=shape[0], + zoom=0.05) + + for blockage in self.blockages: + self.cell.add_rect(layer="boundary", + offset=blockage.ll(), + width=blockage.width(), + height=blockage.height()) + + # FIXME: This should be replaced with vector.snap_to_grid at some point def snap_to_grid(offset): diff --git a/compiler/router/signal_router.py b/compiler/router/signal_router.py index 7d06262e..3358d75f 100644 --- a/compiler/router/signal_router.py +++ b/compiler/router/signal_router.py @@ -26,7 +26,7 @@ class signal_router(router): def create_routing_grid(self): """ - Create a routing grid that spans given area. Wires cannot exist outside region. + Create a sprase routing grid with A* expansion functions. """ # We will add a halo around the boundary # of this many tracks @@ -44,6 +44,8 @@ class signal_router(router): This is used to speed up the routing when there is not much detouring needed. """ self.cell = cell + self.source_pin_name = src + self.target_pin_name = dest # Clear the pins if we have previously routed if (hasattr(self,'rg')): @@ -73,7 +75,7 @@ class signal_router(router): # returns the path in tracks - (path,cost) = self.rg.astar_route(detour_scale) + (path,cost) = self.rg.route(detour_scale) if path: debug.info(1,"Found path: cost={0} ".format(cost)) debug.info(2,str(path)) @@ -158,59 +160,3 @@ class signal_router(router): - - def write_debug_gds(self): - """ - Write out a GDS file with the routing grid and search information annotated on it. - """ - # Only add the debug info to the gds file if we have any debugging on. - # This is because we may reroute a wire with detours and don't want the debug information. - if OPTS.debug_level==0: return - - self.add_router_info() - pin_names = list(self.pins.keys()) - debug.error("Writing debug_route.gds from {0} to {1}".format(self.source_pin_name,self.target_pin_name)) - self.cell.gds_write("debug_route.gds") - - def add_router_info(self): - """ - Write the routing grid and router cost, blockage, pins on - the boundary layer for debugging purposes. This can only be - called once or the labels will overlap. - """ - debug.info(0,"Adding router info for {0} to {1}".format(self.source_pin_name,self.target_pin_name)) - grid_keys=self.rg.map.keys() - partial_track=vector(0,self.track_width/6.0) - for g in grid_keys: - shape = self.convert_full_track_to_shape(g) - self.cell.add_rect(layer="boundary", - offset=shape[0], - width=shape[1].x-shape[0].x, - height=shape[1].y-shape[0].y) - # These are the on grid pins - #rect = self.convert_track_to_pin(g) - #self.cell.add_rect(layer="boundary", - # offset=rect[0], - # width=rect[1].x-rect[0].x, - # height=rect[1].y-rect[0].y) - - t=self.rg.map[g].get_type() - - # midpoint offset - off=vector((shape[1].x+shape[0].x)/2, - (shape[1].y+shape[0].y)/2) - if g[2]==1: - # Upper layer is upper right label - type_off=off+partial_track - else: - # Lower layer is lower left label - type_off=off-partial_track - if t!=None: - self.cell.add_label(text=str(t), - layer="text", - offset=type_off) - self.cell.add_label(text="{0},{1}".format(g[0],g[1]), - layer="text", - offset=shape[0], - zoom=0.05) - diff --git a/compiler/router/supply_router.py b/compiler/router/supply_router.py index b58e6e16..ff505a78 100644 --- a/compiler/router/supply_router.py +++ b/compiler/router/supply_router.py @@ -66,24 +66,22 @@ class supply_router(router): # Add blockages from previous routes self.add_path_blockages() - # Now add the src/tgt if they are not blocked by other shapes - self.add_pin(vdd_name,True) - #self.add_pin() - + # source pin will be a specific layout pin + # target pin will be the rails only # returns the path in tracks - (path,cost) = self.rg.route(detour_scale) - if path: - debug.info(1,"Found path: cost={0} ".format(cost)) - debug.info(2,str(path)) - self.add_route(path) - return True - else: - self.write_debug_gds() - # clean up so we can try a reroute - self.clear_pins() + # (path,cost) = self.rg.route(detour_scale) + # if path: + # debug.info(1,"Found path: cost={0} ".format(cost)) + # debug.info(2,str(path)) + # self.add_route(path) + # return True + # else: + # self.write_debug_gds() + # # clean up so we can try a reroute + # self.clear_pins() - + self.write_debug_gds() return False @@ -114,6 +112,17 @@ class supply_router(router): self.cell.add_route(self.layers,abs_path) + def create_routing_grid(self): + """ + Create a sprase routing grid with A* expansion functions. + """ + # We will add a halo around the boundary + # of this many tracks + size = self.ur - self.ll + debug.info(1,"Size: {0} x {1}".format(size.x,size.y)) + + import supply_grid + self.rg = supply_grid.supply_grid() ########################## @@ -135,6 +144,3 @@ class supply_router(router): """ Create alternating vdd/gnd lines horizontally """ pass - def route(self): - #self.create_grid() - pass diff --git a/compiler/router/tests/10_supply_grid_test.py b/compiler/router/tests/10_supply_grid_test.py index 7d196c6f..91c892b0 100755 --- a/compiler/router/tests/10_supply_grid_test.py +++ b/compiler/router/tests/10_supply_grid_test.py @@ -38,7 +38,7 @@ class no_blockages_test(openram_test): self.connect_inst([]) r=router(gds_file) - layer_stack =("metal3","via1","metal2") + layer_stack =("metal3","via2","metal2") self.assertTrue(r.route(self,layer_stack)) r=routing("10_supply_grid_test_{0}".format(OPTS.tech_name)) diff --git a/compiler/router/tests/10_supply_grid_test_scn3me_subm.gds b/compiler/router/tests/10_supply_grid_test_scn3me_subm.gds index 1c4742dd..7cfbc0cb 100644 Binary files a/compiler/router/tests/10_supply_grid_test_scn3me_subm.gds and b/compiler/router/tests/10_supply_grid_test_scn3me_subm.gds differ diff --git a/compiler/tests/19_single_bank_test.py b/compiler/tests/19_single_bank_test.py index 96291201..25567e82 100755 --- a/compiler/tests/19_single_bank_test.py +++ b/compiler/tests/19_single_bank_test.py @@ -20,7 +20,7 @@ class single_bank_test(openram_test): debug.info(1, "No column mux") a = bank(word_size=4, num_words=16, words_per_row=1, num_banks=1, name="bank1_single") self.local_check(a) - + debug.info(1, "Two way column mux") a = bank(word_size=4, num_words=32, words_per_row=2, num_banks=1, name="bank2_single") self.local_check(a) diff --git a/compiler/tests/20_sram_1bank_test.py b/compiler/tests/20_sram_1bank_test.py index 0ee98c60..7079b715 100755 --- a/compiler/tests/20_sram_1bank_test.py +++ b/compiler/tests/20_sram_1bank_test.py @@ -21,17 +21,17 @@ class sram_1bank_test(openram_test): a = sram(word_size=4, num_words=16, num_banks=1, name="sram1") self.local_check(a, final_verification=True) - debug.info(1, "Single bank two way column mux with control logic") - a = sram(word_size=4, num_words=32, num_banks=1, name="sram2") - self.local_check(a, final_verification=True) + # debug.info(1, "Single bank two way column mux with control logic") + # a = sram(word_size=4, num_words=32, num_banks=1, name="sram2") + # self.local_check(a, final_verification=True) - debug.info(1, "Single bank, four way column mux with control logic") - a = sram(word_size=4, num_words=64, num_banks=1, name="sram3") - self.local_check(a, final_verification=True) + # debug.info(1, "Single bank, four way column mux with control logic") + # a = sram(word_size=4, num_words=64, num_banks=1, name="sram3") + # self.local_check(a, final_verification=True) - debug.info(1, "Single bank, eight way column mux with control logic") - a = sram(word_size=2, num_words=128, num_banks=1, name="sram4") - self.local_check(a, final_verification=True) + # debug.info(1, "Single bank, eight way column mux with control logic") + # a = sram(word_size=2, num_words=128, num_banks=1, name="sram4") + # self.local_check(a, final_verification=True) globals.end_openram()