OpenASIP 2.2
Loading...
Searching...
No Matches
CriticalPathBBMoveNodeSelector.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 CriticalPathBBMoveNodeSelector.cc
26 *
27 * Implementation of CriticalPathBBMoveNodeSelector interface.
28 *
29 * @author Pekka Jääskeläinen 2007 (pekka.jaaskelainen-no.spam-tut.fi)
30 * @note rating: red
31 */
32
36#include "POMDisassembler.hh"
37#include "ProgramOperation.hh"
38#include "Procedure.hh"
39#include "BasicBlock.hh"
41#include "Terminal.hh"
42
43//#define DEBUG_OUTPUT__
44//#define WRITE_DOT_SNAPSHOTS
45
46/**
47 * Add the unscheduled root nodes of the DDG to the ready list
48 */
49void
52 for (DataDependenceGraph::NodeSet::iterator i = roots.begin();
53 i != roots.end();
54 ++i) {
55 MoveNode& node = **i;
56
57 // a hack to avoid adding the root operations multiple times
58 // (the count of input moves): only "announce" the move to the first
59 // operand (every operation should have one input operand)
60 if (!node.isDestinationOperation())
61 mightBeReady(**i);
62 else if (node.move().destination().operationIndex() == 1) {
63 mightBeReady(**i);
64 }
65 }
66
67}
68
69/**
70 * Constructor. Creates subgraph of the given big graph
71 *
72 * @param bigDDG big ddg containing more than just the basic block
73 * @param bb basic block for this selector.
74 */
78 : ddgOwned_(true) {
79 try {
80 ddg_ = bigDDG.createSubgraph(bb);
82 } catch (InstanceNotFound& inf) {
84 __FILE__,__LINE__,__func__,"Creation of subgraph failed");
85 e.setCause(inf);
86 throw e;
87 }
89}
90
91/**
92 * Constructor.
93 *
94 * @param bb The basic block from which to select moves.
95 */
98 ddgOwned_(true) {
99
101 ddg_ = ddgBuilder.build(
104
105#ifdef WRITE_DOT_SNAPSHOTS
106 ddg_->setCycleGrouping(true);
107 ddg_->writeToDotFile("ddg.dot");
108#endif
109
111}
112
113/**
114 * Constructor.
115 *
116 * @param ddg The data dependence graph from which to select moves.
117 * Selector does not take the ownership of the ddg.
118 */
121 ddg_(&ddg), ddgOwned_(false) {
122
124
125#ifdef WRITE_DOT_SNAPSHOTS
126 ddg_->setCycleGrouping(true);
127 ddg_->writeToDotFile("ddg.dot");
128#endif
129
131}
132
133/**
134 * Destructor.
135 */
141
142/**
143 * Returns a group of move nodes which should be scheduled next.
144 *
145 * @return Move node group.
146 */
149
150 // find a MoveNodeGroup with unscheduled MoveNodes
151 while (readyList_.size() > 0) {
152 MoveNodeGroup moves = readyList_.top();
153 if (!moves.isAlive() || moves.isScheduled())
154 readyList_.pop();
155 else
156 return moves;
157 }
158 // nothing in ready list, let's see if there are "orphan" nodes
159 // still to schedule
160 if (ddg_->nodeCount() - ddg_->scheduledNodeCount() > 0) {
162 for (DataDependenceGraph::NodeSet::iterator i = unscheduled.begin();
163 i != unscheduled.end();
164 ++i) {
165 MoveNode& node = **i;
166 mightBeReady(node);
167 }
168 }
169
170 // did we find new nodes?
171 while (readyList_.size() > 0) {
172 MoveNodeGroup moves = readyList_.top();
173 if (moves.isScheduled())
174 readyList_.pop();
175 else
176 return moves;
177 }
178
179 // return an empty move node group
180 return MoveNodeGroup();
181}
182
183/**
184 * Returns the DDG used internally.
185 *
186 * This is needed temporarily only until the MoveNodeManager is done.
187 *
188 * @return The DDG.
189 */
194
195/**
196 * This should be called by the client as soon as a MoveNode is scheduled
197 * in order to update the internal state of the selector.
198 *
199 * @param node The scheduled MoveNode.
200 */
201void
203
204 assert(node.isScheduled() && "Notifying scheduled even though it isn't.");
206 for (DataDependenceGraph::NodeSet::iterator i = succ.begin();
207 i != succ.end(); ++i) {
208 MoveNode& successor = **i;
209
210 // we schedule operations as entities, so if the successor is a
211 // (result) move, it's already in the ready list along with the
212 // move itself
213 if (!successor.inSameOperation(node))
214 mightBeReady(**i);
215 }
216
217#ifdef WRITE_DOT_SNAPSHOTS
218 ddg_->setCycleGrouping(true);
219 ddg_->writeToDotFile("ddg.dot");
220#endif
221}
222
223/**
224 * Adds the given move node (along with the other possible move nodes in the
225 * same operation) to the ready list in case all its parents in the DDG have
226 * been scheduled.
227 *
228 * In case the node belongs to an operation, also checks that the other
229 * operand moves are also ready. In that case adds all the nodes in the said
230 * MoveOperation to the ready list in a single MoveNodeGroup.
231 *
232 * @param node Move node that might be ready.
233 */
234void
236
237 if (node.isScheduled()) {
238 return;
239 }
240
241 if (!isReadyToBeScheduled(node))
242 return;
243
244 if (node.isDestinationOperation() || node.isSourceOperation()) {
245 // it's a trigger, result, or operand move, let's see if all the
246 // moves of the operation are ready to be scheduled
247 ProgramOperation& operation =
249 (node.destinationOperation()) : node.sourceOperation());
250 bool allReady = true;
251 MoveNodeGroup moves(*ddg_);
252 for (int inputIndex = 0; inputIndex < operation.inputMoveCount();
253 ++inputIndex) {
254 MoveNode& m = operation.inputMove(inputIndex);
255 if (&m != &node) {
256 if (!isReadyToBeScheduled(m)) {
257 allReady = false;
258 break;
259 }
260 }
261 if (!m.isScheduled())
262 moves.addNode(m);
263 }
264 if (allReady) {
265 // let's add also the output move(s) to the MoveNodeGroup
266 for (int outputIndex = 0;
267 outputIndex < operation.outputMoveCount();
268 ++outputIndex) {
269 MoveNode& m = operation.outputMove(outputIndex);
270 if (&m != &node) {
271 if (!isReadyToBeScheduled(m)) {
272 allReady = false;
273 break;
274 }
275 }
276 if (!m.isScheduled())
277 moves.addNode(m);
278 }
279 if (allReady) {
280 readyList_.push(moves);
281 }
282 }
283 } else if ((node.isSourceVariable() || node.move().source().isRA()) &&
284 (node.isDestinationVariable() ||
285 node.move().destination().isRA())) {
286 // it's a register to register move, we can always schedule these
287 // as soon as all the dependencies are satisfied
288 // handle RA -> ireg also as a register to register move
289 if (isReadyToBeScheduled(node)) {
290 MoveNodeGroup move(*ddg_);
291 move.addNode(node);
292 readyList_.push(move);
293 }
294 } else if (node.isSourceConstant() && node.isDestinationVariable()) {
295 if (isReadyToBeScheduled(node)) {
296 MoveNodeGroup move(*ddg_);
297 move.addNode(node);
298 readyList_.push(move);
299 }
300
301 } else {
302 throw IllegalProgram(
303 __FILE__, __LINE__, __func__,
304 (boost::format("Illegal move '%s'.") %
305 POMDisassembler::disassemble(node.move())).str());
306 }
307}
308
309/**
310 * Returns true in case the move is "data ready", that is, all its
311 * predecessors have been scheduled.
312 *
313 * It should be noted that moves within same operation are treated
314 * specially. Result move is considered ready even if the operands
315 * moves are not to allow scheduling all moves in the same operation
316 * as a single entity. Additionally, as we are considering a basic block
317 * at a time, the branch operation is considered never ready before
318 * all the other moves in the basic block have been scheduled.
319 *
320 * @param node Move to check.
321 * @return True if the move is ready to be scheduled.
322 */
323bool
325 const {
326
327 // the control flow move(s) are ready only if all other moves have been
328 // scheduled. In rare case of conditional branching with SPU operation set
329 // branch operation can have 2 moves, condition register and destination.
330 if (node.move().isControlFlowMove() &&
333 for (DataDependenceGraph::NodeSet::iterator i = unscheduledMoves.begin();
334 i != unscheduledMoves.end(); ++i) {
335 if ((*i)->move().isControlFlowMove() == false) {
336 return false;
337 }
338 }
339 }
340 return ddg_->predecessorsReady(node);
341}
#define __func__
#define assert(condition)
TTAMachine::Machine * machine
the architecture definition of the estimated processor
find Finds info of the inner loops in the false
int nodeCount() const
virtual NodeSet rootNodes() const
useful utility functions
virtual NodeSet successors(const Node &node, bool ignoreBackEdges=false, bool ignoreForwardEdges=false) const
ReadyMoveNodeGroupList readyList_
The prioritized ready list.
CriticalPathBBMoveNodeSelector(TTAProgram::BasicBlock &bb, const TTAMachine::Machine &machine)
DataDependenceGraph * ddg_
The data dependence graph built from the basic block.
void initializeReadylist()
Initializes ready list from nodes that are ready.
virtual MoveNodeGroup candidates()
virtual DataDependenceGraph & dataDependenceGraph()
void initializeReadylist()
Initializes ready list from nodes that are ready.
bool isReadyToBeScheduled(MoveNode &node) const
virtual void notifyScheduled(MoveNode &node)
void mightBeReady(MoveNode &node)
virtual DataDependenceGraph * build(ControlFlowGraph &cGraph, DataDependenceGraph::AntidependenceLevel antidependenceLevel, const TTAMachine::Machine &mach, const UniversalMachine *um=NULL, bool createMemAndFUDeps=true, bool createDeathInformation=true, llvm::AliasAnalysis *AA=NULL)
NodeSet unscheduledMoves() const
DataDependenceGraph * createSubgraph(NodeSet &nodes, bool includeLoops=false)
virtual void setCycleGrouping(bool flag)
bool predecessorsReady(MoveNode &node) const
void setMachine(const TTAMachine::Machine &machine)
void setCause(const Exception &cause)
Definition Exception.cc:75
virtual void writeToDotFile(const TCEString &fileName) const
std::set< GraphNode *, typename GraphNode::Comparator > NodeSet
Definition Graph.hh:53
void addNode(MoveNode &node)
bool isAlive() const
bool isScheduled() const
bool isSourceVariable() const
Definition MoveNode.cc:196
ProgramOperation & sourceOperation() const
Definition MoveNode.cc:453
bool isDestinationOperation() const
TTAProgram::Move & move()
bool isSourceOperation() const
Definition MoveNode.cc:168
bool isScheduled() const
Definition MoveNode.cc:409
bool isSourceConstant() const
Definition MoveNode.cc:238
bool isDestinationVariable() const
Definition MoveNode.cc:264
bool inSameOperation(const MoveNode &other) const
Definition MoveNode.cc:306
ProgramOperation & destinationOperation(unsigned int index=0) const
static std::string disassemble(const TTAProgram::Move &move)
int outputMoveCount() const
int inputMoveCount() const
MoveNode & inputMove(int index) const
MoveNode & outputMove(int index) const
bool isControlFlowMove() const
Definition Move.cc:233
Terminal & source() const
Definition Move.cc:302
Terminal & destination() const
Definition Move.cc:323
virtual bool isRA() const
Definition Terminal.cc:129
virtual int operationIndex() const
Definition Terminal.cc:364