13
13
#include < memory>
14
14
#include < utility>
15
15
#include < vector>
16
+ #include " PreClusterTimingManager.h"
17
+ #include " atom_netlist.h"
18
+ #include " atom_netlist_fwd.h"
16
19
#include " device_grid.h"
17
20
#include " flat_placement_types.h"
18
21
#include " partial_placement.h"
42
45
std::unique_ptr<AnalyticalSolver> make_analytical_solver (e_ap_analytical_solver solver_type,
43
46
const APNetlist& netlist,
44
47
const DeviceGrid& device_grid,
48
+ const AtomNetlist& atom_netlist,
49
+ const PreClusterTimingManager& pre_cluster_timing_manager,
50
+ float ap_timing_tradeoff,
45
51
int log_verbosity) {
46
52
// Based on the solver type passed in, build the solver.
47
53
switch (solver_type) {
48
54
case e_ap_analytical_solver::QP_Hybrid:
49
55
#ifdef EIGEN_INSTALLED
50
- return std::make_unique<QPHybridSolver>(netlist, device_grid, log_verbosity);
56
+ return std::make_unique<QPHybridSolver>(netlist,
57
+ device_grid,
58
+ atom_netlist,
59
+ pre_cluster_timing_manager,
60
+ ap_timing_tradeoff,
61
+ log_verbosity);
51
62
#else
52
63
(void )netlist;
53
64
(void )device_grid;
@@ -58,7 +69,12 @@ std::unique_ptr<AnalyticalSolver> make_analytical_solver(e_ap_analytical_solver
58
69
#endif // EIGEN_INSTALLED
59
70
case e_ap_analytical_solver::LP_B2B:
60
71
#ifdef EIGEN_INSTALLED
61
- return std::make_unique<B2BSolver>(netlist, device_grid, log_verbosity);
72
+ return std::make_unique<B2BSolver>(netlist,
73
+ device_grid,
74
+ atom_netlist,
75
+ pre_cluster_timing_manager,
76
+ ap_timing_tradeoff,
77
+ log_verbosity);
62
78
#else
63
79
VPR_FATAL_ERROR (VPR_ERROR_AP,
64
80
" LP B2B Solver requires the Eigen library" );
@@ -72,10 +88,15 @@ std::unique_ptr<AnalyticalSolver> make_analytical_solver(e_ap_analytical_solver
72
88
return nullptr ;
73
89
}
74
90
75
- AnalyticalSolver::AnalyticalSolver (const APNetlist& netlist, int log_verbosity)
91
+ AnalyticalSolver::AnalyticalSolver (const APNetlist& netlist,
92
+ const AtomNetlist& atom_netlist,
93
+ const PreClusterTimingManager& pre_cluster_timing_manager,
94
+ float ap_timing_tradeoff,
95
+ int log_verbosity)
76
96
: netlist_(netlist)
77
97
, blk_id_to_row_id_(netlist.blocks().size(), APRowId::INVALID())
78
98
, row_id_to_blk_id_(netlist.blocks().size(), APBlockId::INVALID())
99
+ , net_weights_(netlist.nets().size(), 1.0f)
79
100
, log_verbosity_(log_verbosity) {
80
101
// Get the number of moveable blocks in the netlist and create a unique
81
102
// row ID from [0, num_moveable_blocks) for each moveable block in the
@@ -94,6 +115,21 @@ AnalyticalSolver::AnalyticalSolver(const APNetlist& netlist, int log_verbosity)
94
115
current_row_id++;
95
116
num_moveable_blocks_++;
96
117
}
118
+
119
+ if (pre_cluster_timing_manager.is_valid ()) {
120
+ for (APNetId net_id : netlist.nets ()) {
121
+ // Get the atom net associated with the given AP net. When
122
+ // constructing the AP netlist, we happen to set the name of each
123
+ // AP net to the same name as the atom net that generated them!
124
+ // TODO: Create a proper lookup structure to go from the AP Netlist
125
+ // back to the Atom Netlist.
126
+ AtomNetId atom_net_id = atom_netlist.find_net (netlist.net_name (net_id));
127
+ VTR_ASSERT (atom_net_id.is_valid ());
128
+ float crit = pre_cluster_timing_manager.calc_net_setup_criticality (atom_net_id, atom_netlist);
129
+
130
+ net_weights_[net_id] = ap_timing_tradeoff * crit + (1 .0f - ap_timing_tradeoff);
131
+ }
132
+ }
97
133
}
98
134
99
135
#ifdef EIGEN_INSTALLED
@@ -201,12 +237,15 @@ void QPHybridSolver::init_linear_system() {
201
237
for (APNetId net_id : netlist_.nets ()) {
202
238
size_t num_pins = netlist_.net_pins (net_id).size ();
203
239
VTR_ASSERT_DEBUG (num_pins > 1 );
240
+
241
+ double net_weight = net_weights_[net_id];
242
+
204
243
if (num_pins > star_num_pins_threshold) {
205
244
// Create a star node and connect each block in the net to the star
206
245
// node.
207
246
// Using the weight from FastPlace
208
247
// TODO: Investigate other weight terms.
209
- double w = static_cast <double >(num_pins) / static_cast <double >(num_pins - 1 );
248
+ double w = net_weight * static_cast <double >(num_pins) / static_cast <double >(num_pins - 1 );
210
249
size_t star_node_id = num_moveable_blocks_ + star_node_offset;
211
250
for (APPinId pin_id : netlist_.net_pins (net_id)) {
212
251
APBlockId blk_id = netlist_.pin_block (pin_id);
@@ -220,7 +259,7 @@ void QPHybridSolver::init_linear_system() {
220
259
// exactly once to every other block in the net.
221
260
// Using the weight from FastPlace
222
261
// TODO: Investigate other weight terms.
223
- double w = 1.0 / static_cast <double >(num_pins - 1 );
262
+ double w = net_weight * 1.0 / static_cast <double >(num_pins - 1 );
224
263
for (size_t ipin_idx = 0 ; ipin_idx < num_pins; ipin_idx++) {
225
264
APPinId first_pin_id = netlist_.net_pin (net_id, ipin_idx);
226
265
APBlockId first_blk_id = netlist_.pin_block (first_pin_id);
@@ -638,6 +677,7 @@ static inline APNetBounds get_unique_net_bounds(APNetId net_id,
638
677
void B2BSolver::add_connection_to_system (APBlockId first_blk_id,
639
678
APBlockId second_blk_id,
640
679
size_t num_pins,
680
+ double net_w,
641
681
const vtr::vector<APBlockId, double >& blk_locs,
642
682
std::vector<Eigen::Triplet<double >>& triplet_list,
643
683
Eigen::VectorXd& b) {
@@ -660,7 +700,7 @@ void B2BSolver::add_connection_to_system(APBlockId first_blk_id,
660
700
// The denominator of weight is zero, which causes infinity term in the matrix. Another way of
661
701
// interpreting epsilon is the minimum distance two nodes are considered to be in placement.
662
702
double dist = std::max (std::abs (blk_locs[first_blk_id] - blk_locs[second_blk_id]), distance_epsilon_);
663
- double w = (2.0 / static_cast <double >(num_pins - 1 )) * (1.0 / dist);
703
+ double w = net_w * (2.0 / static_cast <double >(num_pins - 1 )) * (1.0 / dist);
664
704
665
705
// Update the connectivity matrix and the constant vector.
666
706
// This is similar to how connections are added for the quadratic formulation.
@@ -696,6 +736,8 @@ void B2BSolver::init_linear_system(PartialPlacement& p_placement) {
696
736
size_t num_pins = netlist_.net_pins (net_id).size ();
697
737
VTR_ASSERT_SAFE_MSG (num_pins > 1 , " net must have at least 2 pins" );
698
738
739
+ double net_w = net_weights_[net_id];
740
+
699
741
// Find the bounding blocks
700
742
APNetBounds net_bounds = get_unique_net_bounds (net_id, p_placement, netlist_);
701
743
@@ -706,19 +748,19 @@ void B2BSolver::init_linear_system(PartialPlacement& p_placement) {
706
748
for (APPinId pin_id : netlist_.net_pins (net_id)) {
707
749
APBlockId blk_id = netlist_.pin_block (pin_id);
708
750
if (blk_id != net_bounds.max_x_blk && blk_id != net_bounds.min_x_blk ) {
709
- add_connection_to_system (blk_id, net_bounds.max_x_blk , num_pins, p_placement.block_x_locs , triplet_list_x, b_x);
710
- add_connection_to_system (blk_id, net_bounds.min_x_blk , num_pins, p_placement.block_x_locs , triplet_list_x, b_x);
751
+ add_connection_to_system (blk_id, net_bounds.max_x_blk , num_pins, net_w, p_placement.block_x_locs , triplet_list_x, b_x);
752
+ add_connection_to_system (blk_id, net_bounds.min_x_blk , num_pins, net_w, p_placement.block_x_locs , triplet_list_x, b_x);
711
753
}
712
754
if (blk_id != net_bounds.max_y_blk && blk_id != net_bounds.min_y_blk ) {
713
- add_connection_to_system (blk_id, net_bounds.max_y_blk , num_pins, p_placement.block_y_locs , triplet_list_y, b_y);
714
- add_connection_to_system (blk_id, net_bounds.min_y_blk , num_pins, p_placement.block_y_locs , triplet_list_y, b_y);
755
+ add_connection_to_system (blk_id, net_bounds.max_y_blk , num_pins, net_w, p_placement.block_y_locs , triplet_list_y, b_y);
756
+ add_connection_to_system (blk_id, net_bounds.min_y_blk , num_pins, net_w, p_placement.block_y_locs , triplet_list_y, b_y);
715
757
}
716
758
}
717
759
718
760
// Connect the bounds to each other. Its just easier to put these here
719
761
// instead of in the for loop above.
720
- add_connection_to_system (net_bounds.max_x_blk , net_bounds.min_x_blk , num_pins, p_placement.block_x_locs , triplet_list_x, b_x);
721
- add_connection_to_system (net_bounds.max_y_blk , net_bounds.min_y_blk , num_pins, p_placement.block_y_locs , triplet_list_y, b_y);
762
+ add_connection_to_system (net_bounds.max_x_blk , net_bounds.min_x_blk , num_pins, net_w, p_placement.block_x_locs , triplet_list_x, b_x);
763
+ add_connection_to_system (net_bounds.max_y_blk , net_bounds.min_y_blk , num_pins, net_w, p_placement.block_y_locs , triplet_list_y, b_y);
722
764
}
723
765
724
766
// Build the sparse connectivity matrices from the triplets.
0 commit comments