OpenASIP 2.2
Loading...
Searching...
No Matches
Classes | Public Member Functions | Protected Types | Protected Member Functions | Private Member Functions | Private Attributes | List of all members
TTAProgram::TPEFProgramFactory Class Reference

#include <TPEFProgramFactory.hh>

Collaboration diagram for TTAProgram::TPEFProgramFactory:
Collaboration graph

Classes

class  CacheKey
 Cache key for resources that are accessed from MOM(s) More...
 
struct  SocketAllocation
 

Public Member Functions

 TPEFProgramFactory (const TPEF::Binary &aBinary, const TTAMachine::Machine &aMachine)
 
 TPEFProgramFactory (const TPEF::Binary &aBinary, const TTAMachine::Machine &aMachine, UniversalMachine *aUniversalMachine)
 
 TPEFProgramFactory (const TPEF::Binary &aBinary, UniversalMachine *aMachine)
 
virtual ~TPEFProgramFactory ()
 
Programbuild ()
 

Protected Types

typedef std::map< HalfWord, SimValue * > InlineValues
 
typedef std::pair< Word, Word > ImmediateKey
 
typedef std::map< ImmediateKey, TPEF::ImmediateElement * > ImmediateMap
 
typedef std::vector< TPEF::MoveElement * > MoveVector
 
typedef std::vector< TPEF::ImmediateElement * > ImmediateVector
 

Protected Member Functions

InstructioncreateInstruction (const TPEF::ResourceSection &resources, MoveVector &moveElements, ImmediateVector &longImmediates, ImmediateMap &immElements) const
 
void addProcedures (Program &program, const TTAMachine::AddressSpace &programASpace) const
 
TerminalcreateTerminal (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::BusfindBus (const TPEF::ResourceSection &resources, HalfWord busId) const
 
TTAMachine::RegisterFilefindRegisterFile (const TPEF::ResourceSection &resources, HalfWord rfId) const
 
TTAMachine::ImmediateUnitfindImmediateUnit (const TPEF::ResourceSection &resources, Byte immUnitId) const
 
TTAMachine::FunctionUnitfindFunctionUnit (const TPEF::ResourceSection &resources, HalfWord unitId, std::string tpefOpName="") const
 
TTAMachine::PortfindPort (const TTAMachine::Bus &bus, const TTAMachine::Unit &portParent, std::string tpefOpName="", int tpefOpIndex=0) const
 
TTAMachine::AddressSpacefindAddressSpace (const TPEF::ASpaceElement *aSpace) const
 
TTAMachine::GuardfindGuard (const TPEF::ResourceSection &resources, TTAMachine::Bus &bus, TPEF::MoveElement::FieldType type, HalfWord unitId, HalfWord index, bool isInverted) const
 
TTAMachine::InstructionTemplatefindInstrTemplate (const TPEF::ResourceSection &resources, ImmediateVector &longImmediates, MoveVector &moves) const
 
void seekFunctionStartPoints ()
 
void createLabels (Program &prog)
 
void createDataRelocs (Program &prog)
 
void createDataMemories (Program &prog)
 
bool isFunctionStart (const TPEF::InstructionElement &instructionElement) const
 
std::string functionName (const TPEF::InstructionElement &instructionElement) const
 
std::string stringOfChunk (const TPEF::Chunk *chunk, const TPEF::Section *chunkOwner) const
 

Private Member Functions

void clearResourceAllocations () const
 
bool canSourceBeAssigned (SocketAllocation &alloc, std::map< TTAMachine::Socket *, std::vector< SocketAllocation * > > &fixedSockets) const
 
bool canDestinationBeAssigned (SocketAllocation &alloc, std::map< TTAMachine::Socket *, std::vector< SocketAllocation * > > &fixedSockets) const
 
void resolveSocketAllocations (std::vector< SocketAllocation > &allocs) const
 
TerminalgetFromCache (const CacheKey &key) const
 
void addToCache (const CacheKey &key, Terminal *cachedTerm) const
 
void clearCache () const
 

Private Attributes

const TPEF::Binarybinary_
 Binary that is used for creating program.
 
const TTAMachine::Machinemachine_
 Target machine of program.
 
UniversalMachineuniversalMachine_
 Universal machine of program.
 
TPEF::TPEFTools tpefTools_
 TPEFTools object for helper functions.
 
TTAMachine::AddressSpaceadfInstrASpace_
 Instruction address space of machine.
 
TPEF::ASpaceElementtpefInstrASpace_
 Instruction address space element of TPEF.
 
std::map< const TPEF::InstructionElement *, class FunctionStart * > functionStartPositions_
 Stores information of start points of procedures that were found.
 
std::list< std::shared_ptr< Move > > instructionImmediates_
 Moves whose source terminals are addresses referring to instructions.
 
std::list< std::shared_ptr< Immediate > > longInstructionImmediates_
 Long immediates whose value terminals refers to instructions.
 
std::map< const CacheKey, Terminal * > cache_
 Cache map of terminals that are returned by different search parameters.
 
std::set< HalfWord > allocatedBusses_
 Busses that are already allocated by moves of current instruction.
 
std::map< TPEF::InstructionElement *, Instruction * > instructionMap_
 Program instruction by TPEF instruction element.
 

Detailed Description

Creates a new TTA program out of a description of a binary representation of the program and a model of the target architecture.

This class builds only one program, even if the input binary contains many programs (the original TPEF file has multiple code sections with different address spaces).

Definition at line 87 of file TPEFProgramFactory.hh.

Member Typedef Documentation

◆ ImmediateKey

typedef std::pair<Word, Word> TTAProgram::TPEFProgramFactory::ImmediateKey
protected

Definition at line 107 of file TPEFProgramFactory.hh.

◆ ImmediateMap

Definition at line 108 of file TPEFProgramFactory.hh.

◆ ImmediateVector

Definition at line 110 of file TPEFProgramFactory.hh.

◆ InlineValues

typedef std::map<HalfWord, SimValue*> TTAProgram::TPEFProgramFactory::InlineValues
protected

Definition at line 106 of file TPEFProgramFactory.hh.

◆ MoveVector

Definition at line 109 of file TPEFProgramFactory.hh.

Constructor & Destructor Documentation

◆ TPEFProgramFactory() [1/3]

TTAProgram::TPEFProgramFactory::TPEFProgramFactory ( const TPEF::Binary aBinary,
const TTAMachine::Machine aMachine 
)

Constructor for fully scheduled code.

Parameters
aBinaryBinary that contains a program's instructions and data.
aMachineMachine to which code refers.
relocsManaged collection of relocation points in the program.

Definition at line 137 of file TPEFProgramFactory.cc.

138 :
139 binary_(&aBinary), machine_(&aMachine),
141 tpefTools_(aBinary),
142 adfInstrASpace_(NULL),
143 tpefInstrASpace_(NULL) {
144}
const TTAMachine::Machine * machine_
Target machine of program.
TPEF::ASpaceElement * tpefInstrASpace_
Instruction address space element of TPEF.
const TPEF::Binary * binary_
Binary that is used for creating program.
TTAMachine::AddressSpace * adfInstrASpace_
Instruction address space of machine.
TPEF::TPEFTools tpefTools_
TPEFTools object for helper functions.
UniversalMachine * universalMachine_
Universal machine of program.
static UniversalMachine & instance()

◆ TPEFProgramFactory() [2/3]

TTAProgram::TPEFProgramFactory::TPEFProgramFactory ( const TPEF::Binary aBinary,
const TTAMachine::Machine aMachine,
UniversalMachine aUniversalMachine 
)

Constructor.

For mixed code which contains universal machine references and target machine references.

Parameters
aBinaryBinary that contains a program's instructions and data.
aMachineActual machine to which parallel code refers.
aUniversalMachineUniversal machine for sequential code.
relocsManaged collection of relocation points in the program.

Definition at line 119 of file TPEFProgramFactory.cc.

122 :
123 binary_(&aBinary), machine_(&aMachine),
125 tpefTools_(aBinary),
126 adfInstrASpace_(NULL),
127 tpefInstrASpace_(NULL) {
128}

◆ TPEFProgramFactory() [3/3]

TTAProgram::TPEFProgramFactory::TPEFProgramFactory ( const TPEF::Binary aBinary,
UniversalMachine aMachine 
)

Constructor for fully unscheduled code.

Parameters
aBinaryBinary that contains a program's instructions and data.
uMachineUniversal Machine to which code refers.
relocsManaged collection of relocation points in the program.

Definition at line 153 of file TPEFProgramFactory.cc.

154 :
155 binary_(&aBinary), machine_(NULL),
157 tpefTools_(aBinary),
158 adfInstrASpace_(NULL),
159 tpefInstrASpace_(NULL) {
160}

◆ ~TPEFProgramFactory()

TTAProgram::TPEFProgramFactory::~TPEFProgramFactory ( )
virtual

Destructor.

Definition at line 166 of file TPEFProgramFactory.cc.

166 {
168}
static void deleteAllValues(MapType &aMap)
std::map< const TPEF::InstructionElement *, class FunctionStart * > functionStartPositions_
Stores information of start points of procedures that were found.

References MapTools::deleteAllValues(), and functionStartPositions_.

Here is the call graph for this function:

Member Function Documentation

◆ addProcedures()

void TTAProgram::TPEFProgramFactory::addProcedures ( Program program,
const TTAMachine::AddressSpace programASpace 
) const
protected

Parses procedures from all TPEF CodeSections and adds them to Program.

Parameters
programProgram where to add new procedures.
programASpaceAddress space of instruction memory.

Definition at line 344 of file TPEFProgramFactory.cc.

346 {
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 }
#define __func__
#define abortWithError(message)
#define assert(condition)
find Finds info of the inner loops in the program
std::string errorMessage() const
Definition Exception.cc:123
Word sectionCount() const
Section * section(Word index) const
virtual InstructionElement * element(Word index) const
Byte destinationIndex() const
Byte destinationUnit() const
AddressImage startingAddress() const
Section * link() const
@ ST_CODE
Text section.
Definition Section.hh:79
Word elementCount() const
std::vector< TPEF::ImmediateElement * > ImmediateVector
std::vector< TPEF::MoveElement * > MoveVector
std::string functionName(const TPEF::InstructionElement &instructionElement) const
std::map< ImmediateKey, TPEF::ImmediateElement * > ImmediateMap
bool isFunctionStart(const TPEF::InstructionElement &instructionElement) const
Instruction * createInstruction(const TPEF::ResourceSection &resources, MoveVector &moveElements, ImmediateVector &longImmediates, ImmediateMap &immElements) const
std::map< TPEF::InstructionElement *, Instruction * > instructionMap_
Program instruction by TPEF instruction element.

References __func__, abortWithError, assert, TPEF::InstructionElement::begin(), binary_, createInstruction(), TPEF::ImmediateElement::destinationIndex(), TPEF::ImmediateElement::destinationUnit(), TPEF::CodeSection::element(), TPEF::Section::elementCount(), Exception::errorMessage(), functionName(), instructionMap_, isFunctionStart(), TPEF::InstructionElement::isImmediate(), TPEF::ImmediateElement::isInline(), TPEF::InstructionElement::isMove(), TPEF::Section::link(), program, TPEF::Binary::section(), TPEF::Binary::sectionCount(), Exception::setCause(), TPEF::Section::ST_CODE, and TPEF::Section::startingAddress().

Referenced by build().

Here is the call graph for this function:

◆ addToCache()

void TTAProgram::TPEFProgramFactory::addToCache ( const CacheKey key,
Terminal cachedTerm 
) const
private

Adds Terminal to cache.

Parameters
keyKey of search variables for getting terminal from machine(s).
cachedTermTerminal to be add to cache.
Returns
cached terminal if there is one.

Definition at line 1968 of file TPEFProgramFactory.cc.

1970 {
1971
1972 cache_[key] = cachedTerm;
1973}
std::map< const CacheKey, Terminal * > cache_
Cache map of terminals that are returned by different search parameters.

References cache_.

Referenced by createTerminal().

◆ build()

Program * TTAProgram::TPEFProgramFactory::build ( )

Builds program model out of TPEF model.

Returns
Created program.
Exceptions
NotAvailableif there the binary contains no sections; if the instruction address space is missing or conflicting with architecture definition.
Exceptionif the TPEF or program in it is somehow broken.

Definition at line 200 of file TPEFProgramFactory.cc.

200 {
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_);
276 newProgram->setUniversalMachine(universalMachine_);
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 =
300 newProgram->instructionReferenceManager().createReference(
301 referencedInstruction);
302
303 TerminalInstructionReference* instrTerm =
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 =
322 newProgram->instructionReferenceManager().createReference(
323 referencedInstruction);
324
325 TerminalInstructionReference* instrTerm =
326 new TerminalInstructionReference(instructionReference);
327
328 immediate->setValue(instrTerm);
329 }
330
331 createDataMemories(*newProgram);
332 createLabels(*newProgram);
333
334 return newProgram;
335}
UInt32 InstructionAddress
Definition BaseType.hh:175
Chunk * name() 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
FileType type() const
@ ST_ADDRSP
Address space section.
Definition Section.hh:77
ASpaceElement * aSpace() const
ComponentType * item(int index) const
bool hasItem(const std::string &name) const
virtual AddressSpaceNavigator addressSpaceNavigator() const
Definition Machine.cc:392
std::vector< Instruction * > InstructionVector
Vector for instructions.
Definition Program.hh:66
std::string stringOfChunk(const TPEF::Chunk *chunk, const TPEF::Section *chunkOwner) const
std::list< std::shared_ptr< Immediate > > longInstructionImmediates_
Long immediates whose value terminals refers to instructions.
void addProcedures(Program &program, const TTAMachine::AddressSpace &programASpace) const
std::list< std::shared_ptr< Move > > instructionImmediates_
Moves whose source terminals are addresses referring to instructions.
TTAMachine::AddressSpace & instructionAddressSpace() const

References __func__, addProcedures(), TTAProgram::Terminal::address(), TTAMachine::Machine::addressSpaceNavigator(), adfInstrASpace_, TPEF::Section::aSpace(), assert, binary_, clearCache(), createDataMemories(), createLabels(), TTAProgram::InstructionReferenceManager::createReference(), TPEF::Binary::FT_LIBSEQ, TPEF::Binary::FT_OBJSEQ, TPEF::Binary::FT_PARALLEL, TPEF::Binary::FT_PURESEQ, TTAMachine::Machine::Navigator< ComponentType >::hasItem(), UniversalMachine::instructionAddressSpace(), instructionImmediates_, TTAProgram::Program::instructionReferenceManager(), TTAProgram::Program::instructionVector(), TTAMachine::Machine::Navigator< ComponentType >::item(), TPEF::Section::link(), TTAProgram::Address::location(), longInstructionImmediates_, machine_, TPEF::ASpaceElement::name(), TPEF::Binary::section(), TPEF::Binary::sectionCount(), seekFunctionStartPoints(), TTAProgram::Program::setUniversalMachine(), TTAProgram::Address::space(), TPEF::Section::ST_ADDRSP, TPEF::Section::ST_CODE, TTAProgram::Program::startAddress(), stringOfChunk(), tpefInstrASpace_, TPEF::Binary::type(), universalMachine_, and TTAProgram::TerminalImmediate::value().

Referenced by InstructionDictionary::compress(), TTAProgram::Program::loadFromTPEF(), TTAProgram::Program::loadFromUnscheduledTPEF(), TTAProgram::Program::loadFromUnscheduledTPEF(), loadInputs(), SimulatorFrontend::loadProgram(), main(), InlineAsmParser::parse(), and CodeCompressorPlugin::startNewProgram().

Here is the call graph for this function:

◆ canDestinationBeAssigned()

bool TTAProgram::TPEFProgramFactory::canDestinationBeAssigned ( SocketAllocation alloc,
std::map< TTAMachine::Socket *, std::vector< SocketAllocation * > > &  fixedSockets 
) const
private

Checks if the destination of SocketAllocation can be assigned towards given map of already allocated sockets.

If tried socket is already used, it still can be used for another writing if the moves have opposite guards.

Parameters
allocSocket allocation structure which is checked.
fixedSocketsMap of already made socket allocations.
Returns
True if tried alloc is possible.

Definition at line 1667 of file TPEFProgramFactory.cc.

1669 {
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}
static bool containsKey(const MapType &aMap, const KeyType &aKey)

References MapTools::containsKey(), TTAProgram::TPEFProgramFactory::SocketAllocation::dst, TTAProgram::TPEFProgramFactory::SocketAllocation::dstSocks, and TTAProgram::TPEFProgramFactory::SocketAllocation::move.

Referenced by resolveSocketAllocations().

Here is the call graph for this function:

◆ canSourceBeAssigned()

bool TTAProgram::TPEFProgramFactory::canSourceBeAssigned ( SocketAllocation alloc,
std::map< TTAMachine::Socket *, std::vector< SocketAllocation * > > &  fixedSockets 
) const
private

Checks if the source of SocketAllocation can be assigned towards given map of already allocated sockets.

If tried socket is already used, it still can be used for another reading if 1) the source register index is same for both of the allocations, or 2) the moves have opposite guards.

Parameters
allocSocket allocation structure which is checked.
fixedSocketsMap of already made socket allocations.
Returns
True if tried alloc is possible.

Definition at line 1624 of file TPEFProgramFactory.cc.

1626 {
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}

References MapTools::containsKey(), TTAProgram::Terminal::index(), TTAProgram::TPEFProgramFactory::SocketAllocation::move, TTAProgram::TPEFProgramFactory::SocketAllocation::src, and TTAProgram::TPEFProgramFactory::SocketAllocation::srcSocks.

Referenced by resolveSocketAllocations().

Here is the call graph for this function:

◆ clearCache()

void TTAProgram::TPEFProgramFactory::clearCache ( ) const
private

Clears cache.

Definition at line 1979 of file TPEFProgramFactory.cc.

1979 {
1980 cache_.clear();
1981}

References cache_.

Referenced by build().

◆ clearResourceAllocations()

void TTAProgram::TPEFProgramFactory::clearResourceAllocations ( ) const
private

◆ createDataMemories()

void TTAProgram::TPEFProgramFactory::createDataMemories ( Program prog)
protected

Creates data memories to program.

Parameters
progProgram containing converted TPEF instructions.

Definition at line 2176 of file TPEFProgramFactory.cc.

2176 {
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()),
2227 prog.targetProcessor().isLittleEndian());
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 =
2296 prog.instructionReferenceManager().
2297 createReference(*instructionMap_[tpefInstr]);
2298
2299 DataInstructionAddressDef* newDataDef =
2300 new DataInstructionAddressDef(
2301 startAddr, mauSize, instrRef,
2302 prog.targetProcessor().isLittleEndian());
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,
2342 prog.targetProcessor().isLittleEndian());
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,
2430 prog.targetProcessor().isLittleEndian(),
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}
virtual MinimumAddressableUnit MAU(Word index) const
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
@ ST_DATA
Initialized data section.
Definition Section.hh:80
@ ST_UDATA
Uninitialized data section.
Definition Section.hh:81
@ ST_LEDATA
Initialized little endian data section.
Definition Section.hh:82
@ ST_RELOC
Relocation section.
Definition Section.hh:74
SectionElement * element(Word index) const
virtual SectionType type() const =0
Returns SectioType of actual section instance.
virtual SectionType type() const
virtual ULongWord end() const
virtual int width() const
TTAMachine::AddressSpace & findAddressSpace(const TPEF::ASpaceElement *aSpace) const

References TTAProgram::DataMemory::addDataDefinition(), TTAProgram::Program::addDataMemory(), adfInstrASpace_, TPEF::RelocElement::aSpace(), TPEF::Section::aSpace(), assert, TPEF::RawSection::belongsToSection(), binary_, TPEF::RawSection::chunkToMAUIndex(), TTAProgram::DataMemory::dataDefinition(), TTAProgram::DataMemory::dataDefinitionCount(), TPEF::RelocElement::destination(), TPEF::Section::element(), TPEF::Section::elementCount(), TTAMachine::AddressSpace::end(), findAddressSpace(), instructionMap_, TTAProgram::Program::instructionReferenceManager(), TTAMachine::Machine::isLittleEndian(), TPEF::RawSection::lengthInMAUs(), TTAProgram::Address::location(), TPEF::RelocElement::location(), TPEF::DataSection::MAU(), TPEF::RelocSection::referencedSection(), TPEF::Binary::section(), TPEF::Binary::sectionCount(), TTAProgram::DataDefinition::size(), TPEF::RelocElement::size(), TPEF::Section::ST_DATA, TPEF::Section::ST_LEDATA, TPEF::Section::ST_RELOC, TPEF::Section::ST_UDATA, TTAProgram::DataDefinition::startAddress(), TPEF::Section::startingAddress(), TTAProgram::Program::targetProcessor(), TPEF::UDataSection::type(), TPEF::Section::type(), and TTAMachine::AddressSpace::width().

Referenced by build().

Here is the call graph for this function:

◆ createDataRelocs()

void TTAProgram::TPEFProgramFactory::createDataRelocs ( Program prog)
protected

◆ createInstruction()

Instruction * TTAProgram::TPEFProgramFactory::createInstruction ( const TPEF::ResourceSection resources,
MoveVector moveElements,
ImmediateVector longImmediates,
ImmediateMap immElements 
) const
protected

Creates an instruction out of given moves and immediate elements.

Parameters
resourcesTPEF resource section.
moveElementsMove elements of instruction.
longImemdiatesLong immediates of instruction.
immElementsImmediate elements of instruction.
Returns
A new instruction.

Definition at line 512 of file TPEFProgramFactory.cc.

516 {
517
518 std::vector<SocketAllocation> allocatedSockets;
519
520 Instruction* newInstruction =
521 new Instruction(NullInstructionTemplate::instance());
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(
644 ProgramAnnotation(
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(
666 ProgramAnnotation(
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}
unsigned char Byte
Definition BaseType.hh:116
LongWord longWord() const
SignedLongWord sLongWord() 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_IMM
Immediate.
const RelocElement & relocation(const SectionElement &element) const
Definition TPEFTools.cc:119
bool hasRelocation(const SectionElement &element) const
Definition TPEFTools.cc:107
virtual Machine * machine() const
virtual SocketNavigator socketNavigator() const
Definition Machine.cc:368
static NullInstructionTemplate & instance()
Unit * parentUnit() 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 Port * port(const std::string &name) const
Definition Unit.cc:116
Id
the ID in TPEF is 24 bits, here enum
TTAMachine::Bus & findBus(const TPEF::ResourceSection &resources, HalfWord busId) const
TTAMachine::Guard & findGuard(const TPEF::ResourceSection &resources, TTAMachine::Bus &bus, TPEF::MoveElement::FieldType type, HalfWord unitId, HalfWord index, bool isInverted) const
TTAMachine::ImmediateUnit & findImmediateUnit(const TPEF::ResourceSection &resources, Byte immUnitId) const
void resolveSocketAllocations(std::vector< SocketAllocation > &allocs) 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::InstructionTemplate & findInstrTemplate(const TPEF::ResourceSection &resources, ImmediateVector &longImmediates, MoveVector &moves) const

References TTAProgram::AnnotatedInstructionElement::addAnnotation(), TTAProgram::Instruction::addImmediate(), TTAProgram::Instruction::addMove(), adfInstrASpace_, TPEF::InstructionElement::annotation(), TPEF::InstructionElement::annotationCount(), TPEF::RelocElement::aSpace(), assert, TPEF::MoveElement::bus(), TTAMachine::Machine::Navigator< ComponentType >::count(), createTerminal(), TPEF::ImmediateElement::destinationIndex(), TPEF::MoveElement::destinationIndex(), TPEF::MoveElement::destinationType(), TPEF::ImmediateElement::destinationUnit(), TPEF::MoveElement::destinationUnit(), TTAMachine::Socket::direction(), TTAProgram::TPEFProgramFactory::SocketAllocation::dstSocks, findAddressSpace(), findBus(), findGuard(), findImmediateUnit(), findInstrTemplate(), TPEF::MoveElement::guardIndex(), TPEF::MoveElement::guardType(), TPEF::MoveElement::guardUnit(), TPEF::TPEFTools::hasRelocation(), TPEF::InstructionAnnotation::id(), TTAMachine::Socket::INPUT, TTAMachine::NullInstructionTemplate::instance(), instructionImmediates_, TTAMachine::Socket::isConnectedTo(), TPEF::MoveElement::isEmpty(), TTAProgram::Terminal::isGPR(), TPEF::MoveElement::isGuarded(), TPEF::MoveElement::isGuardInverted(), TTAProgram::Terminal::isImmediateRegister(), TTAMachine::Machine::Navigator< ComponentType >::item(), longInstructionImmediates_, TPEF::ImmediateElement::longWord(), TTAMachine::Component::machine(), TPEF::MoveElement::MF_IMM, TTAMachine::Socket::OUTPUT, TTAMachine::Port::parentUnit(), TPEF::InstructionAnnotation::payload(), TTAProgram::Terminal::port(), TTAMachine::Socket::port(), TTAMachine::Socket::portCount(), TPEF::TPEFTools::relocation(), resolveSocketAllocations(), TTAProgram::Instruction::setInstructionTemplate(), TTAMachine::ImmediateUnit::signExtends(), TPEF::ImmediateElement::sLongWord(), TTAMachine::Machine::socketNavigator(), TPEF::MoveElement::sourceIndex(), TPEF::MoveElement::sourceType(), TPEF::MoveElement::sourceUnit(), TTAProgram::TPEFProgramFactory::SocketAllocation::srcSocks, TTAMachine::InstructionTemplate::supportedWidth(), tpefInstrASpace_, and tpefTools_.

Referenced by addProcedures().

◆ createLabels()

void TTAProgram::TPEFProgramFactory::createLabels ( Program prog)
protected

Adds global labels of TPEF to Program.

Parameters
progProgram where to add labels.

prevent addition of local symbol with same name multiple times

prevent addition of local symbol with same name multiple times

Definition at line 2036 of file TPEFProgramFactory.cc.

2036 {
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 =
2148 prog.instructionReferenceManager().createReference(
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}
SectionOffset offset() const
InstructionElement * reference() const
Chunk * reference() const
virtual Word bytesToMAUs(Word byteCount) const
Definition Section.cc:296
@ ST_SYMTAB
Symbol table.
Definition Section.hh:72
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.

References __func__, TTAProgram::Scope::addCodeLabel(), TTAProgram::Scope::addDataLabel(), TPEF::Section::aSpace(), assert, binary_, TPEF::SymbolElement::binding(), TPEF::RawSection::bytesToMAUs(), TPEF::StringSection::chunk2String(), MapTools::containsKey(), TTAProgram::InstructionReferenceManager::createReference(), TPEF::Section::element(), TPEF::Section::elementCount(), findAddressSpace(), TTAProgram::Program::globalScope(), instructionMap_, TTAProgram::Program::instructionReferenceManager(), TPEF::Section::link(), TPEF::SymbolElement::name(), TPEF::Chunk::offset(), TPEF::CodeSymElement::reference(), TPEF::DataSymElement::reference(), TPEF::SymbolElement::section(), TPEF::Binary::section(), TPEF::Binary::sectionCount(), Exception::setCause(), TPEF::Section::ST_SYMTAB, TPEF::Section::startingAddress(), TPEF::SymbolElement::STB_GLOBAL, TPEF::SymbolElement::STT_CODE, TPEF::SymbolElement::STT_DATA, and TPEF::SymbolElement::type().

Referenced by build().

Here is the call graph for this function:

◆ createTerminal()

Terminal * TTAProgram::TPEFProgramFactory::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
protected

Creates a move terminal of the appropriate type for given input data.

This method cannot be used for creating terminal for immediate unit or register file registers.

Parameters
resourcesTPEF resource section.
aBusBus to which terminal is connected.
directionRead or write terminal.
typeTPEF type of terminal.
unitIdTPEF identification code of the unit to which terminal belongs.
indexRegister or operation terminal index, or immediate identifier.
immediateMapAll immediates of currently created instruction.
Returns
A new move terminal.

Definition at line 759 of file TPEFProgramFactory.cc.

762 {
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(
851 ProgramAnnotation(
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}
static void abortProgram() __attribute__((noreturn))
static std::ostream & logStream()
static std::string toString(const T &source)
static int toInt(const T &source)
static KeyType keyForValue(const MapType &aMap, const ValueType &aValue)
@ MF_RF
Register file.
@ MF_UNIT
Function unit.
@ MRT_SR
Special register.
@ MRT_PORT
Function unit port.
@ MRT_OP
Operation operand or function unit register.
@ 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
virtual RFPort * port(const std::string &name) const
int immediateWidth() const
Definition Bus.cc:160
virtual HWOperation * operation(const std::string &name) const
void addAnnotation(const ProgramAnnotation &annotation)
TTAMachine::RegisterFile & findRegisterFile(const TPEF::ResourceSection &resources, HalfWord rfId) const
void addToCache(const CacheKey &key, Terminal *cachedTerm) const
std::pair< Word, Word > ImmediateKey
Terminal * getFromCache(const CacheKey &key) const
TTAMachine::FunctionUnit & findFunctionUnit(const TPEF::ResourceSection &resources, HalfWord unitId, std::string tpefOpName="") const
TTAMachine::Port & findPort(const TTAMachine::Bus &bus, const TTAMachine::Unit &portParent, std::string tpefOpName="", int tpefOpIndex=0) const

References __func__, Application::abortProgram(), abortWithError, TTAProgram::AnnotatedInstructionElement::addAnnotation(), addToCache(), adfInstrASpace_, TPEF::InstructionElement::annotation(), TPEF::InstructionElement::annotationCount(), TPEF::RelocElement::aSpace(), assert, MapTools::containsKey(), TTAProgram::Terminal::copy(), findAddressSpace(), findFunctionUnit(), findImmediateUnit(), findPort(), findRegisterFile(), TPEF::ResourceSection::findResource(), getFromCache(), TPEF::TPEFTools::hasRelocation(), TPEF::ResourceSection::hasResource(), TPEF::InstructionAnnotation::id(), TTAMachine::Bus::immediateWidth(), TPEF::ResourceElement::INLINE_IMM, TPEF::ImmediateElement::isInline(), MapTools::keyForValue(), TPEF::Section::link(), Application::logStream(), TPEF::ImmediateElement::longWord(), TPEF::MoveElement::MF_IMM, TPEF::MoveElement::MF_RF, TPEF::MoveElement::MF_UNIT, TPEF::ResourceElement::MRT_OP, TPEF::ResourceElement::MRT_PORT, TPEF::ResourceElement::MRT_SR, TPEF::ResourceElement::name(), TTAMachine::FunctionUnit::operation(), TPEF::InstructionAnnotation::payload(), TTAMachine::BaseRegisterFile::port(), TPEF::TPEFTools::relocation(), Exception::setCause(), stringOfChunk(), Conversion::toInt(), Conversion::toString(), tpefInstrASpace_, tpefTools_, and TPEF::ImmediateElement::word().

Referenced by createInstruction().

Here is the call graph for this function:

◆ findAddressSpace()

TTAMachine::AddressSpace & TTAProgram::TPEFProgramFactory::findAddressSpace ( const TPEF::ASpaceElement aSpace) const
protected

Finds address space by name.

Parameters
Nameof address space.
Returns
Address space.
Exceptions
NotAvailableif requested address space does not belong to the target architecture.

Definition at line 1333 of file TPEFProgramFactory.cc.

1333 {
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}
Byte MAU() const
std::string addressSpaceName(const ASpaceElement &aSpace) const
Definition TPEFTools.cc:96
virtual TCEString name() const
TTAMachine::AddressSpace & dataAddressSpace() const

References __func__, TPEF::TPEFTools::addressSpaceName(), TTAMachine::Machine::addressSpaceNavigator(), UniversalMachine::dataAddressSpace(), TTAMachine::Machine::Navigator< ComponentType >::hasItem(), UniversalMachine::instructionAddressSpace(), TTAMachine::Machine::Navigator< ComponentType >::item(), machine_, TPEF::ASpaceElement::MAU(), TTAMachine::Component::name(), Conversion::toString(), tpefTools_, and universalMachine_.

Referenced by createDataMemories(), createInstruction(), createLabels(), and createTerminal().

Here is the call graph for this function:

◆ findBus()

Bus & TTAProgram::TPEFProgramFactory::findBus ( const TPEF::ResourceSection resources,
HalfWord  busId 
) const
protected

Returns the bus of real or universal machine with the given bus identification number, as found in TPEF.

Parameters
resourcesThe resource section where the bus should be searched.
busIdId of requested bus.
Returns
Requested bus.
Exceptions
NotAvailableif requested bus does not belong to the target architecture.

Definition at line 972 of file TPEFProgramFactory.cc.

974 {
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}
@ MRT_BUS
Transport bus.
@ UNIVERSAL_BUS
Universal bus.
virtual BusNavigator busNavigator() const
Definition Machine.cc:356
TTAMachine::Bus & universalBus() const

References __func__, assert, TTAMachine::Machine::busNavigator(), TPEF::ResourceSection::findResource(), TTAMachine::Machine::Navigator< ComponentType >::hasItem(), TPEF::ResourceSection::hasResource(), TTAMachine::Machine::Navigator< ComponentType >::item(), TPEF::Section::link(), machine_, TPEF::ResourceElement::MRT_BUS, TPEF::ResourceElement::name(), stringOfChunk(), TPEF::ResourceElement::UNIVERSAL_BUS, UniversalMachine::universalBus(), and universalMachine_.

Referenced by createInstruction(), and findInstrTemplate().

Here is the call graph for this function:

◆ findFunctionUnit()

FunctionUnit & TTAProgram::TPEFProgramFactory::findFunctionUnit ( const TPEF::ResourceSection resources,
HalfWord  unitId,
std::string  tpefOpName = "" 
) const
protected

Returns FunctionUnit by TPEF identification number and operation name.

If function unit ID corresponds to the universal function unit, then operation name is checked to see if we should return universal gcu or universal fu.

If operation name is special register of function unit or if operation name is operation of gcu then universal gcu is returned.

Parameters
resourcesThe resource section where the bus should be searched.
unitIdId of requested unit.
tpefOpNameName of operation or special register for universal machine resources.
Returns
Function unit from real or universal machine.
Exceptions
NotAvailableif requested function unit does not belong to the target architecture.

Definition at line 1143 of file TPEFProgramFactory.cc.

1146 {
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}
static const std::string RETURN_ADDRESS_NAME
Reserved string of return address special register.
@ MRT_UNIT
Function unit.
@ UNIVERSAL_FU
Universal function unit.
virtual bool hasOperation(const std::string &name) const
virtual FunctionUnitNavigator functionUnitNavigator() const
Definition Machine.cc:380
virtual ControlUnit * controlUnit() const
Definition Machine.cc:345
UniversalFunctionUnit & universalFunctionUnit() const

References __func__, abortWithError, assert, TTAMachine::Machine::controlUnit(), TPEF::ResourceSection::findResource(), TTAMachine::Machine::functionUnitNavigator(), TTAMachine::Machine::Navigator< ComponentType >::hasItem(), TTAMachine::FunctionUnit::hasOperation(), TTAMachine::Machine::Navigator< ComponentType >::item(), TPEF::Section::link(), machine_, TPEF::ResourceElement::MRT_UNIT, TTAMachine::Component::name(), TPEF::ResourceElement::name(), TPEF::ResourceElement::RETURN_ADDRESS_NAME, stringOfChunk(), TPEF::ResourceElement::UNIVERSAL_FU, UniversalMachine::universalFunctionUnit(), and universalMachine_.

Referenced by createTerminal(), and findGuard().

Here is the call graph for this function:

◆ findGuard()

TTAMachine::Guard & TTAProgram::TPEFProgramFactory::findGuard ( const TPEF::ResourceSection resources,
TTAMachine::Bus bus,
TPEF::MoveElement::FieldType  type,
HalfWord  unitId,
HalfWord  index,
bool  isInverted 
) const
protected

Finds guard of bus.

Parameters
resourcesTPEF resource section.
busBus of guard.
typeIs fu or register guard.
unitIdId of the unit that contains guard register or port.
indexRegister or operand index of guard.
isInvertedIs inverted guard.

Definition at line 1373 of file TPEFProgramFactory.cc.

1376 {
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}
Guard * guard(int index) const
Definition Bus.cc:456
int guardCount() const
Definition Bus.cc:441
virtual BaseFUPort * port(const std::string &name) const
virtual bool isInverted() const
virtual FUPort * port(int operand) const
FUPort * port() const
const RegisterFile * registerFile() const
virtual bool hasPort(const std::string &name) const
Definition Unit.cc:96

References __func__, abortWithError, assert, findFunctionUnit(), findRegisterFile(), TPEF::ResourceSection::findResource(), TTAMachine::Bus::guard(), TTAMachine::Bus::guardCount(), TTAMachine::Unit::hasPort(), TPEF::ResourceSection::hasResource(), TTAMachine::Guard::isInverted(), TPEF::Section::link(), TPEF::MoveElement::MF_RF, TPEF::MoveElement::MF_UNIT, TPEF::ResourceElement::MRT_OP, TPEF::ResourceElement::MRT_PORT, TPEF::ResourceElement::MRT_SR, TTAMachine::Component::name(), TPEF::ResourceElement::name(), TTAMachine::FunctionUnit::operation(), TTAMachine::PortGuard::port(), TTAMachine::FunctionUnit::port(), TTAMachine::HWOperation::port(), TTAMachine::RegisterGuard::registerFile(), TTAMachine::RegisterGuard::registerIndex(), stringOfChunk(), Conversion::toInt(), and Conversion::toString().

Referenced by createInstruction().

Here is the call graph for this function:

◆ findImmediateUnit()

ImmediateUnit & TTAProgram::TPEFProgramFactory::findImmediateUnit ( const TPEF::ResourceSection resources,
Byte  immUnitId 
) const
protected

Returns ImmediateUnit by TPEF id number.

Parameters
resourcesThe resource section where the bus should be searched.
immUnitIdId of requested immediate unit.
Returns
Immediate unit.
Exceptions
NotAvailableif requested immediate unit does not belong to the target architecture.

Definition at line 1099 of file TPEFProgramFactory.cc.

1101 {
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}
@ MRT_IMM
Immediate unit.
virtual ImmediateUnitNavigator immediateUnitNavigator() const
Definition Machine.cc:416

References __func__, TPEF::ResourceSection::findResource(), TTAMachine::Machine::Navigator< ComponentType >::hasItem(), TTAMachine::Machine::immediateUnitNavigator(), TTAMachine::Machine::Navigator< ComponentType >::item(), TPEF::Section::link(), machine_, TPEF::ResourceElement::MRT_IMM, TPEF::ResourceElement::name(), and stringOfChunk().

Referenced by createInstruction(), createTerminal(), and findInstrTemplate().

Here is the call graph for this function:

◆ findInstrTemplate()

InstructionTemplate & TTAProgram::TPEFProgramFactory::findInstrTemplate ( const TPEF::ResourceSection resources,
ImmediateVector longImmediates,
MoveVector moves 
) const
protected

Returns instruction template that can be used for current instruction.

Parameters
resourcesTPEF resource section.
longImmediatesLong immediates of instruction.
movesMoves of instruction.
Returns
Instruction template that can be used for this instruction.

Definition at line 1502 of file TPEFProgramFactory.cc.

1505 {
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() ?
1531 MathTools::requiredBitsSigned(imm->sLongWord());
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}
#define THROW_EXCEPTION(exceptionType, message)
Exception wrapper macro that automatically includes file name, line number and function name where th...
Definition Exception.hh:39
static int requiredBits(unsigned long int number)
virtual bool usesSlot(const std::string &slotName) const
virtual bool isOneOfDestinations(const ImmediateUnit &dstUnit) const
virtual InstructionTemplateNavigator instructionTemplateNavigator() const
Definition Machine.cc:428

References __func__, assert, TPEF::MoveElement::bus(), MapTools::containsKey(), TTAMachine::Machine::Navigator< ComponentType >::count(), TPEF::ImmediateElement::destinationUnit(), findBus(), findImmediateUnit(), TTAMachine::Machine::instructionTemplateNavigator(), TPEF::MoveElement::isEmpty(), TTAMachine::InstructionTemplate::isOneOfDestinations(), TTAMachine::Machine::Navigator< ComponentType >::item(), TPEF::ImmediateElement::longWord(), machine_, TTAMachine::Component::name(), TTAMachine::InstructionTemplate::numberOfDestinations(), MathTools::requiredBits(), MathTools::requiredBitsSigned(), TPEF::ImmediateElement::sLongWord(), TTAMachine::InstructionTemplate::supportedWidth(), THROW_EXCEPTION, Conversion::toString(), universalMachine_, TTAMachine::InstructionTemplate::usesSlot(), and TTAMachine::ImmediateUnit::zeroExtends().

Referenced by createInstruction().

Here is the call graph for this function:

◆ findPort()

Port & TTAProgram::TPEFProgramFactory::findPort ( const TTAMachine::Bus bus,
const TTAMachine::Unit portParent,
std::string  tpefOpName = "",
int  tpefOpIndex = 0 
) const
protected

Finds any function unit or special register port from target architecture (possiby the universal machine).

NOTE: this is currently used only for plain port references (sr or port without opcode) if TPEFProgramFactory. However method should be able finding also function unit ports.

Parameters
busBus where to socket is connected.
portParentParent to which port in connected to.
tpefOpNameName of operation if opcode port to find.
tpefOpIndexTerminal index of operation if opcode port to find.
Returns
Found port.
Exceptions
NotAvailableif requested port does not belong to the target architecture.

Definition at line 1237 of file TPEFProgramFactory.cc.

1241 {
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}
SpecialRegisterPort * returnAddressPort() const
bool hasReturnAddressPort() const

References __func__, assert, TTAMachine::Machine::controlUnit(), TTAMachine::FunctionUnit::hasOperation(), TTAMachine::Unit::hasPort(), TTAMachine::ControlUnit::hasReturnAddressPort(), machine_, TTAMachine::Component::name(), TTAMachine::FunctionUnit::operation(), TTAMachine::FunctionUnit::port(), TTAMachine::HWOperation::port(), TPEF::ResourceElement::RETURN_ADDRESS_NAME, TTAMachine::ControlUnit::returnAddressPort(), Conversion::toString(), UniversalMachine::universalBus(), and universalMachine_.

Referenced by createTerminal().

Here is the call graph for this function:

◆ findRegisterFile()

RegisterFile & TTAProgram::TPEFProgramFactory::findRegisterFile ( const TPEF::ResourceSection resources,
HalfWord  rfId 
) const
protected

Returns RegisterFile by TPEF id number.

Parameters
resourcesThe resource section where the bus should be searched.
rfIdId of requested register file.
Returns
Register file from real or universal machine.
Exceptions
NotAvailableif requested register file does not belong to the target architecture.

Definition at line 1021 of file TPEFProgramFactory.cc.

1023 {
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}
@ INT_RF
Universal integer register file.
@ ILLEGAL_RF
Illegal register file.
@ BOOL_RF
Universal boolean register file.
@ FP_RF
Universal floating point register file.
virtual RegisterFileNavigator registerFileNavigator() const
Definition Machine.cc:450
TTAMachine::RegisterFile & booleanRegisterFile() const
UnboundedRegisterFile & integerRegisterFile() const
UnboundedRegisterFile & doubleRegisterFile() const

References __func__, abortWithError, TPEF::ResourceElement::BOOL_RF, UniversalMachine::booleanRegisterFile(), UniversalMachine::doubleRegisterFile(), TPEF::ResourceSection::findResource(), TPEF::ResourceElement::FP_RF, TTAMachine::Machine::Navigator< ComponentType >::hasItem(), TPEF::ResourceElement::ILLEGAL_RF, TPEF::ResourceElement::INT_RF, UniversalMachine::integerRegisterFile(), TTAMachine::Machine::Navigator< ComponentType >::item(), TPEF::Section::link(), machine_, TPEF::ResourceElement::MRT_RF, TPEF::ResourceElement::name(), TTAMachine::Machine::registerFileNavigator(), stringOfChunk(), and universalMachine_.

Referenced by createTerminal(), and findGuard().

Here is the call graph for this function:

◆ functionName()

std::string TTAProgram::TPEFProgramFactory::functionName ( const TPEF::InstructionElement instructionElement) const
protected

Returns name of function, that starts, from given instruction element.

Parameters
instructionElementStarting element, of procedure.
Returns
Function name string.

Definition at line 2471 of file TPEFProgramFactory.cc.

2472 {
2473 if (MapTools::containsKey(functionStartPositions_, &instructionElement)) {
2475 functionStartPositions_, &instructionElement)->name();
2476 } else {
2477 return "unknownFunctionName";
2478 }
2479}

References MapTools::containsKey(), functionStartPositions_, and MapTools::keyForValue().

Referenced by addProcedures(), and seekFunctionStartPoints().

Here is the call graph for this function:

◆ getFromCache()

Terminal * TTAProgram::TPEFProgramFactory::getFromCache ( const CacheKey key) const
private

Returns cached terminal.

Parameters
keyCache key of terminal.
Returns
Cached terminal if there is one, NULL otherwise.

Definition at line 1951 of file TPEFProgramFactory.cc.

1952 {
1953
1954 if (MapTools::containsKey(cache_,key)) {
1956 }
1957 return NULL;
1958}

References cache_, MapTools::containsKey(), and MapTools::keyForValue().

Referenced by createTerminal().

Here is the call graph for this function:

◆ isFunctionStart()

bool TTAProgram::TPEFProgramFactory::isFunctionStart ( const TPEF::InstructionElement instructionElement) const
protected

Checks if move is start point of function.

Parameters
instructionElementIntruction element which should be checked.
Returns
True if instruction in parameter is function start point.

Definition at line 2458 of file TPEFProgramFactory.cc.

2459 {
2460 return MapTools::containsKey(
2461 functionStartPositions_, &instructionElement);
2462}

References MapTools::containsKey(), and functionStartPositions_.

Referenced by addProcedures().

Here is the call graph for this function:

◆ resolveSocketAllocations()

void TTAProgram::TPEFProgramFactory::resolveSocketAllocations ( std::vector< SocketAllocation > &  allocs) const
private

Resolves sockets that are used for GPR and Immediate Unit reading and writing for instruction.

NOTE: TPEF specification currently supports storing port information of GPR references, so if this solution does not work or if this is too slow, then register port information should be implemented to TPEF object modell.

Todo:
Yes, we should store the port allocations also to TPEF, if they have been assigned by the scheduler. This kind of resolving again and again does not make sense!
Parameters
allocsAll GPR and IU reads and writes of instruction. One item in this vector represents one move in the instruction.

Definition at line 1711 of file TPEFProgramFactory.cc.

1712 {
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}
virtual std::string name() const
Definition Port.cc:141
bool canDestinationBeAssigned(SocketAllocation &alloc, std::map< TTAMachine::Socket *, std::vector< SocketAllocation * > > &fixedSockets) const
bool canSourceBeAssigned(SocketAllocation &alloc, std::map< TTAMachine::Socket *, std::vector< SocketAllocation * > > &fixedSockets) const

References __func__, canDestinationBeAssigned(), canSourceBeAssigned(), TTAProgram::TPEFProgramFactory::SocketAllocation::dst, TTAProgram::TPEFProgramFactory::SocketAllocation::dstSocks, TTAProgram::TPEFProgramFactory::SocketAllocation::move, TTAMachine::Port::parentUnit(), TTAMachine::Socket::port(), TTAMachine::Socket::portCount(), TTAProgram::TPEFProgramFactory::SocketAllocation::src, and TTAProgram::TPEFProgramFactory::SocketAllocation::srcSocks.

Referenced by createInstruction().

Here is the call graph for this function:

◆ seekFunctionStartPoints()

void TTAProgram::TPEFProgramFactory::seekFunctionStartPoints ( )
protected

Analyses all CodeSection from TPEF and tries to find function start points.

Todo:
This function should do code analysis, but for it actually scans symbol sections for code symbol, which are intepret as function start points.

Definition at line 1991 of file TPEFProgramFactory.cc.

1991 {
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] =
2025 new FunctionStart(functionName);
2026 }
2027 }
2028}

References assert, binary_, MapTools::deleteAllValues(), TPEF::Section::element(), TPEF::Section::elementCount(), functionName(), functionStartPositions_, TPEF::Section::link(), TPEF::SymbolElement::name(), TPEF::CodeSymElement::reference(), TPEF::Binary::section(), TPEF::Binary::sectionCount(), TPEF::Section::ST_SYMTAB, and stringOfChunk().

Referenced by build().

Here is the call graph for this function:

◆ stringOfChunk()

std::string TTAProgram::TPEFProgramFactory::stringOfChunk ( const TPEF::Chunk chunk,
const TPEF::Section chunkOwner 
) const
protected

Returns value of chunk as string.

Helps getting names for various TPEF resources.

Parameters
chunkChunk referring to section.
chunkOwnerStringSection that contains requested string.
Returns
String referred by chunk.

Definition at line 180 of file TPEFProgramFactory.cc.

182 {
183
184 const StringSection* strSect =
185 dynamic_cast<const StringSection*>(chunkOwner);
186 assert(strSect != NULL);
187 return strSect->chunk2String(chunk);
188}

References assert, and TPEF::StringSection::chunk2String().

Referenced by build(), createTerminal(), findBus(), findFunctionUnit(), findGuard(), findImmediateUnit(), findRegisterFile(), and seekFunctionStartPoints().

Here is the call graph for this function:

Member Data Documentation

◆ adfInstrASpace_

TTAMachine::AddressSpace* TTAProgram::TPEFProgramFactory::adfInstrASpace_
private

Instruction address space of machine.

Definition at line 281 of file TPEFProgramFactory.hh.

Referenced by build(), createDataMemories(), createInstruction(), and createTerminal().

◆ allocatedBusses_

std::set<HalfWord> TTAProgram::TPEFProgramFactory::allocatedBusses_
mutableprivate

Busses that are already allocated by moves of current instruction.

Definition at line 300 of file TPEFProgramFactory.hh.

◆ binary_

const TPEF::Binary* TTAProgram::TPEFProgramFactory::binary_
private

Binary that is used for creating program.

Definition at line 272 of file TPEFProgramFactory.hh.

Referenced by addProcedures(), build(), createDataMemories(), createLabels(), and seekFunctionStartPoints().

◆ cache_

std::map<const CacheKey, Terminal *> TTAProgram::TPEFProgramFactory::cache_
mutableprivate

Cache map of terminals that are returned by different search parameters.

Definition at line 297 of file TPEFProgramFactory.hh.

Referenced by addToCache(), clearCache(), and getFromCache().

◆ functionStartPositions_

std::map<const TPEF::InstructionElement*, class FunctionStart*> TTAProgram::TPEFProgramFactory::functionStartPositions_
private

Stores information of start points of procedures that were found.

Definition at line 287 of file TPEFProgramFactory.hh.

Referenced by functionName(), isFunctionStart(), seekFunctionStartPoints(), and ~TPEFProgramFactory().

◆ instructionImmediates_

std::list<std::shared_ptr<Move> > TTAProgram::TPEFProgramFactory::instructionImmediates_
mutableprivate

Moves whose source terminals are addresses referring to instructions.

Definition at line 290 of file TPEFProgramFactory.hh.

Referenced by build(), and createInstruction().

◆ instructionMap_

std::map<TPEF::InstructionElement*, Instruction*> TTAProgram::TPEFProgramFactory::instructionMap_
mutableprivate

Program instruction by TPEF instruction element.

Definition at line 303 of file TPEFProgramFactory.hh.

Referenced by addProcedures(), createDataMemories(), and createLabels().

◆ longInstructionImmediates_

std::list<std::shared_ptr<Immediate> > TTAProgram::TPEFProgramFactory::longInstructionImmediates_
mutableprivate

Long immediates whose value terminals refers to instructions.

Definition at line 293 of file TPEFProgramFactory.hh.

Referenced by build(), and createInstruction().

◆ machine_

const TTAMachine::Machine* TTAProgram::TPEFProgramFactory::machine_
private

◆ tpefInstrASpace_

TPEF::ASpaceElement* TTAProgram::TPEFProgramFactory::tpefInstrASpace_
private

Instruction address space element of TPEF.

Definition at line 283 of file TPEFProgramFactory.hh.

Referenced by build(), createInstruction(), and createTerminal().

◆ tpefTools_

TPEF::TPEFTools TTAProgram::TPEFProgramFactory::tpefTools_
private

TPEFTools object for helper functions.

Definition at line 279 of file TPEFProgramFactory.hh.

Referenced by createInstruction(), createTerminal(), and findAddressSpace().

◆ universalMachine_

UniversalMachine* TTAProgram::TPEFProgramFactory::universalMachine_
private

Universal machine of program.

Definition at line 276 of file TPEFProgramFactory.hh.

Referenced by build(), findAddressSpace(), findBus(), findFunctionUnit(), findInstrTemplate(), findPort(), and findRegisterFile().


The documentation for this class was generated from the following files: