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

Private GIT Repository
add graph modif, progress on vhdl generation
[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   if (idsStr.isEmpty()) {
108     categories.append(99);
109   }
110   else {
111     QStringList listCat = idsStr.split(",");
112     foreach(QString str, listCat)
113     {
114       int idCat = str.toInt(&ok);
115       categories.append(idCat);
116     }
117   }
118
119   // getting description
120   cout << "Block info : get description" << endl;  
121   QDomElement eltDesc = eltCat.nextSiblingElement("description");
122   // getting brief  
123   QDomElement eltBrief = eltDesc.firstChildElement("brief");
124   QDomNode nodeBriefTxt = eltBrief.firstChild();
125   if (nodeBriefTxt.isNull()) {
126     descriptionBrief = "no brief description";
127   }
128   else {
129     QDomText txtBrief = nodeBriefTxt.toText();
130     descriptionBrief = txtBrief.data().trimmed();
131     cout << "block brief desc : " << qPrintable(descriptionBrief) << endl;
132   }
133   // getting detailed  
134   QDomElement eltDetail = eltBrief.nextSiblingElement("detailed");
135   QDomNode nodeDetailTxt = eltDetail.firstChild();
136   if (nodeDetailTxt.isNull()) {
137     descriptionDetail = "no detailed description";
138   }
139   else {
140     QDomText txtDetail = nodeDetailTxt.toText();
141     descriptionDetail = txtDetail.data().trimmed();
142     cout << "block detail desc : " << qPrintable(descriptionDetail) << endl;
143   }
144 }
145
146 void ReferenceBlock::loadParameters(QDomElement &elt) throw(Exception) {
147
148   if ((elt.isNull()) || (elt.tagName() != "parameters")) throw (Exception(BLOCKFILE_CORRUPTED));
149
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;
159
160     if(valueStr == "none"){
161         if (contextStr == "generic") throw (Exception(BLOCKFILE_CORRUPTED)); // set is required for generics
162         valueStr = "";
163     }
164     if (contextStr == "user") {
165       param = new BlockParameterUser(this,nameStr,typeStr,valueStr);
166     }
167     else if (contextStr == "generic") {
168       param = new BlockParameterGeneric(this,nameStr,typeStr,valueStr);
169     }
170     else if (contextStr == "wb") {
171       QString widthStr = elt.attribute("width","none");
172       QString wbStr = elt.attribute("wishbone","none");
173       int access = 0;
174       int duration = 0;
175       QString wbValue = "";
176       QStringList listWb = wbStr.split(",");
177       cout << "wb param has:";
178       foreach(QString s, listWb) {
179         cout << qPrintable(s) << " | ";
180       }
181       cout << endl;
182
183       if (listWb.at(0) == "r") {
184         access = BlockParameter::Read;
185       }
186       else if (listWb.at(0) == "w") {
187         access = BlockParameter::Write;
188         bool ok;
189         wbValue = listWb.at(1).toInt(&ok);
190         if(!ok){
191             if(listWb.at(1) == "true" || listWb.at(1) == "false"){
192                 wbValue = listWb.at(1);
193             } else {
194                 wbValue = "data";
195             }
196         }
197         if(listWb.at(2) == "trigger") {
198             duration = BlockParameter::Trigger;
199         }
200         else if(listWb.at(2) == "perm") {
201             duration = BlockParameter::Permanent;
202         }
203       }
204       param = new BlockParameterWishbone(this,nameStr,typeStr,widthStr,valueStr,access,wbValue,duration);
205     }
206     else if (contextStr == "port") {
207       QString ifaceStr = elt.attribute("iface","none");
208       param = new BlockParameterPort(this,nameStr,valueStr,ifaceStr);
209
210     }
211     else {
212       throw (Exception(BLOCKFILE_CORRUPTED));
213     }
214     params.append(param);
215   }
216 }
217
218 void ReferenceBlock::loadInterfaces(QDomElement &elt) throw(Exception) {
219
220   QString nameStr;
221   QString typeStr;
222   QString widthStr;
223   QString endianStr;
224   QString purposeStr;
225   int purpose;
226   QString multStr;
227   int mult;
228   AbstractInterface* inter;
229
230   if ((elt.isNull()) || (elt.tagName() != "interfaces")) throw (Exception(BLOCKFILE_CORRUPTED));
231
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");
242     int endianess;
243     if ((endianStr == "none") || (endianStr == "little")) {
244       endianess = AbstractInterface::LittleEndian;
245     }
246     else if (endianStr == "big") {
247       endianess = AbstractInterface::BigEndian;
248     }
249     else {
250       throw (Exception(BLOCKFILE_CORRUPTED));
251     }
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);
259
260     inter = new ReferenceInterface(this,nameStr,AbstractInterface::Input, purpose, typeStr, widthStr, endianess, mult);
261     inputs.append(inter);
262   }
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));      
275     }
276     cout << "created a control input named " << qPrintable(inter->getName()) << endl;
277     inputs.append(inter);
278   }
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");
288     int endianess;
289     if ((endianStr == "none") || (endianStr == "little")) {
290       endianess = AbstractInterface::LittleEndian;
291     }
292     else if (endianStr == "big") {
293       endianess = AbstractInterface::BigEndian;
294     }
295     else {
296       throw (Exception(BLOCKFILE_CORRUPTED));
297     }
298     purposeStr = eltOutput.attribute("purpose","none");
299     purpose = ReferenceInterface::translatePurpose(purposeStr);
300     multStr = eltOutput.attribute("multiplicity","none");
301     mult = ReferenceInterface::translateMultiplicity(multStr);
302
303     inter = new ReferenceInterface(this,nameStr,AbstractInterface::Output, purpose,typeStr,widthStr, endianess, mult);
304     outputs.append(inter);
305   }
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));      
318     }
319     cout << "created a control output named " << qPrintable(inter->getName()) << endl;
320     outputs.append(inter);
321   }
322
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");
332     int endianess;
333     if ((endianStr == "none") || (endianStr == "little")) {
334       endianess = AbstractInterface::LittleEndian;
335     }
336     else if (endianStr == "big") {
337       endianess = AbstractInterface::BigEndian;
338     }
339     else {
340       throw (Exception(BLOCKFILE_CORRUPTED));
341     }
342     purposeStr = eltBidir.attribute("purpose","none");
343     purpose = ReferenceInterface::translatePurpose(purposeStr);
344     multStr = eltBidir.attribute("multiplicity","none");
345     mult = ReferenceInterface::translateMultiplicity(multStr);
346
347     inter = new ReferenceInterface(this,nameStr,AbstractInterface::InOut, purpose,typeStr,widthStr, endianess, mult);
348     bidirs.append(inter);
349   }
350 }
351
352 void ReferenceBlock::createInterfaceForParameters() throw(Exception){
353   ReferenceInterface* iface = NULL;
354   foreach(BlockParameter* param, params) {
355     
356     if (param->isWishboneParameter()) {
357       
358       BlockParameterWishbone* p = (BlockParameterWishbone*)param;      
359       cout << "creating interface for parameter wb " << qPrintable(p->getName()) << endl;
360       
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);        
364       }
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);                
368       }
369       else {
370         throw (Exception(BLOCKFILE_CORRUPTED));
371       }
372     }
373   }
374 }
375
376 void ReferenceBlock::parametersValidation(QList<AbstractBlock *> *checkedBlocks, QList<AbstractBlock *> *blocksToConfigure) {
377     return;
378 }
379
380 /* operator<<() :
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.
383
384  */
385 QDataStream& operator<<(QDataStream &out, const ReferenceBlock &b) {
386
387   out.setVersion(QDataStream::Qt_5_0);
388
389   QByteArray blockData;
390   QDataStream toWrite(&blockData, QIODevice::WriteOnly);
391
392   toWrite << b.name;
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();
399   BlockParameter* p;
400   for(int i=0;i<b.params.size();i++) {
401     p = b.params.at(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();
408     }
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();
415     }
416
417   }
418
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();
430     }
431   }
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();
442     }
443   }
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();
455     }
456   }
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();
467     }
468   }
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();
478   }
479
480   out << blockData;
481
482   return out;
483 }
484
485 QDataStream& operator>>(QDataStream &in, ReferenceBlock &b) {
486
487   quint32 blockSize;
488   ReferenceInterface* iface;
489   BlockParameter* p;
490   int val;
491   QString txt="";
492
493   in.setVersion(QDataStream::Qt_5_0);
494
495   in >> blockSize;
496
497   in >> b.name;
498   in >> b.xmlFile;
499   in >> b.descriptionBrief;
500   in >> b.descriptionDetail;
501   in >> b.categories;
502   in >> b.hashMd5;
503   b.params.clear();
504   int nb;
505   in >> nb;
506   cout << qPrintable(b.name) << " has " << nb << " parameters" << endl;
507   for(int i=0;i<nb;i++) {
508     QString contextStr = "";
509     QString nameStr= "";
510     QString typeStr = "";
511     QString valueStr = "";
512     in >> contextStr;
513     in >> nameStr;
514     in >> typeStr;
515     in >> valueStr;
516
517     if (contextStr == "user") {
518       p = new BlockParameterUser(&b,nameStr,typeStr,valueStr);
519     }
520     else if (contextStr == "generic") {
521       p = new BlockParameterGeneric(&b,nameStr,typeStr,valueStr);
522     }
523     else if (contextStr == "port") {
524       QString ifaceStr = "";
525       in >> ifaceStr;
526       p = new BlockParameterPort(&b,nameStr,valueStr,ifaceStr);
527     }
528     else if (contextStr == "wb") {
529       QString widthStr = "";
530       int wbAccess;
531       QString wbValue;
532       int wbDuration;
533       in >> widthStr;
534       in >> wbAccess;
535       in >> wbValue;
536       in >> wbDuration;
537       p = new BlockParameterWishbone(&b,nameStr,typeStr,widthStr,valueStr,wbAccess,wbValue,wbDuration);
538     }
539     b.params.append(p);
540   }
541
542   b.inputs.clear();
543   in >> nb;
544   for(int i=0;i<nb;i++) {
545     iface = new ReferenceInterface(&b);
546     in >> txt;
547     iface->setName(txt);
548     int type;
549     in >> type;
550     iface->setType(type);
551     in >> txt;
552     iface->setWidth(txt);
553     in >> val;
554     iface->setPurpose(val);    
555     in >> val;
556     iface->setDirection(val);    
557     in >> 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;
566         }      
567       }        
568     }    
569   }
570
571   b.outputs.clear();
572   in >> nb;
573   for(int i=0;i<nb;i++) {
574     iface = new ReferenceInterface(&b);
575     in >> txt;
576     iface->setName(txt);
577     int type;
578     in >> type;
579     iface->setType(type);
580     in >> txt;
581     iface->setWidth(txt);
582     in >> val;
583     iface->setPurpose(val);    
584     in >> val;
585     iface->setDirection(val);
586     in >> 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;
595         }      
596       }        
597     }    
598   }
599
600   b.bidirs.clear();
601   in >> nb;
602   for(int i=0;i<nb;i++) {
603     iface = new ReferenceInterface(&b);
604     in >> txt;
605     iface->setName(txt);
606     int type;
607     in >> type;
608     iface->setType(type);
609     in >> txt;
610     iface->setWidth(txt);
611     in >> val;
612     iface->setPurpose(val);
613     in >> val;
614     iface->setDirection(val);
615     in >> val;    
616     iface->setMultiplicity(val);
617     b.bidirs.append(iface);
618   }
619
620   return in;
621 }
622
623 void ReferenceBlock::checkInputPatternCompatibility()  throw(Exception){
624   throw(Exception(INVALID_REFBLOCK_USE));
625 }
626
627 void ReferenceBlock::computeOutputPattern(int nbExec)  throw(Exception) {
628   // does strictly nothing
629   throw(Exception(INVALID_REFBLOCK_USE));  
630 }
631
632 void ReferenceBlock::computeAdmittanceDelays() throw(Exception) {
633   // does strictly nothing
634   throw(Exception(INVALID_REFBLOCK_USE));
635 }