OpenASIP  2.0
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"
39 #include "SimpleBrokerDirector.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 
69 using std::string;
70 using 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):
83  BrokerDirector(machine, plan),
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  */
102 }
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  */
119 bool
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  }
171  plan_->setRequest(
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  */
235 void
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()) {
259  OriginalResources* oldRes = new OriginalResources(
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
312  assert(knownMinCycle_ >= 0);
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
322  assert(knownMinCycle_ >= 0);
323  }
324  moveCounts_[instructionIndex(cycle)]++;
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  */
339 void
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  }
367  OriginalResources* oldRes = MapTools::valueForKey<OriginalResources*>(
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) {
400  knownMaxCycle_--;
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) {
421  knownMinCycle_++;
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  */
456 int
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  */
486 int
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
523  debugLogRM(
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  */
559 int
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  */
590 int
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  */
679 bool
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  */
697 IUBroker&
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  */
736 BusBroker&
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,
776  TTAProgram::MoveGuard* guard,
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  */
810 bool
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  */
828  return instructionTemplateBroker().instruction(cycle);
829 }
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  */
837 bool
839  return false;
840 }
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  */
847 int
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  */
858 int
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  */
871 void
874 }
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  */
882 std::shared_ptr<TTAProgram::TerminalImmediate>
884  return immediateUnitBroker().immediateValue(node);
885 }
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  */
893 int
896 }
897 
898 bool
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  */
912 void
917 }
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  */
928 unsigned int
929 SimpleBrokerDirector::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  */
943 void
945  knownMaxCycle_ = -1;
946  knownMinCycle_ = INT_MAX;
947  moveCounts_.clear();
948  plan_->clear();
949 }
950 
951 void
954 }
955 
956 void
958  busBroker().setCFG(cfg);
959 }
960 
961 void
963  busBroker().setBBN(bbn);
964 }
965 
966 void
967 SimpleBrokerDirector::setMaxCycle(unsigned int maxCycle) {
969 }
ITemplateBroker::isTemplateAvailable
virtual bool isTemplateAvailable(int, std::shared_ptr< TTAProgram::Immediate >) const
Definition: ITemplateBroker.cc:948
TTAProgram
Definition: Estimator.hh:65
SimpleBrokerDirector::OriginalResources::isGuarded_
bool isGuarded_
Definition: SimpleBrokerDirector.hh:162
SimpleBrokerDirector::OriginalResources::~OriginalResources
~OriginalResources()
Definition: SimpleBrokerDirector.cc:789
IUBroker::clearOldResources
void clearOldResources()
Definition: IUBroker.cc:598
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
AssignmentPlan::tryCachedAssignment
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)
Definition: AssignmentPlan.cc:310
SimpleBrokerDirector::busBroker
BusBroker & busBroker() const
Definition: SimpleBrokerDirector.cc:737
SimpleBrokerDirector::latestCycle
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
Definition: SimpleBrokerDirector.cc:560
SimpleBrokerDirector::clear
void clear()
Definition: SimpleBrokerDirector.cc:944
MoveNode::toString
std::string toString() const
Definition: MoveNode.cc:576
TTAProgram::Instruction::move
Move & move(int i) const
Definition: Instruction.cc:193
SimpleBrokerDirector::SimpleBrokerDirector
SimpleBrokerDirector(const TTAMachine::Machine &machine, AssignmentPlan &plan, unsigned int initiationInterval_)
Definition: SimpleBrokerDirector.cc:79
TTAProgram::Move::guardLatency
int guardLatency() const
Definition: Move.cc:503
machine
TTAMachine::Machine * machine
the architecture definition of the estimated processor
Definition: EstimatorCmdLineUI.cc:59
SimpleBrokerDirector::unassign
virtual void unassign(MoveNode &node) override
Definition: SimpleBrokerDirector.cc:340
Exception.hh
SimpleBrokerDirector::smallestCycle
virtual int smallestCycle() const override
Definition: SimpleBrokerDirector.cc:859
SimpleBrokerDirector::isTemplateAvailable
virtual bool isTemplateAvailable(int, std::shared_ptr< TTAProgram::Immediate >) const
Definition: SimpleBrokerDirector.cc:899
SimpleBrokerDirector::clearOldResources
void clearOldResources()
Definition: SimpleBrokerDirector.cc:913
SimpleBrokerDirector::hasGuard
virtual bool hasGuard(const MoveNode &node) const
Definition: SimpleBrokerDirector.cc:811
SimpleBrokerDirector::initiationInterval_
unsigned int initiationInterval_
Definition: SimpleBrokerDirector.hh:173
TTAProgram::Instruction
Definition: Instruction.hh:57
TTAProgram::Move::isUnconditional
bool isUnconditional() const
Definition: Move.cc:154
MapTools.hh
TTAMachine::Bus
Definition: Bus.hh:53
SimpleBrokerDirector::canAssign
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
Definition: SimpleBrokerDirector.cc:120
TTAProgram::Move::destination
Terminal & destination() const
Definition: Move.cc:323
BrokerDirector::plan_
AssignmentPlan * plan_
Assignment plan.
Definition: BrokerDirector.hh:49
SimpleBrokerDirector::assign
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
Definition: SimpleBrokerDirector.cc:236
ResourceBroker
Definition: ResourceBroker.hh:61
MapTools::deleteAllValues
static void deleteAllValues(MapType &aMap)
TTAProgram::Move::bus
const TTAMachine::Bus & bus() const
Definition: Move.cc:373
IUBroker.hh
TTAProgram::Move::setGuard
void setGuard(MoveGuard *guard)
Definition: Move.cc:360
MoveNode
Definition: MoveNode.hh:65
SimpleBrokerDirector::canTransportImmediate
virtual bool canTransportImmediate(const MoveNode &node, const TTAMachine::Bus *preAssignedBus) const
Definition: SimpleBrokerDirector.cc:680
SimpleBrokerDirector::loseInstructionOwnership
virtual void loseInstructionOwnership(int cycle)
Definition: SimpleBrokerDirector.cc:872
ITemplateBroker
Definition: ITemplateBroker.hh:65
Terminal.hh
Application::logStream
static std::ostream & logStream()
Definition: Application.cc:155
SimpleBrokerDirector::OriginalResources
Definition: SimpleBrokerDirector.hh:149
AssignmentPlan::setRequest
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)
Definition: AssignmentPlan.cc:81
SimpleBrokerDirector::schedulingWindow_
int schedulingWindow_
the number of instructions to look back in the schedule for a free slot
Definition: SimpleBrokerDirector.hh:177
SchedulerCmdLineOptions
Definition: SchedulerCmdLineOptions.hh:45
Conversion::toString
static std::string toString(const T &source)
BusBroker::hasGuard
virtual bool hasGuard(const MoveNode &node) const
Definition: BusBroker.cc:868
SimpleBrokerDirector::instructionTemplateBroker
ITemplateBroker & instructionTemplateBroker() const
Definition: SimpleBrokerDirector.cc:717
SchedulerCmdLineOptions.hh
SimpleBrokerDirector::~SimpleBrokerDirector
virtual ~SimpleBrokerDirector()
Definition: SimpleBrokerDirector.cc:100
AssignmentPlan::lastBroker
ResourceBroker & lastBroker()
Definition: AssignmentPlan.cc:164
SimpleBrokerDirector::busCount_
int busCount_
Definition: SimpleBrokerDirector.hh:181
MoveNode::isSourceImmediateRegister
bool isSourceImmediateRegister() const
Definition: MoveNode.cc:223
POMDisassembler.hh
debugLogRM
#define debugLogRM(__X)
Definition: ResourceManager.hh:123
MoveNode::isPlaced
bool isPlaced() const
Definition: MoveNode.cc:352
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
BusBroker
Definition: BusBroker.hh:60
ITemplateBroker::loseInstructionOwnership
virtual void loseInstructionOwnership(int cycle)
Definition: ITemplateBroker.cc:908
SimpleBrokerDirector::OriginalResources::OriginalResources
OriginalResources(TTAProgram::Terminal *, TTAProgram::Terminal *, const TTAMachine::Bus *, TTAProgram::MoveGuard *, bool)
Definition: SimpleBrokerDirector.cc:772
MoveNode::isMove
bool isMove() const
TTAProgram::Move::setDestination
void setDestination(Terminal *dst)
Definition: Move.cc:333
AssignmentPlan::isTestedAssignmentPossible
bool isTestedAssignmentPossible()
Definition: AssignmentPlan.cc:263
AssignmentPlan::firstBroker
ResourceBroker & firstBroker()
Definition: AssignmentPlan.cc:130
abortWithError
#define abortWithError(message)
Definition: Application.hh:72
SimpleBrokerDirector::moveCounts_
std::map< int, int > moveCounts_
Definition: SimpleBrokerDirector.hh:180
MoveNode::cycle
int cycle() const
Definition: MoveNode.cc:421
MoveNode::guardLatency
int guardLatency() const
Definition: MoveNode.cc:779
ExecutionPipelineBroker.hh
ExecutionPipelineBroker::longestLatency
virtual int longestLatency() const
Definition: ExecutionPipelineBroker.hh:88
InvalidData
Definition: Exception.hh:149
Instruction.hh
SimpleBrokerDirector.hh
IUResource.hh
BusBroker.hh
SimpleBrokerDirector::OriginalResources::dst_
TTAProgram::Terminal * dst_
Definition: SimpleBrokerDirector.hh:159
SimpleBrokerDirector::earliestCycle
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
Definition: SimpleBrokerDirector.cc:457
SimpleBrokerDirector::setBBN
void setBBN(const BasicBlockNode *bbn)
Definition: SimpleBrokerDirector.cc:962
Conversion.hh
BusBroker::setBBN
void setBBN(const BasicBlockNode *bbn)
Definition: BusBroker.hh:136
SimpleBrokerDirector::largestCycle
virtual int largestCycle() const override
Definition: SimpleBrokerDirector.cc:848
Application.hh
SimpleBrokerDirector::executionPipelineBroker
ExecutionPipelineBroker & executionPipelineBroker() const
Definition: SimpleBrokerDirector.cc:756
TTAProgram::Move::guard
MoveGuard & guard() const
Definition: Move.cc:345
Application::cmdLineOptions
static CmdLineOptions * cmdLineOptions()
Definition: Application.cc:397
__func__
#define __func__
Definition: Application.hh:67
BasicBlockNode
Definition: BasicBlockNode.hh:64
AssignmentPlan::currentBroker
ResourceBroker & currentBroker()
Definition: AssignmentPlan.cc:179
AssignmentPlan::clearCache
void clearCache()
Definition: AssignmentPlan.cc:464
TTAProgram::Terminal::isGPR
virtual bool isGPR() const
Definition: Terminal.cc:107
SimpleBrokerDirector::OriginalResources::guard_
TTAProgram::MoveGuard * guard_
Definition: SimpleBrokerDirector.hh:161
SimpleBrokerDirector::setCFG
void setCFG(const ControlFlowGraph *cfg)
Definition: SimpleBrokerDirector.cc:957
SimpleBrokerDirector::OriginalResources::bus_
const TTAMachine::Bus * bus_
Definition: SimpleBrokerDirector.hh:160
AssignmentPlan::backtrack
void backtrack()
Definition: AssignmentPlan.cc:211
SimpleBrokerDirector::setDDG
void setDDG(const DataDependenceGraph *ddg)
Definition: SimpleBrokerDirector.cc:952
ResourceBroker::isITemplateBroker
virtual bool isITemplateBroker() const
Definition: ResourceBroker.cc:308
SimpleBrokerDirector::immediateValue
virtual std::shared_ptr< TTAProgram::TerminalImmediate > immediateValue(const MoveNode &)
Definition: SimpleBrokerDirector.cc:883
TTAProgram::Move
Definition: Move.hh:55
AssignmentPlan.hh
ModuleRunTimeError
Definition: Exception.hh:1043
AssignmentPlan::resetAssignments
void resetAssignments()
Definition: AssignmentPlan.cc:384
Bus.hh
SimpleBrokerDirector::instructionIndex
unsigned int instructionIndex(unsigned int maxCycle) const
Definition: SimpleBrokerDirector.cc:929
AssignmentPlan::broker
ResourceBroker & broker(int index) const
Definition: AssignmentPlan.cc:436
AssignmentPlan::advance
void advance()
Definition: AssignmentPlan.cc:191
SimpleBrokerDirector::OriginalResources::src_
TTAProgram::Terminal * src_
Definition: SimpleBrokerDirector.hh:158
Exception::errorMessage
std::string errorMessage() const
Definition: Exception.cc:123
SimpleBrokerDirector::immediateWriteCycle
virtual int immediateWriteCycle(const MoveNode &) const
Definition: SimpleBrokerDirector.cc:894
ResourceBroker::isExecutionPipelineBroker
virtual bool isExecutionPipelineBroker() const
Definition: ResourceBroker.cc:318
SimpleBrokerDirector::immediateUnitBroker
IUBroker & immediateUnitBroker() const
Definition: SimpleBrokerDirector.cc:698
options
static MachInfoCmdLineOptions options
Definition: MachInfo.cc:46
ResourceBroker::isIUBroker
virtual bool isIUBroker() const
Definition: ResourceBroker.cc:313
ResourceBroker.hh
MoveNode::move
TTAProgram::Move & move()
MoveNode::setCycle
void setCycle(const int newcycle)
Definition: MoveNode.cc:503
MapTools::containsKey
static bool containsKey(const MapType &aMap, const KeyType &aKey)
POMDisassembler::disassemble
static std::string disassemble(const TTAProgram::Move &move)
Definition: POMDisassembler.cc:629
Immediate.hh
AssignmentPlan::tryNextAssignment
void tryNextAssignment()
Definition: AssignmentPlan.cc:237
AssignmentPlan
Definition: AssignmentPlan.hh:56
ITemplateBroker::instruction
virtual TTAProgram::Instruction * instruction(int cycle)
Definition: ITemplateBroker.cc:693
MoveNodeSet.hh
AssocTools.hh
SimpleBrokerDirector::instruction
virtual TTAProgram::Instruction * instruction(int cycle) const override
Definition: SimpleBrokerDirector.cc:827
BusBroker::canTransportImmediate
virtual bool canTransportImmediate(const MoveNode &node, const TTAMachine::Bus *preAssigndBus) const
Definition: BusBroker.cc:756
ITemplateBroker.hh
TTAProgram::Instruction::immediateCount
int immediateCount() const
Definition: Instruction.cc:267
DataDependenceGraph
Definition: DataDependenceGraph.hh:67
TTAProgram::Terminal::copy
virtual Terminal * copy() const =0
AssignmentPlan::brokerCount
int brokerCount() const
Definition: AssignmentPlan.cc:424
IUBroker::immediateValue
virtual std::shared_ptr< TTAProgram::TerminalImmediate > immediateValue(const MoveNode &node) const
Definition: IUBroker.cc:555
TTAProgram::Terminal
Definition: Terminal.hh:60
MoveNode::isScheduled
bool isScheduled() const
Definition: MoveNode.cc:409
SimpleBrokerDirector::supportsExternalAssignments
virtual bool supportsExternalAssignments() const override
Definition: SimpleBrokerDirector.cc:838
BusBroker::setCFG
void setCFG(const ControlFlowGraph *cfg)
Definition: BusBroker.hh:135
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
BrokerDirector
Definition: BrokerDirector.hh:42
TTAProgram::MoveGuard::copy
MoveGuard * copy() const
Definition: MoveGuard.cc:96
AssignmentPlan::clear
void clear()
Definition: AssignmentPlan.cc:446
SimpleBrokerDirector::origResMap_
std::map< const MoveNode *, OriginalResources *, MoveNode::Comparator > origResMap_
Definition: SimpleBrokerDirector.hh:170
ITemplateBroker::clearOldResources
void clearOldResources()
Definition: ITemplateBroker.cc:966
Move.hh
MoveNode.hh
SimpleBrokerDirector::knownMinCycle_
int knownMinCycle_
Definition: SimpleBrokerDirector.hh:172
TTAProgram::MoveGuard
Definition: MoveGuard.hh:47
TTAProgram::Move::setBus
void setBus(const TTAMachine::Bus &bus)
Definition: Move.cc:383
AssocTools::deleteAllValues
static void deleteAllValues(ContainerType &aMap)
SimpleBrokerDirector::knownMaxCycle_
int knownMaxCycle_
Definition: SimpleBrokerDirector.hh:171
ResourceManager.hh
ExecutionPipelineBroker
Definition: ExecutionPipelineBroker.hh:53
IUBroker::immediateWriteCycle
virtual int immediateWriteCycle(const MoveNode &node) const
Definition: IUBroker.cc:578
TTAProgram::Instruction::moveCount
int moveCount() const
Definition: Instruction.cc:176
IUBroker
Definition: IUBroker.hh:57
ResourceBroker::isBusBroker
virtual bool isBusBroker() const
Definition: ResourceBroker.cc:303
InstanceNotFound
Definition: Exception.hh:304
ControlFlowGraph
Definition: ControlFlowGraph.hh:100
TTAProgram::Move::setSource
void setSource(Terminal *src)
Definition: Move.cc:312
TTAMachine::Machine
Definition: Machine.hh:73
MoveGuard.hh
SimpleBrokerDirector::setMaxCycle
void setMaxCycle(unsigned int cycle)
Definition: SimpleBrokerDirector.cc:967
TTAMachine::ImmediateUnit
Definition: ImmediateUnit.hh:50