mirror of https://github.com/VLSIDA/OpenRAM.git
Refactor and cleanup router grids.
This commit is contained in:
parent
683f4214b2
commit
69fe050bad
|
|
@ -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":
|
||||||
|
|
|
||||||
|
|
@ -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):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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])
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
@ -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("post_{0}_{1}.gds".format(src, dest), False)
|
||||||
|
|
||||||
#self.write_debug_gds("final.gds", True)
|
#self.write_debug_gds("final.gds", True)
|
||||||
#return
|
#return
|
||||||
|
|
||||||
def route_signal(self, pin_name, src_idx, dest_idx):
|
def route_signal(self, pin_name, src_idx, dest_idx):
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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 """
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue