def move_diearea(input_lef, output_def, template_def): if not os.path.isfile(template_def): print("LEF file ", input_lef, " not found") raise FileNotFoundError if not os.path.isfile(template_def): print("Input DEF file ", template_def, " not found") raise FileNotFoundError if not os.path.isfile(output_def): print("Output DEF file ", output_def, " not found") raise FileNotFoundError source_db = odb.dbDatabase.create() destination_db = odb.dbDatabase.create() odb.read_lef(source_db, input_lef) odb.read_lef(destination_db, input_lef) odb.read_def(source_db, template_def) odb.read_def(destination_db, output_def) assert (source_db.getTech().getManufacturingGrid() == destination_db.getTech().getManufacturingGrid()) assert (source_db.getTech().getDbUnitsPerMicron() == destination_db.getTech().getDbUnitsPerMicron()) diearea = source_db.getChip().getBlock().getDieArea() output_block = destination_db.getChip().getBlock() output_block.setDieArea(diearea) # print("Applied die area: ", destination_db.getChip().getBlock().getDieArea().ur(), destination_db.getChip().getBlock().getDieArea().ll(), file=sys.stderr) assert odb.write_def(output_block, output_def) == 1
def extract_pins(db, def_file): odb.read_lef(db, os.environ["TECH_LEF"]) odb.read_lef(db, os.environ["MERGED_LEF"]) odb.read_def(db, def_file) chip = db.getChip() block = chip.getBlock() nets = block.getNets() # tech = db.getTech() # Not needed result_data = {} for net in nets: net_name = net.getName() # BTerms = PINS, if it has a pin we need to keep the net bterms = net.getBTerms() if len(bterms) > 0: for port in bterms: if (port.getSigType() == "POWER") or (port.getSigType() == "GROUND"): # Ignore power pins continue name = port.getName() bbox = port.getBBox() result_data[name] = bbox print( "Net:", net_name, "Port:", name, "ll: ", " ".join(str(e) for e in bbox.ll()), "ur: ", " ".join(str(e) for e in bbox.ur()), ) return result_data
def main(): parser = argparse.ArgumentParser(description="DEF to Liberty.") parser.add_argument( "--input_lef", "-l", nargs="+", type=str, default=None, required=True, help="Input LEF file(s)", ) parser.add_argument("--input_def", "-i", required=True, help="DEF view of the design.") parser.add_argument("--output_def", "-o", required=True, help="Output DEF file") parser.add_argument("--dont_buffer", "-d", required=True, help="Dont Buffer list of output ports.") args = parser.parse_args() input_lef_files = args.input_lef input_def_file = args.input_def output_def = args.output_def dont_buffer_list = args.dont_buffer # parse input def/lef files db_design = odb.dbDatabase.create() for lef in input_lef_files: odb.read_lef(db_design, lef) odb.read_def(db_design, input_def_file) chip_design = db_design.getChip() block_design = chip_design.getBlock() # remove buffers connected to the dont buffer nets remove_buffers(block_design, dont_buffer_list) # write output def odb.write_def(block_design, output_def)
def __init__(self, lef_in, def_in): self.db = odb.dbDatabase.create() self.lef = odb.read_lef(self.db, lef_in) self.sites = self.lef.getSites() self.df = odb.read_def(self.db, def_in) self.block = self.db.getChip().getBlock() self.rows = self.block.getRows() self.dbunits = self.block.getDefUnits()
def main(): parser = argparse.ArgumentParser(description='DEF to Liberty.') parser.add_argument('--input_lef', '-l', nargs='+', type=str, default=None, required=True, help='Input LEF file(s)') parser.add_argument('--input_def', '-i', required=True, help='DEF view of the design.') parser.add_argument('--output_def', '-o', required=True, help='Output DEF file') parser.add_argument('--dont_buffer', '-d', required=True, help='Dont Buffer list of output ports.') args = parser.parse_args() input_lef_files = args.input_lef input_def_file = args.input_def output_def = args.output_def dont_buffer_list = args.dont_buffer # parse input def/lef files db_design = odb.dbDatabase.create() for lef in input_lef_files: odb.read_lef(db_design, lef) odb.read_def(db_design, input_def_file) chip_design = db_design.getChip() block_design = chip_design.getBlock() # remove buffers connected to the dont buffer nets remove_buffers(block_design, dont_buffer_list) # write output def odb.write_def(block_design, output_def)
def __init__(self, lef_in, def_in): self.db = odb.dbDatabase.create() if isinstance(lef_in, list) or isinstance(lef_in, tuple): self.lef = [] for lef in lef_in: self.lef.append(odb.read_lef(self.db, lef)) self.sites = [lef.getSites() for lef in self.lef] else: self.lef = odb.read_lef(self.db, lef_in) self.sites = self.lef.getSites() self.tech = self.db.getTech() if def_in is not None: self.df = odb.read_def(self.db, def_in) self.block = self.db.getChip().getBlock() self.name = self.block.getName() self.rows = self.block.getRows() self.dbunits = self.block.getDefUnits()
required=True, help="output eco_fix.tcl") args = parser.parse_args() input_file = args.input_file output_file = args.output_file def_file = args.def_file lef_file = args.lef_file splitLine = "\n\n\n" printArr = [] db = odb.dbDatabase.create() print(def_file) odb.read_lef(db, lef_file) odb.read_def(db, os.path.join(def_file)) # get db from the file chip = db.getChip() block = chip.getBlock() insts = block.getInsts() insts_pin = block.getBTerms() # pins boundary vio_dict = defaultdict(list) # iteration to find minus slack # create insert_buffer command # Converting Magic DRC if os.path.exists(input_file): drcFileOpener = open(input_file) if drcFileOpener.mode == "r": drcContent = drcFileOpener.read() drcFileOpener.close()
choices=["none", "in", "out", "both"], default="in", help="Always place a true diode on nets connected to selected ports", ) args = parser.parse_args() input_lef_file_names = args.lef input_def_file_name = args.input_def output_def_file_name = args.output_def # Load db_design = odb.dbDatabase.create() for lef in input_lef_file_names: odb.read_lef(db_design, lef) odb.read_def(db_design, input_def_file_name) chip_design = db_design.getChip() block_design = chip_design.getBlock() top_design_name = block_design.getConstName() print("Design name:", top_design_name) pp_val = { "none": [], "in": ["INPUT"], "out": ["OUTPUT"], "both": ["INPUT", "OUTPUT"], } di = DiodeInserter( block_design,
# top_def_new_file_name = os.path.join(os.path.dirname(macro_def_file_name), os.path.basename(macro_def_file_name) + ".top.def") # copy(os.path.normpath(top_lef_file_name), top_lef_new_file_name) # copy(os.path.normpath(top_def_file_name), top_def_new_file_name) # top_lef_file_name = top_lef_new_file_name # top_def_file_name = top_def_new_file_name db_macro = odb.dbDatabase.create() db_top = odb.dbDatabase.create() odb.read_lef(db_macro, top_lef_file_name ) # must read first to have consistent views with the top-level odb.read_lef( db_macro, macro_lef_file_name ) # rest of the macros that don't appear in the top-level are covered here odb.read_def(db_macro, macro_def_file_name) odb.read_lef(db_top, top_lef_file_name) odb.read_def(db_top, top_def_file_name) chip_macro = db_macro.getChip() block_macro = chip_macro.getBlock() macro_design_name = block_macro.getName() chip_top = db_top.getChip() block_top = chip_top.getBlock() top_design_name = block_top.getName() print("Block design name:", macro_design_name) print("Top-level design name:", top_design_name)
else: boxes = getAllBoxes(pad_iterm) for box in boxes: layer, ll, ur = box odb.dbBox_create(pin_bpin, layer, ll.getX(), ll.getY(), ur.getX(), ur.getY()) pad_iterm.connect(net) pin_bterm.connect(net) mapping_db = odb.dbDatabase.create() for lef in netlist_lef_file_names: odb.read_lef(mapping_db, lef) odb.read_def(mapping_db, netlist_def_file_name) # for later chip_db = odb.dbDatabase.create() for lef in input_lef_file_names: print(lef) odb.read_lef(chip_db, lef) odb.read_def(chip_db, input_def_file_name) mapping_chip = mapping_db.getChip() mapping_block = mapping_chip.getBlock() mapping_nets = mapping_block.getNets() pad_pin_map = {} for net in mapping_nets: iterms = net.getITerms()
obs_list = [] for obs in obses: obs = obs.strip() m = re.match(RE_OBS, obs) assert m,\ "Incorrectly formatted input (%s).\n Format: layer llx lly urx ury, ..." % (obs) layer = m.group('layer') bbox = [float(x) for x in m.group('bbox').split()] obs_list.append((layer, bbox)) design_db = odb.dbDatabase.create() for lef in input_lef_file_names: odb.read_lef(design_db, lef) odb.read_def(design_db, input_def_file_name) design_chip = design_db.getChip() design_block = design_chip.getBlock() design_insts = design_block.getInsts() design_tech = design_db.getTech() for obs in obs_list: layer = obs[0] bbox = obs[1] dbu = design_tech.getDbUnitsPerMicron() bbox = [int(x * dbu) for x in bbox] print("Creating an obstruction on", layer, "at", *bbox, "(DBU)") odb.dbObstruction_create(design_block, design_tech.findLayer(layer), *bbox) odb.write_def(design_block, output_def_file_name)
# distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import argparse import odb # overkill parser = argparse.ArgumentParser( description='gets the core dimensions from DEF/LEF') parser.add_argument('--input-def', '-d', required=True) parser.add_argument('--input-lef', '-l', required=True) args = parser.parse_args() input_lef_file_name = args.input_lef input_def_file_name = args.input_def db = odb.dbDatabase.create() odb.read_lef(db, input_lef_file_name) odb.read_def(db, input_def_file_name) chip = db.getChip() tech = db.getTech() block = chip.getBlock() r = block.getCoreArea() print(r.dx() / tech.getDbUnitsPerMicron(), r.dy() / tech.getDbUnitsPerMicron())
) == ground_port_name: gnd_ports.append(port) return (vdd_ports, gnd_ports) def find_power_ground_port(port_name, ports): for port in ports: if port.getName() == port_name: return port return None db = odb.dbDatabase.create() odb.read_lef(db, lef_file_name) odb.read_def(db, def_file_name) chip = db.getChip() block = chip.getBlock() design_name = block.getName() print("Top-level design name:", design_name) VDD_PORTS, GND_PORTS = get_power_ground_ports(block.getBTerms()) assert VDD_PORTS and GND_PORTS, "No power ports found at the top-level. "\ "Make sure that they exist and have the USE POWER|GROUND property or "\ "they match the arguments specified with --power-port and --ground-port." DEFAULT_VDD = VDD_PORTS[0].getNet() DEFAULT_GND = GND_PORTS[0].getNet()
print("STDERR:") print(output[1].strip()) print("openroad exit code:", p.returncode) assert p.returncode == 0, p.returncode # TODO: check for errors else: assert def_netlist is not None working_def = def_netlist assert os.path.exists(working_def), "DEF file doesn't exist" db_top = odb.dbDatabase.create() # odb.read_db(db_top, f"{design}.pf.db") for lef in lefs: odb.read_lef(db_top, lef) odb.read_def(db_top, working_def) chip_top = db_top.getChip() block_top = chip_top.getBlock() top_design_name = block_top.getName() print("Top-level design name:", top_design_name) ## Step 2: create a simple data structure with pads from the library # types: corner, power, other pads = {} libs = db_top.getLibs() for lib in libs: masters = lib.getMasters() for m in masters: name = m.getName()
def replace_pins(output_def, input_lef, logpath, source_def, template_def): # -------------------------------- # 0. Sanity check: Check for all defs and lefs to exist # I removed the output def to NOT exist check, as it was making testing harder # -------------------------------- if not os.path.isfile(input_lef): print("LEF file ", input_lef, " not found") raise FileNotFoundError if not os.path.isfile(source_def): print("First DEF file ", source_def, " not found") raise FileNotFoundError if not os.path.isfile(template_def): print("Template DEF file ", template_def, " not found") raise FileNotFoundError if logpath is None: logfile = sys.stdout else: logfile = open(logpath, "w+") # -------------------------------- # 1. Copy the one def to second # -------------------------------- print("[defutil.py:replace_pins] Creating output DEF based on first DEF", file=logfile) shutil.copy(source_def, output_def) # -------------------------------- # 2. Find list of all bterms in first def # -------------------------------- source_db = odb.dbDatabase.create() odb.read_lef(source_db, input_lef) odb.read_def(source_db, source_def) source_bterms = source_db.getChip().getBlock().getBTerms() manufacturing_grid = source_db.getTech().getManufacturingGrid() dbu_per_microns = source_db.getTech().getDbUnitsPerMicron() print( "Using manufacturing grid:", manufacturing_grid, "Using dbu per mircons: ", dbu_per_microns, file=logfile, ) all_bterm_names = set() for source_bterm in source_bterms: source_name = source_bterm.getName() # TODO: Check for pin name matches net name # print("Bterm", source_name, "is declared as", source_bterm.getSigType()) # -------------------------------- # 3. Check no bterms should be marked as power, because it is assumed that caller already removed them # -------------------------------- if (source_bterm.getSigType() == "POWER") or (source_bterm.getSigType() == "GROUND"): print( "Bterm", source_name, "is declared as", source_bterm.getSigType(), "ignoring it", file=logfile, ) continue all_bterm_names.add(source_name) print( "[defutil.py:replace_pins] Found", len(all_bterm_names), "block terminals in first def", file=logfile, ) # -------------------------------- # 4. Read the template def # -------------------------------- template_db = odb.dbDatabase.create() odb.read_lef(template_db, input_lef) odb.read_def(template_db, template_def) template_bterms = template_db.getChip().getBlock().getBTerms() assert (source_db.getTech().getManufacturingGrid() == template_db.getTech().getManufacturingGrid()) assert (source_db.getTech().getDbUnitsPerMicron() == template_db.getTech().getDbUnitsPerMicron()) # -------------------------------- # 5. Create a dict with net -> pin location. Check for only one pin location to exist, overwise return an error # -------------------------------- template_bterm_locations = dict() for template_bterm in template_bterms: template_name = template_bterm.getName() template_pins = template_bterm.getBPins() # TODO: Check for pin name matches net name for template_pin in template_pins: boxes = template_pin.getBoxes() for box in boxes: layer = box.getTechLayer().getName() if template_name not in template_bterm_locations: template_bterm_locations[template_name] = [] template_bterm_locations[template_name].append(( layer, box.xMin(), box.yMin(), box.xMax(), box.yMax(), )) print( "[defutil.py:replace_pins] Found template_bterms: ", len(template_bterm_locations), file=logfile, ) for template_bterm_name in template_bterm_locations: print( template_bterm_name, ": ", template_bterm_locations[template_bterm_name], file=logfile, ) # -------------------------------- # 6. Modify the pins in out def, according to dict # -------------------------------- output_db = odb.dbDatabase.create() odb.read_lef(output_db, input_lef) odb.read_def(output_db, output_def) output_tech = output_db.getTech() output_block = output_db.getChip().getBlock() output_bterms = output_block.getBTerms() grid_errors = False for output_bterm in output_bterms: name = output_bterm.getName() output_bpins = output_bterm.getBPins() if name in template_bterm_locations and name in all_bterm_names: for output_bpin in output_bpins: odb.dbBPin.destroy(output_bpin) for template_bterm_location_tuple in template_bterm_locations[ name]: layer = output_tech.findLayer(template_bterm_location_tuple[0]) # -------------------------------- # 6.2 Create new pin # -------------------------------- output_new_bpin = odb.dbBPin.create(output_bterm) print( "For:", name, "Wrote on layer:", layer.getName(), "coordinates: ", template_bterm_location_tuple[1], template_bterm_location_tuple[2], template_bterm_location_tuple[3], template_bterm_location_tuple[4], file=logfile, ) grid_errors = (check_pin_grid( manufacturing_grid, dbu_per_microns, name, template_bterm_location_tuple[1], logfile, ) or grid_errors) grid_errors = (check_pin_grid( manufacturing_grid, dbu_per_microns, name, template_bterm_location_tuple[2], logfile, ) or grid_errors) grid_errors = (check_pin_grid( manufacturing_grid, dbu_per_microns, name, template_bterm_location_tuple[3], logfile, ) or grid_errors) grid_errors = (check_pin_grid( manufacturing_grid, dbu_per_microns, name, template_bterm_location_tuple[4], logfile, ) or grid_errors) odb.dbBox.create( output_new_bpin, layer, template_bterm_location_tuple[1], template_bterm_location_tuple[2], template_bterm_location_tuple[3], template_bterm_location_tuple[4], ) output_new_bpin.setPlacementStatus("PLACED") else: print( "[defutil.py:replace_pins] Not found", name, "in template def, but found in output def. Leaving as-is", file=logfile, ) if grid_errors: sys.exit("[ERROR]: Grid errors happened. Check log for grid errors.") # -------------------------------- # 7. Write back the output def # -------------------------------- print("[defutil.py:replace_pins] Writing output def to: ", output_def, file=logfile) assert odb.write_def(output_block, output_def) == 1
def cli( input_lef, output_def, config, ver_layer, hor_layer, ver_width_mult, hor_width_mult, length, hor_extension, ver_extension, reverse, bus_sort, input_def, ): """ Places the IOs in an input def with an optional config file that supports regexes. Config format: #N|#S|#E|#W pin1_regex (low co-ordinates to high co-ordinates; e.g., bottom to top and left to right) pin2_regex ... #S|#N|#E|#W """ def_file_name = input_def lef_file_name = input_lef output_def_file_name = output_def config_file_name = config bus_sort_flag = bus_sort h_layer_name = hor_layer v_layer_name = ver_layer h_width_mult = float(hor_width_mult) v_width_mult = float(ver_width_mult) # Initialize OpenDB db_top = odb.dbDatabase.create() odb.read_lef(db_top, lef_file_name) odb.read_def(db_top, def_file_name) block = db_top.getChip().getBlock() micron_in_units = block.getDefUnits() LENGTH = int(micron_in_units * length) H_EXTENSION = int(micron_in_units * hor_extension) V_EXTENSION = int(micron_in_units * ver_extension) if H_EXTENSION < 0: H_EXTENSION = 0 if V_EXTENSION < 0: V_EXTENSION = 0 reverse_arr_raw = reverse.split(",") reverse_arr = [] for element in reverse_arr_raw: if element.strip() != "": reverse_arr.append(f"#{element}") def getGrid(origin, count, step): tracks = [] pos = origin for i in range(count): tracks.append(pos) pos += step assert len(tracks) > 0 tracks.sort() return tracks def equallySpacedSeq(m, arr): seq = [] n = len(arr) # Bresenham indices = [i * n // m + n // (2 * m) for i in range(m)] for i in indices: seq.append(arr[i]) return seq # HUMAN SORTING: https://stackoverflow.com/questions/5967500/how-to-correctly-sort-a-string-with-a-number-inside def natural_keys(enum): def atof(text): try: retval = float(text) except ValueError: retval = text return retval text = enum[0] text = re.sub(r"(\[|\]|\.|\$)", "", text) """ alist.sort(key=natural_keys) sorts in human order http://nedbatchelder.com/blog/200712/human_sorting.html (see toothy's implementation in the comments) float regex comes from https://stackoverflow.com/a/12643073/190597 """ return [ atof(c) for c in re.split(r"[+-]?([0-9]+(?:[.][0-9]*)?|[.][0-9]+)", text) ] def bus_keys(enum): text = enum[0] m = re.match(r"^.*\[(\d+)\]$", text) if not m: return -1 else: return int(m.group(1)) # read config pin_placement_cfg = {"#N": [], "#E": [], "#S": [], "#W": []} cur_side = None if config_file_name is not None and config_file_name != "": with open(config_file_name, "r") as config_file: for line in config_file: line = line.split() if len(line) == 0: continue if len(line) > 1: print("Only one entry allowed per line.") sys.exit(1) token = line[0] if cur_side is not None and token[0] != "#": pin_placement_cfg[cur_side].append(token) elif token not in [ "#N", "#E", "#S", "#W", "#NR", "#ER", "#SR", "#WR", "#BUS_SORT", ]: print( "Valid directives are #N, #E, #S, or #W. Append R for reversing the default order.", "Use #BUS_SORT to group 'bus bits' by index.", "Please make sure you have set a valid side first before listing pins", ) sys.exit(1) elif token == "#BUS_SORT": bus_sort_flag = True else: if len(token) == 3: token = token[0:2] reverse_arr.append(token) cur_side = token # build a list of pins chip_top = db_top.getChip() block_top = chip_top.getBlock() top_design_name = block_top.getName() tech = db_top.getTech() H_LAYER = tech.findLayer(h_layer_name) V_LAYER = tech.findLayer(v_layer_name) H_WIDTH = int(h_width_mult * H_LAYER.getWidth()) V_WIDTH = int(v_width_mult * V_LAYER.getWidth()) print("Top-level design name:", top_design_name) bterms = block_top.getBTerms() bterms_enum = [] for bterm in bterms: pin_name = bterm.getName() bterms_enum.append((pin_name, bterm)) # sort them "humanly" bterms_enum.sort(key=natural_keys) if bus_sort_flag: bterms_enum.sort(key=bus_keys) bterms = [bterm[1] for bterm in bterms_enum] pin_placement = {"#N": [], "#E": [], "#S": [], "#W": []} bterm_regex_map = {} for side in pin_placement_cfg: for regex in pin_placement_cfg[side]: # going through them in order regex += "$" # anchor for bterm in bterms: # if a pin name matches multiple regexes, their order will be # arbitrary. More refinement requires more strict regexes (or just # the exact pin name). pin_name = bterm.getName() if re.match(regex, pin_name) is not None: if bterm in bterm_regex_map: print( "Error: Multiple regexes matched", pin_name, ". Those are", bterm_regex_map[bterm], "and", regex, ) sys.exit(os.EX_DATAERR) bterm_regex_map[bterm] = regex pin_placement[side].append(bterm) # to maintain the order unmatched_bterms = [bterm for bterm in bterms if bterm not in bterm_regex_map] if len(unmatched_bterms) > 0: print("Warning: Some pins weren't matched by the config file") print("Those are:", [bterm.getName() for bterm in unmatched_bterms]) if True: print("Assigning random sides to the above pins") for bterm in unmatched_bterms: random_side = random.choice(list(pin_placement.keys())) pin_placement[random_side].append(bterm) else: sys.exit(1) assert len(block_top.getBTerms()) == len( pin_placement["#N"] + pin_placement["#E"] + pin_placement["#S"] + pin_placement["#W"] ) # generate slots DIE_AREA = block_top.getDieArea() BLOCK_LL_X = DIE_AREA.xMin() BLOCK_LL_Y = DIE_AREA.yMin() BLOCK_UR_X = DIE_AREA.xMax() BLOCK_UR_Y = DIE_AREA.yMax() print("Block boundaries:", BLOCK_LL_X, BLOCK_LL_Y, BLOCK_UR_X, BLOCK_UR_Y) origin, count, step = block_top.findTrackGrid(H_LAYER).getGridPatternY(0) h_tracks = getGrid(origin, count, step) origin, count, step = block_top.findTrackGrid(V_LAYER).getGridPatternX(0) v_tracks = getGrid(origin, count, step) for rev in reverse_arr: pin_placement[rev].reverse() # create the pins for side in pin_placement: if side in ["#N", "#S"]: slots = equallySpacedSeq(len(pin_placement[side]), v_tracks) else: slots = equallySpacedSeq(len(pin_placement[side]), h_tracks) assert len(slots) == len(pin_placement[side]) for i in range(len(pin_placement[side])): bterm = pin_placement[side][i] slot = slots[i] pin_name = bterm.getName() pins = bterm.getBPins() if len(pins) > 0: print("Warning:", pin_name, "already has shapes. Modifying them") assert len(pins) == 1 pin_bpin = pins[0] else: pin_bpin = odb.dbBPin_create(bterm) pin_bpin.setPlacementStatus("PLACED") if side in ["#N", "#S"]: rect = odb.Rect(0, 0, V_WIDTH, LENGTH + V_EXTENSION) if side == "#N": y = BLOCK_UR_Y - LENGTH else: y = BLOCK_LL_Y - V_EXTENSION rect.moveTo(slot - V_WIDTH // 2, y) odb.dbBox_create(pin_bpin, V_LAYER, *rect.ll(), *rect.ur()) else: rect = odb.Rect(0, 0, LENGTH + H_EXTENSION, H_WIDTH) if side == "#E": x = BLOCK_UR_X - LENGTH else: x = BLOCK_LL_X - H_EXTENSION rect.moveTo(x, slot - H_WIDTH // 2) odb.dbBox_create(pin_bpin, H_LAYER, *rect.ll(), *rect.ur()) print( f"Writing {output_def_file_name}...", ) odb.write_def(block_top, output_def_file_name)
}, ] else: gnd_pad_pin_map = [{ "pad_pin": mapping[0], "pad_name_substr": mapping[1] } for mapping in gnd_pad_pin_map] SPECIAL_NETS[VDD_NET_NAME]["map"] = vdd_pad_pin_map SPECIAL_NETS[GND_NET_NAME]["map"] = gnd_pad_pin_map ################## db_top = odb.dbDatabase.create() odb.read_lef(db_top, lef_file_name) odb.read_def(db_top, def_file_name) chip_top = db_top.getChip() block_top = chip_top.getBlock() top_design_name = block_top.getName() tech = db_top.getTech() via_rules = tech.getViaGenerateRules() print("Found", len(via_rules), "VIA GENERATE rules") # build dictionary of basic custom vias (ROW = COL = 1) custom_vias = {} for rule in via_rules: lower_rules = rule.getViaLayerRule(0) upper_rules = rule.getViaLayerRule(1) cut_rules = rule.getViaLayerRule(2)
def __init__(self, lef_in, def_in): self.db = odb.dbDatabase.create() self.lef = odb.read_lef(self.db, lef_in) self.df = odb.read_def(self.db, def_in) self.block = self.db.getChip().getBlock() self.insts = self.block.getInsts()