OpenFPGA/openfpga/src/annotation/openfpga_annotate_routing.cpp

184 lines
6.5 KiB
C++
Raw Normal View History

2020-02-05 23:12:44 -06:00
/********************************************************************
* This file includes functions that are used to annotate routing results
* from VPR to OpenFPGA
*******************************************************************/
/* Headers from vtrutil library */
#include "vtr_assert.h"
#include "vtr_log.h"
#include "openfpga_annotate_routing.h"
2020-02-05 23:12:44 -06:00
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* Create a mapping between each rr_node and its mapped nets
* based on VPR routing results
* - Unmapped rr_node will use invalid ids
*******************************************************************/
void annotate_rr_node_nets(const DeviceContext& device_ctx,
const ClusteringContext& clustering_ctx,
const RoutingContext& routing_ctx,
VprRoutingAnnotation& vpr_routing_annotation,
const bool& verbose) {
2020-02-05 23:12:44 -06:00
size_t counter = 0;
VTR_LOG("Annotating rr_node with routed nets...");
VTR_LOGV(verbose, "\n");
2020-02-05 23:12:44 -06:00
for (auto net_id : clustering_ctx.clb_nlist.nets()) {
2020-02-05 23:12:44 -06:00
/* Ignore nets that are not routed */
if (true == clustering_ctx.clb_nlist.net_is_ignored(net_id)) {
2020-02-05 23:12:44 -06:00
continue;
}
/* Ignore used in local cluster only, reserved one CLB pin */
if (false == clustering_ctx.clb_nlist.net_sinks(net_id).size()) {
2020-02-05 23:12:44 -06:00
continue;
}
t_trace* tptr = routing_ctx.trace[net_id].head;
2020-02-05 23:12:44 -06:00
while (tptr != nullptr) {
2022-08-16 23:05:50 -05:00
RRNodeId rr_node = RRNodeId(tptr->index);
/* Ignore source and sink nodes, they are the common node multiple starting and ending points */
if ( (SOURCE != device_ctx.rr_graph.node_type(rr_node))
&& (SINK != device_ctx.rr_graph.node_type(rr_node)) ) {
vpr_routing_annotation.set_rr_node_net(rr_node, net_id);
counter++;
}
2020-02-05 23:12:44 -06:00
tptr = tptr->next;
}
}
VTR_LOG("Done with %d nodes mapping\n", counter);
}
/********************************************************************
* 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) {
2022-08-16 23:05:50 -05:00
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
* - Unmapped rr_node will have an invalid id of previous rr_node
*******************************************************************/
void annotate_rr_node_previous_nodes(const DeviceContext& device_ctx,
const ClusteringContext& clustering_ctx,
const RoutingContext& routing_ctx,
VprRoutingAnnotation& vpr_routing_annotation,
const bool& verbose) {
size_t counter = 0;
VTR_LOG("Annotating previous nodes for rr_node...");
VTR_LOGV(verbose, "\n");
for (auto net_id : clustering_ctx.clb_nlist.nets()) {
/* Ignore nets that are not routed */
if (true == clustering_ctx.clb_nlist.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()) {
continue;
}
/* Cache Previous nodes */
RRNodeId prev_node = RRNodeId::INVALID();
t_trace* tptr = routing_ctx.trace[net_id].head;
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,
routing_ctx.trace[net_id].head,
prev_node,
rr_node);
/* Only update mapped nodes */
if (prev_node) {
vpr_routing_annotation.set_rr_node_prev_node(rr_node, prev_node);
counter++;
}
/* Update prev_node */
prev_node = rr_node;
/* Move on to the next */
tptr = tptr->next;
}
}
VTR_LOG("Done with %d nodes mapping\n", counter);
}
2020-02-05 23:12:44 -06:00
} /* end namespace openfpga */