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