Otawa  0.10
ExeGraph.h
Go to the documentation of this file.
1 /*
2  * $Id$
3  * exegraph module interface
4  *
5  * This file is part of OTAWA
6  * Copyright (c) 2007, IRIT UPS.
7  *
8  * OTAWA is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * OTAWA is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with OTAWA; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 #ifndef __EXEGRAPH_H__
23 #define __EXEGRAPH_H__
24 
25 #include <elm/assert.h>
26 #include <elm/genstruct/Vector.h>
27 #include <otawa/graph/GenGraph.h>
28 #include "Microprocessor.h"
29 #include <otawa/instruction.h>
30 #include <elm/genstruct/DLList.h>
31 #include <otawa/otawa.h>
32 #include <otawa/hard/Platform.h>
34 #include <otawa/cfg.h>
35 
36 namespace otawa {
37 
38 extern Identifier<bool> START;
39 
40 template <class N> class ExeGraph;
41 
42 
43 /* --------------------------
44  * class ExeInst
45  * --------------------------
46  */
47 
48 template <class N>
49 class ExeInst {
50  private:
53  int _index;
56 
57  public:
58  inline ExeInst(Inst * inst, BasicBlock *bb, typename ExeGraph<N>::code_part_t part, int index)
59  : _inst(inst), _bb(bb), _index(index), _part(part) {}
60  inline Inst * inst()
61  {return _inst;}
63  {return _part;}
64  inline int index()
65  {return _index;}
66  inline void setIndex(int index)
67  {_index=index;}
68  inline void addNode(N * node)
69  {_nodes.addLast(node);}
70  inline void deleteNodes()
71  {_nodes.clear();}
72  inline N * firstNode()
73  {return _nodes.first();}
74  inline N * lastNode()
75  {return _nodes.last();}
76  inline BasicBlock * basicBlock()
77  {return _bb;}
78  class NodeIterator: public elm::genstruct::DLList<N *>::Iterator {
79  public:
80  inline NodeIterator(const ExeInst *inst)
81  : elm::genstruct::DLList<N *>::Iterator(inst->_nodes) {}
82  };
83  };
84 
85 /* --------------------------
86  * class ExeSequence
87  * --------------------------
88  */
89 
90  template <class N>
91  class ExeSequence : public elm::genstruct::DLList<ExeInst<N> *> {
92  public:
93  class InstIterator: public elm::genstruct::DLList<ExeInst<N> *>::Iterator {
94  public:
95  inline InstIterator(const ExeSequence *seq)
96  : elm::genstruct::DLList<ExeInst<N> *>::Iterator(*seq) {}
97  };
98  inline int length()
100  };
101 
102 
103 /* --------------------------
104  * class ExeGraph
105  * --------------------------
106  */
107 
108  template <class N>
109  class ExeGraph {
110  public:
111  typedef enum code_part_t {
113  PROLOGUE = 1,
114  BODY = 2,
115  EPILOGUE = 3,
116  CODE_PARTS_NUMBER // should be the last value
117  } code_part_t;
118  typedef enum {MIN=0, MAX=1, BOUNDS=2} time_bound_t;
119  typedef enum {READY=0, START=1, FINISH=2, STEPS=3} time_step_t;
120 
121  class ExeEdge: public GenGraph<N, ExeEdge>::GenEdge {
122  public:
123  typedef enum edge_type_t {
124  SOLID = 1,
125  SLASHED = 2,
126  NONE = 3
127  } edge_type_t_t;
128  private:
131  public:
133  : GenGraph<N, ExeEdge>::GenEdge(source,target), _type(type) {
134  StringBuffer _buffer;
137  _name = _buffer.toString();
138  }
139  inline edge_type_t type(void)
140  {return _type;}
141  inline elm::String name()
142  {return _name;}
143  };
144 
145  class ExeNode: public GenGraph<N, ExeEdge >::GenNode {
146  private:
153  protected:
155  public:
157  : GenGraph<N,ExeEdge>::GenNode((otawa::graph::Graph *)graph->graph()),
158  _inst(inst), _pipeline_stage(stage), _needs_operands(false),
159  _produces_operands(false)
160  {
161  _latency[MIN] = stage->minLatency();
162  _latency[MAX] = stage->maxLatency();
163  StringBuffer _buffer;
164  _buffer << stage->shortName() << "(I" << inst->index() << ")";
165  _name = _buffer.toString();
166  }
168  {return _pipeline_stage;}
169  inline ExeInst<N> * inst(void)
170  {return _inst;}
171  inline int latency()
172  {return _latency[MIN];}
173  inline int latency(time_bound_t bound)
174  {return _latency[bound];}
175  inline void setLatency(time_bound_t bound, int latency)
176  {_latency[bound] = latency;}
177  inline bool needsOperands(void)
178  {return _needs_operands;}
179  inline void setNeedsOperands(bool val)
180  {_needs_operands = val;}
181  inline bool producesOperands(void)
182  {return _produces_operands;}
183  inline void setProducesOperands(bool val)
184  {_produces_operands = val;}
185  inline void addContender(N *cont)
186  {_contenders.add(cont);}
188  {return &_contenders;}
189  inline elm::String name()
190  {return _name;}
191  class ContenderIterator: public elm::genstruct::Vector<N *>::Iterator {
192  public:
194  : elm::genstruct::Vector<N *>::Iterator(node->_contenders) {}
195  };
196  };
197 
198  protected:
205  typedef struct rename_table_t {
208  } rename_table_t;
210  public:
211  inline ExeGraph() {
213  _buffer[BEFORE_PROLOGUE] << "BEFORE_PROLOGUE";
214  _buffer[PROLOGUE] << "PROLOGUE";
215  _buffer[BODY] << "BODY";
216  _buffer[EPILOGUE] << "EPILOGUE";
217  for (int i=0 ; i<CODE_PARTS_NUMBER ; i++)
218  _part_name[i] = _buffer[i].toString();
219  _entry_node = NULL;
220  for (int i=0 ; i<CODE_PARTS_NUMBER ; i++) {
221  _first_node[i] = NULL;
222  _last_node[i] = NULL;
223  }
224  }
226  {return &_graph;}
227  inline void setEntryNode(N *node)
228  {_entry_node = node;}
229  inline N * entryNode(void)
230  {return _entry_node;}
231  virtual void build(WorkSpace *fw, Microprocessor<N> * microprocessor, ExeSequence<N> *sequence);
233  {return _part_name[part].toString();}
234  inline void setFirstNode(code_part_t part, N *node)
235  {_first_node[part] = node;}
236  inline void setLastNode(code_part_t part, N *node)
237  {_last_node[part] = node;}
238  inline N * firstNode(code_part_t part)
239  {return _first_node[part];}
240  inline N * lastNode(code_part_t part)
241  {return _last_node[part];}
242 
244  public:
245  inline PipelineIterator(const Microprocessor<N> * processor)
246  : Microprocessor<N>::PipelineIterator(processor) {}
247  };
249  public elm::genstruct::Vector<typename PipelineStage<N>::FunctionalUnit *>::Iterator {
250  public:
252  : elm::genstruct::Vector<typename PipelineStage<N>::FunctionalUnit *>::Iterator(stage->getFUs()) {}
253  };
254  class FunctionalUnitPipelineIterator : public PipelineStage<N>::FunctionalUnit::PipelineIterator {
255  public:
257  : PipelineStage<N>::FunctionalUnit::PipelineIterator(fu) {}
258  };
260  public:
261  inline InstIterator(const ExeSequence<N> *sequence)
262  : ExeSequence<N>::InstIterator(sequence) {}
263  };
264  class InstNodeIterator : public ExeInst<N>::NodeIterator {
265  public:
267  : ExeInst<N>::NodeIterator(inst) {}
268  };
269  class StageNodeIterator : public PipelineStage<N>::ExeNodeIterator {
270  public:
271  inline StageNodeIterator(const PipelineStage<N> *stage)
272  : PipelineStage<N>::ExeNodeIterator(stage) {}
273  };
274 
275  class Predecessor: public PreIterator<Predecessor, N *> {
276  public:
277  inline Predecessor(const N* node): iter(node) { }
278  inline bool ended(void) const { return iter.ended(); }
279  inline N *item(void) const { return iter->source(); }
280  inline void next(void) { iter.next(); }
281  inline ExeEdge *edge(void) const { return iter; }
282  private:
284  };
285 
286  class Successor: public PreIterator<Successor, N *> {
287  public:
288  inline Successor(const N* node): iter(node) {}
289  inline bool ended(void) const { return iter.ended(); }
290  inline N *item(void) const { return iter->target(); }
291  inline void next(void) { iter.next(); }
292  inline ExeEdge *edge(void) const { return iter; }
293  private:
295  };
296 
299  public:
300  inline PreorderIterator(ExeGraph<N> * graph, N *node)
301  : graph::PreorderIterator<Graph>(*graph->graph(), node) {}
302  };
303  };
304 
305 
306 
307  template <class N>
308  void ExeGraph<N>::build(WorkSpace *fw, Microprocessor<N> * microprocessor, ExeSequence<N> *sequence) {
309  _sequence = sequence;
310  _microprocessor = microprocessor;
311  // Init rename tables
312  otawa::hard::Platform *pf = fw->platform();
313  AllocatedTable<rename_table_t> rename_tables(pf->banks().count());
314  int reg_bank_count = pf->banks().count();
315  for(int i = 0; i <reg_bank_count ; i++) {
316  rename_tables[i].reg_bank = (otawa::hard::RegBank *) pf->banks()[i];
317  rename_tables[i].table =
318  new AllocatedTable<N *>(rename_tables[i].reg_bank->count());
319  for (int j=0 ; j<rename_tables[i].reg_bank->count() ; j++)
320  rename_tables[i].table->set(j,NULL);
321  }
322 
323  // clear node queues for instructions and for pipeline stages
324  for (PipelineIterator stage(microprocessor) ; stage ; stage++) {
325  stage->deleteNodes();
326  if (stage->usesFunctionalUnits()) {
327  for(FunctionalUnitIterator fu(stage); fu; fu++)
328  for (FunctionalUnitPipelineIterator fu_stage(fu); fu_stage; fu_stage++)
329  fu_stage->deleteNodes();
330  }
331  }
332  int nb_inst = 0;
333  for (InstIterator inst(sequence) ; inst ; inst++) {
334  inst->deleteNodes();
335  nb_inst++;
336  }
337 
338  // build nodes
339  // consider every pipeline stage
340  for (PipelineIterator stage(microprocessor) ; stage ; stage++) {
341  code_part_t current_code_part = BEFORE_PROLOGUE;
342 
343  // consider every instruction
344  for (InstIterator inst(sequence) ; inst ; inst++) {
345  // the instruction before the prologue (if any) is unknown
346  // => it deserves a specific treatment
347  if (inst->codePart() == BEFORE_PROLOGUE) {
348  N * node = new N(this, stage, inst);
349  node->setLatency(MIN,0);
350  node->setLatency(MAX,0);
351  inst->addNode(node);
352  stage->addNode(node);
353  if (microprocessor->operandProducingStage() == stage) {
354  for (int b=0 ; b<reg_bank_count ; b++) {
355  for (int r=0 ; r < rename_tables[b].reg_bank ->count() ; r++) {
356  rename_tables[b].table->set(r,node);
357  }
358  }
359  }
360  setFirstNode(BEFORE_PROLOGUE,inst->firstNode());
361  setLastNode(BEFORE_PROLOGUE,inst->lastNode());
362  }
363  else {
364  if (!stage->usesFunctionalUnits()) {
365  N * node = new N(this, stage, inst);
366  inst->addNode(node);
367  stage->addNode(node);
368  if (microprocessor->operandReadingStage() == stage)
369  node->setNeedsOperands(true);
370  if (microprocessor->operandProducingStage() == stage)
371  node->setProducesOperands(true);
372  }
373  else {
374  typename PipelineStage<N>::FunctionalUnit *fu = stage->findFU(inst->inst()->kind());
375  bool first_fu_node = true;
376  N * node;
377  for(FunctionalUnitPipelineIterator fu_stage(fu); fu_stage; fu_stage++) {
378  node = new N(this, fu_stage, inst);
379  inst->addNode(node);
380  fu_stage->addNode(node);
381  if (first_fu_node) {
382  stage->addNode(node);
383  if (microprocessor->operandReadingStage() == stage)
384  node->setNeedsOperands(true);
385  first_fu_node = false;
386  }
387  }
388  if (microprocessor->operandProducingStage() == stage)
389  node->setProducesOperands(true);
390  }
391  if (inst->codePart() != current_code_part) {
392  current_code_part = inst->codePart();
393  setFirstNode(current_code_part,inst->firstNode());
394  }
395  setLastNode(current_code_part,inst->lastNode());
396  }
397  }
398  }
399 
400  setEntryNode(sequence->first()->firstNode());
401  bool trace = false;
402 
403  // build edges for pipeline order and data dependencies
404  for (InstIterator inst(sequence) ; inst ; inst++) {
405  N * previous = NULL;
406  for (InstNodeIterator node (inst) ; node ; node++) {
407  if (previous != NULL) {
408  // edge between consecutive pipeline stages
409  new ExeEdge(previous, node, ExeEdge::SOLID);
410  if (trace)
411  elm::cout << "SOLID edge between " << previous->name() << " and " << node->name() << " (pipeline order)\n";
412  }
413  previous = node;
414  if (node->needsOperands()) {
415  // check for data dependencies
416  const elm::genstruct::Table<hard::Register *>& reads = node->inst()->inst()->readRegs();
417  for(int i = 0; i < reads.count(); i++) {
418  for (int b=0 ; b<reg_bank_count ; b++) {
419  if (rename_tables[b].reg_bank == reads[i]->bank()) {
420  N *producing_node = rename_tables[b].table->get(reads[i]->number());
421  if (producing_node != NULL) {
422  // check whether there is already an edge between the two nodes
423  bool exists = false;
424  for (Predecessor pred(node) ; pred ; pred++) {
425  if (pred == producing_node) {
426  exists = true;
427  break;
428  }
429  }
430  if (!exists) {
431  // add an edge for data dependency
432  if (trace)
433  elm::cout << "SOLID edge between " << producing_node->name() << " and " << node->name() << " (data dependency)\n";
434  new ExeEdge(producing_node, node, ExeEdge::SOLID);
435  }
436  }
437  }
438  }
439  }
440  }
441  // note that this instruction produces some registers
442  if (node->producesOperands()) {
444  node->inst()->inst()->writtenRegs();
445  for(int i = 0; i < writes.count(); i++) {
446  for (int b=0 ; b<reg_bank_count ; b++) {
447  if (rename_tables[b].reg_bank == writes[i]->bank()) {
448  rename_tables[b].table->set(writes[i]->number(),node);
449  }
450  }
451  }
452  }
453  }
454  }
455 
456  // build edges for program order
457  bool in_order = false;
458  for (PipelineIterator stage(microprocessor) ; stage ; stage++) {
459  if (stage->orderPolicy() == PipelineStage<N>::IN_ORDER) {
460  if (microprocessor->operandReadingStage() == stage)
461  in_order = true;
462  if (stage->width() == 1) {
463  // scalar stage
464  N * previous = NULL;
465  for (StageNodeIterator node(stage) ; node ; node++) {
466  if (previous != NULL) {
467  // scalar stage => draw a solid edge
468  new ExeEdge(previous, node, ExeEdge::SOLID);
469  if (trace)
470  elm::cout << "SOLID edge between " << previous->name() << " and " << node->name() << " (program order)\n";
471  }
472  previous = node;
473  }
474  } // end scalar
475  else { //superscalar
476  if (stage->category() == PipelineStage<N>::FETCH) {
477  N * previous = NULL;
478  for (StageNodeIterator node(stage) ; node ; node++) {
479  // superscalar => draw a slashed edge between adjacent instructions
480  if(previous) {
481  if (previous->inst()->codePart() == BEFORE_PROLOGUE) {
482  new ExeEdge(previous, node, ExeEdge::SOLID);
483  }
484  else {
485  if (node->inst()->inst()->address().offset() != previous->inst()->inst()->address().offset() + 4)
486  new ExeEdge(previous, node, ExeEdge::SOLID);
487  else {
488  if (node->inst()->inst()->address().offset() % (stage->width()*4) == 0)
489  new ExeEdge(previous, node, ExeEdge::SOLID);
490  else
491  new ExeEdge(previous, node, ExeEdge::SLASHED);
492  }
493  }
494  }
495  previous = node;
496  }
497  } // end FETCH
498  else { // superscalar, other than FETCH
499  if (!stage->usesFunctionalUnits()) {
500  elm::genstruct::DLList<N *> previous_nodes;
501  N * previous = NULL;
502  for (StageNodeIterator node(stage) ; node ; node++) {
503  // superscalar => draw a slashed edge between adjacent instructions
504  if(previous){
505  new ExeEdge(previous, node, ExeEdge::SLASHED);
506  if (trace)
507  elm::cout << "SLASHED edge between " << previous->name() << " and " << node->name() << " (stage width)\n";
508  }
509  // draw a solid edge to model the stage width
510  if (previous_nodes.count() == stage->width()) {
511  new ExeEdge(previous_nodes.first(), node, ExeEdge::SOLID);
512  if (trace)
513  elm::cout << "SOLID edge between " << previous_nodes.first()->name() << " and " << node->name() << " (stage width)\n";
514  previous_nodes.removeFirst();
515  }
516  previous_nodes.addLast(node);
517  previous = node;
518  }
519  } // no FUs
520  else { //uses FUs
521  for(FunctionalUnitIterator fu(stage); fu; fu++) {
522  PipelineStage<N> *fu_stage = fu->firstStage();
523  elm::genstruct::DLList<N *> previous_nodes;
524  N * previous = NULL;
525  for (StageNodeIterator node(fu_stage) ; node ; node++) {
526  if(previous) {
527  new ExeEdge(previous, node, ExeEdge::SLASHED);
528  if (trace)
529  elm::cout << "SLASHED edge between " << previous->name() << " and " << node->name() << " (stage width)\n";
530  }
531  // draw a solid edge to model the stage width
532  if (previous_nodes.count() == fu_stage->width()) {
533  new ExeEdge(previous_nodes.first(), node, ExeEdge::SOLID);
534  if (trace)
535  elm::cout << "SOLID edge between " << previous_nodes.first()->name() << " and " << node->name() << " (stage width)\n";
536  previous_nodes.removeFirst();
537  }
538  previous_nodes.addLast(node);
539  previous = node;
540  }
541  }
542  }
543  }//end superscalar, other than FETCH
544  } // end superscalar
545  } // end IN ORDER
546  else { //stage OOO
547  if (stage->usesFunctionalUnits()) {
548  for(FunctionalUnitIterator fu(stage); fu; fu++) {
549  PipelineStage<N> *fu_stage = fu->firstStage();
550  N * previous_load = NULL;
551  N * previous_store = NULL;
552  for (StageNodeIterator node(fu_stage) ; node ; node++) {
553  if (node->inst()->inst()->isMem()) {
554  if (node->inst()->inst()->isLoad()) {
555  if (previous_store) {// memory access are executed in order
556  new ExeEdge(previous_store, node, ExeEdge::SLASHED);
557  if (trace)
558  elm::cout << "SLASHED edge between " << previous_store->name() << " and " << node->name() << " (load after store)\n";
559  }
560  previous_load = node;
561  }
562  if (node->inst()->inst()->isStore()) {
563  if (previous_store) {// memory access are executed in order
564  new ExeEdge(previous_store, node, ExeEdge::SLASHED);
565  if (trace)
566  elm::cout << "SLASHED edge between " << previous_store->name() << " and " << node->name() << " (store after store)\n";
567  }
568  if (previous_load) {// memory access are executed in order
569  new ExeEdge(previous_load, node, ExeEdge::SLASHED);
570  if (trace)
571  elm::cout << "SLASHED edge between " << previous_load->name() << " and " << node->name() << " (store after load)\n";
572  }
573  previous_store = node;
574  }
575  }
576  }
577  }
578  }
579  }
580  if (in_order) {
581  N * previous = NULL;
582  for (InstIterator inst(sequence) ; inst ; inst++) {
583  for (InstNodeIterator node (inst) ; node ; node++) {
584  if (node->needsOperands()) {
585  if (previous) {
586  new ExeEdge(previous, node, ExeEdge::SLASHED);
587  if (trace)
588  elm::cout << "SLASHED edge between " << previous->name() << " and " << node->name() << " (program order)\n";
589  }
590  previous = node;
591  }
592  }
593  }
594  }
595 
596  // build edges for queues with limited capacity
597  if (stage->sourceQueue() != NULL) {
598  Queue<N> *queue = stage->sourceQueue();
599  PipelineStage<N> * prod_stage;
600  for (PipelineIterator st(microprocessor) ; st ; st++) {
601  if (st->destinationQueue() == queue) {
602  prod_stage = st;
603  break;
604  }
605  }
606  for (StageNodeIterator node(stage) ; node ; node++) {
607  // compute the index of the instruction that cannot be admitted
608  // into the queue until the current instruction leaves it
609  int index = node->inst()->index() + stage->sourceQueue()->size();
610  for (StageNodeIterator waiting_node(prod_stage) ; waiting_node ; waiting_node++) {
611  if (waiting_node->inst()->index() == index) {
612  new ExeEdge(node, waiting_node, ExeEdge::SLASHED);
613  break;
614  }
615  }
616  }
617  }
618  }
619 
620  // search for contending nodes (i.e. pairs of nodes that use the same pipeline stage)
621  for (PipelineIterator stage(microprocessor) ; stage ; stage++) {
622  if (stage->orderPolicy() == PipelineStage<N>::OUT_OF_ORDER) {
623  if (!stage->usesFunctionalUnits()) {
624  for (StageNodeIterator node1(stage) ; node1 ; node1++) {
625  for (StageNodeIterator node2(stage) ; node2 ; node2++) {
626  if ((N*)node1 != (N*)node2)
627  node1->addContender(node2);
628  }
629  }
630  }
631  else {
632  for(FunctionalUnitIterator fu(stage); fu; fu++) {
633  PipelineStage<N> *fu_stage = fu->firstStage();
634  for (StageNodeIterator node1(fu_stage) ; node1 ; node1++) {
635  for (StageNodeIterator node2(fu_stage) ; node2 ; node2++) {
636  if ((N*)node1 != (N*)node2)
637  node1->addContender(node2);
638  }
639  }
640  }
641  }
642  }
643  }
644 
645  // Free rename tables
646  for(int i = 0; i <reg_bank_count ; i++)
647  delete rename_tables[i].table;
648  }
649 
650 
651 }
652 
653 #endif // EXE_GRAPH
void deleteNodes()
Clears the list of nodes related to this instruction.
Definition: ExeGraph.h:70
Definition: ExeGraph.h:248
N * _entry_node
Definition: ExeGraph.h:199
struct otawa::sem::inst inst
Definition: GenGraph.h:38
bool ended(void) const
Definition: ExeGraph.h:289
ExeNodeIterator(const PipelineStage< N > *stage)
Definition: Microprocessor.h:235
dtd::RefAttr< BasicBlock * > source("source", dtd::STRICT|dtd::REQUIRED)
ExeEdge * edge(void) const
Definition: ExeGraph.h:281
N * source(void) const
Definition: GenGraph.h:67
This class represents a bank of registers.
Definition: Register.h:68
void next(void)
Definition: ExeGraph.h:280
Definition: ExeGraph.h:243
Definition: ExeGraph.h:269
void setLatency(time_bound_t bound, int latency)
Definition: ExeGraph.h:175
Predecessor(const N *node)
Constructor.
Definition: ExeGraph.h:277
GenEdge(GenNode *source, GenNode *target)
Definition: GenGraph.h:66
struct otawa::ExeGraph::rename_table_t rename_table_t
PreorderIterator(ExeGraph< N > *graph, N *node)
Constructor.
Definition: ExeGraph.h:300
GenGraph< N, ExeEdge >::OutIterator iter
Definition: ExeGraph.h:294
ExeGraph()
Constructor.
Definition: ExeGraph.h:211
N * entryNode(void)
Definition: ExeGraph.h:229
elm::String _name
Definition: ExeGraph.h:152
bool _produces_operands
Definition: ExeGraph.h:151
Definition: features.h:47
edge_type_t _type
Definition: ExeGraph.h:129
Inst * _inst
Definition: ExeGraph.h:51
Iterator on the list of instructions of the sequence.
Definition: ExeGraph.h:93
GenGraph< N, ExeEdge > _graph
Definition: ExeGraph.h:209
FunctionalUnitPipelineIterator(const typename PipelineStage< N >::FunctionalUnit *fu)
Constructor.
Definition: ExeGraph.h:256
Definition: ExeGraph.h:121
Definition: ExeGraph.h:124
void setEntryNode(N *node)
Sets the entry node (used for topological graph exploration).
Definition: ExeGraph.h:227
int minLatency(void)
Definition: Microprocessor.h:200
GenGraph< N, typename ExeGraph< N >::ExeEdge > Graph
Definition: ExeGraph.h:297
Microprocessor< N > * _microprocessor
Definition: ExeGraph.h:203
N * _first_node[CODE_PARTS_NUMBER]
Definition: ExeGraph.h:200
hard::RegBank * reg_bank
Definition: ExeGraph.h:206
PipelineStage< N > * operandReadingStage(void)
Definition: Microprocessor.h:312
Definition: ExeGraph.h:205
Definition: ExeGraph.h:119
void trace(CString file, int line, CString fun)
void addNode(N *node)
Adds a node to the list of nodes related to this instruction.
Definition: ExeGraph.h:68
PipelineIterator(const Microprocessor< N > *processor)
Constructor.
Definition: ExeGraph.h:245
ContenderIterator(const ExeGraph< N >::ExeNode *node)
Constructor.
Definition: ExeGraph.h:193
int index()
Definition: ExeGraph.h:64
InstNodeIterator(const ExeInst< N > *inst)
Definition: ExeGraph.h:266
elm::genstruct::AllocatedTable< N * > * table
Definition: ExeGraph.h:207
int maxLatency(void)
Definition: Microprocessor.h:202
Definition: ExeGraph.h:118
ExeInst< N > * _inst
Definition: ExeGraph.h:147
int index(void)
Definition: Microprocessor.h:198
ExeInst(Inst *inst, BasicBlock *bb, typename ExeGraph< N >::code_part_t part, int index)
Constructor.
Definition: ExeGraph.h:58
void setIndex(int index)
Sets the instruction index.
Definition: ExeGraph.h:66
ExeEdge * edge(void) const
Definition: ExeGraph.h:292
Definition: ExeGraph.h:118
Definition: ExeGraph.h:145
Definition: ExeGraph.h:259
Inst * inst()
Definition: ExeGraph.h:60
ExeSequence< N > * _sequence
Definition: ExeGraph.h:202
A sequence of instructions (ExeInst)
Definition: ExeGraph.h:91
bool producesOperands(void)
Definition: ExeGraph.h:181
dtd::Element bb(dtd::make("bb", _BB).attr(id).attr(address).attr(size))
elm::genstruct::Vector< N * > _contenders
Definition: ExeGraph.h:154
elm::genstruct::Vector< N * > * contenders()
Definition: ExeGraph.h:187
ExeEdge(N *source, N *target, edge_type_t type)
Constructor.
Definition: ExeGraph.h:132
void next(void)
Definition: ExeGraph.h:291
void setLastNode(code_part_t part, N *node)
Definition: ExeGraph.h:236
void addLast(const T &value)
elm::String partName(code_part_t part)
Definition: ExeGraph.h:232
io::Output cout(io::out)
elm::genstruct::DLList< N * > _nodes
Definition: ExeGraph.h:55
ExeGraph< N >::code_part_t codePart()
Definition: ExeGraph.h:62
Definition: ExeGraph.h:275
Definition: Microprocessor.h:40
Definition: ExeGraph.h:116
N * firstNode()
Definition: ExeGraph.h:72
GenNode(graph::Graph *graph=0)
Definition: GenGraph.h:47
bool ended(void) const
Definition: ExeGraph.h:278
NodeIterator(const ExeInst *inst)
Constructor.
Definition: ExeGraph.h:80
Iterator(const DLList &_list)
Definition: ExeGraph.h:113
edge_type_t
Definition: ExeGraph.h:123
elm::String name()
Returns the name of the node, composed of the name of the pipeline stage and the name of the instruct...
Definition: ExeGraph.h:189
Iterator on the list of nodes related to the instruction.
Definition: ExeGraph.h:78
N * item(void) const
Definition: ExeGraph.h:279
inst cont(void)
Definition: inst.h:151
virtual hard::Platform * platform(void)
Definition: WorkSpace.h:75
An iterator allowing to traverse the graph using preorder, that is, a node is only traversed when its...
Definition: PreorderIterator.h:31
PipelineStage< N > * pipelineStage(void)
Definition: ExeGraph.h:167
bool _needs_operands
Definition: ExeGraph.h:150
Graph * graph(void) const
Get the container graph if any.
Definition: Graph.h:75
void addContender(N *cont)
Adds a contender to the lists of contenders for the node.
Definition: ExeGraph.h:185
ExeNode(ExeGraph< N > *graph, PipelineStage< N > *stage, ExeInst< N > *inst)
Constructor.
Definition: ExeGraph.h:156
const T & last(void) const
InstIterator(const ExeSequence *seq)
Constructor.
Definition: ExeGraph.h:95
A workspace represents a program, its run-time and all information about WCET computation or any othe...
Definition: WorkSpace.h:67
Definition: Microprocessor.h:38
void setNeedsOperands(bool val)
Sets whether the node depends on input operands.
Definition: ExeGraph.h:179
const T & first(void) const
elm::String name()
Returns the name of the edge composed of the names of the source and target nodes separated by an arr...
Definition: ExeGraph.h:141
PipelineStage< N > * operandProducingStage(void)
Definition: Microprocessor.h:314
time_bound_t
Definition: ExeGraph.h:118
N * firstNode(code_part_t part)
Definition: ExeGraph.h:238
time_step_t
Definition: ExeGraph.h:119
enum otawa::ExeGraph::ExeEdge::edge_type_t edge_type_t_t
InstIterator(const ExeSequence< N > *sequence)
Constructor.
Definition: ExeGraph.h:261
Definition: ExeGraph.h:126
ExeGraph< N >::code_part_t _part
Definition: ExeGraph.h:54
const banks_t & banks(void) const
Definition: Platform.h:163
BasicBlock * basicBlock()
Definition: ExeGraph.h:76
edge_type_t type(void)
Definition: ExeGraph.h:139
Identifier< bool > START
inst(void)
Definition: inst.h:118
Definition: ExeGraph.h:119
GenGraph< N, ExeEdge >::InIterator iter
Definition: ExeGraph.h:283
dtd::RefAttr< BasicBlock * > target("target", dtd::STRICT|dtd::REQUIRED)
An instruction represented in an ExeGraph.
Definition: ExeGraph.h:49
An execution graph that expresses precedence constraints on the execution of a sequence of instructio...
Definition: ExeGraph.h:40
Definition: Microprocessor.h:116
elm::String _name
Definition: ExeGraph.h:130
This class records information about the architecture where the processed program will run...
Definition: Platform.h:48
Definition: ExeGraph.h:119
bool needsOperands(void)
Definition: ExeGraph.h:177
This is the minimal definition of a basic block.
Definition: BasicBlock.h:43
Definition: Microprocessor.h:65
Definition: ExeGraph.h:298
virtual void build(WorkSpace *fw, Microprocessor< N > *microprocessor, ExeSequence< N > *sequence)
Definition: ExeGraph.h:308
Successor(const N *node)
Constructor.
Definition: ExeGraph.h:288
N * _last_node[CODE_PARTS_NUMBER]
Definition: ExeGraph.h:201
PipelineStage< N > * _pipeline_stage
Definition: ExeGraph.h:148
int _latency[BOUNDS]
Definition: ExeGraph.h:149
ExeInst< N > * inst(void)
Definition: ExeGraph.h:169
elm::String shortName(void)
Definition: Microprocessor.h:186
This class represents assembly instruction of a piece of code.
Definition: Inst.h:62
Definition: ExeGraph.h:264
Definition: GenGraph.h:104
BasicBlock * _bb
Definition: ExeGraph.h:52
Definition: ExeGraph.h:115
Definition: ExeGraph.h:112
int latency()
Definition: ExeGraph.h:171
FunctionalUnitIterator(PipelineStage< N > *stage)
Constructor.
Definition: ExeGraph.h:251
N * target(void) const
Definition: GenGraph.h:68
Definition: GenGraph.h:121
N * item(void) const
Definition: ExeGraph.h:290
int latency(time_bound_t bound)
Definition: ExeGraph.h:173
void setFirstNode(code_part_t part, N *node)
Definition: ExeGraph.h:234
Definition: ExeGraph.h:119
code_part_t
Definition: ExeGraph.h:111
StageNodeIterator(const PipelineStage< N > *stage)
Definition: ExeGraph.h:271
Definition: ExeGraph.h:118
Definition: ExeGraph.h:125
N * lastNode(code_part_t part)
Definition: ExeGraph.h:240
Definition: ExeGraph.h:286
int _index
Definition: ExeGraph.h:53
GenGraph< N, typename ExeGraph< N >::ExeEdge > * graph()
Definition: ExeGraph.h:225
N * lastNode()
Definition: ExeGraph.h:74
elm::String _part_name[CODE_PARTS_NUMBER]
Definition: ExeGraph.h:204
Definition: ExeGraph.h:114
String toString(void)
void setProducesOperands(bool val)
Sets whether the node produces output operands.
Definition: ExeGraph.h:183
int width(void) const
Definition: Microprocessor.h:182
int length()
Definition: ExeGraph.h:98