def gds_read(self): """Reads a GDSII file in the library and checks if it exists Otherwise, start a new layout for dynamic generation.""" # 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) self.gds = gdsMill.VlsiLayout(units=GDS["unit"]) reader = gdsMill.Gds2reader(self.gds) reader.loadFromFile(self.gds_file) else: debug.info(3, "creating structure %s" % self.name) self.gds = gdsMill.VlsiLayout(name=self.name, units=GDS["unit"])
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 """ self.gds_name = gds_name self.module = module debug.check(not (gds_name and module), "Specify only a GDS file or module") # If we specified a module instead, 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) # 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.top_name = self.layout.rootStructureName self.pins = {} self.blockages = [] # all the paths we've routed so far (to supplement the blockages) self.paths = [] # The boundary will determine the limits to the size of the routing grid self.boundary = self.layout.measureBoundary(self.top_name) self.ll = vector(self.boundary[0]) self.ur = vector(self.boundary[1])
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 {}".format(gds_file)) arrayCellLayout = gdsMill.VlsiLayout(units=GDS["unit"]) reader = gdsMill.Gds2reader(arrayCellLayout, debugToTerminal=1) reader.loadFromFile(gds_file)
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(3, "Printing %s" % gds_file) arrayCellLayout = gdsMill.VlsiLayout() reader = gdsMill.Gds2reader(arrayCellLayout, debugToTerminal=1) reader.loadFromFile(gds_file)
def __init__(self, layers, design, gds_filename=None, rail_track_width=1): """ 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. """ router_tech.__init__(self, layers, rail_track_width) self.cell = design # If didn't specify a gds blockage file, write it out to read the gds # This isn't efficient, but easy for now # start_time = datetime.now() 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=GDS["unit"]) self.reader = gdsMill.Gds2reader(self.layout) self.reader.loadFromFile(gds_filename) self.top_name = self.layout.rootStructureName # print_time("GDS read",datetime.now(), start_time) # The pin data structures # A map of pin names to a set of pin_layout structures # (i.e. pins with a given label) self.pins = {} # This is a set of all pins (ignoring names) so that can quickly # not create blockages for pins # (They will be blocked when we are routing other # nets based on their name.) self.all_pins = set() # The labeled pins above categorized into pin groups # that are touching/connected. self.pin_groups = {} # The blockage data structures # A list of metal shapes (using the same pin_layout structure) # that are not pins but blockages. self.blockages = [] # The corresponding set of blocked grids for above pin shapes self.blocked_grids = set() # The routed data structures # A list of paths that have been "routed" self.paths = [] # A list of path blockages (they might be expanded for wide metal DRC) self.path_blockages = [] # The boundary will determine the limits to the size # of the routing grid self.boundary = self.layout.measureBoundary(self.top_name) # These must be un-indexed to get rid of the matrix type self.ll = vector(self.boundary[0][0], self.boundary[0][1]) self.ur = vector(self.boundary[1][0], self.boundary[1][1])
def gds_read(self): """Reads a GDSII file in the library and checks if it exists Otherwise, start a new layout for dynamic generation.""" # This must be done for netlist only mode too if os.path.isfile(self.gds_file): self.is_library_cell = True if OPTS.netlist_only: self.gds = None return # open the gds file if it exists or else create a blank layout if os.path.isfile(self.gds_file): debug.info(3, "opening {}".format(self.gds_file)) self.gds = gdsMill.VlsiLayout(units=GDS["unit"]) reader = gdsMill.Gds2reader(self.gds) reader.loadFromFile(self.gds_file) else: debug.info(3, "Creating layout structure {}".format(self.name)) self.gds = gdsMill.VlsiLayout(name=self.name, units=GDS["unit"])
def _get_gds_reader(units, gds_filename): gds_absname = os.path.realpath(gds_filename) k = (units, gds_absname) try: return _GDS_READER_CACHE[k] except KeyError: debug.info(4, "Creating VLSI layout from {}".format(gds_absname)) cell_vlsi = gdsMill.VlsiLayout(units=units) reader = gdsMill.Gds2reader(cell_vlsi) reader.loadFromFile(gds_absname) _GDS_READER_CACHE[k] = cell_vlsi return cell_vlsi
def __init__(self, gdsName, lefName, sr): self.gdsName = gdsName self.lef = open(lefName, "w") self.sr = sr self.myLayout = gdsMill.VlsiLayout(units=tech.GDS["unit"]) self.reader = gdsMill.Gds2reader(self.myLayout) self.reader.loadFromFile(gdsName) self.unit = float(self.myLayout.info['units'][0]) self.layer = ["metal1", "via1", "metal2", "via2", "metal3"] self.create() self.lef.close()
def get_libcell_size(name, units, layer): """ Open a GDS file and return the library cell size from either the bounding box or a border layer. """ cell_gds = OPTS.AMC_tech + "gds_lib/" + str(name) + ".gds" cell_vlsi = gdsMill.VlsiLayout(units=units) reader = gdsMill.Gds2reader(cell_vlsi) reader.loadFromFile(cell_gds) cell = {} measure_result = cell_vlsi.getLayoutBorder(layer) if measure_result == None: measure_result = cell_vlsi.measureSize(name) return measure_result
def auto_measure_libcell(pin_list, name, units, layer): cell_gds = OPTS.openram_tech + "gds_lib/" + str(name) + ".gds" cell_vlsi = gdsMill.VlsiLayout(units=units) reader = gdsMill.Gds2reader(cell_vlsi) reader.loadFromFile(cell_gds) cell = {} measure_result = cell_vlsi.readLayoutBorder(layer) if measure_result == None: measure_result = cell_vlsi.measureSize(name) [cell["width"], cell["height"]] = measure_result for pin in pin_list: cell[str(pin)] = gdsPinToOffset(cell_vlsi.readPin(str(pin))) return cell
def get_gds_size(name, gds_filename, units, lpp): """ Open a GDS file and return the size from either the bounding box or a border layer. """ debug.info(4, "Creating VLSI layout for {}".format(name)) cell_vlsi = gdsMill.VlsiLayout(units=units) reader = gdsMill.Gds2reader(cell_vlsi) reader.loadFromFile(gds_filename) measure_result = cell_vlsi.getLayoutBorder(lpp) if not measure_result: debug.info( 2, "Layout border failed. Trying to measure size for {}".format(name)) measure_result = cell_vlsi.measureSize(name) # returns width,height return measure_result
def get_libcell_pins(pin_list, name, units): """ Open a GDS file and find the pins in pin_list as text on a given layer. Return these as a rectangle layer pair for each pin. """ cell_gds = OPTS.AMC_tech + "gds_lib/" + str(name) + ".gds" cell_vlsi = gdsMill.VlsiLayout(units=units) reader = gdsMill.Gds2reader(cell_vlsi) reader.loadFromFile(cell_gds) cell = {} for pin in pin_list: cell[str(pin)]=[] label_list=cell_vlsi.getPinShapeByLabel(str(pin)) for label in label_list: (name, layer, boundary)=label rect = pin_rect(boundary) # this is a list because other cells/designs may have must-connect pins cell[str(pin)].append(pin_layout(pin, rect, layer)) return cell
def auto_measure_libcell(pin_list, name, units, layer): """ Open a GDS file and find the pins in pin_list as text on a given layer. Return these as a set of properties including the cell width/height too. """ cell_gds = OPTS.AMC_tech + "gds_lib/" + str(name) + ".gds" cell_vlsi = gdsMill.VlsiLayout(units=units) reader = gdsMill.Gds2reader(cell_vlsi) reader.loadFromFile(cell_gds) cell = {} measure_result = cell_vlsi.getLayoutBorder(layer) if measure_result == None: measure_result = cell_vlsi.measureSize(name) [cell["width"], cell["height"]] = measure_result for pin in pin_list: (name, layer, boundary)=cell_vlsi.getPinShapeByLabel(str(pin)) cell[str(pin)] = pin_center(boundary) return cell
def __init__(self, gds_name): """Use the gds file for the blockages with the top module topName and layers for the layers to route on """ # Load the gds file and read in all the shapes self.gds_name = gds_name self.layout = gdsMill.VlsiLayout(units=tech.GDS["unit"]) self.reader = gdsMill.Gds2reader(self.layout) self.reader.loadFromFile(gds_name) self.top_name = self.layout.rootStructureName self.source_pin_shapes = [] self.source_pin_zindex = None self.target_pin_shapes = [] self.target_pin_zindex = None # The boundary will determine the limits to the size of the routing grid self.boundary = self.layout.measureBoundary(self.top_name) self.ll = vector(self.boundary[0]) self.ur = vector(self.boundary[1])
def get_gds_pins(pin_names, name, gds_filename, units): """ Open a GDS file and find the pins in pin_names as text on a given layer. Return these as a rectangle layer pair for each pin. """ cell_vlsi = gdsMill.VlsiLayout(units=units) reader = gdsMill.Gds2reader(cell_vlsi) reader.loadFromFile(gds_filename) cell = {} for pin_name in pin_names: cell[str(pin_name)] = [] pin_list = cell_vlsi.getPinShape(str(pin_name)) for pin_shape in pin_list: (layer, boundary) = pin_shape rect = [ vector(boundary[0], boundary[1]), vector(boundary[2], boundary[3]) ] # this is a list because other cells/designs may have must-connect pins cell[str(pin_name)].append(pin_layout(pin_name, rect, layer)) return cell
def gds_write(self, gds_name): """Write the entire gds of the object to the file.""" 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! # 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))
gds_file_in = "sram_lib2.gds" #"sram_cell_6t.gds" #"gds_sram_tgate2.gds" gds_file_out = "newcell.gds" debug = 0 streamer = gdsMill.GdsStreamer() # use the streamer to take a cadence layout, and convert it to GDS 2 for us to work with # the GDS will be named testLayoutA.gds #streamer.streamFromCadence(cadenceLibraryContainerPath = "~/design/600nmAmi", # libraryName = "gdsMillTest", # cellName = "testLayoutA", # outputPath = "./gdsFiles") #next, load our base cell layout from the GDS generated above arrayCellLayout = gdsMill.VlsiLayout() reader = gdsMill.Gds2reader(arrayCellLayout, debugToTerminal=debug) reader.loadFromFile(gds_file_in) ##since we will be streaming into the same library that testLayout came from #let's rename it here so that we don't overwrite accidentally later #arrayCellLayout.rename("tom_2x2") #now create a new layout #be sure to assign a name, since this will be the root object in our hierarchy to which #all other objects are referenced #newLayout = gdsMill.VlsiLayout(name="arrayExample", debug=1, units=(5e-4,5e-10)) # newLayout = gdsMill.VlsiLayout(name="tom_2x2", debug=0, units=(0.001, 1.0000000000000001e-09)) #
import gdsMill #we are going to make an array of instances of an existing layout #assume that we designed the "base cell" in cadence #step 1 is to stream it out of cadence into a GDS to work with # creater a streamer object to interact with the cadence libraries streamer = gdsMill.GdsStreamer() # use the streamer to take a cadence layout, and convert it to GDS 2 for us to work with # the GDS will be named testLayoutA.gds #streamer.streamFromCadence(cadenceLibraryContainerPath = "~/design/600nmAmi", # libraryName = "gdsMillTest", # cellName = "testLayoutA", # outputPath = "./gdsFiles") #next, load our base cell layout from the GDS generated above arrayCellLayout = gdsMill.VlsiLayout() reader = gdsMill.Gds2reader(arrayCellLayout) reader.loadFromFile("./gdsFiles/testLayoutA.gds") ##since we will be streaming into the same library that testLayout came from #let's rename it here so that we don't overwrite accidentally later arrayCellLayout.rename("arrayCell") #now create a new layout #be sure to assign a name, since this will be the root object in our hierarchy to which #all other objects are referenced newLayout = gdsMill.VlsiLayout(name="arrayExample") #now place an instnace of our top level layout into the filled layout #hierarchy looks like this: # array example
#!/usr/bin/env python import gdsMill, sys gds_file = sys.argv[ 1] #"layoutB.gds" #"sram_cell_6t.gds" #"gds_sram_tgate2.gds" #streamer = gdsMill.GdsStreamer() arrayCellLayout = gdsMill.VlsiLayout() reader = gdsMill.Gds2reader(arrayCellLayout, debugToTerminal=1) reader.loadFromFile(gds_file)
#!/usr/bin/env python import gdsMill #creater a streamer object to interact with the cadence libraries streamer = gdsMill.GdsStreamer() #use the streamer to take a cadence layout, and convert it to GDS 2 for us to work with #the GDS will be named testLayoutA.gds streamer.streamFromCadence(cadenceLibraryContainerPath="../AMC_temp", libraryName="gdsMillTest", cellName="testLayoutA", outputPath="./gdsFiles") #create a layout object - this object represents all of the elements within the layout myLayout = gdsMill.VlsiLayout() #give our layout object to a gds reader object. The gds reader will look at the binary gds 2 file and #populate the layout object with the file's contents reader = gdsMill.Gds2reader(myLayout) #tell the reader object to process the gds file that we streamed in above #un-comment the next line to see some details about the gds contents #reader.debugToTerminal=1 reader.loadFromFile("./gdsFiles/testLayoutA.gds") #our layout object now contains all of the elements of the layout #let add a box to the layout myLayout.addBox( layerNumber=myLayout.layerNumbersInUse[0], #pick some layer offsetInMicrons=(-10, 0), #location width=10.0, #units are microns
#!/usr/bin/env python import gdsMill #we will add the filler at a higher level of hiearchy #so first, load our top level layout from GDS myTopLevelLayout = gdsMill.VlsiLayout() reader = gdsMill.Gds2reader(myTopLevelLayout) reader.loadFromFile("./gdsFiles/testLayoutA.gds") #now create a new layout #be sure to assign a name, since this will be the root object in our hierarchy to which #all other objects are referenced filledLayout = gdsMill.VlsiLayout(name="filledLayout") #now place an instnace of our top level layout into the filled layout #hierarchy looks like this: # filled layout # top level layout # layout elements # layout elements # layout elements # fill elements # fill elements ..... filledLayout.addInstance(myTopLevelLayout, offsetInMicrons = (0,0), mirror = "", rotate = 0.0) #now actaully add the fill - gds mill will create an array of boxes # maintaining spacing from existing layout elements #we'll do it once for two different layers
gds_file_in = "sram_lib2.gds" #"sram_cell_6t.gds" #"gds_sram_tgate2.gds" gds_file_out = "layoutB.gds" debug = 0 streamer = gdsMill.GdsStreamer() # use the streamer to take a cadence layout, and convert it to GDS 2 for us to work with # the GDS will be named testLayoutA.gds #streamer.streamFromCadence(cadenceLibraryContainerPath = "~/design/600nmAmi", # libraryName = "gdsMillTest", # cellName = "testLayoutA", # outputPath = "./gdsFiles") #next, load our base cell layout from the GDS generated above arrayCellLayout = gdsMill.VlsiLayout() reader = gdsMill.Gds2reader(arrayCellLayout, debugToTerminal=debug) reader.loadFromFile(gds_file_in) ##since we will be streaming into the same library that testLayout came from #let's rename it here so that we don't overwrite accidentally later arrayCellLayout.rename("arrayCell") #now create a new layout #be sure to assign a name, since this will be the root object in our hierarchy to which #all other objects are referenced newLayout = gdsMill.VlsiLayout( name="arrayExample", debug=1, units=(0.001, 2.0000000000000000e-09)) #units=(5e-4,5e-10)) # #now place an instnace of our top level layout into the filled layout