OpenASIP 2.2
Loading...
Searching...
No Matches
TPEFProgramFactory.cc
Go to the documentation of this file.
1/*
2 Copyright (c) 2002-2014 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 TPEFProgramFactory.cc
26 *
27 * Implementation of TPEFProgramFactory class.
28 *
29 * @author Mikael Lepistö 2005 (tmlepist-no.spam-cs.tut.fi)
30 * @author Pekka Jääskeläinen 2011,2014
31 * @note rating: yellow
32 */
33
34#include <list>
35#include <map>
36#include <vector>
37#include <boost/format.hpp>
38
39#include "TPEFProgramFactory.hh"
40#include "ContainerTools.hh"
41#include "ASpaceElement.hh"
42#include "Section.hh"
43#include "SymbolSection.hh"
44#include "CodeSymElement.hh"
45#include "CodeSection.hh"
46#include "DataSymElement.hh"
47#include "ImmediateElement.hh"
48#include "Instruction.hh"
49#include "Procedure.hh"
50#include "MoveGuard.hh"
51#include "Move.hh"
54#include "TerminalRegister.hh"
55#include "TerminalFUPort.hh"
56#include "TerminalImmediate.hh"
57#include "OperationPool.hh"
58#include "FUPort.hh"
59#include "Guard.hh"
60#include "HWOperation.hh"
61#include "ControlUnit.hh"
63#include "Application.hh"
64#include "CodeLabel.hh"
65#include "DataLabel.hh"
66#include "RelocElement.hh"
67#include "AddressSpace.hh"
70#include "TerminalAddress.hh"
72#include "RelocSection.hh"
73#include "ProcedSymElement.hh"
74#include "Immediate.hh"
76#include "DataMemory.hh"
77#include "DataDefinition.hh"
78#include "DataAddressDef.hh"
80#include "ProgramAnnotation.hh"
81#include "BinaryStream.hh"
82#include "BinaryReader.hh"
83#include "MathTools.hh"
84#include "GlobalScope.hh"
85#include "UniversalMachine.hh"
86#include "Program.hh"
87
88using namespace TTAMachine;
89using namespace TPEF;
90using std::string;
91
92namespace TTAProgram {
93
94/**
95 * Little helper class for storing information of function start points.
96 */
98public:
99 FunctionStart(std::string aName) :
100 name_(aName) { }
101
102 std::string name() const {return name_;}
103
104private:
105 std::string name_;
106};
107
108/**
109 * Constructor.
110 *
111 * For mixed code which contains universal machine references and
112 * target machine references.
113 *
114 * @param aBinary Binary that contains a program's instructions and data.
115 * @param aMachine Actual machine to which parallel code refers.
116 * @param aUniversalMachine Universal machine for sequential code.
117 * @param relocs Managed collection of relocation points in the program.
118 */
120 const Binary& aBinary,
121 const Machine& aMachine,
123 binary_(&aBinary), machine_(&aMachine),
124 universalMachine_(&UniversalMachine::instance()),
125 tpefTools_(aBinary),
126 adfInstrASpace_(NULL),
127 tpefInstrASpace_(NULL) {
128}
129
130/**
131 * Constructor for fully scheduled code.
132 *
133 * @param aBinary Binary that contains a program's instructions and data.
134 * @param aMachine Machine to which code refers.
135 * @param relocs Managed collection of relocation points in the program.
136 */
138 const Binary& aBinary, const Machine& aMachine):
139 binary_(&aBinary), machine_(&aMachine),
140 universalMachine_(&UniversalMachine::instance()),
141 tpefTools_(aBinary),
142 adfInstrASpace_(NULL),
143 tpefInstrASpace_(NULL) {
144}
145
146/**
147 * Constructor for fully unscheduled code.
148 *
149 * @param aBinary Binary that contains a program's instructions and data.
150 * @param uMachine Universal Machine to which code refers.
151 * @param relocs Managed collection of relocation points in the program.
152 */
154 const Binary &aBinary, UniversalMachine*):
155 binary_(&aBinary), machine_(NULL),
156 universalMachine_(&UniversalMachine::instance()),
157 tpefTools_(aBinary),
158 adfInstrASpace_(NULL),
159 tpefInstrASpace_(NULL) {
160}
161
162
163/**
164 * Destructor.
165 */
169
170/**
171 * Returns value of chunk as string.
172 *
173 * Helps getting names for various TPEF resources.
174 *
175 * @param chunk Chunk referring to section.
176 * @param chunkOwner StringSection that contains requested string.
177 * @return String referred by chunk.
178 */
179std::string
181 const Chunk* chunk,
182 const Section* chunkOwner) const {
183
184 const StringSection* strSect =
185 dynamic_cast<const StringSection*>(chunkOwner);
186 assert(strSect != NULL);
187 return strSect->chunk2String(chunk);
188}
189
190/**
191 * Builds program model out of TPEF model.
192 *
193 * @return Created program.
194 * @exception NotAvailable if there the binary contains no sections; if the
195 * instruction address space is missing or conflicting with architecture
196 * definition.
197 * @exception Exception if the TPEF or program in it is somehow broken.
198 */
199Program*
201 assert(machine_ != NULL || universalMachine_ != NULL);
202
204 throw NotAvailable(
205 __FILE__, __LINE__, __func__,
206 "No code sections in TPEF.");
207 }
208
210
211 // get address space for program from machine depending on
212 // type of code (sequential, partially scheduled, fully scheduled)
213 adfInstrASpace_ = NULL;
214
215 if (machine_ == NULL) {
217
218 } else {
219
220 if (binary_->type() == Binary::FT_OBJSEQ ||
223 throw NotAvailable(
224 __FILE__, __LINE__, __func__,
225 "Tried to load a sequential program with ADF already "
226 "loaded.");
227 }
228
229 // check if real machine has address space by defined name.
230 // if not found then use universal address space.
233
234 std::string aSpaceName = stringOfChunk(
237
238 if (aSpaceNav.hasItem(aSpaceName )) {
239 adfInstrASpace_ = aSpaceNav.item(aSpaceName);
240
241 } else {
242 if (universalMachine_ == NULL) {
243 throw NotAvailable(
244 __FILE__, __LINE__, __func__,
245 "No instruction(gcu) address space in ADF.");
246 }
247
249 }
250 }
251
252 if (machine_ == NULL &&
254 throw NotAvailable(
255 __FILE__, __LINE__, __func__,
256 "Tried to load a parallel TPEF without ADF.");
257 }
258
259 assert(adfInstrASpace_ != NULL);
260
261 // ignored for backwards compatibility
262 // if (tpefInstrASpace_->MAU() != 0) {
263 // throw NotAvailable(
264 // __FILE__, __LINE__, __func__,
265 // (boost::format(
266 // "TPEF instruction address space MAU size should be (%d).") %
267 // static_cast<int>(tpefInstrASpace_->MAU())).str());
268 // }
269
270
271 clearCache();
272
274
275 Program* newProgram = new Program(*adfInstrASpace_);
277
278 // create all the code
279 addProcedures(*newProgram, *adfInstrASpace_);
280
282 newProgram->instructionVector();
283 const InstructionAddress startAddress =
284 newProgram->startAddress().location();
285
286 // fix TerminalAddresses pointing to instructions to be
287 // TerminalInstructionAddresses.
288 while (!instructionImmediates_.empty()) {
289 auto move = *instructionImmediates_.begin();
291
292 Terminal &addressTerm = move->source();
293
294 assert(&(addressTerm.address().space()) == adfInstrASpace_);
295
296 Instruction& referencedInstruction =
297 *allInstructions.at(addressTerm.address().location() - startAddress);
298
299 InstructionReference instructionReference =
301 referencedInstruction);
302
304 new TerminalInstructionReference(instructionReference);
305
306 move->setSource(instrTerm);
307 }
308
309 // and same for long immediates which refers to instruction addresses
310 while (!longInstructionImmediates_.empty()) {
311 auto immediate = *longInstructionImmediates_.begin();
313
314 TerminalImmediate &addressTerm = immediate->value();
315
316 assert(&(addressTerm.address().space()) == adfInstrASpace_);
317
318 Instruction& referencedInstruction =
319 *allInstructions.at(addressTerm.address().location() - startAddress);
320
321 InstructionReference instructionReference =
323 referencedInstruction);
324
326 new TerminalInstructionReference(instructionReference);
327
328 immediate->setValue(instrTerm);
329 }
330
331 createDataMemories(*newProgram);
332 createLabels(*newProgram);
333
334 return newProgram;
335}
336
337/**
338 * Parses procedures from all TPEF CodeSections and adds them to Program.
339 *
340 * @param program Program where to add new procedures.
341 * @param programASpace Address space of instruction memory.
342 */
343 void
346 const AddressSpace& programASpace) const {
347
348 // find code sections to chop and organize them by start address
349 std::list<CodeSection*> sectionsToChop;
350
351 for (Word i = 0; i < binary_->sectionCount(Section::ST_CODE); i++) {
352
353 CodeSection* sectionToAdd =
354 dynamic_cast<CodeSection*>(
356
357 if (sectionsToChop.empty()) {
358 sectionsToChop.push_back(sectionToAdd);
359 continue;
360 }
361
362 std::list<CodeSection*>::iterator iter = sectionsToChop.begin();
363
364 while (iter != sectionsToChop.end()) {
365
366 if ((*iter)->startingAddress() >
367 sectionToAdd->startingAddress()) {
368 sectionsToChop.insert(iter, sectionToAdd);
369 break;
370 }
371
372 iter++;
373 }
374 }
375
376 // NOTE: maybe it should be checked if found code sections are legal.
377 // (adressSpaces and addresses does not collide)
378
379 // add instruction elements of every found section
380 std::list<CodeSection*>::iterator sectionIterator =
381 sectionsToChop.begin();
382
383 while (sectionIterator != sectionsToChop.end()) {
384 CodeSection* section = *sectionIterator;
385
386 ResourceSection* resources =
387 dynamic_cast<ResourceSection*>(section->link());
388 assert(resources != NULL);
389
390 Word i = 0;
391 int currentInstructionNumber = 0;
392 while (i < section->elementCount()) {
393
394 try {
395 // Create and add a new procedure to program with name if
396 // new procedure is started by current instruction or if
397 // there is no procedures in program.
398
399 SectionElement* element = section->element(i);
400 InstructionElement* instructionElement =
401 dynamic_cast<InstructionElement*>(element);
402 assert(instructionElement != NULL);
403
404 if (isFunctionStart(*instructionElement) ||
405 program.procedureCount() == 0) {
406
407 assert(instructionElement->begin());
408
409 // TODO: set the real start address.. ?
410
411 Procedure* newProcedure = new Procedure(
412 functionName(*instructionElement),
413 programASpace, 0);
414
415 program.addProcedure(newProcedure);
416 }
417
418 // scan instruction elements of next instruction
419
420 // moves of instruction
421 MoveVector moveElements;
422 // slots that encode immediate bits of instruction
423 ImmediateVector longImmediates;
424 // inline immediates of instruction
425 ImmediateMap immElements;
426
427 InstructionElement* beginElement = NULL;
428
429 do {
430 if (instructionElement->begin()) {
431 beginElement = instructionElement;
432 }
433
434 if (instructionElement->isMove()) {
435 moveElements.push_back(
436 dynamic_cast<MoveElement*>(instructionElement));
437
438 } else if (instructionElement->isImmediate()) {
439 ImmediateElement* imm =
440 dynamic_cast<ImmediateElement*>(
441 instructionElement);
442
443 if (imm->isInline()) {
444 std::pair<Word,Word>
445 immKey(imm->destinationUnit(),
446 imm->destinationIndex());
447 immElements[immKey] = imm;
448 } else {
449 longImmediates.push_back(imm);
450 }
451 } else {
452 abortWithError("Unknown instruction element type.");
453 }
454
455 i++;
456 if (i >= section->elementCount()) {
457 break;
458 }
459
460 SectionElement* sectionElement = section->element(i);
461 assert(sectionElement != NULL);
462
463 instructionElement =
464 dynamic_cast<InstructionElement*>(sectionElement);
465
466 assert(i < section->elementCount());
467
468 } while (instructionElement->begin() == false);
469
470 Instruction* currentInstruction =
471 createInstruction(*resources, moveElements,
472 longImmediates, immElements);
473
474 // add created instruction to map for finding program
475 // instruction by tpef instruction element
476 assert(beginElement != NULL);
477
478 instructionMap_[beginElement] = currentInstruction;
479
480 assert(currentInstruction != NULL);
481
482 program.addInstruction(currentInstruction);
483 currentInstructionNumber++;
484
485 } catch (const Exception& e) {
486 // add instruction number to start of exception message
487 NotAvailable error(
488 __FILE__, __LINE__, __func__,
489 (boost::format(
490 "Instruction %d: ") % currentInstructionNumber).
491 str() + e.errorMessage());
492 error.setCause(e);
493
494 throw error;
495 }
496 }
497
498 sectionIterator++;
499 }
500 }
501
502/**
503 * Creates an instruction out of given moves and immediate elements.
504 *
505 * @param resources TPEF resource section.
506 * @param moveElements Move elements of instruction.
507 * @param longImemdiates Long immediates of instruction.
508 * @param immElements Immediate elements of instruction.
509 * @return A new instruction.
510 */
513 const TPEF::ResourceSection& resources,
514 MoveVector& moveElements,
515 ImmediateVector& longImmediates,
516 ImmediateMap& immElements) const {
517
518 std::vector<SocketAllocation> allocatedSockets;
519
520 Instruction* newInstruction =
522
523 for (unsigned int i = 0; i < moveElements.size(); i++) {
524 MoveElement* move = moveElements[i];
525
526 // NOTE: we just ignore empty moves
527 if (!move->isEmpty()) {
528 std::shared_ptr<TTAProgram::Move> newMove;
529 Terminal* source = NULL;
530 Terminal* destination = NULL;
531 Terminal* guardRegister = NULL;
532 MoveGuard* guard = NULL;
533
534 // get bus
535 Bus& bus = findBus(resources, move->bus());
536
537 try {
538 // create source terminal
539 source = createTerminal(
540 resources, &bus, Socket::OUTPUT, move->sourceType(),
541 move->sourceUnit(), move->sourceIndex(), &immElements);
542
543 // and destination terminal
544 destination = createTerminal(
545 resources, &bus, Socket::INPUT, move->destinationType(),
546 move->destinationUnit(), move->destinationIndex());
547
548 // create guard if move is guarded
549 if (move->isGuarded()) {
550
551 Guard &adfGuard = findGuard(
552 resources,
553 bus,
554 move->guardType(),
555 move->guardUnit(),
556 move->guardIndex(),
557 move->isGuardInverted());
558
559 guard = new MoveGuard(adfGuard);
560
561 assert(guard != NULL);
562 }
563
564 } catch (const NotAvailable& e) {
565
566 if (guard != NULL) {
567 delete guard;
568 guard = NULL;
569
570 } else {
571 if (guardRegister != NULL) {
572 delete guardRegister;
573 guardRegister = NULL;
574 }
575 }
576
577 if (source != NULL) {
578 delete source;
579 source = NULL;
580 }
581
582 if (destination != NULL) {
583 delete destination;
584 destination = NULL;
585 }
586
587 delete newInstruction;
588 newInstruction = NULL;
589
590 throw e;
591 } catch (Exception& e) {
592 throw e;
593 }
594
595 if (guard != NULL) {
596 newMove = std::make_shared<TTAProgram::Move>(source, destination, bus, guard);
597 } else {
598 newMove = std::make_shared<TTAProgram::Move>(source, destination, bus);
599 }
600 assert(newMove != NULL);
601
602 // Add possible sockets for register references.
603 Machine::SocketNavigator socketNav =
604 bus.machine()->socketNavigator();
605
606 SocketAllocation newAlloc(newMove, allocatedSockets.size());
607
608 // find possible sockets for move source and destination
609 for (int i = 0; i < socketNav.count(); i++) {
610 Socket* currSocket = socketNav.item(i);
611
612 if (currSocket->isConnectedTo(bus)) {
613 for (int j = 0; j < currSocket->portCount(); j++) {
614
615 if ((source->isGPR() ||
616 source->isImmediateRegister()) &&
617 currSocket->direction() == Socket::OUTPUT &&
618 currSocket->port(j)->parentUnit() ==
619 source->port().parentUnit()) {
620
621 newAlloc.srcSocks.push_back(currSocket);
622 }
623
624 if ((destination->isGPR() ||
625 destination->isImmediateRegister()) &&
626 currSocket->direction() == Socket::INPUT &&
627 currSocket->port(j)->parentUnit() ==
628 destination->port().parentUnit()) {
629
630 newAlloc.dstSocks.push_back(currSocket);
631 }
632 }
633 }
634 }
635
636 allocatedSockets.push_back(newAlloc);
637
638 // add move annotations
639 if (move->annotationCount() > 0) {
640 for (Word annotationIndex = 0;
641 annotationIndex < move->annotationCount();
642 ++annotationIndex) {
643 newMove->addAnnotation(
645 static_cast<ProgramAnnotation::Id>(
646 move->annotation(annotationIndex)->id()),
647 move->annotation(annotationIndex)->payload()));
648 }
649 }
650
651 newInstruction->addMove(newMove);
652
653 if (newMove->source().isAddress() &&
654 &(newMove->source().address().space()) == adfInstrASpace_) {
655 instructionImmediates_.push_back(newMove);
656 }
657 } else {
658 // empty instruction
659
660 // add move annotations
661 if (move->annotationCount() > 0) {
662 for (Word annotationIndex = 0;
663 annotationIndex < move->annotationCount();
664 ++annotationIndex) {
665 newInstruction->addAnnotation(
667 static_cast<ProgramAnnotation::Id>(
668 move->annotation(annotationIndex)->id()),
669 move->annotation(annotationIndex)->payload()));
670 }
671 }
672
673 }
674 }
675
676 // get template
677 InstructionTemplate& instrTemplate =
678 findInstrTemplate(resources, longImmediates, moveElements);
679
680 newInstruction->setInstructionTemplate(instrTemplate);
681
682 // and add long immediates
683 for (unsigned int i = 0; i < longImmediates.size(); i++) {
684 ImmediateElement* imm = longImmediates[i];
685 Byte iUnitID = imm->destinationUnit();
686
687 Terminal* destination = createTerminal(
688 resources, NULL, Socket::INPUT,
689 MoveElement::MF_IMM, iUnitID, imm->destinationIndex());
690
691 ImmediateUnit& immUnit(findImmediateUnit(resources, iUnitID));
692 SimValue simVal(instrTemplate.supportedWidth(immUnit));
693
694 if (immUnit.signExtends()) {
695 simVal = imm->sLongWord();
696 } else {
697 simVal = imm->longWord();
698 }
699
700 TerminalImmediate* immTerm = NULL;
701
702 // TODO: refactor with createTerminal method's line 57
703 bool isInstructionReference = false;
704
705 if (tpefTools_.hasRelocation(*imm)) {
706 const RelocElement &reloc = tpefTools_.relocation(*imm);
707
708 // check if instruction address space
709 if (tpefInstrASpace_ == reloc.aSpace()) {
710 // create temporary TerminalAddress and add to vector
711 // for late replacement
712 immTerm = new TerminalAddress(simVal, *adfInstrASpace_);
713
714 isInstructionReference = true;
715
716 } else {
717 AddressSpace& adfDataSpace =
718 findAddressSpace(reloc.aSpace());
719 immTerm =
720 new TerminalAddress(simVal, adfDataSpace);
721 }
722
723 } else {
724 immTerm = new TerminalImmediate(simVal);
725 }
726
727 auto newImmediate = std::make_shared<Immediate>(immTerm, destination);
728
729 newInstruction->addImmediate(newImmediate);
730
731 if (isInstructionReference) {
732 longInstructionImmediates_.push_back(newImmediate);
733 }
734 }
735
736 resolveSocketAllocations(allocatedSockets);
737 return newInstruction;
738}
739
740/**
741 * Creates a move terminal of the appropriate type for given input data.
742 *
743 * This method *cannot* be used for creating terminal for immediate unit
744 * or register file registers.
745 *
746 *
747 * @param resources TPEF resource section.
748 * @param aBus Bus to which terminal is connected.
749 * @param direction Read or write terminal.
750 * @param type TPEF type of terminal.
751 * @param unitId TPEF identification code of the unit to which terminal
752 * belongs.
753 * @param index Register or operation terminal index, or immediate
754 * identifier.
755 * @param immediateMap All immediates of currently created instruction.
756 * @return A new move terminal.
757 */
760 const ResourceSection& resources, const Bus* aBus,
761 Socket::Direction direction, MoveElement::FieldType type, HalfWord unitId,
762 HalfWord index, const ImmediateMap* immediateMap) const {
763
764 // omit caching because RF and IMM unit ports are resolved later
765 if (type == MoveElement::MF_RF) {
766 // port(0) just a dummy temporary assignment, it may even be illegal
767 RegisterFile& registerFile = findRegisterFile(resources, unitId);
768 return new TerminalRegister(*registerFile.port(0), index);
769
770 } else if (type == MoveElement::MF_IMM &&
771 unitId != ResourceElement::INLINE_IMM) {
772
773 // port(0) just a dummy temporary assignment, it may even be illegal
774 ImmediateUnit& immUnit = findImmediateUnit(resources, unitId);
775 return new TerminalRegister(*immUnit.port(0), index);
776 }
777
778 CacheKey cacheKey(*aBus, direction, type, unitId, index);
779
780 Terminal* returnValue = getFromCache(cacheKey);
781
782 if (returnValue == NULL) {
783
784 switch (type) {
785
786 case MoveElement::MF_IMM: {
787 ImmediateKey immKey(unitId, index);
788 ImmediateElement* imm = NULL;
789
790 if (MapTools::containsKey(*immediateMap, immKey)) {
792 *immediateMap, immKey);
793 } else {
795 << "Cannot find immediate with unitId/index "
796 << static_cast<int>(unitId) << "/" << index << std::endl
797 << "immediateMap.size(): " << immediateMap->size()
798 << std::endl;
800 }
801
802 if (imm->isInline()) {
803
804 int immWidth = aBus->immediateWidth();
805 SimValue simValue(immWidth);
806 simValue = imm->longWord();
807
808 // TODO: refactor with line createInstruction
809 // method's line 158
810 if (tpefTools_.hasRelocation(*imm)) {
811 const RelocElement &reloc = tpefTools_.relocation(*imm);
812
813 // check if instruction address space
814 if (tpefInstrASpace_ == reloc.aSpace()) {
815 // create temporary TerminalAddress and add to vector
816 // for late replacement
817 returnValue =
818 new TerminalAddress(simValue, *adfInstrASpace_);
819
820 } else {
821 try {
822 AddressSpace& adfDataSpace =
823 findAddressSpace(reloc.aSpace());
824 returnValue =
825 new TerminalAddress(simValue, adfDataSpace);
826 } catch (const NotAvailable& e) {
827 NotAvailable newException(
828 __FILE__, __LINE__, __func__,
829 (boost::format(
830 "Unable to find address space for "
831 "target of reloc element for immediate "
832 "'%d'.") % imm->word()).
833 str());
834 newException.setCause(e);
835 throw newException;
836 }
837 }
838
839 } else {
840 returnValue = new TerminalImmediate(simValue);
841 }
843 dynamic_cast<TerminalImmediate*>(returnValue);
844 assert(returnValue != NULL);
845 // add immediate annotations
846 if (imm->annotationCount() > 0) {
847 for (Word annotationIndex = 0;
848 annotationIndex < imm->annotationCount();
849 ++annotationIndex) {
850 retVal->addAnnotation(
852 static_cast<ProgramAnnotation::Id>(
853 imm->annotation(annotationIndex)->id()),
854 imm->annotation(annotationIndex)->payload()));
855 }
856 }
857
858 } else {
859 abortWithError("Error: immediate register references "
860 "should be already handled in same place "
861 "with normal register references.");
862 }
863 } break;
864
866 ResourceElement* tpefResource = NULL;
867
868 // TODO refactor
869 if (resources.hasResource(
870 ResourceElement::MRT_OP, index)) {
871
872 tpefResource =
873 &resources.findResource(ResourceElement::MRT_OP, index);
874
875 } else if (resources.hasResource(
877
878 tpefResource =
879 &resources.findResource(ResourceElement::MRT_PORT, index);
880
881 } else if (resources.hasResource(
882 ResourceElement::MRT_SR, index)) {
883
884 tpefResource =
885 &resources.findResource(ResourceElement::MRT_SR, index);
886
887 } else {
888 abortWithError("Can't find resource port, operation or "
889 "special register with index:" +
890 Conversion::toString(index));
891
892 }
893
894 assert(tpefResource != NULL);
895
896 std::string tpefOpStr =
897 stringOfChunk(tpefResource->name(), resources.link());
898
899 // TODO:
900 // I need only unit.port and unit.operation.index parsing since
901 // unit.port.opcode references are converted to
902 // unit.operation.index form in tpef
903
904 // NOTE:
905 // for now parser can chop just add.1 and sub.3 etc. kind of
906 // strings.
907
908 // start of hack parser
909 bool opCodePort = false;
910 std::string::size_type opNameLength = tpefOpStr.rfind('.');
911 std::string tpefOpName = tpefOpStr;
912 int tpefOpIndex = 0;
913
914 if (opNameLength != std::string::npos) {
915 tpefOpName = tpefOpStr.substr(0, opNameLength);
916 std::string::size_type opIndexStart = opNameLength + 1;
917 std::string tpefOpIndexStr =
918 tpefOpStr.substr(
919 opIndexStart, tpefOpStr.length() - opIndexStart);
920 tpefOpIndex = Conversion::toInt(tpefOpIndexStr);
921 opCodePort = true;
922 }
923 // end of hack parser
924
925 // returns normal fu or universal fu or universal gcu..
926 FunctionUnit& functionUnit =
927 findFunctionUnit(resources, unitId, tpefOpName);
928
929 if (opCodePort) {
930 // find HWOperation....
931 HWOperation& oper = *functionUnit.operation(tpefOpName);
932 returnValue = new TerminalFUPort(oper, tpefOpIndex);
933
934 } else {
935 // special register or plain port reference
936 BaseFUPort& port = dynamic_cast<BaseFUPort&>(
937 findPort(*aBus, functionUnit, tpefOpName));
938
939 returnValue = new TerminalFUPort(port);
940 }
941 } break;
942
943 default: {
944 abortWithError("Unknown move field type!");
945 }
946
947 }
948
949 // immediates are not cached...
950 if (type != MoveElement::MF_IMM) {
951 addToCache(cacheKey, returnValue);
952 }
953
954 } else {
955 return returnValue->copy();
956 }
957
958 return returnValue;
959}
960
961/**
962 * Returns the bus of real or universal machine with the given bus
963 * identification number, as found in TPEF.
964 *
965 * @param resources The resource section where the bus should be searched.
966 * @param busId Id of requested bus.
967 * @return Requested bus.
968 * @exception NotAvailable if requested bus does not belong to the
969 * target architecture.
970 */
971Bus&
973 const ResourceSection &resources,
974 HalfWord busId) const {
975
976 if (busId == ResourceElement::UNIVERSAL_BUS) {
977 if (universalMachine_ == NULL) {
978 throw NotAvailable(
979 __FILE__, __LINE__, __func__,
980 "TPEF needs universal machine for universal bus reference.");
981 }
982
984
985 } else {
986 if (machine_ == NULL) {
987 throw NotAvailable(
988 __FILE__, __LINE__, __func__,
989 "TPEF needs real machine for non-universal bus reference.");
990 }
991
992 // internal error with TPEF...
994
995 ResourceElement &tpefBus =
996 resources.findResource(ResourceElement::MRT_BUS, busId);
997
998 std::string busName =
999 stringOfChunk(tpefBus.name(), resources.link());
1000
1001 if (!machine_->busNavigator().hasItem(busName)) {
1002 throw NotAvailable(
1003 __FILE__, __LINE__, __func__,
1004 "ADF does not contain bus: " + busName);
1005 }
1006
1007 return *(machine_->busNavigator().item(busName));
1008 }
1009}
1010
1011/**
1012 * Returns RegisterFile by TPEF id number.
1013 *
1014 * @param resources The resource section where the bus should be searched.
1015 * @param rfId Id of requested register file.
1016 * @return Register file from real or universal machine.
1017 * @exception NotAvailable if requested register file does not belong to the
1018 * target architecture.
1019 */
1022 const ResourceSection& resources,
1023 HalfWord rfId) const {
1024
1025 switch (rfId) {
1026
1028 abortWithError("Illegal registerfile ID!");
1029
1031 if (universalMachine_ == NULL) {
1032 throw NotAvailable(
1033 __FILE__, __LINE__, __func__,
1034 "TPEF needs universal machine for universal integer RF "
1035 "reference.");
1036 }
1037
1039
1041 if (universalMachine_ == NULL) {
1042 throw NotAvailable(
1043 __FILE__, __LINE__, __func__,
1044 "TPEF needs universal machine for universal boolean RF "
1045 "reference.");
1046 }
1047
1049
1051 if (universalMachine_ == NULL) {
1052 throw NotAvailable(
1053 __FILE__, __LINE__, __func__,
1054 "TPEF needs universal machine for universal floating point "
1055 "RF reference.");
1056 }
1057
1059
1060 default: {
1061
1062 if (machine_ == NULL) {
1063 throw NotAvailable(
1064 __FILE__, __LINE__, __func__,
1065 "TPEF needs real machine for non-universal RF reference.");
1066 }
1067
1068 ResourceElement &tpefRF =
1069 resources.findResource(ResourceElement::MRT_RF, rfId);
1070
1071 std::string rfName =
1072 stringOfChunk(tpefRF.name(), resources.link());
1073
1074 if (!machine_->registerFileNavigator().hasItem(rfName)) {
1075 throw NotAvailable(
1076 __FILE__, __LINE__, __func__,
1077 "Can't find RF \"" + rfName + "\" from ADF.");
1078 }
1079
1080 return *(machine_->registerFileNavigator().item(rfName));
1081 }
1082
1083 }
1084
1085 abortWithError("This line should never be executed!");
1087}
1088
1089/**
1090 * Returns ImmediateUnit by TPEF id number.
1091 *
1092 * @param resources The resource section where the bus should be searched.
1093 * @param immUnitId Id of requested immediate unit.
1094 * @return Immediate unit.
1095 * @exception NotAvailable if requested immediate unit does not belong to the
1096 * target architecture.
1097 */
1100 const ResourceSection& resources,
1101 Byte immUnitId) const {
1102
1103 if (machine_ == NULL) {
1104 throw NotAvailable(
1105 __FILE__, __LINE__, __func__,
1106 "TPEF needs real machine for immediate unit reference.");
1107 }
1108
1109 ResourceElement &tpefImmUnit =
1110 resources.findResource(ResourceElement::MRT_IMM, immUnitId);
1111
1112 std::string immUnitName =
1113 stringOfChunk(tpefImmUnit.name(), resources.link());
1114
1115 if (!machine_->immediateUnitNavigator().hasItem(immUnitName)) {
1116 throw NotAvailable(
1117 __FILE__, __LINE__, __func__,
1118 "Can't find immediate unit \"" + immUnitName + "\" from ADF.");
1119 }
1120
1121 return *(machine_->immediateUnitNavigator().item(immUnitName));
1122}
1123
1124/**
1125 * Returns FunctionUnit by TPEF identification number and operation name.
1126 *
1127 * If function unit ID corresponds to the universal function unit, then
1128 * operation name is checked to see if we should return universal gcu or
1129 * universal fu.
1130 *
1131 * If operation name is special register of function unit or if operation
1132 * name is operation of gcu then universal gcu is returned.
1133 *
1134 * @param resources The resource section where the bus should be searched.
1135 * @param unitId Id of requested unit.
1136 * @param tpefOpName Name of operation or special register for
1137 * universal machine resources.
1138 * @return Function unit from real or universal machine.
1139 * @exception NotAvailable if requested function unit does not belong to the
1140 * target architecture.
1141 */
1144 const ResourceSection& resources,
1145 HalfWord unitId,
1146 std::string tpefOpName) const {
1147
1148 switch (unitId) {
1149
1151
1152 if (universalMachine_ == NULL) {
1153 throw NotAvailable(
1154 __FILE__, __LINE__, __func__,
1155 "TPEF needs universal machine for getting universal FU.");
1156 }
1157
1159
1160 assert(gcu != NULL);
1161
1162 if (tpefOpName == ResourceElement::RETURN_ADDRESS_NAME) {
1163 return *gcu;
1164 }
1165
1167 assert(fu != NULL);
1168
1169 if (gcu->hasOperation(tpefOpName)) {
1170 return *gcu;
1171
1172 } else if (fu->hasOperation(tpefOpName)) {
1173 return *fu;
1174
1175 } else {
1176 boost::format errMsg(
1177 "Unknown operation '%1%'. Operation definition not found.");
1178 throw NotAvailable(
1179 __FILE__, __LINE__, __func__, (errMsg % tpefOpName).str());
1180 }
1181 }
1182
1183 default: {
1184
1185 if (machine_ == NULL) {
1186 throw NotAvailable(__FILE__, __LINE__, __func__,
1187 "TPEF needs real target architecture for getting a "
1188 "non-universal FU.");
1189 }
1190
1191 ResourceElement &tpefFU = resources.findResource(
1193
1194 std::string fuName =
1195 stringOfChunk(tpefFU.name(), resources.link());
1196
1197 if (machine_->functionUnitNavigator().hasItem(fuName)) {
1198 return *(machine_->functionUnitNavigator().item(fuName));
1199
1200 } else {
1201
1202 // maybe it's GCU ..
1203 if (machine_->controlUnit()->name() == fuName) {
1204 return *machine_->controlUnit();
1205
1206 } else {
1207 throw NotAvailable(
1208 __FILE__, __LINE__, __func__,
1209 "Can't find RFU \"" + fuName + "\" from ADF.");
1210 }
1211 }
1212 }
1213
1214 }
1215
1216 abortWithError("This line should never be run!");
1218}
1219
1220/**
1221 * Finds any function unit or special register port from target architecture
1222 * (possiby the universal machine).
1223 *
1224 * NOTE: this is currently used only for plain port references
1225 * (sr or port without opcode) if TPEFProgramFactory. However
1226 * method should be able finding also function unit ports.
1227 *
1228 * @param bus Bus where to socket is connected.
1229 * @param portParent Parent to which port in connected to.
1230 * @param tpefOpName Name of operation if opcode port to find.
1231 * @param tpefOpIndex Terminal index of operation if opcode port to find.
1232 * @return Found port.
1233 * @exception NotAvailable if requested port does not belong to the target
1234 * architecture.
1235 */
1236Port&
1238 const Bus& bus,
1239 const Unit& portParent,
1240 std::string tpefOpName,
1241 int tpefOpIndex) const {
1242
1243 const Machine* machineOfBus = NULL;
1244
1245 if (universalMachine_ != NULL &&
1246 &bus == &universalMachine_->universalBus()) {
1247 machineOfBus = universalMachine_;
1248 } else {
1249 machineOfBus = machine_;
1250 }
1251
1252 assert(machineOfBus != NULL);
1253
1254 // check if it is function unit port to find
1255 const FunctionUnit* fu =
1256 dynamic_cast<const FunctionUnit*>(&portParent);
1257
1258 if (fu != NULL) {
1259
1260 // check if known special register (for sequential code)
1261 if (tpefOpName == ResourceElement::RETURN_ADDRESS_NAME) {
1262
1263 const ControlUnit &controlUnit =
1264 dynamic_cast<const ControlUnit&>(portParent);
1265
1266 if (controlUnit.hasReturnAddressPort()) {
1267 return *(controlUnit.returnAddressPort());
1268
1269 } else {
1270 throw NotAvailable(
1271 __FILE__, __LINE__, __func__,
1272 "GCU needs return address port.");
1273 }
1274
1275 } else {
1276 // function unit is either gcu or real fu
1277
1278 // if operation index is valid and opname is found from FU
1279 // then we know that it's port with opcode given
1280 if (fu->hasOperation(tpefOpName) && tpefOpIndex != 0) {
1281 // must be operation port
1282 HWOperation* oper = fu->operation(tpefOpName);
1283 return *(oper->port(tpefOpIndex));
1284
1285 } else if (fu->hasPort(tpefOpName)) {
1286 // must be special plain port reference
1288 dynamic_cast<TTAMachine::SpecialRegisterPort*>(
1289 fu->port(tpefOpName));
1290
1291 if (srPort != NULL) {
1292 // NOTE: only known specialregister ports are allowed!
1293 // add asserts for special registers here :)
1294 assert(srPort ==
1295 machineOfBus->controlUnit()->returnAddressPort());
1296 return *srPort;
1297 } else {
1298 return *fu->port(tpefOpName);
1299 }
1300
1301 } else {
1302 throw NotAvailable(
1303 __FILE__, __LINE__, __func__, "Can't find port for: " +
1304 fu->name() + "." + tpefOpName + "." +
1305 Conversion::toString(tpefOpIndex));
1306 }
1307 }
1308 }
1309
1310 // didn't seem to be fu port... this is not used for normal
1311 // registers anymore...
1312
1313 std::string throwError = "Can't find port for: " + portParent.name();
1314
1315 if (tpefOpName != "") {
1316 throwError += "." + tpefOpName;
1317 }
1318
1319 throwError += "." + Conversion::toString(tpefOpIndex);
1320
1321 throw NotAvailable(__FILE__, __LINE__, __func__,throwError);
1322}
1323
1324/**
1325 * Finds address space by name.
1326 *
1327 * @param Name of address space.
1328 * @return Address space.
1329 * @exception NotAvailable if requested address space does not belong to
1330 * the target architecture.
1331 */
1334
1335 std::string aSpaceName = tpefTools_.addressSpaceName(*aSpace);
1336
1337 if (machine_ != NULL) {
1340
1341 if (aSpaceNavi.hasItem(aSpaceName)) {
1342 return *aSpaceNavi.item(aSpaceName);
1343 }
1344 }
1345
1346 if (universalMachine_ != NULL) {
1347 if (aSpaceName == universalMachine_->dataAddressSpace().name()) {
1349 } else if (aSpaceName ==
1352
1353 }
1354 }
1355
1356 throw NotAvailable(
1357 __FILE__, __LINE__, __func__,
1358 "Can't find address space by name: " + aSpaceName +
1359 " MAU: " + Conversion::toString(static_cast<int>(aSpace->MAU())));
1360}
1361
1362/**
1363 * Finds guard of bus.
1364 *
1365 * @param resources TPEF resource section.
1366 * @param bus Bus of guard.
1367 * @param type Is fu or register guard.
1368 * @param unitId Id of the unit that contains guard register or port.
1369 * @param index Register or operand index of guard.
1370 * @param isInverted Is inverted guard.
1371 */
1374 const TPEF::ResourceSection &resources,
1376 HalfWord unitId, HalfWord index, bool isInverted) const {
1377
1378 RegisterFile* guardRF = NULL;
1379 Port* guardPort = NULL;
1380
1381 // find corresponding function unit or register file.
1382 switch (type) {
1384 FunctionUnit &guardUnit = findFunctionUnit(resources, unitId);
1385
1386 // find port
1387 ResourceElement* resource = NULL;
1388
1389 // TODO refactor
1390 if (resources.hasResource(
1391 ResourceElement::MRT_OP, index)) {
1392
1393 resource =
1394 &resources.findResource(ResourceElement::MRT_OP, index);
1395
1396 } else if (resources.hasResource(
1397 ResourceElement::MRT_PORT, index)) {
1398
1399 resource =
1400 &resources.findResource(ResourceElement::MRT_PORT, index);
1401
1402 } else if (resources.hasResource(
1403 ResourceElement::MRT_SR, index)) {
1404
1405 resource =
1406 &resources.findResource(ResourceElement::MRT_SR, index);
1407
1408 } else {
1409 abortWithError("Can't find resource port, operation or "
1410 "special register with index:" +
1411 Conversion::toString(index));
1412
1413 }
1414
1415
1416 std::string tpefOpStr =
1417 stringOfChunk(resource->name(), resources.link());
1418
1419 // find operation port or special register port
1420 if (guardUnit.hasPort(tpefOpStr)) {
1421 guardPort = guardUnit.port(tpefOpStr);
1422
1423 } else {
1424 std::string::size_type dotPos = tpefOpStr.find('.');
1425 assert (dotPos != std::string::npos);
1426 std::string operationName = tpefOpStr.substr(0, dotPos);
1427 HWOperation* oper = guardUnit.operation(operationName);
1428 Word operandIndex = Conversion::toInt(
1429 tpefOpStr.substr(dotPos+1, tpefOpStr.length() - dotPos - 1));
1430
1431 guardPort = oper->port(operandIndex);
1432 }
1433 } break;
1434
1436 guardRF = &findRegisterFile(resources, unitId);
1437 break;
1438
1439 default:
1441 "Error: Unknown guard type. Guard must be either FU port "
1442 "or RF index.");
1443 }
1444
1445 assert (reinterpret_cast<long int>(guardPort) !=
1446 reinterpret_cast<long int>(guardRF));
1447
1448 for (int i = 0; i < bus.guardCount(); i++) {
1449 Guard* currGuard = bus.guard(i);
1450
1451 if (currGuard->isInverted() == isInverted) {
1452 PortGuard* portGuard = dynamic_cast<PortGuard*>(currGuard);
1453 RegisterGuard* registerGuard =
1454 dynamic_cast<RegisterGuard*>(currGuard);
1455
1456 if (portGuard != NULL && guardPort != NULL) {
1457 if (portGuard->port() == guardPort) {
1458 return *currGuard;
1459 }
1460
1461 } else if (registerGuard != NULL && guardRF != NULL) {
1462 if (registerGuard->registerFile() == guardRF &&
1463 registerGuard->registerIndex() == index) {
1464 return *currGuard;
1465 }
1466 }
1467 }
1468 }
1469
1470 std::string guardType;
1471 if (isInverted) {
1472 guardType = "! ";
1473 } else {
1474 guardType = "? ";
1475 }
1476
1477 if (guardRF != NULL) {
1478 guardType += guardRF->name() + "." + Conversion::toString(index);
1479 }
1480
1481 if (guardPort != NULL) {
1482 guardType += "Some FU operation or special register.";
1483 }
1484
1485 throw NotAvailable(
1486 __FILE__, __LINE__, __func__,
1487 "Can't find suitable guard: " + guardType + "\tfrom bus: " +
1488 bus.name());
1489
1490 return *bus.guard(0);
1491}
1492
1493/**
1494 * Returns instruction template that can be used for current instruction.
1495 *
1496 * @param resources TPEF resource section.
1497 * @param longImmediates Long immediates of instruction.
1498 * @param moves Moves of instruction.
1499 * @return Instruction template that can be used for this instruction.
1500 */
1503 const TPEF::ResourceSection &resources,
1504 ImmediateVector& longImmediates,
1505 MoveVector& moves) const {
1506
1507 if (machine_ == NULL) {
1508 assert(
1511 }
1512
1513 // check how many bits must be written to each immediate unit....
1514 std::map<ImmediateUnit*, int> bitsToWrite;
1515
1516 for (unsigned int i = 0; i < longImmediates.size(); i++) {
1517 ImmediateElement* imm = longImmediates[i];
1518
1519 // destination unit
1520 ImmediateUnit* dstUnit =
1521 &findImmediateUnit(resources, imm->destinationUnit());
1522
1523 if (MapTools::containsKey(bitsToWrite, dstUnit)) {
1524 throw NotAvailable(
1525 __FILE__, __LINE__, __func__,
1526 "Can't write two immediates to the same immediate unit "
1527 " in the same instruction.");
1528 } else {
1529 bitsToWrite[dstUnit] = dstUnit->zeroExtends() ?
1532 }
1533 }
1534
1535 // find suitable template
1538
1539 // try to find an instruction template with the most NOP slots
1540 // to enhance the possible variable length encoding benefits
1541 InstructionTemplate* bestiTempFound = NULL;
1542
1543 for (int i = 0; i < tempNav.count(); i++) {
1544 InstructionTemplate* insTemp = tempNav.item(i);
1545
1546 // check if numberOfDestinations is same that number of
1547 // immediates to write
1548 if (insTemp->numberOfDestinations() ==
1549 static_cast<int>(bitsToWrite.size())) {
1550
1551 bool templateIsGood = true;
1552
1553 // check that destinations and bitwidths match
1554 for (std::map<ImmediateUnit*, int>::iterator iter =
1555 bitsToWrite.begin();
1556 iter != bitsToWrite.end();
1557 iter++) {
1558
1559 if (!insTemp->isOneOfDestinations(*(*iter).first) ||
1560 (*iter).second >
1561 insTemp->supportedWidth(*(*iter).first)) {
1562 templateIsGood = false;
1563 break;
1564 }
1565 }
1566
1567 // check if move slots allows to use this template
1568 if (templateIsGood) {
1569 for (unsigned int j = 0; j < moves.size(); j++) {
1570 MoveElement* move = moves[j];
1571
1572 if (move->isEmpty()) {
1573 continue;
1574 }
1575
1576 Bus& usedBus = findBus(resources, move->bus());
1577
1578 // can be NOP slot also in which case the template cannot
1579 // used for the move either
1580 if (insTemp->usesSlot(usedBus.name())) {
1581 templateIsGood = false;
1582 break;
1583 }
1584 }
1585 }
1586
1587 // if template passed all the checks
1588 if (templateIsGood) {
1589 if (bestiTempFound == NULL)
1590 bestiTempFound = insTemp;
1591 }
1592 }
1593 }
1594
1595 if (bestiTempFound == NULL) {
1596 std::string bitRequirementmsg;
1597 for (const auto& pair : bitsToWrite) {
1598 bitRequirementmsg += Conversion::toString(pair.second)
1599 + " bits to IU: " + pair.first->name() + "\n";
1600 }
1602 "Valid instruction template is not found for instruction layout:\n"
1603 + "An instruction template is needed that can write:\n"
1604 + bitRequirementmsg);
1605 } else {
1606 return *bestiTempFound;
1607 }
1608}
1609
1610/**
1611 * Checks if the source of SocketAllocation can be assigned towards
1612 * given map of already allocated sockets.
1613 *
1614 * If tried socket is already used, it still can be used for another
1615 * reading if
1616 * 1) the source register index is same for both of the allocations, or
1617 * 2) the moves have opposite guards.
1618 *
1619 * @param alloc Socket allocation structure which is checked.
1620 * @param fixedSockets Map of already made socket allocations.
1621 * @return True if tried alloc is possible.
1622 */
1623bool
1625 SocketAllocation& alloc,
1626 std::map<Socket*, std::vector<SocketAllocation*> >& fixedSockets) const {
1627
1628 Socket* currentSocket = alloc.srcSocks[alloc.src];
1629
1630 if (MapTools::containsKey(fixedSockets, currentSocket)) {
1631
1632 std::vector<SocketAllocation*>& socketAllocs = fixedSockets[currentSocket];
1633
1634 // test against all allocations.
1635 for (unsigned int i = 0; i < socketAllocs.size(); i++) {
1636 // TODO: check against all users.
1637 auto oldMove = socketAllocs[i]->move;
1638 Terminal* oldTerminal = &(oldMove->source());
1639
1640 // allowed for same register of opposite guard.
1641 if (alloc.move->source().index() != oldTerminal->index() &&
1642 (alloc.move->isUnconditional() || oldMove->isUnconditional() ||
1643 !alloc.move->guard().guard().isOpposite(oldMove->guard().guard()))) {
1644 return false;
1645 }
1646 }
1647 //Application::errorStream() << insTemp->NOPSlotCount() << " " << templateIsGood << " ";
1648 //Application::errorStream() << std::endl;
1649 }
1650
1651 return true;
1652}
1653
1654
1655/**
1656 * Checks if the destination of SocketAllocation can be assigned towards
1657 * given map of already allocated sockets.
1658 *
1659 * If tried socket is already used, it still can be used for another
1660 * writing if the moves have opposite guards.
1661 *
1662 * @param alloc Socket allocation structure which is checked.
1663 * @param fixedSockets Map of already made socket allocations.
1664 * @return True if tried alloc is possible.
1665 */
1666bool
1668 SocketAllocation& alloc,
1669 std::map<Socket*, std::vector<SocketAllocation*> >& fixedSockets) const {
1670
1671 Socket* currentSocket = alloc.dstSocks[alloc.dst];
1672
1673 if (MapTools::containsKey(fixedSockets, currentSocket)) {
1674
1675 std::vector<SocketAllocation*>& socketAllocs = fixedSockets[currentSocket];
1676
1677 // test against all allocations.
1678 for (unsigned int i = 0; i < socketAllocs.size(); i++) {
1679 // TODO: check against all users.
1680 auto oldMove = socketAllocs[i]->move;
1681 if (alloc.move->isUnconditional() || oldMove->isUnconditional() ||
1682 !alloc.move->guard().guard().isOpposite(
1683 oldMove->guard().guard())) {
1684 return false;
1685 }
1686 }
1687 }
1688 return true;
1689}
1690
1691
1692
1693
1694/**
1695 * Resolves sockets that are used for GPR and Immediate Unit reading and
1696 * writing for instruction.
1697 *
1698 * NOTE: TPEF specification currently supports storing port information
1699 * of GPR references, so if this solution does not work or
1700 * if this is too slow, then register port information should
1701 * be implemented to TPEF object modell.
1702 *
1703 * @todo Yes, we should store the port allocations also
1704 * to TPEF, if they have been assigned by the scheduler. This kind of
1705 * resolving again and again does not make sense!
1706 *
1707 * @param allocs All GPR and IU reads and writes of instruction.
1708 * One item in this vector represents one move in the instruction.
1709 */
1710void
1712 std::vector<SocketAllocation>& allocs) const {
1713
1714 // map of socket to all moves which use it.
1715 std::map<Socket*, std::vector<SocketAllocation*> > fixedSockets;
1716
1717 // try to resolve working combination starting from the first allocation
1718 unsigned currIndex = 0;
1719
1720 while (currIndex < allocs.size()) {
1721 bool allocationWasSuccess = true;
1722
1723 SocketAllocation& alloc = allocs[currIndex];
1724
1725 if (alloc.srcSocks.empty()) {
1726 currIndex++;
1727 continue;
1728 }
1729
1730 // try to get allocation for current element
1731 if (alloc.src < alloc.srcSocks.size()) {
1732 while (!canSourceBeAssigned(alloc, fixedSockets)) {
1733 alloc.src++;
1734
1735 if (alloc.src == alloc.srcSocks.size()) {
1736 // working socket could not be found
1737 allocationWasSuccess = false;
1738 break;
1739 }
1740 }
1741 } else {
1742 allocationWasSuccess = false;
1743 }
1744
1745 // if allocation was success add allocation to for the socket
1746 // otherwise remove the latest allocations and try to resolve them
1747 // again
1748
1749 if (allocationWasSuccess) {
1750 // assign allocation for this socket
1751 Socket* currentSocket = alloc.srcSocks[alloc.src];
1752 fixedSockets[currentSocket].push_back(&alloc);
1753
1754 } else {
1755 // reset allocation try sequence
1756 alloc.src = 0;
1757
1758 // free previous allocation and try again
1759 unsigned int prevIndex = currIndex;
1760
1761 do {
1762 if (prevIndex == 0) {
1763 throw NotAvailable(
1764 __FILE__, __LINE__, __func__,
1765 "Can't resolve src sockets for instruction.");
1766 }
1767
1768 prevIndex--;
1769
1770 } while (allocs[prevIndex].srcSocks.empty());
1771
1772
1773 Socket* socketToFree =
1774 allocs[prevIndex].srcSocks[allocs[prevIndex].src];
1775 std::vector<SocketAllocation*>& freedAllocs =
1776 fixedSockets[socketToFree];
1777
1778 bool prevFound = false;
1779 // find first freed allocation where we continue search
1780 for (int k = prevIndex; k >= 0 && !prevFound; k--) {
1781 for (std::vector<SocketAllocation*>::iterator j =
1782 freedAllocs.begin(); j != freedAllocs.end(); j++) {
1783
1784 if (static_cast<int>((*j)->index) == k) {
1785 (*j)->src++;
1786 currIndex = k;
1787 prevFound = true;
1788 freedAllocs.erase(j);
1789 break;
1790 }
1791 }
1792 }
1793 continue; // don't touch currIndex here
1794 }
1795
1796 currIndex++;
1797 }
1798
1799
1800 // and same for the destinations
1801 fixedSockets.clear();
1802 currIndex = 0;
1803
1804 while (currIndex < allocs.size()) {
1805 bool allocationWasSuccess = true;
1806
1807 SocketAllocation& alloc = allocs[currIndex];
1808
1809 if (alloc.dstSocks.empty()) {
1810 currIndex++;
1811 continue;
1812 }
1813
1814 // try to get allocation for current element
1815 if (alloc.dst < alloc.dstSocks.size()) {
1816 while (!canDestinationBeAssigned(alloc, fixedSockets)) {
1817 alloc.dst++;
1818
1819 if (alloc.dst == alloc.dstSocks.size()) {
1820 // working socket could not be found
1821 allocationWasSuccess = false;
1822 break;
1823 }
1824 }
1825 } else {
1826 allocationWasSuccess = false;
1827 }
1828
1829 // if allocation was success add allocation to for the socket
1830 // otherwise remove the latest allocations and try to resolve them
1831 // again
1832
1833 if (allocationWasSuccess) {
1834 // assign allocation for this socket
1835 Socket* currentSocket = alloc.dstSocks[alloc.dst];
1836 fixedSockets[currentSocket].push_back(&alloc);
1837
1838 } else {
1839 // reset allocation try sequence
1840 alloc.dst = 0;
1841
1842 // free previous allocation and try again
1843 unsigned int prevIndex = currIndex;
1844
1845 do {
1846 if (prevIndex == 0) {
1847 throw NotAvailable(
1848 __FILE__, __LINE__, __func__,
1849 "Can't resolve dst sockets for instruction.");
1850 }
1851
1852 prevIndex--;
1853
1854 } while (allocs[prevIndex].dstSocks.empty());
1855
1856
1857 Socket* socketToFree =
1858 allocs[prevIndex].dstSocks[allocs[prevIndex].dst];
1859 std::vector<SocketAllocation*>& freedAllocs =
1860 fixedSockets[socketToFree];
1861
1862 // find first freed allocation where we continue search
1863 for (unsigned int j = 0; j < freedAllocs.size(); j++) {
1864 if (freedAllocs[j]->index < currIndex) {
1865 currIndex = freedAllocs[j]->index;
1866 }
1867 }
1868
1869 // clean allocation indexes and increment index that is used
1870 // as a next start point for the search loop
1871 for (unsigned int j = 0; j < freedAllocs.size(); j++) {
1872 if (freedAllocs[j]->index != currIndex) {
1873 freedAllocs[j]->dst = 0;
1874 } else {
1875 freedAllocs[j]->dst++;
1876 }
1877 }
1878
1879 fixedSockets.erase(socketToFree);
1880 continue; // don't touch currIndex here
1881 }
1882
1883 currIndex++;
1884 }
1885
1886 // fix terminals
1887 for (unsigned i = 0; i < allocs.size(); i++) {
1888 SocketAllocation &alloc = allocs[i];
1889
1890#if 0
1891 std::cerr << "next allocation source: "
1892 << alloc.move->source().isGPR()
1893 << " destination: "
1894 << alloc.move->destination().isGPR() << std::endl;
1895#endif
1896
1897 if (!alloc.srcSocks.empty()) {
1898 Socket* srcSocket = alloc.srcSocks[alloc.src];
1899 Unit* parent = alloc.move->source().port().parentUnit();
1900
1901 for (int j = 0; j < srcSocket->portCount(); j++) {
1902 if (srcSocket->port(j)->parentUnit() == parent) {
1903 alloc.move->setSource(
1904 new TerminalRegister(
1905 *srcSocket->port(j),
1906 alloc.move->source().index()));
1907#if 0
1908 std::cerr << "source was replaced" << std::endl;
1909#endif
1910 break;
1911 }
1912 }
1913 }
1914
1915 if (!alloc.dstSocks.empty()) {
1916 Socket* dstSocket = alloc.dstSocks[alloc.dst];
1917 Unit* parent = alloc.move->destination().port().parentUnit();
1918
1919 for (int j = 0; j < dstSocket->portCount(); j++) {
1920 if (dstSocket->port(j)->parentUnit() == parent) {
1921 alloc.move->setDestination(
1922 new TerminalRegister(
1923 *dstSocket->port(j),
1924 alloc.move->destination().index()));
1925#if 0
1926 std::cerr << "dst was replaced" << std::endl;
1927#endif
1928 break;
1929 }
1930 }
1931 }
1932#if 0
1933 if (alloc.move->source().isGPR() &&
1934 alloc.move->destination().isGPR()) {
1935 std::cerr << "next allocation source: "
1936 << alloc.move->source().port().name()
1937 << " destination: "
1938 << alloc.move->destination().port().name() << std::endl;
1939 }
1940#endif
1941 }
1942}
1943
1944/**
1945 * Returns cached terminal.
1946 *
1947 * @param key Cache key of terminal.
1948 * @return Cached terminal if there is one, NULL otherwise.
1949 */
1950Terminal*
1952 const TPEFProgramFactory::CacheKey &key) const {
1953
1954 if (MapTools::containsKey(cache_,key)) {
1956 }
1957 return NULL;
1958}
1959
1960/**
1961 * Adds Terminal to cache.
1962 *
1963 * @param key Key of search variables for getting terminal from machine(s).
1964 * @param cachedTerm Terminal to be add to cache.
1965 * @return cached terminal if there is one.
1966 */
1967void
1969 const CacheKey &key,
1970 Terminal* cachedTerm) const {
1971
1972 cache_[key] = cachedTerm;
1973}
1974
1975/**
1976 * Clears cache.
1977 */
1978void
1980 cache_.clear();
1981}
1982
1983/**
1984 * Analyses all CodeSection from TPEF and tries to find function start points.
1985 *
1986 * @todo This function should do code analysis, but for it actually scans
1987 * symbol sections for code symbol, which are intepret as function
1988 * start points.
1989 */
1990void
1992
1993 // clear table if already exists (from previous POM builds)
1995
1996 // check every symbol section
1997 for (Word i = 0; i < binary_->sectionCount(Section::ST_SYMTAB); i++) {
1998
1999 SymbolSection *currSect =
2000 dynamic_cast<SymbolSection*>(
2002
2003 for (Word j = 0; j < currSect->elementCount(); j++) {
2004 ProcedSymElement* procedSymbol =
2005 dynamic_cast<ProcedSymElement*>(currSect->element(j));
2006
2007 // symbol was not procedure symbol
2008 if (procedSymbol == NULL) {
2009 continue;
2010 }
2011
2012 InstructionElement* referencedInstruction =
2013 procedSymbol->reference();
2014
2015 // maybe we just could ignore null elements... but
2016 // there really should not be NULL code symbols, unless
2017 // referenced instruction has been moved or something...
2018 assert(referencedInstruction != NULL);
2019
2020 std::string functionName =
2021 stringOfChunk(procedSymbol->name(), currSect->link());
2022
2023 // add instruction element of symbol to entrypoint table
2024 functionStartPositions_[referencedInstruction] =
2026 }
2027 }
2028}
2029
2030/**
2031 * Adds global labels of TPEF to Program.
2032 *
2033 * @param prog Program where to add labels.
2034 */
2035void
2037 /// prevent addition of local symbol with same name multiple times
2038 std::map<string, std::pair<DataLabel*, bool> > dataLabels;
2039
2040 for (Word i = 0; i < binary_->sectionCount(Section::ST_SYMTAB); i++) {
2041
2042 SymbolSection* currSect = dynamic_cast<SymbolSection*>(
2044
2045 assert(currSect != NULL);
2046
2047 StringSection* strings =
2048 dynamic_cast<StringSection*>(currSect->link());
2049
2050 assert(strings != NULL);
2051
2052 for (Word j = 0; j < currSect->elementCount(); j++) {
2053 SymbolElement* sym =
2054 dynamic_cast<SymbolElement*>(currSect->element(j));
2055
2056 // read all local and global data labels
2057 if (sym->type() == SymbolElement::STT_DATA) {
2058
2059 DataSymElement* dataSym =
2060 dynamic_cast<DataSymElement*>(sym);
2061
2062 const std::string labelString =
2063 strings->chunk2String(dataSym->name());
2064
2065 UDataSection* dataSection = dynamic_cast<UDataSection*>(
2066 dataSym->section());
2067
2068 assert(dataSection != NULL);
2069
2070 TTAMachine::AddressSpace* targetASpace = NULL;
2071 try {
2072 targetASpace =
2073 &findAddressSpace(dataSection->aSpace());
2074 } catch (const NotAvailable& e) {
2075 NotAvailable newException(
2076 __FILE__, __LINE__, __func__,
2077 (boost::format(
2078 "Unable to find address space for target "
2079 "of data label '%s'") % labelString).str());
2080 newException.setCause(e);
2081 throw newException;
2082 }
2083
2084 Address refAddress(
2085 dataSection->bytesToMAUs(
2086 dataSym->reference()->offset()) +
2087 dataSection->startingAddress(),
2088 *targetASpace);
2089
2090 DataLabel* dataLabel = new DataLabel(
2091 labelString, refAddress, prog.globalScope());
2092
2093// nice debug info
2094// std::cerr << "Added data label\t"
2095// <<"\tname: " << dataLabel->name()
2096// << "\taddress: "
2097// << Conversion::toString(dataLabel->address().location())
2098// << std::endl;
2099
2100 // check if label name is already used
2101 if (MapTools::containsKey(dataLabels, labelString)) {
2102
2103 // if latest is global remove old one
2104 if (sym->binding() == SymbolElement::STB_GLOBAL) {
2105
2106 // if there is two global symbols with same name
2107 // throw exception
2108 if (dataLabels[labelString].second) {
2109
2110 // free reserved labels
2111 for (std::map<string,
2112 std::pair<DataLabel*,
2113 bool> >::iterator iter =
2114 dataLabels.begin();
2115 iter != dataLabels.end(); iter++) {
2116 delete (*iter).second.first;
2117 }
2118 delete dataLabel;
2119
2120 throw NotAvailable(
2121 __FILE__, __LINE__, __func__,
2122 "Found two global symbols with same name: " +
2123 labelString);
2124 }
2125
2126 delete dataLabels[labelString].first;
2127 dataLabels[labelString].first = dataLabel;
2128 dataLabels[labelString].second = true;
2129 }
2130 } else {
2131 // add symbol first time
2132 dataLabels[labelString].first = dataLabel;
2133 dataLabels[labelString].second =
2135 }
2136
2137 // Global code labels
2138 } else if (sym->binding() == SymbolElement::STB_GLOBAL &&
2139 sym->type() == SymbolElement::STT_CODE) {
2140
2141 CodeSymElement* codeSym =
2142 dynamic_cast<CodeSymElement*>(sym);
2143
2145 instructionMap_, codeSym->reference()));
2146
2147 InstructionReference refIns =
2149 *instructionMap_[codeSym->reference()]);
2150
2151 CodeLabel* newLabel =
2152 new CodeLabel(refIns,
2153 strings->chunk2String(sym->name()));
2154
2155 prog.globalScope().addCodeLabel(newLabel);
2156 }
2157 }
2158 }
2159
2160 // Add symbols to program
2161 /// prevent addition of local symbol with same name multiple times
2162 for (std::map<string, std::pair<DataLabel*, bool> >::iterator iter =
2163 dataLabels.begin();
2164 iter != dataLabels.end(); iter++) {
2165
2166 prog.globalScope().addDataLabel((*iter).second.first);
2167 }
2168}
2169
2170/**
2171 * Creates data memories to program.
2172 *
2173 * @param prog Program containing converted TPEF instructions.
2174 */
2175void
2177
2178 // ------- search through data sections and group them by address spaces
2179 std::map<AddressSpace*, std::vector<UDataSection*> > memories;
2180
2181 for (int i = 0; i < static_cast<int>(binary_->sectionCount()); i++) {
2182 Section* currSect = binary_->section(i);
2183
2184 if (currSect->type() == Section::ST_DATA ||
2185 currSect->type() == Section::ST_UDATA ||
2186 currSect->type() == Section::ST_LEDATA) {
2187
2188 UDataSection* uDataSect = dynamic_cast<UDataSection*>(currSect);
2189
2190 AddressSpace& aSpace = findAddressSpace(uDataSect->aSpace());
2191 std::vector<UDataSection*>& secVec = memories[&aSpace];
2192
2193 // sort sections of current vector by addess...
2194 UDataSection* temp = NULL;
2195 for (int j = 0; j < static_cast<int>(secVec.size()); j++) {
2196 if (secVec[j]->startingAddress() >
2197 uDataSect->startingAddress()) {
2198 temp = secVec[j];
2199 secVec[j] = uDataSect;
2200 uDataSect = temp;
2201 }
2202 }
2203
2204 secVec.push_back(uDataSect);
2205 }
2206 }
2207
2208 // ------------- create DataMemory for each address space
2209 for (std::map<AddressSpace*, std::vector<UDataSection*> >::iterator iter =
2210 memories.begin();
2211 iter != memories.end(); iter++) {
2212
2213 AddressSpace& aSpace = *(*iter).first;
2214 std::vector<UDataSection*>& secVec = (*iter).second;
2215
2216 DataMemory* newDataMem = new DataMemory(aSpace);
2217
2218 for (int i = 0; i < static_cast<int>(secVec.size()); i++) {
2219 UDataSection* currSect = secVec[i];
2220
2221 if (currSect->type() == Section::ST_UDATA) {
2222 // ------- create uninitializes data definition
2223 DataDefinition* newDef =
2224 new DataDefinition(
2225 Address(currSect->startingAddress(), aSpace),
2226 static_cast<int>(currSect->lengthInMAUs()),
2228
2229 newDataMem->addDataDefinition(newDef);
2230
2231 } else {
2232 // -------- create initialized data definition
2233 assert(currSect->type() == Section::ST_DATA ||
2234 currSect->type() == Section::ST_LEDATA);
2235
2236 // find relocation section for this section
2237 RelocSection* relocs = NULL;
2238
2239 for (int j = 0;
2240 j < static_cast<int>(
2242
2243 RelocSection* temp =
2244 dynamic_cast<RelocSection*>(
2246
2247 if (temp->referencedSection() == currSect) {
2248 // found it!
2249 relocs = temp;
2250 break;
2251 }
2252 }
2253
2254 // ------- create relocated definitions.
2255 if (relocs != NULL) {
2256
2257 DataSection* refSect = dynamic_cast<DataSection*>(
2258 relocs->referencedSection());
2259
2260 for (int j = 0;
2261 j < static_cast<int>(relocs->elementCount()); j++) {
2262
2263 RelocElement* currElem =
2264 dynamic_cast<RelocElement*>(relocs->element(j));
2265
2266 AddressSpace& dstSpace =
2267 findAddressSpace(currElem->aSpace());
2268
2269 // resolve location address of relocation
2270 Chunk* srcChunk =
2271 dynamic_cast<Chunk*>(currElem->location());
2272
2273 int sourceAddress =
2274 refSect->startingAddress() +
2275 refSect->chunkToMAUIndex(srcChunk);
2276
2277 Address startAddr(sourceAddress, aSpace);
2278
2279 // resolve mau size of address field
2280 int mauSize = currElem->size() / aSpace.width();
2281
2282 // field size must be multiple of mau of address space
2283 assert(currElem->size() % aSpace.width() == 0);
2284
2285 if (&dstSpace == adfInstrASpace_) {
2286 // ------- destination is instruction
2287
2288 InstructionElement* tpefInstr =
2289 dynamic_cast<InstructionElement*>(
2290 currElem->destination());
2291
2292 assert(tpefInstr != NULL);
2293
2294 // get the instruction reference of destination
2295 InstructionReference instrRef =
2297 createReference(*instructionMap_[tpefInstr]);
2298
2299 DataInstructionAddressDef* newDataDef =
2301 startAddr, mauSize, instrRef,
2303
2304 newDataMem->addDataDefinition(newDataDef);
2305
2306 } else {
2307 // ------- destination is chunk
2308
2309 // find dst section of destination() chunk
2310 Chunk* dstChunk =
2311 dynamic_cast<Chunk*>(currElem->destination());
2312
2313 assert(dstChunk != NULL);
2314
2315 UDataSection* dstSect = NULL;
2316
2317 std::vector<UDataSection*>& dstSecs =
2318 memories[&dstSpace];
2319
2320 for (int k = 0;
2321 k < static_cast<int>(dstSecs.size()); k++) {
2322
2323 UDataSection* temp = dstSecs[k];
2324
2325 if (temp->belongsToSection(dstChunk)) {
2326 // dst section found!
2327 dstSect = temp;
2328 break;
2329 }
2330 }
2331
2332 assert(dstSect != NULL);
2333
2334 Address dstAddr(
2335 dstSect->startingAddress() +
2336 dstSect->chunkToMAUIndex(dstChunk),
2337 dstSpace);
2338
2339 DataAddressDef* newDataDef =
2340 new DataAddressDef(
2341 startAddr, mauSize, dstAddr,
2343
2344 newDataMem->addDataDefinition(newDataDef);
2345
2346 }
2347 }
2348 }
2349
2350 // ----- create all the rest of the init data
2351
2352 // find start and end addresses of current section
2353 std::pair<int, int> wholeSection(currSect->startingAddress(),
2354 currSect->lengthInMAUs());
2355
2356 std::vector<std::pair <int, int> > dataAreas;
2357 dataAreas.push_back(wholeSection);
2358
2359 // split area if there is some data area definitions in the
2360 // same addresses with current section
2361 for (int k = 0; k < newDataMem->dataDefinitionCount(); k++) {
2362 DataDefinition& currDef = newDataMem->dataDefinition(k);
2363
2364 int prevIndex = dataAreas.size()-1;
2365 std::pair<int, int>& lastArea = dataAreas[prevIndex];
2366
2367 // if data definition is inside this section, it splits
2368 // the last data area definition
2369 if (static_cast<int>(currDef.startAddress().location()) >=
2370 lastArea.first &&
2371 static_cast<int>(currDef.startAddress().location()) <
2372 lastArea.first + lastArea.second) {
2373
2374 int lastAreaStart = lastArea.first;
2375 int lastAreaEnd = currDef.startAddress().location();
2376
2377 int newAreaStart =
2378 currDef.startAddress().location() +
2379 currDef.size();
2380
2381 int newAreaEnd = lastArea.first + lastArea.second;
2382
2383 // new area starts after this data definition
2384 std::pair<int, int> newArea(
2385 newAreaStart, newAreaEnd - newAreaStart);
2386
2387 // if the last area is no area anymore
2388 lastArea.second = lastAreaEnd - lastAreaStart;
2389
2390 if (lastArea.second == 0) {
2391 dataAreas.pop_back();
2392 }
2393
2394 if (newArea.second != 0) {
2395 dataAreas.push_back(newArea);
2396 }
2397 }
2398 }
2399
2400 DataSection* dataSect = dynamic_cast<DataSection*>(currSect);
2401 assert(dataSect != NULL);
2402
2403 // write out collected initialized data areas
2404 for (unsigned int k = 0; k < dataAreas.size(); k++) {
2405
2406 std::pair<int, int>& currArea = dataAreas[k];
2407 std::vector<MinimumAddressableUnit> initData;
2408
2409 int mauIndex =
2410 currArea.first - currSect->startingAddress();
2411
2412 assert(mauIndex >= 0);
2413
2414 assert(mauIndex + currArea.second <=
2415 static_cast<int>(currSect->lengthInMAUs()));
2416
2417 bool allZeros = true;
2418 for (int l = 0; l < currArea.second; l++) {
2419 if(dataSect->MAU(mauIndex + l) != 0) {
2420 allZeros = false;
2421 }
2422 }
2423
2424 DataDefinition* newDataDef = NULL;
2425
2426 if (allZeros) {
2427 newDataDef = new DataDefinition(
2428 Address(currArea.first, aSpace),
2429 currArea.second,
2431 NULL, true);
2432 } else {
2433 for (int l = 0; l < currArea.second; l++) {
2434 initData.push_back(dataSect->MAU(mauIndex++));
2435 }
2436
2437 newDataDef = new DataDefinition(
2438 Address(currArea.first, aSpace),
2439 initData, prog.targetProcessor().isLittleEndian());
2440 }
2441
2442 newDataMem->addDataDefinition(newDataDef);
2443 }
2444 }
2445 }
2446
2447 prog.addDataMemory(newDataMem);
2448 }
2449}
2450
2451/**
2452 * Checks if move is start point of function.
2453 *
2454 * @param instructionElement Intruction element which should be checked.
2455 * @return True if instruction in parameter is function start point.
2456 */
2457bool
2459 const InstructionElement &instructionElement) const {
2460 return MapTools::containsKey(
2461 functionStartPositions_, &instructionElement);
2462}
2463
2464/**
2465 * Returns name of function, that starts, from given instruction element.
2466 *
2467 * @param instructionElement Starting element, of procedure.
2468 * @return Function name string.
2469 */
2470std::string
2472 const InstructionElement &instructionElement) const {
2473 if (MapTools::containsKey(functionStartPositions_, &instructionElement)) {
2475 functionStartPositions_, &instructionElement)->name();
2476 } else {
2477 return "unknownFunctionName";
2478 }
2479}
2480}
#define __func__
#define abortWithError(message)
#define assert(condition)
UInt32 InstructionAddress
Definition BaseType.hh:175
unsigned char Byte
Definition BaseType.hh:116
#define THROW_EXCEPTION(exceptionType, message)
Exception wrapper macro that automatically includes file name, line number and function name where th...
Definition Exception.hh:39
find Finds info of the inner loops in the program
static void abortProgram() __attribute__((noreturn))
static std::ostream & logStream()
static std::string toString(const T &source)
static int toInt(const T &source)
std::string errorMessage() const
Definition Exception.cc:123
void setCause(const Exception &cause)
Definition Exception.cc:75
static KeyType keyForValue(const MapType &aMap, const ValueType &aValue)
static void deleteAllValues(MapType &aMap)
static bool containsKey(const MapType &aMap, const KeyType &aKey)
static int requiredBits(unsigned long int number)
static int requiredBitsSigned(SLongWord number)
Chunk * name() const
Byte MAU() const
@ FT_OBJSEQ
Sequential TTA object code.
Definition Binary.hh:56
@ FT_PARALLEL
Fully scheduled or mixed code.
Definition Binary.hh:61
@ FT_LIBSEQ
Collection of sequential object code files for linkage.
Definition Binary.hh:58
@ FT_PURESEQ
Sequential TTA code, no unresolved symbols.
Definition Binary.hh:57
Word sectionCount() const
Section * section(Word index) const
FileType type() const
SectionOffset offset() const
virtual InstructionElement * element(Word index) const
InstructionElement * reference() const
virtual MinimumAddressableUnit MAU(Word index) const
Chunk * reference() const
LongWord longWord() const
SignedLongWord sLongWord() const
Byte destinationIndex() const
Byte destinationUnit() const
const std::vector< Byte > & payload() const
Word annotationCount() const
InstructionAnnotation * annotation(Word index) const
bool isGuarded() const
FieldType destinationType() const
HalfWord destinationIndex() const
HalfWord destinationUnit() const
bool isEmpty() const
HalfWord bus() const
HalfWord guardUnit() const
HalfWord sourceUnit() const
FieldType guardType() const
HalfWord guardIndex() const
bool isGuardInverted() const
HalfWord sourceIndex() const
FieldType sourceType() const
@ MF_RF
Register file.
@ MF_IMM
Immediate.
@ MF_UNIT
Function unit.
virtual Word bytesToMAUs(Word byteCount) const
Definition Section.cc:296
virtual Word chunkToMAUIndex(const Chunk *chunk) const
Definition Section.cc:341
virtual Word lengthInMAUs() const
Definition Section.cc:285
bool belongsToSection(const Chunk *chunk) const
Definition Section.cc:238
SectionElement * destination() const
ASpaceElement * aSpace() const
SectionElement * location() const
Byte size() const
Section * referencedSection() const
static const std::string RETURN_ADDRESS_NAME
Reserved string of return address special register.
@ MRT_BUS
Transport bus.
@ MRT_IMM
Immediate unit.
@ MRT_SR
Special register.
@ MRT_UNIT
Function unit.
@ MRT_PORT
Function unit port.
@ MRT_OP
Operation operand or function unit register.
@ UNIVERSAL_BUS
Universal bus.
@ UNIVERSAL_FU
Universal function unit.
@ INT_RF
Universal integer register file.
@ ILLEGAL_RF
Illegal register file.
@ BOOL_RF
Universal boolean register file.
@ FP_RF
Universal floating point register file.
@ INLINE_IMM
Inline immediate unit id.
Chunk * name() const
ResourceElement & findResource(ResourceElement::ResourceType aType, HalfWord anId) const
bool hasResource(ResourceElement::ResourceType aType, HalfWord anId) const
AddressImage startingAddress() const
Section * link() const
@ ST_SYMTAB
Symbol table.
Definition Section.hh:72
@ ST_DATA
Initialized data section.
Definition Section.hh:80
@ ST_ADDRSP
Address space section.
Definition Section.hh:77
@ ST_UDATA
Uninitialized data section.
Definition Section.hh:81
@ ST_LEDATA
Initialized little endian data section.
Definition Section.hh:82
@ ST_CODE
Text section.
Definition Section.hh:79
@ ST_RELOC
Relocation section.
Definition Section.hh:74
SectionElement * element(Word index) const
Word elementCount() const
virtual SectionType type() const =0
Returns SectioType of actual section instance.
ASpaceElement * aSpace() const
std::string chunk2String(const Chunk *chunk) const
@ STT_CODE
Associated with executable code.
@ STT_DATA
Associated with data object.
virtual SymbolType type() const =0
Returns type of symbol.
Section * section() const
SymbolBinding binding() const
Chunk * name() const
@ STB_GLOBAL
Visible to all files that are combined in TPEF file.
const RelocElement & relocation(const SectionElement &element) const
Definition TPEFTools.cc:119
std::string addressSpaceName(const ASpaceElement &aSpace) const
Definition TPEFTools.cc:96
bool hasRelocation(const SectionElement &element) const
Definition TPEFTools.cc:107
virtual SectionType type() const
virtual ULongWord end() const
virtual int width() const
virtual RFPort * port(const std::string &name) const
int immediateWidth() const
Definition Bus.cc:160
Guard * guard(int index) const
Definition Bus.cc:456
int guardCount() const
Definition Bus.cc:441
virtual Machine * machine() const
virtual TCEString name() const
SpecialRegisterPort * returnAddressPort() const
bool hasReturnAddressPort() const
virtual HWOperation * operation(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
virtual FUPort * port(int operand) const
virtual bool usesSlot(const std::string &slotName) const
virtual bool isOneOfDestinations(const ImmediateUnit &dstUnit) const
ComponentType * item(int index) const
bool hasItem(const std::string &name) const
virtual RegisterFileNavigator registerFileNavigator() const
Definition Machine.cc:450
virtual FunctionUnitNavigator functionUnitNavigator() const
Definition Machine.cc:380
virtual InstructionTemplateNavigator instructionTemplateNavigator() const
Definition Machine.cc:428
bool isLittleEndian() const
Definition Machine.hh:258
virtual SocketNavigator socketNavigator() const
Definition Machine.cc:368
virtual ImmediateUnitNavigator immediateUnitNavigator() const
Definition Machine.cc:416
virtual BusNavigator busNavigator() const
Definition Machine.cc:356
virtual AddressSpaceNavigator addressSpaceNavigator() const
Definition Machine.cc:392
virtual ControlUnit * controlUnit() const
Definition Machine.cc:345
static NullInstructionTemplate & instance()
FUPort * port() const
Unit * parentUnit() const
const RegisterFile * registerFile() const
@ OUTPUT
Data goes from port to bus.
Definition Socket.hh:60
@ INPUT
Data goes from bus to port.
Definition Socket.hh:59
bool isConnectedTo(const Bus &bus) const
Definition Socket.cc:331
Direction direction() const
Port * port(int index) const
Definition Socket.cc:266
int portCount() const
virtual bool hasPort(const std::string &name) const
Definition Unit.cc:96
const TTAMachine::AddressSpace & space() const
InstructionAddress location() const
void addAnnotation(const ProgramAnnotation &annotation)
virtual Address startAddress() const
void addDataDefinition(DataDefinition *dataDef)
Definition DataMemory.cc:66
DataDefinition & dataDefinition(Address address) const
Definition DataMemory.cc:79
int dataDefinitionCount() const
FunctionStart(std::string aName)
InstructionReference createReference(Instruction &ins)
void addImmediate(std::shared_ptr< Immediate > imm)
void addMove(std::shared_ptr< Move > move)
void setInstructionTemplate(const TTAMachine::InstructionTemplate &insTemp)
Id
the ID in TPEF is 24 bits, here enum
std::vector< Instruction * > InstructionVector
Vector for instructions.
Definition Program.hh:66
GlobalScope & globalScope()
Definition Program.cc:180
Address startAddress() const
Definition Program.cc:286
TTAMachine::Machine & targetProcessor() const
Definition Program.cc:202
void addDataMemory(DataMemory *dataMem)
Definition Program.cc:954
InstructionReferenceManager & instructionReferenceManager() const
Definition Program.cc:688
InstructionVector instructionVector() const
Definition Program.cc:1196
void setUniversalMachine(UniversalMachine *umach)
Definition Program.hh:81
virtual void addDataLabel(const DataLabel *dataLabel)
Definition Scope.cc:415
virtual void addCodeLabel(const CodeLabel *codeLabel)
Definition Scope.cc:376
Cache key for resources that are accessed from MOM(s)
std::vector< TPEF::ImmediateElement * > ImmediateVector
std::vector< TPEF::MoveElement * > MoveVector
const TTAMachine::Machine * machine_
Target machine of program.
TTAMachine::Bus & findBus(const TPEF::ResourceSection &resources, HalfWord busId) const
bool canDestinationBeAssigned(SocketAllocation &alloc, std::map< TTAMachine::Socket *, std::vector< SocketAllocation * > > &fixedSockets) const
std::string stringOfChunk(const TPEF::Chunk *chunk, const TPEF::Section *chunkOwner) const
bool canSourceBeAssigned(SocketAllocation &alloc, std::map< TTAMachine::Socket *, std::vector< SocketAllocation * > > &fixedSockets) const
TPEF::ASpaceElement * tpefInstrASpace_
Instruction address space element of TPEF.
TTAMachine::RegisterFile & findRegisterFile(const TPEF::ResourceSection &resources, HalfWord rfId) const
TTAMachine::AddressSpace & findAddressSpace(const TPEF::ASpaceElement *aSpace) const
std::string functionName(const TPEF::InstructionElement &instructionElement) const
std::map< ImmediateKey, TPEF::ImmediateElement * > ImmediateMap
const TPEF::Binary * binary_
Binary that is used for creating program.
TTAMachine::Guard & findGuard(const TPEF::ResourceSection &resources, TTAMachine::Bus &bus, TPEF::MoveElement::FieldType type, HalfWord unitId, HalfWord index, bool isInverted) const
bool isFunctionStart(const TPEF::InstructionElement &instructionElement) const
TPEFProgramFactory(const TPEF::Binary &aBinary, const TTAMachine::Machine &aMachine)
std::list< std::shared_ptr< Immediate > > longInstructionImmediates_
Long immediates whose value terminals refers to instructions.
TTAMachine::ImmediateUnit & findImmediateUnit(const TPEF::ResourceSection &resources, Byte immUnitId) const
TTAMachine::AddressSpace * adfInstrASpace_
Instruction address space of machine.
void resolveSocketAllocations(std::vector< SocketAllocation > &allocs) const
TPEF::TPEFTools tpefTools_
TPEFTools object for helper functions.
std::map< const CacheKey, Terminal * > cache_
Cache map of terminals that are returned by different search parameters.
void addToCache(const CacheKey &key, Terminal *cachedTerm) const
std::pair< Word, Word > ImmediateKey
Terminal * getFromCache(const CacheKey &key) const
void addProcedures(Program &program, const TTAMachine::AddressSpace &programASpace) const
TTAMachine::FunctionUnit & findFunctionUnit(const TPEF::ResourceSection &resources, HalfWord unitId, std::string tpefOpName="") const
Instruction * createInstruction(const TPEF::ResourceSection &resources, MoveVector &moveElements, ImmediateVector &longImmediates, ImmediateMap &immElements) const
Terminal * createTerminal(const TPEF::ResourceSection &resources, const TTAMachine::Bus *aBus, TTAMachine::Socket::Direction direction, TPEF::MoveElement::FieldType type, HalfWord unitId, HalfWord index, const ImmediateMap *immediateMap=NULL) const
TTAMachine::Port & findPort(const TTAMachine::Bus &bus, const TTAMachine::Unit &portParent, std::string tpefOpName="", int tpefOpIndex=0) const
UniversalMachine * universalMachine_
Universal machine of program.
std::map< TPEF::InstructionElement *, Instruction * > instructionMap_
Program instruction by TPEF instruction element.
TTAMachine::InstructionTemplate & findInstrTemplate(const TPEF::ResourceSection &resources, ImmediateVector &longImmediates, MoveVector &moves) const
std::list< std::shared_ptr< Move > > instructionImmediates_
Moves whose source terminals are addresses referring to instructions.
std::map< const TPEF::InstructionElement *, class FunctionStart * > functionStartPositions_
Stores information of start points of procedures that were found.
virtual SimValue value() const
virtual int index() const
Definition Terminal.cc:274
virtual Address address() const
Definition Terminal.cc:210
virtual Terminal * copy() const =0
virtual bool isGPR() const
Definition Terminal.cc:107
virtual bool isImmediateRegister() const
Definition Terminal.cc:97
virtual const TTAMachine::Port & port() const
Definition Terminal.cc:378
TTAMachine::AddressSpace & dataAddressSpace() const
TTAMachine::AddressSpace & instructionAddressSpace() const
TTAMachine::RegisterFile & booleanRegisterFile() const
UniversalFunctionUnit & universalFunctionUnit() const
UnboundedRegisterFile & integerRegisterFile() const
TTAMachine::Bus & universalBus() const
UnboundedRegisterFile & doubleRegisterFile() const