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"
10 ReferenceBlock::ReferenceBlock(const QString _xmlFile) : AbstractBlock() {
14 void ReferenceBlock::addCategory(int id) {
15 categories.append(id);
18 void ReferenceBlock::setBriefDescription(const QString& str) {
20 descriptionBrief = str;
23 void ReferenceBlock::setDetailedDescription(const QString& str) {
25 descriptionDetail = str;
28 void ReferenceBlock::addImplementation(BlockImplementation *impl) {
29 implementations.append(impl);
32 void ReferenceBlock::setHashMd5() {
34 if (file.open(QIODevice::ReadOnly)) {
35 QByteArray fileData = file.readAll();
36 QByteArray hashData = QCryptographicHash::hash(fileData, QCryptographicHash::Md5);
37 hashMd5 = QString(hashData.toHex());
38 cout << qPrintable(xmlFile) << " has md5 hash : " << qPrintable(hashMd5) << endl;
45 void ReferenceBlock::load(QDomElement &elt) throw(Exception) {
48 cout << "Block : get informations" << endl;
49 QDomElement eltInfo = elt.firstChildElement("informations");
51 loadInformations(eltInfo);
57 cout << "Block : get params" << endl;
58 QDomElement eltParams = eltInfo.nextSiblingElement("parameters");
60 loadParameters(eltParams);
66 cout << "Block : get interfaces" << endl;
67 QDomElement eltInter = eltParams.nextSiblingElement("interfaces");
69 loadInterfaces(eltInter);
75 // create interfaces that correspond to a wishbone parameter, if any.
77 createInterfaceForParameters();
84 void ReferenceBlock::loadInformations(QDomElement &elt) throw(Exception) {
87 if ((elt.isNull()) || (elt.tagName() != "informations")) throw (Exception(BLOCKFILE_CORRUPTED));
89 cout << "Block info : get name" << endl;
90 QDomNode nodeName = elt.firstChild();
91 QDomNode nodeNameTxt = nodeName.firstChild();
92 if (nodeNameTxt.isNull()) {
96 QDomText txtName = nodeNameTxt.toText();
97 name = txtName.data().trimmed();
98 cout<< "block name : " << qPrintable(name) << endl;
101 // getting categories
102 cout << "Block info : get categories" << endl;
103 QDomElement eltCat = nodeName.nextSiblingElement("category");
105 QString idsStr = eltCat.attribute("ids","none");
106 if (idsStr == "none") throw (Exception(BLOCKFILE_CORRUPTED));
107 if (idsStr.isEmpty()) {
108 categories.append(99);
111 QStringList listCat = idsStr.split(",");
112 foreach(QString str, listCat)
114 int idCat = str.toInt(&ok);
115 categories.append(idCat);
119 // getting description
120 cout << "Block info : get description" << endl;
121 QDomElement eltDesc = eltCat.nextSiblingElement("description");
123 QDomElement eltBrief = eltDesc.firstChildElement("brief");
124 QDomNode nodeBriefTxt = eltBrief.firstChild();
125 if (nodeBriefTxt.isNull()) {
126 descriptionBrief = "no brief description";
129 QDomText txtBrief = nodeBriefTxt.toText();
130 descriptionBrief = txtBrief.data().trimmed();
131 cout << "block brief desc : " << qPrintable(descriptionBrief) << endl;
134 QDomElement eltDetail = eltBrief.nextSiblingElement("detailed");
135 QDomNode nodeDetailTxt = eltDetail.firstChild();
136 if (nodeDetailTxt.isNull()) {
137 descriptionDetail = "no detailed description";
140 QDomText txtDetail = nodeDetailTxt.toText();
141 descriptionDetail = txtDetail.data().trimmed();
142 cout << "block detail desc : " << qPrintable(descriptionDetail) << endl;
146 void ReferenceBlock::loadParameters(QDomElement &elt) throw(Exception) {
148 if ((elt.isNull()) || (elt.tagName() != "parameters")) throw (Exception(BLOCKFILE_CORRUPTED));
150 QDomNodeList listNodeParam = elt.elementsByTagName("parameter");
151 for(int i=0; i<listNodeParam.size(); i++) {
152 QDomNode node = listNodeParam.at(i);
153 QDomElement elt = node.toElement();
154 QString nameStr = elt.attribute("name","none");
155 QString contextStr = elt.attribute("context","none");
156 QString typeStr = elt.attribute("type","none");
157 QString valueStr = elt.attribute("value","none");
158 BlockParameter *param = NULL;
160 if(valueStr == "none"){
161 if (contextStr == "generic") throw (Exception(BLOCKFILE_CORRUPTED)); // set is required for generics
164 if (contextStr == "user") {
165 param = new BlockParameterUser(this,nameStr,typeStr,valueStr);
167 else if (contextStr == "generic") {
168 param = new BlockParameterGeneric(this,nameStr,typeStr,valueStr);
170 else if (contextStr == "wb") {
171 QString widthStr = elt.attribute("width","none");
172 QString wbStr = elt.attribute("wishbone","none");
175 QString wbValue = "";
176 QStringList listWb = wbStr.split(",");
177 cout << "wb param has:";
178 foreach(QString s, listWb) {
179 cout << qPrintable(s) << " | ";
183 if (listWb.at(0) == "r") {
184 access = BlockParameter::Read;
186 else if (listWb.at(0) == "w") {
187 access = BlockParameter::Write;
189 wbValue = listWb.at(1).toInt(&ok);
191 if(listWb.at(1) == "true" || listWb.at(1) == "false"){
192 wbValue = listWb.at(1);
197 if(listWb.at(2) == "trigger") {
198 duration = BlockParameter::Trigger;
200 else if(listWb.at(2) == "perm") {
201 duration = BlockParameter::Permanent;
204 param = new BlockParameterWishbone(this,nameStr,typeStr,widthStr,valueStr,access,wbValue,duration);
206 else if (contextStr == "port") {
207 QString ifaceStr = elt.attribute("iface","none");
208 param = new BlockParameterPort(this,nameStr,valueStr,ifaceStr);
212 throw (Exception(BLOCKFILE_CORRUPTED));
214 params.append(param);
218 void ReferenceBlock::loadInterfaces(QDomElement &elt) throw(Exception) {
228 AbstractInterface* inter;
230 if ((elt.isNull()) || (elt.tagName() != "interfaces")) throw (Exception(BLOCKFILE_CORRUPTED));
232 QDomElement eltInputs = elt.firstChildElement("inputs");
233 // getting each input
234 QDomNodeList listNodeInputs = eltInputs.elementsByTagName("input");
235 for(int i=0;i<listNodeInputs.size();i++) {
236 QDomNode node = listNodeInputs.at(i);
237 QDomElement eltInput = node.toElement();
238 nameStr = eltInput.attribute("name","none");
239 typeStr = eltInput.attribute("type","none");
240 widthStr = eltInput.attribute("width","none");
241 endianStr = eltInput.attribute("endian","none");
243 if ((endianStr == "none") || (endianStr == "little")) {
244 endianess = AbstractInterface::LittleEndian;
246 else if (endianStr == "big") {
247 endianess = AbstractInterface::BigEndian;
250 throw (Exception(BLOCKFILE_CORRUPTED));
252 purposeStr = eltInput.attribute("purpose","none");
253 cout << "block : " << this->getName().toStdString() << endl;
254 cout << "purpose for " << nameStr.toStdString() << " : " << purposeStr.toStdString() << endl;
255 purpose = ReferenceInterface::translatePurpose(purposeStr);
256 cout << "translated purpose : " << purpose << endl;
257 multStr = eltInput.attribute("multiplicity","none");
258 mult = ReferenceInterface::translateMultiplicity(multStr);
260 inter = new ReferenceInterface(this,nameStr,AbstractInterface::Input, purpose, typeStr, widthStr, endianess, mult);
261 inputs.append(inter);
263 // getting each control
264 QDomNodeList listNodeInCtl = eltInputs.elementsByTagName("control");
265 for(int i=0;i<listNodeInCtl.size();i++) {
266 QDomNode node = listNodeInCtl.at(i);
267 QDomElement eltInput = node.toElement();
268 nameStr = eltInput.attribute("iface","none");
269 AbstractInterface* dataIface = getIfaceFromName(nameStr);
270 if (dataIface == NULL) throw (Exception(BLOCKFILE_CORRUPTED));
271 nameStr = dataIface->getName()+"_enb";
272 inter = new ReferenceInterface(this,nameStr,AbstractInterface::Input, AbstractInterface::Control,"boolean","1", AbstractInterface::LittleEndian, 1);
273 if (!inter->setAssociatedIface(dataIface)) {
274 throw (Exception(BLOCKFILE_CORRUPTED));
276 cout << "created a control input named " << qPrintable(inter->getName()) << endl;
277 inputs.append(inter);
279 QDomElement eltOutputs = eltInputs.nextSiblingElement("outputs");
280 QDomNodeList listNodeOutputs = eltOutputs.elementsByTagName("output");
281 for(int i=0;i<listNodeOutputs.size();i++) {
282 QDomNode node = listNodeOutputs.at(i);
283 QDomElement eltOutput = node.toElement();
284 nameStr = eltOutput.attribute("name","none");
285 typeStr = eltOutput.attribute("type","none");
286 widthStr = eltOutput.attribute("width","none");
287 endianStr = eltOutput.attribute("endian","none");
289 if ((endianStr == "none") || (endianStr == "little")) {
290 endianess = AbstractInterface::LittleEndian;
292 else if (endianStr == "big") {
293 endianess = AbstractInterface::BigEndian;
296 throw (Exception(BLOCKFILE_CORRUPTED));
298 purposeStr = eltOutput.attribute("purpose","none");
299 purpose = ReferenceInterface::translatePurpose(purposeStr);
300 multStr = eltOutput.attribute("multiplicity","none");
301 mult = ReferenceInterface::translateMultiplicity(multStr);
303 inter = new ReferenceInterface(this,nameStr,AbstractInterface::Output, purpose,typeStr,widthStr, endianess, mult);
304 outputs.append(inter);
306 // getting each control
307 QDomNodeList listNodeOutCtl = eltOutputs.elementsByTagName("control");
308 for(int i=0;i<listNodeOutCtl.size();i++) {
309 QDomNode node = listNodeOutCtl.at(i);
310 QDomElement eltOutput = node.toElement();
311 nameStr = eltOutput.attribute("iface","none");
312 AbstractInterface* dataIface = getIfaceFromName(nameStr);
313 if (dataIface == NULL) throw (Exception(BLOCKFILE_CORRUPTED));
314 nameStr = dataIface->getName()+"_enb";
315 inter = new ReferenceInterface(this,nameStr,AbstractInterface::Output, AbstractInterface::Control,"boolean","1",AbstractInterface::LittleEndian, 1);
316 if (!inter->setAssociatedIface(dataIface)) {
317 throw (Exception(BLOCKFILE_CORRUPTED));
319 cout << "created a control output named " << qPrintable(inter->getName()) << endl;
320 outputs.append(inter);
323 QDomElement eltBidirs = eltInputs.nextSiblingElement("bidirs");
324 QDomNodeList listNodeBidirs = eltBidirs.elementsByTagName("bidir");
325 for(int i=0;i<listNodeBidirs.size();i++) {
326 QDomNode node = listNodeBidirs.at(i);
327 QDomElement eltBidir = node.toElement();
328 nameStr = eltBidir.attribute("name","none");
329 typeStr = eltBidir.attribute("type","none");
330 widthStr = eltBidir.attribute("width","none");
331 endianStr = eltBidir.attribute("endian","none");
333 if ((endianStr == "none") || (endianStr == "little")) {
334 endianess = AbstractInterface::LittleEndian;
336 else if (endianStr == "big") {
337 endianess = AbstractInterface::BigEndian;
340 throw (Exception(BLOCKFILE_CORRUPTED));
342 purposeStr = eltBidir.attribute("purpose","none");
343 purpose = ReferenceInterface::translatePurpose(purposeStr);
344 multStr = eltBidir.attribute("multiplicity","none");
345 mult = ReferenceInterface::translateMultiplicity(multStr);
347 inter = new ReferenceInterface(this,nameStr,AbstractInterface::InOut, purpose,typeStr,widthStr, endianess, mult);
348 bidirs.append(inter);
352 void ReferenceBlock::createInterfaceForParameters() throw(Exception){
353 ReferenceInterface* iface = NULL;
354 foreach(BlockParameter* param, params) {
356 if (param->isWishboneParameter()) {
358 BlockParameterWishbone* p = (BlockParameterWishbone*)param;
359 cout << "creating interface for parameter wb " << qPrintable(p->getName()) << endl;
361 if (p->getWBAccess() == BlockParameter::Read) {
362 iface = new ReferenceInterface(this,p->getName(), AbstractInterface::Output, AbstractInterface::Wishbone, p->getTypeString(),p->getWidth(), AbstractInterface::LittleEndian, 1);
363 outputs.append(iface);
365 else if (p->getWBAccess() == BlockParameter::Write) {
366 iface = new ReferenceInterface(this,p->getName(), AbstractInterface::Input, AbstractInterface::Wishbone,p->getTypeString(),p->getWidth(),AbstractInterface::LittleEndian,1);
367 inputs.append(iface);
370 throw (Exception(BLOCKFILE_CORRUPTED));
376 void ReferenceBlock::parametersValidation(QList<AbstractBlock *> *checkedBlocks, QList<AbstractBlock *> *blocksToConfigure) {
381 only used to save all ReferenceBlock in a library in binary format, so that reference blocks
382 are read very fast at application startup.
385 QDataStream& operator<<(QDataStream &out, const ReferenceBlock &b) {
387 out.setVersion(QDataStream::Qt_5_0);
389 QByteArray blockData;
390 QDataStream toWrite(&blockData, QIODevice::WriteOnly);
393 toWrite << b.xmlFile;
394 toWrite << b.descriptionBrief;
395 toWrite << b.descriptionDetail;
396 toWrite << b.categories;
397 toWrite << b.hashMd5;
398 toWrite << b.params.size();
400 for(int i=0;i<b.params.size();i++) {
402 toWrite << p->getContext();
403 toWrite << p->getName();
404 toWrite << p->getTypeString();
405 toWrite << p->getValue().toString();
406 if (p->isPortParameter()) {
407 toWrite << ((BlockParameterPort*)p)->getIfaceName();
409 else if (p->isWishboneParameter()) {
410 BlockParameterWishbone* pwb = (BlockParameterWishbone*)p;
411 toWrite << pwb->getWidth();
412 toWrite << pwb->getWBAccess();
413 toWrite << pwb->getWBValue();
414 toWrite << pwb->getWBDuration();
419 toWrite << b.inputs.size();
420 // firstly write control ifaces
421 for(int i=0; i<b.inputs.size(); i++){
422 ReferenceInterface *iface = (ReferenceInterface *)(b.inputs.at(i));
423 if (iface->getPurpose() == AbstractInterface::Control) {
424 toWrite << iface->getName();
425 toWrite << iface->getType();
426 toWrite << iface->getWidth();
427 toWrite << iface->getPurpose();
428 toWrite << iface->getDirection();
429 toWrite << iface->getMultiplicity();
432 // secondly, write other ifaces
433 for(int i=0; i<b.inputs.size(); i++){
434 ReferenceInterface *iface = (ReferenceInterface *)(b.inputs.at(i));
435 if (iface->getPurpose() != AbstractInterface::Control) {
436 toWrite << iface->getName();
437 toWrite << iface->getType();
438 toWrite << iface->getWidth();
439 toWrite << iface->getPurpose();
440 toWrite << iface->getDirection();
441 toWrite << iface->getMultiplicity();
444 toWrite << b.outputs.size();
445 // firstly write control ifaces
446 for(int i=0; i<b.outputs.size(); i++){
447 ReferenceInterface *iface = (ReferenceInterface *)(b.outputs.at(i));
448 if (iface->getPurpose() == AbstractInterface::Control) {
449 toWrite << iface->getName();
450 toWrite << iface->getType();
451 toWrite << iface->getWidth();
452 toWrite << iface->getPurpose();
453 toWrite << iface->getDirection();
454 toWrite << iface->getMultiplicity();
457 // secondly, write other ifaces
458 for(int i=0; i<b.outputs.size(); i++){
459 ReferenceInterface *iface = (ReferenceInterface *)(b.outputs.at(i));
460 if (iface->getPurpose() != AbstractInterface::Control) {
461 toWrite << iface->getName();
462 toWrite << iface->getType();
463 toWrite << iface->getWidth();
464 toWrite << iface->getPurpose();
465 toWrite << iface->getDirection();
466 toWrite << iface->getMultiplicity();
469 toWrite << b.bidirs.size();
470 for(int i=0; i<b.bidirs.size(); i++){
471 ReferenceInterface *iface = (ReferenceInterface *)(b.bidirs.at(i));
472 toWrite << iface->getName();
473 toWrite << iface->getType();
474 toWrite << iface->getWidth();
475 toWrite << iface->getPurpose();
476 toWrite << iface->getDirection();
477 toWrite << iface->getMultiplicity();
485 QDataStream& operator>>(QDataStream &in, ReferenceBlock &b) {
488 ReferenceInterface* iface;
493 in.setVersion(QDataStream::Qt_5_0);
499 in >> b.descriptionBrief;
500 in >> b.descriptionDetail;
506 cout << qPrintable(b.name) << " has " << nb << " parameters" << endl;
507 for(int i=0;i<nb;i++) {
508 QString contextStr = "";
510 QString typeStr = "";
511 QString valueStr = "";
517 if (contextStr == "user") {
518 p = new BlockParameterUser(&b,nameStr,typeStr,valueStr);
520 else if (contextStr == "generic") {
521 p = new BlockParameterGeneric(&b,nameStr,typeStr,valueStr);
523 else if (contextStr == "port") {
524 QString ifaceStr = "";
526 p = new BlockParameterPort(&b,nameStr,valueStr,ifaceStr);
528 else if (contextStr == "wb") {
529 QString widthStr = "";
537 p = new BlockParameterWishbone(&b,nameStr,typeStr,widthStr,valueStr,wbAccess,wbValue,wbDuration);
544 for(int i=0;i<nb;i++) {
545 iface = new ReferenceInterface(&b);
550 iface->setType(type);
552 iface->setWidth(txt);
554 iface->setPurpose(val);
556 iface->setDirection(val);
558 iface->setMultiplicity(val);
559 b.inputs.append(iface);
560 if (iface->getPurpose() == AbstractInterface::Data) {
561 QString ctlRefName = iface->getName()+"_enb";
562 ReferenceInterface* ctlRefIface = AI_TO_REF(b.getIfaceFromName(ctlRefName));
563 if (ctlRefIface != NULL) {
564 if (! ctlRefIface->setAssociatedIface(iface)) {
565 cerr << "Abnormal case while reading a reference block in library" << endl;
573 for(int i=0;i<nb;i++) {
574 iface = new ReferenceInterface(&b);
579 iface->setType(type);
581 iface->setWidth(txt);
583 iface->setPurpose(val);
585 iface->setDirection(val);
587 iface->setMultiplicity(val);
588 b.outputs.append(iface);
589 if (iface->getPurpose() == AbstractInterface::Data) {
590 QString ctlRefName = iface->getName()+"_enb";
591 ReferenceInterface* ctlRefIface = AI_TO_REF(b.getIfaceFromName(ctlRefName));
592 if (ctlRefIface != NULL) {
593 if (! ctlRefIface->setAssociatedIface(iface)) {
594 cerr << "Abnormal case while reading a reference block in library" << endl;
602 for(int i=0;i<nb;i++) {
603 iface = new ReferenceInterface(&b);
608 iface->setType(type);
610 iface->setWidth(txt);
612 iface->setPurpose(val);
614 iface->setDirection(val);
616 iface->setMultiplicity(val);
617 b.bidirs.append(iface);
623 void ReferenceBlock::checkInputPatternCompatibility() throw(Exception){
624 throw(Exception(INVALID_REFBLOCK_USE));
627 void ReferenceBlock::computeOutputPattern(int nbExec) throw(Exception) {
628 // does strictly nothing
629 throw(Exception(INVALID_REFBLOCK_USE));
632 void ReferenceBlock::computeAdmittanceDelays() throw(Exception) {
633 // does strictly nothing
634 throw(Exception(INVALID_REFBLOCK_USE));