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