OpenASIP 2.2
Loading...
Searching...
No Matches
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"
55
56using namespace TTAMachine;
57using 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
73void
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 */
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 */
101void
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 */
117void
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 */
136int
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 */
192int
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 */
221bool
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 */
239bool
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 */
254void
256
258 for (int i = 0; i < navi.count(); i++) {
259 FunctionUnit* fu = navi.item(i);
260 ExecutionPipelineResource* epResource =
263
264 ResourceBroker::addResource(*fu, epResource);
265 fuPipelineMap_.insert(
266 pair<SchedulingResource*, const FunctionUnit*>(epResource, fu));
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 */
290void
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 {
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 */
365int
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
377bool
381
382/**
383 * Set initiation interval, if ii = 0 then initiation interval is not used.
384 *
385 * @param ii initiation interval
386 */
387void
389{
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 */
424int
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 */
537int
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 */
599int
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(
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 */
718int
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
805void
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
#define __func__
#define abortWithError(message)
#define assert(condition)
#define debugLogRM(__X)
bool hasNode(const Node &) const
EdgeSet operationInEdges(const MoveNode &node) const
std::string errorMessageStack(bool messagesOnly=false) const
Definition Exception.cc:138
const DataDependenceGraph * ddg_
ExecutionPipelineBroker(std::string, unsigned int initiationInterval=0)
virtual void buildResources(const TTAMachine::Machine &target) override
virtual void assign(int cycle, MoveNode &node, SchedulingResource &res, int immWriteCycle, int immRegIndex) override
bool isLoopBypass(const MoveNode &node) const
void setDDG(const DataDependenceGraph *ddg)
virtual void setupResourceLinks(const ResourceMapper &mapper) override
virtual void setInitiationInterval(unsigned int cycles) override
int earliestFromSource(int, const MoveNode &, const TTAMachine::FunctionUnit *srcFU) const
virtual void unassign(MoveNode &node) override
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
bool isMoveTrigger(const MoveNode &node) const
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
int latestFromDestination(int, const MoveNode &, const TTAMachine::FunctionUnit *dstFU) const
int latestFromSource(int, const MoveNode &, const TTAMachine::FunctionUnit *srcFU) const
virtual void setMaxCycle(unsigned int maxCycle) override
virtual bool isAlreadyAssigned(int cycle, const MoveNode &node, const TTAMachine::Bus *preassignedBus) const override
int earliestFromDestination(int, const MoveNode &, const TTAMachine::FunctionUnit *dstFU) const
FUPipelineMap fuPipelineMap_
FU's and their corresponding pipeline resources.
virtual bool isApplicable(const MoveNode &node, const TTAMachine::Bus *) const override
virtual bool isExecutionPipelineBroker() const override
virtual int highestKnownCycle() const
int longestLatency_
Longest latency of all operations of all the FUs.
bool resultNotOverWritten(int resultReadCycle, int resultReadyCycle, const MoveNode &node, const TTAMachine::Port &port, const MoveNode *trigger, int triggerCycle) const
int nextResultCycle(const TTAMachine::Port &port, int cycle, const MoveNode &node, const MoveNode *trigger=NULL, int triggerCycle=INT_MAX) const
static KeyType keyForValue(const MapType &aMap, const ValueType &aValue)
int earliestResultReadCycle() const
Definition MoveNode.cc:652
unsigned int destinationOperationCount() const
bool isGuardOperation() const
Definition MoveNode.cc:181
int cycle() const
Definition MoveNode.cc:421
ProgramOperation & sourceOperation() const
Definition MoveNode.cc:453
bool isDestinationOperation() const
std::string toString() const
Definition MoveNode.cc:576
ProgramOperation & guardOperation() const
Definition MoveNode.cc:479
TTAProgram::Move & move()
bool isSourceOperation() const
Definition MoveNode.cc:168
bool isScheduled() const
Definition MoveNode.cc:409
ProgramOperation & destinationOperation(unsigned int index=0) const
virtual TCEString name() const
Definition Operation.cc:93
int outputMoveCount() const
const Operation & operation() const
int outputIndexFromGuardOfMove(const MoveNode &node) const
int inputMoveCount() const
MoveNode & inputMove(int index) const
const TTAMachine::FunctionUnit * fuFromOutMove(const MoveNode &outputNode) const
MoveNode & outputMove(int index) const
int outputIndexOfMove(const MoveNode &mn) const
void addResource(const TTAMachine::MachinePart &mp, SchedulingResource *res)
SchedulingResource * resourceOf(const TTAMachine::MachinePart &mp) const
virtual void setInitiationInterval(unsigned int cycles)
void setResourceMapper(const ResourceMapper &mapper)
unsigned int initiationInterval_
ResourceMap resMap_
SchedulingResource & resourceOf(const TTAMachine::MachinePart &mp, int index=0) const
virtual void addToRelatedGroup(const int group, SchedulingResource &resource)
virtual const std::string & name() const
virtual bool isTriggering() const =0
virtual BaseFUPort * triggerPort() const
virtual HWOperation * operation(const std::string &name) const
virtual int maxLatency() const
virtual BaseFUPort * port(const std::string &name) const
virtual FUPort * port(int operand) const
ComponentType * item(int index) const
virtual FunctionUnitNavigator functionUnitNavigator() const
Definition Machine.cc:380
virtual ControlUnit * controlUnit() const
Definition Machine.cc:345
virtual Socket * outputSocket() const
Definition Port.cc:281
virtual Socket * inputSocket() const
Definition Port.cc:261
virtual int portCount() const
Definition Unit.cc:135
Terminal & source() const
Definition Move.cc:302
bool isTriggering() const
Definition Move.cc:284
Terminal & destination() const
Definition Move.cc:323
virtual const TTAMachine::FunctionUnit & functionUnit() const
Definition Terminal.cc:251
virtual int operationIndex() const
Definition Terminal.cc:364
virtual bool isFUPort() const
Definition Terminal.cc:118