mirror of https://github.com/VLSIDA/OpenRAM.git
Supply tree uses signal grid. PEP8 cleanup.
This commit is contained in:
parent
98250cf115
commit
348001b1c8
|
|
@ -11,7 +11,7 @@ nominal_corner_only = True
|
|||
|
||||
route_supplies = True
|
||||
check_lvsdrc = True
|
||||
perimeter_pins = True
|
||||
perimeter_pins = False
|
||||
#netlist_only = True
|
||||
#analytical_delay = False
|
||||
output_name = "sram_{0}rw{1}r{2}w_{3}_{4}_{5}".format(num_rw_ports,
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ num_w_ports = 0
|
|||
tech_name = "scn4m_subm"
|
||||
nominal_corner_only = True
|
||||
|
||||
route_supplies = False
|
||||
check_lvsdrc = False
|
||||
route_supplies = "tree"
|
||||
check_lvsdrc = True
|
||||
perimeter_pins = False
|
||||
#netlist_only = True
|
||||
#analytical_delay = False
|
||||
|
|
|
|||
|
|
@ -27,13 +27,14 @@ 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, rail_track_width=1):
|
||||
def __init__(self, layers, design, gds_filename=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
|
||||
considered.
|
||||
"""
|
||||
router_tech.__init__(self, layers, rail_track_width)
|
||||
|
||||
router_tech.__init__(self, layers, route_track_width)
|
||||
|
||||
self.cell = design
|
||||
|
||||
|
|
@ -1165,6 +1166,14 @@ class router(router_tech):
|
|||
|
||||
return keep_pin
|
||||
|
||||
def check_all_routed(self, pin_name):
|
||||
"""
|
||||
Check that all pin groups are routed.
|
||||
"""
|
||||
for pg in self.pin_groups[pin_name]:
|
||||
if not pg.is_routed():
|
||||
return False
|
||||
|
||||
|
||||
# FIXME: This should be replaced with vector.snap_to_grid at some point
|
||||
def snap_to_grid(offset):
|
||||
|
|
|
|||
|
|
@ -16,13 +16,13 @@ class router_tech:
|
|||
"""
|
||||
This is a class to hold the router tech constants.
|
||||
"""
|
||||
def __init__(self, layers, rail_track_width):
|
||||
def __init__(self, layers, route_track_width):
|
||||
"""
|
||||
Allows us to change the layers that we are routing on.
|
||||
This uses the preferreed directions.
|
||||
"""
|
||||
self.layers = layers
|
||||
self.rail_track_width = rail_track_width
|
||||
self.route_track_width = route_track_width
|
||||
|
||||
if len(self.layers) == 1:
|
||||
self.horiz_layer_name = self.vert_layer_name = self.layers[0]
|
||||
|
|
@ -123,8 +123,8 @@ class router_tech:
|
|||
|
||||
min_wire_width = drc("minwidth_{0}".format(layer_name), 0, math.inf)
|
||||
|
||||
min_width = drc("minwidth_{0}".format(layer_name), self.rail_track_width*min_wire_width, math.inf)
|
||||
min_spacing = drc(str(layer_name)+"_to_"+str(layer_name), self.rail_track_width*min_wire_width, math.inf)
|
||||
min_width = drc("minwidth_{0}".format(layer_name), self.route_track_width * min_wire_width, math.inf)
|
||||
min_spacing = drc(str(layer_name)+"_to_"+str(layer_name), self.route_track_width * min_wire_width, math.inf)
|
||||
|
||||
return (min_width, min_spacing)
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
# (acting for and on behalf of Oklahoma State University)
|
||||
# All rights reserved.
|
||||
#
|
||||
from itertools import tee
|
||||
import debug
|
||||
from heapq import heappush,heappop
|
||||
from copy import deepcopy
|
||||
|
|
@ -14,6 +13,7 @@ from grid import grid
|
|||
from grid_path import grid_path
|
||||
from vector3d import vector3d
|
||||
|
||||
|
||||
class signal_grid(grid):
|
||||
"""
|
||||
Expand the two layer grid to include A* search functions for a source and target.
|
||||
|
|
@ -34,8 +34,8 @@ class signal_grid(grid):
|
|||
p.reset()
|
||||
|
||||
# clear source and target pins
|
||||
self.source=[]
|
||||
self.target=[]
|
||||
self.source = set()
|
||||
self.target = set()
|
||||
|
||||
# Clear the queue
|
||||
while len(self.q) > 0:
|
||||
|
|
@ -60,7 +60,6 @@ class signal_grid(grid):
|
|||
heappush(self.q, (cost, self.counter, grid_path([vector3d(s)])))
|
||||
self.counter+=1
|
||||
|
||||
|
||||
def route(self, detour_scale):
|
||||
"""
|
||||
This does the A* maze routing with preferred direction routing.
|
||||
|
|
@ -83,9 +82,6 @@ class signal_grid(grid):
|
|||
|
||||
# Put the source items into the queue
|
||||
self.init_queue()
|
||||
cheapest_path = None
|
||||
cheapest_cost = None
|
||||
|
||||
|
||||
# Keep expanding and adding to the priority queue until we are done
|
||||
while len(self.q)>0:
|
||||
|
|
@ -142,7 +138,6 @@ class signal_grid(grid):
|
|||
|
||||
return unblocked_neighbors
|
||||
|
||||
|
||||
def hpwl(self, src, dest):
|
||||
"""
|
||||
Return half perimeter wire length from point to another.
|
||||
|
|
@ -167,7 +162,6 @@ class signal_grid(grid):
|
|||
|
||||
return cost
|
||||
|
||||
|
||||
def get_inertia(self, p0, p1):
|
||||
"""
|
||||
Sets the direction based on the previous direction we came from.
|
||||
|
|
|
|||
|
|
@ -5,15 +5,10 @@
|
|||
# (acting for and on behalf of Oklahoma State University)
|
||||
# All rights reserved.
|
||||
#
|
||||
import gdsMill
|
||||
import tech
|
||||
from contact import contact
|
||||
import math
|
||||
import debug
|
||||
from pin_layout import pin_layout
|
||||
from globals import OPTS
|
||||
from router import router
|
||||
|
||||
|
||||
class signal_router(router):
|
||||
"""
|
||||
A router class to read an obstruction map from a gds and plan a
|
||||
|
|
@ -27,7 +22,6 @@ class signal_router(router):
|
|||
"""
|
||||
router.__init__(self, layers, design, gds_filename)
|
||||
|
||||
|
||||
def create_routing_grid(self):
|
||||
"""
|
||||
Create a sprase routing grid with A* expansion functions.
|
||||
|
|
@ -38,8 +32,7 @@ class signal_router(router):
|
|||
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.track_width)
|
||||
|
||||
self.rg = signal_grid.signal_grid(self.ll, self.ur, self.route_track_width)
|
||||
|
||||
def route(self, src, dest, detour_scale=5):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -5,12 +5,8 @@
|
|||
# (acting for and on behalf of Oklahoma State University)
|
||||
# All rights reserved.
|
||||
#
|
||||
import debug
|
||||
from vector3d import vector3d
|
||||
from grid import grid
|
||||
from signal_grid import signal_grid
|
||||
from grid_path import grid_path
|
||||
from direction import direction
|
||||
|
||||
|
||||
class supply_grid(signal_grid):
|
||||
|
|
@ -27,13 +23,14 @@ class supply_grid(signal_grid):
|
|||
|
||||
def reinit(self):
|
||||
""" Reinitialize everything for a new route. """
|
||||
|
||||
self.source = set()
|
||||
self.target = set()
|
||||
|
||||
# Reset all the cells in the map
|
||||
for p in self.map.values():
|
||||
p.reset()
|
||||
|
||||
|
||||
def find_start_wave(self, wave, direct):
|
||||
"""
|
||||
Finds the first loc starting at loc and up that is open.
|
||||
|
|
@ -57,7 +54,6 @@ class supply_grid(signal_grid):
|
|||
|
||||
return wave
|
||||
|
||||
|
||||
def is_wave_blocked(self, wave):
|
||||
"""
|
||||
Checks if any of the locations are blocked
|
||||
|
|
@ -68,7 +64,6 @@ class supply_grid(signal_grid):
|
|||
else:
|
||||
return False
|
||||
|
||||
|
||||
def probe(self, wave, direct):
|
||||
"""
|
||||
Expand the wave until there is a blockage and return
|
||||
|
|
|
|||
|
|
@ -28,9 +28,9 @@ class supply_grid_router(router):
|
|||
start_time = datetime.now()
|
||||
|
||||
# Power rail width in minimum wire widths
|
||||
self.rail_track_width = 3
|
||||
self.route_track_width = 3
|
||||
|
||||
router.__init__(self, layers, design, gds_filename, self.rail_track_width)
|
||||
router.__init__(self, layers, design, gds_filename, self.route_track_width)
|
||||
|
||||
# The list of supply rails (grid sets) that may be routed
|
||||
self.supply_rails = {}
|
||||
|
|
@ -47,7 +47,7 @@ class supply_grid_router(router):
|
|||
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.track_width)
|
||||
self.rg = supply_grid.supply_grid(self.ll, self.ur, self.route_track_width)
|
||||
|
||||
def route(self, vdd_name="vdd", gnd_name="gnd"):
|
||||
"""
|
||||
|
|
@ -104,14 +104,6 @@ class supply_grid_router(router):
|
|||
|
||||
return True
|
||||
|
||||
def check_all_routed(self, pin_name):
|
||||
"""
|
||||
Check that all pin groups are routed.
|
||||
"""
|
||||
for pg in self.pin_groups[pin_name]:
|
||||
if not pg.is_routed():
|
||||
return False
|
||||
|
||||
def route_simple_overlaps(self, pin_name):
|
||||
"""
|
||||
This checks for simple cases where a pin component already overlaps a supply rail.
|
||||
|
|
@ -317,7 +309,7 @@ class supply_grid_router(router):
|
|||
data structure. Return whether it was added or not.
|
||||
"""
|
||||
# We must have at least 2 tracks to drop plus 2 tracks for a via
|
||||
if len(wave_path) >= 4 * self.rail_track_width:
|
||||
if len(wave_path) >= 4 * self.route_track_width:
|
||||
grid_set = wave_path.get_grids()
|
||||
self.supply_rails[name].append(grid_set)
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -26,9 +26,9 @@ class supply_tree_router(router):
|
|||
either the gds file name or the design itself (by saving to a gds file).
|
||||
"""
|
||||
# Power rail width in minimum wire widths
|
||||
self.rail_track_width = 3
|
||||
self.route_track_width = 3
|
||||
|
||||
router.__init__(self, layers, design, gds_filename, self.rail_track_width)
|
||||
router.__init__(self, layers, design, gds_filename, self.route_track_width)
|
||||
|
||||
def create_routing_grid(self):
|
||||
"""
|
||||
|
|
@ -37,8 +37,8 @@ class supply_tree_router(router):
|
|||
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.track_width)
|
||||
import signal_grid
|
||||
self.rg = signal_grid.signal_grid(self.ll, self.ur, self.route_track_width)
|
||||
|
||||
def route(self, vdd_name="vdd", gnd_name="gnd"):
|
||||
"""
|
||||
|
|
@ -85,15 +85,6 @@ class supply_tree_router(router):
|
|||
|
||||
return True
|
||||
|
||||
|
||||
def check_all_routed(self, pin_name):
|
||||
"""
|
||||
Check that all pin groups are routed.
|
||||
"""
|
||||
for pg in self.pin_groups[pin_name]:
|
||||
if not pg.is_routed():
|
||||
return False
|
||||
|
||||
def prepare_blockages(self, pin_name):
|
||||
"""
|
||||
Reset and add all of the blockages in the design.
|
||||
|
|
@ -125,7 +116,6 @@ class supply_tree_router(router):
|
|||
blockage_grids = {y for x in self.pin_groups[pin_name] for y in x.grids}
|
||||
self.set_blockages(blockage_grids,False)
|
||||
|
||||
|
||||
def route_pins(self, pin_name):
|
||||
"""
|
||||
This will route each of the remaining pin components to the other pins.
|
||||
|
|
@ -137,6 +127,7 @@ class supply_tree_router(router):
|
|||
remaining_components))
|
||||
|
||||
# Create full graph
|
||||
debug.info(2,"Creating adjacency matrix")
|
||||
pin_size = len(self.pin_groups[pin_name])
|
||||
adj_matrix = [[0] * pin_size for i in range(pin_size)]
|
||||
|
||||
|
|
@ -148,6 +139,7 @@ class supply_tree_router(router):
|
|||
adj_matrix[index1][index2] = dist
|
||||
|
||||
# Find MST
|
||||
debug.info(2,"Finding MinimumSpanning Tree")
|
||||
X = csr_matrix(adj_matrix)
|
||||
Tcsr = minimum_spanning_tree(X)
|
||||
mst = Tcsr.toarray().astype(int)
|
||||
|
|
|
|||
|
|
@ -87,6 +87,17 @@ class sram():
|
|||
def save(self):
|
||||
""" Save all the output files while reporting time to do it as well. """
|
||||
|
||||
# Save the spice file
|
||||
start_time = datetime.datetime.now()
|
||||
spname = OPTS.output_path + self.s.name + ".sp"
|
||||
debug.print_raw("SP: Writing to {0}".format(spname))
|
||||
self.sp_write(spname)
|
||||
functional(self.s,
|
||||
os.path.basename(spname),
|
||||
cycles=200,
|
||||
output_path=OPTS.output_path)
|
||||
print_time("Spice writing", datetime.datetime.now(), start_time)
|
||||
|
||||
if not OPTS.netlist_only:
|
||||
# Write the layout
|
||||
start_time = datetime.datetime.now()
|
||||
|
|
@ -107,17 +118,6 @@ class sram():
|
|||
self.lef_write(lefname)
|
||||
print_time("LEF", datetime.datetime.now(), start_time)
|
||||
|
||||
# Save the spice file
|
||||
start_time = datetime.datetime.now()
|
||||
spname = OPTS.output_path + self.s.name + ".sp"
|
||||
debug.print_raw("SP: Writing to {0}".format(spname))
|
||||
self.sp_write(spname)
|
||||
functional(self.s,
|
||||
os.path.basename(spname),
|
||||
cycles=200,
|
||||
output_path=OPTS.output_path)
|
||||
print_time("Spice writing", datetime.datetime.now(), start_time)
|
||||
|
||||
# Save the LVS file
|
||||
start_time = datetime.datetime.now()
|
||||
lvsname = OPTS.output_path + self.s.name + ".lvs.sp"
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
# (acting for and on behalf of Oklahoma State University)
|
||||
# All rights reserved.
|
||||
#
|
||||
import debug
|
||||
from vector import vector
|
||||
from sram_base import sram_base
|
||||
from contact import m2_via
|
||||
|
|
@ -102,12 +101,17 @@ class sram_1bank(sram_base):
|
|||
|
||||
# Place with an initial wide channel (from above)
|
||||
self.place_dffs()
|
||||
|
||||
# Route the channel and set to the new data bus size
|
||||
# We need to temporarily add some pins for the x offsets
|
||||
# but we'll remove them so that they have the right y
|
||||
# offsets after the DFF placement.
|
||||
self.add_layout_pins()
|
||||
self.route_dffs(add_routes=False)
|
||||
self.remove_layout_pins()
|
||||
|
||||
# Re-place with the new channel size
|
||||
self.place_dffs()
|
||||
# Now route the channel
|
||||
self.route_dffs()
|
||||
|
||||
def place_row_addr_dffs(self):
|
||||
"""
|
||||
|
|
@ -298,8 +302,9 @@ class sram_1bank(sram_base):
|
|||
"din{0}[{1}]".format(port, bit))
|
||||
|
||||
# Data output pins go to BOTTOM/TOP
|
||||
if port in self.readwrite_ports and OPTS.perimeter_pins:
|
||||
if port in self.readwrite_ports:
|
||||
for bit in range(self.word_size + self.num_spare_cols):
|
||||
if OPTS.perimeter_pins:
|
||||
# This should be routed next to the din pin
|
||||
p = din_ports[bit]
|
||||
self.add_layout_pin_rect_center(text="dout{0}[{1}]".format(port, bit),
|
||||
|
|
@ -307,6 +312,10 @@ class sram_1bank(sram_base):
|
|||
offset=p.center() + vector(self.m3_pitch, 0),
|
||||
width=p.width(),
|
||||
height=p.height())
|
||||
else:
|
||||
self.copy_layout_pin(self.bank_inst,
|
||||
"dout{0}_{1}".format(port, bit),
|
||||
"dout{0}[{1}]".format(port, bit))
|
||||
elif port in self.read_ports:
|
||||
for bit in range(self.word_size + self.num_spare_cols):
|
||||
if OPTS.perimeter_pins:
|
||||
|
|
@ -384,6 +393,8 @@ class sram_1bank(sram_base):
|
|||
|
||||
self.route_row_addr_dff()
|
||||
|
||||
self.route_dffs()
|
||||
|
||||
def route_dffs(self, add_routes=True):
|
||||
|
||||
for port in self.all_ports:
|
||||
|
|
|
|||
|
|
@ -11,7 +11,9 @@ num_words = 16
|
|||
|
||||
tech_name = OPTS.tech_name
|
||||
|
||||
# perimeter_pins = True
|
||||
|
||||
nominal_corner_only = True
|
||||
route_supplies = "tree"
|
||||
route_supplies = "grid"
|
||||
check_lvsdrc = True
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ from tech import lvs_name
|
|||
from tech import pex_name
|
||||
|
||||
debug.info(1, "Initializing verify...")
|
||||
|
||||
if not OPTS.check_lvsdrc:
|
||||
debug.info(1, "LVS/DRC/PEX disabled.")
|
||||
OPTS.drc_exe = None
|
||||
|
|
|
|||
|
|
@ -68,7 +68,6 @@ num_pex_runs = 0
|
|||
|
||||
def write_drc_script(cell_name, gds_name, extract, final_verification, output_path, sp_name=None):
|
||||
""" Write a magic script to perform DRC and optionally extraction. """
|
||||
|
||||
global OPTS
|
||||
|
||||
# Copy .magicrc file into the output directory
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ lvs_warned = False
|
|||
pex_warned = False
|
||||
|
||||
|
||||
def write_drc_script(cell_name, gds_name, extract, final_verification=False, output_path=None):
|
||||
pass
|
||||
def write_drc_script(cell_name, gds_name, extract, final_verification=False, output_path=None, sp_name=None):
|
||||
debug.error("Cannot write DRC script for unknown tool", -1)
|
||||
|
||||
|
||||
def run_drc(cell_name, gds_name, sp_name, extract=False, final_verification=False, output_path=None):
|
||||
|
|
|
|||
Loading…
Reference in New Issue