OpenASIP 2.2
Loading...
Searching...
No Matches
ProgramWriter.cc
Go to the documentation of this file.
1/*
2 Copyright (c) 2002-2009 Tampere University.
3
4 This file is part of TTA-Based Codesign Environment (TCE).
5
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the "Software"),
8 to deal in the Software without restriction, including without limitation
9 the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 and/or sell copies of the Software, and to permit persons to whom the
11 Software is furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 DEALINGS IN THE SOFTWARE.
23 */
24/**
25 * @file ProgramWriter.cc
26 *
27 * Implementation of ProgramWriter class.
28 *
29 * @author Mikael Lepistö 2005 (tmlepist-no.spam-cs.tut.fi)
30 * @author Pekka Jääskeläinen 2006 (pjaaskel-no.spam-cs.tut.fi)
31 * @note rating: red
32 */
33
34#include <boost/format.hpp>
35#include <cmath>
36
37#include "ProgramWriter.hh"
38#include "Binary.hh"
39#include "NullSection.hh"
40#include "ResourceSection.hh"
41#include "StringSection.hh"
42#include "ASpaceSection.hh"
43#include "StringSection.hh"
44#include "RelocSection.hh"
45#include "CodeSection.hh"
46#include "DataSection.hh"
47#include "UDataSection.hh"
48#include "SymbolSection.hh"
49#include "AddressSpace.hh"
50#include "Machine.hh"
51#include "UniversalMachine.hh"
52#include "FunctionUnit.hh"
54#include "ASpaceElement.hh"
55#include "RelocElement.hh"
56#include "Program.hh"
57#include "ControlUnit.hh"
58#include "Procedure.hh"
59#include "Instruction.hh"
60#include "Bus.hh"
61#include "MoveElement.hh"
62#include "Move.hh"
63#include "Terminal.hh"
64#include "TerminalFUPort.hh"
65#include "RegisterFile.hh"
67#include "Guard.hh"
68#include "MoveGuard.hh"
69#include "FUPort.hh"
71#include "HWOperation.hh"
72#include "Operation.hh"
73#include "ImmediateElement.hh"
74#include "UDataSection.hh"
75#include "DataSection.hh"
76#include "NullInstruction.hh"
77#include "Chunk.hh"
79#include "TPEFTools.hh"
80#include "GlobalScope.hh"
81#include "CodeSymElement.hh"
82#include "ProcedSymElement.hh"
83#include "DataSymElement.hh"
84#include "NoTypeSymElement.hh"
85#include "SymbolElement.hh"
86#include "CodeLabel.hh"
87#include "DataLabel.hh"
88#include "Immediate.hh"
89#include "TerminalImmediate.hh"
90#include "DataMemory.hh"
91#include "DataDefinition.hh"
92#include "SectionElement.hh"
93#include "ProgramAnnotation.hh"
94#include "InstructionElement.hh"
95#include "TCEString.hh"
96#include "MathTools.hh"
97#include "POMDisassembler.hh"
98#include "TPEFHeaders.hh"
99
100using TPEF::Binary;
101using TPEF::Section;
120using TPEF::Chunk;
121using TPEF::TPEFTools;
126using TPEF::Binary;
129
134using TTAMachine::Bus;
135using TTAMachine::Port;
144
145namespace TTAProgram {
146
147////////////////////////////////////////////////////////////////////////////
148// TPEFResourceUpdater
149////////////////////////////////////////////////////////////////////////////
150
152 Machine &mach, ResourceSection &resources) :
153 mach_(mach), resources_(resources),
154 lastBusId_(1), lastUnitPortId_(1),
155 lastFunctionUnitId_(1), lastRegisterFileId_(1),
156 lastImmediateUnitId_(1) {
157
158 initCache();
159}
160
161/**
162 * Initialises resource updater cache, for finding TPEF resources by machine
163 * resources.
164 *
165 * This also checks already created TPEF resources to prevent multiple
166 * creation of the same ResourceElement.
167 */
168void
170
171 for (Word i = 0; i < resources_.elementCount(); i++) {
172 ResourceElement* currRes =
173 dynamic_cast<ResourceElement*>(resources_.element(i));
174
175 StringSection* strings =
176 dynamic_cast<StringSection*>(resources_.link());
177
178 std::string resourceName = strings->chunk2String(currRes->name());
179
180 switch(currRes->type()) {
181
182 case ResourceElement::MRT_NULL: {
183 abortWithError("There should not be NULL resources.");
184 } break;
185
186 case ResourceElement::MRT_BUS: {
187 Machine::BusNavigator navi = mach_.busNavigator();
188 assert(navi.hasItem(resourceName));
189 Bus *bus = navi.item(resourceName);
190
191 cache_[CacheKey(bus, 0)] = currRes;
192 } break;
193
194 case ResourceElement::MRT_UNIT: {
195 Machine::FunctionUnitNavigator navi =
197 assert(navi.hasItem(resourceName));
198
199 if (lastFunctionUnitId_ < currRes->id()) {
200 lastFunctionUnitId_ = currRes->id()+1;
201 }
202
203 FunctionUnit *fu = navi.item(resourceName);
204
205 cache_[CacheKey(fu, 0)] = currRes;
206 } break;
207
208 case ResourceElement::MRT_RF: {
209 Machine::RegisterFileNavigator navi =
211 assert(navi.hasItem(resourceName));
212
213 if (lastRegisterFileId_ < currRes->id()) {
214 lastRegisterFileId_ = currRes->id()+1;
215 }
216
217 RegisterFile *rf = navi.item(resourceName);
218
219 cache_[CacheKey(rf, 0)] = currRes;
220 } break;
221
222 case ResourceElement::MRT_OP: {
223 std::string::size_type dotPos = resourceName.find('.');
224 assert(dotPos != std::string::npos);
225
226 std::string operName = resourceName.substr(0, dotPos);
227
228 int operandIndex = Conversion::toInt(
229 resourceName.substr(
230 dotPos+1, resourceName.length() - dotPos - 1));
231
232 Machine::FunctionUnitNavigator navi =
234
235 if (lastUnitPortId_ < currRes->id()) {
236 lastUnitPortId_ = currRes->id()+1;
237 }
238
239 // if function unit has operation by that name, get HWOperation...
240 for (int i = 0; i < navi.count(); i++) {
241 FunctionUnit *fu = navi.item(i);
242 if (fu->hasOperation(operName)) {
243 cache_[CacheKey(fu->operation(operName), operandIndex)] =
244 currRes;
245 }
246 }
247
248 } break;
249
250 case ResourceElement::MRT_IMM: {
251 Machine::ImmediateUnitNavigator navi =
253 assert(navi.hasItem(resourceName));
254
255 if (lastImmediateUnitId_ < currRes->id()) {
256 lastImmediateUnitId_ = currRes->id()+1;
257 }
258
259 ImmediateUnit* immUnit = navi.item(resourceName);
260
261 cache_[CacheKey(immUnit, 0)] = currRes;
262
263 } break;
264
265 case ResourceElement::MRT_PORT:
266 case ResourceElement::MRT_SR: {
267 Machine::FunctionUnitNavigator navi =
269
270 if (lastUnitPortId_ < currRes->id()) {
271 lastUnitPortId_ = currRes->id()+1;
272 }
273
274 // if function unit has port by that name, get port
275 for (int i = 0; i < navi.count(); i++) {
276 FunctionUnit *fu = navi.item(i);
277
278 if (fu->hasPort(resourceName)) {
279 cache_[CacheKey(fu->port(resourceName), 0)] = currRes;
280 }
281 }
282 } break;
283
284 default:
285 abortWithError("Unknown resource type.");
286 }
287
288 }
289}
290
291
292/**
293 * Clears the temporary variables and reinits the cache.
294 */
295void
305
306
307/**
308 * Finds and creates ResourceElement for the bus given in parameter.
309 *
310 * If resource id not already created to TPEF method creates it
311 * and adds CacheKey for it.
312 *
313 * @param bus Bus whose tpef resource is looked for.
314 * @return ResourceElement for the bus given in parameter.
315 */
318
319 CacheKey key = CacheKey(&bus, 0);
320 if (!MapTools::containsKey(cache_, key)) {
321 ResourceElement *newRes = new ResourceElement();
322
323 newRes->setType(ResourceElement::MRT_BUS);
324
325 // check if bus belongs to universal machine, set universal bus ID
326 // if it does
327 UniversalMachine *uMach =
328 dynamic_cast<UniversalMachine*>(bus.machine());
329
330 if (uMach == NULL) {
331 newRes->setId(lastBusId_++);
332
333 } else {
334 // find universal bus
335 if (&bus == &uMach->universalBus()) {
336 newRes->setId(ResourceElement::UNIVERSAL_BUS);
337
338 } else {
339 boost::format unexpectedBusMsg(
340 "Unexpected bus '%1%' in universal machine in addition "
341 "to the unique universal bus '%2%'.");
342
343 abortWithError(unexpectedBusMsg.str());
344 }
345 }
346
347 StringSection *strings =
348 dynamic_cast<StringSection*>(resources_.link());
349
350 newRes->setName(strings->string2Chunk(bus.name()));
351#if 0
352 std::cerr << "added MRT_BUS resource type: " << newRes->type()
353 << "\tid:" << newRes->id() << "\tname: "
354 << strings->chunk2String(newRes->name()) << std::endl;
355#endif
356 resources_.addElement(newRes);
357 cache_[key] = newRes;
358 }
359
360 return *cache_[key];
361}
362
363/**
364 * Finds and creates ResourceElement for a fu port given in parameter.
365 *
366 * If resource id not already created to TPEF method creates it
367 * and adds CacheKey for it.
368 *
369 * @param port Port whose tpef resource is looked for.
370 * @return ResourceElement for the machine part given in parameter.
371 */
374
375 CacheKey key = CacheKey(&port, 0);
376 if (!MapTools::containsKey(cache_, key)) {
377 ResourceElement *newRes = new ResourceElement();
378
379 if (dynamic_cast<const TTAMachine::FUPort*>(&port) != NULL) {
380 newRes->setType(ResourceElement::MRT_PORT);
381
382 } else if (dynamic_cast<const TTAMachine::SpecialRegisterPort*>(
383 &port) != NULL) {
384
385 newRes->setType(ResourceElement::MRT_SR);
386
387 } else {
389 "Port must be either FUPort or SpecialRegisterPort!");
390 }
391
392 newRes->setId((lastUnitPortId_++));
393
394 StringSection *strings =
395 dynamic_cast<StringSection*>(resources_.link());
396
397 // check if universal and set return-address register name if needed
398 UniversalMachine *uMach =
399 dynamic_cast<UniversalMachine*>(port.parentUnit()->machine());
400
401 if (uMach != NULL) {
403 if (uMach->controlUnit()->returnAddressPort() == &port) {
404
405 newRes->setName(
406 strings->string2Chunk(
407 ResourceElement::RETURN_ADDRESS_NAME));
408 } else {
409
410 const SpecialRegisterPort* srp =
411 dynamic_cast<const SpecialRegisterPort*>(&port);
412
413 if (srp == NULL) {
414 boost::format unexpectedPortMsg(
415 "Port '%1%' in universal global control unit. "
416 "Normal RF and FU ports are not allowed there.");
417 unexpectedPortMsg % port.name();
418 abortWithError(unexpectedPortMsg.str());
419
420 } else {
421 // Might be allowed in the future if the system can
422 // be extended to support open-ended sets of special
423 // register ports in GCU.
424 boost::format unexpectedSRPortMsg(
425 "The special register port '%1%' is not one of "
426 "the ports currently supported by the global "
427 "control unit.");
428 unexpectedSRPortMsg % port.name();
429 abortWithError(unexpectedSRPortMsg.str());
430 }
431 }
432 } else {
433 newRes->setName(strings->string2Chunk(port.name()));
434 }
435
436#if 0
437 std::cerr << "added MRT_SR resource type: " << newRes->type()
438 << "\tid:" << newRes->id() << "\tname: "
439 << strings->chunk2String(newRes->name()) << std::endl;
440#endif
441 resources_.addElement(newRes);
442
443 // TODO: check that port is really found from universal or normal
444 // machine
445 cache_[CacheKey(&port, 0)] = newRes;
446
447 }
448
449 return *cache_[key];
450}
451
452
453/**
454 * Finds and creates ResourceElement for a fu operand given in parameter.
455 *
456 * If resource id not already created to TPEF method creates it
457 * and adds CacheKey for it.
458 *
459 * @param oper Operation whose TPEF resource is looked for.
460 * @param operandIndex Index of the operand of operation.
461 * @return ResourceElement for the operand given in parameter.
462 */
464TPEFResourceUpdater::operand(const HWOperation &oper, int operandIndex) {
465
466 CacheKey key = CacheKey(&oper, operandIndex);
467 if (!MapTools::containsKey(cache_, key)) {
468
469 ResourceElement *newRes = new ResourceElement();
470
471 newRes->setType(ResourceElement::MRT_OP);
472 newRes->setId(lastUnitPortId_++);
473
474 StringSection *strings =
475 dynamic_cast<StringSection*>(resources_.link());
476
477 newRes->setName(
478 strings->string2Chunk(
479 oper.name() + "." + Conversion::toString(operandIndex)));
480#if 0
481 std::cerr << "Added MRT_OP resource type: " << newRes->type()
482 << "\tid:" << newRes->id() << "\tname: "
483 << strings->chunk2String(newRes->name()) << std::endl;
484#endif
485 resources_.addElement(newRes);
486
487 FunctionUnit *parentUnit = oper.parentUnit();
488
489 if (parentUnit->hasOperation(oper.name())) {
490 cache_[CacheKey(parentUnit->operation(oper.name()),
491 operandIndex)] = newRes;
492 } else {
494 "Parent unit: " + parentUnit->name() +
495 " didn't contain requested operation:" + oper.name());
496 }
497 }
498 return *cache_[key];
499}
500
501
502/**
503 * Finds and creates ResourceElement for a fu given in parameter.
504 *
505 * If resource id not already created to TPEF method creates it
506 * and adds CacheKey for it.
507 *
508 * @param fu Function unit whose TPEF resource is looked for.
509 * @return ResourceElement for the function unit given in parameter.
510 */
513
514 CacheKey key = CacheKey(&fu, 0);
515
516 if (!MapTools::containsKey(cache_, key)) {
517 ResourceElement *newRes = new ResourceElement();
518
519 newRes->setType(ResourceElement::MRT_UNIT);
520
521 // check if universal and set universal id
522 // if reference to universal machine
523 UniversalMachine *uMach =
524 dynamic_cast<UniversalMachine*>(fu.machine());
525
526 if (uMach == NULL) {
527 newRes->setId(lastFunctionUnitId_++);
528 resources_.addElement(newRes);
529
530 } else {
531 // find universal function unit or gcu...
532 if (&fu == &uMach->universalFunctionUnit() ||
533 &fu == uMach->controlUnit()) {
534
535 CacheKey uFUKey = CacheKey(
536 &uMach->universalFunctionUnit(), 0);
537 CacheKey uGCUKey = CacheKey(uMach->controlUnit(), 0);
538
539 // check if resource element is already created
540 if (MapTools::containsKey(cache_, uFUKey)) {
541 delete newRes;
542 newRes = cache_[uFUKey];
543
544 } else if (MapTools::containsKey(cache_, uGCUKey)) {
545 delete newRes;
546 newRes = cache_[uGCUKey];
547
548 } else {
549 newRes->setId(ResourceElement::UNIVERSAL_FU);
550 resources_.addElement(newRes);
551 }
552
553 } else {
555 "Unknown universal machine reference to function unit: " +
556 fu.name());
557 }
558 }
559
560 StringSection *strings =
561 dynamic_cast<StringSection*>(resources_.link());
562
563 newRes->setName(strings->string2Chunk(fu.name()));
564#if 0
565 std::cerr << "added MRT_UNIT resource type: " << newRes->type()
566 << "\tid:" << newRes->id() << "\tname: "
567 << strings->chunk2String(newRes->name()) << std::endl;
568#endif
569
570 cache_[key] = newRes;
571 }
572 return *cache_[key];
573}
574
575
576/**
577 * Finds and creates ResourceElement for a rf given in parameter.
578 *
579 * If resource id not already created to TPEF method creates it
580 * and adds CacheKey for it.
581 *
582 * @param rf Register file whose TPEF resource is looked for.
583 * @return ResourceElement for the register file given in parameter.
584 */
587
588 CacheKey key = CacheKey(&rf, 0);
589 if (!MapTools::containsKey(cache_, key)) {
590 ResourceElement *newRes = new ResourceElement();
591
592 newRes->setType(ResourceElement::MRT_RF);
593
594 // check if universal RF
595 UniversalMachine *uMach =
596 dynamic_cast<UniversalMachine*>(rf.machine());
597
598 if (uMach == NULL) {
599 newRes->setId(lastRegisterFileId_++);
600
601 } else {
602
603 // find universal register file
604 if (&rf == &uMach->booleanRegisterFile()) {
605 newRes->setId(ResourceElement::BOOL_RF);
606 } else if (&rf == &uMach->integerRegisterFile()) {
607 newRes->setId(ResourceElement::INT_RF);
608 } else if (&rf == &uMach->doubleRegisterFile()) {
609 newRes->setId(ResourceElement::FP_RF);
610 } else {
612 "Reference to unknown universal register file.");
613 }
614 }
615
616 StringSection *strings =
617 dynamic_cast<StringSection*>(resources_.link());
618
619 newRes->setName(strings->string2Chunk(rf.name()));
620
621#if 0
622 std::cerr << "added MRT_RF resource type: " << newRes->type()
623 << "\tid:" << newRes->id() << "\tname: "
624 << strings->chunk2String(newRes->name()) << std::endl;
625#endif
626
627 resources_.addElement(newRes);
628 cache_[key] = newRes;
629 }
630 return *cache_[key];
631}
632
633
634/**
635 * Find and return the TPEF machine resource entry that corresponds to a
636 * given immediate unit of the target processor.
637 *
638 * If no machine resource entry exists for the given unit, it is created,
639 * cached into the resource updater and added to the TPEF machine resource
640 * section.
641 *
642 * @param immUnit An immediate unit of the target processor.
643 * @return The machine resource entry corresponding to given unit.
644 */
647
648 CacheKey key = CacheKey(&immUnit, 0);
649 if (!MapTools::containsKey(cache_, key)) {
650 ResourceElement* newRes = new ResourceElement();
651
652 newRes->setType(ResourceElement::MRT_IMM);
653 newRes->setId(lastImmediateUnitId_++);
654
655 StringSection* strings =
656 dynamic_cast<StringSection*>(resources_.link());
657
658 newRes->setName(strings->string2Chunk(immUnit.name()));
659
660#if 0
661 std::cerr << "added MRT_IMM resource type: " << newRes->type()
662 << "\tid:" << newRes->id() << "\tname: "
663 << strings->chunk2String(newRes->name()) << std::endl;
664#endif
665
666 resources_.addElement(newRes);
667 cache_[key] = newRes;
668 }
669 return *cache_[key];
670}
671
672
673////////////////////////////////////////////////////////////////////////////
674// ProgramWriter part
675////////////////////////////////////////////////////////////////////////////
676
677const HalfWord
679
680const int
682
683/**
684 * Constructor.
685 *
686 * @param prog Program that from TPEF is created.
687 */
689 const Program& prog):
690 prog_(prog) {
691}
692
693
694/**
695 * Creates TPEF binary.
696 *
697 * @return TPEF binary of a program.
698 */
699Binary*
701 Binary* newBin = new Binary();
702
703 // create and initialize sections
704 NullSection* nullSection = dynamic_cast<NullSection*>(
705 Section::createSection(Section::ST_NULL));
706
707 StringSection* strings = dynamic_cast<StringSection*>(
708 Section::createSection(Section::ST_STRTAB));
709 strings->addByte(0);
710
711 ASpaceSection* aSpaces = dynamic_cast<ASpaceSection*>(
712 Section::createSection(Section::ST_ADDRSP));
713
714 ASpaceElement* undefASpace = new ASpaceElement();
715 undefASpace->setName(strings->string2Chunk(""));
716 aSpaces->setUndefinedASpace(undefASpace);
717
718 // check instruction address space from adf and init instruction space
720 ControlUnit* unit = adf.controlUnit();
721 AddressSpace* adfInstrASpace = unit->addressSpace();
722
723 if (prog_.instructionCount() > 0 &&
724 (prog_.startAddress().location() < adfInstrASpace->start() ||
726 adfInstrASpace->end())) {
727 TCEString err =
728 "The program is out of bounds of the imem."
729 " Please increase the instruction address space size in adf or "
730 " make the program smaller. "
731 "Using a smaller unroll and/or inlining threshold may help.";
732 err << " Imem address space size: "
733 << (adfInstrASpace->end() - adfInstrASpace->start() +1)
734 << ", required program size: "
736
737 throw CompileError(__FILE__, __LINE__, __func__, err);
738 }
739
740 aSpaces->addElement(undefASpace);
741
742 ResourceSection* resources = dynamic_cast<ResourceSection*>(
743 Section::createSection(Section::ST_MR));
744
745 CodeSection* code =
746 dynamic_cast<CodeSection*>(Section::createSection(Section::ST_CODE));
747
748 SymbolSection* symbols =
749 dynamic_cast<SymbolSection*>(
750 Section::createSection(Section::ST_SYMTAB));
751
752 NoTypeSymElement *undefSymbol = new NoTypeSymElement();
753 undefSymbol->setName(strings->string2Chunk(""));
754 symbols->addElement(undefSymbol);
755
756 // add sections to binary
757 newBin->addSection(nullSection);
758 newBin->addSection(aSpaces);
759 newBin->addSection(strings);
760 newBin->addSection(resources);
761 newBin->addSection(code);
762 newBin->addSection(symbols);
763 newBin->setStrings(strings);
764
765 // set link fields
766 nullSection->setLink(nullSection);
767 strings->setLink(nullSection);
768 aSpaces->setLink(strings);
769 resources->setLink(strings);
770 code->setLink(resources);
771 symbols->setLink(strings);
772
773 // set name fields
774 nullSection->setName(strings->string2Chunk(""));
775 strings->setName(strings->string2Chunk(""));
776 aSpaces->setName(strings->string2Chunk(""));
777 resources->setName(strings->string2Chunk(""));
778 code->setName(strings->string2Chunk(""));
779 symbols->setName(strings->string2Chunk(""));
780
781 // set adress space fields
782 nullSection->setASpace(undefASpace);
783 strings->setASpace(undefASpace);
784 aSpaces->setASpace(undefASpace);
785 resources->setASpace(undefASpace);
786 code->setASpace(&createASpaceElement(*adfInstrASpace, *newBin));
787 symbols->setASpace(undefASpace);
788
789 TPEFResourceUpdater resourceUpdater(prog_.targetProcessor(), *resources);
790
791 createCodeSection(code, resourceUpdater);
792 createDataSections(newBin, adf.isLittleEndian());
793
794 // TODO: add labels here (all labels are inserted at once from skope
795 // information after writing porgram sections)
796
797 // TODO: refactor this...
798
799 // procedure symbols
800 for (int i = 0; i < prog_.procedureCount(); i++) {
801 Procedure &currProced = prog_.procedure(i);
802
803 // create CodeSymElement and add it to symbols
804 ProcedSymElement *procedSym = new ProcedSymElement();
805
806 procedSym->setAbsolute(false);
807 procedSym->setBinding(SymbolElement::STB_LOCAL);
808
809 procedSym->setName(
810 strings->string2Chunk(currProced.name()));
811
812 procedSym->setSection(code);
813
814 procedSym->setReference(
815 &code->instruction(currProced.startAddress().location()));
816
817 symbols->addElement(procedSym);
818 }
819
820 // we add only global scope labels for now
821 const GlobalScope &globalScope = prog_.globalScopeConst();
822
823 for (int i = 0; i < globalScope.globalCodeLabelCount(); i++) {
824 const CodeLabel &currLabel = globalScope.globalCodeLabel(i);
825
826 // create CodeSymElement and add it to symbols
827 CodeSymElement *codeSym = new CodeSymElement();
828
829 codeSym->setAbsolute(false);
830 codeSym->setBinding(SymbolElement::STB_GLOBAL);
831
832 codeSym->setName(
833 strings->string2Chunk(currLabel.name()));
834
835 codeSym->setSection(code);
836
837 codeSym->setReference(
838 &code->instruction(currLabel.address().location()));
839
840 symbols->addElement(codeSym);
841 }
842
843 for (int i = 0; i < globalScope.globalDataLabelCount(); i++) {
844 const DataLabel &currLabel = globalScope.globalDataLabel(i);
845
846 // create DataSymElement and add it to symbols
847 DataSymElement *dataSym = new DataSymElement();
848
849 dataSym->setAbsolute(false);
850 dataSym->setBinding(SymbolElement::STB_GLOBAL);
851
852 dataSym->setName(strings->string2Chunk(currLabel.name()));
853
854 // TODO: find section by address.
855 // refactor to own method (Method is already written)
856
857 // it seems that we need to have some kind of data
858 // section finding by address
859 ASpaceSection* aSpaces = dynamic_cast<ASpaceSection*>(
860 newBin->section(Section::ST_ADDRSP,0));
861
862 ASpaceElement* dstASpace = NULL;
863
864 // find out dst address space by comparing names
865 for (Word k = 0; k < aSpaces->elementCount(); k++) {
866 ASpaceElement *currElem = dynamic_cast<ASpaceElement*>(
867 aSpaces->element(k));
868
869 if (TPEFTools::addressSpaceName(*newBin, *currElem) ==
870 currLabel.address().space().name()) {
871
872 dstASpace = currElem;
873 break;
874 }
875 }
876
877 if (dstASpace == NULL) {
878 throw NotAvailable(
879 __FILE__, __LINE__, __func__,
880 std::string("Cannot find address space ") +
881 currLabel.address().space().name() +
882 " for data label " + currLabel.name());
883
884 }
885 UDataSection* dstSection = NULL;
886 LongWord dstAddress = currLabel.address().location();
887
888 for (Word k = 0; k < newBin->sectionCount(); k++) {
889 UDataSection *currSect = dynamic_cast<UDataSection*>(
890 newBin->section(k));
891
892 if (currSect != NULL &&
893 (currSect->type() == Section::ST_DATA ||
894 currSect->type() == Section::ST_UDATA||
895 currSect->type() == Section::ST_LEDATA) &&
896 currSect->aSpace() == dstASpace &&
897 currSect->startingAddress() <= dstAddress &&
898 dstAddress <
899 currSect->startingAddress() + currSect->lengthInMAUs()) {
900
901 dstSection = currSect;
902 break;
903 }
904 }
905
906 if (dstSection == NULL) {
907 abortWithError("Can't find section for data address: " +
908 Conversion::toString(dstAddress));
909 }
910
911 dataSym->setSection(dstSection);
912
913 dstAddress -= dstSection->startingAddress();
914
915 dataSym->setReference(
916 dstSection->chunk(
917 dstSection->MAUsToBytes(dstAddress)));
918
919 symbols->addElement(dataSym);
920 }
921
922 // all the data is written... do the relocations
923 createRelocSections(newBin);
924
925 // clean up internal tables
926 aSpaceMap_.clear();
927 relocInfos_.clear();
928
929 newBin->setArch(Binary::FA_TTA_TUT);
930 newBin->setType(resolveFileType(*resources));
931
932 return newBin;
933}
934
935/**
936 * Creates TPEF binary of given Program.
937 *
938 * @return TPEF binary of a program.
939 */
942 ProgramWriter writer(prog);
943 return writer.createBinary();
944}
945
946/**
947 * Creates code section.
948 *
949 * @param code Code section where to instructions are added.
950 * @param updater Resource updater for finding TPEF resources for machine
951 * parts.
952 */
953void
955 CodeSection* code,
956 TPEFResourceUpdater& updater) const {
957
958 // add all busses from machine to resource section
960 Machine::BusNavigator navi = adf.busNavigator();
961 for (int i = 0; i < navi.count(); i++) {
962 // just call once for each bus, to make sure that all busses
963 // are written to machine resource table.
964 updater.bus(*navi.item(i));
965 }
966
968
969 for (int i = 0; i < prog_.procedureCount(); i++) {
970 Procedure& currProcedure = prog_.procedure(i);
971
972 for (int j = 0; j < currProcedure.instructionCount(); j++) {
973 Instruction &currInstr = currProcedure.instructionAtIndex(j);
974 HalfWord immediateIndex = 0;
975 bool beginFlag = true;
976
977 for (int k = 0; k < currInstr.moveCount(); k++) {
978 Move& progMove = currInstr.move(k);
979 MoveElement* tpefMove = new MoveElement();
980
981 tpefMove->setBegin(beginFlag);
982 beginFlag = false;
983 tpefMove->setBus(updater.bus(progMove.bus()).id());
984 tpefMove->setEmpty(false);
985
986 // add the possible move annotations
987 if (progMove.hasAnnotations()) {
988 for (int annotationIndex = 0;
989 annotationIndex < progMove.annotationCount();
990 ++annotationIndex) {
991 const ProgramAnnotation& annot =
992 progMove.annotation(annotationIndex);
993 tpefMove->addAnnotation(
995 annot.id(), annot.payload()));
996 }
997 }
998
999 code->addElement(tpefMove);
1000
1001 if (!tpefMove->isEmpty()) {
1002
1003 // set source
1004 if (!progMove.source().isImmediate()) {
1005
1006 ResourceID sourceId =
1007 terminalResource(progMove.source(), updater);
1008
1009#if 0
1010 std::cerr << "src type: " << sourceId.type
1011 << "\tunit: " << sourceId.unit
1012 << "\tindex: " << sourceId.index
1013 << std::endl;
1014#endif
1015
1016 tpefMove->setSourceType(sourceId.type);
1017 tpefMove->setSourceUnit(sourceId.unit);
1018 tpefMove->setSourceIndex(sourceId.index);
1019
1020 } else {
1021
1022 ImmediateElement *newImmediate =
1023 new ImmediateElement();
1024 newImmediate->setBegin(false);
1025
1026 const TTAProgram::TerminalImmediate& termImm =
1027 dynamic_cast<TerminalImmediate&>(
1028 progMove.source());
1029
1030 // add the possible immediate annotations
1031 if (termImm.hasAnnotations()) {
1032 for (int annotationIndex = 0;
1033 annotationIndex < termImm.annotationCount();
1034 ++annotationIndex) {
1035 const ProgramAnnotation& annot =
1036 termImm.annotation(annotationIndex);
1037 newImmediate->addAnnotation(
1039 annot.id(), annot.payload()));
1040 }
1041 }
1042
1043
1044 // check that inline immediate fits to bus's
1045 // inline immediate field
1046 unsigned long wordToStore =
1047 progMove.source().value().uLongWordValue();
1048
1049 unsigned long uvalue = wordToStore;
1050 int requiredBits = 0;
1051 int fieldWidth = progMove.bus().immediateWidth();
1052
1053 // TODO: why here? immediateelement can handle this???
1054 if (progMove.bus().signExtends()) {
1055 // Interpret as signed and sign extend if needed
1056 long svalue = static_cast<long>(uvalue);
1057 if (fieldWidth < MAX_SIMM_WIDTH) {
1058 svalue = MathTools::signExtendTo(
1059 svalue, fieldWidth);
1060 }
1061 requiredBits =
1063 } else {
1064 requiredBits =
1066 }
1067
1068 if (requiredBits <= fieldWidth) {
1069 wordToStore =
1071 wordToStore, fieldWidth);
1072 } else {
1073 TCEString disasm = POMDisassembler::disassemble(progMove);
1074 long location =
1075 progMove.parent().address().location();
1076 TCEString message = "In procedure:";
1077 message << currProcedure.name() << " Move: " <<
1078 disasm << " Inline immediate value " <<
1079 progMove.source().value().unsignedValue() <<
1080 " of required width " <<
1081 Conversion::toString(requiredBits) <<
1082 " at location " <<
1083 Conversion::toString(location) <<
1084 " doesn't fit to bus: " <<
1085 progMove.bus().name();
1086
1087 throw NotAvailable(
1088 __FILE__, __LINE__, __func__, message);
1089 }
1090
1091 if (progMove.bus().signExtends()) {
1092 newImmediate->setSignedLong(wordToStore);
1093 } else {
1094 newImmediate->setULongWord(wordToStore);
1095 }
1096 newImmediate->setDestinationUnit(
1097 ResourceElement::INLINE_IMM);
1098 newImmediate->setDestinationIndex(immediateIndex);
1099 immediateIndex++;
1100
1101 code->addElement(newImmediate);
1102
1103 tpefMove->setSourceType(MoveElement::MF_IMM);
1104 tpefMove->setSourceUnit(
1105 newImmediate->destinationUnit());
1106 tpefMove->setSourceIndex(
1107 newImmediate->destinationIndex());
1108
1109 // add relocation antries if needed
1110 if (progMove.source().isInstructionAddress()) {
1111
1112 // TODO: check size of inline immediate field
1113 RelocInfo newReloc(
1114 code, newImmediate,
1115 progMove.source().address(),
1117
1118 relocInfos_.push_back(newReloc);
1119
1120 } else if (progMove.source().isAddress()) {
1121
1122 // TODO: check size of inline immediate field
1123 RelocInfo newReloc(
1124 code, newImmediate,
1125 progMove.source().address(),
1127
1128 relocInfos_.push_back(newReloc);
1129
1130 }
1131 }
1132
1133 // set destination
1134 ResourceID destinationId =
1135 terminalResource(progMove.destination(), updater);
1136#if 0
1137 std::cerr << "dst type: " << destinationId.type
1138 << "\tunit: " << destinationId.unit
1139 << "\tindex: " << destinationId.index
1140 << std::endl;
1141#endif
1142 tpefMove->setDestinationType(destinationId.type);
1143 tpefMove->setDestinationUnit(destinationId.unit);
1144 tpefMove->setDestinationIndex(destinationId.index);
1145
1146 // set guard stuff
1147 if (progMove.isUnconditional()) {
1148 tpefMove->setGuarded(false);
1149 } else {
1150
1151 const Guard *guard = &progMove.guard().guard();
1152
1153 tpefMove->setGuarded(true);
1154
1155 tpefMove->setGuardInverted(guard->isInverted());
1156
1157 const PortGuard *portGuard =
1158 dynamic_cast<const PortGuard*>(guard);
1159 const RegisterGuard *registerGuard =
1160 dynamic_cast<const RegisterGuard*>(guard);
1161
1162 if (portGuard != NULL) {
1163 tpefMove->setGuardType(MoveElement::MF_UNIT);
1164
1165 FunctionUnit &funcUnit =
1166 *portGuard->port()->parentUnit();
1167
1168 ResourceElement &fu =
1169 updater.functionUnit(funcUnit);
1170 tpefMove->setGuardUnit(fu.id());
1171
1172 // is operation or special register port
1173 FunctionUnit *parentFu =
1174 portGuard->port()->parentUnit();
1175
1176 const FUPort *fuPort = portGuard->port();
1177
1178 if (parentFu->hasOperationPort(fuPort->name())) {
1179 HWOperation *oper = NULL;
1180
1181 // find just any operation that is
1182 // bound to guarded port
1183 for (int i = 0;
1184 i < parentFu->operationCount(); i++) {
1185 oper = parentFu->operation(i);
1186
1187 if (oper->isBound(*fuPort)) {
1188 break;
1189 }
1190
1191 oper = NULL;
1192 }
1193
1194 assert(oper != NULL);
1195
1196 ResourceElement &opPort =
1197 updater.operand(
1198 *oper, oper->io(*fuPort));
1199
1200 tpefMove->setGuardIndex(opPort.id());
1201
1202 } else {
1203 ResourceElement &fuPortResource =
1204 updater.functionUnitPort(*fuPort);
1205
1206 tpefMove->setGuardIndex(fuPortResource.id());
1207 }
1208
1209 } else if (registerGuard != NULL) {
1210 tpefMove->setGuardType(MoveElement::MF_RF);
1211
1212 const RegisterFile &regFile =
1213 *registerGuard->registerFile();
1214
1215 ResourceElement &rf =
1216 updater.registerFile(regFile);
1217
1218 tpefMove->setGuardUnit(rf.id());
1219
1220 tpefMove->setGuardIndex(
1221 registerGuard->registerIndex());
1222
1223 } else {
1224 abortWithError("Unknown machine guard type.");
1225 }
1226 }
1227 }
1228 }
1229
1230 // write long immediates
1231 for (int k = 0; k < currInstr.immediateCount(); k++) {
1232 Immediate& imm = currInstr.immediate(k);
1233
1234 ImmediateElement* tpefImm = new ImmediateElement();
1235
1236 tpefImm->setBegin(beginFlag);
1237 beginFlag = false;
1238
1239 if (imm.destination().immediateUnit().signExtends()) {
1240 tpefImm->setSignedLong(imm.value().value().sLongWordValue());
1241 } else {
1242 tpefImm->setULongWord(imm.value().value().uLongWordValue());
1243 }
1244
1245 ResourceID dstRes =
1246 terminalResource(imm.destination(), updater);
1247
1248 tpefImm->setDestinationUnit(dstRes.unit);
1249 tpefImm->setDestinationIndex(dstRes.index);
1250
1251 code->addElement(tpefImm);
1252
1253 // add relocation antries if needed
1254 if (imm.value().isInstructionAddress()) {
1255
1256 // TODO: check size of long immediate field
1257 RelocInfo newReloc(
1258 code, tpefImm,
1259 imm.value().address(),
1261
1262 relocInfos_.push_back(newReloc);
1263
1264 } else if (imm.value().isAddress()) {
1265
1266 // TODO: check size of long immediate field
1267 RelocInfo newReloc(
1268 code, tpefImm,
1269 imm.value().address(),
1271
1272 relocInfos_.push_back(newReloc);
1273
1274 }
1275 }
1276
1277 // add empty instruction (instruction containing one empty move)
1278 if (currInstr.moveCount() == 0 &&
1279 currInstr.immediateCount() == 0) {
1280
1281 MoveElement *tpefNOP = new MoveElement();
1282 tpefNOP->setBegin(true);
1283 tpefNOP->setEmpty(true);
1284
1285 if (currInstr.hasAnnotations()) {
1286 for (int annotationIndex = 0;
1287 annotationIndex < currInstr.annotationCount();
1288 ++annotationIndex) {
1289 const ProgramAnnotation& annot =
1290 currInstr.annotation(annotationIndex);
1291 tpefNOP->addAnnotation(
1293 annot.id(), annot.payload()));
1294 }
1295 }
1296 code->addElement(tpefNOP);
1297 }
1298 }
1299 }
1300}
1301
1302
1303/**
1304 * Finds out resource element and index by terminal.
1305 *
1306 * @param term Terminal whose TPEF resource information is needed.
1307 * @param updater Resource updater for finding TPEF resources.
1308 */
1311 const Terminal& term,
1312 TPEFResourceUpdater& updater) const {
1313
1314 ResourceID retVal;
1315 retVal.type = MoveElement::MF_RF;
1316 retVal.unit = 0;
1317 retVal.index = 0;
1318
1319 try {
1320
1321 if (term.isImmediate()) {
1323 "This function should never be called with ImmediateTerminal "
1324 " instance type.");
1325
1326 } else if (term.isGPR()) {
1327 retVal.type = MoveElement::MF_RF;
1328 retVal.unit = updater.registerFile(term.registerFile()).id();
1329 retVal.index = term.index();
1330
1331 } else if (term.isImmediateRegister()) {
1332 retVal.type = MoveElement::MF_IMM;
1333 retVal.unit = updater.immediateUnit(term.immediateUnit()).id();
1334 retVal.index = term.index();
1335
1336 } else if (term.isFUPort()) {
1337
1338 retVal.type = MoveElement::MF_UNIT;
1339
1340 FunctionUnit &fu =
1341 *dynamic_cast<FunctionUnit*>(term.port().parentUnit());
1342
1343 retVal.unit = updater.functionUnit(fu).id();
1344
1345 const TerminalFUPort& fuTerm =
1346 dynamic_cast<const TerminalFUPort&>(term);
1347
1348 // find if there is information of operation in terminal
1349 if (&fuTerm.hintOperation() != &NullOperation::instance() ||
1350 fuTerm.isOpcodeSetting()) {
1351
1352 std::string operationName =
1353 (fuTerm.isOpcodeSetting()) ?
1354 (fuTerm.operation().name()) :
1355 (fuTerm.hintOperation().name());
1356
1357 if (fu.hasOperation(operationName)) {
1358 HWOperation *oper = fu.operation(operationName);
1359
1360 int index = oper->io(
1361 dynamic_cast<const FUPort&>(term.port()));
1362
1363 retVal.index = updater.operand(*oper, index).id();
1364
1365 } else {
1367 "Can't find operation " + operationName +
1368 " from FU: " + fu.name());
1369 }
1370
1371 } else {
1372 // not opcode setting normal fu port without operation hint
1373 assert(!fuTerm.isOpcodeSetting());
1374 ResourceElement &fuPort =
1375 updater.functionUnitPort(term.port());
1376 retVal.index = fuPort.id();
1377 }
1378
1379 } else {
1380 abortWithError("Unknown terminal type.");
1381 }
1382
1383 } catch (const InvalidData& e) {
1384 NotAvailable error(__FILE__, __LINE__, __func__,
1385 "Problems with finding terminal: " +
1386 e.errorMessage());
1387
1388 error.setCause(e);
1389
1390 throw error;
1391 }
1392
1393 return retVal;
1394}
1395
1396
1397/**
1398 * Creates data section to TPEF.
1399 *
1400 * @param bin Binary to write the sections to.
1401 */
1402void
1403ProgramWriter::createDataSections(Binary* bin, bool littleEndian) const {
1404
1405 std::map<AddressSpace*, ASpaceElement*> aSpaceMap;
1406
1407 ASpaceSection* aSpaceSection = dynamic_cast<ASpaceSection*>(
1408 bin->section(Section::ST_ADDRSP, 0));
1409
1410 StringSection* strings =
1411 dynamic_cast<StringSection*>(aSpaceSection->link());
1412
1413 // go through all the DataMemories of POM
1414 for (int i = 0; i < prog_.dataMemoryCount(); i++) {
1415 DataMemory& currMem = prog_.dataMemory(i);
1416
1417 UDataSection* currSect = NULL;
1418
1419 for (int j = 0; j < currMem.dataDefinitionCount(); j++) {
1420 DataDefinition& currDef = currMem.dataDefinition(j);
1421
1422 assert(&currDef.startAddress().space() ==
1423 &currMem.addressSpace());
1424
1425 // create new data dection if needed
1426 if (currSect == NULL ||
1427
1428 (currDef.isInitialized() &&
1429 !currSect->isDataSection()) ||
1430
1431 (!currDef.isInitialized() &&
1432 currSect->isDataSection()) ||
1433
1434 (currDef.startAddress().location() !=
1435 currSect->startingAddress() +
1436 currSect->lengthInMAUs())) {
1437
1438 if (currDef.isInitialized()) {
1439 if (!littleEndian) {
1440 currSect = dynamic_cast<DataSection*>(
1441 Section::createSection(Section::ST_DATA));
1442 } else {
1443 currSect = dynamic_cast<DataSection*>(
1444 Section::createSection(Section::ST_LEDATA));
1445 }
1446 } else {
1447 currSect = dynamic_cast<UDataSection*>(
1448 Section::createSection(Section::ST_UDATA));
1449 }
1450
1451 // add section to binary
1452 assert (currSect != NULL);
1453 bin->addSection(currSect);
1454
1455 currSect->setStartingAddress(
1456 currDef.startAddress().location());
1457
1458 currSect->setName(strings->string2Chunk(""));
1459
1460 currSect->setLink(bin->section(Section::ST_NULL,0));
1461
1462 const AddressSpace& adfASpace = currMem.addressSpace();
1463 currSect->setASpace(&createASpaceElement(adfASpace, *bin));
1464 }
1465
1466 // add data to section
1467 if (currDef.isInitialized()) {
1468 DataSection* dataSect = dynamic_cast<DataSection*>(currSect);
1469
1470 int byteOffset = dataSect->length();
1471
1472 for (int k = 0; k < currDef.size(); k++) {
1473 dataSect->addMAU(currDef.MAU(k));
1474 }
1475
1476 if (currDef.isAddress()) {
1477 RelocInfo newReloc(
1478 dataSect, dataSect->chunk(byteOffset),
1479 currDef.destinationAddress(),
1480 currDef.size() * dataSect->aSpace()->MAU());
1481
1482 relocInfos_.push_back(newReloc);
1483 }
1484
1485 } else {
1486 currSect->setLengthInMAUs(
1487 currSect->lengthInMAUs() + currDef.size());
1488 }
1489
1490
1491#if 0
1492 // Prints debug data of all encountered data definitions.
1493 if (currSect != NULL) {
1495 << "datadef: addr: "
1496 << currDef.startAddress().space().name() << ":"
1497 << currDef.startAddress().location()
1498 << "\t" << "size: " << currDef.size()
1499 << "\t" << "init: " << currDef.isInitialized()
1500 << "\t" << "isAddr: " << currDef.isAddress();
1501 if (currDef.isAddress()) {
1503 << "\t" << "dest: "
1504 << currDef.destinationAddress().space().name() << ":"
1505 << currDef.destinationAddress().location();
1506 }
1508 << std::endl;
1509 }
1510#endif
1511
1512#if 0
1513 // prints out debug data of all created data sections
1514 if (currSect != NULL) {
1515 DataSection* dSectTmp = dynamic_cast<DataSection*>(currSect);
1517 << "data section " << currSect << " length: "
1518 << currSect->lengthInMAUs()
1519 << "\tstart address: "
1520 << TPEFTools::addressSpaceName(
1521 *bin, *currSect->aSpace())
1522 << ":" << currSect->startingAddress()
1523 << "\tinitialized: "
1524 // << static_cast<int>(currSect->isDataSection())
1525 << (dSectTmp?true:false)
1526 << std::endl;
1527 }
1528#endif
1529
1530 }
1531 }
1532}
1533
1534/**
1535 * Creates new address space element to binary or returns already created one.
1536 *
1537 * This function should be used always with same TPEF bin.
1538 *
1539 * @param addressSpace ADF address space whose TPEF version is needed.
1540 * @param bin Binary to which created address space is added.
1541 * @return Address space element of corresponding ADF address space.
1542 */
1545 const TTAMachine::AddressSpace& addressSpace, TPEF::Binary& bin) const {
1546
1547 StringSection* strings = dynamic_cast<StringSection*>(
1548 bin.section(Section::ST_STRTAB,0));
1549 Section* aSpaceSection = bin.section(Section::ST_ADDRSP,0);
1550
1551 // create new address space if necessary
1552 if (!MapTools::containsKey(aSpaceMap_, &addressSpace)) {
1553 ASpaceElement *newASpace = new ASpaceElement();
1554
1555 // set mau of instruction address space to be 0
1556 if (&addressSpace ==
1558 newASpace->setMAU(0);
1559 } else {
1560 newASpace->setMAU(addressSpace.width());
1561 }
1562 newASpace->setName(
1563 strings->string2Chunk(addressSpace.name()));
1564 aSpaceSection->addElement(newASpace);
1565 aSpaceMap_[&addressSpace] = newASpace;
1566 }
1567
1568 return *aSpaceMap_[&addressSpace];
1569}
1570
1571/**
1572 * Create relocation tables to binary and add relocation elements.
1573 *
1574 * @param bin Binary where to add relocation sections.
1575 * @exception NotAvailable Can't find needed resource.
1576 */
1577void
1579 StringSection* strings = dynamic_cast<StringSection*>(
1580 bin->section(Section::ST_STRTAB,0));
1581
1582 ASpaceSection* aSpaces = dynamic_cast<ASpaceSection*>(
1583 bin->section(Section::ST_ADDRSP,0));
1584
1585 SymbolSection* symbols = dynamic_cast<SymbolSection*>(
1586 bin->section(Section::ST_SYMTAB, 0));
1587
1588 RelocSection* currRelocs = NULL;
1589
1590 for (int i = 0; i < static_cast<int>(relocInfos_.size()); i++) {
1591 RelocInfo& currReloc = relocInfos_[i];
1592
1593 Section& dstSect = findSection(*bin, currReloc.destination);
1594
1595 // create new reloc section if needed
1596 if (currRelocs == NULL ||
1597 currRelocs->referencedSection() != currReloc.srcSect) {
1598
1599 currRelocs = dynamic_cast<RelocSection*>(
1600 Section::createSection(Section::ST_RELOC));
1601 bin->addSection(currRelocs);
1602
1603 currRelocs->setName(strings->string2Chunk(""));
1604 currRelocs->setLink(symbols);
1605 currRelocs->setASpace(aSpaces->undefinedASpace());
1606 currRelocs->setReferencedSection(currReloc.srcSect);
1607 }
1608
1609 SectionElement* dstElem = NULL;
1610
1611 // get element by address (destination element)
1612 if (dstSect.isCodeSection()) {
1613 CodeSection& codeSect =
1614 dynamic_cast<CodeSection&>(dstSect);
1615
1616 dstElem = &codeSect.instruction(
1617 currReloc.destination.location() -
1618 codeSect.startingAddress());
1619
1620 } else {
1621 UDataSection& dataSect =
1622 dynamic_cast<UDataSection&>(dstSect);
1623
1624 int byteOffset = dataSect.MAUsToBytes(
1625 currReloc.destination.location() -
1626 dataSect.startingAddress());
1627
1628 dstElem = dataSect.chunk(byteOffset);
1629 }
1630
1631 RelocElement* newReloc = new RelocElement();
1632 currRelocs->addElement(newReloc);
1633
1634 newReloc->setType(RelocElement::RT_SELF);
1635
1636 newReloc->setLocation(currReloc.srcElem);
1637
1638 newReloc->setDestination(dstElem);
1639
1640 newReloc->setSymbol(
1641 dynamic_cast<SymbolElement*>(symbols->element(0)));
1642
1643 newReloc->setASpace(
1645 currReloc.destination.space(), *bin));
1646
1647 newReloc->setSize(currReloc.bits);
1648
1649 }
1650}
1651
1652/**
1653 * Finds section which contain requested address.
1654 *
1655 * @param bin TPEF where from sections are searched.
1656 * @param address The address that are looked for.
1657 * @return The section which contains requested address.
1658 */
1661
1662 for (int i = 0; i < static_cast<int>(bin.sectionCount()); i++) {
1663 Section& currSect = *bin.section(i);
1664
1665 if (currSect.isProgramSection()) {
1666 if (currSect.startingAddress() <= address.location() &&
1667 &createASpaceElement(address.space(), bin) ==
1668 currSect.aSpace()) {
1669
1670 if (currSect.isCodeSection()) {
1671 CodeSection& codeSect =
1672 dynamic_cast<CodeSection&>(currSect);
1673
1674 if (codeSect.instructionCount() +
1675 codeSect.startingAddress() > address.location()) {
1676
1677 return codeSect;
1678 }
1679 } else {
1680 UDataSection& dataSect =
1681 dynamic_cast<UDataSection&>(currSect);
1682
1683 if (dataSect.startingAddress() +
1684 dataSect.lengthInMAUs() > address.location()) {
1685
1686 return dataSect;
1687 }
1688 }
1689 }
1690 }
1691 }
1692
1693 throw NotAvailable(
1694 __FILE__, __LINE__, __func__,
1695 "Can't find section containing address: " + address.space().name() +
1696 ":" + Conversion::toString(address.location()));
1697}
1698
1699
1700/**
1701 * Find out the kind of TPEF file type.
1702 *
1703 * This method scans the resource section and checks the type of processor
1704 * resource elements it contains. Based on their types, it figures out what
1705 * should be the file type.
1706 *
1707 * @param resources Resource section.
1708 * @return File type of TPEF binary.
1709 */
1712
1713 bool univRefs = false;
1714 bool realRefs = false;
1715
1716 for (unsigned int i = 0; i < resources.elementCount(); i++) {
1717 ResourceElement* res =
1718 dynamic_cast<ResourceElement*>(resources.element(i));
1719
1720 switch(res->type()) {
1721
1722 case ResourceElement::MRT_BUS:
1723 if (res->id() == ResourceElement::UNIVERSAL_BUS) {
1724 univRefs = true;
1725 } else {
1726 realRefs = true;
1727 }
1728 break;
1729
1730 case ResourceElement::MRT_UNIT:
1731 if (res->id() == ResourceElement::UNIVERSAL_FU) {
1732 univRefs = true;
1733 } else {
1734 realRefs = true;
1735 }
1736 break;
1737
1738 case ResourceElement::MRT_RF:
1739 if (res->id() == ResourceElement::INT_RF ||
1740 res->id() == ResourceElement::BOOL_RF ||
1741 res->id() == ResourceElement::FP_RF) {
1742 univRefs = true;
1743 } else {
1744 realRefs = true;
1745 }
1746 break;
1747
1748 case ResourceElement::MRT_IMM:
1749 realRefs = true;
1750 break;
1751
1752 default:
1753 ;// just omit MRT_PORT, MRT_SR and MRT_OP
1754 }
1755 }
1756
1757 if (univRefs && realRefs) {
1758 return Binary::FT_MIXED;
1759 } else if (univRefs) {
1760 return Binary::FT_PURESEQ;
1761 } else if (!univRefs && realRefs) {
1762 return Binary::FT_PARALLEL;
1763 }
1764
1765 return Binary::FT_NULL;
1766}
1767
1768}
#define __func__
#define abortWithError(message)
#define assert(condition)
const Byte WORD_BITWIDTH
Definition BaseType.hh:138
unsigned long LongWord
Definition BaseType.hh:49
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 bool containsKey(const MapType &aMap, const KeyType &aKey)
static SLongWord signExtendTo(SLongWord value, int width)
static int requiredBits(unsigned long int number)
static int requiredBitsSigned(SLongWord number)
static ULongWord zeroExtendTo(ULongWord value, int width)
static NullOperation & instance()
virtual TCEString name() const
Definition Operation.cc:93
static std::string disassemble(const TTAProgram::Move &move)
ULongWord uLongWordValue() const
Definition SimValue.cc:1027
unsigned int unsignedValue() const
Definition SimValue.cc:919
SLongWord sLongWordValue() const
Definition SimValue.cc:997
void setName(const ReferenceManager::SafePointer *aName)
void setMAU(Byte aMAU)
Byte MAU() const
ASpaceElement * undefinedASpace() const
void setUndefinedASpace(ASpaceElement *aSpace)
void addSection(Section *section)
void setArch(FileArchitecture arch)
Word sectionCount() const
Section * section(Word index) const
void setType(FileType type)
void setStrings(StringSection *strTable)
InstructionElement & instruction(Word index) const
virtual void addElement(SectionElement *element)
Word instructionCount() const
void setReference(InstructionElement *aReference)
virtual void addMAU(MinimumAddressableUnit aMAU)
virtual Word length() const
virtual void addByte(Byte aByte)
void setReference(Chunk *aReference)
void setDestinationIndex(Byte aDestinationIndex)
void setULongWord(ULongWord aValue)
Byte destinationIndex() const
void setDestinationUnit(Byte aDestinationUnit)
Byte destinationUnit() const
void setSignedLong(SLongWord aValue)
void setBegin(bool isBegin)
void addAnnotation(InstructionAnnotation *anAnnotation)
void setGuardIndex(HalfWord aGuardIndex)
void setSourceType(FieldType aType)
void setGuardInverted(bool flag)
bool isEmpty() const
void setSourceIndex(HalfWord aSourceIndex)
void setBus(HalfWord aBus)
void setDestinationUnit(HalfWord aDestinationUnit)
void setGuarded(bool flag)
void setSourceUnit(HalfWord aSourceUnit)
void setGuardUnit(HalfWord aGuardUnit)
void setDestinationIndex(HalfWord aDestinationIndex)
void setEmpty(bool flag)
void setDestinationType(FieldType aType)
void setGuardType(FieldType gType)
virtual void setLengthInMAUs(Word length)
Definition Section.cc:265
virtual Chunk * chunk(SectionOffset offset) const
Definition Section.cc:212
virtual Word MAUsToBytes(Word mauCount) const
Definition Section.cc:320
virtual Word lengthInMAUs() const
Definition Section.cc:285
void setASpace(ASpaceElement *anASpace)
void setLocation(SectionElement *aLocation)
void setSize(Byte aSize)
void setSymbol(SymbolElement *aSymbol)
void setType(RelocType aType)
void setDestination(SectionElement *aDestination)
void setReferencedSection(Section *section)
Section * referencedSection() const
void setId(HalfWord aId)
ResourceType type() const
void setName(ReferenceManager::SafePointer *aName)
HalfWord id() const
Chunk * name() const
void setType(ResourceType aType)
AddressImage startingAddress() const
bool isProgramSection() const
virtual void addElement(SectionElement *element)
Definition Section.cc:133
Section * link() const
void setStartingAddress(AddressImage address)
SectionElement * element(Word index) const
virtual bool isCodeSection() const
Definition Section.hh:143
Word elementCount() const
void setLink(const ReferenceManager::SafePointer *aLink)
void setASpace(const ReferenceManager::SafePointer *addrSpace)
void setName(const ReferenceManager::SafePointer *sectionName)
ASpaceElement * aSpace() const
virtual bool isDataSection() const
Definition Section.hh:142
std::string chunk2String(const Chunk *chunk) const
Chunk * string2Chunk(const std::string &str)
void setAbsolute(bool anAbsoluteness)
void setName(Chunk *aName)
void setBinding(SymbolBinding aBinding)
void setSection(Section *aSect)
virtual SectionType type() const
virtual ULongWord end() const
virtual int width() const
virtual ULongWord start() const
FunctionUnit * parentUnit() const
Definition BaseFUPort.cc:96
int immediateWidth() const
Definition Bus.cc:160
bool signExtends() const
Definition Bus.cc:171
virtual Machine * machine() const
virtual TCEString name() const
SpecialRegisterPort * returnAddressPort() const
bool hasReturnAddressPort() const
virtual AddressSpace * addressSpace() const
virtual HWOperation * operation(const std::string &name) const
virtual int operationCount() const
virtual bool hasOperationPort(const std::string &name) const
virtual bool hasOperation(const std::string &name) const
virtual BaseFUPort * port(const std::string &name) const
virtual bool isInverted() const
int io(const FUPort &port) const
const std::string & name() const
bool isBound(const FUPort &port) const
FunctionUnit * parentUnit() const
virtual RegisterFileNavigator registerFileNavigator() const
Definition Machine.cc:450
virtual FunctionUnitNavigator functionUnitNavigator() const
Definition Machine.cc:380
bool isLittleEndian() const
Definition Machine.hh:258
virtual ImmediateUnitNavigator immediateUnitNavigator() const
Definition Machine.cc:416
virtual BusNavigator busNavigator() const
Definition Machine.cc:356
virtual ControlUnit * controlUnit() const
Definition Machine.cc:345
FUPort * port() const
Unit * parentUnit() const
virtual std::string name() const
Definition Port.cc:141
const RegisterFile * registerFile() const
virtual bool hasPort(const std::string &name) const
Definition Unit.cc:96
const TTAMachine::AddressSpace & space() const
InstructionAddress location() const
int annotationCount(ProgramAnnotation::Id id=ProgramAnnotation::ANN_UNDEF_ID) const
ProgramAnnotation annotation(int index, ProgramAnnotation::Id id=ProgramAnnotation::ANN_UNDEF_ID) const
bool hasAnnotations(ProgramAnnotation::Id id=ProgramAnnotation::ANN_UNDEF_ID) const
virtual Address address() const
Definition CodeLabel.cc:101
virtual int instructionCount() const
virtual Address startAddress() const
virtual Instruction & instructionAtIndex(int index) const
virtual Address startAddress() const
virtual bool isAddress() const
virtual bool isInitialized() const
virtual MinimumAddressableUnit MAU(int index) const
virtual Address destinationAddress() const
DataDefinition & dataDefinition(Address address) const
Definition DataMemory.cc:79
int dataDefinitionCount() const
const TTAMachine::AddressSpace & addressSpace() const
const DataLabel & globalDataLabel(Address address, int index) const
const CodeLabel & globalCodeLabel(Address address, int index) const
int globalDataLabelCount(Address address) const
int globalCodeLabelCount(Address address) const
TerminalImmediate & value() const
Definition Immediate.cc:103
const Terminal & destination() const
Definition Immediate.cc:92
Move & move(int i) const
Address address() const
Immediate & immediate(int i) const
std::string name() const
Definition Label.cc:74
virtual Address address() const
Definition Label.cc:84
const TTAMachine::Guard & guard() const
Definition MoveGuard.cc:86
MoveGuard & guard() const
Definition Move.cc:345
bool isUnconditional() const
Definition Move.cc:154
Instruction & parent() const
Definition Move.cc:115
Terminal & source() const
Definition Move.cc:302
Terminal & destination() const
Definition Move.cc:323
const TTAMachine::Bus & bus() const
Definition Move.cc:373
TCEString name() const
Definition Procedure.hh:66
const std::vector< Byte > & payload() const
ProgramAnnotation::Id id() const
std::vector< RelocInfo > relocInfos_
void createDataSections(TPEF::Binary *bin, bool littleEndian) const
void createRelocSections(TPEF::Binary *bin) const
void createCodeSection(TPEF::CodeSection *code, TPEFResourceUpdater &updater) const
ResourceID terminalResource(const Terminal &term, TPEFResourceUpdater &updater) const
static const HalfWord IMMEDIATE_ADDRESS_WIDTH
Default widt that is used as address width of relocations of immediate elements. This should be fixed...
const Program & prog_
Program that is written to TPEF.
TPEF::Binary * createBinary() const
TPEF::Binary::FileType resolveFileType(TPEF::ResourceSection &resources) const
ProgramWriter(const Program &prog)
TPEF::Section & findSection(TPEF::Binary &bin, Address address) const
std::map< const TTAMachine::AddressSpace *, TPEF::ASpaceElement * > aSpaceMap_
Created TPEF binary.
TPEF::ASpaceElement & createASpaceElement(const TTAMachine::AddressSpace &addressSpace, TPEF::Binary &bin) const
static const int MAX_SIMM_WIDTH
Maximum width for short immediates.
Procedure & procedure(int index) const
Definition Program.cc:622
Address startAddress() const
Definition Program.cc:286
const GlobalScope & globalScopeConst() const
Definition Program.cc:192
TTAMachine::Machine & targetProcessor() const
Definition Program.cc:202
DataMemory & dataMemory(int index) const
Definition Program.cc:967
int procedureCount() const
Definition Program.cc:610
int instructionCount() const
Definition Program.cc:1209
int dataMemoryCount() const
Definition Program.cc:942
HalfWord lastUnitPortId_
Last TPEF unit port id that was generated.
TPEF::ResourceElement & registerFile(const TTAMachine::RegisterFile &rf)
TPEF::ResourceElement & bus(const TTAMachine::Bus &bus)
HalfWord lastBusId_
Last TPEF bus id that was generated.
HalfWord lastFunctionUnitId_
Last TPEF function unit id that was generated.
TPEF::ResourceElement & functionUnit(const TTAMachine::FunctionUnit &fu)
TPEFResourceUpdater(TTAMachine::Machine &mach, TPEF::ResourceSection &resources)
TPEF::ResourceElement & immediateUnit(const TTAMachine::ImmediateUnit &immUnit)
HalfWord lastRegisterFileId_
Last TPEF register file id that was generated.
TPEF::ResourceElement & operand(const TTAMachine::HWOperation &oper, int operandIndex)
TPEF::ResourceSection & resources_
The TPEF input section that contains all machine resource entries.
std::pair< const TTAMachine::MachinePart *, int > CacheKey
HalfWord lastImmediateUnitId_
Last TPEF immediate unit id that was generated.
TTAMachine::Machine & mach_
The model of the target processor architecture.
TPEF::ResourceElement & functionUnitPort(const TTAMachine::Port &port)
ResourceCache cache_
Aggregate of all mappings between machine resource entries and target processor parts (machine parts)...
virtual Operation & hintOperation() const
virtual Operation & operation() const
virtual bool isOpcodeSetting() const
virtual SimValue value() const
virtual SimValue value() const
Definition Terminal.cc:178
virtual bool isAddress() const
Definition Terminal.cc:75
virtual int index() const
Definition Terminal.cc:274
virtual Address address() const
Definition Terminal.cc:210
virtual bool isGPR() const
Definition Terminal.cc:107
virtual bool isInstructionAddress() const
Definition Terminal.cc:87
virtual bool isImmediateRegister() const
Definition Terminal.cc:97
virtual const TTAMachine::Port & port() const
Definition Terminal.cc:378
virtual bool isImmediate() const
Definition Terminal.cc:63
virtual const TTAMachine::ImmediateUnit & immediateUnit() const
Definition Terminal.cc:240
virtual const TTAMachine::RegisterFile & registerFile() const
Definition Terminal.cc:225
virtual bool isFUPort() const
Definition Terminal.cc:118
TTAMachine::RegisterFile & booleanRegisterFile() const
UniversalFunctionUnit & universalFunctionUnit() const
UnboundedRegisterFile & integerRegisterFile() const
TTAMachine::Bus & universalBus() const
UnboundedRegisterFile & doubleRegisterFile() const
TPEF::SectionElement * srcElem
Location element.
TPEF::Section * srcSect
Location section.
Address destination
Destination address.
TPEF::MoveElement::FieldType type
RF, UNIT or IMM.
HalfWord index
Operand or register file index.