Cleanup of router.

Made offsets in geometry snap to grid.
Changed gds_write to use list for visited flag.
Rewrite self.gds each call in case of any changes.
This commit is contained in:
Matt Guthaus 2018-10-04 14:04:29 -07:00
parent 7432192e5e
commit 985d04d4b5
17 changed files with 201 additions and 196 deletions

View File

@ -53,3 +53,14 @@ class design(hierarchy_design):
for inst in self.insts:
total_module_power += inst.mod.analytical_power(proc, vdd, temp, load)
return total_module_power
def __str__(self):
""" override print function output """
pins = ",".join(self.pins)
insts = [" {}".format(x) for x in self.insts]
objs = [" {}".format(x) for x in self.objs]
s = "********** design {0} **********\n".format(self.name)
s += "\n pins ({0})={1}\n".format(len(self.pins), pins)
s += "\n objs ({0})=\n{1}".format(len(self.objs), "\n".join(objs))
s += "\n insts ({0})=\n{1}\n".format(len(self.insts), "\n".join(insts))
return s

View File

@ -6,6 +6,7 @@ from vector import vector
import tech
import math
from globals import OPTS
from utils import round_to_grid
class geometry:
"""
@ -46,8 +47,8 @@ class geometry:
def normalize(self):
""" Re-find the LL and UR points after a transform """
(first,second)=self.boundary
ll = vector(min(first[0],second[0]),min(first[1],second[1]))
ur = vector(max(first[0],second[0]),max(first[1],second[1]))
ll = vector(min(first[0],second[0]),min(first[1],second[1])).snap_to_grid()
ur = vector(max(first[0],second[0]),max(first[1],second[1])).snap_to_grid()
self.boundary=[ll,ur]
def update_boundary(self):
@ -142,8 +143,8 @@ class instance(geometry):
self.rotate = rotate
self.offset = vector(offset).snap_to_grid()
self.mirror = mirror
self.width = mod.width
self.height = mod.height
self.width = round_to_grid(mod.width)
self.height = round_to_grid(mod.height)
self.compute_boundary(offset,mirror,rotate)
debug.info(4, "creating instance: " + self.name)
@ -191,15 +192,15 @@ class instance(geometry):
self.mod.gds_write_file(self.gds)
# now write an instance of my module/structure
new_layout.addInstance(self.gds,
offsetInMicrons=self.offset,
mirror=self.mirror,
rotate=self.rotate)
offsetInMicrons=self.offset,
mirror=self.mirror,
rotate=self.rotate)
def place(self, offset, mirror="R0", rotate=0):
""" This updates the placement of an instance. """
debug.info(3, "placing instance {}".format(self.name))
# Update the placement of an already added instance
self.offset = vector(offset)
self.offset = vector(offset).snap_to_grid()
self.mirror = mirror
self.rotate = rotate
self.update_boundary()
@ -238,7 +239,7 @@ class instance(geometry):
def __str__(self):
""" override print function output """
return "inst: " + self.name + " mod=" + self.mod.name
return "( inst: " + self.name + " @" + str(self.offset) + " mod=" + self.mod.name + " " + self.mirror + " R=" + str(self.rotate) + ")"
def __repr__(self):
""" override print function output """
@ -260,13 +261,13 @@ class path(geometry):
# supported right now. It might not work in gdsMill.
assert(0)
def gds_write_file(self, newLayout):
def gds_write_file(self, new_layout):
"""Writes the path to GDS"""
debug.info(4, "writing path (" + str(self.layerNumber) + "): " + self.coordinates)
newLayout.addPath(layerNumber=self.layerNumber,
purposeNumber=0,
coordinates=self.coordinates,
width=self.path_width)
new_layout.addPath(layerNumber=self.layerNumber,
purposeNumber=0,
coordinates=self.coordinates,
width=self.path_width)
def get_blockages(self, layer):
""" Fail since we don't support paths yet. """
@ -301,15 +302,15 @@ class label(geometry):
debug.info(4,"creating label " + self.text + " " + str(self.layerNumber) + " " + str(self.offset))
def gds_write_file(self, newLayout):
def gds_write_file(self, new_layout):
"""Writes the text label to GDS"""
debug.info(4, "writing label (" + str(self.layerNumber) + "): " + self.text)
newLayout.addText(text=self.text,
layerNumber=self.layerNumber,
purposeNumber=0,
offsetInMicrons=self.offset,
magnification=self.zoom,
rotate=None)
new_layout.addText(text=self.text,
layerNumber=self.layerNumber,
purposeNumber=0,
offsetInMicrons=self.offset,
magnification=self.zoom,
rotate=None)
def get_blockages(self, layer):
""" Returns an empty list since text cannot be blockages. """
@ -321,7 +322,7 @@ class label(geometry):
def __repr__(self):
""" override print function output """
return "( label: " + self.text + " @" + str(self.offset) + " layer=" + self.layerNumber + " )"
return "( label: " + self.text + " @" + str(self.offset) + " layer=" + str(self.layerNumber) + " )"
class rectangle(geometry):
"""Represents a rectangular shape"""
@ -333,8 +334,8 @@ class rectangle(geometry):
self.layerNumber = layerNumber
self.offset = vector(offset).snap_to_grid()
self.size = vector(width, height).snap_to_grid()
self.width = self.size.x
self.height = self.size.y
self.width = round_to_grid(self.size.x)
self.height = round_to_grid(self.size.y)
self.compute_boundary(offset,"",0)
debug.info(4, "creating rectangle (" + str(self.layerNumber) + "): "
@ -348,16 +349,16 @@ class rectangle(geometry):
else:
return []
def gds_write_file(self, newLayout):
def gds_write_file(self, new_layout):
"""Writes the rectangular shape to GDS"""
debug.info(4, "writing rectangle (" + str(self.layerNumber) + "):"
+ str(self.width) + "x" + str(self.height) + " @ " + str(self.offset))
newLayout.addBox(layerNumber=self.layerNumber,
purposeNumber=0,
offsetInMicrons=self.offset,
width=self.width,
height=self.height,
center=False)
new_layout.addBox(layerNumber=self.layerNumber,
purposeNumber=0,
offsetInMicrons=self.offset,
width=self.width,
height=self.height,
center=False)
def __str__(self):
""" override print function output """

View File

@ -28,7 +28,7 @@ class layout(lef.lef):
self.insts = [] # Holds module/cell layout instances
self.objs = [] # Holds all other objects (labels, geometries, etc)
self.pin_map = {} # Holds name->pin_layout map for all pins
self.visited = False # Flag for traversing the hierarchy
self.visited = [] # List of modules we have already visited
self.is_library_cell = False # Flag for library cells
self.gds_read()
@ -432,59 +432,66 @@ class layout(lef.lef):
# open the gds file if it exists or else create a blank layout
if os.path.isfile(self.gds_file):
debug.info(3, "opening %s" % self.gds_file)
debug.info(3, "opening {}".format(self.gds_file))
self.is_library_cell=True
self.gds = gdsMill.VlsiLayout(units=GDS["unit"])
reader = gdsMill.Gds2reader(self.gds)
reader.loadFromFile(self.gds_file)
else:
debug.info(4, "creating structure %s" % self.name)
debug.info(3, "Creating layout structure {}".format(self.name))
self.gds = gdsMill.VlsiLayout(name=self.name, units=GDS["unit"])
def print_gds(self, gds_file=None):
"""Print the gds file (not the vlsi class) to the terminal """
if gds_file == None:
gds_file = self.gds_file
debug.info(4, "Printing %s" % gds_file)
debug.info(4, "Printing {}".format(gds_file))
arrayCellLayout = gdsMill.VlsiLayout(units=GDS["unit"])
reader = gdsMill.Gds2reader(arrayCellLayout, debugToTerminal=1)
reader.loadFromFile(gds_file)
def clear_visited(self):
""" Recursively clear the visited flag """
if not self.visited:
for i in self.insts:
i.mod.clear_visited()
self.visited = False
self.visited = []
def gds_write_file(self, newLayout):
def gds_write_file(self, gds_layout):
"""Recursive GDS write function"""
# Visited means that we already prepared self.gds for this subtree
if self.visited:
if self.name in self.visited:
return
for i in self.insts:
i.gds_write_file(newLayout)
i.gds_write_file(gds_layout)
for i in self.objs:
i.gds_write_file(newLayout)
i.gds_write_file(gds_layout)
for pin_name in self.pin_map.keys():
for pin in self.pin_map[pin_name]:
pin.gds_write_file(newLayout)
self.visited = True
pin.gds_write_file(gds_layout)
self.visited.append(self.name)
def gds_write(self, gds_name):
"""Write the entire gds of the object to the file."""
debug.info(3, "Writing to {0}".format(gds_name))
debug.info(3, "Writing to {}".format(gds_name))
# If we already wrote a GDS, we need to reset and traverse it again in
# case we made changes.
if not self.is_library_cell and self.visited:
debug.info(3, "Creating layout structure {}".format(self.name))
self.gds = gdsMill.VlsiLayout(name=self.name, units=GDS["unit"])
writer = gdsMill.Gds2writer(self.gds)
# MRG: 3/2/18 We don't want to clear the visited flag since
# this would result in duplicates of all instances being placed in self.gds
# which may have been previously processed!
#self.clear_visited()
# MRG: 10/4/18 We need to clear if we make changes and write a second GDS!
self.clear_visited()
# recursively create all the remaining objects
self.gds_write_file(self.gds)
# populates the xyTree data structure for gds
# self.gds.prepareForWrite()
writer.writeToFile(gds_name)
debug.info(3, "Done writing to {}".format(gds_name))
def get_boundary(self):
""" Return the lower-left and upper-right coordinates of boundary """
@ -1008,7 +1015,7 @@ class layout(lef.lef):
def pdf_write(self, pdf_name):
# NOTE: Currently does not work (Needs further research)
#self.pdf_name = self.name + ".pdf"
debug.info(0, "Writing to %s" % pdf_name)
debug.info(0, "Writing to {}".format(pdf_name))
pdf = gdsMill.pdfLayout(self.gds)
return

View File

@ -13,8 +13,8 @@ class options(optparse.Values):
# This is the name of the technology.
tech_name = ""
# This is the temp directory where all intermediate results are stored.
openram_temp = "/tmp/openram_{0}_{1}_temp/".format(getpass.getuser(),os.getpid())
#openram_temp = "{0}/openram_temp/".format(os.getenv("HOME"))
#openram_temp = "/tmp/openram_{0}_{1}_temp/".format(getpass.getuser(),os.getpid())
openram_temp = "{0}/openram_temp/".format(os.getenv("HOME"))
# This is the verbosity level to control debug information. 0 is none, 1
# is minimal, etc.
debug_level = 0

View File

@ -65,7 +65,6 @@ class grid:
self.map[n].path=value
def clear_blockages(self):
debug.info(2,"Clearing all blockages")
self.set_blocked(set(self.map.keys()),False)
def set_source(self,n,value=True):

View File

@ -17,26 +17,28 @@ class router:
It populates blockages on a grid class.
"""
def __init__(self, gds_name=None, module=None):
"""Use the gds file or the cell for the blockages with the top module topName and
layers for the layers to route on
def __init__(self, layers, design, gds_filename=None):
"""
self.gds_name = gds_name
self.module = module
debug.check(not (gds_name and module), "Specify only a GDS file or module")
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.
"""
self.cell = design
# If we specified a module instead, write it out to read the gds
# If didn't specify a gds blockage file, write it out to read the gds
# This isn't efficient, but easy for now
if module:
gds_name = OPTS.openram_temp+"temp.gds"
module.gds_write(gds_name)
if not gds_filename:
gds_filename = OPTS.openram_temp+"temp.gds"
self.cell.gds_write(gds_filename)
# Load the gds file and read in all the shapes
self.layout = gdsMill.VlsiLayout(units=tech.GDS["unit"])
self.reader = gdsMill.Gds2reader(self.layout)
self.reader.loadFromFile(gds_name)
self.reader.loadFromFile(gds_filename)
self.top_name = self.layout.rootStructureName
# Set up layers and track sizes
self.set_layers(layers)
### The pin data structures
# A map of pin names to pin structures
self.pins = {}
@ -157,6 +159,7 @@ class router:
self.pins[pin_name] = pin_set
self.all_pins.update(pin_set)
def find_pins(self,pin_name):
"""
Finds the pin shapes and converts to tracks.
@ -189,7 +192,53 @@ class router:
# # self.rg.reinit()
def find_pins_and_blockages(self, pin_list):
"""
Find the pins and blockages in the design
"""
# This finds the pin shapes and sorts them into "groups" that are connected
for pin in pin_list:
self.find_pins(pin)
# This will get all shapes as blockages and convert to grid units
# This ignores shapes that were pins
self.find_blockages()
# This will convert the pins to grid units
# It must be done after blockages to ensure no DRCs between expanded pins and blocked grids
for pin in pin_list:
self.convert_pins(pin)
# Enclose the continguous grid units in a metal rectangle to fix some DRCs
self.enclose_pins()
def prepare_blockages(self):
"""
Reset and add all of the blockages in the design.
Names is a list of pins to add as a blockage.
"""
debug.info(1,"Preparing blockages.")
# 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)
self.set_blockages(self.blocked_grids,True)
# Block all of the supply rails (some will be unblocked if they're a target)
self.set_supply_rail_blocked(True)
# Block all of the pin components (some will be unblocked if they're a source/target)
for name in self.pin_components.keys():
self.set_blockages(self.pin_components[name],True)
# Block all of the pin component partial blockages
for name in self.pin_component_blockages.keys():
self.set_blockages(self.pin_component_blockages[name],True)
# These are the paths that have already been routed.
self.set_path_blockages()
def translate_coordinates(self, coord, mirr, angle, xyShift):
"""
Calculate coordinates after flip, rotate, and shift
@ -251,6 +300,7 @@ class router:
"""
Clear all blockages on the grid.
"""
debug.info(2,"Clearing all blockages")
self.rg.clear_blockages()
def set_blockages(self, blockages, value=True):
@ -776,6 +826,7 @@ class router:
# FIXME: This could be optimized, but we just do a simple greedy biggest shape
# for now.
for pin_name in self.pin_components.keys():
print("Enclosing {}".format(pin_name))
for pin_set,partial_set in zip(self.pin_components[pin_name],self.pin_component_blockages[pin_name]):
total_pin_grids = pin_set | partial_set
while self.enclose_pin_grids(total_pin_grids):
@ -834,6 +885,7 @@ class router:
"""
Add the supply rails of given name as a routing target.
"""
debug.info(2,"Add supply rail target {}".format(pin_name))
for rail in self.supply_rails:
if rail.name != pin_name:
continue
@ -847,6 +899,7 @@ class router:
"""
Add the supply rails of given name as a routing target.
"""
debug.info(2,"Blocking supply rail")
for rail in self.supply_rails:
for wave_index in range(len(rail)):
pin_in_tracks = rail[wave_index]
@ -857,6 +910,7 @@ class router:
"""
Block all of the pin components.
"""
debug.info(2,"Setting blockages {0} {1}".format(pin_name,value))
for component in self.pin_components[pin_name]:
self.set_blockages(component, value)
@ -892,15 +946,16 @@ class router:
"""
path=self.prepare_path(path)
# convert the path back to absolute units from tracks
# This assumes 1-track wide again
abs_path = [self.convert_point_to_units(x[0]) for x in path]
debug.info(1,str(abs_path))
debug.info(1,"Adding route: {}".format(str(path)))
# If it is only a square, add an enclosure to the track
if len(path)==1:
self.add_single_enclosure(abs_path[0])
print("Single {}".format(str(path[0][0])))
self.add_single_enclosure(path[0][0])
else:
print("Route")
# convert the path back to absolute units from tracks
# This assumes 1-track wide again
abs_path = [self.convert_point_to_units(x[0]) for x in path]
# Otherwise, add the route which includes enclosures
self.cell.add_route(layers=self.layers,
coordinates=abs_path,

View File

@ -15,12 +15,12 @@ class signal_router(router):
route on a given layer. This is limited to two layer routes.
"""
def __init__(self, gds_name=None, module=None):
def __init__(self, layers, design, gds_filename=None):
"""
Use the gds file for the blockages with the top module topName and
layers for the layers to route on
This will route on layers in design. It will get the blockages from
either the gds file name or the design itself (by saving to a gds file).
"""
router.__init__(self, gds_name, module)
router.__init__(self, layers, design, gds_filename)
def create_routing_grid(self):
@ -36,14 +36,13 @@ class signal_router(router):
self.rg = signal_grid.signal_grid(self.ll, self.ur, self.track_width)
def route(self, cell, layers, src, dest, detour_scale=5):
def route(self, src, dest, detour_scale=5):
"""
Route a single source-destination net and return
the simplified rectilinear path. Cost factor is how sub-optimal to explore for a feasible route.
This is used to speed up the routing when there is not much detouring needed.
"""
debug.info(1,"Running signal router from {0} to {1}...".format(src,dest))
self.cell = cell
self.pins[src] = []
self.pins[dest] = []
@ -52,38 +51,29 @@ class signal_router(router):
if (hasattr(self,'rg')):
self.clear_pins()
else:
# Set up layers and track sizes
self.set_layers(layers)
# Creat a routing grid over the entire area
# FIXME: This could be created only over the routing region,
# but this is simplest for now.
self.create_routing_grid()
# Now add the blockages (all shapes except the pins)
self.find_pins(src)
self.find_pins(dest)
# Get the pin shapes
self.find_pins_and_blockages([src, dest])
# This will get all shapes as blockages
self.find_blockages()
# Now add the blockages
self.set_blockages(self.blocked_grids,True)
#self.set_blockages(self.pin_partials[src],True)
#self.set_blockages(self.pin_partials[dest],True)
# Add blockages from previous paths
self.set_path_blockages()
# Block everything
self.prepare_blockages()
# Clear the pins we are routing
self.set_blockages(self.pin_components[src],False)
self.set_blockages(self.pin_components[dest],False)
# Now add the src/tgt if they are not blocked by other shapes
self.add_source(src)
self.add_target(dest)
if not self.run_router(detour_scale):
if not self.run_router(detour_scale=detour_scale):
self.write_debug_gds(stop_program=False)
return False
self.write_debug_gds()
self.write_debug_gds(stop_program=False)
return True

View File

@ -17,13 +17,13 @@ class supply_router(router):
routes a grid to connect the supply on the two layers.
"""
def __init__(self, gds_name=None, module=None):
def __init__(self, layers, design, gds_filename=None):
"""
Use the gds file for the blockages with the top module topName and
layers for the layers to route on
This will route on layers in design. It will get the blockages from
either the gds file name or the design itself (by saving to a gds file).
"""
router.__init__(self, gds_name, module)
router.__init__(self, layers, design, gds_filename)
# Power rail width in grid units.
self.rail_track_width = 2
@ -38,12 +38,11 @@ class supply_router(router):
import supply_grid
self.rg = supply_grid.supply_grid(self.ll, self.ur, self.track_width)
def route(self, cell, layers, vdd_name="vdd", gnd_name="gnd"):
def route(self, vdd_name="vdd", gnd_name="gnd"):
"""
Add power supply rails and connect all pins to these rails.
"""
debug.info(1,"Running supply router on {0} and {1}...".format(vdd_name, gnd_name))
self.cell = cell
self.vdd_name = vdd_name
self.gnd_name = gnd_name
@ -51,15 +50,13 @@ class supply_router(router):
if (hasattr(self,'rg')):
self.clear_pins()
else:
# Set up layers and track sizes
self.set_layers(layers)
# Creat a routing grid over the entire area
# FIXME: This could be created only over the routing region,
# but this is simplest for now.
self.create_routing_grid()
# Get the pin shapes
self.find_pins_and_blockages()
self.find_pins_and_blockages([self.vdd_name, self.gnd_name])
# Add the supply rails in a mesh network and connect H/V with vias
# Block everything
@ -84,51 +81,6 @@ class supply_router(router):
self.write_debug_gds(stop_program=False)
return True
def find_pins_and_blockages(self):
"""
Find the pins and blockages in teh design
"""
# This finds the pin shapes and sorts them into "groups" that are connected
self.find_pins(self.vdd_name)
self.find_pins(self.gnd_name)
# This will get all shapes as blockages and convert to grid units
# This ignores shapes that were pins
self.find_blockages()
# This will convert the pins to grid units
# It must be done after blockages to ensure no DRCs between expanded pins and blocked grids
self.convert_pins(self.vdd_name)
self.convert_pins(self.gnd_name)
# Enclose the continguous grid units in a metal rectangle to fix some DRCs
self.enclose_pins()
def prepare_blockages(self):
"""
Reset and add all of the blockages in the design.
Names is a list of pins to add as a blockage.
"""
# 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)
self.set_blockages(self.blocked_grids,True)
# Block all of the supply rails (some will be unblocked if they're a target)
self.set_supply_rail_blocked(True)
# Block all of the pin components (some will be unblocked if they're a source/target)
for name in self.pin_components.keys():
self.set_blockages(self.pin_components[name],True)
# Block all of the pin component partial blockages
for name in self.pin_component_blockages.keys():
self.set_blockages(self.pin_component_blockages[name],True)
# These are the paths that have already been routed.
self.set_path_blockages()
def connect_supply_rails(self, name):
"""

View File

@ -37,9 +37,9 @@ class no_blockages_test(openram_test):
offset=[0,0])
self.connect_inst([])
r=router(gds_file)
layer_stack =("metal1","via1","metal2")
self.assertTrue(r.route(self,layer_stack,src="A",dest="B"))
r=router(layer_stack,self,gds_file)
self.assertTrue(r.route(src="A",dest="B"))
r=routing("01_no_blockages_test_{0}".format(OPTS.tech_name))
self.local_drc_check(r)

View File

@ -37,9 +37,9 @@ class blockages_test(openram_test):
offset=[0,0])
self.connect_inst([])
r=router(gds_file)
layer_stack =("metal1","via1","metal2")
self.assertTrue(r.route(self,layer_stack,src="A",dest="B"))
r=router(layer_stack,self,gds_file)
self.assertTrue(r.route(src="A",dest="B"))
r=routing("02_blockages_test_{0}".format(OPTS.tech_name))
self.local_drc_check(r)

View File

@ -36,9 +36,9 @@ class same_layer_pins_test(openram_test):
offset=[0,0])
self.connect_inst([])
r=router(gds_file)
layer_stack =("metal1","via1","metal2")
self.assertTrue(r.route(self,layer_stack,src="A",dest="B"))
r=router(layer_stack,self,gds_file)
self.assertTrue(r.route(src="A",dest="B"))
r = routing("03_same_layer_pins_test_{0}".format(OPTS.tech_name))
self.local_drc_check(r)

View File

@ -38,9 +38,9 @@ class diff_layer_pins_test(openram_test):
offset=[0,0])
self.connect_inst([])
r=router(gds_file)
layer_stack =("metal1","via1","metal2")
self.assertTrue(r.route(self,layer_stack,src="A",dest="B"))
r=router(layer_stack,self,gds_file)
self.assertTrue(r.route(src="A",dest="B"))
r = routing("04_diff_layer_pins_test_{0}".format(OPTS.tech_name))
self.local_drc_check(r)

View File

@ -38,10 +38,10 @@ class two_nets_test(openram_test):
offset=[0,0])
self.connect_inst([])
r=router(gds_file)
layer_stack =("metal1","via1","metal2")
self.assertTrue(r.route(self,layer_stack,src="A",dest="B"))
self.assertTrue(r.route(self,layer_stack,src="C",dest="D"))
r=router(layer_stack,self,gds_file)
self.assertTrue(r.route(src="A",dest="B"))
self.assertTrue(r.route(src="C",dest="D"))
r = routing("05_two_nets_test_{0}".format(OPTS.tech_name))
self.local_drc_check(r)

View File

@ -37,13 +37,13 @@ class pin_location_test(openram_test):
offset=[0,0])
self.connect_inst([])
r=router(gds_file)
layer_stack =("metal1","via1","metal2")
r=router(layer_stack,self,gds_file)
# these are user coordinates and layers
src_pin = [[0.52, 4.099],11]
tgt_pin = [[3.533, 1.087],11]
#r.route(layer_stack,src="A",dest="B")
self.assertTrue(r.route(self,layer_stack,src=src_pin,dest=tgt_pin))
self.assertTrue(r.route(src=src_pin,dest=tgt_pin))
# This only works for freepdk45 since the coordinates are hard coded
if OPTS.tech_name == "freepdk45":

View File

@ -37,8 +37,8 @@ class big_test(openram_test):
offset=[0,0])
self.connect_inst([])
r=router(gds_file)
layer_stack =("metal1","via1","metal2")
r=router(layer_stack,self,gds_file)
connections=[('out_0_2', 'a_0_0'),
('out_0_3', 'b_0_0'),
('out_0_0', 'a_0_1'),
@ -61,7 +61,7 @@ class big_test(openram_test):
('out_4_1', 'a_4_3'),
('out_4_5', 'b_4_3')]
for (src,tgt) in connections:
self.assertTrue(r.route(self,layer_stack,src=src,dest=tgt))
self.assertTrue(r.route(src=src,dest=tgt))
# This test only runs on scn3me_subm tech
if OPTS.tech_name=="scn3me_subm":

View File

@ -37,12 +37,12 @@ class expand_region_test(openram_test):
offset=[0,0])
self.connect_inst([])
r=router(gds_file)
layer_stack =("metal1","via1","metal2")
r=router(layer_stack,self,gds_file)
# This should be infeasible because it is blocked without a detour.
self.assertFalse(r.route(self,layer_stack,src="A",dest="B",detour_scale=1))
self.assertFalse(r.route(src="A",dest="B",detour_scale=1))
# This should be feasible because we allow it to detour
self.assertTrue(r.route(self,layer_stack,src="A",dest="B",detour_scale=3))
self.assertTrue(r.route(src="A",dest="B",detour_scale=3))
r = routing("08_expand_region_test_{0}".format(OPTS.tech_name))
self.local_drc_check(r)

View File

@ -17,36 +17,26 @@ class no_blockages_test(openram_test):
def runTest(self):
globals.init_openram("config_{0}".format(OPTS.tech_name))
from gds_cell import gds_cell
from design import design
from supply_router import supply_router as router
class routing(design, openram_test):
"""
A generic GDS design that we can route on.
"""
def __init__(self, name):
design.__init__(self, "top")
# Instantiate a GDS cell with the design
globals.setup_paths()
from control_logic import control_logic
cell = control_logic(16)
#from pinv import pinv
#cell = pinv()
#gds_file = "{0}/{1}.gds".format(os.path.dirname(os.path.realpath(__file__)),"control_logic")
#cell = gds_cell(name, gds_file)
self.add_inst(name=name,
mod=cell,
offset=[0,0])
self.connect_inst(cell.pin_map.keys())
if True:
from control_logic import control_logic
cell = control_logic(16)
else:
from sram import sram
from sram_config import sram_config
c = sram_config(word_size=4,
num_words=16,
num_banks=1)
c.words_per_row=1
cell = sram(c, "sram1")
r=router(module=cell)
layer_stack =("metal3","via3","metal4")
self.assertTrue(r.route(self,layer_stack))
r=routing("10_supply_grid_test_{0}".format(OPTS.tech_name))
self.local_drc_check(r)
print("PRE:",cell)
layer_stack =("metal3","via3","metal4")
rtr=router(layer_stack, cell)
self.assertTrue(rtr.route())
self.local_check(cell,True)
# fails if there are any DRC errors on any cells
globals.end_openram()