示例#1
0
def add_direct(directlist_xml, direct):
    direct_dict = {
        'name':
            '{}_to_{}_dx_{}_dy_{}_dz_{}'.format(
                direct['from_pin'], direct['to_pin'], direct['x_offset'],
                direct['y_offset'], direct['z_offset']
            ),
        'from_pin':
            add_vpr_tile_prefix(direct['from_pin']),
        'to_pin':
            add_vpr_tile_prefix(direct['to_pin']),
        'x_offset':
            str(direct['x_offset']),
        'y_offset':
            str(direct['y_offset']),
        'z_offset':
            str(direct['z_offset']),
    }

    # If the switch is a delayless_switch, the switch name
    # needs to be avoided as VPR automatically assigns
    # the delayless switch to this direct connection
    if direct['switch_name'] != '__vpr_delayless_switch__':
        direct_dict['switch_name'] = direct['switch_name']

    ET.SubElement(directlist_xml, 'direct', direct_dict)
示例#2
0
    def add_equivalent_sites(tile_xml, equivalent_sites, inc_priority=False):
        """ Used to add to the <tile> tag the equivalent tiles associated with it."""

        pb_types = equivalent_sites.split(',')

        equivalent_sites_xml = ET.SubElement(tile_xml, 'equivalent_sites')

        priority = 0

        for eq_site in pb_types:
            eq_pb_type_xml = ET.parse(
                "{}/{tile}/{tile}.pb_type.xml".format(
                    args.tiles_directory, tile=eq_site.lower()
                )
            )
            pb_type_root = eq_pb_type_xml.getroot()

            site_xml = ET.SubElement(
                equivalent_sites_xml, 'site', {
                    'pb_type': tile_import.add_vpr_tile_prefix(eq_site),
                    'priority': str(priority)
                }
            )

            if inc_priority:
                priority += 1

            add_direct_mappings(tile_xml, site_xml, pb_type_root)
def get_tiles(conn, g, roi, synth_loc_map, synth_tile_map, tile_types):
    """ Yields tiles in grid.

    Yields
    ------
    vpr_tile_type : str
        VPR tile type at this grid location.
    grid_x, grid_y : int
        Grid coordinate of tile
    fasm_tile_prefix : str
        FASM prefix for this tile.

    """
    c = conn.cursor()
    c2 = conn.cursor()

    only_emit_roi = roi is not None

    for tile_pkey, grid_x, grid_y, phy_tile_pkey, tile_type_pkey, site_as_tile_pkey in c.execute(
            """
        SELECT pkey, grid_x, grid_y, phy_tile_pkey, tile_type_pkey, site_as_tile_pkey FROM tile
        """):

        # Just output synth tiles, no additional processing is required here.
        if (grid_x, grid_y) in synth_loc_map:
            synth_tile = synth_loc_map[(grid_x, grid_y)]

            assert len(synth_tile['pins']) == 1

            vpr_tile_type = synth_tile_map[synth_tile['pins'][0]['port_type']]

            # Synth tiles have no bits, but there needs to be a prefix, so
            # use the original tile name.
            c2.execute(
                "SELECT name FROM phy_tile WHERE pkey = ?", (phy_tile_pkey, )
            )
            fasm_tile_prefix = c2.fetchone()[0]

            yield vpr_tile_type, grid_x, grid_y, fasm_tile_prefix
            continue

        c2.execute(
            "SELECT name FROM tile_type WHERE pkey = ?", (tile_type_pkey, )
        )
        tile_type = c2.fetchone()[0]
        if tile_type not in tile_types:
            # We don't want this tile
            continue

        if only_emit_roi and not is_in_roi(conn, roi, tile_pkey):
            # Tile is outside ROI, skip it
            continue

        vpr_tile_type = add_vpr_tile_prefix(tile_type)

        fasm_tile_prefix = get_fasm_tile_prefix(
            conn, g, tile_pkey, site_as_tile_pkey
        )

        yield vpr_tile_type, grid_x, grid_y, fasm_tile_prefix
示例#4
0
def get_tiles(conn, g, roi, synth_loc_map, synth_tile_map, tile_types,
              tile_capacity):
    """ Yields tiles in grid.

    Yields
    ------
    vpr_tile_type : str
        VPR tile type at this grid location.
    grid_x, grid_y : int
        Grid coordinate of tile
    metadata_function : function that takes lxml.Element
        Function for attaching metadata tags to <single> elements.
        Function must be supplied, but doesn't need to add metadata if not
        required.

    """
    c = conn.cursor()
    c2 = conn.cursor()

    only_emit_roi = roi is not None

    for tile_pkey, grid_x, grid_y, phy_tile_pkey, tile_type_pkey, site_as_tile_pkey in c.execute(
            """
        SELECT pkey, grid_x, grid_y, phy_tile_pkey, tile_type_pkey, site_as_tile_pkey FROM tile
        """):

        # Just output synth tiles, no additional processing is required here.
        if (grid_x, grid_y) in synth_loc_map:
            vpr_tile_type = synth_loc_map[(grid_x, grid_y)]

            yield vpr_tile_type, grid_x, grid_y, lambda x: None
            continue

        c2.execute("SELECT name FROM tile_type WHERE pkey = ?",
                   (tile_type_pkey, ))
        tile_type = c2.fetchone()[0]
        if tile_type not in tile_types:
            # We don't want this tile
            continue

        if only_emit_roi and not is_in_roi(conn, roi, tile_pkey):
            # Tile is outside ROI, skip it
            continue

        vpr_tile_type = add_vpr_tile_prefix(tile_type)

        meta_fun = get_fasm_tile_prefix(conn, g, tile_pkey, site_as_tile_pkey,
                                        tile_capacity[tile_type])

        yield vpr_tile_type, grid_x, grid_y, meta_fun
示例#5
0
    def add_equivalent_sites(tile_xml, equivalent_sites):
        """ Used to add to the <tile> tag the equivalent tiles associated with it."""

        pb_types = equivalent_sites.split(',')

        equivalent_sites_xml = ET.SubElement(tile_xml, 'equivalent_sites')

        for eq_site in pb_types:
            eq_pb_type_xml = ET.parse("{}/{tile}/{tile}.pb_type.xml".format(
                args.tiles_directory, tile=eq_site.lower()))
            pb_type_root = eq_pb_type_xml.getroot()

            site_xml = ET.SubElement(
                equivalent_sites_xml, 'site', {
                    'pb_type': tile_import.add_vpr_tile_prefix(eq_site),
                    'pin_mapping': 'custom'
                })

            add_direct_mappings(tile_xml, site_xml, pb_type_root)
示例#6
0
def import_physical_tile(args):
    """ Imports the physical tile.

    This created the actual tile.xml definition of the tile which will be
    merged in the arch.xml.
    """

    ##########################################################################
    # Utility functions to create tile tag.                                  #
    ##########################################################################

    def get_ports_from_xml(xml):
        """ Used to retrieve ports from a given XML root of a pb_type."""
        ports = set()

        for child in xml:
            if child.tag in PORT_TAGS:
                ports.add(child.attrib['name'])

        return ports

    def add_ports(tile_xml, pb_type_xml):
        """ Used to copy the ports from a given XML root of a pb_type."""

        for child in pb_type_xml:
            if child.tag in PORT_TAGS:
                child_copy = copy.deepcopy(child)
                tile_xml.append(child_copy)

    def add_direct_mappings(tile_xml, site_xml, eq_pb_type_xml):
        """ Used to add the direct pin mappings between a pb_type and the corresponding tile """

        tile_ports = sorted(get_ports_from_xml(tile_xml))
        site_ports = sorted(get_ports_from_xml(eq_pb_type_xml))

        tile_name = tile_xml.attrib['name']
        site_name = site_xml.attrib['pb_type']

        for site_port in site_ports:
            for tile_port in tile_ports:
                if site_port == tile_port:
                    direct_map = ET.SubElement(
                        site_xml, 'direct', {
                            'from': "{}.{}".format(tile_name, tile_port),
                            'to': "{}.{}".format(site_name, site_port)
                        }
                    )

    def add_equivalent_sites(tile_xml, equivalent_sites, inc_priority=False):
        """ Used to add to the <tile> tag the equivalent tiles associated with it."""

        pb_types = equivalent_sites.split(',')

        equivalent_sites_xml = ET.SubElement(tile_xml, 'equivalent_sites')

        priority = 0

        for eq_site in pb_types:
            eq_pb_type_xml = ET.parse(
                "{}/{tile}/{tile}.pb_type.xml".format(
                    args.tiles_directory, tile=eq_site.lower()
                )
            )
            pb_type_root = eq_pb_type_xml.getroot()

            site_xml = ET.SubElement(
                equivalent_sites_xml, 'site', {
                    'pb_type': tile_import.add_vpr_tile_prefix(eq_site),
                    'priority': str(priority)
                }
            )

            if inc_priority:
                priority += 1

            add_direct_mappings(tile_xml, site_xml, pb_type_root)

    ##########################################################################
    # Generate the tile.xml file                                             #
    ##########################################################################

    tile_name = args.tile

    pb_type_xml = ET.parse(
        "{}/{tile}/{tile}.pb_type.xml".format(
            args.tiles_directory, tile=tile_name.lower()
        )
    )
    pb_type_root = pb_type_xml.getroot()

    ports = sorted(get_ports_from_xml(pb_type_root))

    tile_xml = ET.Element(
        'tile',
        {
            'name': tile_import.add_vpr_tile_prefix(tile_name),
        },
        nsmap={'xi': XI_URL},
    )

    add_ports(tile_xml, pb_type_root)

    equivalent_sites = args.equivalent_sites
    add_equivalent_sites(tile_xml, equivalent_sites, args.priority)

    fc_xml = tile_import.add_fc(tile_xml)

    pin_assignments = json.load(args.pin_assignments)
    tile_import.add_pinlocations(
        tile_name, tile_xml, fc_xml, pin_assignments, ports
    )

    tile_import.add_switchblock_locations(tile_xml)

    tile_str = ET.tostring(tile_xml, pretty_print=True).decode('utf-8')
    args.output_tile.write(tile_str)
    args.output_tile.close()
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="Generate arch.xml")
    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(
        '--output-arch',
        nargs='?',
        type=argparse.FileType('w'),
        help="""File to output arch."""
    )
    parser.add_argument(
        '--tile-types', help="Semi-colon seperated tile types."
    )
    parser.add_argument(
        '--pin_assignments', required=True, type=argparse.FileType('r')
    )
    parser.add_argument('--use_roi', required=False)
    parser.add_argument('--device', required=True)
    parser.add_argument('--synth_tiles', required=False)
    parser.add_argument('--connection_database', required=True)
    parser.add_argument(
        '--graph_limit',
        help='Limit grid to specified dimensions in x_min,y_min,x_max,y_max',
    )

    args = parser.parse_args()

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

    tile_model = "../../tiles/{0}/{0}.model.xml"
    tile_pbtype = "../../tiles/{0}/{0}.pb_type.xml"
    tile_tile = "../../tiles/{0}/{0}.tile.xml"

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

    arch_xml = ET.Element(
        'architecture',
        {},
        nsmap={'xi': xi_url},
    )

    model_xml = ET.SubElement(arch_xml, 'models')
    for tile_type in tile_types:
        ET.SubElement(
            model_xml, xi_include, {
                'href': tile_model.format(tile_type.lower()),
                'xpointer': "xpointer(models/child::node())",
            }
        )

    tiles_xml = ET.SubElement(arch_xml, 'tiles')
    for tile_type in tile_types:
        ET.SubElement(
            tiles_xml, xi_include, {
                'href': tile_tile.format(tile_type.lower()),
            }
        )

    complexblocklist_xml = ET.SubElement(arch_xml, 'complexblocklist')
    for tile_type in tile_types:
        ET.SubElement(
            complexblocklist_xml, xi_include, {
                'href': tile_pbtype.format(tile_type.lower()),
            }
        )

    layout_xml = ET.SubElement(arch_xml, 'layout')
    db = prjxray.db.Database(os.path.join(prjxray_db, args.part))
    g = db.grid()

    synth_tiles = {}
    synth_tiles['tiles'] = {}
    synth_loc_map = {}
    synth_tile_map = {}
    roi = None
    if args.use_roi:
        with open(args.use_roi) as f:
            j = json.load(f)

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

        roi = Roi(
            db=db,
            x1=j['info']['GRID_X_MIN'],
            y1=j['info']['GRID_Y_MIN'],
            x2=j['info']['GRID_X_MAX'],
            y2=j['info']['GRID_Y_MAX'],
        )

        synth_tile_map = add_synthetic_tiles(
            model_xml, complexblocklist_xml, tiles_xml, need_io=True
        )

        for _, tile_info in synth_tiles['tiles'].items():
            assert tuple(tile_info['loc']) not in synth_loc_map

            assert len(tile_info['pins']) == 1

            vpr_tile_type = synth_tile_map[tile_info['pins'][0]['port_type']]

            synth_loc_map[tuple(tile_info['loc'])] = vpr_tile_type

    elif args.graph_limit:
        x_min, y_min, x_max, y_max = map(int, args.graph_limit.split(','))
        roi = Roi(
            db=db,
            x1=x_min,
            y1=y_min,
            x2=x_max,
            y2=y_max,
        )

    with DatabaseCache(args.connection_database, read_only=True) as conn:
        c = conn.cursor()

        if 'GND' not in synth_tile_map:
            synth_tile_map, synth_loc_map = insert_constant_tiles(
                conn, model_xml, complexblocklist_xml, tiles_xml
            )

        # Find the grid extent.
        y_max = 0
        x_max = 0
        for grid_x, grid_y in c.execute("SELECT grid_x, grid_y FROM tile"):
            x_max = max(grid_x + 2, x_max)
            y_max = max(grid_y + 2, y_max)

        name = '{}-test'.format(args.device)
        fixed_layout_xml = ET.SubElement(
            layout_xml, 'fixed_layout', {
                'name': name,
                'height': str(y_max),
                'width': str(x_max),
            }
        )

        for vpr_tile_type, grid_x, grid_y, metadata_function in get_tiles(
                conn=conn,
                g=g,
                roi=roi,
                synth_loc_map=synth_loc_map,
                synth_tile_map=synth_tile_map,
                tile_types=tile_types,
        ):
            single_xml = ET.SubElement(
                fixed_layout_xml, 'single', {
                    'priority': '1',
                    'type': vpr_tile_type,
                    'x': str(grid_x),
                    'y': str(grid_y),
                }
            )
            metadata_function(single_xml)

        switchlist_xml = ET.SubElement(arch_xml, 'switchlist')

        for name, internal_capacitance, drive_resistance, intrinsic_delay, \
                switch_type in c.execute("""
SELECT
    name,
    internal_capacitance,
    drive_resistance,
    intrinsic_delay,
    switch_type
FROM
    switch;"""):
            attrib = {
                'type': switch_type,
                'name': name,
                "R": str(drive_resistance),
                "Cin": str(0),
                "Cout": str(0),
                "Tdel": str(intrinsic_delay),
            }

            if internal_capacitance != 0:
                attrib["Cinternal"] = str(internal_capacitance)

            if False:
                attrib["mux_trans_size"] = str(0)
                attrib["buf_size"] = str(0)

            ET.SubElement(switchlist_xml, 'switch', attrib)

        segmentlist_xml = ET.SubElement(arch_xml, 'segmentlist')

        # VPR requires a segment, so add one.
        dummy_xml = ET.SubElement(
            segmentlist_xml, 'segment', {
                'name': 'dummy',
                'length': '2',
                'freq': '1.0',
                'type': 'bidir',
                'Rmetal': '0',
                'Cmetal': '0',
            }
        )
        ET.SubElement(dummy_xml, 'wire_switch', {
            'name': 'buffer',
        })
        ET.SubElement(dummy_xml, 'opin_switch', {
            'name': 'buffer',
        })
        ET.SubElement(dummy_xml, 'sb', {
            'type': 'pattern',
        }).text = ' '.join('1' for _ in range(3))
        ET.SubElement(dummy_xml, 'cb', {
            'type': 'pattern',
        }).text = ' '.join('1' for _ in range(2))

        for (name, length) in c.execute("SELECT name, length FROM segment"):
            if length is None:
                length = 1

            segment_xml = ET.SubElement(
                segmentlist_xml, 'segment', {
                    'name': name,
                    'length': str(length),
                    'freq': '1.0',
                    'type': 'bidir',
                    'Rmetal': '0',
                    'Cmetal': '0',
                }
            )
            ET.SubElement(segment_xml, 'wire_switch', {
                'name': 'buffer',
            })
            ET.SubElement(segment_xml, 'opin_switch', {
                'name': 'buffer',
            })
            ET.SubElement(segment_xml, 'sb', {
                'type': 'pattern',
            }).text = ' '.join('1' for _ in range(length + 1))
            ET.SubElement(segment_xml, 'cb', {
                'type': 'pattern',
            }).text = ' '.join('1' for _ in range(length))

    ET.SubElement(
        switchlist_xml,
        'switch',
        {
            'type': 'mux',
            'name': 'buffer',
            "R": "551",
            "Cin": ".77e-15",
            "Cout": "4e-15",
            # TODO: This value should be the "typical" pip switch delay from
            # This value is the dominate term in the inter-cluster delay
            # estimate.
            "Tdel": "0.178e-9",
            "mux_trans_size": "2.630740",
            "buf_size": "27.645901"
        }
    )

    device_xml = ET.SubElement(arch_xml, 'device')

    ET.SubElement(
        device_xml, 'sizing', {
            "R_minW_nmos": "6065.520020",
            "R_minW_pmos": "18138.500000",
        }
    )
    ET.SubElement(device_xml, 'area', {
        "grid_logic_tile_area": "14813.392",
    })
    ET.SubElement(
        device_xml, 'connection_block', {
            "input_switch_name": "buffer",
        }
    )
    ET.SubElement(device_xml, 'switch_block', {
        "type": "wilton",
        "fs": "3",
    })
    chan_width_distr_xml = ET.SubElement(device_xml, 'chan_width_distr')

    ET.SubElement(
        chan_width_distr_xml, 'x', {
            'distr': 'uniform',
            'peak': '1.0',
        }
    )
    ET.SubElement(
        chan_width_distr_xml, 'y', {
            'distr': 'uniform',
            'peak': '1.0',
        }
    )

    directlist_xml = ET.SubElement(arch_xml, 'directlist')

    pin_assignments = json.load(args.pin_assignments)

    # Choose smallest distance for block to block connections with multiple
    # direct_connections.  VPR cannot handle multiple block to block connections.
    directs = {}
    for direct in pin_assignments['direct_connections']:
        key = (direct['from_pin'], direct['to_pin'])

        if key not in directs:
            directs[key] = []

        directs[key].append(
            (abs(direct['x_offset']) + abs(direct['y_offset']), direct)
        )

    for direct in directs.values():
        _, direct = min(direct, key=lambda v: v[0])

        if direct['from_pin'].split('.')[0] not in tile_types:
            continue
        if direct['to_pin'].split('.')[0] not in tile_types:
            continue

        if direct['x_offset'] == 0 and direct['y_offset'] == 0:
            continue

        ET.SubElement(
            directlist_xml, 'direct', {
                'name':
                    '{}_to_{}_dx_{}_dy_{}'.format(
                        direct['from_pin'], direct['to_pin'],
                        direct['x_offset'], direct['y_offset']
                    ),
                'from_pin':
                    add_vpr_tile_prefix(direct['from_pin']),
                'to_pin':
                    add_vpr_tile_prefix(direct['to_pin']),
                'x_offset':
                    str(direct['x_offset']),
                'y_offset':
                    str(direct['y_offset']),
                'z_offset':
                    '0',
                'switch_name':
                    direct['switch_name'],
            }
        )

    arch_xml_str = ET.tostring(arch_xml, pretty_print=True).decode('utf-8')
    args.output_arch.write(arch_xml_str)
    args.output_arch.close()
示例#8
0
def get_tiles(
        conn, g, roi, synth_loc_map, synth_tile_map, tile_types, tile_capacity
):
    """ Yields tiles in grid.

    Yields
    ------
    vpr_tile_type : str
        VPR tile type at this grid location.
    grid_x, grid_y : int
        Grid coordinate of tile
    metadata_function : function that takes lxml.Element
        Function for attaching metadata tags to <single> elements.
        Function must be supplied, but doesn't need to add metadata if not
        required.

    """
    c = conn.cursor()
    c2 = conn.cursor()

    only_emit_roi = roi is not None

    for tile_pkey, grid_x, grid_y, phy_tile_pkey, tile_type_pkey, site_as_tile_pkey in c.execute(
            """
        SELECT pkey, grid_x, grid_y, phy_tile_pkey, tile_type_pkey, site_as_tile_pkey FROM tile
        """):

        if phy_tile_pkey is not None:
            c2.execute(
                "SELECT prohibited FROM site_instance WHERE phy_tile_pkey = ?",
                (phy_tile_pkey, )
            )

            any_prohibited_sites = any(
                prohibited for (prohibited, ) in c2.fetchall()
            )

            # Skip generation of tiles containing prohibited sites
            if any_prohibited_sites:
                continue

        # Just output synth tiles, no additional processing is required here.
        if (grid_x, grid_y) in synth_loc_map:
            vpr_tile_type = synth_loc_map[(grid_x, grid_y)]

            yield vpr_tile_type, grid_x, grid_y, lambda x: None
            continue

        c2.execute(
            "SELECT name FROM tile_type WHERE pkey = ?", (tile_type_pkey, )
        )
        tile_type = c2.fetchone()[0]
        if tile_type not in tile_types:
            # We don't want this tile
            continue

        if only_emit_roi and not is_in_roi(conn, roi, tile_pkey):
            # Tile is outside ROI, skip it
            continue

        vpr_tile_type = add_vpr_tile_prefix(tile_type)

        # For Zynq PSS* tiles do not emit fasm prefixes
        if tile_type.startswith('PSS'):

            def get_none_tile_prefix(single_xml):
                return None

            meta_fun = get_none_tile_prefix
        else:
            meta_fun = get_fasm_tile_prefix(
                conn, g, tile_pkey, site_as_tile_pkey, tile_capacity[tile_type]
            )

        yield vpr_tile_type, grid_x, grid_y, meta_fun