| #!/usr/bin/env python3 |
| |
| import argparse |
| import re |
| from lib.rr_graph import graph |
| |
| |
| def inaccessible_node_ids(forward_connections, node_id, target_node_ids): |
| """ |
| Takes a mapping of forward connectionso from nodes, a starting `node_id` and |
| a set of all the target node ids for which we want to check routability. |
| Returns a set of all the target node ids that are not accessible from `node_id`. |
| """ |
| layer = [node_id] |
| visited = set() |
| layer_index = 0 |
| while layer: |
| layer_index += 1 |
| new_layer = set() |
| for this_node_id in layer: |
| new_layer |= forward_connections[this_node_id] |
| new_layer -= visited |
| visited |= new_layer |
| layer = new_layer |
| return target_node_ids - visited |
| |
| |
| def routing_graph_to_dictionary(routing_graph): |
| edge_map = routing_graph._ids_map(graph.RoutingEdge) |
| edges_by_node = routing_graph.edges_for_allnodes() |
| dict_graph = {} |
| for node in routing_graph._xml_parent(graph.RoutingNode): |
| node_id = int(node.get('id')) |
| dest_ids = set() |
| for edge_id in edges_by_node[node_id]: |
| edge = edge_map[edge_id] |
| if int(edge.get('src_node')) == node_id: |
| dest_ids.add(int(edge.get('sink_node'))) |
| dict_graph[node_id] = dest_ids |
| return dict_graph |
| |
| |
| def filter_nodes(all_node_ids, g, f): |
| node_map = g.routing._ids_map(graph.RoutingNode) |
| f = re.compile(f) |
| node_ids = set() |
| for nid in all_node_ids: |
| node = node_map[nid] |
| n = graph.RoutingGraphPrinter.node(node, g.block_grid) |
| if f.search(n): |
| print("Filtering out ", n) |
| continue |
| node_ids.add(nid) |
| return node_ids |
| |
| |
| def inaccessible_sink_node_ids_by_source_node_id(g, filter=""): |
| """ |
| Returns a dictionary that maps source node ids to sets of sink node ids |
| which are inaccessible to them. |
| If a source node id can access all sink nodes it is not present in the |
| returned dictionary. |
| """ |
| routing_graph = g.routing |
| |
| # First convert the graph to a dictionary. |
| cyclic_graph = routing_graph_to_dictionary(routing_graph) |
| |
| all_source_node_ids = set( |
| [ |
| int(node.get('id')) |
| for node in routing_graph._xml_parent(graph.RoutingNode) |
| if node.get('type') == 'SOURCE' |
| ] |
| ) |
| source_node_ids = filter_nodes(all_source_node_ids, g, filter) |
| |
| all_sink_node_ids = set( |
| [ |
| int(node.get('id')) |
| for node in routing_graph._xml_parent(graph.RoutingNode) |
| if node.get('type') == 'SINK' |
| ] |
| ) |
| sink_node_ids = filter_nodes(all_sink_node_ids, g, filter) |
| |
| inaccessible_by_source_node = {} |
| total = len(source_node_ids) |
| for index, source_node_id in enumerate(source_node_ids): |
| inaccessible_ids = inaccessible_node_ids( |
| cyclic_graph, source_node_id, target_node_ids=sink_node_ids |
| ) |
| if inaccessible_ids: |
| inaccessible_by_source_node[source_node_id] = inaccessible_ids |
| if index % 100 == 0: |
| print('Checked {}/{} source nodes'.format(index, total)) |
| return inaccessible_by_source_node |
| |
| |
| def check_graph(rr_graph_file, filter): |
| ''' |
| Check that the rr_graph has connections from all SOURCE nodes to all SINK nodes. |
| ''' |
| print('Loading the routing graph file') |
| g = graph.Graph(rr_graph_file, verbose=True, clear_fabric=False) |
| routing_graph = g.routing |
| print('Checking if all source nodes connect to all sink nodes.') |
| inaccessible_nodes = inaccessible_sink_node_ids_by_source_node_id( |
| g, filter |
| ) |
| if inaccessible_nodes: |
| print('FAIL') |
| node_map = routing_graph._ids_map(graph.RoutingNode) |
| for source_id, sink_ids in inaccessible_nodes.items(): |
| source_node = graph.RoutingGraphPrinter.node( |
| node_map[source_id], g.block_grid |
| ) |
| sink_nodes = [ |
| graph.RoutingGraphPrinter.node(node_map[i], g.block_grid) |
| for i in sink_ids |
| ] |
| |
| print('Node {} does not connect to nodes:.'.format(source_node)) |
| for n in sink_nodes: |
| print(' ', n) |
| print() |
| import pdb |
| pdb.set_trace() |
| else: |
| print('SUCCESS') |
| |
| |
| def main(): |
| parser = argparse.ArgumentParser() |
| parser.add_argument('rr_graph_file', type=str) |
| parser.add_argument('filter', type=str) |
| args = parser.parse_args() |
| check_graph(args.rr_graph_file, args.filter) |
| |
| |
| if __name__ == '__main__': |
| main() |