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 QStringList listCat = idsStr.split(",");
108 foreach(QString str, listCat)
110 int idCat = str.toInt(&ok);
111 categories.append(idCat);
114 // getting description
115 cout << "Block info : get description" << endl;
116 QDomElement eltDesc = eltCat.nextSiblingElement("description");
118 QDomElement eltBrief = eltDesc.firstChildElement("brief");
119 QDomNode nodeBriefTxt = eltBrief.firstChild();
120 if (nodeBriefTxt.isNull()) {
121 descriptionBrief = "no brief description";
124 QDomText txtBrief = nodeBriefTxt.toText();
125 descriptionBrief = txtBrief.data().trimmed();
126 cout << "block brief desc : " << qPrintable(descriptionBrief) << endl;
129 QDomElement eltDetail = eltBrief.nextSiblingElement("detailed");
130 QDomNode nodeDetailTxt = eltDetail.firstChild();
131 if (nodeDetailTxt.isNull()) {
132 descriptionDetail = "no detailed description";
135 QDomText txtDetail = nodeDetailTxt.toText();
136 descriptionDetail = txtDetail.data().trimmed();
137 cout << "block detail desc : " << qPrintable(descriptionDetail) << endl;
141 void ReferenceBlock::loadParameters(QDomElement &elt) throw(Exception) {
143 if ((elt.isNull()) || (elt.tagName() != "parameters")) throw (Exception(BLOCKFILE_CORRUPTED));
145 QDomNodeList listNodeParam = elt.elementsByTagName("parameter");
146 for(int i=0; i<listNodeParam.size(); i++) {
147 QDomNode node = listNodeParam.at(i);
148 QDomElement elt = node.toElement();
149 QString nameStr = elt.attribute("name","none");
150 QString contextStr = elt.attribute("context","none");
151 QString typeStr = elt.attribute("type","none");
152 QString valueStr = elt.attribute("value","none");
153 BlockParameter *param = NULL;
155 if(valueStr == "none"){
156 if (contextStr == "generic") throw (Exception(BLOCKFILE_CORRUPTED)); // set is required for generics
159 if (contextStr == "user") {
160 param = new BlockParameterUser(this,nameStr,typeStr,valueStr);
162 else if (contextStr == "generic") {
163 param = new BlockParameterGeneric(this,nameStr,typeStr,valueStr);
165 else if (contextStr == "wb") {
166 QString widthStr = elt.attribute("width","none");
167 QString wbStr = elt.attribute("wishbone","none");
170 QString wbValue = "";
171 QStringList listWb = wbStr.split(",");
172 cout << "wb param has:";
173 foreach(QString s, listWb) {
174 cout << qPrintable(s) << " | ";
178 if (listWb.at(0) == "r") {
179 access = BlockParameter::Read;
181 else if (listWb.at(0) == "w") {
182 access = BlockParameter::Write;
184 wbValue = listWb.at(1).toInt(&ok);
186 if(listWb.at(1) == "true" || listWb.at(1) == "false"){
187 wbValue = listWb.at(1);
192 if(listWb.at(2) == "trigger") {
193 duration = BlockParameter::Trigger;
195 else if(listWb.at(2) == "perm") {
196 duration = BlockParameter::Permanent;
199 param = new BlockParameterWishbone(this,nameStr,typeStr,widthStr,valueStr,access,wbValue,duration);
201 else if (contextStr == "port") {
202 QString ifaceStr = elt.attribute("iface","none");
203 param = new BlockParameterPort(this,nameStr,valueStr,ifaceStr);
207 throw (Exception(BLOCKFILE_CORRUPTED));
209 params.append(param);
213 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");
230 for(int i=0;i<listNodeInputs.size();i++) {
231 QDomNode node = listNodeInputs.at(i);
232 QDomElement eltInput = node.toElement();
233 nameStr = eltInput.attribute("name","none");
234 typeStr = eltInput.attribute("type","none");
235 widthStr = eltInput.attribute("width","none");
236 endianStr = eltInput.attribute("endian","none");
238 if ((endianStr == "none") || (endianStr == "little")) {
239 endianess = AbstractInterface::LittleEndian;
241 else if (endianStr == "big") {
242 endianess = AbstractInterface::BigEndian;
245 throw (Exception(BLOCKFILE_CORRUPTED));
247 purposeStr = eltInput.attribute("purpose","none");
248 cout << "block : " << this->getName().toStdString() << endl;
249 cout << "purpose for " << nameStr.toStdString() << " : " << purposeStr.toStdString() << endl;
250 purpose = ReferenceInterface::translatePurpose(purposeStr);
251 cout << "translated purpose : " << purpose << endl;
252 multStr = eltInput.attribute("multiplicity","none");
253 mult = ReferenceInterface::translateMultiplicity(multStr);
255 inter = new ReferenceInterface(this,nameStr,AbstractInterface::Input, purpose, typeStr, widthStr, endianess, mult);
256 inputs.append(inter);
258 // getting each control
259 QDomNodeList listNodeInCtl = eltInputs.elementsByTagName("control");
260 for(int i=0;i<listNodeInCtl.size();i++) {
261 QDomNode node = listNodeInCtl.at(i);
262 QDomElement eltInput = node.toElement();
263 nameStr = eltInput.attribute("iface","none");
264 AbstractInterface* dataIface = getIfaceFromName(nameStr);
265 if (dataIface == NULL) throw (Exception(BLOCKFILE_CORRUPTED));
266 nameStr = dataIface->getName()+"_enb";
267 inter = new ReferenceInterface(this,nameStr,AbstractInterface::Input, AbstractInterface::Control,"boolean","1", AbstractInterface::LittleEndian, 1);
268 if (!inter->setAssociatedIface(dataIface)) {
269 throw (Exception(BLOCKFILE_CORRUPTED));
271 cout << "created a control input named " << qPrintable(inter->getName()) << endl;
272 inputs.append(inter);
274 QDomElement eltOutputs = eltInputs.nextSiblingElement("outputs");
275 QDomNodeList listNodeOutputs = eltOutputs.elementsByTagName("output");
276 for(int i=0;i<listNodeOutputs.size();i++) {
277 QDomNode node = listNodeOutputs.at(i);
278 QDomElement eltOutput = node.toElement();
279 nameStr = eltOutput.attribute("name","none");
280 typeStr = eltOutput.attribute("type","none");
281 widthStr = eltOutput.attribute("width","none");
282 endianStr = eltOutput.attribute("endian","none");
284 if ((endianStr == "none") || (endianStr == "little")) {
285 endianess = AbstractInterface::LittleEndian;
287 else if (endianStr == "big") {
288 endianess = AbstractInterface::BigEndian;
291 throw (Exception(BLOCKFILE_CORRUPTED));
293 purposeStr = eltOutput.attribute("purpose","none");
294 purpose = ReferenceInterface::translatePurpose(purposeStr);
295 multStr = eltOutput.attribute("multiplicity","none");
296 mult = ReferenceInterface::translateMultiplicity(multStr);
298 inter = new ReferenceInterface(this,nameStr,AbstractInterface::Output, purpose,typeStr,widthStr, endianess, mult);
299 outputs.append(inter);
301 // getting each control
302 QDomNodeList listNodeOutCtl = eltOutputs.elementsByTagName("control");
303 for(int i=0;i<listNodeOutCtl.size();i++) {
304 QDomNode node = listNodeOutCtl.at(i);
305 QDomElement eltOutput = node.toElement();
306 nameStr = eltOutput.attribute("iface","none");
307 AbstractInterface* dataIface = getIfaceFromName(nameStr);
308 if (dataIface == NULL) throw (Exception(BLOCKFILE_CORRUPTED));
309 nameStr = dataIface->getName()+"_enb";
310 inter = new ReferenceInterface(this,nameStr,AbstractInterface::Output, AbstractInterface::Control,"boolean","1",AbstractInterface::LittleEndian, 1);
311 if (!inter->setAssociatedIface(dataIface)) {
312 throw (Exception(BLOCKFILE_CORRUPTED));
314 cout << "created a control output named " << qPrintable(inter->getName()) << endl;
315 outputs.append(inter);
318 QDomElement eltBidirs = eltInputs.nextSiblingElement("bidirs");
319 QDomNodeList listNodeBidirs = eltBidirs.elementsByTagName("bidir");
320 for(int i=0;i<listNodeBidirs.size();i++) {
321 QDomNode node = listNodeBidirs.at(i);
322 QDomElement eltBidir = node.toElement();
323 nameStr = eltBidir.attribute("name","none");
324 typeStr = eltBidir.attribute("type","none");
325 widthStr = eltBidir.attribute("width","none");
326 endianStr = eltBidir.attribute("endian","none");
328 if ((endianStr == "none") || (endianStr == "little")) {
329 endianess = AbstractInterface::LittleEndian;
331 else if (endianStr == "big") {
332 endianess = AbstractInterface::BigEndian;
335 throw (Exception(BLOCKFILE_CORRUPTED));
337 purposeStr = eltBidir.attribute("purpose","none");
338 purpose = ReferenceInterface::translatePurpose(purposeStr);
339 multStr = eltBidir.attribute("multiplicity","none");
340 mult = ReferenceInterface::translateMultiplicity(multStr);
342 inter = new ReferenceInterface(this,nameStr,AbstractInterface::InOut, purpose,typeStr,widthStr, endianess, mult);
343 bidirs.append(inter);
347 void ReferenceBlock::createInterfaceForParameters() throw(Exception){
348 ReferenceInterface* iface = NULL;
349 foreach(BlockParameter* param, params) {
351 if (param->isWishboneParameter()) {
353 BlockParameterWishbone* p = (BlockParameterWishbone*)param;
354 cout << "creating interface for parameter wb " << qPrintable(p->getName()) << endl;
356 if (p->getWBAccess() == BlockParameter::Read) {
357 iface = new ReferenceInterface(this,p->getName(), AbstractInterface::Output, AbstractInterface::Wishbone, p->getTypeString(),p->getWidth(), AbstractInterface::LittleEndian, 1);
358 outputs.append(iface);
360 else if (p->getWBAccess() == BlockParameter::Write) {
361 iface = new ReferenceInterface(this,p->getName(), AbstractInterface::Input, AbstractInterface::Wishbone,p->getTypeString(),p->getWidth(),AbstractInterface::LittleEndian,1);
362 inputs.append(iface);
365 throw (Exception(BLOCKFILE_CORRUPTED));
371 void ReferenceBlock::parametersValidation(QList<AbstractBlock *> *checkedBlocks, QList<AbstractBlock *> *blocksToConfigure) {
376 only used to save all ReferenceBlock in a library in binary format, so that reference blocks
377 are read very fast at application startup.
380 QDataStream& operator<<(QDataStream &out, const ReferenceBlock &b) {
382 out.setVersion(QDataStream::Qt_5_0);
384 QByteArray blockData;
385 QDataStream toWrite(&blockData, QIODevice::WriteOnly);
388 toWrite << b.xmlFile;
389 toWrite << b.descriptionBrief;
390 toWrite << b.descriptionDetail;
391 toWrite << b.categories;
392 toWrite << b.hashMd5;
393 toWrite << b.params.size();
395 for(int i=0;i<b.params.size();i++) {
397 toWrite << p->getContext();
398 toWrite << p->getName();
399 toWrite << p->getTypeString();
400 toWrite << p->getValue().toString();
401 if (p->isPortParameter()) {
402 toWrite << ((BlockParameterPort*)p)->getIfaceName();
404 else if (p->isWishboneParameter()) {
405 BlockParameterWishbone* pwb = (BlockParameterWishbone*)p;
406 toWrite << pwb->getWidth();
407 toWrite << pwb->getWBAccess();
408 toWrite << pwb->getWBValue();
409 toWrite << pwb->getWBDuration();
414 toWrite << b.inputs.size();
415 // firstly write control ifaces
416 for(int i=0; i<b.inputs.size(); i++){
417 ReferenceInterface *iface = (ReferenceInterface *)(b.inputs.at(i));
418 if (iface->getPurpose() == AbstractInterface::Control) {
419 toWrite << iface->getName();
420 toWrite << iface->getWidth();
421 toWrite << iface->getPurpose();
422 toWrite << iface->getDirection();
423 toWrite << iface->getMultiplicity();
426 // secondly, write other ifaces
427 for(int i=0; i<b.inputs.size(); i++){
428 ReferenceInterface *iface = (ReferenceInterface *)(b.inputs.at(i));
429 if (iface->getPurpose() != AbstractInterface::Control) {
430 toWrite << iface->getName();
431 toWrite << iface->getWidth();
432 toWrite << iface->getPurpose();
433 toWrite << iface->getDirection();
434 toWrite << iface->getMultiplicity();
437 toWrite << b.outputs.size();
438 // firstly write control ifaces
439 for(int i=0; i<b.outputs.size(); i++){
440 ReferenceInterface *iface = (ReferenceInterface *)(b.outputs.at(i));
441 if (iface->getPurpose() == AbstractInterface::Control) {
442 toWrite << iface->getName();
443 toWrite << iface->getWidth();
444 toWrite << iface->getPurpose();
445 toWrite << iface->getDirection();
446 toWrite << iface->getMultiplicity();
449 // secondly, write other ifaces
450 for(int i=0; i<b.outputs.size(); i++){
451 ReferenceInterface *iface = (ReferenceInterface *)(b.outputs.at(i));
452 if (iface->getPurpose() != AbstractInterface::Control) {
453 toWrite << iface->getName();
454 toWrite << iface->getWidth();
455 toWrite << iface->getPurpose();
456 toWrite << iface->getDirection();
457 toWrite << iface->getMultiplicity();
460 toWrite << b.bidirs.size();
461 for(int i=0; i<b.bidirs.size(); i++){
462 ReferenceInterface *iface = (ReferenceInterface *)(b.bidirs.at(i));
463 toWrite << iface->getName();
464 toWrite << iface->getWidth();
465 toWrite << iface->getPurpose();
466 toWrite << iface->getDirection();
467 toWrite << iface->getMultiplicity();
475 QDataStream& operator>>(QDataStream &in, ReferenceBlock &b) {
478 ReferenceInterface* iface;
483 in.setVersion(QDataStream::Qt_5_0);
489 in >> b.descriptionBrief;
490 in >> b.descriptionDetail;
496 cout << qPrintable(b.name) << " has " << nb << " parameters" << endl;
497 for(int i=0;i<nb;i++) {
498 QString contextStr = "";
500 QString typeStr = "";
501 QString valueStr = "";
507 if (contextStr == "user") {
508 p = new BlockParameterUser(&b,nameStr,typeStr,valueStr);
510 else if (contextStr == "generic") {
511 p = new BlockParameterGeneric(&b,nameStr,typeStr,valueStr);
513 else if (contextStr == "port") {
514 QString ifaceStr = "";
516 p = new BlockParameterPort(&b,nameStr,valueStr,ifaceStr);
518 else if (contextStr == "wb") {
519 QString widthStr = "";
527 p = new BlockParameterWishbone(&b,nameStr,typeStr,widthStr,valueStr,wbAccess,wbValue,wbDuration);
534 for(int i=0;i<nb;i++) {
535 iface = new ReferenceInterface(&b);
539 iface->setWidth(txt);
541 iface->setPurpose(val);
543 iface->setDirection(val);
545 iface->setMultiplicity(val);
546 b.inputs.append(iface);
547 if (iface->getPurpose() == AbstractInterface::Data) {
548 QString ctlRefName = iface->getName()+"_enb";
549 ReferenceInterface* ctlRefIface = AI_TO_REF(b.getIfaceFromName(ctlRefName));
550 if (ctlRefIface != NULL) {
551 if (! ctlRefIface->setAssociatedIface(iface)) {
552 cerr << "Abnormal case while reading a reference block in library" << endl;
560 for(int i=0;i<nb;i++) {
561 iface = new ReferenceInterface(&b);
565 iface->setWidth(txt);
567 iface->setPurpose(val);
569 iface->setDirection(val);
571 iface->setMultiplicity(val);
572 b.outputs.append(iface);
573 if (iface->getPurpose() == AbstractInterface::Data) {
574 QString ctlRefName = iface->getName()+"_enb";
575 ReferenceInterface* ctlRefIface = AI_TO_REF(b.getIfaceFromName(ctlRefName));
576 if (ctlRefIface != NULL) {
577 if (! ctlRefIface->setAssociatedIface(iface)) {
578 cerr << "Abnormal case while reading a reference block in library" << endl;
586 for(int i=0;i<nb;i++) {
587 iface = new ReferenceInterface(&b);
591 iface->setWidth(txt);
593 iface->setPurpose(val);
595 iface->setDirection(val);
597 iface->setMultiplicity(val);
598 b.bidirs.append(iface);
604 void ReferenceBlock::checkInputPatternCompatibility() throw(Exception){
605 throw(Exception(INVALID_REFBLOCK_USE));
608 void ReferenceBlock::computeOutputPattern(int nbExec) throw(Exception) {
609 // does strictly nothing
610 throw(Exception(INVALID_REFBLOCK_USE));