@@ -111,15 +111,32 @@ std::unique_ptr<AnalyticalSolver> make_analytical_solver(e_ap_analytical_solver
111
111
AnalyticalSolver::AnalyticalSolver (const APNetlist& netlist,
112
112
const AtomNetlist& atom_netlist,
113
113
const PreClusterTimingManager& pre_cluster_timing_manager,
114
+ const DeviceGrid& device_grid,
114
115
float ap_timing_tradeoff,
115
116
int log_verbosity)
116
117
: netlist_(netlist)
117
118
, atom_netlist_(atom_netlist)
118
119
, blk_id_to_row_id_(netlist.blocks().size(), APRowId::INVALID())
119
120
, row_id_to_blk_id_(netlist.blocks().size(), APBlockId::INVALID())
120
121
, net_weights_(netlist.nets().size(), 1.0f)
122
+ , device_grid_width_(device_grid.width())
123
+ , device_grid_height_(device_grid.height())
121
124
, ap_timing_tradeoff_(ap_timing_tradeoff)
122
125
, log_verbosity_(log_verbosity) {
126
+
127
+ // Mark completely disconnected blocks. Since these blocks are not connected
128
+ // to any nets that we care about for AP, we should not pass them into the
129
+ // AP solver.
130
+ vtr::vector<APBlockId, bool > block_is_used (netlist.blocks ().size (), false );
131
+ for (APNetId net_id : netlist.nets ()) {
132
+ if (netlist.net_is_ignored (net_id))
133
+ continue ;
134
+ for (APPinId pin_id : netlist.net_pins (net_id)) {
135
+ APBlockId blk_id = netlist.pin_block (pin_id);
136
+ block_is_used[blk_id] = true ;
137
+ }
138
+ }
139
+
123
140
// Get the number of moveable blocks in the netlist and create a unique
124
141
// row ID from [0, num_moveable_blocks) for each moveable block in the
125
142
// netlist.
@@ -131,6 +148,12 @@ AnalyticalSolver::AnalyticalSolver(const APNetlist& netlist,
131
148
num_fixed_blocks_++;
132
149
if (netlist.block_mobility (blk_id) != APBlockMobility::MOVEABLE)
133
150
continue ;
151
+ // If this block is disconnected (unused), add it to the disconnected
152
+ // blocks vector and skip creating a row ID for it.
153
+ if (!block_is_used[blk_id]) {
154
+ disconnected_blocks_.push_back (blk_id);
155
+ continue ;
156
+ }
134
157
APRowId new_row_id = APRowId (current_row_id);
135
158
blk_id_to_row_id_[blk_id] = new_row_id;
136
159
row_id_to_blk_id_[new_row_id] = blk_id;
@@ -404,6 +427,15 @@ void QPHybridSolver::solve(unsigned iteration, PartialPlacement& p_placement) {
404
427
// solution to the zero vector if we do not set it to the guess directly.
405
428
if (iteration == 0 && num_fixed_blocks_ == 0 ) {
406
429
store_solution_into_placement (guess_x, guess_y, p_placement);
430
+
431
+ // Store disconnected blocks into solution at the center of the device
432
+ for (APBlockId blk_id : disconnected_blocks_) {
433
+ // All disconnected blocks should not have row IDs or be fixed blocks.
434
+ VTR_ASSERT_SAFE (!blk_id_to_row_id_[blk_id].is_valid () && netlist_.block_mobility (blk_id) != APBlockMobility::FIXED);
435
+ p_placement.block_x_locs [blk_id] = device_grid_width_ / 2 .0f ;
436
+ p_placement.block_y_locs [blk_id] = device_grid_height_ / 2 .0f ;
437
+ }
438
+
407
439
return ;
408
440
}
409
441
@@ -442,6 +474,18 @@ void QPHybridSolver::solve(unsigned iteration, PartialPlacement& p_placement) {
442
474
// Write the results back into the partial placement object.
443
475
store_solution_into_placement (x, y, p_placement);
444
476
477
+ // In the very first iteration, the solver must provide a location for all
478
+ // of the blocks. The disconnected blocks will not be given a placement by
479
+ // the solver above. Just put them in the middle of the device and let the
480
+ // legalizer find good places for them. In future iterations, the prior
481
+ // position of these blocks will already be in the p_placement object.
482
+ if (iteration == 0 ) {
483
+ for (APBlockId blk_id : disconnected_blocks_) {
484
+ p_placement.block_x_locs [blk_id] = device_grid_width_ / 2.0 ;
485
+ p_placement.block_y_locs [blk_id] = device_grid_height_ / 2.0 ;
486
+ }
487
+ }
488
+
445
489
// Update the guess. The guess for the next iteration is the solution in
446
490
// this iteration.
447
491
guess_x = x;
@@ -497,9 +541,8 @@ void B2BSolver::solve(unsigned iteration, PartialPlacement& p_placement) {
497
541
// tile location for each AP block. The center is just an
498
542
// approximation.
499
543
if (num_fixed_blocks_ == 0 ) {
500
- for (size_t row_id_idx = 0 ; row_id_idx < num_moveable_blocks_; row_id_idx++) {
501
- APRowId row_id = APRowId (row_id_idx);
502
- APBlockId blk_id = row_id_to_blk_id_[row_id];
544
+ for (APBlockId blk_id : netlist_.blocks ()) {
545
+ VTR_ASSERT_SAFE (netlist_.block_mobility (blk_id) != APBlockMobility::FIXED);
503
546
p_placement.block_x_locs [blk_id] = device_grid_width_ / 2.0 ;
504
547
p_placement.block_y_locs [blk_id] = device_grid_height_ / 2.0 ;
505
548
}
@@ -559,6 +602,13 @@ void B2BSolver::initialize_placement_least_dense(PartialPlacement& p_placement)
559
602
p_placement.block_y_locs [blk_id] = r * gap;
560
603
}
561
604
}
605
+
606
+ // Any blocks which are disconnected can be put anywhere. Just put them at
607
+ // the center of the device for now.
608
+ for (APBlockId blk_id : disconnected_blocks_) {
609
+ p_placement.block_x_locs [blk_id] = device_grid_width_ / 2.0 ;
610
+ p_placement.block_y_locs [blk_id] = device_grid_height_ / 2.0 ;
611
+ }
562
612
}
563
613
564
614
void B2BSolver::b2b_solve_loop (unsigned iteration, PartialPlacement& p_placement) {
@@ -654,6 +704,24 @@ void B2BSolver::b2b_solve_loop(unsigned iteration, PartialPlacement& p_placement
654
704
x_guess = x;
655
705
y_guess = y;
656
706
}
707
+
708
+ // Disconnected blocks are not optimized by the solver.
709
+ if (iteration == 0 ) {
710
+ // In the first iteration of GP, just place the disconnected blocks at the
711
+ // center of the device. The legalizer will find a good place to put
712
+ // them.
713
+ for (APBlockId blk_id : disconnected_blocks_) {
714
+ p_placement.block_x_locs [blk_id] = device_grid_width_ / 2.0 ;
715
+ p_placement.block_y_locs [blk_id] = device_grid_height_ / 2.0 ;
716
+ }
717
+ } else {
718
+ // If a legalized solution is available (after the first iteration of GP), then
719
+ // set the disconnected blocks to their legalized position.
720
+ for (APBlockId blk_id : disconnected_blocks_) {
721
+ p_placement.block_x_locs [blk_id] = block_x_locs_legalized[blk_id];
722
+ p_placement.block_y_locs [blk_id] = block_y_locs_legalized[blk_id];
723
+ }
724
+ }
657
725
}
658
726
659
727
namespace {
@@ -791,11 +859,11 @@ void B2BSolver::init_linear_system(PartialPlacement& p_placement) {
791
859
792
860
// Create triplet lists to store the sparse positions to update and reserve
793
861
// space for them.
794
- size_t num_nets = netlist_.nets ().size ();
862
+ size_t total_num_pins_in_netlist = netlist_.pins ().size ();
795
863
std::vector<Eigen::Triplet<double >> triplet_list_x;
796
- triplet_list_x.reserve (num_nets );
864
+ triplet_list_x.reserve (total_num_pins_in_netlist );
797
865
std::vector<Eigen::Triplet<double >> triplet_list_y;
798
- triplet_list_y.reserve (num_nets );
866
+ triplet_list_y.reserve (total_num_pins_in_netlist );
799
867
800
868
for (APNetId net_id : netlist_.nets ()) {
801
869
if (netlist_.net_is_ignored (net_id))
0 commit comments