1 #include "GroupBlock.h"
2 #include "BlockParameterGeneric.h"
3 #include "AbstractInterface.h"
4 #include "ConnectedInterface.h"
5 #include "GroupInterface.h"
9 int GroupBlock::counter = 1;
11 GroupBlock::GroupBlock(GroupBlock *_parent) throw(Exception) : AbstractBlock() {
13 // force topGroup to false if this group has a parent
14 if (_parent != NULL) {
16 name = QString("sub_group")+"_"+QString::number(counter++);
20 name = QString("top_group");
21 // creating external clk/rst interfaces
22 GroupInterface* clk = new GroupInterface(this,"ext_clk", AbstractInterface::Input, AbstractInterface::Clock);
23 GroupInterface* rst = new GroupInterface(this,"ext_reset", AbstractInterface::Input, AbstractInterface::Reset);
26 // creating clkrstgen block : done in Dispatcher since this has no access to library
30 // adding this to the child blocks of parent
31 AB_TO_GRP(parent)->addBlock(this);
35 GroupBlock::~GroupBlock() {
36 foreach(AbstractBlock* block, blocks) {
41 bool GroupBlock::isGroupBlock() {
45 bool GroupBlock::isTopGroupBlock() {
49 void GroupBlock::setParent(AbstractBlock *_parent) {
56 void GroupBlock::removeAllBlocks() {
57 foreach(AbstractBlock* block, blocks) {
58 if (block->isGroupBlock()) {
59 GroupBlock* group = AB_TO_GRP(block);
60 group->removeAllBlocks();
66 void GroupBlock::removeBlock(AbstractBlock* block) {
67 /* CAUTION: no check is done if the block has connected interface
68 or not. Thus, they must be deleted elsewhere.
70 blocks.removeAll(block);
74 AbstractBlock *GroupBlock::getFunctionalBlockByName(QString name) {
75 foreach(AbstractBlock* block, blocks) {
76 if (block->isFunctionalBlock()) {
77 if (block->getName() == name) return block;
83 void GroupBlock::parametersValidation(QList<AbstractBlock *> *checkedBlocks, QList<AbstractBlock *> *blocksToConfigure) {
86 checkedBlocks->append(this);
88 foreach(BlockParameter* param, params){
89 if(param->isUserParameter() && !param->isValueSet()){
90 if(!blocksToConfigure->contains(param->getOwner())){
91 blocksToConfigure->append(param->getOwner());
95 foreach(AbstractInterface *inter, outputs){
96 foreach(AbstractInterface *connectedInter, inter->getConnectedTo()){
97 if(!checkedBlocks->contains(connectedInter->getOwner())){
98 connectedInter->getOwner()->parametersValidation(checkedBlocks, blocksToConfigure);
105 void GroupBlock::addGenericParameter(QString name, QString type, QString value) {
106 BlockParameter* param = new BlockParameterGeneric(this, name, type, value);
107 params.append(param);
110 void GroupBlock::removeGenericParameter(QString name) {
111 BlockParameter* p = getParameterFromName(name);
112 if (p != NULL) params.removeAll(p);
115 void GroupBlock::createInputPattern() {
116 foreach(AbstractInterface* iface, getControlInputs()) {
117 ConnectedInterface* connIface = AI_TO_CON(iface);
118 QList<char>* pattern = new QList<char>(*(connIface->getConnectedFrom()->getOutputPattern()));
119 connIface->setOutputPattern(pattern);
123 void GroupBlock::computeAdmittanceDelays() throw(Exception) {
124 throw(Exception(INVALID_GROUPBLOCK_USE));
127 void GroupBlock::checkInputPatternCompatibility() throw(Exception){
128 throw(Exception(INVALID_GROUPBLOCK_USE));
132 void GroupBlock::computeOutputPattern(int nbExec) throw(Exception) {
134 static QString fctName = "GroupBlock::computeOutputPattern()";
136 cout << "call to " << qPrintable(fctName) << endl;
139 cout << "computing output pattern of group " << qPrintable(name) << endl;
141 bool canCompute = false;
142 // get the input pattern on each inputs
143 createInputPattern();
145 cout << "Input pattern OK" << endl;
146 // find blocks that are connected to that inputs and generators
147 QList<AbstractBlock*> fifo;
148 foreach(AbstractBlock* block, blocks) {
151 // if a block is a generator and has control outputs, add it
152 if (block->isGeneratorBlock()) {
153 if (block->getControlOutputs().size() > 0) addIt = true;
156 // if the block has all its connected inputs that are connected to an intput of the group, add it too
158 foreach(AbstractInterface* iface, block->getControlInputs()) {
159 //cout << qPrintable(iface->getName()) << " of " << qPrintable(iface->getOwner()->getName()) << " connected to " << endl;
160 ConnectedInterface* connFrom = ((ConnectedInterface*)iface)->getConnectedFrom();
161 //cout << qPrintable(connFrom->getName()) << " of " << qPrintable(connFrom->getOwner()->getName()) << endl;
163 if (connFrom == NULL) {
167 else if (connFrom->getOwner() != this) {
174 cout << "adding " << qPrintable(block->getName()) << " to initialize the FIFO" << endl;
175 block->setTraversalLevel(0); // level 0 = first blocks to be evaluated
180 while (!fifo.isEmpty()) {
181 AbstractBlock* block = fifo.takeFirst();
183 if (block->getPatternComputed()) continue; // block has already been processed
185 cout << "computing compat and output for " << qPrintable(block->getName()) << endl;
189 block->checkInputPatternCompatibility();
192 cout << qPrintable(block->getName()) << " is not compatible with its input pattern" << endl;
197 block->computeOutputPattern();
200 cout << "cannot finalize output pattern computation of " << qPrintable(block->getName()) << endl;
204 block->setPatternComputed(true);
205 /* add other blocks connected from block to the fifo but only if
206 all their connected inputs are connected to blocks that have
209 foreach(AbstractInterface* iface, block->getControlOutputs()) {
210 ConnectedInterface* conn = (ConnectedInterface*)iface;
211 foreach(ConnectedInterface* connTo, conn->getConnectedTo()) {
213 AbstractBlock* block1 = connTo->getOwner();
214 cout << "testing if " << qPrintable(block1->getName()) << " has all connected inputs connected to already processed blocks" << endl;
218 foreach(AbstractInterface* iface, block1->getControlInputs()) {
219 //cout << qPrintable(iface->getName()) << " of " << qPrintable(iface->getOwner()->getName()) << " connected to " << endl;
220 ConnectedInterface* connFrom = ((ConnectedInterface*)iface)->getConnectedFrom();
221 //cout << qPrintable(connFrom->getName()) << " of " << qPrintable(connFrom->getOwner()->getName()) << endl;
223 if ((connFrom != NULL) && (connFrom->getOwner()->getPatternComputed() == false)) {
228 if (connFrom->getOwner()->getTraversalLevel() > maxLevel) maxLevel = connFrom->getOwner()->getTraversalLevel();
233 cout << "adding " << qPrintable(block1->getName()) << " to the FIFO" << endl;
234 block1->setTraversalLevel(maxLevel+1); // level 0 = first blocks to be evaluated
242 foreach(AbstractInterface* iface, getControlOutputs()) {
243 ConnectedInterface* connIface = AI_TO_CON(iface);
244 QList<char>* pattern = new QList<char>(*(connIface->getConnectedFrom()->getOutputPattern()));
245 connIface->setOutputPattern(pattern);
247 setPatternComputed(true);
251 void GroupBlock::generateVHDL(const QString& path) throw(Exception) {
253 QString coreFile = "";
256 coreFile.append(normalizeName(name));
257 coreFile.append(".vhd");
259 QFile vhdlCore(coreFile);
261 if (!vhdlCore.open(QIODevice::WriteOnly)) {
262 throw(Exception(VHDLFILE_NOACCESS));
265 QTextStream outCore(&vhdlCore);
268 generateComments(outCore);
269 generateLibraries(outCore);
270 generateEntity(outCore);
271 generateArchitecture(outCore);
273 catch(Exception err) {
281 void GroupBlock::generateComments(QTextStream& out) throw(Exception) {
282 out << " -- VHDL generated automatically for " << name << " --" << endl << endl;
285 void GroupBlock::generateLibraries(QTextStream& out) throw(Exception) {
287 out << "library IEEE;" << endl;
288 out << "use IEEE.STD_LOGIC_1164.all;" << endl;
289 out << "use IEEE.numeric_std.all;" << endl;
293 void GroupBlock::generateEntity(QTextStream& out) throw(Exception) {
297 out << "entity " << name << " is " << endl;
299 QList<BlockParameter*> listGenerics = getGenericParameters();
300 QList<AbstractInterface*> listInputs = getInputs();
301 QList<AbstractInterface*> listOutputs = getOutputs();
302 QList<AbstractInterface*> listBidirs = getBidirs();
304 if (!listGenerics.isEmpty()) {
305 out << " generic (" << endl;
306 for(i=0;i<listGenerics.size()-1;i++) {
307 out << " " << listGenerics.at(i)->toVHDL(BlockParameter::Entity, 0) << endl;
309 out << " " << listGenerics.at(i)->toVHDL(BlockParameter::Entity,BlockParameter::NoComma) << endl;
310 out << " );" << endl;
313 out << " port (" << endl;
315 // Generation of the clk & rst signals
316 out << " -- clk/rst" << endl;
317 foreach(AbstractInterface* iface, listInputs) {
318 if(iface->getPurpose() == AbstractInterface::Clock || iface->getPurpose() == AbstractInterface::Reset) {
319 out << " " << iface->getName() << " : in std_logic;" << endl;
324 foreach(AbstractInterface* iface, getInterfaces()) {
325 if((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) count++;
327 // Generation of the data/control signals
332 foreach(AbstractInterface* iface, listInputs) {
333 if(iface->getPurpose() == AbstractInterface::Data) {
335 out << " -- input data ports" << endl;
339 if (count == 0) flag = AbstractInterface::NoComma;
340 out << " " << iface->toVHDL(AbstractInterface::Entity, flag) << endl;
344 foreach(AbstractInterface* iface, listInputs) {
345 if(iface->getPurpose() == AbstractInterface::Control) {
347 out << " -- input control ports" << endl;
351 if (count == 0) flag = AbstractInterface::NoComma;
352 out << " " << iface->toVHDL(AbstractInterface::Entity, flag) << endl;
356 foreach(AbstractInterface* iface, listOutputs) {
357 if(iface->getPurpose() == AbstractInterface::Data) {
359 out << " -- output data ports" << endl;
363 if (count == 0) flag = AbstractInterface::NoComma;
364 out << " " << iface->toVHDL(AbstractInterface::Entity, flag) << endl;
368 foreach(AbstractInterface* iface, listOutputs) {
369 if(iface->getPurpose() == AbstractInterface::Control) {
371 out << " -- output control ports" << endl;
375 if (count == 0) flag = AbstractInterface::NoComma;
376 out << " " << iface->toVHDL(AbstractInterface::Entity, flag) << endl;
380 foreach(AbstractInterface* iface, listBidirs) {
381 if(iface->getPurpose() == AbstractInterface::Data) {
383 out << " -- bidirs data ports" << endl;
387 if (count == 0) flag = AbstractInterface::NoComma;
388 out << " " << iface->toVHDL(AbstractInterface::Entity, flag) << endl;
391 out << " );" << endl << endl;
392 out << "end " << name << ";" << endl << endl;
396 void GroupBlock::generateArchitecture(QTextStream& out) throw(Exception) {