├── BBox.cpp ├── BBox.h ├── DataPlace.cpp ├── DataPlace.h ├── Makefile ├── README.md ├── SimAnneal.cpp ├── SimAnneal.h ├── UCLApack-43-040113.tar.gz_ ├── paramproc.cpp ├── paramproc.h ├── simulated annealing.cpp ├── visualization.cpp └── visualization.h /BBox.cpp: -------------------------------------------------------------------------------- 1 | #include "BBox.h" 2 | #include 3 | 4 | BBox::BBox(DataPlace& rbplace, bool forViewer) 5 | : rb(rbplace), 6 | xMin(DBL_MAX), 7 | yMin(DBL_MAX), 8 | xMax(-DBL_MAX), 9 | yMax(-DBL_MAX) { 10 | vector& _rw = rb.rows; 11 | 12 | vector::iterator termMinY, termMaxY; 13 | vector::iterator termMinX, termMaxX; 14 | if (!rb.terminals.empty()) { 15 | tie(termMinY, termMaxY) = 16 | minmax_element(rb.terminals.begin(), rb.terminals.end(), 17 | [](terminal const& s1, terminal const& s2) { 18 | return s1.pos_y < s2.pos_y; 19 | }); 20 | 21 | tie(termMinX, termMaxX) = 22 | minmax_element(rb.terminals.begin(), rb.terminals.end(), 23 | [](terminal const& s1, terminal const& s2) { 24 | return s1.pos_x < s2.pos_x; 25 | }); 26 | } 27 | 28 | double CoreXmin = _rw.begin()->coord_x; 29 | double CoreYmin = _rw.begin()->coord_y; 30 | double CoreXmax = 31 | CoreXmin + (_rw.begin()->num_sites) * (_rw.begin()->site_sp); 32 | double CoreYmax = CoreYmin + rb.NumRows * _rw.begin()->h; 33 | 34 | if (!rb.terminals.empty() && forViewer) { 35 | yMin = (termMinY->pos_y > CoreYmin) ? CoreYmin - _rw.begin()->site_sp 36 | : termMinY->pos_y; 37 | yMax = (termMaxY->pos_y > CoreYmax) ? termMaxY->pos_y + termMaxX->h 38 | : CoreYmax + _rw.begin()->site_sp; 39 | xMin = (termMinX->pos_x > CoreXmin) ? CoreXmin - _rw.begin()->site_sp 40 | : termMinX->pos_x; 41 | xMax = (termMaxX->pos_x > CoreXmax) ? termMaxX->pos_x + termMaxX->w 42 | : CoreXmax + _rw.begin()->site_sp; 43 | } else if (rb.terminals.empty() && forViewer) { 44 | yMin = CoreYmin - _rw.begin()->site_sp; 45 | xMin = CoreXmin - _rw.begin()->site_sp; 46 | yMax = CoreYmax + _rw.begin()->site_sp; 47 | xMax = CoreXmax + _rw.begin()->site_sp; 48 | } else { 49 | yMin = CoreYmin; 50 | xMin = CoreXmin; 51 | yMax = CoreYmax; 52 | xMax = CoreXmax; 53 | } 54 | } -------------------------------------------------------------------------------- /BBox.h: -------------------------------------------------------------------------------- 1 | #ifndef _BBOX_H_ 2 | #define _BBOX_H_ 3 | 4 | #include "DataPlace.h" 5 | 6 | class BBox { 7 | public: 8 | double xMin; 9 | double yMin; 10 | double xMax; 11 | double yMax; 12 | 13 | BBox(DataPlace& rbplace, bool forViewer = false); 14 | 15 | double getHeight() const { return fabs(yMax - yMin); } 16 | double getWidth() const { return fabs(xMax - xMin); } 17 | 18 | private: 19 | DataPlace& rb; 20 | }; 21 | 22 | #endif -------------------------------------------------------------------------------- /DataPlace.cpp: -------------------------------------------------------------------------------- 1 | // DataPlace.cpp 2 | 3 | #include "DataPlace.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | DataPlace::DataPlace() : LengthNodes(0), heightSC(0) { 11 | srand((unsigned int)time(NULL)); 12 | } 13 | 14 | void DataPlace::Start(const char* p_aux) { 15 | parseAuxFile(p_aux); 16 | parser(); 17 | heightSC = rows[0].h; 18 | } 19 | 20 | void DataPlace::parseAuxFile(const char* p_aux) { 21 | path_nodes = new char[15]; 22 | path_nets = new char[15]; 23 | path_pl = new char[15]; 24 | path_scl = new char[15]; 25 | char temp[50]; 26 | 27 | ifstream f_aux(p_aux, ios::in); 28 | if (!f_aux) { 29 | cerr << "Ошибка чтения файла .aux" << endl; 30 | system("pause"); 31 | exit(1); 32 | } else { 33 | f_aux.ignore(100, ':'); 34 | f_aux >> path_nodes; 35 | f_aux >> path_nets; 36 | f_aux >> temp; 37 | f_aux >> path_pl; 38 | f_aux >> path_scl; 39 | } 40 | f_aux.close(); 41 | } 42 | 43 | void DataPlace::parseNodes() { 44 | cout << "Parse .nodes ... | "; 45 | char temp[50]; 46 | ifstream f_nd(path_nodes, ios::in); 47 | if (!f_nd) { 48 | cerr << "Ошибка чтения файла .nodes" << endl; 49 | system("pause"); 50 | exit(1); 51 | } 52 | 53 | while (f_nd) { 54 | f_nd >> temp; 55 | if (!strcmp(temp, "NumNodes")) { 56 | f_nd.ignore(50, ':'); 57 | f_nd >> NumNodes; 58 | f_nd.get(); 59 | f_nd.ignore(50, ':'); 60 | f_nd >> NumTerminals; 61 | f_nd.ignore(50, '\n'); 62 | f_nd >> temp; 63 | string name; 64 | double w, h; 65 | for (int i = 0; i < NumNodes; i++) { 66 | name = temp; 67 | f_nd >> w; 68 | f_nd >> h; 69 | f_nd >> temp; 70 | if (!strcmp(temp, "terminal") || !strcmp(temp, "terminal_NI")) { 71 | terminal tr; 72 | tr.name = name; 73 | tr.w = w; 74 | tr.h = h; 75 | terminals.push_back(tr); 76 | f_nd.ignore(50, '\n'); 77 | f_nd >> temp; 78 | } else { 79 | node nd; 80 | nd.name = name; 81 | nd.w = w; 82 | nd.h = h; 83 | // f_nd.seekg(20,ios::cur); 84 | nodes.push_back(nd); 85 | nd.i = nodes.size() - 1; 86 | // f_nd.getline(temp,30); 87 | LengthNodes += w; 88 | } 89 | } 90 | break; 91 | } 92 | } 93 | f_nd.close(); 94 | 95 | NumCells = NumNodes - NumTerminals; 96 | } 97 | 98 | void DataPlace::parseNets() { 99 | cout << "Parse .nets ... | "; 100 | char temp[50]; 101 | ifstream f_nt(path_nets, ios::in); 102 | if (!f_nt) { 103 | cerr << "Ошибка чтения файла .nets" << endl; 104 | system("pause"); 105 | exit(1); 106 | } 107 | 108 | while (f_nt) { 109 | f_nt >> temp; 110 | if (!strcmp(temp, "NumNets")) { 111 | f_nt.ignore(10, ':'); 112 | f_nt >> NumNets; 113 | f_nt.get(); 114 | f_nt.ignore(50, ':'); 115 | f_nt >> NumPins; 116 | for (int k = 0; k < NumNets; k++) { 117 | f_nt >> temp; 118 | if (!strcmp(temp, "NetDegree")) { 119 | unsigned n; 120 | net nt; 121 | f_nt.ignore(10, ':'); 122 | f_nt >> n; 123 | f_nt.ignore(50, '\n'); 124 | for (int i = 0; i < n; i++) { 125 | string t; 126 | f_nt >> t; 127 | bool finded = false; 128 | 129 | for (int j = 0; j < (NumCells); j++) 130 | if (nodes[j].name == t) { 131 | finded = true; 132 | nt.ls.push_back(&nodes[j]); 133 | nodes[j].nets_of_nodes.push_back(nets.size()); 134 | break; 135 | } 136 | 137 | if (!finded) { 138 | for (int j = 0; j < NumTerminals; j++) 139 | if (terminals[j].name == t) { 140 | nt.ls.push_back(&terminals[j]); 141 | terminals[j].nets_of_nodes.push_back( 142 | nets.size()); 143 | break; 144 | } 145 | } 146 | f_nt.ignore(50, '\n'); 147 | } 148 | nets.push_back(nt); 149 | } 150 | } 151 | } 152 | } 153 | f_nt.close(); 154 | } 155 | 156 | void DataPlace::parseScl() { 157 | cout << "Parse .scl ... | "; 158 | char temp[50]; 159 | ifstream f_scl(path_scl, ios::in); 160 | if (!f_scl) { 161 | cerr << "Ошибка чтения файла .scl" << endl; 162 | system("pause"); 163 | exit(1); 164 | } 165 | 166 | while (f_scl) { 167 | f_scl >> temp; 168 | if (!strcmp(_strlwr(temp), "numrows")) { 169 | f_scl.ignore(10, ':'); 170 | f_scl >> NumRows; 171 | for (int i = 0; i < NumRows; i++) { 172 | row rw; 173 | f_scl.ignore(50, ':'); 174 | f_scl >> rw.coord_y; 175 | f_scl.ignore(50, ':'); 176 | f_scl >> rw.h; 177 | f_scl.ignore(50, ':'); 178 | f_scl.ignore(50, ':'); 179 | f_scl >> rw.site_sp; 180 | f_scl.ignore(50, ':'); 181 | f_scl.ignore(50, ':'); 182 | f_scl.ignore(50, ':'); 183 | f_scl >> rw.coord_x; 184 | f_scl.ignore(50, ':'); 185 | f_scl >> rw.num_sites; 186 | rows.push_back(rw); 187 | } 188 | break; 189 | } 190 | } 191 | f_scl.close(); 192 | } 193 | 194 | void DataPlace::parsePl() { 195 | cout << "Parse .pl ... "; 196 | ifstream f_pl(path_pl, ios::in); 197 | if (!f_pl) { 198 | cerr << "Ошибка чтения файла .pl" << endl; 199 | system("pause"); 200 | exit(1); 201 | } 202 | 203 | string s; 204 | while (getline(f_pl, s)) { 205 | stringstream ss(s); 206 | vector words(5); 207 | 208 | for (int i = 0; i < 5; i++) ss >> words[i]; 209 | 210 | if (words[3] == ":") { 211 | bool finded = false; 212 | 213 | for (int j = 0; j < NumCells; j++) 214 | if (nodes[j].name == words[0]) { 215 | finded = true; 216 | nodes[j].pos_x = stoi(words[1]); 217 | nodes[j].pos_y = stoi(words[2]); 218 | break; 219 | } 220 | 221 | if (!finded) { 222 | for (int j = 0; j < NumTerminals; j++) 223 | if (terminals[j].name == words[0]) { 224 | terminals[j].pos_x = stoi(words[1]); 225 | terminals[j].pos_y = stoi(words[2]); 226 | break; 227 | } 228 | } 229 | } 230 | } 231 | 232 | f_pl.close(); 233 | } 234 | 235 | void DataPlace::parser() { 236 | cout << " << Parser... >> " << endl; 237 | cout << " [ "; 238 | parseNodes(); 239 | parseNets(); 240 | parseScl(); 241 | parsePl(); 242 | cout << " ] " << endl; 243 | cout << endl; 244 | } 245 | 246 | void DataPlace::print_nodes() { 247 | cout << "Список нодов:" << endl; 248 | for (int i = 0; i < (NumNodes - NumTerminals); i++) { 249 | cout << "Нод " << nodes[i].name << ": номера связей ["; 250 | for (int j = 0; j < nodes[i].nets_of_nodes.size(); j++) 251 | cout << " " << nodes[i].nets_of_nodes[j] + 1; 252 | cout << " ]" << endl; 253 | } 254 | cout << endl; 255 | for (int i = 0; i < NumTerminals; i++) { 256 | cout << "Терминал " << terminals[i].name << endl; 257 | } 258 | } 259 | 260 | void DataPlace::print_nets() { 261 | cout << "Список цепей:" << endl; 262 | for (int i = 0; i < NumNets; i++) { 263 | cout << "Цепь " << i + 1 << ": {"; 264 | for (int j = 0; j < nets[i].ls.size(); j++) 265 | cout << " " << nets[i].ls[j]->name; 266 | cout << " }" << endl; 267 | } 268 | cout << endl; 269 | } 270 | 271 | void DataPlace::print_scl() { 272 | cout << "Список строк:" << endl; 273 | for (int i = 0; i < NumRows; i++) { 274 | cout << "Row " << i + 1 << endl; 275 | cout << "\t coordinate: " << rows[i].coord_y << endl; 276 | cout << "\t height: " << rows[i].h << endl; 277 | cout << "\t sitespacing: " << rows[i].site_sp << endl; 278 | cout << "\t subrowOrigin: " << rows[i].coord_x << endl; 279 | cout << "\t numsites: " << rows[i].num_sites << endl; 280 | } 281 | cout << endl; 282 | } 283 | 284 | void DataPlace::print_pl() { 285 | cout << "Список координат нодов:" << endl; 286 | 287 | for (int i = 0; i < NumNodes - NumTerminals; i++) { 288 | cout << nodes[i].name << " : " << nodes[i].pos_x << "\t" 289 | << nodes[i].pos_y << " Row: " << nodes[i].lRow->coord_y << endl; 290 | } 291 | cout << endl; 292 | 293 | // if(!terminals.empty()) 294 | // for(int i=0; ils.empty()) { 309 | cout << "VECTOR EMPTY!!!!" << endl; 310 | return false; 311 | } 312 | 313 | return binary_search(point.lRow->ls.begin(), point.lRow->ls.end(), &nd, 314 | [](node* const& comp1, node* const& comp2) { 315 | return (comp1->pos_x < comp2->pos_x); 316 | }); 317 | } 318 | 319 | void DataPlace::findCoreRow(Point& point) { 320 | vector::iterator fIt = lower_bound( 321 | rows.begin(), rows.end(), point.y, 322 | [](row const& comp, double const& rY) { return comp.coord_y < rY; }); 323 | if (fIt != rows.end()) { 324 | if (fIt->coord_y != point.y) { 325 | cerr << "ERROR Row!!!!" << endl; 326 | exit(1); 327 | } 328 | point.lRow = &(*fIt); 329 | } else { 330 | cerr << "function findCoreRow. ERROR!" << endl; 331 | exit(1); 332 | } 333 | } 334 | 335 | size_t DataPlace::findCellIdx(Point& point) { 336 | findCoreRow(point); 337 | 338 | // for(vector::const_iterator itN = l.begin(); itN != l.end(); itN++) 339 | // //better 340 | //{ 341 | // if(point.x == (*itN)->pos_x) 342 | // return (*itN)->i; 343 | // else if(point.x < (*itN)->pos_x) 344 | // break; 345 | //} 346 | 347 | node nd; 348 | nd.pos_x = point.x; 349 | vector& l = point.lRow->ls; 350 | 351 | pair::iterator, vector::iterator> fIt = equal_range( 352 | l.begin(), l.end(), &nd, [](node* const& comp1, node* const& comp2) { 353 | return (comp1->pos_x < comp2->pos_x); 354 | }); 355 | 356 | if (fIt.first != fIt.second) { 357 | return (*fIt.first)->i; 358 | } 359 | 360 | return UINT_MAX; 361 | } 362 | 363 | bool DataPlace::findClosestWS(Point& loc, Point& WSLoc, double& width) { 364 | if (loc.lRow == NULL) findCoreRow(loc); 365 | WSLoc.lRow = loc.lRow; 366 | 367 | node nd; 368 | nd.pos_x = loc.x; 369 | vector& l = loc.lRow->ls; 370 | vector::iterator itn, itntemp, itnleft, itnright; 371 | 372 | bool leftRight = false; // false means move left else move right 373 | double WS, xDiff; 374 | 375 | if (l.empty()) // no cells in row 376 | return (true); 377 | 378 | pair::iterator, vector::iterator> fIt = equal_range( 379 | l.begin(), l.end(), &nd, [](node* const& comp1, node* const& comp2) { 380 | return (comp1->pos_x < comp2->pos_x); 381 | }); 382 | 383 | if (fIt.second == l.begin()) { 384 | itn = fIt.first; 385 | xDiff = (*itn)->pos_x - loc.lRow->coord_x; 386 | } else if (fIt.first == fIt.second) { 387 | itn = fIt.second - 1; 388 | if (fIt.first == l.end()) 389 | xDiff = 390 | (loc.lRow->coord_x + loc.lRow->num_sites * loc.lRow->site_sp) - 391 | ((*itn)->pos_x + (*itn)->w); 392 | else 393 | xDiff = (*fIt.second)->pos_x - ((*itn)->pos_x + (*itn)->w); 394 | } else { 395 | itn = fIt.first; 396 | if (fIt.second == l.end()) 397 | xDiff = 398 | (loc.lRow->coord_x + loc.lRow->num_sites * loc.lRow->site_sp) - 399 | ((*itn)->pos_x + (*itn)->w); 400 | else 401 | xDiff = (*fIt.second)->pos_x - ((*itn)->pos_x + (*itn)->w); 402 | } 403 | 404 | if (xDiff >= width) { 405 | if (fIt.second == l.begin()) 406 | WSLoc.x = loc.lRow->coord_x; 407 | else 408 | WSLoc.x = (*itn)->pos_x + (*itn)->w; 409 | return (true); 410 | } 411 | 412 | // closest node found, now try to find WS 413 | 414 | itnleft = itnright = itn; 415 | 416 | while (itnleft != (loc.lRow->ls.begin()) || 417 | itnright != (loc.lRow->ls.end() - 1)) { 418 | // choose the direction of search 419 | if (leftRight == false && itnright != loc.lRow->ls.end() - 1) 420 | leftRight = true; 421 | else if (leftRight == true && itnleft != loc.lRow->ls.begin()) 422 | leftRight = false; 423 | 424 | if (leftRight == true) // search right fow WS 425 | { 426 | itntemp = itnright + 1; 427 | WS = (*itntemp)->pos_x - (*itnright)->pos_x - (*itnright)->w; 428 | if (WS >= width) // WS found 429 | { 430 | WSLoc.x = (*itnright)->pos_x + (*itnright)->w; 431 | return (true); 432 | } 433 | ++itnright; 434 | } else // search left for WS 435 | { 436 | itntemp = itnleft - 1; 437 | WS = (*itnleft)->pos_x - (*itntemp)->pos_x - (*itntemp)->w; 438 | if (WS >= width) // WS found 439 | { 440 | WSLoc.x = (*itnleft)->pos_x - width; 441 | return (true); 442 | } 443 | --itnleft; 444 | } 445 | } 446 | return (false); 447 | } 448 | 449 | Point DataPlace::calcMeanLoc(size_t& cellId) { 450 | size_t pinCount = 0; 451 | Point meanLoc; 452 | 453 | vector& edge = nodes[cellId].nets_of_nodes; 454 | for (vector::const_iterator itN = edge.begin(); itN != edge.end(); 455 | itN++) { 456 | for (vector::const_iterator itE = nets[*itN].ls.begin(); 457 | itE != nets[*itN].ls.end(); itE++) { 458 | if (!(*itE)->is_terminal() && (*itE)->i == cellId) continue; 459 | meanLoc += Point((*itE)->pos_x, (*itE)->pos_y, NULL); 460 | pinCount++; 461 | } 462 | } 463 | if (pinCount == 0) { 464 | meanLoc = nodes[cellId]; 465 | } else { 466 | meanLoc.x /= pinCount; 467 | meanLoc.y /= pinCount; 468 | } 469 | return meanLoc; 470 | } 471 | 472 | double DataPlace::findLimitRow() { return (LengthNodes / NumRows); } 473 | 474 | double DataPlace::evalHPWL() { 475 | vector::iterator elMinY, elMaxY; 476 | vector::iterator elMinX, elMaxX; 477 | 478 | double totalHPWL = 0; 479 | 480 | for (vector::iterator it = nets.begin(); it != nets.end(); it++) { 481 | tie(elMinY, elMaxY) = minmax_element( 482 | it->ls.begin(), it->ls.end(), 483 | [](element* const& s1, element* const& s2) { 484 | return (s1->pos_y + 0.5 * s1->h) < (s2->pos_y + 0.5 * s2->h); 485 | }); 486 | 487 | tie(elMinX, elMaxX) = minmax_element( 488 | it->ls.begin(), it->ls.end(), 489 | [](element* const& s1, element* const& s2) { 490 | return (s1->pos_x + 0.5 * s1->w) < (s2->pos_x + 0.5 * s2->w); 491 | }); 492 | 493 | totalHPWL += (fabs((*elMaxX)->pos_x + 0.5 * (*elMaxX)->w - 494 | (*elMinX)->pos_x - 0.5 * (*elMinX)->w) + 495 | fabs((*elMaxY)->pos_y + 0.5 * (*elMaxY)->h - 496 | (*elMinY)->pos_y - 0.5 * (*elMinY)->h)); 497 | } 498 | 499 | return totalHPWL; 500 | } 501 | 502 | double DataPlace::calcOverlap(bool det) { 503 | double totalOverlap = 0; 504 | vector::iterator next; 505 | 506 | if (det) { 507 | for (vector::iterator itR = rows.begin(); itR != rows.end(); 508 | itR++) { 509 | for (vector::iterator it = itR->ls.begin(); 510 | it != itR->ls.end(); it++) { 511 | if (it != itR->ls.end() - 1) { 512 | next = it + 1; 513 | 514 | while (((*it)->pos_x + (*it)->w) > (*next)->pos_x) { 515 | if (((*it)->pos_x + (*it)->w) > 516 | ((*next)->pos_x + (*next)->w)) 517 | totalOverlap += (*next)->w * heightSC; 518 | else 519 | totalOverlap += fabs(((*it)->pos_x + (*it)->w) - 520 | (*next)->pos_x) * 521 | heightSC; 522 | next++; 523 | if (next == itR->ls.end()) break; 524 | } 525 | } 526 | } 527 | } 528 | } 529 | 530 | return totalOverlap; 531 | } 532 | 533 | double DataPlace::calcInstHPWL(vector& movables) { 534 | unordered_set seenNets; 535 | if (movables.size() == 2) 536 | seenNets.insert(nodes[movables.front()].nets_of_nodes.begin(), 537 | nodes[movables.front()].nets_of_nodes.end()); 538 | 539 | double totalHPWL = 0; 540 | 541 | vector::iterator elMinY, elMaxY; 542 | vector::iterator elMinX, elMaxX; 543 | 544 | for (vector::iterator it = movables.begin(); it != movables.end(); 545 | it++) { 546 | for (vector::iterator itN = nodes[*it].nets_of_nodes.begin(); 547 | itN != nodes[*it].nets_of_nodes.end(); itN++) { 548 | if (movables.size() == 2 && it == movables.end() - 1) 549 | if (seenNets.find(*itN) != seenNets.end()) continue; 550 | tie(elMinY, elMaxY) = 551 | minmax_element(nets[*itN].ls.begin(), nets[*itN].ls.end(), 552 | [](element* const& s1, element* const& s2) { 553 | return (s1->pos_y + 0.5 * s1->h) < 554 | (s2->pos_y + 0.5 * s2->h); 555 | }); 556 | 557 | tie(elMinX, elMaxX) = 558 | minmax_element(nets[*itN].ls.begin(), nets[*itN].ls.end(), 559 | [](element* const& s1, element* const& s2) { 560 | return (s1->pos_x + 0.5 * s1->w) < 561 | (s2->pos_x + 0.5 * s2->w); 562 | }); 563 | 564 | totalHPWL += (fabs((*elMaxX)->pos_x + 0.5 * (*elMaxX)->w - 565 | (*elMinX)->pos_x - 0.5 * (*elMinX)->w) + 566 | fabs((*elMaxY)->pos_y + 0.5 * (*elMaxY)->h - 567 | (*elMinY)->pos_y - 0.5 * (*elMinY)->h)); 568 | } 569 | } 570 | 571 | return totalHPWL; 572 | } 573 | 574 | double DataPlace::calcInstOverlap(vector& movables) { 575 | double totalOverlap = 0; 576 | double fall = 0; 577 | 578 | // if(movables.size() == 2) 579 | //{ 580 | // node& N1 = nodes[movables[0]]; 581 | // node& N2 = nodes[movables[1]]; 582 | // if(N1.lRow == N2.lRow && (N1.pos_x + N1.w > N2.pos_x || N2.pos_x + N2.w 583 | //> N1.pos_x) ) 584 | // { 585 | // vector::iterator next; 586 | // for(vector::iterator it = N1.lRow->ls.begin(); it != 587 | // N1.lRow->ls.end(); it++) 588 | // { 589 | // if(it != N1.lRow->ls.end()-1) 590 | // { 591 | // next = it + 1; 592 | 593 | // while( ( (*it)->pos_x + (*it)->w ) > 594 | //(*next)->pos_x 595 | //) 596 | // { 597 | // if ( ( (*it)->pos_x + (*it)->w ) > ( 598 | //(*next)->pos_x 599 | //+ 600 | //(*next)->w 601 | //) ) 602 | // totalOverlap += (*next)->w * 603 | // heightSC; 604 | // else 605 | // totalOverlap += fabs( ( (*it)->pos_x 606 | //+ 607 | //(*it)->w 608 | //) 609 | //- 610 | //(*next)->pos_x) * heightSC; 611 | // next++; 612 | // if( next == N1.lRow->ls.end() ) break; 613 | // } 614 | // } 615 | // } 616 | // return totalOverlap; 617 | // } 618 | //} 619 | 620 | if (movables.size() == 2) { 621 | node& N1 = nodes[movables[0]]; 622 | node& N2 = nodes[movables[1]]; 623 | if (N1.lRow == N2.lRow && 624 | (N1.pos_x + N1.w > N2.pos_x || N2.pos_x + N2.w > N1.pos_x)) { 625 | if ((N1.pos_x >= N2.pos_x) && (N1.pos_x + N1.w <= N2.pos_x + N2.w)) 626 | fall += N1.w * heightSC; 627 | else if ((N1.pos_x <= N2.pos_x) && 628 | (N1.pos_x + N1.w >= N2.pos_x + N2.w)) 629 | fall += N2.w * heightSC; 630 | else if ((N1.pos_x > N2.pos_x) && (N1.pos_x < N2.pos_x + N2.w)) 631 | fall += fabs(N2.pos_x + N2.w - N1.pos_x) * heightSC; 632 | else if ((N1.pos_x + N1.w > N2.pos_x) && 633 | (N1.pos_x + N1.w < N2.pos_x + N2.w)) 634 | fall += fabs(N1.pos_x + N1.w - N2.pos_x) * heightSC; 635 | } 636 | } 637 | 638 | for (vector::iterator itM = movables.begin(); itM != movables.end(); 639 | itM++) { 640 | row& Row = *nodes[*itM].lRow; 641 | double mLeftEdge = nodes[*itM].pos_x; 642 | double mRightEdge = nodes[*itM].pos_x + nodes[*itM].w; 643 | for (vector::iterator it = Row.ls.begin(); it != Row.ls.end(); 644 | it++) { 645 | double everyLeftEdge = (*it)->pos_x; 646 | double everyRightEdge = (*it)->pos_x + (*it)->w; 647 | 648 | if (everyLeftEdge > mRightEdge) break; 649 | if (&nodes[*itM] == &(**it)) continue; 650 | 651 | if ((mLeftEdge >= everyLeftEdge) && (mRightEdge <= everyRightEdge)) 652 | totalOverlap += nodes[*itM].w * heightSC; 653 | else if ((mLeftEdge <= everyLeftEdge) && 654 | (mRightEdge >= everyRightEdge)) 655 | totalOverlap += (*it)->w * heightSC; 656 | else if ((mLeftEdge > everyLeftEdge) && 657 | (mLeftEdge < everyRightEdge)) 658 | totalOverlap += fabs(everyRightEdge - mLeftEdge) * heightSC; 659 | else if ((mRightEdge > everyLeftEdge) && 660 | (mRightEdge < everyRightEdge)) 661 | totalOverlap += fabs(mRightEdge - everyLeftEdge) * heightSC; 662 | } 663 | } 664 | return totalOverlap - fall; 665 | } 666 | 667 | double DataPlace::evalPRow() { 668 | double totalPRow = 0; 669 | double limitRow = findLimitRow(); 670 | 671 | for (vector::iterator it = rows.begin(); it != rows.end(); it++) { 672 | totalPRow += fabs(it->busySRow - limitRow); 673 | } 674 | return totalPRow; 675 | } 676 | 677 | void DataPlace::checkPRow() { 678 | for (vector::iterator it = rows.begin(); it != rows.end(); it++) { 679 | cout << it->busySRow << endl; 680 | if (it->busySRow > it->num_sites * it->site_sp) 681 | cout << it->coord_y << endl; 682 | } 683 | } 684 | 685 | void DataPlace::updateCells(const vector& movables, 686 | const vector& soln, double& prow) { 687 | for (int i = 0; i < movables.size(); i++) { 688 | setLocation(movables[i], soln[i], prow); 689 | } 690 | } 691 | 692 | void DataPlace::setLocation(const size_t id, const Point& pt, double& prow) { 693 | vector& eraseCell = nodes[id].lRow->ls; 694 | 695 | vector::iterator fIt = upper_bound( 696 | eraseCell.begin(), eraseCell.end(), nodes[id].pos_x, 697 | [](double const& rX, node* const& comp) { return rX < comp->pos_x; }); 698 | if ((*(fIt - 1))->name == nodes[id].name) { 699 | prow -= fabs(nodes[id].lRow->busySRow - findLimitRow()); 700 | nodes[id].lRow->busySRow -= nodes[id].w; 701 | prow += fabs(nodes[id].lRow->busySRow - findLimitRow()); 702 | eraseCell.erase(fIt - 1); 703 | } else { 704 | cerr << "function setLocation. ERROR - erase element!" << endl; 705 | exit(1); 706 | } 707 | 708 | nodes[id].pos_x = pt.x; 709 | nodes[id].pos_y = pt.y; 710 | nodes[id].lRow = pt.lRow; 711 | 712 | if (pt.lRow->ls.empty()) cout << "ERROR/ VECTOR EMPTY" << endl; 713 | 714 | vector& insertCell = nodes[id].lRow->ls; 715 | 716 | if (insertCell.empty() || (*(insertCell.end() - 1))->pos_x < pt.x) { 717 | prow -= fabs(nodes[id].lRow->busySRow - findLimitRow()); 718 | nodes[id].lRow->busySRow += nodes[id].w; 719 | prow += fabs(nodes[id].lRow->busySRow - findLimitRow()); 720 | insertCell.insert(insertCell.end(), &nodes[id]); 721 | } else { 722 | vector::iterator fIt = 723 | lower_bound(insertCell.begin(), insertCell.end(), pt.x, 724 | [](node* const& comp, double const& rX) { 725 | return comp->pos_x < rX; 726 | }); 727 | if (pt.x <= (*fIt)->pos_x) { 728 | prow -= fabs(nodes[id].lRow->busySRow - findLimitRow()); 729 | nodes[id].lRow->busySRow += nodes[id].w; 730 | prow += fabs(nodes[id].lRow->busySRow - findLimitRow()); 731 | insertCell.insert(fIt, &nodes[id]); 732 | } else { 733 | cerr << "function setLocation. ERROR - insert element" << endl; 734 | exit(1); 735 | } 736 | } 737 | } 738 | 739 | void DataPlace::remOverlaps() { 740 | double offset; 741 | for (vector::iterator itR = rows.begin(); itR != rows.end(); itR++) { 742 | offset = 743 | itR->coord_x + (itR->num_sites * itR->site_sp - itR->busySRow) / 2; 744 | for (vector::iterator it = itR->ls.begin(); it != itR->ls.end(); 745 | it++) { 746 | (*it)->pos_x = offset; 747 | offset += (*it)->w; 748 | } 749 | } 750 | } 751 | 752 | double DataPlace::RandomDouble(double min, double max) { 753 | return (double)(rand()) / RAND_MAX * (max - min) + min; 754 | } 755 | 756 | unsigned int DataPlace::RandomUnsigned(unsigned int min, unsigned int max) { 757 | return (rand() % (max - min)) + min; 758 | } 759 | 760 | void DataPlace::savePlacement(const char* plFileName) const { 761 | time_t rawtime; 762 | struct tm* timeinfo; 763 | time(&rawtime); 764 | timeinfo = localtime(&rawtime); 765 | 766 | ofstream out(plFileName); 767 | 768 | out << "UCLA pl 1.0" << endl; 769 | out << "# Created\t: " << asctime(timeinfo); 770 | out << "# User\t: Loskutov V" << endl; 771 | out << "# Platform\t: Windows 7\n\n" << endl; 772 | 773 | for (vector::const_iterator it = nodes.begin(); it != nodes.end(); 774 | it++) { 775 | out << setw(8) << it->name << " " << setw(10) << it->pos_x << " " 776 | << setw(10) << it->pos_y << " : N"; 777 | out << endl; 778 | } 779 | 780 | for (vector::const_iterator it = terminals.begin(); 781 | it != terminals.end(); it++) { 782 | out << setw(8) << it->name << " " << setw(10) << it->pos_x << " " 783 | << setw(10) << it->pos_y << " : N"; 784 | out << endl; 785 | } 786 | 787 | out.close(); 788 | } -------------------------------------------------------------------------------- /DataPlace.h: -------------------------------------------------------------------------------- 1 | // DataPlace.h 2 | #ifndef _DATAPLACE_H_ 3 | #define _DATAPLACE_H_ 4 | 5 | #include 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | struct row; 11 | 12 | // delete element.h, row.h, row.site_sp 13 | 14 | struct element { 15 | string name; // element name 16 | size_t i; 17 | double w, h; // element width and height 18 | vector nets_of_nodes; // element of nets 19 | double pos_x, pos_y; // element coordinate 20 | element() : pos_x(0), pos_y(0), i(0) {} 21 | virtual bool is_terminal() { return true; } 22 | }; 23 | 24 | typedef element terminal; 25 | 26 | struct node : element { 27 | row *lRow; // link to row 28 | node() : element(), lRow(NULL) {} 29 | bool is_terminal() { return false; } 30 | }; 31 | 32 | struct row { 33 | int coord_y; // coordinate 34 | int coord_x; // subroworigin 35 | float h; // height of row 36 | unsigned int site_sp; // sitespacing 37 | unsigned int num_sites; // numsites 38 | unsigned int busySRow; 39 | vector ls; 40 | row() : coord_x(0), coord_y(0), busySRow(0) {} 41 | }; 42 | 43 | struct net { 44 | vector ls; 45 | }; 46 | 47 | struct Point { 48 | double x, y; 49 | row *lRow; 50 | Point() : x(0), y(0), lRow(NULL) {} 51 | Point(double a, double b, row *r) { 52 | x = a; 53 | y = b; 54 | lRow = r; 55 | } 56 | Point(node &cell) { 57 | x = cell.pos_x; 58 | y = cell.pos_y; 59 | lRow = cell.lRow; 60 | } 61 | inline Point &operator+=(const Point &right) { 62 | this->x += right.x; 63 | this->y += right.y; 64 | return *this; 65 | } 66 | }; 67 | 68 | class DataPlace { 69 | public: 70 | unsigned NumNodes; // include NumTerminals 71 | unsigned NumTerminals; 72 | unsigned NumCells; // without terminals 73 | unsigned NumRows; 74 | unsigned NumNets; 75 | unsigned NumPins; 76 | double LengthNodes; //сумма длин ¤чеек 77 | unsigned heightSC; // heightRow = heightNodes 78 | char *path_nodes, *path_nets, *path_scl, *path_pl; 79 | vector nodes; // вектор, содержащий структуры node 80 | vector terminals; // терминалы 81 | vector nets; // вектор св¤зей 82 | vector rows; // вектор структур строк с их параметрами 83 | 84 | DataPlace(); 85 | void Start(const char *); 86 | 87 | void parseAuxFile(const char *); // 88 | void parseNodes(); // 89 | void parseNets(); // 90 | void parseScl(); // 91 | void parsePl(); // 92 | void parser(); // считывает данные из файлов .nodes, .nets, .scl, .pl 93 | void print_nodes(); // выводит на экран все вершины 94 | void print_nets(); // выводит на экран все св¤зи 95 | void print_scl(); // вывод строк с их параметрами 96 | void print_pl(); // вывод размещений нодов 97 | 98 | bool checkPointInRow(const Point &point); 99 | void findCoreRow(Point &point); 100 | size_t findCellIdx(Point &point); 101 | bool findClosestWS(Point &loc, Point &WSLoc, double &width); 102 | Point calcMeanLoc(size_t &cellId); 103 | double findLimitRow(); 104 | 105 | double evalHPWL(); 106 | double calcOverlap(bool det = false); 107 | double evalPRow(); 108 | void checkPRow(); 109 | double calcInstHPWL(vector &movables); 110 | double calcInstOverlap(vector &movables); 111 | void updateCells(const vector &movables, const vector &soln, 112 | double &prow); 113 | void setLocation(const size_t id, const Point &pt, double &prow); 114 | 115 | void remOverlaps(); // Legalization 116 | void savePlacement(const char *plFileName) const; 117 | 118 | double RandomDouble(double min, double max); 119 | unsigned int RandomUnsigned(unsigned int num1, unsigned int num2); 120 | }; 121 | 122 | #endif -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/en9inerd/SimAn/d267ded7c837cc2304b86da8d4fd6aa9a0977d74/Makefile -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Placer Based on the "Simulated Annealing" Algorithm 2 | 3 | A standard cell placer for both global and detailed placement, based on a modified "simulated annealing" algorithm for VLSI and FPGA design. 4 | 5 | This source code was once part of my master's thesis, where I explored the simulated annealing algorithm with certain modifications for placing standard cells on an integrated circuit. I never found the time to refactor and eliminate bad practices, but I used to compile this with VS2013-VS2015 on Windows 7 and it worked with [IBM-PLACE Benchmarks] in the Bookshelf format. Since I haven't had experience with C++ for over 9 years, I don't see the point in spending time on refactoring or making improvements now. I'm leaving it here as it was, hoping someone might find it useful. 6 | 7 | Some logic as I remember was borrowed from [TimberWolf], [UMpack] and [UCLApack]. 8 | 9 | [IBM-PLACE Benchmarks]: http://vlsicad.eecs.umich.edu/BK/Slots/cache/er.cs.ucla.edu/benchmarks/ibm-place/ 10 | [UMpack]: http://vlsicad.eecs.umich.edu/BK/PDtools/tar.gz/LATEST/UMpack-45-120708.tar.gz 11 | [UCLApack]: ./UCLApack-43-040113.tar.gz_ 12 | [TimberWolf]: https://github.com/rubund/graywolf/blob/master/README.md 13 | -------------------------------------------------------------------------------- /SimAnneal.cpp: -------------------------------------------------------------------------------- 1 | // SimAnneal.cpp 2 | 3 | #include "SimAnneal.h" 4 | 5 | using std::cout; 6 | using std::endl; 7 | using std::setw; 8 | 9 | SimAnneal::SimAnneal(DataPlace& rbplace, bool gr, bool det) 10 | : rb(rbplace), 11 | greedy(gr), 12 | detailed(det), 13 | calibMaxIter(500), 14 | oldCost(0), 15 | newCost(0), 16 | oldPlace(0), 17 | newPlace(0), 18 | lambda(1), 19 | lambdaP(1), 20 | layoutBBox(rb) { 21 | acceptCount = 0; 22 | curRate = 1.0; 23 | maxI = 150; 24 | I = 0; 25 | maxUpdate = 25; 26 | 27 | negAcceptCount = posAcceptCount = 0; 28 | layoutXSize = layoutBBox.getWidth(); 29 | layoutYSize = layoutBBox.getHeight(); 30 | layoutArea = layoutXSize * layoutYSize; 31 | cout << "Placement area: " << layoutXSize << " x " << layoutYSize << endl; 32 | cout << "Num move_cells: " << rb.NumCells << endl; 33 | 34 | if (!detailed) { 35 | initPlacement(rb); 36 | } else { 37 | fillingRows(rb); 38 | } 39 | 40 | hpwl = rb.evalHPWL(); 41 | overlap = rb.calcOverlap(detailed); 42 | penaltyRow = rb.evalPRow(); 43 | oldCost = cost(); 44 | 45 | initTemp = curTemp = 46 | (detailed) ? hpwl / rb.NumNets : oldCost; // initial HPWL per net 47 | stopTemp = curTemp / 100; 48 | k = 1; // specify user 49 | maxIter = k * rb.NumCells; 50 | 51 | cout << "Initial:\t Temp: " << curTemp << " Iter: " << maxIter 52 | << " HPWL: " << rb.evalHPWL() << " Over: " << rb.calcOverlap(detailed) 53 | << " Cost: " << oldCost << endl; 54 | 55 | dynamic_window(); 56 | cout << windowfactor << " : " << xspan << " , " << yspan << endl; 57 | 58 | if (!greedy && detailed) calibrate(); 59 | 60 | initTemp = curTemp; 61 | stopTemp = curTemp / 100; 62 | 63 | if (detailed) 64 | anneal_detailed(); 65 | else 66 | anneal_global(); 67 | rb.checkPRow(); 68 | 69 | cout << "Final:\t HPWL: " << rb.evalHPWL() 70 | << " Over: " << rb.calcOverlap(true) << endl; 71 | } 72 | 73 | /* For Detailed Placement */ 74 | void SimAnneal::anneal_detailed() { 75 | movables.clear(); 76 | oldPlace.clear(); 77 | newPlace.clear(); 78 | 79 | hpwl = rb.evalHPWL(); 80 | overlap = rb.calcOverlap(); 81 | penaltyRow = rb.evalPRow(); 82 | oldCost = cost(); 83 | lambda = 1; 84 | 85 | cout << "Beginning temperature decline..." << endl; 86 | unsigned int j = 0; 87 | 88 | while (curTemp > stopTemp) { 89 | negAcceptCount = posAcceptCount = 0; 90 | totaloverlap = totalhpwl = 0; 91 | 92 | itCount = 0; 93 | 94 | cout << "It#: " << j << "\tTemp: " << curTemp << endl; 95 | 96 | while (itCount++ <= maxIter) { 97 | totalhpwl += hpwl; 98 | totaloverlap += overlap; 99 | if (!(itCount % (maxIter / 20))) { 100 | avghpwl = totalhpwl / itCount; 101 | avgoverlap = totaloverlap / itCount; 102 | if (avgoverlap == 0) 103 | lambda = 1; 104 | else 105 | lambda = (avghpwl > avgoverlap) ? avghpwl / avgoverlap : 1; 106 | 107 | oldCost = hpwl + lambda * overlap; 108 | } 109 | generate(); 110 | 111 | hpwl -= rb.calcInstHPWL(movables); 112 | overlap -= rb.calcInstOverlap(movables); 113 | rb.updateCells(movables, newPlace, penaltyRow); 114 | newCost = cost(); 115 | 116 | if (!accept(newCost, oldCost, curTemp)) { 117 | hpwl -= rb.calcInstHPWL(movables); 118 | overlap -= rb.calcInstOverlap(movables); 119 | rb.updateCells(movables, oldPlace, penaltyRow); 120 | oldCost = cost(); 121 | } else { 122 | oldCost = newCost; 123 | } 124 | } 125 | update(curTemp); 126 | j++; 127 | cout << " HPWL: " << hpwl << " Over: " << overlap 128 | << " penRow: " << penaltyRow << endl; 129 | } 130 | } 131 | 132 | /* For Global Placement */ 133 | void SimAnneal::anneal_global() { 134 | movables.clear(); 135 | oldPlace.clear(); 136 | newPlace.clear(); 137 | 138 | hpwl = rb.evalHPWL(); 139 | overlap = rb.calcOverlap(); 140 | penaltyRow = rb.evalPRow(); 141 | oldCost = cost(); 142 | lambda = 1; 143 | lambdaP = 1; 144 | 145 | cout << "Beginning temperature decline..." << endl; 146 | 147 | while (I++ < maxI) { 148 | acceptCount = 0; 149 | totalCount = 0; 150 | updateCount = 0; 151 | 152 | if (I < 0.15 * maxI) 153 | curRate *= exp(log(0.44) / (0.15 * maxI)); 154 | else if (I < 0.68 * maxI) 155 | curRate = 0.44; 156 | else 157 | curRate *= exp(log(0.01 / 0.44) / (0.35 * maxI)); 158 | 159 | negAcceptCount = posAcceptCount = 0; 160 | totaloverlap = totalhpwl = 0; 161 | 162 | itCount = 0; 163 | 164 | while (itCount++ <= maxIter) { 165 | updateCount++; 166 | if (updateCount == maxUpdate) { 167 | updateCount = 0; 168 | update_Lam(curTemp); 169 | } 170 | 171 | totalhpwl += hpwl; 172 | totaloverlap += overlap; 173 | if (!(itCount % (maxIter / 20))) { 174 | avghpwl = totalhpwl / itCount; 175 | avgoverlap = totaloverlap / itCount; 176 | if (avgoverlap == 0) 177 | lambda = 1; 178 | else 179 | lambda = (avghpwl > avgoverlap) ? avghpwl / avgoverlap : 1; 180 | lambdaP = 6.1 * lambda; 181 | 182 | oldCost = hpwl + 1.5 * overlap + lambdaP * penaltyRow; 183 | } 184 | generate(); 185 | 186 | hpwl -= rb.calcInstHPWL(movables); 187 | overlap -= rb.calcInstOverlap(movables); 188 | rb.updateCells(movables, newPlace, penaltyRow); 189 | newCost = cost(); 190 | 191 | if (!accept(newCost, oldCost, curTemp)) { 192 | hpwl -= rb.calcInstHPWL(movables); 193 | overlap -= rb.calcInstOverlap(movables); 194 | rb.updateCells(movables, oldPlace, penaltyRow); 195 | oldCost = cost(); 196 | } else { 197 | acceptCount++; 198 | oldCost = newCost; 199 | } 200 | } 201 | dynamic_window(); 202 | cout << windowfactor << " : " << xspan << " , " << yspan << endl; 203 | cout << "Iter: " << I << " HPWL: " << hpwl << " Over: " << overlap 204 | << " penRow: " << penaltyRow << endl; 205 | cout << "\tCR: " << curRate 206 | << " AR: " << double(acceptCount) / double(itCount) << endl; 207 | } 208 | } 209 | 210 | void SimAnneal::generate() { 211 | movables.clear(); 212 | oldPlace.clear(); 213 | newPlace.clear(); 214 | 215 | size_t randIdx1 = rb.RandomUnsigned(0, rb.NumCells); 216 | 217 | node& randNode1 = rb.nodes[randIdx1]; 218 | movables.push_back(randIdx1); 219 | oldPlace.push_back(Point(randNode1)); 220 | 221 | double cellWidth1 = randNode1.w; 222 | 223 | unsigned int directedMove = rb.RandomUnsigned(0, 10); 224 | unsigned int whichMove = rb.RandomUnsigned(0, 10); 225 | 226 | if (directedMove < 0) { 227 | if (whichMove < 4) { 228 | size_t crow = rb.RandomUnsigned(0, rb.NumRows); 229 | row& cr = rb.rows[crow]; 230 | size_t site = rb.RandomUnsigned(0, cr.num_sites); 231 | Point randLoc(cr.coord_x + site * cr.site_sp, cr.coord_y, &cr); 232 | 233 | bool check; 234 | Point newLoc = randLoc; 235 | if (!detailed) 236 | check = rb.checkPointInRow(newLoc); 237 | else 238 | check = !rb.findClosestWS(randLoc, newLoc, cellWidth1); 239 | 240 | if (check) { 241 | movables.pop_back(); 242 | oldPlace.pop_back(); 243 | } else { 244 | newPlace.push_back(newLoc); 245 | } 246 | } else { 247 | size_t randIdx2; 248 | 249 | do 250 | randIdx2 = rb.RandomUnsigned(0, rb.NumCells); 251 | while (randIdx2 == randIdx1); 252 | 253 | movables.push_back(randIdx2); 254 | oldPlace.push_back(Point(rb.nodes[randIdx2])); 255 | 256 | newPlace.push_back(Point(rb.nodes[randIdx2])); 257 | newPlace.push_back(Point(randNode1)); 258 | } 259 | } else { 260 | double rowpitch = rb.rows[1].coord_y - rb.rows[0].coord_y; 261 | double sitepitch = randNode1.lRow->site_sp; 262 | double ycellcoordoffset = layoutBBox.yMin; 263 | double xcellcoordoffset = layoutBBox.xMin; 264 | 265 | Point curLoc = randNode1; 266 | 267 | if (whichMove < 4) { 268 | Point optLoc = rb.calcMeanLoc(randIdx1); 269 | 270 | optLoc.x = 271 | (floor((optLoc.x - xcellcoordoffset) / sitepitch)) * sitepitch + 272 | xcellcoordoffset; 273 | optLoc.y = 274 | (floor((optLoc.y - ycellcoordoffset) / rowpitch)) * rowpitch + 275 | ycellcoordoffset; 276 | 277 | optLoc.x = 278 | (optLoc.x >= layoutBBox.xMax) ? layoutBBox.xMax : optLoc.x; 279 | optLoc.x = 280 | (optLoc.x <= layoutBBox.xMin) ? layoutBBox.xMin : optLoc.x; 281 | optLoc.y = (optLoc.y >= layoutBBox.yMax) 282 | ? layoutBBox.yMax - rb.heightSC 283 | : optLoc.y; 284 | optLoc.y = 285 | (optLoc.y <= layoutBBox.yMin) ? layoutBBox.yMin : optLoc.y; 286 | 287 | bool check; 288 | Point newLoc = optLoc; 289 | if (!detailed) { 290 | rb.findCoreRow(newLoc); 291 | check = rb.checkPointInRow(newLoc); 292 | } else { 293 | check = !rb.findClosestWS(optLoc, newLoc, cellWidth1); 294 | } 295 | 296 | if (check) { 297 | movables.pop_back(); 298 | oldPlace.pop_back(); 299 | } else { 300 | newPlace.push_back(newLoc); 301 | } 302 | } else if (whichMove < 8) { 303 | Point newLoc; 304 | double ymin = ((curLoc.y - yspan) <= layoutBBox.yMin) 305 | ? layoutBBox.yMin 306 | : curLoc.y - yspan; 307 | double ymax = ((curLoc.y + yspan) >= layoutBBox.yMax) 308 | ? layoutBBox.yMax 309 | : curLoc.y + yspan; 310 | newLoc.y = rb.RandomDouble(ymin, ymax); 311 | 312 | double xmin = ((curLoc.x - xspan) <= layoutBBox.xMin) 313 | ? layoutBBox.xMin 314 | : curLoc.x - xspan; 315 | double xmax = ((curLoc.x + xspan) >= layoutBBox.xMax) 316 | ? layoutBBox.xMax 317 | : curLoc.x + xspan; 318 | newLoc.x = rb.RandomDouble(xmin, xmax); 319 | 320 | newLoc.x = 321 | (floor((newLoc.x - xcellcoordoffset) / sitepitch)) * sitepitch + 322 | xcellcoordoffset; 323 | newLoc.y = 324 | (floor((newLoc.y - ycellcoordoffset) / rowpitch)) * rowpitch + 325 | ycellcoordoffset; 326 | if (newLoc.y == layoutBBox.yMax) newLoc.y -= rb.heightSC; 327 | 328 | bool check; 329 | Point Loc = newLoc; 330 | if (!detailed) { 331 | rb.findCoreRow(Loc); 332 | check = rb.checkPointInRow(Loc); 333 | } else { 334 | check = !rb.findClosestWS(newLoc, Loc, cellWidth1); 335 | } 336 | 337 | if (check) { 338 | movables.pop_back(); 339 | oldPlace.pop_back(); 340 | } else { 341 | newPlace.push_back(Loc); 342 | } 343 | } else { 344 | Point newLoc; 345 | double ymin = ((curLoc.y - yspan) <= layoutBBox.yMin) 346 | ? layoutBBox.yMin 347 | : curLoc.y - yspan; 348 | double ymax = ((curLoc.y + yspan) >= layoutBBox.yMax) 349 | ? layoutBBox.yMax 350 | : curLoc.y + yspan; 351 | 352 | double xmin = ((curLoc.x - xspan) <= layoutBBox.xMin) 353 | ? layoutBBox.xMin 354 | : curLoc.x - xspan; 355 | double xmax = ((curLoc.x + xspan) >= layoutBBox.xMax) 356 | ? layoutBBox.xMax 357 | : curLoc.x + xspan; 358 | 359 | size_t randIdx2; 360 | do { 361 | newLoc.y = rb.RandomDouble(ymin, ymax); 362 | newLoc.x = rb.RandomDouble(xmin, xmax); 363 | newLoc.x = (floor((newLoc.x - xcellcoordoffset) / sitepitch)) * 364 | sitepitch + 365 | xcellcoordoffset; 366 | newLoc.y = (floor((newLoc.y - ycellcoordoffset) / rowpitch)) * 367 | rowpitch + 368 | ycellcoordoffset; 369 | if (newLoc.y == layoutBBox.yMax) newLoc.y -= rb.heightSC; 370 | randIdx2 = rb.findCellIdx(newLoc); 371 | } while (randIdx2 == randIdx1); 372 | 373 | if (randIdx2 < rb.NumCells) { 374 | movables.push_back(randIdx2); 375 | oldPlace.push_back(Point(rb.nodes[randIdx2])); 376 | 377 | newPlace.push_back(Point(rb.nodes[randIdx2])); 378 | newPlace.push_back(Point(randNode1)); 379 | } else { 380 | newPlace.push_back(newLoc); 381 | } 382 | } 383 | } 384 | } 385 | 386 | double SimAnneal::cost() { 387 | hpwl += rb.calcInstHPWL(movables); 388 | overlap += rb.calcInstOverlap(movables); 389 | 390 | return ((!detailed) ? (hpwl + 1.5 * overlap + lambdaP * penaltyRow) 391 | : (hpwl + lambda * overlap)); 392 | } 393 | 394 | bool SimAnneal::accept(double newCost, double oldCost, double curTemp) { 395 | if (newCost <= oldCost) { 396 | posAcceptCount++; 397 | return (true); 398 | } 399 | 400 | if (greedy) return (false); 401 | 402 | if (rb.RandomDouble(0, 1) < exp(-fabs(newCost - oldCost) / curTemp)) { 403 | negAcceptCount++; 404 | return (true); 405 | } 406 | 407 | return (false); 408 | } 409 | 410 | void SimAnneal::update(double& _curTemp) { 411 | if (_curTemp > 0.66 * initTemp) 412 | _curTemp *= 0.8; 413 | else if (curTemp > 0.33 * initTemp) 414 | _curTemp *= 0.85; 415 | else if (_curTemp > 0.1 * initTemp) 416 | _curTemp *= 0.90; 417 | else 418 | _curTemp *= 0.96; 419 | 420 | if (curRate < initTemp && detailed) maxIter = 2 * rb.NumCells; 421 | 422 | dynamic_window(); 423 | 424 | cout << windowfactor << " : " << xspan << " , " << yspan << endl; 425 | } 426 | 427 | void SimAnneal::update_Lam(double& _curTemp) { 428 | totalCount = itCount; 429 | double acceptRate = double(acceptCount) / totalCount; 430 | double change = (1 - (acceptRate - curRate) / 3); 431 | _curTemp *= change; 432 | } 433 | 434 | void SimAnneal::calibrate() { 435 | cout << "Performing a warm-up run to calibrate acceptance rates..." << endl; 436 | cout << "\t" << setw(10) << "Iter" << setw(10) << "\tTemp" << setw(10) 437 | << "\tNAR" << setw(10) << "\tAR" << setw(10) << "\tCost(HPWL+OV+PR)" 438 | << endl; 439 | 440 | double oldTemp = DBL_MAX; 441 | int it = 0; 442 | int maxIter = 500; 443 | 444 | while (fabs(oldTemp - curTemp) / oldTemp > 0.01 && it < maxIter) { 445 | ++it; 446 | oldTemp = curTemp; 447 | negAcceptCount = posAcceptCount = 0; 448 | totaloverlap = totalhpwl = 0; 449 | itCount = 0; 450 | cout << "[ "; 451 | 452 | while (itCount++ <= calibMaxIter) { 453 | totalhpwl += hpwl; 454 | totaloverlap += overlap; 455 | if (!(itCount % (calibMaxIter / 5))) { 456 | cout << "."; 457 | cout.flush(); 458 | } 459 | if (itCount == 1) { 460 | avghpwl = totalhpwl / itCount; 461 | avgoverlap = totaloverlap / itCount; 462 | if (avgoverlap == 0) 463 | lambda = 1; 464 | else 465 | lambda = (avghpwl > avgoverlap) ? avghpwl / avgoverlap : 1; 466 | 467 | oldCost = hpwl + lambda * overlap; 468 | } 469 | if (!(itCount % (calibMaxIter / 5)) || itCount == 1) { 470 | double negAcceptRate = negAcceptCount / itCount; 471 | curTemp *= (1 - (negAcceptRate - 0.01) / 1); 472 | } 473 | 474 | generate(); 475 | 476 | hpwl -= rb.calcInstHPWL(movables); 477 | overlap -= rb.calcInstOverlap(movables); 478 | rb.updateCells(movables, newPlace, penaltyRow); 479 | newCost = cost(); 480 | 481 | accept(newCost, oldCost, curTemp); 482 | 483 | hpwl -= rb.calcInstHPWL(movables); 484 | overlap -= rb.calcInstOverlap(movables); 485 | rb.updateCells(movables, oldPlace, penaltyRow); 486 | oldCost = cost(); 487 | } 488 | 489 | cout << " ]"; 490 | 491 | double negAcceptRate = negAcceptCount / calibMaxIter; 492 | double acceptRate = (posAcceptCount + negAcceptCount) / calibMaxIter; 493 | cout << setw(10) << it << setw(10) << curTemp << "\t" << setw(10) 494 | << negAcceptRate << "\t" << setw(10) << acceptRate << "\t" 495 | << setw(10) << oldCost << endl; 496 | } 497 | } 498 | 499 | void SimAnneal::initPlacement(DataPlace& _rb) { 500 | double limitRow = 1.007 * _rb.findLimitRow(); 501 | double ws = 0; //_rb.rows.begin()->site_sp; 502 | double tab = 15 * ws; // static_cast( (_rb.rows.begin()->num_sites * 503 | // _rb.rows.begin()->site_sp - limitRow)/2 ); 504 | double offset; 505 | 506 | vector& _nd = _rb.nodes; 507 | vector& _rw = _rb.rows; 508 | vector::iterator it_last = _nd.begin(); 509 | vector::iterator it = it_last; 510 | 511 | for (vector::iterator itR = _rw.begin(); 512 | itR != _rw.end(), it != _nd.end(); itR++) { 513 | offset = itR->coord_x; 514 | for (it = it_last; it != _nd.end(); it++) { 515 | if (limitRow > (itR->busySRow + it->w)) { 516 | it->pos_x = tab + offset; 517 | it->pos_y = itR->coord_y; 518 | offset += (ws + it->w); 519 | itR->busySRow += it->w; 520 | it->lRow = &(*itR); 521 | itR->ls.push_back(&(*it)); 522 | } else { 523 | it_last = it; 524 | if (itR == _rw.end() - 1) { 525 | cerr << "Ошибка инициализации размещения: недостаточно " 526 | "строк для расположения всех нодов" 527 | << endl; 528 | system("pause"); 529 | exit(1); 530 | } 531 | break; 532 | } 533 | } 534 | } 535 | } 536 | 537 | void SimAnneal::fillingRows(DataPlace& _rb) { 538 | vector& _nd = _rb.nodes; 539 | vector& _rw = _rb.rows; 540 | 541 | for (vector::iterator it = rb.nodes.begin(); it != rb.nodes.end(); 542 | it++) { 543 | vector::iterator fIt = 544 | lower_bound(_rw.begin(), _rw.end(), it->pos_y, 545 | [](row const& comp, double const& rY) { 546 | return comp.coord_y < rY; 547 | }); 548 | if (fIt != _rw.end()) { 549 | if (fIt->coord_y != it->pos_y) { 550 | cerr << "ERROR Row! fillingRows" << endl; 551 | exit(1); 552 | } 553 | it->lRow = &(*fIt); 554 | fIt->ls.push_back(&(*it)); 555 | fIt->busySRow += it->w; 556 | } else { 557 | cerr << "function fillingRows. ERROR!" << endl; 558 | exit(1); 559 | } 560 | } 561 | 562 | for (vector::iterator itR = _rw.begin(); itR != _rw.end(); itR++) { 563 | sort( 564 | itR->ls.begin(), itR->ls.end(), 565 | [](node* const& a, node* const& b) { return a->pos_x < b->pos_x; }); 566 | } 567 | } 568 | 569 | void SimAnneal::dynamic_window() { 570 | double areaPerCell = layoutArea / rb.NumCells; 571 | double layoutAR = layoutXSize / layoutYSize; 572 | double widthPerCell = sqrt(areaPerCell * layoutAR); 573 | double heightPerCell = widthPerCell / layoutAR; 574 | 575 | double minyspan = 2 * (rb.rows[1].coord_y - rb.rows[0].coord_y); 576 | double minxspan = 5 * widthPerCell; 577 | 578 | if (detailed) { 579 | windowfactor = log10(curTemp / stopTemp) / log10(initTemp / stopTemp); 580 | } else { 581 | if (I < 23) 582 | windowfactor = 1; 583 | else if (I <= 97) 584 | windowfactor = exp(-1.5 * (I - 22) / 75); 585 | else 586 | windowfactor = exp(-5.5); 587 | } 588 | 589 | const double scale = (!detailed) ? 150 : 15; 590 | xspan = windowfactor * scale * widthPerCell; 591 | yspan = windowfactor * scale * heightPerCell; 592 | 593 | if (xspan < minxspan) xspan = minxspan; 594 | if (yspan < minyspan) yspan = minyspan; 595 | } -------------------------------------------------------------------------------- /SimAnneal.h: -------------------------------------------------------------------------------- 1 | // SimAnneal.h 2 | 3 | #ifndef _SIMANNEAL_H_ 4 | #define _SIMANNEAL_H_ 5 | 6 | #include "BBox.h" 7 | #include "DataPlace.h" 8 | 9 | using namespace std; 10 | 11 | class SimAnneal { 12 | private: 13 | void generate(); 14 | void calibrate(); 15 | double cost(); 16 | bool accept(double newCost, double oldCost, double curTemp); 17 | void dynamic_window(); 18 | void update(double& curTemp); 19 | void update_Lam(double& curTemp); 20 | void anneal_detailed(); 21 | void anneal_global(); 22 | 23 | size_t I, maxI; 24 | size_t updateCount, maxUpdate; 25 | size_t acceptCount; 26 | double curRate; 27 | 28 | double windowfactor; 29 | double xspan, yspan; 30 | 31 | DataPlace& rb; 32 | BBox layoutBBox; 33 | double layoutXSize, layoutYSize, layoutArea; 34 | size_t maxIter; 35 | size_t calibMaxIter; 36 | double initTemp; 37 | double curTemp; 38 | double stopTemp; 39 | double k; 40 | 41 | bool greedy, detailed; 42 | double hpwl, avghpwl, totalhpwl; 43 | double overlap, avgoverlap, totaloverlap; 44 | double penaltyRow; 45 | double oldCost, newCost; 46 | double lambda, lambdaP; 47 | 48 | vector movables; 49 | vector oldPlace; 50 | vector newPlace; 51 | 52 | double posAcceptCount, negAcceptCount, totalCount; 53 | size_t itCount; 54 | 55 | void initPlacement(DataPlace& _rb); 56 | void fillingRows(DataPlace& _rb); 57 | 58 | public: 59 | SimAnneal(DataPlace& rbplace, bool gr, bool det); 60 | }; 61 | 62 | #endif -------------------------------------------------------------------------------- /UCLApack-43-040113.tar.gz_: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/en9inerd/SimAn/d267ded7c837cc2304b86da8d4fd6aa9a0977d74/UCLApack-43-040113.tar.gz_ -------------------------------------------------------------------------------- /paramproc.cpp: -------------------------------------------------------------------------------- 1 | #ifdef _MSC_VER 2 | #pragma warning(disable : 4786) 3 | #endif 4 | 5 | #include "paramproc.h" 6 | #include 7 | #include 8 | 9 | static char _uninitialized[] = "Uninitialized"; 10 | 11 | // using namespace std; 12 | 13 | Param::Param(Type pt, int argc, const char* const argv[]) 14 | : _b(false), 15 | _on(false), 16 | _i(INT_MAX), 17 | _u(unsigned(-1)), 18 | _d(-1.29384756657), 19 | _s(_uninitialized), 20 | _pt(pt), 21 | _key("") { 22 | // errproc(pt==NOPARAM," This constructor can only work with 23 | // Param:NOPARAM\n"); 24 | (void)argv; // please compiler 25 | 26 | _b = (argc < 2 ? true : false); 27 | return; 28 | } 29 | 30 | Param::Param(const char* key, Type pt, int argc, const char* const argv[]) 31 | : _b(false), 32 | _on(false), 33 | _i(-1), 34 | _u(unsigned(-1)), 35 | _d(-1.23456), 36 | _s(_uninitialized), 37 | _pt(pt), 38 | _key(key) { 39 | // errproc(strlen(_key)>0," Zero length key for command line parameter"); 40 | 41 | int n = 0; 42 | if (_pt == NOPARAM) { 43 | if (argc < 2) 44 | _b = true; 45 | else 46 | _b = false; 47 | return; 48 | } 49 | while (++n < argc && !found()) { 50 | if (argv[n][0] == '-' || argv[n][0] == '+') { 51 | const char* start = argv[n] + 1; 52 | if (argv[n][0] == '-') { 53 | if (argv[n][1] == '-') start++; 54 | } else 55 | _on = true; 56 | 57 | if (strcmp(start, _key) == 0) { 58 | _b = true; 59 | if (n + 1 < argc) { 60 | char tmp[80]; 61 | strncpy_s(tmp, argv[n + 1], 80); 62 | switch (_pt) { 63 | case BOOL: 64 | break; 65 | case INT: 66 | _i = atoi(argv[n + 1]); 67 | break; 68 | case UNSIGNED: 69 | _u = strtoul(argv[n + 1], (char**)NULL, 10); 70 | break; 71 | case DOUBLE: 72 | _d = atof(argv[n + 1]); 73 | break; 74 | case STRING: 75 | _s = argv[n + 1]; 76 | break; 77 | default: 78 | printf( 79 | " Unknown command line parameter"); // abkfatal(0," 80 | // Unknown 81 | // command 82 | // line 83 | // parameter"); 84 | } 85 | } 86 | } 87 | } 88 | } 89 | } 90 | 91 | bool Param::found() const { return _b; } 92 | 93 | bool Param::on() const // true for +option, false otherwise 94 | { 95 | // errproc(found()," Parameter not found: you need to check for this 96 | // first\n"); 97 | return _on; 98 | } 99 | 100 | int Param::getInt() const { 101 | // errproc(_pt==INT," Parameter is not INT "); 102 | // errproc(found()," Parameter not found: you need to check for this 103 | // first\n"); 104 | return _i; 105 | } 106 | 107 | unsigned Param::getUnsigned() const { 108 | // errproc(_pt==UNSIGNED," Parameter is not UNSIGNED "); 109 | // errproc(found(), 110 | // " UNSIGNED Parameter not found: you need to check for this first\n"); 111 | return _u; 112 | } 113 | 114 | double Param::getDouble() const { 115 | // errproc(_pt==DOUBLE," Parameter is not DOUBLE "); 116 | // errproc(found(), 117 | // " DOUBLE parameter not found: you need to check for this first\n"); 118 | return _d; 119 | } 120 | 121 | const char* Param::getString() const { 122 | // errproc(_pt==STRING," Parameter is not STRING"); 123 | // errproc(found(), 124 | // " STRING parameter not found: you need to check for this first\n"); 125 | return _s; 126 | } -------------------------------------------------------------------------------- /paramproc.h: -------------------------------------------------------------------------------- 1 | #ifndef PARAMPROC_H 2 | #define PARAMPROC_H 3 | 4 | //:(base class) Catches a given parameter from the command line 5 | class Param { 6 | public: 7 | enum Type { NOPARAM, BOOL, INT, UNSIGNED, DOUBLE, STRING }; 8 | // NOPARAM means "empty command line" 9 | // BOOL means "no value: either found in command line or not" 10 | private: 11 | bool _b; // found 12 | bool _on; 13 | int _i; 14 | unsigned _u; 15 | double _d; 16 | const char* _s; 17 | Type _pt; 18 | const char* _key; 19 | 20 | public: 21 | Param(const char* keyy, Type part, int argc, const char* const argv[]); 22 | Param(Type part, int argc, const char* const argv[]); // for NOPARAM only 23 | ~Param(){}; 24 | bool found() const; 25 | // for any Param::Type, always need to check before anything else 26 | bool on() const; 27 | // for any Param::Type; true if the option was invoked with + 28 | 29 | int getInt() const; 30 | unsigned getUnsigned() const; 31 | double getDouble() const; 32 | const char* getString() const; 33 | 34 | /* operator double() const; // deprecated : use below classes */ 35 | /* operator char* () const; // instead of Param */ 36 | }; 37 | 38 | //:Constructed from argc/argv, returns to true 39 | // if the command line had no parameters 40 | class NoParams : private Param { 41 | public: 42 | NoParams(int argc, const char* const argv[]) 43 | : Param(Param::NOPARAM, argc, argv) {} 44 | bool found() const { return Param::found(); } 45 | operator bool() const { return Param::found(); } 46 | Param::on; // base class member access adjustment 47 | }; 48 | 49 | //: Catches a given boolean parameter 50 | class BoolParam : private Param { 51 | public: 52 | BoolParam(const char* key, int argc, const char* const argv[]) 53 | : Param(key, Param::BOOL, argc, argv) {} 54 | bool found() const { return Param::found(); } 55 | operator bool() const { return Param::found(); } 56 | Param::on; // base class member access adjustment 57 | }; 58 | 59 | //: Catches a given Unsigned parameter 60 | class UnsignedParam : private Param { 61 | public: 62 | UnsignedParam(const char* key, int argc, const char* const argv[]) 63 | : Param(key, Param::UNSIGNED, argc, argv) {} 64 | bool found() const { 65 | return Param::found() && getUnsigned() != unsigned(-1); 66 | } 67 | operator unsigned() const { return getUnsigned(); } 68 | Param::on; // base class member access adjustment 69 | }; 70 | 71 | //: Catches a given integer parameter 72 | class IntParam : private Param { 73 | public: 74 | IntParam(const char* key, int argc, const char* const argv[]) 75 | : Param(key, Param::INT, argc, argv) {} 76 | bool found() const { return Param::found(); } 77 | operator int() const { return getInt(); } 78 | Param::on; // base class member access adjustment 79 | }; 80 | 81 | //: Catches a given double parameter 82 | class DoubleParam : private Param { 83 | public: 84 | DoubleParam(const char* key, int argc, const char* const argv[]) 85 | : Param(key, Param::DOUBLE, argc, argv) {} 86 | bool found() const { 87 | return Param::found() && getDouble() != -1.29384756657; 88 | } 89 | operator double() const { return getDouble(); } 90 | Param::on; // base class member access adjustment 91 | }; 92 | 93 | //: Catches a given string parameter 94 | class StringParam : private Param { 95 | public: 96 | StringParam(const char* key, int argc, const char* const argv[]) 97 | : Param(key, Param::STRING, argc, argv) {} 98 | bool found() const { 99 | return Param::found() && strcmp(getString(), "Uninitialized"); 100 | } 101 | operator const char*() const { return getString(); } 102 | Param::on; // base class member access adjustment 103 | }; 104 | 105 | #endif -------------------------------------------------------------------------------- /simulated annealing.cpp: -------------------------------------------------------------------------------- 1 | // simulated annealing.cpp : Defines the entry point for the console 2 | // application. 3 | 4 | #include 5 | #include 6 | #include "DataPlace.h" 7 | #include "SimAnneal.h" 8 | #include "paramproc.h" 9 | #include "visualization.h" 10 | 11 | using std::cerr; 12 | using std::cout; 13 | using std::ostream; 14 | using std::istream; 15 | using std::endl; 16 | 17 | DataPlace rbplace; 18 | 19 | int main(int argc, char* argv[]) { 20 | setlocale(LC_ALL, "Russian"); 21 | NoParams noParams(argc, argv); 22 | BoolParam helpRequest("help", argc, argv); 23 | BoolParam helpRequest1("h", argc, argv); 24 | StringParam auxFileName("f", argc, argv); 25 | StringParam outFileName("save", argc, argv); 26 | BoolParam keepOverlaps("skipLegal", argc, argv); 27 | // BoolParam detailed ("detailed",argc,argv); 28 | BoolParam greedy("greedy", argc, argv); 29 | // BoolParam viewer ("viewer",argc,argv); 30 | 31 | if (noParams.found() || helpRequest.found() || helpRequest1.found()) 32 | { 33 | cout<<" Use '-help' or '-f filename.aux' "<(clock() - start) / CLOCKS_PER_SEC; 66 | 67 | double HPWLafter = rbplace.evalHPWL(); 68 | 69 | cout << " Final Center-to-Center WL: " << HPWLafter << endl; 70 | cout << " % improvement in HPWL is " 71 | << (initHPWL - HPWLafter) * 100 / HPWLafter << endl; 72 | cout << "Time taken = " << GlobalTime << " seconds\n"; 73 | 74 | bool viewer = true; 75 | 76 | if (true) { 77 | cout << "ibm_SA_out.pl" << endl; 78 | rbplace.savePlacement("ibm_SA_out.pl"); 79 | } 80 | 81 | if (viewer) { 82 | cout << "\n\t --" << endl; 83 | opengl_control(argc, argv); 84 | } 85 | 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /visualization.cpp: -------------------------------------------------------------------------------- 1 | #include "visualization.h" 2 | #include 3 | 4 | extern DataPlace rbplace; 5 | 6 | float moving_x = 0, moving_y = 0, zoom = 0; 7 | int Rotate = 0, origx = 0, origy = 0, angle = 0; 8 | 9 | void draw_circle(double x, double y, double r) { 10 | const int t = 50; // на сколько частей делится окружность 11 | glBegin(GL_TRIANGLE_FAN); 12 | glVertex2f(x, y); //центр окружности 13 | for (int i = 0; i <= t; i++) { 14 | float a = (float)i / (float)t * 3.1415f * 2.0f; 15 | glVertex2f(x - cos(a) * r, y - sin(a) * r); 16 | } 17 | glEnd(); 18 | } 19 | 20 | void draw_quads(double x, double y, double a) { 21 | glBegin(GL_QUADS); 22 | glVertex2d(x - 0.5 * a, y + 0.5 * a); 23 | glVertex2d(x + 0.5 * a, y + 0.5 * a); 24 | glVertex2d(x + 0.5 * a, y - 0.5 * a); 25 | glVertex2d(x - 0.5 * a, y - 0.5 * a); 26 | glEnd(); 27 | } 28 | 29 | void draw_cross(double x, double y, double a) { 30 | glBegin(GL_LINES); 31 | glVertex2f(x - 0.5 * a, y - 0.5 * a); 32 | glVertex2f(x + 0.5 * a, y + 0.5 * a); 33 | glEnd(); 34 | 35 | glBegin(GL_LINES); 36 | glVertex2f(x - 0.5 * a, y + 0.5 * a); 37 | glVertex2f(x + 0.5 * a, y - 0.5 * a); 38 | glEnd(); 39 | } 40 | 41 | void draw_scene() { 42 | vector& nd = rbplace.nodes; 43 | vector& tr = rbplace.terminals; 44 | vector& rw = rbplace.rows; 45 | 46 | BBox layoutBBox(rbplace, true); 47 | double Xmin = layoutBBox.xMin; 48 | double Xmax = layoutBBox.xMax; 49 | double Ymin = layoutBBox.yMin; 50 | double Ymax = layoutBBox.yMax; 51 | 52 | BBox Core(rbplace); 53 | 54 | float sc = 0.1503 * fabs(Core.getHeight()); 55 | 56 | // double midX = 0.5*abs(Xmin - Xmax); 57 | // double midY = 0.5*abs(Ymin - Ymax); 58 | // glTranslated(midX, midY, 0); 59 | 60 | glColor3f(0.0, 0.0, 0.0); 61 | glBegin(GL_POLYGON); 62 | glVertex2f(Xmin / sc, Ymin / sc); 63 | glVertex2f(Xmax / sc, Ymin / sc); 64 | glVertex2f(Xmax / sc, Ymax / sc); 65 | glVertex2f(Xmin / sc, Ymax / sc); 66 | glEnd(); 67 | 68 | glLineWidth(3); 69 | glColor3f(0.5, 0.5, 0.5); 70 | glBegin(GL_LINE_LOOP); 71 | glVertex2f(Xmin / sc, Ymin / sc); 72 | glVertex2f(Xmax / sc, Ymin / sc); 73 | glVertex2f(Xmax / sc, Ymax / sc); 74 | glVertex2f(Xmin / sc, Ymax / sc); 75 | glEnd(); 76 | 77 | glLineWidth(1); 78 | glColor3f(0, 1.0, 0); 79 | glBegin(GL_LINE_LOOP); 80 | glVertex2f(Core.xMin / sc, Core.yMin / sc); 81 | glVertex2f(Core.xMax / sc, Core.yMin / sc); 82 | glVertex2f(Core.xMax / sc, Core.yMax / sc); 83 | glVertex2f(Core.xMin / sc, Core.yMax / sc); 84 | glEnd(); 85 | 86 | for (vector::iterator itR = rw.begin(); itR != rw.end(); itR++) { 87 | glBegin(GL_LINE_LOOP); 88 | glVertex2f(itR->coord_x / sc, itR->coord_y / sc); 89 | glVertex2f((itR->coord_x + itR->num_sites * itR->site_sp) / sc, 90 | itR->coord_y / sc); 91 | glVertex2f((itR->coord_x + itR->num_sites * itR->site_sp) / sc, 92 | (itR->coord_y + itR->h) / sc); 93 | glVertex2f(itR->coord_x / sc, (itR->coord_y + itR->h) / sc); 94 | glEnd(); 95 | } 96 | 97 | if (!tr.empty()) 98 | for (vector::iterator it = tr.begin(); it != tr.end(); it++) { 99 | glColor3f(1.0, 0, 0); 100 | glBegin(GL_POLYGON); 101 | glVertex2f(it->pos_x / sc, it->pos_y / sc); 102 | glVertex2f((it->pos_x + it->w) / sc, it->pos_y / sc); 103 | glVertex2f((it->pos_x + it->w) / sc, (it->pos_y + it->h) / sc); 104 | glVertex2f(it->pos_x / sc, (it->pos_y + it->h) / sc); 105 | glEnd(); 106 | } 107 | 108 | for (vector::iterator it = nd.begin(); it != nd.end(); it++) { 109 | glColor3f(1.0, 0, 0); 110 | glBegin(GL_LINE_LOOP); 111 | glVertex2f(it->pos_x / sc, it->pos_y / sc); 112 | glVertex2f((it->pos_x + it->w) / sc, it->pos_y / sc); 113 | glVertex2f((it->pos_x + it->w) / sc, (it->pos_y + it->h) / sc); 114 | glVertex2f(it->pos_x / sc, (it->pos_y + it->h) / sc); 115 | glEnd(); 116 | } 117 | } 118 | 119 | void render_scene() { 120 | glClearColor(255, 255, 255, 1); 121 | glClear(GL_COLOR_BUFFER_BIT); 122 | glViewport(0, 0, glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT)); 123 | glMatrixMode(GL_PROJECTION); 124 | glLoadIdentity(); 125 | gluPerspective(45, glutGet(GLUT_WINDOW_WIDTH) / glutGet(GLUT_WINDOW_HEIGHT), 126 | 0.1, 100); 127 | glTranslated(moving_x, moving_y, -10 + zoom); 128 | glRotatef(angle, 0, 0, 1); 129 | 130 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 131 | glEnable(GL_BLEND); 132 | glEnable(GL_LINE_SMOOTH); 133 | glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); 134 | glEnable(GL_POLYGON_SMOOTH); 135 | glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); 136 | 137 | draw_scene(); 138 | 139 | glutSwapBuffers(); 140 | } 141 | 142 | void keyboard_control(unsigned char key, int, int) { 143 | // поворот по часовой стрелке // 144 | if (key == 'a') { 145 | angle -= 10; 146 | glutPostRedisplay(); 147 | } 148 | // поворот против часовой стрелки // 149 | if (key == 's') { 150 | angle += 10; 151 | glutPostRedisplay(); 152 | } 153 | // вернуться к исходному виду // 154 | if (key == 'r') { 155 | angle = 0; 156 | zoom = 0; 157 | moving_x = moving_y = 0; 158 | glutPostRedisplay(); 159 | } 160 | // приблизить // 161 | if (key == '+') { 162 | zoom += 1; 163 | glutPostRedisplay(); 164 | } 165 | // отдалить // 166 | if (key == '-') { 167 | zoom -= 1; 168 | glutPostRedisplay(); 169 | } 170 | } 171 | 172 | void mouse_control(int button, int state, int x, int y) { 173 | switch (button) { 174 | case GLUT_LEFT_BUTTON: 175 | if (state == GLUT_DOWN) { 176 | origx = x; 177 | origy = y; 178 | Rotate = 1; 179 | } else 180 | Rotate = 0; 181 | break; 182 | } 183 | } 184 | 185 | void mouse_move(int x, int y) { 186 | if (Rotate) { 187 | int k = zoom <= 0 ? 60 : 40 * zoom; 188 | moving_x += (float)(x - origx) / k; 189 | moving_y -= (float)(y - origy) / k; 190 | origx = x; 191 | origy = y; 192 | glutPostRedisplay(); 193 | } 194 | } 195 | 196 | void timf(int value) { 197 | glutPostRedisplay(); 198 | glutTimerFunc(40, timf, 0); 199 | } 200 | 201 | void opengl_control(int argcp, char** argv) { 202 | glutInit(&argcp, argv); 203 | glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); 204 | glutInitWindowPosition(0, 0); 205 | glutInitWindowSize(800, 800); 206 | glutCreateWindow("Placement 2D Visualization"); 207 | glutDisplayFunc(render_scene); 208 | glutKeyboardFunc(keyboard_control); 209 | glutMouseFunc(mouse_control); 210 | glutMotionFunc(mouse_move); 211 | glutMainLoop(); 212 | } -------------------------------------------------------------------------------- /visualization.h: -------------------------------------------------------------------------------- 1 | #ifndef _VISUALIZATION_H_ 2 | #define _VISUALIZATION_H_ 3 | 4 | #include 5 | #include 6 | #include "BBox.h" 7 | #include "DataPlace.h" 8 | #pragma comment(lib, "glut32.lib") 9 | 10 | void draw_circle(double x, double y, double r); // отрисовывает окружность по 11 | // заданным координатам центра 12 | // и радиусу 13 | void draw_quads(double x, double y, double a); // отрисовывает квадрат по 14 | // заданным координатам центра и 15 | // длине стороны 16 | void draw_cross(double x, double y, double k); // отрисовывает крест по 17 | // заданным координатам центра и 18 | // коэффициенту масштабировани¤ 19 | void draw_scene(); // отрисовывает основную поверхность, на которой в 20 | // дальнейшем будут располагатьс¤ все элементы 21 | void render_scene(); // функци¤, внутри которой вызываютс¤ все функции OpenGL, 22 | // отвечающие за отрисовку 23 | void keyboard_control(unsigned char key, int, int); // функци¤, осуществл¤юща¤ 24 | // управление параметрами 25 | // отображени¤ с помощью 26 | // клавиатуры 27 | void mouse_control(int button, int state, int x, 28 | int y); // функци¤, осуществл¤юща¤ управление параметрами 29 | // отображени¤ с помощью мыши 30 | void mouse_move(int x, int y); // функци¤, осуществл¤юща¤ изменение параметров 31 | // отображени¤ в соответствии с перемещением 32 | // мыши 33 | void timf(int value); // функци¤, отвечающа¤ за автоматическое вращение сцены 34 | void opengl_control(int argcp, char **argv); // функци¤, внутри которой 35 | // осуществл¤етс¤ вызов всех 36 | // св¤занных с OpenGL функций 37 | 38 | #endif --------------------------------------------------------------------------------