OpenASIP 2.2
Loading...
Searching...
No Matches
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) \
76public: \
77OPNAME##_Behavior(const Operation& parent) : OperationBehavior(parent) {}; \
78private: \
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) \
91class OPNAME##_Behavior : public OperationBehavior { \
92public: \
93 typedef NullOperationState StateType; \
94private: \
95 StateType* fetchState(const OperationContext&) const { \
96 return NullOperationState::instance(); \
97 }; \
98OPERATION_COMMON(OPNAME) \
99public:
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}; \
133extern "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) \
163class OPNAME##_Behavior : public OperationBehavior { \
164public: \
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 }\
184private: \
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 }\
196OPERATION_COMMON(OPNAME) \
197public:
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) \
215class 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 \
262bool 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 \
506virtual 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