1 #include "ReferenceBlock.h"
3 #include "ReferenceInterface.h"
4 #include "BlockParameter.h"
5 #include "BlockParameterUser.h"
6 #include "BlockParameterGeneric.h"
7 #include "BlockParameterPort.h"
8 #include "BlockParameterWishbone.h"
9 #include "Parameters.h"
11 ReferenceBlock::ReferenceBlock(const QString _xmlFile) : AbstractBlock() {
15 void ReferenceBlock::addCategory(int id) {
16 categories.append(id);
19 void ReferenceBlock::setDescription(const QString& str) {
24 void ReferenceBlock::addImplementation(BlockImplementation *impl) {
25 implementations.append(impl);
28 void ReferenceBlock::setHashMd5() {
30 if (file.open(QIODevice::ReadOnly)) {
31 QByteArray fileData = file.readAll();
32 QByteArray hashData = QCryptographicHash::hash(fileData, QCryptographicHash::Md5);
33 hashMd5 = QString(hashData.toHex());
34 cout << qPrintable(xmlFile) << " has md5 hash : " << qPrintable(hashMd5) << endl;
41 void ReferenceBlock::load(QDomElement &elt) throw(Exception) {
44 cout << "Block : get informations" << endl;
45 QDomElement eltInfo = elt.firstChildElement("informations");
47 loadInformations(eltInfo);
53 cout << "Block : get params" << endl;
54 QDomElement eltParams = eltInfo.nextSiblingElement("parameters");
56 loadParameters(eltParams);
62 cout << "Block : get interfaces" << endl;
63 QDomElement eltInter = eltParams.nextSiblingElement("interfaces");
65 loadInterfaces(eltInter);
71 // create interfaces that correspond to a wishbone parameter, if any.
73 createInterfaceForParameters();
80 void ReferenceBlock::loadInformations(QDomElement &elt) throw(Exception) {
83 if ((elt.isNull()) || (elt.tagName() != "informations")) throw (Exception(BLOCKFILE_CORRUPTED));
85 cout << "Block info : get name" << endl;
86 QDomNode nodeName = elt.firstChild();
87 QDomNode nodeNameTxt = nodeName.firstChild();
88 if (nodeNameTxt.isNull()) {
92 QDomText txtName = nodeNameTxt.toText();
93 name = Parameters::normalizeName(txtName.data().trimmed());
94 cout<< "block name : " << qPrintable(name) << endl;
98 cout << "Block info : get categories" << endl;
99 QDomElement eltCat = nodeName.nextSiblingElement("category");
101 QString idsStr = eltCat.attribute("ids","none");
102 if (idsStr == "none") throw (Exception(BLOCKFILE_CORRUPTED));
103 if (idsStr.isEmpty()) {
104 categories.append(99);
107 QStringList listCat = idsStr.split(",");
108 foreach(QString str, listCat)
110 int idCat = str.toInt(&ok);
111 categories.append(idCat);
115 // getting description
116 cout << "Block info : get description" << endl;
117 QDomElement eltDesc = eltCat.nextSiblingElement("description");
119 QDomNode nodeTxt = eltDesc.firstChild();
120 if (nodeTxt.isNull()) {
121 description = "no description";
124 QDomText txtBrief = nodeTxt.toText();
125 description = txtBrief.data().trimmed();
126 cout << "block desc : " << qPrintable(description) << endl;
130 void ReferenceBlock::loadParameters(QDomElement &elt) throw(Exception) {
132 if ((elt.isNull()) || (elt.tagName() != "parameters")) throw (Exception(BLOCKFILE_CORRUPTED));
134 QDomNodeList listNodeParam = elt.elementsByTagName("parameter");
135 for(int i=0; i<listNodeParam.size(); i++) {
136 QDomNode node = listNodeParam.at(i);
137 QDomElement elt = node.toElement();
138 QString nameStr = elt.attribute("name","none");
139 QString contextStr = elt.attribute("context","none");
140 QString typeStr = elt.attribute("type","none");
141 QString valueStr = elt.attribute("value","none");
142 BlockParameter *param = NULL;
144 if(valueStr == "none"){
145 if (contextStr == "generic") throw (Exception(BLOCKFILE_CORRUPTED)); // set is required for generics
148 if (contextStr == "user") {
149 param = new BlockParameterUser(this,nameStr,typeStr,valueStr);
151 else if (contextStr == "generic") {
152 param = new BlockParameterGeneric(this,nameStr,typeStr,valueStr);
154 else if (contextStr == "wb") {
155 QString widthStr = elt.attribute("width","none");
156 QString wbStr = elt.attribute("wishbone","none");
159 QString wbValue = "";
160 QStringList listWb = wbStr.split(",");
161 cout << "wb param has:";
162 foreach(QString s, listWb) {
163 cout << qPrintable(s) << " | ";
167 if (listWb.at(0) == "r") {
168 access = BlockParameter::Read;
170 else if (listWb.at(0) == "w") {
171 access = BlockParameter::Write;
173 wbValue = listWb.at(1).toInt(&ok);
175 if(listWb.at(1) == "true" || listWb.at(1) == "false"){
176 wbValue = listWb.at(1);
181 if(listWb.at(2) == "trigger") {
182 duration = BlockParameter::Trigger;
184 else if(listWb.at(2) == "perm") {
185 duration = BlockParameter::Permanent;
188 param = new BlockParameterWishbone(this,nameStr,typeStr,widthStr,valueStr,access,wbValue,duration);
190 else if (contextStr == "port") {
191 QString ifaceStr = elt.attribute("iface","none");
192 param = new BlockParameterPort(this,nameStr,valueStr,ifaceStr);
196 throw (Exception(BLOCKFILE_CORRUPTED));
198 params.append(param);
202 void ReferenceBlock::loadInterfaces(QDomElement &elt) throw(Exception) {
213 AbstractInterface* inter;
215 if ((elt.isNull()) || (elt.tagName() != "interfaces")) throw (Exception(BLOCKFILE_CORRUPTED));
217 QDomElement eltInputs = elt.firstChildElement("inputs");
218 // getting each input
219 QDomNodeList listNodeInputs = eltInputs.elementsByTagName("input");
221 // find all input clocks
222 QList<AbstractInterface*> clocks;
223 for(int i=0;i<listNodeInputs.size();i++) {
224 QDomNode node = listNodeInputs.at(i);
225 QDomElement eltInput = node.toElement();
226 purposeStr = eltInput.attribute("purpose","none");
227 if (purposeStr == "clock") {
228 nameStr = eltInput.attribute("name","none");
229 inter = new ReferenceInterface(this,nameStr,AbstractInterface::Input, AbstractInterface::Clock, "boolean", "1", AbstractInterface::LittleEndian, 1);
230 inputs.append(inter);
231 clocks.append(inter);
234 cout << "number of clocks: " << clocks.size() << endl;
237 for(int i=0;i<listNodeInputs.size();i++) {
238 QDomNode node = listNodeInputs.at(i);
239 QDomElement eltInput = node.toElement();
240 purposeStr = eltInput.attribute("purpose","none");
241 purpose = ReferenceInterface::translatePurpose(purposeStr);
242 if (purpose != AbstractInterface::Clock) {
243 cout << "translated purpose : " << purpose << endl;
244 nameStr = eltInput.attribute("name","none");
245 typeStr = eltInput.attribute("type","none");
246 widthStr = eltInput.attribute("width","none");
247 endianStr = eltInput.attribute("endian","none");
248 clockStr = eltInput.attribute("clock","none");
250 if ((endianStr == "none") || (endianStr == "little")) {
251 endianess = AbstractInterface::LittleEndian;
253 else if (endianStr == "big") {
254 endianess = AbstractInterface::BigEndian;
257 throw (Exception(BLOCKFILE_CORRUPTED));
260 multStr = eltInput.attribute("multiplicity","none");
261 mult = ReferenceInterface::translateMultiplicity(multStr);
263 inter = new ReferenceInterface(this,nameStr, AbstractInterface::Input, purpose, typeStr, widthStr, endianess, mult);
264 if (clockStr == "none") {
265 // no clock given, take the first one (hope that there is a single one !)
266 clockStr = clocks.at(0)->getName();
268 if (! inter->setClockIface(clockStr)) {
269 throw (Exception(BLOCKFILE_CORRUPTED));
271 inputs.append(inter);
274 // getting each control
275 QDomNodeList listNodeInCtl = eltInputs.elementsByTagName("control");
276 for(int i=0;i<listNodeInCtl.size();i++) {
277 QDomNode node = listNodeInCtl.at(i);
278 QDomElement eltInput = node.toElement();
279 nameStr = eltInput.attribute("iface","none");
280 AbstractInterface* dataIface = getIfaceFromName(nameStr);
281 if (dataIface == NULL) throw (Exception(BLOCKFILE_CORRUPTED));
282 nameStr = dataIface->getName()+"_enb";
283 inter = new ReferenceInterface(this,nameStr,AbstractInterface::Input, AbstractInterface::Control,"boolean","1", AbstractInterface::LittleEndian, 1);
284 if (!inter->setAssociatedIface(dataIface)) {
285 throw (Exception(BLOCKFILE_CORRUPTED));
287 cout << "created a control input named " << qPrintable(inter->getName()) << endl;
288 inputs.append(inter);
290 QDomElement eltOutputs = eltInputs.nextSiblingElement("outputs");
291 QDomNodeList listNodeOutputs = eltOutputs.elementsByTagName("output");
292 for(int i=0;i<listNodeOutputs.size();i++) {
293 QDomNode node = listNodeOutputs.at(i);
294 QDomElement eltOutput = node.toElement();
296 nameStr = eltOutput.attribute("name","none");
297 typeStr = eltOutput.attribute("type","none");
298 widthStr = eltOutput.attribute("width","none");
299 endianStr = eltOutput.attribute("endian","none");
300 clockStr = eltOutput.attribute("clock","none");
302 if ((endianStr == "none") || (endianStr == "little")) {
303 endianess = AbstractInterface::LittleEndian;
305 else if (endianStr == "big") {
306 endianess = AbstractInterface::BigEndian;
309 throw (Exception(BLOCKFILE_CORRUPTED));
311 purposeStr = eltOutput.attribute("purpose","none");
312 purpose = ReferenceInterface::translatePurpose(purposeStr);
313 multStr = eltOutput.attribute("multiplicity","none");
314 mult = ReferenceInterface::translateMultiplicity(multStr);
316 inter = new ReferenceInterface(this,nameStr,AbstractInterface::Output, purpose,typeStr,widthStr, endianess, mult);
317 if (clockStr == "none") {
318 // no clock given, take the first one (hope that there is a single one !)
319 clockStr = clocks.at(0)->getName();
321 if (! inter->setClockIface(clockStr)) {
322 throw (Exception(BLOCKFILE_CORRUPTED));
324 outputs.append(inter);
326 // getting each control
327 QDomNodeList listNodeOutCtl = eltOutputs.elementsByTagName("control");
328 for(int i=0;i<listNodeOutCtl.size();i++) {
329 QDomNode node = listNodeOutCtl.at(i);
330 QDomElement eltOutput = node.toElement();
331 nameStr = eltOutput.attribute("iface","none");
332 AbstractInterface* dataIface = getIfaceFromName(nameStr);
333 if (dataIface == NULL) throw (Exception(BLOCKFILE_CORRUPTED));
334 nameStr = dataIface->getName()+"_enb";
335 inter = new ReferenceInterface(this,nameStr,AbstractInterface::Output, AbstractInterface::Control,"boolean","1",AbstractInterface::LittleEndian, 1);
336 if (!inter->setAssociatedIface(dataIface)) {
337 throw (Exception(BLOCKFILE_CORRUPTED));
339 cout << "created a control output named " << qPrintable(inter->getName()) << endl;
340 outputs.append(inter);
343 QDomElement eltBidirs = eltInputs.nextSiblingElement("bidirs");
344 QDomNodeList listNodeBidirs = eltBidirs.elementsByTagName("bidir");
345 for(int i=0;i<listNodeBidirs.size();i++) {
346 QDomNode node = listNodeBidirs.at(i);
347 QDomElement eltBidir = node.toElement();
348 nameStr = eltBidir.attribute("name","none");
349 typeStr = eltBidir.attribute("type","none");
350 widthStr = eltBidir.attribute("width","none");
351 endianStr = eltBidir.attribute("endian","none");
352 clockStr = eltBidir.attribute("clock","none");
354 if ((endianStr == "none") || (endianStr == "little")) {
355 endianess = AbstractInterface::LittleEndian;
357 else if (endianStr == "big") {
358 endianess = AbstractInterface::BigEndian;
361 throw (Exception(BLOCKFILE_CORRUPTED));
363 purposeStr = eltBidir.attribute("purpose","none");
364 purpose = ReferenceInterface::translatePurpose(purposeStr);
365 multStr = eltBidir.attribute("multiplicity","none");
366 mult = ReferenceInterface::translateMultiplicity(multStr);
368 inter = new ReferenceInterface(this,nameStr,AbstractInterface::InOut, purpose,typeStr,widthStr, endianess, mult);
369 if (clockStr == "none") {
370 // no clock given, take the first one (hope that there is a single one !)
371 clockStr = clocks.at(0)->getName();
373 if (! inter->setClockIface(clockStr)) {
374 throw (Exception(BLOCKFILE_CORRUPTED));
376 bidirs.append(inter);
380 void ReferenceBlock::createInterfaceForParameters() throw(Exception){
381 ReferenceInterface* iface = NULL;
382 foreach(BlockParameter* param, params) {
384 if (param->isWishboneParameter()) {
386 BlockParameterWishbone* p = (BlockParameterWishbone*)param;
387 cout << "creating interface for parameter wb " << qPrintable(p->getName()) << endl;
389 if (p->getWBAccess() == BlockParameter::Read) {
390 iface = new ReferenceInterface(this,p->getName(), AbstractInterface::Output, AbstractInterface::Wishbone, p->getTypeString(),p->getWidth(), AbstractInterface::LittleEndian, 1);
391 outputs.append(iface);
393 else if (p->getWBAccess() == BlockParameter::Write) {
394 iface = new ReferenceInterface(this,p->getName(), AbstractInterface::Input, AbstractInterface::Wishbone,p->getTypeString(),p->getWidth(),AbstractInterface::LittleEndian,1);
395 inputs.append(iface);
398 throw (Exception(BLOCKFILE_CORRUPTED));
404 void ReferenceBlock::parametersValidation(QList<AbstractBlock *> *checkedBlocks, QList<AbstractBlock *> *blocksToConfigure) {
409 only used to save all ReferenceBlock in a library in binary format, so that reference blocks
410 are read very fast at application startup.
413 QDataStream& operator<<(QDataStream &out, const ReferenceBlock &b) {
415 out.setVersion(QDataStream::Qt_5_0);
417 QByteArray blockData;
418 QDataStream toWrite(&blockData, QIODevice::WriteOnly);
421 toWrite << b.xmlFile;
422 toWrite << b.description;
423 toWrite << b.categories;
424 toWrite << b.hashMd5;
425 toWrite << b.params.size();
427 for(int i=0;i<b.params.size();i++) {
429 toWrite << p->getContext();
430 toWrite << p->getName();
431 toWrite << p->getTypeString();
432 toWrite << p->getValue().toString();
433 if (p->isPortParameter()) {
434 toWrite << ((BlockParameterPort*)p)->getIfaceName();
436 else if (p->isWishboneParameter()) {
437 BlockParameterWishbone* pwb = (BlockParameterWishbone*)p;
438 toWrite << pwb->getWidth();
439 toWrite << pwb->getWBAccess();
440 toWrite << pwb->getWBValue();
441 toWrite << pwb->getWBDuration();
446 toWrite << b.inputs.size();
447 // firstly write clock ifaces
448 for(int i=0; i<b.inputs.size(); i++){
449 ReferenceInterface *iface = (ReferenceInterface *)(b.inputs.at(i));
450 if (iface->getPurpose() == AbstractInterface::Clock) {
451 toWrite << iface->getName();
452 toWrite << iface->getType();
453 toWrite << iface->getWidthString();
454 toWrite << iface->getPurpose();
455 toWrite << iface->getDirection();
456 toWrite << iface->getMultiplicity();
457 toWrite << iface->getClockIfaceType();
458 toWrite << iface->getClockIfaceString();
461 // secondly write control ifaces
462 for(int i=0; i<b.inputs.size(); i++){
463 ReferenceInterface *iface = (ReferenceInterface *)(b.inputs.at(i));
464 if (iface->getPurpose() == AbstractInterface::Control) {
465 toWrite << iface->getName();
466 toWrite << iface->getType();
467 toWrite << iface->getWidthString();
468 toWrite << iface->getPurpose();
469 toWrite << iface->getDirection();
470 toWrite << iface->getMultiplicity();
471 toWrite << iface->getClockIfaceType();
472 toWrite << iface->getClockIfaceString();
475 // secondly, write other ifaces
476 for(int i=0; i<b.inputs.size(); i++){
477 ReferenceInterface *iface = (ReferenceInterface *)(b.inputs.at(i));
478 if ((iface->getPurpose() != AbstractInterface::Control) && (iface->getPurpose() != AbstractInterface::Clock)) {
479 toWrite << iface->getName();
480 toWrite << iface->getType();
481 toWrite << iface->getWidthString();
482 toWrite << iface->getPurpose();
483 toWrite << iface->getDirection();
484 toWrite << iface->getMultiplicity();
485 toWrite << iface->getClockIfaceType();
486 toWrite << iface->getClockIfaceString();
489 toWrite << b.outputs.size();
490 // firstly write control ifaces
491 for(int i=0; i<b.outputs.size(); i++){
492 ReferenceInterface *iface = (ReferenceInterface *)(b.outputs.at(i));
493 if (iface->getPurpose() == AbstractInterface::Control) {
494 toWrite << iface->getName();
495 toWrite << iface->getType();
496 toWrite << iface->getWidthString();
497 toWrite << iface->getPurpose();
498 toWrite << iface->getDirection();
499 toWrite << iface->getMultiplicity();
500 toWrite << iface->getClockIfaceType();
501 toWrite << iface->getClockIfaceString();
504 // secondly, write other ifaces
505 for(int i=0; i<b.outputs.size(); i++){
506 ReferenceInterface *iface = (ReferenceInterface *)(b.outputs.at(i));
507 if (iface->getPurpose() != AbstractInterface::Control) {
508 toWrite << iface->getName();
509 toWrite << iface->getType();
510 toWrite << iface->getWidthString();
511 toWrite << iface->getPurpose();
512 toWrite << iface->getDirection();
513 toWrite << iface->getMultiplicity();
514 toWrite << iface->getClockIfaceType();
515 toWrite << iface->getClockIfaceString();
518 toWrite << b.bidirs.size();
519 for(int i=0; i<b.bidirs.size(); i++){
520 ReferenceInterface *iface = (ReferenceInterface *)(b.bidirs.at(i));
521 toWrite << iface->getName();
522 toWrite << iface->getType();
523 toWrite << iface->getWidthString();
524 toWrite << iface->getPurpose();
525 toWrite << iface->getDirection();
526 toWrite << iface->getMultiplicity();
527 toWrite << iface->getClockIfaceType();
528 toWrite << iface->getClockIfaceString();
536 QDataStream& operator>>(QDataStream &in, ReferenceBlock &b) {
539 ReferenceInterface* iface;
544 in.setVersion(QDataStream::Qt_5_0);
556 cout << qPrintable(b.name) << " has " << nb << " parameters" << endl;
557 for(int i=0;i<nb;i++) {
558 QString contextStr = "";
560 QString typeStr = "";
561 QString valueStr = "";
567 if (contextStr == "user") {
568 p = new BlockParameterUser(&b,nameStr,typeStr,valueStr);
570 else if (contextStr == "generic") {
571 p = new BlockParameterGeneric(&b,nameStr,typeStr,valueStr);
573 else if (contextStr == "port") {
574 QString ifaceStr = "";
576 p = new BlockParameterPort(&b,nameStr,valueStr,ifaceStr);
578 else if (contextStr == "wb") {
579 QString widthStr = "";
587 p = new BlockParameterWishbone(&b,nameStr,typeStr,widthStr,valueStr,wbAccess,wbValue,wbDuration);
594 for(int i=0;i<nb;i++) {
595 iface = new ReferenceInterface(&b);
600 iface->setType(type);
602 iface->setWidth(txt);
604 iface->setPurpose(val);
606 iface->setDirection(val);
608 iface->setMultiplicity(val);
613 if (clkType == AbstractInterface::ParameterName) {
616 if (! iface->setClockIface(clk)) {
617 cerr << "Abnormal case while reading a reference block in library: cannot set ref clock for an interface" << endl;
620 b.inputs.append(iface);
621 if (iface->getPurpose() == AbstractInterface::Data) {
622 QString ctlRefName = iface->getName()+"_enb";
623 ReferenceInterface* ctlRefIface = AI_TO_REF(b.getIfaceFromName(ctlRefName));
624 if (ctlRefIface != NULL) {
625 if (! ctlRefIface->setAssociatedIface(iface)) {
626 cerr << "Abnormal case while reading a reference block in library: cannot set associated control interface for data interface" << endl;
634 for(int i=0;i<nb;i++) {
635 iface = new ReferenceInterface(&b);
640 iface->setType(type);
642 iface->setWidth(txt);
644 iface->setPurpose(val);
646 iface->setDirection(val);
648 iface->setMultiplicity(val);
653 if (clkType == AbstractInterface::ParameterName) {
656 if (! iface->setClockIface(clk)) {
657 cerr << "Abnormal case while reading a reference block in library: cannot set ref clock for an interface" << endl;
659 b.outputs.append(iface);
660 if (iface->getPurpose() == AbstractInterface::Data) {
661 QString ctlRefName = iface->getName()+"_enb";
662 ReferenceInterface* ctlRefIface = AI_TO_REF(b.getIfaceFromName(ctlRefName));
663 if (ctlRefIface != NULL) {
664 if (! ctlRefIface->setAssociatedIface(iface)) {
665 cerr << "Abnormal case while reading a reference block in library" << endl;
673 for(int i=0;i<nb;i++) {
674 iface = new ReferenceInterface(&b);
679 iface->setType(type);
681 iface->setWidth(txt);
683 iface->setPurpose(val);
685 iface->setDirection(val);
687 iface->setMultiplicity(val);
692 if (clkType == AbstractInterface::ParameterName) {
695 if (! iface->setClockIface(clk)) {
696 cerr << "Abnormal case while reading a reference block in library: cannot set ref clock for an interface" << endl;
698 b.bidirs.append(iface);
704 void ReferenceBlock::checkInputPatternCompatibility() throw(Exception){
705 throw(Exception(INVALID_REFBLOCK_USE));
708 void ReferenceBlock::computeOutputPattern(int nbExec) throw(Exception) {
709 // does strictly nothing
710 throw(Exception(INVALID_REFBLOCK_USE));
713 void ReferenceBlock::computeAdmittanceDelays() throw(Exception) {
714 // does strictly nothing
715 throw(Exception(INVALID_REFBLOCK_USE));
719 void ReferenceBlock::generateVHDL(const QString& path) throw(Exception){
720 throw(Exception(INVALID_REFBLOCK_USE));
723 void ReferenceBlock::generateComments(QTextStream& out, QDomElement &elt, QString coreFile) throw(Exception) {
724 throw(Exception(INVALID_REFBLOCK_USE));
727 void ReferenceBlock::generateLibraries(QTextStream& out, QDomElement &elt) throw(Exception) {
728 throw(Exception(INVALID_REFBLOCK_USE));
731 void ReferenceBlock::generateArchitecture(QTextStream& out, QDomElement &elt ) throw(Exception) {
732 throw(Exception(INVALID_REFBLOCK_USE));
735 void ReferenceBlock::generateController(QTextStream& out) throw(Exception) {
736 throw(Exception(INVALID_REFBLOCK_USE));
739 void ReferenceBlock::generateEntityOrComponentBody(QTextStream &out, int indentLevel, bool hasController) throw(Exception) {
740 throw(Exception(INVALID_REFBLOCK_USE));
743 QList<QString> ReferenceBlock::getExternalResources() {