def process_pio_db(ddrg, device):
    piofile = path.join(database.get_db_root(), "ECP5", dev_names[device],
                        "iodb.json")
    with open(piofile, 'r') as f:
        piodb = json.load(f)
        for pkgname, pkgdata in sorted(piodb["packages"].items()):
            pins = []
            for name, pinloc in sorted(pkgdata.items()):
                x = pinloc["col"]
                y = pinloc["row"]
                loc = pytrellis.Location(x, y)
                pio = "PIO" + pinloc["pio"]
                bel_idx = get_bel_index(ddrg, loc, pio)
                if bel_idx is not None:
                    pins.append((name, loc, bel_idx))
            packages[pkgname] = pins
        for metaitem in piodb["pio_metadata"]:
            x = metaitem["col"]
            y = metaitem["row"]
            loc = pytrellis.Location(x, y)
            pio = "PIO" + metaitem["pio"]
            bank = metaitem["bank"]
            if "function" in metaitem:
                pinfunc = metaitem["function"]
            else:
                pinfunc = None
            bel_idx = get_bel_index(ddrg, loc, pio)
            if bel_idx is not None:
                pindata.append((loc, bel_idx, bank, pinfunc))
Esempio n. 2
0
def process_pio_db(rg, device):
    piofile = path.join(database.get_db_root(), "MachXO2", dev_names[device], "iodb.json")
    with open(piofile, 'r') as f:
        piodb = json.load(f)
        for pkgname, pkgdata in sorted(piodb["packages"].items()):
            pins = []
            for name, pinloc in sorted(pkgdata.items()):
                x = pinloc["col"]
                y = pinloc["row"]
                if x == 0 or x == max_col:
                    # FIXME: Oversight in read_pinout.py. We use 0-based
                    # columns for 0 and max row, but we otherwise extract
                    # the names from the CSV, and...
                    loc = pytrellis.Location(x, y)
                else:
                    # Lattice uses 1-based columns!
                    loc = pytrellis.Location(x - 1, y)
                pio = "PIO" + pinloc["pio"]
                bel_idx = get_bel_index(rg, loc, pio)
                if bel_idx is not None:
                    pins.append((name, loc, bel_idx))
            packages[pkgname] = pins
        for metaitem in piodb["pio_metadata"]:
            x = metaitem["col"]
            y = metaitem["row"]
            if x == 0 or x == max_col:
                loc = pytrellis.Location(x, y)
            else:
                loc = pytrellis.Location(x - 1, y)
            pio = "PIO" + metaitem["pio"]
            bank = metaitem["bank"]
            if "function" in metaitem:
                pinfunc = metaitem["function"]
            else:
                pinfunc = None
            dqs = -1
            if "dqs" in metaitem:
                pass
                # tdqs = metaitem["dqs"]
                # if tdqs[0] == "L":
                #     dqs = 0
                # elif tdqs[0] == "R":
                #     dqs = 2048
                # suffix_size = 0
                # while tdqs[-(suffix_size+1)].isdigit():
                #     suffix_size += 1
                # dqs |= int(tdqs[-suffix_size:])
            bel_idx = get_bel_index(rg, loc, pio)
            if bel_idx is not None:
                pindata.append((loc, bel_idx, bank, pinfunc, dqs))
Esempio n. 3
0
 def get_wire_name(arc_loctype, rel, idx):
     loc = loc_with_type[arc_loctype]
     lt = ddrg.typeAtLocation[pytrellis.Location(loc[0] + rel.x,
                                                 loc[1] + rel.y)]
     wire = ddrg.locationTypes[lt].wires[idx]
     return "R{}C{}_{}".format(loc[1] + rel.y, loc[0] + rel.x,
                               ddrg.to_str(wire.name))
Esempio n. 4
0
def process_pio_db(ddrg, device):
    piofile = path.join(database.get_db_root(), "ECP5", dev_names[device],
                        "iodb.json")
    with open(piofile, 'r') as f:
        piodb = json.load(f)
        for pkgname, pkgdata in sorted(piodb["packages"].items()):
            pins = []
            for name, pinloc in sorted(pkgdata.items()):
                x = pinloc["col"]
                y = pinloc["row"]
                loc = pytrellis.Location(x, y)
                pio = "PIO" + pinloc["pio"]
                bel_idx = get_bel_index(ddrg, loc, pio)
                if bel_idx is not None:
                    pins.append((name, loc, bel_idx))
            packages[pkgname] = pins
        for metaitem in piodb["pio_metadata"]:
            x = metaitem["col"]
            y = metaitem["row"]
            loc = pytrellis.Location(x, y)
            pio = "PIO" + metaitem["pio"]
            bank = metaitem["bank"]
            if "function" in metaitem:
                pinfunc = metaitem["function"]
            else:
                pinfunc = None
            dqs = -1
            if "dqs" in metaitem:
                tdqs = metaitem["dqs"]
                if tdqs[0] == "L":
                    dqs = 0
                elif tdqs[0] == "R":
                    dqs = 2048
                suffix_size = 0
                while tdqs[-(suffix_size + 1)].isdigit():
                    suffix_size += 1
                dqs |= int(tdqs[-suffix_size:])
            bel_idx = get_bel_index(ddrg, loc, pio)
            if bel_idx is not None:
                pindata.append((loc, bel_idx, bank, pinfunc, dqs))
Esempio n. 5
0
def make_tiles_by_loc(chip: pytrellis.Chip) -> TilesByLoc:
    tiles_by_loc: TilesByLoc = defaultdict(list)

    for tilename, tile in chip.tiles.items():
        locator = pytrellis.TileLocator(chip.info.family, chip.info.name,
                                        tile.info.type)
        tilebitdb = pytrellis.get_tile_bitdata(locator)
        tilecfg = tilebitdb.tile_cram_to_config(tile.cram)

        rc = tile.info.get_row_col()
        row, col = rc.first, rc.second
        tileloc = pytrellis.Location(col, row)

        tiles_by_loc[tileloc.x, tileloc.y].append(TileData(tile, tilecfg))

    return tiles_by_loc
Esempio n. 6
0
def write_database(dev_name, chip, ddrg, endianness):
    def write_loc(loc, sym_name):
        bba.u16(loc.x, "%s.x" % sym_name)
        bba.u16(loc.y, "%s.y" % sym_name)

    loctypes = list([_.key() for _ in ddrg.locationTypes])
    loc_with_type = {}
    for y in range(0, max_row+1):
        for x in range(0, max_col+1):
            loc_with_type[loctypes.index(ddrg.typeAtLocation[pytrellis.Location(x, y)])] = (x, y)

    def get_wire_name(arc_loctype, rel, idx):
        loc = loc_with_type[arc_loctype]
        lt = ddrg.typeAtLocation[pytrellis.Location(loc[0] + rel.x, loc[1] + rel.y)]
        wire = ddrg.locationTypes[lt].wires[idx]
        return "R{}C{}_{}".format(loc[1] + rel.y, loc[0] + rel.x, ddrg.to_str(wire.name))

    bba = BinaryBlobAssembler()
    bba.pre('#include "nextpnr.h"')
    bba.pre('#include "embed.h"')
    bba.pre('NEXTPNR_NAMESPACE_BEGIN')
    bba.post('EmbeddedFile chipdb_file_%s("ecp5/chipdb-%s.bin", chipdb_blob_%s);' % (dev_name, dev_name, dev_name))
    bba.post('NEXTPNR_NAMESPACE_END')
    bba.push("chipdb_blob_%s" % dev_name)
    bba.r("chip_info", "chip_info")


    for idx in range(len(loctypes)):
        loctype = ddrg.locationTypes[loctypes[idx]]
        if len(loctype.arcs) > 0:
            bba.l("loc%d_pips" % idx, "PipInfoPOD")
            for arc in loctype.arcs:
                write_loc(arc.srcWire.rel, "src")
                write_loc(arc.sinkWire.rel, "dst")
                bba.u32(arc.srcWire.id, "src_idx")
                bba.u32(arc.sinkWire.id, "dst_idx")
                src_name = get_wire_name(idx, arc.srcWire.rel, arc.srcWire.id)
                snk_name = get_wire_name(idx, arc.sinkWire.rel, arc.sinkWire.id)
                bba.u32(get_pip_class(src_name, snk_name), "timing_class")
                bba.u16(get_tiletype_index(ddrg.to_str(arc.tiletype)), "tile_type")
                cls = arc.cls
                if cls == 1 and "PCS" in snk_name or "DCU" in snk_name or "DCU" in src_name:
                   cls = 2
                bba.u8(cls, "pip_type")
                bba.u8(0, "padding")
        if len(loctype.wires) > 0:
            for wire_idx in range(len(loctype.wires)):
                wire = loctype.wires[wire_idx]
                if len(wire.arcsDownhill) > 0:
                    bba.l("loc%d_wire%d_downpips" % (idx, wire_idx), "PipLocatorPOD")
                    for dp in wire.arcsDownhill:
                        write_loc(dp.rel, "rel_loc")
                        bba.u32(dp.id, "index")
                if len(wire.arcsUphill) > 0:
                    bba.l("loc%d_wire%d_uppips" % (idx, wire_idx), "PipLocatorPOD")
                    for up in wire.arcsUphill:
                        write_loc(up.rel, "rel_loc")
                        bba.u32(up.id, "index")
                if len(wire.belPins) > 0:
                    bba.l("loc%d_wire%d_belpins" % (idx, wire_idx), "BelPortPOD")
                    for bp in wire.belPins:
                        write_loc(bp.bel.rel, "rel_bel_loc")
                        bba.u32(bp.bel.id, "bel_index")
                        bba.u32(constids[ddrg.to_str(bp.pin)], "port")
            bba.l("loc%d_wires" % idx, "WireInfoPOD")
            for wire_idx in range(len(loctype.wires)):
                wire = loctype.wires[wire_idx]
                bba.s(ddrg.to_str(wire.name), "name")
                bba.u32(constids[wire_type(ddrg.to_str(wire.name))], "type")
                if ("TILE_WIRE_" + ddrg.to_str(wire.name)) in gfx_wire_ids:
                    bba.u32(gfx_wire_ids["TILE_WIRE_" + ddrg.to_str(wire.name)], "tile_wire")
                else:
                    bba.u32(0, "tile_wire")
                bba.u32(len(wire.arcsUphill), "num_uphill")
                bba.u32(len(wire.arcsDownhill), "num_downhill")
                bba.r("loc%d_wire%d_uppips" % (idx, wire_idx) if len(wire.arcsUphill) > 0 else None, "pips_uphill")
                bba.r("loc%d_wire%d_downpips" % (idx, wire_idx) if len(wire.arcsDownhill) > 0 else None, "pips_downhill")
                bba.u32(len(wire.belPins), "num_bel_pins")
                bba.r("loc%d_wire%d_belpins" % (idx, wire_idx) if len(wire.belPins) > 0 else None, "bel_pins")

        if len(loctype.bels) > 0:
            for bel_idx in range(len(loctype.bels)):
                bel = loctype.bels[bel_idx]
                bba.l("loc%d_bel%d_wires" % (idx, bel_idx), "BelWirePOD")
                for pin in bel.wires:
                    write_loc(pin.wire.rel, "rel_wire_loc")
                    bba.u32(pin.wire.id, "wire_index")
                    bba.u32(constids[ddrg.to_str(pin.pin)], "port")
                    bba.u32(int(pin.dir), "dir")
            bba.l("loc%d_bels" % idx, "BelInfoPOD")
            for bel_idx in range(len(loctype.bels)):
                bel = loctype.bels[bel_idx]
                bba.s(ddrg.to_str(bel.name), "name")
                bba.u32(constids[ddrg.to_str(bel.type)], "type")
                bba.u32(bel.z, "z")
                bba.u32(len(bel.wires), "num_bel_wires")
                bba.r("loc%d_bel%d_wires" % (idx, bel_idx), "bel_wires")

    bba.l("locations", "LocationTypePOD")
    for idx in range(len(loctypes)):
        loctype = ddrg.locationTypes[loctypes[idx]]
        bba.u32(len(loctype.bels), "num_bels")
        bba.u32(len(loctype.wires), "num_wires")
        bba.u32(len(loctype.arcs), "num_pips")
        bba.r("loc%d_bels" % idx if len(loctype.bels) > 0 else None, "bel_data")
        bba.r("loc%d_wires" % idx if len(loctype.wires) > 0 else None, "wire_data")
        bba.r("loc%d_pips" % idx if len(loctype.arcs) > 0 else None, "pips_data")

    for y in range(0, max_row+1):
        for x in range(0, max_col+1):
            bba.l("tile_info_%d_%d" % (x, y), "TileNamePOD")
            for tile in chip.get_tiles_by_position(y, x):
                bba.s(tile.info.name, "name")
                bba.u16(get_tiletype_index(tile.info.type), "type_idx")
                bba.u16(0, "padding")

    bba.l("tiles_info", "TileInfoPOD")
    for y in range(0, max_row+1):
        for x in range(0, max_col+1):
            bba.u32(len(chip.get_tiles_by_position(y, x)), "num_tiles")
            bba.r("tile_info_%d_%d" % (x, y), "tile_names")

    bba.l("location_types", "int32_t")
    for y in range(0, max_row+1):
        for x in range(0, max_col+1):
            bba.u32(loctypes.index(ddrg.typeAtLocation[pytrellis.Location(x, y)]), "loctype")

    bba.l("location_glbinfo", "GlobalInfoPOD")
    for y in range(0, max_row+1):
        for x in range(0, max_col+1):
            bba.u16(global_data[x, y][2], "tap_col")
            bba.u8(global_data[x, y][1], "tap_dir")
            bba.u8(global_data[x, y][0], "quad")
            bba.u16(global_data[x, y][3][1], "spine_row")
            bba.u16(global_data[x, y][3][0], "spine_col")

    for package, pkgdata in sorted(packages.items()):
        bba.l("package_data_%s" % package, "PackagePinPOD")
        for pin in pkgdata:
            name, loc, bel_idx = pin
            bba.s(name, "name")
            write_loc(loc, "abs_loc")
            bba.u32(bel_idx, "bel_index")

    bba.l("package_data", "PackageInfoPOD")
    for package, pkgdata in sorted(packages.items()):
        bba.s(package, "name")
        bba.u32(len(pkgdata), "num_pins")
        bba.r("package_data_%s" % package, "pin_data")

    bba.l("pio_info", "PIOInfoPOD")
    for pin in pindata:
        loc, bel_idx, bank, func, dqs = pin
        write_loc(loc, "abs_loc")
        bba.u32(bel_idx, "bel_index")
        if func is not None and func != "WRITEN":
            bba.s(func, "function_name")
        else:
            bba.r(None, "function_name")
        bba.u16(bank, "bank")
        bba.u16(dqs, "dqsgroup")

    bba.l("tiletype_names", "RelPtr<char>")
    for tt, idx in sorted(tiletype_names.items(), key=lambda x: x[1]):
        bba.s(tt, "name")

    for grade in speed_grade_names:
        for cell in speed_grade_cells[grade]:
            celltype, delays, setupholds = cell
            if len(delays) > 0:
                bba.l("cell_%d_delays_%s" % (celltype, grade))
                for delay in delays:
                    from_pin, to_pin, min_delay, max_delay = delay
                    bba.u32(from_pin, "from_pin")
                    bba.u32(to_pin, "to_pin")
                    bba.u32(min_delay, "min_delay")
                    bba.u32(max_delay, "max_delay")
            if len(setupholds) > 0:
                bba.l("cell_%d_setupholds_%s" % (celltype, grade))
                for sh in setupholds:
                    pin, clock, min_setup, max_setup, min_hold, max_hold = sh
                    bba.u32(pin, "sig_port")
                    bba.u32(clock, "clock_port")
                    bba.u32(min_setup, "min_setup")
                    bba.u32(max_setup, "max_setup")
                    bba.u32(min_hold, "min_hold")
                    bba.u32(max_hold, "max_hold")
        bba.l("cell_timing_data_%s" % grade)
        for cell in speed_grade_cells[grade]:
            celltype, delays, setupholds = cell
            bba.u32(celltype, "cell_type")
            bba.u32(len(delays), "num_delays")
            bba.u32(len(setupholds), "num_setup_hold")
            bba.r("cell_%d_delays_%s" % (celltype, grade) if len(delays) > 0 else None, "delays")
            bba.r("cell_%d_setupholds_%s" % (celltype, grade) if len(delays) > 0 else None, "setupholds")
        bba.l("pip_timing_data_%s" % grade)
        for pipclass in speed_grade_pips[grade]:
            min_delay, max_delay, min_fanout, max_fanout = pipclass
            bba.u32(min_delay, "min_delay")
            bba.u32(max_delay, "max_delay")
            bba.u32(min_fanout, "min_fanout")
            bba.u32(max_fanout, "max_fanout")
    bba.l("speed_grade_data")
    for grade in speed_grade_names:
        bba.u32(len(speed_grade_cells[grade]), "num_cell_timings")
        bba.u32(len(speed_grade_pips[grade]), "num_pip_classes")
        bba.r("cell_timing_data_%s" % grade, "cell_timings")
        bba.r("pip_timing_data_%s" % grade, "pip_classes")

    bba.l("chip_info")
    bba.u32(max_col + 1, "width")
    bba.u32(max_row + 1, "height")
    bba.u32((max_col + 1) * (max_row + 1), "num_tiles")
    bba.u32(len(location_types), "num_location_types")
    bba.u32(len(packages), "num_packages")
    bba.u32(len(pindata), "num_pios")
    bba.u32(const_id_count, "const_id_count")

    bba.r("locations", "locations")
    bba.r("location_types", "location_type")
    bba.r("location_glbinfo", "location_glbinfo")
    bba.r("tiletype_names", "tiletype_names")
    bba.r("package_data", "package_info")
    bba.r("pio_info", "pio_info")
    bba.r("tiles_info", "tile_info")
    bba.r("speed_grade_data", "speed_grades")

    bba.pop()
    return bba
Esempio n. 7
0
 def loc(self) -> pytrellis.Location:
     return pytrellis.Location(self.x, self.y)
Esempio n. 8
0
def gen_config_graph(chip: pytrellis.Chip, rgraph: pytrellis.RoutingGraph,
                     tiles_by_loc: TilesByLoc) -> ConnectionGraph:
    @lru_cache(None)
    def get_zero_bit_arcs(chip: pytrellis.Chip,
                          tiletype: str) -> Dict[str, List[str]]:
        """Get configurable zero-bit arcs from the given tile.

        tile_cram_to_config ignores zero-bit arcs when generating the TileConfig,
        which means that if all bits are unset for a given mux, no connection is
        generated at all."""
        locator = pytrellis.TileLocator(chip.info.family, chip.info.name,
                                        tiletype)
        tilebitdb = pytrellis.get_tile_bitdata(locator)
        arcs: Dict[str, List[str]] = defaultdict(list)
        for sink in tilebitdb.get_sinks():
            mux_data = tilebitdb.get_mux_data_for_sink(sink)
            for arc_name, arc_data in mux_data.arcs.items():
                if len(arc_data.bits.bits) == 0:
                    arcs[sink].append(arc_name)
        return arcs

    def bel_to_node(pos: Tuple[pytrellis.RoutingId, int]) -> Node:
        rid, bel_pin = pos
        id = Ident.from_id(rgraph, rid.id)
        pin = Ident.from_id(rgraph, bel_pin)
        return Node(x=rid.loc.x, y=rid.loc.y, id=id, pin=pin)

    def wire_to_node(rid: pytrellis.RoutingId) -> Node:
        id = Ident.from_id(rgraph, rid.id)
        return Node(x=rid.loc.x, y=rid.loc.y, id=id)

    def _get_enum_value(cfg: pytrellis.TileConfig,
                        enum_name: str) -> Optional[str]:
        for cenum in cfg.cenums:
            if cenum.name == enum_name:
                return cenum.value
        return None

    def _filter_data_pin(node: Node) -> bool:
        # IOLOGIC[AC].[RT]XDATA[456] are mutually exclusive with IOLOGIC[BD].[RT]XDATA[0123],
        # depending on whether 7:1 gearing is used, becacuse 7:1 gearing occupies two adjacent
        # IOLOGIC units (A+B or C+D). Because they're mutually exclusive, some of the pins are
        # hardwired together (e.g. 4A and 0B). To avoid a multi-root situation and spurious
        # inputs/outputs, we need to pick which set to include based on the IO configuration.

        bel_id = node.mod_name[-1]
        assert bel_id in "ABCD"
        pin_id = node.pin_name[-1]
        assert pin_id in "0123456"

        if bel_id in "AC" and pin_id in "0123":
            # These pins are unconflicted
            return True

        if bel_id in "AB":
            tiles = tiles_by_loc[node.x, node.y]
            main_mod = "IOLOGICA"
        else:
            # HACK: The IOLOGICC enums seem to be the PIC[LR]2 tiles,
            # which appear to always be exactly two tiles down from
            # the PIC[LR]0 tiles where the actual pins are.
            # This seems very fragile.
            tiles = tiles_by_loc[node.x, node.y + 2]
            main_mod = "IOLOGICC"

        # Make sure we get the right tile on the tile location
        for tiledata in tiles:
            if any(site.type == main_mod for site in tiledata.tile.info.sites):
                break
        else:
            print("error: could not locate IOLOGIC enums", file=sys.stderr)
            return True

        if node.pin_name.startswith("RX"):
            is_71_mode = _get_enum_value(tiledata.cfg,
                                         main_mod + "IDDRXN.MODE") == "IDDR71"
        else:
            is_71_mode = _get_enum_value(tiledata.cfg,
                                         main_mod + "ODDRXN.MODE") == "ODDR71"

        # Note that [456][BD] do not exist.
        if pin_id in "456" and is_71_mode:
            return True
        elif pin_id in "0123" and not is_71_mode:
            return True
        return False

    def add_edge(graph: ConnectionGraph, sourcenode: Node,
                 sinknode: Node) -> None:
        """ Add an edge subject to special-case filtering """

        if re.match(r"^F[5X][ABCD]_SLICE$", sourcenode.name) and re.match(
                r"^F\d$", sinknode.name):
            # Some of the -> Fn muxes use the same bits as the CCU2.INJECT enums.
            # In CCU2 mode, these muxes should be fixed to Fn_SLICE -> Fn, and should
            # not be set to F[5X] -> Fn no matter what the value of the mux bits are
            # (since they represent CCU2_INJECT instead)
            enum_name = f"SLICE{sourcenode.name[2]}.MODE"
            for tiledata in tiles_by_loc[sourcenode.x, sinknode.y]:
                if tiledata.tile.info.type.startswith(
                        "PLC2") and _get_enum_value(tiledata.cfg,
                                                    enum_name) == "CCU2":
                    # CCU2: correct F[5X]n_SLICE connection to Fn_SLICE -> Fn
                    newsource = Ident.from_label(rgraph,
                                                 sinknode.name + "_SLICE")
                    sourcenode = Node(x=sourcenode.x,
                                      y=sourcenode.y,
                                      id=newsource)
                    break
        elif sourcenode.pin_name.startswith(
                "RXDATA") and not _filter_data_pin(sourcenode):
            # See comment in _filter_data_pin
            return
        elif sinknode.pin_name.startswith(
                "TXDATA") and not _filter_data_pin(sinknode):
            # See comment in _filter_data_pin
            return

        graph.add_edge(sourcenode, sinknode)

    config_graph = ConnectionGraph()

    for loc in tiles_by_loc:
        rtile = rgraph.tiles[pytrellis.Location(loc[0], loc[1])]
        for tiledata in tiles_by_loc[loc]:
            tile = tiledata.tile
            for arc in tiledata.cfg.carcs:
                rarc = rtile.arcs[rgraph.ident(f"{arc.source}->{arc.sink}")]
                sourcenode = wire_to_node(rarc.source)
                sinknode = wire_to_node(rarc.sink)
                add_edge(config_graph, sourcenode, sinknode)

    # Expand configuration arcs to include BEL connections and zero-bit arcs
    arc_graph = ConnectionGraph()
    nodes_seen: Set[Node] = set()

    def visit_node(node: Node, bel_func: Callable[[Node], None]) -> None:
        """ Add unconfigurable or implicit arcs to the given node """
        if node in nodes_seen:
            return
        nodes_seen.add(node)

        try:
            rtile = rgraph.tiles[node.loc]
            rwire = rtile.wires[node.id.id]
        except KeyError:
            # there's a handful of troublesome cases which are outside of my control.
            # Example: R0C31_G_ULDDRDEL does not exist; it's actually supposed to be the "fixed"
            # connection G_ULDDRDEL=>DDRDEL but G_ULDDRDEL is not in the same tile.
            print(f"Error: failed to find node {str(node)}", file=sys.stderr)
            return

        if node not in config_graph.edges_rev:
            # Not configured - possible zero-bit configuration
            for tiledata in tiles_by_loc[node.x, node.y]:
                arcs = get_zero_bit_arcs(chip, tiledata.tile.info.type)
                sources = arcs.get(node.id.label, [])
                if not sources:
                    continue
                for source in sources:
                    sourceid = Ident.from_label(rgraph, source)
                    sourcenode = Node(x=node.x, y=node.y, id=sourceid)
                    add_edge(arc_graph, sourcenode, node)
                    visit_node(sourcenode, bel_func)

        # Add fixed connections
        for bel in rwire.belsUphill:
            add_edge(arc_graph, bel_to_node(bel), node)
            bel_func(wire_to_node(bel[0]))
        for bel in rwire.belsDownhill:
            add_edge(arc_graph, node, bel_to_node(bel))
            bel_func(wire_to_node(bel[0]))
        for routes in [rwire.uphill, rwire.downhill]:
            for rarcrid in routes:
                rarcname = rgraph.to_str(rarcrid.id)
                if "=>" in rarcname:
                    # => means a fixed (unconfigurable) connection
                    rarc = rgraph.tiles[rarcrid.loc].arcs[rarcrid.id]
                    sourcenode = wire_to_node(rarc.source)
                    sinknode = wire_to_node(rarc.sink)
                    add_edge(arc_graph, sourcenode, sinknode)
                    visit_node(sourcenode, bel_func)
                    visit_node(sinknode, bel_func)

        # Add global (clock) connections - Project Trellis omits a lot of these :(
        if node.name.startswith("G_HPBX"):
            # TAP_DRIVE -> PLB tile
            tap = chip.global_data.get_tap_driver(node.y, node.x)
            if tap.dir == pytrellis.TapDir.LEFT:
                tap_name = node.name.replace("G_HPBX", "L_HPBX")
            else:
                tap_name = node.name.replace("G_HPBX", "R_HPBX")
            tap_id = Ident.from_label(rgraph, tap_name)
            tap_node = Node(x=tap.col, y=node.y, id=tap_id)
            add_edge(arc_graph, tap_node, node)
            visit_node(tap_node, bel_func)

        elif node.name.startswith("G_VPTX"):
            # Spine tile -> TAP_DRIVE
            tap = chip.global_data.get_tap_driver(node.y, node.x)
            if tap.col == node.x:
                # Spine output
                quadrant = chip.global_data.get_quadrant(node.y, node.x)
                spine = chip.global_data.get_spine_driver(quadrant, node.x)
                spine_node = Node(x=spine.second, y=spine.first, id=node.id)
                add_edge(arc_graph, spine_node, node)
                visit_node(spine_node, bel_func)

        elif node.name.startswith("G_HPRX"):
            # Center mux -> spine tile (qqPCLKn -> G_HPRXnn00)
            quadrant = chip.global_data.get_quadrant(node.y, node.x)
            assert node.name.endswith("00")
            clkid = int(node.name[6:-2])
            global_id = Ident.from_label(rgraph, f"G_{quadrant}PCLK{clkid}")
            global_node = Node(x=0, y=0, id=global_id)
            add_edge(arc_graph, global_node, node)
            visit_node(global_node, bel_func)

    # Visit every configured arc and record all BELs seen
    bels_todo: Set[Node] = set()
    for sourcenode, nodes in config_graph.edges_fwd.items():
        for sinknode in nodes:
            add_edge(arc_graph, sourcenode, sinknode)
            visit_node(sourcenode, bels_todo.add)
            visit_node(sinknode, bels_todo.add)

    # Adding *every* fixed connection is too expensive.
    # As a compromise, add any fixed connection connected
    # to used BELs. Ignore BELs that don't have any configured
    # arcs.
    for node in bels_todo:
        rtile = rgraph.tiles[node.loc]
        for _, rwire in rtile.wires.items():
            wireident = Ident.from_id(rgraph, rwire.id)
            wirenode = Node(x=node.x, y=node.y, id=wireident)
            for bel in rwire.belsUphill:
                if bel[0].id == node.id.id:
                    add_edge(arc_graph, bel_to_node(bel), wirenode)
                    visit_node(wirenode, lambda node: None)
            for bel in rwire.belsDownhill:
                if bel[0].id == node.id.id:
                    add_edge(arc_graph, wirenode, bel_to_node(bel))
                    visit_node(wirenode, lambda node: None)

    return arc_graph
def write_database(dev_name, chip, ddrg, endianness):
    def write_loc(loc, sym_name):
        bba.u16(loc.x, "%s.x" % sym_name)
        bba.u16(loc.y, "%s.y" % sym_name)

    bba = BinaryBlobAssembler()
    bba.pre('#include "nextpnr.h"')
    bba.pre('NEXTPNR_NAMESPACE_BEGIN')
    bba.post('NEXTPNR_NAMESPACE_END')
    bba.push("chipdb_blob_%s" % dev_name)
    bba.r("chip_info", "chip_info")

    loctypes = list([_.key() for _ in ddrg.locationTypes])

    for idx in range(len(loctypes)):
        loctype = ddrg.locationTypes[loctypes[idx]]
        if len(loctype.arcs) > 0:
            bba.l("loc%d_pips" % idx, "PipInfoPOD")
            for arc in loctype.arcs:
                write_loc(arc.srcWire.rel, "src")
                write_loc(arc.sinkWire.rel, "dst")
                bba.u32(arc.srcWire.id, "src_idx")
                bba.u32(arc.sinkWire.id, "dst_idx")
                bba.u32(arc.delay, "delay")  # TODO:delay
                bba.u16(get_tiletype_index(ddrg.to_str(arc.tiletype)),
                        "tile_type")
                bba.u8(int(arc.cls), "pip_type")
                bba.u8(0, "padding")
        if len(loctype.wires) > 0:
            for wire_idx in range(len(loctype.wires)):
                wire = loctype.wires[wire_idx]
                if len(wire.arcsDownhill) > 0:
                    bba.l("loc%d_wire%d_downpips" % (idx, wire_idx),
                          "PipLocatorPOD")
                    for dp in wire.arcsDownhill:
                        write_loc(dp.rel, "rel_loc")
                        bba.u32(dp.id, "index")
                if len(wire.arcsUphill) > 0:
                    bba.l("loc%d_wire%d_uppips" % (idx, wire_idx),
                          "PipLocatorPOD")
                    for up in wire.arcsUphill:
                        write_loc(up.rel, "rel_loc")
                        bba.u32(up.id, "index")
                if len(wire.belPins) > 0:
                    bba.l("loc%d_wire%d_belpins" % (idx, wire_idx),
                          "BelPortPOD")
                    for bp in wire.belPins:
                        write_loc(bp.bel.rel, "rel_bel_loc")
                        bba.u32(bp.bel.id, "bel_index")
                        bba.u32(portpins[ddrg.to_str(bp.pin)], "port")
            bba.l("loc%d_wires" % idx, "WireInfoPOD")
            for wire_idx in range(len(loctype.wires)):
                wire = loctype.wires[wire_idx]
                bba.s(ddrg.to_str(wire.name), "name")
                bba.u32(len(wire.arcsUphill), "num_uphill")
                bba.u32(len(wire.arcsDownhill), "num_downhill")
                bba.r(
                    "loc%d_wire%d_uppips" %
                    (idx, wire_idx) if len(wire.arcsUphill) > 0 else None,
                    "pips_uphill")
                bba.r(
                    "loc%d_wire%d_downpips" %
                    (idx, wire_idx) if len(wire.arcsDownhill) > 0 else None,
                    "pips_downhill")
                bba.u32(len(wire.belPins), "num_bel_pins")
                bba.r(
                    "loc%d_wire%d_belpins" %
                    (idx, wire_idx) if len(wire.belPins) > 0 else None,
                    "bel_pins")

        if len(loctype.bels) > 0:
            for bel_idx in range(len(loctype.bels)):
                bel = loctype.bels[bel_idx]
                bba.l("loc%d_bel%d_wires" % (idx, bel_idx), "BelWirePOD")
                for pin in bel.wires:
                    write_loc(pin.wire.rel, "rel_wire_loc")
                    bba.u32(pin.wire.id, "wire_index")
                    bba.u32(portpins[ddrg.to_str(pin.pin)], "port")
                    bba.u32(int(pin.dir), "dir")
            bba.l("loc%d_bels" % idx, "BelInfoPOD")
            for bel_idx in range(len(loctype.bels)):
                bel = loctype.bels[bel_idx]
                bba.s(ddrg.to_str(bel.name), "name")
                bba.u32(bel_types[ddrg.to_str(bel.type)], "type")
                bba.u32(bel.z, "z")
                bba.u32(len(bel.wires), "num_bel_wires")
                bba.r("loc%d_bel%d_wires" % (idx, bel_idx), "bel_wires")

    bba.l("locations", "LocationTypePOD")
    for idx in range(len(loctypes)):
        loctype = ddrg.locationTypes[loctypes[idx]]
        bba.u32(len(loctype.bels), "num_bels")
        bba.u32(len(loctype.wires), "num_wires")
        bba.u32(len(loctype.arcs), "num_pips")
        bba.r("loc%d_bels" % idx if len(loctype.bels) > 0 else None,
              "bel_data")
        bba.r("loc%d_wires" % idx if len(loctype.wires) > 0 else None,
              "wire_data")
        bba.r("loc%d_pips" % idx if len(loctype.arcs) > 0 else None,
              "pips_data")

    for y in range(0, max_row + 1):
        for x in range(0, max_col + 1):
            bba.l("tile_info_%d_%d" % (x, y), "TileNamePOD")
            for tile in chip.get_tiles_by_position(y, x):
                bba.s(tile.info.name, "name")
                bba.u16(get_tiletype_index(tile.info.type), "type_idx")
                bba.u16(0, "padding")

    bba.l("tiles_info", "TileInfoPOD")
    for y in range(0, max_row + 1):
        for x in range(0, max_col + 1):
            bba.u32(len(chip.get_tiles_by_position(y, x)), "num_tiles")
            bba.r("tile_info_%d_%d" % (x, y), "tile_names")

    bba.l("location_types", "int32_t")
    for y in range(0, max_row + 1):
        for x in range(0, max_col + 1):
            bba.u32(
                loctypes.index(ddrg.typeAtLocation[pytrellis.Location(x, y)]),
                "loctype")

    bba.l("location_glbinfo", "GlobalInfoPOD")
    for y in range(0, max_row + 1):
        for x in range(0, max_col + 1):
            bba.u16(global_data[x, y][2], "tap_col")
            bba.u8(global_data[x, y][1], "tap_dir")
            bba.u8(global_data[x, y][0], "quad")

    for package, pkgdata in sorted(packages.items()):
        bba.l("package_data_%s" % package, "PackagePinPOD")
        for pin in pkgdata:
            name, loc, bel_idx = pin
            bba.s(name, "name")
            write_loc(loc, "abs_loc")
            bba.u32(bel_idx, "bel_index")

    bba.l("package_data", "PackageInfoPOD")
    for package, pkgdata in sorted(packages.items()):
        bba.s(package, "name")
        bba.u32(len(pkgdata), "num_pins")
        bba.r("package_data_%s" % package, "pin_data")

    bba.l("pio_info", "PIOInfoPOD")
    for pin in pindata:
        loc, bel_idx, bank, func = pin
        write_loc(loc, "abs_loc")
        bba.u32(bel_idx, "bel_index")
        if func is not None:
            bba.s(func, "function_name")
        else:
            bba.r(None, "function_name")
        bba.u16(bank, "bank")
        bba.u16(0, "padding")

    bba.l("tiletype_names", "RelPtr<char>")
    for tt, idx in sorted(tiletype_names.items(), key=lambda x: x[1]):
        bba.s(tt, "name")

    bba.l("chip_info")
    bba.u32(max_col + 1, "width")
    bba.u32(max_row + 1, "height")
    bba.u32((max_col + 1) * (max_row + 1), "num_tiles")
    bba.u32(len(location_types), "num_location_types")
    bba.u32(len(packages), "num_packages")
    bba.u32(len(pindata), "num_pios")

    bba.r("locations", "locations")
    bba.r("location_types", "location_type")
    bba.r("location_glbinfo", "location_glbinfo")
    bba.r("tiletype_names", "tiletype_names")
    bba.r("package_data", "package_info")
    bba.r("pio_info", "pio_info")
    bba.r("tiles_info", "tile_info")

    bba.pop()
    return bba
Esempio n. 10
0
import pytrellis
import database

pytrellis.load_database(database.get_db_root())
chip = pytrellis.Chip("LFE5U-12F")
graph = chip.get_routing_graph()
tile = graph.tiles[pytrellis.Location(12, 6)]


def rid_to_arc(routingId):
    return graph.tiles[routingId.loc].arcs[routingId.id]


def rid_to_wire(routingId):
    return graph.tiles[routingId.loc].wires[routingId.id]


def rid_to_bel(bel):
    return graph.tiles[bel.loc].bels[bel.id]


routingBelIds = dict()
routingPortIds = dict()
routingArcIds = dict()
routingWiresIds = dict()
foreignRoutingWiresIds = dict()
counter = 0

toBeMatched = set()
for arc in [
        x.data() for x in tile.arcs if x.data().source.loc == tile.loc and (
Esempio n. 11
0
#!/usr/bin/env python3
"""
Testing the routing graph generator
"""
import pytrellis
import sys

pytrellis.load_database("../../database")
chip = pytrellis.Chip("LFE5U-45F")
rg = chip.get_routing_graph()
tile = rg.tiles[pytrellis.Location(9, 71)]
for wire in tile.wires:
    print("Wire {}:".format(rg.to_str(wire.key())))
    for dh in wire.data().downhill:
        arc = rg.tiles[dh.loc].arcs[dh.id]
        print("     --> R{}C{}_{}".format(arc.sink.loc.y, arc.sink.loc.x,
                                          rg.to_str(arc.sink.id)))
    for bdh in wire.data().belsDownhill:
        print("     ->| R{}C{}_{}.{}".format(bdh.bel.loc.y, bdh.bel.loc.x,
                                             rg.to_str(bdh.bel.id),
                                             rg.to_str(bdh.pin)))
    print()
    for uh in wire.data().uphill:
        arc = rg.tiles[uh.loc].arcs[uh.id]
        print("     <-- R{}C{}_{}".format(arc.source.loc.y, arc.source.loc.x,
                                          rg.to_str(arc.source.id)))
    for buh in wire.data().belsUphill:
        print("     <-| R{}C{}_{}.{}".format(buh.bel.loc.y, buh.bel.loc.x,
                                             rg.to_str(buh.bel.id),
                                             rg.to_str(buh.pin)))
    print()