-
Notifications
You must be signed in to change notification settings - Fork 431
[AP][Solver][3D] 3D AP Solver Support #3265
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
Open
AlexandreSinger
wants to merge
13
commits into
verilog-to-routing:master
Choose a base branch
from
AlexandreSinger:feature-3d-ap-solver
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+596
−286
Open
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
297b856
[AP][Solver][3D] 3D AP Solver Support
AlexandreSinger 4c3423a
Merge branch 'master' into feature-3d-ap-solver
AlexandreSinger eff8a21
Merge remote-tracking branch 'origin/master' into feature-3d-ap-solver
AlexandreSinger 743a02c
[AP] Updated Solver Docs and Fixed Typo
AlexandreSinger a7511e7
Make format
AlexandreSinger 045c4e5
[Place] Separated Out the Channel Cost Factor Code
AlexandreSinger de9334e
[AP] Added Per-Dimension Channel Cost Based on Routing Demand
AlexandreSinger f2054f2
[AP][Solver] Normalized the Channel Factors
AlexandreSinger 69e29b6
[AP][Solver] Clamped the Chan Cost Factor BB
AlexandreSinger 4218628
Merge remote-tracking branch 'origin/master' into feature-3d-ap-solver
AlexandreSinger a06777b
Updated Golden Results
AlexandreSinger eb71815
Merge remote-tracking branch 'origin/master' into feature-3d-ap-solver
AlexandreSinger 17635d7
Resolved Assorted PR Comments
AlexandreSinger File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| /** | ||
| * @file | ||
| * @author Alex Singer | ||
| * @date December 2025 | ||
| * @brief The definition of the channel cost handler class. | ||
| */ | ||
|
|
||
| #include "chan_cost_handler.h" | ||
| #include <cmath> | ||
| #include "rr_graph_view.h" | ||
|
|
||
| ChanCostHandler::ChanCostHandler(const std::vector<int>& rr_chanx_width, | ||
| const std::vector<int>& rr_chany_width, | ||
| const RRGraphView& rr_graph, | ||
| const DeviceGrid& grid) { | ||
|
|
||
| // These arrays contain accumulative channel width between channel zero and | ||
| // the channel specified by the given index. The accumulated channel width | ||
| // is inclusive, meaning that it includes both channel zero and channel `idx`. | ||
| // To compute the total channel width between channels 'low' and 'high', use the | ||
| // following formula: | ||
| // acc_chan?_width_[high] - acc_chan?_width_[low - 1] | ||
| // This returns the total number of tracks between channels 'low' and 'high', | ||
| // including tracks in these channels. | ||
| acc_chanx_width_ = vtr::PrefixSum1D<int>(grid.height(), [&](size_t y) noexcept { | ||
| int chan_x_width = rr_chanx_width[y]; | ||
|
|
||
| // If the number of tracks in a channel is zero, two consecutive elements take the same | ||
| // value. This can lead to a division by zero in get_chanxy_cost_fac_(). To avoid this | ||
| // potential issue, we assume that the channel width is at least 1. | ||
| if (chan_x_width == 0) { | ||
| return 1; | ||
| } | ||
|
|
||
| return chan_x_width; | ||
| }); | ||
|
|
||
| acc_chany_width_ = vtr::PrefixSum1D<int>(grid.width(), [&](size_t x) noexcept { | ||
| int chan_y_width = rr_chany_width[x]; | ||
|
|
||
| // to avoid a division by zero | ||
| if (chan_y_width == 0) { | ||
| return 1; | ||
| } | ||
|
|
||
| return chan_y_width; | ||
| }); | ||
|
|
||
| // If this is a multi-layer (3D) architecture, compute Z-channel cost term. | ||
| if (grid.get_num_layers() > 1) { | ||
| vtr::NdMatrix<float, 2> 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 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_. | ||
| */ | ||
|
|
||
| for (const RRNodeId node : rr_graph.nodes()) { | ||
| if (rr_graph.node_type(node) == e_rr_type::CHANZ) { | ||
| int x = rr_graph.node_xlow(node); | ||
| int y = rr_graph.node_ylow(node); | ||
| VTR_ASSERT_SAFE(x == rr_graph.node_xhigh(node) && y == rr_graph.node_yhigh(node)); | ||
| tile_num_inter_die_conn[x][y]++; | ||
| } | ||
| } | ||
|
|
||
| int num_layers = grid.get_num_layers(); | ||
| for (size_t x = 0; x < grid.width(); x++) { | ||
| for (size_t y = 0; y < 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_ = vtr::PrefixSum2D<int>(grid.width(), | ||
| grid.height(), | ||
| [&](size_t x, size_t y) { | ||
| return static_cast<int>(std::round(tile_num_inter_die_conn[x][y])); | ||
| }); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,124 @@ | ||
| #pragma once | ||
| /** | ||
| * @file | ||
| * @author Alex Singer | ||
| * @date December 2025 | ||
| * @brief Declaration of the channel cost handler class. | ||
| */ | ||
|
|
||
| #include "vpr_types.h" | ||
| #include "vtr_prefix_sum.h" | ||
|
|
||
| // Forward declarations. | ||
| class DeviceGrid; | ||
| class RRGraphView; | ||
|
|
||
| /** | ||
| * @brief Manager class for computing the cost factors for channels in different | ||
| * dimensions. | ||
| */ | ||
| class ChanCostHandler { | ||
| public: | ||
| ChanCostHandler() = delete; | ||
|
|
||
| /** | ||
| * @brief Constructor for the ChanCostHanlder class. | ||
| * | ||
| * This will pre-compute prefix sum data structures which will make getting | ||
| * the x, y, and z chan cost factors more efficient. | ||
| * | ||
| * @param rr_chanx_width | ||
| * The horizontal channel width distribution across the device grid. | ||
| * @param rr_chany_width | ||
| * The vertical channel width distribution across the device grid. | ||
| * @param rr_graph | ||
| * The Routing Resource Graph of the device. | ||
| * @param grid | ||
| * The device grid. | ||
| */ | ||
| ChanCostHandler(const std::vector<int>& rr_chanx_width, | ||
| const std::vector<int>& rr_chany_width, | ||
| const RRGraphView& rr_graph, | ||
| const DeviceGrid& grid); | ||
|
|
||
| /** | ||
| * @brief Computes the inverse of average channel width for horizontal | ||
| * channels within a bounding box. | ||
| * | ||
| * @tparam BBT This can be either t_bb or t_2D_bb. | ||
| * @param bb The bounding box for which the inverse of average channel width | ||
| * within the bounding box is computed. | ||
| * @return The inverse of average channel width for horizontal channels. | ||
| */ | ||
| template<typename BBT> | ||
| inline double get_chanx_cost_fac(const BBT& bb) const { | ||
| int total_chanx_width = acc_chanx_width_.get_sum(bb.ymin, bb.ymax); | ||
| double inverse_average_chanx_width = (bb.ymax - bb.ymin + 1.0) / total_chanx_width; | ||
| return inverse_average_chanx_width; | ||
| } | ||
|
|
||
| /** | ||
| * @brief Computes the inverse of average channel width for vertical | ||
| * channels within a bounding box. | ||
| * | ||
| * @tparam BBT This can be either t_bb or t_2D_bb. | ||
| * @param bb The bounding box for which the inverse of average channel width | ||
| * within the bounding box is computed. | ||
| * @return The inverse of average channel width for vertical channels. | ||
| */ | ||
| template<typename BBT> | ||
| inline double get_chany_cost_fac(const BBT& bb) const { | ||
| int total_chany_width = acc_chany_width_.get_sum(bb.xmin, bb.xmax); | ||
| double inverse_average_chany_width = (bb.xmax - bb.xmin + 1.0) / total_chany_width; | ||
| return inverse_average_chany_width; | ||
| } | ||
|
|
||
| /** | ||
| * @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, but it | ||
| * will still weight z-directed vs. x- and y-directed connections appropriately. | ||
| * | ||
| * @param bb Bounding box of the net which chanz cost factor is to be calculated | ||
| * @return ChanZ cost factor | ||
| */ | ||
| inline double get_chanz_cost_fac(const t_bb& bb) const { | ||
| int num_inter_dir_conn = acc_tile_num_inter_die_conn_.get_sum(bb.xmin, | ||
| bb.ymin, | ||
| bb.xmax, | ||
| bb.ymax); | ||
|
|
||
| if (num_inter_dir_conn == 0) | ||
| return 1.0; | ||
|
|
||
| int bb_num_tiles = (bb.xmax - bb.xmin + 1) * (bb.ymax - bb.ymin + 1); | ||
| return static_cast<double>(bb_num_tiles) / num_inter_dir_conn; | ||
| } | ||
|
|
||
| private: | ||
| /** | ||
| * @brief Matrices below are used to precompute the inverse of the average | ||
| * number of tracks per channel between [subhigh] and [sublow]. Access | ||
| * them as chan?_place_cost_fac(subhigh, sublow). They are used to | ||
| * speed up the computation of the cost function that takes the length | ||
| * of the net bounding box in each dimension, divided by the average | ||
| * number of tracks in that direction; for other cost functions they | ||
| * will never be used. | ||
| */ | ||
| vtr::PrefixSum1D<int> acc_chanx_width_; // [0..grid_width-1] | ||
| vtr::PrefixSum1D<int> acc_chany_width_; // [0..grid_height-1] | ||
|
|
||
| /** | ||
| * @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::PrefixSum2D<int> acc_tile_num_inter_die_conn_; // [0..grid_width-1][0..grid_height-1] | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.