Refactor and cleanup router grids.

This commit is contained in:
mrg 2021-01-15 13:25:57 -08:00
parent 683f4214b2
commit 69fe050bad
8 changed files with 101 additions and 109 deletions

View File

@ -36,7 +36,7 @@ class grid:
# The bounds are in grids for this # The bounds are in grids for this
# This is really lower left bottom layer and upper right top layer in 3D. # 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.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 # let's leave the map sparse, cells are created on demand to reduce memory
self.map={} self.map={}
@ -124,7 +124,7 @@ class grid:
def add_perimeter_target(self, side="all"): def add_perimeter_target(self, side="all"):
debug.info(3, "Adding perimeter target") debug.info(3, "Adding perimeter target")
print(self.ll, self.ur)
perimeter_list = [] perimeter_list = []
# Add the left/right columns # Add the left/right columns
if side=="all" or side=="left": if side=="all" or side=="left":

View File

@ -28,7 +28,7 @@ class router(router_tech):
route on a given layer. This is limited to two layer routes. route on a given layer. This is limited to two layer routes.
It populates blockages on a grid class. 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 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 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) # A list of path blockages (they might be expanded for wide metal DRC)
self.path_blockages = [] self.path_blockages = []
# The boundary will determine the limits to the size self.init_bbox(bbox)
# of the routing grid
self.boundary = self.layout.measureBoundary(self.top_name) def init_bbox(self, bbox=None):
# These must be un-indexed to get rid of the matrix type """
self.ll = vector(self.boundary[0][0], self.boundary[0][1]) Initialize the ll,ur values with the paramter or using the layout boundary.
self.ur = vector(self.boundary[1][0], self.boundary[1][1]) """
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): def clear_pins(self):
""" """

View File

@ -17,20 +17,12 @@ class signal_escape_router(router):
A router that routes signals to perimeter and makes pins. 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 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). either the gds file name or the design itself (by saving to a gds file).
""" """
router.__init__(self, layers, design, gds_filename, 1) router.__init__(self, layers, design, gds_filename, bbox)
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)
def perimeter_dist(self, pin_name): 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, 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. 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() start_time = datetime.now()
self.find_pins_and_blockages(pin_names) 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 # Marks the grid cells all along the perimeter as a target
self.add_perimeter_target(side) self.add_perimeter_target(side)
#if pin_name == "dout1[1]": # if pin_name == "dout0[3]":
# self.write_debug_gds("preroute.gds", False) # self.write_debug_gds("pre_route.gds", False)
# breakpoint()
# Actually run the A* router # Actually run the A* router
if self.run_router(detour_scale=detour_scale): 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) self.cell.replace_layout_pin(pin_name, new_pin)
return return
# if pin_name == "dout0[3]":
# self.write_debug_gds("pre_route.gds", False)
# breakpoint()
self.write_debug_gds("debug_route.gds", True) self.write_debug_gds("debug_route.gds", True)

View File

@ -15,24 +15,12 @@ class signal_router(router):
route on a given layer. This is limited to two layer routes. 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 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). either the gds file name or the design itself (by saving to a gds file).
""" """
router.__init__(self, layers, design, gds_filename) router.__init__(self, layers, design, gds_filename, bbox)
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)
def route(self, src, dest, detour_scale=5): def route(self, src, dest, detour_scale=5):
""" """
@ -52,7 +40,7 @@ class signal_router(router):
# Creat a routing grid over the entire area # Creat a routing grid over the entire area
# FIXME: This could be created only over the routing region, # FIXME: This could be created only over the routing region,
# but this is simplest for now. # but this is simplest for now.
self.create_routing_grid() self.create_routing_grid(signal_grid)
# Get the pin shapes # Get the pin shapes
self.find_pins_and_blockages([src, dest]) self.find_pins_and_blockages([src, dest])

View File

@ -11,6 +11,7 @@ from vector3d import vector3d
from router import router from router import router
from direction import direction from direction import direction
from datetime import datetime from datetime import datetime
from supply_grid import supply_grid
import grid_utils import grid_utils
@ -20,7 +21,7 @@ class supply_grid_router(router):
routes a grid to connect the supply on the two layers. 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 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). 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 # Power rail width in minimum wire widths
self.route_track_width = 2 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 # The list of supply rails (grid sets) that may be routed
self.supply_rails = {} self.supply_rails = {}
@ -39,16 +40,6 @@ class supply_grid_router(router):
print_time("Init supply router", datetime.now(), start_time, 3) 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"): def route(self, vdd_name="vdd", gnd_name="gnd"):
""" """
Add power supply rails and connect all pins to these rails. 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 # Creat a routing grid over the entire area
# FIXME: This could be created only over the routing region, # FIXME: This could be created only over the routing region,
# but this is simplest for now. # but this is simplest for now.
self.create_routing_grid() self.create_routing_grid(supply_grid)
# Get the pin shapes # Get the pin shapes
start_time = datetime.now() start_time = datetime.now()

View File

@ -13,7 +13,7 @@ import grid_utils
from scipy.sparse import csr_matrix from scipy.sparse import csr_matrix
from scipy.sparse.csgraph import minimum_spanning_tree from scipy.sparse.csgraph import minimum_spanning_tree
from signal_grid import signal_grid from signal_grid import signal_grid
from vector3d import vector3d
class supply_tree_router(router): 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. 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 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). either the gds file name or the design itself (by saving to a gds file).
""" """
# Power rail width in minimum wire widths # 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) router.__init__(self, layers, design, gds_filename, bbox, 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)
def route(self, vdd_name="vdd", gnd_name="gnd"): 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 # Creat a routing grid over the entire area
# FIXME: This could be created only over the routing region, # FIXME: This could be created only over the routing region,
# but this is simplest for now. # but this is simplest for now.
self.create_routing_grid() self.create_routing_grid(signal_grid)
# Get the pin shapes # Get the pin shapes
start_time = datetime.now() start_time = datetime.now()

View File

@ -9,9 +9,7 @@ from vector import vector
from sram_base import sram_base from sram_base import sram_base
from contact import m2_via from contact import m2_via
from channel_route import channel_route from channel_route import channel_route
from signal_escape_router import signal_escape_router as router
from globals import OPTS from globals import OPTS
import debug
class sram_1bank(sram_base): class sram_1bank(sram_base):
@ -247,49 +245,6 @@ class sram_1bank(sram_base):
self.data_pos[port] = vector(x_offset, y_offset) self.data_pos[port] = vector(x_offset, y_offset)
self.spare_wen_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): def add_layout_pins(self, add_vias=True):
""" """
Add the top-level pins for a single bank SRAM with control. Add the top-level pins for a single bank SRAM with control.

View File

@ -264,6 +264,50 @@ class sram_base(design, verilog, lef):
pin.width(), pin.width(),
pin.height()) 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): def compute_bus_sizes(self):
""" Compute the independent bus widths shared between two and four bank SRAMs """ """ Compute the independent bus widths shared between two and four bank SRAMs """