diff --git a/compiler/options.py b/compiler/options.py index d583eaca..bd4bf607 100644 --- a/compiler/options.py +++ b/compiler/options.py @@ -13,8 +13,8 @@ class options(optparse.Values): # This is the name of the technology. tech_name = "" # This is the temp directory where all intermediate results are stored. - #openram_temp = "/tmp/openram_{0}_{1}_temp/".format(getpass.getuser(),os.getpid()) - openram_temp = "{0}/openram_temp/".format(os.getenv("HOME")) + openram_temp = "/tmp/openram_{0}_{1}_temp/".format(getpass.getuser(),os.getpid()) + #openram_temp = "{0}/openram_temp/".format(os.getenv("HOME")) # This is the verbosity level to control debug information. 0 is none, 1 # is minimal, etc. debug_level = 0 diff --git a/compiler/router/pin_group.py b/compiler/router/pin_group.py index e50f94d9..eaeb2421 100644 --- a/compiler/router/pin_group.py +++ b/compiler/router/pin_group.py @@ -172,7 +172,6 @@ class pin_group: ymax = max(plc.y,elc.y) ll = vector(plc.x, ymin) ur = vector(prc.x, ymax) - p = pin_layout(pin.name, [ll, ur], pin.layer) elif pin.yoverlaps(enclosure): # Is it horizontal overlap, extend pin shape to enclosure pbc = pin.bc() @@ -183,7 +182,6 @@ class pin_group: xmax = max(pbc.x,ebc.x) ll = vector(xmin, pbc.y) ur = vector(xmax, puc.y) - p = pin_layout(pin.name, [ll, ur], pin.layer) else: # Neither, so we must do a corner-to corner pc = pin.center() @@ -194,8 +192,10 @@ class pin_group: ymax = max(pc.y, ec.y) ll = vector(xmin, ymin) ur = vector(xmax, ymax) - p = pin_layout(pin.name, [ll, ur], pin.layer) + if ll.x==ur.x or ll.y==ur.y: + return None + p = pin_layout(pin.name, [ll, ur], pin.layer) return p def find_above_connector(self, pin, enclosures): @@ -226,7 +226,7 @@ class pin_group: # If it already overlaps, no connector needed if above_item.overlaps(pin): return None - + # Otherwise, make a connector to the item p = self.compute_connector(pin, above_item) return p @@ -485,7 +485,9 @@ class pin_group: for pin_list in self.pins: if not self.overlap_any_shape(pin_list, self.enclosures): connector = self.find_smallest_connector(pin_list, self.enclosures) - debug.check(connector!=None, "Could not find a connector for {} with {}".format(pin_list, self.enclosures)) + if connector==None: + debug.error("Could not find a connector for {} with {}".format(pin_list, self.enclosures)) + self.router.write_debug_gds("no_connector.gds") self.enclosures.append(connector) @@ -623,61 +625,61 @@ class pin_group: debug.info(2," pins {}".format(self.grids)) debug.info(2," secondary {}".format(self.secondary_grids)) - def recurse_simple_overlap_enclosure(self, start_set, direct): - """ - Recursive function to return set of tracks that connects to - the actual supply rail wire in a given direction (or terminating - when any track is no longer in the supply rail. - """ - next_set = grid_utils.expand_border(start_set, direct) + # def recurse_simple_overlap_enclosure(self, start_set, direct): + # """ + # Recursive function to return set of tracks that connects to + # the actual supply rail wire in a given direction (or terminating + # when any track is no longer in the supply rail. + # """ + # next_set = grid_utils.expand_border(start_set, direct) - supply_tracks = self.router.supply_rail_tracks[self.name] - supply_wire_tracks = self.router.supply_rail_wire_tracks[self.name] + # supply_tracks = self.router.supply_rail_tracks[self.name] + # supply_wire_tracks = self.router.supply_rail_wire_tracks[self.name] - supply_overlap = next_set & supply_tracks - wire_overlap = next_set & supply_wire_tracks + # supply_overlap = next_set & supply_tracks + # wire_overlap = next_set & supply_wire_tracks - # If the rail overlap is the same, we are done, since we connected to the actual wire - if len(wire_overlap)==len(start_set): - new_set = start_set | wire_overlap - # If the supply overlap is the same, keep expanding unti we hit the wire or move out of the rail region - elif len(supply_overlap)==len(start_set): - recurse_set = self.recurse_simple_overlap_enclosure(supply_overlap, direct) - new_set = start_set | supply_overlap | recurse_set - else: - # If we got no next set, we are done, can't expand! - new_set = set() + # # If the rail overlap is the same, we are done, since we connected to the actual wire + # if len(wire_overlap)==len(start_set): + # new_set = start_set | wire_overlap + # # If the supply overlap is the same, keep expanding unti we hit the wire or move out of the rail region + # elif len(supply_overlap)==len(start_set): + # recurse_set = self.recurse_simple_overlap_enclosure(supply_overlap, direct) + # new_set = start_set | supply_overlap | recurse_set + # else: + # # If we got no next set, we are done, can't expand! + # new_set = set() - return new_set + # return new_set - def create_simple_overlap_enclosure(self, start_set): - """ - This takes a set of tracks that overlap a supply rail and creates an enclosure - that is ensured to overlap the supply rail wire. - It then adds rectangle(s) for the enclosure. - """ - additional_set = set() - # Check the layer of any element in the pin to determine which direction to route it - e = next(iter(start_set)) - new_set = start_set.copy() - if e.z==0: - new_set = self.recurse_simple_overlap_enclosure(start_set, direction.NORTH) - if not new_set: - new_set = self.recurse_simple_overlap_enclosure(start_set, direction.SOUTH) - else: - new_set = self.recurse_simple_overlap_enclosure(start_set, direction.EAST) - if not new_set: - new_set = self.recurse_simple_overlap_enclosure(start_set, direction.WEST) + # def create_simple_overlap_enclosure(self, start_set): + # """ + # This takes a set of tracks that overlap a supply rail and creates an enclosure + # that is ensured to overlap the supply rail wire. + # It then adds rectangle(s) for the enclosure. + # """ + # additional_set = set() + # # Check the layer of any element in the pin to determine which direction to route it + # e = next(iter(start_set)) + # new_set = start_set.copy() + # if e.z==0: + # new_set = self.recurse_simple_overlap_enclosure(start_set, direction.NORTH) + # if not new_set: + # new_set = self.recurse_simple_overlap_enclosure(start_set, direction.SOUTH) + # else: + # new_set = self.recurse_simple_overlap_enclosure(start_set, direction.EAST) + # if not new_set: + # new_set = self.recurse_simple_overlap_enclosure(start_set, direction.WEST) - # Expand the pin grid set to include some extra grids that connect the supply rail - self.grids.update(new_set) + # # Expand the pin grid set to include some extra grids that connect the supply rail + # self.grids.update(new_set) - # Add the inflated set so we don't get wide metal spacing issues (if it exists) - self.blockages.update(grid_utils.inflate_set(new_set,self.router.supply_rail_space_width)) + # # Block the grids + # self.blockages.update(new_set) - # Add the polygon enclosures and set this pin group as routed - self.set_routed() - self.enclosures = self.compute_enclosures() + # # Add the polygon enclosures and set this pin group as routed + # self.set_routed() + # self.enclosures = self.compute_enclosures() diff --git a/compiler/router/router.py b/compiler/router/router.py index bb6e1efc..3f81e33d 100644 --- a/compiler/router/router.py +++ b/compiler/router/router.py @@ -21,12 +21,12 @@ class router(router_tech): It populates blockages on a grid class. """ - def __init__(self, layers, design, gds_filename=None): + def __init__(self, layers, design, gds_filename=None, rail_track_width=1): """ This will instantiate a copy of the gds file or the module at (0,0) and route on top of this. The blockages from the gds/module will be considered. """ - router_tech.__init__(self, layers) + router_tech.__init__(self, layers, rail_track_width) self.cell = design @@ -177,15 +177,15 @@ class router(router_tech): #print_time("Convert pins",datetime.now(), start_time) #start_time = datetime.now() - for pin in pin_list: - self.combine_adjacent_pins(pin) + #for pin in pin_list: + # self.combine_adjacent_pins(pin) #print_time("Combine pins",datetime.now(), start_time) #self.write_debug_gds("debug_combine_pins.gds",stop_program=True) # Separate any adjacent grids of differing net names to prevent wide metal DRC violations # Must be done before enclosing pins #start_time = datetime.now() - self.separate_adjacent_pins(self.supply_rail_space_width) + #self.separate_adjacent_pins(self.supply_rail_space_width) #print_time("Separate pins",datetime.now(), start_time) # For debug #self.separate_adjacent_pins(1) @@ -201,7 +201,7 @@ class router(router_tech): """ Find pins that have adjacent routing tracks and merge them into a single pin_group. The pins themselves may not be touching, but - enclose_pis in the next step will ensure they are touching. + enclose_pins in the next step will ensure they are touching. """ debug.info(1,"Combining adjacent pins for {}.".format(pin_name)) # Find all adjacencies @@ -519,7 +519,7 @@ class router(router_tech): # Keep tabs on tracks with sufficient and insufficient overlap sufficient_list = set() insufficient_list = set() - + zindex=self.get_zindex(pin.layer_num) for x in range(int(ll[0])+expansion,int(ur[0])+1+expansion): for y in range(int(ll[1]+expansion),int(ur[1])+1+expansion): @@ -528,7 +528,7 @@ class router(router_tech): sufficient_list.update([full_overlap]) if partial_overlap: insufficient_list.update([partial_overlap]) - debug.info(4,"Converting [ {0} , {1} ] full={2} partial={3}".format(x,y, full_overlap, partial_overlap)) + debug.info(3,"Converting [ {0} , {1} ] full={2} partial={3}".format(x,y, full_overlap, partial_overlap)) # Remove the blocked grids sufficient_list.difference_update(self.blocked_grids) @@ -620,7 +620,7 @@ class router(router_tech): return set([best_coord]) - def convert_pin_coord_to_tracks(self, pin, coord): + def convert_pin_coord_to_minimal_tracks(self, pin, coord): """ Given a pin and a track coordinate, determine if the pin overlaps enough. If it does, add additional metal to make the pin "on grid". @@ -642,6 +642,25 @@ class router(router_tech): else: debug.info(3," Partial/no overlap: {0} >? {1}".format(overlap_length,spacing)) return (None, coord) + + def convert_pin_coord_to_tracks(self, pin, coord): + """ + Return all tracks that an inflated pin overlaps + """ + + # This is the rectangle if we put a pin in the center of the track + track_pin = self.convert_track_to_inflated_pin(coord) + overlap_length = pin.overlap_length(track_pin) + + debug.info(3,"Check overlap: {0} {1} . {2} = {3}".format(coord, pin.rect, track_pin, overlap_length)) + # If it overlaps by more than the min width DRC, we can just use the track + if overlap_length==math.inf or snap_val_to_grid(overlap_length) > 0: + debug.info(3," Overlap: {0} >? {1}".format(overlap_length,0)) + return (coord, None) + # Otherwise, keep track of the partial overlap grids in case we need to patch it later. + else: + debug.info(3," Partial/no overlap: {0} >? {1}".format(overlap_length,0)) + return (None, coord) @@ -653,20 +672,14 @@ class router(router_tech): Convert a grid point into a rectangle shape that is centered track in the track and leaves half a DRC space in each direction. """ - # space depends on which layer it is - if self.get_layer(track[2])==self.horiz_layer_name: - space = 0.5*self.horiz_layer_spacing - else: - space = 0.5*self.vert_layer_spacing - # calculate lower left - x = track.x*self.track_width - 0.5*self.track_width + space - y = track.y*self.track_width - 0.5*self.track_width + space + x = track.x*self.track_width - 0.5*self.track_width + 0.5*self.track_space + y = track.y*self.track_width - 0.5*self.track_width + 0.5*self.track_space ll = snap_to_grid(vector(x,y)) # calculate upper right - x = track.x*self.track_width + 0.5*self.track_width - space - y = track.y*self.track_width + 0.5*self.track_width - space + x = track.x*self.track_width + 0.5*self.track_width - 0.5*self.track_space + y = track.y*self.track_width + 0.5*self.track_width - 0.5*self.track_space ur = snap_to_grid(vector(x,y)) p = pin_layout("", [ll, ur], self.get_layer(track[2])) @@ -685,6 +698,23 @@ class router(router_tech): ur = snap_to_grid(ll + vector(self.track_width,self.track_width)) return [ll,ur] + + def convert_track_to_inflated_pin(self, track): + """ + Convert a grid point into a rectangle shape that is inflated by a half DRC space. + """ + # calculate lower left + x = track.x*self.track_width - 0.5*self.track_width - 0.5*self.track_space + y = track.y*self.track_width - 0.5*self.track_width - 0.5*self.track_space + ll = snap_to_grid(vector(x,y)) + + # calculate upper right + x = track.x*self.track_width + 0.5*self.track_width + 0.5*self.track_space + y = track.y*self.track_width + 0.5*self.track_width + 0.5*self.track_space + ur = snap_to_grid(vector(x,y)) + + p = pin_layout("", [ll, ur], self.get_layer(track[2])) + return p def analyze_pins(self, pin_name): """ @@ -877,8 +907,6 @@ class router(router_tech): Enclose the tracks from ll to ur in a single rectangle that meets the track DRC rules. """ - # Get the layer information - (width, space) = self.get_layer_width_space(zindex) layer = self.get_layer(zindex) # This finds the pin shape enclosed by the track with DRC spacing on the sides @@ -894,35 +922,35 @@ class router(router_tech): return pin - def compute_wide_enclosure(self, ll, ur, zindex, name=""): - """ - Enclose the tracks from ll to ur in a single rectangle that meets the track DRC rules. - """ + # def compute_wide_enclosure(self, ll, ur, zindex, name=""): + # """ + # Enclose the tracks from ll to ur in a single rectangle that meets the track DRC rules. + # """ - # Find the pin enclosure of the whole track shape (ignoring DRCs) - (abs_ll,unused) = self.convert_track_to_shape(ll) - (unused,abs_ur) = self.convert_track_to_shape(ur) + # # Find the pin enclosure of the whole track shape (ignoring DRCs) + # (abs_ll,unused) = self.convert_track_to_shape(ll) + # (unused,abs_ur) = self.convert_track_to_shape(ur) - # Get the layer information - x_distance = abs(abs_ll.x-abs_ur.x) - y_distance = abs(abs_ll.y-abs_ur.y) - shape_width = min(x_distance, y_distance) - shape_length = max(x_distance, y_distance) + # # Get the layer information + # x_distance = abs(abs_ll.x-abs_ur.x) + # y_distance = abs(abs_ll.y-abs_ur.y) + # shape_width = min(x_distance, y_distance) + # shape_length = max(x_distance, y_distance) - # Get the DRC rule for the grid dimensions - (width, space) = self.get_layer_width_space(zindex, shape_width, shape_length) - layer = self.get_layer(zindex) + # # Get the DRC rule for the grid dimensions + # (width, space) = self.get_supply_layer_width_space(zindex) + # layer = self.get_layer(zindex) - if zindex==0: - spacing = vector(0.5*self.track_width, 0.5*space) - else: - spacing = vector(0.5*space, 0.5*self.track_width) - # Compute the shape offsets with correct spacing - new_ll = abs_ll + spacing - new_ur = abs_ur - spacing - pin = pin_layout(name, [new_ll, new_ur], layer) + # if zindex==0: + # spacing = vector(0.5*self.track_width, 0.5*space) + # else: + # spacing = vector(0.5*space, 0.5*self.track_width) + # # Compute the shape offsets with correct spacing + # new_ll = abs_ll + spacing + # new_ur = abs_ur - spacing + # pin = pin_layout(name, [new_ll, new_ur], layer) - return pin + # return pin def contract_path(self,path): @@ -963,8 +991,7 @@ class router(router_tech): self.add_route(path) path_set = grid_utils.flatten_set(path) - inflated_path = grid_utils.inflate_set(path_set,self.supply_rail_space_width) - self.path_blockages.append(inflated_path) + self.path_blockages.append(path_set) else: self.write_debug_gds("failed_route.gds") # clean up so we can try a reroute diff --git a/compiler/router/router_tech.py b/compiler/router/router_tech.py index cd52a164..cfe3735a 100644 --- a/compiler/router/router_tech.py +++ b/compiler/router/router_tech.py @@ -9,13 +9,15 @@ class router_tech: """ This is a class to hold the router tech constants. """ - def __init__(self, layers, supply_router=False): + def __init__(self, layers, rail_track_width): """ Allows us to change the layers that we are routing on. First layer is always horizontal, middle is via, and last is always vertical. """ self.layers = layers + self.rail_track_width = rail_track_width + (self.horiz_layer_name, self.via_layer_name, self.vert_layer_name) = self.layers # This is the minimum routed track spacing via_connect = contact(self.layers, (1, 1)) @@ -24,9 +26,9 @@ class router_tech: self.horiz_layer_number = layer[self.horiz_layer_name] self.vert_layer_number = layer[self.vert_layer_name] - if supply_router: - (self.vert_layer_minwidth, self.vert_layer_spacing) = self.get_supply_layer_width_space(1,2) - (self.horiz_layer_minwidth, self.horiz_layer_spacing) = self.get_supply_layer_width_space(0,2) + if self.rail_track_width>1: + (self.vert_layer_minwidth, self.vert_layer_spacing) = self.get_supply_layer_width_space(1) + (self.horiz_layer_minwidth, self.horiz_layer_spacing) = self.get_supply_layer_width_space(0) # For supplies, we will make the wire wider than the vias self.vert_layer_minwidth = max(self.vert_layer_minwidth, max_via_size) @@ -45,13 +47,17 @@ class router_tech: # We'll keep horizontal and vertical tracks the same for simplicity. self.track_width = max(self.horiz_track_width,self.vert_track_width) debug.info(1,"Track width: "+str(self.track_width)) + self.track_space = max(self.horiz_layer_spacing,self.vert_layer_spacing) + debug.info(1,"Track spacing: "+str(self.track_space)) + self.track_wire = self.track_width - self.track_space + debug.info(1,"Wire width: "+str(self.track_wire)) self.track_widths = vector([self.track_width] * 2) self.track_factor = vector([1/self.track_width] * 2) debug.info(2,"Track factor: {0}".format(self.track_factor)) # When we actually create the routes, make them the width of the track (minus 1/2 spacing on each side) - self.layer_widths = [self.track_width - self.horiz_layer_spacing, 1, self.track_width - self.vert_layer_spacing] + self.layer_widths = [self.track_wire, 1, self.track_wire] def get_zindex(self,layer_num): if layer_num==self.horiz_layer_number: @@ -85,7 +91,7 @@ class router_tech: return (min_width,min_spacing) - def get_supply_layer_width_space(self, zindex, widths=2): + def get_supply_layer_width_space(self, zindex): """ These are the width and spacing of a supply layer given a supply rail of the given number of min wire widths. @@ -97,10 +103,10 @@ class router_tech: else: debug.error("Invalid zindex for track", -1) - wire_width = widths*drc("minwidth_{0}".format(layer_name), 0, math.inf) + min_wire_width = drc("minwidth_{0}".format(layer_name), 0, math.inf) - min_width = drc("minwidth_{0}".format(layer_name), wire_width, math.inf) - min_spacing = drc(str(layer_name)+"_to_"+str(layer_name), wire_width, math.inf) + min_width = drc("minwidth_{0}".format(layer_name), self.rail_track_width*min_wire_width, math.inf) + min_spacing = drc(str(layer_name)+"_to_"+str(layer_name), self.rail_track_width*min_wire_width, math.inf) return (min_width,min_spacing) diff --git a/compiler/router/supply_router.py b/compiler/router/supply_router.py index fcf3f7fb..a9d0b445 100644 --- a/compiler/router/supply_router.py +++ b/compiler/router/supply_router.py @@ -24,17 +24,16 @@ class supply_router(router): This will route on layers in design. It will get the blockages from either the gds file name or the design itself (by saving to a gds file). """ - router.__init__(self, layers, design, gds_filename) + # Power rail width in minimum wire widths + self.rail_track_width = 3 + + router.__init__(self, layers, design, gds_filename, self.rail_track_width) # The list of supply rails (grid sets) that may be routed self.supply_rails = {} - self.supply_rail_wires = {} # This is the same as above but as a sigle set for the all the rails self.supply_rail_tracks = {} - self.supply_rail_wire_tracks = {} - # Power rail width in grid units. - self.rail_track_width = 2 @@ -116,9 +115,7 @@ class supply_router(router): debug.info(1,"Routing simple overlap pins for {0}".format(pin_name)) # These are the wire tracks - wire_tracks = self.supply_rail_wire_tracks[pin_name] - # These are the wire and space tracks - supply_tracks = self.supply_rail_tracks[pin_name] + wire_tracks = self.supply_rail_tracks[pin_name] for pg in self.pin_groups[pin_name]: if pg.is_routed(): @@ -129,13 +126,10 @@ class supply_router(router): if len(overlap_grids)>0: pg.set_routed() continue - - # Else, if we overlap some of the space track, we can patch it with an enclosure - common_set = supply_tracks & pg.grids - if len(common_set)>0: - pg.create_simple_overlap_enclosure(common_set) - pg.add_enclosure(self.cell) + # Else, if we overlap some of the space track, we can patch it with an enclosure + #pg.create_simple_overlap_enclosure(pg.grids) + #pg.add_enclosure(self.cell) @@ -146,7 +140,7 @@ class supply_router(router): NOTE: It is still possible though unlikely that there are disconnected groups of rails. """ - all_rails = self.supply_rail_wires[name] + all_rails = self.supply_rails[name] connections = set() via_areas = [] @@ -186,8 +180,8 @@ class supply_router(router): # the indices to determine a rail is connected to another # the overlap area for placement of a via overlap = new_r1 & new_r2 - if len(overlap) >= self.supply_rail_wire_width**2: - debug.info(3,"Via overlap {0} {1} {2}".format(len(overlap),self.supply_rail_wire_width**2,overlap)) + if len(overlap) >= 1: + debug.info(3,"Via overlap {0} {1}".format(len(overlap),overlap)) connections.update([i1,i2]) via_areas.append(overlap) @@ -196,7 +190,7 @@ class supply_router(router): ll = grid_utils.get_lower_left(area) ur = grid_utils.get_upper_right(area) center = (ll + ur).scale(0.5,0.5,0) - self.add_via(center,self.rail_track_width) + self.add_via(center,1) # Determien which indices were not connected to anything above missing_indices = set([x for x in range(len(self.supply_rails[name]))]) @@ -209,7 +203,6 @@ class supply_router(router): ur = grid_utils.get_upper_right(all_rails[rail_index]) debug.info(1,"Removing disconnected supply rail {0} .. {1}".format(ll,ur)) self.supply_rails[name].pop(rail_index) - self.supply_rail_wires[name].pop(rail_index) # Make the supply rails into a big giant set of grids for easy blockages. # Must be done after we determine which ones are connected. @@ -226,7 +219,7 @@ class supply_router(router): ll = grid_utils.get_lower_left(rail) ur = grid_utils.get_upper_right(rail) z = ll.z - pin = self.compute_wide_enclosure(ll, ur, z, name) + pin = self.compute_pin_enclosure(ll, ur, z, name) debug.info(2,"Adding supply rail {0} {1}->{2} {3}".format(name,ll,ur,pin)) self.cell.add_layout_pin(text=name, layer=pin.layer, @@ -242,33 +235,30 @@ class supply_router(router): self.max_yoffset = self.rg.ur.y self.max_xoffset = self.rg.ur.x - # Longest length is conservative - rail_length = max(self.max_yoffset,self.max_xoffset) - # Convert the number of tracks to dimensions to get the design rule spacing - rail_width = self.track_width*self.rail_track_width + # # Longest length is conservative + # rail_length = max(self.max_yoffset,self.max_xoffset) + # # Convert the number of tracks to dimensions to get the design rule spacing + # rail_width = self.track_width*self.rail_track_width - # Get the conservative width and spacing of the top rails - (horizontal_width, horizontal_space) = self.get_supply_layer_width_space(0,2) - (vertical_width, vertical_space) = self.get_supply_layer_width_space(1,2) - width = max(horizontal_width, vertical_width) - space = max(horizontal_space, vertical_space) + # # Get the conservative width and spacing of the top rails + # (horizontal_width, horizontal_space) = self.get_supply_layer_width_space(0) + # (vertical_width, vertical_space) = self.get_supply_layer_width_space(1) + # width = max(horizontal_width, vertical_width) + # space = max(horizontal_space, vertical_space) - # This is the supply rail pitch in terms of routing grids - # i.e. a rail of self.rail_track_width needs this many tracks including - # space - track_pitch = self.rail_track_width*width + space + # track_pitch = width + space - # Determine the pitch (in tracks) of the rail wire + spacing - self.supply_rail_width = math.ceil(track_pitch/self.track_width) - debug.info(1,"Rail step: {}".format(self.supply_rail_width)) + # # Determine the pitch (in tracks) of the rail wire + spacing + # self.supply_rail_width = math.ceil(track_pitch/self.track_width) + # debug.info(1,"Rail step: {}".format(self.supply_rail_width)) - # Conservatively determine the number of tracks that the rail actually occupies - space_tracks = math.ceil(space/self.track_width) - self.supply_rail_wire_width = self.supply_rail_width - space_tracks - debug.info(1,"Rail wire tracks: {}".format(self.supply_rail_wire_width)) - total_space = self.supply_rail_width - self.supply_rail_wire_width - self.supply_rail_space_width = math.floor(0.5*total_space) - debug.info(1,"Rail space tracks: {} (on both sides)".format(self.supply_rail_space_width)) + # # Conservatively determine the number of tracks that the rail actually occupies + # space_tracks = math.ceil(space/self.track_width) + # self.supply_rail_wire_width = self.supply_rail_width - space_tracks + # debug.info(1,"Rail wire tracks: {}".format(self.supply_rail_wire_width)) + # total_space = self.supply_rail_width - self.supply_rail_wire_width + # self.supply_rail_space_width = math.floor(0.5*total_space) + # debug.info(1,"Rail space tracks: {} (on both sides)".format(self.supply_rail_space_width)) def compute_supply_rails(self, name, supply_number): @@ -279,14 +269,13 @@ class supply_router(router): """ self.supply_rails[name]=[] - self.supply_rail_wires[name]=[] - start_offset = supply_number*self.supply_rail_width + start_offset = supply_number # Horizontal supply rails - for offset in range(start_offset, self.max_yoffset, 2*self.supply_rail_width): + for offset in range(start_offset, self.max_yoffset, 2): # Seed the function at the location with the given width - wave = [vector3d(0,offset+i,0) for i in range(self.supply_rail_width)] + wave = [vector3d(0,offset,0)] # While we can keep expanding east in this horizontal track while wave and wave[0].x < self.max_xoffset: added_rail = self.find_supply_rail(name, wave, direction.EAST) @@ -299,9 +288,9 @@ class supply_router(router): # Vertical supply rails max_offset = self.rg.ur.x - for offset in range(start_offset, self.max_xoffset, 2*self.supply_rail_width): + for offset in range(start_offset, self.max_xoffset, 2): # Seed the function at the location with the given width - wave = [vector3d(offset+i,0,1) for i in range(self.supply_rail_width)] + wave = [vector3d(offset,0,1)] # While we can keep expanding north in this vertical track while wave and wave[0].y < self.max_yoffset: added_rail = self.find_supply_rail(name, wave, direction.NORTH) @@ -378,11 +367,6 @@ class supply_router(router): if len(wave_path)>=4*self.rail_track_width: grid_set = wave_path.get_grids() self.supply_rails[name].append(grid_set) - - start_wire_index = self.supply_rail_space_width - end_wire_index = self.supply_rail_width - self.supply_rail_space_width - wire_set = wave_path.get_wire_grids(start_wire_index,end_wire_index) - self.supply_rail_wires[name].append(wire_set) return True return False @@ -417,10 +401,6 @@ class supply_router(router): rail_set.update(rail) self.supply_rail_tracks[pin_name] = rail_set - wire_set = set() - for rail in self.supply_rail_wires[pin_name]: - wire_set.update(rail) - self.supply_rail_wire_tracks[pin_name] = wire_set def route_pins_to_rails(self, pin_name): @@ -465,7 +445,7 @@ class supply_router(router): """ debug.info(4,"Add supply rail target {}".format(pin_name)) # Add the wire itself as the target - self.rg.set_target(self.supply_rail_wire_tracks[pin_name]) + self.rg.set_target(self.supply_rail_tracks[pin_name]) # But unblock all the rail tracks including the space self.rg.set_blocked(self.supply_rail_tracks[pin_name],False) diff --git a/compiler/router/tests/10_supply_grid_test.py b/compiler/router/tests/10_supply_grid_test.py index ef9a1be3..7258ab40 100755 --- a/compiler/router/tests/10_supply_grid_test.py +++ b/compiler/router/tests/10_supply_grid_test.py @@ -22,6 +22,9 @@ class no_blockages_test(openram_test): if False: from control_logic import control_logic cell = control_logic(16) + layer_stack =("metal3","via3","metal4") + rtr=router(layer_stack, cell) + self.assertTrue(rtr.route()) else: from sram import sram from sram_config import sram_config @@ -33,9 +36,6 @@ class no_blockages_test(openram_test): sram = sram(c, "sram1") cell = sram.s - layer_stack =("metal3","via3","metal4") - rtr=router(layer_stack, cell) - self.assertTrue(rtr.route()) self.local_check(cell,True) # fails if there are any DRC errors on any cells