OpenASIP 2.2
Loading...
Searching...
No Matches
CodeGenerator.cc
Go to the documentation of this file.
1/**
2 * @file CodeGenerator.cc
3 *
4 * Implementation of CodeGenerator class.
5 *
6 * @author Mikael Lepistö 2008 (mikael.lepisto@tut.fi)
7 * @note rating: red
8 */
9
10#include "CodeGenerator.hh"
11
12#include <boost/format.hpp>
13
14#include "CodeSnippet.hh"
15#include "ControlUnit.hh"
16#include "Conversion.hh"
17#include "Guard.hh"
18#include "HWOperation.hh"
19#include "Instruction.hh"
22#include "Machine.hh"
23#include "MachineInfo.hh"
24#include "MathTools.hh"
25#include "Move.hh"
26#include "MoveGuard.hh"
27#include "MoveNode.hh"
28#include "Operation.hh"
29#include "Procedure.hh"
30#include "Program.hh"
31#include "ProgramAnnotation.hh"
32#include "RFPort.hh"
34#include "TerminalFUPort.hh"
35#include "TerminalImmediate.hh"
37#include "TerminalRegister.hh"
41#include "UniversalMachine.hh"
42
43namespace TTAProgram {
44
50
52
55 TTAProgram::CodeSnippet& dstProcedure,
56 TTAProgram::Terminal* srcTerminal,
57 TTAProgram::Terminal* dstTerminal) {
58
59 TTAProgram::Instruction* newInstr =
62
63 newInstr->addMove(std::make_shared<TTAProgram::Move>(
64 srcTerminal, dstTerminal, uMach_->universalBus()));
65
66 dstProcedure.add(newInstr);
67 return newInstr;
68}
69
70void
72 TTAProgram::CodeSnippet& dstProcedure,
73 TTAProgram::Terminal* srcTerminal,
74 TTAProgram::Terminal* dstTerminal,
75 const TTAProgram::ProgramAnnotation& annotation) {
76
77 TTAProgram::Instruction* newInstr =
80
81 auto movePtr = std::make_shared<TTAProgram::Move>(
82 srcTerminal, dstTerminal, uMach_->universalBus());
83
84 movePtr->addAnnotation(annotation);
85 newInstr->addMove(movePtr);
86
87 dstProcedure.add(newInstr);
88}
89
90/**
91 * If operand is not given return return address terminal.
92 */
94CodeGenerator::createTerminalFUPort(const TCEString& opName, int operand = 0) {
95 if (operand != 0) {
96
97 OperationPool pool;
98 const Operation& op = pool.operation(opName.c_str());
99 if (op.isControlFlowOperation()) {
101 *uMach_->controlUnit()->operation(opName);
102 return new TTAProgram::TerminalFUPort(hwOp, operand);
103 } else {
106 return new TTAProgram::TerminalFUPort(hwOp, operand);
107 }
108 } else {
111 }
112}
113
116 const TTAMachine::RegisterFile& rf, int regNum, bool readPort) const {
117 for (int i = 0; i < rf.portCount(); i++) {
118 if (readPort) {
119 if (rf.port(i)->isOutput()) {
121 *rf.port(i), regNum);
122 }
123 } else {
124 if (rf.port(i)->isInput()) {
126 *rf.port(i), regNum);
127 }
128 }
129 }
130 return NULL;
131}
132
133
136
137 if (name == "RA") {
138 return createTerminalFUPort("RA");
139 } else {
140 const TTAMachine::RegisterFile* rf = NULL;
141 size_t findResult = name.find(".");
142 int regNum;
143 if (findResult == std::string::npos) {
145 regNum = Conversion::toInt(name.substr(1));
146
147 } else {
148 TCEString rfName = name.substr(0, findResult);
151 rf = regNav.item(rfName);
152 regNum = Conversion::toInt(
153 name.substr(findResult + 1, name.length()-findResult+1));
154 }
155 return createTerminalRegister(*rf, regNum, readPort);
156 }
157
158 return NULL;
159}
160
161/**
162 * Loads terminal from address in a terminal.
163 *
164 * @param dstProcedure Procedure to add the moves to.
165 * @param srcTerminal Address to load from.
166 * @param dstTerminal Terminal to store loaded value.
167 */
168void
170 TTAProgram::CodeSnippet& dstProcedure,
171 TTAProgram::Terminal* srcTerminal,
172 TTAProgram::Terminal* dstTerminal) {
173 TCEString loadOp;
174 int width = 0;
175 if (dstTerminal->isGPR()) {
176 width = dstTerminal->registerFile().width();
177 }
178
179 int defaultWidth = mach_->is64bit() ? 64 : 32;
180 if (width < defaultWidth) {
181 width = defaultWidth;
182 }
183 if (mach_->isLittleEndian()) {
184 loadOp = (boost::format("ld%d") % width).str();
185 } else {
186 loadOp = "ldw";
187 }
188 if (opset_.count(loadOp) == 0) {
190 (boost::format("Operation %s not found in the machine") % loadOp)
191 .str());
192 }
193
194 // create terminal references
195 TTAProgram::TerminalFUPort* load1Terminal =
196 createTerminalFUPort(loadOp, 1);
197
198 TTAProgram::TerminalFUPort* load2Terminal =
199 createTerminalFUPort(loadOp, 2);
200
201 addMoveToProcedure(dstProcedure, srcTerminal, load1Terminal);
202 addMoveToProcedure(dstProcedure, load2Terminal, dstTerminal);
203}
204
205/**
206 * Store terminal to address in a terminal.
207 *
208 * @param dstProcedure Procedure to add the moves to.
209 * @param dstTerminal Address to store to.
210 * @param srcTerminal Terminal to store.
211 */
212void
214 TTAProgram::CodeSnippet& dstProcedure,
215 TTAProgram::Terminal* dstTerminal,
216 TTAProgram::Terminal* srcTerminal) {
217 TCEString storeOp;
218 int width = 0;
219 if (srcTerminal->isGPR()) {
220 width = srcTerminal->registerFile().width();
221 }
222 int defaultWidth = mach_->is64bit() ? 64 : 32;
223 if (width < defaultWidth) {
224 width = defaultWidth;
225 }
226
227 if (mach_->isLittleEndian()) {
228 storeOp = (boost::format("st%d") % width).str();
229 } else {
230 storeOp = "stw";
231 }
232 if (opset_.count(storeOp) == 0) {
234 (boost::format("Operation %s not found in the machine") % storeOp)
235 .str());
236 }
237
238 TTAProgram::TerminalFUPort* stw1Terminal =
239 createTerminalFUPort(storeOp, 1);
240
241 TTAProgram::TerminalFUPort* stw2Terminal =
242 createTerminalFUPort(storeOp, 2);
243
244 addMoveToProcedure(dstProcedure, dstTerminal, stw1Terminal);
245 addMoveToProcedure(dstProcedure, srcTerminal, stw2Terminal);
246}
247
248/**
249 * Loads register from address in a terminal.
250 *
251 * @param dstProcedure Procedure to add the moves to.
252 * @param srcTerminal Address to load from.
253 * @param dstReg Register to store loaded value.
254 */
255void
257 TTAProgram::CodeSnippet& dstProcedure,
258 TTAProgram::Terminal* srcTerminal,
259 const TCEString& dstReg) {
260
261 // create terminal references
262 TTAProgram::Terminal* dstRegTerminal =
263 createTerminalRegister(dstReg, false);
264
265 loadTerminal(dstProcedure, srcTerminal, dstRegTerminal);
266}
267
268/**
269 * Store register to address in a terminal.
270 *
271 * @param dstProcedure Procedure to add the moves to.
272 * @param dstTerminal Address to store to.
273 * @param srcReg Register to store.
274 */
275void
277 TTAProgram::CodeSnippet& dstProcedure,
278 TTAProgram::Terminal* dstTerminal,
279 const TCEString& srcReg) {
280
281 TTAProgram::Terminal* srcRegTerminal =
282 createTerminalRegister(srcReg, true);
283
284 storeTerminal(dstProcedure, dstTerminal, srcRegTerminal);
285}
286
287/**
288 * Loads register from address in another register.
289 *
290 * @param dstProcedure Procedure to add the moves to.
291 * @param srcReg Address to load from.
292 * @param dstReg Register to store loaded value.
293 */
294void
296 TTAProgram::CodeSnippet& dstProcedure,
297 const TCEString& srcReg,
298 const TCEString& dstReg) {
299
300 // create terminal references
301 TTAProgram::Terminal* srcTerminal =
302 createTerminalRegister(srcReg, true);
303
304 loadFromAddress(dstProcedure, srcTerminal, dstReg);
305}
306
307/**
308 * Store register to address in another register.
309 *
310 * @param dstProcedure Procedure to add the moves to.
311 * @param dstReg Address to store to.
312 * @param srcReg Register to store.
313 */
314void
316 TTAProgram::CodeSnippet& dstProcedure,
317 const TCEString& dstReg,
318 const TCEString& srcReg) {
319
320 // create terminal references
321 TTAProgram::Terminal* dstTerminal =
322 createTerminalRegister(dstReg, true);
323
324 storeToAddress(dstProcedure, dstTerminal, srcReg);
325}
326
327/**
328 * Increment address in a register by value of increment.
329 *
330 * @param dstProcedure Procedure to add the moves to.
331 * @param dstReg Register to increment.
332 * @param increment How much to increment.
333 */
334void
336 TTAProgram::CodeSnippet& dstProcedure, const TCEString& dstReg,
337 int increment) {
338
339 TCEString addOp = mach_->is64bit() ? "add64" : "add";
340
341 // create terminal references
342 TTAProgram::Terminal* regReadTerminal =
343 createTerminalRegister(dstReg, true);
344
345 TTAProgram::Terminal* regWriteTerminal =
346 createTerminalRegister(dstReg, false);
347
348 // TODO: immediate creator function which calculates immWidth
349 SimValue immVal(MathTools::requiredBitsSigned(increment));
350 immVal = increment;
351 TTAProgram::TerminalImmediate* imm4Terminal =
353
354 TTAProgram::TerminalFUPort* add1Terminal =
355 createTerminalFUPort(addOp, 1);
356
357 TTAProgram::TerminalFUPort* add2Terminal =
358 createTerminalFUPort(addOp, 2);
359
360 TTAProgram::TerminalFUPort* add3Terminal =
361 createTerminalFUPort(addOp, 3);
362
363 // dstProcedure->add(
364 // new CodeSnippet("sp -> ldw.1; ldw.2 -> dstReg; "
365 // "4 -> add.1; sp -> add.2; add.3 -> sp"));
366
367 addMoveToProcedure(dstProcedure, imm4Terminal, add1Terminal);
368 addMoveToProcedure(dstProcedure, regReadTerminal, add2Terminal);
369 addMoveToProcedure(dstProcedure, add3Terminal, regWriteTerminal);
370}
371
372/**
373 * Decrement address in a register by value of decrement.
374 *
375 * @param dstProcedure Procedure to add the moves to.
376 * @param dstReg Register to decrement.
377 * @param decrement How much to decrement.
378 */
379void
381 TTAProgram::CodeSnippet& dstProcedure, const TCEString& dstReg,
382 int decrement) {
383
384 TCEString subOp = mach_->is64bit() ? "sub64" : "sub";
385
386 // create terminal references
387 TTAProgram::Terminal* regReadTerminal =
388 createTerminalRegister(dstReg, true);
389
390 TTAProgram::Terminal* regWriteTerminal =
391 createTerminalRegister(dstReg, false);
392
393 // TODO: immediate creator function which calculates immWidth
394 SimValue immVal(MathTools::requiredBitsSigned(decrement));
395 immVal = decrement;
396 TTAProgram::TerminalImmediate* imm4Terminal =
398
399 TTAProgram::TerminalFUPort* sub1Terminal =
400 createTerminalFUPort(subOp, 1);
401
402 TTAProgram::TerminalFUPort* sub2Terminal =
403 createTerminalFUPort(subOp, 2);
404
405 TTAProgram::TerminalFUPort* sub3Terminal =
406 createTerminalFUPort(subOp, 3);
407
408 // dstProcedure->add(
409 // new CodeSnippet("sp -> sub.1; 4 -> sub.2; sub.3 -> sp;"
410 // "sp -> stw.1; srcTerm -> stw.2;"));
411 addMoveToProcedure(dstProcedure, regReadTerminal, sub1Terminal);
412 addMoveToProcedure(dstProcedure, imm4Terminal, sub2Terminal);
413 addMoveToProcedure(dstProcedure, sub3Terminal, regWriteTerminal);
414}
415
416void
421
422void
427
428/**
429 * Pops value from stack and stores it in a given terminal.
430 *
431 * @param dstProcedure Procedure to add the moves to.
432 * @param stackRegister Stack pointer name.
433 * @param dstTerminal Terminal to put the value into.
434 */
435void
437 TTAProgram::CodeSnippet& dstProcedure,
438 const TCEString& stackRegister,
439 TTAProgram::Terminal* dstTerminal) {
440
441 TTAProgram::Terminal* stackTerminal =
442 createTerminalRegister(stackRegister, true);
443 loadTerminal(dstProcedure, stackTerminal, dstTerminal);
444
445 incrementStackPointer(dstProcedure, stackRegister);
446}
447
448/**
449 * Pops value from stack and stores it in a register.
450 *
451 * @param dstProcedure Procedure to add the moves to.
452 * @param stackRegister Stack pointer name.
453 * @param dstReg Register to put the value into.
454 */
455void
457 TTAProgram::CodeSnippet& dstProcedure,
458 const TCEString& stackRegister,
459 const TCEString& dstReg) {
460
461 loadFromRegisterAddress(dstProcedure, stackRegister, dstReg);
462
463 incrementStackPointer(dstProcedure, stackRegister);
464}
465
466/**
467 * Push a value in a terminal to the stack.
468 *
469 * @param dstProcedure Procedure to add the moves to.
470 * @param stackRegister Stack pointer name.
471 * @param srcTerminal Value to push.
472 */
473void
475 TTAProgram::CodeSnippet& dstProcedure,
476 const TCEString& stackRegister,
477 TTAProgram::Terminal* srcTerminal) {
478 decrementStackPointer(dstProcedure, stackRegister);
479
480 TTAProgram::Terminal* stackTerminal =
481 createTerminalRegister(stackRegister, true);
482 storeTerminal(dstProcedure, stackTerminal, srcTerminal);
483}
484
485/**
486 * Push a value in a register to the stack.
487 *
488 * @param dstProcedure Procedure to add the moves to.
489 * @param stackRegister Stack pointer name.
490 * @param srcTerminal Value to push.
491 */
492void
494 TTAProgram::CodeSnippet& dstProcedure,
495 const TCEString& stackRegister,
496 const TCEString& srcReg) {
497 decrementStackPointer(dstProcedure, stackRegister);
498
499 storeToRegisterAddress(dstProcedure, stackRegister, srcReg);
500}
501
502void
504 TTAProgram::CodeSnippet& dstProcedure, const TCEString& stackRegister,
506 // create terminal references
509
510 pushToStack(dstProcedure, stackRegister, srcTerminal);
511}
512
513/**
514 * TODO Decide how much the register value should be incremented in
515 * the following buffer operations. Right now it's 4, but maybe it should be
516 * calculated based on the terminal size. These operations aren't currently
517 * used anywhere. For stack buffer operations you should use the above
518 * functions, since they take into account the stack alignment.
519 */
520
521/**
522 * Pops value from buffer and stores it in a given terminal.
523 *
524 * @param dstProcedure Procedure to add the moves to.
525 * @param indexRegister Pointer to the buffer.
526 * @param dstTerminal Terminal to put the value into.
527 */
528void
530 TTAProgram::CodeSnippet& dstProcedure,
531 const TCEString& indexRegister,
532 TTAProgram::Terminal* dstTerminal) {
533 decrementRegisterAddress(dstProcedure, indexRegister, 4);
534
535 TTAProgram::Terminal* indexTerminal =
536 createTerminalRegister(indexRegister, true);
537 loadTerminal(dstProcedure, indexTerminal, dstTerminal);
538}
539
540/**
541 * Pops value from buffer and stores it in a register.
542 *
543 * @param dstProcedure Procedure to add the moves to.
544 * @param indexRegister Pointer to the buffer.
545 * @param dstReg Register to put the value into.
546 */
547void
549 TTAProgram::CodeSnippet& dstProcedure,
550 const TCEString& indexRegister,
551 const TCEString& dstReg) {
552 decrementRegisterAddress(dstProcedure, indexRegister, 4);
553
554 loadFromRegisterAddress(dstProcedure, indexRegister, dstReg);
555}
556
557/**
558 * Push a value in a terminal to a buffer.
559 *
560 * @param dstProcedure Procedure to add the moves to.
561 * @param indexRegister Pointer to the buffer.
562 * @param srcTerminal Value to push.
563 */
564void
566 TTAProgram::CodeSnippet& dstProcedure,
567 const TCEString& indexRegister,
568 TTAProgram::Terminal* srcTerminal) {
569
570 TTAProgram::Terminal* indexTerminal =
571 createTerminalRegister(indexRegister, true);
572 storeTerminal(dstProcedure, indexTerminal, srcTerminal);
573
574 incrementRegisterAddress(dstProcedure, indexRegister, 4);
575}
576
577/**
578 * Push a value in a register to a buffer.
579 *
580 * @param dstProcedure Procedure to add the moves to.
581 * @param indexRegister Pointer to the buffer.
582 * @param srcTerminal Value to push.
583 */
584void
586 TTAProgram::CodeSnippet& dstProcedure,
587 const TCEString& indexRegister,
588 const TCEString& srcReg) {
589
590 storeToRegisterAddress(dstProcedure, indexRegister, srcReg);
591
592 incrementRegisterAddress(dstProcedure, indexRegister, 4);
593}
594
595void
597 TTAProgram::CodeSnippet& dstProcedure,
598 const TCEString& indexRegister,
600
601 // create terminal references
604
605 pushToBuffer(dstProcedure, indexRegister, srcTerminal);
606}
607
608void
610 TTAProgram::CodeSnippet& dstProcedure,
611 const TCEString& jumpAddrReg) {
612
613 TTAProgram::Terminal* jumpDestTerminal =
614 createTerminalRegister(jumpAddrReg, true);
615
616 TTAProgram::TerminalFUPort* jump1Terminal =
617 createTerminalFUPort("jump", 1);
618
619 // dstProcedure->add(new CodeSnippet("jumpAddrReg -> jmp.1;"));
620 addMoveToProcedure(dstProcedure, jumpDestTerminal, jump1Terminal);
621}
622
623void
625 TTAProgram::CodeSnippet& dstProcedure,
626 const TCEString& jumpAddrReg,
627 const TTAProgram::ProgramAnnotation& annotation) {
628
629 TTAProgram::Terminal* jumpDestTerminal =
630 createTerminalRegister(jumpAddrReg, true);
631
632 TTAProgram::TerminalFUPort* jump1Terminal =
633 createTerminalFUPort("jump", 1);
634
636 dstProcedure, jumpDestTerminal, jump1Terminal, annotation);
637}
638
639std::shared_ptr<TTAProgram::Move>
641
642 TTAProgram::TerminalFUPort* jump1Terminal =
643 createTerminalFUPort("jump", 1);
644
645 TTAProgram::Terminal* jump0Terminal =
647
648 return std::make_shared<TTAProgram::Move>(jump0Terminal, jump1Terminal,
650}
651
652
653/**
654 * Creates a call move.
655 */
656std::shared_ptr<TTAProgram::Move>
660
661 TTAProgram::TerminalFUPort* dstTerminal =
662 createTerminalFUPort("call", 1);
663 return std::make_shared<TTAProgram::Move>(
664 srcTerminal, dstTerminal, uMach_->universalBus());
665}
666
667/**
668 * Creates an external call move.
669 */
670void
672 TTAProgram::CodeSnippet& dstProcedure,
673 const TCEString& procedureName) {
674
676 new TTAProgram::TerminalSymbolReference(procedureName);
677
678 TTAProgram::TerminalFUPort* dstTerminal =
679 createTerminalFUPort("call", 1);
680
681 addMoveToProcedure(dstProcedure, srcTerminal, dstTerminal);
682}
683
684
685/**
686 * Creates a call move and adds it to the given procedure.
687 */
688void
690 TTAProgram::CodeSnippet& dstProcedure,
692
695
696 TTAProgram::TerminalFUPort* dstTerminal =
697 createTerminalFUPort("call", 1);
698
699 addMoveToProcedure(dstProcedure, srcTerminal, dstTerminal);
700}
701
702void
704 TTAProgram::CodeSnippet& dstProcedure,
705 const TCEString& srcReg, const TCEString& dstReg) {
706
707 TTAProgram::Terminal* srcTerminal =
708 createTerminalRegister(srcReg, true);
709
710 TTAProgram::Terminal* dstTerminal =
711 createTerminalRegister(dstReg, false);
712
713 addMoveToProcedure(dstProcedure, srcTerminal, dstTerminal);
714}
715
716void
718 TTAProgram::CodeSnippet& dstProcedure,
719 int imm, const TCEString& dstReg) {
720
721 SimValue immVal(32);
722 immVal = imm;
723 TTAProgram::TerminalImmediate* srcTerminal =
725
726 TTAProgram::Terminal* dstTerminal =
727 createTerminalRegister(dstReg, false);
728
729 addMoveToProcedure(dstProcedure, srcTerminal, dstTerminal);
730}
731
732/**
733 * Creates yield function which saves requested registers.
734 *
735 * @param refManager Reference manager of destination program.
736 * @param name Name for the created procedure.
737 * @param schedProcedure Scheduler function to call sp = schedule(sp)
738 * @param stackReg Stack register name assigned for program.
739 * @param rvReg Return value register name.
740 * @param saveRegs Set of registers, which should be saved.
741 */
745 const TCEString& name,
746 const TCEString& schedProcedureName,
747 const TCEString& stackReg,
748 const TCEString& rvReg,
749 const RegisterSet& saveRegs) {
750
751 TTAProgram::Procedure* retVal =
753 name, *mach_->controlUnit()->addressSpace());
754
755 // *** Push registers to stack
756 for(RegisterSet::const_iterator i = saveRegs.begin();
757 i != saveRegs.end(); i++) {
758 pushRegisterToStack(*retVal, stackReg, *i);
759 }
760
761 // *** Push return address to stack as well
762 pushRegisterToStack(*retVal, stackReg, "RA");
763
764 // *** Create empty instruction to be used as yield_return destination
765 TTAProgram::Instruction* yeldReturnInstruction =
768
769 TTAProgram::InstructionReference yeldReturnReference =
770 refManager.createReference(*yeldReturnInstruction);
771
772 // *** Push InstructionReference to sp reading instruction to stack
773 pushInstructionReferenceToStack(*retVal, stackReg, yeldReturnReference);
774
775 // *** Save sp, switch thread and update sp
776
777 // put stackpointer address to be parameter
778#ifdef ALL_STACK_PARAMETERS
779 pushRegisterToStack(*retVal, stackReg, stackReg);
780#else
781 registerMove(*retVal, stackReg, rvReg);
782#endif
783 createExternalCall(*retVal, schedProcedureName);
784
785 // read new sp value from rv register
786 registerMove(*retVal, rvReg, stackReg);
787
788#ifdef ALL_STACK_PARAMETERS
789 // need to pop the parameter from stack
790 incrementStackPointer(*retVal, stackReg);
791#endif
792
793 // read yeld address from stack
794 popRegisterFromStack(*retVal, stackReg, "RA");
795
796 // jump to yeld point
799
800 // add previously created "label" instruction
801 retVal->add(yeldReturnInstruction);
802
803 // restore return address
804 popRegisterFromStack(*retVal, stackReg, "RA");
805
806 // read registers from stack
807 for(RegisterSet::const_reverse_iterator i = saveRegs.rbegin();
808 i != saveRegs.rend(); i++) {
809 popRegisterFromStack(*retVal, stackReg, *i);
810 }
811
812 // jump to yeld point
813 registerJump(*retVal, "RA");
814
815 // remove the placeholder instr.
816 refManager.replace(
817 *yeldReturnInstruction,
818 retVal->nextInstruction(*yeldReturnInstruction));
819
820 retVal->remove(*yeldReturnInstruction);
821 // debug print created function
822
823 return retVal;
824}
825
826/**
827 * Creates a guard with same guard register etc but inverted.
828 * The guard must be found from the given bus if bus given.
829 *
830 * @TODO: support for port guards
831 *
832 * @param mg guard to inverse
833 * @param bus bus where the guard must be. if null same as bug of mg.
834 * @return new MoveGuard that is given guard inverted, NULL if cannot create.
835 */
838 const TTAProgram::MoveGuard &mg, const TTAMachine::Bus* bus) {
839
840 const TTAMachine::Guard& g = mg.guard();
841 if (bus == NULL) {
842 bus = g.parentBus();
843 }
844
845 bool inv = g.isInverted();
846 const TTAMachine::RegisterGuard* rg =
847 dynamic_cast<const TTAMachine::RegisterGuard*>(&g);
848 if (rg != NULL) {
849 const TTAMachine::RegisterFile* rf = rg->registerFile();
850 int regIndex = rg->registerIndex();
851
852 // fake guard to be bypassed as port guard?
853 if (bus == nullptr) {
854 return new TTAProgram::MoveGuard(
856 !rg->isInverted(), *rg->registerFile(), rg->registerIndex(), nullptr));
857 }
858 // find guard
859 for (int i = 0 ; i < bus->guardCount(); i++) {
860 const TTAMachine::Guard *g2 = bus->guard(i);
861 const TTAMachine::RegisterGuard* rg2 =
862 dynamic_cast<const TTAMachine::RegisterGuard*>(g2);
863 if (rg2) {
864 if( rg2->registerFile() == rf &&
865 rg2->registerIndex() == regIndex &&
866 rg2->isInverted() == !inv ) {
867 return new TTAProgram::MoveGuard(*rg2);
868 }
869 }
870 }
871 }
872 const TTAMachine::PortGuard* pg =
873 dynamic_cast<const TTAMachine::PortGuard*>(&g);
874 if (pg) {
875 auto port = pg->port();
876
877 // find guard
878 for (int i = 0 ; i < bus->guardCount(); i++) {
879 const TTAMachine::Guard *g2 = bus->guard(i);
880 const TTAMachine::PortGuard* pg2 =
881 dynamic_cast<const TTAMachine::PortGuard*>(g2);
882 if (pg2 && pg2->port() == port &&
883 pg2->isInverted() == !inv) {
884 return new TTAProgram::MoveGuard(*pg2);
885 }
886 }
887 }
888
889 return NULL;
890}
891/*
892 * Returns the operations in order.
893 * Last is the lbufs op.
894 * It may be preceeded by sub op.
895 * The first may be a shift op.
896 */
897std::vector <ProgramOperationPtr>
899 const MoveNode* dynamicLimitMove, int iterationCount, int loopSize, int divider) {
900
901 std::vector<ProgramOperationPtr> res;
902 // is power-of-2?
903 if (divider & (divider-1)) {
904 return res;
905 }
906
907 const char* opName = "lbufs";
909 if (!cu.hasOperation(opName)) {
910 return res;
911 }
912
913 OperationPool pool;
914 const Operation& lbufsOp = pool.operation(opName);
915 SimValue loopSizeSV(MathTools::requiredBitsSigned(loopSize));
916 loopSizeSV = loopSize;
917 TTAProgram::TerminalImmediate* loopSizeSrc =
918 new TTAProgram::TerminalImmediate(loopSizeSV);
919
920 MoveNode* iterCountMN = NULL;
921 ProgramOperationPtr shiftPO;
923
924 // TODO: universalmachine is buggy. these should be in control unit,
925 // not universalfunction unit
926 TTAProgram::TerminalFUPort* iterCountDst =
928 *uMach_->universalFunctionUnit().operation(opName), 1);
929
930 TTAProgram::TerminalFUPort* loopSizeDst =
932 *uMach_->universalFunctionUnit().operation(opName), 2);
933
934 // static iteration count
935 if (dynamicLimitMove == NULL) {
936 SimValue iterCountSV(MathTools::requiredBitsSigned(iterationCount));
937 iterCountSV = iterationCount;
938 TTAProgram::Terminal* iterCountSrc = new TTAProgram::TerminalImmediate(iterCountSV);
939 iterCountMN = new MoveNode(createMove(iterCountSrc, iterCountDst));
940 } else {
941 bool decrement = false;
942 bool increment = false;
943 switch (iterationCount) {
944 case -1:
945 decrement = true;
946 case 0:
947 break;
948 default:
949 if (iterationCount > 0)
950 increment = true;
951 else
952 return res;
953 }
954 TTAProgram::Terminal* counterValSrc = NULL;
955 if (dynamicLimitMove->isSourceOperation())
956 counterValSrc = dynamicLimitMove->move().destination().copy();
957 else
958 counterValSrc = dynamicLimitMove->move().source().copy();
959
960 // if divider not 1, need shift of to scale it down.
961 TCEString adjustName = decrement ? "sub" : "add";
962 if (mach_->is64bit()) {
963 adjustName << "64";
964 }
965 if (decrement || increment) {
966 const Operation& subOp = pool.operation(adjustName.c_str());
967 subPO = std::make_shared<ProgramOperation>(subOp);
968
969 // signed 1 is 2 bits.
970 TTAProgram::TerminalImmediate* subAmountSrc =
972 SimValue(abs(iterationCount),
973 MathTools::requiredBitsSigned(iterationCount)));
974
975 TTAProgram::TerminalFUPort* subAmntDst = createTerminalFUPort(adjustName, 2);
976 TTAProgram::TerminalFUPort* subRes = createTerminalFUPort(adjustName, 3);
977
978 MoveNode* subAmtMN = new MoveNode(createMove(subAmountSrc, subAmntDst));
979 subPO->addInputNode(*subAmtMN);
980 subAmtMN->addDestinationOperationPtr(subPO);
981
982 iterCountMN = new MoveNode(createMove(subRes, iterCountDst));
983 subPO->addOutputNode(*iterCountMN);
984 iterCountMN->setSourceOperationPtr(subPO);
985
986 res.push_back(subPO);
987 // first input not here but later
988 }
989
990 if (divider > 1) {
991 TCEString shiftName = "shr";
992 if (mach_->is64bit()) {
993 shiftName << "64";
994 }
995 const Operation& shiftOp = pool.operation(shiftName.c_str());
996
997 int shiftAmount = MathTools::ceil_log2(divider);
998
999 SimValue shiftAmountSV(MathTools::requiredBitsSigned(shiftAmount));
1000 shiftAmountSV = shiftAmount;
1001
1002 TTAProgram::TerminalImmediate* shiftAmountSrc =
1003 new TTAProgram::TerminalImmediate(shiftAmountSV);
1004
1005 // create terminal references
1006 TTAProgram::TerminalFUPort* shiftValDst =
1007 createTerminalFUPort(shiftName, 1);
1008 TTAProgram::TerminalFUPort* shiftAmntDst =
1009 createTerminalFUPort(shiftName, 2);
1010 TTAProgram::TerminalFUPort* shiftRes =
1011 createTerminalFUPort(shiftName, 3);
1012
1013 MoveNode* shiftValMN = new MoveNode(createMove(counterValSrc, shiftValDst));
1014 MoveNode* shiftAmtMN = new MoveNode(createMove(shiftAmountSrc, shiftAmntDst));
1015
1016 shiftPO = std::make_shared<ProgramOperation>(shiftOp);
1017 shiftPO->addInputNode(*shiftValMN);
1018 shiftPO->addInputNode(*shiftAmtMN);
1019 shiftValMN->addDestinationOperationPtr(shiftPO);
1020 shiftAmtMN->addDestinationOperationPtr(shiftPO);
1021
1022 // push before the possible sub
1023 res.insert(res.begin(),shiftPO);
1024 MoveNode* shift2dec = NULL;
1025 if (!(decrement||increment)) {
1026 iterCountMN = new MoveNode(createMove(shiftRes, iterCountDst));
1027 shiftPO->addOutputNode(*iterCountMN);
1028 iterCountMN->setSourceOperationPtr(shiftPO);
1029 } else {
1030 // use dsub operation
1031 TTAProgram::TerminalFUPort* subValDst =
1032 createTerminalFUPort(adjustName, 1);
1033 shift2dec = new MoveNode(createMove(shiftRes, subValDst));
1034 subPO->addInputNode(*shift2dec);
1035 shift2dec->addDestinationOperationPtr(subPO);
1036
1037 shiftPO->addOutputNode(*shift2dec);
1038 shift2dec->setSourceOperationPtr(shiftPO);
1039 }
1040 } else { // no shifting, maybe decrement
1041 if (decrement||increment) {
1042 // create terminal references
1043 TTAProgram::TerminalFUPort* subValDst =
1044 createTerminalFUPort(adjustName, 1);
1045 MoveNode* subValMN = new MoveNode(createMove(counterValSrc, subValDst));
1046 subPO->addInputNode(*subValMN);
1047 subValMN->addDestinationOperationPtr(subPO);
1048 } else {
1049 iterCountMN = new MoveNode(createMove(counterValSrc, iterCountDst));
1050 }
1051 }
1052 }
1053 MoveNode* loopSizeMN = new MoveNode(createMove(loopSizeSrc, loopSizeDst));
1054
1055 ProgramOperationPtr loopBusInitOp(new ProgramOperation(lbufsOp));
1056 loopBusInitOp->addInputNode(*iterCountMN);
1057 loopBusInitOp->addInputNode(*loopSizeMN);
1058 iterCountMN->addDestinationOperationPtr(loopBusInitOp);
1059 loopSizeMN->addDestinationOperationPtr(loopBusInitOp);
1060
1061 res.push_back(loopBusInitOp);
1062 return res;
1063}
1064
1065std::shared_ptr<TTAProgram::Move> CodeGenerator::createMove(
1067 return std::make_shared<TTAProgram::Move>(src, dst, uMach_->universalBus());
1068}
1069
1071 // 4ever loop or buggy input?
1072 if (jump->move().isUnconditional()) {
1073 return nullptr;
1074 }
1075
1076 const TTAMachine::Guard& guard = jump->move().guard().guard();
1077 auto rg = dynamic_cast<const TTAMachine::RegisterGuard*>(&guard);
1078 if (!rg) {
1079 return nullptr;
1080 }
1081
1082 // TODO: change eq->ne or add xor to support non-inverted without
1083 // both ops.
1084 const char* opName = rg->isInverted() ? "lbufc" : "lbufz";
1086 if (!cu.hasOperation(opName)) {
1087 return nullptr;
1088 }
1089
1092 *uMach_->universalFunctionUnit().operation(opName), 1);
1093
1094 // create terminal for reading register
1095 auto src = createTerminalRegister(
1096 *rg->registerFile(), rg->registerIndex(), true);
1097
1098 MoveNode* loopSizeMN = new MoveNode(createMove(src, dst));
1099
1100 OperationPool pool;
1101 const Operation& op = pool.operation(opName);
1103 po->addInputNode(*loopSizeMN);
1104 loopSizeMN->addDestinationOperationPtr(po);
1105 return po;
1106}
1107
1108
1109/*
1110 * Returns the operations in order.
1111 * Last is the lbufs op.
1112 * It may be preceeded by sub op.
1113 * The first may be a shift op.
1114 */
1117 const char* opName = "infloop";
1119 if (!cu.hasOperation(opName)) {
1120 return nullptr;
1121 }
1122
1123 TTAProgram::TerminalFUPort* loopSizeDst =
1125 *uMach_->universalFunctionUnit().operation(opName), 1);
1126
1127 OperationPool pool;
1128 const Operation& lbufsOp = pool.operation(opName);
1129 SimValue loopSizeSV(MathTools::requiredBitsSigned(loopSize));
1130 loopSizeSV = loopSize;
1131 TTAProgram::TerminalImmediate* loopSizeSrc =
1132 new TTAProgram::TerminalImmediate(loopSizeSV);
1133
1134 MoveNode* loopSizeMN = new MoveNode(createMove(loopSizeSrc, loopSizeDst));
1135
1136 ProgramOperationPtr loopBufInitOp(new ProgramOperation(lbufsOp));
1137 loopBufInitOp->addInputNode(*loopSizeMN);
1138 loopSizeMN->addDestinationOperationPtr(loopBufInitOp);
1139 return loopBufInitOp;
1140}
1141
1142}
#define abortWithError(message)
std::shared_ptr< ProgramOperation > ProgramOperationPtr
Definition MoveNode.hh:53
static int toInt(const T &source)
static int maxMemoryAlignment(const TTAMachine::Machine &mach)
static OperationSet getOpset(const TTAMachine::Machine &mach)
static int requiredBitsSigned(SLongWord number)
static int ceil_log2(long unsigned int number)
void setSourceOperationPtr(ProgramOperationPtr po)
Definition MoveNode.cc:541
TTAProgram::Move & move()
bool isSourceOperation() const
Definition MoveNode.cc:168
void addDestinationOperationPtr(ProgramOperationPtr po)
Definition MoveNode.cc:533
virtual bool isControlFlowOperation() const
Definition Operation.cc:294
virtual int width() const
virtual RFPort * port(const std::string &name) const
Guard * guard(int index) const
Definition Bus.cc:456
int guardCount() const
Definition Bus.cc:441
SpecialRegisterPort * returnAddressPort() const
virtual AddressSpace * addressSpace() const
virtual HWOperation * operation(const std::string &name) const
virtual bool hasOperation(const std::string &name) const
virtual bool isInverted() const
virtual Bus * parentBus() const
ComponentType * item(int index) const
virtual RegisterFileNavigator registerFileNavigator() const
Definition Machine.cc:450
bool isLittleEndian() const
Definition Machine.hh:258
virtual ControlUnit * controlUnit() const
Definition Machine.cc:345
bool is64bit() const
Definition Machine.hh:260
static NullInstructionTemplate & instance()
FUPort * port() const
virtual bool isInput() const
Definition Port.cc:298
virtual bool isOutput() const
Definition Port.cc:308
const RegisterFile * registerFile() const
virtual int portCount() const
Definition Unit.cc:135
TTAProgram::TerminalFUPort * createTerminalFUPort(const TCEString &opName, int operand)
TTAProgram::Terminal * createTerminalRegister(const TTAMachine::RegisterFile &rf, int regNum, bool readPort) const
void pushToStack(TTAProgram::CodeSnippet &dstProcedure, const TCEString &stackRegister, TTAProgram::Terminal *srcTerminal)
CodeGenerator(const TTAMachine::Machine &mach)
const TTAMachine::Machine * mach_
Target machine.
void registerMove(TTAProgram::CodeSnippet &dstProcedure, const TCEString &srcReg, const TCEString &dstReg)
TTAProgram::Instruction * addMoveToProcedure(TTAProgram::CodeSnippet &dstProcedure, TTAProgram::Terminal *srcTerminal, TTAProgram::Terminal *dstTerminal)
void storeToRegisterAddress(TTAProgram::CodeSnippet &dstProcedure, const TCEString &dstReg, const TCEString &srcReg)
void immediateMove(TTAProgram::CodeSnippet &dstProcedure, int imm, const TCEString &dstReg)
ProgramOperationPtr createBreakOperation(const MoveNode *jump)
std::shared_ptr< TTAProgram::Move > createMove(TTAProgram::Terminal *src, TTAProgram::Terminal *dst)
static TTAProgram::MoveGuard * createInverseGuard(const TTAProgram::MoveGuard &mg, const TTAMachine::Bus *bus=NULL)
void loadFromAddress(TTAProgram::CodeSnippet &dstProcedure, TTAProgram::Terminal *srcTerminal, const TCEString &dstReg)
void pushToBuffer(TTAProgram::CodeSnippet &dstProcedure, const TCEString &indexRegister, TTAProgram::Terminal *srcTerminal)
void createExternalCall(TTAProgram::CodeSnippet &dstProcedure, const TCEString &procedureName)
void decrementRegisterAddress(TTAProgram::CodeSnippet &dstProcedure, const TCEString &dstReg, int decrement)
void decrementStackPointer(TTAProgram::CodeSnippet &dstProcedure, const TCEString &spReg)
void pushRegisterToStack(TTAProgram::CodeSnippet &dstProcedure, const TCEString &stackRegister, const TCEString &srcReg)
void registerJump(TTAProgram::CodeSnippet &dstProcedure, const TCEString &jumpAddrReg)
void storeTerminal(TTAProgram::CodeSnippet &dstProcedure, TTAProgram::Terminal *dstTerminal, TTAProgram::Terminal *srcTerminal)
void pushInstructionReferenceToBuffer(TTAProgram::CodeSnippet &dstProcedure, const TCEString &indexRegister, TTAProgram::InstructionReference &srcAddr)
void addAnnotatedMoveToProcedure(TTAProgram::CodeSnippet &dstProcedure, TTAProgram::Terminal *srcTerminal, TTAProgram::Terminal *dstTerminal, const TTAProgram::ProgramAnnotation &annotation)
TTAProgram::Procedure * createSchedYieldProcedure(TTAProgram::InstructionReferenceManager &refManager, const TCEString &name, const TCEString &schedProcedureName, const TCEString &stackReg, const TCEString &rvReg, const RegisterSet &saveRegs)
void loadFromRegisterAddress(TTAProgram::CodeSnippet &dstProcedure, const TCEString &srcReg, const TCEString &dstReg)
const UniversalMachine * uMach_
Universal machine.
void incrementRegisterAddress(TTAProgram::CodeSnippet &dstProcedure, const TCEString &dstReg, int increment)
std::vector< ProgramOperationPtr > createForLoopBufferInit(const MoveNode *dynamicLimitMove, int iterationCount, int divider, int loopSize)
void incrementStackPointer(TTAProgram::CodeSnippet &dstProcedure, const TCEString &spReg)
void popFromBuffer(TTAProgram::CodeSnippet &dstProcedure, const TCEString &indexRegister, TTAProgram::Terminal *dstTerminal)
void pushRegisterToBuffer(TTAProgram::CodeSnippet &dstProcedure, const TCEString &stackRegister, const TCEString &srcReg)
std::set< TCEString > RegisterSet
void storeToAddress(TTAProgram::CodeSnippet &dstProcedure, TTAProgram::Terminal *dstTerminal, const TCEString &srcReg)
MachineInfo::OperationSet opset_
ProgramOperationPtr createWhileLoopBufferInit(int loopSize)
std::shared_ptr< TTAProgram::Move > createJump(TTAProgram::InstructionReference &dst)
void popFromStack(TTAProgram::CodeSnippet &dstProcedure, const TCEString &stackRegister, TTAProgram::Terminal *dstTerminal)
void popRegisterFromBuffer(TTAProgram::CodeSnippet &dstProcedure, const TCEString &indexRegister, const TCEString &dstReg)
std::shared_ptr< TTAProgram::Move > createCall(TTAProgram::InstructionReference &callDst)
void loadTerminal(TTAProgram::CodeSnippet &dstProcedure, TTAProgram::Terminal *srcTerminal, TTAProgram::Terminal *dstTerminal)
void pushInstructionReferenceToStack(TTAProgram::CodeSnippet &dstProcedure, const TCEString &stackRegister, TTAProgram::InstructionReference &srcAddr)
void popRegisterFromStack(TTAProgram::CodeSnippet &dstProcedure, const TCEString &stackRegister, const TCEString &dstReg)
virtual Instruction & nextInstruction(const Instruction &ins) const
virtual void add(Instruction *ins)
void replace(Instruction &insA, Instruction &insB)
InstructionReference createReference(Instruction &ins)
void addMove(std::shared_ptr< Move > move)
const TTAMachine::Guard & guard() const
Definition MoveGuard.cc:86
MoveGuard & guard() const
Definition Move.cc:345
bool isUnconditional() const
Definition Move.cc:154
Terminal & source() const
Definition Move.cc:302
Terminal & destination() const
Definition Move.cc:323
void add(Instruction *ins)
Definition Procedure.cc:160
void remove(Instruction &ins)
Definition Procedure.cc:297
virtual Terminal * copy() const =0
virtual bool isGPR() const
Definition Terminal.cc:107
virtual const TTAMachine::RegisterFile & registerFile() const
Definition Terminal.cc:225
virtual TTAMachine::HWOperation * operation(const std::string &name) const
UniversalFunctionUnit & universalFunctionUnit() const
UnboundedRegisterFile & integerRegisterFile() const
TTAMachine::Bus & universalBus() const