Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable bitstream generation with flat routing #1866

Merged
merged 1 commit into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions openfpga/src/annotation/annotate_rr_graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,12 @@ 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
Expand Down
120 changes: 16 additions & 104 deletions openfpga/src/annotation/openfpga_annotate_routing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#include "openfpga_annotate_routing.h"

#include "annotate_routing.h"
#include "old_traceback.h"
#include "route_utils.h"
#include "vtr_assert.h"
#include "vtr_log.h"
#include "vtr_time.h"
Expand Down Expand Up @@ -123,130 +123,42 @@ void annotate_vpr_rr_node_nets(const DeviceContext& device_ctx,
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
* - 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()) {
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;
auto& tree = get_route_tree_from_cluster_net_id(net_id);
if (!tree) {
continue;
}

/* Move on to the next */
tptr = tptr->next;
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);
Expand Down
1 change: 0 additions & 1 deletion openfpga/src/annotation/openfpga_annotate_routing.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ void annotate_vpr_rr_node_nets(const DeviceContext& device_ctx,

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);

} /* end namespace openfpga */
Expand Down
1 change: 0 additions & 1 deletion openfpga/src/base/openfpga_link_arch_template.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ int link_arch_template(T& openfpga_ctx, const Command& cmd,
cmd_context.option_enable(cmd, opt_verbose));

annotate_rr_node_previous_nodes(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));

Expand Down
9 changes: 8 additions & 1 deletion openfpga/src/mux_lib/mux_library_builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,18 @@ 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) */
auto switch_name = rr_graph.rr_switch_inf(driver_switches[0]).name;
if (switch_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(
"Unable to find the circuit model for rr_switch '%s'!\n",
rr_graph.rr_switch_inf(driver_switches[0]).name.c_str());
switch_name.c_str());
VTR_LOG("Node type: %s\n", rr_graph.node_type_string(node));
VTR_LOG("Node coordinate: %s\n",
rr_graph.node_coordinate_to_string(node).c_str());
Expand Down
Loading