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 */
|
2022-10-06 19:08:50 -05:00
|
|
|
#include "openfpga_annotate_routing.h"
|
2020-02-05 23:12:44 -06:00
|
|
|
|
2022-08-18 21:33:56 -05:00
|
|
|
#include "annotate_routing.h"
|
2022-10-06 19:08:50 -05:00
|
|
|
#include "vtr_assert.h"
|
|
|
|
#include "vtr_log.h"
|
2020-02-05 23:12:44 -06:00
|
|
|
|
|
|
|
/* begin namespace openfpga */
|
|
|
|
namespace openfpga {
|
|
|
|
|
|
|
|
/********************************************************************
|
2022-10-06 19:08:50 -05:00
|
|
|
* Create a mapping between each rr_node and its mapped nets
|
2020-02-05 23:12:44 -06:00
|
|
|
* based on VPR routing results
|
2022-10-06 19:08:50 -05:00
|
|
|
* - Unmapped rr_node will use invalid ids
|
2020-02-05 23:12:44 -06:00
|
|
|
*******************************************************************/
|
2022-08-18 21:33:56 -05:00
|
|
|
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) {
|
2022-10-06 19:08:50 -05:00
|
|
|
vtr::vector<RRNodeId, ClusterNetId> node2net = annotate_rr_node_nets(
|
|
|
|
device_ctx, clustering_ctx, routing_ctx, verbose, false);
|
|
|
|
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),
|
|
|
|
node2net[RRNodeId(node_id)]);
|
2020-02-05 23:12:44 -06:00
|
|
|
}
|
2022-08-18 21:33:56 -05:00
|
|
|
VTR_LOG("Loaded node-to-net mapping\n");
|
2020-02-05 23:12:44 -06:00
|
|
|
}
|
|
|
|
|
2020-06-17 12:17:57 -05:00
|
|
|
/********************************************************************
|
|
|
|
* 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
|
|
|
|
*******************************************************************/
|
2022-10-06 19:08:50 -05:00
|
|
|
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) {
|
2020-06-17 12:17:57 -05:00
|
|
|
RRNodeId prev_node = prev_node_candidate;
|
|
|
|
|
2022-10-06 19:08:50 -05:00
|
|
|
/* For a valid prev_node, ensure prev node is one of the driving nodes for
|
|
|
|
* this rr_node! */
|
2020-06-17 12:17:57 -05:00
|
|
|
if (prev_node) {
|
2022-10-06 19:08:50 -05:00
|
|
|
/* Try to spot the previous node in the incoming node list of this rr_node
|
|
|
|
*/
|
2020-06-17 12:17:57 -05:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2022-10-06 19:08:50 -05:00
|
|
|
/* If we cannot find one, it could be possible that this rr_node branches
|
2020-06-17 12:17:57 -05:00
|
|
|
* from an earlier point in the routing tree
|
|
|
|
*
|
|
|
|
* +----- ... --->prev_node
|
|
|
|
* |
|
|
|
|
* src_node->+
|
|
|
|
* |
|
|
|
|
* +-----+ rr_node
|
|
|
|
*
|
2022-10-06 19:08:50 -05:00
|
|
|
* Our job now is to start from the head of the traces and find the
|
|
|
|
* prev_node that drives this rr_node
|
2020-06-17 12:17:57 -05:00
|
|
|
*
|
|
|
|
* This search will find the first-fit and finish.
|
2022-10-06 19:08:50 -05:00
|
|
|
* This is reasonable because if there is a second-fit, it should be a
|
|
|
|
* longer path which should be considered in routing optimization
|
2020-06-17 12:17:57 -05:00
|
|
|
*/
|
|
|
|
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);
|
2020-06-17 12:17:57 -05:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2022-10-06 19:08:50 -05:00
|
|
|
|
2020-06-17 12:17:57 -05:00
|
|
|
if (true == is_good_cand) {
|
|
|
|
/* Update prev_node */
|
|
|
|
prev_node = cand_prev_node;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Move on to the next */
|
|
|
|
tptr = tptr->next;
|
|
|
|
}
|
2022-10-06 19:08:50 -05:00
|
|
|
}
|
2020-06-17 12:17:57 -05:00
|
|
|
}
|
|
|
|
|
2022-10-06 19:08:50 -05:00
|
|
|
return prev_node;
|
2020-06-17 12:17:57 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* 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
|
|
|
|
*******************************************************************/
|
2022-10-06 19:08:50 -05:00
|
|
|
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) {
|
2020-06-17 12:17:57 -05:00
|
|
|
size_t counter = 0;
|
|
|
|
VTR_LOG("Annotating previous nodes for rr_node...");
|
|
|
|
VTR_LOGV(verbose, "\n");
|
2022-10-06 19:08:50 -05:00
|
|
|
|
2020-06-17 12:17:57 -05:00
|
|
|
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;
|
|
|
|
}
|
2022-10-06 19:08:50 -05:00
|
|
|
|
2020-06-17 12:17:57 -05:00
|
|
|
/* Cache Previous nodes */
|
|
|
|
RRNodeId prev_node = RRNodeId::INVALID();
|
|
|
|
|
|
|
|
t_trace* tptr = routing_ctx.trace[net_id].head;
|
|
|
|
while (tptr != nullptr) {
|
2022-08-17 11:54:31 -05:00
|
|
|
RRNodeId rr_node = RRNodeId(tptr->index);
|
2020-06-17 12:17:57 -05:00
|
|
|
|
|
|
|
/* Find the right previous node */
|
2022-10-06 19:08:50 -05:00
|
|
|
prev_node = find_previous_node_from_routing_traces(
|
|
|
|
device_ctx.rr_graph, routing_ctx.trace[net_id].head, prev_node,
|
|
|
|
rr_node);
|
2020-06-17 12:17:57 -05:00
|
|
|
|
|
|
|
/* Only update mapped nodes */
|
|
|
|
if (prev_node) {
|
2022-10-06 19:08:50 -05:00
|
|
|
vpr_routing_annotation.set_rr_node_prev_node(device_ctx.rr_graph,
|
|
|
|
rr_node, prev_node);
|
2020-06-17 12:17:57 -05:00
|
|
|
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 */
|