OpenASIP  2.0
AssignmentPlan.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 AssignmentPlan.cc
26  *
27  * Implementation of AssignmentPlan class.
28  *
29  * @author Ari Mets�halme 2006 (ari.metsahalme-no.spam-tut.fi)
30  * @note rating: red
31  */
32 
33 #include <string>
34 
35 #include "TCEString.hh"
36 #include "Application.hh"
37 #include "AssignmentPlan.hh"
38 #include "PendingAssignment.hh"
39 #include "AssocTools.hh"
40 #include "ResourceBroker.hh"
41 #include "MoveNode.hh"
42 #include "ResourceManager.hh"
43 #include "Move.hh"
44 
45 using std::string;
46 
47 /**
48  * Constructor.
49  */
51  node_(NULL), cycle_(0), currentBroker_(0), resourceFound_(false),
52  lastTriedNode_(NULL), lastTriedCycle_(-1) {
53 }
54 
55 /**
56  * Destructor.
57  */
60 }
61 
62 /**
63  * Insert a resource broker in the sequence of brokers.
64  *
65  * @param broker Resource broker to be inserted.
66  */
67 void
69  assignments_.push_back(new PendingAssignment(broker));
70  brokers_.push_back(&broker);
71 }
72 
73 /**
74  * Record the input node to which resources have to be assigned or allocated
75  * and the cycle in which the node should be placed.
76  *
77  * @param node The node of current assignment request.
78  * @param cycle The cycle in which the node should be placed.
79  */
80 void
82  const TTAMachine::Bus* bus,
83  const TTAMachine::FunctionUnit* srcFU,
84  const TTAMachine::FunctionUnit* dstFU,
85  int immWriteCycle,
86  const TTAMachine::ImmediateUnit* immu,
87  int immRegIndex) {
88 
89  if (node.isPlaced() && node.cycle() != cycle) {
90  TCEString msg = "Node: " + node.toString();
91  msg << "already placed on different cycle, cur cycle: " << cycle;
92  throw ModuleRunTimeError(__FILE__, __LINE__, __func__, msg);
93  }
94 
95  bus_ = bus;
96  srcFU_ = srcFU;
97  dstFU_ = dstFU;
98  immWriteCycle_ = immWriteCycle;
99  immu_ = immu;
100  immRegIndex_ = immRegIndex;
101 
102  currentBroker_ = 0;
103  node.setCycle(cycle);
104 
105  cycle_ = cycle;
106  node_ = &node;
107 
108  // optimise broker sequence by disabling not applicable brokers
109  applicableAssignments_.clear();
110  for (unsigned int i = 0; i < assignments_.size(); i++) {
111  if (assignments_[i]->broker().isApplicable(node, bus)) {
112  assignments_[i]->setRequest(
113  cycle, node, bus_, srcFU_, dstFU_, immWriteCycle_, immu_,
114  immRegIndex_);
115  applicableAssignments_.push_back(assignments_[i]);
116  }
117  }
118  if (applicableAssignments_.empty()) {
119  string msg = "No applicable brokers found for assignment!";
120  throw ModuleRunTimeError(__FILE__, __LINE__, __func__, msg);
121  }
122 }
123 
124 /**
125  * Return the first broker to be evaluated during an assignment process.
126  *
127  * @return The first broker to be evaluated during an assignment process.
128  */
131  if (applicableAssignments_.empty()) {
132  string msg = "No applicable brokers found for assignment!";
133  throw ModuleRunTimeError(__FILE__, __LINE__, __func__, msg);
134  }
135  return applicableAssignments_[0]->broker();
136 }
137 
140 
141  if (applicableAssignments_.empty()) {
142  string msg = "No applicable brokers found for assignment!";
143  throw ModuleRunTimeError(__FILE__, __LINE__, __func__, msg);
144  }
145 
146  unsigned int i = 0;
147  while (i < applicableAssignments_.size() - 1) {
148  if (&applicableAssignments_[i]->broker() == &pos) {
149  return applicableAssignments_[++i]->broker();
150  }
151  i++;
152  }
153 
154  string msg = "Given broker not found!";
155  throw ModuleRunTimeError(__FILE__, __LINE__, __func__, msg);
156 }
157 
158 /**
159  * Return the last broker to be evaluated during an assignment process.
160  *
161  * @return The last broker to be evaluated during an assignment process.
162  */
165  if (applicableAssignments_.empty()) {
166  string msg = "No applicable brokers found for assignment!";
167  throw ModuleRunTimeError(__FILE__, __LINE__, __func__, msg);
168  }
169  return applicableAssignments_[applicableAssignments_.size() - 1]->broker();
170 }
171 
172 /**
173  * Return the current broker, that is, the broker whose resources are
174  * being evaluated during an assignment process.
175  *
176  * @return The current broker.
177  */
180  if (applicableAssignments_.empty()) {
181  string msg = "No applicable brokers found for assignment!";
182  throw ModuleRunTimeError(__FILE__, __LINE__, __func__, msg);
183  }
184  return applicableAssignments_[currentBroker_]->broker();
185 }
186 
187 /**
188  * Move to the next resource broker in the sequence.
189  */
190 void
192  if (resourceFound_) {
193  currentBroker_++;
194  } else {
195  string msg = "Tried to advance before a valid assignment was made!";
196  throw ModuleRunTimeError(__FILE__, __LINE__, __func__, msg);
197  }
198  if (currentBroker_ >= static_cast<int>(applicableAssignments_.size())) {
199  string msg = "Advanced beyond last resource broker!";
200  throw ModuleRunTimeError(__FILE__, __LINE__, __func__, msg);
201  }
202 }
203 
204 /**
205  * Unassign (if needed) the resource of current broker from the node
206  * and then move to previous resource broker in the sequence.
207  *
208  * The pending assignments of the current node are forgotten.
209  */
210 void
212  // forget assignment history and assignments for current broker
214  assignment->forget();
215  if (assignment->broker().isAlreadyAssigned(cycle_, *node_, bus_)) {
216  assignment->undoAssignment();
217  }
218  currentBroker_--;
219  if (currentBroker_ < 0) {
220  string msg = "Backtracked beyond first resource broker!";
221  throw ModuleRunTimeError(__FILE__, __LINE__, __func__, msg);
222  } else {
223  // undo possible assignments for broker we backtracked to
225  if (assignment->broker().isAlreadyAssigned(cycle_, *node_, bus_)) {
226  assignment->undoAssignment();
227  }
228  }
229 }
230 
231 /**
232  * Unassign (if needed) the resource of current broker from the node
233  * and then assign the next resource from the same list of pending
234  * assignments.
235  */
236 void
239  if (assignment->broker().isAlreadyAssigned(cycle_, *node_, bus_)) {
240  assignment->undoAssignment();
241  }
242  assignment->tryNext();
243  resourceFound_ = true;
244 }
245 
246 /**
247  * Return true if at least one tentative assignment is possible with
248  * the current broker and the tentative assignments currently applied
249  * from the preceding resource brokers.
250  *
251  * There are two reasons why no possible assignments are left with the
252  * current broker: because all pending assignments have been tried, or
253  * because no valid assignment at all is possible.
254  *
255  * If the assignment being tested was last of the assignments in the plan
256  * (which means move can be assigned completely) stores the information
257  * about used resources into the last working assignment cache.
258  *
259  * @return True if at least one tentative assignment is possible with
260  * the current broker
261  */
262 bool
264  bool possible =
265  applicableAssignments_[currentBroker_]->isAssignmentPossible();
266  if (possible) {
267  // is this the last broker?
268  if (currentBroker_ == (int)(applicableAssignments_.size())-1) {
269  // add this to the cache.
270  // first clear the cache.
272  // then set the cache for this assignment.
275  for (unsigned int i = 0; i < applicableAssignments_.size()-1;
276  i++) {
279  std::pair<ResourceBroker*, SchedulingResource*>(
280  &pa.broker(),
281  &pa.resource(pa.lastTriedAssignment())));
282  }
283  // Last one need to be handled separately because
284  // tryNext has not increased lastTriedAssignment.
285  if (!applicableAssignments_.empty()) {
287  applicableAssignments_.size()-1];
289  std::pair<ResourceBroker*, SchedulingResource*>(
290  &pa.broker(),
291  &pa.resource(pa.lastTriedAssignment()+1)));
292  }
293  }
294  } else {
295  debugLogRM("No applicable assignments at all:");
296  debugLogRM(currentBroker().brokerName());
297  }
298  return possible;
299 }
300 
301 /**
302  * Tries to assign with same resources that which previous canassign
303  * succeeded.
304  *
305  * If cannot assign with these resources, clear the information of previous
306  * successfull canassign and return false.
307  * If succeeds, the node is assigned.
308  */
309 bool
311  const TTAMachine::Bus* bus,
312  const TTAMachine::FunctionUnit* srcFU,
313  const TTAMachine::FunctionUnit* dstFU,
314  int immWriteCycle,
315  const TTAMachine::ImmediateUnit* immu,
316  int immRegIndex) {
317  // is the cache valid for this node?
318  if (lastTriedNode_ != &node ||
319  lastTriedCycle_ != cycle ||
320  immRegIndex_ != immRegIndex ||
321  immu != immu_ ||
322  immWriteCycle_ != immWriteCycle ||
323  srcFU_ != srcFU ||
324  dstFU_ != dstFU ||
326  clearCache();
327  return false;
328  }
329 
330  // test that same brokers are applicable for both cached and current.
331  // may change in case of bypassing.
332  for (size_t j = 0, i = 0; j < brokers_.size(); j++) {
334  if (broker->isApplicable(node, bus)) {
335  if (i >= lastTestedWorkingAssignment_.size() ||
336  lastTestedWorkingAssignment_[i].first != broker) {
337  clearCache();
338  return false;
339  }
340  i++;
341  } else {
342  // if not applicable, must not found in the cached brokers.
343  if (i < lastTestedWorkingAssignment_.size() &&
344  lastTestedWorkingAssignment_[i].first == broker) {
345  clearCache();
346  return false;
347  }
348  }
349  }
350  node.setCycle(cycle);
351 
352  for (int i = 0; i < (int)lastTestedWorkingAssignment_.size(); i++) {
353  std::pair<ResourceBroker*, SchedulingResource*>& ca =
355  if (!ca.first->isAvailable(
356  *ca.second, node, cycle, bus, srcFU, dstFU, immWriteCycle,
357  immu, immRegIndex)) {
358  // failed. backtrack all previous brokers.
359  // unassign, clear cache and return false.
360  for (i--; i >= 0; i--) {
361  std::pair<ResourceBroker*, SchedulingResource*>& ca =
363  ca.first->unassign(node);
364  }
365  node.unsetCycle();
366  clearCache();
367  return false;
368  } else {
369  // can assign. do the assign.
370  ca.first->assign(cycle, node, *ca.second, immWriteCycle, immRegIndex);
371  }
372  }
373  // everything succeeded. clear cache(state of rm changed) and return true.
374  clearCache();
375  return true;
376 }
377 
378 /**
379  * Unassign as needed all the resources tentatively assigned by all brokers.
380  *
381  * Reset the current broker position to the first one.
382  */
383 void
385  for (unsigned int i = 0; i < applicableAssignments_.size(); i++) {
386  applicableAssignments_[i]->forget();
387  }
388  currentBroker_ = 0;
389  node_->unsetCycle();
390  bus_ = NULL;
391 }
392 
393 /**
394  * Unassign as needed all the resources tentatively assigned to the
395  * given node.
396  *
397  * Given node needs to be placed on a cycle.
398  *
399  * @param node Node to unassign.
400  * @exception InvalidData If node is not placed on a cycle.
401  */
402 void
404  if (!node.isPlaced()) {
405  string msg = "Node is not placed in a cycle.";
406  throw InvalidData(__FILE__, __LINE__, __func__, msg);
407  }
408  bus_ = &node.move().bus();
409  for (unsigned int i = 0; i < brokers_.size(); i++) {
410  if (brokers_[i]->isApplicable(node, bus_)) {
411  brokers_[i]->unassign(node);
412  }
413  }
414  node.unsetCycle();
415  bus_ = NULL;
416 }
417 
418 /**
419  * Return the number of brokers in assignment plan.
420  *
421  * @return The number of brokers in assignment plan.
422  */
423 int
425  return brokers_.size();
426 }
427 
428 /**
429  * Return the broker in the given index.
430  *
431  * @param index Index of broker.
432  * @return The broker in the given index.
433  * @exception OutOfRange if index is out of bounds.
434  */
436 AssignmentPlan::broker(int index) const {
437  if (index < 0 || index >= static_cast<int>(brokers_.size())) {
438  string msg = "Broker index out of range.";
439  throw OutOfRange(__FILE__, __LINE__, __func__, msg);
440  } else {
441  return *brokers_[index];
442  }
443 }
444 
445 void
447  node_= NULL;
448  cycle_ = 0;
449  currentBroker_ = 0;
450  resourceFound_ = false;
451  for (size_t i = 0; i < assignments_.size(); i++) {
452  assignments_[i]->clear();
453  }
454  bus_ = NULL;
455  srcFU_ = NULL;
456  dstFU_ = NULL;
457  immWriteCycle_ = -1;
458  immu_ = NULL;
459  immRegIndex_ = -1;
460  clearCache();
461  applicableAssignments_.clear();
462 }
463 
466  lastTriedCycle_ = -1;
467  lastTriedNode_ = NULL;
468 }
ResourceBroker::isAlreadyAssigned
virtual bool isAlreadyAssigned(int cycle, const MoveNode &node, const TTAMachine::Bus *preassignedBus) const =0
AssignmentPlan::srcFU_
const TTAMachine::FunctionUnit * srcFU_
Definition: AssignmentPlan.hh:95
PendingAssignment::forget
void forget()
Definition: PendingAssignment.cc:164
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
MoveNode::toString
std::string toString() const
Definition: MoveNode.cc:576
AssignmentPlan::dstFU_
const TTAMachine::FunctionUnit * dstFU_
Definition: AssignmentPlan.hh:96
AssignmentPlan::~AssignmentPlan
virtual ~AssignmentPlan()
Definition: AssignmentPlan.cc:58
OutOfRange
Definition: Exception.hh:320
TTAMachine::Bus
Definition: Bus.hh:53
AssignmentPlan::AssignmentPlan
AssignmentPlan()
Definition: AssignmentPlan.cc:50
ResourceBroker
Definition: ResourceBroker.hh:61
AssignmentPlan::currentBroker_
int currentBroker_
Current broker.
Definition: AssignmentPlan.hh:112
TTAProgram::Move::bus
const TTAMachine::Bus & bus() const
Definition: Move.cc:373
AssignmentPlan::lastTestedWorkingAssignment_
std::vector< std::pair< ResourceBroker *, SchedulingResource * > > lastTestedWorkingAssignment_
cache.
Definition: AssignmentPlan.hh:118
MoveNode
Definition: MoveNode.hh:65
ResourceBroker::isApplicable
virtual bool isApplicable(const MoveNode &node, const TTAMachine::Bus *preassignedBus) const =0
PendingAssignment::broker
ResourceBroker & broker()
Definition: PendingAssignment.cc:61
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
MoveNode::unsetCycle
void unsetCycle()
Definition: MoveNode.cc:519
AssignmentPlan::immRegIndex_
int immRegIndex_
Definition: AssignmentPlan.hh:99
AssignmentPlan::lastBroker
ResourceBroker & lastBroker()
Definition: AssignmentPlan.cc:164
debugLogRM
#define debugLogRM(__X)
Definition: ResourceManager.hh:123
MoveNode::isPlaced
bool isPlaced() const
Definition: MoveNode.cc:352
TCEString.hh
AssignmentPlan::insertBroker
void insertBroker(ResourceBroker &broker)
Definition: AssignmentPlan.cc:68
TTAMachine::FunctionUnit
Definition: FunctionUnit.hh:55
AssignmentPlan::immu_
const TTAMachine::ImmediateUnit * immu_
Definition: AssignmentPlan.hh:98
AssignmentPlan::isTestedAssignmentPossible
bool isTestedAssignmentPossible()
Definition: AssignmentPlan.cc:263
AssignmentPlan::firstBroker
ResourceBroker & firstBroker()
Definition: AssignmentPlan.cc:130
MoveNode::cycle
int cycle() const
Definition: MoveNode.cc:421
AssignmentPlan::node_
MoveNode * node_
Move of current resource assignment request.
Definition: AssignmentPlan.hh:108
InvalidData
Definition: Exception.hh:149
AssignmentPlan::applicableAssignments_
std::vector< PendingAssignment * > applicableAssignments_
Sequence of applicable pending assignments.
Definition: AssignmentPlan.hh:104
AssocTools::deleteAllItems
static void deleteAllItems(ContainerType &aMap)
Application.hh
__func__
#define __func__
Definition: Application.hh:67
PendingAssignment::resource
SchedulingResource & resource(int index)
Definition: PendingAssignment.hh:66
AssignmentPlan::currentBroker
ResourceBroker & currentBroker()
Definition: AssignmentPlan.cc:179
AssignmentPlan::clearCache
void clearCache()
Definition: AssignmentPlan.cc:464
AssignmentPlan::backtrack
void backtrack()
Definition: AssignmentPlan.cc:211
AssignmentPlan.hh
ModuleRunTimeError
Definition: Exception.hh:1043
AssignmentPlan::resetAssignments
void resetAssignments()
Definition: AssignmentPlan.cc:384
AssignmentPlan::broker
ResourceBroker & broker(int index) const
Definition: AssignmentPlan.cc:436
AssignmentPlan::assignments_
std::vector< PendingAssignment * > assignments_
Sequence of pending assignments.
Definition: AssignmentPlan.hh:102
AssignmentPlan::advance
void advance()
Definition: AssignmentPlan.cc:191
PendingAssignment::lastTriedAssignment
int lastTriedAssignment() const
Definition: PendingAssignment.hh:68
AssignmentPlan::immWriteCycle_
int immWriteCycle_
Definition: AssignmentPlan.hh:97
AssignmentPlan::nextBroker
ResourceBroker & nextBroker(ResourceBroker &pos)
Definition: AssignmentPlan.cc:139
ResourceBroker.hh
PendingAssignment::tryNext
void tryNext()
Definition: PendingAssignment.cc:119
MoveNode::move
TTAProgram::Move & move()
MoveNode::setCycle
void setCycle(const int newcycle)
Definition: MoveNode.cc:503
AssignmentPlan::lastTriedNode_
MoveNode * lastTriedNode_
Definition: AssignmentPlan.hh:119
PendingAssignment
Definition: PendingAssignment.hh:48
AssignmentPlan::lastTriedCycle_
int lastTriedCycle_
Definition: AssignmentPlan.hh:120
AssignmentPlan::tryNextAssignment
void tryNextAssignment()
Definition: AssignmentPlan.cc:237
false
find Finds info of the inner loops in the false
Definition: InnerLoopFinder.cc:81
AssocTools.hh
TCEString
Definition: TCEString.hh:53
AssignmentPlan::brokers_
std::vector< ResourceBroker * > brokers_
Sequence of resource brokers.
Definition: AssignmentPlan.hh:106
AssignmentPlan::brokerCount
int brokerCount() const
Definition: AssignmentPlan.cc:424
PendingAssignment.hh
AssignmentPlan::clear
void clear()
Definition: AssignmentPlan.cc:446
Move.hh
MoveNode.hh
ResourceManager.hh
AssignmentPlan::bus_
const TTAMachine::Bus * bus_
Definition: AssignmentPlan.hh:94
AssignmentPlan::resourceFound_
bool resourceFound_
True if a valid resource of current broker has been assigned.
Definition: AssignmentPlan.hh:114
AssignmentPlan::cycle_
int cycle_
Cycle in which current node should be placed.
Definition: AssignmentPlan.hh:110
PendingAssignment::undoAssignment
void undoAssignment()
Definition: PendingAssignment.cc:146
TTAMachine::ImmediateUnit
Definition: ImmediateUnit.hh:50