OpenASIP 2.2
Loading...
Searching...
No Matches
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"
45#include "DisassemblyFUPort.hh"
46
47using std::string;
48using namespace TTAMachine;
49
50namespace TTAProgram {
51
52/**
53 * Constructor.
54 *
55 * @param port The port of the terminal.
56 */
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 */
104TerminalFUPort::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 */
150
151/**
152 * Tells whether the terminal is a function unit port (possibly,
153 * including an operation code).
154 *
155 * @return True always.
156 */
157bool
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 */
167bool
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*/
179bool
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*/
190bool
194
195/**
196 * Returns the function unit of the port.
197 *
198 * @return The function unit of the port.
199 * @exception WrongSubclass never.
200 */
201const 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 */
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 */
237int
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 */
263 if (opcode_ != NULL) {
264 return *opcode_;
265 } else {
267 }
268}
269
270void 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
277void
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 */
290const 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 */
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 */
315bool
316TerminalFUPort::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 */
365int
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 */
378const HWOperation*
380 return operation_;
381}
382
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}
#define __func__
#define abortWithError(message)
#define assert(condition)
virtual std::string toString() const
virtual std::string toString() const
std::string errorMessage() const
Definition Exception.cc:123
void setCause(const Exception &cause)
Definition Exception.cc:75
static NullOperation & instance()
Operation & operation(const char *name)
virtual TCEString name() const
Definition Operation.cc:93
FunctionUnit * parentUnit() const
Definition BaseFUPort.cc:96
virtual bool isOpcodeSetting() const =0
virtual bool isTriggering() const =0
virtual bool isOpcodeSetting() const
Definition FUPort.cc:195
virtual HWOperation * operation(const std::string &name) const
int io(const FUPort &port) const
const std::string & name() const
virtual bool equals(const Terminal &other) const
int opIndex_
Operation index.
const TTAMachine::HWOperation * operation_
Operation code transported to the port.
virtual bool isTriggering() const
virtual const TTAMachine::FunctionUnit & functionUnit() const
virtual Operation & hintOperation() const
virtual bool isRA() const
virtual Operation & operation() const
virtual TCEString toString() const
virtual void setOperation(const TTAMachine::HWOperation &hwOp)
TerminalFUPort(const TTAMachine::FUPort &opcodeSettingPort, const TTAMachine::HWOperation &opcode)
virtual const TTAMachine::Port & port() const
const TTAMachine::BaseFUPort & port_
Port of the unit.
virtual bool isOpcodeSetting() const
virtual int operationIndex() const
virtual Terminal * copy() const
virtual const TTAMachine::HWOperation * hwOperation() const
virtual bool isFUPort() const
Operation * opcode_
The OSAL operation.
void setHintOperation(const char *name)
virtual bool isFUPort() const
Definition Terminal.cc:118