OpenASIP 2.2
Loading...
Searching...
No Matches
HWOperation.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 HWOperation.cc
26 *
27 * Implementation of HWOperation class.
28 *
29 * @author Lasse Laasonen 2003 (lasse.laasonen-no.spam-tut.fi)
30 * @note rating: red
31 */
32
33#include "HWOperation.hh"
34#include "FunctionUnit.hh"
35#include "ExecutionPipeline.hh"
36#include "PipelineElement.hh"
37#include "FUPort.hh"
38#include "MachineTester.hh"
39#include "MOMTextGenerator.hh"
40#include "MapTools.hh"
41#include "ContainerTools.hh"
42#include "StringTools.hh"
43#include "ObjectState.hh"
44
45using std::string;
46using std::pair;
47using boost::format;
48
49namespace TTAMachine {
50
51// initialization of static data members
52const string HWOperation::OSNAME_OPERATION = "operation";
53const string HWOperation::OSKEY_NAME = "name";
54const string HWOperation::OSNAME_OPERAND_BINDING = "binding";
55const string HWOperation::OSKEY_OPERAND = "operand";
56const string HWOperation::OSKEY_PORT = "port";
57
58/**
59 * Constructor.
60 *
61 * @param name Name of the operation.
62 * @param parent The parent unit.
63 * @exception ComponentAlreadyExists If there is already an operation by the
64 * same name in the given function unit.
65 * @exception InvalidName If the given name is not valid for a component.
66 */
67HWOperation::HWOperation(const string& name, FunctionUnit& parent) :
68 SubComponent(), name_(name), pipeline_(NULL), parent_(NULL) {
69
71
73 const string procName = "HWOperation::HWOperation";
74 MOMTextGenerator textGen;
75 format errorMsg = textGen.text(MOMTextGenerator::TXT_INVALID_NAME);
76 errorMsg % name;
77 throw InvalidName(__FILE__, __LINE__, procName, errorMsg.str());
78 }
79
80 parent.addOperation(*this);
81 parent_ = &parent;
82 pipeline_ = new ExecutionPipeline(*this);
83}
84
85/**
86 * Constructor.
87 *
88 * Loads the state of the operation from the given ObjectState instance.
89 *
90 * @param state The ObjectState instance.
91 * @param parent The parent unit.
92 * @exception ObjectStateLoadingException If an error occurs while loading
93 * the state.
94 */
96 SubComponent(), name_(""), pipeline_(NULL), parent_(&parent) {
97
98 const string procName = "HWOperation::HWOperation";
99
100 // set name
101 try {
103 } catch (const Exception& exception) {
105 __FILE__, __LINE__, procName, exception.errorMessage());
106 }
107
108 parent_ = NULL;
109
110 // register to parent unit
111 parent.addOperation(*this);
112 parent_ = &parent;
113
114 try {
115 loadState(state);
116 } catch (const ObjectStateLoadingException& e) {
117 if (pipeline_ != NULL) {
118 delete pipeline_;
119 }
120 throw;
121 }
122}
123
124/**
125 * Destructor.
126 */
128 delete pipeline_;
129 FunctionUnit* parent = parentUnit();
130 parent_ = NULL;
131 parent->deleteOperation(*this);
132}
133
134
135/**
136 * Returns the name of the operation.
137 *
138 * @return The name of the operation.
139 */
140const string&
142 return name_;
143}
144
145
146/**
147 * Sets the name of the operation.
148 *
149 * @param name The new name.
150 * @exception ComponentAlreadyExists If another operation exists by the same
151 * name in the function unit.
152 * @exception InvalidName If the given name is not valid.
153 */
154void
155HWOperation::setName(const std::string& name) {
156
157 string lowerName = StringTools::stringToLower(name);
158
159 if (lowerName == this->name()) {
160 return;
161 }
162
163 const string procName = "HWOperation::setName";
164
165 if (parentUnit()->hasOperation(lowerName)) {
166 MOMTextGenerator textGenerator;
167 format text = textGenerator.text(
169 text % name % parentUnit()->name();
171 __FILE__, __LINE__, procName, text.str());
172 }
173
174 if (!MachineTester::isValidComponentName(lowerName)) {
175 MOMTextGenerator textGen;
176 format errorMsg = textGen.text(MOMTextGenerator::TXT_INVALID_NAME);
177 errorMsg % lowerName;
178 throw InvalidName(__FILE__, __LINE__, procName, errorMsg.str());
179 }
180
181 name_ = lowerName;
182}
183
184/**
185 * Returns the parent unit of the operation.
186 *
187 * @return The parent unit of the operation.
188 */
191 return parent_;
192}
193
194
195/**
196 * Returns the pipeline used by this operation.
197 *
198 * @return The pipeline used by this operation.
199 */
202 return pipeline_;
203}
204
205
206/**
207 * Returns the number of cycles used during execution of the operation.
208 *
209 * Different results may have different latencies, thus this is the longest
210 * latency of any result produced by the operation. After this latency the
211 * operation execution has been finished and no results will be produced.
212 *
213 * @return The latency of the operation.
214 */
215int
217 return pipeline_->latency();
218}
219
220
221/**
222 * Returns the latency for the given output.
223 *
224 * @param output The number of the output.
225 * @return The latency for the given output.
226 * @exception IllegalParameters If the given output is not written in the
227 * pipeline.
228 */
229int
230HWOperation::latency(int output) const {
231
232 return pipeline_->latency(output);
233}
234
235/**
236 * Returns the slack of the given input.
237 *
238 * The slack tells how many cycles AFTER the trigger, opcode-setting move is
239 * scheduled, can the operand be scheduled (and still affect correctly the
240 * result of the operation).
241 *
242 * @param input The number of the input.
243 * @return The slack of the given input.
244 * @exception IllegalParameters If the given input is not read in the
245 * pipeline.
246 */
247int
248HWOperation::slack(int input) const {
249
250 return pipeline_->slack(input);
251}
252
253/**
254 * Binds the given operand of the operation to the given port of the
255 * function unit.
256 *
257 * If the given operand is already bound to another port, the old binding is
258 * replaced with the new one.
259 *
260 * @param operand Index of the operand.
261 * @param port The port.
262 * @exception IllegalRegistration If the given port does not belong to the
263 * same function unit as this operation.
264 * @exception ComponentAlreadyExists If the given port is already reserved
265 * for another operand.
266 * @exception OutOfRange If the given operand is less than 1.
267 */
268void
269HWOperation::bindPort(int operand, const FUPort& port) {
270
271 const string procName = "HWOperation::bindPort";
272
273 if (operand < 1) {
274 throw OutOfRange(__FILE__, __LINE__, procName);
275 }
276
277 if (port.parentUnit() != parentUnit()) {
278 throw IllegalRegistration(__FILE__, __LINE__, procName);
279 }
280
282 this->HWOperation::port(operand) != &port) {
283 throw ComponentAlreadyExists(__FILE__, __LINE__, procName);
284 }
285
286 operandBinding_[operand] = &port;
288}
289
290/**
291 * Unbinds the operand bound to the given port.
292 *
293 * @param port The port.
294 */
295void
300
301
302/**
303 * Returns number of operands for this operation.
304 */
305int
307 return operandBinding_.size();
308}
309
310
311/**
312 * Returns the port of the function unit that is bound to the given operand.
313 *
314 * Returns NULL if no port is bound to the given operand.
315 *
316 * @param operand Index of the operand.
317 * @return The port or NULL.
318 */
319FUPort*
320HWOperation::port(int operand) const {
321 OperandBindingMap::const_iterator iter = operandBinding_.find(operand);
322 if (iter != operandBinding_.end()) {
323 return const_cast<FUPort*>((*iter).second);
324 } else {
325 return NULL;
326 }
327}
328
329
330/**
331 * Checks whether the given port is bound to one of the operands of the
332 * operation.
333 *
334 * @param port The port.
335 * @return True if the port is bound, otherwise false.
336 */
337bool
341
342/**
343 * Checks whetever the given operand is bound to some port.
344 *
345 * @param operand The operand.
346 * @return True if bound and otherwise false.
347 */
348bool
349HWOperation::isBound(int operand) const {
350 if (operand < 1) {
351 THROW_EXCEPTION(OutOfRange, "Operand out of range (must be > 0).");
352 }
353 return MapTools::containsKey(operandBinding_, operand);
354}
355
356/**
357 * Returns the index of the input or output that is bound to the given port.
358 *
359 * @param port The port.
360 * @return The index of the input or output.
361 * @exception InstanceNotFound If no io is bound to the given port.
362 */
363int
364HWOperation::io(const FUPort& port) const {
365
366 if (!isBound(port)) {
367 const string procName = "HWOperation::operand";
368 const string msg = string("The port '") + port.name()
369 + "' is not bound to the operation '"
370 + name() + "'.";
371 throw InstanceNotFound(__FILE__, __LINE__, procName, msg);
372 }
373
375}
376
377/**
378 * Returns the number of input ports tied to the operation
379 *
380 * @return Number of input ports
381 */
382
383int
385 int inputs = 0;
386 for (int i = 1; i < operandCount() + 1; i++) {
387 FUPort* p = port(i);
388 if (p == NULL) {
389 continue;
390 } else if (p->isInput()) {
391 inputs++;
392 }
393 }
394 return inputs;
395}
396
397/**
398 * Returns the number of output ports tied to the operation
399 *
400 * @return Number of output ports
401 */
402
403int
405 int outputs = 0;
406 for (int i = 1; i < operandCount() + 1; i++) {
407 FUPort* p = port(i);
408 if (p == NULL) {
409 continue;
410 }
411 if (p->isOutput()) {
412 outputs++;
413 }
414 }
415 return outputs;
416}
417
418/**
419 * Saves the contents to an ObjectState tree.
420 *
421 * @return The newly created ObjectState tree.
422 */
425
426 ObjectState* operation = new ObjectState(OSNAME_OPERATION);
427 operation->setAttribute(OSKEY_NAME, name());
428
429 // save operand binding map
430 for (OperandBindingMap::const_iterator iter = operandBinding_.begin();
431 iter != operandBinding_.end(); iter++) {
432 pair<int, const FUPort*> binding = *iter;
434 operation->addChild(bindingState);
435 bindingState->setAttribute(OSKEY_OPERAND, binding.first);
436 bindingState->setAttribute(OSKEY_PORT, binding.second->name());
437 }
438
439 // save pipeline
440 operation->addChild(pipeline_->saveState());
441
442 return operation;
443}
444
445
446/**
447 * Loads the state of the operation from the given ObjectState tree.
448 *
449 * @param state The ObjectState tree.
450 * @exception ObjectStateLoadingException If an error occurs while loading
451 * the state.
452 */
453void
455
456 const string procName = "HWOperation::loadState";
457
458 if (state->name() != OSNAME_OPERATION) {
459 throw ObjectStateLoadingException(__FILE__, __LINE__, procName);
460 }
461
462 MOMTextGenerator textGenerator;
463
464 try {
466 } catch (const Exception& exception) {
468 __FILE__, __LINE__, procName, exception.errorMessage());
469 }
470
471 try {
472 // load operand binding map
473 operandBinding_.clear();
474 for (int i = 0; i < state->childCount(); i++) {
475 ObjectState* child = state->child(i);
476 if (child->name() == OSNAME_OPERAND_BINDING) {
477 int operand = child->intAttribute(OSKEY_OPERAND);
478 string portName = child->stringAttribute(OSKEY_PORT);
479
480 if (parentUnit()->hasOperationPort(portName)) {
481 FUPort* port = parentUnit()->operationPort(portName);
482 if (isBound(*port)) {
483 format text = textGenerator.text(
485 text % name() % portName % parentUnit()->name();
487 __FILE__, __LINE__, procName, text.str());
488 } else if (this->port(operand) != NULL) {
489 format text = textGenerator.text(
491 text % operand % portName % name() %
492 parentUnit()->name() %
493 this->port(operand)->name();
495 __FILE__, __LINE__, procName, text.str());
496 } else {
497 bindPort(operand, *port);
498 }
499 } else {
500 format text = textGenerator.text(
502 text % portName % name() % parentUnit()->name();
504 __FILE__, __LINE__, procName, text.str());
505 }
506
507 }
508 }
509
510 // load pipeline
511 if (pipeline_ != NULL) {
512 delete pipeline_;
513 }
514 ObjectState* pipelineState = state->childByName(
516 pipeline_ = new ExecutionPipeline(*this);
517 pipeline()->loadState(pipelineState);
518
519 } catch (const Exception& e) {
521 __FILE__, __LINE__, procName, e.errorMessage());
522 }
523}
524}
#define THROW_EXCEPTION(exceptionType, message)
Exception wrapper macro that automatically includes file name, line number and function name where th...
Definition Exception.hh:39
std::string errorMessage() const
Definition Exception.cc:123
static bool isValidComponentName(const std::string &name)
static KeyType keyForValue(const MapType &aMap, const ValueType &aValue)
static bool removeItemsByValue(MapType &aMap, const ValueType &aValue)
static bool containsKey(const MapType &aMap, const KeyType &aKey)
static bool containsValue(const MapType &aMap, const ValueType &aValue)
ObjectState * childByName(const std::string &name) const
void setAttribute(const std::string &name, const std::string &value)
ObjectState * child(int index) const
void addChild(ObjectState *child)
std::string stringAttribute(const std::string &name) const
int intAttribute(const std::string &name) const
std::string name() const
int childCount() const
static std::string stringToLower(const std::string &source)
FunctionUnit * parentUnit() const
Definition BaseFUPort.cc:96
virtual TCEString name() const
void loadState(const ObjectState *state)
static const std::string OSNAME_PIPELINE
ObjectState name for ExecutionPipeline.
void updateBindingString() const
Definition FUPort.cc:294
virtual void addOperation(HWOperation &operation)
virtual void deleteOperation(HWOperation &operation)
virtual FUPort * operationPort(const std::string &name) const
std::string name_
Name of the operation.
ExecutionPipeline * pipeline_
Pipeline of the operation.
ExecutionPipeline * pipeline() const
virtual void bindPort(int operand, const FUPort &port)
static const std::string OSKEY_NAME
ObjectState attribute key for name of the operation.
virtual void loadState(const ObjectState *state)
virtual void unbindPort(const FUPort &port)
virtual FUPort * port(int operand) const
virtual void setName(const std::string &name)
static const std::string OSKEY_PORT
ObjectState attribute key for port name.
int io(const FUPort &port) const
int slack(int input) const
virtual ObjectState * saveState() const
static const std::string OSKEY_OPERAND
ObjectState attribute key for operand index.
OperandBindingMap operandBinding_
Maps operands of operation to particular ports of the parent unit.
const std::string & name() const
bool isBound(const FUPort &port) const
static const std::string OSNAME_OPERAND_BINDING
ObjectState name for an operand binding.
HWOperation(const std::string &name, FunctionUnit &parent)
FunctionUnit * parentUnit() const
static const std::string OSNAME_OPERATION
ObjectState name for HWOperation.
FunctionUnit * parent_
The parent unit.
virtual bool isInput() const
Definition Port.cc:298
virtual bool isOutput() const
Definition Port.cc:308
virtual std::string name() const
Definition Port.cc:141
virtual boost::format text(int textId)