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(NULL) {
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) {
43 cout << "Block : get version" << endl;
44 QString verStr = elt.attribute("version","none");
45 QString specialStr = elt.attribute("special","none");
46 if (verStr != "none") {
52 setSpecialType(getSpecialTypeFromString(specialStr));
54 cout << "Block : get informations" << endl;
55 QDomElement eltInfo = elt.firstChildElement("informations");
57 loadInformations(eltInfo);
63 cout << "Block : get params" << endl;
64 QDomElement eltParams = eltInfo.nextSiblingElement("parameters");
66 loadParameters(eltParams);
72 cout << "Block : get interfaces" << endl;
73 QDomElement eltInter = eltParams.nextSiblingElement("interfaces");
75 loadInterfaces(eltInter);
81 // create interfaces that correspond to a wishbone parameter, if any.
83 createInterfaceForParameters();
90 void ReferenceBlock::loadInformations(QDomElement &elt) throw(Exception) {
93 if ((elt.isNull()) || (elt.tagName() != "informations")) throw (Exception(BLOCKFILE_CORRUPTED));
95 cout << "Block info : get name" << endl;
96 QDomNode nodeName = elt.firstChild();
97 QDomNode nodeNameTxt = nodeName.firstChild();
98 if (nodeNameTxt.isNull()) {
102 QDomText txtName = nodeNameTxt.toText();
103 name = Parameters::normalizeName(txtName.data().trimmed());
104 cout<< "block name : " << qPrintable(name) << endl;
107 // getting categories
108 cout << "Block info : get categories" << endl;
109 QDomElement eltCat = nodeName.nextSiblingElement("category");
111 QString idsStr = eltCat.attribute("ids","none");
112 if (idsStr == "none") throw (Exception(BLOCKFILE_CORRUPTED));
113 if (idsStr.isEmpty()) {
114 categories.append(99);
117 QStringList listCat = idsStr.split(",");
118 foreach(QString str, listCat)
120 int idCat = str.toInt(&ok);
121 categories.append(idCat);
125 // getting description
126 cout << "Block info : get description" << endl;
127 QDomElement eltDesc = eltCat.nextSiblingElement("description");
129 QDomNode nodeTxt = eltDesc.firstChild();
130 if (nodeTxt.isNull()) {
131 description = "no description";
134 QDomText txtBrief = nodeTxt.toText();
135 description = txtBrief.data().trimmed();
136 cout << "block desc : " << qPrintable(description) << endl;
140 void ReferenceBlock::loadParameters(QDomElement &elt) throw(Exception) {
142 if ((elt.isNull()) || (elt.tagName() != "parameters")) throw (Exception(BLOCKFILE_CORRUPTED));
144 QDomNodeList listNodeParam = elt.elementsByTagName("parameter");
145 for(int i=0; i<listNodeParam.size(); i++) {
146 QDomNode node = listNodeParam.at(i);
147 QDomElement elt = node.toElement();
148 QString nameStr = elt.attribute("name","none");
149 QString contextStr = elt.attribute("context","none");
150 QString typeStr = elt.attribute("type","none");
151 QString valueStr = elt.attribute("value","none");
152 BlockParameter *param = NULL;
154 if(valueStr == "none"){
155 if (contextStr == "generic") throw (Exception(BLOCKFILE_CORRUPTED)); // set is required for generics
158 if (contextStr == "user") {
159 param = new BlockParameterUser(this,nameStr,typeStr,valueStr);
161 else if (contextStr == "generic") {
162 param = new BlockParameterGeneric(this,nameStr,typeStr,valueStr);
164 else if (contextStr == "wb") {
165 QString widthStr = elt.attribute("width","none");
166 QString wbStr = elt.attribute("wishbone","none");
169 QString wbValue = "";
170 QStringList listWb = wbStr.split(",");
171 cout << "wb param has:";
172 foreach(QString s, listWb) {
173 cout << qPrintable(s) << " | ";
177 if (listWb.at(0) == "r") {
178 access = BlockParameter::Read;
180 else if (listWb.at(0) == "w") {
181 access = BlockParameter::Write;
183 wbValue = listWb.at(1).toInt(&ok);
185 if(listWb.at(1) == "true" || listWb.at(1) == "false"){
186 wbValue = listWb.at(1);
191 if(listWb.at(2) == "trigger") {
192 duration = BlockParameter::Trigger;
194 else if(listWb.at(2) == "perm") {
195 duration = BlockParameter::Permanent;
198 param = new BlockParameterWishbone(this,nameStr,typeStr,widthStr,valueStr,access,wbValue,duration);
200 else if (contextStr == "port") {
201 QString ifaceStr = elt.attribute("iface","none");
202 param = new BlockParameterPort(this,nameStr,valueStr,ifaceStr);
206 throw (Exception(BLOCKFILE_CORRUPTED));
208 params.append(param);
212 void ReferenceBlock::loadInterfaces(QDomElement &elt) throw(Exception) {
223 AbstractInterface* inter;
225 if ((elt.isNull()) || (elt.tagName() != "interfaces")) throw (Exception(BLOCKFILE_CORRUPTED));
227 QDomElement eltInputs = elt.firstChildElement("inputs");
228 // getting each input
229 QDomNodeList listNodeInputs = eltInputs.elementsByTagName("input");
231 // find all input clocks
232 QList<AbstractInterface*> clocks;
233 for(int i=0;i<listNodeInputs.size();i++) {
234 QDomNode node = listNodeInputs.at(i);
235 QDomElement eltInput = node.toElement();
236 purposeStr = eltInput.attribute("purpose","none");
237 if (purposeStr == "clock") {
238 nameStr = eltInput.attribute("name","none");
239 inter = new ReferenceInterface(this,nameStr,AbstractInterface::Input, AbstractInterface::Clock, "boolean", "1", AbstractInterface::LittleEndian, 1);
240 inputs.append(inter);
241 clocks.append(inter);
244 cout << "number of clocks: " << clocks.size() << endl;
247 for(int i=0;i<listNodeInputs.size();i++) {
248 QDomNode node = listNodeInputs.at(i);
249 QDomElement eltInput = node.toElement();
250 purposeStr = eltInput.attribute("purpose","none");
251 purpose = ReferenceInterface::translatePurpose(purposeStr);
252 if (purpose != AbstractInterface::Clock) {
253 cout << "translated purpose : " << purpose << endl;
254 nameStr = eltInput.attribute("name","none");
255 typeStr = eltInput.attribute("type","none");
256 widthStr = eltInput.attribute("width","none");
257 endianStr = eltInput.attribute("endian","none");
258 clockStr = eltInput.attribute("clock","none");
260 if ((endianStr == "none") || (endianStr == "little")) {
261 endianess = AbstractInterface::LittleEndian;
263 else if (endianStr == "big") {
264 endianess = AbstractInterface::BigEndian;
267 throw (Exception(BLOCKFILE_CORRUPTED));
270 multStr = eltInput.attribute("multiplicity","none");
271 mult = ReferenceInterface::translateMultiplicity(multStr);
273 inter = new ReferenceInterface(this,nameStr, AbstractInterface::Input, purpose, typeStr, widthStr, endianess, mult);
274 if (clockStr == "none") {
275 // no clock given, take the first one (hope that there is a single one !)
276 clockStr = clocks.at(0)->getName();
278 if (! inter->setClockIface(clockStr)) {
279 throw (Exception(BLOCKFILE_CORRUPTED));
281 inputs.append(inter);
284 // getting each control
285 QDomNodeList listNodeInCtl = eltInputs.elementsByTagName("control");
286 for(int i=0;i<listNodeInCtl.size();i++) {
287 QDomNode node = listNodeInCtl.at(i);
288 QDomElement eltInput = node.toElement();
289 nameStr = eltInput.attribute("iface","none");
290 AbstractInterface* dataIface = getIfaceFromName(nameStr);
291 if (dataIface == NULL) throw (Exception(BLOCKFILE_CORRUPTED));
292 nameStr = dataIface->getName()+"_enb";
293 inter = new ReferenceInterface(this,nameStr,AbstractInterface::Input, AbstractInterface::Control,"boolean","1", AbstractInterface::LittleEndian, 1);
294 if (!inter->setAssociatedIface(dataIface)) {
295 throw (Exception(BLOCKFILE_CORRUPTED));
297 cout << "created a control input named " << qPrintable(inter->getName()) << endl;
298 inputs.append(inter);
300 QDomElement eltOutputs = eltInputs.nextSiblingElement("outputs");
301 QDomNodeList listNodeOutputs = eltOutputs.elementsByTagName("output");
302 for(int i=0;i<listNodeOutputs.size();i++) {
303 QDomNode node = listNodeOutputs.at(i);
304 QDomElement eltOutput = node.toElement();
306 nameStr = eltOutput.attribute("name","none");
307 typeStr = eltOutput.attribute("type","none");
308 widthStr = eltOutput.attribute("width","none");
309 endianStr = eltOutput.attribute("endian","none");
310 clockStr = eltOutput.attribute("clock","none");
312 if ((endianStr == "none") || (endianStr == "little")) {
313 endianess = AbstractInterface::LittleEndian;
315 else if (endianStr == "big") {
316 endianess = AbstractInterface::BigEndian;
319 throw (Exception(BLOCKFILE_CORRUPTED));
321 purposeStr = eltOutput.attribute("purpose","none");
322 purpose = ReferenceInterface::translatePurpose(purposeStr);
323 multStr = eltOutput.attribute("multiplicity","none");
324 mult = ReferenceInterface::translateMultiplicity(multStr);
326 inter = new ReferenceInterface(this,nameStr,AbstractInterface::Output, purpose,typeStr,widthStr, endianess, mult);
327 if (clockStr == "none") {
328 // no clock given, take the first one (hope that there is a single one !)
329 clockStr = clocks.at(0)->getName();
331 if (! inter->setClockIface(clockStr)) {
332 throw (Exception(BLOCKFILE_CORRUPTED));
334 outputs.append(inter);
336 // getting each control
337 QDomNodeList listNodeOutCtl = eltOutputs.elementsByTagName("control");
338 for(int i=0;i<listNodeOutCtl.size();i++) {
339 QDomNode node = listNodeOutCtl.at(i);
340 QDomElement eltOutput = node.toElement();
341 nameStr = eltOutput.attribute("iface","none");
342 AbstractInterface* dataIface = getIfaceFromName(nameStr);
343 if (dataIface == NULL) throw (Exception(BLOCKFILE_CORRUPTED));
344 nameStr = dataIface->getName()+"_enb";
345 inter = new ReferenceInterface(this,nameStr,AbstractInterface::Output, AbstractInterface::Control,"boolean","1",AbstractInterface::LittleEndian, 1);
346 if (!inter->setAssociatedIface(dataIface)) {
347 throw (Exception(BLOCKFILE_CORRUPTED));
349 cout << "created a control output named " << qPrintable(inter->getName()) << endl;
350 outputs.append(inter);
353 QDomElement eltBidirs = eltInputs.nextSiblingElement("bidirs");
354 QDomNodeList listNodeBidirs = eltBidirs.elementsByTagName("bidir");
355 for(int i=0;i<listNodeBidirs.size();i++) {
356 QDomNode node = listNodeBidirs.at(i);
357 QDomElement eltBidir = node.toElement();
358 nameStr = eltBidir.attribute("name","none");
359 typeStr = eltBidir.attribute("type","none");
360 widthStr = eltBidir.attribute("width","none");
361 endianStr = eltBidir.attribute("endian","none");
362 clockStr = eltBidir.attribute("clock","none");
364 if ((endianStr == "none") || (endianStr == "little")) {
365 endianess = AbstractInterface::LittleEndian;
367 else if (endianStr == "big") {
368 endianess = AbstractInterface::BigEndian;
371 throw (Exception(BLOCKFILE_CORRUPTED));
373 purposeStr = eltBidir.attribute("purpose","none");
374 purpose = ReferenceInterface::translatePurpose(purposeStr);
375 multStr = eltBidir.attribute("multiplicity","none");
376 mult = ReferenceInterface::translateMultiplicity(multStr);
378 inter = new ReferenceInterface(this,nameStr,AbstractInterface::InOut, purpose,typeStr,widthStr, endianess, mult);
379 if (clockStr == "none") {
380 // no clock given, take the first one (hope that there is a single one !)
381 clockStr = clocks.at(0)->getName();
383 if (! inter->setClockIface(clockStr)) {
384 throw (Exception(BLOCKFILE_CORRUPTED));
386 bidirs.append(inter);
390 void ReferenceBlock::createInterfaceForParameters() throw(Exception){
391 ReferenceInterface* iface = NULL;
392 foreach(BlockParameter* param, params) {
394 if (param->isWishboneParameter()) {
396 BlockParameterWishbone* p = (BlockParameterWishbone*)param;
397 cout << "creating interface for parameter wb " << qPrintable(p->getName()) << endl;
399 if (p->getWBAccess() == BlockParameter::Read) {
400 iface = new ReferenceInterface(this,p->getName(), AbstractInterface::Output, AbstractInterface::Wishbone, p->getTypeString(),p->getWidth(), AbstractInterface::LittleEndian, 1);
401 outputs.append(iface);
403 else if (p->getWBAccess() == BlockParameter::Write) {
404 iface = new ReferenceInterface(this,p->getName(), AbstractInterface::Input, AbstractInterface::Wishbone,p->getTypeString(),p->getWidth(),AbstractInterface::LittleEndian,1);
405 inputs.append(iface);
408 throw (Exception(BLOCKFILE_CORRUPTED));
414 void ReferenceBlock::parametersValidation(QList<AbstractBlock *> *checkedBlocks, QList<AbstractBlock *> *blocksToConfigure) {
419 only used to save all ReferenceBlock in a library in binary format, so that reference blocks
420 are read very fast at application startup.
423 QDataStream& operator<<(QDataStream &out, const ReferenceBlock &b) {
425 out.setVersion(QDataStream::Qt_5_0);
427 QByteArray blockData;
428 QDataStream toWrite(&blockData, QIODevice::WriteOnly);
431 toWrite << b.xmlFile;
432 toWrite << b.specialType;
433 toWrite << b.version;
434 toWrite << b.description;
435 toWrite << b.categories;
436 toWrite << b.hashMd5;
437 toWrite << b.params.size();
439 for(int i=0;i<b.params.size();i++) {
441 toWrite << p->getContext();
442 toWrite << p->getName();
443 toWrite << p->getTypeString();
444 toWrite << p->getValue().toString();
445 if (p->isPortParameter()) {
446 toWrite << ((BlockParameterPort*)p)->getIfaceName();
448 else if (p->isWishboneParameter()) {
449 BlockParameterWishbone* pwb = (BlockParameterWishbone*)p;
450 toWrite << pwb->getWidth();
451 toWrite << pwb->getWBAccess();
452 toWrite << pwb->getWBValue();
453 toWrite << pwb->getWBDuration();
458 toWrite << b.inputs.size();
459 // firstly write clock ifaces
460 for(int i=0; i<b.inputs.size(); i++){
461 ReferenceInterface *iface = (ReferenceInterface *)(b.inputs.at(i));
462 if (iface->getPurpose() == AbstractInterface::Clock) {
463 toWrite << iface->getName();
464 toWrite << iface->getType();
465 toWrite << iface->getWidthString();
466 toWrite << iface->getPurpose();
467 toWrite << iface->getDirection();
468 toWrite << iface->getMultiplicity();
469 toWrite << iface->getClockIfaceType();
470 toWrite << iface->getClockIfaceString();
473 // secondly write control ifaces
474 for(int i=0; i<b.inputs.size(); i++){
475 ReferenceInterface *iface = (ReferenceInterface *)(b.inputs.at(i));
476 if (iface->getPurpose() == AbstractInterface::Control) {
477 toWrite << iface->getName();
478 toWrite << iface->getType();
479 toWrite << iface->getWidthString();
480 toWrite << iface->getPurpose();
481 toWrite << iface->getDirection();
482 toWrite << iface->getMultiplicity();
483 toWrite << iface->getClockIfaceType();
484 toWrite << iface->getClockIfaceString();
487 // secondly, write other ifaces
488 for(int i=0; i<b.inputs.size(); i++){
489 ReferenceInterface *iface = (ReferenceInterface *)(b.inputs.at(i));
490 if ((iface->getPurpose() != AbstractInterface::Control) && (iface->getPurpose() != AbstractInterface::Clock)) {
491 toWrite << iface->getName();
492 toWrite << iface->getType();
493 toWrite << iface->getWidthString();
494 toWrite << iface->getPurpose();
495 toWrite << iface->getDirection();
496 toWrite << iface->getMultiplicity();
497 toWrite << iface->getClockIfaceType();
498 toWrite << iface->getClockIfaceString();
501 toWrite << b.outputs.size();
502 // firstly write control ifaces
503 for(int i=0; i<b.outputs.size(); i++){
504 ReferenceInterface *iface = (ReferenceInterface *)(b.outputs.at(i));
505 if (iface->getPurpose() == AbstractInterface::Control) {
506 toWrite << iface->getName();
507 toWrite << iface->getType();
508 toWrite << iface->getWidthString();
509 toWrite << iface->getPurpose();
510 toWrite << iface->getDirection();
511 toWrite << iface->getMultiplicity();
512 toWrite << iface->getClockIfaceType();
513 toWrite << iface->getClockIfaceString();
516 // secondly, write other ifaces
517 for(int i=0; i<b.outputs.size(); i++){
518 ReferenceInterface *iface = (ReferenceInterface *)(b.outputs.at(i));
519 if (iface->getPurpose() != AbstractInterface::Control) {
520 toWrite << iface->getName();
521 toWrite << iface->getType();
522 toWrite << iface->getWidthString();
523 toWrite << iface->getPurpose();
524 toWrite << iface->getDirection();
525 toWrite << iface->getMultiplicity();
526 toWrite << iface->getClockIfaceType();
527 toWrite << iface->getClockIfaceString();
530 toWrite << b.bidirs.size();
531 for(int i=0; i<b.bidirs.size(); i++){
532 ReferenceInterface *iface = (ReferenceInterface *)(b.bidirs.at(i));
533 toWrite << iface->getName();
534 toWrite << iface->getType();
535 toWrite << iface->getWidthString();
536 toWrite << iface->getPurpose();
537 toWrite << iface->getDirection();
538 toWrite << iface->getMultiplicity();
539 toWrite << iface->getClockIfaceType();
540 toWrite << iface->getClockIfaceString();
548 QDataStream& operator>>(QDataStream &in, ReferenceBlock &b) {
551 ReferenceInterface* iface;
556 in.setVersion(QDataStream::Qt_5_0);
570 cout << qPrintable(b.name) << " has " << nb << " parameters" << endl;
571 for(int i=0;i<nb;i++) {
572 QString contextStr = "";
574 QString typeStr = "";
575 QString valueStr = "";
581 if (contextStr == "user") {
582 p = new BlockParameterUser(&b,nameStr,typeStr,valueStr);
584 else if (contextStr == "generic") {
585 p = new BlockParameterGeneric(&b,nameStr,typeStr,valueStr);
587 else if (contextStr == "port") {
588 QString ifaceStr = "";
590 p = new BlockParameterPort(&b,nameStr,valueStr,ifaceStr);
592 else if (contextStr == "wb") {
593 QString widthStr = "";
601 p = new BlockParameterWishbone(&b,nameStr,typeStr,widthStr,valueStr,wbAccess,wbValue,wbDuration);
608 for(int i=0;i<nb;i++) {
609 iface = new ReferenceInterface(&b);
614 iface->setType(type);
616 iface->setWidth(txt);
618 iface->setPurpose(val);
620 iface->setDirection(val);
622 iface->setMultiplicity(val);
627 if (clkType == AbstractInterface::ParameterName) {
630 if (! iface->setClockIface(clk)) {
631 cerr << "Abnormal case while reading a reference block in library: cannot set ref clock for an interface" << endl;
634 b.inputs.append(iface);
635 if (iface->getPurpose() == AbstractInterface::Data) {
636 QString ctlRefName = iface->getName()+"_enb";
637 ReferenceInterface* ctlRefIface = AI_TO_REF(b.getIfaceFromName(ctlRefName));
638 if (ctlRefIface != NULL) {
639 if (! ctlRefIface->setAssociatedIface(iface)) {
640 cerr << "Abnormal case while reading a reference block in library: cannot set associated control interface for data interface" << endl;
648 for(int i=0;i<nb;i++) {
649 iface = new ReferenceInterface(&b);
654 iface->setType(type);
656 iface->setWidth(txt);
658 iface->setPurpose(val);
660 iface->setDirection(val);
662 iface->setMultiplicity(val);
667 if (clkType == AbstractInterface::ParameterName) {
670 if (! iface->setClockIface(clk)) {
671 cerr << "Abnormal case while reading a reference block in library: cannot set ref clock for an interface" << endl;
673 b.outputs.append(iface);
674 if (iface->getPurpose() == AbstractInterface::Data) {
675 QString ctlRefName = iface->getName()+"_enb";
676 ReferenceInterface* ctlRefIface = AI_TO_REF(b.getIfaceFromName(ctlRefName));
677 if (ctlRefIface != NULL) {
678 if (! ctlRefIface->setAssociatedIface(iface)) {
679 cerr << "Abnormal case while reading a reference block in library" << endl;
687 for(int i=0;i<nb;i++) {
688 iface = new ReferenceInterface(&b);
693 iface->setType(type);
695 iface->setWidth(txt);
697 iface->setPurpose(val);
699 iface->setDirection(val);
701 iface->setMultiplicity(val);
706 if (clkType == AbstractInterface::ParameterName) {
709 if (! iface->setClockIface(clk)) {
710 cerr << "Abnormal case while reading a reference block in library: cannot set ref clock for an interface" << endl;
712 b.bidirs.append(iface);
718 void ReferenceBlock::checkInputPatternCompatibility() throw(Exception){
719 throw(Exception(INVALID_REFBLOCK_USE));
722 void ReferenceBlock::computeOutputPattern(int nbExec) throw(Exception) {
723 // does strictly nothing
724 throw(Exception(INVALID_REFBLOCK_USE));
727 void ReferenceBlock::computeAdmittanceDelays() throw(Exception) {
728 // does strictly nothing
729 throw(Exception(INVALID_REFBLOCK_USE));
733 void ReferenceBlock::generateVHDL(const QString& path) throw(Exception){
734 throw(Exception(INVALID_REFBLOCK_USE));
737 void ReferenceBlock::generateComments(QTextStream& out, QDomElement &elt, QString coreFile) throw(Exception) {
738 throw(Exception(INVALID_REFBLOCK_USE));
741 void ReferenceBlock::generateLibraries(QTextStream& out, QDomElement &elt) throw(Exception) {
742 throw(Exception(INVALID_REFBLOCK_USE));
745 void ReferenceBlock::generateArchitecture(QTextStream& out, QDomElement &elt ) throw(Exception) {
746 throw(Exception(INVALID_REFBLOCK_USE));
749 void ReferenceBlock::generateController(QTextStream& out) throw(Exception) {
750 throw(Exception(INVALID_REFBLOCK_USE));
753 void ReferenceBlock::generateEntityOrComponentBody(QTextStream &out, int indentLevel, bool hasController) throw(Exception) {
754 throw(Exception(INVALID_REFBLOCK_USE));
757 QList<QString> ReferenceBlock::getExternalResources() {