Supply tree uses signal grid. PEP8 cleanup.

This commit is contained in:
mrg 2020-12-21 13:51:50 -08:00
parent 98250cf115
commit 348001b1c8
15 changed files with 114 additions and 128 deletions

View File

@ -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,

View File

@ -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

View File

@ -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):

View File

@ -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)

View File

@ -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.

View File

@ -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):
"""

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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"

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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):