Skip to content

RRGraphView node_cost_index() Implementation #1843

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

Merged
Merged
15 changes: 8 additions & 7 deletions vpr/src/power/power.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -858,16 +858,17 @@ static void power_usage_routing(t_power_usage* power_usage,
for (size_t rr_node_idx = 0; rr_node_idx < device_ctx.rr_nodes.size(); rr_node_idx++) {
t_power_usage sub_power_usage;
auto node = device_ctx.rr_nodes[rr_node_idx];
RRNodeId rr_node = RRNodeId(rr_node_idx);
t_rr_node_power* node_power = &rr_node_power[rr_node_idx];
float C_wire;
float buffer_size;
int connectionbox_fanout;
int switchbox_fanout;
//float C_per_seg_split;
int wire_length;
const t_edge_size node_fan_in = rr_graph.node_fan_in(RRNodeId(rr_node_idx));
const t_edge_size node_fan_in = rr_graph.node_fan_in(rr_node);

switch (rr_graph.node_type(RRNodeId(rr_node_idx))) {
switch (rr_graph.node_type(rr_node)) {
case SOURCE:
case SINK:
case OPIN:
Expand Down Expand Up @@ -905,12 +906,12 @@ static void power_usage_routing(t_power_usage* power_usage,
VTR_ASSERT(node_power->in_prob);

wire_length = 0;
if (rr_graph.node_type(RRNodeId(rr_node_idx)) == CHANX) {
wire_length = rr_graph.node_xhigh(node.id()) - rr_graph.node_xlow(node.id()) + 1;
} else if (rr_graph.node_type(RRNodeId(rr_node_idx)) == CHANY) {
wire_length = rr_graph.node_yhigh(node.id()) - rr_graph.node_ylow(node.id()) + 1;
if (rr_graph.node_type(rr_node) == CHANX) {
wire_length = rr_graph.node_xhigh(rr_node) - rr_graph.node_xlow(rr_node) + 1;
} else if (rr_graph.node_type(rr_node) == CHANY) {
wire_length = rr_graph.node_yhigh(rr_node) - rr_graph.node_ylow(rr_node) + 1;
}
int seg_index = device_ctx.rr_indexed_data[node.cost_index()].seg_index;
int seg_index = device_ctx.rr_indexed_data[rr_graph.node_cost_index(rr_node)].seg_index;
C_wire = wire_length * device_ctx.rr_segments[seg_index].Cmetal;
//(double)power_ctx.commonly_used->tile_length);
VTR_ASSERT(node_power->selected_input < node_fan_in);
Expand Down
2 changes: 1 addition & 1 deletion vpr/src/route/check_rr_graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ void check_rr_node(int inode, enum e_route_type route_type, const DeviceContext&
yhigh = rr_graph.node_yhigh(rr_node);
ptc_num = device_ctx.rr_nodes[inode].ptc_num();
capacity = rr_graph.node_capacity(rr_node);
cost_index = device_ctx.rr_nodes[inode].cost_index();
cost_index = rr_graph.node_cost_index(rr_node);
type = nullptr;

const auto& grid = device_ctx.grid;
Expand Down
4 changes: 2 additions & 2 deletions vpr/src/route/route_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ float get_rr_cong_cost(int inode, float pres_fac);
/* Returns the base cost of using this rr_node */
inline float get_single_rr_cong_base_cost(int inode) {
auto& device_ctx = g_vpr_ctx.device();
auto cost_index = device_ctx.rr_nodes[inode].cost_index();
auto cost_index = device_ctx.rr_graph.node_cost_index(RRNodeId(inode));

return device_ctx.rr_indexed_data[cost_index].base_cost;
}
Expand Down Expand Up @@ -78,7 +78,7 @@ inline float get_single_rr_cong_cost(int inode, float pres_fac) {
pres_cost = 1.;
}

auto cost_index = device_ctx.rr_nodes[inode].cost_index();
auto cost_index = rr_graph.node_cost_index(RRNodeId(inode));

float cost = device_ctx.rr_indexed_data[cost_index].base_cost * route_ctx.rr_node_route_inf[inode].acc_cost * pres_cost;

Expand Down
4 changes: 2 additions & 2 deletions vpr/src/route/router_lookahead.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ std::pair<float, float> ClassicLookahead::get_expected_delay_and_cong(RRNodeId n
int num_segs_ortho_dir = 0;
int num_segs_same_dir = get_expected_segs_to_target(node, target_node, &num_segs_ortho_dir);

int cost_index = device_ctx.rr_nodes.node_cost_index(node);
int cost_index = rr_graph.node_cost_index(node);
int ortho_cost_index = device_ctx.rr_indexed_data[cost_index].ortho_cost_index;

const auto& same_data = device_ctx.rr_indexed_data[cost_index];
Expand Down Expand Up @@ -120,7 +120,7 @@ static int get_expected_segs_to_target(RRNodeId inode, RRNodeId target_node, int
target_x = rr_graph.node_xlow(target_node);
target_y = rr_graph.node_ylow(target_node);

cost_index = device_ctx.rr_nodes.node_cost_index(inode);
cost_index = rr_graph.node_cost_index(inode);
inv_length = device_ctx.rr_indexed_data[cost_index].inv_length;
ortho_cost_index = device_ctx.rr_indexed_data[cost_index].ortho_cost_index;
ortho_inv_length = device_ctx.rr_indexed_data[ortho_cost_index].inv_length;
Expand Down
5 changes: 1 addition & 4 deletions vpr/src/route/router_lookahead_cost_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,7 @@ void CostMap::set_counts(size_t seg_count) {
*/
int CostMap::node_to_segment(int from_node_ind) const {
const auto& device_ctx = g_vpr_ctx.device();

auto& from_node = device_ctx.rr_nodes[from_node_ind];

int from_cost_index = from_node.cost_index();
int from_cost_index = device_ctx.rr_graph.node_cost_index(RRNodeId(from_node_ind));
return device_ctx.rr_indexed_data[from_cost_index].seg_index;
}

Expand Down
3 changes: 1 addition & 2 deletions vpr/src/route/router_lookahead_extended_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,8 +293,7 @@ bool ExtendedMapLookahead::add_paths(RRNodeId start_node,
auto parent = start_node;
for (auto it = path.rbegin(); it != path.rend(); it++) {
RRNodeId this_node(*it);
auto& here = device_ctx.rr_nodes[*it];
int seg_index = device_ctx.rr_indexed_data[here.cost_index()].seg_index;
int seg_index = device_ctx.rr_indexed_data[rr_graph.node_cost_index(this_node)].seg_index;

int from_x = rr_graph.node_xlow(this_node);
int from_y = rr_graph.node_ylow(this_node);
Expand Down
14 changes: 7 additions & 7 deletions vpr/src/route/router_lookahead_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,11 +146,12 @@ class PQ_Entry {
this->rr_node = set_rr_node;

auto& device_ctx = g_vpr_ctx.device();
const auto& rr_graph = device_ctx.rr_graph;
this->delay = parent_delay;
this->congestion_upstream = parent_congestion_upstream;
this->R_upstream = parent_R_upstream;
if (!starting_node) {
int cost_index = device_ctx.rr_nodes.node_cost_index(RRNodeId(set_rr_node));
int cost_index = rr_graph.node_cost_index(RRNodeId(set_rr_node));
//this->delay += rr_graph.node_C(RRNodeId(set_rr_node)) * (g_rr_switch_inf[switch_ind].R + 0.5*rr_graph.node_R(RRNodeId(set_rr_node))) +
// g_rr_switch_inf[switch_ind].Tdel;

Expand Down Expand Up @@ -335,7 +336,7 @@ std::pair<float, float> MapLookahead::get_expected_delay_and_cong(RRNodeId from_
VTR_ASSERT_SAFE(from_type == CHANX || from_type == CHANY);
//When estimating costs from a wire, we directly look-up the result in the wire lookahead (f_wire_cost_map)

int from_cost_index = rr_graph.node_cost_index(from_node);
int from_cost_index = temp_rr_graph.node_cost_index(from_node);
int from_seg_index = device_ctx.rr_indexed_data[from_cost_index].seg_index;

VTR_ASSERT(from_seg_index >= 0);
Expand Down Expand Up @@ -478,7 +479,7 @@ static void compute_router_wire_lookahead(const std::vector<t_segment_inf>& segm
auto rr_type = temp_rr_graph.node_type(rr_node);
if (rr_type != chan_type) continue;

int cost_index = rr_graph.node_cost_index(rr_node);
int cost_index = temp_rr_graph.node_cost_index(rr_node);
VTR_ASSERT(cost_index != OPEN);

int seg_index = device_ctx.rr_indexed_data[cost_index].seg_index;
Expand Down Expand Up @@ -544,9 +545,8 @@ static void compute_router_wire_lookahead(const std::vector<t_segment_inf>& segm
/* returns index of a node from which to start routing */
static RRNodeId get_start_node(int start_x, int start_y, int target_x, int target_y, t_rr_type rr_type, int seg_index, int track_offset) {
auto& device_ctx = g_vpr_ctx.device();
const auto& temp_rr_graph = device_ctx.rr_graph; //TODO rename to rr_graph once the rr_graph below is unneeded
auto& rr_graph = device_ctx.rr_nodes;
const auto& node_lookup = device_ctx.rr_graph.node_lookup();
const auto& rr_graph = device_ctx.rr_graph;
const auto& node_lookup = rr_graph.node_lookup();

RRNodeId result = RRNodeId::INVALID();

Expand All @@ -565,7 +565,7 @@ static RRNodeId get_start_node(int start_x, int start_y, int target_x, int targe

/* find first node in channel that has specified segment index and goes in the desired direction */
for (const RRNodeId& node_id : node_lookup.find_channel_nodes(start_lookup_x, start_lookup_y, rr_type)) {
VTR_ASSERT(temp_rr_graph.node_type(node_id) == rr_type);
VTR_ASSERT(rr_graph.node_type(node_id) == rr_type);

Direction node_direction = rr_graph.node_direction(node_id);
int node_cost_ind = rr_graph.node_cost_index(node_id);
Expand Down
6 changes: 3 additions & 3 deletions vpr/src/route/router_lookahead_map_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ static void dijkstra_flood_to_wires(int itile, RRNodeId node, util::t_src_opin_d
int seg_index;
if (curr_rr_type != SINK) {
//It's a wire, figure out its type
int cost_index = rr_graph.node_cost_index(curr.node);
int cost_index = temp_rr_graph.node_cost_index(curr.node);
seg_index = device_ctx.rr_indexed_data[cost_index].seg_index;
} else {
//This is a direct-connect path between an IPIN and OPIN,
Expand All @@ -493,7 +493,7 @@ static void dijkstra_flood_to_wires(int itile, RRNodeId node, util::t_src_opin_d

} else if (curr_rr_type == SOURCE || curr_rr_type == OPIN || curr_rr_type == IPIN) {
//We allow expansion through SOURCE/OPIN/IPIN types
int cost_index = rr_graph.node_cost_index(curr.node);
int cost_index = temp_rr_graph.node_cost_index(curr.node);
float incr_cong = device_ctx.rr_indexed_data[cost_index].base_cost; //Current nodes congestion cost

for (RREdgeId edge : rr_graph.edge_range(curr.node)) {
Expand Down Expand Up @@ -588,7 +588,7 @@ static void dijkstra_flood_to_ipins(RRNodeId node, util::t_chan_ipins_delays& ch
}

//We allow expansion through SOURCE/OPIN/IPIN types
int cost_index = rr_graph.node_cost_index(curr.node);
int cost_index = temp_rr_graph.node_cost_index(curr.node);
float new_cong = device_ctx.rr_indexed_data[cost_index].base_cost; //Current nodes congestion cost

for (RREdgeId edge : rr_graph.edge_range(curr.node)) {
Expand Down
13 changes: 7 additions & 6 deletions vpr/src/route/router_lookahead_sampling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,19 +128,20 @@ static uint64_t interleave(uint32_t x) {
static std::tuple<int, int, int> get_node_info(const t_rr_node& node, int num_segments) {
auto& device_ctx = g_vpr_ctx.device();
const auto& rr_graph = device_ctx.rr_graph;
RRNodeId rr_node = node.id();

if (rr_graph.node_type(node.id()) != CHANX && rr_graph.node_type(node.id()) != CHANY) {
if (rr_graph.node_type(rr_node) != CHANX && rr_graph.node_type(rr_node) != CHANY) {
return std::tuple<int, int, int>(OPEN, OPEN, OPEN);
}

if (rr_graph.node_capacity(node.id()) == 0 || node.num_edges() == 0) {
if (rr_graph.node_capacity(rr_node) == 0 || node.num_edges() == 0) {
return std::tuple<int, int, int>(OPEN, OPEN, OPEN);
}

int x = rr_graph.node_xlow(node.id());
int y = rr_graph.node_ylow(node.id());
int x = rr_graph.node_xlow(rr_node);
int y = rr_graph.node_ylow(rr_node);

int seg_index = device_ctx.rr_indexed_data[node.cost_index()].seg_index;
int seg_index = device_ctx.rr_indexed_data[rr_graph.node_cost_index(rr_node)].seg_index;

VTR_ASSERT(seg_index != OPEN);
VTR_ASSERT(seg_index < num_segments);
Expand Down Expand Up @@ -205,7 +206,7 @@ std::vector<SampleRegion> find_sample_regions(int num_segments) {
for (auto& node : rr_nodes) {
if (rr_graph.node_type(node.id()) != CHANX && rr_graph.node_type(node.id()) != CHANY) continue;
if (rr_graph.node_capacity(node.id()) == 0 || node.num_edges() == 0) continue;
int seg_index = device_ctx.rr_indexed_data[node.cost_index()].seg_index;
int seg_index = device_ctx.rr_indexed_data[rr_graph.node_cost_index(node.id())].seg_index;

VTR_ASSERT(seg_index != OPEN);
VTR_ASSERT(seg_index < num_segments);
Expand Down
2 changes: 1 addition & 1 deletion vpr/src/route/rr_graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2431,7 +2431,7 @@ std::string describe_rr_node(int inode) {
auto rr_node = device_ctx.rr_nodes[inode];

if (rr_graph.node_type(RRNodeId(inode)) == CHANX || rr_graph.node_type(RRNodeId(inode)) == CHANY) {
int cost_index = rr_node.cost_index();
int cost_index = rr_graph.node_cost_index(RRNodeId(inode));

int seg_index = device_ctx.rr_indexed_data[cost_index].seg_index;
std::string rr_node_direction_string = rr_graph.node_direction_string(RRNodeId(inode));
Expand Down
4 changes: 2 additions & 2 deletions vpr/src/route/rr_graph_indexed_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ static std::vector<size_t> count_rr_segment_types() {
for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); ++inode) {
if (rr_graph.node_type(RRNodeId(inode)) != CHANX && rr_graph.node_type(RRNodeId(inode)) != CHANY) continue;

int cost_index = device_ctx.rr_nodes[inode].cost_index();
int cost_index = rr_graph.node_cost_index(RRNodeId(inode));

int seg_index = device_ctx.rr_indexed_data[cost_index].seg_index;

Expand Down Expand Up @@ -350,7 +350,7 @@ static void load_rr_indexed_data_T_values() {
continue;
}

int cost_index = rr_nodes[inode].cost_index();
int cost_index = rr_graph.node_cost_index(RRNodeId(inode));

/* get average switch parameters */
double avg_switch_R = 0;
Expand Down
8 changes: 4 additions & 4 deletions vpr/src/route/rr_graph_uxsdcxx_serializer.h
Original file line number Diff line number Diff line change
Expand Up @@ -706,23 +706,23 @@ class RrGraphSerializer final : public uxsd::RrGraphBase<RrGraphContextTypes> {
node.set_cost_index(0);
} else if (rr_graph.node_type(node.id()) == CHANX) {
node.set_cost_index(CHANX_COST_INDEX_START + segment_id);
seg_index_[node.cost_index()] = segment_id;
seg_index_[rr_graph.node_cost_index(node.id())] = segment_id;
} else if (rr_graph.node_type(node.id()) == CHANY) {
node.set_cost_index(CHANX_COST_INDEX_START + segment_inf_.size() + segment_id);
seg_index_[node.cost_index()] = segment_id;
seg_index_[rr_graph.node_cost_index(node.id())] = segment_id;
}
return inode;
}
inline void finish_node_segment(int& /*inode*/) final {}
inline int get_node_segment_segment_id(const t_rr_node& node) final {
return (*rr_indexed_data_)[node.cost_index()].seg_index;
return (*rr_indexed_data_)[(*rr_graph_).node_cost_index(node.id())].seg_index;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may use rr_graph->node_cost_index to avoid too many brackets

}

inline const t_rr_node get_node_segment(const t_rr_node& node) final {
return node;
}
inline bool has_node_segment(const t_rr_node& node) final {
return (*rr_indexed_data_)[node.cost_index()].seg_index != -1;
return (*rr_indexed_data_)[(*rr_graph_).node_cost_index(node.id())].seg_index != -1;
}

inline MetadataBind init_node_metadata(int& inode) final {
Expand Down
4 changes: 0 additions & 4 deletions vpr/src/route/rr_node_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,6 @@ inline short t_rr_node::class_num() const {
return storage_->node_class_num(id_);
}

inline short t_rr_node::cost_index() const {
return storage_->node_cost_index(id_);
}

inline bool t_rr_node::is_node_on_specific_side(e_side side) const {
return storage_->is_node_on_specific_side(id_, side);
}
Expand Down
2 changes: 1 addition & 1 deletion vpr/src/route/segment_stats.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ void get_segment_usage_stats(std::vector<t_segment_inf>& segment_inf) {

for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); inode++) {
if (rr_graph.node_type(RRNodeId(inode)) == CHANX || rr_graph.node_type(RRNodeId(inode)) == CHANY) {
cost_index = device_ctx.rr_nodes[inode].cost_index();
cost_index = rr_graph.node_cost_index(RRNodeId(inode));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's an example of where I think we should eventually hide the cost_index.
Instead of asking for a cost_index, and then looking up seg_type, we instead should have an api that takes an RRNodeId and returns the seg_type
seg_type = rr_graph.seg_type(RRNodeId(inode));
Internally, the .seg_type() function would get the cost_index, and then look up the seg_type and return it.

It hides the fact that this seg_type lookup goes through a cost_index (flyweight) for storage efficiency; the caller doesn't care.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's possible there's some cpu time penalty to that in some code, if we ask for a bunch of cost_index data in rapid succession. But in that case we could return a struct with the data that tends to be requested together packed into it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vaughnbetz I think it is a good idea to streamline the API here. Actually, I am thinking about if we should include the rr_segments and rr_switch_inf as part of the RRGraphView and RRGraphBuilder.

///@brief Autogenerated in build_rr_graph based on switch fan-in. [0..(num_rr_switches-1)]
std::vector<t_rr_switch_inf> rr_switch_inf;
///@brief Wire segment types in RR graph
std::vector<t_segment_inf> rr_segments;

I said so because these two data structures are modified copies of the original ones in architecture data. They have been updated to accurately model the switches and segments in the context of a specific routing resource graph.
Since they are adhoc to RRGraph, they can be part of the graph and we can provide shortcut APIs rather than force developers to visit several data structures.

However, it may be too complicated to this PR. It can be in a pull request near future (I can take the lead on it; since I have already tried in the rr_graph_obj.h)

Let me know what you think.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we decide to add API calls, the following are all a part of t_rr_indexed_data: base_cost, saved_base_cost, ortho_cost_index, seg_index, inv_length, T_linear, T_quadratic, C_load.

The ortho_cost_index is used to access each of these data points for a different cost index, so we would have to consider how the API would handle that. We could have a second argument to the functions rr_graph.seg_type(rr_node, is_ortho) or potentially two separate functions rr_graph.seg_type(), rr_graph.ortho_seg_type()

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, I think both those data structures should go in RRGraphView, and be built in RRGraphBuilder.
I also talked to @kmurray about this today in another meeting, and he also thinks hiding the cost_index and rr_indexed_data in RRGraphView api calls is the right way to go.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the rr_graph.ortho_seg_type() style would be more clear.
For items that tend to be used together, I'd make the API return a tuple or struct with them packed in (e.g. inv_length, T_linear, T_quadratic and C_load are all probably used just for the classic lookahead and could be returned as a group only).

size_t seg_type = device_ctx.rr_indexed_data[cost_index].seg_index;

if (!segment_inf[seg_type].longline)
Expand Down
2 changes: 1 addition & 1 deletion vpr/src/util/vpr_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ std::string rr_node_arch_name(int inode) {
} else {
VTR_ASSERT(rr_graph.node_type(RRNodeId(inode)) == CHANX || rr_graph.node_type(RRNodeId(inode)) == CHANY);
//Wire segment name
auto cost_index = rr_node.cost_index();
auto cost_index = rr_graph.node_cost_index(RRNodeId(inode));
int seg_index = device_ctx.rr_indexed_data[cost_index].seg_index;

rr_node_arch_name += device_ctx.rr_segments[seg_index].name;
Expand Down