OpenASIP  2.0
UniversalFunctionUnit.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 UniversalFunctionUnit.cc
26  *
27  * Implementation of UniversalFunctionUnit class.
28  *
29  * @author Lasse Laasonen 2004 (lasse.laasonen-no.spam-tut.fi)
30  * @author Pekka Jääskeläinen 2006 (pekka.jaaskelainen-no.spam-tut.fi)
31  * @note rating: yellow
32  */
33 
34 #include "UniversalFunctionUnit.hh"
35 #include "UniversalMachine.hh"
36 #include "UniversalFUPort.hh"
37 #include "HWOperation.hh"
38 #include "SmartHWOperation.hh"
39 #include "OperationPool.hh"
40 #include "Operation.hh"
41 #include "TCEString.hh"
42 #include "Conversion.hh"
43 
44 using std::string;
45 using namespace TTAMachine;
46 
47 const string UniversalFunctionUnit::OC_SETTING_PORT_32 = "OCSetting32";
48 const string UniversalFunctionUnit::OC_SETTING_PORT_64 = "OCSetting64";
50  "ADD", "SUB", "LDW", "LDQ", "LDH", "STW", "STQ", "STH", "EQ", "GT",
51  "GTU", "SHL", "SHR", "SHRU", "AND", "IOR", "XOR", "SYS", "JUMP", "CALL",
52  "MIN", "MAX", "MINU", "MAXU", "SXQW", "SXHW", "NEG", "MUL", "DIV",
53  "DIVU", "CFI", "CIF", "ROTL", "ROTR", "ABS", "LDQU", "LDHU"};
54 
55 
56 /**
57  * The constructor.
58  *
59  * @param name Name of the function unit.
60  * @param opPool The operation pool from which the operations are obtained on
61  * demand.
62  * @exception InvalidName If the given name is not a valid component name.
63  */
65  const std::string& name, OperationPool& opPool)
66  : FunctionUnit(name), opPool_(opPool) {}
67 
68 /**
69  * The destructor.
70  */
72 }
73 
74 
75 /**
76  * Tells whether the universal function unit has an operation of the given
77  * name.
78  *
79  * Returns true even if the operation is not loaded yet but it exists in
80  * the operation pool.
81  *
82  * @param name Name of the operation.
83  */
84 bool
85 UniversalFunctionUnit::hasOperation(const std::string& name) const {
86  return &opPool_.operation(name.c_str()) != &NullOperation::instance();
87 }
88 
89 
90 /**
91  * Returns an operation by the given name.
92  *
93  * Adds the operation to the function unit if it doen't exist yet but
94  * exist in the operation pool.
95  *
96  * @param name Name of the operation.
97  * @exception InstanceNotFound If an operation by the given name does not
98  * exist in the operation pool.
99  * @return The operation.
100  */
102 UniversalFunctionUnit::operation(const std::string& name) const {
103  const string procName = "UniversalFunctionUnit::operation";
104 
105  if (FunctionUnit::hasOperation(name)) {
106  return FunctionUnit::operation(name);
107  } else {
108  Operation& oper = opPool_.operation(name.c_str());
109 
110  if (&oper == &NullOperation::instance()) {
111  throw InstanceNotFound(__FILE__, __LINE__, procName);
112  } else {
113  // need to take non-const pointer of this FU to call non-const
114  // method addOperation
115  UniversalFunctionUnit* thisFU =
116  const_cast<UniversalFunctionUnit*>(this);
117  SmartHWOperation& hwOper = thisFU->addSupportedOperation(oper);
118  return &hwOper;
119  }
120  }
121 }
122 
123 /**
124  * Aborts the program. It should not be needed to add pipeline
125  * elements to universal function unit.
126  *
127  * @param element Never used.
128  * @exception ComponentAlreadyExists Never thrown.
129  */
130 void
132  const string procName = "UniversalFunctionUnit::addPipelineElement";
133  const string errorMsg =
134  "Tried to add pipeline element to UniversalFunctionUnit!";
135  Application::writeToErrorLog(__FILE__, __LINE__, procName, errorMsg);
137 }
138 
139 /**
140  * Aborts the program. It is not allowed to load UniversalFunctionUnit from
141  * an ObjectState instance. DO NOT CALL THIS METHOD!
142  *
143  * @param state Never used.
144  * @exception ObjectStateLoadingException Never thrown.
145  */
146 void
148  const string procName = "UniversalFunctionUnit::loadState";
149  const string errorMsg =
150  "Tried to load state of UniversalFunctionUnit from an ObjectState "
151  "tree!";
152  Application::writeToErrorLog(__FILE__, __LINE__, procName, errorMsg);
154 }
155 
156 /**
157  * Returns the number of ports of the given bit width.
158  *
159  * @param width The bit width.
160  * @return The number of ports of the given bit width.
161  * @exception OutOfRange If the given bit width is out of range.
162  */
163 int
165  if (width < 1) {
166  const string procName = "UniversalFunctionUnit::portCount";
167  throw OutOfRange(__FILE__, __LINE__, procName);
168  }
169 
170  int count(0);
171 
172  for (int i = 0; i < FunctionUnit::portCount(); i++) {
173  if (FunctionUnit::port(i)->width() == width) {
174  count++;
175  }
176  }
177 
178  return count;
179 }
180 
181 /**
182  * By the given index, returns a port which has the given bit width.
183  *
184  * @param index The index.
185  * @param width The bit width.
186  * @return A port of the given bit width.
187  * @exception OutOfRange If the given bit width or index is out of range.
188  */
189 FUPort&
190 UniversalFunctionUnit::portWithWidth(int index, int width) const {
191  if (width < 1 || index >= portCountWithWidth(width)) {
192  const string procName = "UniversalFunctionUnit::port";
193  throw OutOfRange(__FILE__, __LINE__, procName);
194  }
195 
196  int count(0);
197  int portC = portCount();
198  for (int i = 0; i < portC; i++) {
199  auto p = port(i);
201  dynamic_cast<FUPort*>(p);
202  if (p != nullptr && port->width() == width) {
203  count++;
204  if (count > index) {
205  return *port;
206  }
207  }
208  }
209 
210  assert(false);
211 
212  // dummy return to avoid compilation warning
213  FUPort* port = NULL;
214  return *port;
215 }
216 
217 /**
218  * Adds the given operation to the function unit.
219  *
220  * Adds input and/or output ports if there is not enough ports for the
221  * operands of the given operation. Operand bindings and pipeline are not
222  * created.
223  *
224  * @param operation The operation to be added.
225  * @return The added operation.
226  */
229 
230  int inputCount = operation.numberOfInputs();
231  int outputCount = operation.numberOfOutputs();
232 
233  int operandWidth = is32BitOperation(operation.name()) ? 32 : 64;
234 
235  ensureInputPorts(operandWidth, inputCount);
236  ensureOutputPorts(operandWidth, outputCount);
237 
238  // create the operation
239  SmartHWOperation* hwOper = NULL;
240  try {
241  hwOper = new SmartHWOperation(operation, *this);
242  return *hwOper;
243  } catch (const InvalidName& exception) {
244  const string procName = "UniversalFunctionUnit::addOperation";
245  const string errorMsg =
246  "Operation pool contained an operation with illegal"
247  "name: " + string(operation.name());
248  Application::writeToErrorLog(__FILE__, __LINE__, procName, errorMsg);
250  } catch (...) {
251  assert(false);
252  }
253 
254  assert(false);
255 
256  // dummy return to avoid compilation warning
257  return *hwOper;
258 }
259 
260 
261 /**
262  * Ensures that there is at least the given number of input ports of the
263  * given width.
264  *
265  * Adds input ports if there is not enough ports.
266  *
267  * @param width Bit width of the ports to be ensured.
268  * @param count The number of ports to be ensured.
269  */
270 void
272 
273  assert(width == 32 || width == 64);
274 
275  Socket* inputSocket = machine()->socketNavigator().item(
277 
278  int portCount = this->portCountWithWidth(width);
279 
280  // create opcode setting port if there are no ports at all
281  if (count > 0 && portCount == 0) {
282  string portName =
283  width == 32 ? OC_SETTING_PORT_32 : OC_SETTING_PORT_64;
284  FUPort* ocPort = new UniversalFUPort(
285  portName, width, *this, true, true);
286  portCount++;
287  ocPort->attachSocket(*inputSocket);
288  }
289 
290  // check the amount of matches
291  int matches(1);
292  for (int i = 1; i < portCount; i++) {
293  FUPort& port = this->portWithWidth(i, width);
294  assert(port.width() == width);
295  if (port.inputSocket() != NULL) {
296  matches++;
297  }
298  }
299 
300  // create new ports as necessary
301  while (matches < count) {
302  string portName = "i" + Conversion::toString(width) + "_" +
303  Conversion::toString(matches);
304  FUPort* newPort = new UniversalFUPort(
305  portName, width, *this, false, false);
306  newPort->attachSocket(*inputSocket);
307  matches++;
308  }
309 }
310 
311 
312 /**
313  * Ensures that there is at least the given number of output ports of the
314  * given width.
315  *
316  * Adds output ports if there is not enough ports.
317  *
318  * @param width Bit width of the ports to be ensured.
319  * @param count The number of ports to be ensured.
320  */
321 void
323 
324  Socket* outputSocket =
326 
327  // check the amount of matches
328  int matches(0);
329  for (int i = 0; i < portCountWithWidth(width); i++) {
330  FUPort& port = this->portWithWidth(i, width);
331  assert(port.width() == width);
332  if (port.outputSocket() != NULL) {
333  matches++;
334  }
335  }
336 
337  // create new ports as necessary
338  while (matches < count) {
339  string portName = "output" + Conversion::toString(width) + "_" +
340  Conversion::toString(matches + 1);
341  FUPort* newPort = new UniversalFUPort(
342  portName, width, *this, false, false);
343  newPort->attachSocket(*outputSocket);
344  matches++;
345  }
346 }
347 
348 
349 /**
350  * Tells whether operation of the given name has 32 bits wide operands and
351  * return value.
352  *
353  * @param opName Name of the operation.
354  * @return True if the operation has 32 bits wide operands and return value,
355  * otherwise false.
356  */
357 bool
358 UniversalFunctionUnit::is32BitOperation(const std::string& opName) {
359  int numberOfElements = sizeof(OPERATIONS_OF_32_BITS) / sizeof(string);
360  for (int i = 0; i < numberOfElements; i++) {
361  if (OPERATIONS_OF_32_BITS[i] == opName) {
362  return true;
363  }
364  }
365  return false;
366 }
UniversalFunctionUnit::ensureInputPorts
void ensureInputPorts(int width, int count)
Definition: UniversalFunctionUnit.cc:271
UniversalFunctionUnit::operation
virtual TTAMachine::HWOperation * operation(const std::string &name) const
Definition: UniversalFunctionUnit.cc:102
OperationPool::operation
Operation & operation(const char *name)
Definition: OperationPool.cc:99
TTAMachine::Port::inputSocket
virtual Socket * inputSocket() const
Definition: Port.cc:261
UniversalFunctionUnit::OC_SETTING_PORT_32
static const std::string OC_SETTING_PORT_32
Name of the 32 bit wide opcode setting port.
Definition: UniversalFunctionUnit.hh:66
UniversalFunctionUnit::is32BitOperation
static bool is32BitOperation(const std::string &opName)
Definition: UniversalFunctionUnit.cc:358
UniversalFunctionUnit::portCountWithWidth
int portCountWithWidth(int width) const
Definition: UniversalFunctionUnit.cc:164
TTAMachine::Component::name
virtual TCEString name() const
Definition: MachinePart.cc:125
UniversalFunctionUnit::ensureOutputPorts
void ensureOutputPorts(int width, int count)
Definition: UniversalFunctionUnit.cc:322
TTAMachine::HWOperation
Definition: HWOperation.hh:52
UniversalFunctionUnit::portWithWidth
TTAMachine::FUPort & portWithWidth(int index, int width) const
Definition: UniversalFunctionUnit.cc:190
Application::writeToErrorLog
static void writeToErrorLog(const std::string fileName, const int lineNumber, const std::string functionName, const std::string message, const int neededVerbosity=0)
Definition: Application.cc:224
OutOfRange
Definition: Exception.hh:320
UM_INPUT_SOCKET_NAME
#define UM_INPUT_SOCKET_NAME
Definition: UniversalMachine.hh:108
ObjectState
Definition: ObjectState.hh:59
UniversalFunctionUnit
Definition: UniversalFunctionUnit.hh:50
TTAMachine::FunctionUnit::port
virtual BaseFUPort * port(const std::string &name) const
Definition: FunctionUnit.cc:145
UniversalFunctionUnit::OC_SETTING_PORT_64
static const std::string OC_SETTING_PORT_64
Name of the 64 bit wide opcode setting port.
Definition: UniversalFunctionUnit.hh:68
SmartHWOperation
Definition: SmartHWOperation.hh:47
NullOperation::instance
static NullOperation & instance()
Conversion::toString
static std::string toString(const T &source)
TCEString.hh
UniversalFUPort
Definition: UniversalFUPort.hh:47
assert
#define assert(condition)
Definition: Application.hh:86
TTAMachine::FunctionUnit
Definition: FunctionUnit.hh:55
TTAMachine::Port::attachSocket
virtual void attachSocket(Socket &socket)
Definition: Port.cc:191
UniversalMachine.hh
TTAMachine::FUPort
Definition: FUPort.hh:46
UniversalFunctionUnit::OPERATIONS_OF_32_BITS
static const std::string OPERATIONS_OF_32_BITS[]
Table of names of 32 bit operations.
Definition: UniversalFunctionUnit.hh:78
SmartHWOperation.hh
HWOperation.hh
InvalidName
Definition: Exception.hh:827
TTAMachine::HWOperation::name
const std::string & name() const
Definition: HWOperation.cc:141
UniversalFunctionUnit.hh
Conversion.hh
TTAMachine::Socket
Definition: Socket.hh:53
TTAMachine::HWOperation::numberOfInputs
int numberOfInputs() const
Definition: HWOperation.cc:384
Operation.hh
TTAMachine::Machine::socketNavigator
virtual SocketNavigator socketNavigator() const
Definition: Machine.cc:368
TTAMachine::Unit::portCount
virtual int portCount() const
Definition: Unit.cc:135
Operation
Definition: Operation.hh:59
UniversalFunctionUnit::hasOperation
virtual bool hasOperation(const std::string &name) const
Definition: UniversalFunctionUnit.cc:85
UniversalFUPort.hh
UniversalFunctionUnit::addPipelineElement
virtual void addPipelineElement(TTAMachine::PipelineElement &element)
Definition: UniversalFunctionUnit.cc:131
TTAMachine::PipelineElement
Definition: PipelineElement.hh:46
UniversalFunctionUnit::opPool_
OperationPool & opPool_
Operation pool from which the operations are searched.
Definition: UniversalFunctionUnit.hh:76
TTAMachine::Component::machine
virtual Machine * machine() const
UniversalFunctionUnit::loadState
virtual void loadState(const ObjectState *state)
Definition: UniversalFunctionUnit.cc:147
UniversalFunctionUnit::UniversalFunctionUnit
UniversalFunctionUnit(const std::string &name, OperationPool &opPool)
Definition: UniversalFunctionUnit.cc:64
TTAMachine::Port::outputSocket
virtual Socket * outputSocket() const
Definition: Port.cc:281
UniversalFunctionUnit::~UniversalFunctionUnit
virtual ~UniversalFunctionUnit()
Definition: UniversalFunctionUnit.cc:71
TTAMachine::Machine::Navigator::item
ComponentType * item(int index) const
TTAMachine::HWOperation::numberOfOutputs
int numberOfOutputs() const
Definition: HWOperation.cc:404
OperationPool
Definition: OperationPool.hh:52
TTAMachine
Definition: Assembler.hh:48
Application::abortProgram
static void abortProgram() __attribute__((noreturn))
Definition: Application.cc:266
UM_OUTPUT_SOCKET_NAME
#define UM_OUTPUT_SOCKET_NAME
Definition: UniversalMachine.hh:109
OperationPool.hh
TTAMachine::BaseFUPort::width
virtual int width() const
Definition: BaseFUPort.cc:109
InstanceNotFound
Definition: Exception.hh:304
UniversalFunctionUnit::addSupportedOperation
SmartHWOperation & addSupportedOperation(const Operation &operation)
Definition: UniversalFunctionUnit.cc:228