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 GroupInterface* clk = NULL;
14 GroupInterface* rst = NULL;
16 // force topGroup to false if this group has a parent
17 if (_parent != NULL) {
19 name = QString("sub_group")+"_"+QString::number(counter++);
20 // creating clk/rst interfaces
21 clk = new GroupInterface(this,"clk", AbstractInterface::Input, AbstractInterface::Clock);
22 rst = new GroupInterface(this,"reset", AbstractInterface::Input, AbstractInterface::Reset);
28 name = QString("top_group");
29 // creating external clk/rst interfaces
30 clk = new GroupInterface(this,"ext_clk", AbstractInterface::Input, AbstractInterface::Clock);
31 rst = new GroupInterface(this,"ext_reset", AbstractInterface::Input, AbstractInterface::Reset);
34 // creating clkrstgen block : done in Dispatcher since this has no access to library
37 if (_parent != NULL) {
38 // adding this to the child blocks of parent
39 _parent->addBlock(this);
40 // connect clk/rst ifaces to parent clk/rst or to clkrstgen if parent is top group
41 if (_parent->isTop()) {
50 GroupBlock::~GroupBlock() {
51 foreach(AbstractBlock* block, blocks) {
56 bool GroupBlock::isGroupBlock() {
60 bool GroupBlock::isTopGroupBlock() {
64 void GroupBlock::setParent(AbstractBlock *_parent) {
71 void GroupBlock::removeAllBlocks() {
72 foreach(AbstractBlock* block, blocks) {
73 if (block->isGroupBlock()) {
74 GroupBlock* group = AB_TO_GRP(block);
75 group->removeAllBlocks();
81 void GroupBlock::removeBlock(AbstractBlock* block) {
82 /* CAUTION: no check is done if the block has connected interface
83 or not. Thus, they must be deleted elsewhere.
85 blocks.removeAll(block);
89 AbstractBlock *GroupBlock::getFunctionalBlockByName(QString name) {
90 foreach(AbstractBlock* block, blocks) {
91 if (block->isFunctionalBlock()) {
92 if (block->getName() == name) return block;
98 void GroupBlock::parametersValidation(QList<AbstractBlock *> *checkedBlocks, QList<AbstractBlock *> *blocksToConfigure) {
101 checkedBlocks->append(this);
103 foreach(BlockParameter* param, params){
104 if(param->isUserParameter() && !param->isValueSet()){
105 if(!blocksToConfigure->contains(param->getOwner())){
106 blocksToConfigure->append(param->getOwner());
110 foreach(AbstractInterface *inter, outputs){
111 foreach(AbstractInterface *connectedInter, inter->getConnectedTo()){
112 if(!checkedBlocks->contains(connectedInter->getOwner())){
113 connectedInter->getOwner()->parametersValidation(checkedBlocks, blocksToConfigure);
120 void GroupBlock::addGenericParameter(QString name, QString type, QString value) {
121 BlockParameter* param = new BlockParameterGeneric(this, name, type, value);
122 params.append(param);
125 void GroupBlock::removeGenericParameter(QString name) {
126 BlockParameter* p = getParameterFromName(name);
127 if (p != NULL) params.removeAll(p);
130 void GroupBlock::createInputPattern() {
131 foreach(AbstractInterface* iface, getControlInputs()) {
132 ConnectedInterface* connIface = AI_TO_CON(iface);
133 QList<char>* pattern = new QList<char>(*(connIface->getConnectedFrom()->getOutputPattern()));
134 connIface->setOutputPattern(pattern);
138 void GroupBlock::computeAdmittanceDelays() throw(Exception) {
139 throw(Exception(INVALID_GROUPBLOCK_USE));
142 void GroupBlock::checkInputPatternCompatibility() throw(Exception){
143 throw(Exception(INVALID_GROUPBLOCK_USE));
147 void GroupBlock::computeOutputPattern(int nbExec) throw(Exception) {
149 static QString fctName = "GroupBlock::computeOutputPattern()";
151 cout << "call to " << qPrintable(fctName) << endl;
154 cout << "computing output pattern of group " << qPrintable(name) << endl;
156 bool canCompute = false;
157 // get the input pattern on each inputs
158 createInputPattern();
160 cout << "Input pattern OK" << endl;
161 // find blocks that are connected to that inputs and generators
162 QList<AbstractBlock*> fifo;
163 foreach(AbstractBlock* block, blocks) {
166 // if a block is a generator and has control outputs, add it
167 if (block->isGeneratorBlock()) {
168 if (block->getControlOutputs().size() > 0) addIt = true;
171 // if the block has all its connected inputs that are connected to an intput of the group, add it too
173 foreach(AbstractInterface* iface, block->getControlInputs()) {
174 //cout << qPrintable(iface->getName()) << " of " << qPrintable(iface->getOwner()->getName()) << " connected to " << endl;
175 ConnectedInterface* connFrom = ((ConnectedInterface*)iface)->getConnectedFrom();
176 //cout << qPrintable(connFrom->getName()) << " of " << qPrintable(connFrom->getOwner()->getName()) << endl;
178 if (connFrom == NULL) {
182 else if (connFrom->getOwner() != this) {
189 cout << "adding " << qPrintable(block->getName()) << " to initialize the FIFO" << endl;
190 block->setTraversalLevel(0); // level 0 = first blocks to be evaluated
195 while (!fifo.isEmpty()) {
196 AbstractBlock* block = fifo.takeFirst();
198 if (block->getPatternComputed()) continue; // block has already been processed
200 cout << "computing compat and output for " << qPrintable(block->getName()) << endl;
204 block->checkInputPatternCompatibility();
207 cout << qPrintable(block->getName()) << " is not compatible with its input pattern" << endl;
212 block->computeOutputPattern();
215 cout << "cannot finalize output pattern computation of " << qPrintable(block->getName()) << endl;
219 block->setPatternComputed(true);
220 /* add other blocks connected from block to the fifo but only if
221 all their connected inputs are connected to blocks that have
224 foreach(AbstractInterface* iface, block->getControlOutputs()) {
225 ConnectedInterface* conn = (ConnectedInterface*)iface;
226 foreach(ConnectedInterface* connTo, conn->getConnectedTo()) {
228 AbstractBlock* block1 = connTo->getOwner();
229 cout << "testing if " << qPrintable(block1->getName()) << " has all connected inputs connected to already processed blocks" << endl;
233 foreach(AbstractInterface* iface, block1->getControlInputs()) {
234 //cout << qPrintable(iface->getName()) << " of " << qPrintable(iface->getOwner()->getName()) << " connected to " << endl;
235 ConnectedInterface* connFrom = ((ConnectedInterface*)iface)->getConnectedFrom();
236 //cout << qPrintable(connFrom->getName()) << " of " << qPrintable(connFrom->getOwner()->getName()) << endl;
238 if ((connFrom != NULL) && (connFrom->getOwner()->getPatternComputed() == false)) {
243 if (connFrom->getOwner()->getTraversalLevel() > maxLevel) maxLevel = connFrom->getOwner()->getTraversalLevel();
248 cout << "adding " << qPrintable(block1->getName()) << " to the FIFO" << endl;
249 block1->setTraversalLevel(maxLevel+1); // level 0 = first blocks to be evaluated
257 foreach(AbstractInterface* iface, getControlOutputs()) {
258 ConnectedInterface* connIface = AI_TO_CON(iface);
259 QList<char>* pattern = new QList<char>(*(connIface->getConnectedFrom()->getOutputPattern()));
260 connIface->setOutputPattern(pattern);
262 setPatternComputed(true);
266 void GroupBlock::generateVHDL(const QString& path) throw(Exception) {
268 QString coreFile = "";
271 coreFile.append(normalizeName(name));
272 coreFile.append(".vhd");
274 QFile vhdlCore(coreFile);
276 if (!vhdlCore.open(QIODevice::WriteOnly)) {
277 throw(Exception(VHDLFILE_NOACCESS));
280 QTextStream outCore(&vhdlCore);
283 generateComments(outCore);
284 generateLibraries(outCore);
285 generateEntity(outCore);
286 generateArchitecture(outCore);
288 catch(Exception err) {
296 void GroupBlock::generateComments(QTextStream& out) throw(Exception) {
297 out << " -- VHDL generated automatically for " << name << " --" << endl << endl;
300 void GroupBlock::generateLibraries(QTextStream& out) throw(Exception) {
302 out << "library IEEE;" << endl;
303 out << "use IEEE.STD_LOGIC_1164.all;" << endl;
304 out << "use IEEE.numeric_std.all;" << endl;
308 void GroupBlock::generateEntity(QTextStream& out) throw(Exception) {
312 out << "entity " << name << " is " << endl;
314 QList<BlockParameter*> listGenerics = getGenericParameters();
315 QList<AbstractInterface*> listInputs = getInputs();
316 QList<AbstractInterface*> listOutputs = getOutputs();
317 QList<AbstractInterface*> listBidirs = getBidirs();
319 if (!listGenerics.isEmpty()) {
320 out << " generic (" << endl;
321 for(i=0;i<listGenerics.size()-1;i++) {
322 out << " " << listGenerics.at(i)->toVHDL(BlockParameter::Entity, 0) << endl;
324 out << " " << listGenerics.at(i)->toVHDL(BlockParameter::Entity,BlockParameter::NoComma) << endl;
325 out << " );" << endl;
328 out << " port (" << endl;
330 // Generation of the clk & rst signals
331 out << " -- clk/rst" << endl;
332 foreach(AbstractInterface* iface, listInputs) {
333 if(iface->getPurpose() == AbstractInterface::Clock || iface->getPurpose() == AbstractInterface::Reset) {
334 out << " " << iface->getName() << " : in std_logic;" << endl;
339 foreach(AbstractInterface* iface, getInterfaces()) {
340 if((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) count++;
342 // Generation of the data/control signals
347 foreach(AbstractInterface* iface, listInputs) {
348 if(iface->getPurpose() == AbstractInterface::Data) {
350 out << " -- input data ports" << endl;
354 if (count == 0) flag = AbstractInterface::NoComma;
355 out << " " << iface->toVHDL(AbstractInterface::Entity, flag) << endl;
359 foreach(AbstractInterface* iface, listInputs) {
360 if(iface->getPurpose() == AbstractInterface::Control) {
362 out << " -- input control ports" << endl;
366 if (count == 0) flag = AbstractInterface::NoComma;
367 out << " " << iface->toVHDL(AbstractInterface::Entity, flag) << endl;
371 foreach(AbstractInterface* iface, listOutputs) {
372 if(iface->getPurpose() == AbstractInterface::Data) {
374 out << " -- output data ports" << endl;
378 if (count == 0) flag = AbstractInterface::NoComma;
379 out << " " << iface->toVHDL(AbstractInterface::Entity, flag) << endl;
383 foreach(AbstractInterface* iface, listOutputs) {
384 if(iface->getPurpose() == AbstractInterface::Control) {
386 out << " -- output control ports" << endl;
390 if (count == 0) flag = AbstractInterface::NoComma;
391 out << " " << iface->toVHDL(AbstractInterface::Entity, flag) << endl;
395 foreach(AbstractInterface* iface, listBidirs) {
396 if(iface->getPurpose() == AbstractInterface::Data) {
398 out << " -- bidirs data ports" << endl;
402 if (count == 0) flag = AbstractInterface::NoComma;
403 out << " " << iface->toVHDL(AbstractInterface::Entity, flag) << endl;
406 out << " );" << endl << endl;
407 out << "end " << name << ";" << endl << endl;
411 void GroupBlock::generateArchitecture(QTextStream& out) throw(Exception) {