From 400b5a10c3397ed6842fca870b65075d67237730 Mon Sep 17 00:00:00 2001 From: amin1377 Date: Fri, 18 Oct 2024 09:17:41 -0400 Subject: [PATCH 01/18] [vpr][place] add acc_tile_num_inter_die_conn --- vpr/src/place/net_cost_handler.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/vpr/src/place/net_cost_handler.cpp b/vpr/src/place/net_cost_handler.cpp index 63fd0bf07fd..4d651b4c5d1 100644 --- a/vpr/src/place/net_cost_handler.cpp +++ b/vpr/src/place/net_cost_handler.cpp @@ -271,8 +271,21 @@ void NetCostHandler::alloc_and_load_for_fast_vertical_cost_update_(float place_c } } - for (int x_high = 0; x_high < (int)device_ctx.grid.width(); x_high++) { - for (int y_high = 0; y_high < (int)device_ctx.grid.height(); y_high++) { + vtr::NdMatrix acc_tile_num_inter_die_conn({grid_width, grid_height}, 0.); + acc_tile_num_inter_die_conn[0][0] = tile_num_inter_die_conn[0][0]; + // Initialize the first row and column + for (size_t x = 1; x < device_ctx.grid.width(); x++) { + acc_tile_num_inter_die_conn[x][0] = acc_tile_num_inter_die_conn[x-1][0] + \ + tile_num_inter_die_conn[x][0]; + } + + for (size_t y = 1; y < device_ctx.grid.height(); y++) { + acc_tile_num_inter_die_conn[0][y] = acc_tile_num_inter_die_conn[0][y-1] + \ + tile_num_inter_die_conn[0][y]; + } + + for (size_t x_high = 0; x_high < device_ctx.grid.width(); x_high++) { + for (size_t y_high = 0; y_high < device_ctx.grid.height(); y_high++) { for (int x_low = 0; x_low <= x_high; x_low++) { for (int y_low = 0; y_low <= y_high; y_low++) { int num_inter_die_conn = 0; From 4018188139cda74cc150c177bb9ffec303274b9a Mon Sep 17 00:00:00 2001 From: amin1377 Date: Fri, 18 Oct 2024 09:39:24 -0400 Subject: [PATCH 02/18] [vpr][place] use prefix sum to populate chanz_place_cost_fac_ --- vpr/src/place/net_cost_handler.cpp | 32 ++++++++++++++++-------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/vpr/src/place/net_cost_handler.cpp b/vpr/src/place/net_cost_handler.cpp index 4d651b4c5d1..895893930e5 100644 --- a/vpr/src/place/net_cost_handler.cpp +++ b/vpr/src/place/net_cost_handler.cpp @@ -284,22 +284,24 @@ void NetCostHandler::alloc_and_load_for_fast_vertical_cost_update_(float place_c tile_num_inter_die_conn[0][y]; } - for (size_t x_high = 0; x_high < device_ctx.grid.width(); x_high++) { - for (size_t y_high = 0; y_high < device_ctx.grid.height(); y_high++) { - for (int x_low = 0; x_low <= x_high; x_low++) { - for (int y_low = 0; y_low <= y_high; y_low++) { - int num_inter_die_conn = 0; - for (int x = x_low; x <= x_high; x++) { - for (int y = y_low; y <= y_high; y++) { - num_inter_die_conn += tile_num_inter_die_conn[x][y]; - } - } + for (size_t x_high = 1; x_high < device_ctx.grid.width(); x_high++) { + for (size_t y_high = 1; y_high < device_ctx.grid.height(); y_high++) { + for (size_t x_low = 1; x_low <= x_high; x_low++) { + for (size_t y_low = 1; y_low <= y_high; y_low++) { + int num_inter_die_conn = acc_tile_num_inter_die_conn[x_high][y_high] - \ + acc_tile_num_inter_die_conn[x_low-1][y_high] - \ + acc_tile_num_inter_die_conn[x_high][y_low-1] + \ + acc_tile_num_inter_die_conn[x_low-1][y_low-1]; int seen_num_tiles = (x_high - x_low + 1) * (y_high - y_low + 1); - chanz_place_cost_fac_[x_high][y_high][x_low][y_low] = seen_num_tiles / static_cast(num_inter_die_conn); - - chanz_place_cost_fac_[x_high][y_high][x_low][y_low] = pow( - (double)chanz_place_cost_fac_[x_high][y_high][x_low][y_low], - (double)place_cost_exp); + if (num_inter_die_conn == 0) { + VTR_LOG_WARN("CHANZ place cost fac is 0 at (%lu,%lu), (%lu,%lu)\n", x_low, y_low, x_high, y_high); + chanz_place_cost_fac_[x_high][y_high][x_low][y_low] = 1.0f; + } else { + chanz_place_cost_fac_[x_high][y_high][x_low][y_low] = seen_num_tiles / static_cast(num_inter_die_conn); + chanz_place_cost_fac_[x_high][y_high][x_low][y_low] = pow( + (double)chanz_place_cost_fac_[x_high][y_high][x_low][y_low], + (double)place_cost_exp); + } } } } From 11ee10f64f256bc8f7f6f1737bb288e2d21df81d Mon Sep 17 00:00:00 2001 From: amin1377 Date: Wed, 30 Oct 2024 09:38:47 -0400 Subject: [PATCH 03/18] [vpr][place] initialize other entried of acc_tile_num_inter_die_conn --- vpr/src/place/net_cost_handler.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/vpr/src/place/net_cost_handler.cpp b/vpr/src/place/net_cost_handler.cpp index 895893930e5..b953af95062 100644 --- a/vpr/src/place/net_cost_handler.cpp +++ b/vpr/src/place/net_cost_handler.cpp @@ -283,6 +283,14 @@ void NetCostHandler::alloc_and_load_for_fast_vertical_cost_update_(float place_c acc_tile_num_inter_die_conn[0][y] = acc_tile_num_inter_die_conn[0][y-1] + \ tile_num_inter_die_conn[0][y]; } + + for (size_t x_high = 1; x_high < device_ctx.grid.width(); x_high++) { + for (size_t y_high = 1; y_high < device_ctx.grid.height(); y_high++) { + acc_tile_num_inter_die_conn[x_high][y_high] = acc_tile_num_inter_die_conn[x_high-1][y_high] + \ + acc_tile_num_inter_die_conn[x_high][y_high-1] - \ + acc_tile_num_inter_die_conn[x_high][y_high]; + } + } for (size_t x_high = 1; x_high < device_ctx.grid.width(); x_high++) { for (size_t y_high = 1; y_high < device_ctx.grid.height(); y_high++) { From 8bead96eb120063b2821b272013748b5e6ee0fdd Mon Sep 17 00:00:00 2001 From: amin1377 Date: Wed, 30 Oct 2024 10:20:19 -0400 Subject: [PATCH 04/18] [vpr][place][net_cost] add get_chanz_cost_factor signiture and acc_tile_num_inter_die_conn_ --- vpr/src/place/net_cost_handler.h | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/vpr/src/place/net_cost_handler.h b/vpr/src/place/net_cost_handler.h index 3048b7637ea..c41c1680275 100644 --- a/vpr/src/place/net_cost_handler.h +++ b/vpr/src/place/net_cost_handler.h @@ -196,12 +196,12 @@ class NetCostHandler { vtr::NdOffsetMatrix chanx_place_cost_fac_; // [-1...device_ctx.grid.width()-1] vtr::NdOffsetMatrix chany_place_cost_fac_; // [-1...device_ctx.grid.height()-1] /** - @brief This data structure functions similarly to the matrices described above - but is applied to 3D connections linking different FPGA layers. It is used in the - placement cost function calculation, where the height of the bounding box is divided - by the average number of inter-die connections within the bounding box. + @brief This data structure stores the cumulative number of inter-die connections from the lower-left corner. + * It is later used to calculate the chanZ factor, which functions similarly to chanx_place_cost_fac_ and chany_place_cost_fac_, + * but applies to the height of the bounding box. The chanZ factor is calculated during block placement because storing it in the + * same way as the X and Y cost factors would require a 4D array and population it is an O(n^2) operation. */ - vtr::NdMatrix chanz_place_cost_fac_; // [0...device_ctx.grid.width()-1][0...device_ctx.grid.height()-1][0...device_ctx.grid.width()-1][0...device_ctx.grid.height()-1] + vtr::NdMatrix acc_tile_num_inter_die_conn_; private: @@ -511,4 +511,14 @@ class NetCostHandler { */ double get_net_wirelength_from_layer_bb_(ClusterNetId net_id); + /** + * @brief Calculate the chanz cost factor based on the inverse of the average number of inter-die connections + * in the given bounding box. This cost factor increases the placement cost for blocks that require inter-layer + * connections in areas with, on average, fewer inter-die connections. If inter-die connections are evenly + * distributed across tiles, the cost factor will be the same for all bounding boxes. + * @param bounding_box Bounding box of the net which chanz cost factor is to be calculated + * @return ChanZ cost factor + */ + float get_chanz_cost_factor(const t_bb& bounding_box); + }; From bea400e08a797bcaefbfa4623f96f91cf531f9e5 Mon Sep 17 00:00:00 2001 From: amin1377 Date: Wed, 30 Oct 2024 10:32:42 -0400 Subject: [PATCH 05/18] [vpr][place][net_cost] get_chanz_cost_factor impl --- vpr/src/place/net_cost_handler.cpp | 26 ++++++++++++++++++++++++++ vpr/src/place/net_cost_handler.h | 4 ++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/vpr/src/place/net_cost_handler.cpp b/vpr/src/place/net_cost_handler.cpp index b953af95062..cdb5cc7bc6d 100644 --- a/vpr/src/place/net_cost_handler.cpp +++ b/vpr/src/place/net_cost_handler.cpp @@ -1604,6 +1604,32 @@ double NetCostHandler::get_net_wirelength_from_layer_bb_(ClusterNetId net_id) { return ncost; } +float NetCostHandler::get_chanz_cost_factor(const t_bb& bounding_box, float place_cost_exp) { + int x_high = bounding_box.xmax; + int x_low = bounding_box.xmin; + int y_high = bounding_box.ymax; + int y_low = bounding_box.ymin; + + int num_inter_dir_conn = acc_tile_num_inter_die_conn_[x_high][y_high] - \ + acc_tile_num_inter_die_conn_[x_low-1][y_high] - \ + acc_tile_num_inter_die_conn_[x_high][y_low-1] + \ + acc_tile_num_inter_die_conn_[x_low-1][y_low-1]; + + int bb_num_tiles = (x_high - x_low + 1) * (y_high - y_low + 1); + + float z_cost_factor; + if (num_inter_dir_conn == 0) { + return 1.0f; + } else { + z_cost_factor = bb_num_tiles / static_cast(num_inter_dir_conn); + z_cost_factor = pow((double)z_cost_factor, (double)place_cost_exp); + + } + + return z_cost_factor; + +} + double NetCostHandler::recompute_bb_cost_() { double cost = 0; diff --git a/vpr/src/place/net_cost_handler.h b/vpr/src/place/net_cost_handler.h index c41c1680275..86581989ee9 100644 --- a/vpr/src/place/net_cost_handler.h +++ b/vpr/src/place/net_cost_handler.h @@ -201,7 +201,7 @@ class NetCostHandler { * but applies to the height of the bounding box. The chanZ factor is calculated during block placement because storing it in the * same way as the X and Y cost factors would require a 4D array and population it is an O(n^2) operation. */ - vtr::NdMatrix acc_tile_num_inter_die_conn_; + vtr::NdMatrix acc_tile_num_inter_die_conn_; private: @@ -519,6 +519,6 @@ class NetCostHandler { * @param bounding_box Bounding box of the net which chanz cost factor is to be calculated * @return ChanZ cost factor */ - float get_chanz_cost_factor(const t_bb& bounding_box); + float get_chanz_cost_factor(const t_bb& bounding_box, float place_cost_exp); }; From 01b9cd63d3ae44d2640f543d0668fd72f461454f Mon Sep 17 00:00:00 2001 From: amin1377 Date: Wed, 30 Oct 2024 10:48:36 -0400 Subject: [PATCH 06/18] [vpr][place][net_cost] remove place_cost_exp from functions arguments --- vpr/src/place/net_cost_handler.h | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/vpr/src/place/net_cost_handler.h b/vpr/src/place/net_cost_handler.h index 86581989ee9..8f473af9930 100644 --- a/vpr/src/place/net_cost_handler.h +++ b/vpr/src/place/net_cost_handler.h @@ -250,11 +250,8 @@ class NetCostHandler { * have to bother calling this routine; when using the cost function described above, however, you must always * call this routine before you do any placement cost determination. The place_cost_exp factor specifies to * what power the width of the channel should be taken -- larger numbers make narrower channels more expensive. - * - * @param place_cost_exp It is an exponent to which you take the average inverse channel capacity; - * a higher value would favour wider channels more over narrower channels during placement (usually we use 1). */ - void alloc_and_load_chan_w_factors_for_place_cost_(float place_cost_exp); + void alloc_and_load_chan_w_factors_for_place_cost_(); /** * @brief Allocates and loads the chanz_place_cost_fac array with the inverse of @@ -262,11 +259,8 @@ class NetCostHandler { * * @details This is only useful for multi-die FPGAs. The place_cost_exp factor specifies to * what power the average number of inter-die connections should be take -- larger numbers make narrower channels more expensive. - * - * @param place_cost_exp It is an exponent to which you take the average number of inter-die connections; - * a higher value would favour areas with more inter-die connections over areas with less of those during placement (usually we use 1). */ - void alloc_and_load_for_fast_vertical_cost_update_(float place_cost_exp); + void alloc_and_load_for_fast_vertical_cost_update_(); /** * @brief Calculate the new connection delay and timing cost of all the @@ -519,6 +513,6 @@ class NetCostHandler { * @param bounding_box Bounding box of the net which chanz cost factor is to be calculated * @return ChanZ cost factor */ - float get_chanz_cost_factor(const t_bb& bounding_box, float place_cost_exp); + float get_chanz_cost_factor(const t_bb& bounding_box); }; From af5659d76c2d440c22bf4330a43a05ab96c32c24 Mon Sep 17 00:00:00 2001 From: amin1377 Date: Wed, 30 Oct 2024 11:20:14 -0400 Subject: [PATCH 07/18] [vpr][place][net_cost] fix num_inter_dir_conn corner cases --- vpr/src/place/net_cost_handler.cpp | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/vpr/src/place/net_cost_handler.cpp b/vpr/src/place/net_cost_handler.cpp index cdb5cc7bc6d..47d2e636025 100644 --- a/vpr/src/place/net_cost_handler.cpp +++ b/vpr/src/place/net_cost_handler.cpp @@ -1604,16 +1604,29 @@ double NetCostHandler::get_net_wirelength_from_layer_bb_(ClusterNetId net_id) { return ncost; } -float NetCostHandler::get_chanz_cost_factor(const t_bb& bounding_box, float place_cost_exp) { +float NetCostHandler::get_chanz_cost_factor(const t_bb& bounding_box) { + float place_cost_exp = placer_opts_.place_cost_exp; int x_high = bounding_box.xmax; int x_low = bounding_box.xmin; int y_high = bounding_box.ymax; int y_low = bounding_box.ymin; - int num_inter_dir_conn = acc_tile_num_inter_die_conn_[x_high][y_high] - \ - acc_tile_num_inter_die_conn_[x_low-1][y_high] - \ - acc_tile_num_inter_die_conn_[x_high][y_low-1] + \ - acc_tile_num_inter_die_conn_[x_low-1][y_low-1]; + int num_inter_dir_conn; + + if (x_low == 0 && y_low == 0) { + num_inter_dir_conn = acc_tile_num_inter_die_conn_[x_high][y_high]; + } else if (x_low == 0) { + num_inter_dir_conn = acc_tile_num_inter_die_conn_[x_high][y_high] - \ + acc_tile_num_inter_die_conn_[x_high][y_low-1]; + } else if (y_low == 0) { + num_inter_dir_conn = acc_tile_num_inter_die_conn_[x_high][y_high] - \ + acc_tile_num_inter_die_conn_[x_low-1][y_high]; + } else { + num_inter_dir_conn = acc_tile_num_inter_die_conn_[x_high][y_high] - \ + acc_tile_num_inter_die_conn_[x_low-1][y_high] - \ + acc_tile_num_inter_die_conn_[x_high][y_low-1] + \ + acc_tile_num_inter_die_conn_[x_low-1][y_low-1]; + } int bb_num_tiles = (x_high - x_low + 1) * (y_high - y_low + 1); @@ -1623,7 +1636,6 @@ float NetCostHandler::get_chanz_cost_factor(const t_bb& bounding_box, float plac } else { z_cost_factor = bb_num_tiles / static_cast(num_inter_dir_conn); z_cost_factor = pow((double)z_cost_factor, (double)place_cost_exp); - } return z_cost_factor; From 736d826d5aa5f6e0af3cd3b0a4c4b3f52a4b67a4 Mon Sep 17 00:00:00 2001 From: amin1377 Date: Wed, 30 Oct 2024 11:21:31 -0400 Subject: [PATCH 08/18] [vpr][place][net_cost] call get_chanz_cost_factor instead of chanz_place_cost_fac_ --- vpr/src/place/net_cost_handler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vpr/src/place/net_cost_handler.cpp b/vpr/src/place/net_cost_handler.cpp index 47d2e636025..d681f6f1437 100644 --- a/vpr/src/place/net_cost_handler.cpp +++ b/vpr/src/place/net_cost_handler.cpp @@ -1501,7 +1501,7 @@ double NetCostHandler::get_net_cube_bb_cost_(ClusterNetId net_id, bool use_ts) { ncost = (bb.xmax - bb.xmin + 1) * crossing * chanx_place_cost_fac_[bb.ymax][bb.ymin - 1]; ncost += (bb.ymax - bb.ymin + 1) * crossing * chany_place_cost_fac_[bb.xmax][bb.xmin - 1]; if (is_multi_layer) { - ncost += (bb.layer_max - bb.layer_min) * crossing * chanz_place_cost_fac_[bb.xmax][bb.ymax][bb.xmin][bb.ymin]; + ncost += (bb.layer_max - bb.layer_min) * crossing * get_chanz_cost_factor(bb); } return ncost; From 1a3e56dc73b8d5a2f8797bd6361632c79c38cc6b Mon Sep 17 00:00:00 2001 From: amin1377 Date: Wed, 30 Oct 2024 11:22:52 -0400 Subject: [PATCH 09/18] [vpr][place][net_cost] remove chanz_place_cost_fac_ calculation --- vpr/src/place/net_cost_handler.cpp | 48 ++++++++---------------------- 1 file changed, 13 insertions(+), 35 deletions(-) diff --git a/vpr/src/place/net_cost_handler.cpp b/vpr/src/place/net_cost_handler.cpp index d681f6f1437..64e3c97c8da 100644 --- a/vpr/src/place/net_cost_handler.cpp +++ b/vpr/src/place/net_cost_handler.cpp @@ -149,10 +149,11 @@ NetCostHandler::NetCostHandler(const t_placer_opts& placer_opts, * been recomputed. */ bb_update_status_.resize(num_nets, NetUpdateState::NOT_UPDATED_YET); - alloc_and_load_chan_w_factors_for_place_cost_(placer_opts_.place_cost_exp); + alloc_and_load_chan_w_factors_for_place_cost_(); } -void NetCostHandler::alloc_and_load_chan_w_factors_for_place_cost_(float place_cost_exp) { +void NetCostHandler::alloc_and_load_chan_w_factors_for_place_cost_() { + float place_cost_exp = placer_opts_.place_cost_exp; auto& device_ctx = g_vpr_ctx.device(); const int grid_height = device_ctx.grid.height(); @@ -229,11 +230,11 @@ void NetCostHandler::alloc_and_load_chan_w_factors_for_place_cost_(float place_c } if (device_ctx.grid.get_num_layers() > 1) { - alloc_and_load_for_fast_vertical_cost_update_(place_cost_exp); + alloc_and_load_for_fast_vertical_cost_update_(); } } -void NetCostHandler::alloc_and_load_for_fast_vertical_cost_update_(float place_cost_exp) { +void NetCostHandler::alloc_and_load_for_fast_vertical_cost_update_() { const auto& device_ctx = g_vpr_ctx.device(); const auto& rr_graph = device_ctx.rr_graph; @@ -241,7 +242,7 @@ void NetCostHandler::alloc_and_load_for_fast_vertical_cost_update_(float place_c const size_t grid_width = device_ctx.grid.width(); - chanz_place_cost_fac_ = vtr::NdMatrix({grid_width, grid_height, grid_width, grid_height}, 0.); + acc_tile_num_inter_die_conn_ = vtr::NdMatrix({grid_width, grid_height}, 0.); vtr::NdMatrix tile_num_inter_die_conn({grid_width, grid_height}, 0.); @@ -271,47 +272,24 @@ void NetCostHandler::alloc_and_load_for_fast_vertical_cost_update_(float place_c } } - vtr::NdMatrix acc_tile_num_inter_die_conn({grid_width, grid_height}, 0.); - acc_tile_num_inter_die_conn[0][0] = tile_num_inter_die_conn[0][0]; + acc_tile_num_inter_die_conn_[0][0] = tile_num_inter_die_conn[0][0]; // Initialize the first row and column for (size_t x = 1; x < device_ctx.grid.width(); x++) { - acc_tile_num_inter_die_conn[x][0] = acc_tile_num_inter_die_conn[x-1][0] + \ + acc_tile_num_inter_die_conn_[x][0] = acc_tile_num_inter_die_conn_[x-1][0] + \ tile_num_inter_die_conn[x][0]; } for (size_t y = 1; y < device_ctx.grid.height(); y++) { - acc_tile_num_inter_die_conn[0][y] = acc_tile_num_inter_die_conn[0][y-1] + \ + acc_tile_num_inter_die_conn_[0][y] = acc_tile_num_inter_die_conn_[0][y-1] + \ tile_num_inter_die_conn[0][y]; } for (size_t x_high = 1; x_high < device_ctx.grid.width(); x_high++) { for (size_t y_high = 1; y_high < device_ctx.grid.height(); y_high++) { - acc_tile_num_inter_die_conn[x_high][y_high] = acc_tile_num_inter_die_conn[x_high-1][y_high] + \ - acc_tile_num_inter_die_conn[x_high][y_high-1] - \ - acc_tile_num_inter_die_conn[x_high][y_high]; - } - } - - for (size_t x_high = 1; x_high < device_ctx.grid.width(); x_high++) { - for (size_t y_high = 1; y_high < device_ctx.grid.height(); y_high++) { - for (size_t x_low = 1; x_low <= x_high; x_low++) { - for (size_t y_low = 1; y_low <= y_high; y_low++) { - int num_inter_die_conn = acc_tile_num_inter_die_conn[x_high][y_high] - \ - acc_tile_num_inter_die_conn[x_low-1][y_high] - \ - acc_tile_num_inter_die_conn[x_high][y_low-1] + \ - acc_tile_num_inter_die_conn[x_low-1][y_low-1]; - int seen_num_tiles = (x_high - x_low + 1) * (y_high - y_low + 1); - if (num_inter_die_conn == 0) { - VTR_LOG_WARN("CHANZ place cost fac is 0 at (%lu,%lu), (%lu,%lu)\n", x_low, y_low, x_high, y_high); - chanz_place_cost_fac_[x_high][y_high][x_low][y_low] = 1.0f; - } else { - chanz_place_cost_fac_[x_high][y_high][x_low][y_low] = seen_num_tiles / static_cast(num_inter_die_conn); - chanz_place_cost_fac_[x_high][y_high][x_low][y_low] = pow( - (double)chanz_place_cost_fac_[x_high][y_high][x_low][y_low], - (double)place_cost_exp); - } - } - } + acc_tile_num_inter_die_conn_[x_high][y_high] = acc_tile_num_inter_die_conn_[x_high-1][y_high] + \ + acc_tile_num_inter_die_conn_[x_high][y_high-1] - \ + acc_tile_num_inter_die_conn_[x_high-1][y_high-1] + \ + tile_num_inter_die_conn[x_high][y_high]; } } } From 54fe8d7751e1e4bb70b57cd9efb5f8ead27d6d75 Mon Sep 17 00:00:00 2001 From: amin1377 Date: Wed, 30 Oct 2024 11:36:58 -0400 Subject: [PATCH 10/18] [vpr][place][net_cost] recomment on how to calculate acc_tile_num_inter_die_conn_ --- vpr/src/place/net_cost_handler.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/vpr/src/place/net_cost_handler.cpp b/vpr/src/place/net_cost_handler.cpp index 64e3c97c8da..2b112635962 100644 --- a/vpr/src/place/net_cost_handler.cpp +++ b/vpr/src/place/net_cost_handler.cpp @@ -246,6 +246,16 @@ void NetCostHandler::alloc_and_load_for_fast_vertical_cost_update_() { vtr::NdMatrix tile_num_inter_die_conn({grid_width, grid_height}, 0.); + /* + * To calculate the accumulative number of inter-die connections we first need to get the number of + * inter-die connection per loaction. To be able to work for the cases that RR Graph is read instead + * of being made from the architecture file, we calculate this number by iterating over RR graph. Once + * tile_num_inter_die_conn is populated, we can start populating acc_tile_num_inter_die_conn_. First, + * we populate the first row and column. Then, we iterate over the rest of blocks and get the number of + * inter-die connections by adding up the number of inter-die block at that location + the accumulative + * for the block below and left to it. Then, since the accumulative number of inter-die connection to + * the block on the lower left connection of the block is added twice, that part needs to be removed. + */ for (const auto& src_rr_node : rr_graph.nodes()) { for (const auto& rr_edge_idx : rr_graph.configurable_edges(src_rr_node)) { const auto& sink_rr_node = rr_graph.edge_sink_node(src_rr_node, rr_edge_idx); @@ -287,9 +297,9 @@ void NetCostHandler::alloc_and_load_for_fast_vertical_cost_update_() { for (size_t x_high = 1; x_high < device_ctx.grid.width(); x_high++) { for (size_t y_high = 1; y_high < device_ctx.grid.height(); y_high++) { acc_tile_num_inter_die_conn_[x_high][y_high] = acc_tile_num_inter_die_conn_[x_high-1][y_high] + \ - acc_tile_num_inter_die_conn_[x_high][y_high-1] - \ - acc_tile_num_inter_die_conn_[x_high-1][y_high-1] + \ - tile_num_inter_die_conn[x_high][y_high]; + acc_tile_num_inter_die_conn_[x_high][y_high-1] + \ + tile_num_inter_die_conn[x_high][y_high] - \ + acc_tile_num_inter_die_conn_[x_high-1][y_high-1]; } } } From df4159b4a4d9cfb0ce023711771a2ca9c6557799 Mon Sep 17 00:00:00 2001 From: amin1377 Date: Tue, 5 Nov 2024 17:29:25 -0500 Subject: [PATCH 11/18] [vpr][place] fix typos + unify edge loops --- vpr/src/place/net_cost_handler.cpp | 73 +++++++++++++++--------------- 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/vpr/src/place/net_cost_handler.cpp b/vpr/src/place/net_cost_handler.cpp index 2b112635962..e6c50891bf4 100644 --- a/vpr/src/place/net_cost_handler.cpp +++ b/vpr/src/place/net_cost_handler.cpp @@ -244,61 +244,62 @@ void NetCostHandler::alloc_and_load_for_fast_vertical_cost_update_() { acc_tile_num_inter_die_conn_ = vtr::NdMatrix({grid_width, grid_height}, 0.); - vtr::NdMatrix tile_num_inter_die_conn({grid_width, grid_height}, 0.); + vtr::NdMatrix tile_num_inter_die_conn({grid_width, grid_height}, 0.); + + /* + * Step 1: iterate over the rr-graph, recording how many edges go between layers at each (x,y) location + * in the device. We count all these edges, regardless of which layers they connect. Then we divide by + * the number of layers - 1 to get the average cross-layer edge count per (x,y) location -- this mirrors + * what we do for the horizontal and vertical channels where we assume the channel width doesn't change + * along the length of the channel. It lets us be more memory-efficient for 3D devices, and could be revisited + * if someday we have architectures with widely varying connectivity between different layers in a stack. + */ /* * To calculate the accumulative number of inter-die connections we first need to get the number of - * inter-die connection per loaction. To be able to work for the cases that RR Graph is read instead - * of being made from the architecture file, we calculate this number by iterating over RR graph. Once + * inter-die connection per location. To be able to work for the cases that RR Graph is read instead + * of being made from the architecture file, we calculate this number by iterating over the RR graph. Once * tile_num_inter_die_conn is populated, we can start populating acc_tile_num_inter_die_conn_. First, * we populate the first row and column. Then, we iterate over the rest of blocks and get the number of - * inter-die connections by adding up the number of inter-die block at that location + the accumulative - * for the block below and left to it. Then, since the accumulative number of inter-die connection to + * inter-die connections by adding up the number of inter-die block at that location + the accumulation + * for the block below and left to it. Then, since the accumulated number of inter-die connection to * the block on the lower left connection of the block is added twice, that part needs to be removed. */ for (const auto& src_rr_node : rr_graph.nodes()) { - for (const auto& rr_edge_idx : rr_graph.configurable_edges(src_rr_node)) { - const auto& sink_rr_node = rr_graph.edge_sink_node(src_rr_node, rr_edge_idx); - if (rr_graph.node_layer(src_rr_node) != rr_graph.node_layer(sink_rr_node)) { - // We assume that the nodes driving the inter-layer connection or being driven by it - // are not streched across multiple tiles - int src_x = rr_graph.node_xhigh(src_rr_node); - int src_y = rr_graph.node_yhigh(src_rr_node); - VTR_ASSERT(rr_graph.node_xlow(src_rr_node) == src_x && rr_graph.node_ylow(src_rr_node) == src_y); - - tile_num_inter_die_conn[src_x][src_y]++; - } - } - - for (const auto& rr_edge_idx : rr_graph.non_configurable_edges(src_rr_node)) { - const auto& sink_rr_node = rr_graph.edge_sink_node(src_rr_node, rr_edge_idx); - if (rr_graph.node_layer(src_rr_node) != rr_graph.node_layer(sink_rr_node)) { - int src_x = rr_graph.node_xhigh(src_rr_node); - VTR_ASSERT(rr_graph.node_xlow(src_rr_node) == src_x && rr_graph.node_xlow(src_rr_node) == src_x); - int src_y = rr_graph.node_yhigh(src_rr_node); - VTR_ASSERT(rr_graph.node_ylow(src_rr_node) == src_y && rr_graph.node_ylow(src_rr_node) == src_y); - tile_num_inter_die_conn[src_x][src_y]++; + for (auto edge_range: {rr_graph.configurable_edges(src_rr_node), rr_graph.non_configurable_edges(src_rr_node)}) { + for (const auto& rr_edge_idx : edge_range) { + const auto& sink_rr_node = rr_graph.edge_sink_node(src_rr_node, rr_edge_idx); + if (rr_graph.node_layer(src_rr_node) != rr_graph.node_layer(sink_rr_node)) { + // We assume that the nodes driving the inter-layer connection or being driven by it + // are not stretched across multiple tiles + int src_x = rr_graph.node_xhigh(src_rr_node); + int src_y = rr_graph.node_yhigh(src_rr_node); + VTR_ASSERT(rr_graph.node_xlow(src_rr_node) == src_x && rr_graph.node_ylow(src_rr_node) == src_y); + + tile_num_inter_die_conn[src_x][src_y]++; + } } } } + // Step 2: Calculate prefix sum of the inter-die connectivity up to and including the channel at (x, y). acc_tile_num_inter_die_conn_[0][0] = tile_num_inter_die_conn[0][0]; // Initialize the first row and column for (size_t x = 1; x < device_ctx.grid.width(); x++) { - acc_tile_num_inter_die_conn_[x][0] = acc_tile_num_inter_die_conn_[x-1][0] + \ + acc_tile_num_inter_die_conn_[x][0] = acc_tile_num_inter_die_conn_[x-1][0] + tile_num_inter_die_conn[x][0]; } for (size_t y = 1; y < device_ctx.grid.height(); y++) { - acc_tile_num_inter_die_conn_[0][y] = acc_tile_num_inter_die_conn_[0][y-1] + \ + acc_tile_num_inter_die_conn_[0][y] = acc_tile_num_inter_die_conn_[0][y-1] + tile_num_inter_die_conn[0][y]; } for (size_t x_high = 1; x_high < device_ctx.grid.width(); x_high++) { for (size_t y_high = 1; y_high < device_ctx.grid.height(); y_high++) { - acc_tile_num_inter_die_conn_[x_high][y_high] = acc_tile_num_inter_die_conn_[x_high-1][y_high] + \ - acc_tile_num_inter_die_conn_[x_high][y_high-1] + \ - tile_num_inter_die_conn[x_high][y_high] - \ + acc_tile_num_inter_die_conn_[x_high][y_high] = acc_tile_num_inter_die_conn_[x_high-1][y_high] + + acc_tile_num_inter_die_conn_[x_high][y_high-1] + + tile_num_inter_die_conn[x_high][y_high] - acc_tile_num_inter_die_conn_[x_high-1][y_high-1]; } } @@ -1604,15 +1605,15 @@ float NetCostHandler::get_chanz_cost_factor(const t_bb& bounding_box) { if (x_low == 0 && y_low == 0) { num_inter_dir_conn = acc_tile_num_inter_die_conn_[x_high][y_high]; } else if (x_low == 0) { - num_inter_dir_conn = acc_tile_num_inter_die_conn_[x_high][y_high] - \ + num_inter_dir_conn = acc_tile_num_inter_die_conn_[x_high][y_high] - acc_tile_num_inter_die_conn_[x_high][y_low-1]; } else if (y_low == 0) { - num_inter_dir_conn = acc_tile_num_inter_die_conn_[x_high][y_high] - \ + num_inter_dir_conn = acc_tile_num_inter_die_conn_[x_high][y_high] - acc_tile_num_inter_die_conn_[x_low-1][y_high]; } else { - num_inter_dir_conn = acc_tile_num_inter_die_conn_[x_high][y_high] - \ - acc_tile_num_inter_die_conn_[x_low-1][y_high] - \ - acc_tile_num_inter_die_conn_[x_high][y_low-1] + \ + num_inter_dir_conn = acc_tile_num_inter_die_conn_[x_high][y_high] - + acc_tile_num_inter_die_conn_[x_low-1][y_high] - + acc_tile_num_inter_die_conn_[x_high][y_low-1] + acc_tile_num_inter_die_conn_[x_low-1][y_low-1]; } From 21c62d85ad05cbbabf2c9645d68591b2f11090be Mon Sep 17 00:00:00 2001 From: amin1377 Date: Tue, 5 Nov 2024 17:37:01 -0500 Subject: [PATCH 12/18] [vpr][place]make get_chanz_cost_factor a private function --- vpr/src/place/net_cost_handler.cpp | 7 +++---- vpr/src/place/net_cost_handler.h | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/vpr/src/place/net_cost_handler.cpp b/vpr/src/place/net_cost_handler.cpp index e6c50891bf4..04f7482b88c 100644 --- a/vpr/src/place/net_cost_handler.cpp +++ b/vpr/src/place/net_cost_handler.cpp @@ -1490,7 +1490,7 @@ double NetCostHandler::get_net_cube_bb_cost_(ClusterNetId net_id, bool use_ts) { ncost = (bb.xmax - bb.xmin + 1) * crossing * chanx_place_cost_fac_[bb.ymax][bb.ymin - 1]; ncost += (bb.ymax - bb.ymin + 1) * crossing * chany_place_cost_fac_[bb.xmax][bb.xmin - 1]; if (is_multi_layer) { - ncost += (bb.layer_max - bb.layer_min) * crossing * get_chanz_cost_factor(bb); + ncost += (bb.layer_max - bb.layer_min) * crossing * get_chanz_cost_factor_(bb); } return ncost; @@ -1593,7 +1593,7 @@ double NetCostHandler::get_net_wirelength_from_layer_bb_(ClusterNetId net_id) { return ncost; } -float NetCostHandler::get_chanz_cost_factor(const t_bb& bounding_box) { +float NetCostHandler::get_chanz_cost_factor_(const t_bb& bounding_box) { float place_cost_exp = placer_opts_.place_cost_exp; int x_high = bounding_box.xmax; int x_low = bounding_box.xmin; @@ -1617,12 +1617,11 @@ float NetCostHandler::get_chanz_cost_factor(const t_bb& bounding_box) { acc_tile_num_inter_die_conn_[x_low-1][y_low-1]; } - int bb_num_tiles = (x_high - x_low + 1) * (y_high - y_low + 1); - float z_cost_factor; if (num_inter_dir_conn == 0) { return 1.0f; } else { + int bb_num_tiles = (x_high - x_low + 1) * (y_high - y_low + 1); z_cost_factor = bb_num_tiles / static_cast(num_inter_dir_conn); z_cost_factor = pow((double)z_cost_factor, (double)place_cost_exp); } diff --git a/vpr/src/place/net_cost_handler.h b/vpr/src/place/net_cost_handler.h index 8f473af9930..732d22bad99 100644 --- a/vpr/src/place/net_cost_handler.h +++ b/vpr/src/place/net_cost_handler.h @@ -513,6 +513,6 @@ class NetCostHandler { * @param bounding_box Bounding box of the net which chanz cost factor is to be calculated * @return ChanZ cost factor */ - float get_chanz_cost_factor(const t_bb& bounding_box); + float get_chanz_cost_factor_(const t_bb& bounding_box); }; From da925788482cfd2b9c3ba218563b123a7e032adf Mon Sep 17 00:00:00 2001 From: amin1377 Date: Tue, 5 Nov 2024 17:58:54 -0500 Subject: [PATCH 13/18] [vpr][place] add is_multi_layer_ to net cost handler fields --- vpr/src/place/net_cost_handler.cpp | 10 +++++----- vpr/src/place/net_cost_handler.h | 2 ++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/vpr/src/place/net_cost_handler.cpp b/vpr/src/place/net_cost_handler.cpp index 04f7482b88c..c9f1f3e187d 100644 --- a/vpr/src/place/net_cost_handler.cpp +++ b/vpr/src/place/net_cost_handler.cpp @@ -116,6 +116,8 @@ NetCostHandler::NetCostHandler(const t_placer_opts& placer_opts, , placer_opts_(placer_opts) { const int num_layers = g_vpr_ctx.device().grid.get_num_layers(); + is_multi_layer_ = num_layers > 1; + // Either 3D BB or per layer BB data structure are used, not both. if (cube_bb_) { ts_bb_edge_new_.resize(num_nets, t_bb()); @@ -229,7 +231,7 @@ void NetCostHandler::alloc_and_load_chan_w_factors_for_place_cost_() { } } - if (device_ctx.grid.get_num_layers() > 1) { + if (is_multi_layer_) { alloc_and_load_for_fast_vertical_cost_update_(); } } @@ -853,7 +855,7 @@ void NetCostHandler::update_bb_(ClusterNetId net_id, } /* Now account for the layer motion. */ - if (num_layers > 1) { + if (is_multi_layer_) { /* We need to update it only if multiple layers are available */ for (int layer_num = 0; layer_num < num_layers; layer_num++) { num_sink_pin_layer_new[layer_num] = curr_num_sink_pin_layer[layer_num]; @@ -1469,8 +1471,6 @@ double NetCostHandler::get_net_cube_bb_cost_(ClusterNetId net_id, bool use_ts) { const t_bb& bb = use_ts ? ts_bb_coord_new_[net_id] : placer_state_.move().bb_coords[net_id]; - const bool is_multi_layer = (g_vpr_ctx.device().grid.get_num_layers() > 1); - double crossing = wirelength_crossing_count(cluster_ctx.clb_nlist.net_pins(net_id).size()); /* Could insert a check for xmin == xmax. In that case, assume * @@ -1489,7 +1489,7 @@ double NetCostHandler::get_net_cube_bb_cost_(ClusterNetId net_id, bool use_ts) { double ncost; ncost = (bb.xmax - bb.xmin + 1) * crossing * chanx_place_cost_fac_[bb.ymax][bb.ymin - 1]; ncost += (bb.ymax - bb.ymin + 1) * crossing * chany_place_cost_fac_[bb.xmax][bb.xmin - 1]; - if (is_multi_layer) { + if (is_multi_layer_) { ncost += (bb.layer_max - bb.layer_min) * crossing * get_chanz_cost_factor_(bb); } diff --git a/vpr/src/place/net_cost_handler.h b/vpr/src/place/net_cost_handler.h index 732d22bad99..e27aaff6ae4 100644 --- a/vpr/src/place/net_cost_handler.h +++ b/vpr/src/place/net_cost_handler.h @@ -123,6 +123,8 @@ class NetCostHandler { private: ///@brief Specifies whether the bounding box is computed using cube method or per-layer method. bool cube_bb_ = false; + ///@brief Determines whether the FPGA has multiple dies (layers) + bool is_multi_layer_ = false; ///@brief A reference to the placer's state to be updated by this object. PlacerState& placer_state_; ///@brief Contains some parameter that determine how the placement cost is computed. From 052d6b9c39b331dd86e31aa2c7b0a5d26366b3c2 Mon Sep 17 00:00:00 2001 From: amin1377 Date: Tue, 5 Nov 2024 18:00:47 -0500 Subject: [PATCH 14/18] [vpr][place] factor out crossing multiplication --- vpr/src/place/net_cost_handler.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/vpr/src/place/net_cost_handler.cpp b/vpr/src/place/net_cost_handler.cpp index c9f1f3e187d..3b8a2d9c1f7 100644 --- a/vpr/src/place/net_cost_handler.cpp +++ b/vpr/src/place/net_cost_handler.cpp @@ -1487,12 +1487,14 @@ double NetCostHandler::get_net_cube_bb_cost_(ClusterNetId net_id, bool use_ts) { */ double ncost; - ncost = (bb.xmax - bb.xmin + 1) * crossing * chanx_place_cost_fac_[bb.ymax][bb.ymin - 1]; - ncost += (bb.ymax - bb.ymin + 1) * crossing * chany_place_cost_fac_[bb.xmax][bb.xmin - 1]; + ncost = (bb.xmax - bb.xmin + 1) * chanx_place_cost_fac_[bb.ymax][bb.ymin - 1]; + ncost += (bb.ymax - bb.ymin + 1) * chany_place_cost_fac_[bb.xmax][bb.xmin - 1]; if (is_multi_layer_) { - ncost += (bb.layer_max - bb.layer_min) * crossing * get_chanz_cost_factor_(bb); + ncost += (bb.layer_max - bb.layer_min) * get_chanz_cost_factor_(bb); } + ncost *= crossing; + return ncost; } From e15a79614ace84c45a8054e4140bf46bccda7c7c Mon Sep 17 00:00:00 2001 From: amin1377 Date: Tue, 5 Nov 2024 18:17:34 -0500 Subject: [PATCH 15/18] [vpr][place][net_cost] use bb --- vpr/src/place/net_cost_handler.cpp | 32 +++++++++++++----------------- vpr/src/place/net_cost_handler.h | 8 +++++--- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/vpr/src/place/net_cost_handler.cpp b/vpr/src/place/net_cost_handler.cpp index 3b8a2d9c1f7..5805c8bef02 100644 --- a/vpr/src/place/net_cost_handler.cpp +++ b/vpr/src/place/net_cost_handler.cpp @@ -1595,35 +1595,31 @@ double NetCostHandler::get_net_wirelength_from_layer_bb_(ClusterNetId net_id) { return ncost; } -float NetCostHandler::get_chanz_cost_factor_(const t_bb& bounding_box) { +float NetCostHandler::get_chanz_cost_factor_(const t_bb& bb) { float place_cost_exp = placer_opts_.place_cost_exp; - int x_high = bounding_box.xmax; - int x_low = bounding_box.xmin; - int y_high = bounding_box.ymax; - int y_low = bounding_box.ymin; int num_inter_dir_conn; - if (x_low == 0 && y_low == 0) { - num_inter_dir_conn = acc_tile_num_inter_die_conn_[x_high][y_high]; - } else if (x_low == 0) { - num_inter_dir_conn = acc_tile_num_inter_die_conn_[x_high][y_high] - - acc_tile_num_inter_die_conn_[x_high][y_low-1]; - } else if (y_low == 0) { - num_inter_dir_conn = acc_tile_num_inter_die_conn_[x_high][y_high] - - acc_tile_num_inter_die_conn_[x_low-1][y_high]; + if (bb.xmin == 0 && bb.ymin == 0) { + num_inter_dir_conn = acc_tile_num_inter_die_conn_[bb.xmax][bb.ymax]; + } else if (bb.xmin == 0) { + num_inter_dir_conn = acc_tile_num_inter_die_conn_[bb.xmax][bb.ymax] - + acc_tile_num_inter_die_conn_[bb.xmax][bb.ymin-1]; + } else if (bb.ymin == 0) { + num_inter_dir_conn = acc_tile_num_inter_die_conn_[bb.xmax][bb.ymax] - + acc_tile_num_inter_die_conn_[bb.xmin-1][bb.ymax]; } else { - num_inter_dir_conn = acc_tile_num_inter_die_conn_[x_high][y_high] - - acc_tile_num_inter_die_conn_[x_low-1][y_high] - - acc_tile_num_inter_die_conn_[x_high][y_low-1] + - acc_tile_num_inter_die_conn_[x_low-1][y_low-1]; + num_inter_dir_conn = acc_tile_num_inter_die_conn_[bb.xmax][bb.ymax] - + acc_tile_num_inter_die_conn_[bb.xmin-1][bb.ymax] - + acc_tile_num_inter_die_conn_[bb.xmax][bb.ymin-1] + + acc_tile_num_inter_die_conn_[bb.xmin-1][bb.ymin-1]; } float z_cost_factor; if (num_inter_dir_conn == 0) { return 1.0f; } else { - int bb_num_tiles = (x_high - x_low + 1) * (y_high - y_low + 1); + int bb_num_tiles = (bb.xmax - bb.xmin + 1) * (bb.ymax - bb.ymin + 1); z_cost_factor = bb_num_tiles / static_cast(num_inter_dir_conn); z_cost_factor = pow((double)z_cost_factor, (double)place_cost_exp); } diff --git a/vpr/src/place/net_cost_handler.h b/vpr/src/place/net_cost_handler.h index e27aaff6ae4..332e8a0a0d4 100644 --- a/vpr/src/place/net_cost_handler.h +++ b/vpr/src/place/net_cost_handler.h @@ -256,8 +256,8 @@ class NetCostHandler { void alloc_and_load_chan_w_factors_for_place_cost_(); /** - * @brief Allocates and loads the chanz_place_cost_fac array with the inverse of - * the average number of inter-die connections between [subhigh] and [sublow]. + * @brief Allocates and loads acc_tile_num_inter_die_conn_ which contains the accumulative number of inter-die + * conntections. * * @details This is only useful for multi-die FPGAs. The place_cost_exp factor specifies to * what power the average number of inter-die connections should be take -- larger numbers make narrower channels more expensive. @@ -511,7 +511,9 @@ class NetCostHandler { * @brief Calculate the chanz cost factor based on the inverse of the average number of inter-die connections * in the given bounding box. This cost factor increases the placement cost for blocks that require inter-layer * connections in areas with, on average, fewer inter-die connections. If inter-die connections are evenly - * distributed across tiles, the cost factor will be the same for all bounding boxes. + * distributed across tiles, the cost factor will be the same for all bounding boxes, but it will still + * weight z-directed vs. x- and y-directed connections appropriately. + * * @param bounding_box Bounding box of the net which chanz cost factor is to be calculated * @return ChanZ cost factor */ From f2939b1f01c3b66e975ae6dfec520fba37f9a43e Mon Sep 17 00:00:00 2001 From: amin1377 Date: Tue, 5 Nov 2024 18:39:36 -0500 Subject: [PATCH 16/18] [vpr][place][net_cost] fix typos --- vpr/src/place/net_cost_handler.cpp | 35 +++++++++++++++++------------- vpr/src/place/net_cost_handler.h | 12 +++++----- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/vpr/src/place/net_cost_handler.cpp b/vpr/src/place/net_cost_handler.cpp index 5805c8bef02..ca3033615d8 100644 --- a/vpr/src/place/net_cost_handler.cpp +++ b/vpr/src/place/net_cost_handler.cpp @@ -155,7 +155,7 @@ NetCostHandler::NetCostHandler(const t_placer_opts& placer_opts, } void NetCostHandler::alloc_and_load_chan_w_factors_for_place_cost_() { - float place_cost_exp = placer_opts_.place_cost_exp; + const double place_cost_exp = static_cast(placer_opts_.place_cost_exp); auto& device_ctx = g_vpr_ctx.device(); const int grid_height = device_ctx.grid.height(); @@ -197,7 +197,7 @@ void NetCostHandler::alloc_and_load_chan_w_factors_for_place_cost_() { } chanx_place_cost_fac_[high][low] = (high - low + 1.) / chanx_place_cost_fac_[high][low]; - chanx_place_cost_fac_[high][low] = pow((double)chanx_place_cost_fac_[high][low], (double)place_cost_exp); + chanx_place_cost_fac_[high][low] = pow((double)chanx_place_cost_fac_[high][low], place_cost_exp); } } @@ -227,7 +227,7 @@ void NetCostHandler::alloc_and_load_chan_w_factors_for_place_cost_() { } chany_place_cost_fac_[high][low] = (high - low + 1.) / chany_place_cost_fac_[high][low]; - chany_place_cost_fac_[high][low] = pow((double)chany_place_cost_fac_[high][low], (double)place_cost_exp); + chany_place_cost_fac_[high][low] = pow((double)chany_place_cost_fac_[high][low], place_cost_exp); } } @@ -268,22 +268,27 @@ void NetCostHandler::alloc_and_load_for_fast_vertical_cost_update_() { * the block on the lower left connection of the block is added twice, that part needs to be removed. */ for (const auto& src_rr_node : rr_graph.nodes()) { - for (auto edge_range: {rr_graph.configurable_edges(src_rr_node), rr_graph.non_configurable_edges(src_rr_node)}) { - for (const auto& rr_edge_idx : edge_range) { - const auto& sink_rr_node = rr_graph.edge_sink_node(src_rr_node, rr_edge_idx); - if (rr_graph.node_layer(src_rr_node) != rr_graph.node_layer(sink_rr_node)) { - // We assume that the nodes driving the inter-layer connection or being driven by it - // are not stretched across multiple tiles - int src_x = rr_graph.node_xhigh(src_rr_node); - int src_y = rr_graph.node_yhigh(src_rr_node); - VTR_ASSERT(rr_graph.node_xlow(src_rr_node) == src_x && rr_graph.node_ylow(src_rr_node) == src_y); - - tile_num_inter_die_conn[src_x][src_y]++; - } + for (const auto& rr_edge_idx : rr_graph.edges(src_rr_node)) { + const auto& sink_rr_node = rr_graph.edge_sink_node(src_rr_node, rr_edge_idx); + if (rr_graph.node_layer(src_rr_node) != rr_graph.node_layer(sink_rr_node)) { + // We assume that the nodes driving the inter-layer connection or being driven by it + // are not stretched across multiple tiles + int src_x = rr_graph.node_xhigh(src_rr_node); + int src_y = rr_graph.node_yhigh(src_rr_node); + VTR_ASSERT(rr_graph.node_xlow(src_rr_node) == src_x && rr_graph.node_ylow(src_rr_node) == src_y); + + tile_num_inter_die_conn[src_x][src_y]++; } } } + int num_layers = device_ctx.grid.get_num_layers(); + for (size_t x = 0; x < device_ctx.grid.width(); x++) { + for (size_t y = 0; y < device_ctx.grid.height(); y++) { + tile_num_inter_die_conn[x][y] /= (num_layers-1); + } + } + // Step 2: Calculate prefix sum of the inter-die connectivity up to and including the channel at (x, y). acc_tile_num_inter_die_conn_[0][0] = tile_num_inter_die_conn[0][0]; // Initialize the first row and column diff --git a/vpr/src/place/net_cost_handler.h b/vpr/src/place/net_cost_handler.h index 332e8a0a0d4..fd6c7a46767 100644 --- a/vpr/src/place/net_cost_handler.h +++ b/vpr/src/place/net_cost_handler.h @@ -198,12 +198,14 @@ class NetCostHandler { vtr::NdOffsetMatrix chanx_place_cost_fac_; // [-1...device_ctx.grid.width()-1] vtr::NdOffsetMatrix chany_place_cost_fac_; // [-1...device_ctx.grid.height()-1] /** - @brief This data structure stores the cumulative number of inter-die connections from the lower-left corner. - * It is later used to calculate the chanZ factor, which functions similarly to chanx_place_cost_fac_ and chany_place_cost_fac_, - * but applies to the height of the bounding box. The chanZ factor is calculated during block placement because storing it in the - * same way as the X and Y cost factors would require a 4D array and population it is an O(n^2) operation. + * @brief The matrix below is used to calculate a chanz_place_cost_fac based on the average channel width in + * the cross-die-layer direction over a 2D (x,y) region. We don't assume the inter-die connectivity is the same at all (x,y) locations, so we + * can't compute the full chanz_place_cost_fac for all possible (xlow,ylow)(xhigh,yhigh) without a 4D array, which would + * be too big: O(n^2) in circuit size. Instead we compute a prefix sum that stores the number of inter-die connections per layer from + * (x=0,y=0) to (x,y). Given this, we can compute the average number of inter-die connections over a (xlow,ylow) to (xhigh,yhigh) + * region in O(1) (by adding and subtracting 4 entries) */ - vtr::NdMatrix acc_tile_num_inter_die_conn_; + vtr::NdMatrix acc_tile_num_inter_die_conn_; // [0..grid_width-1][0..grid_height-1] private: From a0b2c06b84af703912486cb9ba9e991f59751ca5 Mon Sep 17 00:00:00 2001 From: amin1377 Date: Wed, 6 Nov 2024 16:03:23 -0500 Subject: [PATCH 17/18] [ci] update golden --- .../strong_manual_annealing/config/golden_results.txt | 2 +- .../vtr_reg_strong/strong_sdc/config/golden_results.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_manual_annealing/config/golden_results.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_manual_annealing/config/golden_results.txt index 905d2f3ba19..291897f65f4 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_manual_annealing/config/golden_results.txt +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_manual_annealing/config/golden_results.txt @@ -1,2 +1,2 @@ arch circuit script_params vtr_flow_elapsed_time vtr_max_mem_stage vtr_max_mem error odin_synth_time max_odin_mem parmys_synth_time max_parmys_mem abc_depth abc_synth_time abc_cec_time abc_sec_time max_abc_mem ace_time max_ace_mem num_clb num_io num_memories num_mult vpr_status vpr_revision vpr_build_info vpr_compiler vpr_compiled hostname rundir max_vpr_mem num_primary_inputs num_primary_outputs num_pre_packed_nets num_pre_packed_blocks num_netlist_clocks num_post_packed_nets num_post_packed_blocks device_width device_height device_grid_tiles device_limiting_resources device_name pack_mem pack_time placed_wirelength_est place_mem place_time place_quench_time placed_CPD_est placed_setup_TNS_est placed_setup_WNS_est placed_geomean_nonvirtual_intradomain_critical_path_delay_est place_delay_matrix_lookup_time place_quench_timing_analysis_time place_quench_sta_time place_total_timing_analysis_time place_total_sta_time min_chan_width routed_wirelength min_chan_width_route_success_iteration logic_block_area_total logic_block_area_used min_chan_width_routing_area_total min_chan_width_routing_area_per_tile min_chan_width_route_time min_chan_width_total_timing_analysis_time min_chan_width_total_sta_time crit_path_routed_wirelength crit_path_route_success_iteration crit_path_total_nets_routed crit_path_total_connections_routed crit_path_total_heap_pushes crit_path_total_heap_pops critical_path_delay geomean_nonvirtual_intradomain_critical_path_delay setup_TNS setup_WNS hold_TNS hold_WNS crit_path_routing_area_total crit_path_routing_area_per_tile router_lookahead_computation_time crit_path_route_time crit_path_total_timing_analysis_time crit_path_total_sta_time - k6_frac_N10_40nm.xml stereovision3.v common 1.44 vpr 57.96 MiB -1 -1 0.42 25620 5 0.11 -1 -1 36164 -1 -1 7 10 -1 -1 success v8.0.0-6989-g4a9293e1e-dirty release IPO VTR_ASSERT_LEVEL=3 GNU 11.3.0 on Linux-5.15.0-58-generic x86_64 2023-02-04T01:37:29 dev /home/dev/Desktop/CAS-Atlantic/vtr-verilog-to-routing 59352 10 2 181 183 1 37 19 5 5 25 clb auto 19.7 MiB 0.05 108 58.0 MiB 0.01 0.00 1.93928 -79.1821 -1.93928 1.93928 0.02 0.000104618 8.1277e-05 0.00610425 0.00496002 24 129 10 485046 377258 28445.8 1137.83 0.13 0.0425172 0.0362734 109 8 74 103 1476 611 2.06938 2.06938 -89.2305 -2.06938 0 0 37126.9 1485.07 0.02 0.01 0.00966903 0.00924379 + k6_frac_N10_40nm.xml stereovision3.v common 1.44 vpr 57.96 MiB -1 -1 0.42 25620 5 0.11 -1 -1 36164 -1 -1 7 10 -1 -1 success v8.0.0-6989-g4a9293e1e-dirty release IPO VTR_ASSERT_LEVEL=3 GNU 11.3.0 on Linux-5.15.0-58-generic x86_64 2023-02-04T01:37:29 dev /home/dev/Desktop/CAS-Atlantic/vtr-verilog-to-routing 59352 10 2 181 183 1 37 19 5 5 25 clb auto 19.7 MiB 0.05 108 58.0 MiB 0.01 0.00 1.93928 -79.1821 -1.93928 1.93928 0.02 0.000104618 8.1277e-05 0.00610425 0.00496002 26 129 10 485046 377258 34134.96 1365.396 0.13 0.0425172 0.0362734 109 8 74 103 1476 611 2.06938 2.06938 -89.2305 -2.06938 0 0 37126.9 1485.07 0.02 0.01 0.00966903 0.00924379 diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_sdc/config/golden_results.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_sdc/config/golden_results.txt index 3ff8dccb714..139b1a529a1 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_sdc/config/golden_results.txt +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_sdc/config/golden_results.txt @@ -3,5 +3,5 @@ k6_N10_mem32K_40nm.xml multiclock.blif common_-sdc_file_sdc/samples/B.sdc 0.15 vpr 64.62 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 5 0 0 success e1c7cb1 Release IPO VTR_ASSERT_LEVEL=3 GNU 11.4.0 on Linux-6.8.0-1014-azure x86_64 2024-09-24T03:47:29 fv-az775-518 /home/runner/work/vtr-verilog-to-routing/vtr-verilog-to-routing 66172 5 3 11 14 2 9 10 4 4 16 clb auto 26.2 MiB 0.00 23 30 5 16 9 64.6 MiB 0.00 0.00 0.571 0 0 0.571 0.01 3.1699e-05 2.5357e-05 0.000167513 0.000139209 8 29 4 107788 107788 4794.78 299.674 0.01 0.00129724 0.00119452 564 862 -1 25 4 15 15 546 342 0.571 0.571 0 0 0 0 5401.54 337.596 0.00 0.00 0.00 -1 -1 0.00 0.00123336 0.00115491 k6_N10_mem32K_40nm.xml multiclock.blif common_-sdc_file_sdc/samples/C.sdc 0.15 vpr 64.75 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 5 0 0 success e1c7cb1 Release IPO VTR_ASSERT_LEVEL=3 GNU 11.4.0 on Linux-6.8.0-1014-azure x86_64 2024-09-24T03:47:29 fv-az775-518 /home/runner/work/vtr-verilog-to-routing/vtr-verilog-to-routing 66304 5 3 11 14 2 9 10 4 4 16 clb auto 26.5 MiB 0.00 20 30 10 18 2 64.8 MiB 0.00 0.00 0.645499 -2.18826 -0.645499 0.571 0.01 5.5523e-05 4.2379e-05 0.000203498 0.000159839 8 17 3 107788 107788 4794.78 299.674 0.01 0.0014548 0.0013129 564 862 -1 14 4 15 15 278 103 0.571526 0.571 -1.89284 -0.571526 0 0 5401.54 337.596 0.00 0.00 0.00 -1 -1 0.00 0.00123664 0.00115953 k6_N10_mem32K_40nm.xml multiclock.blif common_-sdc_file_sdc/samples/D.sdc 0.15 vpr 64.75 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 5 0 0 success e1c7cb1 Release IPO VTR_ASSERT_LEVEL=3 GNU 11.4.0 on Linux-6.8.0-1014-azure x86_64 2024-09-24T03:47:29 fv-az775-518 /home/runner/work/vtr-verilog-to-routing/vtr-verilog-to-routing 66308 5 3 11 14 2 9 10 4 4 16 clb auto 26.3 MiB 0.00 20 30 11 18 1 64.8 MiB 0.00 0.00 1.64534 -5.31677 -1.64534 0.571 0.01 2.4636e-05 1.5899e-05 0.000174577 0.000131877 8 17 8 107788 107788 4794.78 299.674 0.01 0.00153355 0.00133955 564 862 -1 15 8 21 21 322 143 1.57153 0.571 -4.91875 -1.57153 0 0 5401.54 337.596 0.00 0.00 0.00 -1 -1 0.00 0.00136833 0.00125557 - k6_N10_mem32K_40nm.xml multiclock.blif common_-sdc_file_sdc/samples/E.sdc 0.16 vpr 64.75 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 5 0 0 success e1c7cb1 Release IPO VTR_ASSERT_LEVEL=3 GNU 11.4.0 on Linux-6.8.0-1014-azure x86_64 2024-09-24T03:47:29 fv-az775-518 /home/runner/work/vtr-verilog-to-routing/vtr-verilog-to-routing 66300 5 3 11 14 2 9 10 4 4 16 clb auto 26.3 MiB 0.00 21 30 10 15 5 64.7 MiB 0.00 0.00 1.44871 -2.90839 -1.44871 0.571 0.01 2.8303e-05 1.9276e-05 0.000183072 0.000124494 8 21 8 107788 107788 4794.78 299.674 0.01 0.00162656 0.00142678 564 862 -1 25 3 11 11 428 274 1.39454 0.571 -2.72425 -1.39454 0 0 5401.54 337.596 0.00 0.00 0.00 -1 -1 0.00 0.0012549 0.00118367 + k6_N10_mem32K_40nm.xml multiclock.blif common_-sdc_file_sdc/samples/E.sdc 0.16 vpr 64.75 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 5 0 0 success e1c7cb1 Release IPO VTR_ASSERT_LEVEL=3 GNU 11.4.0 on Linux-6.8.0-1014-azure x86_64 2024-09-24T03:47:29 fv-az775-518 /home/runner/work/vtr-verilog-to-routing/vtr-verilog-to-routing 66300 5 3 11 14 2 9 10 4 4 16 clb auto 26.3 MiB 0.00 21 30 10 15 5 64.7 MiB 0.00 0.00 1.44871 -2.90839 -1.44871 0.571 0.01 2.8303e-05 1.9276e-05 0.000183072 0.000124494 8 26 8 107788 107788 4794.78 299.674 0.01 0.00162656 0.00142678 564 862 -1 25 3 11 11 428 274 1.39454 0.571 -2.72425 -1.39454 0 0 5401.54 337.596 0.00 0.00 0.00 -1 -1 0.00 0.0012549 0.00118367 k6_N10_mem32K_40nm.xml multiclock.blif common_-sdc_file_sdc/samples/F.sdc 0.15 vpr 64.68 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 5 0 0 success e1c7cb1 Release IPO VTR_ASSERT_LEVEL=3 GNU 11.4.0 on Linux-6.8.0-1014-azure x86_64 2024-09-24T03:47:29 fv-az775-518 /home/runner/work/vtr-verilog-to-routing/vtr-verilog-to-routing 66232 5 3 11 14 2 9 10 4 4 16 clb auto 26.3 MiB 0.00 21 100 23 56 21 64.7 MiB 0.00 0.00 0.145339 0 0 0.571 0.01 3.9153e-05 3.219e-05 0.000324196 0.000258224 8 22 3 107788 107788 4794.78 299.674 0.01 0.00152952 0.00138796 564 862 -1 20 2 9 9 230 115 0.0724097 0.571 0 0 0 0 5401.54 337.596 0.00 0.00 0.00 -1 -1 0.00 0.00122034 0.00116368 From 6ea89219a62808122ab81db3d90d89e3df6c1c2c Mon Sep 17 00:00:00 2001 From: amin1377 Date: Wed, 6 Nov 2024 16:08:51 -0500 Subject: [PATCH 18/18] [ci] update odin golden --- .../vtr_reg_strong_odin/strong_sdc/config/golden_results.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong_odin/strong_sdc/config/golden_results.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong_odin/strong_sdc/config/golden_results.txt index 3ff8dccb714..139b1a529a1 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_strong_odin/strong_sdc/config/golden_results.txt +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong_odin/strong_sdc/config/golden_results.txt @@ -3,5 +3,5 @@ k6_N10_mem32K_40nm.xml multiclock.blif common_-sdc_file_sdc/samples/B.sdc 0.15 vpr 64.62 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 5 0 0 success e1c7cb1 Release IPO VTR_ASSERT_LEVEL=3 GNU 11.4.0 on Linux-6.8.0-1014-azure x86_64 2024-09-24T03:47:29 fv-az775-518 /home/runner/work/vtr-verilog-to-routing/vtr-verilog-to-routing 66172 5 3 11 14 2 9 10 4 4 16 clb auto 26.2 MiB 0.00 23 30 5 16 9 64.6 MiB 0.00 0.00 0.571 0 0 0.571 0.01 3.1699e-05 2.5357e-05 0.000167513 0.000139209 8 29 4 107788 107788 4794.78 299.674 0.01 0.00129724 0.00119452 564 862 -1 25 4 15 15 546 342 0.571 0.571 0 0 0 0 5401.54 337.596 0.00 0.00 0.00 -1 -1 0.00 0.00123336 0.00115491 k6_N10_mem32K_40nm.xml multiclock.blif common_-sdc_file_sdc/samples/C.sdc 0.15 vpr 64.75 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 5 0 0 success e1c7cb1 Release IPO VTR_ASSERT_LEVEL=3 GNU 11.4.0 on Linux-6.8.0-1014-azure x86_64 2024-09-24T03:47:29 fv-az775-518 /home/runner/work/vtr-verilog-to-routing/vtr-verilog-to-routing 66304 5 3 11 14 2 9 10 4 4 16 clb auto 26.5 MiB 0.00 20 30 10 18 2 64.8 MiB 0.00 0.00 0.645499 -2.18826 -0.645499 0.571 0.01 5.5523e-05 4.2379e-05 0.000203498 0.000159839 8 17 3 107788 107788 4794.78 299.674 0.01 0.0014548 0.0013129 564 862 -1 14 4 15 15 278 103 0.571526 0.571 -1.89284 -0.571526 0 0 5401.54 337.596 0.00 0.00 0.00 -1 -1 0.00 0.00123664 0.00115953 k6_N10_mem32K_40nm.xml multiclock.blif common_-sdc_file_sdc/samples/D.sdc 0.15 vpr 64.75 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 5 0 0 success e1c7cb1 Release IPO VTR_ASSERT_LEVEL=3 GNU 11.4.0 on Linux-6.8.0-1014-azure x86_64 2024-09-24T03:47:29 fv-az775-518 /home/runner/work/vtr-verilog-to-routing/vtr-verilog-to-routing 66308 5 3 11 14 2 9 10 4 4 16 clb auto 26.3 MiB 0.00 20 30 11 18 1 64.8 MiB 0.00 0.00 1.64534 -5.31677 -1.64534 0.571 0.01 2.4636e-05 1.5899e-05 0.000174577 0.000131877 8 17 8 107788 107788 4794.78 299.674 0.01 0.00153355 0.00133955 564 862 -1 15 8 21 21 322 143 1.57153 0.571 -4.91875 -1.57153 0 0 5401.54 337.596 0.00 0.00 0.00 -1 -1 0.00 0.00136833 0.00125557 - k6_N10_mem32K_40nm.xml multiclock.blif common_-sdc_file_sdc/samples/E.sdc 0.16 vpr 64.75 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 5 0 0 success e1c7cb1 Release IPO VTR_ASSERT_LEVEL=3 GNU 11.4.0 on Linux-6.8.0-1014-azure x86_64 2024-09-24T03:47:29 fv-az775-518 /home/runner/work/vtr-verilog-to-routing/vtr-verilog-to-routing 66300 5 3 11 14 2 9 10 4 4 16 clb auto 26.3 MiB 0.00 21 30 10 15 5 64.7 MiB 0.00 0.00 1.44871 -2.90839 -1.44871 0.571 0.01 2.8303e-05 1.9276e-05 0.000183072 0.000124494 8 21 8 107788 107788 4794.78 299.674 0.01 0.00162656 0.00142678 564 862 -1 25 3 11 11 428 274 1.39454 0.571 -2.72425 -1.39454 0 0 5401.54 337.596 0.00 0.00 0.00 -1 -1 0.00 0.0012549 0.00118367 + k6_N10_mem32K_40nm.xml multiclock.blif common_-sdc_file_sdc/samples/E.sdc 0.16 vpr 64.75 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 5 0 0 success e1c7cb1 Release IPO VTR_ASSERT_LEVEL=3 GNU 11.4.0 on Linux-6.8.0-1014-azure x86_64 2024-09-24T03:47:29 fv-az775-518 /home/runner/work/vtr-verilog-to-routing/vtr-verilog-to-routing 66300 5 3 11 14 2 9 10 4 4 16 clb auto 26.3 MiB 0.00 21 30 10 15 5 64.7 MiB 0.00 0.00 1.44871 -2.90839 -1.44871 0.571 0.01 2.8303e-05 1.9276e-05 0.000183072 0.000124494 8 26 8 107788 107788 4794.78 299.674 0.01 0.00162656 0.00142678 564 862 -1 25 3 11 11 428 274 1.39454 0.571 -2.72425 -1.39454 0 0 5401.54 337.596 0.00 0.00 0.00 -1 -1 0.00 0.0012549 0.00118367 k6_N10_mem32K_40nm.xml multiclock.blif common_-sdc_file_sdc/samples/F.sdc 0.15 vpr 64.68 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 5 0 0 success e1c7cb1 Release IPO VTR_ASSERT_LEVEL=3 GNU 11.4.0 on Linux-6.8.0-1014-azure x86_64 2024-09-24T03:47:29 fv-az775-518 /home/runner/work/vtr-verilog-to-routing/vtr-verilog-to-routing 66232 5 3 11 14 2 9 10 4 4 16 clb auto 26.3 MiB 0.00 21 100 23 56 21 64.7 MiB 0.00 0.00 0.145339 0 0 0.571 0.01 3.9153e-05 3.219e-05 0.000324196 0.000258224 8 22 3 107788 107788 4794.78 299.674 0.01 0.00152952 0.00138796 564 862 -1 20 2 9 9 230 115 0.0724097 0.571 0 0 0 0 5401.54 337.596 0.00 0.00 0.00 -1 -1 0.00 0.00122034 0.00116368