def create_const_connectors(conn):
    c = conn.cursor()
    c.execute("""
SELECT vcc_track_pkey, gnd_track_pkey FROM constant_sources;
    """)
    vcc_track_pkey, gnd_track_pkey = c.fetchone()

    const_connectors = {}
    const_connectors[0] = Connector(conn=conn,
                                    tracks=get_track_model(
                                        conn, gnd_track_pkey))
    const_connectors[1] = Connector(conn=conn,
                                    tracks=get_track_model(
                                        conn, vcc_track_pkey))

    return const_connectors
Exemple #2
0
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--db_root',
                        help='Project X-Ray Database',
                        required=True)
    parser.add_argument('--connection_database',
                        help='Database of fabric connectivity',
                        required=True)
    parser.add_argument(
        '--pin_assignments',
        help=
        'Output JSON assigning pins to tile types and direction connections',
        required=True)

    args = parser.parse_args()

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

    edge_assignments = {}

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

        edge_assignments, wires_in_tile_types = initialize_edge_assignments(
            db, conn)

        direct_connections = set()
        print('{} Processing direct connections.'.format(now()))
        handle_direction_connections(conn, direct_connections,
                                     edge_assignments)

        wires_not_in_channels = {}
        c = conn.cursor()
        print('{} Processing non-channel nodes.'.format(now()))
        for node_pkey, classification in progressbar_utils.progressbar(
                c.execute(
                    """
    SELECT pkey, classification FROM node WHERE classification != ?;
    """, (NodeClassification.CHANNEL.value, ))):
            reason = NodeClassification(classification)

            for (tile_type,
                 wire) in yield_logical_wire_info_from_node(conn, node_pkey):
                key = (tile_type, wire)

                # Sometimes nodes in particular tile instances are disconnected,
                # disregard classification changes if this is the case.
                if reason != NodeClassification.NULL:
                    if key not in wires_not_in_channels:
                        wires_not_in_channels[key] = reason
                    else:
                        other_reason = wires_not_in_channels[key]
                        assert reason == other_reason, (tile_type, wire,
                                                        reason, other_reason)

                if key in wires_in_tile_types:
                    wires_in_tile_types.remove(key)

        # List of nodes that are channels.
        channel_nodes = []

        # Map of (tile, wire) to track.  This will be used to find channels for pips
        # that come from EDGES_TO_CHANNEL.
        channel_wires_to_tracks = {}

        # Generate track models and verify that wires are either in a channel
        # or not in a channel.
        print('{} Creating models from tracks.'.format(now()))
        for node_pkey, track_pkey in progressbar_utils.progressbar(
                c.execute(
                    """
    SELECT pkey, track_pkey FROM node WHERE classification = ?;
    """, (NodeClassification.CHANNEL.value, ))):
            assert track_pkey is not None

            tracks_model, _ = get_track_model(conn, track_pkey)
            channel_nodes.append(tracks_model)
            channel_wires_to_tracks[track_pkey] = tracks_model

            for (tile_type,
                 wire) in yield_logical_wire_info_from_node(conn, node_pkey):
                key = (tile_type, wire)
                # Make sure all wires in channels always are in channels
                assert key not in wires_not_in_channels

                if key in wires_in_tile_types:
                    wires_in_tile_types.remove(key)

        # Make sure all wires appear to have been assigned.
        if len(wires_in_tile_types) > 0:
            for tile_type, wire in sorted(wires_in_tile_types):
                print(tile_type, wire)

        assert len(wires_in_tile_types) == 0

        # Verify that all tracks are sane.
        for node in channel_nodes:
            node.verify_tracks()

        null_tile_wires = set()

        # Verify that all nodes that are classified as edges to channels have at
        # least one site, and at least one live connection to a channel.
        #
        # If no live connections from the node are present, this node should've
        # been marked as NULL during channel formation.
        print('{} Handling edges to channels.'.format(now()))
        handle_edges_to_channels(conn, null_tile_wires, edge_assignments,
                                 channel_wires_to_tracks)

        print('{} Processing edge assignments.'.format(now()))
        final_edge_assignments = {}
        for key, available_pins in progressbar_utils.progressbar(
                edge_assignments.items()):
            (tile_type, wire) = key

            available_pins = [pins for pins in available_pins if len(pins) > 0]
            if len(available_pins) == 0:
                if (tile_type, wire) not in null_tile_wires:
                    # TODO: Figure out what is going on with these wires.  Appear to
                    # tile internal connections sometimes?
                    print((tile_type, wire))

                final_edge_assignments[key] = [tracks.Direction.RIGHT]
                continue

            pins = set(available_pins[0])
            for p in available_pins[1:]:
                pins &= set(p)

            if len(pins) > 0:
                final_edge_assignments[key] = [list(pins)[0]]
            else:
                # More than 2 pins are required, final the minimal number of pins
                pins = set()
                for p in available_pins:
                    pins |= set(p)

                while len(pins) > 2:
                    pins = list(pins)

                    prev_len = len(pins)

                    for idx in range(len(pins)):
                        pins_subset = list(pins)
                        del pins_subset[idx]

                        pins_subset = set(pins_subset)

                        bad_subset = False
                        for p in available_pins:
                            if len(pins_subset & set(p)) == 0:
                                bad_subset = True
                                break

                        if not bad_subset:
                            pins = list(pins_subset)
                            break

                    # Failed to remove any pins, stop.
                    if len(pins) == prev_len:
                        break

                final_edge_assignments[key] = pins

        for key, available_pins in edge_assignments.items():
            (tile_type, wire) = key
            pins = set(final_edge_assignments[key])

            for required_pins in available_pins:
                if len(required_pins) == 0:
                    continue

                assert len(pins & set(required_pins)) > 0, (tile_type, wire,
                                                            pins,
                                                            required_pins,
                                                            available_pins)

        pin_directions = {}
        for key, pins in progressbar_utils.progressbar(
                final_edge_assignments.items()):
            (tile_type, wire) = key
            if tile_type not in pin_directions:
                pin_directions[tile_type] = {}

            pin_directions[tile_type][wire] = [pin._name_ for pin in pins]

        with open(args.pin_assignments, 'w') as f:
            json.dump(
                {
                    'pin_directions':
                    pin_directions,
                    'direct_connections':
                    [d._asdict() for d in direct_connections],
                },
                f,
                indent=2)

        print('{} Flushing database back to file "{}"'.format(
            now(), args.connection_database))
Exemple #3
0
    def find_connector(wire_pkey, node_pkey):
        """ Finds Connector for a wire and node in the database.

        Args:
            wire_pkey (int): Primary key into wire table of target wire
            node_pkey (int): Primary key into node table of parent node of
                specified wire.

        Returns:
            None if wire is disconnected, otherwise returns Connector objet.
        """

        # Find all graph_nodes for this node.
        c.execute(
            """
        SELECT pkey, track_pkey, graph_node_type, x_low, x_high, y_low, y_high FROM graph_node
        WHERE node_pkey = ?;""", (node_pkey, ))

        graph_nodes = c.fetchall()

        # If there are no graph nodes, this wire is likely disconnected.
        if len(graph_nodes) == 0:
            return

        # If this is a track (e.g. track_pkey is not NULL), then verify
        # all graph_nodes for the specified node belong to the same track,
        # and then retrieved and return the connector for the track.
        track_pkey = graph_nodes[0][1]
        if track_pkey is not None:
            for node in graph_nodes:
                assert node[1] == track_pkey

            return Connector(tracks=get_track_model(conn, track_pkey))

        # This is not a track, so it must be a site pin.  Make sure the
        # graph_nodes share a type and verify that it is in fact a site pin.
        node_type = graph2.NodeType(graph_nodes[0][2])
        for node in graph_nodes:
            assert node_type == graph2.NodeType(node[2])

        assert node_type in [graph2.NodeType.IPIN, graph2.NodeType.OPIN]
        if node_type == graph2.NodeType.IPIN:
            site_pin_direction = SitePinDirection.IN
        elif node_type == graph2.NodeType.OPIN:
            site_pin_direction = SitePinDirection.OUT
        else:
            assert False, node_type

        # Build the edge_map (map of edge direction to graph node).
        c.execute(
            """
SELECT
  top_graph_node_pkey,
  bottom_graph_node_pkey,
  left_graph_node_pkey,
  right_graph_node_pkey
FROM
  wire
WHERE
  node_pkey = ?;""", (node_pkey, ))

        all_graph_node_pkeys = c.fetchall()

        graph_node_pkeys = None
        for keys in all_graph_node_pkeys:
            if any(keys):
                assert graph_node_pkeys is None
                graph_node_pkeys = keys

        # This wire may not have an connections, if so return now.
        if graph_node_pkeys is None:
            return

        edge_map = {}

        for edge, graph_node in zip(
            (
                tracks.Direction.TOP,
                tracks.Direction.BOTTOM,
                tracks.Direction.LEFT,
                tracks.Direction.RIGHT,
            ),
                graph_node_pkeys,
        ):
            if graph_node is not None:
                edge_map[edge] = graph_node

        assert len(edge_map) == len(graph_nodes), (edge_map, graph_node_pkeys,
                                                   graph_nodes)

        # Make sure that all graph nodes for this wire are in the edge_map
        # and at the same grid coordinate.
        x = graph_nodes[0][3]
        y = graph_nodes[0][5]
        for pkey, _, _, x_low, x_high, y_low, y_high in graph_nodes:
            assert x == x_low, (wire_pkey, node_pkey, x, x_low, x_high)
            assert x == x_high, (wire_pkey, node_pkey, x, x_low, x_high)

            assert y == y_low, (wire_pkey, node_pkey, y, y_low, y_high)
            assert y == y_high, (wire_pkey, node_pkey, y, y_low, y_high)

            assert pkey in edge_map.values(), (pkey, edge_map)

        return Connector(pins=Pins(
            edge_map=edge_map,
            x=x,
            y=y,
            site_pin_direction=site_pin_direction,
        ))
Exemple #4
0
def add_synthetic_edges(conn, graph, node_mapping, grid, synth_tiles):
    cur = conn.cursor()
    delayless_switch = graph.get_switch_id('__vpr_delayless_switch__')

    for tile_name, synth_tile in synth_tiles['tiles'].items():
        assert len(synth_tile['pins']) == 1
        for pin in synth_tile['pins']:
            if pin['port_type'] in ['input', 'output']:
                wire_pkey = get_wire_pkey(conn, tile_name, pin['wire'])
                cur.execute(
                    """
SELECT
  track_pkey
FROM
  node
WHERE
  pkey = (
    SELECT
      node_pkey
    FROM
      wire
    WHERE
      pkey = ?
  );""", (wire_pkey, ))
                (track_pkey, ) = cur.fetchone()
                assert track_pkey is not None, (tile_name, pin['wire'],
                                                wire_pkey)
            elif pin['port_type'] == 'VCC':
                cur.execute('SELECT vcc_track_pkey FROM constant_sources')
                (track_pkey, ) = cur.fetchone()
            elif pin['port_type'] == 'GND':
                cur.execute('SELECT gnd_track_pkey FROM constant_sources')
                (track_pkey, ) = cur.fetchone()
            else:
                assert False, pin['port_type']
            tracks_model, track_nodes = get_track_model(conn, track_pkey)

            option = list(
                tracks_model.get_tracks_for_wire_at_coord(
                    tuple(synth_tile['loc'])).values())
            assert len(option) > 0, (pin, len(option))

            if pin['port_type'] == 'input':
                tile_type = 'SYN-OUTPAD'
                wire = 'outpad'
            elif pin['port_type'] == 'output':
                tile_type = 'SYN-INPAD'
                wire = 'inpad'
            elif pin['port_type'] == 'VCC':
                tile_type = 'SYN-VCC'
                wire = 'VCC'
            elif pin['port_type'] == 'GND':
                tile_type = 'SYN-GND'
                wire = 'GND'
            else:
                assert False, pin

            track_node = track_nodes[option[0]]
            assert track_node in node_mapping, (track_node, track_pkey)
            pin_name = graph.create_pin_name_from_tile_type_and_pin(
                tile_type, wire)

            pin_node = graph.get_nodes_for_pin(tuple(synth_tile['loc']),
                                               pin_name)

            if pin['port_type'] == 'input':
                graph.add_edge(
                    src_node=node_mapping[track_node],
                    sink_node=pin_node[0][0],
                    switch_id=delayless_switch,
                    name='synth_{}_{}'.format(tile_name, pin['wire']),
                )
            elif pin['port_type'] in ['VCC', 'GND', 'output']:
                graph.add_edge(
                    src_node=pin_node[0][0],
                    sink_node=node_mapping[track_node],
                    switch_id=delayless_switch,
                    name='synth_{}_{}'.format(tile_name, pin['wire']),
                )
            else:
                assert False, pin
Exemple #5
0
def add_synthetic_edges(conn, graph, node_mapping, grid, synth_tiles):
    c = conn.cursor()
    routing_switch = graph.get_switch_id('routing')

    for loc in grid.tile_locations():
        tile_name = grid.tilename_at_loc(loc)

        if tile_name in synth_tiles['tiles']:
            assert len(synth_tiles['tiles'][tile_name]['pins']) == 1
            for pin in synth_tiles['tiles'][tile_name]['pins']:
                wire_pkey = get_wire_pkey(conn, tile_name, pin['wire'])
                c.execute(
                    """
SELECT
  track_pkey
FROM
  node
WHERE
  pkey = (
    SELECT
      node_pkey
    FROM
      wire
    WHERE
      pkey = ?
  );""", (wire_pkey, ))
                (track_pkey, ) = c.fetchone()
                assert track_pkey is not None, (tile_name, pin['wire'],
                                                wire_pkey)
                tracks_model, track_nodes = get_track_model(conn, track_pkey)

                option = list(tracks_model.get_tracks_for_wire_at_coord(loc))
                assert len(option) > 0

                if pin['port_type'] == 'input':
                    tile_type = 'BLK_SY-OUTPAD'
                    wire = 'outpad'
                elif pin['port_type'] == 'output':
                    tile_type = 'BLK_SY-INPAD'
                    wire = 'inpad'
                else:
                    assert False, pin

                track_node = track_nodes[option[0][0]]
                assert track_node in node_mapping, (track_node, track_pkey)
                pin_name = graph.create_pin_name_from_tile_type_and_pin(
                    tile_type, wire)

                pin_node = graph.get_nodes_for_pin(loc, pin_name)

                if pin['port_type'] == 'input':
                    graph.add_edge(
                        src_node=node_mapping[track_node],
                        sink_node=pin_node[0][0],
                        switch_id=routing_switch,
                        name='synth_{}_{}'.format(tile_name, pin['wire']),
                    )
                elif pin['port_type'] == 'output':
                    graph.add_edge(
                        src_node=pin_node[0][0],
                        sink_node=node_mapping[track_node],
                        switch_id=routing_switch,
                        name='synth_{}_{}'.format(tile_name, pin['wire']),
                    )
                else:
                    assert False, pin