-
Notifications
You must be signed in to change notification settings - Fork 415
Deploy RRGraphBuilder
in RRGraph Clock Builder to replace the use of rr_node_indices
#1801
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
Changes from 5 commits
c37643c
e6e2a2f
8804edd
3dfafbf
1f3c410
d4a76f6
ab9dc4e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -132,6 +132,51 @@ std::vector<RRNodeId> RRSpatialLookup::find_channel_nodes(int x, | |
return channel_nodes; | ||
} | ||
|
||
std::vector<RRNodeId> RRSpatialLookup::find_sink_nodes(int x, | ||
int y) const { | ||
/* TODO: The implementation of this API should be worked | ||
* when rr_node_indices adapts RRNodeId natively! | ||
*/ | ||
std::vector<RRNodeId> sink_nodes; | ||
|
||
/* Pre-check: the x, y, type are valid! Otherwise, return an empty vector */ | ||
if (x < 0 || y < 0) { | ||
return sink_nodes; | ||
} | ||
|
||
VTR_ASSERT_SAFE(3 == rr_node_indices_[SINK].ndims()); | ||
|
||
/* Sanity check to ensure the x, y, side are in range | ||
* - Return a list of valid ids by searching in look-up when all the parameters are in range | ||
* - Return an empty list if any out-of-range is detected | ||
*/ | ||
if (size_t(SINK) >= rr_node_indices_.size()) { | ||
return sink_nodes; | ||
} | ||
|
||
if (size_t(x) >= rr_node_indices_[SINK].dim_size(0)) { | ||
return sink_nodes; | ||
} | ||
|
||
if (size_t(y) >= rr_node_indices_[SINK].dim_size(1)) { | ||
return sink_nodes; | ||
} | ||
|
||
/* By default, we always added the channel nodes to the TOP side (to save memory) */ | ||
e_side node_side = TOP; | ||
if (node_side >= rr_node_indices_[SINK].dim_size(2)) { | ||
return sink_nodes; | ||
} | ||
|
||
for (const auto& node : rr_node_indices_[SINK][x][y][node_side]) { | ||
if (RRNodeId(node)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could comment this to say you're inserting only the valid ids in the returned vector. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agree. Added the comment. |
||
sink_nodes.push_back(RRNodeId(node)); | ||
} | ||
} | ||
|
||
return sink_nodes; | ||
} | ||
|
||
std::vector<RRNodeId> RRSpatialLookup::find_nodes_at_all_sides(int x, | ||
int y, | ||
t_rr_type rr_type, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -81,6 +81,18 @@ class RRSpatialLookup { | |
int y, | ||
t_rr_type type) const; | ||
|
||
/** | ||
* Returns the indices of the specified routing resource nodes, | ||
* representing virtual sinks. | ||
* - (x, y) are the coordinate of the sink nodes within the FPGA | ||
* | ||
* Note: | ||
* - Return an empty list if there are no sinks at the given (x, y) location | ||
* - The node list returned only contain valid ids | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. typo: contain -> contains There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for pointing it out. Fixed. |
||
*/ | ||
std::vector<RRNodeId> find_sink_nodes(int x, | ||
int y) const; | ||
|
||
/** | ||
* Like find_node() but returns all matching nodes on all the sides. | ||
* This is particularly useful for getting all instances | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -52,7 +52,7 @@ void RoutingToClockConnection::create_switches(const ClockRRGraphBuilder& clock_ | |||||||||||||||
std::srand(seed); | ||||||||||||||||
|
||||||||||||||||
auto& device_ctx = g_vpr_ctx.device(); | ||||||||||||||||
auto& rr_node_indices = device_ctx.rr_node_indices; | ||||||||||||||||
const auto& node_lookup = device_ctx.rr_graph.node_lookup(); | ||||||||||||||||
|
||||||||||||||||
int virtual_clock_network_root_idx = create_virtual_clock_network_sink_node(switch_location.x, switch_location.y); | ||||||||||||||||
{ | ||||||||||||||||
|
@@ -61,10 +61,8 @@ void RoutingToClockConnection::create_switches(const ClockRRGraphBuilder& clock_ | |||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
// rr_node indices for x and y channel routing wires and clock wires to connect to | ||||||||||||||||
auto x_wire_indices = get_rr_node_chan_wires_at_location( | ||||||||||||||||
rr_node_indices, CHANX, switch_location.x, switch_location.y); | ||||||||||||||||
auto y_wire_indices = get_rr_node_chan_wires_at_location( | ||||||||||||||||
rr_node_indices, CHANY, switch_location.x, switch_location.y); | ||||||||||||||||
auto x_wire_indices = node_lookup.find_channel_nodes(switch_location.x, switch_location.y, CHANX); | ||||||||||||||||
auto y_wire_indices = node_lookup.find_channel_nodes(switch_location.x, switch_location.y, CHANY); | ||||||||||||||||
auto clock_indices = clock_graph.get_rr_node_indices_at_switch_location( | ||||||||||||||||
clock_to_connect_to, switch_point_name, switch_location.x, switch_location.y); | ||||||||||||||||
|
||||||||||||||||
|
@@ -76,13 +74,13 @@ void RoutingToClockConnection::create_switches(const ClockRRGraphBuilder& clock_ | |||||||||||||||
// Connect to x-channel wires | ||||||||||||||||
unsigned num_wires_x = x_wire_indices.size() * fc; | ||||||||||||||||
for (size_t i = 0; i < num_wires_x; i++) { | ||||||||||||||||
clock_graph.add_edge(rr_edges_to_create, x_wire_indices[i], clock_index, arch_switch_idx); | ||||||||||||||||
clock_graph.add_edge(rr_edges_to_create, size_t(x_wire_indices[i]), clock_index, arch_switch_idx); | ||||||||||||||||
vaughnbetz marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
// Connect to y-channel wires | ||||||||||||||||
unsigned num_wires_y = y_wire_indices.size() * fc; | ||||||||||||||||
for (size_t i = 0; i < num_wires_y; i++) { | ||||||||||||||||
clock_graph.add_edge(rr_edges_to_create, y_wire_indices[i], clock_index, arch_switch_idx); | ||||||||||||||||
clock_graph.add_edge(rr_edges_to_create, size_t(y_wire_indices[i]), clock_index, arch_switch_idx); | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
// Connect to virtual clock sink node | ||||||||||||||||
|
@@ -95,35 +93,38 @@ int RoutingToClockConnection::create_virtual_clock_network_sink_node( | |||||||||||||||
int x, | ||||||||||||||||
int y) { | ||||||||||||||||
auto& device_ctx = g_vpr_ctx.mutable_device(); | ||||||||||||||||
auto& rr_nodes = device_ctx.rr_nodes; | ||||||||||||||||
rr_nodes.emplace_back(); | ||||||||||||||||
auto node_index = rr_nodes.size() - 1; | ||||||||||||||||
auto& rr_graph = device_ctx.rr_nodes; | ||||||||||||||||
auto& node_lookup = device_ctx.rr_graph_builder.node_lookup(); | ||||||||||||||||
rr_graph.emplace_back(); | ||||||||||||||||
RRNodeId node_index = RRNodeId(rr_graph.size() - 1); | ||||||||||||||||
|
||||||||||||||||
//Determine the a valid PTC | ||||||||||||||||
std::vector<int> nodes_at_loc; | ||||||||||||||||
get_rr_node_indices(device_ctx.rr_node_indices, | ||||||||||||||||
x, y, | ||||||||||||||||
SINK, | ||||||||||||||||
&nodes_at_loc); | ||||||||||||||||
std::vector<RRNodeId> nodes_at_loc = node_lookup.find_sink_nodes(x, y); | ||||||||||||||||
|
||||||||||||||||
int max_ptc = 0; | ||||||||||||||||
for (int inode : nodes_at_loc) { | ||||||||||||||||
max_ptc = std::max<int>(max_ptc, device_ctx.rr_nodes[inode].ptc_num()); | ||||||||||||||||
for (RRNodeId inode : nodes_at_loc) { | ||||||||||||||||
max_ptc = std::max<int>(max_ptc, rr_graph.node_ptc_num(inode)); | ||||||||||||||||
} | ||||||||||||||||
int ptc = max_ptc + 1; | ||||||||||||||||
|
||||||||||||||||
rr_nodes[node_index].set_ptc_num(ptc); | ||||||||||||||||
rr_nodes[node_index].set_coordinates(x, y, x, y); | ||||||||||||||||
rr_nodes[node_index].set_capacity(1); | ||||||||||||||||
rr_nodes[node_index].set_cost_index(SINK_COST_INDEX); | ||||||||||||||||
rr_nodes[node_index].set_type(SINK); | ||||||||||||||||
rr_graph.set_node_ptc_num(node_index, ptc); | ||||||||||||||||
rr_graph.set_node_coordinates(node_index, x, y, x, y); | ||||||||||||||||
rr_graph.set_node_capacity(node_index, 1); | ||||||||||||||||
rr_graph.set_node_cost_index(node_index, SINK_COST_INDEX); | ||||||||||||||||
rr_graph.set_node_type(node_index, SINK); | ||||||||||||||||
float R = 0.; | ||||||||||||||||
float C = 0.; | ||||||||||||||||
rr_nodes[node_index].set_rc_index(find_create_rr_rc_data(R, C)); | ||||||||||||||||
rr_graph.set_node_rc_index(node_index, find_create_rr_rc_data(R, C)); | ||||||||||||||||
|
||||||||||||||||
add_to_rr_node_indices(device_ctx.rr_node_indices, rr_nodes, node_index); | ||||||||||||||||
// Use a generic way when adding nodes to lookup. | ||||||||||||||||
// However, since the SINK node has the same xhigh/xlow as well as yhigh/ylow, we can probably use a shortcut | ||||||||||||||||
for (int ix = rr_graph.node_xlow(node_index); ix <= rr_graph.node_xhigh(node_index); ++ix) { | ||||||||||||||||
for (int iy = rr_graph.node_ylow(node_index); iy <= rr_graph.node_yhigh(node_index); ++iy) { | ||||||||||||||||
node_lookup.add_node(node_index, ix, iy, rr_graph.node_type(node_index), rr_graph.node_ptc_num(node_index), SIDES[0]); | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like we use SIDES[0] to insert the sink node, and look for it later on the TOP side. Hence should we use TOP consistently or SIDES[0] consistently to make sure this is always in alignment? I assume SIDES[0] == TOP so this all works, but it still seems dangerous as if anyone ever edits the order of SIDES we'd subtly break code written this way. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agree. We should not expose the side argument to developers because they may feel confused. vtr-verilog-to-routing/vpr/src/device/rr_spatial_lookup.cpp Lines 23 to 29 in c06800f
However, I think it is not a good idea to force the developers to give a dummy side when addethe API. I modified the API so that the side option will have a default value (SIDE[0]) if not specified. In client functions, I remove all the usage of the SIDE[0] for non-IPIN/OPIN nodes. |
||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
return node_index; | ||||||||||||||||
return size_t(node_index); | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we change the return type of this function to RRNodeId and remove the cast? (May have to change the calling function too some then). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just checked the dependency of this API. It is used only by another API. It is simple change. Done. |
||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
/* | ||||||||||||||||
|
@@ -243,7 +244,7 @@ size_t ClockToPinsConnection::estimate_additional_nodes() { | |||||||||||||||
|
||||||||||||||||
void ClockToPinsConnection::create_switches(const ClockRRGraphBuilder& clock_graph, t_rr_edge_info_set* rr_edges_to_create) { | ||||||||||||||||
auto& device_ctx = g_vpr_ctx.device(); | ||||||||||||||||
auto& rr_node_indices = device_ctx.rr_node_indices; | ||||||||||||||||
const auto& node_lookup = device_ctx.rr_graph.node_lookup(); | ||||||||||||||||
auto& grid = clock_graph.grid(); | ||||||||||||||||
|
||||||||||||||||
for (size_t x = 0; x < grid.width(); x++) { | ||||||||||||||||
|
@@ -304,13 +305,11 @@ void ClockToPinsConnection::create_switches(const ClockRRGraphBuilder& clock_gra | |||||||||||||||
clock_y_offset = -1; // pick the chanx below the block | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
auto clock_pin_node_idx = get_rr_node_index( | ||||||||||||||||
rr_node_indices, | ||||||||||||||||
x, | ||||||||||||||||
y, | ||||||||||||||||
IPIN, | ||||||||||||||||
clock_pin_idx, | ||||||||||||||||
side); | ||||||||||||||||
auto clock_pin_node_idx = node_lookup.find_node(x, | ||||||||||||||||
y, | ||||||||||||||||
IPIN, | ||||||||||||||||
clock_pin_idx, | ||||||||||||||||
side); | ||||||||||||||||
|
||||||||||||||||
auto clock_network_indices = clock_graph.get_rr_node_indices_at_switch_location( | ||||||||||||||||
clock_to_connect_from, | ||||||||||||||||
|
@@ -320,7 +319,7 @@ void ClockToPinsConnection::create_switches(const ClockRRGraphBuilder& clock_gra | |||||||||||||||
|
||||||||||||||||
//Create edges depending on Fc | ||||||||||||||||
for (size_t i = 0; i < clock_network_indices.size() * fc; i++) { | ||||||||||||||||
clock_graph.add_edge(rr_edges_to_create, clock_network_indices[i], clock_pin_node_idx, arch_switch_idx); | ||||||||||||||||
clock_graph.add_edge(rr_edges_to_create, clock_network_indices[i], size_t(clock_pin_node_idx), arch_switch_idx); | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we change the function prototype to avoid the cast (send in an RRNodeId instead)? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See my reply in a previous comment on the |
||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -62,11 +62,11 @@ void ClockNetwork::set_num_instance(int num_inst) { | |
|
||
void ClockNetwork::create_rr_nodes_for_clock_network_wires(ClockRRGraphBuilder& clock_graph, | ||
t_rr_graph_storage* rr_nodes, | ||
t_rr_node_indices* rr_node_indices, | ||
RRGraphBuilder& rr_graph_builder, | ||
t_rr_edge_info_set* rr_edges_to_create, | ||
int num_segments) { | ||
for (int inst_num = 0; inst_num < get_num_inst(); inst_num++) { | ||
create_rr_nodes_and_internal_edges_for_one_instance(clock_graph, rr_nodes, rr_node_indices, rr_edges_to_create, num_segments); | ||
create_rr_nodes_and_internal_edges_for_one_instance(clock_graph, rr_nodes, rr_graph_builder, rr_edges_to_create, num_segments); | ||
} | ||
} | ||
|
||
|
@@ -217,7 +217,7 @@ size_t ClockRib::estimate_additional_nodes(const DeviceGrid& grid) { | |
|
||
void ClockRib::create_rr_nodes_and_internal_edges_for_one_instance(ClockRRGraphBuilder& clock_graph, | ||
t_rr_graph_storage* rr_nodes, | ||
t_rr_node_indices* rr_node_indices, | ||
RRGraphBuilder& rr_graph_builder, | ||
t_rr_edge_info_set* rr_edges_to_create, | ||
int num_segments) { | ||
// Only chany wires need to know the number of segments inorder | ||
|
@@ -275,7 +275,7 @@ void ClockRib::create_rr_nodes_and_internal_edges_for_one_instance(ClockRRGraphB | |
ptc_num, | ||
Direction::BIDIR, | ||
rr_nodes, | ||
rr_node_indices); | ||
rr_graph_builder); | ||
clock_graph.add_switch_location(get_name(), drive.name, drive_x, y, drive_node_idx); | ||
|
||
// create rib wire to the right and left of the drive point | ||
|
@@ -285,14 +285,14 @@ void ClockRib::create_rr_nodes_and_internal_edges_for_one_instance(ClockRRGraphB | |
ptc_num, | ||
Direction::DEC, | ||
rr_nodes, | ||
rr_node_indices); | ||
rr_graph_builder); | ||
auto right_node_idx = create_chanx_wire(drive_x + 1, | ||
x_end, | ||
y, | ||
ptc_num, | ||
Direction::INC, | ||
rr_nodes, | ||
rr_node_indices); | ||
rr_graph_builder); | ||
record_tap_locations(x_start + x_offset, | ||
x_end, | ||
y, | ||
|
@@ -313,7 +313,7 @@ int ClockRib::create_chanx_wire(int x_start, | |
int ptc_num, | ||
Direction direction, | ||
t_rr_graph_storage* rr_nodes, | ||
t_rr_node_indices* rr_node_indices) { | ||
RRGraphBuilder& rr_graph_builder) { | ||
rr_nodes->emplace_back(); | ||
auto node_index = rr_nodes->size() - 1; | ||
auto node = rr_nodes->back(); | ||
|
@@ -343,7 +343,15 @@ int ClockRib::create_chanx_wire(int x_start, | |
} | ||
node.set_cost_index(CHANX_COST_INDEX_START + seg_index); // Actual value set later | ||
|
||
add_to_rr_node_indices(*rr_node_indices, *rr_nodes, node_index); | ||
/* Add the node to spatial lookup */ | ||
auto& rr_graph = (*rr_nodes); | ||
RRNodeId chanx_node = RRNodeId(node_index); | ||
for (int ix = rr_graph.node_xlow(chanx_node); ix <= rr_graph.node_xhigh(chanx_node); ++ix) { | ||
for (int iy = rr_graph.node_ylow(chanx_node); iy <= rr_graph.node_yhigh(chanx_node); ++iy) { | ||
//TODO: CHANX uses odd swapped x/y indices here. Will rework once rr_node_indices is shadowed | ||
rr_graph_builder.node_lookup().add_node(chanx_node, iy, ix, rr_graph.node_type(chanx_node), rr_graph.node_ptc_num(chanx_node), SIDES[0]); | ||
} | ||
} | ||
|
||
return node_index; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider changing return type to RRNodeId, and directly making node_index an RRNodeId (and therefore wouldn't need chanx_node). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, I believe, we can use the API
I leave a TODO comment here to remind me to finish the API replacement after PR #1800 is merged. |
||
} | ||
|
@@ -511,7 +519,7 @@ size_t ClockSpine::estimate_additional_nodes(const DeviceGrid& grid) { | |
|
||
void ClockSpine::create_rr_nodes_and_internal_edges_for_one_instance(ClockRRGraphBuilder& clock_graph, | ||
t_rr_graph_storage* rr_nodes, | ||
t_rr_node_indices* rr_node_indices, | ||
RRGraphBuilder& rr_graph_builder, | ||
t_rr_edge_info_set* rr_edges_to_create, | ||
int num_segments) { | ||
auto& grid = clock_graph.grid(); | ||
|
@@ -565,7 +573,7 @@ void ClockSpine::create_rr_nodes_and_internal_edges_for_one_instance(ClockRRGrap | |
ptc_num, | ||
Direction::BIDIR, | ||
rr_nodes, | ||
rr_node_indices, | ||
rr_graph_builder, | ||
num_segments); | ||
clock_graph.add_switch_location(get_name(), drive.name, x, drive_y, drive_node_idx); | ||
|
||
|
@@ -576,15 +584,15 @@ void ClockSpine::create_rr_nodes_and_internal_edges_for_one_instance(ClockRRGrap | |
ptc_num, | ||
Direction::DEC, | ||
rr_nodes, | ||
rr_node_indices, | ||
rr_graph_builder, | ||
num_segments); | ||
auto right_node_idx = create_chany_wire(drive_y + 1, | ||
y_end, | ||
x, | ||
ptc_num, | ||
Direction::INC, | ||
rr_nodes, | ||
rr_node_indices, | ||
rr_graph_builder, | ||
num_segments); | ||
|
||
// Keep a record of the rr_node idx that we will use to connects switches to at | ||
|
@@ -609,7 +617,7 @@ int ClockSpine::create_chany_wire(int y_start, | |
int ptc_num, | ||
Direction direction, | ||
t_rr_graph_storage* rr_nodes, | ||
t_rr_node_indices* rr_node_indices, | ||
RRGraphBuilder& rr_graph_builder, | ||
int num_segments) { | ||
rr_nodes->emplace_back(); | ||
auto node_index = rr_nodes->size() - 1; | ||
|
@@ -640,7 +648,14 @@ int ClockSpine::create_chany_wire(int y_start, | |
} | ||
node.set_cost_index(CHANX_COST_INDEX_START + num_segments + seg_index); | ||
|
||
add_to_rr_node_indices(*rr_node_indices, *rr_nodes, node_index); | ||
/* Add the node to spatial lookup */ | ||
vaughnbetz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
auto& rr_graph = (*rr_nodes); | ||
RRNodeId chany_node = RRNodeId(node_index); | ||
for (int ix = rr_graph.node_xlow(chany_node); ix <= rr_graph.node_xhigh(chany_node); ++ix) { | ||
for (int iy = rr_graph.node_ylow(chany_node); iy <= rr_graph.node_yhigh(chany_node); ++iy) { | ||
rr_graph_builder.node_lookup().add_node(chany_node, ix, iy, rr_graph.node_type(chany_node), rr_graph.node_ptc_num(chany_node), SIDES[0]); | ||
} | ||
} | ||
|
||
return node_index; | ||
} | ||
|
@@ -678,14 +693,14 @@ size_t ClockHTree::estimate_additional_nodes(const DeviceGrid& /*grid*/) { | |
|
||
void ClockHTree::create_rr_nodes_and_internal_edges_for_one_instance(ClockRRGraphBuilder& clock_graph, | ||
t_rr_graph_storage* rr_nodes, | ||
t_rr_node_indices* rr_node_indices, | ||
RRGraphBuilder& rr_graph_builder, | ||
t_rr_edge_info_set* rr_edges_to_create, | ||
int num_segments) { | ||
//Remove unused parameter warning | ||
(void)clock_graph; | ||
(void)num_segments; | ||
(void)rr_nodes; | ||
(void)rr_node_indices; | ||
(void)rr_graph_builder; | ||
(void)rr_edges_to_create; | ||
|
||
VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "HTrees are not yet supported.\n"); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment looks wrong (talking about channels).
This code also points out why we should rework the underlying rr_node_indices implementation; it's strange to have a multi-dimensional array matrix where some dimensions must always be accessed with a specific index. Hopefully that is on your near-term agenda Xifan. Could put a TODO in to refactor that way, if you think such a comment would be a useful reminder.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the typo. Just fixed it.
I think it will be a good time to rethink the
rr_node_indices
data structure once all the related APIs are replaced.Actually, it is not too far. I expect only we need another 2 pull requests, before fully shadowing the current
rr_node_indices
.I put a TODO to remind us during the refactoring. I will take a deep look into the
rr_node_indices
data structure and propose something.