OpenASIP  2.0
ExecutionPipelineBroker.cc
Go to the documentation of this file.
1 /*
2  Copyright (c) 2002-2009 Tampere University.
3 
4  This file is part of TTA-Based Codesign Environment (TCE).
5 
6  Permission is hereby granted, free of charge, to any person obtaining a
7  copy of this software and associated documentation files (the "Software"),
8  to deal in the Software without restriction, including without limitation
9  the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  and/or sell copies of the Software, and to permit persons to whom the
11  Software is furnished to do so, subject to the following conditions:
12 
13  The above copyright notice and this permission notice shall be included in
14  all copies or substantial portions of the Software.
15 
16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  DEALINGS IN THE SOFTWARE.
23  */
24 /**
25  * @file ExecutionPipelineBroker.cc
26  *
27  * Implementation of ExecutionPipelineBroker class.
28  *
29  * @author Ari Mets�halme 2006 (ari.metsahalme-no.spam-tut.fi)
30  * @author Vladimir Guzma 2007 (vladimir.guzma-no.spam-tut.fi)
31  * @note rating: red
32  */
33 
34 #include <climits>
35 
38 #include "Machine.hh"
39 #include "ControlUnit.hh"
40 #include "FUPort.hh"
41 #include "ExecutionPipeline.hh"
42 #include "PipelineElement.hh"
43 #include "HWOperation.hh"
44 #include "ResourceMapper.hh"
45 #include "MapTools.hh"
46 #include "StringTools.hh"
47 #include "PSocketResource.hh"
48 #include "TCEString.hh"
49 #include "ResourceManager.hh"
50 #include "Terminal.hh"
51 #include "ProgramOperation.hh"
52 #include "Operation.hh"
53 #include "Move.hh"
54 #include "DataDependenceGraph.hh"
55 
56 using namespace TTAMachine;
57 using std::pair;
58 
59 /**
60  * Constructor.
61  */
63  unsigned int initiationInterval):
64  ResourceBroker(name, initiationInterval), longestLatency_(0), ddg_(NULL) {
65 
66  // change ii for broker's resources also
67  for (FUPipelineMap::iterator i = fuPipelineMap_.begin();
68  i != fuPipelineMap_.end(); ++i) {
69  i->first->setInitiationInterval(initiationInterval);
70  }
71 }
72 
73 void
74 ExecutionPipelineBroker::setMaxCycle(unsigned int maxCycle) {
75  // change ii for broker's resources also
76  for (FUPipelineMap::iterator i = fuPipelineMap_.begin();
77  i != fuPipelineMap_.end(); ++i) {
78  i->first->setMaxCycle(maxCycle);
79  }
80 }
81 
82 /**
83  * Destructor.
84  */
86 }
87 
88 /**
89  * Mark given resource as in use for the given node, and assign the
90  * corresponding machine part (if applicable) to the node's move.
91  *
92  * If the node is already assigned to given resource, this method does
93  * nothing.
94  *
95  * @exception WrongSubclass If this broker does not recognise the given
96  * type of resource.
97  * @exception InvalidParameters If he given resource cannot be assigned to
98  * given node or no corresponding machine part is found.
99  * @note The execution pipeline broker is used only to construct resources.
100  */
101 void
103 {
104  abortWithError("Not implemented.");
105 }
106 
107 /**
108  * Free the resource type managed by this broker and unassign it from
109  * given node.
110  *
111  * If this broker is not applicable to the given node, or the node is
112  * not assigned a resource of the managed type, this method does
113  * nothing.
114  *
115  * @param node Node.
116  */
117 void
119  abortWithError("Not implemented.");
120 }
121 
122 /**
123  * Return the earliest cycle, starting from given cycle, where a
124  * resource of the type managed by this broker can be assigned to the
125  * given node.
126  *
127  * Considers source and destination terminals independently
128  * and compares the results. Returns -1 if no assignment is possible.
129  *
130  * @param cycle Cycle.
131  * @param node Node.
132  * @param srcFU if not null, srcFu that has to be used.
133  * @param dstFU if not null, dstFU that has to be used.
134  * @param immWriteCycle if not -1 and src is imm, write cycle of limm.
135  */
136 int
138  const TTAMachine::Bus*,
139  const TTAMachine::FunctionUnit* srcFU,
140  const TTAMachine::FunctionUnit* dstFU,
141  int,
143  int)
144  const {
145 
146  int efs = earliestFromSource(cycle, node, srcFU);
147  if (efs == -1 || efs == INT_MAX) {
148  debugLogRM("returning -1");
149  return -1;
150  }
151  int efd = earliestFromDestination(efs, node, dstFU);
152  if (efd == -1 || efd == INT_MAX) {
153  debugLogRM("returning -1");
154  return -1;
155  }
156 
157  // Loop as long as we find cycle which work for both source and
158  // destination.
159  while (efd != efs) {
160  efs = earliestFromSource(efd, node, srcFU);
161  if (efs == -1 || efs == INT_MAX) {
162  debugLogRM("returning -1");
163  return -1;
164  }
165  if (efs == efd) {
166  return efd;
167  }
168  efd = earliestFromDestination(efs, node, dstFU);
169  if (efd == -1 || efd == INT_MAX) {
170  debugLogRM("returning -1");
171  return -1;
172  }
173  }
174  return efd;
175 }
176 
177 /**
178  * Return the latest cycle, starting from given cycle, where a
179  * resource of the type managed by this broker can be assigned to the
180  * given node.
181  *
182  * @param cycle Cycle.
183  * @param node Node.
184  * @param srcFU if not null, srcFu that has to be used.
185  * @param dstFU if not null, dstFU that has to be used.
186  * @param immWriteCycle if not -1 and src is imm, write cycle of limm.
187  * @return The latest cycle, starting from given cycle backwards, where a
188  * resource of the type managed by this broker can be assigned to the
189  * given node. Considers source and destination terminals independently
190  * and compares the results. Returns -1 if no assignment is possible.
191  */
192 int
194  const TTAMachine::Bus*,
195  const TTAMachine::FunctionUnit* srcFU,
196  const TTAMachine::FunctionUnit* dstFU,
197  int,
199  int) const {
200  int src = latestFromSource(cycle,node, srcFU);
201  if (src == -1) {
202  return -1;
203  }
204  int dst = latestFromDestination(src, node, dstFU);
205  return dst;
206 }
207 
208 /**
209  * Return true if the given node is already assigned a resource of the
210  * type managed by this broker, and the assignment appears valid (that
211  * is, the broker has marked that resource as in use in the given
212  * cycle).
213  *
214  * @param cycle Cycle.
215  * @param node Node.
216  * @return True if the given node is already assigned a resource of the
217  * type managed by this broker, and the assignment appears valid (that
218  * is, the broker has marked that resource as in use in the given
219  * cycle).
220  */
221 bool
223  int, const MoveNode&, const TTAMachine::Bus*) const {
224  abortWithError("Not implemented.");
225  return false;
226 }
227 
228 /**
229  * Return true if the given node needs a resource of the type managed
230  * by this broker, false otherwise.
231  *
232  * @param node Node.
233  * @return Always false. Broker is not used standalone, only for creating
234  * resources and setting up resource links.
235  * @note Broker is used only to construct resources, the assignment
236  * and unassignment is done via ExecutionPipelineResource attached to
237  * InputFuResource.
238  */
239 bool
241  const MoveNode&, const TTAMachine::Bus*) const {
242  return false;
243 }
244 
245 /**
246  * Build all resource objects of the controlled type required to model
247  * scheduling resources of the given target processor.
248  *
249  * This method cannot set up the resource links (dependent and related
250  * resources) of the constructed resource objects.
251  *
252  * @param target Target machine.
253  */
254 void
256 
258  for (int i = 0; i < navi.count(); i++) {
259  FunctionUnit* fu = navi.item(i);
260  ExecutionPipelineResource* epResource =
262  *fu, initiationInterval_);
263 
264  ResourceBroker::addResource(*fu, epResource);
265  fuPipelineMap_.insert(
266  pair<SchedulingResource*, const FunctionUnit*>(epResource, fu));
267  longestLatency_ =
268  (longestLatency_ < fu->maxLatency())
269  ? fu->maxLatency() : longestLatency_;
270  }
271 
272  ControlUnit* gcu = target.controlUnit();
273 
274  ExecutionPipelineResource* epResource =
276 
277  ResourceBroker::addResource(*gcu, epResource);
278  fuPipelineMap_.insert(pair<SchedulingResource*, const
279  FunctionUnit*>(epResource, gcu));
280 }
281 
282 /**
283  * Complete resource initialisation by creating the references to
284  * other resources due to a dependency or a relation. Use the given
285  * resource mapper to lookup dependent and related resources using
286  * machine parts as keys.
287  *
288  * @param mapper Resource mapper.
289  */
290 void
292 
293  setResourceMapper(mapper);
294 
295  for (ResourceMap::iterator resIter = resMap_.begin();
296  resIter != resMap_.end(); resIter++) {
297 
298  const FunctionUnit* fuOriginal =
299  dynamic_cast<const FunctionUnit*>((*resIter).first);
300  if (fuOriginal == NULL){
301  throw InvalidData(
302  __FILE__, __LINE__, __func__,
303  "ExecutionPipelineBroker has something "
304  "else then FU registered!");
305  }
306 
307  // resMap_ is local for broker, so it can only contain fu->epResource
308  SchedulingResource* epResource = (*resIter).second;
309 
310  const FunctionUnit* fu = NULL;
311 
312  try {
313  fu = MapTools::valueForKey<const FunctionUnit*>(
314  fuPipelineMap_, epResource);
315  } catch (const Exception& e) {
316  std::string msg = "Pipeline resource \'";
317  msg += epResource->name();
318  msg += "\' not found";
319  abortWithError(msg);
320  }
321 
322  for (int i = 0; i < fu->portCount(); i++) {
323  BaseFUPort* port = fu->port(i);
324  if (port->isTriggering()) {
325  if (port->outputSocket() != NULL) {
326  try {
327  SchedulingResource& relatedRes =
328  mapper.resourceOf(*port->outputSocket());
329  epResource->addToRelatedGroup(0, relatedRes);
330  } catch (const KeyNotFound& e) {
331  std::string msg = "ExecutionPipelineBroker: finding ";
332  msg += " resource for Socket ";
333  msg += " failed with error: ";
334  msg += e.errorMessageStack();
335  msg += " for resource " + epResource->name();
336  throw KeyNotFound(
337  __FILE__, __LINE__, __func__, msg);
338  }
339 
340  } else {
341  try {
342  SchedulingResource& relatedRes =
343  mapper.resourceOf(*port->inputSocket());
344  epResource->addToRelatedGroup(0, relatedRes);
345  } catch (const KeyNotFound& e) {
346  std::string msg = "ExecutionPipelineBroker: finding ";
347  msg += " resource for Socket ";
348  msg += " failed with error: ";
349  msg += e.errorMessageStack();
350  msg += " for resource " + epResource->name();
351  throw KeyNotFound(
352  __FILE__, __LINE__, __func__, msg);
353  }
354  }
355  }
356  }
357  }
358 }
359 
360 /**
361  * Return the highest cycle any of the pipeline is known to be used
362  *
363  * @return A highest cycle in which any of the pipelines is used.
364  */
365 int
367  int localMax = 0;
368  for (ResourceMap::const_iterator resIter = resMap_.begin();
369  resIter != resMap_.end(); resIter++) {
371  (dynamic_cast<ExecutionPipelineResource*>((*resIter).second));
372  localMax = std::max(ep->highestKnownCycle(), localMax);
373  }
374  return localMax;
375 }
376 
377 bool
379  return true;
380 }
381 
382 /**
383  * Set initiation interval, if ii = 0 then initiation interval is not used.
384  *
385  * @param ii initiation interval
386  */
387 void
389 {
390  initiationInterval_ = ii;
391 
392  // change ii for broker's resources also
393  for (FUPipelineMap::iterator i = fuPipelineMap_.begin();
394  i != fuPipelineMap_.end(); ++i) {
395  i->first->setInitiationInterval(ii);
396  }
397 }
398 
400 
401  if (ddg_ == NULL || !ddg_->hasNode(node)) {
402  return false;
403  }
404  auto inEdges = ddg_->operationInEdges(node);
405  for (auto e : inEdges) {
406  if (e->isBackEdge()) {
407  return true;
408  }
409  }
410  return false;
411 }
412 
413 
414 /**
415  * Returns latest cycle, starting from given parameter and going towards
416  * zero, in which the node can be scheduled. Taking into account source
417  * terminal of Move (result read).
418  *
419  * @param cycle Starting cycle for tests
420  * @param node MoveNode to find latest cycle for
421  * @return The latest cycle in which the MoveNode can be scheduled, -1 if
422  * scheduling is not possible, 'cycle' if source is not FUPort
423  */
424 int
426  int cycle, const MoveNode& node, const TTAMachine::FunctionUnit* srcFU)
427  const{
428 
429  if (!node.isSourceOperation()) {
430  return cycle;
431  }
432  // kludge for looop bypass.
433  ProgramOperation& sourceOp = node.sourceOperation();
434  if (isLoopBypass(node)) {
435  cycle+=initiationInterval_;
436  }
437  const MoveNode* triggerNode = NULL;
438  const MoveNode* lastOperandNode = NULL;
439  const MoveNode* lastResultNode = NULL;
440  int minCycle = -1;
441  // Source is result read, we test all operands
442  for (int i = 0; i < sourceOp.inputMoveCount(); i++) {
443  const MoveNode* tempNode = &sourceOp.inputMove(i);
444  if (tempNode->isScheduled() && tempNode != &node) {
445  minCycle = std::max(tempNode->cycle(), minCycle);
446  lastOperandNode = tempNode;
447  if (tempNode->move().isTriggering()) {
448  triggerNode = tempNode;
449  }
450  }
451  }
452  // Source is result read, we test all results
453  for (int i = 0; i < sourceOp.outputMoveCount(); i++) {
454  const MoveNode* tempNode = &sourceOp.outputMove(i);
455  if (tempNode->isScheduled() && tempNode != &node) {
456  int tempCycle = tempNode->cycle();
457  if (isLoopBypass(*tempNode)) {
458  tempCycle += initiationInterval_;
459  }
460  minCycle = std::max(tempCycle, minCycle);
461  lastResultNode = tempNode;
462  }
463  }
464 
465  if (minCycle == -1) {
466  return cycle;
467  }
468  if (minCycle > cycle && lastResultNode == NULL) {
469  // Some operand is already later then where we started to backtrack.
470  debugLogRM("returning -1");
471  return -1;
472  }
473  if (triggerNode != NULL) {
474 
475  if (minCycle >= node.earliestResultReadCycle()
476  && lastResultNode == NULL) {
477  // If we do have minCycle from operands, this is valid test,
478  // otherwise it is not.
479  throw InvalidData(__FILE__, __LINE__, __func__,
480  "Some operand move is written after the result move "
481  "is ready! " + node.toString());
482  }
483  if (node.earliestResultReadCycle() > cycle) {
484  // Result is available later then where we started to backtrack
485  debugLogRM("returning -1");
486  return -1;
487  } else {
488  minCycle = node.earliestResultReadCycle();
489  }
490  }
491  // minCycle has latest of operand writes or earliest result read cycle
492  // find next read of same FU with different PO
493  assert(lastOperandNode != NULL || lastResultNode != NULL);
494  const TTAMachine::FunctionUnit* fu;
495  if (lastOperandNode != NULL) {
496  fu = &lastOperandNode->move().destination().functionUnit();
497  } else {
498  if (lastResultNode->isSourceOperation()) {
499  fu = &lastResultNode->move().source().functionUnit();
500  } else {
501  assert(lastResultNode->isGuardOperation());
502  fu = lastResultNode->guardOperation().fuFromOutMove(*lastResultNode);
503  }
504  }
505 
506  if (srcFU != NULL && fu != srcFU) {
507  return -1;
508  }
509  HWOperation& hwop = *fu->operation(sourceOp.operation().name());
510  const TTAMachine::Port& port =
511  *hwop.port(node.move().source().operationIndex());
512  SchedulingResource& res = *resourceOf(*fu);
514  static_cast<ExecutionPipelineResource*>(&res);
515  int triggerCycle = triggerNode != NULL && triggerNode->isScheduled() ?
516  triggerNode->cycle() :
517  INT_MAX;
518  // last available cycle is one lower then next write
519 
520  int nextResult = ep->nextResultCycle(
521  port, minCycle, node, triggerNode, triggerCycle);
522  if (cycle < nextResult || nextResult < minCycle) {
523  return cycle;
524  }
525  return nextResult-1;
526 }
527 /**
528  * Returns latest cycle, starting from given parameter and going towards
529  * zero, in which the node can be scheduled. Taking into account destination
530  * terminal of Move (operand write).
531  *
532  * @param cycle Starting cycle for tests
533  * @param node MoveNode to find latest cycle for
534  * @return The latest cycle in which the MoveNode can be scheduled, -1 if
535  * scheduling is not possible, 'cycle' if destination is not FUPort
536  */
537 int
539  int cycle,
540  const MoveNode& node, const TTAMachine::FunctionUnit* dstUnit) const {
541 
542  // TODO: this not do full reuslt overwrite another tests.
543  // It is however handled in canassign().
544  // Doing it here would make scheduling faster.
545  int latest = cycle;
546  for (unsigned int j = 0; j < node.destinationOperationCount(); j++) {
547  ProgramOperation& destOp = node.destinationOperation(j);
548  for (int i = 0; i < destOp.inputMoveCount(); i++) {
549  const MoveNode* tempNode = &destOp.inputMove(i);
550  if (tempNode->isScheduled() && tempNode != &node) {
551  if (tempNode->move().isTriggering()) {
552  latest = std::min(tempNode->cycle(), latest);
553  }
554  }
555  }
556 
557  for (int i = 0; i < destOp.outputMoveCount(); i++) {
558  const MoveNode* tempNode = &destOp.outputMove(i);
559  if (tempNode->isScheduled() && tempNode != &node) {
560  const TTAMachine::FunctionUnit* fu =
561  &node.move().destination().functionUnit();
562  if (dstUnit != NULL && dstUnit != fu) {
563  return -1;
564  }
565  const TTAMachine::HWOperation& hwop =
566  *fu->operation(
567  destOp.operation().name());
568  const int outputIndex =
569  (tempNode->isSourceOperation() &&
570  &tempNode->sourceOperation() == &destOp)
571  ?
572  tempNode->move().source().operationIndex() :
573  destOp.outputIndexFromGuardOfMove(*tempNode);
574 
575  int tempCycle = tempNode->cycle();
576  if (isLoopBypass(*tempNode)) {
577  tempCycle += initiationInterval_;
578  }
579 
580  latest = std::min(latest,
581  tempCycle - hwop.latency(outputIndex));
582  }
583  }
584  }
585 
586  return latest;
587 }
588 /**
589  * Returns earliest cycle, starting from given parameter and going towards
590  * INT_MAX, in which the node can be scheduled. Taking into account
591  * source Terminal of Move (result read) and other operands already
592  * scheduled.
593  *
594  * @param cycle Starting cycle for tests
595  * @param node MoveNode to find earliest cycle for
596  * @return The earliest cycle in which the MoveNode can be scheduled, 0 if
597  * source is not FUPort
598  */
599 int
601  int cycle, const MoveNode& node, const TTAMachine::FunctionUnit* srcFU)
602  const {
603 
604  if (!node.isSourceOperation()) {
605  return cycle;
606  }
607  ProgramOperation& sourceOp = node.sourceOperation();
608  const MoveNode* triggerNode = NULL;
609  int minCycle = -1;
610 
611  const FunctionUnit* fu = NULL;
612  assert(node.move().source().isFUPort());
613 
614  const HWOperation* hwop = NULL;
615  const int outputIndex =
616  node.move().source().operationIndex();
617  int latency = 1;
618 
619  for (int i = 0; i < sourceOp.inputMoveCount(); i++) {
620  const MoveNode* tempNode = &sourceOp.inputMove(i);
621  if (tempNode->isScheduled() && tempNode != &node) {
622  fu = &tempNode->move().destination().functionUnit();
623  if (srcFU != NULL&& fu != srcFU) {
624  return -1;
625  }
626  minCycle = std::max(tempNode->cycle()+1, minCycle);
627  if (tempNode->move().isTriggering()) {
628  triggerNode = tempNode;
629  hwop = fu->operation(sourceOp.operation().name());
630  latency = hwop->latency(outputIndex);
631  minCycle = std::max(triggerNode->cycle() + latency, cycle);
632  }
633  }
634  }
635  if (minCycle == -1) {
636  // no operands scheduled for result of given PO
637  // so earliest cycle is 0 + latency or tested cycle
638  if (initiationInterval_ != 0 && latency >= (int)initiationInterval_) {
639  debugLogRM("returning -1");
640  return -1;
641  }
642  minCycle = std::max(cycle,1);
643  }
644 
645  if (triggerNode != NULL && triggerNode->isScheduled()) {
646  int triggerCycle = triggerNode->cycle();
647 
648  const TTAMachine::Port& port = *hwop->port(outputIndex);
649  SchedulingResource& res = *resourceOf(*fu);
651  static_cast<ExecutionPipelineResource*>(&res);
652 
653  if (!ep->resultNotOverWritten(
654  minCycle, node.earliestResultReadCycle(), node,
655  port, triggerNode, triggerCycle)) {
656  return -1;
657  }
658  }
659 
660  return std::max(minCycle, cycle);
661 }
662 
663 // TODO: if some result scheudled?
665  if (!node.isDestinationOperation()) {
666  return false;
667  }
668 
669  for (unsigned int j = 0; j < node.destinationOperationCount(); j++) {
670 // const HWOperation* hwop = NULL;
671 
672  // Test other inputs to the operation.
673  ProgramOperation& destOp = node.destinationOperation(j);
674 
675  for (int i = 0; i < destOp.inputMoveCount(); i++) {
676  const MoveNode* tempNode = &destOp.inputMove(i);
677  if (tempNode->isScheduled()) {
678  if (tempNode->move().isTriggering()) {
679  if (tempNode != &node) {
680  return false;
681  break;
682  } else {
683  return true;
684  }
685  }
686  auto fu = &tempNode->move().destination().functionUnit();
687  auto triggeringPort = fu->triggerPort();
688  auto hwop = fu->operation(
689  node.destinationOperation().operation().name());
690  auto port = hwop->port(
691  node.move().destination().operationIndex());
692  if (port == triggeringPort) {
693  return true;
694  } else {
695  return false;
696  }
697  }
698  }
699  }
700  return false;
701 }
702 
703 /**
704  * Return earliest cycle, starting from given parameter and going towards
705  * INT_MAX, in which the node can be scheduled. Taking into account
706  * destination terminal of Move (operand write).
707  *
708  * This method may return too early for some cases but there is canassign test
709  * after this always at higher level in RM so this does not matter;
710  * having this method is just performance optimization to avoid calling
711  * slow canAssign() for too small values.
712  *
713  * @param cycle Starting cycle for tests
714  * @param node MoveNode to find earliest cycle for
715  * @return The earliest cycle in which the MoveNode can be scheduled, -1 if
716  * scheduling is not possible, 0 if destination is not FUPort
717  */
718 int
720  int cycle,
721  const MoveNode& node, const TTAMachine::FunctionUnit* dstFU) const {
722 
723  if (!node.isDestinationOperation()) {
724  return cycle;
725  }
726  const FunctionUnit* fu = NULL;
727 
728  int minCycle = cycle;
729 
730  bool triggers = isMoveTrigger(node);
731 
732  for (unsigned int j = 0; j < node.destinationOperationCount(); j++) {
733 
734  const HWOperation* hwop = NULL;
735  // Test other inputs to the operation.
736  ProgramOperation& destOp = node.destinationOperation(j);
737 
738  for (int i = 0; i < destOp.inputMoveCount(); i++) {
739  const MoveNode* tempNode = &destOp.inputMove(i);
740  if (tempNode->isScheduled() && tempNode != &node) {
741  fu = &tempNode->move().destination().functionUnit();
742  hwop = fu->operation(destOp.operation().name());
743  if (dstFU != NULL && fu != dstFU) {
744  return -1;
745  }
746 
747  if (triggers) {
748  // TODO: operand slack
749  minCycle = std::max(tempNode->cycle(), minCycle);
750  }
751  if (tempNode->move().isTriggering()) {
752  // TODO: operand slack
753  int triggerCycle = tempNode->cycle();
754  if (triggerCycle < cycle) {
755  // trying to schedule operand after trigger
756  debugLogRM("returning -1");
757  return -1;
758  }
759  }
760  }
761  }
762 
763  // Then check the already scheduled results, do they limit the cycle
764  // where this can be scheduled.
765  int minResultCycle = INT_MAX;
766  for (int i = 0; i < destOp.outputMoveCount(); i++) {
767  const MoveNode* tempNode = &destOp.outputMove(i);
768  if (tempNode->isScheduled()) {
769  if (fu == NULL) {
770  fu = destOp.fuFromOutMove(*tempNode);
771  hwop = fu->operation(destOp.operation().name());
772  }
773 
774  if (dstFU != NULL && fu != dstFU) {
775  return -1;
776  }
777 
778  const int outputIndex =
779  destOp.outputIndexOfMove(*tempNode);
780 
781  // TODO: slack
782 
783  unsigned int latency = hwop->latency(outputIndex);
784  if (initiationInterval_ != 0 && latency >= initiationInterval_) {
785  debugLogRM("returning -1");
786  return -1;
787  }
788  minResultCycle =
789  std::min(
790  minResultCycle,
791  tempNode->cycle() - hwop->latency(outputIndex));
792  }
793  }
794  if (minResultCycle < minCycle) {
795  // tested cycle is larger then last trigger cycle for results
796  // already scheduled
797  debugLogRM("returning -1");
798  return -1;
799  }
800  }
801 
802  return minCycle;
803 }
804 
805 void
807  for (ResourceMap::iterator i = resMap_.begin(); i != resMap_.end(); i++) {
808  (static_cast<ExecutionPipelineResource*>(i->second))->setDDG(ddg);
809  }
810  ddg_ = ddg;
811 }
812 
ExecutionPipelineBroker::isApplicable
virtual bool isApplicable(const MoveNode &node, const TTAMachine::Bus *) const override
Definition: ExecutionPipelineBroker.cc:240
ExecutionPipelineResource
Definition: ExecutionPipelineResource.hh:64
ProgramOperation::operation
const Operation & operation() const
Definition: ProgramOperation.cc:590
TTAProgram::Terminal::isFUPort
virtual bool isFUPort() const
Definition: Terminal.cc:118
ExecutionPipelineBroker::~ExecutionPipelineBroker
virtual ~ExecutionPipelineBroker()
Definition: ExecutionPipelineBroker.cc:85
ProgramOperation::outputIndexFromGuardOfMove
int outputIndexFromGuardOfMove(const MoveNode &node) const
Definition: ProgramOperation.cc:256
TTAProgram::Move::isTriggering
bool isTriggering() const
Definition: Move.cc:284
ExecutionPipelineBroker::latestCycle
virtual int latestCycle(int cycle, const MoveNode &node, const TTAMachine::Bus *bus, const TTAMachine::FunctionUnit *srcFU, const TTAMachine::FunctionUnit *dstFU, int immWriteCycle, const TTAMachine::ImmediateUnit *immu, int immRegIndex) const override
Definition: ExecutionPipelineBroker.cc:193
TTAMachine::Port::inputSocket
virtual Socket * inputSocket() const
Definition: Port.cc:261
ExecutionPipelineBroker::longestLatency_
int longestLatency_
Longest latency of all operations of all the FUs.
Definition: ExecutionPipelineBroker.hh:110
ResourceBroker::initiationInterval_
unsigned int initiationInterval_
Definition: ResourceBroker.hh:158
MoveNode::toString
std::string toString() const
Definition: MoveNode.cc:576
ExecutionPipelineBroker::highestKnownCycle
virtual int highestKnownCycle() const
Definition: ExecutionPipelineBroker.cc:366
ExecutionPipelineBroker::buildResources
virtual void buildResources(const TTAMachine::Machine &target) override
Definition: ExecutionPipelineBroker.cc:255
TTAMachine::HWOperation
Definition: HWOperation.hh:52
ResourceMapper.hh
ExecutionPipeline.hh
ResourceBroker::resMap_
ResourceMap resMap_
Definition: ResourceBroker.hh:165
MoveNode::isDestinationOperation
bool isDestinationOperation() const
TTAMachine::FunctionUnit::triggerPort
virtual BaseFUPort * triggerPort() const
Definition: FunctionUnit.cc:267
ExecutionPipelineBroker::latestFromDestination
int latestFromDestination(int, const MoveNode &, const TTAMachine::FunctionUnit *dstFU) const
Definition: ExecutionPipelineBroker.cc:538
MapTools.hh
TTAMachine::Bus
Definition: Bus.hh:53
TTAMachine::BaseFUPort
Definition: BaseFUPort.hh:44
TTAProgram::Move::destination
Terminal & destination() const
Definition: Move.cc:323
ExecutionPipelineBroker::assign
virtual void assign(int cycle, MoveNode &node, SchedulingResource &res, int immWriteCycle, int immRegIndex) override
Definition: ExecutionPipelineBroker.cc:102
ExecutionPipelineBroker::earliestFromSource
int earliestFromSource(int, const MoveNode &, const TTAMachine::FunctionUnit *srcFU) const
Definition: ExecutionPipelineBroker.cc:600
ProgramOperation::fuFromOutMove
const TTAMachine::FunctionUnit * fuFromOutMove(const MoveNode &outputNode) const
Definition: ProgramOperation.cc:844
ExecutionPipelineBroker::ExecutionPipelineBroker
ExecutionPipelineBroker(std::string, unsigned int initiationInterval=0)
Definition: ExecutionPipelineBroker.cc:62
ResourceBroker
Definition: ResourceBroker.hh:61
DataDependenceGraph.hh
ProgramOperation
Definition: ProgramOperation.hh:70
MoveNode
Definition: MoveNode.hh:65
TTAMachine::FunctionUnit::port
virtual BaseFUPort * port(const std::string &name) const
Definition: FunctionUnit.cc:145
Terminal.hh
ResourceMapper::resourceOf
SchedulingResource & resourceOf(const TTAMachine::MachinePart &mp, int index=0) const
Definition: ResourceMapper.cc:96
TTAMachine::Machine::Navigator::count
int count() const
ResourceBroker::addResource
void addResource(const TTAMachine::MachinePart &mp, SchedulingResource *res)
Definition: ResourceBroker.cc:265
Operation::name
virtual TCEString name() const
Definition: Operation.cc:93
TTAMachine::FunctionUnit::maxLatency
virtual int maxLatency() const
Definition: FunctionUnit.cc:443
ExecutionPipelineBroker::ddg_
const DataDependenceGraph * ddg_
Definition: ExecutionPipelineBroker.hh:111
debugLogRM
#define debugLogRM(__X)
Definition: ResourceManager.hh:123
TCEString.hh
MoveNode::sourceOperation
ProgramOperation & sourceOperation() const
Definition: MoveNode.cc:453
StringTools.hh
assert
#define assert(condition)
Definition: Application.hh:86
ExecutionPipelineBroker::setMaxCycle
virtual void setMaxCycle(unsigned int maxCycle) override
Definition: ExecutionPipelineBroker.cc:74
TTAMachine::FunctionUnit
Definition: FunctionUnit.hh:55
TTAMachine::HWOperation::port
virtual FUPort * port(int operand) const
Definition: HWOperation.cc:320
ResourceBroker::setResourceMapper
void setResourceMapper(const ResourceMapper &mapper)
Definition: ResourceBroker.cc:224
MoveNode::isGuardOperation
bool isGuardOperation() const
Definition: MoveNode.cc:181
DataDependenceGraph::operationInEdges
EdgeSet operationInEdges(const MoveNode &node) const
Definition: DataDependenceGraph.cc:5913
MoveNode::earliestResultReadCycle
int earliestResultReadCycle() const
Definition: MoveNode.cc:652
TTAMachine::Machine::controlUnit
virtual ControlUnit * controlUnit() const
Definition: Machine.cc:345
ExecutionPipelineBroker::isAlreadyAssigned
virtual bool isAlreadyAssigned(int cycle, const MoveNode &node, const TTAMachine::Bus *preassignedBus) const override
Definition: ExecutionPipelineBroker.cc:222
TTAProgram::Terminal::operationIndex
virtual int operationIndex() const
Definition: Terminal.cc:364
abortWithError
#define abortWithError(message)
Definition: Application.hh:72
SchedulingResource::addToRelatedGroup
virtual void addToRelatedGroup(const int group, SchedulingResource &resource)
Definition: SchedulingResource.cc:82
MoveNode::cycle
int cycle() const
Definition: MoveNode.cc:421
HWOperation.hh
ExecutionPipelineBroker.hh
InvalidData
Definition: Exception.hh:149
ExecutionPipelineResource::resultNotOverWritten
bool resultNotOverWritten(int resultReadCycle, int resultReadyCycle, const MoveNode &node, const TTAMachine::Port &port, const MoveNode *trigger, int triggerCycle) const
Definition: ExecutionPipelineResource.cc:2048
TTAMachine::ControlUnit
Definition: ControlUnit.hh:50
ExecutionPipelineBroker::isLoopBypass
bool isLoopBypass(const MoveNode &node) const
Definition: ExecutionPipelineBroker.cc:399
SchedulingResource
Definition: SchedulingResource.hh:52
TTAMachine::Port
Definition: Port.hh:54
ExecutionPipelineBroker::isMoveTrigger
bool isMoveTrigger(const MoveNode &node) const
Definition: ExecutionPipelineBroker.cc:664
__func__
#define __func__
Definition: Application.hh:67
TTAMachine::Machine::functionUnitNavigator
virtual FunctionUnitNavigator functionUnitNavigator() const
Definition: Machine.cc:380
ExecutionPipelineBroker::unassign
virtual void unassign(MoveNode &node) override
Definition: ExecutionPipelineBroker.cc:118
ExecutionPipelineBroker::latestFromSource
int latestFromSource(int, const MoveNode &, const TTAMachine::FunctionUnit *srcFU) const
Definition: ExecutionPipelineBroker.cc:425
ExecutionPipelineBroker::fuPipelineMap_
FUPipelineMap fuPipelineMap_
FU's and their corresponding pipeline resources.
Definition: ExecutionPipelineBroker.hh:108
Exception::errorMessageStack
std::string errorMessageStack(bool messagesOnly=false) const
Definition: Exception.cc:138
Operation.hh
ResourceBroker::setInitiationInterval
virtual void setInitiationInterval(unsigned int cycles)
Definition: ResourceBroker.cc:292
ResourceBroker::resourceOf
SchedulingResource * resourceOf(const TTAMachine::MachinePart &mp) const
MoveNode::isSourceOperation
bool isSourceOperation() const
Definition: MoveNode.cc:168
Machine.hh
Exception
Definition: Exception.hh:54
MoveNode::destinationOperationCount
unsigned int destinationOperationCount() const
ProgramOperation::inputMoveCount
int inputMoveCount() const
Definition: ProgramOperation.cc:600
TTAMachine::BaseFUPort::isTriggering
virtual bool isTriggering() const =0
BoostGraph::hasNode
bool hasNode(const Node &) const
TTAMachine::Unit::portCount
virtual int portCount() const
Definition: Unit.cc:135
ProgramOperation::outputMoveCount
int outputMoveCount() const
Definition: ProgramOperation.cc:610
ProgramOperation.hh
TTAProgram::Terminal::functionUnit
virtual const TTAMachine::FunctionUnit & functionUnit() const
Definition: Terminal.cc:251
ExecutionPipelineBroker::isExecutionPipelineBroker
virtual bool isExecutionPipelineBroker() const override
Definition: ExecutionPipelineBroker.cc:378
MoveNode::destinationOperation
ProgramOperation & destinationOperation(unsigned int index=0) const
MoveNode::move
TTAProgram::Move & move()
ExecutionPipelineBroker::setInitiationInterval
virtual void setInitiationInterval(unsigned int cycles) override
Definition: ExecutionPipelineBroker.cc:388
ExecutionPipelineResource.hh
ExecutionPipelineBroker::setupResourceLinks
virtual void setupResourceLinks(const ResourceMapper &mapper) override
Definition: ExecutionPipelineBroker.cc:291
FUPort.hh
PSocketResource.hh
ExecutionPipelineResource::nextResultCycle
int nextResultCycle(const TTAMachine::Port &port, int cycle, const MoveNode &node, const MoveNode *trigger=NULL, int triggerCycle=INT_MAX) const
Definition: ExecutionPipelineResource.cc:1602
ControlUnit.hh
DataDependenceGraph
Definition: DataDependenceGraph.hh:67
ResourceMapper
Definition: ResourceMapper.hh:51
PipelineElement.hh
TTAMachine::Port::outputSocket
virtual Socket * outputSocket() const
Definition: Port.cc:281
MoveNode::isScheduled
bool isScheduled() const
Definition: MoveNode.cc:409
TTAProgram::Move::source
Terminal & source() const
Definition: Move.cc:302
ExecutionPipelineBroker::setDDG
void setDDG(const DataDependenceGraph *ddg)
Definition: ExecutionPipelineBroker.cc:806
ExecutionPipelineBroker::earliestCycle
virtual int earliestCycle(int cycle, const MoveNode &node, const TTAMachine::Bus *bus, const TTAMachine::FunctionUnit *srcFU, const TTAMachine::FunctionUnit *dstFU, int immWriteCycle, const TTAMachine::ImmediateUnit *immu, int immRegIndex) const override
Definition: ExecutionPipelineBroker.cc:137
TTAMachine::Machine::Navigator::item
ComponentType * item(int index) const
KeyNotFound
Definition: Exception.hh:285
TTAMachine::FunctionUnit::operation
virtual HWOperation * operation(const std::string &name) const
Definition: FunctionUnit.cc:363
SchedulingResource::name
virtual const std::string & name() const
TTAMachine::HWOperation::latency
int latency() const
Definition: HWOperation.cc:216
Move.hh
TTAMachine
Definition: Assembler.hh:48
ExecutionPipelineBroker::earliestFromDestination
int earliestFromDestination(int, const MoveNode &, const TTAMachine::FunctionUnit *dstFU) const
Definition: ExecutionPipelineBroker.cc:719
ProgramOperation::outputMove
MoveNode & outputMove(int index) const
Definition: ProgramOperation.cc:632
TTAMachine::Machine::Navigator
Definition: Machine.hh:186
ExecutionPipelineResource::highestKnownCycle
int highestKnownCycle() const
Definition: ExecutionPipelineResource.cc:1479
ResourceManager.hh
ProgramOperation::outputIndexOfMove
int outputIndexOfMove(const MoveNode &mn) const
Definition: ProgramOperation.cc:886
ProgramOperation::inputMove
MoveNode & inputMove(int index) const
Definition: ProgramOperation.cc:621
TTAMachine::Machine
Definition: Machine.hh:73
MoveNode::guardOperation
ProgramOperation & guardOperation() const
Definition: MoveNode.cc:479
TTAMachine::ImmediateUnit
Definition: ImmediateUnit.hh:50