OpenASIP  2.0
TerminalFUPort.cc
Go to the documentation of this file.
1 /*
2  Copyright (c) 2002-2011 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 TerminalFUPort.cc
26  *
27  * Implementation of TerminalFUPort class.
28  *
29  * @author Ari Metsähalme 2005 (ari.metsahalme-no.spam-tut.fi)
30  * @author Pekka Jääskeläinen 2011
31  * @note rating: red
32  */
33 
34 #include <string>
35 #include <boost/format.hpp>
36 
37 #include "TerminalFUPort.hh"
38 #include "FunctionUnit.hh"
39 #include "OperationPool.hh"
40 #include "Operation.hh"
41 #include "HWOperation.hh"
42 #include "FUPort.hh"
43 #include "SpecialRegisterPort.hh"
45 #include "DisassemblyFUPort.hh"
46 
47 using std::string;
48 using namespace TTAMachine;
49 
50 namespace TTAProgram {
51 
52 /**
53  * Constructor.
54  *
55  * @param port The port of the terminal.
56  */
57 TerminalFUPort::TerminalFUPort(const TTAMachine::BaseFUPort& port)
58  : port_(port), operation_(NULL), opcode_(NULL) {
59  if (port_.isOpcodeSetting()) {
60  std::string msg =
61  "Opcode setting port terminals must have opcode set!";
62  throw IllegalParameters(__FILE__, __LINE__, __func__, msg);
63  }
64 }
65 
66 /**
67  * Creates a destination that writes to an opcode setting FU port.
68  *
69  * @param opcodeSettingPort The port of the terminal.
70  * @param opcode The operation to trigger.
71  */
73  const TTAMachine::FUPort& opcodeSettingPort,
74  const TTAMachine::HWOperation& opcode) :
75  port_(opcodeSettingPort), operation_(&opcode), opcode_(NULL) {
76 
77  assert(opcodeSettingPort.isOpcodeSetting());
78 
79  opIndex_ = opcode.io(opcodeSettingPort);
80 
81  static OperationPool pool;
82  // opcode is NullOperation instance if operation for that name was not
83  // found
84  try {
85  opcode_ = &pool.operation(operation_->name().c_str());
86  } catch (const Exception& e) {
88  __FILE__, __LINE__, __func__,
89  (boost::format(
90  "Error loading the operation '%s' definition: '%s'.")
91  % operation_->name() % e.errorMessage()).str());
92  ip.setCause(e);
93  throw ip;
94  }
95 }
96 
97 
98 /**
99  * Constructor.
100  *
101  * @param operation Operation of terminal.
102  * @param opIndex Operation index.
103  */
104 TerminalFUPort::TerminalFUPort(const HWOperation& operation, int opIndex)
105  : port_(*operation.port(opIndex)),
106  operation_(&operation),
107  opIndex_(opIndex) {
108  /* In case the operand cannot be resolved to a legal port, it's an
109  error in the loaded input program. Thus, we cannot abort the program but
110  we'll throw an exception instead. */
111  if (dynamic_cast<const FUPort*>(&port_) == NULL) {
112  throw IllegalParameters(
113  __FILE__, __LINE__, __func__,
114  (boost::format(
115  "Port binding of operand %d of operation '%s' "
116  "cannot be resolved.") % opIndex % operation.name()).
117  str());
118  }
119  static OperationPool pool;
120  // opcode is NullOperation instance if operation for that name was not
121  // found
122  try {
123  opcode_ = &pool.operation(operation_->name().c_str());
124  } catch (const Exception& e) {
126  __FILE__, __LINE__, __func__,
127  (boost::format(
128  "Error loading the operation '%s' definition: '%s'.")
129  % operation_->name() % e.errorMessage()).str());
130  ip.setCause(e);
131  throw ip;
132  }
133 }
134 
135 /**
136  * Copy Constructor. private, only called internally by copy().
137  *
138  * @param tfup object to copy from.
139  */
141  Terminal(), port_(tfup.port_), operation_(tfup.operation_),
142  opcode_(tfup.opcode_), opIndex_(tfup.opIndex_), po_(tfup.po_) {
143 }
144 
145 /**
146  * The destructor.
147  */
149 }
150 
151 /**
152  * Tells whether the terminal is a function unit port (possibly,
153  * including an operation code).
154  *
155  * @return True always.
156  */
157 bool
159  return true;
160 }
161 
162 /**
163  * Tells whether the terminal is the return address port of gcu.
164  *
165  * @return returns true if this is the RA.
166  */
167 bool
169  return dynamic_cast<const TTAMachine::SpecialRegisterPort*>
170  (&port()) != NULL;
171 }
172 
173 /**
174  * Tells whether terminal transports an opcode to a function unit port.
175  *
176  * @return True if the terminal transports an opcode to a function unit port.
177  * @exception WrongSubclass never.
178 */
179 bool
181  return port_.isOpcodeSetting();
182 }
183 
184 /**
185  * Tells whether terminal is a triggering port.
186  *
187  * @return True if the terminal transports an opcode to a function unit port.
188  * @exception WrongSubclass never.
189 */
190 bool
192  return port_.isTriggering();
193 }
194 
195 /**
196  * Returns the function unit of the port.
197  *
198  * @return The function unit of the port.
199  * @exception WrongSubclass never.
200  */
201 const FunctionUnit&
203  return *port_.parentUnit();
204 }
205 
206 /**
207  * Return the operation code transported into the function unit port.
208  *
209  * @return The operation code transported into the function unit port.
210  * @exception InvalidData If terminal does not set opcode for FU.
211  */
212 Operation&
214  if (port_.isOpcodeSetting() && opcode_ != NULL) {
215  return *opcode_;
216  } else {
217  std::cerr
218  << "operation == NULL || !port_.isopcodesetting()" << std::endl;
219  }
220 
221  throw InvalidData(__FILE__, __LINE__, __func__,
222  "Terminal does not set opcode for FU.");
223 }
224 
225 /**
226  * Return the index that identifies the operation input or output that
227  * is represented by this terminal.
228  *
229  * @return The index that identifies the operation input or output that
230  * is represented by this terminal.
231  * @exception WrongSubclass Never.
232  * @exception InvalidData If the terminal is of the the right class type,
233  * but the FU port of the terminal is not opcode-setting and bears no
234  * auxiliary "hint operation" information.
235  * @todo Rename to operandIndex()?
236  */
237 int
239  if (operation_ != NULL || opcode_ != nullptr) {
240  return opIndex_;
241  } else {
242  const string msg =
243  "FU port of the terminal is not opcode-setting "
244  "and bears no auxiliary 'hint operation' information.";
245  throw InvalidData(__FILE__, __LINE__, __func__, msg);
246  }
247 }
248 
249 /**
250  * Return the operation to which this terminal was originally bound.
251  *
252  * NOTE! : Method must not be used for checkin if terminal contains
253  * opcode. See. operation().
254  *
255  * Method is mainly used for preserving information to which operation
256  * port reference is bound, during TPEF -> POM -> TPEF write cycles.
257  *
258  * @return The operation code to which terminal was originally bound.
259  * Null operation if terminal does not contain operation code.
260  */
261 Operation&
263  if (opcode_ != NULL) {
264  return *opcode_;
265  } else {
266  return NullOperation::instance();
267  }
268 }
269 
270 void TerminalFUPort::setHintOperation(const char* name) {
271  OperationPool opPool;
272  assert(&opPool.operation(name) != &NullOperation::instance());
273  opcode_ = &opPool.operation(name);
274  operation_ = nullptr;
275 }
276 
277 void
279  OperationPool opPool;
280  opcode_ = &opPool.operation(hwOp.name().c_str());
281  operation_ = &hwOp;
282 }
283 
284 /**
285  * Return the port.
286  *
287  * @return The port.
288  * @exception WrongSubclass never.
289  */
290 const Port&
292  return port_;
293 }
294 
295 /**
296  * Creates an exact copy of the terminal and returns it.
297  *
298  * @note The returned copy is a deep cope *but* the copied ProgramOperation,
299  * if contained, will *not* be updated to refer to the new moves. This should
300  * be done in the caller.
301  *
302  * @return A copy of the terminal.
303  */
304 Terminal*
306  return new TerminalFUPort(*this);
307 }
308 
309 /**
310  * Checks if terminals are equal.
311  *
312  * @param other Terminal to compare.
313  * @return true if terminals are equal.
314  */
315 bool
316 TerminalFUPort::equals(const Terminal& other) const {
317 
318  if (!other.isFUPort()) {
319  return false;
320  }
321 
322  const TerminalFUPort& subclass =
323  dynamic_cast<const TerminalFUPort&>(other);
324 
325  // if ports are same
326  if (&port_ == &subclass.port_) {
327 
328  // we care about opcodes only if they are necessary data
329  if (port_.isOpcodeSetting()) {
330 
331  // if opcodes are the same
332  if (operation_ == subclass.operation_) {
333  // same port same operation
334  return true;
335  } else {
336  // if opcodes are not defined -> error
337  if (operation_ == NULL ||
338  subclass.operation_ == NULL) {
339 
341  "Opcode _must_ be set for terminals that "
342  "refers opcode setting port!");
343  }
344 
345  // same port different operations
346  return false;
347  }
348  } else {
349  // same ports not opcode setting
350  return true;
351  }
352  }
353 
354  // different ports
355  return false;
356 }
357 
358 /**
359  * Return operation index bound to the terminal port for a given operation.
360  *
361  * Used if operation in terminal is changed.
362  *
363  * @return Operation index bound to the terminal port for a given operation.
364  */
365 int
367  const FunctionUnit* fu = port_.parentUnit();
368  const HWOperation* hwop = fu->operation(operation_->name());
369  return hwop->io(dynamic_cast<const FUPort&>(port_));
370 }
371 
372 
373 /**
374  * Returns a pointer to the HW operation
375  *
376  * @return a pointer to the HW operation
377  */
378 const HWOperation*
380  return operation_;
381 }
382 
383 TCEString
385  if (operation_ != NULL) {
387  port().parentUnit()->name(), port().name(), operation_->name());
388  return disasm.toString();
389  } else {
390  DisassemblyFUPort disasm(port().parentUnit()->name(), port().name());
391  return disasm.toString();
392  }
393 }
394 
395 }
TTAProgram::TerminalFUPort::opcode_
Operation * opcode_
The OSAL operation.
Definition: TerminalFUPort.hh:117
TTAProgram::Terminal::isFUPort
virtual bool isFUPort() const
Definition: Terminal.cc:118
TTAProgram
Definition: Estimator.hh:65
OperationPool::operation
Operation & operation(const char *name)
Definition: OperationPool.cc:99
TTAProgram::TerminalFUPort::functionUnit
virtual const TTAMachine::FunctionUnit & functionUnit() const
Definition: TerminalFUPort.cc:202
TTAMachine::FUPort::isOpcodeSetting
virtual bool isOpcodeSetting() const
Definition: FUPort.cc:195
TTAMachine::HWOperation
Definition: HWOperation.hh:52
TTAProgram::TerminalFUPort::TerminalFUPort
TerminalFUPort(const TTAMachine::FUPort &opcodeSettingPort, const TTAMachine::HWOperation &opcode)
Definition: TerminalFUPort.cc:72
TTAMachine::BaseFUPort::parentUnit
FunctionUnit * parentUnit() const
Definition: BaseFUPort.cc:96
TTAProgram::TerminalFUPort::isTriggering
virtual bool isTriggering() const
Definition: TerminalFUPort.cc:191
TTAProgram::TerminalFUPort::copy
virtual Terminal * copy() const
Definition: TerminalFUPort.cc:305
TTAProgram::TerminalFUPort::port_
const TTAMachine::BaseFUPort & port_
Port of the unit.
Definition: TerminalFUPort.hh:113
TTAProgram::TerminalFUPort::toString
virtual TCEString toString() const
Definition: TerminalFUPort.cc:384
TTAMachine::BaseFUPort
Definition: BaseFUPort.hh:44
TTAProgram::TerminalFUPort::operation_
const TTAMachine::HWOperation * operation_
Operation code transported to the port.
Definition: TerminalFUPort.hh:115
Exception::setCause
void setCause(const Exception &cause)
Definition: Exception.cc:75
TTAProgram::TerminalFUPort::equals
virtual bool equals(const Terminal &other) const
Definition: TerminalFUPort.cc:316
TTAProgram::TerminalFUPort::operation
virtual Operation & operation() const
Definition: TerminalFUPort.cc:213
TTAProgram::TerminalFUPort::isRA
virtual bool isRA() const
Definition: TerminalFUPort.cc:168
NullOperation::instance
static NullOperation & instance()
Operation::name
virtual TCEString name() const
Definition: Operation.cc:93
TTAProgram::TerminalFUPort::setHintOperation
void setHintOperation(const char *name)
Definition: TerminalFUPort.cc:270
TTAMachine::BaseFUPort::isOpcodeSetting
virtual bool isOpcodeSetting() const =0
assert
#define assert(condition)
Definition: Application.hh:86
TTAMachine::FunctionUnit
Definition: FunctionUnit.hh:55
TTAProgram::TerminalFUPort::isFUPort
virtual bool isFUPort() const
Definition: TerminalFUPort.cc:158
TTAProgram::TerminalFUPort::hintOperation
virtual Operation & hintOperation() const
Definition: TerminalFUPort.cc:262
TTAMachine::FUPort
Definition: FUPort.hh:46
DisassemblyFUOpcodePort::toString
virtual std::string toString() const
Definition: DisassemblyFUOpcodePort.cc:67
IllegalParameters
Definition: Exception.hh:113
TTAMachine::HWOperation::io
int io(const FUPort &port) const
Definition: HWOperation.cc:364
abortWithError
#define abortWithError(message)
Definition: Application.hh:72
HWOperation.hh
TTAProgram::TerminalFUPort::operationIndex
virtual int operationIndex() const
Definition: TerminalFUPort.cc:238
TTAMachine::SpecialRegisterPort
Definition: SpecialRegisterPort.hh:48
TTAMachine::HWOperation::name
const std::string & name() const
Definition: HWOperation.cc:141
InvalidData
Definition: Exception.hh:149
TTAProgram::TerminalFUPort::opIndex_
int opIndex_
Operation index.
Definition: TerminalFUPort.hh:119
TTAMachine::Port
Definition: Port.hh:54
__func__
#define __func__
Definition: Application.hh:67
DisassemblyFUPort::toString
virtual std::string toString() const
Definition: DisassemblyFUPort.cc:61
Operation.hh
TTAProgram::TerminalFUPort::port
virtual const TTAMachine::Port & port() const
Definition: TerminalFUPort.cc:291
TerminalFUPort.hh
Exception
Definition: Exception.hh:54
TTAProgram::TerminalFUPort::~TerminalFUPort
virtual ~TerminalFUPort()
Definition: TerminalFUPort.cc:148
TTAProgram::TerminalFUPort::isOpcodeSetting
virtual bool isOpcodeSetting() const
Definition: TerminalFUPort.cc:180
TTAMachine::BaseFUPort::isTriggering
virtual bool isTriggering() const =0
TTAProgram::TerminalFUPort::setOperation
virtual void setOperation(const TTAMachine::HWOperation &hwOp)
Definition: TerminalFUPort.cc:278
Operation
Definition: Operation.hh:59
Exception::errorMessage
std::string errorMessage() const
Definition: Exception.cc:123
TTAProgram::TerminalFUPort
Definition: TerminalFUPort.hh:56
TCEString
Definition: TCEString.hh:53
FUPort.hh
TTAProgram::TerminalFUPort::hwOperation
virtual const TTAMachine::HWOperation * hwOperation() const
Definition: TerminalFUPort.cc:379
SpecialRegisterPort.hh
DisassemblyFUOpcodePort
Definition: DisassemblyFUOpcodePort.hh:38
DisassemblyFUPort
Definition: DisassemblyFUPort.hh:41
TTAProgram::Terminal
Definition: Terminal.hh:60
TTAMachine::FunctionUnit::operation
virtual HWOperation * operation(const std::string &name) const
Definition: FunctionUnit.cc:363
DisassemblyFUOpcodePort.hh
OperationPool
Definition: OperationPool.hh:52
TTAMachine
Definition: Assembler.hh:48
OperationPool.hh
DisassemblyFUPort.hh
FunctionUnit.hh
TTAProgram::TerminalFUPort::findNewOperationIndex
int findNewOperationIndex() const
Definition: TerminalFUPort.cc:366