Skip to content

Commit ada220f

Browse files
extend occupancy repots to 3d and use rr graph extracted width
1 parent 441400a commit ada220f

File tree

1 file changed

+106
-70
lines changed

1 file changed

+106
-70
lines changed

vpr/src/base/stats.cpp

Lines changed: 106 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -30,25 +30,25 @@
3030
* channel segments in the FPGA.
3131
*/
3232
static void load_channel_occupancies(const Netlist<>& net_list,
33-
vtr::Matrix<int>& chanx_occ,
34-
vtr::Matrix<int>& chany_occ);
33+
vtr::NdMatrix<int, 3>& chanx_occ,
34+
vtr::NdMatrix<int, 3>& chany_occ);
3535

3636
/**
3737
* @brief Writes channel occupancy data to a file.
3838
*
3939
* Each row contains:
40-
* - (x, y) coordinate
40+
* - (layer, x, y) coordinate
4141
* - Occupancy count
4242
* - Occupancy percentage (occupancy / capacity)
4343
* - Channel capacity
4444
*
4545
* @param filename Output file path.
4646
* @param occupancy Matrix of occupancy counts.
47-
* @param capacity_list List of channel capacities (per y for chanx, per x for chany).
47+
* @param capacity Channel capacities.
4848
*/
49-
static void write_channel_occupancy_table(const std::string_view filename,
50-
const vtr::Matrix<int>& occupancy,
51-
const std::vector<int>& capacity_list);
49+
static void write_channel_occupancy_table( std::string_view filename,
50+
const vtr::NdMatrix<int, 3>& occupancy,
51+
const vtr::NdMatrix<int, 3>& capacity);
5252

5353
/**
5454
* @brief Figures out maximum, minimum and average number of bends
@@ -188,66 +188,94 @@ void length_and_bends_stats(const Netlist<>& net_list, bool is_flat) {
188188
static void get_channel_occupancy_stats(const Netlist<>& net_list, bool /***/) {
189189
const auto& device_ctx = g_vpr_ctx.device();
190190

191-
auto chanx_occ = vtr::Matrix<int>({{
191+
auto chanx_occ = vtr::NdMatrix<int, 3>({{
192+
device_ctx.grid.get_num_layers(),
192193
device_ctx.grid.width(), //[0 .. device_ctx.grid.width() - 1] (length of x channel)
193194
device_ctx.grid.height() - 1 //[0 .. device_ctx.grid.height() - 2] (# x channels)
194195
}},
195196
0);
196197

197-
auto chany_occ = vtr::Matrix<int>({{
198+
auto chany_occ = vtr::NdMatrix<int, 3>({{
199+
device_ctx.grid.get_num_layers(),
198200
device_ctx.grid.width() - 1, //[0 .. device_ctx.grid.width() - 2] (# y channels)
199201
device_ctx.grid.height() //[0 .. device_ctx.grid.height() - 1] (length of y channel)
200202
}},
201203
0);
202204

203205
load_channel_occupancies(net_list, chanx_occ, chany_occ);
204206

205-
write_channel_occupancy_table("chanx_occupancy.txt", chanx_occ, device_ctx.chan_width.x_list);
206-
write_channel_occupancy_table("chany_occupancy.txt", chany_occ, device_ctx.chan_width.y_list);
207+
write_channel_occupancy_table("chanx_occupancy.txt", chanx_occ, device_ctx.rr_chanx_width);
208+
write_channel_occupancy_table("chany_occupancy.txt", chany_occ, device_ctx.rr_chany_width);
209+
210+
int total_cap_x = 0;
211+
int total_used_x = 0;
212+
int total_cap_y = 0;
213+
int total_used_y = 0;
207214

208215
VTR_LOG("\n");
209-
VTR_LOG("X - Directed channels: j max occ ave occ capacity\n");
210-
VTR_LOG(" ---- ------- ------- --------\n");
211-
212-
int total_x = 0;
213-
for (size_t j = 0; j < device_ctx.grid.height() - 1; ++j) {
214-
total_x += device_ctx.chan_width.x_list[j];
215-
float ave_occ = 0.0;
216-
int max_occ = -1;
217-
218-
for (size_t i = 1; i < device_ctx.grid.width(); ++i) {
219-
max_occ = std::max(chanx_occ[i][j], max_occ);
220-
ave_occ += chanx_occ[i][j];
216+
VTR_LOG("X - Directed channels: layer j max occ ave occ ave cap\n");
217+
VTR_LOG(" ----- ---- -------- -------- --------\n");
218+
219+
for (size_t layer = 0; layer < device_ctx.grid.get_num_layers(); ++layer) {
220+
for (size_t j = 0; j < device_ctx.grid.height() - 1; ++j) {
221+
float ave_occ = 0.0f;
222+
float ave_cap = 0.0f;
223+
int max_occ = -1;
224+
225+
for (size_t i = 1; i < device_ctx.grid.width(); ++i) {
226+
max_occ = std::max(chanx_occ[layer][i][j], max_occ);
227+
ave_occ += chanx_occ[layer][i][j];
228+
ave_cap += device_ctx.rr_chanx_width[layer][i][j];
229+
230+
total_cap_x += chanx_occ[layer][i][j];
231+
total_used_x += chanx_occ[layer][i][j];
232+
}
233+
ave_occ /= device_ctx.grid.width() - 2;
234+
ave_cap /= device_ctx.grid.width() - 2;
235+
VTR_LOG(" %5zu %4zu %8d %8.3f %8.0f\n",
236+
layer, j, max_occ, ave_occ, ave_cap);
221237
}
222-
ave_occ /= device_ctx.grid.width();
223-
VTR_LOG(" %4d %7d %7.3f %8d\n", j, max_occ, ave_occ, device_ctx.chan_width.x_list[j]);
224238
}
225239

226-
VTR_LOG("Y - Directed channels: i max occ ave occ capacity\n");
227-
VTR_LOG(" ---- ------- ------- --------\n");
240+
VTR_LOG("Y - Directed channels: layer i max occ ave occ ave cap\n");
241+
VTR_LOG(" ----- ---- -------- -------- --------\n");
242+
243+
for (size_t layer = 0; layer < device_ctx.grid.get_num_layers(); ++layer) {
244+
for (size_t i = 0; i < device_ctx.grid.width() - 1; ++i) {
245+
float ave_occ = 0.0;
246+
float ave_cap = 0.0;
247+
int max_occ = -1;
228248

229-
int total_y = 0;
230-
for (size_t i = 0; i < device_ctx.grid.width() - 1; ++i) {
231-
total_y += device_ctx.chan_width.y_list[i];
232-
float ave_occ = 0.0;
233-
int max_occ = -1;
249+
for (size_t j = 1; j < device_ctx.grid.height(); ++j) {
250+
max_occ = std::max(chany_occ[layer][i][j], max_occ);
251+
ave_occ += chany_occ[layer][i][j];
252+
ave_cap += device_ctx.rr_chany_width[layer][i][j];
234253

235-
for (size_t j = 1; j < device_ctx.grid.height(); ++j) {
236-
max_occ = std::max(chany_occ[i][j], max_occ);
237-
ave_occ += chany_occ[i][j];
254+
total_cap_y += chany_occ[layer][i][j];
255+
total_used_y += chany_occ[layer][i][j];
256+
}
257+
ave_occ /= device_ctx.grid.height() - 2;
258+
ave_cap /= device_ctx.grid.height() - 2;
259+
VTR_LOG(" %5zu %4zu %8d %8.3f %8.0f\n",
260+
layer, i, max_occ, ave_occ, ave_cap);
238261
}
239-
ave_occ /= device_ctx.grid.height();
240-
VTR_LOG(" %4d %7d %7.3f %8d\n", i, max_occ, ave_occ, device_ctx.chan_width.y_list[i]);
241262
}
242263

243264
VTR_LOG("\n");
244-
VTR_LOG("Total tracks in x-direction: %d, in y-direction: %d\n", total_x, total_y);
265+
266+
VTR_LOG("Total existing wires segments: CHANX %d, CHANY %d, ALL %d\n",
267+
total_cap_x, total_cap_y, total_cap_x + total_cap_y);
268+
VTR_LOG("Total used wires segments: CHANX %d, CHANY %d, ALL %d\n",
269+
total_used_x, total_used_y, total_used_x + total_used_y);
270+
VTR_LOG("Usage percentage: CHANX %d%%, CHANY %d%%, ALL %d%%\n",
271+
(float)total_used_x / total_cap_x, (float)total_used_y / total_cap_y, (float)(total_used_x + total_used_y) / (total_cap_x + total_cap_y));
272+
245273
VTR_LOG("\n");
246274
}
247275

248-
static void write_channel_occupancy_table(const std::string_view filename,
249-
const vtr::Matrix<int>& occupancy,
250-
const std::vector<int>& capacity_list) {
276+
static void write_channel_occupancy_table(std::string_view filename,
277+
const vtr::NdMatrix<int, 3>& occupancy,
278+
const vtr::NdMatrix<int, 3>& capacity) {
251279
constexpr int w_coord = 6;
252280
constexpr int w_value = 12;
253281
constexpr int w_percent = 12;
@@ -258,64 +286,72 @@ static void write_channel_occupancy_table(const std::string_view filename,
258286
return;
259287
}
260288

261-
file << std::setw(w_coord) << "x"
262-
<< std::setw(w_coord) << "y"
263-
<< std::setw(w_value) << "occupancy"
289+
file << std::setw(w_coord) << "layer"
290+
<< std::setw(w_coord) << "x"
291+
<< std::setw(w_coord) << "y"
292+
<< std::setw(w_value) << "occupancy"
264293
<< std::setw(w_percent) << "%"
265-
<< std::setw(w_value) << "capacity"
294+
<< std::setw(w_value) << "capacity"
266295
<< "\n";
267296

268-
for (size_t y = 0; y < occupancy.dim_size(1); ++y) {
269-
int capacity = capacity_list[y];
270-
for (size_t x = 0; x < occupancy.dim_size(0); ++x) {
271-
int occ = occupancy[x][y];
272-
float percent = capacity > 0 ? static_cast<float>(occ) / capacity * 100.0f : 0.0f;
273-
274-
file << std::setw(w_coord) << x
275-
<< std::setw(w_coord) << y
276-
<< std::setw(w_value) << occ
277-
<< std::setw(w_percent) << std::fixed << std::setprecision(3) << percent
278-
<< std::setw(w_value) << capacity
279-
<< "\n";
297+
for (size_t layer = 0; layer < occupancy.dim_size(0); ++layer) {
298+
for (size_t x = 0; x < occupancy.dim_size(1); ++x) {
299+
for (size_t y = 0; y < occupancy.dim_size(2); ++y) {
300+
int occ = occupancy[layer][x][y];
301+
int cap = capacity[layer][x][y];
302+
float percent = (cap > 0) ? static_cast<float>(occ) / cap * 100.0f : 0.0f;
303+
304+
file << std::setw(w_coord) << layer
305+
<< std::setw(w_coord) << x
306+
<< std::setw(w_coord) << y
307+
<< std::setw(w_value) << occ
308+
<< std::setw(w_percent) << std::fixed << std::setprecision(3) << percent
309+
<< std::setw(w_value) << cap
310+
<< "\n";
311+
}
280312
}
281313
}
282314

283315
file.close();
284316
}
285317

286318
static void load_channel_occupancies(const Netlist<>& net_list,
287-
vtr::Matrix<int>& chanx_occ,
288-
vtr::Matrix<int>& chany_occ) {
289-
const auto& device_ctx = g_vpr_ctx.device();
319+
vtr::NdMatrix<int, 3>& chanx_occ,
320+
vtr::NdMatrix<int, 3>& chany_occ) {
321+
const DeviceContext& device_ctx = g_vpr_ctx.device();
290322
const auto& rr_graph = device_ctx.rr_graph;
291-
const auto& route_ctx = g_vpr_ctx.routing();
323+
const RoutingContext& route_ctx = g_vpr_ctx.routing();
292324

293-
/* First set the occupancy of everything to zero. */
325+
// First set the occupancy of everything to zero.
294326
chanx_occ.fill(0);
295327
chany_occ.fill(0);
296328

297-
/* Now go through each net and count the tracks and pins used everywhere */
298-
for (auto net_id : net_list.nets()) {
299-
/* Skip global and empty nets. */
300-
if (net_list.net_is_ignored(net_id) && net_list.net_sinks(net_id).size() != 0)
329+
// Now go through each net and count the tracks and pins used everywhere
330+
for (ParentNetId net_id : net_list.nets()) {
331+
// Skip global and empty nets.
332+
if (net_list.net_is_ignored(net_id) && net_list.net_sinks(net_id).size() != 0) {
301333
continue;
334+
}
302335

303-
auto& tree = route_ctx.route_trees[net_id];
304-
if (!tree)
336+
const vtr::optional<RouteTree>& tree = route_ctx.route_trees[net_id];
337+
if (!tree) {
305338
continue;
339+
}
306340

307341
for (const RouteTreeNode& rt_node : tree.value().all_nodes()) {
308342
RRNodeId inode = rt_node.inode;
309343
e_rr_type rr_type = rr_graph.node_type(inode);
310344

311345
if (rr_type == e_rr_type::CHANX) {
312346
int j = rr_graph.node_ylow(inode);
347+
int layer = rr_graph.node_layer_low(inode);
313348
for (int i = rr_graph.node_xlow(inode); i <= rr_graph.node_xhigh(inode); i++)
314-
chanx_occ[i][j]++;
349+
chanx_occ[layer][i][j]++;
315350
} else if (rr_type == e_rr_type::CHANY) {
316351
int i = rr_graph.node_xlow(inode);
352+
int layer = rr_graph.node_layer_low(inode);
317353
for (int j = rr_graph.node_ylow(inode); j <= rr_graph.node_yhigh(inode); j++)
318-
chany_occ[i][j]++;
354+
chany_occ[layer][i][j]++;
319355
}
320356
}
321357
}

0 commit comments

Comments
 (0)