diff --git a/vpr/src/device/rr_graph_obj.cpp b/vpr/src/device/rr_graph_obj.cpp index 316bc6e87..6a05b6a21 100644 --- a/vpr/src/device/rr_graph_obj.cpp +++ b/vpr/src/device/rr_graph_obj.cpp @@ -194,6 +194,11 @@ float RRGraph::node_C(const RRNodeId& node) const { return node_Cs_[node]; } +short RRGraph::node_rc_data_index(const RRNodeId& node) const { + VTR_ASSERT_SAFE(valid_node_id(node)); + return node_rc_data_indices_[node]; +} + /* * Get a segment id of a node in rr_graph */ @@ -769,6 +774,7 @@ void RRGraph::reserve_nodes(const unsigned long& num_nodes) { this->node_sides_.reserve(num_nodes); this->node_Rs_.reserve(num_nodes); this->node_Cs_.reserve(num_nodes); + this->node_rc_data_indices_.reserve(num_nodes); this->node_segments_.reserve(num_nodes); /* Edge-related vectors */ @@ -818,6 +824,7 @@ RRNodeId RRGraph::create_node(const t_rr_type& type) { node_sides_.push_back(NUM_SIDES); node_Rs_.push_back(0.); node_Cs_.push_back(0.); + node_rc_data_indices_.push_back(-1); node_segments_.push_back(RRSegmentId::INVALID()); node_edges_.emplace_back(); //Initially empty @@ -1028,6 +1035,12 @@ void RRGraph::set_node_C(const RRNodeId& node, const float& C) { node_Cs_[node] = C; } +void RRGraph::set_node_rc_data_index(const RRNodeId& node, const short& rc_data_index) { + VTR_ASSERT(valid_node_id(node)); + + node_rc_data_indices_[node] = rc_data_index; +} + /* * Set a segment id for a node in rr_graph */ diff --git a/vpr/src/device/rr_graph_obj.h b/vpr/src/device/rr_graph_obj.h index 85bf7de4b..abafa59b6 100644 --- a/vpr/src/device/rr_graph_obj.h +++ b/vpr/src/device/rr_graph_obj.h @@ -454,6 +454,13 @@ class RRGraph { /* Get capacitance of a node, used to built RC tree for timing analysis */ float node_C(const RRNodeId& node) const; + /* Get the index of rc data in the list of rc_data data structure + * It contains the RC parasitics for different nodes in the RRGraph + * when used in evaluate different routing paths + * See cross-reference section in this header file for more details + */ + short node_rc_data_index(const RRNodeId& node) const; + /* Get segment id of a node, containing the information of the routing * segment that the node represents. See more details in the data structure t_segment_inf */ @@ -694,6 +701,10 @@ class RRGraph { void set_node_R(const RRNodeId& node, const float& R); void set_node_C(const RRNodeId& node, const float& C); + /* Set the flyweight RC data index for node, see node_rc_data_index() for details */ + /* TODO: the cost index should be changed to a StrongId!!! */ + void set_node_rc_data_index(const RRNodeId& node, const short& rc_data_index); + /* Set the routing segment linked to a node, only applicable to CHANX and CHANY */ void set_node_segment(const RRNodeId& node, const RRSegmentId& segment_index); @@ -841,6 +852,7 @@ class RRGraph { vtr::vector node_sides_; vtr::vector node_Rs_; vtr::vector node_Cs_; + vtr::vector node_rc_data_indices_; vtr::vector node_segments_; /* Segment ids for each node */ /* diff --git a/vpr/src/route/rr_graph_timing_params.cpp b/vpr/src/route/rr_graph_timing_params.cpp index 69ea0203a..8d581f957 100644 --- a/vpr/src/route/rr_graph_timing_params.cpp +++ b/vpr/src/route/rr_graph_timing_params.cpp @@ -28,14 +28,14 @@ void add_rr_graph_C_from_switches(float C_ipin_cblock) { * INCLUDE_TRACK_BUFFERS) */ int switch_index, maxlen; - size_t to_node; + RRNodeId to_node; int icblock, isblock, iseg_low, iseg_high; float Cin, Cout; t_rr_type from_rr_type, to_rr_type; bool* cblock_counted; /* [0..maxlen-1] -- 0th element unused. */ float* buffer_Cin; /* [0..maxlen-1] */ bool buffered; - float* Couts_to_add; /* UDSD */ + vtr::vector Couts_to_add; /* UDSD */ auto& device_ctx = g_vpr_ctx.device(); auto& mutable_device_ctx = g_vpr_ctx.mutable_device(); @@ -44,21 +44,21 @@ void add_rr_graph_C_from_switches(float C_ipin_cblock) { cblock_counted = (bool*)vtr::calloc(maxlen, sizeof(bool)); buffer_Cin = (float*)vtr::calloc(maxlen, sizeof(float)); - std::vector rr_node_C(device_ctx.rr_nodes.size(), 0.); //Stores the final C + vtr::vector rr_node_C(device_ctx.rr_graph.nodes().size(), 0.); //Stores the final C - for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); inode++) { + for (const RRNodeId& inode : device_ctx.rr_graph.nodes()) { //The C may have already been partly initialized (e.g. with metal capacitance) - rr_node_C[inode] += device_ctx.rr_nodes[inode].C(); + rr_node_C[inode] += device_ctx.rr_graph.node_C(inode); - from_rr_type = device_ctx.rr_nodes[inode].type(); + from_rr_type = device_ctx.rr_graph.node_type(inode); if (from_rr_type == CHANX || from_rr_type == CHANY) { - for (t_edge_size iedge = 0; iedge < device_ctx.rr_nodes[inode].num_edges(); iedge++) { - to_node = device_ctx.rr_nodes[inode].edge_sink_node(iedge); - to_rr_type = device_ctx.rr_nodes[to_node].type(); + for (const RREdgeId& iedge : device_ctx.rr_graph.node_out_edges(inode)) { + to_node = device_ctx.rr_graph.edge_sink_node(iedge); + to_rr_type = device_ctx.rr_graph.node_type(to_node); if (to_rr_type == CHANX || to_rr_type == CHANY) { - switch_index = device_ctx.rr_nodes[inode].edge_switch(iedge); + switch_index = (int)size_t(device_ctx.rr_graph.edge_switch(iedge)); Cin = device_ctx.rr_switch_inf[switch_index].Cin; Cout = device_ctx.rr_switch_inf[switch_index].Cout; buffered = device_ctx.rr_switch_inf[switch_index].buffered(); @@ -80,14 +80,14 @@ void add_rr_graph_C_from_switches(float C_ipin_cblock) { * the buffers at that location have different sizes, I use the * * input capacitance of the largest one. */ - if (!buffered && inode < to_node) { /* Pass transistor. */ + if (!buffered && size_t(inode) < size_t(to_node)) { /* Pass transistor. */ rr_node_C[inode] += Cin; rr_node_C[to_node] += Cout; } else if (buffered) { /* Prevent double counting of capacitance for UDSD */ - if (device_ctx.rr_nodes[to_node].direction() == BI_DIRECTION) { + if (device_ctx.rr_graph.node_direction(to_node) == BI_DIRECTION) { /* For multiple-driver architectures the output capacitance can * be added now since each edge is actually a driver */ rr_node_C[to_node] += Cout; @@ -129,11 +129,11 @@ void add_rr_graph_C_from_switches(float C_ipin_cblock) { * } */ if (from_rr_type == CHANX) { - iseg_low = device_ctx.rr_nodes[inode].xlow(); - iseg_high = device_ctx.rr_nodes[inode].xhigh(); + iseg_low = device_ctx.rr_graph.node_xlow(inode); + iseg_high = device_ctx.rr_graph.node_xhigh(inode); } else { /* CHANY */ - iseg_low = device_ctx.rr_nodes[inode].ylow(); - iseg_high = device_ctx.rr_nodes[inode].yhigh(); + iseg_low = device_ctx.rr_graph.node_ylow(inode); + iseg_high = device_ctx.rr_graph.node_yhigh(inode); } for (icblock = iseg_low; icblock <= iseg_high; icblock++) { @@ -148,17 +148,17 @@ void add_rr_graph_C_from_switches(float C_ipin_cblock) { } /* End node is CHANX or CHANY */ else if (from_rr_type == OPIN) { - for (t_edge_size iedge = 0; iedge < device_ctx.rr_nodes[inode].num_edges(); iedge++) { - switch_index = device_ctx.rr_nodes[inode].edge_switch(iedge); - to_node = device_ctx.rr_nodes[inode].edge_sink_node(iedge); - to_rr_type = device_ctx.rr_nodes[to_node].type(); + for (const RREdgeId& iedge : device_ctx.rr_graph.node_out_edges(inode)) { + switch_index = (int)size_t(device_ctx.rr_graph.edge_switch(iedge)); + to_node = device_ctx.rr_graph.edge_sink_node(iedge); + to_rr_type = device_ctx.rr_graph.node_type(to_node); if (to_rr_type != CHANX && to_rr_type != CHANY) continue; - if (device_ctx.rr_nodes[to_node].direction() == BI_DIRECTION) { + if (device_ctx.rr_graph.node_direction(to_node) == BI_DIRECTION) { Cout = device_ctx.rr_switch_inf[switch_index].Cout; - to_node = device_ctx.rr_nodes[inode].edge_sink_node(iedge); /* Will be CHANX or CHANY */ + to_node = device_ctx.rr_graph.edge_sink_node(iedge); /* Will be CHANX or CHANY */ rr_node_C[to_node] += Cout; } } @@ -170,30 +170,30 @@ void add_rr_graph_C_from_switches(float C_ipin_cblock) { * Current structures only keep switch information from a node to the next node and * not the reverse. Therefore I need to go through all the possible edges to figure * out what the Cout's should be */ - Couts_to_add = (float*)vtr::calloc(device_ctx.rr_nodes.size(), sizeof(float)); - for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); inode++) { - for (t_edge_size iedge = 0; iedge < device_ctx.rr_nodes[inode].num_edges(); iedge++) { - switch_index = device_ctx.rr_nodes[inode].edge_switch(iedge); - to_node = device_ctx.rr_nodes[inode].edge_sink_node(iedge); - to_rr_type = device_ctx.rr_nodes[to_node].type(); + Couts_to_add.resize(device_ctx.rr_graph.nodes().size(), 0.); + for (const RRNodeId& inode : device_ctx.rr_graph.nodes()) { + for (const RREdgeId& iedge : device_ctx.rr_graph.node_out_edges(inode)) { + switch_index = (int)size_t(device_ctx.rr_graph.edge_switch(iedge)); + to_node = device_ctx.rr_graph.edge_sink_node(iedge); + to_rr_type = device_ctx.rr_graph.node_type(to_node); if (to_rr_type == CHANX || to_rr_type == CHANY) { - if (device_ctx.rr_nodes[to_node].direction() != BI_DIRECTION) { + if (device_ctx.rr_graph.node_direction(to_node) != BI_DIRECTION) { /* Cout was not added in these cases */ Couts_to_add[to_node] = std::max(Couts_to_add[to_node], device_ctx.rr_switch_inf[switch_index].Cout); } } } } - for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); inode++) { + for (const RRNodeId& inode : device_ctx.rr_graph.nodes()) { rr_node_C[inode] += Couts_to_add[inode]; } //Create the final flywieghted t_rr_rc_data - for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); inode++) { - mutable_device_ctx.rr_nodes[inode].set_rc_index(find_create_rr_rc_data(device_ctx.rr_nodes[inode].R(), rr_node_C[inode])); + for (const RRNodeId& inode : device_ctx.rr_graph.nodes()) { + mutable_device_ctx.rr_graph.set_node_rc_data_index(inode, find_create_rr_rc_data(device_ctx.rr_graph.node_R(inode), rr_node_C[inode])); } - free(Couts_to_add); + Couts_to_add.clear(); free(cblock_counted); free(buffer_Cin); }