From a165446fa70dec4d7d83a573d4004c712873ba7e Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Mon, 15 Oct 2018 11:25:51 -0700 Subject: [PATCH] First implementation of multiple track spacing wide DRCs in routing grid. --- compiler/router/router.py | 29 ++++++---- compiler/router/supply_router.py | 93 +++++++++++++++++++------------- 2 files changed, 74 insertions(+), 48 deletions(-) diff --git a/compiler/router/router.py b/compiler/router/router.py index 0ddc2b67..6d597077 100644 --- a/compiler/router/router.py +++ b/compiler/router/router.py @@ -685,7 +685,7 @@ class router: # Put each pin in an equivalence class of it's own equiv_classes = [set([x]) for x in pin_set] if local_debug: - print("INITIAL\n",equiv_classes) + debug.info(0,"INITIAL\n",equiv_classes) def compare_classes(class1, class2): """ @@ -693,8 +693,8 @@ class router: the combined set. Otherwise, return None. """ if local_debug: - print("CLASS1:\n",class1) - print("CLASS2:\n",class2) + debug.info(0,"CLASS1:\n",class1) + debug.info(0,"CLASS2:\n",class2) # Compare each pin in each class, # and if any overlap, return the combined the class for p1 in class1: @@ -702,18 +702,18 @@ class router: if p1.overlaps(p2): combined_class = class1 | class2 if local_debug: - print("COMBINE:",pformat(combined_class)) + debug.info(0,"COMBINE:",pformat(combined_class)) return combined_class if local_debug: - print("NO COMBINE") + debug.info(0,"NO COMBINE") return None def combine_classes(equiv_classes): """ Recursive function to combine classes. """ if local_debug: - print("\nRECURSE:\n",pformat(equiv_classes)) + debug.info(0,"\nRECURSE:\n",pformat(equiv_classes)) if len(equiv_classes)==1: return(equiv_classes) @@ -733,7 +733,7 @@ class router: reduced_classes = combine_classes(equiv_classes) if local_debug: - print("FINAL ",reduced_classes) + debug.info(0,"FINAL ",reduced_classes) self.pin_groups[pin_name]=reduced_classes def convert_pins(self, pin_name): @@ -1132,12 +1132,21 @@ class router: # 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 DRC rule for the grid dimensions - (width, space) = self.get_layer_width_space(zindex) + (width, space) = self.get_layer_width_space(zindex, shape_width, shape_length) layer = self.get_layer(zindex) - - pin = pin_layout(name, [abs_ll, abs_ur], layer) + + # Compute the shape offsets with correct spacing + new_ll = abs_ll + vector(0.5*space, 0.5*space) + new_ur = abs_ur - vector(0.5*space, 0.5*space) + pin = pin_layout(name, [new_ll, new_ur], layer) return pin diff --git a/compiler/router/supply_router.py b/compiler/router/supply_router.py index f0b1d7d1..386f5777 100644 --- a/compiler/router/supply_router.py +++ b/compiler/router/supply_router.py @@ -69,7 +69,7 @@ class supply_router(router): # Determine the rail locations self.route_supply_rails(self.vdd_name,1) - self.write_debug_gds("pre_pin_debug.gds",stop_program=True) + #self.write_debug_gds("pre_pin_debug.gds",stop_program=True) # Route the supply pins to the supply rails self.route_pins_to_rails(gnd_name) @@ -131,6 +131,33 @@ class supply_router(router): if wave_path.name == name: self.add_wavepath(name, wave_path) + def compute_supply_rail_dimensions(self): + """ + Compute the supply rail dimensions including wide metal spacing rules. + """ + + 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 + + # Get the conservative width and spacing of the top rails + (horizontal_width, horizontal_space) = self.get_layer_width_space(0, rail_width, rail_length) + (vertical_width, vertical_space) = self.get_layer_width_space(1, rail_width, rail_length) + 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 + + self.supply_rail_step = math.ceil(track_pitch/self.track_width) + debug.info(1,"Rail step: {}".format(self.supply_rail_step)) + def compute_supply_rails(self, name, start_offset): """ @@ -139,55 +166,25 @@ class supply_router(router): (for vertical). Start with an initial start_offset in x and y direction. """ - max_yoffset = self.rg.ur.y - max_xoffset = self.rg.ur.x - max_length = max(max_yoffset,max_xoffset) - - # Convert the number of tracks to dimensions to get the design rule spacing - rail_width = self.track_width*self.rail_track_width - (horizontal_width, horizontal_space) = self.get_layer_width_space(0, rail_width, max_length) - (vertical_width, vertical_space) = self.get_layer_width_space(1, rail_width, max_length) - width = max(horizontal_width, vertical_width) - space = max(horizontal_space, vertical_space) - - # This is the supply rail pitch in terms of routing grids - # The 2* is to alternate the two supplies - step_offset = 2*math.ceil((width+space)/self.track_width) - # Horizontal supply rails - for offset in range(start_offset, max_yoffset, step_offset): + for offset in range(start_offset, self.max_yoffset, self.supply_rail_step): # Seed the function at the location with the given width - wave = [vector3d(0,offset+i,0) for i in range(self.rail_track_width)] + wave = [vector3d(0,offset+i,0) for i in range(self.supply_rail_step)] # While we can keep expanding east in this horizontal track - while wave and wave[0].x < max_xoffset: + while wave and wave[0].x < self.max_xoffset: wave = self.find_supply_rail(name, wave, direction.EAST) # Vertical supply rails max_offset = self.rg.ur.x - for offset in range(start_offset, max_xoffset, step_offset): + for offset in range(start_offset, self.max_xoffset, self.supply_rail_step): # Seed the function at the location with the given width - wave = [vector3d(offset+i,0,1) for i in range(self.rail_track_width)] + wave = [vector3d(offset+i,0,1) for i in range(self.supply_rail_step)] # While we can keep expanding north in this vertical track - while wave and wave[0].y < max_yoffset: + while wave and wave[0].y < self.max_yoffset: wave = self.find_supply_rail(name, wave, direction.NORTH) - def route_supply_rails(self, name, supply_number): - """ - Route the horizontal and vertical supply rails across the entire design. - Must be done with lower left at 0,0 - """ - - # Compute the grid locations of the supply rails - start_offset = supply_number*self.rail_track_width - self.compute_supply_rails(name, start_offset) - - # Add the supply rail vias (and prune disconnected rails) - self.connect_supply_rails(name) - - # Add the rails themselves - self.add_supply_rails(name) - + def find_supply_rail(self, name, seed_wave, direct): """ This finds the first valid starting location and routes a supply rail @@ -227,6 +224,26 @@ class supply_router(router): + def route_supply_rails(self, name, supply_number): + """ + Route the horizontal and vertical supply rails across the entire design. + Must be done with lower left at 0,0 + """ + + # Compute the grid dimensions + self.compute_supply_rail_dimensions() + + # Compute the grid locations of the supply rails + start_offset = supply_number*self.rail_track_width + self.compute_supply_rails(name, start_offset) + + # Add the supply rail vias (and prune disconnected rails) + self.connect_supply_rails(name) + + # Add the rails themselves + self.add_supply_rails(name) + + def route_pins_to_rails(self, pin_name): """