Ejemplo n.º 1
0
def main():
    parser = argparse.ArgumentParser(description=__doc__)

    parser.add_argument('--db_root', required=True)
    parser.add_argument('--part', required=True)
    parser.add_argument('--output_directory', required=True)
    parser.add_argument('--site_directory', required=True)
    parser.add_argument('--tile_type', required=True)
    parser.add_argument('--pb_types', required=True)
    parser.add_argument('--pin_assignments', required=True)

    args = parser.parse_args()

    with open(args.pin_assignments) as f:
        pin_assignments = json.load(f)

    db = prjxray.db.Database(args.db_root, args.part)
    tile_type = db.get_tile_type(args.tile_type)

    sites = {}

    pb_types = args.pb_types.split(',')

    equivalent_sites_dict = dict()
    for pb_type in pb_types:
        try:
            site, equivalent_sites = pb_type.split("/")
        except ValueError:
            site = pb_type
            equivalent_sites = None

        sites[site] = []

        equivalent_sites_dict[site] = equivalent_sites.split(
            ':') if equivalent_sites else []

    for site in tile_type.get_sites():
        if site.type not in sites.keys():
            continue

        site_type = db.get_site_type(site.type)
        input_wires, output_wires = get_wires(site, site_type)

        sites[site.type].append((site, input_wires, output_wires))

    tile_xml = start_heterogeneous_tile(
        args.tile_type,
        pin_assignments,
        sites,
        equivalent_sites_dict,
    )

    add_switchblock_locations(tile_xml)

    with open(
            '{}/{}.tile.xml'.format(args.output_directory,
                                    args.tile_type.lower()), 'w') as f:
        tile_str = ET.tostring(tile_xml, pretty_print=True).decode('utf-8')
        f.write(tile_str)
Ejemplo n.º 2
0
def main():
    parser = argparse.ArgumentParser(description=__doc__,
                                     fromfile_prefix_chars='@',
                                     prefix_chars='-~')

    parser.add_argument('--db_root', help="""Project X-Ray database to use.""")

    parser.add_argument('--part', help="""FPGA part to use.""")

    parser.add_argument('--site_type', help="""Site type to generate for""")

    parser.add_argument('--output-pb-type',
                        nargs='?',
                        type=argparse.FileType('w'),
                        default=sys.stdout,
                        help="""File to write the output too.""")

    parser.add_argument('--output-model',
                        nargs='?',
                        type=argparse.FileType('w'),
                        default=sys.stdout,
                        help="""File to write the output too.""")

    args = parser.parse_args()

    db = prjxray.db.Database(args.db_root, args.part)

    site_type = db.get_site_type(args.site_type.upper())

    pb_type_xml = ET.Element(
        'pb_type',
        {
            'name': 'DUMMY-{}'.format(args.site_type),
        },
    )

    for site_pin_name in site_type.get_site_pins():
        site_pin = site_type.get_site_pin(site_pin_name)
        if site_pin.direction == prjxray.site_type.SitePinDirection.IN:
            ET.SubElement(pb_type_xml, 'input', {
                'name': site_pin.name,
            })
        elif site_pin.direction == prjxray.site_type.SitePinDirection.OUT:
            ET.SubElement(pb_type_xml, 'output', {
                'name': site_pin.name,
            })
        else:
            assert False, site_pin

    pb_type_str = ET.tostring(pb_type_xml, pretty_print=True).decode('utf-8')
    args.output_pb_type.write(pb_type_str)
    args.output_pb_type.close()

    model_xml = ET.Element('models')

    model_str = ET.tostring(model_xml, pretty_print=True).decode('utf-8')
    args.output_model.write(model_str)
    args.output_model.close()
def initialize_edge_assignments(db, conn):
    """ Create initial edge_assignments map. """
    c = conn.cursor()
    c2 = conn.cursor()

    edge_assignments = {}
    wires_in_tile_types = set()

    # First find out which tile types were split during VPR grid formation.
    # These tile types should not get edge assignments directly, instead
    # their sites will get edge assignements.
    sites_as_tiles = set()
    split_tile_types = set()
    for site_pkey, tile_type_pkey in c.execute("""
        SELECT site_pkey, tile_type_pkey FROM site_as_tile;
        """):
        c2.execute("SELECT name FROM tile_type WHERE pkey = ?",
                   (tile_type_pkey, ))
        split_tile_types.add(c2.fetchone()[0])

        c2.execute(
            """
SELECT name FROM site_type WHERE pkey = (
    SELECT site_type_pkey FROM site WHERE pkey = ?
    );""", (site_pkey, ))
        site_type_name = c2.fetchone()[0]
        sites_as_tiles.add(site_type_name)

    # Initialize edge assignments for split tiles
    for site_type in sites_as_tiles:
        site_obj = db.get_site_type(site_type)
        for site_pin in site_obj.get_site_pins():
            key = (site_type, site_pin)
            assert key not in edge_assignments, key

            edge_assignments[key] = []

    for tile_type in db.get_tile_types():
        # Skip tile types that are split tiles
        if tile_type in split_tile_types:
            continue

        type_obj = db.get_tile_type(tile_type)

        for wire in type_obj.get_wires():
            wires_in_tile_types.add((tile_type, wire))

        for site in type_obj.get_sites():
            for site_pin in site.site_pins:
                if site_pin.wire is None:
                    continue

                key = (tile_type, site_pin.wire)
                assert key not in edge_assignments, key
                edge_assignments[key] = []

    return edge_assignments, wires_in_tile_types
Ejemplo n.º 4
0
def quick_test(db_root):
    db = prjxray.db.Database(db_root)
    g = db.grid()

    # Verify that we have some tile information for every tile in grid.
    tile_types_in_grid = set(
        g.gridinfo_at_loc(loc).tile_type for loc in g.tile_locations())
    tile_types_in_db = set(db.get_tile_types())
    site_types = set(db.get_site_types())
    assert len(tile_types_in_grid - tile_types_in_db) == 0

    # Verify that all tile types can be loaded.
    for tile_type in db.get_tile_types():
        tile = db.get_tile_type(tile_type)
        wires = tile.get_wires()
        for site in tile.get_sites():
            assert site.type in site_types
            site_type = db.get_site_type(site.type)
            site_pins = site_type.get_site_pins()
            for site_pin in site.site_pins:
                if site_pin.wire is not None:
                    assert site_pin.wire in wires, (site_pin.wire, )

                assert site_pin.name in site_pins

        for pip in tile.get_pips():
            assert pip.net_to in wires
            assert pip.net_from in wires

    for loc in g.tile_locations():
        gridinfo = g.gridinfo_at_loc(loc)
        assert gridinfo.tile_type in db.get_tile_types()
        for site_name, site_type in gridinfo.sites.items():
            assert site_type in site_types

        tile = db.get_tile_type(gridinfo.tile_type)

        # FIXME: The way sites are named in Tile.get_instance_sites is broken
        # for thes tile types, skip them until the underlying data is fixed.
        BROKEN_TILE_TYPES = [
            'BRAM_L', 'BRAM_R', 'HCLK_IOI3', 'CMT_TOP_L_UPPER_B',
            'CMT_TOP_R_UPPER_B'
        ]
        if gridinfo.tile_type in BROKEN_TILE_TYPES:
            continue

        instance_sites = list(tile.get_instance_sites(gridinfo))
        assert len(instance_sites) == len(tile.get_sites())
def import_site_type(db, c, site_types, site_type_name):
    assert site_type_name not in site_types
    site_type = db.get_site_type(site_type_name)

    c.execute("INSERT INTO site_type(name) VALUES (?)", (site_type_name, ))
    site_types[site_type_name] = c.lastrowid

    for site_pin in site_type.get_site_pins():
        pin_info = site_type.get_site_pin(site_pin)

        c.execute(
            """
INSERT INTO site_pin(name, site_type_pkey, direction)
VALUES
  (?, ?, ?)""", (pin_info.name, site_types[site_type_name],
                 pin_info.direction.value))
Ejemplo n.º 6
0
def quick_test(db_root):
    db = prjxray.db.Database(db_root)
    g = db.grid()

    # Verify that we have some tile information for every tile in grid.
    tile_types_in_grid = set(
        g.gridinfo_at_loc(loc).tile_type for loc in g.tile_locations())
    tile_types_in_db = set(db.get_tile_types())
    site_types = set(db.get_site_types())
    assert len(tile_types_in_grid - tile_types_in_db) == 0

    # Verify that all tile types can be loaded.
    for tile_type in db.get_tile_types():
        tile = db.get_tile_type(tile_type)
        wires = tile.get_wires()
        for site in tile.get_sites():
            assert site.type in site_types
            site_type = db.get_site_type(site.type)
            site_pins = site_type.get_site_pins()
            for site_pin in site.site_pins:
                if site_pin.wire is not None:
                    assert site_pin.wire in wires, (site_pin.wire, )

                assert site_pin.name in site_pins

        for pip in tile.get_pips():
            assert pip.net_to in wires
            assert pip.net_from in wires

    for loc in g.tile_locations():
        gridinfo = g.gridinfo_at_loc(loc)
        assert gridinfo.tile_type in db.get_tile_types()
        for site_name, site_type in gridinfo.sites.items():
            assert site_type in site_types

        tile = db.get_tile_type(gridinfo.tile_type)

        instance_sites = list(tile.get_instance_sites(gridinfo))
        assert len(instance_sites) == len(tile.get_sites())
Ejemplo n.º 7
0
def main():
    mydir = os.path.dirname(__file__)
    prjxray_db = os.path.abspath(
        os.path.join(mydir, "..", "..", "third_party", "prjxray-db"))

    db_types = prjxray.db.get_available_databases(prjxray_db)

    parser = argparse.ArgumentParser(description=__doc__,
                                     fromfile_prefix_chars='@',
                                     prefix_chars='-~')

    parser.add_argument(
        '--part',
        choices=[os.path.basename(db_type) for db_type in db_types],
        help="""Project X-Ray database to use.""")

    parser.add_argument('--site_type', help="""Site type to generate for""")

    parser.add_argument('--output-pb-type',
                        nargs='?',
                        type=argparse.FileType('w'),
                        default=sys.stdout,
                        help="""File to write the output too.""")

    parser.add_argument('--output-model',
                        nargs='?',
                        type=argparse.FileType('w'),
                        default=sys.stdout,
                        help="""File to write the output too.""")

    args = parser.parse_args()

    db = prjxray.db.Database(os.path.join(prjxray_db, args.part))

    site_type = db.get_site_type(args.site_type.upper())

    pb_type_xml = ET.Element(
        'pb_type',
        {
            'name': 'DUMMY-{}'.format(args.site_type),
        },
    )

    for site_pin_name in site_type.get_site_pins():
        site_pin = site_type.get_site_pin(site_pin_name)
        if site_pin.direction == prjxray.site_type.SitePinDirection.IN:
            ET.SubElement(pb_type_xml, 'input', {
                'name': site_pin.name,
            })
        elif site_pin.direction == prjxray.site_type.SitePinDirection.OUT:
            ET.SubElement(pb_type_xml, 'output', {
                'name': site_pin.name,
            })
        else:
            assert False, site_pin

    pb_type_str = ET.tostring(pb_type_xml, pretty_print=True).decode('utf-8')
    args.output_pb_type.write(pb_type_str)
    args.output_pb_type.close()

    model_xml = ET.Element('models')

    model_str = ET.tostring(model_xml, pretty_print=True).decode('utf-8')
    args.output_model.write(model_str)
    args.output_model.close()
Ejemplo n.º 8
0
def initialize_edge_assignments(db, conn):
    """ Create initial edge_assignments map. """
    c = conn.cursor()
    c2 = conn.cursor()

    c.execute("""
SELECT name, pkey FROM tile_type WHERE pkey IN (
    SELECT DISTINCT tile_type_pkey FROM tile
    );""")
    tiles = dict(c)

    edge_assignments = {}
    wires_in_tile_types = set()

    # First find out which tile types were split during VPR grid formation.
    # These tile types should not get edge assignments directly, instead
    # their sites will get edge assignements.
    sites_as_tiles = set()
    split_tile_types = set()
    for site_pkey, tile_type_pkey in c.execute("""
        SELECT site_pkey, tile_type_pkey FROM site_as_tile;
        """):
        c2.execute("SELECT name FROM tile_type WHERE pkey = ?",
                   (tile_type_pkey, ))
        split_tile_types.add(c2.fetchone()[0])

        c2.execute(
            """
SELECT name FROM site_type WHERE pkey = (
    SELECT site_type_pkey FROM site WHERE pkey = ?
    );""", (site_pkey, ))
        site_type_name = c2.fetchone()[0]
        sites_as_tiles.add(site_type_name)

    # Initialize edge assignments for split tiles
    for site_type in sites_as_tiles:
        del tiles[site_type]

        site_obj = db.get_site_type(site_type)
        for site_pin in site_obj.get_site_pins():
            key = (site_type, site_pin)
            assert key not in edge_assignments, key

            edge_assignments[key] = []

    for tile_type in db.get_tile_types():
        if tile_type not in tiles:
            continue

        del tiles[tile_type]

        # Skip tile types that are split tiles
        if tile_type in split_tile_types:
            continue

        (tile_type_pkey, ) = c.execute(
            """
    SELECT pkey
    FROM tile_type
    WHERE name = ?
        """, (tile_type, )).fetchone()

        for (wire, ) in c.execute(
                """
    SELECT name
    FROM wire_in_tile
    WHERE tile_type_pkey = ?""", (tile_type_pkey, )):
            wires_in_tile_types.add((tile_type, wire))

        type_obj = db.get_tile_type(tile_type)
        for site in type_obj.get_sites():
            for site_pin in site.site_pins:
                if site_pin.wire is None:
                    continue

                # Skip if this wire is not in the database
                c.execute(
                    """
    SELECT pkey
    FROM wire_in_tile
    WHERE name = ?
""", (site_pin.wire, ))
                if not c.fetchone():
                    continue

                key = (tile_type, site_pin.wire)
                assert key not in edge_assignments, key
                edge_assignments[key] = []

    for tile_type, tile_pkey in tiles.items():
        assert tile_type not in split_tile_types

        for (wire, ) in c.execute(
                """
    SELECT name
    FROM wire_in_tile
    WHERE pkey in (
        SELECT DISTINCT wire_in_tile_pkey
        FROM wire
        WHERE tile_pkey IN (
            SELECT pkey
            FROM tile
            WHERE tile_type_pkey = ?)
        );""", (tile_pkey, )):
            wires_in_tile_types.add((tile_type, wire))

        for (wire, ) in c.execute(
                """
SELECT DISTINCT name
FROM wire_in_tile
WHERE pkey in (
    SELECT DISTINCT wire_in_tile_pkey
    FROM wire
    WHERE tile_pkey IN (
        SELECT pkey
        FROM tile
        WHERE tile_type_pkey = ?)
    )
    AND
        site_pin_pkey IS NOT NULL""", (tile_pkey, )):
            key = (tile_type, wire)
            assert key not in edge_assignments, key
            edge_assignments[key] = []

    return edge_assignments, wires_in_tile_types
def import_site_as_tile(db, args):
    """ Create a root-level pb_type with the same pin names as a site type.
    """
    site_type = db.get_site_type(args.tile)

    # Wires sink to a site within the tile are input wires.
    input_wires = set()

    # Wires source from a site within the tile are output wires.
    output_wires = set()

    site_type_instances = parse_site_type_instance(args.site_types)
    assert len(site_type_instances) == 1
    assert args.tile in site_type_instances
    assert len(site_type_instances[args.tile]) == 1

    for site_pin in site_type.get_site_pins():
        site_type_pin = site_type.get_site_pin(site_pin)

        if site_type_pin.direction == prjxray.site_type.SitePinDirection.IN:
            input_wires.add(site_type_pin.name)
        elif site_type_pin.direction == prjxray.site_type.SitePinDirection.OUT:
            output_wires.add(site_type_pin.name)
        else:
            assert False, site_type_pin.direction

    ##########################################################################
    # Generate the model.xml file                                            #
    ##########################################################################
    model = ModelXml(f=args.output_model, site_directory=args.site_directory)
    model.add_model_include(args.tile, site_type_instances[args.tile][0])
    model.write_model()

    ##########################################################################
    # Generate the pb_type.xml file                                          #
    ##########################################################################

    tile_name = args.tile
    pb_type_xml = start_pb_type(tile_name, args.pin_assignments, input_wires,
                                output_wires)

    site = args.tile
    site_instance = site_type_instances[args.tile][0]

    site_pbtype = args.site_directory + "/{0}/{1}.pb_type.xml"
    site_type_path = site_pbtype.format(site.lower(), site_instance.lower())
    ET.SubElement(pb_type_xml, XI_INCLUDE, {
        'href': site_type_path,
    })

    cell_pb_type = ET.ElementTree()
    root_element = cell_pb_type.parse(site_type_path)
    site_name = root_element.attrib['name']

    interconnect_xml = ET.Element('interconnect')

    interconnect_xml.append(ET.Comment(" Tile->Site "))
    for site_pin in sorted(site_type.get_site_pins()):
        site_type_pin = site_type.get_site_pin(site_pin)
        if site_type_pin.direction == prjxray.site_type.SitePinDirection.IN:
            add_direct(interconnect_xml,
                       input=object_ref(add_vpr_tile_prefix(tile_name),
                                        site_pin),
                       output=object_ref(site_name, site_pin))
        elif site_type_pin.direction == prjxray.site_type.SitePinDirection.OUT:
            pass
        else:
            assert False, site_type_pin.direction

    interconnect_xml.append(ET.Comment(" Site->Tile "))
    for site_pin in sorted(site_type.get_site_pins()):
        site_type_pin = site_type.get_site_pin(site_pin)
        if site_type_pin.direction == prjxray.site_type.SitePinDirection.IN:
            pass
        elif site_type_pin.direction == prjxray.site_type.SitePinDirection.OUT:
            add_direct(
                interconnect_xml,
                input=object_ref(site_name, site_pin),
                output=object_ref(add_vpr_tile_prefix(tile_name), site_pin),
            )
        else:
            assert False, site_type_pin.direction

    pb_type_xml.append(interconnect_xml)

    write_xml(args.output_pb_type, pb_type_xml)
def import_tile(db, args):
    """ Create a root-level pb_type with the pin names that match tile wires.

    This will either have 1 intermediate pb_type per site, or 1 large site
    for the entire tile if args.fused_sites is set to true.
    """

    tile = db.get_tile_type(args.tile)

    # Wires sink to a site within the tile are input wires.
    input_wires = set()

    # Wires source from a site within the tile are output wires.
    output_wires = set()

    if args.filter_x:
        xs = list(map(int, args.filter_x.split(',')))

        def x_filter_func(site):
            return site.x in xs

        x_filter = x_filter_func
    else:

        def x_filter_func(site):
            return True

        x_filter = x_filter_func

    if not args.fused_sites:
        site_type_instances = parse_site_type_instance(args.site_types)

        imported_site_types = set()
        ignored_site_types = set()

        for site in tile.get_sites():
            site_type = db.get_site_type(site.type)

            if site.type not in site_type_instances:
                ignored_site_types.add(site.type)
                continue

            imported_site_types.add(site.type)

            for site_pin in site.site_pins:
                site_type_pin = site_type.get_site_pin(site_pin.name)

                if site_type_pin.direction == prjxray.site_type.SitePinDirection.IN:
                    if site_pin.wire is not None:
                        input_wires.add(site_pin.wire)
                elif site_type_pin.direction == prjxray.site_type.SitePinDirection.OUT:
                    if site_pin.wire is not None:
                        output_wires.add(site_pin.wire)
                else:
                    if site.type != "PS7":
                        assert False, site_type_pin.direction

        # Make sure all requested site types actually get imported.
        assert len(set(site_type_instances.keys()) -
                   imported_site_types) == 0, (site_type_instances.keys(),
                                               imported_site_types)

        for ignored_site_type in ignored_site_types:
            print(
                '*** WARNING *** Ignored site type {} in tile type {}'.format(
                    ignored_site_type, args.tile),
                file=sys.stderr)
    else:
        for site in tile.get_sites():
            site_type = db.get_site_type(site.type)

            for site_pin in site.site_pins:
                site_type_pin = site_type.get_site_pin(site_pin.name)

                if site_type_pin.direction == prjxray.site_type.SitePinDirection.IN:
                    if site_pin.wire is not None:
                        input_wires.add(site_pin.wire)
                elif site_type_pin.direction == prjxray.site_type.SitePinDirection.OUT:
                    if site_pin.wire is not None:
                        output_wires.add(site_pin.wire)
                else:
                    assert False, site_type_pin.direction

    site_pbtype = args.site_directory + "/{0}/{1}.pb_type.xml"

    ##########################################################################
    # Generate the model.xml file                                            #
    ##########################################################################

    model = ModelXml(f=args.output_model, site_directory=args.site_directory)

    if args.fused_sites:
        fused_site_name = args.tile.lower()

        model.add_model_include(fused_site_name, fused_site_name)

    ##########################################################################
    # Utility functions for pb_type                                          #
    ##########################################################################
    tile_name = args.tile

    pb_type_xml = start_pb_type(tile_name, args.pin_assignments, input_wires,
                                output_wires)

    cell_names = {}

    interconnect_xml = ET.Element('interconnect')

    if not args.fused_sites:
        site_type_count = {}
        site_prefixes = {}
        cells_idx = {}
        models_added = set()

        site_type_ports = {}
        idx = 0
        for site in tile.get_sites():
            if site.type in ignored_site_types:
                continue

            if not x_filter(site):
                continue

            if site.type not in site_type_count:
                site_type_count[site.type] = 0
                site_prefixes[site.type] = []

            cells_idx[idx] = site_type_count[site.type]
            site_type_count[site.type] += 1

            site_coords = args.site_coords.upper()
            if site_coords == 'X':
                site_prefix = '{}_X{}'.format(site.type, site.x)
            elif site_coords == 'Y':
                site_prefix = '{}_Y{}'.format(site.type, site.y)
            elif site_coords == 'XY':
                site_prefix = '{}.{}_X{}Y{}'.format(site.type, site.type,
                                                    site.x, site.y)
            else:
                assert False, "Invalid --site-coords value '{}'".format(
                    site_coords)

            site_instance = site_type_instances[site.type][cells_idx[idx]]
            idx += 1

            if (site.type, site_instance) not in models_added:
                models_added.add((site.type, site_instance))
                model.add_model_include(site.type, site_instance)

            site_type_path = site_pbtype.format(site.type.lower(),
                                                site_instance.lower())
            cell_pb_type = ET.ElementTree()
            root_element = cell_pb_type.parse(site_type_path)
            cell_names[site_instance] = root_element.attrib['name']

            ports = {}
            for inputs in root_element.iter('input'):
                ports[inputs.attrib['name']] = int(inputs.attrib['num_pins'])

            for clocks in root_element.iter('clock'):
                ports[clocks.attrib['name']] = int(clocks.attrib['num_pins'])

            for outputs in root_element.iter('output'):
                ports[outputs.attrib['name']] = int(outputs.attrib['num_pins'])

            assert site_instance not in site_type_ports, (
                site_instance, site_type_ports.keys())
            site_type_ports[site_instance] = ports

            attrib = dict(root_element.attrib)
            include_xml = ET.SubElement(pb_type_xml, 'pb_type', attrib)
            ET.SubElement(
                include_xml, XI_INCLUDE, {
                    'href':
                    site_type_path,
                    'xpointer':
                    "xpointer(pb_type/child::node()[local-name()!='metadata'])",
                })

            metadata_xml = ET.SubElement(include_xml, 'metadata')

            if not args.no_fasm_prefix:
                ET.SubElement(metadata_xml, 'meta', {
                    'name': 'fasm_prefix',
                }).text = site_prefix

            # Import pb_type metadata if it exists.
            if any(child.tag == 'metadata' for child in root_element):
                ET.SubElement(
                    metadata_xml, XI_INCLUDE, {
                        'href': site_type_path,
                        'xpointer': "xpointer(pb_type/metadata/child::node())",
                    })

            # Prevent emitting empty metadata
            if not any(child.tag == 'meta' for child in metadata_xml):
                include_xml.remove(metadata_xml)

        idx = 0
        for site in tile.get_sites():
            if site.type in ignored_site_types:
                continue

            site_idx = cells_idx[idx]
            idx += 1

            if not x_filter(site):
                continue

            site_instance = site_type_instances[site.type][site_idx]
            site_name = cell_names[site_instance]

            site_type = db.get_site_type(site.type)

            interconnect_xml.append(ET.Comment(" Tile->Site "))
            for site_pin in sorted(site.site_pins,
                                   key=lambda site_pin: site_pin.name):
                if site_pin.wire is None:
                    continue

                port = find_port(site_pin.name, site_type_ports[site_instance])
                if port is None:
                    print(
                        "*** WARNING *** Didn't find port for name {} for site type {}"
                        .format(site_pin.name, site.type),
                        file=sys.stderr)
                    continue

                site_type_pin = site_type.get_site_pin(site_pin.name)

                if site_type_pin.direction == prjxray.site_type.SitePinDirection.IN:
                    add_direct(interconnect_xml,
                               input=object_ref(add_vpr_tile_prefix(tile_name),
                                                site_pin.wire),
                               output=object_ref(site_name, **port))
                elif site_type_pin.direction == prjxray.site_type.SitePinDirection.OUT:
                    pass
                else:
                    if site.type != "PS7":
                        assert False, site_type_pin.direction

            interconnect_xml.append(ET.Comment(" Site->Tile "))
            for site_pin in sorted(site.site_pins,
                                   key=lambda site_pin: site_pin.name):
                if site_pin.wire is None:
                    continue

                port = find_port(site_pin.name, site_type_ports[site_instance])
                if port is None:
                    continue

                site_type_pin = site_type.get_site_pin(site_pin.name)

                if site_type_pin.direction == prjxray.site_type.SitePinDirection.IN:
                    pass
                elif site_type_pin.direction == prjxray.site_type.SitePinDirection.OUT:
                    add_direct(
                        interconnect_xml,
                        input=object_ref(site_name, **port),
                        output=object_ref(add_vpr_tile_prefix(tile_name),
                                          site_pin.wire),
                    )
                else:
                    if site.type != "PS7":
                        assert False, site_type_pin.direction
    else:
        site_type_ports = {}

        site_type_path = site_pbtype.format(fused_site_name, fused_site_name)
        cell_pb_type = ET.ElementTree()
        root_element = cell_pb_type.parse(site_type_path)

        ports = {}
        for inputs in root_element.iter('input'):
            ports[inputs.attrib['name']] = int(inputs.attrib['num_pins'])

        for clocks in root_element.iter('clock'):
            ports[clocks.attrib['name']] = int(clocks.attrib['num_pins'])

        for outputs in root_element.iter('output'):
            ports[outputs.attrib['name']] = int(outputs.attrib['num_pins'])

        attrib = dict(root_element.attrib)
        include_xml = ET.SubElement(pb_type_xml, 'pb_type', attrib)
        ET.SubElement(
            include_xml, XI_INCLUDE, {
                'href': site_type_path,
                'xpointer': "xpointer(pb_type/child::node())",
            })

        site_name = root_element.attrib['name']

        def fused_port_name(site, site_pin):
            return '{}_{}_{}'.format(site.prefix, site.name, site_pin.name)

        for site in tile.get_sites():
            site_type = db.get_site_type(site.type)

            interconnect_xml.append(ET.Comment(" Tile->Site "))
            for site_pin in sorted(site.site_pins,
                                   key=lambda site_pin: site_pin.name):
                if site_pin.wire is None:
                    continue

                port_name = fused_port_name(site, site_pin)
                port = find_port(port_name, ports)
                if port is None:
                    print(
                        "*** WARNING *** Didn't find port for name {} for site type {}"
                        .format(port_name, site.type),
                        file=sys.stderr)
                    continue

                site_type_pin = site_type.get_site_pin(site_pin.name)

                if site_type_pin.direction == prjxray.site_type.SitePinDirection.IN:
                    add_direct(interconnect_xml,
                               input=object_ref(add_vpr_tile_prefix(tile_name),
                                                site_pin.wire),
                               output=object_ref(site_name, **port))
                elif site_type_pin.direction == prjxray.site_type.SitePinDirection.OUT:
                    pass
                else:
                    if site.type != "PS7":
                        assert False, site_type_pin.direction

            interconnect_xml.append(ET.Comment(" Site->Tile "))
            for site_pin in sorted(site.site_pins,
                                   key=lambda site_pin: site_pin.name):
                if site_pin.wire is None:
                    continue

                port = find_port(fused_port_name(site, site_pin), ports)
                if port is None:
                    # Already warned above
                    continue

                site_type_pin = site_type.get_site_pin(site_pin.name)

                if site_type_pin.direction == prjxray.site_type.SitePinDirection.IN:
                    pass
                elif site_type_pin.direction == prjxray.site_type.SitePinDirection.OUT:
                    add_direct(
                        interconnect_xml,
                        input=object_ref(site_name, **port),
                        output=object_ref(add_vpr_tile_prefix(tile_name),
                                          site_pin.wire),
                    )
                else:
                    if site.type != "PS7":
                        assert False, site_type_pin.direction

    pb_type_xml.append(interconnect_xml)

    model.write_model()
    write_xml(args.output_pb_type, pb_type_xml)
Ejemplo n.º 11
0
def main():
    mydir = os.path.dirname(__file__)
    prjxray_db = os.path.abspath(
        os.path.join(mydir, "..", "..", "third_party", "prjxray-db"))

    db_types = prjxray.db.get_available_databases(prjxray_db)

    parser = argparse.ArgumentParser(description=__doc__,
                                     fromfile_prefix_chars='@',
                                     prefix_chars='-~')

    parser.add_argument(
        '--part',
        choices=[os.path.basename(db_type) for db_type in db_types],
        help="""Project X-Ray database to use.""")

    parser.add_argument('--tile', help="""Tile to generate for""")

    parser.add_argument('--site_directory',
                        help="""Diretory where sites are defined""")

    parser.add_argument('--output-pb-type',
                        nargs='?',
                        type=argparse.FileType('w'),
                        default=sys.stdout,
                        help="""File to write the output too.""")

    parser.add_argument('--output-model',
                        nargs='?',
                        type=argparse.FileType('w'),
                        default=sys.stdout,
                        help="""File to write the output too.""")

    parser.add_argument('--pin_assignments',
                        required=True,
                        type=argparse.FileType('r'))

    parser.add_argument(
        '--site_types',
        required=True,
        help="Comma seperated list of site types to include in this tile.")

    parser.add_argument(
        '--fused_sites',
        action='store_true',
        help=
        "Typically a tile can treat the sites within the tile as independent.  For tiles where this is not true, fused sites only imports 1 primatative for the entire tile, which should be named the same as the tile type."
    )

    args = parser.parse_args()

    db = prjxray.db.Database(os.path.join(prjxray_db, args.part))

    tile = db.get_tile_type(args.tile)

    # Wires sink to a site within the tile are input wires.
    input_wires = set()

    # Wires source from a site within the tile are output wires.
    output_wires = set()

    if not args.fused_sites:
        site_type_instances = {}
        for s in args.site_types.split(','):
            site_type, site_type_instance = s.split('/')

            if site_type not in site_type_instances:
                site_type_instances[site_type] = []

            site_type_instances[site_type].append(site_type_instance)

        imported_site_types = set()
        ignored_site_types = set()

        for site in tile.get_sites():
            site_type = db.get_site_type(site.type)

            if site.type not in site_type_instances:
                ignored_site_types.add(site.type)
                continue

            imported_site_types.add(site.type)

            for site_pin in site.site_pins:
                site_type_pin = site_type.get_site_pin(site_pin.name)

                if site_type_pin.direction == prjxray.site_type.SitePinDirection.IN:
                    if site_pin.wire is not None:
                        input_wires.add(site_pin.wire)
                elif site_type_pin.direction == prjxray.site_type.SitePinDirection.OUT:
                    if site_pin.wire is not None:
                        output_wires.add(site_pin.wire)
                else:
                    assert False, site_type_pin.direction

        # Make sure all requested site types actually get imported.
        assert len(set(site_type_instances.keys()) -
                   imported_site_types) == 0, (site_type_instances.keys(),
                                               imported_site_types)

        for ignored_site_type in ignored_site_types:
            print(
                '*** WARNING *** Ignored site type {} in tile type {}'.format(
                    ignored_site_type, args.tile),
                file=sys.stderr)
    else:
        for site in tile.get_sites():
            site_type = db.get_site_type(site.type)

            for site_pin in site.site_pins:
                site_type_pin = site_type.get_site_pin(site_pin.name)

                if site_type_pin.direction == prjxray.site_type.SitePinDirection.IN:
                    if site_pin.wire is not None:
                        input_wires.add(site_pin.wire)
                elif site_type_pin.direction == prjxray.site_type.SitePinDirection.OUT:
                    if site_pin.wire is not None:
                        output_wires.add(site_pin.wire)
                else:
                    assert False, site_type_pin.direction

    site_model = args.site_directory + "/{0}/{1}.model.xml"
    site_pbtype = args.site_directory + "/{0}/{1}.pb_type.xml"

    xi_url = "http://www.w3.org/2001/XInclude"
    ET.register_namespace('xi', xi_url)
    xi_include = "{%s}include" % xi_url

    ##########################################################################
    # Generate the model.xml file                                            #
    ##########################################################################

    model_xml = ET.Element(
        'models',
        nsmap={'xi': xi_url},
    )

    def add_model_include(site_type, instance_name):
        ET.SubElement(
            model_xml, xi_include, {
                'href': site_model.format(site_type.lower(),
                                          instance_name.lower()),
                'xpointer': "xpointer(models/child::node())"
            })

    if not args.fused_sites:
        site_types = set(site.type for site in tile.get_sites())
        for site_type in site_types:
            if site_type in ignored_site_types:
                continue

            for instance in site_type_instances[site_type]:
                add_model_include(site_type, instance)
    else:
        fused_site_name = args.tile.lower()

        add_model_include(fused_site_name, fused_site_name)

    model_str = ET.tostring(model_xml, pretty_print=True).decode('utf-8')
    args.output_model.write(model_str)
    args.output_model.close()

    ##########################################################################
    # Generate the pb_type.xml file                                          #
    ##########################################################################

    def add_direct(xml, input, output):
        ET.SubElement(
            xml, 'direct', {
                'name': '{}_to_{}'.format(input, output),
                'input': input,
                'output': output
            })

    tile_name = "BLK_TI-{}".format(args.tile)

    pb_type_xml = ET.Element(
        'pb_type',
        {
            'name': tile_name,
        },
        nsmap={'xi': xi_url},
    )

    fc_xml = ET.SubElement(pb_type_xml, 'fc', {
        'in_type': 'abs',
        'in_val': '2',
        'out_type': 'abs',
        'out_val': '2',
    })

    interconnect_xml = ET.Element('interconnect')

    pb_type_xml.append(ET.Comment(" Tile Inputs "))

    # Input definitions for the TILE
    for name in sorted(input_wires):
        input_type = 'input'

        if 'CLK' in name:
            input_type = 'clock'

        ET.SubElement(
            pb_type_xml,
            input_type,
            {
                'name': name,
                'num_pins': '1'
            },
        )

    pb_type_xml.append(ET.Comment(" Tile Outputs "))
    for name in sorted(output_wires):
        # Output definitions for the TILE
        ET.SubElement(
            pb_type_xml,
            'output',
            {
                'name': name,
                'num_pins': '1'
            },
        )

    pb_type_xml.append(ET.Comment(" Internal Sites "))

    cell_names = {}

    if not args.fused_sites:
        site_type_count = {}
        site_prefixes = {}
        cells_idx = []

        site_type_ports = {}
        for idx, site in enumerate(tile.get_sites()):
            if site.type in ignored_site_types:
                continue

            if site.type not in site_type_count:
                site_type_count[site.type] = 0
                site_prefixes[site.type] = []

            cells_idx.append(site_type_count[site.type])
            site_type_count[site.type] += 1
            site_prefix = '{}_X{}'.format(site.type, site.x)

            site_instance = site_type_instances[site.type][cells_idx[idx]]

            print(site_prefix, site_instance)

            site_type_path = site_pbtype.format(site.type.lower(),
                                                site_instance.lower())
            cell_pb_type = ET.ElementTree()
            root_element = cell_pb_type.parse(site_type_path)
            cell_names[site_instance] = root_element.attrib['name']

            ports = {}
            for inputs in root_element.iter('input'):
                ports[inputs.attrib['name']] = int(inputs.attrib['num_pins'])

            for clocks in root_element.iter('clock'):
                ports[clocks.attrib['name']] = int(clocks.attrib['num_pins'])

            for outputs in root_element.iter('output'):
                ports[outputs.attrib['name']] = int(outputs.attrib['num_pins'])

            assert site_instance not in site_type_ports, (
                site_instance, site_type_ports.keys())
            site_type_ports[site_instance] = ports

            attrib = dict(root_element.attrib)
            include_xml = ET.SubElement(pb_type_xml, 'pb_type', attrib)
            ET.SubElement(
                include_xml, xi_include, {
                    'href':
                    site_type_path,
                    'xpointer':
                    "xpointer(pb_type/child::node()[local-name()!='metadata'])",
                })

            metadata_xml = ET.SubElement(include_xml, 'metadata')
            ET.SubElement(metadata_xml, 'meta', {
                'name': 'fasm_prefix',
            }).text = site_prefix

            # Import pb_type metadata if it exists.
            if any(child.tag == 'metadata' for child in root_element):
                ET.SubElement(
                    metadata_xml, xi_include, {
                        'href': site_type_path,
                        'xpointer': "xpointer(pb_type/metadata/child::node())",
                    })

        for idx, site in enumerate(tile.get_sites()):
            if site.type in ignored_site_types:
                continue

            site_idx = cells_idx[idx]
            site_instance = site_type_instances[site.type][site_idx]
            site_name = cell_names[site_instance]

            site_type = db.get_site_type(site.type)

            interconnect_xml.append(ET.Comment(" Tile->Site "))
            for site_pin in sorted(site.site_pins,
                                   key=lambda site_pin: site_pin.name):
                if site_pin.wire is None:
                    continue

                port = find_port(site_pin.name, site_type_ports[site_instance])
                if port is None:
                    print(
                        "*** WARNING *** Didn't find port for name {} for site type {}"
                        .format(site_pin.name, site.type),
                        file=sys.stderr)
                    continue

                site_type_pin = site_type.get_site_pin(site_pin.name)

                if site_type_pin.direction == prjxray.site_type.SitePinDirection.IN:
                    add_direct(interconnect_xml,
                               input=object_ref(tile_name, site_pin.wire),
                               output=object_ref(site_name, **port))
                elif site_type_pin.direction == prjxray.site_type.SitePinDirection.OUT:
                    pass
                else:
                    assert False, site_type_pin.direction

            interconnect_xml.append(ET.Comment(" Site->Tile "))
            for site_pin in sorted(site.site_pins,
                                   key=lambda site_pin: site_pin.name):
                if site_pin.wire is None:
                    continue

                port = find_port(site_pin.name, site_type_ports[site_instance])
                if port is None:
                    continue

                site_type_pin = site_type.get_site_pin(site_pin.name)

                if site_type_pin.direction == prjxray.site_type.SitePinDirection.IN:
                    pass
                elif site_type_pin.direction == prjxray.site_type.SitePinDirection.OUT:
                    add_direct(
                        interconnect_xml,
                        input=object_ref(site_name, **port),
                        output=object_ref(tile_name, site_pin.wire),
                    )
                else:
                    assert False, site_type_pin.direction
    else:
        site_type_ports = {}

        site_type_path = site_pbtype.format(fused_site_name, fused_site_name)
        cell_pb_type = ET.ElementTree()
        root_element = cell_pb_type.parse(site_type_path)

        ports = {}
        for inputs in root_element.iter('input'):
            ports[inputs.attrib['name']] = int(inputs.attrib['num_pins'])

        for clocks in root_element.iter('clock'):
            ports[clocks.attrib['name']] = int(clocks.attrib['num_pins'])

        for outputs in root_element.iter('output'):
            ports[outputs.attrib['name']] = int(outputs.attrib['num_pins'])

        attrib = dict(root_element.attrib)
        include_xml = ET.SubElement(pb_type_xml, 'pb_type', attrib)
        ET.SubElement(
            include_xml, xi_include, {
                'href': site_type_path,
                'xpointer': "xpointer(pb_type/child::node())",
            })

        site_name = root_element.attrib['name']

        def fused_port_name(site, site_pin):
            return '{}_{}_{}'.format(site.prefix, site.name, site_pin.name)

        for idx, site in enumerate(tile.get_sites()):
            site_type = db.get_site_type(site.type)

            interconnect_xml.append(ET.Comment(" Tile->Site "))
            for site_pin in sorted(site.site_pins,
                                   key=lambda site_pin: site_pin.name):
                if site_pin.wire is None:
                    continue

                port_name = fused_port_name(site, site_pin)
                port = find_port(port_name, ports)
                if port is None:
                    print(
                        "*** WARNING *** Didn't find port for name {} for site type {}"
                        .format(port_name, site.type),
                        file=sys.stderr)
                    continue

                site_type_pin = site_type.get_site_pin(site_pin.name)

                if site_type_pin.direction == prjxray.site_type.SitePinDirection.IN:
                    add_direct(interconnect_xml,
                               input=object_ref(tile_name, site_pin.wire),
                               output=object_ref(site_name, **port))
                elif site_type_pin.direction == prjxray.site_type.SitePinDirection.OUT:
                    pass
                else:
                    assert False, site_type_pin.direction

            interconnect_xml.append(ET.Comment(" Site->Tile "))
            for site_pin in sorted(site.site_pins,
                                   key=lambda site_pin: site_pin.name):
                if site_pin.wire is None:
                    continue

                port = find_port(fused_port_name(site, site_pin), ports)
                if port is None:
                    # Already warned above
                    continue

                site_type_pin = site_type.get_site_pin(site_pin.name)

                if site_type_pin.direction == prjxray.site_type.SitePinDirection.IN:
                    pass
                elif site_type_pin.direction == prjxray.site_type.SitePinDirection.OUT:
                    add_direct(
                        interconnect_xml,
                        input=object_ref(site_name, **port),
                        output=object_ref(tile_name, site_pin.wire),
                    )
                else:
                    assert False, site_type_pin.direction

    pb_type_xml.append(interconnect_xml)

    ET.SubElement(pb_type_xml, 'switchblock_locations', {
        'pattern': 'all',
    })

    pinlocations_xml = ET.SubElement(pb_type_xml, 'pinlocations', {
        'pattern': 'custom',
    })

    if len(input_wires) > 0 or len(output_wires) > 0:
        pin_assignments = json.load(args.pin_assignments)

        sides = {}
        for pin in input_wires | output_wires:
            for side in pin_assignments['pin_directions'][args.tile][pin]:
                if side not in sides:
                    sides[side] = []

                sides[side].append(object_ref(tile_name, pin))

        for side, pins in sides.items():
            ET.SubElement(pinlocations_xml, 'loc', {
                'side': side.lower(),
            }).text = ' '.join(pins)

    metadata_xml = ET.SubElement(pb_type_xml, 'metadata')
    ET.SubElement(metadata_xml, 'meta', {
        'name': 'fasm_prefix',
    }).text = args.tile

    direct_pins = set()
    for direct in pin_assignments['direct_connections']:
        if direct['from_pin'].split('.')[0] == args.tile:
            direct_pins.add(direct['from_pin'].split('.')[1])

        if direct['to_pin'].split('.')[0] == args.tile:
            direct_pins.add(direct['to_pin'].split('.')[1])

    for fc_override in direct_pins:
        ET.SubElement(fc_xml, 'fc_override', {
            'fc_type': 'frac',
            'fc_val': '0.0',
            'port_name': fc_override,
        })

    pb_type_str = ET.tostring(pb_type_xml, pretty_print=True).decode('utf-8')
    args.output_pb_type.write(pb_type_str)
    args.output_pb_type.close()
def main():
    parser = argparse.ArgumentParser(description=__doc__)

    parser.add_argument('--db_root', required=True)
    parser.add_argument('--part', required=True)
    parser.add_argument('--output_directory', required=True)
    parser.add_argument('--site_directory', required=True)
    parser.add_argument('--tile_type', required=True)
    parser.add_argument('--pb_types', required=True)
    parser.add_argument('--pin_assignments', required=True)
    parser.add_argument(
        '--unused_wires',
        help="Comma seperated list of site wires to exclude in this tile.")

    args = parser.parse_args()

    with open(args.pin_assignments) as f:
        pin_assignments = json.load(f)

    db = prjxray.db.Database(args.db_root, args.part)
    grid = db.grid()
    tile_type = db.get_tile_type(args.tile_type)

    pb_types = args.pb_types.split(',')

    equivalent_sites_dict = dict()

    gridinfo = None
    for tile in grid.tiles():
        if args.tile_type in tile:
            gridinfo = grid.gridinfo_at_tilename(tile)

            break

    assert gridinfo

    for pb_type in pb_types:
        try:
            site, equivalent_sites = pb_type.split("/")
        except ValueError:
            site = pb_type
            equivalent_sites = None

        equivalent_sites_dict[site] = equivalent_sites.split(
            ':') if equivalent_sites else []

    sites = list()

    for site in tile_type.get_sites():
        site_type = db.get_site_type(site.type)
        input_wires, output_wires = get_wires(site, site_type,
                                              args.unused_wires)

        sites.append((site_type, site, input_wires, output_wires))

    sites = sorted(sites,
                   key=lambda site:
                   (site[1].type, int(site[1].x), int(site[1].y)))

    tile_xml = start_heterogeneous_tile(
        args.tile_type,
        pin_assignments,
        sites,
        equivalent_sites_dict,
    )

    add_switchblock_locations(tile_xml)

    with open(
            '{}/{}.tile.xml'.format(args.output_directory,
                                    args.tile_type.lower()), 'w') as f:
        tile_str = ET.tostring(tile_xml, pretty_print=True).decode('utf-8')
        f.write(tile_str)
Ejemplo n.º 13
0
def main():
    parser = argparse.ArgumentParser(description=__doc__)

    parser.add_argument('--db_root', required=True)
    parser.add_argument('--output_directory', required=True)
    parser.add_argument('--site_directory', required=True)
    parser.add_argument('--tile_type', required=True)
    parser.add_argument('--pb_type', required=True)
    parser.add_argument('--pin_assignments', required=True)
    parser.add_argument('--site_coords', required=True)

    args = parser.parse_args()

    with open(args.pin_assignments) as f:
        pin_assignments = json.load(f)

    db = prjxray.db.Database(args.db_root)
    tile_type = db.get_tile_type(args.tile_type)

    input_wires = set()
    output_wires = set()

    sites = []

    for site in tile_type.get_sites():
        if site.type != args.pb_type:
            continue

        site_type = db.get_site_type(site.type)
        sites.append(site)

        for site_pin in site.site_pins:
            if site_type.get_site_pin(
                    site_pin.name).direction == SitePinDirection.IN:
                input_wires.add(site_pin.wire)
            elif site_type.get_site_pin(
                    site_pin.name).direction == SitePinDirection.OUT:
                output_wires.add(site_pin.wire)
            else:
                assert False, site_pin

    sites.sort(key=lambda site: (site.x, site.y))

    tile_xml = start_pb_type(
        args.tile_type,
        pin_assignments,
        input_wires,
        output_wires,
        root_pb_type=True,
        root_tag='tile',
    )

    tile_xml.attrib['capacity'] = str(len(sites))
    tile_xml.attrib['capacity_type'] = "explicit"

    equivalent_sites_xml = ET.Element('equivalent_sites')

    site_xml = ET.Element('site', {
        'pb_type': add_vpr_tile_prefix(site.type),
        'pin_mapping': 'custom'
    })
    for site_idx, site in enumerate(sites):
        if site.type != args.pb_type:
            continue

        for site_pin in site.site_pins:
            add_tile_direct(
                site_xml,
                tile=object_ref(
                    add_vpr_tile_prefix(args.tile_type),
                    site_pin.wire,
                ),
                pb_type=object_ref(
                    pb_name=add_vpr_tile_prefix(site.type),
                    pb_idx=site_idx,
                    pin_name=site_pin.name,
                ),
            )

    equivalent_sites_xml.append(site_xml)
    tile_xml.append(equivalent_sites_xml)
    add_switchblock_locations(tile_xml)

    with open(
            '{}/{}.tile.xml'.format(args.output_directory,
                                    args.tile_type.lower()), 'w') as f:
        tile_str = ET.tostring(tile_xml, pretty_print=True).decode('utf-8')
        f.write(tile_str)