Exemple #1
0
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
Exemple #2
0
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
Exemple #3
0
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)
Exemple #4
0
 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()
Exemple #5
0
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)
Exemple #6
0
    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()
Exemple #7
0
                    "-o",
                    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()
Exemple #8
0
    "--port-protect",
    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(
Exemple #9
0
output_def_file_name = args.output

# in the tcl side
# top_lef_new_file_name = os.path.join(os.path.dirname(macro_lef_file_name), os.path.basename(macro_lef_file_name) + ".top.lef")
# 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()
Exemple #10
0
        boxes = getBiggestBox(pad_iterm)
    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:
Exemple #11
0
obses = obs_args.split(',')
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)
Exemple #12
0
# 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())
Exemple #13
0
        elif port.getSigType() == "GROUND" or port.getName(
        ) == 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()
Exemple #14
0
    print(output[0].strip())
    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:
Exemple #15
0
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
Exemple #16
0
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)
Exemple #17
0
            "pad_name_substr": "vssio"
        },
    ]
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)
Exemple #18
0
 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()