OpenASIP 2.2
Loading...
Searching...
No Matches
POMGenMacros.hh
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 POMGenMacros.hh
26 *
27 * A macro set and helper functions for implementing the macros
28 * to make creating of Program Object Models for unit tests manually
29 * easy.
30 *
31 * @author Pekka Jääskeläinen 2005 (pjaaskel-no.spam-cs.tut.fi)
32 */
33#ifndef TTA_POMGEN_MACROS
34#define TTA_POMGEN_MACROS
35
36
37#include "UniversalMachine.hh"
38#include "Program.hh"
39#include "Procedure.hh"
40#include "Instruction.hh"
41#include "Move.hh"
42#include "MoveGuard.hh"
43#include "Guard.hh"
44#include "Terminal.hh"
45#include "TerminalImmediate.hh"
46#include "TerminalRegister.hh"
47
48#include "SimValue.hh"
49#include "OperationPool.hh"
50#include "Application.hh"
53#include "SmartHWOperation.hh"
54#include "FUPort.hh"
55#include "TerminalFUPort.hh"
56#include "BaseFUPort.hh"
57#include "Port.hh"
58#include "Guard.hh"
60#include "RegisterFile.hh"
61#include "FunctionUnit.hh"
62#include "ControlUnit.hh"
63#include "AssocTools.hh"
64#include "StringTools.hh"
65#include "Conversion.hh"
66
67
68/// define this to get the programs printed to stdout while they are
69/// contructed
70#ifdef PRINT_PROGRAMS
71# define PRINTOUT(STUFF) Application::logStream() << STUFF
72#else
73# define PRINTOUT(STUFF)
74#endif
75
77
78/**
79 * A procedure that does nothing.
80 */
81void null__() {
82}
83
84/**
85 * Helper function which finds a register file in the machine.
86 *
87 * Aborts with error if the register file is not found.
88 *
89 * @param machine The machine to search in.
90 * @param name The name of the register file.
91 * @return The found register file.
92 */
94findRegisterFile(const TTAMachine::Machine& machine, std::string name) {
95
96 if (dynamic_cast<const UniversalMachine*>(&machine) != NULL) {
97 if (StringTools::ciEqual(name, "r")) {
98 return dynamic_cast<const UniversalMachine&>(
99 machine).integerRegisterFile();
100 } else
101 if (StringTools::ciEqual(name, "f")) {
102 return dynamic_cast<const UniversalMachine&>(
103 machine).doubleRegisterFile();
104 }
105 abortWithError(std::string("No register file ") + name + " found.");
106 } else {
109 return *nav.item(name);
110 }
111
112 abortWithError("Can't find register file " + name);
113 // just to avoid compiler warnings
114 throw 1;
115}
116
117/**
118 * Creates a TerminalRegister using the given register file and register.
119 *
120 * @param RFNAME The register file name (either 'r' or 'f' in sequential).
121 * @param REGNUM The index of the register.
122 */
123#define REG(RFNAME, REGNUM) \
124 new TerminalRegister(\
125 *findRegisterFile(machine__, #RFNAME).port(0), \
126 REGNUM);\
127 PRINTOUT(#RFNAME "" #REGNUM)
128/**
129 * Shortcut to an integer register in sequential code.
130 *
131 * @param REGNUM The integer register index.
132 */
133#define IREG(REGNUM) \
134 REG(r, REGNUM)
135
136/**
137 * Helper function which finds a function unit in the machine.
138 *
139 * Aborts with error if the function unit is not found.
140 *
141 * @param machine The machine to search in.
142 * @param name The name of the function unit. Can be empty in sequential.
143 * @return The found register file.
144 */
147 if (dynamic_cast<const UniversalMachine*>(&machine) != NULL) {
148 return dynamic_cast<const UniversalMachine&>(
149 machine).universalFunctionUnit();
150 } else {
153 return *nav.item(name);
154 }
155}
156
157/**
158 * Creates terminal of given parameters.
159 */
163 std::string fuName, std::string pName, std::string opName) {
164
166 TTAMachine::HWOperation *op = NULL;
167
168 if (fu.hasOperation(opName)) {
169 op = fu.operation(opName);
170 } else {
171 op = new TTAMachine::HWOperation(opName, fu);
172 }
173
174 int index = 0;
175
176 try {
177 index = Conversion::toInt(pName);
178 } catch ( ... ) {
179 index = op->io(*fu.operationPort(pName));
180 }
181
182 return new TTAProgram::TerminalFUPort(*op, index);
183}
184
185/**
186 * Helper function which finds a port in a function unit.
187 *
188 * Aborts with error if the port is not found.
189 *
190 * @param machine The machine to search in.
191 * @param fuName The name of the function unit. The operation, if sequential.
192 * @param portName The name of the port. The operand, if sequential code.
193 * @return The found port.
194 */
198 std::string fuName,
199 std::string portName) {
200
201 if (dynamic_cast<const UniversalMachine*>(&machine) != NULL) {
202 return *dynamic_cast<const UniversalMachine&>(machine).
203 universalFunctionUnit().operation(fuName)->port(
204 Conversion::toInt(portName));
205 } else {
206 return *findFunctionUnit(machine, fuName).port(portName);
207 }
208}
209
210/**
211 * Creates a TerminalFUPort using the given name strings.
212 *
213 * @param FUNAME The function unit or operation name (in sequential).
214 * @param PORTNAME The port name or operand index (in sequential).
215 */
216#define PORT(FUNAME, PORTNAME) \
217 new TerminalFUPort( \
218 dynamic_cast<BaseFUPort&>( \
219 findFUPort(machine__, #FUNAME, #PORTNAME)));\
220 PRINTOUT(#FUNAME "." #PORTNAME)
221
222/**
223 * Creates a TerminalFUPort using the given name strings.
224 *
225 * @param FUNAME The function unit or operation name (in sequential).
226 * @param PORTNAME The port name or operand index (in sequential).
227 * @param OPERATION The name of the operation.
228 */
229#define OPORT(FUNAME, PORTNAME, OPERATION) \
230 createTerminalFUPort( \
231 machine__, #FUNAME, #PORTNAME, #OPERATION);\
232 PRINTOUT(#FUNAME "." #OPERATION "." #PORTNAME)
233
234
235/**
236 * A shortcut to an operand in sequential code.
237 *
238 * @param OPERATION The name of the operation.
239 * @param OPERAND_INDEX Index of the operand.
240 */
241#define OPERAND(OPERATION, OPERAND_INDEX) \
242 OPORT(OPERATION, OPERAND_INDEX, OPERATION)
243
244/**
245 * Creates a temporary SimValue to be used in TerminalImmediate construction.
246 *
247 * @param bitWidth The bit width of the SimValue.
248 * @param intValue The integer value of the SimValue.
249 * @return A SimValue reference (owned by the function).
250 */
252tempSimValue(unsigned int bitWidth, SIntWord intValue) {
253 delete temporary;
254 temporary = new SimValue(bitWidth);
255 *temporary = intValue;
256 return *temporary;
257}
258
259/**
260 * Helper function which finds a bus in a machine.
261 *
262 * Aborts with error if the bus is not found.
263 *
264 * @param machine The machine to search in.
265 * @param busName The name of the bus. Unused in case of UniversalMachine.
266 * @return The found bus.
267 */
269findBus(const TTAMachine::Machine& machine, std::string busName) {
270 if (dynamic_cast<const UniversalMachine*>(&machine) != NULL) {
271 return dynamic_cast<const UniversalMachine&>(machine).universalBus();
272 } else {
274 return *nav.item(busName);
275 }
276}
277
278/**
279 * Creates a TerminalImmediate by width and value.
280 *
281 * Expects the creator to manage deallocation.
282 *
283 * @param WIDTH The bit width of the value.
284 * @param VALUE The value of the immediate.
285 */
286#define IMM(WIDTH, VALUE) \
287 new TerminalImmediate(tempSimValue(WIDTH, VALUE)); \
288 PRINTOUT("#" #VALUE)
289
290/**
291 * Creates a TerminalFUPort that writes to the GCU operand port, thus
292 * triggering a control flow operation.
293 *
294 * @param OPERATION The name of the operation to trigger.
295 * @param OPNUM The operand number.
296 */
297#define CONTROL_OPERAND(OPERATION, OPNUM) \
298 new TerminalFUPort( \
299 *machine__.controlUnit()->operation(#OPERATION), \
300 OPNUM);\
301 PRINTOUT(#OPERATION "." #OPNUM)
302
303/**
304 * Helper function which finds the boolean register file in the machine.
305 *
306 * Aborts with error if the boolean register file is not found.
307 *
308 * @param machine The machine to search in.
309 * @return The found register file.
310 */
313
316
317 // go through all the register files in the machine
318 for (int i = 0; i < navigator.count(); ++i) {
319 TTAMachine::RegisterFile& rf = *navigator.item(i);
320
321 // expect the boolean register to be the first register file with
322 // only one register of width 1
323 if (rf.width() == 1 && rf.numberOfRegisters() == 1) {
324 return rf;
325 }
326 }
327 // just to avoid compiler warnings
328 abortWithError("Can't find boolean register file from machine!.");
329 throw 1;
330}
331
332/**
333 * Helper function which finds either normal or inverted guard pointing
334 * to boolean register
335 *
336 * Aborts with error if the boolean register file is not found.
337 *
338 * @param machine The machine to search in.
339 * @param isInverted Do we look for inverted guard.
340 * @return The found Guard
341 */
344
346
347 // go through all the register files in the machine
348 for (int i = 0; i < bus->guardCount(); ++i) {
349 TTAMachine::RegisterGuard *regGuard =
350 dynamic_cast<TTAMachine::RegisterGuard*>(bus->guard(i));
351
352 if (regGuard == NULL) {
353 continue;
354 }
355
356 if (regGuard->isInverted() == isInverted &&
357 regGuard->registerFile()->width() == 1 &&
358 regGuard->registerFile()->numberOfRegisters() == 1) {
359 return *regGuard;
360 }
361 }
362
363 // just to avoid compiler warnings
364 abortWithError("Can't find BooleanGuard!");
365 throw 1;
366}
367
368/**
369 * Creates a terminal pointing to the boolean register.
370 */
371#define BOOL() \
372 new TerminalRegister(\
373 *findBooleanRegisterFile(machine__).port(0), 0);\
374 PRINTOUT("bool")
375
376/**
377 * Returns RegisterGuard pointing to boolean register
378 */
379#define BOOLGUARD() \
380 findBooleanGuard(machine__, false);\
381 PRINTOUT("boolguard")
382
383/**
384 * Returns Inverted RegisterGuard pointing to boolean register
385 */
386#define INVBOOLGUARD() \
387 findBooleanGuard(machine__, true);\
388 PRINTOUT("invboolguard")
389
390/**
391 * Creates a terminal pointing to the return address port of the GCU.
392 */
393#define RA() \
394 new TerminalFUPort(\
395 dynamic_cast<BaseFUPort&>( \
396 *machine__.controlUnit()->returnAddressPort()));\
397 PRINTOUT("ra")
398
399
400/**
401 * A shortcut which creates a 32 bit TerminalImmediate.
402 *
403 * @param VALUE The value of the immediate.
404 */
405#define IMM32(VALUE) \
406 IMM(32, VALUE)
407
408/**
409 * Creates an instruction and adds it to a procedure.
410 *
411 * @param ADD_MOVES A (list of) move creation statement(s).
412 */
413#define INSTRUCTION(ADD_MOVES) \
414{\
415 Instruction* tempInstruction__ = new Instruction(); \
416 int moveCounter__ = 1; \
417 PRINTOUT("\t" << currentIP__ << ": ");\
418 ADD_MOVES; \
419 PRINTOUT("\n");\
420 proc->add(tempInstruction__); \
421} currentIP__ += incrementOfIP__
422
423/**
424 * A helper macro to create different types of moves.
425 *
426 * @param SRC The source terminal.
427 * @param DST The destination terminal.
428 * @param MOVE_CONSTRUCTOR A constructor of the move to create.
429 */
430#define MOVE_TEMPLATE(SRC, DST, CONSTRUCT_MOVE) \
431{\
432 Terminal* src__ = SRC;\
433 PRINTOUT(" -> "); \
434 Terminal* dst__ = DST;\
435 PRINTOUT(" "); \
436 Bus* bus__ = &findBus(\
437 machine__, std::string("bus") + Conversion::toString(moveCounter__));\
438 std::shared_ptr<Move> tempMove = nullptr; \
439 CONSTRUCT_MOVE;\
440 tempInstruction__->addMove(tempMove);\
441} moveCounter__++;
442
443/**
444 * Creates a basic move without any guards.
445 */
446#define BASIC_MOVE_CONSTRUCTION tempMove = std::make_shared<Move>(src__, dst__, *bus__)
447
448/**
449 * Creates a basic move and adds it to the instruction this macro is
450 * invoked in.
451 *
452 * Expects that the bus names of the machine are named by appending the
453 * index of the bus to the word 'bus', i.e., 'bus1', 'bus2', etc.
454 *
455 * @param SRC The source terminal.
456 * @param DST The destination terminal.
457 */
458#define MOVE(SRC, DST) MOVE_TEMPLATE(SRC, DST, BASIC_MOVE_CONSTRUCTION);
459
460/**
461 * A no-operation move.
462 *
463 * Just skips the move slot by incrementing the move counter.
464 */
465#define NOP PRINTOUT("nop "); moveCounter__++;
466
467/**
468 * Gets the variable connected to a label.
469 *
470 * Using LABEL and SET_LABEL macros one can make implementing backward
471 * jumps easier.
472 *
473 * @param LABEL_NAME The name of the label to refer to.
474 */
475#define LABEL(LABEL_NAME) iaddress_##LABEL_NAME
476
477/**
478 * Sets a label at the current instruction pointer position.
479 *
480 * Using LABEL and SET_LABEL macros one can make implementing backward
481 * jumps easier.
482 *
483 * @param LABEL_NAME The name of the label to refer to.
484 */
485#define SET_LABEL(LABEL_NAME) \
486 PRINTOUT(#LABEL_NAME ":\n");\
487 unsigned int LABEL(LABEL_NAME) = currentIP__; \
488 LABEL(LABEL_NAME) = currentIP__;
489
490/**
491 * Forces a new value to the instruction pointer.
492 *
493 * @param VALUE The new value to assign to the instruction pointer counter.
494 */
495#define SET_IP(VALUE) currentIP__ = VALUE
496
497/**
498 * Sets the amount how much instruction pointer should be incremented after
499 * adding an instruction.
500 *
501 * @param COUNT The increment.
502 */
503#define SET_IP_INCREMENT(COUNT) incrementOfIP__ = COUNT
504
505/**
506 * Creation of guarded move.
507 *
508 * @param TERMINAL The terminal the guard should watch.
509 * @param INVERT Is the guard inverted? true if it is.
510
511#define GUARDED_MOVE_CONSTRUCTION(TERMINAL, INVERT) \
512 PRINTOUT(" || only if ");\
513 Terminal* term__ = TERMINAL;\
514 PRINTOUT(" != " #INVERT); \
515 PRINTOUT(" ||"); \
516 MoveGuard* guard__ = new MoveGuard(term__, INVERT); \
517 tempMove = new Move(src__, dst__, *bus__, guard__);
518 */
519
520#define GUARDED_MOVE_CONSTRUCTION(ADFGUARD) \
521 TTAMachine::Guard &adfGuard__ = ADFGUARD; \
522 MoveGuard* guard__ = new MoveGuard(adfGuard__); \
523 tempMove = std::make_shared<Move>(src__, dst__, *bus__, guard__);
524
525
526/**
527 * Creates a guarded move and adds it to the instruction this macro is
528 * invoked in.
529 *
530 * Non-inverted version.
531 *
532 * @param SRC The source terminal.
533 * @param DST The destination terminal.
534 * @param GTERM The termimal that is watched by this guard.
535 #define GMOVE(SRC, DST, GTERM) \
536 MOVE_TEMPLATE(SRC, DST, GUARDED_MOVE_CONSTRUCTION(GTERM, false));
537 */
538
539#define GMOVE(SRC, DST, GUARD) \
540 MOVE_TEMPLATE(SRC, DST, GUARDED_MOVE_CONSTRUCTION(GUARD));
541
542/**
543 * Creates a guarded move and adds it to the instruction this macro is
544 * invoked in.
545 *
546 * Inverted version.s
547 *
548 * @param SRC The source terminal.
549 * @param DST The destination terminal.
550 * @param GTERM The termimal that is watched by this guard.
551 #define IGMOVE(SRC, DST, GTERM) \
552 MOVE_TEMPLATE(SRC, DST, GUARDED_MOVE_CONSTRUCTION(GTERM, true));
553*/
554
555/**
556 * Initializes the POM generator macros.
557 *
558 * This should be stated before using the above macros.
559 *
560 * @PROGRAM The name of the program.
561 * @MACHINE The target processor of the program.
562 */
563#define CREATE_PROGRAM(PROGRAM, MACHINE) \
564\
565 Application::initialize(); \
566 OperationPool operationPool; \
567 unsigned int currentIP__ = 0; \
568 currentIP__ = 0; \
569 unsigned int incrementOfIP__ = 1; \
570 incrementOfIP__ = 1; \
571 Procedure* proc = NULL;\
572 const AddressSpace& programSpace__ = \
573 *MACHINE.controlUnit()->addressSpace();\
574 Program PROGRAM(programSpace__);\
575 Program& program__ = PROGRAM; \
576 const Machine& machine__ = MACHINE;\
577 PRINTOUT("\n# program '" #PROGRAM "':\n")
578
579/**
580 * Creates a new procedure to add instructions to.
581 *
582 * Sets a label to the creation position.
583 */
584#define CREATE_PROCEDURE(PROCNAME) \
585 SET_LABEL(PROCNAME); \
586 Procedure* PROCNAME = \
587 new Procedure("proc_"#PROCNAME, programSpace__, LABEL(PROCNAME));\
588 program__.addProcedure(PROCNAME);\
589 proc = PROCNAME
590
591/**
592 * Frees the resources allocated by the POM generator macros.
593 *
594 * Currently does basically nothing. Code is there just to avoid compiler
595 * warnings/errors.
596 */
597#define END_PROGRAM \
598 int foooooO__ = 1; foooooO__++;\
599 PRINTOUT("\n# program ends\n")
600
601#endif
#define abortWithError(message)
SignedWord SIntWord
Definition BaseType.hh:149
TTAMachine::Machine * machine
the architecture definition of the estimated processor
TTAMachine::RegisterFile & findRegisterFile(const TTAMachine::Machine &machine, std::string name)
TTAMachine::Port & findFUPort(const TTAMachine::Machine &machine, std::string fuName, std::string portName)
TTAMachine::Bus & findBus(const TTAMachine::Machine &machine, std::string busName)
SimValue & tempSimValue(unsigned int bitWidth, SIntWord intValue)
TTAMachine::Guard & findBooleanGuard(const TTAMachine::Machine &machine, bool isInverted)
void null__()
TTAProgram::TerminalFUPort * createTerminalFUPort(const TTAMachine::Machine &machine, std::string fuName, std::string pName, std::string opName)
TTAMachine::FunctionUnit & findFunctionUnit(const TTAMachine::Machine &machine, std::string name)
TTAMachine::RegisterFile & findBooleanRegisterFile(const TTAMachine::Machine &machine)
SimValue * temporary
static int toInt(const T &source)
static bool ciEqual(const std::string &a, const std::string &b)
virtual int numberOfRegisters() const
virtual int width() const
Guard * guard(int index) const
Definition Bus.cc:456
int guardCount() const
Definition Bus.cc:441
virtual HWOperation * operation(const std::string &name) const
virtual FUPort * operationPort(const std::string &name) const
virtual bool hasOperation(const std::string &name) const
virtual BaseFUPort * port(const std::string &name) const
virtual bool isInverted() const
int io(const FUPort &port) const
ComponentType * item(int index) const
virtual RegisterFileNavigator registerFileNavigator() const
Definition Machine.cc:450
virtual FunctionUnitNavigator functionUnitNavigator() const
Definition Machine.cc:380
virtual BusNavigator busNavigator() const
Definition Machine.cc:356
const RegisterFile * registerFile() const