mirror of https://github.com/VLSIDA/OpenRAM.git
Merge remote-tracking branch 'private/dev'
This commit is contained in:
commit
c0df3ff1da
|
|
@ -23,10 +23,14 @@ class geometry:
|
|||
A specific path, shape, or text geometry. Base class for shared
|
||||
items.
|
||||
"""
|
||||
def __init__(self):
|
||||
def __init__(self, lpp=None):
|
||||
""" By default, everything has no size. """
|
||||
self.width = 0
|
||||
self.height = 0
|
||||
if lpp:
|
||||
self.lpp = lpp
|
||||
self.layerNumber = lpp[0]
|
||||
self.layerPurpose = lpp[1]
|
||||
|
||||
def __str__(self):
|
||||
""" override print function output """
|
||||
|
|
@ -410,10 +414,8 @@ class path(geometry):
|
|||
|
||||
def __init__(self, lpp, coordinates, path_width):
|
||||
"""Initializes a path for the specified layer"""
|
||||
super().__init__()
|
||||
super().__init__(lpp)
|
||||
self.name = "path"
|
||||
self.layerNumber = lpp[0]
|
||||
self.layerPurpose = lpp[1]
|
||||
self.coordinates = map(lambda x: [x[0], x[1]], coordinates)
|
||||
self.coordinates = vector(self.coordinates).snap_to_grid()
|
||||
self.path_width = path_width
|
||||
|
|
@ -448,11 +450,9 @@ class label(geometry):
|
|||
|
||||
def __init__(self, text, lpp, offset, zoom=None):
|
||||
"""Initializes a text label for specified layer"""
|
||||
super().__init__()
|
||||
super().__init__(lpp)
|
||||
self.name = "label"
|
||||
self.text = text
|
||||
self.layerNumber = lpp[0]
|
||||
self.layerPurpose = lpp[1]
|
||||
self.offset = vector(offset).snap_to_grid()
|
||||
|
||||
if not zoom:
|
||||
|
|
@ -495,10 +495,8 @@ class rectangle(geometry):
|
|||
|
||||
def __init__(self, lpp, offset, width, height):
|
||||
"""Initializes a rectangular shape for specified layer"""
|
||||
super().__init__()
|
||||
super().__init__(lpp)
|
||||
self.name = "rect"
|
||||
self.layerNumber = lpp[0]
|
||||
self.layerPurpose = lpp[1]
|
||||
self.offset = vector(offset).snap_to_grid()
|
||||
self.size = vector(width, height).snap_to_grid()
|
||||
self.width = round_to_grid(self.size.x)
|
||||
|
|
|
|||
|
|
@ -473,11 +473,25 @@ class layout():
|
|||
"""
|
||||
self.pin_map = {}
|
||||
|
||||
def copy_layout_pin_shapes(self, text):
|
||||
"""
|
||||
Copy the shapes of the layout pins as objects.
|
||||
"""
|
||||
for s in self.pin_map[text]:
|
||||
self.add_rect(layer=s.layer,
|
||||
offset=s.ll(),
|
||||
width=s.width(),
|
||||
height=s.height())
|
||||
|
||||
def replace_layout_pin(self, text, pin):
|
||||
"""
|
||||
Remove the old pin and replace with a new one
|
||||
"""
|
||||
# Keep the shapes as they were used to connect to the router pins
|
||||
self.copy_layout_pin_shapes(text)
|
||||
# Remove the shapes as actual pins
|
||||
self.remove_layout_pin(text)
|
||||
# Add the new pin
|
||||
self.add_layout_pin(text=text,
|
||||
layer=pin.layer,
|
||||
offset=pin.ll(),
|
||||
|
|
|
|||
|
|
@ -108,7 +108,10 @@ class dff_buf(design.design):
|
|||
well_spacing = max(well_spacing, self.pwell_to_nwell)
|
||||
except AttributeError:
|
||||
pass
|
||||
self.inv1_inst.place(vector(self.dff_inst.rx() + well_spacing + self.well_extend_active, 0))
|
||||
|
||||
well_spacing += self.well_extend_active
|
||||
|
||||
self.inv1_inst.place(vector(self.dff_inst.rx() + well_spacing, 0))
|
||||
|
||||
# Add INV2 to the right
|
||||
self.inv2_inst.place(vector(self.inv1_inst.rx(), 0))
|
||||
|
|
|
|||
|
|
@ -78,81 +78,80 @@ class grid:
|
|||
for k in self.map:
|
||||
self.map[k].blocked=False
|
||||
|
||||
def set_source(self, n, value=True):
|
||||
def clear_source(self):
|
||||
for k in self.map:
|
||||
self.map[k].source=False
|
||||
self.source = set()
|
||||
|
||||
def set_source(self, n):
|
||||
if not isinstance(n, vector3d):
|
||||
for item in n:
|
||||
self.set_source(item, value)
|
||||
self.set_source(item)
|
||||
else:
|
||||
self.add_map(n)
|
||||
self.map[n].source=value
|
||||
self.map[n].source=True
|
||||
self.map[n].blocked=False
|
||||
self.source.add(n)
|
||||
|
||||
def set_target(self, n, value=True):
|
||||
def clear_target(self):
|
||||
for k in self.map:
|
||||
self.map[k].target=False
|
||||
self.target = set()
|
||||
|
||||
def set_target(self, n):
|
||||
if not isinstance(n, vector3d):
|
||||
for item in n:
|
||||
self.set_target(item, value)
|
||||
self.set_target(item)
|
||||
else:
|
||||
self.add_map(n)
|
||||
self.map[n].target=value
|
||||
self.map[n].target=True
|
||||
self.map[n].blocked=False
|
||||
self.target.add(n)
|
||||
|
||||
def add_source(self, track_list, value=True):
|
||||
|
||||
def add_source(self, track_list):
|
||||
debug.info(3, "Adding source list={0}".format(str(track_list)))
|
||||
for n in track_list:
|
||||
debug.info(4, "Adding source ={0}".format(str(n)))
|
||||
self.set_source(n, value)
|
||||
self.set_blocked(n, False)
|
||||
self.set_source(n)
|
||||
# self.set_blocked(n, False)
|
||||
|
||||
def add_target(self, track_list, value=True):
|
||||
def add_target(self, track_list):
|
||||
debug.info(3, "Adding target list={0}".format(str(track_list)))
|
||||
for n in track_list:
|
||||
debug.info(4, "Adding target ={0}".format(str(n)))
|
||||
self.set_target(n, value)
|
||||
self.set_blocked(n, False)
|
||||
self.set_target(n)
|
||||
# self.set_blocked(n, False)
|
||||
|
||||
def add_perimeter_target(self, side="all", value=True):
|
||||
def add_perimeter_target(self, side="all"):
|
||||
debug.info(3, "Adding perimeter target")
|
||||
|
||||
perimeter_list = []
|
||||
# Add the left/right columns
|
||||
if side=="all" or side=="left":
|
||||
x = self.ll.x
|
||||
for y in range(self.ll.y, self.ur.y, 1):
|
||||
n = vector3d(x, y, 0)
|
||||
self.set_target(n, value)
|
||||
self.set_blocked(n, False)
|
||||
n = vector3d(x, y, 1)
|
||||
self.set_target(n, value)
|
||||
self.set_blocked(n, False)
|
||||
perimeter_list.append(vector3d(x, y, 0))
|
||||
perimeter_list.append(vector3d(x, y, 1))
|
||||
|
||||
if side=="all" or side=="right":
|
||||
x = self.ur.x
|
||||
for y in range(self.ll.y, self.ur.y, 1):
|
||||
n = vector3d(x, y, 0)
|
||||
self.set_target(n, value)
|
||||
self.set_blocked(n, False)
|
||||
n = vector3d(x, y, 1)
|
||||
self.set_target(n, value)
|
||||
self.set_blocked(n, False)
|
||||
perimeter_list.append(vector3d(x, y, 0))
|
||||
perimeter_list.append(vector3d(x, y, 1))
|
||||
|
||||
if side=="all" or side=="bottom":
|
||||
y = self.ll.y
|
||||
for x in range(self.ll.x, self.ur.x, 1):
|
||||
n = vector3d(x, y, 0)
|
||||
self.set_target(n, value)
|
||||
self.set_blocked(n, False)
|
||||
n = vector3d(x, y, 1)
|
||||
self.set_target(n, value)
|
||||
self.set_blocked(n, False)
|
||||
perimeter_list.append(vector3d(x, y, 0))
|
||||
perimeter_list.append(vector3d(x, y, 1))
|
||||
|
||||
if side=="all" or side=="top":
|
||||
y = self.ur.y
|
||||
for x in range(self.ll.x, self.ur.x, 1):
|
||||
n = vector3d(x, y, 0)
|
||||
self.set_target(n, value)
|
||||
self.set_blocked(n, False)
|
||||
n = vector3d(x, y, 1)
|
||||
self.set_target(n, value)
|
||||
self.set_blocked(n, False)
|
||||
perimeter_list.append(vector3d(x, y, 0))
|
||||
perimeter_list.append(vector3d(x, y, 1))
|
||||
|
||||
self.set_target(perimeter_list)
|
||||
|
||||
def is_target(self, point):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ class grid_cell:
|
|||
if self.min_cost > 0:
|
||||
return self.min_cost
|
||||
|
||||
|
||||
def get_type(self):
|
||||
type_string = ""
|
||||
|
||||
|
|
@ -50,7 +49,5 @@ class grid_cell:
|
|||
if self.path:
|
||||
type_string += "P"
|
||||
|
||||
if type_string != "":
|
||||
return type_string
|
||||
return type_string
|
||||
|
||||
return None
|
||||
|
|
|
|||
|
|
@ -6,10 +6,11 @@
|
|||
# All rights reserved.
|
||||
#
|
||||
|
||||
import itertools
|
||||
import math
|
||||
import gdsMill
|
||||
from tech import drc, GDS
|
||||
from tech import layer as techlayer
|
||||
import math
|
||||
import debug
|
||||
from router_tech import router_tech
|
||||
from pin_layout import pin_layout
|
||||
|
|
@ -189,7 +190,6 @@ class router(router_tech):
|
|||
# self.combine_adjacent_pins(pin)
|
||||
# print_time("Combining adjacent pins",datetime.now(), start_time, 4)
|
||||
|
||||
|
||||
# Separate any adjacent grids of differing net names
|
||||
# that overlap
|
||||
# Must be done before enclosing pins
|
||||
|
|
@ -266,18 +266,10 @@ class router(router_tech):
|
|||
This will try to separate all grid pins by the supplied
|
||||
number of separation tracks (default is to prevent adjacency).
|
||||
"""
|
||||
# Commented out to debug with SCMOS
|
||||
# if separation==0:
|
||||
# return
|
||||
|
||||
pin_names = self.pin_groups.keys()
|
||||
for i, pin_name1 in enumerate(pin_names):
|
||||
for j, pin_name2 in enumerate(pin_names):
|
||||
if i == j:
|
||||
continue
|
||||
if i > j:
|
||||
return
|
||||
self.separate_adjacent_pin(pin_name1, pin_name2, separation)
|
||||
|
||||
for (pin_name1, pin_name2) in itertools.combinations(pin_names, 2):
|
||||
self.separate_adjacent_pin(pin_name1, pin_name2, separation)
|
||||
|
||||
def separate_adjacent_pin(self, pin_name1, pin_name2, separation):
|
||||
"""
|
||||
|
|
@ -290,6 +282,7 @@ class router(router_tech):
|
|||
"Comparing {0} and {1} adjacency".format(pin_name1,
|
||||
pin_name2))
|
||||
removed_grids = 0
|
||||
|
||||
for index1, pg1 in enumerate(self.pin_groups[pin_name1]):
|
||||
for index2, pg2 in enumerate(self.pin_groups[pin_name2]):
|
||||
adj_grids = pg1.adjacent_grids(pg2, separation)
|
||||
|
|
@ -362,7 +355,7 @@ class router(router_tech):
|
|||
# Start fresh. Not the best for run-time, but simpler.
|
||||
self.clear_blockages()
|
||||
# This adds the initial blockges of the design
|
||||
#print("BLOCKING:", self.blocked_grids)
|
||||
# print("BLOCKING:", self.blocked_grids)
|
||||
self.set_blockages(self.blocked_grids, True)
|
||||
|
||||
# Block all of the supply rails
|
||||
|
|
@ -389,8 +382,9 @@ class router(router_tech):
|
|||
# Don't mark the other components as targets since we want to route
|
||||
# directly to a rail, but unblock all the source components so we can
|
||||
# route over them
|
||||
blockage_grids = {y for x in self.pin_groups[pin_name] for y in x.grids}
|
||||
self.set_blockages(blockage_grids, False)
|
||||
# 1/6/21: This would cause things that looked like loops in the supply tree router
|
||||
# blockage_grids = {y for x in self.pin_groups[pin_name] for y in x.grids}
|
||||
# self.set_blockages(blockage_grids, False)
|
||||
|
||||
def convert_shape_to_units(self, shape):
|
||||
"""
|
||||
|
|
@ -1039,18 +1033,18 @@ class router(router_tech):
|
|||
(ll, ur) = self.convert_track_to_shape(coord)
|
||||
self.cell.add_rect(layer="text",
|
||||
offset=ll,
|
||||
width=ur[0]-ll[0],
|
||||
height=ur[1]-ll[1])
|
||||
(ll, ur) = self.convert_track_to_pin(coord).rect
|
||||
self.cell.add_rect(layer="boundary",
|
||||
offset=ll,
|
||||
width=ur[0]-ll[0],
|
||||
height=ur[1]-ll[1])
|
||||
width=ur[0] - ll[0],
|
||||
height=ur[1] - ll[1])
|
||||
# (ll, ur) = self.convert_track_to_pin(coord).rect
|
||||
# self.cell.add_rect(layer="boundary",
|
||||
# offset=ll,
|
||||
# width=ur[0] - ll[0],
|
||||
# height=ur[1] - ll[1])
|
||||
(ll, ur) = pin.rect
|
||||
self.cell.add_rect(layer="text",
|
||||
offset=ll,
|
||||
width=ur[0]-ll[0],
|
||||
height=ur[1]-ll[1])
|
||||
width=ur[0] - ll[0],
|
||||
height=ur[1] - ll[1])
|
||||
|
||||
def write_debug_gds(self, gds_name="debug_route.gds", stop_program=True):
|
||||
"""
|
||||
|
|
@ -1058,9 +1052,9 @@ class router(router_tech):
|
|||
search information annotated on it.
|
||||
"""
|
||||
debug.info(0, "Writing annotated router gds file to {}".format(gds_name))
|
||||
self.del_router_info()
|
||||
self.add_router_info()
|
||||
self.cell.gds_write(gds_name)
|
||||
self.del_router_info()
|
||||
|
||||
if stop_program:
|
||||
import sys
|
||||
|
|
@ -1071,17 +1065,17 @@ class router(router_tech):
|
|||
Display grid information in the GDS file for a single grid cell.
|
||||
"""
|
||||
shape = self.convert_track_to_shape(g)
|
||||
partial_track = vector(0,self.track_width/6.0)
|
||||
partial_track = vector(0, self.track_width / 6.0)
|
||||
self.cell.add_rect(layer="text",
|
||||
offset=shape[0],
|
||||
width=shape[1].x-shape[0].x,
|
||||
height=shape[1].y-shape[0].y)
|
||||
width=shape[1].x - shape[0].x,
|
||||
height=shape[1].y - shape[0].y)
|
||||
t = self.rg.map[g].get_type()
|
||||
|
||||
# midpoint offset
|
||||
off = vector((shape[1].x+shape[0].x)/2,
|
||||
(shape[1].y+shape[0].y)/2)
|
||||
if t != None:
|
||||
off = vector((shape[1].x + shape[0].x) / 2,
|
||||
(shape[1].y + shape[0].y) / 2)
|
||||
if t:
|
||||
if g[2] == 1:
|
||||
# Upper layer is upper right label
|
||||
type_off = off + partial_track
|
||||
|
|
@ -1107,16 +1101,15 @@ class router(router_tech):
|
|||
|
||||
self.cell.add_label(text="{0},{1}".format(g[0], g[1]),
|
||||
layer="text",
|
||||
offset=shape[0],
|
||||
zoom=0.05)
|
||||
|
||||
offset=shape[0])
|
||||
|
||||
def del_router_info(self):
|
||||
"""
|
||||
Erase all of the comments on the current level.
|
||||
"""
|
||||
debug.info(0, "Erasing router info")
|
||||
layer_num = techlayer["text"]
|
||||
self.cell.objs = [x for x in self.cell.objs if x.layerNumber != layer_num]
|
||||
lpp = techlayer["text"]
|
||||
self.cell.objs = [x for x in self.cell.objs if x.lpp != lpp]
|
||||
|
||||
def add_router_info(self):
|
||||
"""
|
||||
|
|
@ -1132,7 +1125,6 @@ class router(router_tech):
|
|||
show_all_grids = True
|
||||
|
||||
if show_all_grids:
|
||||
# self.rg.add_all_grids()
|
||||
for g in self.rg.map:
|
||||
self.annotate_grid(g)
|
||||
|
||||
|
|
@ -1143,8 +1135,8 @@ class router(router_tech):
|
|||
(ll, ur) = blockage.inflate()
|
||||
self.cell.add_rect(layer="text",
|
||||
offset=ll,
|
||||
width=ur.x-ll.x,
|
||||
height=ur.y-ll.y)
|
||||
width=ur.x - ll.x,
|
||||
height=ur.y - ll.y)
|
||||
if show_blockage_grids:
|
||||
self.set_blockages(self.blocked_grids, True)
|
||||
for g in self.rg.map:
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import debug
|
|||
from globals import print_time
|
||||
from router import router
|
||||
from datetime import datetime
|
||||
from supply_grid import supply_grid
|
||||
from signal_grid import signal_grid
|
||||
|
||||
|
||||
class signal_escape_router(router):
|
||||
|
|
@ -30,31 +30,38 @@ class signal_escape_router(router):
|
|||
"""
|
||||
size = self.ur - self.ll
|
||||
debug.info(1,"Size: {0} x {1}".format(size.x, size.y))
|
||||
self.rg = supply_grid(self.ll, self.ur, self.track_width)
|
||||
self.rg = signal_grid(self.ll, self.ur, self.track_width)
|
||||
|
||||
def escape_route(self, pin_list):
|
||||
def perimeter_dist(self, pin_name):
|
||||
"""
|
||||
Return the shortest Manhattan distance to the bounding box perimeter.
|
||||
"""
|
||||
loc = self.cell.get_pin(pin_name).center()
|
||||
x_dist = min(loc.x - self.ll.x, self.ur.x - loc.x)
|
||||
y_dist = min(loc.y - self.ll.y, self.ur.y - loc.y)
|
||||
|
||||
return min(x_dist, y_dist)
|
||||
|
||||
def escape_route(self, pin_names):
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
pin_names = [x[0] for x in pin_list]
|
||||
|
||||
# Clear the pins if we have previously routed
|
||||
if (hasattr(self,'rg')):
|
||||
self.clear_pins()
|
||||
else:
|
||||
self.create_routing_grid()
|
||||
self.create_routing_grid()
|
||||
|
||||
# Get the pin shapes
|
||||
start_time = datetime.now()
|
||||
self.find_pins_and_blockages(pin_names)
|
||||
print_time("Finding pins and blockages",datetime.now(), start_time, 3)
|
||||
|
||||
# Order the routes by closest to the perimeter first
|
||||
# This prevents some pins near the perimeter from being blocked by other pins
|
||||
ordered_pin_names = sorted(pin_names, key=lambda x: self.perimeter_dist(x))
|
||||
|
||||
# Route the supply pins to the supply rails
|
||||
# Route vdd first since we want it to be shorter
|
||||
start_time = datetime.now()
|
||||
for pin_name, side in pin_list:
|
||||
self.route_signal(pin_name, side)
|
||||
for pin_name in ordered_pin_names:
|
||||
self.route_signal(pin_name)
|
||||
|
||||
print_time("Maze routing pins",datetime.now(), start_time, 3)
|
||||
|
||||
|
|
@ -62,10 +69,10 @@ class signal_escape_router(router):
|
|||
|
||||
return True
|
||||
|
||||
def route_signal(self, pin_name, side):
|
||||
def route_signal(self, pin_name, side="all"):
|
||||
|
||||
for detour_scale in [5 * pow(2, x) for x in range(5)]:
|
||||
debug.info(1, "Exit routing {0} with scale {1}".format(pin_name, detour_scale))
|
||||
debug.info(1, "Escape routing {0} with scale {1}".format(pin_name, detour_scale))
|
||||
|
||||
# Clear everything in the routing grid.
|
||||
self.rg.reinit()
|
||||
|
|
|
|||
|
|
@ -23,9 +23,6 @@ class signal_grid(grid):
|
|||
""" Create a routing map of width x height cells and 2 in the z-axis. """
|
||||
grid.__init__(self, ll, ur, track_factor)
|
||||
|
||||
# priority queue for the maze routing
|
||||
self.q = []
|
||||
|
||||
def reinit(self):
|
||||
""" Reinitialize everything for a new route. """
|
||||
|
||||
|
|
@ -33,14 +30,8 @@ class signal_grid(grid):
|
|||
for p in self.map.values():
|
||||
p.reset()
|
||||
|
||||
# clear source and target pins
|
||||
self.source = set()
|
||||
self.target = set()
|
||||
|
||||
# Clear the queue
|
||||
while len(self.q) > 0:
|
||||
heappop(self.q)
|
||||
self.counter = 0
|
||||
self.clear_source()
|
||||
self.clear_target()
|
||||
|
||||
def init_queue(self):
|
||||
"""
|
||||
|
|
@ -51,12 +42,13 @@ class signal_grid(grid):
|
|||
"""
|
||||
# Counter is used to not require data comparison in Python 3.x
|
||||
# Items will be returned in order they are added during cost ties
|
||||
self.q = []
|
||||
self.counter = 0
|
||||
for s in self.source:
|
||||
cost = self.cost_to_target(s)
|
||||
debug.info(3, "Init: cost=" + str(cost) + " " + str([s]))
|
||||
heappush(self.q, (cost, self.counter, grid_path([vector3d(s)])))
|
||||
self.counter+=1
|
||||
self.counter += 1
|
||||
|
||||
def route(self, detour_scale):
|
||||
"""
|
||||
|
|
@ -72,11 +64,7 @@ class signal_grid(grid):
|
|||
# Check if something in the queue is already a source and a target!
|
||||
for s in self.source:
|
||||
if self.is_target(s):
|
||||
return((grid_path([vector3d(s)]),0))
|
||||
|
||||
# Make sure the queue is empty if we run another route
|
||||
while len(self.q)>0:
|
||||
heappop(self.q)
|
||||
return((grid_path([vector3d(s)]), 0))
|
||||
|
||||
# Put the source items into the queue
|
||||
self.init_queue()
|
||||
|
|
|
|||
|
|
@ -144,15 +144,13 @@ class supply_tree_router(router):
|
|||
|
||||
# Marks all pin components except index as target
|
||||
self.add_pin_component_target(pin_name, dest_idx)
|
||||
|
||||
|
||||
# Actually run the A* router
|
||||
if self.run_router(detour_scale=detour_scale):
|
||||
return
|
||||
|
||||
self.write_debug_gds("debug_route.gds", True)
|
||||
|
||||
|
||||
|
||||
def add_io_pin(self, instance, pin_name, new_name=""):
|
||||
"""
|
||||
Add a signle input or output pin up to metal 3.
|
||||
|
|
|
|||
|
|
@ -254,43 +254,37 @@ class sram_1bank(sram_base):
|
|||
# List of pin to new pin name
|
||||
pins_to_route = []
|
||||
for port in self.all_ports:
|
||||
# Depending on the port, use the bottom/top or left/right sides
|
||||
# Port 0 is left/bottom
|
||||
# Port 1 is right/top
|
||||
bottom_or_top = "bottom" if port==0 else "top"
|
||||
left_or_right = "left" if port==0 else "right"
|
||||
|
||||
# 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), bottom_or_top))
|
||||
pins_to_route.append("{0}{1}".format(signal, port))
|
||||
else:
|
||||
pins_to_route.append(("{0}{1}".format(signal, port), left_or_right))
|
||||
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), bottom_or_top))
|
||||
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), bottom_or_top))
|
||||
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), bottom_or_top))
|
||||
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), left_or_right))
|
||||
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), bottom_or_top))
|
||||
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), bottom_or_top))
|
||||
pins_to_route.append("spare_wen{0}[{1}]".format(port, bit))
|
||||
|
||||
rtr=router(self.m3_stack, self)
|
||||
rtr.escape_route(pins_to_route)
|
||||
|
|
|
|||
|
|
@ -88,9 +88,12 @@ def write_drc_script(cell_name, gds_name, extract, final_verification, output_pa
|
|||
f.write("drc off\n")
|
||||
f.write("gds polygon subcell true\n")
|
||||
f.write("gds warning default\n")
|
||||
f.write("gds flatten true\n")
|
||||
f.write("gds readonly true\n")
|
||||
# These two options are temporarily disabled until Tim fixes a bug in magic related
|
||||
# to flattening channel routes and vias (hierarchy with no devices in it). Otherwise,
|
||||
# they appear to be disconnected.
|
||||
f.write("#gds flatten true\n")
|
||||
f.write("#gds ordering true\n")
|
||||
f.write("gds readonly true\n")
|
||||
f.write("gds read {}\n".format(gds_name))
|
||||
f.write('puts "Finished reading gds {}"\n'.format(gds_name))
|
||||
f.write("load {}\n".format(cell_name))
|
||||
|
|
|
|||
Loading…
Reference in New Issue