OpenASIP  2.0
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"
46 #include "SpecialRegisterPort.hh"
47 #include "TCEString.hh"
48 #include "POMDisassembler.hh"
49 #include "MoveGuard.hh"
50 #include "Guard.hh"
51 
52 using namespace TTAMachine;
53 
54 namespace 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  */
73 Move::Move(
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  */
115 Move::parent() const {
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  */
129 void
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  */
143 bool
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  */
153 bool
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  */
163 bool
164 Move::isJump() const {
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  */
189 bool
190 Move::isCall() const {
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  */
218 bool
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  */
232 bool
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  */
258 bool
259 Move::isReturn() const {
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  */
283 bool
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  */
301 Terminal&
302 Move::source() const {
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  */
311 void
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  */
322 Terminal&
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  */
332 void
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  */
344 MoveGuard&
345 Move::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  */
359 void
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  */
372 const Bus&
373 Move::bus() const {
374  return *bus_;
375 }
376 
377 /**
378  * Sets a new bus for the move.
379  *
380  * @param bus The new bus.
381  */
382 void
384  bus_ = &bus;
385 }
386 
387 Socket&
389  return *dst_->port().inputSocket();
390 }
391 
392 Socket&
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  */
412 std::shared_ptr<Move>
413 Move::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  */
435 std::string
436 Move::toString() const {
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  */
444 bool
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  */
458 int
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  */
477 bool
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  */
487 std::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  */
502 int
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 {
515  return g.parentBus()->machine()->controlUnit()->globalGuardLatency();
516  }
517  } else {
518  return 0;
519  }
520 }
521 
522 }
TTAProgram::Move::copy
std::shared_ptr< Move > copy() const
Definition: Move.cc:413
TTAMachine::Guard
Definition: Guard.hh:55
TTAProgram::Move::sourceFileName
std::string sourceFileName() const
Definition: Move.cc:488
TTAProgram::Terminal::isFUPort
virtual bool isFUPort() const
Definition: Terminal.cc:118
TTAProgram::Move::destinationSocket
TTAMachine::Socket & destinationSocket() const
Definition: Move.cc:388
TTAProgram
Definition: Estimator.hh:65
TTAProgram::Move::isTriggering
bool isTriggering() const
Definition: Move.cc:284
TTAMachine::Port::inputSocket
virtual Socket * inputSocket() const
Definition: Port.cc:261
TTAProgram::ProgramAnnotation::ANN_JUMP_FUNCTION_CALL
@ ANN_JUMP_FUNCTION_CALL
The JUMP in the annotated move is a function call and should be treated as such in the data dependenc...
Definition: ProgramAnnotation.hh:129
TTAProgram::Move::dst_
Terminal * dst_
The destination of the move.
Definition: Move.hh:110
TTAProgram::Move::guardLatency
int guardLatency() const
Definition: Move.cc:503
TTAProgram::Move::isFunctionCall
bool isFunctionCall() const
Definition: Move.cc:219
TTAProgram::TerminalFUPort::isTriggering
virtual bool isTriggering() const
Definition: TerminalFUPort.cc:191
TTAProgram::Move::isReturn
bool isReturn() const
Definition: Move.cc:259
TTAProgram::Instruction
Definition: Instruction.hh:57
TTAProgram::Move::isUnconditional
bool isUnconditional() const
Definition: Move.cc:154
TTAProgram::ProgramAnnotation::stringValue
std::string stringValue() const
Definition: ProgramAnnotation.cc:90
TTAProgram::Move::sourceLineNumber
int sourceLineNumber() const
Definition: Move.cc:459
TTAMachine::Bus
Definition: Bus.hh:53
TTAProgram::Move::destination
Terminal & destination() const
Definition: Move.cc:323
TTAProgram::Move::bus
const TTAMachine::Bus & bus() const
Definition: Move.cc:373
TTAProgram::TerminalFUPort::operation
virtual Operation & operation() const
Definition: TerminalFUPort.cc:213
TTAProgram::Move::setGuard
void setGuard(MoveGuard *guard)
Definition: Move.cc:360
TTAProgram::Move::toString
std::string toString() const
Definition: Move.cc:436
TTAProgram::ProgramAnnotation::ANN_DEBUG_SOURCE_CODE_LINE
@ ANN_DEBUG_SOURCE_CODE_LINE
The line number in the source code file the annotated move originates from.
Definition: ProgramAnnotation.hh:138
NullOperation::instance
static NullOperation & instance()
Socket.hh
TTAProgram::Move::setParent
void setParent(Instruction &ins)
Definition: Move.cc:130
POMDisassembler.hh
TCEString.hh
TTAProgram::ProgramAnnotation::Id
Id
the ID in TPEF is 24 bits, here enum
Definition: ProgramAnnotation.hh:52
StringTools.hh
TTAProgram::Move::sourceSocket
TTAMachine::Socket & sourceSocket() const
Definition: Move.cc:393
TTAProgram::TerminalFUPort::hintOperation
virtual Operation & hintOperation() const
Definition: TerminalFUPort.cc:262
Port.hh
TTAProgram::Move::setDestination
void setDestination(Terminal *dst)
Definition: Move.cc:333
TTAMachine::Machine::controlUnit
virtual ControlUnit * controlUnit() const
Definition: Machine.cc:345
TTAProgram::Move::isControlFlowMove
bool isControlFlowMove() const
Definition: Move.cc:233
TTAProgram::Move::isCall
bool isCall() const
Definition: Move.cc:190
InvalidData
Definition: Exception.hh:149
WrongSubclass
Definition: Exception.hh:336
TTAMachine::RegisterGuard
Definition: Guard.hh:137
TTAProgram::Move::guard
MoveGuard & guard() const
Definition: Move.cc:345
TTAProgram::Move::src_
Terminal * src_
The source of the move.
Definition: Move.hh:108
NullInstruction.hh
__func__
#define __func__
Definition: Application.hh:67
TTAMachine::Socket
Definition: Socket.hh:53
Guard.hh
Operation.hh
TerminalFUPort.hh
Machine.hh
TTAProgram::Move::bus_
const TTAMachine::Bus * bus_
The bus where the transport is carried.
Definition: Move.hh:112
TTAProgram::Move::Move
Move(Terminal *src, Terminal *dst, const TTAMachine::Bus &bus, MoveGuard *guard)
Definition: Move.cc:73
TTAProgram::Move::isInInstruction
bool isInInstruction() const
Definition: Move.cc:144
TTAProgram::NullInstruction::instance
static NullInstruction & instance()
Definition: NullInstruction.cc:66
TTAProgram::TerminalFUPort::isOpcodeSetting
virtual bool isOpcodeSetting() const
Definition: TerminalFUPort.cc:180
Operation
Definition: Operation.hh:59
TTAProgram::AnnotatedInstructionElement::hasAnnotations
bool hasAnnotations(ProgramAnnotation::Id id=ProgramAnnotation::ANN_UNDEF_ID) const
Definition: AnnotatedInstructionElement.cc:165
TTAProgram::Move::~Move
~Move()
Definition: Move.cc:97
IllegalRegistration
Definition: Exception.hh:532
TTAProgram::TerminalFUPort
Definition: TerminalFUPort.hh:56
TTAProgram::AnnotatedInstructionElement::annotation
ProgramAnnotation annotation(int index, ProgramAnnotation::Id id=ProgramAnnotation::ANN_UNDEF_ID) const
Definition: AnnotatedInstructionElement.cc:100
TTAProgram::Move::parent_
Instruction * parent_
Parent instruction of the move.
Definition: Move.hh:106
TTAMachine::Guard::parentBus
virtual Bus * parentBus() const
POMDisassembler::disassemble
static std::string disassemble(const TTAProgram::Move &move)
Definition: POMDisassembler.cc:629
TTAProgram::Move::hasSourceLineNumber
bool hasSourceLineNumber() const
Definition: Move.cc:445
TTAProgram::Move::parent
Instruction & parent() const
Definition: Move.cc:115
TTAProgram::ProgramAnnotation::ANN_STACKFRAME_PROCEDURE_RETURN
@ ANN_STACKFRAME_PROCEDURE_RETURN
precedure return jmp
Definition: ProgramAnnotation.hh:76
TTAMachine::Component::machine
virtual Machine * machine() const
ControlUnit.hh
SpecialRegisterPort.hh
TTAProgram::Terminal::copy
virtual Terminal * copy() const =0
TTAMachine::Port::outputSocket
virtual Socket * outputSocket() const
Definition: Port.cc:281
TTAProgram::Terminal
Definition: Terminal.hh:60
TTAProgram::Move::source
Terminal & source() const
Definition: Move.cc:302
TTAProgram::ProgramAnnotation::ANN_DEBUG_SOURCE_CODE_PATH
@ ANN_DEBUG_SOURCE_CODE_PATH
debugging info annotations
Definition: ProgramAnnotation.hh:134
TTAProgram::MoveGuard::copy
MoveGuard * copy() const
Definition: MoveGuard.cc:96
TTAProgram::Terminal::port
virtual const TTAMachine::Port & port() const
Definition: Terminal.cc:378
TTAProgram::Move::guard_
MoveGuard * guard_
The boolean expression that predicates the move.
Definition: Move.hh:114
TTAMachine::RegisterFile::guardLatency
virtual int guardLatency() const
Definition: RegisterFile.cc:333
TTAMachine::RegisterFile
Definition: RegisterFile.hh:47
TTAProgram::MoveGuard::guard
const TTAMachine::Guard & guard() const
Definition: MoveGuard.cc:86
Operation::isCall
virtual bool isCall() const
Definition: Operation.cc:318
TTAProgram::Move::isJump
bool isJump() const
Definition: Move.cc:164
Move.hh
TTAMachine
Definition: Assembler.hh:48
TTAMachine::ControlUnit::globalGuardLatency
int globalGuardLatency() const
TTAProgram::Terminal::isImmediate
virtual bool isImmediate() const
Definition: Terminal.cc:63
TTAProgram::MoveGuard
Definition: MoveGuard.hh:47
TTAMachine::RegisterGuard::registerFile
const RegisterFile * registerFile() const
TTAProgram::Move::setBus
void setBus(const TTAMachine::Bus &bus)
Definition: Move.cc:383
Operation::isBranch
virtual bool isBranch() const
Definition: Operation.cc:306
TTAProgram::Move::setSource
void setSource(Terminal *src)
Definition: Move.cc:312
FunctionUnit.hh
Operation::isControlFlowOperation
virtual bool isControlFlowOperation() const
Definition: Operation.cc:294
TTAProgram::AnnotatedInstructionElement::annotationCount
int annotationCount(ProgramAnnotation::Id id=ProgramAnnotation::ANN_UNDEF_ID) const
Definition: AnnotatedInstructionElement.cc:133
TTAProgram::Move::hasSourceFileName
bool hasSourceFileName() const
Definition: Move.cc:478
MoveGuard.hh