00001
00002 #include "oagFpga.h"
00003 #include "oagFpgaModGraph.h"
00004 #include "oagFpgaOccGraph.h"
00005 #include <memory>
00006
00007 #include "oagFpgaDebug.h"
00008
00009 namespace oagFpga {
00010
00011
00012 typedef oa::oaIter<oa::oaOccNet> OccNetIter;
00013
00014
00015
00016
00017
00023
00024
00025 void
00026 OccGraph::convertRefListToOccRefList(const list<BBRef> &source,
00027 oa::oaOccurrence *occurrence,
00028 list<OccRef> &result) {
00029 for(list<BBRef>::const_iterator it = source.begin(); it != source.end(); ++it) {
00030 result.push_back(OccRef(*it, occurrence));
00031 }
00032 }
00033
00034
00035
00036
00037
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00079
00080
00081 void
00082 OccGraph::getFanout(OccRef x, list<OccRef> &result) {
00083 convertRefListToOccRefList(getGraph(x)->getFanout(x.ref), x.occurrence, result);
00084 }
00085
00086
00087
00088
00089
00099
00100
00101 void
00102 OccGraph::getTransitiveFanin(OccRef x, list<OccRef> &transitiveFanin) {
00103 list<BBRef> flatResult;
00104 getGraph(x)->getTransitiveFanin(x.ref, flatResult);
00105
00106 convertRefListToOccRefList(flatResult, x.occurrence, transitiveFanin);
00107 }
00108
00109
00110
00111
00112
00122
00123
00124 void
00125 OccGraph::getTransitiveFanout(OccRef x, list<OccRef> &transitiveFanout) {
00126 list<BBRef> flatResult;
00127 getGraph(x)->getTransitiveFanout(x.ref, flatResult);
00128
00129 convertRefListToOccRefList(flatResult, x.occurrence, transitiveFanout);
00130 }
00131
00132
00133
00134
00135
00136
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00240
00241
00242 oa::oaOccBitNet *
00243 OccGraph::getNetToBBConnection(OccRef x) {
00244 Manager *manager = Manager::get(x.occurrence->getModule()->getDesign());
00245 oa::oaModBitNet *modNet = manager->getNetToBBConnection(x.ref);
00246 if (!modNet) {
00247 return NULL;
00248 }
00249
00250 oa::oaOccurrence *topOcc = x.occurrence->getTopOccurrence();
00251 auto_ptr<OccNetIter> occNetIter;
00252 if (x.occurrence == topOcc) {
00253
00254
00255 occNetIter.reset(new OccNetIter(modNet->getOccNets(topOcc)));
00256 } else {
00257
00258
00259 occNetIter.reset(
00260 new OccNetIter(x.occurrence->getNets(oacNetIterSingleBit)));
00261 }
00262 oa::oaOccNet *occNet;
00263 while((occNet = occNetIter->getNext())) {
00264 oa::oaOccBitNet *occBitNet = toBitNet(occNet);
00265 if (occBitNet->getModNet() == modNet) {
00266 return occBitNet;
00267 }
00268 }
00269
00270
00271 QUIT_ON_INTERNAL_ERROR;
00272 return NULL;
00273 }
00274
00275
00276
00277
00278
00283
00284
00285 OccRef
00286 OccGraph::getNetToAiConnection(oa::oaOccBitNet *net) {
00287 Manager *manager = Manager::get(net->getModNet()->getDesign());
00288 oa::oaModBitNet *modNet = static_cast<oa::oaModBitNet*>(net->getModNet());
00289 return OccRef(manager->getNetToAiConnection(modNet), net->getOccurrence());
00290 }
00291
00292
00293
00294
00295
00305
00306
00307 void
00308 OccGraph::getOutputs(oa::oaOccurrence *top, list<OccRef> &result) {
00309 assert(top);
00310 oa::oaOccTerm *term;
00311 oa::oaIter<oa::oaOccTerm> termIter(top->getTerms(oacTermIterSingleBit));
00312 while((term = termIter.getNext())) {
00313 if(term->getTermType() == oa::oacOutputTermType) {
00314 ModRef modRef = oagFpga::ModGraph::prepareNetToAiConnection(toBitNet(term->getNet()->getModNet()));
00315 result.push_back(OccRef(modRef.ref, top));
00316 }
00317 }
00318 }
00319
00320
00321
00322
00323
00333
00334
00335 void
00336 OccGraph::getOutputs(oa::oaOccurrence *top, list<oa::oaOccBitNet *> &result) {
00337 assert(top);
00338 oa::oaOccTerm *term;
00339 oa::oaIter<oa::oaOccTerm> termIter(top->getTerms(oacTermIterSingleBit));
00340 while((term = termIter.getNext())) {
00341 if(term->getTermType() == oa::oacOutputTermType) {
00342 result.push_back(toBitNet(term->getNet()));
00343 }
00344 }
00345 }
00346
00347
00348
00349
00350
00357
00358
00359 void
00360 OccGraph::getInputs(oa::oaOccurrence *top, list<OccRef> &result) {
00361 assert(top);
00362 oa::oaOccTerm *term;
00363 oa::oaIter<oa::oaOccTerm> termIter(top->getTerms(oacTermIterSingleBit));
00364 while((term = termIter.getNext())) {
00365 if(term->getTermType() == oa::oacInputTermType) {
00366 ModRef modRef = oagFpga::ModGraph::prepareNetToAiConnection(toBitNet(term->getNet()->getModNet()));
00367 result.push_back(OccRef(modRef.ref, top));
00368 }
00369 }
00370 }
00371
00372
00373
00374
00375
00382
00383
00384 void
00385 OccGraph::getInputs(oa::oaOccurrence *top, list<oa::oaOccBitNet *> &result) {
00386 assert(top);
00387 oa::oaOccTerm *term;
00388 oa::oaIter<oa::oaOccTerm> termIter(top->getTerms(oacTermIterSingleBit));
00389 while((term = termIter.getNext())) {
00390 if(term->getTermType() == oa::oacInputTermType) {
00391 result.push_back(toBitNet(term->getNet()));
00392 }
00393 }
00394 }
00395
00396
00397
00398
00399
00406
00407 void
00408 OccGraph::getConstants(oa::oaOccurrence *occurrence, list<OccRef> &zeros, list<OccRef> &ones) {
00409 assert(occurrence);
00410
00411 const oa::oaNativeNS nativeNS;
00412 const oa::oaScalarName tie0Name(nativeNS, "tie0");
00413 const oa::oaScalarName tie1Name(nativeNS, "tie1");
00414
00415 list<oa::oaOccurrence*> toBeVisited;
00416 toBeVisited.push_back(occurrence);
00417
00418 while(!toBeVisited.empty()) {
00419 oa::oaOccurrence *currentOcc = toBeVisited.front();
00420 toBeVisited.pop_front();
00421
00422
00423 zeros.push_back(OccGraph::constantZero(currentOcc));
00424 oa::oaOccScalarNet *net;
00425 if ((net = oa::oaOccScalarNet::find(currentOcc, tie0Name))) {
00426 OccRef ref = getNetToAiConnection(net);
00427 assert(!isNull(ref));
00428 zeros.push_back(ref);
00429 }
00430 if ((net = oa::oaOccScalarNet::find(currentOcc, tie1Name))) {
00431 OccRef ref = getNetToAiConnection(net);
00432 assert(!isNull(ref));
00433 ones.push_back(ref);
00434 }
00435
00436
00437 oa::oaOccInst *inst;
00438 oa::oaIter<oa::oaOccInst> instIter(currentOcc->getInsts());
00439 while((inst = instIter.getNext())) {
00440 oa::oaOccurrence *subOcc = inst->getMasterOccurrence();
00441 if(!subOcc) {
00442 oa::oaString str;
00443 inst->getInst()->getCellName(oa::oaVerilogNS(), str);
00444 cerr << "ERROR: Could not find instantiated design \"" << str << "\" in OA database" << endl;
00445 QUIT_ON_ERROR;
00446 }
00447 toBeVisited.push_back(subOcc);
00448 }
00449 }
00450 }
00451
00452
00453
00454
00455
00461
00462 void
00463 OccGraph::getStates(oa::oaOccurrence *occurrence, list<OccRef> &result) {
00464 assert(occurrence);
00465
00466 list<oa::oaOccurrence*> toBeVisited;
00467 toBeVisited.push_back(occurrence);
00468
00469 while(!toBeVisited.empty()) {
00470 oa::oaOccurrence *currentOcc = toBeVisited.front();
00471 toBeVisited.pop_front();
00472
00473
00474 list<oagAi::Ref> currentResult;
00475 getGraph(currentOcc)->getAllSequential(currentResult);
00476 convertRefListToOccRefList(currentResult, currentOcc, result);
00477
00478
00479 oa::oaOccInst *inst;
00480 oa::oaIter<oa::oaOccInst> instIter(currentOcc->getInsts());
00481 while((inst = instIter.getNext())) {
00482 oa::oaOccurrence *subOcc = inst->getMasterOccurrence();
00483 if(!subOcc) {
00484 oa::oaString str;
00485 inst->getInst()->getCellName(oa::oaVerilogNS(), str);
00486 cerr << "ERROR: Could not find instantiated design \"" << str << "\" in OA database" << endl;
00487 QUIT_ON_ERROR;
00488 }
00489 toBeVisited.push_back(subOcc);
00490 }
00491 }
00492 }
00493
00494
00495
00496
00497
00502
00503
00504 void
00505 OccGraph::getLocalStates(oa::oaOccurrence *occurrence, list<OccRef> &result) {
00506 assert(occurrence);
00507
00508
00509 list<oagAi::Ref> flatResult;
00510 getGraph(occurrence)->getAllSequential(flatResult);
00511 convertRefListToOccRefList(flatResult, occurrence, result);
00512 }
00513
00514
00515
00516
00517
00529
00530
00531 void
00532 OccGraph::getAllConnections(oa::oaOccBitNet *net,
00533 set<oa::oaOccBitNet*> &connectedNets,
00534 set<OccRef> &connectedRefs,
00535 bool searchForwardThroughGraph,
00536 bool searchBackwardThroughGraph,
00537 bool searchThroughHierarchy,
00538 bool searchThroughEquivNets,
00539 bool searchThroughEquivRefs,
00540 bool includeSelf) {
00541 assert(net);
00542
00543
00544 if (connectedNets.find(net) == connectedNets.end()) {
00545 connectedNets.insert(net);
00546 } else {
00547 return;
00548 }
00549
00550
00551 getAllConnections(getNetToAiConnection(net), connectedNets, connectedRefs,
00552 searchForwardThroughGraph, searchBackwardThroughGraph, searchThroughHierarchy,
00553 searchThroughEquivNets, searchThroughEquivRefs, true);
00554
00555
00556 if (searchThroughEquivNets) {
00557 oa::oaOccBitNet *equivNet;
00558 oa::oaIter<oa::oaOccBitNet> equivIter(net->getEquivalentNets());
00559 while((equivNet = equivIter.getNext())) {
00560 getAllConnections(equivNet, connectedNets, connectedRefs,
00561 searchForwardThroughGraph, searchBackwardThroughGraph, searchThroughHierarchy,
00562 searchThroughEquivNets, searchThroughEquivRefs, true);
00563 }
00564 }
00565
00566
00567 if (searchThroughHierarchy) {
00568
00569
00570 oa::oaOccInstTerm *nextInstTerm;
00571 oa::oaIter<oa::oaOccInstTerm> instTermIter(net->getInstTerms(oacInstTermIterAll));
00572 while((nextInstTerm = instTermIter.getNext())) {
00573 oa::oaOccTerm *nextTerm = nextInstTerm->getTerm();
00574 assert(nextTerm);
00575 assert(nextTerm->getNumBits() == 1);
00576 oa::oaOccBitNet *nextNet = toBitNet(nextTerm->getNet());
00577 assert(nextNet);
00578 getAllConnections(nextNet, connectedNets, connectedRefs,
00579 searchForwardThroughGraph, searchBackwardThroughGraph, searchThroughHierarchy,
00580 searchThroughEquivNets, searchThroughEquivRefs, true);
00581 }
00582
00583
00584 oa::oaOccTerm *nextTerm;
00585 oa::oaIter<oa::oaOccTerm> termIter(net->getTerms(oacTermIterAll));
00586 while((nextTerm = termIter.getNext())) {
00587 oa::oaOccInst *parent = net->getOccurrence()->getOccInst();
00588 if (parent) {
00589
00590
00591 oa::oaOccInstTerm *nextInstTerm;
00592 unsigned int bitIndex = oacNullIndex;
00593 if (nextTerm->isImplicit()) {
00594
00595
00596
00597 oa::oaOccTerm *busTerm = findBusTerm(static_cast<oa::oaOccBusTermBit*>(nextTerm));
00598 assert(busTerm);
00599
00600
00601 oa::oaName generalName;
00602 nextTerm->getName(generalName);
00603 assert(generalName.getVectorBit());
00604 bitIndex = generalName.getVectorBit()->getIndex();
00605
00606 if (parent->usesTermPositions()) {
00607
00608 unsigned int portPosition = busTerm->getPosition();
00609 assert(portPosition != oacNullIndex);
00610 nextInstTerm = oa::oaOccInstTerm::find(parent, portPosition);
00611 } else {
00612
00613 oa::oaName termName;
00614 busTerm->getName(termName);
00615 nextInstTerm = oa::oaOccInstTerm::find(parent, termName);
00616 }
00617
00618
00619 if (nextInstTerm) {
00620 nextInstTerm = nextInstTerm->getBit(bitIndex);
00621 }
00622
00623 } else {
00624
00625
00626 if (parent->usesTermPositions()) {
00627
00628 unsigned int portPosition = nextTerm->getPosition();
00629 assert(portPosition != oacNullIndex);
00630 nextInstTerm = oa::oaOccInstTerm::find(parent, portPosition);
00631 } else {
00632
00633 oa::oaName termName;
00634 nextTerm->getName(termName);
00635 nextInstTerm = oa::oaOccInstTerm::find(parent, termName);
00636 }
00637 }
00638
00639 if (!nextInstTerm) {
00640
00641 DEBUG_PRINTLN("\tterminal isn't bound to any instTerm!")
00642 continue;
00643 }
00644
00645 assert(nextInstTerm->getNumBits() == 1);
00646 oa::oaOccBitNet *nextNet = toBitNet(nextInstTerm->getNet());
00647 assert(nextNet);
00648
00649 getAllConnections(nextNet, connectedNets, connectedRefs,
00650 searchForwardThroughGraph, searchBackwardThroughGraph, searchThroughHierarchy,
00651 searchThroughEquivNets, searchThroughEquivRefs, true);
00652
00653 } else {
00654 DEBUG_PRINTLN("\t\talready at top of hierarchy")
00655 }
00656
00657 }
00658 }
00659
00660
00661 if (!includeSelf) {
00662 connectedNets.erase(net);
00663 }
00664 }
00665
00666
00667
00668
00669
00681
00682
00683 void
00684 OccGraph::getAllConnections(OccRef x,
00685 set<oa::oaOccBitNet*> &connectedNets,
00686 set<OccRef> &connectedRefs,
00687 bool searchForwardThroughGraph,
00688 bool searchBackwardThroughGraph,
00689 bool searchThroughHierarchy,
00690 bool searchThroughEquivNets,
00691 bool searchThroughEquivRefs,
00692 bool includeSelf) {
00693 if (isNull(x)) {
00694 return;
00695 }
00696
00697
00698 if (connectedRefs.find(x) == connectedRefs.end()) {
00699 connectedRefs.insert(x);
00700 } else {
00701 return;
00702 }
00703
00704
00705 if (isTerminal(x) && !isInverted(x)) {
00706 oa::oaOccBitNet *net;
00707 if ((net = getNetToAiConnection(x))) {
00708 getAllConnections(net, connectedNets, connectedRefs,
00709 searchForwardThroughGraph, searchBackwardThroughGraph, searchThroughHierarchy,
00710 searchThroughEquivNets, searchThroughEquivRefs, true);
00711 }
00712 }
00713
00714
00715 if (searchBackwardThroughGraph) {
00716
00717 if (isTerminal(x)) {
00718 OccRef driver = getTerminalDriver(x);
00719 driver = isInverted(x) ? notOf(driver) : driver;
00720 getAllConnections(driver, connectedNets, connectedRefs,
00721 searchForwardThroughGraph, searchBackwardThroughGraph, searchThroughHierarchy,
00722 searchThroughEquivNets, searchThroughEquivRefs, true);
00723 }
00724 }
00725
00726
00727 if (searchForwardThroughGraph) {
00728
00729 list<OccRef> fanoutList;
00730 getFanout(x, fanoutList);
00731 while(!fanoutList.empty()) {
00732 OccRef fanout(fanoutList.front());
00733 fanoutList.pop_front();
00734 if(isTerminal(fanout)) {
00735 fanout = isInverted(x) ? notOf(fanout) : fanout;
00736 fanout = isInverted(getTerminalDriver(fanout)) ? notOf(fanout) : fanout;
00737 getAllConnections(fanout, connectedNets, connectedRefs,
00738 searchForwardThroughGraph, searchBackwardThroughGraph, searchThroughHierarchy,
00739 searchThroughEquivNets, searchThroughEquivRefs, true);
00740 }
00741 }
00742 }
00743
00744
00745 if (searchThroughEquivRefs) {
00746 list<OccRef> equivList;
00747 getEquivalents(x, equivList);
00748 while(!equivList.empty()) {
00749 OccRef equiv(equivList.front());
00750 equivList.pop_front();
00751 getAllConnections(equiv, connectedNets, connectedRefs,
00752 searchForwardThroughGraph, searchBackwardThroughGraph, searchThroughHierarchy,
00753 searchThroughEquivNets, searchThroughEquivRefs, true);
00754 }
00755 }
00756
00757
00758 if (!includeSelf) {
00759 connectedRefs.erase(x);
00760 }
00761 }
00762
00763
00764
00765
00766
00779
00780
00781 OccRef
00782 OccGraph::getTerminalDriver(OccRef terminal,
00783 bool searchHierarchy) {
00784 assert(isTerminal(terminal));
00785
00786 oagAi::Ref result = getGraph(terminal)->getTerminalDriver(terminal.ref);
00787 if (!oagAi::Graph::isNull(result)) {
00788 return OccRef(result, terminal.occurrence);
00789 }
00790
00791 if (searchHierarchy) {
00792 QUIT_ON_ERROR
00793 }
00794
00795 return OccRef();
00796 }
00797
00798
00799
00800
00801
00805
00806
00807 void
00808 OccRef::print(bool lineFeed) {
00809
00810 oa::oaString occPathString;
00811 if (!occurrence) {
00812 occPathString = "(null)";
00813 } else if (occurrence->getOccInst()) {
00814 occurrence->getOccInst()->getPathName(oa::oaVerilogNS(), occPathString);
00815 } else {
00816 occPathString = "(top)";
00817 }
00818
00819 if (OccGraph::getNodeType(*this) == oagAi::Node::AND) {
00820 cout << "AND " << occPathString << "." << ref << " :\t"
00821 << OccGraph::getAndLeft(*this).ref << ", " << OccGraph::getAndLeft(*this).ref;
00822 } else if (OccGraph::getNodeType(*this) == oagAi::Node::SEQUENTIAL) {
00823 cout << "SEQ " << occPathString << "." << ref << " :\t"
00824 << OccGraph::getNextState(*this).ref;
00825 } else if (OccGraph::getNodeType(*this) == oagAi::Node::CONSTANT0) {
00826 cout << "ZRO " << occPathString << "." << ref << " :\t";
00827 } else if (OccGraph::getNodeType(*this) == oagAi::Node::TERMINAL) {
00828 cout << "TRM " << occPathString << "." << ref << " :\t"
00829 << OccGraph::getTerminalDriver(*this).ref;
00830 } else if (OccGraph::getNodeType(*this) == oagAi::Node::NONE) {
00831 cout << "NUL " << occPathString << "." << ref << " :\t";
00832 }
00833
00834 if (OccGraph::isInverted(*this)) {
00835 cout << " (inverted)";
00836 }
00837
00838 if (lineFeed) {
00839 cout << endl;
00840 }
00841 }
00842
00843
00844
00845
00846
00850
00851
00852 void
00853 OccRef::printName(bool lineFeed) {
00854
00855 oa::oaString occPathString;
00856 if (!occurrence) {
00857 occPathString = "(null)";
00858 } else if (occurrence->getOccInst()) {
00859 occurrence->getOccInst()->getPathName(oa::oaVerilogNS(), occPathString);
00860 } else {
00861 occPathString = "(top)";
00862 }
00863
00864 cout << occPathString << "." << ref;
00865
00866 if (lineFeed) {
00867 cout << endl;
00868 }
00869 }
00870
00871
00872 }