diff --git a/openfpga/src/annotation/annotate_rr_graph.cpp b/openfpga/src/annotation/annotate_rr_graph.cpp index 5f325d0a73..d743746870 100644 --- a/openfpga/src/annotation/annotate_rr_graph.cpp +++ b/openfpga/src/annotation/annotate_rr_graph.cpp @@ -554,6 +554,11 @@ static void annotate_rr_switch_circuit_models( rr_switch_id++) { std::string switch_name( vpr_device_ctx.rr_graph.rr_switch()[RRSwitchId(rr_switch_id)].name); + + /* Skip flat router-generated internal switches */ + if(switch_name.rfind(VPR_INTERNAL_SWITCH_NAME, 0) == 0) + continue; + /* Skip the delayless switch, which is only used by the edges between * - SOURCE and OPIN * - IPIN and SINK diff --git a/openfpga/src/annotation/openfpga_annotate_routing.cpp b/openfpga/src/annotation/openfpga_annotate_routing.cpp index 384cf9041b..df022ebbaa 100644 --- a/openfpga/src/annotation/openfpga_annotate_routing.cpp +++ b/openfpga/src/annotation/openfpga_annotate_routing.cpp @@ -6,104 +6,13 @@ #include "annotate_routing.h" #include "old_traceback.h" +#include "route_util.h" #include "vtr_assert.h" #include "vtr_log.h" -#include "vtr_time.h" /* begin namespace openfpga */ namespace openfpga { -/******************************************************************** - * Create a mapping between each rr_node and its mapped nets - * - Only applicable to global nets for dedicated clock routing purpose - * - Note that this function is different than annotate_vpr_rr_nodes() - * Please do not annotate global nets in vpr_routing_annotation! - *******************************************************************/ -vtr::vector annotate_rr_node_global_net( - const DeviceContext& device_ctx, const ClusteredNetlist& cluster_nlist, - const PlacementContext& placement_ctx, - const VprClusteringAnnotation& clustering_annotation, const bool& verbose) { - vtr::vector rr_node_nets; - - size_t counter = 0; - vtr::ScopedStartFinishTimer timer("Annotating rr_node with global nets"); - - const auto& rr_graph = device_ctx.rr_graph; - - rr_node_nets.resize(rr_graph.num_nodes(), ClusterNetId::INVALID()); - - size_t layer = 0; - - for (ClusterNetId net_id : cluster_nlist.nets()) { - if (!cluster_nlist.net_is_ignored(net_id)) { - continue; - } - /* Walk through all the sinks */ - for (ClusterPinId pin_id : cluster_nlist.net_pins(net_id)) { - ClusterBlockId block_id = cluster_nlist.pin_block(pin_id); - t_block_loc blk_loc = get_block_loc(block_id, false); - int phy_pin = placement_ctx.physical_pins()[pin_id]; - t_physical_tile_type_ptr phy_tile = device_ctx.grid.get_physical_type( - t_physical_tile_loc(blk_loc.loc.x, blk_loc.loc.y, 0)); - int node_pin_num = phy_tile->num_pins; - /* Note that the phy_pin may not reflect the actual pin index at the - * top-level physical tile type. It could be one of the random pin to the - * same pin class. So here, we have to find an exact match of the pin - * index from the clustering results! */ - int subtile_idx = blk_loc.loc.sub_tile; - auto logical_block = cluster_nlist.block_type(block_id); - for (int j = 0; j < logical_block->pb_type->num_pins; j++) { - /* Find the net mapped to this pin in clustering results*/ - ClusterNetId cluster_net_id = cluster_nlist.block_net(block_id, j); - /* Get the actual net id because it may be renamed during routing */ - if (true == clustering_annotation.is_net_renamed(block_id, j)) { - cluster_net_id = clustering_annotation.net(block_id, j); - } - /* Bypass unmatched pins */ - if (cluster_net_id != net_id) { - continue; - } - int curr_pin_num = get_physical_pin_at_sub_tile_location( - phy_tile, logical_block, subtile_idx, j); - if (phy_tile->pin_class[curr_pin_num] != phy_tile->pin_class[phy_pin]) { - continue; - } - node_pin_num = curr_pin_num; - break; - } - VTR_ASSERT(node_pin_num < phy_tile->num_pins); - t_rr_type rr_pin_type = IPIN; - if (phy_tile->class_inf[phy_tile->pin_class[node_pin_num]].type == - RECEIVER) { - rr_pin_type = IPIN; - } else if (phy_tile->class_inf[phy_tile->pin_class[node_pin_num]].type == - DRIVER) { - rr_pin_type = OPIN; - } else { - VTR_LOG_ERROR( - "When annotating global net '%s', invalid rr node pin type for '%s' " - "pin '%d'\n", - cluster_nlist.net_name(net_id).c_str(), phy_tile->name, node_pin_num); - exit(1); - } - std::vector curr_rr_nodes = - rr_graph.node_lookup().find_nodes_at_all_sides( - layer, blk_loc.loc.x, blk_loc.loc.y, rr_pin_type, node_pin_num); - for (RRNodeId curr_rr_node : curr_rr_nodes) { - VTR_LOGV(verbose, "Annotate global net '%s' on '%s' pin '%d'\n", - cluster_nlist.net_name(net_id).c_str(), phy_tile->name, - node_pin_num); - rr_node_nets[curr_rr_node] = net_id; - counter++; - } - } - } - - VTR_LOGV(verbose, "Done with %d nodes mapping\n", counter); - - return rr_node_nets; -} - /******************************************************************** * Create a mapping between each rr_node and its mapped nets * based on VPR routing results @@ -111,95 +20,19 @@ vtr::vector annotate_rr_node_global_net( *******************************************************************/ void annotate_vpr_rr_node_nets(const DeviceContext& device_ctx, const ClusteringContext& clustering_ctx, - const RoutingContext& routing_ctx, VprRoutingAnnotation& vpr_routing_annotation, const bool& verbose) { - vtr::vector node2net = - annotate_rr_node_nets((const Netlist<>&)clustering_ctx.clb_nlist, - device_ctx, routing_ctx, verbose, false); + vtr::vector node2net = + annotate_rr_node_nets(clustering_ctx, device_ctx, verbose); for (size_t node_id = 0; node_id < device_ctx.rr_graph.num_nodes(); ++node_id) { vpr_routing_annotation.set_rr_node_net( RRNodeId(node_id), - convert_to_cluster_net_id(node2net[RRNodeId(node_id)])); + node2net[RRNodeId(node_id)]); } VTR_LOG("Loaded node-to-net mapping\n"); } -/******************************************************************** - * This function will find a previous node for a given rr_node - * from the routing traces - * - * It requires a candidate which provided by upstream functions - * Try to validate a candidate by searching it from driving node list - * If not validated, try to find a right one in the routing traces - *******************************************************************/ -static RRNodeId find_previous_node_from_routing_traces( - const RRGraphView& rr_graph, t_trace* routing_trace_head, - const RRNodeId& prev_node_candidate, const RRNodeId& cur_rr_node) { - RRNodeId prev_node = prev_node_candidate; - - /* For a valid prev_node, ensure prev node is one of the driving nodes for - * this rr_node! */ - if (prev_node) { - /* Try to spot the previous node in the incoming node list of this rr_node - */ - bool valid_prev_node = false; - for (const RREdgeId& in_edge : rr_graph.node_in_edges(cur_rr_node)) { - if (prev_node == rr_graph.edge_src_node(in_edge)) { - valid_prev_node = true; - break; - } - } - - /* Early exit if we already validate the node */ - if (true == valid_prev_node) { - return prev_node; - } - - /* If we cannot find one, it could be possible that this rr_node branches - * from an earlier point in the routing tree - * - * +----- ... --->prev_node - * | - * src_node->+ - * | - * +-----+ rr_node - * - * Our job now is to start from the head of the traces and find the - * prev_node that drives this rr_node - * - * This search will find the first-fit and finish. - * This is reasonable because if there is a second-fit, it should be a - * longer path which should be considered in routing optimization - */ - if (false == valid_prev_node) { - t_trace* tptr = routing_trace_head; - while (tptr != nullptr) { - RRNodeId cand_prev_node = RRNodeId(tptr->index); - bool is_good_cand = false; - for (const RREdgeId& in_edge : rr_graph.node_in_edges(cur_rr_node)) { - if (cand_prev_node == rr_graph.edge_src_node(in_edge)) { - is_good_cand = true; - break; - } - } - - if (true == is_good_cand) { - /* Update prev_node */ - prev_node = cand_prev_node; - break; - } - - /* Move on to the next */ - tptr = tptr->next; - } - } - } - - return prev_node; -} - /******************************************************************** * Create a mapping between each rr_node and its previous node * based on VPR routing results @@ -213,43 +46,27 @@ void annotate_rr_node_previous_nodes( VTR_LOG("Annotating previous nodes for rr_node..."); VTR_LOGV(verbose, "\n"); - for (auto net_id : clustering_ctx.clb_nlist.nets()) { + auto& netlist = clustering_ctx.clb_nlist; + + for (auto net_id : netlist.nets()) { /* Ignore nets that are not routed */ - if (true == clustering_ctx.clb_nlist.net_is_ignored(net_id)) { + if (true == netlist.net_is_ignored(net_id)) { continue; } /* Ignore used in local cluster only, reserved one CLB pin */ - if (false == clustering_ctx.clb_nlist.net_sinks(net_id).size()) { + if (false == netlist.net_sinks(net_id).size()) { continue; } - - /* Cache Previous nodes */ - RRNodeId prev_node = RRNodeId::INVALID(); - - t_trace* tptr = TracebackCompat::traceback_from_route_tree( - routing_ctx.route_trees[net_id].value()); - t_trace* head = tptr; - while (tptr != nullptr) { - RRNodeId rr_node = RRNodeId(tptr->index); - - /* Find the right previous node */ - prev_node = find_previous_node_from_routing_traces( - device_ctx.rr_graph, head, prev_node, rr_node); - - /* Only update mapped nodes */ - if (prev_node) { - vpr_routing_annotation.set_rr_node_prev_node(device_ctx.rr_graph, - rr_node, prev_node); - counter++; - } - - /* Update prev_node */ - prev_node = rr_node; - - /* Move on to the next */ - tptr = tptr->next; + + auto& tree = get_route_tree_from_cluster_net_id(net_id); + if(!tree) + continue; + + for(auto& rt_node: tree->all_nodes()){ + RRNodeId rr_node = rt_node.inode; + auto parent = rt_node.parent(); + vpr_routing_annotation.set_rr_node_prev_node(device_ctx.rr_graph, rr_node, parent ? parent->inode : RRNodeId::INVALID()); } - free_traceback(head); } VTR_LOG("Done with %d nodes mapping\n", counter); diff --git a/openfpga/src/annotation/openfpga_annotate_routing.h b/openfpga/src/annotation/openfpga_annotate_routing.h index 8c9f0e40a1..b8f5a83e7b 100644 --- a/openfpga/src/annotation/openfpga_annotate_routing.h +++ b/openfpga/src/annotation/openfpga_annotate_routing.h @@ -23,7 +23,6 @@ vtr::vector annotate_rr_node_global_net( void annotate_vpr_rr_node_nets(const DeviceContext& device_ctx, const ClusteringContext& clustering_ctx, - const RoutingContext& routing_ctx, VprRoutingAnnotation& vpr_routing_annotation, const bool& verbose); diff --git a/openfpga/src/base/openfpga_link_arch_template.h b/openfpga/src/base/openfpga_link_arch_template.h index 9898d5f75e..eb289c471d 100644 --- a/openfpga/src/base/openfpga_link_arch_template.h +++ b/openfpga/src/base/openfpga_link_arch_template.h @@ -90,7 +90,6 @@ int link_arch_template(T& openfpga_ctx, const Command& cmd, // rr_graph from an external file g_vpr_ctx.mutable_device().rr_graph_builder.build_in_edges(); annotate_vpr_rr_node_nets(g_vpr_ctx.device(), g_vpr_ctx.clustering(), - g_vpr_ctx.routing(), openfpga_ctx.mutable_vpr_routing_annotation(), cmd_context.option_enable(cmd, opt_verbose)); diff --git a/openfpga/src/mux_lib/mux_library_builder.cpp b/openfpga/src/mux_lib/mux_library_builder.cpp index 6b5b7bc77d..2d6e6009e3 100644 --- a/openfpga/src/mux_lib/mux_library_builder.cpp +++ b/openfpga/src/mux_lib/mux_library_builder.cpp @@ -52,6 +52,11 @@ static void build_routing_arch_mux_library( VTR_ASSERT(1 == driver_switches.size()); const CircuitModelId& rr_switch_circuit_model = vpr_device_annotation.rr_switch_circuit_model(driver_switches[0]); + + /* Skip flat router-generated internal switches (not relevant) */ + if(rr_graph.rr_switch_inf(driver_switches[0]).name.rfind(VPR_INTERNAL_SWITCH_NAME, 0) == 0) + continue; + /* we should select a circuit model for the routing resource switch */ if (CircuitModelId::INVALID() == rr_switch_circuit_model) { VTR_LOG_ERROR(