Merge remote-tracking branch 'private/dev'

This commit is contained in:
mrg 2021-01-07 10:20:17 -08:00
commit c0df3ff1da
11 changed files with 137 additions and 144 deletions

View File

@ -23,10 +23,14 @@ class geometry:
A specific path, shape, or text geometry. Base class for shared A specific path, shape, or text geometry. Base class for shared
items. items.
""" """
def __init__(self): def __init__(self, lpp=None):
""" By default, everything has no size. """ """ By default, everything has no size. """
self.width = 0 self.width = 0
self.height = 0 self.height = 0
if lpp:
self.lpp = lpp
self.layerNumber = lpp[0]
self.layerPurpose = lpp[1]
def __str__(self): def __str__(self):
""" override print function output """ """ override print function output """
@ -410,10 +414,8 @@ class path(geometry):
def __init__(self, lpp, coordinates, path_width): def __init__(self, lpp, coordinates, path_width):
"""Initializes a path for the specified layer""" """Initializes a path for the specified layer"""
super().__init__() super().__init__(lpp)
self.name = "path" self.name = "path"
self.layerNumber = lpp[0]
self.layerPurpose = lpp[1]
self.coordinates = map(lambda x: [x[0], x[1]], coordinates) self.coordinates = map(lambda x: [x[0], x[1]], coordinates)
self.coordinates = vector(self.coordinates).snap_to_grid() self.coordinates = vector(self.coordinates).snap_to_grid()
self.path_width = path_width self.path_width = path_width
@ -448,11 +450,9 @@ class label(geometry):
def __init__(self, text, lpp, offset, zoom=None): def __init__(self, text, lpp, offset, zoom=None):
"""Initializes a text label for specified layer""" """Initializes a text label for specified layer"""
super().__init__() super().__init__(lpp)
self.name = "label" self.name = "label"
self.text = text self.text = text
self.layerNumber = lpp[0]
self.layerPurpose = lpp[1]
self.offset = vector(offset).snap_to_grid() self.offset = vector(offset).snap_to_grid()
if not zoom: if not zoom:
@ -495,10 +495,8 @@ class rectangle(geometry):
def __init__(self, lpp, offset, width, height): def __init__(self, lpp, offset, width, height):
"""Initializes a rectangular shape for specified layer""" """Initializes a rectangular shape for specified layer"""
super().__init__() super().__init__(lpp)
self.name = "rect" self.name = "rect"
self.layerNumber = lpp[0]
self.layerPurpose = lpp[1]
self.offset = vector(offset).snap_to_grid() self.offset = vector(offset).snap_to_grid()
self.size = vector(width, height).snap_to_grid() self.size = vector(width, height).snap_to_grid()
self.width = round_to_grid(self.size.x) self.width = round_to_grid(self.size.x)

View File

@ -473,11 +473,25 @@ class layout():
""" """
self.pin_map = {} 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): def replace_layout_pin(self, text, pin):
""" """
Remove the old pin and replace with a new one 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) self.remove_layout_pin(text)
# Add the new pin
self.add_layout_pin(text=text, self.add_layout_pin(text=text,
layer=pin.layer, layer=pin.layer,
offset=pin.ll(), offset=pin.ll(),

View File

@ -108,7 +108,10 @@ class dff_buf(design.design):
well_spacing = max(well_spacing, self.pwell_to_nwell) well_spacing = max(well_spacing, self.pwell_to_nwell)
except AttributeError: except AttributeError:
pass 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 # Add INV2 to the right
self.inv2_inst.place(vector(self.inv1_inst.rx(), 0)) self.inv2_inst.place(vector(self.inv1_inst.rx(), 0))

View File

@ -78,81 +78,80 @@ class grid:
for k in self.map: for k in self.map:
self.map[k].blocked=False 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): if not isinstance(n, vector3d):
for item in n: for item in n:
self.set_source(item, value) self.set_source(item)
else: else:
self.add_map(n) self.add_map(n)
self.map[n].source=value self.map[n].source=True
self.map[n].blocked=False
self.source.add(n) 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): if not isinstance(n, vector3d):
for item in n: for item in n:
self.set_target(item, value) self.set_target(item)
else: else:
self.add_map(n) self.add_map(n)
self.map[n].target=value self.map[n].target=True
self.map[n].blocked=False
self.target.add(n) 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))) debug.info(3, "Adding source list={0}".format(str(track_list)))
for n in track_list: for n in track_list:
debug.info(4, "Adding source ={0}".format(str(n))) debug.info(4, "Adding source ={0}".format(str(n)))
self.set_source(n, value) self.set_source(n)
self.set_blocked(n, False) # 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))) debug.info(3, "Adding target list={0}".format(str(track_list)))
for n in track_list: for n in track_list:
debug.info(4, "Adding target ={0}".format(str(n))) debug.info(4, "Adding target ={0}".format(str(n)))
self.set_target(n, value) self.set_target(n)
self.set_blocked(n, False) # 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") debug.info(3, "Adding perimeter target")
perimeter_list = []
# Add the left/right columns # Add the left/right columns
if side=="all" or side=="left": if side=="all" or side=="left":
x = self.ll.x x = self.ll.x
for y in range(self.ll.y, self.ur.y, 1): for y in range(self.ll.y, self.ur.y, 1):
n = vector3d(x, y, 0) perimeter_list.append(vector3d(x, y, 0))
self.set_target(n, value) perimeter_list.append(vector3d(x, y, 1))
self.set_blocked(n, False)
n = vector3d(x, y, 1)
self.set_target(n, value)
self.set_blocked(n, False)
if side=="all" or side=="right": if side=="all" or side=="right":
x = self.ur.x x = self.ur.x
for y in range(self.ll.y, self.ur.y, 1): for y in range(self.ll.y, self.ur.y, 1):
n = vector3d(x, y, 0) perimeter_list.append(vector3d(x, y, 0))
self.set_target(n, value) perimeter_list.append(vector3d(x, y, 1))
self.set_blocked(n, False)
n = vector3d(x, y, 1)
self.set_target(n, value)
self.set_blocked(n, False)
if side=="all" or side=="bottom": if side=="all" or side=="bottom":
y = self.ll.y y = self.ll.y
for x in range(self.ll.x, self.ur.x, 1): for x in range(self.ll.x, self.ur.x, 1):
n = vector3d(x, y, 0) perimeter_list.append(vector3d(x, y, 0))
self.set_target(n, value) perimeter_list.append(vector3d(x, y, 1))
self.set_blocked(n, False)
n = vector3d(x, y, 1)
self.set_target(n, value)
self.set_blocked(n, False)
if side=="all" or side=="top": if side=="all" or side=="top":
y = self.ur.y y = self.ur.y
for x in range(self.ll.x, self.ur.x, 1): for x in range(self.ll.x, self.ur.x, 1):
n = vector3d(x, y, 0) perimeter_list.append(vector3d(x, y, 0))
self.set_target(n, value) perimeter_list.append(vector3d(x, y, 1))
self.set_blocked(n, False)
n = vector3d(x, y, 1) self.set_target(perimeter_list)
self.set_target(n, value)
self.set_blocked(n, False)
def is_target(self, point): def is_target(self, point):
""" """

View File

@ -34,7 +34,6 @@ class grid_cell:
if self.min_cost > 0: if self.min_cost > 0:
return self.min_cost return self.min_cost
def get_type(self): def get_type(self):
type_string = "" type_string = ""
@ -50,7 +49,5 @@ class grid_cell:
if self.path: if self.path:
type_string += "P" type_string += "P"
if type_string != "": return type_string
return type_string
return None

View File

@ -6,10 +6,11 @@
# All rights reserved. # All rights reserved.
# #
import itertools
import math
import gdsMill import gdsMill
from tech import drc, GDS from tech import drc, GDS
from tech import layer as techlayer from tech import layer as techlayer
import math
import debug import debug
from router_tech import router_tech from router_tech import router_tech
from pin_layout import pin_layout from pin_layout import pin_layout
@ -189,7 +190,6 @@ class router(router_tech):
# self.combine_adjacent_pins(pin) # self.combine_adjacent_pins(pin)
# print_time("Combining adjacent pins",datetime.now(), start_time, 4) # print_time("Combining adjacent pins",datetime.now(), start_time, 4)
# Separate any adjacent grids of differing net names # Separate any adjacent grids of differing net names
# that overlap # that overlap
# Must be done before enclosing pins # 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 This will try to separate all grid pins by the supplied
number of separation tracks (default is to prevent adjacency). 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() pin_names = self.pin_groups.keys()
for i, pin_name1 in enumerate(pin_names):
for j, pin_name2 in enumerate(pin_names): for (pin_name1, pin_name2) in itertools.combinations(pin_names, 2):
if i == j: self.separate_adjacent_pin(pin_name1, pin_name2, separation)
continue
if i > j:
return
self.separate_adjacent_pin(pin_name1, pin_name2, separation)
def separate_adjacent_pin(self, 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, "Comparing {0} and {1} adjacency".format(pin_name1,
pin_name2)) pin_name2))
removed_grids = 0 removed_grids = 0
for index1, pg1 in enumerate(self.pin_groups[pin_name1]): for index1, pg1 in enumerate(self.pin_groups[pin_name1]):
for index2, pg2 in enumerate(self.pin_groups[pin_name2]): for index2, pg2 in enumerate(self.pin_groups[pin_name2]):
adj_grids = pg1.adjacent_grids(pg2, separation) 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. # Start fresh. Not the best for run-time, but simpler.
self.clear_blockages() self.clear_blockages()
# This adds the initial blockges of the design # 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) self.set_blockages(self.blocked_grids, True)
# Block all of the supply rails # 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 # 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 # directly to a rail, but unblock all the source components so we can
# route over them # route over them
blockage_grids = {y for x in self.pin_groups[pin_name] for y in x.grids} # 1/6/21: This would cause things that looked like loops in the supply tree router
self.set_blockages(blockage_grids, False) # 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): def convert_shape_to_units(self, shape):
""" """
@ -1039,18 +1033,18 @@ class router(router_tech):
(ll, ur) = self.convert_track_to_shape(coord) (ll, ur) = self.convert_track_to_shape(coord)
self.cell.add_rect(layer="text", self.cell.add_rect(layer="text",
offset=ll, offset=ll,
width=ur[0]-ll[0], width=ur[0] - ll[0],
height=ur[1]-ll[1]) height=ur[1] - ll[1])
(ll, ur) = self.convert_track_to_pin(coord).rect # (ll, ur) = self.convert_track_to_pin(coord).rect
self.cell.add_rect(layer="boundary", # self.cell.add_rect(layer="boundary",
offset=ll, # offset=ll,
width=ur[0]-ll[0], # width=ur[0] - ll[0],
height=ur[1]-ll[1]) # height=ur[1] - ll[1])
(ll, ur) = pin.rect (ll, ur) = pin.rect
self.cell.add_rect(layer="text", self.cell.add_rect(layer="text",
offset=ll, offset=ll,
width=ur[0]-ll[0], width=ur[0] - ll[0],
height=ur[1]-ll[1]) height=ur[1] - ll[1])
def write_debug_gds(self, gds_name="debug_route.gds", stop_program=True): 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. search information annotated on it.
""" """
debug.info(0, "Writing annotated router gds file to {}".format(gds_name)) debug.info(0, "Writing annotated router gds file to {}".format(gds_name))
self.del_router_info()
self.add_router_info() self.add_router_info()
self.cell.gds_write(gds_name) self.cell.gds_write(gds_name)
self.del_router_info()
if stop_program: if stop_program:
import sys import sys
@ -1071,17 +1065,17 @@ class router(router_tech):
Display grid information in the GDS file for a single grid cell. Display grid information in the GDS file for a single grid cell.
""" """
shape = self.convert_track_to_shape(g) 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", self.cell.add_rect(layer="text",
offset=shape[0], offset=shape[0],
width=shape[1].x-shape[0].x, width=shape[1].x - shape[0].x,
height=shape[1].y-shape[0].y) height=shape[1].y - shape[0].y)
t = self.rg.map[g].get_type() t = self.rg.map[g].get_type()
# midpoint offset # midpoint offset
off = vector((shape[1].x+shape[0].x)/2, off = vector((shape[1].x + shape[0].x) / 2,
(shape[1].y+shape[0].y)/2) (shape[1].y + shape[0].y) / 2)
if t != None: if t:
if g[2] == 1: if g[2] == 1:
# Upper layer is upper right label # Upper layer is upper right label
type_off = off + partial_track 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]), self.cell.add_label(text="{0},{1}".format(g[0], g[1]),
layer="text", layer="text",
offset=shape[0], offset=shape[0])
zoom=0.05)
def del_router_info(self): def del_router_info(self):
""" """
Erase all of the comments on the current level. Erase all of the comments on the current level.
""" """
debug.info(0, "Erasing router info") debug.info(0, "Erasing router info")
layer_num = techlayer["text"] lpp = techlayer["text"]
self.cell.objs = [x for x in self.cell.objs if x.layerNumber != layer_num] self.cell.objs = [x for x in self.cell.objs if x.lpp != lpp]
def add_router_info(self): def add_router_info(self):
""" """
@ -1132,7 +1125,6 @@ class router(router_tech):
show_all_grids = True show_all_grids = True
if show_all_grids: if show_all_grids:
# self.rg.add_all_grids()
for g in self.rg.map: for g in self.rg.map:
self.annotate_grid(g) self.annotate_grid(g)
@ -1143,8 +1135,8 @@ class router(router_tech):
(ll, ur) = blockage.inflate() (ll, ur) = blockage.inflate()
self.cell.add_rect(layer="text", self.cell.add_rect(layer="text",
offset=ll, offset=ll,
width=ur.x-ll.x, width=ur.x - ll.x,
height=ur.y-ll.y) height=ur.y - ll.y)
if show_blockage_grids: if show_blockage_grids:
self.set_blockages(self.blocked_grids, True) self.set_blockages(self.blocked_grids, True)
for g in self.rg.map: for g in self.rg.map:

View File

@ -9,7 +9,7 @@ import debug
from globals import print_time from globals import print_time
from router import router from router import router
from datetime import datetime from datetime import datetime
from supply_grid import supply_grid from signal_grid import signal_grid
class signal_escape_router(router): class signal_escape_router(router):
@ -30,31 +30,38 @@ class signal_escape_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))
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, 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.
""" """
pin_names = [x[0] for x in pin_list] self.create_routing_grid()
# Clear the pins if we have previously routed
if (hasattr(self,'rg')):
self.clear_pins()
else:
self.create_routing_grid()
# Get the pin shapes
start_time = datetime.now() start_time = datetime.now()
self.find_pins_and_blockages(pin_names) self.find_pins_and_blockages(pin_names)
print_time("Finding pins and blockages",datetime.now(), start_time, 3) 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 the supply pins to the supply rails
# Route vdd first since we want it to be shorter # Route vdd first since we want it to be shorter
start_time = datetime.now() start_time = datetime.now()
for pin_name, side in pin_list: for pin_name in ordered_pin_names:
self.route_signal(pin_name, side) self.route_signal(pin_name)
print_time("Maze routing pins",datetime.now(), start_time, 3) print_time("Maze routing pins",datetime.now(), start_time, 3)
@ -62,10 +69,10 @@ class signal_escape_router(router):
return True 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)]: 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. # Clear everything in the routing grid.
self.rg.reinit() self.rg.reinit()

View File

@ -23,9 +23,6 @@ class signal_grid(grid):
""" Create a routing map of width x height cells and 2 in the z-axis. """ """ Create a routing map of width x height cells and 2 in the z-axis. """
grid.__init__(self, ll, ur, track_factor) grid.__init__(self, ll, ur, track_factor)
# priority queue for the maze routing
self.q = []
def reinit(self): def reinit(self):
""" Reinitialize everything for a new route. """ """ Reinitialize everything for a new route. """
@ -33,14 +30,8 @@ class signal_grid(grid):
for p in self.map.values(): for p in self.map.values():
p.reset() p.reset()
# clear source and target pins self.clear_source()
self.source = set() self.clear_target()
self.target = set()
# Clear the queue
while len(self.q) > 0:
heappop(self.q)
self.counter = 0
def init_queue(self): def init_queue(self):
""" """
@ -51,12 +42,13 @@ class signal_grid(grid):
""" """
# Counter is used to not require data comparison in Python 3.x # Counter is used to not require data comparison in Python 3.x
# Items will be returned in order they are added during cost ties # Items will be returned in order they are added during cost ties
self.q = []
self.counter = 0 self.counter = 0
for s in self.source: for s in self.source:
cost = self.cost_to_target(s) cost = self.cost_to_target(s)
debug.info(3, "Init: cost=" + str(cost) + " " + str([s])) debug.info(3, "Init: cost=" + str(cost) + " " + str([s]))
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):
""" """
@ -72,11 +64,7 @@ class signal_grid(grid):
# Check if something in the queue is already a source and a target! # Check if something in the queue is already a source and a target!
for s in self.source: for s in self.source:
if self.is_target(s): if self.is_target(s):
return((grid_path([vector3d(s)]),0)) 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)
# Put the source items into the queue # Put the source items into the queue
self.init_queue() self.init_queue()

View File

@ -151,8 +151,6 @@ class supply_tree_router(router):
self.write_debug_gds("debug_route.gds", True) self.write_debug_gds("debug_route.gds", True)
def add_io_pin(self, instance, pin_name, new_name=""): def add_io_pin(self, instance, pin_name, new_name=""):
""" """
Add a signle input or output pin up to metal 3. Add a signle input or output pin up to metal 3.

View File

@ -254,43 +254,37 @@ class sram_1bank(sram_base):
# List of pin to new pin name # List of pin to new pin name
pins_to_route = [] pins_to_route = []
for port in self.all_ports: 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 # Connect the control pins as inputs
for signal in self.control_logic_inputs[port]: for signal in self.control_logic_inputs[port]:
if signal.startswith("rbl"): if signal.startswith("rbl"):
continue continue
if signal=="clk": 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: 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: if port in self.write_ports:
for bit in range(self.word_size + self.num_spare_cols): 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: if port in self.readwrite_ports or 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):
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): 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): 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 port in self.write_ports:
if self.write_size: if self.write_size:
for bit in range(self.num_wmasks): 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: if port in self.write_ports:
for bit in range(self.num_spare_cols): 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=router(self.m3_stack, self)
rtr.escape_route(pins_to_route) rtr.escape_route(pins_to_route)

View File

@ -88,9 +88,12 @@ def write_drc_script(cell_name, gds_name, extract, final_verification, output_pa
f.write("drc off\n") f.write("drc off\n")
f.write("gds polygon subcell true\n") f.write("gds polygon subcell true\n")
f.write("gds warning default\n") f.write("gds warning default\n")
f.write("gds flatten true\n") # These two options are temporarily disabled until Tim fixes a bug in magic related
f.write("gds readonly true\n") # 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 ordering true\n")
f.write("gds readonly true\n")
f.write("gds read {}\n".format(gds_name)) f.write("gds read {}\n".format(gds_name))
f.write('puts "Finished reading gds {}"\n'.format(gds_name)) f.write('puts "Finished reading gds {}"\n'.format(gds_name))
f.write("load {}\n".format(cell_name)) f.write("load {}\n".format(cell_name))