00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 #include "btreeanneal.h"
00048 #include "btreecompact.h"
00049 #include "basepacking.h"
00050 #include "mixedpacking.h"
00051 #include "mixedpackingfromdb.h"
00052 #include "pltobtree.h"
00053
00054 #include "debugflags.h"
00055
00056
00057
00058
00059
00060
00061 #include "allparquet.h"
00062
00063 #include <cmath>
00064 #include <cfloat>
00065 #include <algorithm>
00066 #include <iterator>
00067 using namespace std;
00068
00069 using parquetfp::Nodes;
00070 using parquetfp::DB;
00071 using parquetfp::Command_Line;
00072 using parquetfp::AnalytSolve;
00073
00074
00075 BTreeAreaWireAnnealer::BTreeAreaWireAnnealer(
00076 MixedBlockInfoType& nBlockinfo)
00077 : BaseAnnealer(),
00078 _blockinfo_cleaner(NULL),
00079 _blockinfo(nBlockinfo),
00080 blockinfo(nBlockinfo),
00081 in_curr_solution(_blockinfo.currDimensions),
00082 in_next_solution(_blockinfo.currDimensions),
00083 in_best_solution(_blockinfo.currDimensions),
00084 _slackEval(NULL)
00085 {}
00086
00087 BTreeAreaWireAnnealer::BTreeAreaWireAnnealer(
00088 MixedBlockInfoType& nBlockinfo,
00089 const Command_Line *const params,
00090 DB *const db)
00091 : BaseAnnealer(params, db),
00092 _blockinfo_cleaner(NULL),
00093 _blockinfo(nBlockinfo),
00094 blockinfo(nBlockinfo),
00095 in_curr_solution(_blockinfo.currDimensions),
00096 in_next_solution(_blockinfo.currDimensions),
00097 in_best_solution(_blockinfo.currDimensions),
00098 _slackEval(new BTreeSlackEval(in_curr_solution))
00099 {
00100 constructor_core();
00101 }
00102
00103 BTreeAreaWireAnnealer::BTreeAreaWireAnnealer(
00104 const Command_Line *const params,
00105 DB *const db)
00106 : BaseAnnealer(params, db),
00107 _blockinfo_cleaner(static_cast<MixedBlockInfoType*>
00108 (new MixedBlockInfoTypeFromDB(*db))),
00109 _blockinfo(*_blockinfo_cleaner),
00110 blockinfo(_blockinfo),
00111 in_curr_solution(_blockinfo.currDimensions),
00112 in_next_solution(_blockinfo.currDimensions),
00113 in_best_solution(_blockinfo.currDimensions),
00114 _slackEval(new BTreeSlackEval(in_curr_solution))
00115 {
00116 constructor_core();
00117 }
00118
00119 void BTreeAreaWireAnnealer::constructor_core()
00120 {
00121
00122 _physicalOrient.resize(in_curr_solution.NUM_BLOCKS);
00123 for (int i = 0; i < in_curr_solution.NUM_BLOCKS; i++)
00124 {
00125 _physicalOrient[i].resize(blockinfo.ORIENT_NUM);
00126 for (int theta = 0; theta < blockinfo.ORIENT_NUM; theta++)
00127 {
00128 parquetfp::Node& currBlock = _db->getNodes()->getNode(i);
00129 if (currBlock.isOrientFixed())
00130 _physicalOrient[i][theta] = parquetfp::N;
00131 else
00132 _physicalOrient[i][theta] = parquetfp::ORIENT(theta);
00133 }
00134 }
00135
00136
00137 GenerateRandomSoln(in_curr_solution, blockinfo.currDimensions.blocknum());
00138 in_best_solution = in_curr_solution;
00139 in_next_solution = in_curr_solution;
00140
00141
00142 for (int i = 0; i < in_curr_solution.NUM_BLOCKS; i++)
00143 {
00144 int initOrient = int(in_curr_solution.tree[i].orient);
00145 initOrient = _physicalOrient[i][initOrient];
00146
00147 double initWidth = in_curr_solution.width(i);
00148 double initHeight = in_curr_solution.height(i);
00149
00150 _db->getNodes()->changeOrient(i, parquetfp::ORIENT(initOrient),
00151 *(_db->getNets()));
00152 _db->getNodes()->putNodeWidth(i, initWidth);
00153 _db->getNodes()->putNodeHeight(i, initHeight);
00154 }
00155
00156
00157
00158 for (int i = 0; i < in_curr_solution.NUM_BLOCKS; i++)
00159 {
00160 for (int theta = 0; theta < blockinfo.ORIENT_NUM; theta++)
00161 if ((_db->getNodes()->getNode(i)).isOrientFixed() &&
00162 int(in_curr_solution.tree[i].orient) != 0)
00163 {
00164 cout << "ctor: orient of block[" << i << "] should be \"n\"" << endl;
00165 printf("in_curr_solution:orient %d\n",
00166 int(in_curr_solution.tree[i].orient));
00167 cin.get();
00168 }
00169
00170 if (_params->minWL && (int(in_curr_solution.tree[i].orient) !=
00171 int(_db->getNodes()->getNode(i).getOrient())))
00172 {
00173 cout << "ctor: orient of block[" << i << "] is not consistent" << endl;
00174 printf("in_curr_solution:orient %d vs. _db->orient: %d\n",
00175 int(in_curr_solution.tree[i].orient),
00176 int(_db->getNodes()->getNode(i).getOrient()));
00177 cin.get();
00178 }
00179
00180 int theta = in_curr_solution.tree[i].orient;
00181 if (fabs(in_curr_solution.width(i) - blockinfo.currDimensions[i].width[theta]) > 1e-6)
00182 {
00183 printf("ctor: width of block[%d] is not consistent. in_curr_soln: %.2f vs. blockinfo: %.2f\n",
00184 i, in_curr_solution.width(i), blockinfo.currDimensions[i].width[theta]);
00185 cin.get();
00186 }
00187
00188 if (fabs(in_curr_solution.height(i) - blockinfo.currDimensions[i].height[theta]) > 1e-6)
00189 {
00190 printf("ctor: height of block[%d] is not consistent. in_curr_soln: %.2f vs. blockinfo: %.2f\n",
00191 i, in_curr_solution.height(i), blockinfo.currDimensions[i].height[theta]);
00192 cin.get();
00193 }
00194
00195 if (_params->minWL && fabs(in_curr_solution.width(i) - _db->getNodes()->getNodeWidth(i)) > 1e-6)
00196 {
00197 printf("ctor: width of block[%d] is not consistent. in_curr_solution: %.2f vs._db: %.2f\n",
00198 i, in_curr_solution.width(i), _db->getNodes()->getNodeWidth(i));
00199 cin.get();
00200 }
00201 }
00202 }
00203
00204 bool BTreeAreaWireAnnealer::go()
00205 {
00206 Timer T;
00207 T.stop();
00208
00209 DBfromSoln(in_curr_solution);
00210
00211 T.start(0.0);
00212 bool success = false;
00213 if (in_curr_solution.NUM_BLOCKS > 1)
00214 success = anneal();
00215 else
00216 success = packOneBlock();
00217 T.stop();
00218
00219 annealTime += T.getUserTime();
00220
00221
00222 DBfromSoln(in_curr_solution);
00223 in_best_solution = in_curr_solution;
00224
00225
00226 SolutionInfo currSoln;
00227 currSoln.area = in_curr_solution.totalArea();
00228 currSoln.width = in_curr_solution.totalWidth();
00229 currSoln.height = in_curr_solution.totalHeight();
00230 currSoln.HPWL = _db->evalHPWL();
00231 printResults(T, currSoln);
00232
00233 return success;
00234 }
00235
00236 void BTreeAreaWireAnnealer::DBfromSoln(const BTree& soln)
00237 {
00238 _db->updatePlacement(const_cast<vector<double>&>(soln.xloc()),
00239 const_cast<vector<double>&>(soln.yloc()));
00240 for (int i = 0; i < soln.NUM_BLOCKS; i++)
00241 {
00242 parquetfp::ORIENT newOrient =
00243 parquetfp::ORIENT(soln.tree[i].orient);
00244 _db->getNodes()->changeOrient(i, newOrient, *(_db->getNets()));
00245 _db->getNodes()->putNodeWidth(i, soln.width(i));
00246 _db->getNodes()->putNodeHeight(i, soln.height(i));
00247 }
00248
00249 _slackEval->evaluateSlacks(soln);
00250
00251 int blocknum = soln.NUM_BLOCKS;
00252 vector<double> xSlacks(blocknum);
00253 vector<double> ySlacks(blocknum);
00254 double totalWidth = soln.totalWidth();
00255 double totalHeight = soln.totalHeight();
00256 for (int i = 0; i < blocknum; i++)
00257 {
00258 xSlacks[i] = (_slackEval->xSlack()[i] / totalWidth) * 100;
00259 ySlacks[i] = (_slackEval->ySlack()[i] / totalHeight) * 100;
00260 }
00261 _db->updateSlacks(xSlacks, ySlacks);
00262
00263 #ifdef PARQUET_DEBUG_HAYWARD_ASSERT_BTREEANNEAL
00264 for (int i = 0; i < blocknum; i++)
00265 {
00266 int theta = soln.tree[i].orient;
00267 if (theta != _physicalOrient[i][theta])
00268 {
00269 printf("block: %d theta: %d physicalOrient: %d\n",
00270 i, theta, _physicalOrient[i][theta]);
00271 cin.get();
00272 }
00273 }
00274 #endif
00275 }
00276
00277 bool BTreeAreaWireAnnealer::packOneBlock()
00278 {
00279 const double blocksArea = in_curr_solution.blockArea();
00280 const double reqdAR = _params->reqdAR;
00281 const double reqdArea = blocksArea * (1+(_params->maxWS/100.0));
00282 const double reqdWidth = sqrt(reqdArea * reqdAR);
00283 const double reqdHeight = reqdWidth / reqdAR;
00284
00285 const vector<double> defaultXloc(1, 0);
00286 const vector<double> defaultYloc(1, 0);
00287 const int defaultOrient = 0;
00288
00289 cout << "Only one block is detected, deterministic algo used." << endl;
00290 if (_params->reqdAR != FREE_OUTLINE)
00291 cout << "outline width: " << reqdWidth
00292 << " outline height: " << reqdHeight << endl;
00293
00294 int bestOrient = defaultOrient;
00295 double bestHPWL = basepacking_h::Dimension::INFTY;
00296 bool success = false;
00297 for (int theta = 0;
00298 theta < basepacking_h::Dimension::ORIENT_NUM; theta++)
00299 {
00300 in_curr_solution.rotate(0, theta);
00301
00302 double blockWidth = in_curr_solution.width(0);
00303 double blockHeight = in_curr_solution.height(0);
00304 bool fitsInside = ((_params->reqdAR == FREE_OUTLINE) ||
00305 ((blockWidth <= reqdWidth) &&
00306 (blockHeight <= reqdHeight)));
00307
00308 cout << "orient: " << theta
00309 << " width: " << blockWidth
00310 << " height: " << blockHeight
00311 << " inside: " << ((fitsInside)? "T" : "F");
00312
00313 success = success || fitsInside;
00314 if (fitsInside && _params->minWL)
00315 {
00316 DBfromSoln(in_curr_solution);
00317 double currHPWL = _db->evalHPWL();
00318
00319 cout << " HPWL: " << currHPWL;
00320 if (currHPWL < bestHPWL)
00321 {
00322 bestOrient = theta;
00323 bestHPWL = currHPWL;
00324 }
00325 }
00326 else if (fitsInside)
00327 bestOrient = theta;
00328
00329 cout << endl;
00330 }
00331
00332 in_curr_solution.rotate(0, bestOrient);
00333 DBfromSoln(in_curr_solution);
00334
00335 return success;
00336 }
00337
00338 bool BTreeAreaWireAnnealer::anneal()
00339 {
00340
00341 bool budgetTime = _params->budgetTime;
00342 double seconds = _params->seconds;
00343 bool minWL = _params->minWL;
00344
00345
00346 double wireWeight = _params->wireWeight;
00347 double areaWeight = _params->areaWeight;
00348 double ARWeight = max(1 - areaWeight - wireWeight, 0.0);
00349
00350
00351 double blocksArea = _db->getNodesArea();
00352 double size = in_curr_solution.NUM_BLOCKS;
00353
00354 double currTime = _params->startTime;
00355
00356
00357 const double reqdAR = _params->reqdAR;
00358
00359
00360
00361
00362
00363 const double real_reqdArea = blocksArea * (1+(_params->maxWS/100.0));
00364 const double real_reqdWidth = sqrt(real_reqdArea*reqdAR);
00365 const double real_reqdHeight = real_reqdWidth / reqdAR;
00366
00367
00368
00369
00370
00371
00372 int move = UNINITIALIZED;
00373 int count = 0;
00374 int prev_move = UNINITIALIZED;
00375
00376 unsigned int timeChangeCtr = 0;
00377 unsigned int moveSelect = UNSIGNED_UNINITIALIZED;
00378 unsigned int iter = UNSIGNED_UNINITIALIZED;
00379 unsigned int masterMoveSel = 0;
00380
00381 bool moveAccepted = false;
00382 bool brokeFromLoop = false;
00383
00384 double unit=0, total=seconds, percent=1;
00385 unsigned int moves = 2000;
00386
00387 Timer looptm;
00388 looptm.stop();
00389
00390 _db->updatePlacement(const_cast<vector<double>&>(in_curr_solution.xloc()),
00391 const_cast<vector<double>&>(in_curr_solution.yloc()));
00392 double currHPWL = _db->evalHPWL();
00393 while(currTime > _params->timeCool || budgetTime)
00394 {
00395 brokeFromLoop = false;
00396 iter = 0;
00397
00398
00399
00400
00401 do
00402 {
00403
00404
00405
00406 if (budgetTime)
00407 {
00408 if (count==0)
00409 {
00410 looptm.start(0.0);
00411 }
00412 else if (count==1000)
00413 {
00414 looptm.stop();
00415 unit = looptm.getUserTime() / 1000;
00416 if (unit == 0)
00417 {
00418 unit = 10e-6;
00419 }
00420 seconds -= looptm.getUserTime();
00421 cout << int(seconds/unit) << " moves left with "
00422 << (unit*1000000) <<" micro seconds per move.\n";
00423 moves = unsigned(seconds/unit/125);
00424 }
00425 else if (count > 1000)
00426 {
00427 seconds -= unit;
00428 if (seconds <= 0)
00429 {
00430 cout << "TimeOut" << endl;
00431 return false;
00432 }
00433 }
00434 }
00435 else
00436 {
00437 if (count==0)
00438 {
00439 looptm.start(0.0);
00440 }
00441 else if (count==1000)
00442 {
00443 looptm.stop();
00444 unit = looptm.getUserTime() / 1000;
00445 if (unit == 0)
00446 {
00447 unit = 10e-6;
00448 }
00449 cout << (unit * 1e6) <<" micro seconds per move." << endl;
00450 }
00451 }
00452
00453
00454
00455
00456
00457
00458
00459 double currArea = in_curr_solution.totalArea();
00460 double currHeight = in_curr_solution.totalHeight();
00461 double currWidth = in_curr_solution.totalWidth();
00462 double currAR = currWidth / currHeight;
00463
00464 ++count;
00465 ++iter;
00466 prev_move = move;
00467
00468
00469 if (_params->softBlocks && currTime < 50)
00470 masterMoveSel = rand() % 1000;
00471 moveSelect = rand() % 1000;
00472
00473
00474 int indexOrient = UNSIGNED_UNINITIALIZED;
00475 parquetfp::ORIENT newOrient = parquetfp::N;
00476 parquetfp::ORIENT oldOrient = parquetfp::N;
00477
00478 int index = UNINITIALIZED;
00479 double newWidth = UNINITIALIZED;
00480 double newHeight = UNINITIALIZED;
00481
00482 if(_params->softBlocks && masterMoveSel == 1)
00483 move = packSoftBlocks(2);
00484
00485 else if(_params->softBlocks && masterMoveSel > 950)
00486 move = makeSoftBlMove(index, newWidth, newHeight);
00487
00488 else if (((reqdAR-currAR)/reqdAR > 0.00005 ||
00489 (currAR-reqdAR)/reqdAR > 0.00005) &&
00490 (timeChangeCtr % 4) == 0 && reqdAR != FREE_OUTLINE)
00491 {
00492 move = makeMove(indexOrient, newOrient, oldOrient);
00493
00494 }
00495
00496 else if (false && !minWL &&
00497 currTime < 30 && (timeChangeCtr % 5) == 0)
00498 move = compactBlocks();
00499
00500 else if (moveSelect < 150)
00501 {
00502 if (reqdAR != FREE_OUTLINE)
00503 move = makeARMove();
00504 else
00505 move = makeMove(indexOrient, newOrient, oldOrient);
00506 }
00507
00508 else if (moveSelect < 300 && minWL)
00509 {
00510 if (reqdAR != FREE_OUTLINE)
00511 move = makeARWLMove();
00512 else
00513 move = makeHPWLMove();
00514 }
00515
00516 else
00517 move = makeMove(indexOrient, newOrient, oldOrient);
00518
00519
00520
00521 if (move == REP_SPEC_ORIENT || move == ORIENT)
00522 {
00523
00524 if (minWL)
00525 {
00526 _db->getNodes()->changeOrient(indexOrient, newOrient,
00527 *(_db->getNets()));
00528 }
00529 }
00530
00531
00532 if (move == SOFT_BL)
00533 {
00534 int indexTheta = in_curr_solution.tree[index].orient;
00535 _blockinfo.setBlockDimensions(index,
00536 newWidth, newHeight, indexTheta);
00537 in_next_solution.evaluate(in_curr_solution.tree);
00538
00539 if (minWL)
00540 {
00541 _db->getNodes()->putNodeWidth(index, newWidth);
00542 _db->getNodes()->putNodeHeight(index, newHeight);
00543 }
00544 }
00545
00546
00547 double tempHeight = in_next_solution.totalHeight();
00548 double tempWidth = in_next_solution.totalWidth();
00549 double tempArea = in_next_solution.totalArea();
00550 double tempAR = tempWidth / tempHeight;
00551 double tempHPWL = UNINITIALIZED;
00552
00553
00554
00555
00556
00557 double deltaArea = 0;
00558 double deltaHPWL = 0;
00559 double deltaAR = UNINITIALIZED;
00560 double delta = UNINITIALIZED;
00561
00562
00563 if (currTime > 30)
00564 deltaArea = ((tempArea-currArea)*1.2*_params->timeInit) / blocksArea;
00565 else
00566 deltaArea = ((tempArea-currArea)*1.5*_params->timeInit) / blocksArea;
00567
00568
00569 if (minWL)
00570 {
00571 _db->updatePlacement(const_cast<vector<double>&>(in_next_solution.xloc()),
00572 const_cast<vector<double>&>(in_next_solution.yloc()));
00573
00574 tempHPWL = _db->evalHPWL();
00575 if(currHPWL == 0)
00576 deltaHPWL = 0;
00577 else
00578 {
00579 if(currTime>30)
00580 deltaHPWL = ((tempHPWL-currHPWL)*1.2*_params->timeInit)/currHPWL;
00581 else
00582 deltaHPWL = ((tempHPWL-currHPWL)*1.5*_params->timeInit)/currHPWL;
00583 }
00584 }
00585
00586
00587 delta = deltaArea;
00588 if(reqdAR != FREE_OUTLINE)
00589 {
00590 deltaAR = ((tempAR - reqdAR)*(tempAR - reqdAR) -
00591 (currAR - reqdAR)*(currAR - reqdAR)) * 20 * _params->timeInit;
00592
00593 if(minWL)
00594 delta = (areaWeight * deltaArea +
00595 wireWeight * deltaHPWL +
00596 ARWeight * deltaAR);
00597 else
00598 delta = ((areaWeight + wireWeight/2.0) * deltaArea +
00599 (ARWeight + wireWeight/2.0) * deltaAR);
00600
00601 }
00602 else if(minWL)
00603 {
00604 delta = ((areaWeight + ARWeight/2.0)*deltaArea +
00605 (wireWeight + ARWeight/2.0)*deltaHPWL);
00606 }
00607 else
00608 delta = deltaArea;
00609
00610
00611
00612
00613
00614
00615 if (delta < 0 || move == MISC)
00616 moveAccepted = true;
00617 else if (currTime > _params->timeCool)
00618
00619 {
00620 double ran = rand() % 10000;
00621 double r = double(ran) / 9999;
00622 if (r < exp(-1*delta/currTime))
00623 moveAccepted = true;
00624 else
00625 moveAccepted = false;
00626 }
00627 else
00628 moveAccepted = false;
00629
00630
00631 if (moveAccepted && move != MISC)
00632 {
00633 in_curr_solution = in_next_solution;
00634 currHPWL = tempHPWL;
00635 }
00636
00637
00638 if (move == REP_SPEC_ORIENT || move == ORIENT)
00639 {
00640
00641 parquetfp::ORIENT actualOrient =
00642 parquetfp::ORIENT(in_curr_solution.tree[indexOrient].orient);
00643
00644 if (minWL)
00645 _db->getNodes()->changeOrient(indexOrient, actualOrient,
00646 *(_db->getNets()));
00647 }
00648
00649 if (move == SOFT_BL)
00650 {
00651
00652 double actualWidth = in_curr_solution.width(index);
00653 double actualHeight = in_curr_solution.height(index);
00654 int actualTheta = in_curr_solution.tree[index].orient;
00655 _blockinfo.setBlockDimensions(index,
00656 actualWidth, actualHeight,
00657 actualTheta);
00658
00659 if (minWL)
00660 {
00661 _db->getNodes()->putNodeWidth(index, actualWidth);
00662 _db->getNodes()->putNodeHeight(index, actualHeight);
00663 }
00664 }
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702 if (minWL)
00703 {
00704
00705 if(currArea <= real_reqdArea && currHeight <= real_reqdHeight &&
00706 currWidth <= real_reqdWidth && reqdAR != FREE_OUTLINE && currTime < 5)
00707 return true;
00708
00709 if (reqdAR != FREE_OUTLINE && currTime < 5 &&
00710 _params->dontClusterMacros && _params->solveTop)
00711 {
00712 double widthWMacroOnly = _db->getXSizeWMacroOnly();
00713 double heightWMacroOnly = _db->getYSizeWMacroOnly();
00714
00715 if (widthWMacroOnly <= real_reqdWidth &&
00716 heightWMacroOnly <= real_reqdHeight)
00717 return true;
00718 }
00719 }
00720 else
00721 {
00722 if(currArea <= real_reqdArea && currHeight <= real_reqdHeight &&
00723 currWidth <= real_reqdWidth && reqdAR != FREE_OUTLINE)
00724 return true;
00725 }
00726
00727 if (iter >= moves)
00728 break;
00729
00730 #ifdef PARQUET_DEBUG_HAYWARD_ASSERT_BTREEANNEAL
00731
00732 for (int i = 0; i < in_curr_solution.NUM_BLOCKS; i++)
00733 {
00734 if (minWL && (int(in_curr_solution.tree[i].orient) !=
00735 int(_db->getNodes()->getNode(i).getOrient())))
00736 {
00737 cout << "round [" << count << "]: orient of block[" << i << "] is not consistent" << endl;
00738 printf("in_curr_solution:orient %d vs. _db->orient: %d, move: %d",
00739 int(in_curr_solution.tree[i].orient),
00740 int(_db->getNodes()->getNode(i).getOrient()), move);
00741 cin.get();
00742 }
00743
00744 int theta = in_curr_solution.tree[i].orient;
00745 if (theta != int(_physicalOrient[i][theta]))
00746 {
00747 printf("round[%d]: orient of block[%d] is not consistent, in_curr_soln: %d vs phyOrient: %d move: %d\n",
00748 count, i, theta, _physicalOrient[i][theta], move);
00749 cin.get();
00750 }
00751
00752 if (fabs(in_curr_solution.width(i) - blockinfo.currDimensions[i].width[theta]) > 1e-6)
00753 {
00754 printf("round[%d]: width of block[%d] is not consistent. in_curr_soln: %.2f vs. blockinfo: %.2f move: %d prevMove: %d\n",
00755 count, i, in_curr_solution.width(i), blockinfo.currDimensions[i].width[theta], move, prev_move);
00756 printf("round[%d]: oldWidth: %.2f oldHeight: %.2f newWidth: %.2f newHeight: %.2f moveAccepted: %s\n",
00757 count, -1.0, -1.0, newWidth, newHeight, (moveAccepted)? "T" : "F");
00758 cin.get();
00759 }
00760
00761 if (fabs(in_curr_solution.height(i) - blockinfo.currDimensions[i].height[theta]) > 1e-6)
00762 {
00763 printf("round[%d]: height of block[%d] is not consistent. in_curr_soln: %.2f vs. blockinfo: %.2f move: %d prevMove: %d\n",
00764 count, i, in_curr_solution.height(i), blockinfo.currDimensions[i].height[theta], move, prev_move);
00765 printf("round[%d]: oldWidth: %.2f oldHeight: %.2f newWidth: %.2f newHeight: %.2f moveAccepted: %s\n",
00766 count, -1.0, -1.0, newWidth, newHeight, (moveAccepted)? "T" : "F");
00767 cin.get();
00768 }
00769
00770 if (minWL && fabs(in_curr_solution.width(i) - _db->getNodes()->getNodeWidth(i)) > 1e-6)
00771 {
00772 printf("round[%d]: width of block[%d] is not consistent. in_curr_solution: %.2f vs._db: %.2f move: %d\n",
00773 count, i, in_curr_solution.width(i), _db->getNodes()->getNodeWidth(i), move);
00774 cin.get();
00775 }
00776
00777 if (in_curr_solution.width(i) < 1e-10 ||
00778 in_curr_solution.height(i) < 1e-10)
00779 {
00780 printf("round[%d]: width of block[%d]: %f height: %f move: %d\n",
00781 count, i, in_curr_solution.width(i), in_curr_solution.height(i), move);
00782 cin.get();
00783 }
00784 }
00785
00786 #endif
00787 }
00788 while (iter < 4*size || budgetTime);
00789
00790
00791
00792
00793
00794
00795 double alpha = UNINITIALIZED;
00796 ++timeChangeCtr;
00797 if (budgetTime)
00798 {
00799 percent = seconds/total;
00800
00801 if (percent < 0.66666 && percent > 0.33333)
00802 alpha = 0.9;
00803 else if (percent < 0.33333 && percent > 0.16666)
00804 alpha = 0.95;
00805 else if (percent < 0.16666 && percent > 0.06666)
00806 alpha = 0.96;
00807 else if(percent <.06666 && percent >.00333)
00808 alpha = 0.8;
00809 else if(percent <.00333 && percent >.00003)
00810 alpha = 0.98;
00811 else
00812 alpha = 0.85;
00813 }
00814 else
00815 {
00816 if (currTime < 2000 && currTime > 1000)
00817 alpha = 0.9;
00818 else if (currTime < 1000 && currTime > 500)
00819 alpha = 0.95;
00820 else if (currTime < 500 && currTime > 200)
00821 alpha = 0.96;
00822 else if (currTime < 200 && currTime > 10)
00823 alpha = 0.96;
00824 else if (currTime < 15 && currTime > 0.1)
00825 alpha = 0.98;
00826 else
00827 alpha = 0.85;
00828 }
00829 currTime *= alpha;
00830
00831 if (brokeFromLoop)
00832 break;
00833 }
00834
00835 cout << "NumMoves attempted: " << count << endl;
00836 if (reqdAR != FREE_OUTLINE)
00837 return false;
00838 else
00839 return true;
00840 }
00841
00842 void BTreeAreaWireAnnealer::takePlfromDB()
00843 {
00844 Pl2BTree converter(_db->getXLocs(),
00845 _db->getYLocs(),
00846 _db->getNodeWidths(),
00847 _db->getNodeHeights(),
00848 Pl2BTree::TCG);
00849 in_curr_solution.evaluate(converter.btree());
00850 in_next_solution = in_curr_solution;
00851 }
00852
00853 void BTreeAreaWireAnnealer::compactSoln()
00854 {
00855 BTreeCompactor compactor(in_curr_solution);
00856
00857 int round = 0;
00858 int numBlkChange = compactor.compact();
00859 double lastArea = in_curr_solution.totalArea();
00860 double currArea = compactor.totalArea();
00861 while (numBlkChange > 0)
00862 {
00863 printf("round[%d] %d blks moved, area: %.2f -> %.2f\n",
00864 round, numBlkChange, lastArea, currArea);
00865
00866 numBlkChange = compactor.compact();
00867 round++;
00868 lastArea = currArea;
00869 currArea = compactor.totalArea();
00870 }
00871 printf("round[%d] %d blks moved, area: %.2f -> %.2f\n",
00872 round, numBlkChange, lastArea, currArea);
00873
00874 in_curr_solution = compactor;
00875 DBfromSoln(in_curr_solution);
00876 }
00877
00878 int BTreeAreaWireAnnealer::makeMove(int& indexOrient,
00879 parquetfp::ORIENT& newOrient,
00880 parquetfp::ORIENT& oldOrient)
00881 {
00882 BTree::MoveType move = get_move();
00883 indexOrient = UNSIGNED_UNINITIALIZED;
00884 newOrient = parquetfp::N;
00885 oldOrient = parquetfp::N;
00886 switch(move)
00887 {
00888 case BTree::SWAP:
00889 perform_swap();
00890 return 1;
00891
00892 case BTree::ROTATE:
00893 perform_rotate(indexOrient, newOrient, oldOrient);
00894 return int(REP_SPEC_ORIENT);
00895
00896 case BTree::MOVE:
00897 perform_move();
00898 return 3;
00899
00900 default:
00901 cout << "ERROR: invalid move specified in makeMove()" << endl;
00902 exit(1);
00903 }
00904 return MISC;
00905 }
00906
00907 int BTreeAreaWireAnnealer::makeMoveSlacks()
00908 {
00909 int movedir = rand() % 100;
00910 int threshold = 50;
00911 bool horizontal = (movedir < threshold);
00912
00913 makeMoveSlacksCore(horizontal);
00914
00915 static int total = 0;
00916 static int numHoriz = 0;
00917
00918 total++;
00919 numHoriz += ((horizontal)? 1 : 0);
00920
00921 if (total % 1000 == 0)
00922 cout << "total: " << total << "horiz: " << numHoriz << endl;
00923 return SLACKS_MOVE;
00924 }
00925
00926 int BTreeAreaWireAnnealer::makeARMove()
00927 {
00928 double currWidth = in_curr_solution.totalWidth();
00929 double currHeight = in_curr_solution.totalHeight();
00930 double currAR = currWidth / currHeight;
00931
00932 const double reqdAR = _params->reqdAR;
00933 bool horizontal = currAR > reqdAR;
00934
00935 makeMoveSlacksCore(horizontal);
00936 return AR_MOVE;
00937 }
00938
00939 void BTreeAreaWireAnnealer::makeMoveSlacksCore(bool horizontal)
00940 {
00941 _slackEval->evaluateSlacks(in_curr_solution);
00942
00943 vector<int> indices_sorted;
00944 const vector<double>& slacks = (horizontal)?
00945 _slackEval->xSlack() : _slackEval->ySlack();
00946
00947 sort_slacks(slacks, indices_sorted);
00948
00949 int blocknum = in_curr_solution.NUM_BLOCKS;
00950 int range = int(ceil(blocknum / 5.0));
00951
00952 int operand_ptr = rand() % range;
00953 int operand = indices_sorted[operand_ptr];
00954 while (operand_ptr > 0 && slacks[operand] > 0)
00955 {
00956 operand_ptr--;
00957 operand = indices_sorted[operand_ptr];
00958 }
00959
00960 int target_ptr = blocknum - 1 - (rand() % range);
00961 int target = indices_sorted[target_ptr];
00962 while (target_ptr < (blocknum-1) && slacks[target] == 0)
00963 {
00964 target_ptr++;
00965 target = indices_sorted[target_ptr];
00966 }
00967
00968 in_next_solution = in_curr_solution;
00969 in_next_solution.move(operand, target, horizontal);
00970 }
00971
00972 int BTreeAreaWireAnnealer::makeHPWLMove()
00973 {
00974 int size = in_curr_solution.NUM_BLOCKS;
00975 int operand = rand() % size;
00976 int target = UNSIGNED_UNINITIALIZED;
00977
00978 vector<int> searchBlocks;
00979 locateSearchBlocks(operand, searchBlocks);
00980
00981 if (searchBlocks.size() > 0)
00982 {
00983 int temp = rand() % searchBlocks.size();
00984 target = searchBlocks[temp];
00985 }
00986 else
00987 {
00988 do
00989 target = rand() % size;
00990 while(target == operand);
00991 }
00992
00993 bool leftChild = bool(rand() % 2);
00994 in_next_solution = in_curr_solution;
00995 in_next_solution.move(operand, target, leftChild);
00996 return HPWL;
00997 }
00998
00999 int BTreeAreaWireAnnealer::makeARWLMove()
01000 {
01001 _slackEval->evaluateSlacks(in_curr_solution);
01002
01003 const double reqdAR = _params->reqdAR;
01004 const double currAR =
01005 in_curr_solution.totalWidth() / in_curr_solution.totalHeight();
01006 const bool horizontal = currAR > reqdAR;
01007 const vector<double>& slacks = (horizontal)?
01008 _slackEval->xSlack() : _slackEval->ySlack();
01009
01010 vector<int> indices_sorted;
01011 sort_slacks(slacks, indices_sorted);
01012
01013 int blocknum = in_curr_solution.NUM_BLOCKS;
01014 int range = int(ceil(blocknum / 5.0));
01015
01016 int operand_ptr = rand() % range;
01017 int operand = indices_sorted[operand_ptr];
01018 while (operand_ptr > 0 && slacks[operand] > 0)
01019 {
01020 operand_ptr--;
01021 operand = indices_sorted[operand_ptr];
01022 }
01023
01024 vector<int> searchBlocks;
01025 locateSearchBlocks(operand, searchBlocks);
01026
01027 int target = UNSIGNED_UNINITIALIZED;
01028 double maxSlack = -1;
01029 if (searchBlocks.size() == 0)
01030 {
01031 do
01032 target = rand() % blocknum;
01033 while(target == operand);
01034 }
01035 else
01036 {
01037 for (unsigned int i = 0; i < searchBlocks.size(); i++)
01038 {
01039 int thisBlk = searchBlocks[i];
01040 if (slacks[thisBlk] > maxSlack)
01041 {
01042 maxSlack = slacks[thisBlk];
01043 target = thisBlk;
01044 }
01045 }
01046 }
01047
01048 in_next_solution = in_curr_solution;
01049 in_curr_solution.move(operand, target, horizontal);
01050 return ARWL;
01051 }
01052
01053 int BTreeAreaWireAnnealer::makeSoftBlMove(int& index,
01054 double& newWidth,
01055 double& newHeight)
01056 {
01057 static const int NOT_FOUND = NOT_FOUND;
01058 _slackEval->evaluateSlacks(in_curr_solution);
01059
01060 int moveDir = rand() % 2;
01061 bool horizontal = (moveDir%2 == 0);
01062 index = getSoftBlIndex(horizontal);
01063
01064 if (index == NOT_FOUND)
01065 index = getSoftBlIndex(!horizontal);
01066
01067 if (index != NOT_FOUND)
01068 {
01069 return getSoftBlNewDimensions(index, newWidth, newHeight);
01070 }
01071 else
01072 {
01073 newWidth = NOT_FOUND;
01074 newHeight = NOT_FOUND;
01075 return MISC;
01076 }
01077 }
01078
01079 int BTreeAreaWireAnnealer::getSoftBlIndex(bool horizontal) const
01080 {
01081 static const int NOT_FOUND = NOT_FOUND;
01082 const int blocknum = in_curr_solution.NUM_BLOCKS;
01083 const vector<double>& slacks = (horizontal)?
01084 _slackEval->xSlack() : _slackEval->ySlack();
01085
01086 const vector<double>& orth_slacks = (horizontal)?
01087 _slackEval->ySlack() : _slackEval->xSlack();
01088
01089 vector<int> indices_sorted;
01090 sort_slacks(slacks, indices_sorted);
01091
01092 int operand = NOT_FOUND;
01093 for (int i = 0; (i < blocknum) && (operand == NOT_FOUND); i++)
01094 {
01095 int index = indices_sorted[i];
01096 if (blockinfo.blockARinfo[index].isSoft)
01097 {
01098 int theta = in_curr_solution.tree[index].orient;
01099 double minAR = blockinfo.blockARinfo[index].minAR[theta];
01100 double maxAR = blockinfo.blockARinfo[index].maxAR[theta];
01101
01102 double currWidth = in_curr_solution.width(index);
01103 double currHeight = in_curr_solution.height(index);
01104 double currAR = currWidth / currHeight;
01105
01106 bool adjustable = (horizontal)?
01107 (currAR > minAR) : (currAR < maxAR);
01108
01109 if (orth_slacks[index] > 0 && adjustable)
01110 operand = index;
01111 }
01112 }
01113 return operand;
01114 }
01115
01116 int BTreeAreaWireAnnealer::getSoftBlNewDimensions(int index,
01117 double& newWidth,
01118 double& newHeight) const
01119 {
01120 if (blockinfo.blockARinfo[index].isSoft)
01121 {
01122 double origWidth = in_curr_solution.width(index);
01123 double origHeight = in_curr_solution.height(index);
01124 double indexArea = blockinfo.blockARinfo[index].area;
01125
01126 int theta = in_curr_solution.tree[index].orient;
01127 double minAR = blockinfo.blockARinfo[index].minAR[theta];
01128 double maxAR = blockinfo.blockARinfo[index].maxAR[theta];
01129
01130 double maxWidth = sqrt(indexArea * maxAR);
01131 double maxHeight = sqrt(indexArea / minAR);
01132
01133 double indexSlackX = _slackEval->xSlack()[index];
01134 double indexSlackY = _slackEval->ySlack()[index];
01135 if (indexSlackX > indexSlackY)
01136 {
01137 newWidth = min(origWidth+indexSlackX, maxWidth);
01138 newHeight = indexArea / newWidth;
01139 }
01140 else
01141 {
01142 newHeight = min(origHeight+indexSlackY, maxHeight);
01143 newWidth = indexArea / newHeight;
01144 }
01145 return SOFT_BL;
01146 }
01147 else
01148 return NOOP;
01149 }
01150
01151 int BTreeAreaWireAnnealer::packSoftBlocks(int numIter)
01152 {
01153 const int NUM_BLOCKS = in_curr_solution.NUM_BLOCKS;
01154 for (int iter = 0; iter < numIter; iter++)
01155 {
01156 bool horizontal = (iter % 2 == 0);
01157 _slackEval->evaluateSlacks(in_curr_solution);
01158
01159 const vector<double>& slacks = (horizontal)?
01160 _slackEval->xSlack() : _slackEval->ySlack();
01161
01162 vector<int> indices_sorted;
01163 sort_slacks(slacks, indices_sorted);
01164 for (int i = 0; i < NUM_BLOCKS; i++)
01165 {
01166 int index = indices_sorted[i];
01167 double origWidth = in_curr_solution.width(index);
01168 double origHeight = in_curr_solution.height(index);
01169
01170 double newWidth, newHeight;
01171 int softDecision = makeIndexSoftBlMove(index, newWidth, newHeight);
01172
01173 if (softDecision == SOFT_BL)
01174 {
01175
01176 int theta = in_curr_solution.tree[index].orient;
01177 _blockinfo.setBlockDimensions(index, newWidth, newHeight, theta);
01178
01179 in_next_solution.evaluate(in_curr_solution.tree);
01180
01181 double origTotalArea = in_curr_solution.totalArea();
01182 double newTotalArea = in_next_solution.totalArea();
01183 if (newTotalArea < origTotalArea)
01184 {
01185 in_curr_solution = in_next_solution;
01186 if (_params->minWL)
01187 {
01188 _db->getNodes()->putNodeWidth(index, newWidth);
01189 _db->getNodes()->putNodeHeight(index, newHeight);
01190 }
01191 }
01192 else
01193 {
01194 _blockinfo.setBlockDimensions(index, origWidth, origHeight, theta);
01195 }
01196 }
01197 }
01198 }
01199 return MISC;
01200 }
01201
01202 void BTreeAreaWireAnnealer::locateSearchBlocks(int operand,
01203 vector<int>& searchBlocks)
01204 {
01205 int size = in_curr_solution.NUM_BLOCKS;
01206 vector<bool> seenBlocks(size, false);
01207 seenBlocks[operand] = true;
01208 double unitRadiusSize = max(in_curr_solution.totalWidth(),
01209 in_curr_solution.totalHeight());
01210 unitRadiusSize /= sqrt(double(size));
01211
01212 vector<double>& xloc = const_cast<vector<double>&>(in_curr_solution.xloc());
01213 vector<double>& yloc = const_cast<vector<double>&>(in_curr_solution.yloc());
01214 parquetfp::Point idealLoc(_analSolve->getOptLoc(operand, xloc, yloc));
01215
01216
01217 int searchRadiusNum = int(ceil(size / 5.0));
01218 double searchRadius = 0;
01219 for(int i = 0; ((i < searchRadiusNum) &&
01220 (searchBlocks.size() < unsigned(searchRadiusNum))); ++i)
01221 {
01222 searchRadius += unitRadiusSize;
01223 for(int j = 0; ((j < size) &&
01224 (searchBlocks.size() < unsigned(searchRadiusNum))); ++j)
01225 {
01226 if (!seenBlocks[j])
01227 {
01228 double xDist = xloc[j] - idealLoc.x;
01229 double yDist = yloc[j] - idealLoc.y;
01230 double distance = sqrt(xDist*xDist + yDist*yDist);
01231 if(distance < searchRadius)
01232 {
01233 seenBlocks[j] = true;
01234 searchBlocks.push_back(j);
01235 }
01236 }
01237 }
01238 }
01239 }
01240
01241 void BTreeAreaWireAnnealer::GenerateRandomSoln(BTree& soln,
01242 int blocknum) const
01243 {
01244 vector<int> tree_bits;
01245 int balance = 0;
01246 int num_zeros = 0;
01247 for (int i = 0; i < 2*blocknum; i++)
01248 {
01249 bool assigned = false;
01250 double rand_num = double(rand()) / (RAND_MAX+1.0);
01251 double threshold;
01252
01253 if (balance == 0)
01254 threshold = 1;
01255 else if (num_zeros == blocknum)
01256 threshold = 0;
01257 else
01258 threshold = 1;
01259
01260 if (rand_num >= threshold)
01261 {
01262 tree_bits.push_back(1);
01263 balance--;
01264 assigned = true;
01265 }
01266 else
01267 {
01268 tree_bits.push_back(0);
01269 balance++;
01270 num_zeros++;
01271 assigned = true;
01272 }
01273 }
01274
01275 vector<int> tree_perm;
01276 tree_perm.resize(blocknum);
01277 for (int i = 0; i < blocknum; i++)
01278 tree_perm[i] = i;
01279 random_shuffle(tree_perm.begin(), tree_perm.end());
01280
01281 vector<int> tree_perm_inverse(blocknum);
01282 for (int i = 0; i < blocknum; i++)
01283 tree_perm_inverse[tree_perm[i]] = i;
01284
01285 vector<int> tree_orient(blocknum);
01286 for (int i = 0; i < blocknum; i++)
01287 {
01288 int rand_num = int(8 * (double(rand()) / (RAND_MAX + 1.0)));
01289 rand_num = _physicalOrient[i][rand_num];
01290
01291 tree_orient[tree_perm_inverse[i]] = rand_num;
01292 }
01293
01294 soln.evaluate(tree_bits, tree_perm, tree_orient);
01295 }
01296