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;
65
+ (void )atom_netlist;
66
+ (void )pre_cluster_timing_manager;
67
+ (void )ap_timing_tradeoff;
54
68
(void )log_verbosity;
55
69
VPR_FATAL_ERROR (VPR_ERROR_AP,
56
70
" QP Hybrid Solver requires the Eigen library" );
57
71
break ;
58
72
#endif // EIGEN_INSTALLED
59
73
case e_ap_analytical_solver::LP_B2B:
60
74
#ifdef EIGEN_INSTALLED
61
- return std::make_unique<B2BSolver>(netlist, device_grid, log_verbosity);
75
+ return std::make_unique<B2BSolver>(netlist,
76
+ device_grid,
77
+ atom_netlist,
78
+ pre_cluster_timing_manager,
79
+ ap_timing_tradeoff,
80
+ log_verbosity);
62
81
#else
63
82
VPR_FATAL_ERROR (VPR_ERROR_AP,
64
83
" LP B2B Solver requires the Eigen library" );
@@ -72,10 +91,15 @@ std::unique_ptr<AnalyticalSolver> make_analytical_solver(e_ap_analytical_solver
72
91
return nullptr ;
73
92
}
74
93
75
- AnalyticalSolver::AnalyticalSolver (const APNetlist& netlist, int log_verbosity)
94
+ AnalyticalSolver::AnalyticalSolver (const APNetlist& netlist,
95
+ const AtomNetlist& atom_netlist,
96
+ const PreClusterTimingManager& pre_cluster_timing_manager,
97
+ float ap_timing_tradeoff,
98
+ int log_verbosity)
76
99
: netlist_(netlist)
77
100
, blk_id_to_row_id_(netlist.blocks().size(), APRowId::INVALID())
78
101
, row_id_to_blk_id_(netlist.blocks().size(), APBlockId::INVALID())
102
+ , net_weights_(netlist.nets().size(), 1.0f)
79
103
, log_verbosity_(log_verbosity) {
80
104
// Get the number of moveable blocks in the netlist and create a unique
81
105
// row ID from [0, num_moveable_blocks) for each moveable block in the
@@ -94,6 +118,21 @@ AnalyticalSolver::AnalyticalSolver(const APNetlist& netlist, int log_verbosity)
94
118
current_row_id++;
95
119
num_moveable_blocks_++;
96
120
}
121
+
122
+ if (pre_cluster_timing_manager.is_valid ()) {
123
+ for (APNetId net_id : netlist.nets ()) {
124
+ // Get the atom net associated with the given AP net. When
125
+ // constructing the AP netlist, we happen to set the name of each
126
+ // AP net to the same name as the atom net that generated them!
127
+ // TODO: Create a proper lookup structure to go from the AP Netlist
128
+ // back to the Atom Netlist.
129
+ AtomNetId atom_net_id = atom_netlist.find_net (netlist.net_name (net_id));
130
+ VTR_ASSERT (atom_net_id.is_valid ());
131
+ float crit = pre_cluster_timing_manager.calc_net_setup_criticality (atom_net_id, atom_netlist);
132
+
133
+ net_weights_[net_id] = ap_timing_tradeoff * crit + (1 .0f - ap_timing_tradeoff);
134
+ }
135
+ }
97
136
}
98
137
99
138
#ifdef EIGEN_INSTALLED
@@ -201,12 +240,15 @@ void QPHybridSolver::init_linear_system() {
201
240
for (APNetId net_id : netlist_.nets ()) {
202
241
size_t num_pins = netlist_.net_pins (net_id).size ();
203
242
VTR_ASSERT_DEBUG (num_pins > 1 );
243
+
244
+ double net_weight = net_weights_[net_id];
245
+
204
246
if (num_pins > star_num_pins_threshold) {
205
247
// Create a star node and connect each block in the net to the star
206
248
// node.
207
249
// Using the weight from FastPlace
208
250
// TODO: Investigate other weight terms.
209
- double w = static_cast <double >(num_pins) / static_cast <double >(num_pins - 1 );
251
+ double w = net_weight * static_cast <double >(num_pins) / static_cast <double >(num_pins - 1 );
210
252
size_t star_node_id = num_moveable_blocks_ + star_node_offset;
211
253
for (APPinId pin_id : netlist_.net_pins (net_id)) {
212
254
APBlockId blk_id = netlist_.pin_block (pin_id);
@@ -220,7 +262,7 @@ void QPHybridSolver::init_linear_system() {
220
262
// exactly once to every other block in the net.
221
263
// Using the weight from FastPlace
222
264
// TODO: Investigate other weight terms.
223
- double w = 1.0 / static_cast <double >(num_pins - 1 );
265
+ double w = net_weight * 1.0 / static_cast <double >(num_pins - 1 );
224
266
for (size_t ipin_idx = 0 ; ipin_idx < num_pins; ipin_idx++) {
225
267
APPinId first_pin_id = netlist_.net_pin (net_id, ipin_idx);
226
268
APBlockId first_blk_id = netlist_.pin_block (first_pin_id);
@@ -638,6 +680,7 @@ static inline APNetBounds get_unique_net_bounds(APNetId net_id,
638
680
void B2BSolver::add_connection_to_system (APBlockId first_blk_id,
639
681
APBlockId second_blk_id,
640
682
size_t num_pins,
683
+ double net_w,
641
684
const vtr::vector<APBlockId, double >& blk_locs,
642
685
std::vector<Eigen::Triplet<double >>& triplet_list,
643
686
Eigen::VectorXd& b) {
@@ -660,7 +703,7 @@ void B2BSolver::add_connection_to_system(APBlockId first_blk_id,
660
703
// The denominator of weight is zero, which causes infinity term in the matrix. Another way of
661
704
// interpreting epsilon is the minimum distance two nodes are considered to be in placement.
662
705
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);
706
+ double w = net_w * (2.0 / static_cast <double >(num_pins - 1 )) * (1.0 / dist);
664
707
665
708
// Update the connectivity matrix and the constant vector.
666
709
// This is similar to how connections are added for the quadratic formulation.
@@ -696,6 +739,8 @@ void B2BSolver::init_linear_system(PartialPlacement& p_placement) {
696
739
size_t num_pins = netlist_.net_pins (net_id).size ();
697
740
VTR_ASSERT_SAFE_MSG (num_pins > 1 , " net must have at least 2 pins" );
698
741
742
+ double net_w = net_weights_[net_id];
743
+
699
744
// Find the bounding blocks
700
745
APNetBounds net_bounds = get_unique_net_bounds (net_id, p_placement, netlist_);
701
746
@@ -706,19 +751,19 @@ void B2BSolver::init_linear_system(PartialPlacement& p_placement) {
706
751
for (APPinId pin_id : netlist_.net_pins (net_id)) {
707
752
APBlockId blk_id = netlist_.pin_block (pin_id);
708
753
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);
754
+ 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);
755
+ 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
756
}
712
757
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);
758
+ 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);
759
+ 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
760
}
716
761
}
717
762
718
763
// Connect the bounds to each other. Its just easier to put these here
719
764
// 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);
765
+ 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);
766
+ 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
767
}
723
768
724
769
// Build the sparse connectivity matrices from the triplets.
0 commit comments