OpenASIP 2.2
Loading...
Searching...
No Matches
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
45using 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 */
61
62/**
63 * Insert a resource broker in the sequence of brokers.
64 *
65 * @param broker Resource broker to be inserted.
66 */
67void
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 */
80void
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
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_,
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 */
190void
192 if (resourceFound_) {
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 */
210void
212 // forget assignment history and assignments for current broker
214 assignment->forget();
215 if (assignment->broker().isAlreadyAssigned(cycle_, *node_, bus_)) {
216 assignment->undoAssignment();
217 }
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 */
236void
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 */
262bool
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 */
309bool
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() ||
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() &&
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 */
383void
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 */
402void
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 */
423int
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 */
436AssignmentPlan::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
445void
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();
462}
463
#define __func__
find Finds info of the inner loops in the false
#define debugLogRM(__X)
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)
const TTAMachine::Bus * bus_
MoveNode * node_
Move of current resource assignment request.
MoveNode * lastTriedNode_
bool isTestedAssignmentPossible()
std::vector< ResourceBroker * > brokers_
Sequence of resource brokers.
std::vector< PendingAssignment * > applicableAssignments_
Sequence of applicable pending assignments.
ResourceBroker & lastBroker()
std::vector< std::pair< ResourceBroker *, SchedulingResource * > > lastTestedWorkingAssignment_
cache.
ResourceBroker & nextBroker(ResourceBroker &pos)
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)
void insertBroker(ResourceBroker &broker)
ResourceBroker & firstBroker()
ResourceBroker & currentBroker()
const TTAMachine::ImmediateUnit * immu_
int brokerCount() const
virtual ~AssignmentPlan()
const TTAMachine::FunctionUnit * srcFU_
int cycle_
Cycle in which current node should be placed.
std::vector< PendingAssignment * > assignments_
Sequence of pending assignments.
const TTAMachine::FunctionUnit * dstFU_
bool resourceFound_
True if a valid resource of current broker has been assigned.
int currentBroker_
Current broker.
ResourceBroker & broker(int index) const
static void deleteAllItems(ContainerType &aMap)
int cycle() const
Definition MoveNode.cc:421
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
void unsetCycle()
Definition MoveNode.cc:519
ResourceBroker & broker()
SchedulingResource & resource(int index)
int lastTriedAssignment() const
virtual bool isAlreadyAssigned(int cycle, const MoveNode &node, const TTAMachine::Bus *preassignedBus) const =0
virtual bool isApplicable(const MoveNode &node, const TTAMachine::Bus *preassignedBus) const =0
const TTAMachine::Bus & bus() const
Definition Move.cc:373