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

oagFpgaVerilogWriter.cpp

Go to the documentation of this file.
00001 
00002 #include "oaDesignDB.h"
00003 #include "oagFpga.h"
00004 #include "oagFpgaManager.h"
00005 #include "oagFpgaModGraph.h"
00006 #include <list>
00007 #include <string>
00008 #include <fstream>
00009 
00010 #include "oagFpgaDebug.h"
00011 
00012 namespace oagFpga {
00013 
00014 map<string, ModRef> verilogWriterPrimitives;
00015 
00016 // *****************************************************************************
00017 // getBaseName()
00018 //
00025 //
00026 // *****************************************************************************
00027 string
00028 getBaseName(oa::oaName &name) {
00029 
00030   oa::oaString str;  
00031   const oa::oaVerilogNS verilogNS;
00032 
00033   switch(name.getType()) {
00034   case oa::oacScalarNameType: {
00035     oa::oaScalarName *scalarName = name.getScalar();
00036     assert(scalarName);
00037     scalarName->get(verilogNS, str);
00038     return string(str);
00039   }
00040   case oa::oacVectorNameType: {
00041     oa::oaVectorName *vectorName = name.getVector();
00042     assert(vectorName);
00043     vectorName->getBaseName(verilogNS, str);
00044     return string(str);
00045   }
00046   case oa::oacVectorBitNameType: {
00047     oa::oaVectorBitName *vectorBitName = name.getVectorBit(); 
00048     assert(vectorBitName);
00049     vectorBitName->getBaseName(verilogNS, str);
00050     return string(str);
00051   }          
00052   default:
00053     cerr << "ERROR: Unsupported name type" << endl;
00054     QUIT_ON_ERROR;
00055   }
00056 
00057   return string("");
00058 }
00059 
00060 
00061 // *****************************************************************************
00062 // writeNetDef()
00063 //
00072 //
00073 // *****************************************************************************
00074 void
00075 writeNetDef(stringstream & ss, oa::oaModNet *net) {
00076   assert(net);
00077   
00078   oa::oaString str;
00079   const oa::oaVerilogNS verilogNS;
00080 
00081   oa::oaName name;
00082   net->getName(name);
00083   switch(name.getType()) {
00084   case oa::oacScalarNameType: {
00085     oa::oaScalarName *scalarName = name.getScalar();
00086     assert(scalarName);
00087     scalarName->get(verilogNS, str);
00088     ss << str;
00089     break;
00090   }
00091   case oa::oacVectorNameType: {
00092     oa::oaVectorName *vectorName = name.getVector();
00093     assert(vectorName);
00094     ss << "[" << vectorName->getStart()
00095        << ":" << vectorName->getStop() << "] ";
00096     vectorName->getBaseName(verilogNS, str);
00097     ss << str;    
00098     break;
00099   }
00100   case oa::oacVectorBitNameType: {
00101     oa::oaVectorBitName *vectorBitName = name.getVectorBit(); 
00102     assert(vectorBitName);
00103     ss << "[" << vectorBitName->getIndex() << "] ";
00104     vectorBitName->getBaseName(verilogNS, str);
00105     ss << str; 
00106     break;
00107   }          
00108   default:
00109     cerr << "ERROR: Unsupported name type" << endl;
00110     QUIT_ON_ERROR;
00111   }
00112 }
00113 
00114 // *****************************************************************************
00115 // refToVerilogName()
00116 //
00126 //
00127 // *****************************************************************************
00128 string
00129 refToVerilogName(ModRef ref) {
00130   // const char *NULL_ASSIGNMENT = "1'b0";
00131   const char *NULL_ASSIGNMENT = "1'bx";
00132 
00133   stringstream result;
00134   if (ModGraph::isNull(ref)) {
00135     result << NULL_ASSIGNMENT;
00136   } else {
00137     result << "bb_" << ref.ref;
00138   }
00139   return result.str();
00140 }
00141 
00142 // *****************************************************************************
00143 // BBRefToVerilogName()
00144 //
00154 //
00155 // *****************************************************************************
00156 string
00157 BBRefToVerilogName(BBRef ref) {
00158   // const char *NULL_ASSIGNMENT = "1'b0";
00159   const char *NULL_ASSIGNMENT = "1'bx";
00160 
00161   stringstream result;
00162   if (RtlGraph::isNull(ref)) {
00163     result << NULL_ASSIGNMENT;
00164   } else {
00165     result << "bb_" << ref;
00166   }
00167   return result.str();
00168 }
00169 
00170 // *****************************************************************************
00171 // writeBBNodeToVerilog()
00172 //
00175 // *****************************************************************************
00176 void 
00177 writeBBNodeToVerilog(ofstream& outFile, ModRef x) {
00178 
00179     outFile << "\t";
00180 
00181     // Firstly, generate the primitive name
00182 
00183     RtlNode::FuncType type = ModGraph::getNodeType(x);
00184     stringstream primitiveName;
00185     switch(type) {
00186         case RtlNode::CONTROL:
00187             // So far the MUX is one-bit
00188             assert(ModGraph::getNumOutputBits(x) == 1);
00189             primitiveName << "MUX";
00190             break;
00191         case RtlNode::OPERATOR: {
00192             RtlNode::OptType optType = ModGraph::getNodeOptType(x);
00193             const char* optName = RtlNode::optTypeName[optType];
00194             primitiveName << optName;
00195             break;
00196         }
00197         case RtlNode::SEQ: {
00198             // So far the sequential element is one-bit
00199             assert(ModGraph::getNumOutputBits(x) == 1);
00200             RtlNode::SeqType seqType = ModGraph::getNodeSeqType(x);
00201             const char* seqName = RtlNode::seqTypeName[seqType];
00202             primitiveName << seqName;
00203             break;
00204         }
00205         default:
00206             cerr << "ERROR: Unknown BB node type" << endl;
00207             QUIT_ON_ERROR;
00208     }
00209     list<ModRef> fanin = ModGraph::getFanin(x);
00210     primitiveName << "_" << fanin.size() ;
00211 
00212     // setup a symbol list for all black box primitives used
00213     if(verilogWriterPrimitives.find(primitiveName.str()) ==
00214             verilogWriterPrimitives.end()){
00215         verilogWriterPrimitives[primitiveName.str()] = x;
00216     }
00217 
00218     outFile << primitiveName.str();
00219 
00220     // print instance name
00221     outFile << " inst_" << BBRefToVerilogName(ModGraph::getPrimaryBBID(x));
00222    
00223     outFile << "( ";
00224 
00225     // Then, print input pins
00226 
00227     for(list<ModRef>::iterator refIter = fanin.begin(); refIter != fanin.end();
00228             ++ refIter){
00229         outFile << refToVerilogName(*refIter) << ", ";
00230     }
00231 
00232     // Finally, print output pins according to the width of the outputs of a BB node
00233 
00234     int numOutputBits = ModGraph::getNumOutputBits(x);
00235     BBRef pID = ModGraph::getPrimaryBBID(x);
00236     for(BBRef cID = pID; cID < pID+numOutputBits; ++ cID){
00237         outFile << BBRefToVerilogName(cID);
00238         if(cID+1<pID+numOutputBits)
00239             outFile << ", ";
00240     }
00241 
00242     outFile << " );" << endl;
00243 }
00244 
00245 // *****************************************************************************
00246 // writeVerilog()
00247 //
00250 // *****************************************************************************
00251 void
00252 writePrimitiveBlackBoxs(const char* filename) {
00253 
00254     ofstream outFile;
00255     outFile.open(filename, ios::app); 
00256     if (!outFile) {
00257         cerr << "ERROR: Could not open file " << filename << " for output" << endl;
00258         QUIT_ON_ERROR;
00259     }
00260 
00261     for(map<string, ModRef>::iterator primIter = verilogWriterPrimitives.begin();
00262             primIter != verilogWriterPrimitives.end(); ++ primIter) {
00263         string pName = primIter->first;
00264         ModRef pID = primIter->second;
00265         outFile << endl << "// black box module" << endl;
00266         outFile << "module " << pName << " (";
00267         int numInputs = ModGraph::getFanin(pID).size();
00268         for(int i=1;i<=numInputs;i++){
00269             outFile << "in" << i << ", ";
00270         }
00271         int numOutputs = ModGraph::getNumOutputBits(pID);
00272         for(int i=1;i<=numOutputs;i++){
00273             outFile << "out" << i;
00274             if(i<numOutputs)
00275                 outFile << ", ";
00276         }
00277         outFile << ");" << endl;
00278         outFile << "input ";
00279         for(int i=1;i<=numInputs;i++){
00280             outFile << "in" << i;
00281             if(i<numInputs)
00282                 outFile << ", ";
00283         }
00284         outFile << ";" << endl;
00285         outFile << "output ";
00286         for(int i=1;i<=numOutputs;i++){
00287             outFile << "out" << i;
00288             if(i<numOutputs)
00289                 outFile << ", ";
00290         }
00291         outFile << ";" << endl;
00292         outFile << "endmodule" << endl << endl;
00293     }
00294 }
00295 
00296 // *****************************************************************************
00297 // writeVerilog()
00298 //
00317 //
00318 // *****************************************************************************
00319 void            
00320 writeVerilog(oa::oaDesign *design, const char *filename) {
00321     assert(design);
00322     assert(filename);
00323 
00324     const oa::oaVerilogNS verilogNS;
00325 
00326     ofstream outFile;
00327     outFile.open(filename, ios::app); 
00328     if (!outFile) {
00329         cerr << "ERROR: Could not open file " << filename << " for output" << endl;
00330         QUIT_ON_ERROR;
00331     }
00332 
00333     cerr << "Begin to write output Verilog " << filename << "..." << endl;
00334     cerr << "Number of BBNodes is " << 
00335         ModGraph::getGraph(design)->getBBNodeNum() << endl;
00336 
00337     outFile << "// Written by oagFpga Verilog writer" << endl << endl;
00338 
00339     // for each module...
00340     oa::oaModule *module;
00341     oa::oaIter<oa::oaModule> moduleIter(design->getModules());
00342     while((module = moduleIter.getNext())) {
00343         oa::oaString str;
00344 
00345         // 1. write module definition
00346         module->getName(verilogNS, str);
00347         outFile << "module " << str << "(";
00348 
00349         // 1.a. portlist
00350         bool first = true;
00351         oa::oaModTerm *term;
00352         oa::oaIter<oa::oaModTerm> termIter(module->getTerms(oacTermIterNotImplicit));
00353         while((term = termIter.getNext())) {
00354             oa::oaName termName, netName;
00355 
00356             term->getNet()->getName(netName);
00357             term->getName(termName);
00358 
00359             if (!first) {
00360                 outFile << ", ";
00361             }
00362 
00363             if (getBaseName(termName) == getBaseName(netName)) {
00364                 outFile << getBaseName(termName);
00365             } else {
00366                 outFile << "." << getBaseName(termName) << "(" 
00367                     << getBaseName(netName) << ")";
00368             }
00369 
00370             first = false;
00371         }
00372         outFile << ");" << endl;
00373 
00374         // 2. definitions
00375 
00376         // 2.a. inputs/outputs
00377         outFile << "\t" << "// inputs/outputs" << endl;
00378         termIter.reset();
00379         while((term = termIter.getNext())) {
00380             stringstream ss;
00381             writeNetDef(ss, term->getNet());
00382             if(term->getTermType() == oa::oacInputTermType) {
00383                 outFile << "\t" << "input " << ss.str() << ";" << endl;
00384             } else if(term->getTermType() == oa::oacOutputTermType) {
00385                 outFile << "\t" << "output " << ss.str() << ";" << endl;
00386             }
00387         }
00388 
00389         // 2.b. nets
00390         outFile << "\t" << "// intermediate nets defined " 
00391             << "in the original Verilog" << endl;
00392         oa::oaModNet *net;
00393         oa::oaIter<oa::oaModNet> netIter(module->getNets());
00394         while((net = netIter.getNext())) {
00395             // do not write if this is already a terminal
00396             if (net->getTerms().isEmpty()) {
00397                 stringstream ss;
00398                 writeNetDef(ss, net);
00399                 if (net->getSigType() == oa::oacSignalSigType) {
00400                     outFile << "\t" << "wire " << ss.str() << ";" << endl;
00401                 } else if (net->getSigType() == oa::oacTieHiSigType) {
00402                     outFile << "\t" << "supply1 " << ss.str() << ";" << endl;
00403                 }  else if (net->getSigType() == oa::oacTieLoSigType) {
00404                     outFile << "\t" << "supply0 " << ss.str() << ";" << endl;
00405                 }
00406             }
00407         }
00408 
00409         // 2.c. bb graph
00410         outFile << "\t" << "// intermediate wires/regs due to BBNodes" << endl;
00411         list<ModRef> outputNodes, all;
00412         if (Manager::hasManager(module->getDesign())) {
00413             ModGraph::getOutputs(module, outputNodes);
00414             ModGraph::getTransitiveFanin(outputNodes, all, true, true);
00415             all.splice(all.end(), outputNodes);
00416 
00417             for(list<ModRef>::iterator nodeIter = all.begin();
00418                     nodeIter != all.end(); nodeIter++) {
00419                 ModRef ref = *nodeIter;
00420                 int numOutputBits = ModGraph::getNumOutputBits(ref);
00421                 BBRef pID = ModGraph::getPrimaryBBID(ref);
00422                 // write the declarations for every single bit of a BB node
00423                 for(BBRef cID = pID; cID < pID+numOutputBits; ++ cID){
00424                     if (ModGraph::isSequential(ref)) {
00425                         // NOTE: somehow Quartus has trouble for the output
00426                         // Verilog with these "reg", there should be no
00427                         // difference between "reg" and "wire" for a structural
00428                         // Verilog
00429                         //outFile << "\t" << "reg " << "bb_" << cID << ";" << endl;
00430                         outFile << "\t" << "wire " << "bb_" << cID << ";" << endl;
00431                     } else {
00432                         outFile << "\t" << "wire " << "bb_" << cID << ";" << endl;
00433                     }
00434                 }
00435             }
00436             outFile << endl;
00437         }      
00438 
00439         // 3. equivalent nets
00440         outFile << "\t" << "// equivalent nets" << endl;
00441         oa::oaIter<oa::oaModNet> singleNetIter(module->getNets(oacNetIterSingleBit));
00442         while((net = netIter.getNext())) {     
00443             oa::oaModBitNet *bitNet = toBitNet(net);
00444             oa::oaModBitNet *driverNet = ModGraph::findDriverOfEquivalentNets(bitNet);
00445             if (driverNet) {
00446                 bitNet->getName(verilogNS, str);
00447                 outFile << "\t" << "assign " << str << " = ";
00448                 driverNet->getName(verilogNS, str);
00449                 outFile << str << ";" << endl;
00450             }
00451         }
00452 
00453         // 4. Black box graph
00454         outFile << "\t" << "// connections due to BB graph" << endl;
00455         if (Manager::hasManager(module->getDesign())) {
00456 
00457             for(list<ModRef>::iterator nodeIter = all.begin();
00458                     nodeIter != all.end(); nodeIter++) {
00459                 ModRef ref = *nodeIter;
00460 
00461                 // check for naming conflict
00462                 char bbNetString[64];
00463                 int numOutputBits = ModGraph::getNumOutputBits(ref);
00464                 BBRef pID = ModGraph::getPrimaryBBID(ref);
00465                 // check the name for every single bit of a BB node
00466                 for(BBRef cID = pID; cID < pID+numOutputBits; ++ cID){
00467                     sprintf(bbNetString, "bb_%d", cID);
00468                     if (oa::oaModScalarNet::find(module, oa::oaScalarName(verilogNS,
00469                                     bbNetString))) {
00470                         cerr << "ERROR : Module has pre-existing net of conflicting\
00471                             name type \"bb_XXX\"" << endl;
00472                         QUIT_ON_ERROR;
00473                     }
00474                 }
00475 
00476                 if (ModGraph::isTerminal(ref)) {
00477                     // TERMINAL node
00478 
00479                     oa::oaModBitNet *net = ModGraph::getNetToBBConnection(ref);
00480                     if (net) {
00481                         net->getName(verilogNS, str);
00482                     }
00483 
00484                     ModRef driver = ModGraph::getTerminalDriver(ref);
00485                     if (!ModGraph::isNull(driver)) {
00486                         // driven by another node            
00487                         outFile << "\t" << "assign " << bbNetString << " = " 
00488                             << refToVerilogName(driver) << ";" << endl;
00489 
00490                         if (net && net->getSigType() == oa::oacSignalSigType) {
00491                             // net driven by terminal
00492                             outFile << "\t" << "assign " << str << " = " 
00493                                 << "bb_" << ref.ref << ";" << endl;
00494                         }
00495 
00496                     } else if (net) {
00497                         // driven by net
00498                         outFile << "\t" << "assign " << bbNetString 
00499                             << " = " << str << ";" << endl;
00500                     } else {
00501                         // driven by nothing
00502                         cerr << "WARNING: BB Node " << ref.ref << " is driven by\
00503                             nothing" << endl;
00504                     }
00505 
00506                 } else if (ModGraph::isFunctional(ref) ||
00507                         ModGraph::isSequential(ref)) {
00508                     writeBBNodeToVerilog(outFile, ref);
00509 
00510                 } else if (ref == ModGraph::constantZero(module)) {
00511                     outFile << "\t" << "assign " << bbNetString << " = 1'b0;" << endl;
00512                 } else if (ref == ModGraph::constantOne(module)) {
00513                     outFile << "\t" << "assign " << bbNetString << " = 1'b1;" << endl;
00514                 }
00515 
00516             }
00517         }
00518 
00519         // 5. module instantiations
00520         oa::oaModInst *inst;
00521         oa::oaIter<oa::oaModInst> instIter(module->getInsts());
00522         while((inst = instIter.getNext())) {
00523             oa::oaModule *master = inst->getMasterModule();
00524             if (!master) {
00525                 cerr << "ERROR: Could not bind to master module" << endl;
00526                 QUIT_ON_INTERNAL_ERROR;
00527             }
00528             master->getName(verilogNS, str);
00529             outFile << "\t" << str << " ";
00530 
00531             inst->getName(verilogNS, str);
00532             outFile << str << " (";
00533 
00534             // are the connections by name or position?
00535             bool first = true;
00536             if (inst->usesTermPositions()) {
00537                 // connected by position
00538 
00539                 set<int> validPositions;
00540                 oa::oaModInstTerm *instTerm;
00541                 oa::oaIter<oa::oaModInstTerm> instTermIter(inst->getInstTerms());
00542                 while((instTerm = instTermIter.getNext())) {
00543                     validPositions.insert(instTerm->getTermPosition());
00544                 }
00545                 for(int i=*(validPositions.begin()); i<=*(validPositions.rbegin()); i++) {
00546                     assert(validPositions.find(i) != validPositions.end());
00547                     instTerm = oa::oaModInstTerm::find(inst, i);
00548                     assert(instTerm);
00549                     if (!first) {
00550                         outFile << ", ";
00551                     }
00552                     oa::oaModNet *net = instTerm->getNet();
00553                     if (net) {
00554                         first = false;
00555                         net->getName(verilogNS, str);
00556                         outFile << str;
00557                     } else {
00558                         outFile << " "; // no assignment
00559                     }
00560                 }
00561 
00562             } else {
00563                 // connected by name
00564 
00565                 oa::oaModInstTerm *instTerm;
00566                 oa::oaIter<oa::oaModInstTerm> instTermIter(inst->getInstTerms());
00567                 while((instTerm = instTermIter.getNext())) {
00568                     oa::oaModNet *net = instTerm->getNet();
00569                     if (net) {
00570                         if (!first) {
00571                             outFile << ", ";
00572                         }
00573                         first = false;
00574 
00575                         oa::oaName termName;
00576                         instTerm->getTermName(termName);
00577                         net->getName(verilogNS, str);
00578                         outFile << "." << getBaseName(termName) << "(" << str << ")";
00579                     }
00580                 }
00581             }
00582 
00583             outFile << ");" << endl;
00584         }
00585 
00586         outFile << "endmodule" << endl << endl;
00587     }
00588 
00589     outFile.close();
00590 }
00591 
00592 
00593 // *****************************************************************************
00594 // writeVerilog()
00595 //
00602 //
00603 // *****************************************************************************
00604 void            
00605 writeVerilog(oa::oaLib *lib, oa::oaView *view, const char *filename) {
00606     assert(lib);
00607     assert(filename);
00608     assert(view);
00609 
00610     oa::oaScalarName libName;
00611     lib->getName(libName);
00612     oa::oaScalarName viewName;
00613     view->getName(viewName);
00614 
00615     oa::oaCellView *cellView;
00616     oa::oaIter<oa::oaCellView> cellViewIter(view->getCellViews());
00617     while((cellView = cellViewIter.getNext())) {
00618         oa::oaScalarName cellName;
00619         cellView->getCell()->getName(cellName);
00620 
00621         oa::oaDesign *design = oa::oaDesign::find(libName, cellName, viewName);
00622         if (design) {
00623             writeVerilog(design, filename);
00624         }
00625     }
00626     writePrimitiveBlackBoxs(filename);
00627 }
00628 
00629 }

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