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)
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
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))
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())
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()
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)
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)
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)