]> AND Private Git Repository - blast.git/blob - ReferenceBlock.cpp
Logo AND Algorithmique Numérique Distribuée

Private GIT Repository
037c64459ff8185ee0f05be5f09fd7c404019c55
[blast.git] / ReferenceBlock.cpp
1 #include "ReferenceBlock.h"
2
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
10 ReferenceBlock::ReferenceBlock(const QString _xmlFile) : AbstractBlock() {
11   xmlFile = _xmlFile;
12 }
13
14 void ReferenceBlock::addCategory(int id) {
15  categories.append(id);
16 }
17
18 void ReferenceBlock::setBriefDescription(const QString& str) {
19   if(str != NULL)
20     descriptionBrief = str;
21 }
22
23 void ReferenceBlock::setDetailedDescription(const QString& str) {
24   if(str != NULL)
25     descriptionDetail = str;
26 }
27
28 void ReferenceBlock::addImplementation(BlockImplementation *impl) {
29   implementations.append(impl);
30 }
31
32 void ReferenceBlock::setHashMd5() {
33   QFile file(xmlFile);
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;
39   }
40   else {
41     hashMd5 = "";
42   }
43 }
44
45 void ReferenceBlock::load(QDomElement &elt) throw(Exception) {
46
47
48   cout << "Block : get informations" << endl;  
49   QDomElement eltInfo  = elt.firstChildElement("informations");
50   try {
51     loadInformations(eltInfo);
52   }
53   catch(int err) {
54     throw(err);
55   }
56
57   cout << "Block : get params" << endl;  
58   QDomElement eltParams  = eltInfo.nextSiblingElement("parameters");
59   try {
60     loadParameters(eltParams);
61   }
62   catch(int err) {
63     throw(err);
64   }
65
66   cout << "Block : get interfaces" << endl;  
67   QDomElement eltInter  = eltParams.nextSiblingElement("interfaces");
68   try {
69     loadInterfaces(eltInter);
70   }
71   catch(int err) {
72     throw(err);
73   }
74
75   // create interfaces that correspond to a wishbone parameter, if any.
76   try {
77     createInterfaceForParameters();    
78   }
79   catch(int err) {
80     throw(err);
81   }  
82 }
83
84 void ReferenceBlock::loadInformations(QDomElement &elt) throw(Exception) {
85
86   bool ok;
87   if ((elt.isNull()) || (elt.tagName() != "informations")) throw (Exception(BLOCKFILE_CORRUPTED));
88   // getting name
89   cout << "Block info : get name" << endl;
90   QDomNode nodeName = elt.firstChild();  
91   QDomNode nodeNameTxt = nodeName.firstChild();
92   if (nodeNameTxt.isNull()) {
93     name = "no_name";
94   }
95   else {
96     QDomText txtName = nodeNameTxt.toText();
97     name = txtName.data().trimmed();
98     cout<< "block name : " << qPrintable(name) << endl;
99   }
100
101   // getting categories
102   cout << "Block info : get categories" << endl;  
103   QDomElement eltCat = nodeName.nextSiblingElement("category");
104
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)
109   {
110     int idCat = str.toInt(&ok);
111     categories.append(idCat);
112   }
113
114   // getting description
115   cout << "Block info : get description" << endl;  
116   QDomElement eltDesc = eltCat.nextSiblingElement("description");
117   // getting brief  
118   QDomElement eltBrief = eltDesc.firstChildElement("brief");
119   QDomNode nodeBriefTxt = eltBrief.firstChild();
120   if (nodeBriefTxt.isNull()) {
121     descriptionBrief = "no brief description";
122   }
123   else {
124     QDomText txtBrief = nodeBriefTxt.toText();
125     descriptionBrief = txtBrief.data().trimmed();
126     cout << "block brief desc : " << qPrintable(descriptionBrief) << endl;
127   }
128   // getting detailed  
129   QDomElement eltDetail = eltBrief.nextSiblingElement("detailed");
130   QDomNode nodeDetailTxt = eltDetail.firstChild();
131   if (nodeDetailTxt.isNull()) {
132     descriptionDetail = "no detailed description";
133   }
134   else {
135     QDomText txtDetail = nodeDetailTxt.toText();
136     descriptionDetail = txtDetail.data().trimmed();
137     cout << "block detail desc : " << qPrintable(descriptionDetail) << endl;
138   }
139 }
140
141 void ReferenceBlock::loadParameters(QDomElement &elt) throw(Exception) {
142
143   if ((elt.isNull()) || (elt.tagName() != "parameters")) throw (Exception(BLOCKFILE_CORRUPTED));
144
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;
154
155     if(valueStr == "none"){
156         if (contextStr == "generic") throw (Exception(BLOCKFILE_CORRUPTED)); // set is required for generics
157         valueStr = "";
158     }
159     if (contextStr == "user") {
160       param = new BlockParameterUser(this,nameStr,typeStr,valueStr);
161     }
162     else if (contextStr == "generic") {
163       param = new BlockParameterGeneric(this,nameStr,typeStr,valueStr);
164     }
165     else if (contextStr == "wb") {
166       QString widthStr = elt.attribute("width","none");
167       QString wbStr = elt.attribute("wishbone","none");
168       int access = 0;
169       int duration = 0;
170       QString wbValue = "";
171       QStringList listWb = wbStr.split(",");
172       cout << "wb param has:";
173       foreach(QString s, listWb) {
174         cout << qPrintable(s) << " | ";
175       }
176       cout << endl;
177
178       if (listWb.at(0) == "r") {
179         access = BlockParameter::Read;
180       }
181       else if (listWb.at(0) == "w") {
182         access = BlockParameter::Write;
183         bool ok;
184         wbValue = listWb.at(1).toInt(&ok);
185         if(!ok){
186             if(listWb.at(1) == "true" || listWb.at(1) == "false"){
187                 wbValue = listWb.at(1);
188             } else {
189                 wbValue = "data";
190             }
191         }
192         if(listWb.at(2) == "trigger") {
193             duration = BlockParameter::Trigger;
194         }
195         else if(listWb.at(2) == "perm") {
196             duration = BlockParameter::Permanent;
197         }
198       }
199       param = new BlockParameterWishbone(this,nameStr,typeStr,widthStr,valueStr,access,wbValue,duration);
200     }
201     else if (contextStr == "port") {
202       QString ifaceStr = elt.attribute("iface","none");
203       param = new BlockParameterPort(this,nameStr,valueStr,ifaceStr);
204
205     }
206     else {
207       throw (Exception(BLOCKFILE_CORRUPTED));
208     }
209     params.append(param);
210   }
211 }
212
213 void ReferenceBlock::loadInterfaces(QDomElement &elt) throw(Exception) {
214
215   QString nameStr;
216   QString typeStr;
217   QString widthStr;
218   QString endianStr;
219   QString purposeStr;
220   int purpose;
221   QString multStr;
222   int mult;
223   AbstractInterface* inter;
224
225   if ((elt.isNull()) || (elt.tagName() != "interfaces")) throw (Exception(BLOCKFILE_CORRUPTED));
226
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");
237     int endianess;
238     if ((endianStr == "none") || (endianStr == "little")) {
239       endianess = AbstractInterface::LittleEndian;
240     }
241     else if (endianStr == "big") {
242       endianess = AbstractInterface::BigEndian;
243     }
244     else {
245       throw (Exception(BLOCKFILE_CORRUPTED));
246     }
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);
254
255     inter = new ReferenceInterface(this,nameStr,AbstractInterface::Input, purpose, typeStr, widthStr, endianess, mult);
256     inputs.append(inter);
257   }
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));      
270     }
271     cout << "created a control input named " << qPrintable(inter->getName()) << endl;
272     inputs.append(inter);
273   }
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");
283     int endianess;
284     if ((endianStr == "none") || (endianStr == "little")) {
285       endianess = AbstractInterface::LittleEndian;
286     }
287     else if (endianStr == "big") {
288       endianess = AbstractInterface::BigEndian;
289     }
290     else {
291       throw (Exception(BLOCKFILE_CORRUPTED));
292     }
293     purposeStr = eltOutput.attribute("purpose","none");
294     purpose = ReferenceInterface::translatePurpose(purposeStr);
295     multStr = eltOutput.attribute("multiplicity","none");
296     mult = ReferenceInterface::translateMultiplicity(multStr);
297
298     inter = new ReferenceInterface(this,nameStr,AbstractInterface::Output, purpose,typeStr,widthStr, endianess, mult);
299     outputs.append(inter);
300   }
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));      
313     }
314     cout << "created a control output named " << qPrintable(inter->getName()) << endl;
315     outputs.append(inter);
316   }
317
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");
327     int endianess;
328     if ((endianStr == "none") || (endianStr == "little")) {
329       endianess = AbstractInterface::LittleEndian;
330     }
331     else if (endianStr == "big") {
332       endianess = AbstractInterface::BigEndian;
333     }
334     else {
335       throw (Exception(BLOCKFILE_CORRUPTED));
336     }
337     purposeStr = eltBidir.attribute("purpose","none");
338     purpose = ReferenceInterface::translatePurpose(purposeStr);
339     multStr = eltBidir.attribute("multiplicity","none");
340     mult = ReferenceInterface::translateMultiplicity(multStr);
341
342     inter = new ReferenceInterface(this,nameStr,AbstractInterface::InOut, purpose,typeStr,widthStr, endianess, mult);
343     bidirs.append(inter);
344   }
345 }
346
347 void ReferenceBlock::createInterfaceForParameters() throw(Exception){
348   ReferenceInterface* iface = NULL;
349   foreach(BlockParameter* param, params) {
350     
351     if (param->isWishboneParameter()) {
352       
353       BlockParameterWishbone* p = (BlockParameterWishbone*)param;      
354       cout << "creating interface for parameter wb " << qPrintable(p->getName()) << endl;
355       
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);        
359       }
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);                
363       }
364       else {
365         throw (Exception(BLOCKFILE_CORRUPTED));
366       }
367     }
368   }
369 }
370
371 void ReferenceBlock::parametersValidation(QList<AbstractBlock *> *checkedBlocks, QList<AbstractBlock *> *blocksToConfigure) {
372     return;
373 }
374
375 /* operator<<() :
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.
378
379  */
380 QDataStream& operator<<(QDataStream &out, const ReferenceBlock &b) {
381
382   out.setVersion(QDataStream::Qt_5_0);
383
384   QByteArray blockData;
385   QDataStream toWrite(&blockData, QIODevice::WriteOnly);
386
387   toWrite << b.name;
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();
394   BlockParameter* p;
395   for(int i=0;i<b.params.size();i++) {
396     p = b.params.at(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();
403     }
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();
410     }
411
412   }
413
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();
424     }
425   }
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();
435     }
436   }
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();
447     }
448   }
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();
458     }
459   }
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();
468   }
469
470   out << blockData;
471
472   return out;
473 }
474
475 QDataStream& operator>>(QDataStream &in, ReferenceBlock &b) {
476
477   quint32 blockSize;
478   ReferenceInterface* iface;
479   BlockParameter* p;
480   int val;
481   QString txt="";
482
483   in.setVersion(QDataStream::Qt_5_0);
484
485   in >> blockSize;
486
487   in >> b.name;
488   in >> b.xmlFile;
489   in >> b.descriptionBrief;
490   in >> b.descriptionDetail;
491   in >> b.categories;
492   in >> b.hashMd5;
493   b.params.clear();
494   int nb;
495   in >> nb;
496   cout << qPrintable(b.name) << " has " << nb << " parameters" << endl;
497   for(int i=0;i<nb;i++) {
498     QString contextStr = "";
499     QString nameStr= "";
500     QString typeStr = "";
501     QString valueStr = "";
502     in >> contextStr;
503     in >> nameStr;
504     in >> typeStr;
505     in >> valueStr;
506
507     if (contextStr == "user") {
508       p = new BlockParameterUser(&b,nameStr,typeStr,valueStr);
509     }
510     else if (contextStr == "generic") {
511       p = new BlockParameterGeneric(&b,nameStr,typeStr,valueStr);
512     }
513     else if (contextStr == "port") {
514       QString ifaceStr = "";
515       in >> ifaceStr;
516       p = new BlockParameterPort(&b,nameStr,valueStr,ifaceStr);
517     }
518     else if (contextStr == "wb") {
519       QString widthStr = "";
520       int wbAccess;
521       QString wbValue;
522       int wbDuration;
523       in >> widthStr;
524       in >> wbAccess;
525       in >> wbValue;
526       in >> wbDuration;
527       p = new BlockParameterWishbone(&b,nameStr,typeStr,widthStr,valueStr,wbAccess,wbValue,wbDuration);
528     }
529     b.params.append(p);
530   }
531
532   b.inputs.clear();
533   in >> nb;
534   for(int i=0;i<nb;i++) {
535     iface = new ReferenceInterface(&b);
536     in >> txt;
537     iface->setName(txt);
538     in >> txt;
539     iface->setWidth(txt);
540     in >> val;
541     iface->setPurpose(val);    
542     in >> val;
543     iface->setDirection(val);    
544     in >> 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;
553         }      
554       }        
555     }    
556   }
557
558   b.outputs.clear();
559   in >> nb;
560   for(int i=0;i<nb;i++) {
561     iface = new ReferenceInterface(&b);
562     in >> txt;
563     iface->setName(txt);
564     in >> txt;
565     iface->setWidth(txt);
566     in >> val;
567     iface->setPurpose(val);    
568     in >> val;
569     iface->setDirection(val);
570     in >> 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;
579         }      
580       }        
581     }    
582   }
583
584   b.bidirs.clear();
585   in >> nb;
586   for(int i=0;i<nb;i++) {
587     iface = new ReferenceInterface(&b);
588     in >> txt;
589     iface->setName(txt);
590     in >> txt;
591     iface->setWidth(txt);
592     in >> val;
593     iface->setPurpose(val);
594     in >> val;
595     iface->setDirection(val);
596     in >> val;    
597     iface->setMultiplicity(val);
598     b.bidirs.append(iface);
599   }
600
601   return in;
602 }
603
604 void ReferenceBlock::checkInputPatternCompatibility()  throw(Exception){
605   throw(Exception(INVALID_REFBLOCK_USE));
606 }
607
608 void ReferenceBlock::computeOutputPattern(int nbExec)  throw(Exception) {
609   // does strictly nothing
610   throw(Exception(INVALID_REFBLOCK_USE));  
611 }