Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

oagFpgaMapper.cpp

Go to the documentation of this file.
00001 
00002 #include "oagFpgaMapperUtils.h"
00003 #include "oagFpgaMapper.h"
00004 #include "oagFpga.h"
00005 #include "oagFpgaAiModGraph.h"
00006 #include "oagFpgaSimMod.h"
00007 //#include "oagFpgaSimOcc.h"
00008 #include "oagFpgaManager.h"
00009 #include "oagFpgaDebug.h"
00010 #include <values.h>
00011 
00012 using namespace oagFpga;
00013 
00014 namespace oagMapper {
00015 
00016 // *****************************************************************************
00017 // FpgaMapper()
00018 //
00023 // *****************************************************************************
00024 FpgaMapper::FpgaMapper(int cutsPerNode) {
00025 
00026     // set the maximum number of cuts generated per node
00027     this->cutsPerNode = cutsPerNode;
00028 
00029     gateCount = seqCount = 0;
00030     //useAlternateViews = false;
00031 
00032 #ifdef CELL_MAPPING
00033     // create table for library gate cut functions
00034     addTrivialGates();
00035 #endif
00036 
00037     // there must be enough bits in the table entry to store cut function
00038     assert((1<<MAX_CUT_SIZE) <= TableEntry::MAX_WORDS*TableEntry::BITS_PER_WORD);
00039 
00040     // prepare simulation vectors
00041     initializeSimulation();
00042 }
00043 
00044 #ifdef CELL_MAPPING
00045 
00046 // *****************************************************************************
00047 // useAlternateView()
00048 //
00055 // *****************************************************************************
00056 void
00057 FpgaMapper::useAlternateView(const oa::oaScalarName &viewName) {
00058   useAlternateViews = true;
00059   alternateViewName = viewName;
00060 }
00061 
00062 
00063 // *****************************************************************************
00064 // addTrivialGates()
00065 //
00070 //
00071 // *****************************************************************************
00072 void
00073 FpgaMapper::addTrivialGates() {
00074 
00075     // for each cut width
00076     for(int i=0; i<=MAX_CUT_SIZE; i++) {
00077 
00078         // add constant zero entry
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         // add constant one entry
00089         for(int bit=0; bit<(1<<i); bit++) {
00090             constantEntry.setBit(bit, true);
00091         }
00092         tables[i].push_back(constantEntry);
00093 
00094         // add all direct connections
00095         // YH: 06/26/07, don't understand what is direct connections...
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 // addLibraryGate()
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   // find all input and output terminals
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   // if this gate has zero or multiple outputs, ignore
00160   if (outputTerms.size() != 1) {
00161     std::cout << "WARNING: Ignoring library cell.  "
00162               << "Multiple outputs are currently unsupported." << std::endl;
00163     return;
00164   }
00165   // if this gate has zero inputs, ignore
00166   if (inputTerms.size() == 0) return;
00167 
00168   // find the AI nodes of the inputs and outputs
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   // check that there is enough room for the full truth table
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   // find an alternate view, if specified
00191   oa::oaDesign *implementDesign = NULL;
00192   if (useAlternateViews) {
00193     // an alternate view was specified...
00194     oa::oaScalarName libName, viewName, cellName;
00195     design->getLibName(libName);
00196     design->getCellName(cellName);
00197     implementDesign = oa::oaDesign::find(libName, cellName, alternateViewName);
00198     // try opening from disk
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       // couldn't open alternate view!
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   // N_input...
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;         // input permutation unsupported
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; // don't bother with inverting 1-input gates
00233   }
00234 
00235   DEBUG_PRINTMORE("\n");
00236 }
00237 
00238 #endif // #ifdef CELL_MAPPING
00239 
00240 // *****************************************************************************
00241 // initializeSimulation()
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 // simulate()
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   // Note: because this is such a performance critical component of the mapper,
00279   // the logic cone between a cut and a mapping point is computed using a direct
00280   // call to the oagAi class instead of the AiModGraph.  this avoids some slight
00281   // overhead in converting the oagAi::Refs to AiModRefs
00282 
00283   // gather full cone
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   // add back vertex
00293   cone.push_back(out.ref);
00294   
00295   // create simulation engine
00296   static SimMod sim(design);
00297 
00298   // repeat with as many words as necessary for the full truth table
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     // simulate every node in the cone
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   // if the last result was a partial word, mask invalid bits
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   // print out the binary result
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 // setAreaCosts()
00334 //
00340 // *****************************************************************************
00341 void
00342 FpgaMapper::setAreaCosts() {
00343 
00344 #ifdef CELL_MAPPING
00345 
00346     // iterate through all table entries
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             // is a trivial mapping?
00352             if (choice->directFlag || choice->constantFlag) {
00353                 choice->cost = 0.0;
00354                 continue;
00355             }
00356             assert(choice->implementCell);
00357 
00358             // has a top block?
00359             oa::oaBlock *topBlock;
00360             if ((topBlock = choice->implementCell->getTopBlock())) {
00361                 // has a bounding box?
00362                 oa::oaBox box;
00363                 topBlock->getBBox(box);
00364                 choice->cost = box.getWidth()*box.getHeight();
00365                 if (choice->cost > 0) continue;
00366 
00367                 // count input terms
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             // has a top module?
00381             oa::oaModule *topModule;
00382             if ((topModule = choice->implementCell->getTopModule())) {
00383                 // count input terms
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 // setDelayCosts()
00412 //
00418 // *****************************************************************************
00419 void
00420 FpgaMapper::setDelayCosts() {
00421 
00422 #ifdef CELL_MAPPING
00423 
00424     // iterate through all table entries
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             // is a trivial mapping?
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 // getCumulativeAreaCost()
00449 //
00458 // *****************************************************************************
00459 double
00460 FpgaMapper::getCumulativeAreaCost(AiModGraph::Cut *cut, TableEntry *choice) {
00461     assert(cut);
00462     assert(choice);
00463 
00464     // 1. cost of choice
00465     double cost = choice->cost;
00466     // 2. cost of inputs
00467     int i=0;
00468     for(AiModGraph::Cut::iterator it = cut->begin(); it!= cut->end(); it++) {
00469         if ((choice->N_input >> i) & 0x1) {
00470             // inverted
00471             assert(cost_n.find(*it) != cost_n.end());
00472             cost += cost_n[*it];
00473         } else {
00474             // non-inverted
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 // getCumulativeDelayCost()
00486 //
00492 // *****************************************************************************
00493 double
00494 FpgaMapper::getCumulativeDelayCost(AiModGraph::Cut *cut, TableEntry *choice) {
00495     assert(cut);
00496     assert(choice);
00497 
00498     // 1. cost of inputs
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             // inverted
00504             assert(cost_n.find(*it) != cost_n.end());
00505             cost >?= cost_n[*it];
00506         } else {
00507             // non-inverted
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 // techmapArea()
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     // has a set of library cells been supplied?
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         // the design is already entirely structural
00550         cerr << "ERROR: Target is already structural or is missing functional "
00551              << "description.  Aborting." << endl;
00552         return;
00553     }
00554 
00555     // initialize
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     // check for combinational cycles
00563     if (AiModGraph::hasCombinationalCycle(target)) {
00564       cerr << "ERROR: Target graph has a combinational cycle" << endl;
00565       QUIT_ON_ERROR;
00566     }
00567 
00568     // set cost of all mapping choices to area
00569     setAreaCosts();
00570 
00571 #ifdef CELL_MAPPING
00572 
00573     // identify not (and corresponding table entry)
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     // identify seq gate
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     // setup some frequently used technology entries
00600 
00601     // add not entry
00602     bzero(notEntry.func, sizeof(int)*notEntry.MAX_WORDS);
00603     notEntry.setBit(0, true);
00604     notEntry.cost = 0.;
00605     // add constant zero entry
00606     bzero(constantZeroEntry.func, sizeof(int)*constantZeroEntry.MAX_WORDS);
00607     constantZeroEntry.cost = 0.;
00608 
00609 #endif // #ifdef CELL_MAPPING
00610 
00611     // strip reset nets
00612     mapUtils.identifyControls(target);
00613     mapUtils.removeAsyncResetsFromLogic(target);
00614 
00615     // handle constant nodes and nets
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     // collect the points that must be mapped
00631     //    1. primary outputs
00632     //    2. next state inputs of sequential nodes
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     // collect all fan-ins of these points
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     // --- PHASE 1 : collect best choice for each node
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     // map each point
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       // progress indicator (one dot = 1000 points mapped)
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] = &notEntry;
00684               cost_n[mapPoint] = notEntry.cost;
00685       } else {
00686           // explore all possible k-feasible cuts
00687           // AiModGraph::clearKfeasibleCuts(target);
00688           AiModGraph::CutSet cuts = AiModGraph::enumerateKfeasibleCuts(
00689               mapPoint, MAX_CUT_SIZE, cutsPerNode, -1, true);
00690 
00691           // choose best "p" and "n" cuts and choices
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               // ignore self-cut
00706               if (cutWidth == 1 && *(currentCut->begin()) == mapPoint) continue;
00707 
00708               // construct cut array
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               // compute cut function
00721               TableEntry cutFunction;
00722               simulate(target->getDesign(), cutFunction, mapPoint, cutArray);
00723               // compute complement of cut function
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               // match cut function
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                       // with non-inverted function...
00737                       if (currentChoice->match(cutFunction)) {
00738                           // print name
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                           // keep best match
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                       // with inverted function...
00759                       if (currentChoice->match(complementFunction)) {
00760                           // print name
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                           // keep best match
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               // only one choice for each cut when LUT map is assumed
00783 
00784               // with non-inverted function...
00785               TableEntry *currentChoice = new TableEntry(cutFunction);
00786               minCost_p = getCumulativeAreaCost(currentCut, currentChoice);
00787               bestChoice_p = currentChoice;
00788               bestCut_p = currentCut;
00789               // with inverted function...
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           // could we not find a mapping?
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           // lastly, check self-cuts (i.e. just using an inverter)
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     // --- PHASE 2 : implement choices
00841 
00842     cout << endl << "\t(ii) implementing best global choices" << endl;
00843 
00844     implementAll(target);
00845 
00846     // PHASE 3 : clean up
00847 
00848     cout << "\t(iii) cleaning up" << endl;
00849     AiModGraph::clearKfeasibleCuts(target);
00850 
00851     // make module structural
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     // delete manager if this is the only module
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 // implementAll()
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     // make all bus nets and terms explicit
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     // map all existings wires
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     // pre-map sequential nodes
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     // map sequential nodes
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     // map primary outputs
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 // implementSeqNode()
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   // create new sequential gate
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   // create output net
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   // TODO: need to find some way to connect those asynchronous signals
01004 #ifdef CELL_MAPPING
01005   // connect clocks, resets, etc.
01006   mapUtils.connectAllControls(ref, inst);
01007 #endif
01008 
01009   return inst;
01010 }
01011 
01012 
01013 // *****************************************************************************
01014 // implementNode()
01015 //
01027 // *****************************************************************************
01028 oa::oaModBitNet *
01029 FpgaMapper::implementNode(oagFpga::AiModRef ref) {
01030 
01031   // has this node already been mapped?
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   // is this a dangling node?
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     // default action: connect to constant zero
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   // is this a constant node?
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   // is this an inverted ref? return with "p" or "n" version of node
01073   TableEntry    *choice;
01074   AiModGraph::Cut *cut;
01075   if (AiModGraph::isInverted(ref)) {
01076     // "n" mapping
01077     choice = choice_n[AiModGraph::getNonInverted(ref)];
01078     cut = &(cut_n[AiModGraph::getNonInverted(ref)]);
01079     totalDelay >?= cost_n[AiModGraph::getNonInverted(ref)];
01080   } else {
01081     // "p" mapping
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   // come back !! for the direct connect (06/29/07)
01098   // is this a trivial mapping?
01099   if (choice->directFlag) {
01100     // return the wire that is connected to the direct input
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     // return the constant 0 or 1 wire
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   // create logic gate
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   // at this point, the choice of the node must be a LUT (seq node has been mapped)
01138   cerr << "begin to create a modual instant" << endl;
01139 
01140 #ifdef YU_TEST
01141   //oagFpga::YuTest(YuTestCurLib, YuTestCurView, currentModule);
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   // map inputs
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     // is this input inverted in the mapping?
01164     if ((choice->N_input >> num) & 0x1) {
01165 #ifndef CELL_MAPPING
01166         assert(0); // none of inputs is inverted, should never reach here ...
01167 #endif // #ifndef CELL_MAPPING
01168       cutRef = AiModGraph::notOf(cutRef);
01169     }
01170     // was an inverter used to map _p <=> _n?
01171     if (choice == &notEntry && cutRef == ref) {
01172 #ifndef CELL_MAPPING
01173         assert(0); // only LUT is used for map, should never reach here ...
01174 #endif // #ifndef CELL_MAPPING
01175       cutRef = AiModGraph::notOf(cutRef);
01176     }
01177     assert(cutRef != ref);
01178 
01179     // get corresponding instTerm
01180     while((term = termIter.getNext())) {
01181       if (term->getTermType() == oa::oacInputTermType) {
01182         break;
01183       } else if (term->getTermType() == oa::oacOutputTermType) {
01184         assert(!outputTerm); // can only handle gates with one output
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   // find output term (if not already found)
01197   while(!outputTerm && (term = termIter.getNext())) {
01198     if (term->getTermType() == oa::oacOutputTermType) {
01199       outputTerm = term;
01200     }
01201   }
01202   assert(outputTerm);
01203   
01204   // create output net
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 // techmapDelay()
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     // has a set of library cells been supplied?
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         // the design is already entirely structural
01242         cerr << "ERROR: Target is already structural or is missing functional "
01243              << "description.  Aborting." << endl;
01244         return;
01245     }
01246 
01247     // initialize
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     // check for combinational cycles
01255     if (AiModGraph::hasCombinationalCycle(target)) {
01256       cerr << "ERROR: Target graph has a combinational cycle" << endl;
01257       QUIT_ON_ERROR;
01258     }
01259 
01260     // set cost of all mapping choices to delay
01261     setDelayCosts();
01262 
01263 #ifdef CELL_MAPPING
01264 
01265     // identify not (and corresponding table entry)
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     // identify seq gate
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     // setup some frequently used technology entries
01292 
01293     // add not entry
01294     bzero(notEntry.func, sizeof(int)*notEntry.MAX_WORDS);
01295     notEntry.setBit(0, true);
01296     notEntry.cost = 0.;
01297     // add constant zero entry
01298     bzero(constantZeroEntry.func, sizeof(int)*constantZeroEntry.MAX_WORDS);
01299     constantZeroEntry.cost = 0.;
01300 
01301 #endif // #ifdef CELL_MAPPING
01302 
01303     // strip reset nets
01304     mapUtils.identifyControls(target);
01305     mapUtils.removeAsyncResetsFromLogic(target);
01306 
01307     // handle constant nodes and nets
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     // collect the points that must be mapped
01323     //    1. primary outputs
01324     //    2. next state inputs of sequential nodes
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     // collect all fan-ins of these points
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     // --- PHASE 1 : collect best choice for each node
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     // map each point
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       // progress indicator (one dot = 1000 points mapped)
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] = &notEntry;
01376               cost_n[mapPoint] = notEntry.cost;
01377       } else {
01378           // explore all possible k-feasible cuts
01379           // AiModGraph::clearKfeasibleCuts(target);
01380           AiModGraph::CutSet cuts = AiModGraph::enumerateKfeasibleCuts(
01381               mapPoint, MAX_CUT_SIZE, cutsPerNode, -1, true);
01382 
01383           // choose best "p" and "n" cuts and choices
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               // ignore self-cut
01398               if (cutWidth == 1 && *(currentCut->begin()) == mapPoint) continue;
01399 
01400               // construct cut array
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               // compute cut function
01413               TableEntry cutFunction;
01414               simulate(target->getDesign(), cutFunction, mapPoint, cutArray);
01415               // compute complement of cut function
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               // match cut function
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                       // with non-inverted function...
01429                       if (currentChoice->match(cutFunction)) {
01430                           // print name
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                           // keep best match
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                       // with inverted function...
01451                       if (currentChoice->match(complementFunction)) {
01452                           // print name
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                           // keep best match
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               // only one choice for each cut when LUT map is assumed
01475 
01476               // with non-inverted function...
01477               TableEntry *currentChoice = new TableEntry(cutFunction);
01478               minCost_p = getCumulativeDelayCost(currentCut, currentChoice);
01479               bestChoice_p = currentChoice;
01480               bestCut_p = currentCut;
01481               // with inverted function...
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           // could we not find a mapping?
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           // lastly, check self-cuts (i.e. just using an inverter)
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     // --- PHASE 2 : implement choices
01533 
01534     cout << endl << "\t(ii) implementing best global choices" << endl;
01535     implementAll(target);
01536 
01537     // PHASE 3 : clean up
01538 
01539     cout << "\t(iii) cleaning up" << endl;
01540     AiModGraph::clearKfeasibleCuts(target);
01541 
01542     // make module structural
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     // delete manager if this is the only module
01552     if (target->getDesign()->getModules().getCount() == 1) {
01553       Manager::destroy(target->getDesign());
01554     }
01555 
01556     cout << "\tdelay cost = " << totalDelay << endl;
01557 }
01558 
01559 
01560 }

Generated on Mon Jul 9 14:17:19 2007 for OA Gear Fpga by  doxygen 1.3.9.1