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::setBriefDescription(const QString& str) {
21 descriptionBrief = str;
24 void ReferenceBlock::setDetailedDescription(const QString& str) {
26 descriptionDetail = str;
29 void ReferenceBlock::addImplementation(BlockImplementation *impl) {
30 implementations.append(impl);
33 void ReferenceBlock::setHashMd5() {
35 if (file.open(QIODevice::ReadOnly)) {
36 QByteArray fileData = file.readAll();
37 QByteArray hashData = QCryptographicHash::hash(fileData, QCryptographicHash::Md5);
38 hashMd5 = QString(hashData.toHex());
39 cout << qPrintable(xmlFile) << " has md5 hash : " << qPrintable(hashMd5) << endl;
46 void ReferenceBlock::load(QDomElement &elt) throw(Exception) {
49 cout << "Block : get informations" << endl;
50 QDomElement eltInfo = elt.firstChildElement("informations");
52 loadInformations(eltInfo);
58 cout << "Block : get params" << endl;
59 QDomElement eltParams = eltInfo.nextSiblingElement("parameters");
61 loadParameters(eltParams);
67 cout << "Block : get interfaces" << endl;
68 QDomElement eltInter = eltParams.nextSiblingElement("interfaces");
70 loadInterfaces(eltInter);
76 // create interfaces that correspond to a wishbone parameter, if any.
78 createInterfaceForParameters();
85 void ReferenceBlock::loadInformations(QDomElement &elt) throw(Exception) {
88 if ((elt.isNull()) || (elt.tagName() != "informations")) throw (Exception(BLOCKFILE_CORRUPTED));
90 cout << "Block info : get name" << endl;
91 QDomNode nodeName = elt.firstChild();
92 QDomNode nodeNameTxt = nodeName.firstChild();
93 if (nodeNameTxt.isNull()) {
97 QDomText txtName = nodeNameTxt.toText();
98 name = Parameters::normalizeName(txtName.data().trimmed());
99 cout<< "block name : " << qPrintable(name) << endl;
102 // getting categories
103 cout << "Block info : get categories" << endl;
104 QDomElement eltCat = nodeName.nextSiblingElement("category");
106 QString idsStr = eltCat.attribute("ids","none");
107 if (idsStr == "none") throw (Exception(BLOCKFILE_CORRUPTED));
108 if (idsStr.isEmpty()) {
109 categories.append(99);
112 QStringList listCat = idsStr.split(",");
113 foreach(QString str, listCat)
115 int idCat = str.toInt(&ok);
116 categories.append(idCat);
120 // getting description
121 cout << "Block info : get description" << endl;
122 QDomElement eltDesc = eltCat.nextSiblingElement("description");
124 QDomElement eltBrief = eltDesc.firstChildElement("brief");
125 QDomNode nodeBriefTxt = eltBrief.firstChild();
126 if (nodeBriefTxt.isNull()) {
127 descriptionBrief = "no brief description";
130 QDomText txtBrief = nodeBriefTxt.toText();
131 descriptionBrief = txtBrief.data().trimmed();
132 cout << "block brief desc : " << qPrintable(descriptionBrief) << endl;
135 QDomElement eltDetail = eltBrief.nextSiblingElement("detailed");
136 QDomNode nodeDetailTxt = eltDetail.firstChild();
137 if (nodeDetailTxt.isNull()) {
138 descriptionDetail = "no detailed description";
141 QDomText txtDetail = nodeDetailTxt.toText();
142 descriptionDetail = txtDetail.data().trimmed();
143 cout << "block detail desc : " << qPrintable(descriptionDetail) << endl;
147 void ReferenceBlock::loadParameters(QDomElement &elt) throw(Exception) {
149 if ((elt.isNull()) || (elt.tagName() != "parameters")) throw (Exception(BLOCKFILE_CORRUPTED));
151 QDomNodeList listNodeParam = elt.elementsByTagName("parameter");
152 for(int i=0; i<listNodeParam.size(); i++) {
153 QDomNode node = listNodeParam.at(i);
154 QDomElement elt = node.toElement();
155 QString nameStr = elt.attribute("name","none");
156 QString contextStr = elt.attribute("context","none");
157 QString typeStr = elt.attribute("type","none");
158 QString valueStr = elt.attribute("value","none");
159 BlockParameter *param = NULL;
161 if(valueStr == "none"){
162 if (contextStr == "generic") throw (Exception(BLOCKFILE_CORRUPTED)); // set is required for generics
165 if (contextStr == "user") {
166 param = new BlockParameterUser(this,nameStr,typeStr,valueStr);
168 else if (contextStr == "generic") {
169 param = new BlockParameterGeneric(this,nameStr,typeStr,valueStr);
171 else if (contextStr == "wb") {
172 QString widthStr = elt.attribute("width","none");
173 QString wbStr = elt.attribute("wishbone","none");
176 QString wbValue = "";
177 QStringList listWb = wbStr.split(",");
178 cout << "wb param has:";
179 foreach(QString s, listWb) {
180 cout << qPrintable(s) << " | ";
184 if (listWb.at(0) == "r") {
185 access = BlockParameter::Read;
187 else if (listWb.at(0) == "w") {
188 access = BlockParameter::Write;
190 wbValue = listWb.at(1).toInt(&ok);
192 if(listWb.at(1) == "true" || listWb.at(1) == "false"){
193 wbValue = listWb.at(1);
198 if(listWb.at(2) == "trigger") {
199 duration = BlockParameter::Trigger;
201 else if(listWb.at(2) == "perm") {
202 duration = BlockParameter::Permanent;
205 param = new BlockParameterWishbone(this,nameStr,typeStr,widthStr,valueStr,access,wbValue,duration);
207 else if (contextStr == "port") {
208 QString ifaceStr = elt.attribute("iface","none");
209 param = new BlockParameterPort(this,nameStr,valueStr,ifaceStr);
213 throw (Exception(BLOCKFILE_CORRUPTED));
215 params.append(param);
219 void ReferenceBlock::loadInterfaces(QDomElement &elt) throw(Exception) {
229 AbstractInterface* inter;
231 if ((elt.isNull()) || (elt.tagName() != "interfaces")) throw (Exception(BLOCKFILE_CORRUPTED));
233 QDomElement eltInputs = elt.firstChildElement("inputs");
234 // getting each input
235 QDomNodeList listNodeInputs = eltInputs.elementsByTagName("input");
236 for(int i=0;i<listNodeInputs.size();i++) {
237 QDomNode node = listNodeInputs.at(i);
238 QDomElement eltInput = node.toElement();
239 nameStr = eltInput.attribute("name","none");
240 typeStr = eltInput.attribute("type","none");
241 widthStr = eltInput.attribute("width","none");
242 endianStr = eltInput.attribute("endian","none");
244 if ((endianStr == "none") || (endianStr == "little")) {
245 endianess = AbstractInterface::LittleEndian;
247 else if (endianStr == "big") {
248 endianess = AbstractInterface::BigEndian;
251 throw (Exception(BLOCKFILE_CORRUPTED));
253 purposeStr = eltInput.attribute("purpose","none");
254 cout << "block : " << this->getName().toStdString() << endl;
255 cout << "purpose for " << nameStr.toStdString() << " : " << purposeStr.toStdString() << endl;
256 purpose = ReferenceInterface::translatePurpose(purposeStr);
257 cout << "translated purpose : " << purpose << endl;
258 multStr = eltInput.attribute("multiplicity","none");
259 mult = ReferenceInterface::translateMultiplicity(multStr);
261 inter = new ReferenceInterface(this,nameStr,AbstractInterface::Input, purpose, typeStr, widthStr, endianess, mult);
262 inputs.append(inter);
264 // getting each control
265 QDomNodeList listNodeInCtl = eltInputs.elementsByTagName("control");
266 for(int i=0;i<listNodeInCtl.size();i++) {
267 QDomNode node = listNodeInCtl.at(i);
268 QDomElement eltInput = node.toElement();
269 nameStr = eltInput.attribute("iface","none");
270 AbstractInterface* dataIface = getIfaceFromName(nameStr);
271 if (dataIface == NULL) throw (Exception(BLOCKFILE_CORRUPTED));
272 nameStr = dataIface->getName()+"_enb";
273 inter = new ReferenceInterface(this,nameStr,AbstractInterface::Input, AbstractInterface::Control,"boolean","1", AbstractInterface::LittleEndian, 1);
274 if (!inter->setAssociatedIface(dataIface)) {
275 throw (Exception(BLOCKFILE_CORRUPTED));
277 cout << "created a control input named " << qPrintable(inter->getName()) << endl;
278 inputs.append(inter);
280 QDomElement eltOutputs = eltInputs.nextSiblingElement("outputs");
281 QDomNodeList listNodeOutputs = eltOutputs.elementsByTagName("output");
282 for(int i=0;i<listNodeOutputs.size();i++) {
283 QDomNode node = listNodeOutputs.at(i);
284 QDomElement eltOutput = node.toElement();
285 nameStr = eltOutput.attribute("name","none");
286 typeStr = eltOutput.attribute("type","none");
287 widthStr = eltOutput.attribute("width","none");
288 endianStr = eltOutput.attribute("endian","none");
290 if ((endianStr == "none") || (endianStr == "little")) {
291 endianess = AbstractInterface::LittleEndian;
293 else if (endianStr == "big") {
294 endianess = AbstractInterface::BigEndian;
297 throw (Exception(BLOCKFILE_CORRUPTED));
299 purposeStr = eltOutput.attribute("purpose","none");
300 purpose = ReferenceInterface::translatePurpose(purposeStr);
301 multStr = eltOutput.attribute("multiplicity","none");
302 mult = ReferenceInterface::translateMultiplicity(multStr);
304 inter = new ReferenceInterface(this,nameStr,AbstractInterface::Output, purpose,typeStr,widthStr, endianess, mult);
305 outputs.append(inter);
307 // getting each control
308 QDomNodeList listNodeOutCtl = eltOutputs.elementsByTagName("control");
309 for(int i=0;i<listNodeOutCtl.size();i++) {
310 QDomNode node = listNodeOutCtl.at(i);
311 QDomElement eltOutput = node.toElement();
312 nameStr = eltOutput.attribute("iface","none");
313 AbstractInterface* dataIface = getIfaceFromName(nameStr);
314 if (dataIface == NULL) throw (Exception(BLOCKFILE_CORRUPTED));
315 nameStr = dataIface->getName()+"_enb";
316 inter = new ReferenceInterface(this,nameStr,AbstractInterface::Output, AbstractInterface::Control,"boolean","1",AbstractInterface::LittleEndian, 1);
317 if (!inter->setAssociatedIface(dataIface)) {
318 throw (Exception(BLOCKFILE_CORRUPTED));
320 cout << "created a control output named " << qPrintable(inter->getName()) << endl;
321 outputs.append(inter);
324 QDomElement eltBidirs = eltInputs.nextSiblingElement("bidirs");
325 QDomNodeList listNodeBidirs = eltBidirs.elementsByTagName("bidir");
326 for(int i=0;i<listNodeBidirs.size();i++) {
327 QDomNode node = listNodeBidirs.at(i);
328 QDomElement eltBidir = node.toElement();
329 nameStr = eltBidir.attribute("name","none");
330 typeStr = eltBidir.attribute("type","none");
331 widthStr = eltBidir.attribute("width","none");
332 endianStr = eltBidir.attribute("endian","none");
334 if ((endianStr == "none") || (endianStr == "little")) {
335 endianess = AbstractInterface::LittleEndian;
337 else if (endianStr == "big") {
338 endianess = AbstractInterface::BigEndian;
341 throw (Exception(BLOCKFILE_CORRUPTED));
343 purposeStr = eltBidir.attribute("purpose","none");
344 purpose = ReferenceInterface::translatePurpose(purposeStr);
345 multStr = eltBidir.attribute("multiplicity","none");
346 mult = ReferenceInterface::translateMultiplicity(multStr);
348 inter = new ReferenceInterface(this,nameStr,AbstractInterface::InOut, purpose,typeStr,widthStr, endianess, mult);
349 bidirs.append(inter);
353 void ReferenceBlock::createInterfaceForParameters() throw(Exception){
354 ReferenceInterface* iface = NULL;
355 foreach(BlockParameter* param, params) {
357 if (param->isWishboneParameter()) {
359 BlockParameterWishbone* p = (BlockParameterWishbone*)param;
360 cout << "creating interface for parameter wb " << qPrintable(p->getName()) << endl;
362 if (p->getWBAccess() == BlockParameter::Read) {
363 iface = new ReferenceInterface(this,p->getName(), AbstractInterface::Output, AbstractInterface::Wishbone, p->getTypeString(),p->getWidth(), AbstractInterface::LittleEndian, 1);
364 outputs.append(iface);
366 else if (p->getWBAccess() == BlockParameter::Write) {
367 iface = new ReferenceInterface(this,p->getName(), AbstractInterface::Input, AbstractInterface::Wishbone,p->getTypeString(),p->getWidth(),AbstractInterface::LittleEndian,1);
368 inputs.append(iface);
371 throw (Exception(BLOCKFILE_CORRUPTED));
377 void ReferenceBlock::parametersValidation(QList<AbstractBlock *> *checkedBlocks, QList<AbstractBlock *> *blocksToConfigure) {
382 only used to save all ReferenceBlock in a library in binary format, so that reference blocks
383 are read very fast at application startup.
386 QDataStream& operator<<(QDataStream &out, const ReferenceBlock &b) {
388 out.setVersion(QDataStream::Qt_5_0);
390 QByteArray blockData;
391 QDataStream toWrite(&blockData, QIODevice::WriteOnly);
394 toWrite << b.xmlFile;
395 toWrite << b.descriptionBrief;
396 toWrite << b.descriptionDetail;
397 toWrite << b.categories;
398 toWrite << b.hashMd5;
399 toWrite << b.params.size();
401 for(int i=0;i<b.params.size();i++) {
403 toWrite << p->getContext();
404 toWrite << p->getName();
405 toWrite << p->getTypeString();
406 toWrite << p->getValue().toString();
407 if (p->isPortParameter()) {
408 toWrite << ((BlockParameterPort*)p)->getIfaceName();
410 else if (p->isWishboneParameter()) {
411 BlockParameterWishbone* pwb = (BlockParameterWishbone*)p;
412 toWrite << pwb->getWidth();
413 toWrite << pwb->getWBAccess();
414 toWrite << pwb->getWBValue();
415 toWrite << pwb->getWBDuration();
420 toWrite << b.inputs.size();
421 // firstly write control ifaces
422 for(int i=0; i<b.inputs.size(); i++){
423 ReferenceInterface *iface = (ReferenceInterface *)(b.inputs.at(i));
424 if (iface->getPurpose() == AbstractInterface::Control) {
425 toWrite << iface->getName();
426 toWrite << iface->getType();
427 toWrite << iface->getWidth();
428 toWrite << iface->getPurpose();
429 toWrite << iface->getDirection();
430 toWrite << iface->getMultiplicity();
433 // secondly, write other ifaces
434 for(int i=0; i<b.inputs.size(); i++){
435 ReferenceInterface *iface = (ReferenceInterface *)(b.inputs.at(i));
436 if (iface->getPurpose() != AbstractInterface::Control) {
437 toWrite << iface->getName();
438 toWrite << iface->getType();
439 toWrite << iface->getWidth();
440 toWrite << iface->getPurpose();
441 toWrite << iface->getDirection();
442 toWrite << iface->getMultiplicity();
445 toWrite << b.outputs.size();
446 // firstly write control ifaces
447 for(int i=0; i<b.outputs.size(); i++){
448 ReferenceInterface *iface = (ReferenceInterface *)(b.outputs.at(i));
449 if (iface->getPurpose() == AbstractInterface::Control) {
450 toWrite << iface->getName();
451 toWrite << iface->getType();
452 toWrite << iface->getWidth();
453 toWrite << iface->getPurpose();
454 toWrite << iface->getDirection();
455 toWrite << iface->getMultiplicity();
458 // secondly, write other ifaces
459 for(int i=0; i<b.outputs.size(); i++){
460 ReferenceInterface *iface = (ReferenceInterface *)(b.outputs.at(i));
461 if (iface->getPurpose() != AbstractInterface::Control) {
462 toWrite << iface->getName();
463 toWrite << iface->getType();
464 toWrite << iface->getWidth();
465 toWrite << iface->getPurpose();
466 toWrite << iface->getDirection();
467 toWrite << iface->getMultiplicity();
470 toWrite << b.bidirs.size();
471 for(int i=0; i<b.bidirs.size(); i++){
472 ReferenceInterface *iface = (ReferenceInterface *)(b.bidirs.at(i));
473 toWrite << iface->getName();
474 toWrite << iface->getType();
475 toWrite << iface->getWidth();
476 toWrite << iface->getPurpose();
477 toWrite << iface->getDirection();
478 toWrite << iface->getMultiplicity();
486 QDataStream& operator>>(QDataStream &in, ReferenceBlock &b) {
489 ReferenceInterface* iface;
494 in.setVersion(QDataStream::Qt_5_0);
500 in >> b.descriptionBrief;
501 in >> b.descriptionDetail;
507 cout << qPrintable(b.name) << " has " << nb << " parameters" << endl;
508 for(int i=0;i<nb;i++) {
509 QString contextStr = "";
511 QString typeStr = "";
512 QString valueStr = "";
518 if (contextStr == "user") {
519 p = new BlockParameterUser(&b,nameStr,typeStr,valueStr);
521 else if (contextStr == "generic") {
522 p = new BlockParameterGeneric(&b,nameStr,typeStr,valueStr);
524 else if (contextStr == "port") {
525 QString ifaceStr = "";
527 p = new BlockParameterPort(&b,nameStr,valueStr,ifaceStr);
529 else if (contextStr == "wb") {
530 QString widthStr = "";
538 p = new BlockParameterWishbone(&b,nameStr,typeStr,widthStr,valueStr,wbAccess,wbValue,wbDuration);
545 for(int i=0;i<nb;i++) {
546 iface = new ReferenceInterface(&b);
551 iface->setType(type);
553 iface->setWidth(txt);
555 iface->setPurpose(val);
557 iface->setDirection(val);
559 iface->setMultiplicity(val);
560 b.inputs.append(iface);
561 if (iface->getPurpose() == AbstractInterface::Data) {
562 QString ctlRefName = iface->getName()+"_enb";
563 ReferenceInterface* ctlRefIface = AI_TO_REF(b.getIfaceFromName(ctlRefName));
564 if (ctlRefIface != NULL) {
565 if (! ctlRefIface->setAssociatedIface(iface)) {
566 cerr << "Abnormal case while reading a reference block in library" << endl;
574 for(int i=0;i<nb;i++) {
575 iface = new ReferenceInterface(&b);
580 iface->setType(type);
582 iface->setWidth(txt);
584 iface->setPurpose(val);
586 iface->setDirection(val);
588 iface->setMultiplicity(val);
589 b.outputs.append(iface);
590 if (iface->getPurpose() == AbstractInterface::Data) {
591 QString ctlRefName = iface->getName()+"_enb";
592 ReferenceInterface* ctlRefIface = AI_TO_REF(b.getIfaceFromName(ctlRefName));
593 if (ctlRefIface != NULL) {
594 if (! ctlRefIface->setAssociatedIface(iface)) {
595 cerr << "Abnormal case while reading a reference block in library" << endl;
603 for(int i=0;i<nb;i++) {
604 iface = new ReferenceInterface(&b);
609 iface->setType(type);
611 iface->setWidth(txt);
613 iface->setPurpose(val);
615 iface->setDirection(val);
617 iface->setMultiplicity(val);
618 b.bidirs.append(iface);
624 void ReferenceBlock::checkInputPatternCompatibility() throw(Exception){
625 throw(Exception(INVALID_REFBLOCK_USE));
628 void ReferenceBlock::computeOutputPattern(int nbExec) throw(Exception) {
629 // does strictly nothing
630 throw(Exception(INVALID_REFBLOCK_USE));
633 void ReferenceBlock::computeAdmittanceDelays() throw(Exception) {
634 // does strictly nothing
635 throw(Exception(INVALID_REFBLOCK_USE));
639 void ReferenceBlock::generateVHDL(const QString& path) throw(Exception){
640 throw(Exception(INVALID_REFBLOCK_USE));
643 void ReferenceBlock::generateComments(QTextStream& out, QDomElement &elt, QString coreFile) throw(Exception) {
644 throw(Exception(INVALID_REFBLOCK_USE));
647 void ReferenceBlock::generateLibraries(QTextStream& out, QDomElement &elt) throw(Exception) {
648 throw(Exception(INVALID_REFBLOCK_USE));
651 void ReferenceBlock::generateEntity(QTextStream& out, bool hasController=false) throw(Exception) {
652 throw(Exception(INVALID_REFBLOCK_USE));
655 void ReferenceBlock::generateArchitecture(QTextStream& out, QDomElement &elt ) throw(Exception) {
656 throw(Exception(INVALID_REFBLOCK_USE));
659 void ReferenceBlock::generateController(QTextStream& out) throw(Exception) {
660 throw(Exception(INVALID_REFBLOCK_USE));