X-Git-Url: https://bilbo.iut-bm.univ-fcomte.fr/and/gitweb/blast.git/blobdiff_plain/756baf5c8eaf003e8271dab9c395de2b0e704857..9bfa0c13066918f440ac2b5461fb3f8847f43fd6:/FunctionalBlock.cpp diff --git a/FunctionalBlock.cpp b/FunctionalBlock.cpp index b494784..1ec0c11 100644 --- a/FunctionalBlock.cpp +++ b/FunctionalBlock.cpp @@ -29,6 +29,7 @@ FunctionalBlock::FunctionalBlock(GroupBlock *_parent, ReferenceBlock *_reference lengthPP = -1; delta = -1; evaluator = NULL; + } FunctionalBlock::~FunctionalBlock() { @@ -77,6 +78,8 @@ void FunctionalBlock::populate() { addParameter(p); } + ConnectedInterface* toClk = NULL; + ConnectedInterface* toRst = NULL; // create interfaces from reference block QList lstRef = reference->getInterfaces(); // store relation between functional and reference @@ -90,8 +93,19 @@ void FunctionalBlock::populate() { exit(1); } hashIface.insert(lstRef.at(i),inter); - addInterface(inter); + /* WARNING FOR THE FUTURE : + in case of there are several clock interfaces ofr that block + it would be a godd idea to make the user choose which one + must be connected to defautl clk. + Presently, the first encountered is chosen + */ + if ((toClk == NULL) && (inter->getPurpose() == AbstractInterface::Clock)) { + toClk = AI_TO_CON(inter); + } + if ((toRst == NULL) && (inter->getPurpose() == AbstractInterface::Reset)) { + toRst = AI_TO_CON(inter); + } } AbstractInterface* funCtlIface = NULL; @@ -108,8 +122,19 @@ void FunctionalBlock::populate() { } } } -} + // connect clk and rst to group clk/rst or to clkrstgen + if ((name != "clkrstgen") && (parent != NULL)) { + try { + connectClkReset(); + } + catch(Exception e) { + AbstractBlock* source = (AbstractBlock *)(e.getSource()); + cerr << qPrintable(source->getName()) << ":" << qPrintable(e.getMessage()) << endl; + throw(e); + } + } +} QString FunctionalBlock::getReferenceXmlFile() { return ((ReferenceBlock *)reference)->getXmlFile(); @@ -124,6 +149,8 @@ void FunctionalBlock::createPatterns() throw(Exception) { #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif + + if (implementation->hasNoPatterns()) return; cout << "create patterns for block " << qPrintable(name) << endl; if (evaluator == NULL) evaluator = new ArithmeticEvaluator(); @@ -1287,3 +1314,304 @@ int FunctionalBlock::createTriggers() { } return triggers.size(); } + +void FunctionalBlock::generateVHDL(const QString& path) throw(Exception){ + + BlockImplementation* impl = reference->getImplementations().at(0); // for now only take first impl available + QFile implFile(impl->getXmlFile()); + + // reading in into QDomDocument + QDomDocument document("implFile"); + + if (!implFile.open(QIODevice::ReadOnly)) { + throw(Exception(IMPLFILE_NOACCESS)); + } + if (!document.setContent(&implFile)) { + implFile.close(); + throw(Exception(IMPLFILE_NOACCESS)); + } + implFile.close(); + + bool genController = false; + QString coreFile = ""; + QString controllerFile = ""; + + if (reference->isWBConfigurable()) { + genController = true; + controllerFile = path; + controllerFile += "/"; + controllerFile.append(name); + controllerFile.append("_ctrl.vhd"); + } + else { + controllerFile = "nofile.vhd"; + } + coreFile = path; + coreFile += "/"; + coreFile.append(name); + coreFile.append(".vhd"); + + QFile vhdlCore(coreFile); + QFile vhdlController(controllerFile); + + if (!vhdlCore.open(QIODevice::WriteOnly)) { + throw(Exception(VHDLFILE_NOACCESS)); + } + + if (genController) { + if (!vhdlController.open(QIODevice::WriteOnly)) { + throw(Exception(VHDLFILE_NOACCESS)); + } + } + QTextStream outCore(&vhdlCore); + QTextStream outController; + if (genController) { + outController.setDevice(&vhdlController); + } + + try { + //Get the root element + QDomElement impl = document.documentElement(); + QDomElement eltComments = impl.firstChildElement("comments"); + generateComments(outCore,eltComments, coreFile); + QDomElement eltLibs = eltComments.nextSiblingElement("libraries"); + generateLibraries(outCore, eltLibs); + generateEntity(outCore, genController); + QDomElement eltArch = eltLibs.nextSiblingElement("architecture"); + generateArchitecture(outCore, eltArch ); + if (genController) { + generateController(outController); + } + } + catch(Exception err) { + throw(err); + } + + vhdlCore.close(); + vhdlController.close(); + + } + +void FunctionalBlock::generateComments(QTextStream& out, QDomElement &elt, QString coreFile) throw(Exception) { + + for(int i = 0; i < 50; i++) { + out << "--"; + } + out << "\n--" << endl; + QString fileName = coreFile; + out << "-- File : " << fileName << endl; + out << "--" << endl; + QDomElement eltAuthor = elt.firstChildElement("author"); + QString firstName = eltAuthor.attribute("firstname",""); + QString lastName = eltAuthor.attribute("lastname",""); + QString mail = eltAuthor.attribute("mail",""); + out << "-- Author(s) : "< listParams = reference->getParameters(); + QList listInputs = getInputs(); + QList listOutputs = getOutputs(); + QList listBidirs = getBidirs(); + QString typePort, namePort; + + out << "entity " << name << " is" << endl; + + + /* TODO : rewrite the generation to take into acocunt the new object hierarchy */ + + // Generation of the generics + QList listGenerics = getGenericParameters(); + if ((!listGenerics.isEmpty()) || (hasController)) { + out << " generic (" << endl; + if (hasController) { + out << " wb_data_width : integer = 16;" << endl; + out << " wb_addr_width : integer = 12"; + if (!listGenerics.isEmpty()) out << ";"; + out << endl; + } + for(i=0;itoVHDL(BlockParameter::Entity, 0) << endl; + } + out << " " << listGenerics.at(i)->toVHDL(BlockParameter::Entity,BlockParameter::NoComma) << endl; + + out << " );" << endl; + } + + out << " port (" << endl; + + // Generation of the clk & rst signals + out << " -- clk/rst" << endl; + foreach(AbstractInterface* iface, listInputs) { + if(iface->getPurpose() == AbstractInterface::Clock || iface->getPurpose() == AbstractInterface::Reset) { + out << " " << iface->getName() << " : in std_logic;" << endl; + } + } + + if (hasController) { + // Generation of the wishbone signals + out << " -- registers r/w via wishbone" << endl; + QList listWB = reference->getWishboneParameters(); + for(i=0;itoVHDL(BlockParameter::Entity, 0) << endl; + } + out << " " << listWB.at(i)->toVHDL(BlockParameter::Entity,BlockParameter::NoComma) << endl; + } + + + int count = 0; + foreach(AbstractInterface* iface, getInterfaces()) { + if((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) count++; + } + // Generation of the data/control signals + + int flag = 0; + bool first = true; + + foreach(AbstractInterface* iface, listInputs) { + if(iface->getPurpose() == AbstractInterface::Data) { + if (first) { + out << " -- input data ports" << endl; + first = false; + } + count--; + if (count == 0) flag = AbstractInterface::NoComma; + out << " " << iface->toVHDL(AbstractInterface::Entity, flag) << endl; + } + } + first = true; + foreach(AbstractInterface* iface, listInputs) { + if(iface->getPurpose() == AbstractInterface::Control) { + if (first) { + out << " -- input control ports" << endl; + first = false; + } + count--; + if (count == 0) flag = AbstractInterface::NoComma; + out << " " << iface->toVHDL(AbstractInterface::Entity, flag) << endl; + } + } + first = true; + foreach(AbstractInterface* iface, listOutputs) { + if(iface->getPurpose() == AbstractInterface::Data) { + if (first) { + out << " -- output data ports" << endl; + first = false; + } + count--; + if (count == 0) flag = AbstractInterface::NoComma; + out << " " << iface->toVHDL(AbstractInterface::Entity, flag) << endl; + } + } + first = true; + foreach(AbstractInterface* iface, listOutputs) { + if(iface->getPurpose() == AbstractInterface::Control) { + if (first) { + out << " -- output control ports" << endl; + first = false; + } + count--; + if (count == 0) flag = AbstractInterface::NoComma; + out << " " << iface->toVHDL(AbstractInterface::Entity, flag) << endl; + } + } + first = true; + foreach(AbstractInterface* iface, listBidirs) { + if(iface->getPurpose() == AbstractInterface::Data) { + if (first) { + out << " -- bidirs data ports" << endl; + first = false; + } + count--; + if (count == 0) flag = AbstractInterface::NoComma; + out << " " << iface->toVHDL(AbstractInterface::Entity, flag) << endl; + } + } + out << " );" << endl << endl; + out << "end " << name << ";" << endl << endl; +} + +void FunctionalBlock::generateArchitecture(QTextStream& out, QDomElement &elt ) throw(Exception) { + QString expr; + QString code = elt.text(); + cout << qPrintable(code) << endl; + out << "architecture rtl of " << name << " is" << endl; + + QStringList listLine = code.split("\n"); + for(int i =0; i < listLine.size(); i++) { + QString line = listLine.at(i).simplified(); + + /* + if(listLine.at(i).contains(QRegularExpression("@foreach{"))) { + while(listLine.at(i).compare("@endforeach") != -1) { + expr = expr + listLine.at(i) + '\n'; + i++; + } + expr = expr + listLine.at(i); + out << evalComplex(expr, 1) << '\n'; + } + if(listLine.at(i).contains(QRegularExpression("@caseeach{"))) { + while(listLine.at(i).compare("@endcaseeach") != -1) { + expr = expr + listLine.at(i) + '\n'; + i++; + } + expr = expr + listLine.at(i); + out << evalComplex(expr, 2) << '\n'; + } +*/ + if(line.contains("@{")) { + out << line << endl; + } + } +} + +void FunctionalBlock::generateController(QTextStream &out) throw(Exception) { + +} +