diff --git a/compiler/base/design.py b/compiler/base/design.py index 09522f35..7b2ec974 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -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 diff --git a/compiler/base/geometry.py b/compiler/base/geometry.py index 7144a2cf..8f0edb29 100644 --- a/compiler/base/geometry.py +++ b/compiler/base/geometry.py @@ -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 """ diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index 90d710c6..bd6c85f8 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -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 diff --git a/compiler/options.py b/compiler/options.py index 58d97ea0..edcad66b 100644 --- a/compiler/options.py +++ b/compiler/options.py @@ -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 diff --git a/compiler/router/grid.py b/compiler/router/grid.py index 18a51b61..b7b1e91b 100644 --- a/compiler/router/grid.py +++ b/compiler/router/grid.py @@ -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): diff --git a/compiler/router/router.py b/compiler/router/router.py index b9bc3597..298591f8 100644 --- a/compiler/router/router.py +++ b/compiler/router/router.py @@ -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, diff --git a/compiler/router/signal_router.py b/compiler/router/signal_router.py index ff813125..0f65b2ca 100644 --- a/compiler/router/signal_router.py +++ b/compiler/router/signal_router.py @@ -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 diff --git a/compiler/router/supply_router.py b/compiler/router/supply_router.py index 47e0c7f5..b14cdb7e 100644 --- a/compiler/router/supply_router.py +++ b/compiler/router/supply_router.py @@ -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): """ diff --git a/compiler/router/tests/01_no_blockages_test.py b/compiler/router/tests/01_no_blockages_test.py index c7344a64..4197f714 100755 --- a/compiler/router/tests/01_no_blockages_test.py +++ b/compiler/router/tests/01_no_blockages_test.py @@ -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) diff --git a/compiler/router/tests/02_blockages_test.py b/compiler/router/tests/02_blockages_test.py index 2e85b1c2..6e3bee08 100755 --- a/compiler/router/tests/02_blockages_test.py +++ b/compiler/router/tests/02_blockages_test.py @@ -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) diff --git a/compiler/router/tests/03_same_layer_pins_test.py b/compiler/router/tests/03_same_layer_pins_test.py index 98ce3a2a..726cd02b 100755 --- a/compiler/router/tests/03_same_layer_pins_test.py +++ b/compiler/router/tests/03_same_layer_pins_test.py @@ -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) diff --git a/compiler/router/tests/04_diff_layer_pins_test.py b/compiler/router/tests/04_diff_layer_pins_test.py index cbc21470..2882156f 100755 --- a/compiler/router/tests/04_diff_layer_pins_test.py +++ b/compiler/router/tests/04_diff_layer_pins_test.py @@ -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) diff --git a/compiler/router/tests/05_two_nets_test.py b/compiler/router/tests/05_two_nets_test.py index 166292d0..e71920a8 100755 --- a/compiler/router/tests/05_two_nets_test.py +++ b/compiler/router/tests/05_two_nets_test.py @@ -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) diff --git a/compiler/router/tests/06_pin_location_test.py b/compiler/router/tests/06_pin_location_test.py index e67fed53..f469d326 100755 --- a/compiler/router/tests/06_pin_location_test.py +++ b/compiler/router/tests/06_pin_location_test.py @@ -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": diff --git a/compiler/router/tests/07_big_test.py b/compiler/router/tests/07_big_test.py index 5f844ec5..8fcf2826 100755 --- a/compiler/router/tests/07_big_test.py +++ b/compiler/router/tests/07_big_test.py @@ -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": diff --git a/compiler/router/tests/08_expand_region_test.py b/compiler/router/tests/08_expand_region_test.py index 96edab57..3e63bd51 100755 --- a/compiler/router/tests/08_expand_region_test.py +++ b/compiler/router/tests/08_expand_region_test.py @@ -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) diff --git a/compiler/router/tests/10_supply_grid_test.py b/compiler/router/tests/10_supply_grid_test.py index 792e6956..222fd58f 100755 --- a/compiler/router/tests/10_supply_grid_test.py +++ b/compiler/router/tests/10_supply_grid_test.py @@ -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()