OpenASIP 2.2
Loading...
Searching...
No Matches
SimpleBrokerDirector.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 SimpleBrokerDirector.cc
26 *
27 * Implementation of not so simple ;) BrokerDirector 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 <string>
35#include <climits>
36#include <typeinfo>
37
38#include "Application.hh"
40#include "AssignmentPlan.hh"
41#include "Exception.hh"
42#include "MoveNode.hh"
43#include "MoveNodeSet.hh"
44#include "Instruction.hh"
45#include "ResourceBroker.hh"
46#include "BusBroker.hh"
47#include "IUBroker.hh"
48#include "ITemplateBroker.hh"
50#include "IUResource.hh"
51#include "Immediate.hh"
52#include "MapTools.hh"
54#include "AssocTools.hh"
55#include "POMDisassembler.hh"
56#include "ResourceManager.hh"
57#include "Terminal.hh"
58#include "MoveGuard.hh"
59#include "Move.hh"
60#include "Bus.hh"
61#include "Conversion.hh"
62
63//#define DEBUG_RM
64
65#ifdef DEBUG_RM
66#include <typeinfo>
67#endif
68
69using std::string;
70using namespace TTAProgram;
71
72/**
73 * Constructor.
74 *
75 * @param machine Target machine.
76 * @param plan Resource assignment plan.
77 * @param ii Initiation interval.
78 */
81 AssignmentPlan& plan,
82 unsigned int ii):
84 initiationInterval_(ii), schedulingWindow_(140),
85 busCount_(machine.busNavigator().count()) {
86 knownMaxCycle_ = -1;
87 knownMinCycle_ = INT_MAX;
88
89 if (Application::cmdLineOptions() != NULL) {
91 dynamic_cast<SchedulerCmdLineOptions*>(
93 schedulingWindow_ = options->schedulingWindowSize();
94 }
95}
96
97/**
98 * Destructor.
99 */
103
104/**
105 * Return true if given node can be assigned without resource
106 * conflicts in given cycle.
107 *
108 * For those parts of the node that have
109 * been already assigned to a resource, the manager simply keeps the
110 * assignment and verifies that the resource is available. For those
111 * parts that are not yet assigned, the resource manager looks for any
112 * compatible resource that could be assigned.
113 *
114 * @param cycle Cycle.
115 * @param node Node.
116 * @return True if given node can be assigned without resource
117 * conflicts in given cycle, false otherwise.
118 */
119bool
121 int cycle, MoveNode& node,
122 const TTAMachine::Bus* bus,
123 const TTAMachine::FunctionUnit* srcFU,
124 const TTAMachine::FunctionUnit* dstFU,
125 int immWriteCycle,
126 const TTAMachine::ImmediateUnit* immu,
127 int immRegIndex) const {
128
129#ifdef DEBUG_RM
130 std::cerr << "testing canassign, cycle: " << cycle <<
131 " node: " << node.toString() << std::endl;
132#endif
133
134 if (initiationInterval_ != 0 && cycle >= (int)(initiationInterval_ * 2)) {
135 return false;
136 }
137
138 if (node.isScheduled()) {
139 debugLogRM("isScheduled == true");
140 return false;
141 }
142
143 // fast way to reject some cases. Makes scheduling faster
144 // for bus-limited machines.
145 std::map<int,int>::const_iterator i = moveCounts_.find(cycle);
146 if (i != moveCounts_.end() && i->second >= busCount_) {
147 debugLogRM("instruction full!");
148 return false;
149 }
150
151 OriginalResources* oldRes = NULL;
152 if (node.isMove()) {
153 // Store original resources of node
154 oldRes = new OriginalResources(
155 node.move().source().copy(),
156 node.move().destination().copy(),
157 &node.move().bus(),
158 NULL,
159 false);
160 if (node.move().isUnconditional()) {
161 oldRes->isGuarded_ = false;
162 } else {
163 oldRes->isGuarded_ = true;
164 oldRes->guard_ = node.move().guard().copy();
165 }
166 }
167 int placedInCycle = -1;
168 if (node.isPlaced()) {
169 placedInCycle = node.cycle();
170 }
172 cycle, node, bus, srcFU, dstFU, immWriteCycle, immu, immRegIndex);
173
174 bool success = false;
175 while (!success) {
176#ifdef DEBUG_RM
178 << "current broker: "
179 << typeid(plan_->currentBroker()).name()
180 << std::endl;
181#endif
183 if (&plan_->currentBroker() == &plan_->firstBroker()) {
185 debugLogRM("no assignment found");
186 success = false; // no assignment found
187 break;
188 } else {
189 debugLogRM("backtracking");
190 plan_->backtrack();
191 }
192 } else if (&plan_->currentBroker() == &plan_->lastBroker()) {
194 success = true;
195 } else {
197 plan_->advance();
198 }
199 }
200 if (node.isMove()) {
201 // restore original resources of node
202 node.move().setSource(oldRes->src_);
203 oldRes->src_ = NULL;
204
205 node.move().setDestination(oldRes->dst_);
206 oldRes->dst_ = NULL;
207 node.move().setBus(*oldRes->bus_);
208 if (oldRes->isGuarded_) {
209 node.move().setGuard(oldRes->guard_);
210 oldRes->guard_ = NULL;
211 }
212 delete oldRes;
213 }
214 if (placedInCycle != -1) {
215 node.setCycle(placedInCycle);
216 }
217 return success;
218}
219
220/**
221 * Assign all resources needed by a given node starting from given
222 * cycle, and place the node in that cycle.
223 *
224 * The manager keeps any pre-existing assignment and verifies that
225 * assigned resource is available. For all unassigned parts of the
226 * node, the resource manager looks for and then assigns the necessary
227 * resources. If the node is not fully assigned after the invocation
228 * of this operation, it means the assignment attempt failed.
229 *
230 * @param cycle Cycle.
231 * @param node Node.
232 * @exception InvalidData exception if given node is already placed in a
233 * cycle different from given cycle.
234 */
235void
237 const TTAMachine::Bus* bus,
238 const TTAMachine::FunctionUnit* srcFU,
239 const TTAMachine::FunctionUnit* dstFU,
240 int immWriteCycle,
241 const TTAMachine::ImmediateUnit* immu,
242 int immRegIndex) {
243 if (cycle < 0) {
244 throw InvalidData(__FILE__, __LINE__, __func__,
245 "Negative cycles not supported by RM");
246 }
247 if (cycle == INT_MAX) {
248 throw InvalidData(__FILE__, __LINE__, __func__,
249 "INT_MAX cycle not supported by RM");
250 }
251
252 if (node.isPlaced() && node.cycle() != cycle) {
253 string msg =
254 "Node is already placed in a cycle different from given cycle.";
255 throw InvalidData(__FILE__, __LINE__, __func__, msg);
256 }
257
258 if (node.isMove()) {
260 node.move().source().copy(),
261 node.move().destination().copy(),
262 &node.move().bus(),
263 NULL,
264 false);
265 if (node.move().isUnconditional()) {
266 oldRes->isGuarded_ = false;
267 } else {
268 oldRes->isGuarded_ = true;
269 oldRes->guard_ = node.move().guard().copy();
270 }
271 origResMap_.insert(
272 std::pair<const MoveNode*, OriginalResources*>(&node, oldRes));
273 }
274
275 bool success = plan_->tryCachedAssignment(
276 node, cycle, bus, srcFU, dstFU, immWriteCycle, immu, immRegIndex);
277
278 plan_->setRequest(cycle, node, bus, srcFU, dstFU, immWriteCycle, immu, immRegIndex);
279 assert( cycle != -1 );
280
281 while (!success) {
283 if (&plan_->currentBroker() == &plan_->firstBroker()) {
284 string msg = "No resource assignment found for ";
285 msg += node.toString() + "!\n" ;
286 msg += "Instruction at cycle " + Conversion::toString(cycle);
287 msg += " is: ";
289 throw ModuleRunTimeError(__FILE__, __LINE__, __func__, msg);
290 } else {
291 plan_->backtrack();
292 }
293
294 } else {
296 if (&plan_->currentBroker() == &plan_->lastBroker()) {
297 success = true;
298 } else {
299 plan_->advance();
300 }
301 }
302 }
303 if (knownMaxCycle_ < cycle) {
304 knownMaxCycle_ = cycle;
305 }
306 int guardSlack = std::max(0, node.guardLatency() -1);
307 if (knownMinCycle_ > cycle - guardSlack) {
308 knownMinCycle_ = std::max(cycle - guardSlack,0);
309#ifdef DEBUG_RM
310 std::cerr << "Set known min cycle to" << knownMinCycle_ << std::endl;
311#endif
313 }
314 if (node.isMove()) {
315 int iwc = immediateWriteCycle(node);
316 if (node.isSourceImmediateRegister() &&
317 knownMinCycle_ > iwc && iwc >= 0) {
318 knownMinCycle_ = iwc;
319#ifdef DEBUG_RM
320 std::cerr << "Set known min cycle(2) to" << knownMinCycle_ << std::endl;
321#endif
323 }
325 }
326}
327
328/**
329 * Free all resource assignments of the given node.
330 *
331 * If the node is only partially assigned, the resource manager
332 * ignores those parts of the node that are already unassigned.
333 *
334 * @param node Node to unassign.
335 * @exception InvalidData If the given node is not placed in any
336 * cycle. Assigned but not placed nodes are not considered by the
337 * resource manager.
338 */
339void
341
342 if (!node.isPlaced()) {
343 string msg = "Node " + node.toString();
344 msg += " is not placed in any cycle.";
345 throw InvalidData(__FILE__, __LINE__, __func__, msg);
346 }
347
348 int nodeCycle = node.cycle();
349
350 bool minCycleImmSrc = false;
351 if (node.isMove()) {
352 if (node.isSourceImmediateRegister() &&
354 minCycleImmSrc = true;
355 }
356 }
357
358 moveCounts_[instructionIndex(nodeCycle)]--;
359
360 plan_->clearCache();
361 plan_->resetAssignments(node);
362
363 if (node.isMove()) {
364 if (!MapTools::containsKey(origResMap_, &node)) {
365 abortWithError("Original resources lost!");
366 }
368 origResMap_, &node);
369
370 // restore original resources of node
371 if (!node.move().source().isGPR()) {
372 node.move().setSource(oldRes->src_);
373 } else {
374 delete oldRes->src_;
375 }
376 oldRes->src_ = NULL;
377 if (!node.move().destination().isGPR()) {
378 node.move().setDestination(oldRes->dst_);
379 } else {
380 delete oldRes->dst_;
381 }
382 oldRes->dst_ = NULL;
383 node.move().setBus(*oldRes->bus_);
384 if (oldRes->isGuarded_) {
385 node.move().setGuard(oldRes->guard_);
386 oldRes->guard_ = NULL;
387 }
388 delete oldRes;
389 origResMap_.erase(&node);
390 }
391 // if unassigned move was known to be in highest cycle assigned so far
392 // tries to decrease highest cycle checking for assigned moves and
393 // immediates
394 int cycleCounter = nodeCycle;
395 if (cycleCounter == knownMaxCycle_) {
396 while(cycleCounter >= knownMinCycle_) {
397 // this may memory leak
398 Instruction* tempIns = instruction(cycleCounter);
399 if (tempIns->moveCount() == 0 && tempIns->immediateCount() == 0) {
401 cycleCounter--;
402 } else {
403 break;
404 }
405 }
407 knownMinCycle_ = INT_MAX;
408 knownMaxCycle_ = -1;
409 }
410 }
411 // if unassigned move was known to be in smallest cycle assigned so far
412 // tries to increase smallest cycle checking for assigned moves and
413 // immediates
414 int guardSlack = std::max(0, node.guardLatency() -1);
415 cycleCounter = knownMinCycle_;
416 if (cycleCounter == nodeCycle - guardSlack || minCycleImmSrc) {
417 while(cycleCounter <= knownMaxCycle_) {
418 // this may memory leak
419 Instruction* tempIns = instruction(cycleCounter);
420 if (tempIns->moveCount() == 0 && tempIns->immediateCount() == 0) {
422 cycleCounter++;
423 } else {
424 for (int i = 0; i < tempIns->moveCount(); i++) {
425 int guardSlack = std::max(0, tempIns->move(i).guardLatency() -1);
426 if (cycleCounter - guardSlack < knownMinCycle_) {
427 knownMinCycle_ = cycleCounter - guardSlack;
428#ifdef DEBUG_RM
429 std::cerr << "Set known min cycle(3) to" << knownMinCycle_ << std::endl;
430#endif
431 }
432 }
433 break;
434 }
435 }
436 }
437}
438
439/**
440 * Return the earliest cycle in the scope where all required resources
441 * can be assigned to the given node.
442 *
443 * If the node is partially assigned, the manager keeps existing
444 * assignments. This means that a client can apply arbitrary
445 * constraints to resource allocation.
446 *
447 * @param move The move.
448 * @param bus if not null, bus that has to be used.
449 * @param srcFU if not null, srcFu that has to be used.
450 * @param dstFU if not null, dstFU that has to be used.
451 * @param immWriteCycle if not -1 and src is imm, write cycle of limm.
452 * @return The earliest cycle in the scope where all required resources
453 * can be assigned to the given node. Returns -1 if assignment
454 * is not possible starting from given cycle.
455 */
456int
458 const TTAMachine::Bus* bus,
459 const TTAMachine::FunctionUnit* srcFU,
460 const TTAMachine::FunctionUnit* dstFU,
461 int immWriteCycle,
462 const TTAMachine::ImmediateUnit* immu,
463 int immRegIndex) const {
464 return earliestCycle(
465 0, move, bus, srcFU, dstFU, immWriteCycle, immu, immRegIndex);
466}
467
468/**
469 * Return the earliest cycle starting from the given cycle in which
470 * required resources can be assigned to given node.
471 *
472 * If the node is partially assigned, the manager keeps existing
473 * assignments. This means that a client can apply arbitrary
474 * constraints to resource allocation.
475 *
476 * @param cycle Cycle to start from.
477 * @param node MoveNode.
478 * @param bus if not null, bus that has to be used.
479 * @param srcFU if not null, srcFu that has to be used.
480 * @param dstFU if not null, dstFU that has to be used.
481 * @param immWriteCycle if not -1 and src is imm, write cycle of limm.
482 * @return The earliest cycle starting from the given cycle in which
483 * required resources can be assigned to given node. Returns -1 if assignment
484 * is not possible starting from given cycle.
485 */
486int
488 const TTAMachine::Bus* bus,
489 const TTAMachine::FunctionUnit* srcFU,
490 const TTAMachine::FunctionUnit* dstFU,
491 int immWriteCycle,
492 const TTAMachine::ImmediateUnit* immu,
493 int immRegIndex) const {
494
495 // limit the scheduling window.
496 // makes code for minimal.adf schedule in reasonable time
497 if (cycle < knownMaxCycle_ - schedulingWindow_) {
499 }
500 // TODO: is there need for similar test for knownMinCycle as well?
501
502 int minCycle = executionPipelineBroker().earliestCycle(
503 cycle, node, bus, srcFU, dstFU, immWriteCycle, immu, immRegIndex);
504
505 if (minCycle == -1) {
506 // No assignment possible
507 debugLogRM("No assignment possible from executionPipelineBroker");
508 return -1;
509 }
510
511 minCycle = std::max(minCycle, cycle);
512 int lastCycleToTest;
513 if (initiationInterval_ != 0) {
514 lastCycleToTest = cycle + initiationInterval_ - 2;
515 } else {
516 lastCycleToTest = largestCycle();
517 }
518
519 while (!canAssign(minCycle, node, bus, srcFU, dstFU, immWriteCycle, immu,
520 immRegIndex)) {
521 if (minCycle > lastCycleToTest + 1) {
522 // Even on empty instruction it is not possible to assign
524 "A problem with ADF, cannot schedule even on "
525 "an empty instruction.");
526 return -1;
527 }
528 // find next cycle where exec pipeline could be free,
529 // do not test every cycle with canassign.
531 minCycle + 1, node, bus, srcFU, dstFU, immWriteCycle, immu,
532 immRegIndex);
533 if (minCycle == -1) {
534 debugLogRM("No assignment possible due to executionPipelineBroker.");
535 return -1;
536 }
537 }
538 return minCycle;
539}
540
541/**
542 * Return the latest cycle in the scope where all required resources
543 * can be assigned to the given node.
544 *
545 * If the node is partially assigned, the manager keeps existing
546 * assignments. This means that a client can apply arbitrary
547 * constraints to resource allocation.
548 *
549 * @param node Node.
550 * @param bus if not null, bus that has to be used.
551 * @param srcFU if not null, srcFu that has to be used.
552 * @param dstFU if not null, dstFU that has to be used.
553 * @param immWriteCycle if not -1 and src is imm, write cycle of limm.
554 * @return The latest cycle in the scope where all required resources
555 * can be assigned to the given node. In case assignment is
556 * not possible for given arguments returns -1. Returns INT_MAX if
557 * there is no upper boundary for assignment.
558 */
559int
561 const TTAMachine::Bus* bus,
562 const TTAMachine::FunctionUnit* srcFU,
563 const TTAMachine::FunctionUnit* dstFU,
564 int immWriteCycle,
565 const TTAMachine::ImmediateUnit* immu,
566 int immRegIndex) const {
567 return latestCycle(
568 INT_MAX, node, bus, srcFU, dstFU, immWriteCycle, immu, immRegIndex);
569}
570
571/**
572 * Return the latest cycle starting from the given cycle in which
573 * required resources can be assigned to given node.
574 *
575 * If the node is partially assigned, the manager keeps existing
576 * assignments. This means that a client can apply arbitrary
577 * constraints to resource allocation.
578 *
579 * @param cycle Cycle to start from.
580 * @param node Node.
581 * @param bus if not null, bus that has to be used.
582 * @param srcFU if not null, srcFu that has to be used.
583 * @param dstFU if not null, dstFU that has to be used.
584 * @param immWriteCycle if not -1 and src is imm, write cycle of limm.
585 * @return The latest cycle starting from the given cycle in which
586 * required resources can be assigned to given node. In case assignment is
587 * not possible for given arguments returns -1. Returns INT_MAX if
588 * there is no upper boundary for assignment.
589 */
590int
592 const TTAMachine::Bus* bus,
593 const TTAMachine::FunctionUnit* srcFU,
594 const TTAMachine::FunctionUnit* dstFU,
595 int immWriteCycle,
596 const TTAMachine::ImmediateUnit* immu,
597 int immRegIndex) const {
598
599#ifdef DEBUG_RM
600 std::cerr << "\t\t\t\tLatest cycle called with cycle: " << cycle << std::endl;
601#endif
602 int maxCycle = executionPipelineBroker().latestCycle(
603 cycle, node, bus, srcFU, dstFU, immWriteCycle, immu, immRegIndex);
604#ifdef DEBUG_RM
605 std::cerr << "\t\t\t\t\tmaxCycle from exec pipeline: " << maxCycle << std::endl;
606#endif
607 if (maxCycle == -1) {
608 // Assignment not possible at all
609 return maxCycle;
610 }
611 if (maxCycle == INT_MAX || maxCycle == INT_MAX - 1) {
612 if (cycle == INT_MAX) {
613 // There is no upper limit for assignment and it was not set
614 // either
615 return cycle;
616 }
617 }
618 if (maxCycle > cycle) {
619 maxCycle = cycle;
620 }
621 int lastCycleToTest = -1;
622 lastCycleToTest =
623 std::max(knownMaxCycle_,
624 executionPipelineBroker().highestKnownCycle());
625 if (lastCycleToTest == 0) {
626 lastCycleToTest = cycle;
627 }
628#ifdef DEBUG_RM
629 std::cerr << "\t\t\t\t\tLast cycle to test: " << lastCycleToTest << std::endl;
630#endif
631 // Define earliest cycle where to finish testing. If the move can not
632 // be scheduled after this cycle, it can not be scheduled at all.
633
634 int knownMinCycle = knownMinCycle_ == INT_MAX ? cycle :
635 std::min(cycle,knownMinCycle_);
636 int earliestCycleLimit =
637 (knownMinCycle > executionPipelineBroker().longestLatency() + 1) ?
638 knownMinCycle - executionPipelineBroker().longestLatency() : 0;
639
640#ifdef DEBUG_RM
641 std::cerr << "\tknown min cycle: " << knownMinCycle << std::endl;
642 std::cerr << "\t\t\t\t\tEarlist limit: " << earliestCycleLimit << std::endl;
643#endif
644
645 if (maxCycle <= lastCycleToTest) {
646 for (int i = maxCycle; i >= earliestCycleLimit; i--) {
647 if (canAssign(i, node, bus, srcFU, dstFU, immWriteCycle, immu,
648 immRegIndex)) {
649 return i;
650 }
651 }
652 } else {
653 if (maxCycle > lastCycleToTest) {
654 if (canAssign(maxCycle, node, bus, srcFU, dstFU, immWriteCycle,
655 immu, immRegIndex)) {
656 return maxCycle;
657 }
658 }
659 for (int i = lastCycleToTest; i >= earliestCycleLimit; i--) {
660 if (canAssign(i, node, bus, srcFU, dstFU, immWriteCycle, immu,
661 immRegIndex)) {
662 return i;
663 }
664 }
665 }
666 return -1;
667}
668
669/**
670 * Return true if immediate in given node can be transported by some bus
671 * in the machine.
672 *
673 * @param node Node that contains immediate read.
674 * @return True if immediate in given node can be transported by some bus
675 * in the machine.
676 * @exception ModuleRunTimeError If required resource brokers are not found
677 * in assignment plan.
678 */
679bool
681 const MoveNode& node, const TTAMachine::Bus* preAssignedBus) const {
682 try {
683 BusBroker& broker = busBroker();
684 return broker.canTransportImmediate(node, preAssignedBus);
685 } catch (const InstanceNotFound& e) {
686 throw ModuleRunTimeError(
687 __FILE__, __LINE__, __func__, e.errorMessage());
688 }
689}
690
691 /**
692 * Return the immediate unit broker.
693 *
694 * @return The immediate unit broker.
695 * @exception InstanceNotFound If immediate unit broker is not found.
696 */
699 ResourceBroker* broker = NULL;
700 for (int i = 0; i < plan_->brokerCount(); i++) {
701 broker = &plan_->broker(i);
702 if (broker->isIUBroker()) {
703 return dynamic_cast<IUBroker&>(*broker);
704 }
705 }
706 string msg = "Immediate unit broker not found.";
707 throw InstanceNotFound(__FILE__, __LINE__, __func__, msg);
708}
709
710/**
711 * Return the instruction template broker.
712 *
713 * @return The instruction template broker.
714 * @exception InstanceNotFound If instruction template broker is not found.
715 */
718
719 ResourceBroker* broker = NULL;
720 for (int i = 0; i < plan_->brokerCount(); i++) {
721 broker = &plan_->broker(i);
722 if (broker->isITemplateBroker()) {
723 return dynamic_cast<ITemplateBroker&>(*broker);
724 }
725 }
726 string msg = "Instruction template broker not found.";
727 throw InstanceNotFound(__FILE__, __LINE__, __func__, msg);
728}
729
730/**
731 * Return the bus broker.
732 *
733 * @return The bus broker.
734 * @exception InstanceNotFound If bus broker is not found.
735 */
738 ResourceBroker* broker = NULL;
739 for (int i = 0; i < plan_->brokerCount(); i++) {
740 broker = &plan_->broker(i);
741 if (broker->isBusBroker()) {
742 return dynamic_cast<BusBroker&>(*broker);
743 }
744 }
745 string msg = "Bus broker not found.";
746 throw InstanceNotFound(__FILE__, __LINE__, __func__, msg);
747}
748
749/**
750 * Return the execution pipeline broker.
751 *
752 * @return The execution pipeline broker.
753 * @exception InstanceNotFound If execution pipeline broker is not found.
754 */
757{
758 ResourceBroker* broker = NULL;
759 for (int i = 0; i < plan_->brokerCount(); i++) {
760 broker = &plan_->broker(i);
761 if (broker->isExecutionPipelineBroker()) {
762 return dynamic_cast<ExecutionPipelineBroker&>(*broker);
763 }
764 }
765 string msg = "Execution Pipeline broker not found.";
766 throw InstanceNotFound(__FILE__, __LINE__, __func__, msg);
767}
768
769/**
770 * Constructor for embedded structure for storing the original resources
771 */
775 const TTAMachine::Bus* bus,
777 bool isGuarded) {
778
779 src_ = src;
780 dst_ = dst;
781 bus_ = bus;
782 guard_ = guard;
783 isGuarded_ = isGuarded;
784}
785
786/**
787 * Destructor for embedded structure storing original resources
788 */
790 if (src_!= NULL) {
791 delete src_;
792 }
793 if (dst_!= NULL) {
794 delete dst_;
795 }
796 if (guard_!= NULL) {
797 delete guard_;
798 }
799}
800
801/**
802 * Tests if any of a buses of machine supports guard needed
803 * by a node. Should always return true! Otherwise, scheduler generated
804 * code for different machine.
805 *
806 * @param node MoveNode to test
807 * @return true if any of buses supports guard needed by node, or if move
808 * is not conditional.
809 */
810bool
812 Move& move = const_cast<MoveNode&>(node).move();
813 if (move.isUnconditional()) {
814 return true;
815 }
816 return busBroker().hasGuard(node);
817}
818/**
819 * Returns a copy of instruction that holds a moves for given cycle
820 * and has correct template set.
821 *
822 * @param cycle Cycle for which to get instruction
823 * @return the Instruction with moves and template assigned
824 * @note This method should be called when whole scope is scheduled
825 */
830
831/**
832 * Defines if Broker Director implementation supports node with resources
833 * pre assigned by clients.
834 *
835 * @return For SimpleBrokerDirector allways false.
836 */
837bool
841
842/**
843 * Returns largest cycle known to be used by any of the resources.
844 *
845 * @return Largest cycle resource manager assigned any resource to.
846 */
847int
849 return std::max(knownMaxCycle_,
850 executionPipelineBroker().highestKnownCycle());
851}
852
853/**
854 * Returns smallest cycle known to be used by any of the resources.
855 *
856 * @return Smallest cycle resource manager assigned any resource to.
857 */
858int
860 // No need to check the execution pipeline resource here
861 // since there are no negative pipelines
862 return knownMinCycle_;
863}
864
865/**
866 * Transfer the instruction ownership away from this object.
867 *
868 * If this method is called, resource manager does not delete it's
869 * instructions when it it destroyed.
870 */
871void
875
876/**
877 * Finds the original terminal with value of immediate.
878 *
879 * @param node node with immediate register source
880 * @return terminal with immediate value
881 */
882std::shared_ptr<TTAProgram::TerminalImmediate>
886
887/**
888 * Finds cycle in which the immediate that is read by node is written.
889 *
890 * @param node with source immediate register
891 * @return cycle in which immediate is written to register
892 */
893int
897
898bool
900 int defCycle,
901 std::shared_ptr<TTAProgram::Immediate> immediate) const {
902
904 defCycle, immediate);
905}
906
907/**
908 * Clears bookkeeping which is needed for unassigning previously assigned
909 * moves. After this call these cannot be unassigned, but new moves which
910 * are assigned after this call can still be unassigned.
911 */
912void
918
919/**
920 * Return the instruction index corresponding to cycle.
921 *
922 * If modulo scheduling is not used (ie. initiation interval is 0), then
923 * index is equal to cycle.
924 *
925 * @param cycle Cycle to get instruction index.
926 * @return Return the instruction index for cycle.
927 */
928unsigned int
929SimpleBrokerDirector::instructionIndex(unsigned int cycle) const {
930
931 if (initiationInterval_ != 0) {
932 return cycle % initiationInterval_;
933 } else {
934 return cycle;
935 }
936}
937
938/**
939 * Clears the bookkeeping so that the same RM can be reused for different BB.
940 *
941 * After this call the state of the RM should be identical to a new RM.
942 */
943void
945 knownMaxCycle_ = -1;
946 knownMinCycle_ = INT_MAX;
947 moveCounts_.clear();
948 plan_->clear();
949}
950
951void
955
956void
960
961void
965
966void
967SimpleBrokerDirector::setMaxCycle(unsigned int maxCycle) {
969}
#define __func__
#define abortWithError(message)
#define assert(condition)
TTAMachine::Machine * machine
the architecture definition of the estimated processor
static MachInfoCmdLineOptions options
Definition MachInfo.cc:46
#define debugLogRM(__X)
static CmdLineOptions * cmdLineOptions()
static std::ostream & logStream()
void setRequest(int cycle, MoveNode &node, const TTAMachine::Bus *bus, const TTAMachine::FunctionUnit *srcFU, const TTAMachine::FunctionUnit *dstFU, int immWriteCycle, const TTAMachine::ImmediateUnit *immu, int immRegIndex)
bool isTestedAssignmentPossible()
ResourceBroker & lastBroker()
bool tryCachedAssignment(MoveNode &node, int cycle, const TTAMachine::Bus *bus, const TTAMachine::FunctionUnit *srcFU, const TTAMachine::FunctionUnit *dstFU, int immWriteCycle, const TTAMachine::ImmediateUnit *immu, int immRegIndex)
ResourceBroker & firstBroker()
ResourceBroker & currentBroker()
int brokerCount() const
ResourceBroker & broker(int index) const
static void deleteAllValues(ContainerType &aMap)
AssignmentPlan * plan_
Assignment plan.
void setBBN(const BasicBlockNode *bbn)
Definition BusBroker.hh:136
virtual bool canTransportImmediate(const MoveNode &node, const TTAMachine::Bus *preAssigndBus) const
Definition BusBroker.cc:756
virtual bool hasGuard(const MoveNode &node) const
Definition BusBroker.cc:868
void setCFG(const ControlFlowGraph *cfg)
Definition BusBroker.hh:135
static std::string toString(const T &source)
std::string errorMessage() const
Definition Exception.cc:123
void setDDG(const DataDependenceGraph *ddg)
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
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
virtual void setMaxCycle(unsigned int maxCycle) override
virtual bool isTemplateAvailable(int, std::shared_ptr< TTAProgram::Immediate >) const
virtual TTAProgram::Instruction * instruction(int cycle)
virtual void loseInstructionOwnership(int cycle)
virtual std::shared_ptr< TTAProgram::TerminalImmediate > immediateValue(const MoveNode &node) const
Definition IUBroker.cc:555
void clearOldResources()
Definition IUBroker.cc:598
virtual int immediateWriteCycle(const MoveNode &node) const
Definition IUBroker.cc:578
static KeyType keyForValue(const MapType &aMap, const ValueType &aValue)
static void deleteAllValues(MapType &aMap)
static bool containsKey(const MapType &aMap, const KeyType &aKey)
int cycle() const
Definition MoveNode.cc:421
bool isMove() const
int guardLatency() const
Definition MoveNode.cc:779
std::string toString() const
Definition MoveNode.cc:576
bool isPlaced() const
Definition MoveNode.cc:352
TTAProgram::Move & move()
void setCycle(const int newcycle)
Definition MoveNode.cc:503
bool isScheduled() const
Definition MoveNode.cc:409
bool isSourceImmediateRegister() const
Definition MoveNode.cc:223
static std::string disassemble(const TTAProgram::Move &move)
virtual bool isIUBroker() const
virtual bool isExecutionPipelineBroker() const
virtual bool isITemplateBroker() const
virtual bool isBusBroker() const
virtual void assign(int cycle, MoveNode &node, const TTAMachine::Bus *bus=nullptr, const TTAMachine::FunctionUnit *srcFU=nullptr, const TTAMachine::FunctionUnit *dstFU=nullptr, int immWriteCycle=-1, const TTAMachine::ImmediateUnit *immu=nullptr, int immRegIndex=-1) override
ITemplateBroker & instructionTemplateBroker() const
std::map< const MoveNode *, OriginalResources *, MoveNode::Comparator > origResMap_
virtual bool canAssign(int cycle, MoveNode &node, const TTAMachine::Bus *bus=nullptr, const TTAMachine::FunctionUnit *srcFU=nullptr, const TTAMachine::FunctionUnit *dstFU=nullptr, int immWriteCycle=-1, const TTAMachine::ImmediateUnit *immu=nullptr, int immRegIndex=-1) const override
unsigned int instructionIndex(unsigned int maxCycle) const
std::map< int, int > moveCounts_
virtual int immediateWriteCycle(const MoveNode &) const
virtual int earliestCycle(MoveNode &node, const TTAMachine::Bus *bus=nullptr, const TTAMachine::FunctionUnit *srcFU=nullptr, const TTAMachine::FunctionUnit *dstFU=nullptr, int immWriteCycle=-1, const TTAMachine::ImmediateUnit *immu=nullptr, int immRegIndex=-1) const override
virtual int smallestCycle() const override
int schedulingWindow_
the number of instructions to look back in the schedule for a free slot
IUBroker & immediateUnitBroker() const
void setBBN(const BasicBlockNode *bbn)
virtual void loseInstructionOwnership(int cycle)
void setDDG(const DataDependenceGraph *ddg)
virtual bool isTemplateAvailable(int, std::shared_ptr< TTAProgram::Immediate >) const
virtual void unassign(MoveNode &node) override
virtual bool hasGuard(const MoveNode &node) const
virtual int largestCycle() const override
void setMaxCycle(unsigned int cycle)
ExecutionPipelineBroker & executionPipelineBroker() const
virtual std::shared_ptr< TTAProgram::TerminalImmediate > immediateValue(const MoveNode &)
void setCFG(const ControlFlowGraph *cfg)
virtual int latestCycle(MoveNode &node, const TTAMachine::Bus *bus=nullptr, const TTAMachine::FunctionUnit *srcFU=nullptr, const TTAMachine::FunctionUnit *dstFU=nullptr, int immWriteCycle=-1, const TTAMachine::ImmediateUnit *immu=nullptr, int immRegIndex=-1) const override
SimpleBrokerDirector(const TTAMachine::Machine &machine, AssignmentPlan &plan, unsigned int initiationInterval_)
virtual bool canTransportImmediate(const MoveNode &node, const TTAMachine::Bus *preAssignedBus) const
virtual TTAProgram::Instruction * instruction(int cycle) const override
BusBroker & busBroker() const
virtual bool supportsExternalAssignments() const override
Move & move(int i) const
MoveGuard * copy() const
Definition MoveGuard.cc:96
void setSource(Terminal *src)
Definition Move.cc:312
MoveGuard & guard() const
Definition Move.cc:345
bool isUnconditional() const
Definition Move.cc:154
Terminal & source() const
Definition Move.cc:302
int guardLatency() const
Definition Move.cc:503
void setGuard(MoveGuard *guard)
Definition Move.cc:360
void setBus(const TTAMachine::Bus &bus)
Definition Move.cc:383
Terminal & destination() const
Definition Move.cc:323
void setDestination(Terminal *dst)
Definition Move.cc:333
const TTAMachine::Bus & bus() const
Definition Move.cc:373
virtual Terminal * copy() const =0
virtual bool isGPR() const
Definition Terminal.cc:107
OriginalResources(TTAProgram::Terminal *, TTAProgram::Terminal *, const TTAMachine::Bus *, TTAProgram::MoveGuard *, bool)