| #!/usr/bin/env python3 | |
| """ | |
| Import the physical tile information from Project X-Ray database | |
| files. | |
| Project X-Ray specifies the connections between tiles and the connect | |
| between tiles and their sites. prjxray_tile_type_import generates a VPR tile | |
| that has the correct tile pin location, switchblock location and fc information. | |
| Optionally, if there are available equivalent tiles, the tile information is filled | |
| with the equivalent tile pin mapping as well. This is needed by VPR to have a correct | |
| translation of the pin names when using the equivalent tile. | |
| """ | |
| from __future__ import print_function | |
| import argparse | |
| import sys | |
| import copy | |
| import simplejson as json | |
| from lib.pb_type_xml import add_fc, add_vpr_tile_prefix, add_pinlocations, add_switchblock_locations | |
| import lxml.etree as ET | |
| XI_URL = "http://www.w3.org/2001/XInclude" | |
| # Macros used to select relevant port names | |
| PORT_TAGS = ['input', 'output', 'clock'] | |
| 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: | |
| 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): | |
| """ 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': add_vpr_tile_prefix(eq_site), | |
| 'pin_mapping': 'custom' | |
| } | |
| ) | |
| 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': add_vpr_tile_prefix(tile_name), | |
| }, | |
| nsmap={'xi': XI_URL}, | |
| ) | |
| sub_tile_xml = ET.Element( | |
| 'sub_tile', | |
| { | |
| 'name': add_vpr_tile_prefix(tile_name), | |
| }, | |
| nsmap={'xi': XI_URL}, | |
| ) | |
| add_ports(sub_tile_xml, pb_type_root) | |
| equivalent_sites = args.equivalent_sites | |
| add_equivalent_sites(sub_tile_xml, equivalent_sites) | |
| fc_xml = add_fc(sub_tile_xml) | |
| pin_assignments = json.load(args.pin_assignments) | |
| add_pinlocations(tile_name, sub_tile_xml, fc_xml, pin_assignments, ports) | |
| tile_xml.append(sub_tile_xml) | |
| 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(): | |
| parser = argparse.ArgumentParser( | |
| description=__doc__, fromfile_prefix_chars='@', prefix_chars='-~' | |
| ) | |
| parser.add_argument('--tile', help="""Tile to generate for""") | |
| parser.add_argument( | |
| '--tiles-directory', help="""Diretory where tiles are defined""" | |
| ) | |
| parser.add_argument( | |
| '--equivalent-sites', | |
| help=""" | |
| Comma separated list of equivalent sites that can be placed in this tile.""", | |
| ) | |
| parser.add_argument( | |
| '--pin-prefix', | |
| help=""" | |
| Comma separated list of prefix translation pairs for equivalent tiles.""", | |
| ) | |
| parser.add_argument( | |
| '--output-tile', | |
| 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') | |
| ) | |
| args = parser.parse_args() | |
| ET.register_namespace('xi', XI_URL) | |
| import_physical_tile(args) | |
| if __name__ == '__main__': | |
| main() |