00001
00002 #include "oagFpgaMapperUtils.h"
00003 #include "oagFpga.h"
00004 #include "oagFpgaAiModGraph.h"
00005 #include "oagFpgaManager.h"
00006 #include "oagFpgaSynthesis.h"
00007 #include "oagFpgaSimMod.h"
00008 #include "oagAiNode.h"
00009 #include "oagFpgaDebug.h"
00010 #include <map>
00011 #include <sstream>
00012 #include <algorithm>
00013
00014
00015 using namespace std;
00016
00017 namespace oagFpga {
00018
00019
00020
00021
00024
00025 MapperUtils::MapperUtils() {
00026
00027 seqGate = NULL;
00028 seqInput = seqOutput = NULL;
00029 seqReset = seqPreset = seqClock = NULL;
00030
00031 lutGate = NULL; lutOutput = NULL;
00032 }
00033
00034
00035
00036
00042
00043 oa::oaDesign *
00044 MapperUtils::createSeq(oa::oaLib* curLib, oa::oaView* curView) {
00045
00046 oa::oaDesign *design;
00047
00048 try {
00049
00050
00051 const oa::oaNativeNS nativeNS;
00052 oa::oaScalarName libName;
00053 curLib->getName(libName);
00054 oa::oaScalarName viewName;
00055 curView->getName(viewName);
00056 oa::oaViewType *viewType = oa::oaViewType::get(oa::oacNetlist);
00057 oa::oaScalarName cellName(nativeNS, "SEQ");
00058
00059
00060 if ((design = oa::oaDesign::find(libName, cellName, viewName))) {
00061 return design;
00062 } else {
00063 try {
00064 design = oa::oaDesign::open(libName, cellName, viewName, 'a');
00065 } catch (oa::oaException &e) {
00066
00067 design = oa::oaDesign::open(libName, cellName, viewName, viewType, 'w');
00068 }
00069 }
00070 assert(design);
00071
00072
00073
00074 oa::oaModule *module = design->getTopModule();
00075 if (!module) {
00076 module = oa::oaModule::create(design, cellName);
00077 design->setTopModule(module);
00078 } else {
00079
00080
00081
00082 design->purge();
00083 if (Synthesis::checkForExistenceOfDesign(libName, cellName, viewName)) {
00084 oa::oaDesign::destroy(libName, cellName, viewName);
00085 }
00086 design = oa::oaDesign::open(libName, cellName, viewName, viewType, 'w');
00087 module = oa::oaModule::create(design, cellName);
00088 design->setTopModule(module);
00089
00090 }
00091 assert(module);
00092
00093
00094 oa::oaModScalarNet *net;
00095 net = oa::oaModScalarNet::create( module,
00096 oa::oaScalarName(nativeNS, "D") );
00097 seqInput = oa::oaModScalarTerm::create( net,
00098 oa::oaScalarName(nativeNS,"D"), oa::oacInputTermType);
00099 net = oa::oaModScalarNet::create( module,
00100 oa::oaScalarName(nativeNS, "CLK") );
00101 seqClock = oa::oaModScalarTerm::create( net,
00102 oa::oaScalarName(nativeNS,"CLK"), oa::oacInputTermType);
00103 net = oa::oaModScalarNet::create( module,
00104 oa::oaScalarName(nativeNS, "PRESET") );
00105 seqPreset = oa::oaModScalarTerm::create( net,
00106 oa::oaScalarName(nativeNS,"PRESET"), oa::oacInputTermType);
00107 net = oa::oaModScalarNet::create( module,
00108 oa::oaScalarName(nativeNS, "RESET") );
00109 seqReset = oa::oaModScalarTerm::create( net,
00110 oa::oaScalarName(nativeNS,"RESET"), oa::oacInputTermType);
00111 net = oa::oaModScalarNet::create( module,
00112 oa::oaScalarName(nativeNS, "OUT") );
00113 seqOutput = oa::oaModScalarTerm::create( net,
00114 oa::oaScalarName(nativeNS,"OUT"), oa::oacOutputTermType);
00115
00116
00117
00118 seqClockTrigger = POSEDGE;
00119 seqResetTrigger = POSEDGE;
00120 seqPresetTrigger = POSEDGE;
00121
00122
00123 }catch(oa::oaException &e) {
00124 std::cerr << "ERROR: " << e.getMsg() << std::endl;
00125 assert(0);
00126 }
00127
00128 assert(design);
00129
00130 return seqGate = design;
00131 }
00132
00133
00134
00135
00141
00142 oa::oaDesign *
00143 MapperUtils::createLut(oa::oaLib* curLib, oa::oaView* curView, int K) {
00144
00145 oa::oaDesign *design;
00146
00147 try {
00148
00149
00150 oa::oaScalarName libName;
00151 curLib->getName(libName);
00152 oa::oaScalarName viewName;
00153 curView->getName(viewName);
00154 oa::oaViewType *viewType = oa::oaViewType::get(oa::oacNetlist);
00155 ostringstream lutNameStrStream;
00156 lutNameStrStream << "LUT" << K;
00157 string lutNameStr = lutNameStrStream.str();
00158
00159 const oa::oaNativeNS nativeNS;
00160 oa::oaScalarName cellName(nativeNS, lutNameStr.c_str());
00161
00162
00163 if ((design = oa::oaDesign::find(libName, cellName, viewName))) {
00164 return design;
00165 } else {
00166 try {
00167 design = oa::oaDesign::open(libName, cellName, viewName, 'a');
00168 } catch (oa::oaException &e) {
00169
00170 design = oa::oaDesign::open(libName, cellName, viewName, viewType, 'w');
00171 }
00172 }
00173 assert(design);
00174
00175
00176
00177 oa::oaModule *module = design->getTopModule();
00178 if (!module) {
00179 module = oa::oaModule::create(design, cellName);
00180 design->setTopModule(module);
00181 } else {
00182
00183
00184
00185 design->purge();
00186 if (Synthesis::checkForExistenceOfDesign(libName, cellName, viewName)) {
00187 oa::oaDesign::destroy(libName, cellName, viewName);
00188 }
00189 design = oa::oaDesign::open(libName, cellName, viewName, viewType, 'w');
00190 module = oa::oaModule::create(design, cellName);
00191 design->setTopModule(module);
00192
00193 }
00194 assert(module);
00195
00196
00197 oa::oaModScalarNet *net;
00198 for(int i=0;i<K;i++){
00199 ostringstream lutPinStrStream;
00200 lutPinStrStream << "IN" << i;
00201 string lutTermName = lutPinStrStream.str();
00202 net = oa::oaModScalarNet::create( module,
00203 oa::oaScalarName(nativeNS, lutTermName.c_str()) );
00204 lutInputs.push_back(oa::oaModScalarTerm::create( net,
00205 oa::oaScalarName(nativeNS, lutTermName.c_str()), oa::oacInputTermType));
00206 }
00207 net = oa::oaModScalarNet::create( module,
00208 oa::oaScalarName(nativeNS, "OUT") );
00209 lutOutput = oa::oaModScalarTerm::create( net,
00210 oa::oaScalarName(nativeNS,"OUT"), oa::oacOutputTermType);
00211
00212 }catch(oa::oaException &e) {
00213 std::cerr << "ERROR: " << e.getMsg() << std::endl;
00214 assert(0);
00215 }
00216
00217 assert(design);
00218
00219 return lutGate = design;
00220 }
00221
00222
00223
00224
00249
00250 void
00251 MapperUtils::removeAsyncResetsFromLogic(oa::oaModule *module) {
00252 assert(module);
00253
00254
00255 if (!Manager::hasManager(module->getDesign())) {
00256 return;
00257 }
00258
00259
00260
00261
00262
00263
00264 for(set<oa::oaModBitNet *>::iterator it = posAsyncResets.begin();
00265 it != posAsyncResets.end(); it++) {
00266 AiModRef term = AiModGraph::getNetToAiConnection(*it);
00267 assert(!AiModGraph::isNull(term));
00268 AiModGraph::resubstitute(term, AiModGraph::constantZero(term.module));
00269 }
00270
00271
00272 for(set<oa::oaModBitNet *>::iterator it = negAsyncResets.begin();
00273 it != negAsyncResets.end(); it++) {
00274 AiModRef term = AiModGraph::getNetToAiConnection(*it);
00275 assert(!AiModGraph::isNull(term));
00276 AiModGraph::resubstitute(term, AiModGraph::constantOne(term.module));
00277 }
00278
00279 }
00280
00281
00282
00283
00284
00288
00289
00290 void
00291 MapperUtils::identifyControls(oa::oaModule *module) {
00292 list<AiModRef> seq;
00293 AiModGraph::getLocalStates(module, seq);
00294 for(list<AiModRef>::iterator it = seq.begin(); it!=seq.end(); it++) {
00295 identifyControls(*it);
00296 }
00297 }
00298
00299
00300
00301
00302
00306
00307
00308 void
00309 MapperUtils::identifyControls(AiModRef seq) {
00310
00311 oagAi::Node::SequentialData *data = AiModGraph::getSequentialData(seq);
00312 if (!data) {
00313 return;
00314 }
00315
00316 oa::oaModule *module = seq.module;
00317 assert(module);
00318
00319
00320 list<AiModRef> roots;
00321 AiModGraph::getFaninRoots(seq, roots);
00322
00323 for(map<string, oagAi::Ref>::iterator sigIter = data->signals.begin();
00324 sigIter != data->signals.end(); sigIter++) {
00325
00326 AiModRef ref(sigIter->second, module);
00327
00328
00329 if (!AiModGraph::isTerminal(ref)) {
00330 continue;
00331 }
00332
00333
00334 while (true) {
00335 AiModRef driver = AiModGraph::getTerminalDriver(ref);
00336 if (!AiModGraph::isTerminal(driver)) {
00337 break;
00338 }
00339 ref = driver;
00340 }
00341
00342
00343 oa::oaModNet *net = AiModGraph::getNetToAiConnection(ref);
00344 if (!net) {
00345 continue;
00346 }
00347 oa::oaModBitNet *bitNet = toBitNet(net);
00348
00349 bool inFanin = false;
00350 inFanin |= find(roots.begin(), roots.end(), ref) != roots.end();
00351 inFanin |= find(roots.begin(), roots.end(), AiModGraph::notOf(ref)) != roots.end();
00352
00353 bool posedge = (sigIter->first.find("posedge") != sigIter->first.npos);
00354 bool clocked_on = (sigIter->first == "clocked_on");
00355 bool negedge = (sigIter->first.find("negedge") != sigIter->first.npos);
00356 bool clear = (sigIter->first == "clear");
00357
00358 #if defined(DEBUG)
00359 oa::oaString netString;
00360 bitNet->getName(oa::oaVerilogNS(), netString);
00361 #endif
00362
00363 if (inFanin && posedge || clear) {
00364 DEBUG_PRINTLN(netString << " = pos-triggered reset");
00365 posAsyncResets.insert(bitNet);
00366 } else if (inFanin && negedge) {
00367 DEBUG_PRINTLN(netString << " = neg-triggered reset");
00368 negAsyncResets.insert(bitNet);
00369 } else if (!inFanin && posedge || clocked_on) {
00370 DEBUG_PRINTLN(netString << " = pos-triggered clock");
00371 posClocks.insert(bitNet);
00372 } else if (!inFanin && negedge) {
00373 DEBUG_PRINTLN(netString << " = neg-triggered clock");
00374 negClocks.insert(bitNet);
00375 }
00376 }
00377 }
00378
00379 #ifdef CELL_MAPPING
00380
00381
00382
00389
00390
00391 void
00392 MapperUtils::connectControl(oa::oaModTerm *term, oa::oaModInst *inst,
00393 oa::oaModBitNet *net, bool inverted) {
00394 assert(term);
00395 assert(inst);
00396 assert(net);
00397
00398 oa::oaModule *module = net->getModule();
00399 assert(module);
00400
00401 #if defined(DEBUG)
00402 oa::oaString termString, netString, instString;
00403 term->getName(oa::oaVerilogNS(), termString);
00404 net->getName(oa::oaVerilogNS(), netString);
00405 inst->getName(oa::oaVerilogNS(), instString);
00406 DEBUG_PRINTLN("Connecting " << termString << " of " << instString << " -> " << netString);
00407 #endif
00408
00409 if (oa::oaModInstTerm::find(inst, term)) {
00410 DEBUG_PRINTLN("Aborted. Term is already connected");
00411 return;
00412 }
00413
00414 if (inverted) {
00415 assert(notGate);
00416
00417 oa::oaModScalarInst *notInst = oa::oaModScalarInst::create(module, notGate);
00418 oa::oaModInstTerm::create(net, notInst, notInput);
00419 oa::oaModScalarNet *localInvertedClockNet = oa::oaModScalarNet::create(module);
00420 oa::oaModInstTerm::create(localInvertedClockNet, notInst, notOutput);
00421 oa::oaModInstTerm::create(localInvertedClockNet, inst, term);
00422 } else {
00423 oa::oaModInstTerm::create(net, inst, term);
00424 }
00425
00426 }
00427
00428
00429
00430
00431
00455
00456
00457 void
00458 MapperUtils::connectAllControls(AiModRef ref, oa::oaModInst *inst) {
00459 assert(inst);
00460
00461 oagAi::Node::SequentialData *data = AiModGraph::getSequentialData(ref);
00462 assert(data);
00463
00464
00465 assert(data->abstractionLevel == oagAi::Node::SequentialData::BLACK_BOX);
00466
00467
00468 for(char p = '0'; p <= '9'; p++) {
00469 stringstream label;
00470 label << "trigger_" << p << "_posedge";
00471
00472 if (data->signals.find(label.str()) != data->signals.end()) {
00473 DEBUG_PRINTLN("Trigger " << label.str() << " is present");
00474
00475
00476 AiModRef ref(data->signals[label.str()], inst->getModule());
00477
00478
00479 if (!AiModGraph::isTerminal(ref)) {
00480 continue;
00481 }
00482
00483
00484 while (true) {
00485 AiModRef driver = AiModGraph::getTerminalDriver(ref);
00486 if (!AiModGraph::isTerminal(driver)) {
00487 break;
00488 }
00489 ref = driver;
00490 }
00491
00492 oa::oaModNet *net = AiModGraph::getNetToAiConnection(ref);
00493 if (!net) {
00494 continue;
00495 }
00496 oa::oaModBitNet *bitNet = toBitNet(net);
00497 if (seqClock && find(posClocks.begin(), posClocks.end(), bitNet) != posClocks.end()) {
00498 connectControl(seqClock, inst, bitNet, false);
00499 }
00500 if (seqClock && find(negClocks.begin(), negClocks.end(), bitNet) != negClocks.end()) {
00501 connectControl(seqClock, inst, bitNet, true);
00502 }
00503 if (seqReset && find(posAsyncResets.begin(), posAsyncResets.end(), bitNet) != posAsyncResets.end()) {
00504 connectControl(seqReset, inst, bitNet, false);
00505 }
00506 if (seqReset && find(negAsyncResets.begin(), negAsyncResets.end(), bitNet) != negAsyncResets.end()) {
00507 connectControl(seqReset, inst, bitNet, true);
00508 }
00509 }
00510 }
00511
00512
00513 for(char p = '0'; p <= '9'; p++) {
00514 stringstream label;
00515 label << "trigger_" << p << "_negedge";
00516
00517 if (data->signals.find(label.str()) != data->signals.end()) {
00518 DEBUG_PRINTLN("Trigger " << label.str() << " is present");
00519
00520
00521 AiModRef ref(data->signals[label.str()], inst->getModule());
00522
00523
00524 if (!AiModGraph::isTerminal(ref)) {
00525 continue;
00526 }
00527
00528
00529 while (true) {
00530 AiModRef driver = AiModGraph::getTerminalDriver(ref);
00531 if (!AiModGraph::isTerminal(driver)) {
00532 break;
00533 }
00534 ref = driver;
00535 }
00536
00537 oa::oaModNet *net = AiModGraph::getNetToAiConnection(ref);
00538 if (!net) {
00539 continue;
00540 }
00541 oa::oaModBitNet *bitNet = toBitNet(net);
00542 if (seqClock && find(posClocks.begin(), posClocks.end(), bitNet) != posClocks.end()) {
00543 connectControl(seqClock, inst, bitNet, true);
00544 }
00545 if (seqClock && find(negClocks.begin(), negClocks.end(), bitNet) != negClocks.end()) {
00546 connectControl(seqClock, inst, bitNet, false);
00547 }
00548 if (seqReset && find(posAsyncResets.begin(), posAsyncResets.end(), bitNet) != posAsyncResets.end()) {
00549 connectControl(seqReset, inst, bitNet, true);
00550 }
00551 if (seqReset && find(negAsyncResets.begin(), negAsyncResets.end(), bitNet) != negAsyncResets.end()) {
00552 connectControl(seqReset, inst, bitNet, false);
00553 }
00554 }
00555 }
00556
00557
00558 if (data->signals.find("clocked_on") != data->signals.end()) {
00559 DEBUG_PRINTLN("Trigger clocked_on is present");
00560
00561
00562 AiModRef ref(data->signals["clocked_on"], inst->getModule());
00563
00564
00565 if (AiModGraph::isTerminal(ref)) {
00566
00567
00568 while (true) {
00569 AiModRef driver = AiModGraph::getTerminalDriver(ref);
00570 if (!AiModGraph::isTerminal(driver)) {
00571 break;
00572 }
00573 ref = driver;
00574 }
00575
00576 oa::oaModNet *net = AiModGraph::getNetToAiConnection(ref);
00577 if (net) {
00578 oa::oaModBitNet *bitNet = toBitNet(net);
00579 if (seqClock && find(posClocks.begin(), posClocks.end(), bitNet) != posClocks.end()) {
00580 connectControl(seqClock, inst, bitNet, false);
00581 }
00582 if (seqClock && find(negClocks.begin(), negClocks.end(), bitNet) != negClocks.end()) {
00583 connectControl(seqClock, inst, bitNet, true);
00584 }
00585 }
00586 }
00587 }
00588
00589
00590 if (data->signals.find("clear") != data->signals.end()) {
00591 DEBUG_PRINTLN("Trigger clear is present");
00592
00593
00594 AiModRef ref(data->signals["clear"], inst->getModule());
00595
00596
00597 if (AiModGraph::isTerminal(ref)) {
00598
00599
00600 while (true) {
00601 AiModRef driver = AiModGraph::getTerminalDriver(ref);
00602 if (!AiModGraph::isTerminal(driver)) {
00603 break;
00604 }
00605 ref = driver;
00606 }
00607
00608 oa::oaModNet *net = AiModGraph::getNetToAiConnection(ref);
00609 if (net) {
00610 oa::oaModBitNet *bitNet = toBitNet(net);
00611 if (seqReset && find(posAsyncResets.begin(), posAsyncResets.end(), bitNet) != posAsyncResets.end()) {
00612 connectControl(seqReset, inst, bitNet, false);
00613 }
00614 if (seqReset && find(negAsyncResets.begin(), negAsyncResets.end(), bitNet) != negAsyncResets.end()) {
00615 connectControl(seqReset, inst, bitNet, true);
00616 }
00617 }
00618 }
00619 }
00620 }
00621 #endif // #ifdef CELL_MAPPING
00622
00623
00624
00625
00629
00630
00631 void
00632 MapperUtils::mergeEquivalentNets(oa::oaModule *module) {
00633 assert(module);
00634
00635
00636 bool changed = true;
00637 while(changed) {
00638 changed = false;
00639
00640
00641 oa::oaModNet *net;
00642 oa::oaIter<oa::oaModNet> netIter2(module->getNets(oacNetIterNotImplicit));
00643 while((net = netIter2.getNext())) {
00644 if(!net->isImplicit() && net->getNumBits() > 1) {
00645 net->scalarize();
00646 }
00647 }
00648
00649 oa::oaIter<oa::oaModNet> netIter(module->getNets(oacNetIterSingleBit));
00650 while(!changed && (net = netIter.getNext())) {
00651 oa::oaModBitNet *preferred = toBitNet(net)->getPreferredEquivalent();
00652
00653 oa::oaModBitNet *equivNet;
00654 oa::oaIter<oa::oaModBitNet> equivIter(preferred->getEquivalentNets());
00655 while((equivNet = equivIter.getNext())) {
00656
00657
00658 oa::oaModInstTerm *instTerm;
00659 oa::oaIter<oa::oaModInstTerm> instTermIter(equivNet->getInstTerms(oacInstTermIterAll));
00660 while((instTerm = instTermIter.getNext())) {
00661 if (instTerm->isImplicit()) {
00662 instTerm->scalarize();
00663 }
00664 instTerm->addToNet(preferred);
00665 }
00666
00667
00668 oa::oaModTerm *term;
00669 oa::oaIter<oa::oaModTerm> termIter(equivNet->getTerms(oacTermIterAll));
00670 while((term = termIter.getNext())) {
00671 if (term->isImplicit()) {
00672 term->scalarize();
00673 }
00674 term->moveToNet(preferred);
00675 }
00676
00677
00678 AiModRef target = AiModGraph::getNetToAiConnection(equivNet);
00679 if (!AiModGraph::isNull(target)) {
00680 AiModRef replacement = AiModGraph::prepareNetToAiConnection(preferred);
00681 AiModGraph::resubstitute(target, replacement);
00682 AiModGraph::removeNetToAiConnection(equivNet);
00683 }
00684
00685
00686 equivNet->destroy();
00687 changed = true;
00688 }
00689 }
00690 }
00691 }
00692
00693
00694
00695
00696
00700
00701
00702 void
00703 MapperUtils::printGateUsage(oa::oaModule *target) {
00704 assert(target);
00705
00706 const int NAME_COL_WIDTH = 15;
00707 const int COUNT_COL_WIDTH = 8;
00708
00709 long total = 0;
00710
00711 map<oa::oaModule *,int> histogram;
00712
00713 oa::oaModInst *inst;
00714 oa::oaIter<oa::oaModInst> instIter(target->getInsts());
00715 while((inst = instIter.getNext())) {
00716 oa::oaModule *module = inst->getMasterModule();
00717 assert(module);
00718
00719
00720 if (histogram.find(module) == histogram.end()) {
00721 histogram[module] = 1;
00722 } else {
00723 histogram[module] = histogram[module] + 1;
00724 }
00725 total++;
00726 }
00727
00728
00729 cout << "\tComponent gate usage" << endl;
00730 for(map<oa::oaModule *,int>::iterator cellIter = histogram.begin();
00731 cellIter != histogram.end(); cellIter++) {
00732 oa::oaString modString;
00733 cellIter->first->getName(oa::oaVerilogNS(), modString);
00734 cout << "\t\t";
00735 cout.width(NAME_COL_WIDTH);
00736 cout << modString;
00737 cout.width(COUNT_COL_WIDTH);
00738 cout << cellIter->second;
00739 cout << endl;
00740 }
00741
00742 cout << "\t\t";
00743 cout.width(NAME_COL_WIDTH);
00744 cout << "TOTAL";
00745 cout.width(COUNT_COL_WIDTH);
00746 cout << total << endl;
00747 }
00748
00749
00750
00751
00752
00758
00759
00760 void
00761 MapperUtils::removeDanglingNets(oa::oaModule *module) {
00762 const oa::oaVerilogNS verilogNS;
00763
00764
00765 oa::oaModNet *net;
00766 oa::oaIter<oa::oaModNet> netIter(module->getNets(oacNetIterSingleBit));
00767 while((net = netIter.getNext())) {
00768 oa::oaModBitNet *bitNet = toBitNet(net);
00769 if (net->getInstTerms(oacInstTermIterAll).isEmpty() &&
00770 net->getTerms(oacTermIterAll).isEmpty()) {
00771
00772 #if defined(DEBUG)
00773 oa::oaString netString;
00774 net->getName(verilogNS, netString);
00775 DEBUG_PRINTLN("Removing dangling net " << netString);
00776 #endif
00777
00778
00779 AiModRef termRef = AiModGraph::getNetToAiConnection(bitNet);
00780 if(!AiModGraph::isNull(termRef)) {
00781 assert(AiModGraph::isTerminal(termRef));
00782 AiModRef driverRef = AiModGraph::getTerminalDriver(termRef);
00783 AiModGraph::resubstitute(termRef, driverRef);
00784
00785
00786 AiModGraph::removeNetToAiConnection(bitNet);
00787 }
00788
00789
00790 net->destroy();
00791 }
00792 }
00793 }
00794
00795
00796 }