Skip to content

Commit 00b25eb

Browse files
authored
Merge pull request #2345 from verilog-to-routing/restore_checkpoint_noc_costs
Recompte noc costs when restorting a checkpoint
2 parents 81a4a8e + f1f0e03 commit 00b25eb

12 files changed

+96
-40
lines changed

vpr/src/noc/noc_storage.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ const vtr::vector<NocLinkId, NocLink>& NocStorage::get_noc_links(void) const {
2323
return link_storage;
2424
}
2525

26+
vtr::vector<NocLinkId, NocLink>& NocStorage::get_mutable_noc_links(void) {
27+
return link_storage;
28+
}
29+
2630
int NocStorage::get_number_of_noc_links(void) const {
2731
return link_storage.size();
2832
}
@@ -219,9 +223,9 @@ NocLinkId NocStorage::get_parallel_link(NocLinkId current_link) const {
219223
NocLinkId parallel_link = INVALID_LINK_ID;
220224

221225
// go through the links of the sink router and the link that has the current source router as the sink router of the link is the parallel link we are looking for
222-
for (auto link = sink_router_links->begin(); link != sink_router_links->end(); link++) {
223-
if (link_storage[*link].get_sink_router() == curr_source_router) {
224-
parallel_link = *link;
226+
for (auto sink_router_link : *sink_router_links) {
227+
if (link_storage[sink_router_link].get_sink_router() == curr_source_router) {
228+
parallel_link = sink_router_link;
225229
break;
226230
}
227231
}
@@ -260,17 +264,17 @@ void NocStorage::echo_noc(char* file_name) const {
260264
fprintf(fp, "\n");
261265

262266
// go through each router and print its information
263-
for (auto router = router_storage.begin(); router != router_storage.end(); router++) {
264-
fprintf(fp, "Router %d:\n", router->get_router_user_id());
267+
for (const auto& router : router_storage) {
268+
fprintf(fp, "Router %d:\n", router.get_router_user_id());
265269
// if the router tile is larger than a single grid, the position represents the bottom left corner of the tile
266-
fprintf(fp, "Equivalent Physical Tile Grid Position -> (%d,%d)\n", router->get_router_grid_position_x(), router->get_router_grid_position_y());
270+
fprintf(fp, "Equivalent Physical Tile Grid Position -> (%d,%d)\n", router.get_router_grid_position_x(), router.get_router_grid_position_y());
267271
fprintf(fp, "Router Connections ->");
268272

269-
auto& router_connections = this->get_noc_router_connections(this->convert_router_id(router->get_router_user_id()));
273+
auto& router_connections = this->get_noc_router_connections(this->convert_router_id(router.get_router_user_id()));
270274

271275
// go through the outgoing links of the current router and print the connecting router
272-
for (auto link_id = router_connections.begin(); link_id != router_connections.end(); link_id++) {
273-
const NocRouterId connecting_router_id = get_single_noc_link(*link_id).get_sink_router();
276+
for (auto router_connection : router_connections) {
277+
const NocRouterId connecting_router_id = get_single_noc_link(router_connection).get_sink_router();
274278

275279
fprintf(fp, " %d", get_single_noc_router(connecting_router_id).get_router_user_id());
276280
}

vpr/src/noc/noc_storage.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,15 @@ class NocStorage {
187187
*/
188188
const vtr::vector<NocLinkId, NocLink>& get_noc_links(void) const;
189189

190+
/**
191+
* @brief Get all the links in the NoC. The links themselves can
192+
* be modified. This function should be used when information on
193+
* every link needs to be modified.
194+
*
195+
* @return A vector of links.
196+
*/
197+
vtr::vector<NocLinkId, NocLink>& get_mutable_noc_links(void);
198+
190199
/**
191200
* @return An integer representing the total number of links within the
192201
* NoC.

vpr/src/noc/noc_traffic_flows.cpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ const std::vector<NocTrafficFlowId>& NocTrafficFlows::get_all_traffic_flow_id(vo
5454

5555
// setters for the traffic flows
5656

57-
void NocTrafficFlows::create_noc_traffic_flow(std::string source_router_module_name, std::string sink_router_module_name, ClusterBlockId source_router_cluster_id, ClusterBlockId sink_router_cluster_id, double traffic_flow_bandwidth, double traffic_flow_latency, int traffic_flow_priority) {
57+
void NocTrafficFlows::create_noc_traffic_flow(const std::string& source_router_module_name, const std::string& sink_router_module_name, ClusterBlockId source_router_cluster_id, ClusterBlockId sink_router_cluster_id, double traffic_flow_bandwidth, double traffic_flow_latency, int traffic_flow_priority) {
5858
VTR_ASSERT_MSG(!built_traffic_flows, "NoC traffic flows have already been added, cannot modify further.");
5959

6060
// create and add the new traffic flow to the vector
@@ -106,7 +106,7 @@ void NocTrafficFlows::clear_traffic_flows(void) {
106106
return;
107107
}
108108

109-
bool NocTrafficFlows::check_if_cluster_block_has_traffic_flows(ClusterBlockId block_id) {
109+
bool NocTrafficFlows::check_if_cluster_block_has_traffic_flows(ClusterBlockId block_id) const {
110110
auto traffic_flows = get_traffic_flows_associated_to_router_block(block_id);
111111

112112
// indicate whether a vector of traffic flows were found that are associated to the current cluster block
@@ -149,15 +149,15 @@ void NocTrafficFlows::echo_noc_traffic_flows(char* file_name) {
149149
int traffic_flow_id = 0;
150150

151151
// go through each traffic flow and print its information
152-
for (auto traffic_flow = noc_traffic_flows.begin(); traffic_flow != noc_traffic_flows.end(); traffic_flow++) {
152+
for (const auto& traffic_flow : noc_traffic_flows) {
153153
// print the current traffic flows data
154154
fprintf(fp, "Traffic flow ID: %d\n", traffic_flow_id);
155-
fprintf(fp, "Traffic flow source router block name: %s\n", traffic_flow->source_router_module_name.c_str());
156-
fprintf(fp, "Traffic flow source router block cluster ID: %lu\n", (size_t)traffic_flow->source_router_cluster_id);
157-
fprintf(fp, "Traffic flow sink router block name: %s\n", traffic_flow->sink_router_module_name.c_str());
158-
fprintf(fp, "Traffic flow sink router block cluster ID: %lu\n", (size_t)traffic_flow->sink_router_cluster_id);
159-
fprintf(fp, "Traffic flow bandwidth: %f bps\n", traffic_flow->traffic_flow_bandwidth);
160-
fprintf(fp, "Traffic flow latency: %f seconds\n", traffic_flow->max_traffic_flow_latency);
155+
fprintf(fp, "Traffic flow source router block name: %s\n", traffic_flow.source_router_module_name.c_str());
156+
fprintf(fp, "Traffic flow source router block cluster ID: %lu\n", (size_t)traffic_flow.source_router_cluster_id);
157+
fprintf(fp, "Traffic flow sink router block name: %s\n", traffic_flow.sink_router_module_name.c_str());
158+
fprintf(fp, "Traffic flow sink router block cluster ID: %lu\n", (size_t)traffic_flow.sink_router_cluster_id);
159+
fprintf(fp, "Traffic flow bandwidth: %f bps\n", traffic_flow.traffic_flow_bandwidth);
160+
fprintf(fp, "Traffic flow latency: %f seconds\n", traffic_flow.max_traffic_flow_latency);
161161

162162
// separate the next link information
163163
fprintf(fp, "\n");
@@ -174,16 +174,16 @@ void NocTrafficFlows::echo_noc_traffic_flows(char* file_name) {
174174

175175
// go through each router block cluster and print its associated traffic flows
176176
// we only print out the traffic flow ids
177-
for (auto it = traffic_flows_associated_to_router_blocks.begin(); it != traffic_flows_associated_to_router_blocks.end(); it++) {
177+
for (const auto& router_traffic_flows : traffic_flows_associated_to_router_blocks) {
178178
// print the current router cluster id
179-
fprintf(fp, "Cluster ID %lu: ", (size_t)it->first);
179+
fprintf(fp, "Cluster ID %lu: ", (size_t)router_traffic_flows.first);
180180

181181
// get the vector of associated traffic flows
182-
auto assoc_traffic_flows = &(it->second);
182+
auto assoc_traffic_flows = &(router_traffic_flows.second);
183183

184184
// now go through the associated traffic flows of the current router and print their ids
185-
for (auto traffic_flow = assoc_traffic_flows->begin(); traffic_flow != assoc_traffic_flows->end(); traffic_flow++) {
186-
fprintf(fp, "%lu ", (size_t)*traffic_flow);
185+
for (auto assoc_traffic_flow : *assoc_traffic_flows) {
186+
fprintf(fp, "%lu ", (size_t)assoc_traffic_flow);
187187
}
188188

189189
// separate to the next cluster associated traffic flows information

vpr/src/noc/noc_traffic_flows.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <iostream>
3232
#include <unordered_map>
3333
#include <unordered_set>
34+
#include <utility>
3435
#include <vector>
3536
#include "clustered_netlist_fwd.h"
3637
#include "noc_data_types.h"
@@ -67,8 +68,8 @@ struct t_noc_traffic_flow {
6768

6869
/** Constructor initializes all variables*/
6970
t_noc_traffic_flow(std::string source_router_name, std::string sink_router_name, ClusterBlockId source_router_id, ClusterBlockId sink_router_id, double flow_bandwidth, double max_flow_latency, int flow_priority)
70-
: source_router_module_name(source_router_name)
71-
, sink_router_module_name(sink_router_name)
71+
: source_router_module_name(std::move(source_router_name))
72+
, sink_router_module_name(std::move(sink_router_name))
7273
, source_router_cluster_id(source_router_id)
7374
, sink_router_cluster_id(sink_router_id)
7475
, traffic_flow_bandwidth(flow_bandwidth)
@@ -254,7 +255,7 @@ class NocTrafficFlows {
254255
* at the sink router.
255256
* @param traffic_flow_priority The importance of a given traffic flow.
256257
*/
257-
void create_noc_traffic_flow(std::string source_router_module_name, std::string sink_router_module_name, ClusterBlockId source_router_cluster_id, ClusterBlockId sink_router_cluster_id, double traffic_flow_bandwidth, double traffic_flow_latency, int traffic_flow_priority);
258+
void create_noc_traffic_flow(const std::string& source_router_module_name, const std::string& sink_router_module_name, ClusterBlockId source_router_cluster_id, ClusterBlockId sink_router_cluster_id, double traffic_flow_bandwidth, double traffic_flow_latency, int traffic_flow_priority);
258259

259260
/**
260261
* @brief Copies the passed in router_cluster_id_in_netlist vector to the
@@ -304,7 +305,7 @@ class NocTrafficFlows {
304305
* @return true The block has traffic flows that it is a part of
305306
* @return false The block has no traffic flows it is a prt of
306307
*/
307-
bool check_if_cluster_block_has_traffic_flows(ClusterBlockId block_id);
308+
bool check_if_cluster_block_has_traffic_flows(ClusterBlockId block_id) const;
308309

309310
/**
310311
* @brief Writes out the NocTrafficFlows class information to a file.

vpr/src/noc/xy_routing.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,9 @@ bool XYRouting::move_to_next_router(NocRouterId& curr_router_id, int curr_router
106106
const std::vector<NocLinkId>& router_connections = noc_model.get_noc_router_connections(curr_router_id);
107107

108108
// go through each outgoing link and determine whether the link leads towards the intended route direction
109-
for (auto connecting_link = router_connections.begin(); connecting_link != router_connections.end(); connecting_link++) {
109+
for (auto connecting_link : router_connections) {
110110
// get the current outgoing link which is being processed
111-
const NocLink& curr_outgoing_link = noc_model.get_single_noc_link(*connecting_link);
111+
const NocLink& curr_outgoing_link = noc_model.get_single_noc_link(connecting_link);
112112

113113
// get the next router that we will visit if we travel across the current link
114114
next_router_id = curr_outgoing_link.get_sink_router();
@@ -154,7 +154,7 @@ bool XYRouting::move_to_next_router(NocRouterId& curr_router_id, int curr_router
154154
// If the next router was already visited, then this link is not valid, so indicate this and move onto processing the next link.
155155
if (found_next_router && !visited_next_router) {
156156
// if we are here then the link is legal to traverse, so add it to the found route and traverse the link by moving to the router connected by this link
157-
flow_route.push_back(*connecting_link);
157+
flow_route.push_back(connecting_link);
158158
curr_router_id = next_router_id;
159159

160160
// we found a suitable router to visit next, so add it to the set of visited routers

vpr/src/place/initial_placement.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1105,7 +1105,7 @@ void initial_placement(enum e_pad_loc_type pad_loc_type, const char* constraints
11051105

11061106
// route all the traffic flows in the NoC now that all the router cluster block have been placed (this is done only if the noc optimization is enabled by the user)
11071107
if (noc_enabled) {
1108-
initial_noc_placement();
1108+
initial_noc_routing();
11091109
}
11101110

11111111
//#ifdef VERBOSE

vpr/src/place/noc_place_utils.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ static vtr::vector<NocTrafficFlowId, TrafficFlowPlaceCost> traffic_flow_costs, p
99
static std::vector<NocTrafficFlowId> affected_traffic_flows;
1010
/*********************************************************** *****************************/
1111

12-
void initial_noc_placement(void) {
12+
void initial_noc_routing(void) {
1313
// need to get placement information about where the router cluster blocks are placed on the device
1414
const auto& place_ctx = g_vpr_ctx.placement();
1515

@@ -37,6 +37,22 @@ void initial_noc_placement(void) {
3737
return;
3838
}
3939

40+
void reinitialize_noc_routing(const t_noc_opts& noc_opts, t_placer_costs& costs) {
41+
auto& noc_ctx = g_vpr_ctx.mutable_noc();
42+
43+
// Zero out bandwidth usage for all links
44+
for (auto& noc_link : noc_ctx.noc_model.get_mutable_noc_links()) {
45+
noc_link.set_bandwidth_usage(0.0);
46+
}
47+
48+
// Route traffic flows and update link bandwidth usage
49+
initial_noc_routing();
50+
51+
// Initialize traffic_flow_costs
52+
costs.noc_aggregate_bandwidth_cost = comp_noc_aggregate_bandwidth_cost();
53+
costs.noc_latency_cost = comp_noc_latency_cost(noc_opts);
54+
}
55+
4056
void find_affected_noc_routers_and_update_noc_costs(const t_pl_blocks_to_be_moved& blocks_affected, double& noc_aggregate_bandwidth_delta_c, double& noc_latency_delta_c, const t_noc_opts& noc_opts) {
4157
// provides the positions where the affected blocks have moved to
4258
auto& place_ctx = g_vpr_ctx.placement();

vpr/src/place/noc_place_utils.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,23 @@ struct TrafficFlowPlaceCost {
4949
* routed. This is why this function should only be used once.
5050
*
5151
*/
52-
void initial_noc_placement(void);
52+
void initial_noc_routing(void);
53+
54+
/**
55+
* @brief Zeros out all link bandwidth usage an re-routes traffic flows.
56+
* Initializes static variables in noc_place_utils.cpp that are used to
57+
* keep track of NoC-related costs.
58+
*
59+
* This function should be called when a placement checkpoint is restored.
60+
* If the router placement in the checkpoint is different from the last
61+
* router placement before the checkpoint is restored, link bandwidth usage,
62+
* traffic flow routes, and static variable in noc_place_utils.cpp are no
63+
* longer valid and need to be re-initialized.
64+
*
65+
* @param noc_opts NoC-related options used to calculated NoC costs
66+
* @param costs Used to get aggregate bandwidth and latency costs.
67+
*/
68+
void reinitialize_noc_routing(const t_noc_opts& noc_opts, t_placer_costs& costs);
5369

5470
/**
5571
* @brief Goes through all the cluster blocks that were moved

vpr/src/place/place.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -953,7 +953,7 @@ void try_place(const Netlist<>& net_list,
953953
if (placer_opts.place_checkpointing)
954954
restore_best_placement(placement_checkpoint, timing_info, costs,
955955
placer_criticalities, placer_setup_slacks, place_delay_model,
956-
pin_timing_invalidator, crit_params);
956+
pin_timing_invalidator, crit_params, noc_opts);
957957

958958
if (placer_opts.placement_saves_per_temperature >= 1) {
959959
std::string filename = vtr::string_fmt("placement_%03d_%03d.place",

vpr/src/place/place_checkpoint.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "place_checkpoint.h"
2+
#include "noc_place_utils.h"
23

34
float t_placement_checkpoint::get_cp_cpd() { return cpd; }
45
double t_placement_checkpoint::get_cp_bb_cost() { return costs.bb_cost; }
@@ -26,7 +27,7 @@ void save_placement_checkpoint_if_needed(t_placement_checkpoint& placement_check
2627
}
2728
}
2829

29-
void restore_best_placement(t_placement_checkpoint& placement_checkpoint, std::shared_ptr<SetupTimingInfo>& timing_info, t_placer_costs& costs, std::unique_ptr<PlacerCriticalities>& placer_criticalities, std::unique_ptr<PlacerSetupSlacks>& placer_setup_slacks, std::unique_ptr<PlaceDelayModel>& place_delay_model, std::unique_ptr<NetPinTimingInvalidator>& pin_timing_invalidator, PlaceCritParams crit_params) {
30+
void restore_best_placement(t_placement_checkpoint& placement_checkpoint, std::shared_ptr<SetupTimingInfo>& timing_info, t_placer_costs& costs, std::unique_ptr<PlacerCriticalities>& placer_criticalities, std::unique_ptr<PlacerSetupSlacks>& placer_setup_slacks, std::unique_ptr<PlaceDelayModel>& place_delay_model, std::unique_ptr<NetPinTimingInvalidator>& pin_timing_invalidator, PlaceCritParams crit_params, const t_noc_opts& noc_opts) {
3031
if (placement_checkpoint.cp_is_valid() && timing_info->least_slack_critical_path().delay() > placement_checkpoint.get_cp_cpd() && costs.bb_cost < 1.05 * placement_checkpoint.get_cp_bb_cost()) {
3132
//restore the latest placement checkpoint
3233
costs = placement_checkpoint.restore_placement();
@@ -43,6 +44,15 @@ void restore_best_placement(t_placement_checkpoint& placement_checkpoint, std::s
4344
timing_info.get(),
4445
&costs);
4546

47+
/* If NoC is enabled, re-compute NoC costs and re-initialize NoC internal data structures.
48+
* If some routers have different locations than the last placement, NoC-related costs and
49+
* internal data structures that are used to keep track of each flow's cost are no longer valid,
50+
* and need to be re-computed from scratch.
51+
*/
52+
if (noc_opts.noc) {
53+
reinitialize_noc_routing(noc_opts, costs);
54+
}
55+
4656
VTR_LOG("\nCheckpoint restored\n");
4757
}
4858
}

vpr/src/place/place_checkpoint.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,5 +50,5 @@ class t_placement_checkpoint {
5050
void save_placement_checkpoint_if_needed(t_placement_checkpoint& placement_checkpoint, std::shared_ptr<SetupTimingInfo> timing_info, t_placer_costs& costs, float cpd);
5151

5252
//restore the checkpoint if it's better than the latest placement solution
53-
void restore_best_placement(t_placement_checkpoint& placement_checkpoint, std::shared_ptr<SetupTimingInfo>& timing_info, t_placer_costs& costs, std::unique_ptr<PlacerCriticalities>& placer_criticalities, std::unique_ptr<PlacerSetupSlacks>& placer_setup_slacks, std::unique_ptr<PlaceDelayModel>& place_delay_model, std::unique_ptr<NetPinTimingInvalidator>& pin_timing_invalidator, PlaceCritParams crit_params);
53+
void restore_best_placement(t_placement_checkpoint& placement_checkpoint, std::shared_ptr<SetupTimingInfo>& timing_info, t_placer_costs& costs, std::unique_ptr<PlacerCriticalities>& placer_criticalities, std::unique_ptr<PlacerSetupSlacks>& placer_setup_slacks, std::unique_ptr<PlaceDelayModel>& place_delay_model, std::unique_ptr<NetPinTimingInvalidator>& pin_timing_invalidator, PlaceCritParams crit_params, const t_noc_opts& noc_opts);
5454
#endif

vpr/test/test_noc_place_utils.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ TEST_CASE("test_initial_noc_placement", "[noc_place_utils]") {
179179
}
180180

181181
// now call the test function
182-
initial_noc_placement();
182+
initial_noc_routing();
183183

184184
// now verify the function by comparing the link bandwidths in the noc model (should have been updated by the test function) to the golden set
185185
int number_of_links = golden_link_bandwidths.size();
@@ -357,7 +357,7 @@ TEST_CASE("test_initial_comp_cost_functions", "[noc_place_utils]") {
357357

358358
// assume this works
359359
// this is needed to set up the global noc packet router and also global datastructures
360-
initial_noc_placement();
360+
initial_noc_routing();
361361

362362
SECTION("test_comp_noc_aggregate_bandwidth_cost") {
363363
//initialize all the cost calculator datastructures
@@ -613,7 +613,7 @@ TEST_CASE("test_find_affected_noc_routers_and_update_noc_costs, test_commit_noc_
613613

614614
// assume this works
615615
// this is needed to set up the global noc packet router and also global datastructures
616-
initial_noc_placement();
616+
initial_noc_routing();
617617

618618
// datastructure below will store the bandwidth usages of all the links
619619
// and will be updated throughout this test.
@@ -1344,7 +1344,7 @@ TEST_CASE("test_revert_noc_traffic_flow_routes", "[noc_place_utils]") {
13441344

13451345
// assume this works
13461346
// this is needed to set up the global noc packet router and also global datastructures
1347-
initial_noc_placement();
1347+
initial_noc_routing();
13481348

13491349
// datastructure below will store the bandwidth usages of all the links
13501350
// and will be updated throughout this test.

0 commit comments

Comments
 (0)