|  | #!/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() |