9
9
#include < limits>
10
10
#include < memory>
11
11
#include < random>
12
- #include < unordered_set>
13
12
#include < utility>
14
13
#include < vector>
15
14
#include " PartialPlacement.h"
16
- #include " atom_netlist.h"
17
15
#include " globals.h"
18
- #include " partition_region.h"
19
16
#include " vpr_context.h"
20
17
#include " vpr_error.h"
21
- #include " vpr_types.h"
22
18
#include " vtr_assert.h"
23
19
24
20
std::unique_ptr<AnalyticalSolver> make_analytical_solver (e_analytical_solver solver_type) {
@@ -96,11 +92,9 @@ static inline void populate_hybrid_matrix(Eigen::SparseMatrix<double> &A_sparse,
96
92
Eigen::VectorXd &b_y,
97
93
PartialPlacement& p_placement) {
98
94
size_t num_star_nodes = 0 ;
99
- const AtomNetlist& netlist = p_placement.atom_netlist ;
100
- for (AtomNetId net_id : netlist.nets ()) {
101
- if (p_placement.net_is_ignored_for_placement (net_id))
102
- continue ;
103
- if (netlist.net_pins (net_id).size () > 3 )
95
+ for (const std::vector<size_t > &net : p_placement.ap_netlist ) {
96
+ size_t num_pins = net.size ();
97
+ if (num_pins > 3 )
104
98
num_star_nodes++;
105
99
}
106
100
@@ -109,28 +103,19 @@ static inline void populate_hybrid_matrix(Eigen::SparseMatrix<double> &A_sparse,
109
103
b_x = Eigen::VectorXd::Zero (num_moveable_nodes + num_star_nodes);
110
104
b_y = Eigen::VectorXd::Zero (num_moveable_nodes + num_star_nodes);
111
105
112
- const AtomContext& atom_ctx = g_vpr_ctx.atom ();
113
-
106
+ size_t num_nets = p_placement.ap_netlist .size ();
114
107
std::vector<Eigen::Triplet<double >> tripletList;
115
- tripletList.reserve (num_moveable_nodes * netlist. nets (). size () );
108
+ tripletList.reserve (num_moveable_nodes * num_nets );
116
109
117
110
size_t star_node_offset = 0 ;
118
- // FIXME: Instead of iterating over the whole nelist and reverse looking up
119
- // it may make more sense to pre-compute the netlist.
120
- for (AtomNetId net_id : netlist.nets ()) {
121
- if (p_placement.net_is_ignored_for_placement (net_id))
122
- continue ;
123
- int num_pins = netlist.net_pins (net_id).size ();
111
+ for (const std::vector<size_t > &net : p_placement.ap_netlist ) {
112
+ size_t num_pins = net.size ();
124
113
VTR_ASSERT (num_pins > 1 );
125
114
if (num_pins > 3 ) {
126
- // FIXME: THIS WAS DIRECTLY COPIED FROM THE STAR FORMULATION. MOVE TO OWN FUNCTION.
127
- // (with the exeption of the star node offset).
128
115
// Using the weight from FastPlace
129
116
double w = static_cast <double >(num_pins) / static_cast <double >(num_pins - 1 );
130
117
size_t star_node_id = num_moveable_nodes + star_node_offset;
131
- for (AtomPinId pin_id : netlist.net_pins (net_id)) {
132
- AtomBlockId blk_id = netlist.pin_block (pin_id);
133
- size_t node_id = p_placement.get_node_id_from_blk (blk_id, atom_ctx.atom_molecules );
118
+ for (size_t node_id : net) {
134
119
// Note: the star node is always moveable
135
120
if (p_placement.is_moveable_node (node_id)) {
136
121
tripletList.emplace_back (star_node_id, star_node_id, w);
@@ -145,19 +130,13 @@ static inline void populate_hybrid_matrix(Eigen::SparseMatrix<double> &A_sparse,
145
130
}
146
131
star_node_offset++;
147
132
} else {
148
- // FIXME: THIS WAS DIRECTLY COPIED FROM THE CLIQUE FORMULATION. MOVE TO OWN FUNCTION.
149
133
// Using the weight from FastPlace
150
134
double w = 1.0 / static_cast <double >(num_pins - 1 );
151
135
152
- for (int ipin = 0 ; ipin < num_pins; ipin++) {
153
- // FIXME: Is it possible for two pins to be connected to the same block?
154
- // I am wondering if this doesnt matter because it would appear as tho
155
- // this block really wants to be connected lol.
156
- AtomBlockId first_block_id = netlist.net_pin_block (net_id, ipin);
157
- size_t first_node_id = p_placement.get_node_id_from_blk (first_block_id, atom_ctx.atom_molecules );
158
- for (int jpin = ipin + 1 ; jpin < num_pins; jpin++) {
159
- AtomBlockId second_block_id = netlist.net_pin_block (net_id, jpin);
160
- size_t second_node_id = p_placement.get_node_id_from_blk (second_block_id, atom_ctx.atom_molecules );
136
+ for (size_t inode_idx = 0 ; inode_idx < num_pins; inode_idx++) {
137
+ size_t first_node_id = net[inode_idx];
138
+ for (size_t jnode_idx = inode_idx + 1 ; jnode_idx < num_pins; jnode_idx++) {
139
+ size_t second_node_id = net[jnode_idx];
161
140
// Make sure that the first node is moveable. This makes creating the connection easier.
162
141
if (!p_placement.is_moveable_node (first_node_id)) {
163
142
if (!p_placement.is_moveable_node (second_node_id)) {
@@ -268,7 +247,7 @@ void B2BSolver::initialize_placement_least_dense(PartialPlacement &p_placement)
268
247
}
269
248
270
249
// This function return the two nodes on the bound of a netlist, (max, min)
271
- std::pair<size_t , size_t > B2BSolver::boundNode (std::vector<size_t >& node_ids, std::vector<double >& node_locs){
250
+ std::pair<size_t , size_t > B2BSolver::boundNode (const std::vector<size_t >& node_ids, const std::vector<double >& node_locs){
272
251
auto compare = [&node_locs](size_t a, size_t b) {
273
252
return node_locs[a] < node_locs[b];
274
253
};
@@ -279,54 +258,36 @@ std::pair<size_t, size_t> B2BSolver::boundNode(std::vector<size_t>& node_ids, st
279
258
}
280
259
281
260
void B2BSolver::populate_matrix (PartialPlacement &p_placement) {
282
- const AtomContext& atom_ctx = g_vpr_ctx.atom ();
283
- const AtomNetlist& netlist = p_placement.atom_netlist ;
284
261
// Resetting As bs
285
262
A_sparse_x = Eigen::SparseMatrix<double >(A_sparse_x.rows (), A_sparse_x.cols ());
286
263
A_sparse_y = Eigen::SparseMatrix<double >(A_sparse_y.rows (), A_sparse_y.cols ());
287
264
// A_sparse_x.setZero();
288
265
// A_sparse_y.setZero();
266
+ size_t num_nets = p_placement.ap_netlist .size ();
289
267
std::vector<Eigen::Triplet<double >> tripletList_x;
290
- tripletList_x.reserve (p_placement.num_moveable_nodes * netlist. nets (). size () );
268
+ tripletList_x.reserve (p_placement.num_moveable_nodes * num_nets );
291
269
std::vector<Eigen::Triplet<double >> tripletList_y;
292
- tripletList_y.reserve (p_placement.num_moveable_nodes * netlist. nets (). size () );
270
+ tripletList_y.reserve (p_placement.num_moveable_nodes * num_nets );
293
271
b_x = Eigen::VectorXd::Zero (p_placement.num_moveable_nodes );
294
272
b_y = Eigen::VectorXd::Zero (p_placement.num_moveable_nodes );
295
273
296
- for (AtomNetId net_id : netlist.nets ()) {
297
- if (p_placement.net_is_ignored_for_placement (net_id))
298
- continue ;
299
-
300
- int num_pins = netlist.net_pins (net_id).size ();
274
+ for (const std::vector<size_t > &net : p_placement.ap_netlist ) {
275
+ int num_pins = net.size ();
301
276
VTR_ASSERT (num_pins > 1 && " net least has at least 2 pins" );
302
-
303
- std::vector<size_t > node_ids;
304
- for (AtomPinId pin_id : netlist.net_pins (net_id)) {
305
- AtomBlockId blk_id = netlist.pin_block (pin_id);
306
- size_t node_id = p_placement.get_node_id_from_blk (blk_id, atom_ctx.atom_molecules );
307
- node_ids.push_back (node_id);
308
- }
309
- // remove duplicated node, they are there becaues of prepacked molecules.
310
- // FIXME: duplicate exists because atoms are packed in to molecules so some edges are now hidden.
311
- // We can create our own netlist class to resolve this problem.
312
- std::set<size_t > node_ids_set (node_ids.begin (), node_ids.end ());
313
- std::vector<size_t > node_ids_no_duplicate (node_ids_set.begin (), node_ids_set.end ());
314
-
315
- if (node_ids_no_duplicate.size () <= 1 ){
316
- continue ;
317
- }
318
- // TODO: do this in a for loop instead of creating vectors
319
- auto [maxXId, minXId] = boundNode (node_ids_no_duplicate, p_placement.node_loc_x );
320
- auto [maxYId, minYId] = boundNode (node_ids_no_duplicate, p_placement.node_loc_y );
277
+
278
+ // TODO: do this in a single for loop. Will likely be more efficient than
279
+ // iterating 4 times.
280
+ auto [maxXId, minXId] = boundNode (net, p_placement.node_loc_x );
281
+ auto [maxYId, minYId] = boundNode (net, p_placement.node_loc_y );
321
282
// assign arbitrary node as bound node when they are all equal
322
283
// TODO: although deterministic, investigate other ways to break ties.
323
284
if (maxXId == minXId) {
324
- maxXId = node_ids_no_duplicate [0 ];
325
- minXId = node_ids_no_duplicate [1 ];
285
+ maxXId = net [0 ];
286
+ minXId = net [1 ];
326
287
}
327
288
if (maxYId == minYId) {
328
- maxYId = node_ids_no_duplicate [0 ];
329
- minYId = node_ids_no_duplicate [1 ];
289
+ maxYId = net [0 ];
290
+ minYId = net [1 ];
330
291
}
331
292
auto add_node = [&](size_t first_node_id, size_t second_node_id, unsigned num_nodes, bool is_x){
332
293
if (!p_placement.is_moveable_node (first_node_id)) {
@@ -366,20 +327,19 @@ void B2BSolver::populate_matrix(PartialPlacement &p_placement) {
366
327
}
367
328
}
368
329
};
369
- // TODO: when adding custom netlist, also modify here.
370
- size_t num_nodes = node_ids_no_duplicate.size ();
371
- for (size_t node_id = 0 ; node_id < num_nodes; node_id++) {
330
+
331
+ for (size_t node_id : net) {
372
332
if (node_id != maxXId && node_id != minXId) {
373
- add_node (node_id, maxXId, num_nodes , true );
374
- add_node (node_id, minXId, num_nodes , true );
333
+ add_node (node_id, maxXId, num_pins , true );
334
+ add_node (node_id, minXId, num_pins , true );
375
335
}
376
336
if (node_id != maxYId && node_id != minYId) {
377
- add_node (node_id, maxYId, num_nodes , false );
378
- add_node (node_id, minYId, num_nodes , false );
337
+ add_node (node_id, maxYId, num_pins , false );
338
+ add_node (node_id, minYId, num_pins , false );
379
339
}
380
340
}
381
- add_node (maxXId, minXId, num_nodes , true );
382
- add_node (maxYId, minYId, num_nodes , false );
341
+ add_node (maxXId, minXId, num_pins , true );
342
+ add_node (maxYId, minYId, num_pins , false );
383
343
}
384
344
A_sparse_x.setFromTriplets (tripletList_x.begin (), tripletList_x.end ());
385
345
A_sparse_y.setFromTriplets (tripletList_y.begin (), tripletList_y.end ());
@@ -388,8 +348,11 @@ void B2BSolver::populate_matrix(PartialPlacement &p_placement) {
388
348
// This function adds anchors for legalized solution. Anchors are treated as fixed node,
389
349
// each connecting to a movable node. Number of nodes in a anchor net is always 2.
390
350
void B2BSolver::populate_matrix_anchor (PartialPlacement& p_placement, unsigned iteration) {
391
- double coeff_pseudo_anchor = 0.001 * std::exp ((double )iteration/29.0 );
351
+ // double coeff_pseudo_anchor = 0.001 * std::exp((double)iteration/29.0);
392
352
// double coeff_pseudo_anchor = std::exp((double)iteration/1.0);
353
+
354
+ // Using alpha from the SimPL paper
355
+ double coeff_pseudo_anchor = 0.01 * (1.0 + static_cast <double >(iteration));
393
356
for (size_t i = 0 ; i < p_placement.num_moveable_nodes ; i++){
394
357
// Anchor node are always 2 pins.
395
358
double pseudo_w_x = coeff_pseudo_anchor*2.0 /std::max (std::abs (p_placement.node_loc_x [i] - node_loc_x_legalized[i]), epsilon);
@@ -479,4 +442,4 @@ void B2BSolver::solve(unsigned iteration, PartialPlacement &p_placement) {
479
442
// store solved position in data structure of this class
480
443
// node_loc_x_solved = p_placement.node_loc_x;
481
444
// node_loc_y_solved = p_placement.node_loc_y;
482
- }
445
+ }
0 commit comments