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
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
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
00116
00126
00127
00128 string
00129 refToVerilogName(ModRef ref) {
00130
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
00144
00154
00155
00156 string
00157 BBRefToVerilogName(BBRef ref) {
00158
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
00172
00175
00176 void
00177 writeBBNodeToVerilog(ofstream& outFile, ModRef x) {
00178
00179 outFile << "\t";
00180
00181
00182
00183 RtlNode::FuncType type = ModGraph::getNodeType(x);
00184 stringstream primitiveName;
00185 switch(type) {
00186 case RtlNode::CONTROL:
00187
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
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
00213 if(verilogWriterPrimitives.find(primitiveName.str()) ==
00214 verilogWriterPrimitives.end()){
00215 verilogWriterPrimitives[primitiveName.str()] = x;
00216 }
00217
00218 outFile << primitiveName.str();
00219
00220
00221 outFile << " inst_" << BBRefToVerilogName(ModGraph::getPrimaryBBID(x));
00222
00223 outFile << "( ";
00224
00225
00226
00227 for(list<ModRef>::iterator refIter = fanin.begin(); refIter != fanin.end();
00228 ++ refIter){
00229 outFile << refToVerilogName(*refIter) << ", ";
00230 }
00231
00232
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
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
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
00340 oa::oaModule *module;
00341 oa::oaIter<oa::oaModule> moduleIter(design->getModules());
00342 while((module = moduleIter.getNext())) {
00343 oa::oaString str;
00344
00345
00346 module->getName(verilogNS, str);
00347 outFile << "module " << str << "(";
00348
00349
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
00375
00376
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
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
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
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
00423 for(BBRef cID = pID; cID < pID+numOutputBits; ++ cID){
00424 if (ModGraph::isSequential(ref)) {
00425
00426
00427
00428
00429
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
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
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
00462 char bbNetString[64];
00463 int numOutputBits = ModGraph::getNumOutputBits(ref);
00464 BBRef pID = ModGraph::getPrimaryBBID(ref);
00465
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
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
00487 outFile << "\t" << "assign " << bbNetString << " = "
00488 << refToVerilogName(driver) << ";" << endl;
00489
00490 if (net && net->getSigType() == oa::oacSignalSigType) {
00491
00492 outFile << "\t" << "assign " << str << " = "
00493 << "bb_" << ref.ref << ";" << endl;
00494 }
00495
00496 } else if (net) {
00497
00498 outFile << "\t" << "assign " << bbNetString
00499 << " = " << str << ";" << endl;
00500 } else {
00501
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
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
00535 bool first = true;
00536 if (inst->usesTermPositions()) {
00537
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 << " ";
00559 }
00560 }
00561
00562 } else {
00563
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
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 }