00001
00002 #include "oagFpgaMapperUtils.h"
00003 #include "oagFpgaMapper.h"
00004 #include "oagFpga.h"
00005 #include "oagFpgaAiModGraph.h"
00006 #include "oagFpgaSimMod.h"
00007
00008 #include "oagFpgaManager.h"
00009 #include "oagFpgaDebug.h"
00010 #include <values.h>
00011
00012 using namespace oagFpga;
00013
00014 namespace oagMapper {
00015
00016
00017
00018
00023
00024 FpgaMapper::FpgaMapper(int cutsPerNode) {
00025
00026
00027 this->cutsPerNode = cutsPerNode;
00028
00029 gateCount = seqCount = 0;
00030
00031
00032 #ifdef CELL_MAPPING
00033
00034 addTrivialGates();
00035 #endif
00036
00037
00038 assert((1<<MAX_CUT_SIZE) <= TableEntry::MAX_WORDS*TableEntry::BITS_PER_WORD);
00039
00040
00041 initializeSimulation();
00042 }
00043
00044 #ifdef CELL_MAPPING
00045
00046
00047
00048
00055
00056 void
00057 FpgaMapper::useAlternateView(const oa::oaScalarName &viewName) {
00058 useAlternateViews = true;
00059 alternateViewName = viewName;
00060 }
00061
00062
00063
00064
00065
00070
00071
00072 void
00073 FpgaMapper::addTrivialGates() {
00074
00075
00076 for(int i=0; i<=MAX_CUT_SIZE; i++) {
00077
00078
00079 TableEntry constantEntry;
00080 constantEntry.cell = NULL;
00081 bzero(constantEntry.func, sizeof(int)*constantEntry.MAX_WORDS);
00082 constantEntry.N_input = 0;
00083 constantEntry.P = 0;
00084 constantEntry.directFlag = 0;
00085 constantEntry.constantFlag = 1;
00086 tables[i].push_back(constantEntry);
00087
00088
00089 for(int bit=0; bit<(1<<i); bit++) {
00090 constantEntry.setBit(bit, true);
00091 }
00092 tables[i].push_back(constantEntry);
00093
00094
00095
00096 for(int j=0; j<i; j++) {
00097 TableEntry wireEntry;
00098 wireEntry.cell = NULL;
00099 bzero(wireEntry.func, sizeof(int)*wireEntry.MAX_WORDS);
00100 wireEntry.directInput = j;
00101 wireEntry.P = 0;
00102 wireEntry.directFlag = 1;
00103 wireEntry.constantFlag = 0;
00104 for(int v=0; v<(1<<i); v++) {
00105 wireEntry.setBit(v, (v >> j) & 0x1);
00106 }
00107 tables[i].push_back(wireEntry);
00108 }
00109 }
00110 }
00111
00112
00113
00114
00126
00127 void
00128 FpgaMapper::addLibraryGate(oa::oaDesign* design) {
00129 assert(design);
00130
00131 oa::oaModule *module = design->getTopModule();
00132 assert(module);
00133 Manager *manager = Manager::get(design);
00134 if (!manager) {
00135 std::cout << "WARNING: Ignoring library cell. "
00136 << "Either it is structural or is missing a functional description." << std::endl;
00137 return;
00138 }
00139
00140 #if defined(DEBUG)
00141 oa::oaString modString;
00142 module->getName(oa::oaVerilogNS(), modString);
00143 DEBUG_PRINTLN(modString);
00144 #endif
00145
00146
00147 std::vector<oa::oaModTerm*> inputTerms;
00148 std::vector<oa::oaModTerm*> outputTerms;
00149 oa::oaModTerm *term;
00150 oa::oaIter<oa::oaModTerm> termIter(module->getTerms(oacTermIterSingleBit));
00151 while((term = termIter.getNext())) {
00152 if (term->getTermType() == oa::oacInputTermType) {
00153 inputTerms.push_back(term);
00154 } else if (term->getTermType() == oa::oacOutputTermType) {
00155 outputTerms.push_back(term);
00156 }
00157 }
00158
00159
00160 if (outputTerms.size() != 1) {
00161 std::cout << "WARNING: Ignoring library cell. "
00162 << "Multiple outputs are currently unsupported." << std::endl;
00163 return;
00164 }
00165
00166 if (inputTerms.size() == 0) return;
00167
00168
00169 oa::oaModBitNet *outputNet = oagFpga::toBitNet(outputTerms[0]->getNet());
00170 assert(outputNet);
00171 AiModRef outputNode = AiModGraph::getNetToAiConnection(outputNet);
00172 assert(!AiModGraph::isNull(outputNode));
00173
00174 int len = inputTerms.size();
00175 vector<oagFpga::AiModRef> inputNodes(len);
00176 for(int i=0; i<len; i++) {
00177 oa::oaModBitNet *net = oagFpga::toBitNet(inputTerms[i]->getNet());
00178 inputNodes[i] = AiModGraph::getNetToAiConnection(net);
00179 assert(!AiModGraph::isNull(inputNodes[i]));
00180 }
00181
00182
00183 if (len > MAX_CUT_SIZE) {
00184 std::cout << "WARNING: Ignoring library cell. "
00185 << "Too many inputs for the size of the truth tables." << std::endl;
00186 return;
00187 }
00188 assert(TableEntry::MAX_WORDS >= (1 << len)/TableEntry::BITS_PER_WORD);
00189
00190
00191 oa::oaDesign *implementDesign = NULL;
00192 if (useAlternateViews) {
00193
00194 oa::oaScalarName libName, viewName, cellName;
00195 design->getLibName(libName);
00196 design->getCellName(cellName);
00197 implementDesign = oa::oaDesign::find(libName, cellName, alternateViewName);
00198
00199 if (!implementDesign) {
00200 try {
00201 implementDesign = oa::oaDesign::open(libName, cellName, alternateViewName, 'r');
00202 assert(implementDesign);
00203 } catch (oa::oaException &e) {}
00204 }
00205 if (!implementDesign) {
00206
00207 oa::oaString viewString, cellString;
00208 alternateViewName.get(viewString);
00209 cellName.get(cellString);
00210 std::cerr << "ERROR: Could not find alternate view " << viewString
00211 << " for cell " << cellString << endl;
00212 QUIT_ON_ERROR;
00213 }
00214 } else {
00215 implementDesign = design;
00216 }
00217
00218 libraryCells.push_back(design);
00219
00220
00221 for(unsigned char N_input=0; N_input<(1<<len); N_input++) {
00222 TableEntry t;
00223 t.cell = design;
00224 t.implementCell = implementDesign;
00225 bzero(t.func, sizeof(int)*t.MAX_WORDS);
00226 t.N_input = N_input;
00227 t.P = 0;
00228 t.directFlag = t.constantFlag = 0;
00229 simulate(design, t, outputNode, inputNodes);
00230 DEBUG_PRINTMORE(" ");
00231 tables[len].push_back(t);
00232 if (len <= 1) break;
00233 }
00234
00235 DEBUG_PRINTMORE("\n");
00236 }
00237
00238 #endif // #ifdef CELL_MAPPING
00239
00240
00241
00242
00244
00245
00246 void
00247 FpgaMapper::initializeSimulation() {
00248 bzero(exhaustiveInputVectors, sizeof(unsigned int)*(MAX_CUT_SIZE)*TableEntry::MAX_WORDS);
00249 for(int v=0; v<(1<<MAX_CUT_SIZE); v++) {
00250 assert(v/TableEntry::BITS_PER_WORD < TableEntry::MAX_WORDS);
00251 for(int i=0; i<MAX_CUT_SIZE; i++) {
00252 exhaustiveInputVectors[i][v/TableEntry::BITS_PER_WORD] |= ((v >> i) & 0x1) << (v%TableEntry::BITS_PER_WORD);
00253 }
00254 }
00255 }
00256
00257
00258
00259
00260
00261
00268
00269
00270 void
00271 FpgaMapper::simulate(oa::oaDesign *design,
00272 TableEntry & outResult, oagFpga::AiModRef & out,
00273 const vector<oagFpga::AiModRef> cut) {
00274 assert(design);
00275
00276 const int cutWidth = cut.size();
00277
00278
00279
00280
00281
00282
00283
00284 static vector<oagAi::Ref> cone;
00285 cone.clear();
00286 static vector<oagAi::Ref> coneRoots;
00287 coneRoots.clear();
00288 coneRoots.reserve(cutWidth);
00289 for(int i=0; i<cutWidth; i++)
00290 coneRoots.push_back(cut[i].ref);
00291 Manager::get(design)->getAiGraph()->getFaninCone(out.ref, coneRoots, cone, false);
00292
00293 cone.push_back(out.ref);
00294
00295
00296 static SimMod sim(design);
00297
00298
00299 int bits = (1 << cutWidth);
00300 unsigned int word = 0;
00301 while(bits > 0) {
00302 assert(word < TableEntry::MAX_WORDS);
00303 for(int i=0; i<cutWidth; i++) {
00304 if ((outResult.N_input >> i) & 0x1) {
00305 sim.setVector(cut[i], ~exhaustiveInputVectors[i][word]);
00306 } else {
00307 sim.setVector(cut[i], exhaustiveInputVectors[i][word]);
00308 }
00309 }
00310
00311 for(vector<oagAi::Ref>::iterator it = cone.begin(); it!=cone.end(); it++) {
00312 sim.runOne(AiModRef(*it, out.module));
00313 }
00314 sim.getVector(out, outResult.func[word]);
00315 bits -= TableEntry::BITS_PER_WORD;
00316 word++;
00317 }
00318
00319
00320 if (bits < 0) {
00321 unsigned int mask = (0x1 << (bits + TableEntry::BITS_PER_WORD))-1;
00322 outResult.func[word-1] &= mask;
00323 }
00324
00325 #if defined(DEBUG)
00326
00327 for(unsigned int b=0; b<TableEntry::BITS_PER_WORD*TableEntry::MAX_WORDS; b++)
00328 cout << (outResult.getBit(b) ? "1" : "0");
00329 #endif
00330 }
00331
00332
00333
00334
00340
00341 void
00342 FpgaMapper::setAreaCosts() {
00343
00344 #ifdef CELL_MAPPING
00345
00346
00347 for(int i=0; i<=MAX_CUT_SIZE; i++) {
00348 for(unsigned int j=0; j<tables[i].size(); j++) {
00349 TableEntry *choice = &(tables[i][j]);
00350
00351
00352 if (choice->directFlag || choice->constantFlag) {
00353 choice->cost = 0.0;
00354 continue;
00355 }
00356 assert(choice->implementCell);
00357
00358
00359 oa::oaBlock *topBlock;
00360 if ((topBlock = choice->implementCell->getTopBlock())) {
00361
00362 oa::oaBox box;
00363 topBlock->getBBox(box);
00364 choice->cost = box.getWidth()*box.getHeight();
00365 if (choice->cost > 0) continue;
00366
00367
00368 oa::oaTerm *term;
00369 oa::oaIter<oa::oaTerm> termIter = topBlock->getTerms(oacTermIterSingleBit);
00370 int numInputs = 0;
00371 while((term = termIter.getNext())) {
00372 if (term->getTermType() == oa::oacInputTermType) {
00373 numInputs++;
00374 }
00375 }
00376 choice->cost = numInputs;
00377 continue;
00378 }
00379
00380
00381 oa::oaModule *topModule;
00382 if ((topModule = choice->implementCell->getTopModule())) {
00383
00384 oa::oaModTerm *term;
00385 oa::oaIter<oa::oaModTerm> termIter = topModule->getTerms(oacTermIterSingleBit);
00386 int numInputs = 0;
00387 while((term = termIter.getNext())) {
00388 if (term->getTermType() == oa::oacInputTermType) {
00389 numInputs++;
00390 }
00391 }
00392 choice->cost = numInputs;
00393 continue;
00394 }
00395
00396 cerr << "ERROR: Library cell has neither top block nor top module" << endl;
00397 QUIT_ON_ERROR;
00398 }
00399 }
00400 #else // #ifdef CELL_MAPPING
00401
00402 this->mapUtils.lutArea = 1.0;
00403 this->mapUtils.seqArea = 1.0;
00404
00405 #endif // #ifdef CELL_MAPPING
00406 }
00407
00408
00409
00410
00411
00412
00418
00419 void
00420 FpgaMapper::setDelayCosts() {
00421
00422 #ifdef CELL_MAPPING
00423
00424
00425 for(int i=0; i<=MAX_CUT_SIZE; i++) {
00426 for(unsigned int j=0; j<tables[i].size(); j++) {
00427 TableEntry *choice = &(tables[i][j]);
00428
00429
00430 if (choice->directFlag || choice->constantFlag) {
00431 choice->cost = 0.0;
00432 continue;
00433 }
00434
00435 choice->cost = 1.0;
00436 }
00437 }
00438 #else // #ifdef CELL_MAPPING
00439
00440 this->mapUtils.lutDelay = 1.0;
00441 this->mapUtils.seqDelay = 0.0;
00442
00443 #endif // #ifdef CELL_MAPPING
00444 }
00445
00446
00447
00448
00449
00458
00459 double
00460 FpgaMapper::getCumulativeAreaCost(AiModGraph::Cut *cut, TableEntry *choice) {
00461 assert(cut);
00462 assert(choice);
00463
00464
00465 double cost = choice->cost;
00466
00467 int i=0;
00468 for(AiModGraph::Cut::iterator it = cut->begin(); it!= cut->end(); it++) {
00469 if ((choice->N_input >> i) & 0x1) {
00470
00471 assert(cost_n.find(*it) != cost_n.end());
00472 cost += cost_n[*it];
00473 } else {
00474
00475 assert(cost_p.find(*it) != cost_p.end());
00476 cost += cost_p[*it];
00477 }
00478 i++;
00479 }
00480 return cost;
00481 }
00482
00483
00484
00485
00486
00492
00493 double
00494 FpgaMapper::getCumulativeDelayCost(AiModGraph::Cut *cut, TableEntry *choice) {
00495 assert(cut);
00496 assert(choice);
00497
00498
00499 double cost = 0.0;
00500 int i=0;
00501 for(AiModGraph::Cut::iterator it = cut->begin(); it!= cut->end(); it++) {
00502 if ((choice->N_input >> i) & 0x1) {
00503
00504 assert(cost_n.find(*it) != cost_n.end());
00505 cost >?= cost_n[*it];
00506 } else {
00507
00508 assert(cost_p.find(*it) != cost_p.end());
00509 cost >?= cost_p[*it];
00510 }
00511 i++;
00512 }
00513 return cost + choice->cost;
00514 }
00515
00516
00517
00518
00519
00532
00533 void
00534 FpgaMapper::techmapArea(oa::oaModule *target) {
00535 assert(target);
00536
00537 cout << "Mapping for area..." << endl;
00538
00539 #ifdef CELL_MAPPING
00540
00541 if (libraryCells.empty()) {
00542 cerr << "ERROR: Empty combinational library. Aborting." << endl;
00543 return;
00544 }
00545 #endif // #ifdef CELL_MAPPING
00546
00547 Manager *currentManager = Manager::get(target->getDesign());
00548 if (currentManager->isStructural()) {
00549
00550 cerr << "ERROR: Target is already structural or is missing functional "
00551 << "description. Aborting." << endl;
00552 return;
00553 }
00554
00555
00556 AiModGraph::clearKfeasibleCuts(target);
00557 cut_p.clear(); cut_n.clear();
00558 choice_p.clear(); choice_n.clear();
00559 cost_p.clear(); cost_n.clear();
00560 totalArea = totalDelay = 0;
00561
00562
00563 if (AiModGraph::hasCombinationalCycle(target)) {
00564 cerr << "ERROR: Target graph has a combinational cycle" << endl;
00565 QUIT_ON_ERROR;
00566 }
00567
00568
00569 setAreaCosts();
00570
00571 #ifdef CELL_MAPPING
00572
00573
00574 if (!mapUtils.notGate) {
00575 mapUtils.identifyNot(libraryCells);
00576 }
00577 if (!mapUtils.notGate) {
00578 cerr << "ERROR : Could not identify inverter in cell library" << endl;
00579 QUIT_ON_ERROR;
00580 }
00581 mapUtils.identifyNotTerminals();
00582 notEntry = NULL;
00583 for(unsigned int i = 0; i < tables[1].size(); i++) {
00584 if (tables[1][i].cell == mapUtils.notGate) {
00585 notEntry = &(tables[1][i]);
00586 break;
00587 }
00588 }
00589 assert(notEntry);
00590
00591
00592 if (!mapUtils.seqGate) {
00593 cerr << "ERROR : Could not sequential gate in cell library" << endl;
00594 QUIT_ON_ERROR;
00595 }
00596 mapUtils.identifySeqTerminalsByName();
00597 #else
00598
00599
00600
00601
00602 bzero(notEntry.func, sizeof(int)*notEntry.MAX_WORDS);
00603 notEntry.setBit(0, true);
00604 notEntry.cost = 0.;
00605
00606 bzero(constantZeroEntry.func, sizeof(int)*constantZeroEntry.MAX_WORDS);
00607 constantZeroEntry.cost = 0.;
00608
00609 #endif // #ifdef CELL_MAPPING
00610
00611
00612 mapUtils.identifyControls(target);
00613 mapUtils.removeAsyncResetsFromLogic(target);
00614
00615
00616 AiModRef constantZero = AiModGraph::constantZero(target);
00617 oa::oaModNet *constantNet = oa::oaModNet::find(target,
00618 oa::oaScalarName(oa::oaNativeNS(), "tie0"));
00619 if (constantNet) {
00620 AiModGraph::setTerminalDriver(AiModGraph::getNetToAiConnection(toBitNet(constantNet)),
00621 constantZero);
00622 }
00623 constantNet = oa::oaModNet::find(target,
00624 oa::oaScalarName(oa::oaNativeNS(), "tie1"));
00625 if (constantNet) {
00626 AiModGraph::setTerminalDriver(AiModGraph::getNetToAiConnection(toBitNet(constantNet)),
00627 AiModGraph::constantOne(target));
00628 }
00629
00630
00631
00632
00633 list<AiModRef> outputsToMap, seqNodes;
00634 AiModGraph::getOutputs(target, outputsToMap);
00635 AiModGraph::getLocalStates(target, seqNodes);
00636 for(list<AiModRef>::iterator it = seqNodes.begin();
00637 it != seqNodes.end(); it++) {
00638 if (!AiModGraph::isNull(AiModGraph::getNextState(*it))) {
00639 outputsToMap.push_back(AiModGraph::getNextState(*it));
00640 }
00641 }
00642
00643 vector<AiModRef> nodesToMap;
00644 AiModGraph::getTransitiveFanin(outputsToMap, nodesToMap, true);
00645 for(list<AiModRef>::iterator it = outputsToMap.begin();
00646 it != outputsToMap.end(); it++) {
00647 nodesToMap.push_back(*it);
00648 }
00649
00650
00651
00652 cout << "\tnum. nodes to map = " << nodesToMap.size() << endl;
00653 cout << "\t(i) collecting best choice for each node" << endl;
00654 cout.flush();
00655
00656 int m = 0;
00657 static_cast<void>(m);
00658
00659
00660 for(vector<AiModRef>::iterator it = nodesToMap.begin();
00661 it != nodesToMap.end(); it++) {
00662 AiModRef mapPoint = AiModGraph::getNonInverted(*it);
00663 AiModGraph::Cut selfCut;
00664 selfCut.insert(selfCut.begin(), mapPoint);
00665
00666
00667 #if !defined(DEBUG)
00668 m++;
00669 if (m%1000 == 0) { cout << "."; cout.flush(); }
00670 #else
00671 DEBUG_PRINT("Mapping node ");
00672 mapPoint.print();
00673 #endif
00674
00675 if (mapPoint == constantZero) {
00676 cost_p[mapPoint] = 0;
00677 cost_n[mapPoint] = 0;
00678 } else if (AiModGraph::isTerminal(mapPoint) &&
00679 AiModGraph::isNull(AiModGraph::getTerminalDriver(mapPoint)) ||
00680 AiModGraph::isSequential(mapPoint)) {
00681 cost_p[mapPoint] = 0;
00682 cut_n[mapPoint] = selfCut;
00683 choice_n[mapPoint] = ¬Entry;
00684 cost_n[mapPoint] = notEntry.cost;
00685 } else {
00686
00687
00688 AiModGraph::CutSet cuts = AiModGraph::enumerateKfeasibleCuts(
00689 mapPoint, MAX_CUT_SIZE, cutsPerNode, -1, true);
00690
00691
00692 double minCost_p = DBL_MAX,
00693 minCost_n = DBL_MAX;
00694 AiModGraph::Cut *bestCut_p = NULL,
00695 *bestCut_n = NULL;
00696 TableEntry *bestChoice_p = NULL,
00697 *bestChoice_n = NULL;
00698
00699 for(list<AiModGraph::Cut>::iterator cut_it = cuts.begin(); cut_it != cuts.end(); cut_it++) {
00700 AiModGraph::Cut *currentCut = &(*cut_it);
00701 assert(currentCut);
00702 int cutWidth = currentCut->size();
00703 assert(cutWidth <= MAX_CUT_SIZE);
00704
00705
00706 if (cutWidth == 1 && *(currentCut->begin()) == mapPoint) continue;
00707
00708
00709 DEBUG_PRINT("\tcut {");
00710 int p = 0;
00711 vector<AiModRef> cutArray(cutWidth);
00712 for(set<AiModRef>::iterator cut_it = currentCut->begin();
00713 cut_it != currentCut->end(); cut_it++) {
00714 DEBUG_PRINTMORE(cut_it->ref << ", ");
00715 assert(p < cutWidth);
00716 cutArray[p++] = *cut_it;
00717 }
00718 DEBUG_PRINTMORE("} ");
00719
00720
00721 TableEntry cutFunction;
00722 simulate(target->getDesign(), cutFunction, mapPoint, cutArray);
00723
00724 TableEntry complementFunction;
00725 memcpy(&complementFunction, &cutFunction, sizeof(TableEntry));
00726 for(int bit=0; bit<(1<<cutWidth); bit++) {
00727 complementFunction.setBit(bit, !complementFunction.getBit(bit));
00728 }
00729 #ifdef CELL_MAPPING
00730
00731 for(vector<TableEntry>::iterator lib_it = tables[cutWidth].begin();
00732 lib_it != tables[cutWidth].end(); lib_it++) {
00733 TableEntry *currentChoice = &(*lib_it);
00734 assert(currentChoice);
00735
00736
00737 if (currentChoice->match(cutFunction)) {
00738
00739 if (currentChoice->cell) {
00740 oa::oaScalarName gateName;
00741 currentChoice->cell->getCellName(gateName);
00742 oa::oaString gateString;
00743 gateName.get(gateString);
00744 DEBUG_PRINTMORE(" " << gateString);
00745 } else if (currentChoice->directFlag) {
00746 DEBUG_PRINTMORE(" WIRE");
00747 } else if (currentChoice->constantFlag) {
00748 DEBUG_PRINTMORE(" CONST");
00749 }
00750
00751 if (getCumulativeAreaCost(currentCut, currentChoice) < minCost_p) {
00752 minCost_p = getCumulativeAreaCost(currentCut, currentChoice);
00753 bestChoice_p = currentChoice;
00754 bestCut_p = currentCut;
00755 }
00756 }
00757
00758
00759 if (currentChoice->match(complementFunction)) {
00760
00761 if (currentChoice->cell) {
00762 oa::oaScalarName gateName;
00763 currentChoice->cell->getCellName(gateName);
00764 oa::oaString gateString;
00765 gateName.get(gateString);
00766 DEBUG_PRINTMORE(" !" << gateString);
00767 } else if (currentChoice->directFlag) {
00768 DEBUG_PRINTMORE(" !WIRE");
00769 } else if (currentChoice->constantFlag) {
00770 DEBUG_PRINTMORE(" !CONST");
00771 }
00772
00773 if (getCumulativeAreaCost(currentCut, currentChoice) < minCost_n) {
00774 minCost_n = getCumulativeAreaCost(currentCut, currentChoice);
00775 bestChoice_n = currentChoice;
00776 bestCut_n = currentCut;
00777 }
00778 }
00779 }
00780 #else
00781
00782
00783
00784
00785 TableEntry *currentChoice = new TableEntry(cutFunction);
00786 minCost_p = getCumulativeAreaCost(currentCut, currentChoice);
00787 bestChoice_p = currentChoice;
00788 bestCut_p = currentCut;
00789
00790 currentChoice = new TableEntry(complementFunction);
00791 minCost_n = getCumulativeAreaCost(currentCut, currentChoice);
00792 bestChoice_n = currentChoice;
00793 bestCut_n = currentCut;
00794
00795 #endif // #ifdef CELL_MAPPING
00796
00797 DEBUG_PRINTMORE(endl);
00798 }
00799
00800
00801 if (!bestChoice_p && !bestChoice_n) {
00802 cerr << endl << "ERROR: Could not find a mapping for ";
00803 mapPoint.print();
00804 cerr << " This shouldn't happen. Perhaps the cut count/depth is too small?" << endl;
00805 QUIT_ON_ERROR;
00806 }
00807
00808
00809 #ifdef CELL_MAPPING
00810 if (minCost_p + notEntry->cost < minCost_n) {
00811 minCost_n = minCost_p + notEntry->cost;
00812 bestChoice_n = notEntry;
00813 bestCut_n = &selfCut;
00814 DEBUG_PRINTLN("\tself-cut {} !p");
00815 }
00816 if (minCost_n + notEntry->cost < minCost_p) {
00817 minCost_p = minCost_n + notEntry->cost;
00818 bestChoice_p = notEntry;
00819 bestCut_p = &selfCut;
00820 DEBUG_PRINTLN("\tself-cut {} !n");
00821 }
00822 #else
00823 assert(minCost_p == minCost_n);
00824
00825 #endif // #ifdef CELL_MAPPING
00826 DEBUG_PRINTLN("\tp-cost = " << minCost_p << " n-cost = " << minCost_n);
00827 cost_p[mapPoint] = minCost_p;
00828 cost_n[mapPoint] = minCost_n;
00829 assert(bestChoice_p);
00830 choice_p[mapPoint] = bestChoice_p;
00831 assert(bestChoice_n);
00832 choice_n[mapPoint] = bestChoice_n;
00833 assert(bestCut_p);
00834 cut_p[mapPoint] = *bestCut_p;
00835 assert(bestCut_n);
00836 cut_n[mapPoint] = *bestCut_n;
00837 }
00838 }
00839
00840
00841
00842 cout << endl << "\t(ii) implementing best global choices" << endl;
00843
00844 implementAll(target);
00845
00846
00847
00848 cout << "\t(iii) cleaning up" << endl;
00849 AiModGraph::clearKfeasibleCuts(target);
00850
00851
00852 oa::oaModNet *net;
00853 oa::oaIter<oa::oaModNet> netIter(target->getNets(oacNetIterSingleBit));
00854 while((net = netIter.getNext())) {
00855 AiModRef termNode = AiModGraph::getNetToAiConnection(toBitNet(net));
00856 if (AiModGraph::isTerminal(termNode)) {
00857 AiModGraph::detach(termNode);
00858 }
00859 }
00860
00861 if (target->getDesign()->getModules().getCount() == 1) {
00862 Manager::destroy(target->getDesign());
00863 }
00864
00865 cout << "\tarea cost = " << totalArea << endl;
00866 }
00867
00868
00869
00870
00871
00878
00879
00880 void
00881 FpgaMapper::implementAll(oa::oaModule *target) {
00882 assert(target);
00883
00884 list<AiModRef> toBeImplemented;
00885
00886 #ifdef DEBUG
00887 cerr << "Begin to make all bus nets and terms explicit" << endl;
00888 #endif
00889
00890
00891 oa::oaModNet *net;
00892 oa::oaIter<oa::oaModNet> explicitNetIter(target->getNets(oacNetIterNotImplicit));
00893 while((net = explicitNetIter.getNext())) {
00894 assert(net);
00895 if(!net->isImplicit() && net->getNumBits() > 1) {
00896 net->scalarize();
00897 }
00898 }
00899 oa::oaModTerm *term;
00900 oa::oaIter<oa::oaModTerm> explicitTermIter(target->getTerms(oacTermIterNotImplicit));
00901 while((term = explicitTermIter.getNext())) {
00902 assert(term);
00903 if(!term->isImplicit() && term->getNumBits() > 1) {
00904 term->scalarize();
00905 }
00906 }
00907
00908 #ifdef DEBUG
00909 cerr << "Begin to map all existing wires" << endl;
00910 #endif
00911
00912
00913 oa::oaIter<oa::oaModNet> netIter(target->getNets(oacNetIterSingleBit));
00914 while((net = netIter.getNext())) {
00915 oa::oaModBitNet *bitNet = toBitNet(net);
00916 assert(bitNet);
00917 AiModRef ref = AiModGraph::getNetToAiConnection(bitNet);
00918 if (AiModGraph::isNull(ref)) continue;
00919 assert(AiModGraph::isTerminal(ref));
00920 if (!AiModGraph::isNull(AiModGraph::getTerminalDriver(ref))) continue;
00921 mapped[ref] = bitNet;
00922 }
00923
00924 #ifdef DEBUG
00925 cerr << "Begin to pre-map sequential nodes" << endl;
00926 #endif
00927
00928
00929 map<AiModRef, oa::oaModInst*> seqInsts;
00930 list<AiModRef> outputsToMap, seqNodes;
00931 AiModGraph::getLocalStates(target, seqNodes);
00932 for(list<AiModRef>::iterator it = seqNodes.begin();
00933 it != seqNodes.end(); it++) {
00934 seqInsts[*it] = implementSeqNode(*it);
00935 }
00936
00937 #ifdef DEBUG
00938 cerr << "Begin to map sequential nodes" << endl;
00939 #endif
00940
00941
00942 for(list<AiModRef>::iterator it = seqNodes.begin();
00943 it != seqNodes.end(); it++) {
00944 AiModRef nextState = AiModGraph::getNextState(*it);
00945 if (!AiModGraph::isNull(nextState)) {
00946 oa::oaModBitNet *mapped_in = implementNode(nextState);
00947 assert(mapped_in);
00948 oa::oaModInstTerm::create(mapped_in, seqInsts[*it], mapUtils.seqInput);
00949 }
00950 }
00951
00952 #ifdef DEBUG
00953 cerr << "Begin to map primary outputs" << endl;
00954 #endif
00955
00956
00957 oa::oaIter<oa::oaModTerm> termIter(target->getTerms(oacTermIterSingleBit));
00958 while((term = termIter.getNext())) {
00959 oa::oaModBitNet *oldNet = toBitNet(term->getNet());
00960 assert(oldNet);
00961
00962 AiModRef ref = AiModGraph::getNetToAiConnection(oldNet);
00963 assert(!AiModGraph::isNull(ref));
00964 oa::oaModBitNet *newNet = implementNode(ref);
00965 assert(newNet);
00966
00967 term->moveToNet(newNet);
00968 }
00969 }
00970
00971
00972
00973
00974
00982
00983 oa::oaModInst *
00984 FpgaMapper::implementSeqNode(oagFpga::AiModRef ref) {
00985 oa::oaModule *currentModule = ref.module;
00986 assert(currentModule);
00987
00988 #ifdef DEBUG
00989 cerr << "begin to create new sequential gate" << endl;
00990 #endif
00991
00992 oa::oaModScalarInst *inst = oa::oaModScalarInst::create(currentModule, mapUtils.seqGate);
00993 #ifdef DEBUG
00994 cerr << "end to create new sequential gate" << endl;
00995 #endif
00996
00997
00998 oa::oaModBitNet *mapped_out = oa::oaModScalarNet::create(currentModule);
00999 assert(!mapped_out->isImplicit());
01000 oa::oaModInstTerm::create(mapped_out, inst, mapUtils.seqOutput);
01001 mapped[ref] = mapped_out;
01002
01003
01004 #ifdef CELL_MAPPING
01005
01006 mapUtils.connectAllControls(ref, inst);
01007 #endif
01008
01009 return inst;
01010 }
01011
01012
01013
01014
01015
01027
01028 oa::oaModBitNet *
01029 FpgaMapper::implementNode(oagFpga::AiModRef ref) {
01030
01031
01032 if (mapped.find(ref) != mapped.end()) {
01033 return mapped[ref];
01034 }
01035
01036 DEBUG_PRINTLN("Implementing node " << ref.ref);
01037
01038 oa::oaModule *currentModule = ref.module;
01039 assert(currentModule);
01040
01041
01042 if (AiModGraph::isTerminal(ref) && !AiModGraph::isInverted(ref) &&
01043 AiModGraph::isNull(AiModGraph::getTerminalDriver(ref)) ||
01044 AiModGraph::isAnd(ref) && AiModGraph::isNull(AiModGraph::getAndRight(ref)) &&
01045 AiModGraph::isNull(AiModGraph::getAndLeft(ref))) {
01046
01047 oa::oaModNet *constantNet = oa::oaModNet::find(currentModule,
01048 oa::oaScalarName(oa::oaNativeNS(), "tie0"));
01049 assert(constantNet);
01050 mapped[ref] = toBitNet(constantNet);
01051 DEBUG_PRINTLN("\tfloating... tying to zero");
01052 return toBitNet(constantNet);
01053 }
01054
01055
01056 if (ref == AiModGraph::constantZero(currentModule)) {
01057 oa::oaModNet *constantNet = oa::oaModNet::find(currentModule,
01058 oa::oaScalarName(oa::oaNativeNS(), "tie0"));
01059 assert(constantNet);
01060 mapped[ref] = toBitNet(constantNet);
01061 DEBUG_PRINTLN("\tconstant zero");
01062 return toBitNet(constantNet);
01063 } else if (ref == AiModGraph::constantOne(currentModule)) {
01064 oa::oaModNet *constantNet = oa::oaModNet::find(currentModule,
01065 oa::oaScalarName(oa::oaNativeNS(), "tie1"));
01066 assert(constantNet);
01067 mapped[ref] = toBitNet(constantNet);
01068 DEBUG_PRINTLN("\tconstant one");
01069 return toBitNet(constantNet);
01070 }
01071
01072
01073 TableEntry *choice;
01074 AiModGraph::Cut *cut;
01075 if (AiModGraph::isInverted(ref)) {
01076
01077 choice = choice_n[AiModGraph::getNonInverted(ref)];
01078 cut = &(cut_n[AiModGraph::getNonInverted(ref)]);
01079 totalDelay >?= cost_n[AiModGraph::getNonInverted(ref)];
01080 } else {
01081
01082 choice = choice_p[AiModGraph::getNonInverted(ref)];
01083 cut = &(cut_p[AiModGraph::getNonInverted(ref)]);
01084 totalDelay >?= cost_p[AiModGraph::getNonInverted(ref)];
01085 }
01086 if (!choice || !cut) {
01087 ref.print();
01088 oa::oaModBitNet *net = AiModGraph::getNetToAiConnection(ref);
01089 oa::oaString n;
01090 net->getName(oa::oaVerilogNS(), n);
01091 cout << n << endl;
01092 }
01093 assert(choice);
01094 assert(cut);
01095
01096 #ifdef CELL_MAPPING
01097
01098
01099 if (choice->directFlag) {
01100
01101 int inputNum = choice->directInput;
01102 for(AiModGraph::Cut::iterator it = cut->begin(); it != cut->end(); it++) {
01103 if (!inputNum) {
01104 assert(*it != ref);
01105 DEBUG_PRINTLN("\twire");
01106 return implementNode(*it);
01107 }
01108 --inputNum;
01109 }
01110 assert(false);
01111 }
01112 if (choice->constantFlag) {
01113
01114 oa::oaModNet *constantNet;
01115 if (choice->func[0] & 0x1) {
01116 constantNet = oa::oaModNet::find(currentModule, oa::oaScalarName(oa::oaNativeNS(), "tie1"));
01117 } else {
01118 constantNet = oa::oaModNet::find(currentModule, oa::oaScalarName(oa::oaNativeNS(), "tie0"));
01119 }
01120 assert(constantNet);
01121 mapped[ref] = toBitNet(constantNet);
01122 DEBUG_PRINTLN("\tconstant");
01123 return toBitNet(constantNet);
01124 }
01125 #endif // #ifdef CELL_MAPPING
01126
01127
01128 #ifdef CELL_MAPPING
01129 assert(choice->implementCell);
01130 oa::oaModScalarInst *inst = oa::oaModScalarInst::create(currentModule, choice->implementCell);
01131 #if defined(DEBUG)
01132 oa::oaString gateString;
01133 choice->implementCell->getCellName(oa::oaVerilogNS(), gateString);
01134 DEBUG_PRINTLN("\tgate " << gateString);
01135 #endif
01136 #else
01137
01138 cerr << "begin to create a modual instant" << endl;
01139
01140 #ifdef YU_TEST
01141
01142 oa::oaString lutCellNameString, lutModuleNameString;
01143 mapUtils.getLut()->getCellName(oa::oaNativeNS(),lutCellNameString);
01144 mapUtils.getLut()->getTopModule()->getName(oa::oaNativeNS(), lutModuleNameString);
01145 cerr << "the LUT design's name is " << lutCellNameString << endl;
01146 cerr << "the LUT module's name is " << lutModuleNameString << endl;
01147 #endif // #ifdef YU_TEST
01148
01149 oa::oaModScalarInst *inst = oa::oaModScalarInst::create(currentModule, mapUtils.getLut());
01150 cerr << "end to create a modual instant" << endl;
01151 #endif // #ifdef CELL_MAPPING
01152 totalArea += choice->cost;
01153
01154
01155 int num = 0;
01156 oa::oaModTerm *term, *outputTerm = NULL;
01157 oa::oaIter<oa::oaModTerm> termIter(mapUtils.getLut()->getTopModule()->getTerms(oacTermIterSingleBit));
01158 for(AiModGraph::Cut::iterator it = cut->begin(); it != cut->end(); it++, num++) {
01159 AiModRef cutRef = *it;
01160 assert(!AiModGraph::isNull(cutRef));
01161 assert(!AiModGraph::isInverted(cutRef));
01162
01163
01164 if ((choice->N_input >> num) & 0x1) {
01165 #ifndef CELL_MAPPING
01166 assert(0);
01167 #endif // #ifndef CELL_MAPPING
01168 cutRef = AiModGraph::notOf(cutRef);
01169 }
01170
01171 if (choice == ¬Entry && cutRef == ref) {
01172 #ifndef CELL_MAPPING
01173 assert(0);
01174 #endif // #ifndef CELL_MAPPING
01175 cutRef = AiModGraph::notOf(cutRef);
01176 }
01177 assert(cutRef != ref);
01178
01179
01180 while((term = termIter.getNext())) {
01181 if (term->getTermType() == oa::oacInputTermType) {
01182 break;
01183 } else if (term->getTermType() == oa::oacOutputTermType) {
01184 assert(!outputTerm);
01185 outputTerm = term;
01186 }
01187 }
01188 assert(term);
01189
01190 oa::oaModBitNet *mapped_in = implementNode(cutRef);
01191 assert(mapped_in);
01192 assert(!mapped_in->isImplicit());
01193 oa::oaModInstTerm::create(mapped_in, inst, term);
01194 }
01195
01196
01197 while(!outputTerm && (term = termIter.getNext())) {
01198 if (term->getTermType() == oa::oacOutputTermType) {
01199 outputTerm = term;
01200 }
01201 }
01202 assert(outputTerm);
01203
01204
01205 oa::oaModBitNet *mapped_out = oa::oaModScalarNet::create(currentModule);
01206 assert(!mapped_out->isImplicit());
01207 oa::oaModInstTerm::create(mapped_out, inst, outputTerm);
01208
01209 mapped[ref] = mapped_out;
01210 return mapped_out;
01211 }
01212
01213
01214
01215
01216
01223
01224 void
01225 FpgaMapper::techmapDelay(oa::oaModule *target) {
01226
01227 assert(target);
01228
01229 cout << "Mapping for delay..." << endl;
01230
01231 #ifdef CELL_MAPPING
01232
01233 if (libraryCells.empty()) {
01234 cerr << "ERROR: Empty combinational library. Aborting." << endl;
01235 return;
01236 }
01237 #endif // #ifdef CELL_MAPPING
01238
01239 Manager *currentManager = Manager::get(target->getDesign());
01240 if (currentManager->isStructural()) {
01241
01242 cerr << "ERROR: Target is already structural or is missing functional "
01243 << "description. Aborting." << endl;
01244 return;
01245 }
01246
01247
01248 AiModGraph::clearKfeasibleCuts(target);
01249 cut_p.clear(); cut_n.clear();
01250 choice_p.clear(); choice_n.clear();
01251 cost_p.clear(); cost_n.clear();
01252 totalArea = totalDelay = 0;
01253
01254
01255 if (AiModGraph::hasCombinationalCycle(target)) {
01256 cerr << "ERROR: Target graph has a combinational cycle" << endl;
01257 QUIT_ON_ERROR;
01258 }
01259
01260
01261 setDelayCosts();
01262
01263 #ifdef CELL_MAPPING
01264
01265
01266 if (!mapUtils.notGate) {
01267 mapUtils.identifyNot(libraryCells);
01268 }
01269 if (!mapUtils.notGate) {
01270 cerr << "ERROR : Could not identify inverter in cell library" << endl;
01271 QUIT_ON_ERROR;
01272 }
01273 mapUtils.identifyNotTerminals();
01274 notEntry = NULL;
01275 for(unsigned int i = 0; i < tables[1].size(); i++) {
01276 if (tables[1][i].cell == mapUtils.notGate) {
01277 notEntry = &(tables[1][i]);
01278 break;
01279 }
01280 }
01281 assert(notEntry);
01282
01283
01284 if (!mapUtils.seqGate) {
01285 cerr << "ERROR : Could not sequential gate in cell library" << endl;
01286 QUIT_ON_ERROR;
01287 }
01288 mapUtils.identifySeqTerminalsByName();
01289 #else
01290
01291
01292
01293
01294 bzero(notEntry.func, sizeof(int)*notEntry.MAX_WORDS);
01295 notEntry.setBit(0, true);
01296 notEntry.cost = 0.;
01297
01298 bzero(constantZeroEntry.func, sizeof(int)*constantZeroEntry.MAX_WORDS);
01299 constantZeroEntry.cost = 0.;
01300
01301 #endif // #ifdef CELL_MAPPING
01302
01303
01304 mapUtils.identifyControls(target);
01305 mapUtils.removeAsyncResetsFromLogic(target);
01306
01307
01308 AiModRef constantZero = AiModGraph::constantZero(target);
01309 oa::oaModNet *constantNet = oa::oaModNet::find(target,
01310 oa::oaScalarName(oa::oaNativeNS(), "tie0"));
01311 if (constantNet) {
01312 AiModGraph::setTerminalDriver(AiModGraph::getNetToAiConnection(toBitNet(constantNet)),
01313 constantZero);
01314 }
01315 constantNet = oa::oaModNet::find(target,
01316 oa::oaScalarName(oa::oaNativeNS(), "tie1"));
01317 if (constantNet) {
01318 AiModGraph::setTerminalDriver(AiModGraph::getNetToAiConnection(toBitNet(constantNet)),
01319 AiModGraph::constantOne(target));
01320 }
01321
01322
01323
01324
01325 list<AiModRef> outputsToMap, seqNodes;
01326 AiModGraph::getOutputs(target, outputsToMap);
01327 AiModGraph::getLocalStates(target, seqNodes);
01328 for(list<AiModRef>::iterator it = seqNodes.begin();
01329 it != seqNodes.end(); it++) {
01330 if (!AiModGraph::isNull(AiModGraph::getNextState(*it))) {
01331 outputsToMap.push_back(AiModGraph::getNextState(*it));
01332 }
01333 }
01334
01335 vector<AiModRef> nodesToMap;
01336 AiModGraph::getTransitiveFanin(outputsToMap, nodesToMap, true);
01337 for(list<AiModRef>::iterator it = outputsToMap.begin();
01338 it != outputsToMap.end(); it++) {
01339 nodesToMap.push_back(*it);
01340 }
01341
01342
01343
01344 cout << "\tnum. nodes to map = " << nodesToMap.size() << endl;
01345 cout << "\t(i) collecting best choice for each node";
01346 cout.flush();
01347
01348 int m = 0;
01349 static_cast<void>(m);
01350
01351
01352 for(vector<AiModRef>::iterator it = nodesToMap.begin();
01353 it != nodesToMap.end(); it++) {
01354 AiModRef mapPoint = AiModGraph::getNonInverted(*it);
01355 AiModGraph::Cut selfCut;
01356 selfCut.insert(selfCut.begin(), mapPoint);
01357
01358
01359 #if !defined(DEBUG)
01360 m++;
01361 if (m%1000 == 0) { cout << "."; cout.flush(); }
01362 #else
01363 DEBUG_PRINT("Mapping node ");
01364 mapPoint.print();
01365 #endif
01366
01367 if (mapPoint == constantZero) {
01368 cost_p[mapPoint] = 0;
01369 cost_n[mapPoint] = 0;
01370 } else if (AiModGraph::isTerminal(mapPoint) &&
01371 AiModGraph::isNull(AiModGraph::getTerminalDriver(mapPoint)) ||
01372 AiModGraph::isSequential(mapPoint)) {
01373 cost_p[mapPoint] = 0;
01374 cut_n[mapPoint] = selfCut;
01375 choice_n[mapPoint] = ¬Entry;
01376 cost_n[mapPoint] = notEntry.cost;
01377 } else {
01378
01379
01380 AiModGraph::CutSet cuts = AiModGraph::enumerateKfeasibleCuts(
01381 mapPoint, MAX_CUT_SIZE, cutsPerNode, -1, true);
01382
01383
01384 double minCost_p = DBL_MAX,
01385 minCost_n = DBL_MAX;
01386 AiModGraph::Cut *bestCut_p = NULL,
01387 *bestCut_n = NULL;
01388 TableEntry *bestChoice_p = NULL,
01389 *bestChoice_n = NULL;
01390
01391 for(list<AiModGraph::Cut>::iterator cut_it = cuts.begin(); cut_it != cuts.end(); cut_it++) {
01392 AiModGraph::Cut *currentCut = &(*cut_it);
01393 assert(currentCut);
01394 int cutWidth = currentCut->size();
01395 assert(cutWidth <= MAX_CUT_SIZE);
01396
01397
01398 if (cutWidth == 1 && *(currentCut->begin()) == mapPoint) continue;
01399
01400
01401 DEBUG_PRINT("\tcut {");
01402 int p = 0;
01403 vector<AiModRef> cutArray(cutWidth);
01404 for(set<AiModRef>::iterator cut_it = currentCut->begin();
01405 cut_it != currentCut->end(); cut_it++) {
01406 DEBUG_PRINTMORE(cut_it->ref << ", ");
01407 assert(p < cutWidth);
01408 cutArray[p++] = *cut_it;
01409 }
01410 DEBUG_PRINTMORE("} ");
01411
01412
01413 TableEntry cutFunction;
01414 simulate(target->getDesign(), cutFunction, mapPoint, cutArray);
01415
01416 TableEntry complementFunction;
01417 memcpy(&complementFunction, &cutFunction, sizeof(TableEntry));
01418 for(int bit=0; bit<(1<<cutWidth); bit++) {
01419 complementFunction.setBit(bit, !complementFunction.getBit(bit));
01420 }
01421 #ifdef CELL_MAPPING
01422
01423 for(vector<TableEntry>::iterator lib_it = tables[cutWidth].begin();
01424 lib_it != tables[cutWidth].end(); lib_it++) {
01425 TableEntry *currentChoice = &(*lib_it);
01426 assert(currentChoice);
01427
01428
01429 if (currentChoice->match(cutFunction)) {
01430
01431 if (currentChoice->cell) {
01432 oa::oaScalarName gateName;
01433 currentChoice->cell->getCellName(gateName);
01434 oa::oaString gateString;
01435 gateName.get(gateString);
01436 DEBUG_PRINTMORE(" " << gateString);
01437 } else if (currentChoice->directFlag) {
01438 DEBUG_PRINTMORE(" WIRE");
01439 } else if (currentChoice->constantFlag) {
01440 DEBUG_PRINTMORE(" CONST");
01441 }
01442
01443 if (getCumulativeDelayCost(currentCut, currentChoice) < minCost_p) {
01444 minCost_p = getCumulativeDelayCost(currentCut, currentChoice);
01445 bestChoice_p = currentChoice;
01446 bestCut_p = currentCut;
01447 }
01448 }
01449
01450
01451 if (currentChoice->match(complementFunction)) {
01452
01453 if (currentChoice->cell) {
01454 oa::oaScalarName gateName;
01455 currentChoice->cell->getCellName(gateName);
01456 oa::oaString gateString;
01457 gateName.get(gateString);
01458 DEBUG_PRINTMORE(" !" << gateString);
01459 } else if (currentChoice->directFlag) {
01460 DEBUG_PRINTMORE(" !WIRE");
01461 } else if (currentChoice->constantFlag) {
01462 DEBUG_PRINTMORE(" !CONST");
01463 }
01464
01465 if (getCumulativeDelayCost(currentCut, currentChoice) < minCost_n) {
01466 minCost_n = getCumulativeDelayCost(currentCut, currentChoice);
01467 bestChoice_n = currentChoice;
01468 bestCut_n = currentCut;
01469 }
01470 }
01471 }
01472 #else
01473
01474
01475
01476
01477 TableEntry *currentChoice = new TableEntry(cutFunction);
01478 minCost_p = getCumulativeDelayCost(currentCut, currentChoice);
01479 bestChoice_p = currentChoice;
01480 bestCut_p = currentCut;
01481
01482 currentChoice = new TableEntry(complementFunction);
01483 minCost_n = getCumulativeDelayCost(currentCut, currentChoice);
01484 bestChoice_n = currentChoice;
01485 bestCut_n = currentCut;
01486
01487 #endif // #ifdef CELL_MAPPING
01488
01489 DEBUG_PRINTMORE(endl);
01490 }
01491
01492
01493 if (!bestChoice_p && !bestChoice_n) {
01494 cerr << endl << "ERROR: Could not find a mapping for ";
01495 mapPoint.print();
01496 cerr << " This shouldn't happen. Perhaps the cut count/depth is too small?" << endl;
01497 QUIT_ON_ERROR;
01498 }
01499
01500
01501 #ifdef CELL_MAPPING
01502 if (minCost_p + notEntry->cost < minCost_n) {
01503 minCost_n = minCost_p + notEntry->cost;
01504 bestChoice_n = notEntry;
01505 bestCut_n = &selfCut;
01506 DEBUG_PRINTLN("\tself-cut {} !p");
01507 }
01508 if (minCost_n + notEntry->cost < minCost_p) {
01509 minCost_p = minCost_n + notEntry->cost;
01510 bestChoice_p = notEntry;
01511 bestCut_p = &selfCut;
01512 DEBUG_PRINTLN("\tself-cut {} !n");
01513 }
01514 #else
01515 assert(minCost_p == minCost_n);
01516
01517 #endif // #ifdef CELL_MAPPING
01518 DEBUG_PRINTLN("\tp-cost = " << minCost_p << " n-cost = " << minCost_n);
01519 cost_p[mapPoint] = minCost_p;
01520 cost_n[mapPoint] = minCost_n;
01521 assert(bestChoice_p);
01522 choice_p[mapPoint] = bestChoice_p;
01523 assert(bestChoice_n);
01524 choice_n[mapPoint] = bestChoice_n;
01525 assert(bestCut_p);
01526 cut_p[mapPoint] = *bestCut_p;
01527 assert(bestCut_n);
01528 cut_n[mapPoint] = *bestCut_n;
01529 }
01530 }
01531
01532
01533
01534 cout << endl << "\t(ii) implementing best global choices" << endl;
01535 implementAll(target);
01536
01537
01538
01539 cout << "\t(iii) cleaning up" << endl;
01540 AiModGraph::clearKfeasibleCuts(target);
01541
01542
01543 oa::oaModNet *net;
01544 oa::oaIter<oa::oaModNet> netIter(target->getNets(oacNetIterSingleBit));
01545 while((net = netIter.getNext())) {
01546 AiModRef termNode = AiModGraph::getNetToAiConnection(toBitNet(net));
01547 if (AiModGraph::isTerminal(termNode)) {
01548 AiModGraph::detach(termNode);
01549 }
01550 }
01551
01552 if (target->getDesign()->getModules().getCount() == 1) {
01553 Manager::destroy(target->getDesign());
01554 }
01555
01556 cout << "\tdelay cost = " << totalDelay << endl;
01557 }
01558
01559
01560 }