OpenASIP 2.2
Loading...
Searching...
No Matches
Move.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 Move.cc
26 *
27 * Implementation of Move class.
28 *
29 * @author Ari Metsähalme 2005 (ari.metsahalme-no.spam-tut.fi)
30 * @author Pekka Jääskeläinen 2007 (pekka.jaaskelainen-no.spam-tut.fi)
31 * @note rating: red
32 */
33
34#include <climits>
35
36#include "Move.hh"
37#include "Socket.hh"
38#include "Port.hh"
39#include "NullInstruction.hh"
40#include "TerminalFUPort.hh"
41#include "StringTools.hh"
42#include "Operation.hh"
43#include "FunctionUnit.hh"
44#include "Machine.hh"
45#include "ControlUnit.hh"
47#include "TCEString.hh"
48#include "POMDisassembler.hh"
49#include "MoveGuard.hh"
50#include "Guard.hh"
51
52using namespace TTAMachine;
53
54namespace TTAProgram {
55
56/////////////////////////////////////////////////////////////////////////////
57// Move
58/////////////////////////////////////////////////////////////////////////////
59
60/**
61 * The constructor.
62 *
63 * Creates a guarded move.
64 *
65 * The ownership of the source and destination terminal objects and the
66 * guard will be passed to the move.
67 *
68 * @param src The source of the move.
69 * @param dst The destination of the move.
70 * @param bus The bus on which the transport is carried.
71 * @param guard The Boolean expression the move is predicated with.
72 */
74 Terminal* src, Terminal* dst,
75 const Bus& bus, MoveGuard* guard):
76 parent_(NULL), src_(src), dst_(dst), bus_(&bus), guard_(guard) {
77}
78
79/**
80 * The constructor.
81 *
82 * Creates an unguarded move.
83 *
84 * @param src The source of the move.
85 * @param dst The destination of the move.
86 * @param bus The bus on which the transport is carried.
87 */
89 Terminal* src, Terminal* dst, const Bus& bus):
90 parent_(NULL), src_(src), dst_(dst), bus_(&bus),
91 guard_(NULL) {
92}
93
94/**
95 * The destructor.
96 */
98 delete dst_;
99 dst_ = NULL;
100
101 delete src_;
102 src_ = NULL;
103
104 if (guard_ != NULL) {
105 delete guard_;
106 guard_ = NULL;
107 }
108}
109
110/**
111 * @return The parent instruction of the move.
112 * @exception IllegalRegistration if the move is independent.
113 */
116 if (parent_ != NULL && parent_ != &NullInstruction::instance()) {
117 return *parent_;
118 } else {
119 throw IllegalRegistration(__FILE__, __LINE__, __func__,
120 "Move is not registered.");
121 }
122}
123
124/**
125 * Set a new parent for the move.
126 *
127 * @param ins The new parent.
128 */
129void
131 if (&ins == &NullInstruction::instance()) {
132 parent_ = NULL;
133 } else {
134 parent_ = &ins;
135 }
136}
137
138/**
139 * Return true if this move belongs to an instruction.
140 *
141 * @return True if this move belongs to an instruction.
142 */
143bool
145 return parent_ != NULL && parent_ != &NullInstruction::instance();
146}
147
148/**
149 * Tells whether the move is predicated or not.
150 *
151 * @return true if this move is not predicated.
152 */
153bool
155 return (guard_ == NULL);
156}
157
158/**
159 * Tells whether the move triggers a jump operation.
160 *
161 * @return true if this move triggers a jump operation.
162 */
163bool
165
166 if (dst_->isFUPort()) {
167 // there is already check. no need for double-check.
168 const TerminalFUPort* tfup = static_cast<const TerminalFUPort*>(dst_);
169 if (tfup->isOpcodeSetting()) {
170 if (tfup->operation().isBranch()) {
171 return true;
172 }
173 } else {
174 Operation* tmpOp = &tfup->hintOperation();
175 if (tmpOp != &NullOperation::instance() &&
176 tfup->hintOperation().isBranch()) {
177 return true;
178 }
179 }
180 }
181 return false;
182}
183
184/**
185 * Tells whether the move triggers a call operation.
186 *
187 * @return true if this move triggers a call operation.
188 */
189bool
191
192 if (dst_->isFUPort()) {
193 // there is already check. no need for double-check.
194 const TerminalFUPort* tfup = static_cast<const TerminalFUPort*>(dst_);
195 if (tfup->isOpcodeSetting()) {
196 if (tfup->operation().isCall()) {
197 return true;
198 }
199 } else {
200 Operation* tmpOp = &tfup->hintOperation();
201 if (tmpOp != &NullOperation::instance() &&
202 tfup->hintOperation().isCall()) {
203 return true;
204 }
205 }
206 }
207 return false;
208}
209
210/**
211 * Returns true in case the move performs a function call.
212 *
213 * Currently two ways of calling functions are supported:
214 * the separate CALL operation, and regular JUMP with a
215 * separate RA save move. The latter is detected using an
216 * annotation in the JUMP move.
217 */
218bool
220 if (isCall()) return true;
221 if (!isJump()) return false;
222
224}
225
226/**
227 * Tells whether the move triggers an operation that controls
228 * the program flow.
229 *
230 * @return true if this move triggers a jump/call operation.
231 */
232bool
234
235 if (dst_->isFUPort()) {
236 const TerminalFUPort* tfup = dynamic_cast<const TerminalFUPort*>(dst_);
237 if (tfup->isOpcodeSetting()) {
238 if (tfup->operation().isControlFlowOperation()) {
239 return true;
240 }
241 } else {
242 Operation* tmpOp = &tfup->hintOperation();
243 if (tmpOp != &NullOperation::instance() &&
245 return true;
246 }
247 }
248 }
249 return false;
250}
251
252/**
253 * Tells whether the move is used to return from a procedure.
254 *
255 * Note: the detection is not always reliable, this method can return false
256 * even in case the move actually is a return in some cases.
257 */
258bool
260
261 if (!isJump()) {
262 return false;
263 }
264
265 // direct gcu.ra -> gcu.jump.1 is considered a return
266 if (source().isRA()) {
267 return true;
268 }
269
271 return true;
272 }
273
274 return false;
275}
276
277
278/**
279 * Tells whether the move triggers an operation.
280 *
281 * @return true if this move triggers an operation.
282 */
283bool
285
286 if (dst_->isFUPort()) {
287 const TerminalFUPort* tfup = dynamic_cast<const TerminalFUPort*>(dst_);
288 if (tfup->isTriggering()) {
289 return true;
290 }
291 }
292 return false;
293}
294
295
296/**
297 * Returns the source of this move.
298 *
299 * @return the source of this move.
300 */
303 return *src_;
304}
305
306/**
307 * Sets a new source for the move and deletes the old one.
308 *
309 * @param src The new source.
310 */
311void
313 delete src_;
314 src_ = src;
315}
316
317/**
318 * Returns the destination of this move.
319 *
320 * @return the destination of this move.
321 */
324 return *dst_;
325}
326
327/**
328 * Sets a new destination for the move and deletes the old one.
329 *
330 * @param dst The new destination.
331 */
332void
334 delete dst_;
335 dst_ = dst;
336}
337
338/**
339 * Returns the Boolean expression that guards this move.
340 *
341 * @return the Boolean expression that guards this move.
342 * @exception InvalidData if the move is not predicated.
343 */
345Move::guard() const {
346 if (guard_ != NULL) {
347 return *guard_;
348 } else {
349 throw InvalidData(
350 __FILE__, __LINE__, "Move::guard()", "Move is not predicated.");
351 }
352}
353
354/**
355 * Sets a new guard for the move and deletes the old one.
356 *
357 * @param guard The new guard.
358 */
359void
361 if (guard_ != NULL) {
362 delete guard_;
363 }
364 guard_ = guard;
365}
366
367/**
368 * Returns the bus on which the move is carried.
369 *
370 * @return the bus on which the move is carried.
371 */
372const Bus&
373Move::bus() const {
374 return *bus_;
375}
376
377/**
378 * Sets a new bus for the move.
379 *
380 * @param bus The new bus.
381 */
382void
384 bus_ = &bus;
385}
386
387Socket&
389 return *dst_->port().inputSocket();
390}
391
392Socket&
394 if (src_->isImmediate()) {
395 throw WrongSubclass(
396 __FILE__, __LINE__, "Move::sourceSocket()",
397 "Move source is an immediate.");
398 } else {
399 return *src_->port().outputSocket();
400 }
401}
402
403/**
404 * Makes a copy of the move.
405 *
406 * The copy is identical, except that it is not registered to the
407 * instruction of the original move (and therefore, any address it
408 * refers to is not meaningful).
409 *
410 * @return A copy of the move.
411 */
412std::shared_ptr<Move>
413Move::copy() const {
414
415 std::shared_ptr<Move> newMove = NULL;
416 if (isUnconditional()) {
417 newMove = std::make_shared<Move>(src_->copy(), dst_->copy(), *bus_);
418 } else {
419 newMove = std::make_shared<Move>(
420 src_->copy(), dst_->copy(), *bus_, guard_->copy());
421 }
422
423 for (int i = 0; i < annotationCount(); i++ ) {
424 newMove->addAnnotation(annotation(i));
425 }
426
427 newMove->setParent(NullInstruction::instance());
428
429 return newMove;
430}
431
432/**
433 * Returns the disassembly of the move.
434 */
435std::string
437 return POMDisassembler::disassemble(*this);
438}
439
440/**
441 * Returns true in case at least one source code line number
442 * is known for this move.
443 */
444bool
446 return sourceLineNumber() != -1;
447}
448
449/**
450 * Returns one source code line number for this move.
451 *
452 * There can be at most two source code line numbers associated
453 * to a move in case it's bypassed. This method returns the smaller of
454 * them.
455 *
456 * Returns -1 if no source code line info has been set.
457 */
458int
460 int lineNumber = -1;
463 if (hasAnnotations(id)) {
464 lineNumber = INT_MAX;
465 for (int i = 0; i < annotationCount(id); ++i) {
466 lineNumber = std::min(lineNumber, annotation(i, id).intValue());
467 }
468 }
469 return lineNumber;
470}
471
472
473/**
474 * Returns true in case at least one source code filename
475 * is known for this move.
476 */
477bool
479 return sourceFileName() != "";
480}
481
482/**
483 * Returns one source code filename for this move.
484 *
485 * Returns "" if no source code line info has been set.
486 */
487std::string
489 std::string fileName = "";
492 if (hasAnnotations(id)) {
493 fileName=annotation(0,id).stringValue();
494 }
495 return fileName;
496
497}
498/**
499 * Returns the total guard latency of the guard of given move,
500 * or 0 if the move is unconditional.
501 */
502int
504 if (!isUnconditional()) {
505
506 const TTAMachine::Guard& g = guard().guard();
507 const TTAMachine::RegisterGuard* rg =
508 dynamic_cast<const TTAMachine::RegisterGuard*>(&g);
509 if (rg != NULL) {
510 const TTAMachine::RegisterFile& rf =
511 *rg->registerFile();
512 return rf.guardLatency() +
514 } else {
516 }
517 } else {
518 return 0;
519 }
520}
521
522}
#define __func__
static NullOperation & instance()
virtual bool isCall() const
Definition Operation.cc:318
virtual bool isControlFlowOperation() const
Definition Operation.cc:294
virtual bool isBranch() const
Definition Operation.cc:306
static std::string disassemble(const TTAProgram::Move &move)
virtual Machine * machine() const
int globalGuardLatency() const
virtual Bus * parentBus() const
virtual ControlUnit * controlUnit() const
Definition Machine.cc:345
virtual Socket * outputSocket() const
Definition Port.cc:281
virtual Socket * inputSocket() const
Definition Port.cc:261
virtual int guardLatency() const
const RegisterFile * registerFile() const
int annotationCount(ProgramAnnotation::Id id=ProgramAnnotation::ANN_UNDEF_ID) const
ProgramAnnotation annotation(int index, ProgramAnnotation::Id id=ProgramAnnotation::ANN_UNDEF_ID) const
bool hasAnnotations(ProgramAnnotation::Id id=ProgramAnnotation::ANN_UNDEF_ID) const
MoveGuard * copy() const
Definition MoveGuard.cc:96
const TTAMachine::Guard & guard() const
Definition MoveGuard.cc:86
void setSource(Terminal *src)
Definition Move.cc:312
bool isFunctionCall() const
Definition Move.cc:219
MoveGuard * guard_
The boolean expression that predicates the move.
Definition Move.hh:114
TTAMachine::Socket & destinationSocket() const
Definition Move.cc:388
MoveGuard & guard() const
Definition Move.cc:345
TTAMachine::Socket & sourceSocket() const
Definition Move.cc:393
bool isControlFlowMove() const
Definition Move.cc:233
bool isReturn() const
Definition Move.cc:259
bool hasSourceLineNumber() const
Definition Move.cc:445
bool isUnconditional() const
Definition Move.cc:154
const TTAMachine::Bus * bus_
The bus where the transport is carried.
Definition Move.hh:112
std::string toString() const
Definition Move.cc:436
Instruction & parent() const
Definition Move.cc:115
Terminal & source() const
Definition Move.cc:302
int guardLatency() const
Definition Move.cc:503
std::shared_ptr< Move > copy() const
Definition Move.cc:413
int sourceLineNumber() const
Definition Move.cc:459
bool hasSourceFileName() const
Definition Move.cc:478
bool isJump() const
Definition Move.cc:164
Terminal * dst_
The destination of the move.
Definition Move.hh:110
bool isInInstruction() const
Definition Move.cc:144
bool isCall() const
Definition Move.cc:190
void setGuard(MoveGuard *guard)
Definition Move.cc:360
void setParent(Instruction &ins)
Definition Move.cc:130
bool isTriggering() const
Definition Move.cc:284
Terminal * src_
The source of the move.
Definition Move.hh:108
void setBus(const TTAMachine::Bus &bus)
Definition Move.cc:383
Instruction * parent_
Parent instruction of the move.
Definition Move.hh:106
Terminal & destination() const
Definition Move.cc:323
void setDestination(Terminal *dst)
Definition Move.cc:333
std::string sourceFileName() const
Definition Move.cc:488
const TTAMachine::Bus & bus() const
Definition Move.cc:373
Move(Terminal *src, Terminal *dst, const TTAMachine::Bus &bus, MoveGuard *guard)
Definition Move.cc:73
static NullInstruction & instance()
Id
the ID in TPEF is 24 bits, here enum
@ ANN_STACKFRAME_PROCEDURE_RETURN
precedure return jmp
@ ANN_JUMP_FUNCTION_CALL
The JUMP in the annotated move is a function call and should be treated as such in the data dependenc...
@ ANN_DEBUG_SOURCE_CODE_LINE
The line number in the source code file the annotated move originates from.
@ ANN_DEBUG_SOURCE_CODE_PATH
debugging info annotations
virtual bool isTriggering() const
virtual Operation & hintOperation() const
virtual Operation & operation() const
virtual bool isOpcodeSetting() const
virtual Terminal * copy() const =0
virtual const TTAMachine::Port & port() const
Definition Terminal.cc:378
virtual bool isImmediate() const
Definition Terminal.cc:63
virtual bool isFUPort() const
Definition Terminal.cc:118