OpenASIP  2.0
OSAL.hh
Go to the documentation of this file.
1 /*
2  Copyright (c) 2002-2015 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 OSAL.hh
26  *
27  * Macro definitions for defining the behavior of operations in
28  * the Operation Set Abstraction Layer.
29  *
30  * Macros expand to derived OperationBehavior class definitions and factory
31  * functions that instantiate these custom classes. The factory functions
32  * constitute the plugin interface.
33  *
34  * @author Pekka Jääskeläinen 2004-2015 (pekka.jaaskelainen-no.spam-tut.fi)
35  * @note This file is used in compiled simulation. Keep dependencies *clean*
36  * @note rating: red
37  */
38 
39 #ifndef TTA_OSAL_LANGUAGE_DEFINITIONS_HH
40 #define TTA_OSAL_LANGUAGE_DEFINITIONS_HH
41 
42 #include <vector>
43 
44 #include "tce_config.h"
45 #include "OperationContext.hh"
46 #include "SimValue.hh"
47 #include "OperationBehavior.hh"
48 #include "Operation.hh"
49 #include "Memory.hh"
50 #include "OperationPool.hh"
51 #include "OperationState.hh"
52 #include "OperationGlobals.hh"
53 
55 
56 
57 /**
58  * OPERATION and OPERATION_WITH_STATE start a definition block for operation
59  * behavior. They expand to a definition of a new OperationBehavior class
60  * with name OPERATION_Behavior (e.g., ADD4_Behavior).
61  *
62  * Argument overloading is not supported by the preprocessor macros, thus we
63  * need two differently named OPERATION macros, OPERATION() and
64  * OPERATION_WITH_STATE().
65  *
66  */
67 
68 /**
69  * OPERATION_COMMON provides definitions that are common to both OPERATION
70  * and OPERATION_WITH_STATE:
71  *
72  * - Constructor with Operation reference (points to the operation the
73  * behavior is defined for).
74  */
75 #define OPERATION_COMMON(OPNAME) \
76 public: \
77 OPNAME##_Behavior(const Operation& parent) : OperationBehavior(parent) {}; \
78 private: \
79  mutable OperationPool opPool_;
80 
81 /**
82  * Operation behavior without state.
83  *
84  * fetchState() is called in the simulation functions to fetch instance of
85  * state (using STATE macro).
86  *
87  * In an operation definition without state, the STATE is set point to
88  * an instance of NullOperationState.
89  */
90 #define OPERATION(OPNAME) \
91 class OPNAME##_Behavior : public OperationBehavior { \
92 public: \
93  typedef NullOperationState StateType; \
94 private: \
95  StateType* fetchState(const OperationContext&) const { \
96  return NullOperationState::instance(); \
97  }; \
98 OPERATION_COMMON(OPNAME) \
99 public:
100 
101 /**
102  * Ends the definition of operation behavior without state.
103  *
104  * This macro expands to a factory/destructor functions for the newly defined
105  * behavior class type. The functions are exported using C symbols so they
106  * are accesible without needing C++ name demangling. These two functions
107  * constitute the plugin interface which are used as an access point to the
108  * definitions in an operation behavior plugin module.
109  *
110  * Factory function returns an instance of the newly defined behavior class.
111  * A reference to the operation the behavior belongs to is given as an
112  * argument. The function is named createOpBehavior_OPERATIONNAME(), e.g.,
113  * createOpBehavior_Add4().
114  *
115  * Destructor function needs to be defined because delete operator can be
116  * overridden in the plugin module and the deletion of the custom operation
117  * behavior instance has to be done using the correct delete operator. The
118  * instance cannot be simply deallocated using delete operator in the client's
119  * code. Function takes a pointer to the object that should be deleted as an
120  * argument. It's named deleteOpBehavior_OPERATIONNAME(), for example,
121  * deleteOpBehavior_Add4().
122  *
123  * The dummy variable in the last line is to force addition of semicolon after
124  * the END_OPERATION() statement in user's code because semicolon is not
125  * allowed after an "extern" block (at least with all compilers).
126  *
127  * The semicolon "policy" is wanted to be consistent with all statements:
128  * the statement that starts the block (e.g., OPERATION()) does not require
129  * semicolon after it, but the block ender (e.g., END_OPERATION()) does.
130  */
131 #define END_OPERATION(OPNAME) \
132 }; \
133 extern "C" { \
134  OperationBehavior* createOpBehavior_##OPNAME(const Operation& parent) {\
135  return new OPNAME##_Behavior(parent);\
136  }\
137  void deleteOpBehavior_##OPNAME(OperationBehavior* target) {\
138  delete target;\
139  }\
140 }
141 
142 /**
143  * Operation behavior with state.
144  *
145  * This definition connects user defined state type to an operation behavior
146  * definition. Connection is implemented with a typedef that sets StateType
147  * type to be the custom type.
148  *
149  * createState() is called by the owner of the custom OperationBehavior
150  * instance, it is used to add a custom state instance to the operation
151  * context to be accessed later. deleteState() is used to remove the
152  * custom state from the context. See the design document for more information.
153  *
154  * In an operation definition with state, the STATE is set to point to
155  * an instance of an OperationState object of a custom defined OperationState
156  * derived type. The instance is fetched from context and dynamic_casted
157  * to the correct type.
158  *
159  * stateExists() helper method tells if an instance of the custom state
160  * already exists in the context.
161  */
162 #define OPERATION_WITH_STATE(OPNAME, STATE_NAME) \
163 class OPNAME##_Behavior : public OperationBehavior { \
164 public: \
165  typedef STATE_NAME##_State StateType;\
166 \
167  void createState(OperationContext& context) const {\
168  if (!stateExists(context)) {\
169  context.registerState(new STATE_NAME##_State(context));\
170  }\
171  }\
172 \
173  void deleteState(OperationContext& context) const {\
174  if (!stateExists(context)) {\
175  return;\
176  }\
177  delete &context.state(#STATE_NAME);\
178  context.unregisterState(#STATE_NAME);\
179  }\
180 \
181  const char* stateName() const {\
182  return #STATE_NAME;\
183  }\
184 private: \
185  StateType* fetchState(const OperationContext& oc) const { \
186  return dynamic_cast<StateType*>(&oc.state(#STATE_NAME)); \
187  } \
188  bool stateExists(OperationContext& context) const {\
189  try {\
190  context.state(#STATE_NAME);\
191  } catch (...) {\
192  return false;\
193  }\
194  return true;\
195  }\
196 OPERATION_COMMON(OPNAME) \
197 public:
198 
199 #define END_OPERATION_WITH_STATE(OPNAME) END_OPERATION(OPNAME)
200 
201 /**
202  * Custom state definition.
203  *
204  * The information of the custom state type used by the OPERATION_WITH_STATE
205  * definition is entered using DEFINE_STATE. The custom state must be defined
206  * with this macro before using it in an OPERATION_WITH_STATE definition.
207  *
208  * Macro expands to a class structure which derives itself from OperationState
209  * and implements the pure virtual method name() trivially by returning the
210  * name of the state as a C string. Rest of the class, which are usually public
211  * member variables, are entered by the user.
212  *
213  */
214 #define DEFINE_STATE(STATE_NAME) \
215 class STATE_NAME##_State : public OperationState { \
216  public: \
217  const char* name() { return #STATE_NAME; };
218 
219 #define END_DEFINE_STATE };
220 
221 
222 /**
223  * Custom state initialization.
224  *
225  * If the state data needs to be initialized before use, INIT_STATE can be used
226  * to define a constructor to the state class. isEmpty call is to avoid warning
227  * about unused parameter.
228  */
229 #define INIT_STATE(STATE_NAME) \
230  public: STATE_NAME##_State(OperationContext& context) { \
231  context.isEmpty();
232 
233 #define END_INIT_STATE }
234 
235 
236 /**
237  * Custom state deallocation.
238  *
239  * If the state data needs to be deallocated when state instance is deleted,
240  * FINALIZE_STATE can be used to define a destructor to the state class.
241  */
242 #define FINALIZE_STATE(STATE_NAME) \
243  public: ~STATE_NAME##_State() {
244 
245 #define END_FINALIZE_STATE }
246 
247 
248 /**
249  * Simulation function definition macros.
250  *
251  * Each simulation function fetches the state instance using fetchState() in
252  * the beginning of the function definition.
253  */
254 
255 /**
256  * Starts the definition block for a trigger simulation function.
257  *
258  * "if (&context ..." is an ugly hack to avoid compiler warning
259  * when context is not used.
260  */
261 #define TRIGGER \
262 bool simulateTrigger( \
263  SimValue** io, \
264  OperationContext& context) const { \
265  (void)context; \
266  if (io == 0) { }
267 
268 /**
269  * Fetches the state instance.
270  */
271 #define STATE (*fetchState(context))
272 
273 
274 /**
275  * Ends the definition block for trigger simulation function.
276  */
277 #define END_TRIGGER return true; }
278 
279 /**
280  * Starts the definition block for the state clock advancing simulation
281  * function.
282  *
283  * "if (&context ..." is an ugly hack to avoid compiler warning
284  * when context is not used.
285  *
286  */
287 #define ADVANCE_CLOCK \
288  void advanceClock(OperationContext& context) { \
289  (void)context;
290 
291 /**
292  * Ends the definition block for the clock advancing simulation function.
293  */
294 #define END_ADVANCE_CLOCK }
295 
296 /**
297  * Explicit return statements for simulation function definitions.
298  */
299 
300 /**
301  * RETURN_READY is not needed anymore, macro is deprecated.
302  */
303 #define RETURN_READY
304 
305 /**
306  * Operand value accessor macros for different types.
307  *
308  * Each accessor macro accesses the corresponding type of value_ union of
309  * the operand SimValue. The value is a copy and thus can be only used
310  * as a rvalue of an assignment.
311  */
312 #define INT(OPERAND) (io[(OPERAND) - 1]->intValue())
313 #define UINT(OPERAND) (io[(OPERAND) - 1]->unsignedValue())
314 #define LONG(OPERAND) (io[(OPERAND) - 1]->sLongWordValue())
315 #define ULONG(OPERAND) (io[(OPERAND) - 1]->uLongWordValue())
316 #define FLT(OPERAND) (io[(OPERAND) - 1]->floatWordValue())
317 #define DBL(OPERAND) (io[(OPERAND) - 1]->doubleWordValue())
318 #define HFLT(OPERAND) (io[(OPERAND) -1]->halfFloatWordValue())
319 
320 /**
321  * Operand value accessor macros for raw data field in value_ of SimValue.
322  *
323  * Needed for vector operations to access subwords.
324  */
325 #define SUBWORD1(OPERAND, ELEMENT) \
326  (io[(OPERAND) - 1]->bitElement(ELEMENT))
327 #define SUBWORD8(OPERAND, ELEMENT) \
328  (io[(OPERAND) - 1]->byteElement(ELEMENT))
329 #define SUBWORD16(OPERAND, ELEMENT) \
330  (io[(OPERAND) - 1]->halfWordElement(ELEMENT))
331 #define SUBWORD32(OPERAND, ELEMENT) \
332  (io[(OPERAND) - 1]->wordElement(ELEMENT))
333 #define SET_SUBWORD1(OPERAND, ELEMENT, VALUE) \
334  (io[(OPERAND) - 1]->setBitElement(ELEMENT, VALUE))
335 #define SET_SUBWORD8(OPERAND, ELEMENT, VALUE) \
336  (io[(OPERAND) - 1]->setByteElement(ELEMENT, VALUE))
337 #define SET_SUBWORD16(OPERAND, ELEMENT, VALUE) \
338  (io[(OPERAND) - 1]->setHalfWordElement(ELEMENT, VALUE))
339 #define SET_SUBWORD32(OPERAND, ELEMENT, VALUE) \
340  (io[(OPERAND) - 1]->setWordElement(ELEMENT, VALUE))
341 
342 #define SUBFLOAT16(OPERAND, ELEMENT) \
343  (io[(OPERAND) - 1]->halfFloatElement(ELEMENT))
344 #define SUBFLOAT32(OPERAND, ELEMENT) \
345  (io[(OPERAND) - 1]->floatElement(ELEMENT))
346 #define SUBFLOAT64(OPERAND, ELEMENT) \
347  (io[(OPERAND) - 1]->doubleFloatElement(ELEMENT))
348 
349 #define SET_SUBFLOAT16(OPERAND, ELEMENT, VALUE) \
350  (io[(OPERAND) - 1]->setHalfFloatElement(ELEMENT, VALUE))
351 #define SET_SUBFLOAT32(OPERAND, ELEMENT, VALUE) \
352  (io[(OPERAND) - 1]->setFloatElement(ELEMENT, VALUE))
353 #define SET_SUBFLOAT64(OPERAND, ELEMENT, VALUE) \
354  (io[(OPERAND) - 1]->setDoubleWordElement(ELEMENT, VALUE))
355 
356 /**
357  * Operand accessor macro.
358  *
359  * This macro must be used as lvalue when assigning values to output operands.
360  */
361 #define IO(OPERAND) (*io[(OPERAND) - 1])
362 
363 /**
364  * Macro for obtaining the bit width of the port the operand is bound to.
365  */
366 #define BWIDTH(OPERAND) (((io[(OPERAND) - 1])->width()))
367 
368 /**
369  * Access the program counter register.
370  */
371 #define PROGRAM_COUNTER (context.programCounter())
372 
373 /**
374  * Updates the program counter. This includes transport delay (the number
375  * of delay slots in the machine).
376  */
377 #define SET_PROGRAM_COUNTER(PCVAL) \
378  context.programCounter() = (PCVAL); \
379  context.setUpdateProgramCounter(true)
380 
381 /**
382  * Instruct the GCU to save the return address register.
383  */
384 #define SAVE_RETURN_ADDRESS context.setSaveReturnAddress(true)
385 
386 /**
387  * Access the return address register.
388  */
389 #define RETURN_ADDRESS (context.returnAddress())
390 
391 /**
392  * Access the unique id of the operation context.
393  */
394 #define CONTEXT_ID (context.contextId())
395 
396 /**
397  * Memory interface.
398  */
399 
400 /**
401  * Get the width of the minimum addressable unit of the memory.
402  */
403 #define MAU_SIZE (context.memory().MAUSize())
404 
405 /**
406  * Accesses the memory instance connected to the operation's FU.
407  */
408 #define MEMORY context.memory()
409 
410 /**
411  * Sign extends the given integer.
412  *
413  * Sign extension means that the sign bit of the source word is duplicated
414  * to the extra bits provided by the wider target destination word.
415  *
416  * Example:
417  *
418  * SRC: 1 0010b (5 bits)
419  * DST: 1111 0010b (8 bits)
420  *
421  * The first argument is the integer that should be sign extended.
422  * The second argument is the bit width of the source argument.
423  * In the previous example, the bit width is 5. This is used to figure out
424  * which is the sign bit. Returns a sign extended (to 64 bits) IntWord.
425  */
426 #define SIGN_EXTEND(VALUE, WIDTH) \
427  ((SLongWord)((SLongWord(VALUE) << (64-(WIDTH))) >> (64-(WIDTH))))
428 
429 /**
430  * Zero extends the given integer.
431  *
432  * Zero extension means that the extra bits of the wider target destination
433  * word are set to zero.
434  *
435  * Example:
436  *
437  * SRC: 1 0010b (5 bits)
438  * DST: 0001 0010b (8 bits)
439  *
440  * The first argument is the integer that should be zero extended.
441  * Second argument is the bit width of the source argument.
442  * In the previous example, the bit width is 5. This is used to figure out
443  * which bits to reset in the destination. Returns a zero extended
444  * (to 64 bits) IntWord.
445  */
446 #define ZERO_EXTEND(VALUE, WIDTH) \
447  ((ULongWord(VALUE) << (64-(WIDTH))) >> (64-(WIDTH)))
448 
449 /**
450  * Provides access to the output stream which can be used to print out debug
451  * information to simulator console, or, for example, to simulate output from
452  * the TTA.
453  *
454  * Default output stream is std::cout.
455  */
456 #define OUTPUT_STREAM OperationGlobals::outputStream()
457 
458 /**
459  * Maximum bit width of the inputs and outputs currently fully supported by
460  * behaviour models of base operations.
461  */
462 #define OSAL_WORD_WIDTH sizeof(ULongWord) * BYTE_BITWIDTH
463 
464 
465 /**
466  * Causes runtime error with given error explanation message.
467  *
468  * Can be used to abort simulation in case of illegal operands etc.
469  */
470 #define RUNTIME_ERROR(MESSAGE) OperationGlobals::runtimeError(\
471  MESSAGE, __FILE__, __LINE__, parent_);
472 
473 /**
474  * Executes operation.
475  */
476 #define EXEC_OPERATION(OPNAME, ...) \
477  const Operation& __used_in_macro_temp__ = opPool_.operation(#OPNAME); \
478  executeOperation(__used_in_macro_temp__.behavior(), context, __VA_ARGS__);
479  #define OP(OPNAME, ...) \
480  const Operation& __used_in_macro_temp__ = opPool_.operation(#OPNAME); \
481  executeOperation(__used_in_macro_temp__.behavior(), context, __VA_ARGS__);
482 
483 
484 #endif
485 
486 /**
487  * Returns the cycle count since the beginning of simulation.
488  */
489 #define CYCLE_COUNT (context.cycleCount())
490 
491 /**
492  * Returns the function unit name associated to the OperationContext.
493  */
494 #define FU_NAME (context.functionUnitName())
495 
496 /**
497  * Returns the delay cycle amount caused by pipeline length.
498  */
499 #define BRANCH_DELAY_CYCLES (context.branchDelayCycles())
500 
501 
502 /**
503  * Opening macro for user defined input validation code.
504  */
505 #define INPUT_VALIDATION \
506 virtual bool areValid( \
507  const OperationBehavior::InputOperandVector& inputs, \
508  const OperationContext& context) const { \
509  (void)context; \
510  (void)inputs; \
511  std::vector<const SimValue*> io; \
512  for (size_t i = 0; i < inputs.size(); i++) { \
513  const SimValue* tmp = &inputs.at(i); \
514  io.push_back(tmp); \
515  }
516 
517 /**
518  * Closing macro for user defined input validation code.
519  */
520 #define END_INPUT_VALIDATION \
521  return false; \
522 }
523 
524 /**
525  * Macro to accept given inputs in the user validation code.
526  */
527 #define DECLARE_VALID \
528  return true
529 
Memory.hh
OperationState.hh
SimulateTriggerWrappers.icc
Operation.hh
OperationBehavior.hh
SimValue.hh
OperationPool.hh
OperationContext.hh
OperationGlobals.hh