diff --git a/compiler/router/grid.py b/compiler/router/grid.py index ae6e04ee..e619bf4d 100644 --- a/compiler/router/grid.py +++ b/compiler/router/grid.py @@ -36,7 +36,7 @@ class grid: # The bounds are in grids for this # This is really lower left bottom layer and upper right top layer in 3D. self.ll = vector3d(ll.x, ll.y, 0).scale(self.track_factor).round() - self.ur = vector3d(ur.x, ur.y, 1).scale(self.track_factor).round() + self.ur = vector3d(ur.x, ur.y, 0).scale(self.track_factor).round() # let's leave the map sparse, cells are created on demand to reduce memory self.map={} @@ -124,7 +124,7 @@ class grid: def add_perimeter_target(self, side="all"): debug.info(3, "Adding perimeter target") - + print(self.ll, self.ur) perimeter_list = [] # Add the left/right columns if side=="all" or side=="left": diff --git a/compiler/router/router.py b/compiler/router/router.py index ce0a739a..30ae76e7 100644 --- a/compiler/router/router.py +++ b/compiler/router/router.py @@ -28,7 +28,7 @@ class router(router_tech): route on a given layer. This is limited to two layer routes. It populates blockages on a grid class. """ - def __init__(self, layers, design, gds_filename=None, route_track_width=1): + def __init__(self, layers, design, gds_filename=None, bbox=None, route_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 @@ -83,12 +83,35 @@ class router(router_tech): # A list of path blockages (they might be expanded for wide metal DRC) self.path_blockages = [] - # The boundary will determine the limits to the size - # of the routing grid - 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]) - self.ur = vector(self.boundary[1][0], self.boundary[1][1]) + self.init_bbox(bbox) + + def init_bbox(self, bbox=None): + """ + Initialize the ll,ur values with the paramter or using the layout boundary. + """ + if not bbox: + # The boundary will determine the limits to the size + # of the routing grid + 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]) + self.ur = vector(self.boundary[1][0], self.boundary[1][1]) + else: + self.ll, self.ur = bbox + + self.bbox = (self.ll, self.ur) + size = self.ur - self.ll + debug.info(1, "Size: {0} x {1}".format(size.x, size.y)) + + def get_bbox(self): + return self.bbox + + def create_routing_grid(self, router_type, bbox=None): + """ + Create a sprase routing grid with A* expansion functions. + """ + self.init_bbox(bbox) + self.rg = router_type(self.ll, self.ur, self.track_width) def clear_pins(self): """ diff --git a/compiler/router/signal_escape_router.py b/compiler/router/signal_escape_router.py index 134a2ee3..2352bbc9 100644 --- a/compiler/router/signal_escape_router.py +++ b/compiler/router/signal_escape_router.py @@ -17,20 +17,12 @@ class signal_escape_router(router): A router that routes signals to perimeter and makes pins. """ - def __init__(self, layers, design, gds_filename=None): + def __init__(self, layers, design, bbox=None, gds_filename=None): """ 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, 1) - - def create_routing_grid(self): - """ - Create a sprase routing grid with A* expansion functions. - """ - size = self.ur - self.ll - debug.info(1,"Size: {0} x {1}".format(size.x, size.y)) - self.rg = signal_grid(self.ll, self.ur, self.track_width) + router.__init__(self, layers, design, gds_filename, bbox) def perimeter_dist(self, pin_name): """ @@ -47,7 +39,7 @@ class signal_escape_router(router): Takes a list of tuples (name, side) and routes them. After routing, it removes the old pin and places a new one on the perimeter. """ - self.create_routing_grid() + self.create_routing_grid(signal_grid) start_time = datetime.now() self.find_pins_and_blockages(pin_names) @@ -91,8 +83,9 @@ class signal_escape_router(router): # Marks the grid cells all along the perimeter as a target self.add_perimeter_target(side) - #if pin_name == "dout1[1]": - # self.write_debug_gds("preroute.gds", False) + # if pin_name == "dout0[3]": + # self.write_debug_gds("pre_route.gds", False) + # breakpoint() # Actually run the A* router if self.run_router(detour_scale=detour_scale): @@ -100,6 +93,10 @@ class signal_escape_router(router): self.cell.replace_layout_pin(pin_name, new_pin) return + # if pin_name == "dout0[3]": + # self.write_debug_gds("pre_route.gds", False) + # breakpoint() + self.write_debug_gds("debug_route.gds", True) diff --git a/compiler/router/signal_router.py b/compiler/router/signal_router.py index fda92cd8..2a34bc50 100644 --- a/compiler/router/signal_router.py +++ b/compiler/router/signal_router.py @@ -15,24 +15,12 @@ class signal_router(router): route on a given layer. This is limited to two layer routes. """ - def __init__(self, layers, design, gds_filename=None): + def __init__(self, layers, design, gds_filename=None, bbox=None): """ 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) - - 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 signal_grid - self.rg = signal_grid.signal_grid(self.ll, self.ur, self.route_track_width) + router.__init__(self, layers, design, gds_filename, bbox) def route(self, src, dest, detour_scale=5): """ @@ -52,7 +40,7 @@ class signal_router(router): # Creat a routing grid over the entire area # FIXME: This could be created only over the routing region, # but this is simplest for now. - self.create_routing_grid() + self.create_routing_grid(signal_grid) # Get the pin shapes self.find_pins_and_blockages([src, dest]) diff --git a/compiler/router/supply_grid_router.py b/compiler/router/supply_grid_router.py index 6876329f..8332a212 100644 --- a/compiler/router/supply_grid_router.py +++ b/compiler/router/supply_grid_router.py @@ -11,6 +11,7 @@ from vector3d import vector3d from router import router from direction import direction from datetime import datetime +from supply_grid import supply_grid import grid_utils @@ -20,7 +21,7 @@ class supply_grid_router(router): routes a grid to connect the supply on the two layers. """ - def __init__(self, layers, design, gds_filename=None): + def __init__(self, layers, design, gds_filename=None, bbox=None): """ 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). @@ -30,7 +31,7 @@ class supply_grid_router(router): # Power rail width in minimum wire widths self.route_track_width = 2 - router.__init__(self, layers, design, gds_filename, self.route_track_width) + router.__init__(self, layers, design, gds_filename, bbox, self.route_track_width) # The list of supply rails (grid sets) that may be routed self.supply_rails = {} @@ -39,16 +40,6 @@ class supply_grid_router(router): print_time("Init supply router", datetime.now(), start_time, 3) - def create_routing_grid(self): - """ - Create a sprase routing grid with A* expansion functions. - """ - 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(self.ll, self.ur, self.route_track_width) - def route(self, vdd_name="vdd", gnd_name="gnd"): """ Add power supply rails and connect all pins to these rails. @@ -64,7 +55,7 @@ class supply_grid_router(router): # Creat a routing grid over the entire area # FIXME: This could be created only over the routing region, # but this is simplest for now. - self.create_routing_grid() + self.create_routing_grid(supply_grid) # Get the pin shapes start_time = datetime.now() diff --git a/compiler/router/supply_tree_router.py b/compiler/router/supply_tree_router.py index 31311550..2bae39e3 100644 --- a/compiler/router/supply_tree_router.py +++ b/compiler/router/supply_tree_router.py @@ -13,7 +13,7 @@ import grid_utils from scipy.sparse import csr_matrix from scipy.sparse.csgraph import minimum_spanning_tree from signal_grid import signal_grid -from vector3d import vector3d + class supply_tree_router(router): """ @@ -21,23 +21,17 @@ class supply_tree_router(router): routes a grid to connect the supply on the two layers. """ - def __init__(self, layers, design, gds_filename=None): + def __init__(self, layers, design, gds_filename=None, bbox=None): """ 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). """ # Power rail width in minimum wire widths - self.route_track_width = 2 + # This is set to match the signal router so that the grids are aligned + # for prettier routes. + self.route_track_width = 1 - router.__init__(self, layers, design, gds_filename, self.route_track_width) - - def create_routing_grid(self): - """ - Create a sprase routing grid with A* expansion functions. - """ - size = self.ur - self.ll - debug.info(1,"Size: {0} x {1}".format(size.x,size.y)) - self.rg = signal_grid(self.ll, self.ur, self.route_track_width) + router.__init__(self, layers, design, gds_filename, bbox, self.route_track_width) def route(self, vdd_name="vdd", gnd_name="gnd"): """ @@ -54,7 +48,7 @@ class supply_tree_router(router): # Creat a routing grid over the entire area # FIXME: This could be created only over the routing region, # but this is simplest for now. - self.create_routing_grid() + self.create_routing_grid(signal_grid) # Get the pin shapes start_time = datetime.now() @@ -122,7 +116,7 @@ class supply_tree_router(router): # self.write_debug_gds("post_{0}_{1}.gds".format(src, dest), False) #self.write_debug_gds("final.gds", True) - #return + #return def route_signal(self, pin_name, src_idx, dest_idx): diff --git a/compiler/sram/sram_1bank.py b/compiler/sram/sram_1bank.py index d96f9336..c34b4b3c 100644 --- a/compiler/sram/sram_1bank.py +++ b/compiler/sram/sram_1bank.py @@ -9,9 +9,7 @@ from vector import vector from sram_base import sram_base from contact import m2_via from channel_route import channel_route -from signal_escape_router import signal_escape_router as router from globals import OPTS -import debug class sram_1bank(sram_base): @@ -247,49 +245,6 @@ class sram_1bank(sram_base): self.data_pos[port] = vector(x_offset, y_offset) self.spare_wen_pos[port] = vector(x_offset, y_offset) - def route_escape_pins(self): - """ - Add the top-level pins for a single bank SRAM with control. - """ - - # List of pin to new pin name - pins_to_route = [] - for port in self.all_ports: - # Connect the control pins as inputs - for signal in self.control_logic_inputs[port]: - if signal.startswith("rbl"): - continue - if signal=="clk": - pins_to_route.append("{0}{1}".format(signal, port)) - else: - pins_to_route.append("{0}{1}".format(signal, port)) - - if port in self.write_ports: - for bit in range(self.word_size + self.num_spare_cols): - pins_to_route.append("din{0}[{1}]".format(port, bit)) - - if port in self.readwrite_ports or port in self.read_ports: - for bit in range(self.word_size + self.num_spare_cols): - pins_to_route.append("dout{0}[{1}]".format(port, bit)) - - for bit in range(self.col_addr_size): - pins_to_route.append("addr{0}[{1}]".format(port, bit)) - - for bit in range(self.row_addr_size): - pins_to_route.append("addr{0}[{1}]".format(port, bit + self.col_addr_size)) - - if port in self.write_ports: - if self.write_size: - for bit in range(self.num_wmasks): - pins_to_route.append("wmask{0}[{1}]".format(port, bit)) - - if port in self.write_ports: - for bit in range(self.num_spare_cols): - pins_to_route.append("spare_wen{0}[{1}]".format(port, bit)) - - rtr=router(self.m3_stack, self) - rtr.escape_route(pins_to_route) - def add_layout_pins(self, add_vias=True): """ Add the top-level pins for a single bank SRAM with control. diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 94fa245b..a3beacfa 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -264,6 +264,50 @@ class sram_base(design, verilog, lef): pin.width(), pin.height()) + def route_escape_pins(self): + """ + Add the top-level pins for a single bank SRAM with control. + """ + + # List of pin to new pin name + pins_to_route = [] + for port in self.all_ports: + # Connect the control pins as inputs + for signal in self.control_logic_inputs[port]: + if signal.startswith("rbl"): + continue + if signal=="clk": + pins_to_route.append("{0}{1}".format(signal, port)) + else: + pins_to_route.append("{0}{1}".format(signal, port)) + + if port in self.write_ports: + for bit in range(self.word_size + self.num_spare_cols): + pins_to_route.append("din{0}[{1}]".format(port, bit)) + + if port in self.readwrite_ports or port in self.read_ports: + for bit in range(self.word_size + self.num_spare_cols): + pins_to_route.append("dout{0}[{1}]".format(port, bit)) + + for bit in range(self.col_addr_size): + pins_to_route.append("addr{0}[{1}]".format(port, bit)) + + for bit in range(self.row_addr_size): + pins_to_route.append("addr{0}[{1}]".format(port, bit + self.col_addr_size)) + + if port in self.write_ports: + if self.write_size: + for bit in range(self.num_wmasks): + pins_to_route.append("wmask{0}[{1}]".format(port, bit)) + + if port in self.write_ports: + for bit in range(self.num_spare_cols): + pins_to_route.append("spare_wen{0}[{1}]".format(port, bit)) + + from signal_escape_router import signal_escape_router as router + rtr=router(self.m3_stack, self) + rtr.escape_route(pins_to_route) + def compute_bus_sizes(self): """ Compute the independent bus widths shared between two and four bank SRAMs """