diff --git a/compiler/router/router.py b/compiler/router/router.py index 49e74c7c..42570cb5 100644 --- a/compiler/router/router.py +++ b/compiler/router/router.py @@ -70,8 +70,7 @@ class router(router_tech): self.boundary = self.layout.measureBoundary(self.top_name) # These must be un-indexed to get rid of the matrix type self.ll = vector(self.boundary[0][0], self.boundary[0][1]) - # Pad the UR by a few tracks to add an extra rail possibly - self.ur = vector(self.boundary[1][0], self.boundary[1][1]) + self.track_widths.scale(5,5) + self.ur = vector(self.boundary[1][0], self.boundary[1][1]) def clear_pins(self): """ @@ -130,12 +129,8 @@ class router(router_tech): Pin can either be a label or a location,layer pair: [[x,y],layer]. """ debug.info(1,"Finding pins for {}.".format(pin_name)) - #start_time = datetime.now() self.retrieve_pins(pin_name) - #print_time("Retrieved pins",datetime.now(), start_time) - #start_time = datetime.now() self.analyze_pins(pin_name) - #print_time("Analyzed pins",datetime.now(), start_time) def find_blockages(self): """ @@ -160,41 +155,25 @@ class router(router_tech): # This will get all shapes as blockages and convert to grid units # This ignores shapes that were pins - #start_time = datetime.now() self.find_blockages() - #print_time("Find blockags",datetime.now(), start_time) # Convert the blockages to grid units - #start_time = datetime.now() self.convert_blockages() - #print_time("Find blockags",datetime.now(), start_time) # This will convert the pins to grid units # It must be done after blockages to ensure no DRCs between expanded pins and blocked grids - #start_time = datetime.now() for pin in pin_list: self.convert_pins(pin) - #print_time("Convert pins",datetime.now(), start_time) - #start_time = datetime.now() #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 that overlap # Must be done before enclosing pins - #start_time = datetime.now() self.separate_adjacent_pins(0) - #print_time("Separate pins",datetime.now(), start_time) - # For debug - #self.separate_adjacent_pins(1) # Enclose the continguous grid units in a metal rectangle to fix some DRCs - #start_time = datetime.now() self.enclose_pins() - #print_time("Enclose pins",datetime.now(), start_time) - #self.write_debug_gds("debug_enclose_pins.gds",stop_program=True) def combine_adjacent_pins(self, pin_name): @@ -282,7 +261,7 @@ class router(router_tech): adj_grids = pg1.adjacent_grids(pg2, separation) # These should have the same length, so... if len(adj_grids)>0: - debug.info(2,"Adjacent grids {0} {1} adj={2}".format(index1,index2,adj_grids)) + debug.info(3,"Adjacent grids {0} {1} adj={2}".format(index1,index2,adj_grids)) self.remove_adjacent_grid(pg1, pg2, adj_grids) def remove_adjacent_grid(self, pg1, pg2, adj_grids): @@ -304,12 +283,12 @@ class router(router_tech): # If the adjacent grids are a subset of the secondary grids (i.e. not necessary) # remove them from each if adj in bigger.secondary_grids: - debug.info(2,"Removing {} from bigger secondary {}".format(adj, bigger)) + debug.info(3,"Removing {} from bigger secondary {}".format(adj, bigger)) bigger.grids.remove(adj) bigger.secondary_grids.remove(adj) self.blocked_grids.add(adj) elif adj in smaller.secondary_grids: - debug.info(2,"Removing {} from smaller secondary {}".format(adj, smaller)) + debug.info(3,"Removing {} from smaller secondary {}".format(adj, smaller)) smaller.grids.remove(adj) smaller.secondary_grids.remove(adj) self.blocked_grids.add(adj) @@ -317,10 +296,10 @@ class router(router_tech): # If we couldn't remove from a secondary grid, we must remove from the primary # grid of at least one pin if adj in bigger.grids: - debug.info(2,"Removing {} from bigger primary {}".format(adj, bigger)) + debug.info(3,"Removing {} from bigger primary {}".format(adj, bigger)) bigger.grids.remove(adj) elif adj in smaller.grids: - debug.info(2,"Removing {} from smaller primary {}".format(adj, smaller)) + debug.info(3,"Removing {} from smaller primary {}".format(adj, smaller)) smaller.grids.remove(adj) @@ -361,17 +340,6 @@ class router(router_tech): self.set_blockages(blockage_grids,False) - # def translate_coordinates(self, coord, mirr, angle, xyShift): - # """ - # Calculate coordinates after flip, rotate, and shift - # """ - # coordinate = [] - # for item in coord: - # x = (item[0]*math.cos(angle)-item[1]*mirr*math.sin(angle)+xyShift[0]) - # y = (item[0]*math.sin(angle)+item[1]*mirr*math.cos(angle)+xyShift[1]) - # coordinate += [(x, y)] - # return coordinate - def convert_shape_to_units(self, shape): """ Scale a shape (two vector list) to user units @@ -498,11 +466,6 @@ class router(router_tech): # 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_name, pin, expansion=0): @@ -558,7 +521,6 @@ class router(router_tech): """ Find a list of the single pin with the most overlap. """ - #print("INSUFFICIENT LIST",insufficient_list) # Find the coordinate with the most overlap best_coord = None best_overlap = -math.inf @@ -579,7 +541,6 @@ class router(router_tech): Get a grid cell that is the furthest from the blocked grids. """ - #print("INSUFFICIENT LIST",insufficient_list) # Find the coordinate with the most overlap best_coord = None best_dist = math.inf @@ -596,7 +557,6 @@ class router(router_tech): Given a pin and a list of grid cells (probably non-overlapping), return the nearest grid cell (center to center). """ - #print("INSUFFICIENT LIST",insufficient_list) # Find the coordinate with the most overlap best_coord = None best_dist = math.inf @@ -638,10 +598,6 @@ class router(router_tech): else: debug.info(2," No overlap: {0} {1}".format(overlap_length,0)) return (None,None) - - - - def convert_track_to_pin(self, track): @@ -764,8 +720,6 @@ class router(router_tech): pg.enclose_pin() pg.add_enclosure(self.cell) - #self.write_debug_gds("pin_debug.gds", False) - def add_source(self, pin_name): """ This will mark the grids for all pin components as a source. @@ -835,9 +789,6 @@ class router(router_tech): """ debug.info(4,"Set path: " + str(path)) - # Keep track of path for future blockages - #path.set_blocked() - # This is marked for debug path.set_path() @@ -906,44 +857,10 @@ class router(router_tech): (abs_ll,unused) = pin.rect pin = self.convert_track_to_pin(ur) (unused,abs_ur) = pin.rect - #print("enclose ll={0} ur={1}".format(ll,ur)) - #print("enclose ll={0} ur={1}".format(abs_ll,abs_ur)) pin = pin_layout(name, [abs_ll, abs_ur], layer) 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. - # """ - - # # 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_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) - - # return pin - def contract_path(self,path): """ diff --git a/compiler/router/router_tech.py b/compiler/router/router_tech.py index a565201d..02b6894f 100644 --- a/compiler/router/router_tech.py +++ b/compiler/router/router_tech.py @@ -48,9 +48,9 @@ class router_tech: self.track_width = max(self.horiz_track_width,self.vert_track_width) debug.info(1,"Track width: {:.3f}".format(self.track_width)) self.track_space = max(self.horiz_layer_spacing,self.vert_layer_spacing) - debug.info(1,"Track spacing: {:.3f}".format(self.track_space)) + debug.info(1,"Track space: {:.3f}".format(self.track_space)) self.track_wire = self.track_width - self.track_space - debug.info(1,"Wire width: {:.3f}".format(self.track_wire)) + debug.info(1,"Track wire width: {:.3f}".format(self.track_wire)) self.track_widths = vector([self.track_width] * 2) self.track_factor = vector([1/self.track_width] * 2) diff --git a/compiler/router/supply_router.py b/compiler/router/supply_router.py index e5c8dd7d..0596aaf0 100644 --- a/compiler/router/supply_router.py +++ b/compiler/router/supply_router.py @@ -64,17 +64,10 @@ class supply_router(router): # but this is simplest for now. self.create_routing_grid() - # Compute the grid dimensions - self.compute_supply_rail_dimensions() - # Get the pin shapes - #start_time = datetime.now() self.find_pins_and_blockages([self.vdd_name, self.gnd_name]) - #print_time("Pins and blockages",datetime.now(), start_time) - #self.write_debug_gds("pin_enclosures.gds",stop_program=True) # Add the supply rails in a mesh network and connect H/V with vias - #start_time = datetime.now() # Block everything self.prepare_blockages(self.gnd_name) # Determine the rail locations @@ -84,23 +77,15 @@ class supply_router(router): self.prepare_blockages(self.vdd_name) # Determine the rail locations self.route_supply_rails(self.vdd_name,1) - #self.write_debug_gds("debug_rails.gds",stop_program=True) - #print_time("Supply rails",datetime.now(), start_time) - #start_time = datetime.now() self.route_simple_overlaps(vdd_name) self.route_simple_overlaps(gnd_name) - #print_time("Simple overlaps",datetime.now(), start_time) - #self.write_debug_gds("debug_simple_route.gds",stop_program=False) # Route the supply pins to the supply rails # Route vdd first since we want it to be shorter - #start_time = datetime.now() self.route_pins_to_rails(vdd_name) self.route_pins_to_rails(gnd_name) - #print_time("Routing",datetime.now(), start_time) - #self.write_debug_gds("debug_pin_routes.gds",stop_program=True) - + #self.write_debug_gds("final.gds",False) return True @@ -227,40 +212,6 @@ class supply_router(router): width=pin.width(), height=pin.height()) - 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_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) - - # 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)) - - # # 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): """ Compute the unblocked locations for the horizontal and vertical supply rails. @@ -270,14 +221,19 @@ class supply_router(router): self.supply_rails[name]=[] - start_offset = supply_number + max_yoffset = self.rg.ur.y + max_xoffset = self.rg.ur.x + min_yoffset = self.rg.ll.y + min_xoffset = self.rg.ll.x + start_offset = min_yoffset + supply_number + # Horizontal supply rails - for offset in range(start_offset, self.max_yoffset, 2): + for offset in range(start_offset, max_yoffset, 2): # Seed the function at the location with the given width - wave = [vector3d(0,offset,0)] + wave = [vector3d(min_xoffset,offset,0)] # While we can keep expanding east in this horizontal track - while wave and wave[0].x < self.max_xoffset: + while wave and wave[0].x < max_xoffset: added_rail = self.find_supply_rail(name, wave, direction.EAST) if not added_rail: # Just seed with the next one @@ -288,11 +244,11 @@ class supply_router(router): # Vertical supply rails max_offset = self.rg.ur.x - for offset in range(start_offset, self.max_xoffset, 2): + for offset in range(start_offset, max_xoffset, 2): # Seed the function at the location with the given width - wave = [vector3d(offset,0,1)] + wave = [vector3d(offset,min_yoffset,1)] # While we can keep expanding north in this vertical track - while wave and wave[0].y < self.max_yoffset: + while wave and wave[0].y < max_yoffset: added_rail = self.find_supply_rail(name, wave, direction.NORTH) if not added_rail: # Just seed with the next one diff --git a/compiler/sram_1bank.py b/compiler/sram_1bank.py index be7f20ff..e43dac72 100644 --- a/compiler/sram_1bank.py +++ b/compiler/sram_1bank.py @@ -21,11 +21,6 @@ class sram_1bank(sram_base): def __init__(self, name, sram_config): sram_base.__init__(self, name, sram_config) - - def create_netlist(self): - sram_base.create_netlist(self) - self.create_modules() - def create_modules(self): """ This adds the modules for a single bank SRAM with control diff --git a/compiler/sram_base.py b/compiler/sram_base.py index 3182c5b3..be0797fc 100644 --- a/compiler/sram_base.py +++ b/compiler/sram_base.py @@ -2,6 +2,7 @@ import sys import datetime import getpass import debug +from datetime import datetime from importlib import reload from vector import vector from globals import OPTS, print_time @@ -63,37 +64,52 @@ class sram_base(design): def create_netlist(self): """ Netlist creation """ - + + start_time = datetime.now() + # Must create the control logic before pins to get the pins self.add_modules() self.add_pins() + self.create_modules() # This is for the lib file if we don't create layout self.width=0 self.height=0 + + + if not OPTS.is_unit_test: + print_time("Netlisting",datetime.now(), start_time) def create_layout(self): """ Layout creation """ + start_time = datetime.now() self.place_instances() + if not OPTS.is_unit_test: + print_time("Placement",datetime.now(), start_time) + start_time = datetime.now() self.route_layout() + self.route_supplies() + if not OPTS.is_unit_test: + print_time("Routing",datetime.now(), start_time) self.add_lvs_correspondence_points() self.offset_all_coordinates() - # Must be done after offsetting lower-left - self.route_supplies() - highest_coord = self.find_highest_coords() self.width = highest_coord[0] self.height = highest_coord[1] - + start_time = datetime.now() self.DRC_LVS(final_verification=True) + if not OPTS.is_unit_test: + print_time("Verification",datetime.now(), start_time) - + def create_modules(self): + debug.error("Must override pure virtual function.",-1) + def route_supplies(self): """ Route the supply grid and connect the pins to them. """