OpenASIP  2.0
Classes | Public Member Functions | Protected Member Functions | Private Types | Private Member Functions | Private Attributes | List of all members
ExecutionPipelineResource Class Reference

#include <ExecutionPipelineResource.hh>

Inheritance diagram for ExecutionPipelineResource:
Inheritance graph
Collaboration diagram for ExecutionPipelineResource:
Collaboration graph

Classes

struct  OperandUseHelper
 
struct  ResultHelper
 

Public Member Functions

 ExecutionPipelineResource (const TTAMachine::FunctionUnit &fu, const unsigned int ii=0)
 
virtual ~ExecutionPipelineResource ()
 
virtual bool isInUse (const int cycle) const override
 
virtual bool isAvailable (const int cycle) const override
 
virtual bool canAssign (const int cycle, const MoveNode &node) const override
 
virtual bool canAssignSource (int cycle, const MoveNode &node, const TTAMachine::Port &resultPort) const
 
virtual bool canAssignDestination (const int cycle, const MoveNode &node, const bool triggering=false) const
 
virtual void assign (const int cycle, MoveNode &node) override
 
virtual void assignSource (int cycle, MoveNode &node)
 
virtual void assignDestination (const int cycle, MoveNode &node)
 
virtual void unassign (const int cycle, MoveNode &node) override
 
virtual void unassignSource (const int cycle, MoveNode &node)
 
virtual void unassignDestination (const int cycle, MoveNode &node)
 
virtual bool isExecutionPipelineResource () const override
 
int highestKnownCycle () const
 
int nextResultCycle (const TTAMachine::Port &port, int cycle, const MoveNode &node, const MoveNode *trigger=NULL, int triggerCycle=INT_MAX) const
 
bool otherTriggerBeforeMyTrigger (const TTAMachine::Port &port, const MoveNode &node, int cycle) const
 
bool resultNotOverWritten (int resultReadCycle, int resultReadyCycle, const MoveNode &node, const TTAMachine::Port &port, const MoveNode *trigger, int triggerCycle) const
 
bool hasConflictingResultsOnCycle (const ProgramOperation &po, const TTAMachine::Port &port, int cycle) const
 
bool operandsOverwritten (int triggerCycle, const MoveNode &trigger) const
 
void clear () override
 
void setDDG (const DataDependenceGraph *ddg)
 
virtual void setMaxCycle (unsigned int maxCycle) override
 
- Public Member Functions inherited from SchedulingResource
virtual ~SchedulingResource ()
 
 SchedulingResource (const std::string &name, const unsigned int ii=0)
 
virtual int relatedResourceGroupCount () const
 
virtual int dependentResourceGroupCount () const
 
int relatedResourceCount (const int group) const
 
int dependentResourceCount (const int group) const
 
virtual void addToRelatedGroup (const int group, SchedulingResource &resource)
 
virtual void addToDependentGroup (const int group, SchedulingResource &resource)
 
virtual SchedulingResourcerelatedResource (const int group, const int index) const
 
virtual SchedulingResourcedependentResource (const int group, const int index) const
 
virtual bool hasRelatedResource (const SchedulingResource &sResource) const
 
virtual bool hasDependentResource (const SchedulingResource &sResource) const
 
virtual const std::string & name () const
 
virtual int useCount () const
 
virtual void increaseUseCount ()
 
virtual void decreaseUseCount ()
 
virtual bool isInputPSocketResource () const
 
virtual bool isOutputPSocketResource () const
 
virtual bool isShortImmPSocketResource () const
 
virtual bool isInputFUResource () const
 
virtual bool isOutputFUResource () const
 
virtual bool isBusResource () const
 
virtual bool isSegmentResource () const
 
virtual bool isIUResource () const
 
virtual bool isITemplateResource () const
 
int instructionIndex (int cycle) const
 
void setInitiationInterval (unsigned int ii)
 
int initiationInterval () const
 
virtual bool operator< (const SchedulingResource &other) const
 

Protected Member Functions

virtual bool validateDependentGroups () override
 
virtual bool validateRelatedGroups () override
 
unsigned int size () const
 

Private Types

typedef std::pair< ResultHelper, ResultHelperResultHelperPair
 
typedef std::pair< OperandUseHelper, OperandUseHelperOperandUsePair
 
typedef std::pair< const MoveNode *, const MoveNode * > ResourceReservation
 
typedef std::vector< ResourceReservationResourceReservationVector
 Type for resource vector, represents one cycle of use. Includes the ownerships of the reservation. More...
 
typedef SparseVector< ResultHelperPairResultVector
 Used for both result read and result written. More...
 
typedef std::map< const TTAMachine::Port *, ResultVectorResultMap
 
typedef std::pair< MoveNode *, MoveNode * > MoveNodePtrPair
 
typedef SparseVector< MoveNodePtrPairOperandWriteVector
 
typedef SparseVector< OperandUsePairOperandUseVector
 
typedef std::map< const TTAMachine::Port *, OperandUseVectorOperandUseMap
 
typedef std::map< const TTAMachine::Port *, OperandWriteVectorOperandWriteMap
 
typedef SparseVector< ResourceReservationVectorResourceReservationTable
 Type for resource reservation table, resource vector x latency. Includes the ownerships of the reservation. More...
 

Private Member Functions

bool cyclesOverlap (int rangeFirst, int rangeLast, int targetCycle) const
 
bool cyclesConflict (const MoveNode *mn1, const MoveNode *mn2, int guardCycle, int rangeFirst, int rangeLast, int targetCycle) const
 
bool isLoopBypass (const MoveNode &node) const
 
 ExecutionPipelineResource (const ExecutionPipelineResource &)
 
ExecutionPipelineResourceoperator= (const ExecutionPipelineResource &)
 
void findRange (const int cycle, const MoveNode &node, int popIndex, int &first, int &last, int &triggering) const
 Find first and last cycles already scheduled for same PO. More...
 
int resultReadyCycle (const ProgramOperation &po, const TTAMachine::Port &resultPort) const
 
void setResultWriten (const TTAMachine::Port &port, unsigned int realCycle, const ProgramOperation &po)
 
void setResultWriten (const ProgramOperation &po, unsigned int triggerCycle)
 
void unsetResultWriten (const TTAMachine::Port &port, unsigned int realCycle, const ProgramOperation &po)
 
void unsetResultWriten (const ProgramOperation &po, unsigned int triggerCycle)
 
void setOperandUsed (const TTAMachine::Port &port, unsigned int realCycle, const ProgramOperation &po)
 
void setOperandsUsed (const ProgramOperation &po, unsigned int triggerCycle)
 
void unsetOperandUsed (const TTAMachine::Port &port, unsigned int realCycle, const ProgramOperation &po)
 
void unsetOperandsUsed (const ProgramOperation &po, unsigned int triggerCycle)
 
const TTAMachine::PortoperandPort (const MoveNode &mn) const
 
bool operandOverwritten (int operandWriteCycle, int triggerCycle, const ProgramOperation &po, const MoveNode &operand, const MoveNode &trigger) const
 
bool operandOverwritten (const MoveNode &mn, int cycle) const
 
bool testTriggerResult (const MoveNode &trigger, int cycle) const
 
bool resultAllowedAtCycle (int resultCycle, const ProgramOperation &po, const TTAMachine::Port &resultPort, const MoveNode &trigger, int triggerCycle) const
 
bool resourcesAllowTrigger (int cycle, const MoveNode &move) const
 
bool operandPossibleAtCycle (const TTAMachine::Port &port, const MoveNode &mn, int cycle) const
 
bool operandAllowedAtCycle (const TTAMachine::Port &port, const MoveNode &mn, int cycle) const
 
bool checkOperandAllowed (const MoveNode &currentMn, const TTAMachine::Port &port, int operandWriteCycle, const OperandUseHelper &operandUse, int operandUseModCycle, ProgramOperation &currOp) const
 
bool triggerTooEarly (const MoveNode &trigger, int cycle) const
 
bool operandTooLate (const MoveNode &node, int cycle) const
 
bool triggerAllowedAtCycle (int inputCount, const TTAMachine::HWOperation &hwop, const MoveNode &node, int cycle) const
 
bool operandSharePreventsTriggerForScheduledResult (const TTAMachine::Port &port, const MoveNode &mn, int cycle) const
 
bool resultCausesTriggerBetweenOperandSharing (const MoveNode &mn, int cycle) const
 
const MoveNodenodeOfInputPort (const ProgramOperation &po, TTAMachine::Port &port)
 
bool poConflictsWithInputPort (const TTAMachine::Port &port, const ProgramOperation &po, const MoveNode &mn) const
 
const TTAMachine::PortresultPort (const MoveNode &mn) const
 
bool exclusiveMoves (const MoveNode *mn1, const MoveNode *mn2, int cycle=INT_MAX) const
 
int latestTriggerWriteCycle (const MoveNode &mn) const
 
bool isDestOpOfMN (const MoveNode &mn, const ProgramOperation &po) const
 

Private Attributes

const ExecutionPipelineResourceTableresources
 
ResourceReservationTable fuExecutionPipeline_
 Stores one resource vector per cycle of scope for whole FU. More...
 
OperandWriteMap operandsWriten_
 
OperandUseMap operandsUsed_
 
ResultMap resultWriten_
 
ResultMap resultRead_
 
std::map< MoveNode *, int, MoveNode::ComparatorstoredResultCycles_
 
std::multimap< int, MoveNode * > assignedSourceNodes_
 
std::multimap< int, MoveNode * > assignedDestinationNodes_
 
int cachedSize_
 
int maxCycle_
 
const DataDependenceGraphddg_
 
const TTAMachine::FunctionUnitfu_
 
const TTAMachine::PorttriggerPort_
 
int operandShareCount_
 

Additional Inherited Members

- Protected Attributes inherited from SchedulingResource
int initiationInterval_
 

Detailed Description

ExecutionPipelineResource keeps book of pipeline resource reservation status. It uses rather simple resource reservation table approach.

Definition at line 64 of file ExecutionPipelineResource.hh.

Member Typedef Documentation

◆ MoveNodePtrPair

Definition at line 164 of file ExecutionPipelineResource.hh.

◆ OperandUseMap

Definition at line 169 of file ExecutionPipelineResource.hh.

◆ OperandUsePair

Definition at line 149 of file ExecutionPipelineResource.hh.

◆ OperandUseVector

Definition at line 167 of file ExecutionPipelineResource.hh.

◆ OperandWriteMap

Definition at line 171 of file ExecutionPipelineResource.hh.

◆ OperandWriteVector

Definition at line 166 of file ExecutionPipelineResource.hh.

◆ ResourceReservation

typedef std::pair<const MoveNode*,const MoveNode*> ExecutionPipelineResource::ResourceReservation
private

Definition at line 151 of file ExecutionPipelineResource.hh.

◆ ResourceReservationTable

Type for resource reservation table, resource vector x latency. Includes the ownerships of the reservation.

Definition at line 175 of file ExecutionPipelineResource.hh.

◆ ResourceReservationVector

Type for resource vector, represents one cycle of use. Includes the ownerships of the reservation.

Definition at line 157 of file ExecutionPipelineResource.hh.

◆ ResultHelperPair

Definition at line 148 of file ExecutionPipelineResource.hh.

◆ ResultMap

Definition at line 162 of file ExecutionPipelineResource.hh.

◆ ResultVector

Used for both result read and result written.

Definition at line 160 of file ExecutionPipelineResource.hh.

Constructor & Destructor Documentation

◆ ExecutionPipelineResource() [1/2]

ExecutionPipelineResource::ExecutionPipelineResource ( const TTAMachine::FunctionUnit fu,
const unsigned int  ii = 0 
)

Constructor.

Creates new resource with defined name

Parameters
nameName of resource
resNumNumber of resources in FU
maxLatencyLatency of longest operation FU supports

Definition at line 82 of file ExecutionPipelineResource.cc.

84  :
85  SchedulingResource("ep_" + fu.name(), ii),
87  cachedSize_(INT_MIN), maxCycle_(INT_MAX), ddg_(NULL), fu_(fu),
89 }

◆ ~ExecutionPipelineResource()

ExecutionPipelineResource::~ExecutionPipelineResource ( )
virtual

Empty destructor

Definition at line 94 of file ExecutionPipelineResource.cc.

94 {}

◆ ExecutionPipelineResource() [2/2]

ExecutionPipelineResource::ExecutionPipelineResource ( const ExecutionPipelineResource )
private

Member Function Documentation

◆ assign()

void ExecutionPipelineResource::assign ( const int  cycle,
MoveNode node 
)
overridevirtual

Implements SchedulingResource.

Definition at line 392 of file ExecutionPipelineResource.cc.

392  {
393  abortWithError("Execution Pipeline Resource needs 3 arguments assign");
394 }

References abortWithError.

◆ assignDestination()

void ExecutionPipelineResource::assignDestination ( const int  cycle,
MoveNode node 
)
virtual

Assign resource to given node for given cycle.

Parameters
cycleCycle to assign
nodeMoveNode assigned in case move is bypassed

Definition at line 487 of file ExecutionPipelineResource.cc.

489  {
490  cachedSize_ = INT_MIN;
491 
492 #ifdef DEBUG_RM
493  std::cerr << "\t\t\tAssigning destination: " << node.toString() << std::endl;
494 #endif
495  if (!node.isDestinationOperation()) {
496  return;
497  }
498 
499  assignedDestinationNodes_.insert(std::pair<int, MoveNode*>(cycle, &node));
500 
501  int modCycle = instructionIndex(cycle);
502 
503  std::string opName = "";
504 
505  //TODO: is this correct trigger or UM trigger?
506  if (node.move().destination().isTriggering()) {
507 #ifdef DEBUG_RM
508  std::cerr << "\t\t\t\tis trigger!" << std::endl;
509 #endif
510  assert(node.destinationOperationCount() == 1);
511 
513  if (node.move().destination().isOpcodeSetting()) {
514  opName = node.move().destination().operation().name();
515  } else {
516  std::string msg = "Using non opcodeSetting triggering move. ";
517  msg += " Move: " + node.toString();
518  throw ModuleRunTimeError(__FILE__, __LINE__, __func__, msg);
519  }
520  int pIndex = resources->operationIndex(opName);
521  for (unsigned int i = 0; i < resources->maximalLatency(); i++) {
522  int modic = instructionIndex(cycle+i);
523  // then we can insert the resource usage.
524  for (unsigned int j = 0 ;
525  j < resources->numberOfResources(); j++) {
526  if (fuExecutionPipeline_[modic].size()
527  == 0) {
528  fuExecutionPipeline_[modic] =
531  }
532  ResourceReservation& rr =
533  fuExecutionPipeline_[modic][j];
534  if (resources->operationPipeline(pIndex,i,j)) {
535  if (rr.first != NULL) {
536  assert(rr.second == NULL&&"Resource already in use?");
537  rr.second = &node;
538  } else { // rr.first == NULL
539  rr.first = &node;
540  }
541  }
542  }
543  }
544  setResultWriten(pOp, cycle);
545  setOperandsUsed(pOp, cycle);
546  } else {
547  if (node.destinationOperationCount() > 1) {
549  }
550  }
551 
552  const TTAMachine::Port& opPort = operandPort(node);
553  MoveNodePtrPair& mnpp = operandsWriten_[&opPort][modCycle];
554  if (mnpp.first == NULL) {
555  mnpp.first = &node;
556  } else {
557  if (mnpp.second != NULL || !exclusiveMoves(mnpp.first, &node, cycle)) {
558  std::string msg = name() + " had previous operation ";
559  msg += mnpp.first->destinationOperation().toString() + "\n ";
560  msg += mnpp.first->toString() + " in inst.index " ;
561  msg += Conversion::toString(modCycle);
562  msg += " other trigger: ";
563  msg += mnpp.first->toString();
564  msg += " Node: " + node.toString();
565  msg += "\nThis op: " + node.destinationOperation().toString();
566  msg += "\n";
567 
568  if (node.isDestinationOperation()) {
569  msg += node.destinationOperation().toString();
570  }
571  throw InvalidData(__FILE__, __LINE__, __func__, msg);
572  } else {
573 
574  // Marks all the cycles in range with PO
575  // which is writing operands
576  mnpp.second = &node;
577  }
578  }
579 }

References __func__, assert, assignedDestinationNodes_, cachedSize_, TTAProgram::Move::destination(), MoveNode::destinationOperation(), MoveNode::destinationOperationCount(), exclusiveMoves(), fuExecutionPipeline_, SchedulingResource::instructionIndex(), MoveNode::isDestinationOperation(), TTAProgram::Terminal::isOpcodeSetting(), TTAProgram::Terminal::isTriggering(), ExecutionPipelineResourceTable::maximalLatency(), MoveNode::move(), SchedulingResource::name(), Operation::name(), ExecutionPipelineResourceTable::numberOfResources(), operandPort(), operandShareCount_, operandsWriten_, TTAProgram::Terminal::operation(), ExecutionPipelineResourceTable::operationIndex(), ExecutionPipelineResourceTable::operationPipeline(), resources, setOperandsUsed(), setResultWriten(), size(), Conversion::toString(), MoveNode::toString(), and ProgramOperation::toString().

Referenced by InputFUResource::assign().

Here is the call graph for this function:

◆ assignSource()

void ExecutionPipelineResource::assignSource ( int  cycle,
MoveNode node 
)
virtual

Assign resource to given node for given cycle.

Parameters
cycleCycle to assign
nodeMoveNode assigned
sourceIndicates if we want to unassing source part of move in case move is bypassed

Assiging result read

Record Program Operation in cycle where the "result read" is scheduled

Definition at line 405 of file ExecutionPipelineResource.cc.

407  {
408  unsigned int modCycle = instructionIndex(cycle);
409  cachedSize_ = INT_MIN;
410 
411  unsigned int ii = initiationInterval_;
412  if (initiationInterval_ && isLoopBypass(node)) {
413  cycle += ii;
414  }
415 
416  if (ii < 1) {
417  ii = INT_MAX;
418  }
419 
420  const TTAMachine::Port& port = resultPort(node);
421  ResultVector& resultRead = resultRead_[&port];
422 
423  /// Assiging result read
424  assignedSourceNodes_.insert(std::pair<int, MoveNode*>(cycle, &node));
425 
426  ProgramOperation* pOp = node.isSourceOperation() ?
427  &node.sourceOperation() :
428  &node.guardOperation();
429 
430  /// Record Program Operation in cycle where the "result read"
431  /// is scheduled
432  unsigned int readCount = resultRead.size();
433  if (readCount <= modCycle) {
434  resultRead[modCycle] =
436  ResultHelper(modCycle, NULL, 0),
437  ResultHelper(modCycle, NULL, 0));
438 #if 0
439  for (unsigned int i = readCount; i <= modCycle; i++) {
440  // Increase the size of the vector
441  resultRead.push_back(
443  ResultHelper(i, NULL, 0),
444  ResultHelper(i, NULL, 0)));
445  }
446 #endif
447  }
448  // Record PO in cycle where result is read from output,
449  // increase number of results read if same PO already reads something
450  // in that cycle
451  ResultHelperPair& rhp = resultRead[modCycle];
452  if (rhp.first.po == NULL) {
453  rhp.first = ResultHelper(cycle, pOp, 1);
454  } else {
455  if (rhp.first.po == pOp) {
456  rhp.first.count++;
457  } else {
458  if (rhp.second.po == NULL) {
459  rhp.second = ResultHelper(cycle, pOp, 1);
460  } else {
461  if (rhp.second.po == pOp) {
462  rhp.second.count++;
463  } else {
464  assert(0 && "result read of invalid op");
465  }
466  }
467  }
468  }
469 
470  // Record PO in cycle where result is available in result register.
471  setResultWriten(port, cycle, *pOp);
472 
473  // Record move and cycle in which the result of it is produced
474  // This uses real cycles, not modulo cycles
475  storedResultCycles_.insert(
476  std::pair<MoveNode*, int>(&node,cycle));
477 }

References assert, assignedSourceNodes_, cachedSize_, MoveNode::guardOperation(), SchedulingResource::initiationInterval_, SchedulingResource::instructionIndex(), isLoopBypass(), MoveNode::isSourceOperation(), resultPort(), resultRead_, setResultWriten(), SparseVector< ValueType >::size(), MoveNode::sourceOperation(), and storedResultCycles_.

Referenced by OutputFUResource::assign().

Here is the call graph for this function:

◆ canAssign()

bool ExecutionPipelineResource::canAssign ( const int  cycle,
const MoveNode node 
) const
overridevirtual

Not to be used. ExecutionPipelineResource needs to be tested also with PSocket parameter to find if the desired part of MoveNode is source or destination from type of PSocket.

Implements SchedulingResource.

Definition at line 102 of file ExecutionPipelineResource.cc.

102  {
103  abortWithError("Wrong use of canAssign, use also third parameter!");
104  return false;
105 }

References abortWithError.

Referenced by resourcesAllowTrigger().

◆ canAssignDestination()

bool ExecutionPipelineResource::canAssignDestination ( const int  cycle,
const MoveNode node,
const bool  triggering = false 
) const
virtual

Return true if resource can be assigned for given node in given cycle.

Parameters
cycleCycle to test
nodeMoveNode to test
pSocketSocket which was assigned to move by previous broker
triggersIndicates if move is triggering
Returns
true if node can be assigned to cycle

Definition at line 990 of file ExecutionPipelineResource.cc.

993  {
994 
995  if (!node.isDestinationOperation()) {
996  return true;
997  }
998 
999 #ifdef DEBUG_RM
1000  std::cerr << "\t\t\tCanAssignDestination called for: " << node.toString()
1001  << " Cycle: " << cycle << " PO: "
1002  << node.destinationOperation().toString() << std::endl;
1003  if (triggers) {
1004  std::cerr << "\t\t\t\tTriggers." << std::endl;
1005  }
1006 #endif
1007  unsigned int ii = initiationInterval_;
1008  if (ii < 1) {
1009  ii = INT_MAX;
1010  }
1011 
1012  // then handle operation inputs.
1013 
1014  MoveNode* newNode = const_cast<MoveNode*>(&node);
1015  ProgramOperation* pOp = NULL;
1016  try {
1017  pOp = &newNode->destinationOperation();
1018  } catch (const InvalidData& e) {
1020  }
1021 
1022  const TTAMachine::HWOperation& hwop =
1023  *fu_.operation(pOp->operation().name());
1024  TTAMachine::FUPort& port =
1025  *hwop.port(newNode->move().destination().operationIndex());
1026 
1027  if (!operandPossibleAtCycle(port, node, cycle)) {
1028  return false;
1029  }
1030 
1031  if (!operandAllowedAtCycle(port, node, cycle)) {
1032  return false;
1033  }
1034 
1035  if (otherTriggerBeforeMyTrigger(port, node, cycle)) {
1036  return false;
1037  }
1038 
1039  if (operandOverwritten(node, cycle)) {
1040  return false;
1041  }
1042 
1043  if (!triggers) {
1044  if (operandTooLate(node, cycle)) {
1045 #ifdef DEBUG_RM
1046  std::cerr << "\t\tOperand too late" << std::endl;
1047 #endif
1048  return false;
1049  }
1050 
1051  if (operandSharePreventsTriggerForScheduledResult(port, node, cycle)) {
1052  return false;
1053  }
1054  return true;
1055  }
1056 
1057  if (triggerTooEarly(node, cycle)) {
1058 #ifdef DEBUG_RM
1059  std::cerr << "\t\tTrigger too early" << std::endl;
1060 #endif
1061 
1062  return false;
1063  }
1064 
1065 #ifdef DEBUG_RM
1066  std::cerr << "\t\t\t\tCanAssignDestination is trigger: "
1067  << node.toString() << " Cycle: " << cycle << std::endl;
1068 #endif
1069 
1070  // Too late to schedule trigger, results would not be ready in time.
1071  if (cycle > latestTriggerWriteCycle(node)) {
1072 #ifdef DEBUG_RM
1073  std::cerr << "\t\t\t\t\tTrigger too late for results" << std::endl;
1074 #endif
1075  return false;
1076  }
1077 
1078  // now we know we have a trigger.
1079  if (operandsOverwritten(cycle, node)) {
1080 #ifdef DEBUG_RM
1081  std::cerr << "\t\t\t\tOperands overwritten" << std::endl;
1082 #endif
1083 
1084  return false;
1085  }
1086 
1087  if (!resourcesAllowTrigger(cycle, node)) {
1088 #ifdef DEBUG_RM
1089  std::cerr << "\t\t\t\tResources prevent trigger" << std::endl;
1090 #endif
1091 
1092  return false;
1093  }
1094 
1095  if (!triggerAllowedAtCycle(
1096  pOp->operation().numberOfInputs(), hwop, node, cycle)) {
1097  return false;
1098  }
1099  // TODO: if ports have no regs..
1100 
1101  // Test for result read WaW already when scheduling trigger.
1102  return testTriggerResult(node, cycle);
1103 }

References abortWithError, TTAProgram::Move::destination(), MoveNode::destinationOperation(), Exception::errorMessage(), fu_, SchedulingResource::initiationInterval_, MoveNode::isDestinationOperation(), latestTriggerWriteCycle(), MoveNode::move(), Operation::name(), Operation::numberOfInputs(), operandAllowedAtCycle(), operandOverwritten(), operandPossibleAtCycle(), operandSharePreventsTriggerForScheduledResult(), operandsOverwritten(), operandTooLate(), TTAMachine::FunctionUnit::operation(), ProgramOperation::operation(), TTAProgram::Terminal::operationIndex(), otherTriggerBeforeMyTrigger(), TTAMachine::HWOperation::port(), resourcesAllowTrigger(), testTriggerResult(), MoveNode::toString(), ProgramOperation::toString(), triggerAllowedAtCycle(), and triggerTooEarly().

Referenced by InputFUResource::canAssign().

Here is the call graph for this function:

◆ canAssignSource()

bool ExecutionPipelineResource::canAssignSource ( int  cycle,
const MoveNode node,
const TTAMachine::Port resultPort 
) const
virtual

Return true if resource can be assigned for given node in given cycle.

Parameters
cycleCycle to test
nodeMoveNode to test
pSocketSocket which was assigned to move by previous broker
triggersIndicates if move is triggering
Returns
true if node can be assigned to cycle

Testing the result read move Find the cycle first of the possible results of PO will be produced

Check if the port has a register. If not result read must be in same cycle as result ready.

Definition at line 819 of file ExecutionPipelineResource.cc.

822  {
823 
824  if (initiationInterval_ != 0 && isLoopBypass(node)) {
825  cycle+=initiationInterval_;
826  }
827 
828 #ifdef DEBUG_RM
829  std::cerr << "\t\t\tcanAssignSource called for: " << node.toString() << " on cycle: "
830  << cycle << std::endl;
831 #endif
832  int outputIndex = -1;
833  ProgramOperation* po = nullptr;
834 
835  if (node.isSourceOperation()) {
836  po = &node.sourceOperation();
837  outputIndex = node.move().source().operationIndex();
838  } else {
839  assert(node.isGuardOperation());
840  po = &node.guardOperation();
841  outputIndex = po->outputIndexFromGuardOfMove(node);
842  }
843 
844  const TTAMachine::HWOperation& hwop =
845  *fu_.operation(po->operation().name());
846 
847  if (initiationInterval_ != 0 &&
848  hwop.latency(outputIndex) > (int)initiationInterval_) {
849 #ifdef DEBUG_RM
850  std::cerr << "too long latency overlappingloop" << std::endl;
851 #endif
852  return false;
853  }
854 
855  /// Testing the result read move
856  /// Find the cycle first of the possible results of PO will be produced
857  int resultReady = node.earliestResultReadCycle();
858 
859  /// Check if the port has a register. If not result read must be
860  /// in same cycle as result ready.
861  const TTAMachine::FUPort& port = *hwop.port(outputIndex);
862  if (resultReady != INT_MAX) {
863  if (port.noRegister() && resultReady != cycle) {
864  return false;
865  }
866 
867  if (cycle < resultReady) {
868  // resultReady is INT_MAX if trigger was not scheduled yet
869  // also tested cycle can not be before result is in output
870  // register
871 #ifdef DEBUG_RM
872  std::cerr << "\tresult not yet ready" << std::endl;
873 #endif
874  return false;
875  }
876 
877  const MoveNode* trigger = po->triggeringMove();
878  int triggerCycle = (trigger != NULL && trigger->isPlaced()) ?
879  trigger->cycle() : -1;
880  return resultNotOverWritten(
881  cycle, resultReady, node, resultPort,
882  trigger, triggerCycle) &&
884  resultReady, *po, resultPort, *trigger, triggerCycle);
885  } else {
886  // trigger not yet scheduled, do not know when result ready
887  if (hasConflictingResultsOnCycle(*po, resultPort, cycle)) {
888 #ifdef DEBUG_RM
889  std::cerr << "Other op writing result at same cycle, this is illgal" << std::endl;
890 #endif
891  return false;
892  }
893 
894  // limit result cycle to latency of operation, so that
895  // trigger does nto have to be scheduled to negative cycle.
896  // find the OSAL id of the operand of the output we are reading
897  // ignore this for guard ops due to the thread switch kludge.
898  if (hwop.latency(outputIndex) > cycle && node.isSourceOperation()) {
899 #ifdef DEBUG_RM
900  std::cerr << "\t\t\t\t\ttrigger needs negative cycle" << std::endl;
901 #endif
902  return false;
903  }
904 
905  // If some another result read of this op is scheduled,
906  // take the trigger cycle from that and call resultNotOverWritten?
907 
908  MoveNodeSet& allResults = po->outputNode(outputIndex);
909  if (allResults.count() >1) {
910 #ifdef DEBUG_RM
911  std::cerr << "\t\t\t\tSame op has multiple results." << std::endl;
912 #endif
913  const MoveNode* trigger = NULL;
914  for (int i = 0; i < allResults.count(); i++) {
915  MoveNode& res = allResults.at(i);
916  if (&res == &node || !res.isPlaced()) {
917  continue;
918  }
919  int resCycle = res.cycle();
920  if (initiationInterval_ && isLoopBypass(res)) {
921  resCycle += initiationInterval_;
922  }
923  resultReady = std::min(resultReady, resCycle);
924 #ifdef DEBUG_RM
925  std::cerr << "\t\t\t\t\tother result, of node: "
926  << res.toString()
927  <<" used at cycle: " << resCycle << std::endl;
928 #endif
929  if (trigger == NULL) {
930  trigger = po->triggeringMove();
931  }
932  if (cycle < resCycle && !resultNotOverWritten(
933  resCycle, cycle, node, resultPort, trigger,-1)) {
934  return false;
935  }
936  }
937  if (resultReady != INT_MAX && resultReady < cycle) {
938 #ifdef DEBUG_RM
939  std::cerr << "\t\t\t\tChecking if res not overwritten."
940  << std::endl;
941 #endif
943  cycle, resultReady, node, resultPort, trigger, -1)) {
944  return false;
945  }
946 #ifdef DEBUG_RM
947  std::cerr << "\t\t\t\tres not overwritten." << std::endl;
948 #endif
949  }
950  }
951 
952  const MoveNode* trigger = po->triggeringMove();
953  int triggerCycle = (trigger != NULL && trigger->isPlaced()) ?
954  trigger->cycle() : -1;
955 
956  // We need to test if the write in given cycle is possible
957  // even if we do not yet have trigger scheduled and
958  // node.earliestResultReadCycle() returns INT_MAX.
959  // This allows for comparison of result moves in Bottom-Up schedule
960 
961 #ifdef DEBUG_RM
962  std::cerr << "\t\t\t\tcheck if result allowed at this cycle?" << std::endl;
963 #endif
965  cycle, *po, resultPort, *trigger, triggerCycle)) {
966  return false;
967  }
968 
969 #ifdef DEBUG_RM
970  std::cerr << "\t\t\t\tcheck if result causes trigger between opshares?" << std::endl;
971 #endif
972 
973  if (resultCausesTriggerBetweenOperandSharing(node, cycle)) {
974  return false;
975  }
976  }
977  return true;
978 }

References assert, MoveNodeSet::at(), MoveNodeSet::count(), MoveNode::cycle(), MoveNode::earliestResultReadCycle(), fu_, MoveNode::guardOperation(), hasConflictingResultsOnCycle(), SchedulingResource::initiationInterval_, MoveNode::isGuardOperation(), isLoopBypass(), MoveNode::isPlaced(), MoveNode::isSourceOperation(), TTAMachine::HWOperation::latency(), MoveNode::move(), Operation::name(), TTAMachine::FUPort::noRegister(), TTAMachine::FunctionUnit::operation(), ProgramOperation::operation(), TTAProgram::Terminal::operationIndex(), ProgramOperation::outputIndexFromGuardOfMove(), ProgramOperation::outputNode(), TTAMachine::HWOperation::port(), resultAllowedAtCycle(), resultCausesTriggerBetweenOperandSharing(), resultNotOverWritten(), resultPort(), TTAProgram::Move::source(), MoveNode::sourceOperation(), MoveNode::toString(), and ProgramOperation::triggeringMove().

Referenced by OutputFUResource::canAssign().

Here is the call graph for this function:

◆ checkOperandAllowed()

bool ExecutionPipelineResource::checkOperandAllowed ( const MoveNode currentMn,
const TTAMachine::Port port,
int  operandWriteCycle,
const OperandUseHelper operandUse,
int  operandUseModCycle,
ProgramOperation currOp 
) const
private

Definition at line 2234 of file ExecutionPipelineResource.cc.

2239  {
2240 #ifdef DEBUG_RM
2241  std::cerr << "\t\t\t\tChecking operand allowed for port: " << port.name() << " owc: " << operandWriteCycle << " ouc: " << operandUseModCycle << " po: " << operandUse.po->toString() << std::endl;
2242 #endif
2243  for (int i = 0; i < operandUse.po->inputMoveCount(); i++) {
2244  MoveNode& mn = operandUse.po->inputMove(i);
2245  if (mn.isPlaced()) {
2246  if (&mn.move().destination().port() == &port) {
2247 #ifdef DEBUG_RM
2248  std::cerr << "\t\t\t\t\tInput node using same port: " << mn.toString() << std::endl;
2249 #endif
2250  bool isCurrOp = false;
2251  for (unsigned int i = 0; i < mn.destinationOperationCount();
2252  i++) {
2253  if (&mn.destinationOperation(i) == &currOp) {
2254  isCurrOp = true;
2255  break;
2256  }
2257  }
2258  if (isCurrOp) {
2259  break;
2260  }
2261  // fail if the other operand happens eaelier than this (it has later usage).
2262 
2263  // loop scheudling, op overlaps
2264  // need to also check that is not written before the use.
2265  if (operandUseModCycle <
2266  instructionIndex(mn.cycle())) {
2267  if (instructionIndex(operandWriteCycle) <=
2268  operandUseModCycle ||
2269  instructionIndex(mn.cycle()) <= instructionIndex(operandWriteCycle)) {
2270  if (!exclusiveMoves(&mn, &currentMn, mn.cycle()))
2271  return false;
2272  }
2273  }
2274  // not overlapping.
2275  if (instructionIndex(mn.cycle()) <=
2276  instructionIndex(operandWriteCycle) &&
2277  instructionIndex(operandWriteCycle) <=
2278  operandUseModCycle) {
2279  if (!exclusiveMoves(&mn, &currentMn, mn.cycle()))
2280  return false;
2281  }
2282  }
2283  }
2284  }
2285  return true;
2286 }

References MoveNode::cycle(), TTAProgram::Move::destination(), MoveNode::destinationOperation(), MoveNode::destinationOperationCount(), exclusiveMoves(), ProgramOperation::inputMove(), ProgramOperation::inputMoveCount(), SchedulingResource::instructionIndex(), MoveNode::isPlaced(), MoveNode::move(), TTAMachine::Port::name(), ExecutionPipelineResource::OperandUseHelper::po, TTAProgram::Terminal::port(), MoveNode::toString(), and ProgramOperation::toString().

Referenced by operandAllowedAtCycle().

Here is the call graph for this function:

◆ clear()

void ExecutionPipelineResource::clear ( )
overridevirtual

Clears bookkeeping of the scheduling resource.

After this call the state of the resource should be identical to a newly-created and initialized resource.

Reimplemented from SchedulingResource.

Definition at line 1759 of file ExecutionPipelineResource.cc.

1759  {
1761  fuExecutionPipeline_.clear();
1762  resultWriten_.clear();
1763  operandsUsed_.clear();
1764  operandsWriten_.clear();
1765  resultRead_.clear();
1766  operandsWriten_.clear();
1767  storedResultCycles_.clear();
1768  assignedSourceNodes_.clear();
1769  assignedDestinationNodes_.clear();
1770  cachedSize_ = 0;
1771  ddg_ = NULL;
1772  operandShareCount_ = 0;
1773 }

References assignedDestinationNodes_, assignedSourceNodes_, cachedSize_, SchedulingResource::clear(), ddg_, fuExecutionPipeline_, operandShareCount_, operandsUsed_, operandsWriten_, resultRead_, resultWriten_, and storedResultCycles_.

Here is the call graph for this function:

◆ cyclesConflict()

bool ExecutionPipelineResource::cyclesConflict ( const MoveNode mn1,
const MoveNode mn2,
int  guardCycle,
int  rangeFirst,
int  rangeLast,
int  targetCycle 
) const
private

Definition at line 2843 of file ExecutionPipelineResource.cc.

2845  {
2846  if (exclusiveMoves(mn1, mn2, guardCycle)) {
2847  return false;
2848  }
2849  return cyclesOverlap (rangeFirst, rangeLast, targetCycle);
2850 }

References cyclesOverlap(), and exclusiveMoves().

Referenced by operandSharePreventsTriggerForScheduledResult().

Here is the call graph for this function:

◆ cyclesOverlap()

bool ExecutionPipelineResource::cyclesOverlap ( int  rangeFirst,
int  rangeLast,
int  targetCycle 
) const
inlineprivate

Definition at line 2823 of file ExecutionPipelineResource.cc.

2824  {
2825  int rangeFirstMod = instructionIndex(rangeFirst);
2826  int rangeLastMod = instructionIndex(rangeLast);
2827  int targetCycleMod = instructionIndex(targetCycle);
2828 
2829  // no overlap for the range
2830  if (rangeFirstMod <= rangeLastMod) {
2831  return targetCycleMod >= rangeFirstMod &&
2832  targetCycleMod <= rangeLastMod;
2833  } else { // overlaps.
2834  return targetCycleMod >= rangeFirstMod ||
2835  targetCycleMod <= rangeLastMod;
2836  }
2837 }

References SchedulingResource::instructionIndex().

Referenced by cyclesConflict().

Here is the call graph for this function:

◆ exclusiveMoves()

bool ExecutionPipelineResource::exclusiveMoves ( const MoveNode mn1,
const MoveNode mn2,
int  cycle = INT_MAX 
) const
private

Checks whether both of two moves have exclusive guards so that both moves are never executed, only either of those. Those can then be scheduled to use same resources.

This checks that the guards are exclusive, and that the moves are to be scheduled in same cycle (one already scheduled, on is going to be scheudled to given cycle, which has to be the same. the same cycle requirements makes sure the value of the guard cannot be changed between the moves.

Parameters
mn1movenode which has already been scheduled
mn2move which we are going to schedule
cyclecycle where we are going to scheudle mn2.

Definition at line 1719 of file ExecutionPipelineResource.cc.

1720  {
1721 #ifdef NO_OVERCOMMIT
1722  return false;
1723 #else
1724  if (mn1 == NULL || mn2 == NULL || !mn1->isMove() || !mn2->isMove()) {
1725  return false;
1726  }
1727 
1728  if (mn1->move().isUnconditional() || mn2->move().isUnconditional()) {
1729  return false;
1730  }
1731 
1732  if (ddg_ != NULL) {
1733  return ddg_->exclusingGuards(*mn1, *mn2);
1734  }
1735 
1736  if (!mn1->move().guard().guard().isOpposite(mn2->move().guard().guard())) {
1737  return false;
1738  }
1739 
1740  if (!mn1->isPlaced()) {
1741  return false;
1742  }
1743 
1744  if ((mn2->isPlaced() && mn1->cycle() == mn2->cycle()) ||
1745  (!mn2->isPlaced() && (mn1->cycle() == cycle || cycle == INT_MAX))) {
1746  return true;
1747  }
1748  return false;
1749 #endif
1750 }

References MoveNode::cycle(), ddg_, DataDependenceGraph::exclusingGuards(), TTAProgram::MoveGuard::guard(), TTAProgram::Move::guard(), MoveNode::isMove(), TTAMachine::Guard::isOpposite(), MoveNode::isPlaced(), TTAProgram::Move::isUnconditional(), and MoveNode::move().

Referenced by assignDestination(), checkOperandAllowed(), cyclesConflict(), hasConflictingResultsOnCycle(), nextResultCycle(), operandAllowedAtCycle(), operandOverwritten(), operandPossibleAtCycle(), otherTriggerBeforeMyTrigger(), resourcesAllowTrigger(), resultAllowedAtCycle(), and resultCausesTriggerBetweenOperandSharing().

Here is the call graph for this function:

◆ findRange()

void ExecutionPipelineResource::findRange ( const int  cycle,
const MoveNode node,
int  popIndex,
int &  first,
int &  last,
int &  triggering 
) const
private

Find first and last cycles already scheduled for same PO.

◆ hasConflictingResultsOnCycle()

bool ExecutionPipelineResource::hasConflictingResultsOnCycle ( const ProgramOperation po,
const TTAMachine::Port port,
int  cycle 
) const

Definition at line 1559 of file ExecutionPipelineResource.cc.

1561  {
1562  ResultMap::const_iterator rwi = resultWriten_.find(&port);
1563  if (rwi == resultWriten_.end()) {
1564  return false;
1565  }
1566 
1567  unsigned int modCycle = instructionIndex(cycle);
1568  MoveNode* trigger = po.triggeringMove();
1569  const ResultHelperPair& rhp =
1570  MapTools::valueForKeyNoThrow<ResultHelperPair>(
1571  rwi->second, modCycle);
1572 
1573  if (rhp.first.count != 0) {
1574  assert(rhp.first.po != NULL);
1575  if (rhp.first.po != &po &&
1576  !exclusiveMoves(
1577  rhp.first.po->triggeringMove(), trigger, INT_MAX)) {
1578  return true;
1579  }
1580  if (rhp.second.po != &po && rhp.second.count != 0) {
1581  assert(rhp.second.po != NULL);
1582  if (!exclusiveMoves(
1583  rhp.second.po->triggeringMove(), trigger, INT_MAX)) {
1584  return true;
1585  }
1586  }
1587  }
1588  return false;
1589 }

References assert, exclusiveMoves(), SchedulingResource::instructionIndex(), resultWriten_, and ProgramOperation::triggeringMove().

Referenced by canAssignSource().

Here is the call graph for this function:

◆ highestKnownCycle()

int ExecutionPipelineResource::highestKnownCycle ( ) const

Returns the highest cycle known to Execution Pipeline to be used by either pipeline resources or some operands, trigger or result read/write

TODO: module thingies

Returns
Highest cycle in which the pipeline is known to be used.

Definition at line 1479 of file ExecutionPipelineResource.cc.

1479  {
1480  if (initiationInterval_ == 0 || initiationInterval_ == INT_MAX) {
1481 
1482  // Find largest cycle where any operand or result was previously
1483  // scheduled.
1484  int maximum = 0;
1485  if (assignedDestinationNodes_.size() > 0) {
1486  maximum = (*assignedDestinationNodes_.rbegin()).first;
1487  } else {
1488  maximum = -1;
1489  }
1490 
1491  int maxResults = 0;
1492  if (assignedSourceNodes_.size() > 0) {
1493  maxResults = (*assignedSourceNodes_.rbegin()).first;
1494  } else {
1495  maxResults = 0;
1496  }
1497  if (maxResults> maximum) {
1498  maximum = maxResults;
1499  }
1500  // size returns count of cycle, max cycle address needs -1
1501  return std::max(maximum, (int)(size()) - 1);
1502  } else {
1503  int highest = -1;
1504  int min = INT_MAX;
1505  if (assignedSourceNodes_.size() > 0) {
1506  int srcMin = (*assignedSourceNodes_.begin()).first;
1507  min = std::min(min, srcMin);
1508  }
1509  if (assignedDestinationNodes_.size() > 0) {
1510  int dstMin = (*assignedDestinationNodes_.begin()).first;
1511  min = std::min(min, dstMin);
1512  }
1513 
1514  for (ResultMap::const_iterator rwi = resultWriten_.begin();
1515  rwi != resultWriten_.end(); rwi++) {
1516  const ResultVector& resultWriten = rwi->second;
1517 
1518  for (int i = resultWriten.size() -1; i >= min; i--) {
1519  const ResultHelperPair& rhp =
1520  MapTools::valueForKeyNoThrow<ResultHelperPair>(
1521  resultWriten,i);
1522  if (rhp.first.po != NULL) {
1523  if (int(rhp.first.realCycle) > highest) {
1524  highest = rhp.first.realCycle;
1525  }
1526  if (rhp.second.po != NULL) {
1527  if (int(rhp.second.realCycle) > highest) {
1528  highest = rhp.second.realCycle;
1529  }
1530  }
1531  }
1532  }
1533  }
1534  for (ResultMap::const_iterator rri = resultRead_.begin();
1535  rri != resultRead_.end(); rri++) {
1536  const ResultVector& resultRead = rri->second;
1537  for (int i = resultRead.size() -1; i >= min ; i--) {
1538  const ResultHelperPair& rrp =
1539  MapTools::valueForKeyNoThrow<ResultHelperPair>(
1540  resultRead,i);
1541  if (rrp.first.po != NULL) {
1542  if (int(rrp.first.realCycle) > highest) {
1543  highest = rrp.first.realCycle;
1544  }
1545  if (rrp.second.po != NULL) {
1546  if (int(rrp.second.realCycle) > highest) {
1547  highest = rrp.second.realCycle;
1548  }
1549  }
1550  }
1551  }
1552  }
1553  // TODO: operand writes not yet handled for this.
1554  return highest;
1555  }
1556 }

References assignedDestinationNodes_, assignedSourceNodes_, SchedulingResource::initiationInterval_, resultRead_, resultWriten_, SparseVector< ValueType >::size(), and size().

Referenced by ExecutionPipelineBroker::highestKnownCycle().

Here is the call graph for this function:

◆ isAvailable()

bool ExecutionPipelineResource::isAvailable ( const int  cycle) const
overridevirtual

Test if resource ExecutionPipelineResource is available for any of the supported operations (at least one).

Parameters
cycleCycle which to test
Returns
True if ExecutionPipelineResource is available in cycle

Implements SchedulingResource.

Definition at line 178 of file ExecutionPipelineResource.cc.

178  {
179  // check if all operand ports are used
180  int modCycle = instructionIndex(cycle);
181  for (int i = 0; i < fu_.portCount(); i++) {
182  const TTAMachine::BaseFUPort* port = fu_.port(i);
183  OperandWriteMap::const_iterator it = operandsWriten_.find(port);
184  if (it == operandsWriten_.end()) {
185  return true;
186  }
187  const OperandWriteVector& operandWrites = it->second;
188  OperandWriteVector::const_iterator j = operandWrites.find(modCycle);
189  if (j == operandWrites.end()) {
190  return true;
191  }
192 
193  MoveNodePtrPair mnpp = j->second;
194  if (mnpp.first == NULL ||
195  (!mnpp.first->move().isUnconditional() &&
196  mnpp.second == NULL)) {
197  return true;
198  }
199  }
200  return true;
201 }

References fu_, SchedulingResource::instructionIndex(), operandsWriten_, TTAMachine::FunctionUnit::port(), and TTAMachine::Unit::portCount().

Here is the call graph for this function:

◆ isDestOpOfMN()

bool ExecutionPipelineResource::isDestOpOfMN ( const MoveNode mn,
const ProgramOperation po 
) const
private

Definition at line 2477 of file ExecutionPipelineResource.cc.

2478  {
2479  for (unsigned int i = 0; i < mn.destinationOperationCount(); i++) {
2481  if (&p == &po) {
2482  return true;
2483  }
2484  }
2485  return false;
2486 }

References MoveNode::destinationOperation(), and MoveNode::destinationOperationCount().

Referenced by otherTriggerBeforeMyTrigger().

Here is the call graph for this function:

◆ isExecutionPipelineResource()

bool ExecutionPipelineResource::isExecutionPipelineResource ( ) const
overridevirtual

Always return true.

Returns
true

Reimplemented from SchedulingResource.

Definition at line 1378 of file ExecutionPipelineResource.cc.

1378  {
1379  return true;
1380 }

◆ isInUse()

bool ExecutionPipelineResource::isInUse ( const int  cycle) const
overridevirtual

Test if resource ExecutionPipelineResource is used in given cycle.

If there is any of pipeline resources already used in given cycle.

Parameters
cycleCycle which to test
Returns
True if ExecutionPipelineResource is already used in cycle
Exceptions
Internalerror, the recorded resource usage for cycle is shorter then the number of resources the FU has.

Some result is already read in tested cycle

Cycle is beyond already scheduled scope, not in use therefore

Some pipeline resource is already in use in tested cycle

Implements SchedulingResource.

Definition at line 117 of file ExecutionPipelineResource.cc.

117  {
118 
119  // check if any operand port is used
120  int modCycle = instructionIndex(cycle);
121  for (OperandWriteMap::const_iterator i = operandsWriten_.begin();
122  i != operandsWriten_.end(); i++) {
123 
124  const OperandWriteVector& operandWrites = i->second;
125  OperandWriteVector::const_iterator j = operandWrites.find(modCycle);
126  if (j != operandWrites.end()) {
127  return true;
128  }
129  }
130 
131  for (ResultMap::const_iterator rri = resultRead_.begin();
132  rri != resultRead_.end(); rri++) {
133  const ResultVector& resultRead = rri->second;
134  unsigned int resultReadCount = resultRead.rbegin()->first;//.size();
135  if (modCycle < (int)resultReadCount &&
136  (MapTools::valueForKeyNoThrow<ResultHelperPair>(
137  resultRead, modCycle)).first.po != NULL) {
138  /// Some result is already read in tested cycle
139  return true;
140  }
141  }
142  if (modCycle >= (int)size()) {
143  /// Cycle is beyond already scheduled scope, not in use therefore
144  return false;
145  }
146  if (resources->numberOfResources() !=
147  (MapTools::valueForKeyNoThrow<ResourceReservationVector>(
148  fuExecutionPipeline_, modCycle)).size()) {
149  std::string msg = "Execution pipeline is missing resources!";
150  throw ModuleRunTimeError(__FILE__, __LINE__, __func__, msg);
151  }
152  for (unsigned int i = 0; i < resources->numberOfResources(); i++) {
153  const ResourceReservationVector& rrv =
154  MapTools::valueForKeyNoThrow<ResourceReservationVector>(
155  fuExecutionPipeline_, modCycle);
156  if (rrv.size() == 0) {
157  return false;
158  }
159 
160  const ResourceReservation& rr = rrv[i];
161 
162  if (rr.first != NULL) {
163  /// Some pipeline resource is already in use in tested cycle
164  return true;
165  }
166  }
167  return false;
168 }

References __func__, fuExecutionPipeline_, SchedulingResource::instructionIndex(), ExecutionPipelineResourceTable::numberOfResources(), operandsWriten_, resources, resultRead_, and size().

Here is the call graph for this function:

◆ isLoopBypass()

bool ExecutionPipelineResource::isLoopBypass ( const MoveNode node) const
private

Definition at line 791 of file ExecutionPipelineResource.cc.

791  {
792  if (ddg_ == NULL) {
793  return false;
794  }
795  if (!ddg_->hasNode(node)) {
796  return false;
797  }
798  auto inEdges = ddg_->inEdges(node);
799  for (auto i = inEdges.begin(); i != inEdges.end(); i++) {
800  DataDependenceEdge& e = **i;
802  && e.isBackEdge()) {
803  return true;
804  }
805  }
806  return false;
807 }

References ddg_, DataDependenceEdge::EDGE_OPERATION, DataDependenceEdge::edgeReason(), BoostGraph< GraphNode, GraphEdge >::hasNode(), BoostGraph< GraphNode, GraphEdge >::inEdges(), and DataDependenceEdge::isBackEdge().

Referenced by assignSource(), canAssignSource(), latestTriggerWriteCycle(), and testTriggerResult().

Here is the call graph for this function:

◆ latestTriggerWriteCycle()

int ExecutionPipelineResource::latestTriggerWriteCycle ( const MoveNode mn) const
private

Returns the lates cycle the given trigger move can be scheduled at, taking in the account the latency of the operation results.

In case the none of the result moves has been scheduled yet, returns INT_MAX.

Exceptions
IllegalObjectif this MoveNode is not a result read.

Definition at line 2393 of file ExecutionPipelineResource.cc.

2394  {
2395 
2396  if (!mn.isDestinationOperation())
2397  throw IllegalParameters(
2398  __FILE__, __LINE__, __func__, "Not a result read move.");
2399 
2400  const ProgramOperation& po = mn.destinationOperation();
2401  int latestTrigger = INT_MAX;
2402  for (int i = 0; i < po.outputMoveCount(); i++){
2403  MoveNode& result = po.outputMove(i);
2404  if (!result.isScheduled()) {
2405  continue;
2406  }
2407 
2408  int resultCycle = (initiationInterval_ != 0 && isLoopBypass(result)) ?
2409  result.cycle() + initiationInterval_ :
2410  result.cycle();
2411 
2412  auto fu = po.fuFromOutMove(result);
2413  // find the latency of the operation output we are testing
2414  const TTAMachine::HWOperation& hwop =
2415  *fu->operation(po.operation().name());
2416 
2417  // find the OSAL id of the operand of the output we are testing
2418  const int outputIndex = po.outputIndexOfMove(result);
2419  int latency = hwop.latency(outputIndex);
2420  latestTrigger = std::min(latestTrigger, resultCycle - latency);
2421  }
2422  return latestTrigger;
2423 }

References __func__, MoveNode::cycle(), MoveNode::destinationOperation(), ProgramOperation::fuFromOutMove(), SchedulingResource::initiationInterval_, MoveNode::isDestinationOperation(), isLoopBypass(), MoveNode::isScheduled(), TTAMachine::HWOperation::latency(), Operation::name(), ProgramOperation::operation(), ProgramOperation::outputIndexOfMove(), ProgramOperation::outputMove(), and ProgramOperation::outputMoveCount().

Referenced by canAssignDestination().

Here is the call graph for this function:

◆ nextResultCycle()

int ExecutionPipelineResource::nextResultCycle ( const TTAMachine::Port port,
int  cycle,
const MoveNode node,
const MoveNode trigger = NULL,
int  triggerCycle = INT_MAX 
) const

Returns a cycle in which result of next program operation will be writen to result. This method results the next one of any iteration, not just the current iteration.

Parameters
cycleCycle from which to start testing.
nodeNode for which to test
Returns
Cycle in which next result will be writen, overwriting curent one.

Definition at line 1602 of file ExecutionPipelineResource.cc.

1605  {
1606 
1607  ResultMap::const_iterator rwi = resultWriten_.find(&port);
1608  if (rwi == resultWriten_.end()) {
1609  return INT_MAX;
1610  }
1611  const ResultVector& resultWriten = rwi->second;
1612 
1613  ProgramOperation* sourcePo;
1614  if (!node.isSourceOperation()) {
1615  if (node.isGuardOperation()) {
1616  sourcePo = &node.guardOperation();
1617  } else {
1618  throw InvalidData(__FILE__, __LINE__, __func__,
1619  "Trying to get next result for move that is not"
1620  " in ProgramOperation");
1621  }
1622  } else {
1623  sourcePo = &node.sourceOperation();
1624  if (trigger == NULL) {
1625  trigger = sourcePo->triggeringMove();
1626  }
1627  }
1628 
1629  unsigned int ii = initiationInterval_;
1630  if (ii < 1) {
1631  ii = INT_MAX;
1632  }
1633 
1634  unsigned int rwSize = resultWriten.size();
1635  for (unsigned int i = cycle; i < cycle + ii; i++) {
1636  unsigned int modi = instructionIndex(i);
1637 
1638  if (rwSize <= modi) {
1639  if (ii == INT_MAX) {
1640  return INT_MAX;
1641  } else {
1642  continue;
1643  }
1644  }
1645 
1646  const ResultHelperPair& rhp =
1647  MapTools::valueForKeyNoThrow<ResultHelperPair>(resultWriten,modi);
1648  if (rhp.first.count != 0) {
1649  assert(rhp.first.po != NULL);
1650  if (rhp.first.po != sourcePo &&
1651  !exclusiveMoves(
1652  rhp.first.po->triggeringMove(), trigger,
1653  triggerCycle)) {
1654  return rhp.first.realCycle;
1655  }
1656  if (rhp.second.po != sourcePo && rhp.second.count != 0) {
1657  assert(rhp.second.po != NULL);
1658  if (!exclusiveMoves(
1659  rhp.second.po->triggeringMove(), trigger,
1660  triggerCycle)) {
1661  return rhp.second.realCycle;
1662  }
1663  }
1664  }
1665  }
1666  return INT_MAX;
1667 }

References __func__, assert, exclusiveMoves(), MoveNode::guardOperation(), SchedulingResource::initiationInterval_, SchedulingResource::instructionIndex(), MoveNode::isGuardOperation(), MoveNode::isSourceOperation(), resultWriten_, SparseVector< ValueType >::size(), MoveNode::sourceOperation(), and ProgramOperation::triggeringMove().

Referenced by ExecutionPipelineBroker::latestFromSource(), and resultNotOverWritten().

Here is the call graph for this function:

◆ nodeOfInputPort()

const MoveNode * ExecutionPipelineResource::nodeOfInputPort ( const ProgramOperation po,
TTAMachine::Port port 
)
private

Definition at line 2853 of file ExecutionPipelineResource.cc.

2854  {
2855 
2856  const Operation& op = po.operation();
2857  auto hwop = fu_.operation(op.name());
2858  if (!hwop->isBound(static_cast<TTAMachine::FUPort&>(port))) {
2859  return nullptr;
2860  }
2861  int idx = hwop->io(static_cast<TTAMachine::FUPort&>(port));
2862  return *po.inputNode(idx).begin();
2863 }

References MoveNodeSet::begin(), fu_, ProgramOperation::inputNode(), TTAMachine::HWOperation::io(), Operation::name(), TTAMachine::FunctionUnit::operation(), and ProgramOperation::operation().

Here is the call graph for this function:

◆ operandAllowedAtCycle()

bool ExecutionPipelineResource::operandAllowedAtCycle ( const TTAMachine::Port port,
const MoveNode mn,
int  cycle 
) const
private

Definition at line 2131 of file ExecutionPipelineResource.cc.

2132  {
2133 #ifdef DEBUG_RM
2134  std::cerr << "\t\tTesting " << mn.toString() << " that operand at port: "
2135  << port.name() << " allowed at cycle: " << cycle << std::endl;
2136 #endif
2137  int ii = initiationInterval();
2138  if (ii < 1) {
2139  ii = INT_MAX;
2140  }
2141 
2142  OperandUseMap::const_iterator rui = operandsUsed_.find(&port);
2143  if (rui == operandsUsed_.end()) {
2144  return true;
2145  }
2146 
2147  const OperandUseVector& operandUsed = rui->second;
2148  size_t operandUsedSize = operandUsed.size();
2149 
2150  if (!mn.isDestinationOperation()) {
2151  throw InvalidData(__FILE__, __LINE__, __func__,
2152  "Trying to get next result for move that is not "
2153  "in ProgramOperation");
2154  }
2155 
2156  // TODO: this may be very slow if big BB with not much code
2157  int nextOperandUseCycle = cycle;
2158  int nextOperandUseModCycle = instructionIndex(nextOperandUseCycle);
2159  OperandUseVector::const_iterator i =
2160  operandUsed.find(nextOperandUseModCycle);
2161 
2162  while(true) {
2163 #ifdef DEBUG_RM
2164  std::cerr << "\t\t\tTesting use from cycle: " << nextOperandUseCycle << std::endl;
2165 #endif
2166  if (i != operandUsed.end()) {
2167 #ifdef DEBUG_RM
2168  std::cerr << "\t\t\t\tcycle " << nextOperandUseCycle << " not empty." << std::endl;
2169 #endif
2170  const OperandUseHelper& operandUse = i->second.first;
2171  if (operandUse.po != NULL) {
2172  const MoveNode* opUseTrigger =
2173  operandUse.po->triggeringMove();
2174  if (opUseTrigger != NULL) {
2175 #ifdef DEBUG_RM
2176  std::cerr << "\t\t\t\tFound using trigger: " << opUseTrigger->toString() << std::endl;
2177 #endif
2178  }
2179  if (!exclusiveMoves(opUseTrigger, &mn, cycle)) {
2180  /* destinationOperation(0) sounds suspicious */
2181  if (!checkOperandAllowed(
2182  mn, port, cycle, operandUse, nextOperandUseModCycle,
2183  mn.destinationOperation(0))) {
2184  return false;
2185  }
2186  if (opUseTrigger == NULL ||
2187  opUseTrigger->move().isUnconditional()) {
2188  bool allScheduled = true;
2189  int imc = operandUse.po->inputMoveCount();
2190  for (int i = 0; i < imc; i++) {
2191  if (!operandUse.po->inputMove(i).isPlaced()) {
2192  allScheduled = false;
2193  break;
2194  }
2195  }
2196  if (allScheduled) {
2197  return true;
2198  }
2199  }
2200  }
2201  // conditional moves, second exclusive?
2202  const OperandUseHelper& operandUse2 = i->second.second;
2203  if (operandUse2.po != NULL) {
2204  const MoveNode& opUseTrigger2 =
2205  *operandUse2.po->triggeringMove();
2206  if (!exclusiveMoves(&opUseTrigger2, &mn, cycle)) {
2207  /* destinationOperation(0) sounds suspicious */
2208  if (!checkOperandAllowed(
2209  mn, port, cycle, operandUse2,
2210  nextOperandUseModCycle,
2211  mn.destinationOperation(0))) {
2212  return false;
2213  }
2214  }
2215  }
2216  }
2217  }
2218  nextOperandUseCycle++;
2219 
2220  if (ii == INT_MAX && nextOperandUseCycle >= (int)operandUsedSize) {
2221  return true;
2222  }
2223 
2224  if (nextOperandUseCycle - cycle >= (int)ii) {
2225  return true;
2226  }
2227  nextOperandUseModCycle = instructionIndex(nextOperandUseCycle);
2228  i = operandUsed.find(nextOperandUseModCycle);
2229  }
2230 
2231  return true;
2232 }

References __func__, checkOperandAllowed(), MoveNode::destinationOperation(), exclusiveMoves(), SchedulingResource::initiationInterval(), ProgramOperation::inputMove(), ProgramOperation::inputMoveCount(), SchedulingResource::instructionIndex(), MoveNode::isDestinationOperation(), MoveNode::isPlaced(), TTAProgram::Move::isUnconditional(), MoveNode::move(), TTAMachine::Port::name(), operandsUsed_, ExecutionPipelineResource::OperandUseHelper::po, SparseVector< ValueType >::size(), MoveNode::toString(), and ProgramOperation::triggeringMove().

Referenced by canAssignDestination(), resultCausesTriggerBetweenOperandSharing(), and triggerAllowedAtCycle().

Here is the call graph for this function:

◆ operandOverwritten() [1/2]

bool ExecutionPipelineResource::operandOverwritten ( const MoveNode mn,
int  cycle 
) const
private

Definition at line 1105 of file ExecutionPipelineResource.cc.

1106  {
1107 #ifdef DEBUG_RM
1108  std::cerr << "\t\tTesting operand not overwritten by other ops: " <<
1109  mn.toString() << " cycle: " << cycle << std::endl;
1110 #endif
1111  for (unsigned int i = 0; i < mn.destinationOperationCount(); i++) {
1113  MoveNode* trigger = po.triggeringMove();
1114  if (trigger == &mn) {
1115 #ifdef DEBUG_RM
1116  std::cerr << "\t\t\tmn is trigger, no need to check overwrite" << std::endl;
1117 #endif
1118  return false;
1119  }
1120  if (trigger == NULL || !trigger->isPlaced()) {
1121 #ifdef DEBUG_RM
1122  std::cerr << "\t\t\ttrigger null or not scheduled on PO: "
1123  << po.toString() << std::endl;
1124 #endif
1125  continue;
1126  }
1127 
1128  int triggerCycle = trigger->cycle();
1129 
1130  if (operandOverwritten(cycle, triggerCycle, po, mn, *trigger)) {
1131  return true;
1132  }
1133  }
1134  return false;
1135 }

References MoveNode::cycle(), MoveNode::destinationOperation(), MoveNode::destinationOperationCount(), MoveNode::isPlaced(), operandOverwritten(), MoveNode::toString(), ProgramOperation::toString(), and ProgramOperation::triggeringMove().

Here is the call graph for this function:

◆ operandOverwritten() [2/2]

bool ExecutionPipelineResource::operandOverwritten ( int  operandWriteCycle,
int  triggerCycle,
const ProgramOperation po,
const MoveNode operand,
const MoveNode trigger 
) const
private

Definition at line 1137 of file ExecutionPipelineResource.cc.

1142  {
1143 
1144  unsigned int ii = initiationInterval_;
1145  if (ii < 1) {
1146  ii = INT_MAX;
1147  }
1148 
1149 #ifdef DEBUG_RM
1150  std::cerr << "\t\t\tOperandOverWritten called for: " << operand.toString()
1151  << " PO: " << po.toString()
1152  << " trigger: " << trigger.toString() << "owc: "
1153  << operandWriteCycle << " tc: " << triggerCycle << std::endl;
1154 #endif
1155  const Operation& op = po.operation();
1156  TTAMachine::HWOperation& hwop = *fu_.operation(op.name());
1157 
1158  int opIndex = operand.move().destination().operationIndex();
1159  const TTAMachine::Port& port = *hwop.port(opIndex);
1160  int operandUseCycle = triggerCycle + hwop.slack(opIndex);
1161 
1162  // same op on next loop iteration overwrites?
1163  if (operandUseCycle - operandWriteCycle >= (int)ii) {
1164 #ifdef DEBUG_RM
1165  std::cerr << "\t\t\t\tOperand LR over loop iteration(2): " << ii
1166  << std::endl;
1167 #endif
1168  return true;
1169  }
1170 
1171 #ifdef DEBUG_RM
1172  std::cerr << "\t\t\t\tTesting port: " << port.name() << std::endl;
1173 #endif
1174  OperandWriteMap::const_iterator iter = operandsWriten_.find(&port);
1175  if (iter == operandsWriten_.end()) {
1176  return false;
1177  }
1178  const OperandWriteVector& operandWritten = iter->second;
1179 #ifdef DEBUG_RM
1180 
1181  std::cerr << "\t\t\t\tOperandWriteCycle: " << operandWriteCycle << std::endl
1182  << "\t\t\t\tOperandUseCycle: " << operandUseCycle << std::endl;
1183 #endif
1184 
1185  for (int j = operandWriteCycle; j <= operandUseCycle; j++) {
1186 #ifdef DEBUG_RM
1187  std::cerr << "\t\t\t\tTesting if overwritten in cycle: " << j << std::endl;
1188 #endif
1189  unsigned int modCycle = instructionIndex(j);
1190  OperandWriteVector::const_iterator owi = operandWritten.find(modCycle);
1191  if (owi == operandWritten.end()) {
1192  continue;
1193  }
1194  const MoveNodePtrPair& mnpp = owi->second;
1195  if (mnpp.first != NULL && mnpp.first != &operand &&
1196  !exclusiveMoves(mnpp.first, &trigger, triggerCycle)) {
1197 #ifdef DEBUG_RM
1198  std::cerr << "\t\t\t\t\tOverwritten by: " << mnpp.first->toString() << std::endl;
1199 #endif
1200  return true;
1201  }
1202  if (mnpp.second != NULL && mnpp.second != &operand &&
1203  !exclusiveMoves(mnpp.second, &trigger, triggerCycle)) {
1204 #ifdef DEBUG_RM
1205  std::cerr << "\t\t\t\t\tOverwritten(2) by: " << mnpp.second->toString() << std::endl;
1206 #endif
1207  return true;
1208  }
1209  }
1210 #ifdef DEBUG_RM
1211  std::cerr << "\t\t\tNot overwritten" << std::endl;
1212 #endif
1213  return false;
1214 }

References TTAProgram::Move::destination(), exclusiveMoves(), fu_, SchedulingResource::initiationInterval_, SchedulingResource::instructionIndex(), MoveNode::move(), TTAMachine::Port::name(), Operation::name(), operandsWriten_, TTAMachine::FunctionUnit::operation(), ProgramOperation::operation(), TTAProgram::Terminal::operationIndex(), TTAMachine::HWOperation::port(), TTAMachine::HWOperation::slack(), MoveNode::toString(), and ProgramOperation::toString().

Referenced by canAssignDestination(), operandOverwritten(), and operandsOverwritten().

Here is the call graph for this function:

◆ operandPort()

const TTAMachine::Port & ExecutionPipelineResource::operandPort ( const MoveNode mn) const
private

Gives the port where from the movenode writes an operand.

Definition at line 2027 of file ExecutionPipelineResource.cc.

2027  {
2029  const ProgramOperation& po = mn.destinationOperation();
2030  const TTAMachine::HWOperation& hwop =
2031  *fu_.operation(po.operation().name());
2032  return *hwop.port(mn.move().destination().operationIndex());
2033 }

References assert, TTAProgram::Move::destination(), MoveNode::destinationOperation(), fu_, MoveNode::isDestinationOperation(), MoveNode::move(), Operation::name(), TTAMachine::FunctionUnit::operation(), ProgramOperation::operation(), TTAProgram::Terminal::operationIndex(), and TTAMachine::HWOperation::port().

Referenced by assignDestination(), and unassignDestination().

Here is the call graph for this function:

◆ operandPossibleAtCycle()

bool ExecutionPipelineResource::operandPossibleAtCycle ( const TTAMachine::Port port,
const MoveNode mn,
int  cycle 
) const
private

Checks that no other operand of another op is written at exactly same cycle

Definition at line 2106 of file ExecutionPipelineResource.cc.

2107  {
2108 
2109  int modCycle = instructionIndex(cycle);
2110  // test that nobody writes operand at same cycle
2111  auto owi = operandsWriten_.find(&port);
2112  if (owi != operandsWriten_.end()) {
2113  const OperandWriteVector& owv = owi->second;
2114  auto owi2 = owv.find(modCycle);
2115  if (owi2 != owv.end()) {
2116  auto mnpp = owi2->second;
2117  if (mnpp.first != NULL &&
2118  (mnpp.second!=NULL || !exclusiveMoves(mnpp.first,&mn,cycle))){
2119 #ifdef DEBUG_RM
2120  std::cerr << "MN of other op: " << mnpp.first->toString()
2121  << " writing to same port at same cycle"
2122  << std::endl;
2123 #endif
2124  return false;
2125  }
2126  }
2127  }
2128  return true;
2129 }

References exclusiveMoves(), SchedulingResource::instructionIndex(), and operandsWriten_.

Referenced by canAssignDestination().

Here is the call graph for this function:

◆ operandSharePreventsTriggerForScheduledResult()

bool ExecutionPipelineResource::operandSharePreventsTriggerForScheduledResult ( const TTAMachine::Port port,
const MoveNode mn,
int  cycle 
) const
private

Definition at line 2605 of file ExecutionPipelineResource.cc.

2606  {
2607 
2608  if (mn.destinationOperationCount() < 2) {
2609  return false;
2610  }
2611 
2612  std::map<const TTAMachine::FUPort*, std::set<int> > myActualResultCycles;
2613 
2614  // cycle range these operand shared ops may use the output port.
2615  std::map<const TTAMachine::FUPort*, std::pair<int, int> > myResultCycles;
2616 
2617  // earliest possible cycle of the last trigger of these operand shared ops
2618  // can have.
2619  int lastTriggerCycle = -1;
2620  // needed for calculating the trigger cycle
2621  const MoveNode* prevOutmove = nullptr;
2622  int prevLatency = 0;
2623 
2624  for (unsigned int i = 0; i < mn.destinationOperationCount(); i++) {
2626  MoveNode* trigger = po.triggeringMove();
2627  if (trigger != nullptr && trigger->isScheduled()) {
2628  assert(trigger->cycle() >= cycle);
2629  if (trigger->cycle() > lastTriggerCycle) {
2630  lastTriggerCycle = trigger->cycle();
2631  prevOutmove = nullptr;
2632  prevLatency = 0;
2633  }
2634  }
2635 
2636  for (int j = 0; j < po.outputMoveCount(); j++) {
2637  const MoveNode& outMove = po.outputMove(j);
2638  if (!outMove.move().source().isFUPort()) {
2639  continue;
2640  }
2641 
2642  const int outputIndex = po.outputIndexOfMove(outMove);
2643  const TTAMachine::HWOperation& hwop =
2644  *fu_.operation(po.operation().name());
2645  int latency = hwop.latency(outputIndex);
2646  auto outPort = hwop.port(outputIndex);
2647  auto outPortIter = myResultCycles.find(outPort);
2648  // [] operator would init to 0 which would break min.
2649  if (outPortIter == myResultCycles.end()) {
2650  // initialize to be free.
2651  myResultCycles[outPort] = std::make_pair(INT_MAX, -1);
2652  }
2653 
2654  if (outMove.isScheduled()) {
2655  const TTAMachine::FUPort* outPort =
2656  static_cast<const TTAMachine::FUPort*>(
2657  &outMove.move().source().port());
2658 
2659  myResultCycles[outPort].second = std::max(
2660  myResultCycles[outPort].second, outMove.cycle());
2661 
2662  myResultCycles[outPort].first = std::min(
2663  myResultCycles[outPort].first, outMove.cycle());
2664 
2665  // Is really used during this cycle.
2666  myActualResultCycles[outPort].insert(
2668 
2669  if (trigger == nullptr || !trigger->isScheduled()) {
2670  int optimalTriggerCycle = outMove.cycle() - latency;
2671  if (optimalTriggerCycle > lastTriggerCycle) {
2672  // the trigger cycle was exact,
2673  // based on scheduled trigger
2674  // now make it inexact.
2675  if (prevOutmove == nullptr) {
2676  lastTriggerCycle++;
2677  prevOutmove = &outMove;
2678  prevLatency = latency;
2679  } else {
2680  // was already based on outmove, not trigger.
2681  // need to calculate the earlierst cycle for this
2682  // trigger
2683  // so that it does not prevewrite the prev result.
2684  int prevTriggerCycle =
2685  prevOutmove->cycle() - prevLatency;
2686  lastTriggerCycle = prevTriggerCycle + 1;
2687 
2688  prevOutmove = &outMove;
2689  prevLatency = latency;
2690  }
2691  }
2692  } else { // trigger is scheduled.
2693  int resultReady = trigger->cycle() + latency;
2694  for (int i = outMove.cycle(); i >= resultReady; i--) {
2695  myActualResultCycles[outPort].insert(
2696  instructionIndex(i));
2697  }
2698  }
2699 
2700  } else { // out move not scheduled.
2701  if (trigger != nullptr && trigger->isScheduled()) {
2702  myActualResultCycles[outPort].insert(
2703  instructionIndex(trigger->cycle() + latency));
2704 
2705  myResultCycles[outPort].second = std::max(
2706  myResultCycles[outPort].second,
2707  trigger->cycle() + latency);
2708 
2709  myResultCycles[outPort].first = std::min(
2710  myResultCycles[outPort].first,
2711  trigger->cycle() + latency);
2712  }
2713 
2714  }
2715  }
2716  }
2717 
2718  // loop through all result ports used by the operand.
2719  for (auto p : myResultCycles) {
2720 
2721  auto& myActualResCycles = myActualResultCycles[p.first];
2722  // result read vector for that port
2723  auto rri = resultRead_.find(p.first);
2724  // first and last cycles for that port.
2725  int myFirstResultCycle = p.second.first;
2726  int myLastResultCycle = p.second.second;
2727 
2728  // modulo versions of these cycles
2729  int myFirstModResult = instructionIndex(myFirstResultCycle);
2730  int myLastModResult = instructionIndex(myLastResultCycle);
2731 
2732  // no bookkeeping for this result port? Cannot conflict.
2733  if (rri == resultRead_.end()) {
2734  continue;
2735  }
2736  auto& resVec = rri->second;
2737 
2738  for (auto& res : resVec) {
2739  int anotherResCycle = res.first;
2740  int anotherResModCycle = instructionIndex(anotherResCycle);
2741  assert(anotherResCycle == anotherResModCycle);
2742 
2743  // IF found fromt he actual result cycles, have to check.
2744  if (myActualResCycles.find(anotherResModCycle)
2745  == myActualResCycles.end()) {
2746  // the range overlaps
2747  if (myLastModResult < myFirstModResult) {
2748  // before first but after overlapped last, ok
2749  if (anotherResModCycle < myFirstModResult &&
2750  anotherResModCycle > myLastModResult)
2751  continue;
2752  } else { // no overlap.
2753  // Before first of after last is ok.
2754  if (anotherResModCycle < myFirstModResult ||
2755  anotherResModCycle > myLastModResult)
2756  continue;
2757  }
2758  }
2759  auto& foo = res.second;
2760  const ResultHelper& rh1 = foo.first;
2761  const ResultHelper& rh2 = foo.second;
2762  if (rh1.po != nullptr) {
2763  int rc = rh1.realCycle;
2764  MoveNode* trigger = rh1.po->triggeringMove();
2765  if (!trigger->isScheduled() &&
2766  poConflictsWithInputPort(port, *rh1.po, mn)) {
2767  const TTAMachine::HWOperation& hwop =
2768  *fu_.operation(rh1.po->operation().name());
2769  int outIndex = hwop.io(*p.first);
2770  int latency = hwop.latency(outIndex);
2771  bool foundWorkingCycle = false;
2772  // try to find a legal cycle for the trigger of other op
2773  for (int i = rc;
2774  myActualResCycles.find(instructionIndex(i)) ==
2775  myActualResCycles.end(); i--) {
2776  int otherTriggerCycle = i - latency;
2777  if (!cyclesConflict(
2778  &mn, trigger, cycle, cycle, lastTriggerCycle,
2779  otherTriggerCycle)) {
2780  foundWorkingCycle = true;
2781  }
2782  }
2783  // did not found a legal place for the trigger?
2784  if (!foundWorkingCycle) {
2785  return true;
2786  }
2787  }
2788  }
2789 
2790  if (rh2.po != nullptr) {
2791  int rc = rh2.realCycle;
2792  MoveNode* trigger = rh2.po->triggeringMove();
2793  if (!trigger->isScheduled() &&
2794  poConflictsWithInputPort(port, *rh2.po, mn)) {
2795  const TTAMachine::HWOperation& hwop =
2796  *fu_.operation(rh2.po->operation().name());
2797  int outIndex = hwop.io(*p.first);
2798  int latency = hwop.latency(outIndex);
2799  bool foundWorkingCycle = false;
2800  // try to find a legal cycle for the trigger of other op
2801  for (int i = rc;
2802  myActualResCycles.find(i) == myActualResCycles.end();
2803  i--) {
2804  assert (i > myFirstResultCycle);
2805  int otherTriggerCycle = i - latency;
2806  if (!cyclesConflict(
2807  &mn, trigger, cycle, cycle, lastTriggerCycle,
2808  otherTriggerCycle)) {
2809  foundWorkingCycle = true;
2810  }
2811  }
2812  // did not found a legal place for the trigger?
2813  if (!foundWorkingCycle) {
2814  return true;
2815  }
2816  }
2817  }
2818  }
2819  }
2820  return false;
2821 }

References assert, MoveNode::cycle(), cyclesConflict(), MoveNode::destinationOperation(), MoveNode::destinationOperationCount(), fu_, SchedulingResource::instructionIndex(), TTAMachine::HWOperation::io(), TTAProgram::Terminal::isFUPort(), MoveNode::isScheduled(), TTAMachine::HWOperation::latency(), MoveNode::move(), Operation::name(), TTAMachine::FunctionUnit::operation(), ProgramOperation::operation(), ProgramOperation::outputIndexOfMove(), ProgramOperation::outputMove(), ProgramOperation::outputMoveCount(), ExecutionPipelineResource::ResultHelper::po, poConflictsWithInputPort(), TTAMachine::HWOperation::port(), TTAProgram::Terminal::port(), ExecutionPipelineResource::ResultHelper::realCycle, resultRead_, TTAProgram::Move::source(), and ProgramOperation::triggeringMove().

Referenced by canAssignDestination().

Here is the call graph for this function:

◆ operandsOverwritten()

bool ExecutionPipelineResource::operandsOverwritten ( int  triggerCycle,
const MoveNode trigger 
) const

Definition at line 1216 of file ExecutionPipelineResource.cc.

1217  {
1218  ProgramOperation &po = trigger.destinationOperation();
1219 #ifdef DEBUG_RM
1220  std::cerr << "\t\tTesting op overwrite for: " << po.toString() << " cycle: " << triggerCycle << std::endl;
1221 #endif
1222  for (int i = 0; i < po.inputMoveCount(); i++) {
1223  MoveNode& inputMove = po.inputMove(i);
1224  if (&inputMove == &trigger) {
1225  continue;
1226  }
1227  if (!inputMove.isPlaced()) {
1228  if (operandOverwritten(
1229  triggerCycle, triggerCycle, po, inputMove, trigger)) {
1230  return true;
1231  }
1232  continue;
1233  }
1234  int operandWriteCycle = inputMove.cycle();
1235  if (operandOverwritten(
1236  operandWriteCycle, triggerCycle, po, inputMove, trigger)) {
1237  return true;
1238  }
1239  }
1240  return false;
1241 }

References MoveNode::cycle(), MoveNode::destinationOperation(), ProgramOperation::inputMove(), ProgramOperation::inputMoveCount(), MoveNode::isPlaced(), operandOverwritten(), and ProgramOperation::toString().

Referenced by canAssignDestination().

Here is the call graph for this function:

◆ operandTooLate()

bool ExecutionPipelineResource::operandTooLate ( const MoveNode mn,
int  cycle 
) const
private

Checks that operand is not scheduled too late(after trigger+slack)

Definition at line 2291 of file ExecutionPipelineResource.cc.

2291  {
2292  for (unsigned int i = 0; i < mn.destinationOperationCount(); i++) {
2294  MoveNode* trigger = po.triggeringMove();
2295  if (trigger == &mn) {
2296 #ifdef DEBUG_RM
2297  std::cerr << "\t\t\tmn is trigger, no need to check overwrite" << std::endl;
2298 #endif
2299  return false;
2300  }
2301  if (trigger == NULL || !trigger->isPlaced()) {
2302  continue;
2303  }
2304 
2305  const Operation& op = po.operation();
2306  TTAMachine::HWOperation& hwop = *fu_.operation(op.name());
2307 
2308  int opIndex = mn.move().destination().operationIndex();
2309  int slack = hwop.slack(opIndex);
2310  const TTAMachine::FUPort& port = *hwop.port(opIndex);
2311  if (port.noRegister()) {
2312  if (cycle != trigger->cycle() + slack) {
2313  return true;
2314  }
2315  } else {
2316  if (cycle > trigger->cycle() + slack) {
2317  return true;
2318  }
2319  }
2320  }
2321  return false;
2322 }

References MoveNode::cycle(), TTAProgram::Move::destination(), MoveNode::destinationOperation(), MoveNode::destinationOperationCount(), fu_, MoveNode::isPlaced(), MoveNode::move(), Operation::name(), TTAMachine::FUPort::noRegister(), TTAMachine::FunctionUnit::operation(), ProgramOperation::operation(), TTAProgram::Terminal::operationIndex(), TTAMachine::HWOperation::port(), TTAMachine::HWOperation::slack(), and ProgramOperation::triggeringMove().

Referenced by canAssignDestination().

Here is the call graph for this function:

◆ operator=()

ExecutionPipelineResource& ExecutionPipelineResource::operator= ( const ExecutionPipelineResource )
private

◆ otherTriggerBeforeMyTrigger()

bool ExecutionPipelineResource::otherTriggerBeforeMyTrigger ( const TTAMachine::Port port,
const MoveNode node,
int  cycle 
) const

Definition at line 2425 of file ExecutionPipelineResource.cc.

2426  {
2427 
2428  // find last scheduled trigger cycle
2429  int triggerCycle = -1;
2430  std::set<ProgramOperation*, ProgramOperation::Comparator> poSet;
2431  for (unsigned int i = 0; i < mn.destinationOperationCount(); i++) {
2432  ProgramOperation& po = mn.destinationOperation(i);
2433  MoveNode* trigger = po.triggeringMove();
2434  if (trigger != NULL && trigger->isScheduled()) {
2435  triggerCycle = std::max(triggerCycle, trigger->cycle());
2436  }
2437  }
2438 
2439  // then test each of these cycles.
2440  for (int i = cycle; i <= triggerCycle; i++) {
2441  // has other trigger in this cycle?
2442 
2443  auto opUse = operandsUsed_.find(&port);
2444  if (opUse == operandsUsed_.end())
2445  continue;
2446 
2447  unsigned int modCycle = instructionIndex(i);
2448  auto oupIter = opUse->second.find(modCycle);
2449  if (oupIter == opUse->second.end())
2450  continue;
2451 
2452  auto& oup = oupIter->second;
2453  // no trigger on this cycle?
2454  if (oup.first.po == NULL)
2455  continue;
2456 
2457  // own op reading result on this cycle
2458  if (isDestOpOfMN(mn, *oup.first.po))
2459  continue;
2460 
2461  if (oup.second.po == NULL) {
2462  if (exclusiveMoves(&mn, oup.first.po->triggeringMove(), i)) {
2463  continue;
2464  } else {
2465  return true;
2466  }
2467  }
2468  if (isDestOpOfMN(mn, *oup.second.po)) {
2469  continue;
2470  } else {
2471  return true;
2472  }
2473  }
2474  return false;
2475 }

References MoveNode::cycle(), MoveNode::destinationOperation(), MoveNode::destinationOperationCount(), exclusiveMoves(), SchedulingResource::instructionIndex(), isDestOpOfMN(), MoveNode::isScheduled(), operandsUsed_, and ProgramOperation::triggeringMove().

Referenced by canAssignDestination().

Here is the call graph for this function:

◆ poConflictsWithInputPort()

bool ExecutionPipelineResource::poConflictsWithInputPort ( const TTAMachine::Port port,
const ProgramOperation po,
const MoveNode mn 
) const
private

Definition at line 2866 of file ExecutionPipelineResource.cc.

2869  {
2870 
2871  const TTAMachine::FunctionUnit* fu =
2872  static_cast<const TTAMachine::FunctionUnit*>(port.parentUnit());
2873 
2874 
2875  for (int i = 0; i < po.inputMoveCount(); i++) {
2876  MoveNode& in = po.inputMove(i);
2877  if (&mn == &in) {
2878  return false;
2879  }
2880  TTAProgram::Terminal& dest = in.move().destination();
2881  if (!dest.isFUPort()) {
2882  continue;
2883  }
2884  const TTAMachine::BaseFUPort* fup =
2885  static_cast<const TTAMachine::BaseFUPort*>(&dest.port());
2886  if (fup == &port) {
2887  return true;
2888  }
2889  }
2890 
2891  if (fu != nullptr) {
2892  const Operation& op = po.operation();
2893  auto hwop = fu->operation(op.name());
2894  for (int i = 1; i <= op.numberOfInputs(); i++) {
2895  auto p = hwop->port(i);
2896  if (p == &port) {
2897  return true;
2898  }
2899  }
2900  }
2901  return false;
2902 }

References TTAProgram::Move::destination(), ProgramOperation::inputMove(), ProgramOperation::inputMoveCount(), TTAProgram::Terminal::isFUPort(), MoveNode::move(), Operation::name(), Operation::numberOfInputs(), TTAMachine::FunctionUnit::operation(), ProgramOperation::operation(), TTAMachine::Port::parentUnit(), TTAMachine::HWOperation::port(), and TTAProgram::Terminal::port().

Referenced by operandSharePreventsTriggerForScheduledResult().

Here is the call graph for this function:

◆ resourcesAllowTrigger()

bool ExecutionPipelineResource::resourcesAllowTrigger ( int  cycle,
const MoveNode move 
) const
private

Definition at line 1244 of file ExecutionPipelineResource.cc.

1245  {
1246 
1247  unsigned int ii = initiationInterval();
1248  if (ii < 1) {
1249  ii = INT_MAX;
1250  }
1251 
1252  int modCycle = instructionIndex(cycle);
1253  std::string opName = "";
1254  if (node.move().destination().isOpcodeSetting()) {
1255  opName = node.move().destination().operation().name();
1256 // debugLogRM(opName);
1257  } else {
1258  // If target architecture has different opcode setting port
1259  // as universal machine, pick a name of operation from a hint
1260  opName = node.move().destination().hintOperation().name();
1261  }
1262 
1263  if (!resources->hasOperation(opName)) {
1264  // Operation no supported by FU
1265 // debugLogRM(opName + " not supported by the FU!");
1266  return false;
1267  }
1268 
1269  int pIndex = resources->operationIndex(opName);
1270 
1271  bool canAssign = true;
1272 
1273  std::size_t maxSize = resources->maximalLatency() + modCycle;
1274  if (maxSize > ii) {
1275  maxSize = ii;
1276  }
1277 
1278  unsigned int rLat = resources->maximalLatency();
1279  unsigned int nRes = resources->numberOfResources();
1280 
1281  if (maxCycle_ != INT_MAX) {
1282  for (unsigned int i = 0; i < rLat && canAssign; i++) {
1283 
1284  for (unsigned int j = 0 ; j < nRes; j++) {
1285  // is this resource needed by this operation?
1286  if (resources->operationPipeline(pIndex,i,j)) {
1287  // is the resource free?
1288  if (((unsigned int)(cycle + i)) >
1289  (unsigned int)(maxCycle_)) {
1290  return false;
1291  }
1292  }
1293  }
1294  }
1295  }
1296 
1297  std::vector<std::vector<bool> >
1298  assigned(nRes, std::vector<bool>(rLat, false));
1299 
1300  unsigned int curSize = size();
1301  unsigned int fupSize = fuExecutionPipeline_.size();
1302  for (unsigned int i = 0; i < rLat && canAssign; i++) {
1303  unsigned int modci = instructionIndex(cycle+i);
1304 
1305  if (ii == INT_MAX) {
1306  if (modci >= curSize) {
1307  break;
1308  }
1309  } else {
1310  // may still fail on bigger value of i if overlaps,
1311  // so continue instead of break.
1312  if (fupSize <= modci) {
1313  continue;
1314  }
1315  }
1316 
1318  if (rrv.empty()) {
1319  continue;
1320  }
1321 
1322  for (unsigned int j = 0 ; j < resources->numberOfResources(); j++) {
1323 
1324  ResourceReservation& rr = rrv[j];
1325 
1326  // is this resource needed by this operation?
1327  if (resources->operationPipeline(pIndex,i,j)) {
1328  // is the resource free?
1329  if (rr.first != NULL) {
1330  // can still assign this with opposite guard?
1331  if (rr.second == NULL &&
1332  exclusiveMoves(rr.first, &node, modCycle)) {
1333  assigned[j][i] = true;
1334  rr.second = &node;
1335  } else { // fail.
1336  canAssign = false;
1337  break;
1338  }
1339  } else { // mark it used for this operation.
1340  assigned[j][i] = true;
1341  rr.first = &node;
1342  }
1343  }
1344  }
1345  }
1346 
1347  // reverts usage of this op to resource used table
1348  for (unsigned int i = 0; i < resources->maximalLatency(); i++) {
1349  for (unsigned int j = 0; j < resources->numberOfResources(); j++) {
1350  if (assigned[j][i]) {
1351  ResourceReservation& rr =
1353  // clear the usage.
1354  if (rr.first == &node) {
1355  assert(rr.second == NULL);
1356  rr.first = rr.second;
1357  rr.second = NULL;
1358  } else {
1359  if (rr.second == &node) {
1360  rr.second = NULL;
1361  } else {
1362  assert(0&& "assignment to undo not found");
1363  }
1364  }
1365  }
1366  }
1367 
1368  }
1369  return canAssign;
1370 }

References assert, canAssign(), TTAProgram::Move::destination(), exclusiveMoves(), fuExecutionPipeline_, ExecutionPipelineResourceTable::hasOperation(), TTAProgram::Terminal::hintOperation(), SchedulingResource::initiationInterval(), SchedulingResource::instructionIndex(), TTAProgram::Terminal::isOpcodeSetting(), maxCycle_, ExecutionPipelineResourceTable::maximalLatency(), MoveNode::move(), Operation::name(), ExecutionPipelineResourceTable::numberOfResources(), TTAProgram::Terminal::operation(), ExecutionPipelineResourceTable::operationIndex(), ExecutionPipelineResourceTable::operationPipeline(), resources, SparseVector< ValueType >::size(), and size().

Referenced by canAssignDestination().

Here is the call graph for this function:

◆ resultAllowedAtCycle()

bool ExecutionPipelineResource::resultAllowedAtCycle ( int  resultCycle,
const ProgramOperation po,
const TTAMachine::Port resultPort,
const MoveNode trigger,
int  triggerCycle 
) const
private

Tests that a new result at given cycle does not mess up result of some other operation

Parameters
resultCyclecycle when the nw result appears @po Programoperation which the new result belongs to @resultPort port where the result is written to @trigger trigger movenode of the operation @triggercycle cycle of the trigger

Definition at line 1852 of file ExecutionPipelineResource.cc.

1856  {
1857 
1858 #ifdef DEBUG_RM
1859  if (&trigger != NULL) {
1860  std::cerr << "\t\tChecking that result for po: " << po.toString() << " allowed at cycle "
1861  << resultCycle << " , trigger: " << trigger.toString() << " at cycle: " << triggerCycle << std::endl;
1862  } else {
1863  std::cerr << "\t\tChecking that result for po: " << po.toString() << " allowed at cycle "
1864  << resultCycle << " , trigger: NULL at cycle: " << triggerCycle << std::endl;
1865  }
1866 #endif
1867  // if none found from the map, this used.
1868  ResultVector empty;
1869  ResultMap::const_iterator rri = resultRead_.find(&resultPort);
1870 
1871  const ResultVector& resultRead = (rri != resultRead_.end()) ?
1872  rri->second : empty;
1873 
1874  unsigned int ii = initiationInterval_;
1875  if (ii < 1) {
1876  ii = INT_MAX;
1877  }
1878 
1879  unsigned int rrSize = resultRead.size();
1880  unsigned int rrMod = instructionIndex(resultCycle);
1881  for (unsigned int i = rrMod; i < rrMod + ii; i++) {
1882  unsigned int modi = instructionIndex(i);
1883  bool modiLooped = modi < rrMod;
1884 
1885  if (modi >= rrSize) {
1886  if (ii == INT_MAX) {
1887  break;
1888  } else {
1889  // may be read at small instr index of next iteration.
1890  // so may not abort, but can skip this cycle.
1891  continue;
1892  }
1893  }
1894  const ResultHelperPair& resultReadPair =
1895  MapTools::valueForKeyNoThrow<ResultHelperPair>(resultRead, modi);
1896  if (resultReadPair.first.count > 0) {
1897  // same operation reading result again. cannot fail.
1898  if (resultReadPair.first.po != &po) {
1899  assert (resultReadPair.first.po != NULL);
1900 
1901  // first check conflicts to first of po.
1902  MoveNode* otherTrigger =
1903  resultReadPair.first.po->triggeringMove();
1904  if (!exclusiveMoves(otherTrigger, &trigger, triggerCycle)) {
1905  if (resultReadPair.first.po == &po) {
1906  break;
1907  }
1908  // here check conflicts against first.
1909  int otherReady = resultReadyCycle(
1910  *resultReadPair.first.po, resultPort);
1911 
1912  if (otherReady == -1) {
1913  otherReady = modi;
1914  }
1915  int or2Mod = instructionIndex(otherReady);
1916  bool orLooped = or2Mod > (int)modi; // FAIL HERE?
1917 
1918 #ifdef DEBUG_RM
1919  std::cerr << "\t\t\tOther po: " << resultReadPair.first.po->toString() << std::endl;
1920  std::cerr << "\t\t\tOther ready: " << otherReady << std::endl;
1921  std::cerr << "\t\t\tRR cycle: " << rrMod << std::endl;
1922  std::cerr << "\t\t\tOther ready mod: " << or2Mod << std::endl;
1923 #endif
1924  // neither looped or both looped.
1925  if (modiLooped == orLooped) {
1926  if ((or2Mod <= (int)rrMod && or2Mod != -1) &&
1927  (triggerCycle == -1 || or2Mod != -1)) {
1928 #ifdef DEBUG_RM
1929  std::cerr << "\t\t\t\tfail(1)" << std::endl;
1930 #endif
1931  return false;
1932  } else {
1933  if (otherTrigger != NULL &&
1934  otherTrigger->move().isUnconditional()) {
1935  break;
1936  }
1937  }
1938  } else {
1939  // either one looped, order has to be reverse.
1940  if (or2Mod >= (int)rrMod && (triggerCycle == -1 || or2Mod != -1)) {
1941 #ifdef DEBUG_RM
1942  std::cerr << "\t\t\t\tfail(2)" << std::endl;
1943 #endif
1944  return false;
1945  } else {
1946  if (otherTrigger != NULL &&
1947  otherTrigger->move().isUnconditional()) {
1948  break;
1949  }
1950  }
1951  }
1952  }
1953  }
1954 
1955  // then check conflicts to second po
1956  if (resultReadPair.second.count > 0) {
1957  MoveNode* otherTrigger =
1958  resultReadPair.second.po->triggeringMove();
1959  if (!exclusiveMoves(otherTrigger, &trigger, triggerCycle)) {
1960  if (resultReadPair.second.po == &po) {
1961  break;
1962  }
1963  int otherReady = resultReadyCycle(
1964  *resultReadPair.second.po, resultPort);
1965 
1966  int or2Mod = instructionIndex(otherReady);
1967  bool orLooped = or2Mod > (int)modi;
1968 
1969  // neither looped or both looped.
1970  if (modiLooped == orLooped) {
1971  if (or2Mod <= (int)rrMod &&
1972  (triggerCycle == -1 || or2Mod != -1)) {
1973 #ifdef DEBUG_RM
1974  std::cerr << "\t\t\t\tfail(3)" << std::endl;
1975 #endif
1976  return false;
1977  } else {
1978  if (otherTrigger != NULL &&
1979  otherTrigger->move().isUnconditional()) {
1980  break;
1981  }
1982  }
1983  } else {
1984  // either looped, order has to be reverse.
1985  if (or2Mod >= (int)rrMod &&
1986  (triggerCycle == -1 || or2Mod != -1)) {
1987 #ifdef DEBUG_RM
1988  std::cerr << "\t\t\t\tfail(4)" << std::endl;
1989 #endif
1990  return false;
1991  } else {
1992  if (otherTrigger != NULL &&
1993  otherTrigger->move().isUnconditional()) {
1994  break;
1995  }
1996  }
1997  }
1998  }
1999  }
2000  }
2001  }
2002  return true;
2003 }

References assert, exclusiveMoves(), SchedulingResource::initiationInterval_, SchedulingResource::instructionIndex(), TTAProgram::Move::isUnconditional(), MoveNode::move(), resultPort(), resultRead_, resultReadyCycle(), SparseVector< ValueType >::size(), MoveNode::toString(), and ProgramOperation::toString().

Referenced by canAssignSource(), and testTriggerResult().

Here is the call graph for this function:

◆ resultCausesTriggerBetweenOperandSharing()

bool ExecutionPipelineResource::resultCausesTriggerBetweenOperandSharing ( const MoveNode mn,
int  cycle 
) const
private

Definition at line 2488 of file ExecutionPipelineResource.cc.

2489  {
2490 
2491  if (!operandShareCount_) {
2492  return false;
2493  }
2494 
2495  if (!mn.isSourceOperation()) {
2496  return false;
2497  }
2498  ProgramOperation& po = mn.sourceOperation();
2499  const MoveNode* trigger = po.findTriggerFromUnit(fu_);
2500  // if trigger is already scheduled, the checks have been done
2501  // while scheduling it.
2502  if (trigger == nullptr || trigger->isScheduled()) {
2503  return false;
2504  }
2505  const int outputIndex = po.outputIndexOfMove(mn);
2506  const TTAMachine::HWOperation& hwop =
2507  *fu_.operation(po.operation().name());
2508  const TTAMachine::Port* outPort = hwop.port(outputIndex);
2509  int latency = hwop.latency(outputIndex);
2510  int latestTriggerCycle = cycle - latency;
2511 
2512  std::map<const TTAMachine::Port*, const MoveNode*> usedOperandPorts;
2513 
2514  // result vector for the correct port
2515  auto rvi = resultRead_.find(outPort);
2516  if (rvi == resultRead_.end()) {
2517  return false;
2518  }
2519  auto& rv = rvi->second;
2520 
2521  int smallestCycle = (*rv.begin()).first;
2522  int earliestAllowedResReady = -1;
2523 
2524  for (int c = cycle-1;c >= smallestCycle;c--) {
2525  int mc = instructionIndex(c);
2526  auto ri = rv.find(mc);
2527  if (ri == rv.end()) {
2528  continue;
2529  }
2530  auto res = ri->second;
2531  ResultHelper& rh1 = res.first;
2532  ResultHelper& rh2 = res.second;
2533 
2534  if (rh1.po != nullptr && rh1.po != &po) {
2535  int rc = rh1.realCycle;
2536  if (!exclusiveMoves(trigger, rh1.po->triggeringMove(), c-latency)) {
2537  earliestAllowedResReady = rc +1;
2538  break;
2539  }
2540  }
2541 
2542  if (rh2.po != nullptr && rh2.po != &po) {
2543  int rc = rh2.realCycle;
2544  if (!exclusiveMoves(trigger, rh2.po->triggeringMove(), c-latency)) {
2545  earliestAllowedResReady = rc +1;
2546  break;
2547  }
2548  }
2549  }
2550 
2551  if (earliestAllowedResReady == -1) {
2552  return false;
2553  }
2554 
2555  int earliestTriggerCycle = earliestAllowedResReady - latency;
2556 
2557  // if overlaps between earliest and last trigger
2558  if (earliestTriggerCycle > latestTriggerCycle &&
2559  initiationInterval_ != 0) {
2560  earliestTriggerCycle -= initiationInterval_;
2561  }
2562 
2563 #ifdef DEBUG_RM
2564  std::cerr << "\t\t\t\tEarliest allowed res ready: "
2565  << earliestAllowedResReady << std::endl;
2566  std::cerr << "\t\t\t\tEarliestTrigger cycle: "
2567  << earliestTriggerCycle << std::endl;
2568  std::cerr << "\t\t\t\tLatestTrigger cycle: "
2569  << latestTriggerCycle << std::endl;
2570 #endif
2571 
2572  bool ok = false;
2573  for (int c = latestTriggerCycle; c >= earliestTriggerCycle && !ok ; c--) {
2574 
2575  bool fail = false;
2576  for (int i = 0; i < po.inputMoveCount(); i++) {
2577  const MoveNode& inMove = po.inputMove(i);
2578  if (!inMove.move().destination().isFUPort()) {
2579  continue;
2580  }
2581  const int inputIndex =
2582  inMove.move().destination().operationIndex();
2583  const TTAMachine::HWOperation& hwop =
2584  *fu_.operation(po.operation().name());
2585  auto inPort = hwop.port(inputIndex);
2586  if (!inPort->isTriggering()) {
2587  if (!operandAllowedAtCycle(*inPort, inMove,c)) {
2588  fail = true;
2589 #ifdef DEBUG_RM
2590  std::cerr << "\t\t\t\t\tOperand not allowed at cycle: " << c << std::endl;
2591 #endif
2592  continue;
2593  }
2594  }
2595  }
2596  if (!fail) {
2597  return false;
2598  }
2599  }
2600  return true;
2601 }

References TTAProgram::Move::destination(), exclusiveMoves(), ProgramOperation::findTriggerFromUnit(), fu_, SchedulingResource::initiationInterval_, ProgramOperation::inputMove(), ProgramOperation::inputMoveCount(), SchedulingResource::instructionIndex(), TTAProgram::Terminal::isFUPort(), MoveNode::isScheduled(), MoveNode::isSourceOperation(), TTAMachine::HWOperation::latency(), MoveNode::move(), Operation::name(), operandAllowedAtCycle(), operandShareCount_, TTAMachine::FunctionUnit::operation(), ProgramOperation::operation(), TTAProgram::Terminal::operationIndex(), ProgramOperation::outputIndexOfMove(), ExecutionPipelineResource::ResultHelper::po, TTAMachine::HWOperation::port(), ExecutionPipelineResource::ResultHelper::realCycle, resultRead_, MoveNode::sourceOperation(), and ProgramOperation::triggeringMove().

Referenced by canAssignSource().

Here is the call graph for this function:

◆ resultNotOverWritten()

bool ExecutionPipelineResource::resultNotOverWritten ( int  resultReadCycle,
int  resultReadyCycle,
const MoveNode node,
const TTAMachine::Port resultPort,
const MoveNode trigger,
int  triggerCycle 
) const

Returns if the result can be scheduled to given cycle so that the results of other operations do not overwrite it.

Parameters
resultReadCyclecycle when the result is read
resultReadyCyclecycle when the result becomes available
poProgramOperation where the result move belongs
nodethe result read node being scheduled
resultPortthe port which is being read by the result
triggerTrigger of the program operation
triggercyclecycle of the trigger of the PO

Definition at line 2048 of file ExecutionPipelineResource.cc.

2051  {
2052  unsigned int rrMod = instructionIndex(resultReadyCycle);
2053 
2054  unsigned int modCycle = instructionIndex(resultReadCycle);
2055  unsigned int ii = initiationInterval_;
2056  if (ii < 1) {
2057  // no loop scheduling.
2058  ii = INT_MAX;
2059  } else {
2060  // loop scheudling.
2061  // make sure opeation does not cause conflict
2062  // with itself on next loop iteration.
2063  if (resultReadyCycle + (int)ii <= resultReadCycle) {
2064  return false;
2065  }
2066  }
2067  // Test when some other PO will write result to result register
2068  // starting from cycle when result could be ready
2069  int otherResult = nextResultCycle(
2070  resultPort, resultReadyCycle, node, trigger, triggerCycle);
2071  int orMod = instructionIndex(otherResult);
2072 
2073  if (otherResult == INT_MAX && ii != INT_MAX) {
2074  orMod = INT_MAX;
2075  }
2076 
2077  // overlaps between these.
2078  // TODO: these checks fail. true when no ii.
2079  if (orMod < (int)rrMod) {
2080  // overlaps between these. both overlap, oridinary comparison.
2081  if (modCycle < rrMod && orMod <= (int)modCycle) {
2082  // Result will be overwritten before we will read it
2083  return false;
2084  }
2085  // is cycle does not overlap, it's earlier, so does not fail.
2086  } else {
2087  // overlaps between these. it's later, fails.
2088  // neither overlaps. ordinary comparison.
2089  if ((rrMod != INT_MAX && orMod != INT_MAX && modCycle < rrMod) ||
2090  orMod <= (int)modCycle) {
2091  // Result will be overwritten before we will read it
2092 #ifdef DEBUG_RM
2093  std::cerr << "\t\t\t\tresultnotoverwritten returning fail, rrmod:"
2094  << rrMod << " ormod: " << orMod << " modcycle: "
2095  << modCycle << std::endl;
2096 #endif
2097  return false;
2098  }
2099  }
2100  return true;
2101 }

References SchedulingResource::initiationInterval_, SchedulingResource::instructionIndex(), nextResultCycle(), resultPort(), and resultReadyCycle().

Referenced by canAssignSource(), ExecutionPipelineBroker::earliestFromSource(), and testTriggerResult().

Here is the call graph for this function:

◆ resultPort()

const TTAMachine::Port & ExecutionPipelineResource::resultPort ( const MoveNode mn) const
private

Gives the port where from the movenode reads a result.

Definition at line 2010 of file ExecutionPipelineResource.cc.

2010  {
2011  if (mn.isSourceOperation()) {
2012  const ProgramOperation& po = mn.sourceOperation();
2013  const TTAMachine::HWOperation& hwop =
2014  *fu_.operation(po.operation().name());
2015  return *hwop.port(mn.move().source().operationIndex());
2016  } else {
2017  assert(mn.isGuardOperation());
2018  return *(static_cast<const TTAMachine::PortGuard&>(
2019  mn.move().guard().guard())).port();
2020  }
2021 }

References assert, fu_, TTAProgram::MoveGuard::guard(), TTAProgram::Move::guard(), MoveNode::isGuardOperation(), MoveNode::isSourceOperation(), MoveNode::move(), Operation::name(), TTAMachine::FunctionUnit::operation(), ProgramOperation::operation(), TTAProgram::Terminal::operationIndex(), TTAMachine::HWOperation::port(), TTAProgram::Move::source(), and MoveNode::sourceOperation().

Referenced by assignSource(), canAssignSource(), resultAllowedAtCycle(), resultNotOverWritten(), resultReadyCycle(), and unassignSource().

Here is the call graph for this function:

◆ resultReadyCycle()

int ExecutionPipelineResource::resultReadyCycle ( const ProgramOperation po,
const TTAMachine::Port resultPort 
) const
private

Returns cycle when result of some PO is ready.

Parameters
poprogramoperation int resultReadCycle cycle when the result is read

@TODO: multiple out values still not supported correctly.

Definition at line 1677 of file ExecutionPipelineResource.cc.

1678  {
1679 
1680  MoveNode* trigger = po.triggeringMove();
1681  if (trigger == NULL || !trigger->isPlaced()) {
1682 #ifdef DEBUG_RM
1683  std::cerr << "\t\t\t\tTrigger NULL or not scheduled: "
1684  << po.toString() << std::endl;
1685 #endif
1686  return -1;
1687  }
1688 
1689  const Operation& op = po.operation();
1691  for (int i = 0; i < op.numberOfOutputs(); i++) {
1692  int outIndex = op.numberOfInputs() + 1 + i;
1693  const TTAMachine::Port *p = hwop.port(outIndex);
1694  if (p == &resultPort) {
1695  return trigger->cycle() + hwop.latency(outIndex);
1696  }
1697  }
1698 #ifdef DEBUG_RM
1699  std::cerr << "\t\t\t\treturning -1 at end of rrcycle() " << std::endl;
1700 #endif
1701  return -1;
1702 }

References MoveNode::cycle(), fu_, MoveNode::isPlaced(), TTAMachine::HWOperation::latency(), Operation::name(), Operation::numberOfInputs(), Operation::numberOfOutputs(), TTAMachine::FunctionUnit::operation(), ProgramOperation::operation(), TTAMachine::HWOperation::port(), resultPort(), ProgramOperation::toString(), and ProgramOperation::triggeringMove().

Referenced by resultAllowedAtCycle(), and resultNotOverWritten().

Here is the call graph for this function:

◆ setDDG()

void ExecutionPipelineResource::setDDG ( const DataDependenceGraph ddg)

Definition at line 1776 of file ExecutionPipelineResource.cc.

1776  {
1777  ddg_ = ddg;
1778 }

References ddg_.

◆ setMaxCycle()

virtual void ExecutionPipelineResource::setMaxCycle ( unsigned int  maxCycle)
inlineoverridevirtual

Reimplemented from SchedulingResource.

Definition at line 116 of file ExecutionPipelineResource.hh.

116 { maxCycle_ = maxCycle; }

References maxCycle_.

◆ setOperandsUsed()

void ExecutionPipelineResource::setOperandsUsed ( const ProgramOperation po,
unsigned int  triggerCycle 
)
private

Definition at line 283 of file ExecutionPipelineResource.cc.

284  {
285 
286  const Operation& op = po.operation();
287  TTAMachine::HWOperation& hwop = *fu_.operation(op.name());
288 
289  // Loops over all output values produced by this
290  for (int i = 0; i < op.numberOfInputs(); i++) {
291  const TTAMachine::Port& port = *hwop.port(i+1);
292  int operandUseCycle = triggerCycle + hwop.slack(i+1);
293 
294  setOperandUsed(port, operandUseCycle, po);
295  }
296 }

References fu_, Operation::name(), Operation::numberOfInputs(), TTAMachine::FunctionUnit::operation(), ProgramOperation::operation(), TTAMachine::HWOperation::port(), setOperandUsed(), and TTAMachine::HWOperation::slack().

Referenced by assignDestination().

Here is the call graph for this function:

◆ setOperandUsed()

void ExecutionPipelineResource::setOperandUsed ( const TTAMachine::Port port,
unsigned int  realCycle,
const ProgramOperation po 
)
private

Definition at line 241 of file ExecutionPipelineResource.cc.

243  {
244 
245  OperandUseVector& operandUsed = operandsUsed_[&port];
246  unsigned int modCycle = instructionIndex(realCycle);
247 
248  OperandUsePair& oup = operandUsed[modCycle];
249  if (oup.first.po == NULL) {
250  oup.first.po = &po;
251  } else {
252  if (oup.first.realCycle == realCycle &&
253  oup.first.po == &po) {
254  assert(false);
255  } else {
256  if (oup.second.po == NULL) {
257  oup.second.po = &po;
258  } else {
259  assert(false);
260  }
261  }
262  }
263 }

References assert, SchedulingResource::instructionIndex(), and operandsUsed_.

Referenced by setOperandsUsed().

Here is the call graph for this function:

◆ setResultWriten() [1/2]

void ExecutionPipelineResource::setResultWriten ( const ProgramOperation po,
unsigned int  triggerCycle 
)
private

Definition at line 266 of file ExecutionPipelineResource.cc.

267  {
268 
269  const Operation& op = po.operation();
270  TTAMachine::HWOperation& hwop = *fu_.operation(op.name());
271 
272  // Loops over all output values produced by this
273  for (int i = 0; i < op.numberOfOutputs(); i++) {
274  int outIndex = op.numberOfInputs() + 1 + i;
275  const TTAMachine::Port& port = *hwop.port(outIndex);
276  int resultCycle = triggerCycle + hwop.latency(outIndex);
277 
278  setResultWriten(port, resultCycle, po);
279  }
280 }

References fu_, TTAMachine::HWOperation::latency(), Operation::name(), Operation::numberOfInputs(), Operation::numberOfOutputs(), TTAMachine::FunctionUnit::operation(), ProgramOperation::operation(), TTAMachine::HWOperation::port(), and setResultWriten().

Here is the call graph for this function:

◆ setResultWriten() [2/2]

void ExecutionPipelineResource::setResultWriten ( const TTAMachine::Port port,
unsigned int  realCycle,
const ProgramOperation po 
)
private

Definition at line 211 of file ExecutionPipelineResource.cc.

213  {
214 
215  ResultVector& resultWriten = resultWriten_[&port];
216 
217  unsigned int modCycle = instructionIndex(realCycle);
218 
219  ResultHelperPair& rhp = resultWriten[modCycle];
220  if (rhp.first.po == NULL) {
221  rhp.first = ResultHelper(realCycle, &po, 1);
222  } else {
223  if (rhp.first.realCycle == realCycle &&
224  rhp.first.po == &po) {
225  rhp.first.count++;
226  } else {
227  if (rhp.second.po == NULL) {
228  rhp.second = ResultHelper(realCycle, &po, 1);
229  } else {
230  rhp.second.count++;
231  }
232  }
233  }
234 }

References SchedulingResource::instructionIndex(), and resultWriten_.

Referenced by assignDestination(), assignSource(), and setResultWriten().

Here is the call graph for this function:

◆ size()

unsigned int ExecutionPipelineResource::size ( ) const
protected

Return number of cycles current execution pipeline for FU contains. Effectively, highest cycle in which any of the resources of an FU is occupied plus 1.

Returns
Number of cycles in pipeline.

Definition at line 1417 of file ExecutionPipelineResource.cc.

1417  {
1418 
1419 #if 0
1420  // Breaks for load and store units with internal pipeline resources!!!
1421  if (cachedSize_ != INT_MIN ) {
1422  return cachedSize_;
1423  }
1424 #endif
1425  int length = fuExecutionPipeline_.size() - 1;
1426  int dstCount = assignedDestinationNodes_.size();
1427  int srcCount = assignedSourceNodes_.size();
1428  // If there are no sources or destinations
1429  // assigned then the pipeline has to be empty.
1430  // No point searching whole empty range
1431  if (length == -1 || (dstCount == 0 && srcCount ==0)) {
1432  cachedSize_ = 0;
1433  return 0;
1434  }
1435  int stoppingCycle = length;
1436  if (dstCount > 0) {
1437  int dstMin = (*assignedDestinationNodes_.begin()).first;
1438  stoppingCycle = std::min(stoppingCycle, dstMin);
1439  }
1440  if (srcCount > 0) {
1441  int srcMin = (*assignedSourceNodes_.begin()).first;
1442  stoppingCycle = std::min(stoppingCycle, srcMin);
1443  }
1444  // Don't go bellow smallest known assigned node
1445  for (int i = length; i >= stoppingCycle; i--) {
1446  ResourceReservationTable::const_iterator iter =
1447  fuExecutionPipeline_.find(i);
1448  if (iter == fuExecutionPipeline_.end()) {
1449  continue;
1450  } else {
1451  const ResourceReservationVector& rrv = iter->second;
1452  if (rrv.size() == 0) {
1453  continue;
1454  }
1455 
1456  for (unsigned int j = 0; j < resources->numberOfResources(); j++) {
1457  const ResourceReservation& rr = rrv[j];
1458  if (rr.first != NULL) {
1459  cachedSize_ = i + 1;
1460  return i + 1;
1461  }
1462  }
1463  }
1464  }
1465  cachedSize_ = 0;
1466  return 0;
1467 }

References assignedDestinationNodes_, assignedSourceNodes_, cachedSize_, fuExecutionPipeline_, ExecutionPipelineResourceTable::numberOfResources(), resources, and SparseVector< ValueType >::size().

Referenced by assignDestination(), highestKnownCycle(), isInUse(), resourcesAllowTrigger(), and unassignDestination().

Here is the call graph for this function:

◆ testTriggerResult()

bool ExecutionPipelineResource::testTriggerResult ( const MoveNode trigger,
int  cycle 
) const
private

Tests the conflicts caused by results if a trigger is scheduled to given cycle.

Definition at line 1785 of file ExecutionPipelineResource.cc.

1786  {
1787  ProgramOperation& po = trigger.destinationOperation();
1788  const Operation& op = po.operation();
1789  TTAMachine::HWOperation& hwop = *fu_.operation(op.name());
1790 
1791  // Loops over all output values produced by this
1792  for (int i = 0; i < op.numberOfOutputs(); i++) {
1793  int outIndex = op.numberOfInputs() + 1 + i;
1794  const TTAMachine::Port& port = *hwop.port(outIndex);
1795  int resultCycle = cycle + hwop.latency(outIndex);
1796 
1797  if (!resultAllowedAtCycle(
1798  resultCycle, po, port, trigger, cycle)) {
1799  return false;
1800  }
1801 
1802  if (initiationInterval_ != 0 &&
1803  hwop.latency(outIndex) > (int)initiationInterval_) {
1804  return false;
1805  }
1806  }
1807 
1808  // If we have alreayd scheduled some result, we have to make sure
1809  // nobody overwrites it.
1810  for (int i = 0; i < po.outputMoveCount(); i++) {
1811  MoveNode& mn = po.outputMove(i);
1812  if (mn.isPlaced()) {
1813  int outIndex = -1;
1814  if (mn.isSourceOperation() && &mn.sourceOperation() == &po) {
1815  assert(mn.move().source().isFUPort());
1816  outIndex = mn.move().source().operationIndex();
1817  } else {
1818  assert (mn.isGuardOperation() && &mn.guardOperation() == &po);
1819  outIndex = po.outputIndexFromGuardOfMove(mn);
1820  }
1821  const TTAMachine::Port& port = *hwop.port(outIndex);
1822  int resultCycle = cycle + hwop.latency(outIndex);
1823  // WAW conflict of result on same op on different iteration?
1824  if (initiationInterval_ != 0 && isLoopBypass(mn) && mn.cycle() >= resultCycle) {
1825 #ifdef DEBUG_RM
1826  std::cerr << "\t\t\t\tresult move: " << mn.toString()
1827  << " schedule too late: " << resultCycle << std::endl;
1828 #endif
1829  return false;
1830  }
1831  if (!resultNotOverWritten(
1832  mn.cycle(), resultCycle, mn, port, &trigger, cycle)) {
1833  return false;
1834  }
1835  }
1836  }
1837  return true;
1838 
1839 }

References assert, MoveNode::cycle(), MoveNode::destinationOperation(), fu_, MoveNode::guardOperation(), SchedulingResource::initiationInterval_, TTAProgram::Terminal::isFUPort(), MoveNode::isGuardOperation(), isLoopBypass(), MoveNode::isPlaced(), MoveNode::isSourceOperation(), TTAMachine::HWOperation::latency(), MoveNode::move(), Operation::name(), Operation::numberOfInputs(), Operation::numberOfOutputs(), TTAMachine::FunctionUnit::operation(), ProgramOperation::operation(), TTAProgram::Terminal::operationIndex(), ProgramOperation::outputIndexFromGuardOfMove(), ProgramOperation::outputMove(), ProgramOperation::outputMoveCount(), TTAMachine::HWOperation::port(), resultAllowedAtCycle(), resultNotOverWritten(), TTAProgram::Move::source(), MoveNode::sourceOperation(), and MoveNode::toString().

Referenced by canAssignDestination().

Here is the call graph for this function:

◆ triggerAllowedAtCycle()

bool ExecutionPipelineResource::triggerAllowedAtCycle ( int  inputCount,
const TTAMachine::HWOperation hwop,
const MoveNode node,
int  cycle 
) const
private

Definition at line 2369 of file ExecutionPipelineResource.cc.

2373  {
2374  for (int i = 1; i <= inputCount; i++) {
2375  TTAMachine::FUPort& port = *hwop.port(i);
2376  if (!operandAllowedAtCycle(port, node, cycle)) {
2377  return false;
2378  }
2379  }
2380  return true;
2381 }

References operandAllowedAtCycle(), and TTAMachine::HWOperation::port().

Referenced by canAssignDestination().

Here is the call graph for this function:

◆ triggerTooEarly()

bool ExecutionPipelineResource::triggerTooEarly ( const MoveNode trigger,
int  cycle 
) const
private

Checks that trigger is not scheduled too early(before operand-slack)

Definition at line 2327 of file ExecutionPipelineResource.cc.

2327  {
2328  ProgramOperation& po = trigger.destinationOperation(0);
2329  const Operation& op = po.operation();
2330  TTAMachine::HWOperation& hwop = *fu_.operation(op.name());
2331 #ifdef DEBUG_RM
2332  std::cerr << "\t\t\t\tTesting if trigger too early for: " << trigger.toString() << " PO: " << po.toString() << std::endl;
2333 #endif
2334  for (int i = 0; i < po.inputMoveCount(); i++) {
2335  MoveNode& mn = po.inputMove(i);
2336 #ifdef DEBUG_RM
2337  std::cerr << "\t\t\t\tTesting operand: " << mn.toString() << std::endl;
2338 #endif
2339  if (mn.isPlaced()) {
2340 #ifdef DEBUG_RM
2341  std::cerr << "\t\t\t\tCycle: " << mn.cycle() << ", ";
2342 #endif
2343  int slack = hwop.slack(mn.move().destination().operationIndex());
2344  const TTAMachine::Port& port = mn.move().destination().port();
2345  const TTAMachine::FUPort& fuPort =
2346  dynamic_cast<const TTAMachine::FUPort&>(port);
2347 
2348 #ifdef DEBUG_RM
2349  std::cerr << "slack(" << mn.move().destination().operationIndex()
2350  << ")=" << slack << ", noReg=" << fuPort.noRegister()
2351  << std::endl;
2352 #endif
2353 
2354  if (fuPort.noRegister()) {
2355  if (cycle != mn.cycle() - slack) {
2356  return true;
2357  }
2358  } else {
2359  if (cycle < mn.cycle() - slack) {
2360  return true;
2361  }
2362  }
2363  }
2364  }
2365  return false;
2366 }

References MoveNode::cycle(), TTAProgram::Move::destination(), MoveNode::destinationOperation(), fu_, ProgramOperation::inputMove(), ProgramOperation::inputMoveCount(), MoveNode::isPlaced(), MoveNode::move(), Operation::name(), TTAMachine::FUPort::noRegister(), TTAMachine::FunctionUnit::operation(), ProgramOperation::operation(), TTAProgram::Terminal::operationIndex(), TTAProgram::Terminal::port(), TTAMachine::HWOperation::slack(), MoveNode::toString(), and ProgramOperation::toString().

Referenced by canAssignDestination().

Here is the call graph for this function:

◆ unassign()

void ExecutionPipelineResource::unassign ( const int  cycle,
MoveNode node 
)
overridevirtual

Implements SchedulingResource.

Definition at line 582 of file ExecutionPipelineResource.cc.

582  {
583  abortWithError("Execution Pipeline Resource needs 3 arguments unassign");
584 }

References abortWithError.

◆ unassignDestination()

void ExecutionPipelineResource::unassignDestination ( const int  cycle,
MoveNode node 
)
virtual

Unassign resource from given node for given cycle.

Parameters
cycleCycle to remove assignment from
nodeMoveNode to remove assignment from in case move is bypassed
Exceptions
Incase there was no previous assignment or wrong operation is unassigned

Now unassing destination part of move

Definition at line 676 of file ExecutionPipelineResource.cc.

678  {
679 
680 #ifdef DEBUG_RM
681  std::cerr << "\tUnassigning destination: " << node.toString() << std::endl;
682 #endif
683 
684  if (!node.isDestinationOperation()) {
685 #ifdef DEBUG_RM
686  std::cerr << "\t\tNot dest operatioN!" << std::endl;
687 #endif
688  return;
689  }
690 
691  int modCycle = instructionIndex(cycle);
692  unsigned int ii = initiationInterval_;
693  if (ii < 1) {
694  ii = INT_MAX;
695  }
696 
698 #ifdef DEBUG_RM
699  std::cerr << "\t\t assigned destinations not contain!" << std::endl;
700 #endif
701  return;
702  }
703  /// Now unassing destination part of move
705 
706  const TTAMachine::Port& opPort = operandPort(node);
707  MoveNodePtrPair& mnpp = operandsWriten_[&opPort][modCycle];
708  assert (mnpp.first != NULL);
709  if (mnpp.second == &node) {
710  mnpp.second = NULL;
711  } else {
712  assert(mnpp.first == &node);
713  mnpp.first = mnpp.second;
714  mnpp.second = NULL;
715  }
716 
717  // if not trigger, we are done
718  // TODO: correct trigger or UM trigger?
719  if (!node.move().destination().isTriggering()) {
720 #ifdef DEBUG_RM
721  std::cerr << "\t\t not trigger!" << std::endl;
722 #endif
723 
724  if (node.destinationOperationCount() > 1) {
726  }
727  return;
728  }
729 
730  assert(node.destinationOperationCount() == 1);
731 
732  unsetOperandsUsed(node.destinationOperation(), cycle);
734 
735  std::string opName = "";
736  if (node.move().destination().isOpcodeSetting()) {
737  opName = node.move().destination().operation().name();
738  } else {
739  opName = node.move().destination().hintOperation().name();
740  }
741  if (!resources->hasOperation(opName)) {
742  std::string msg = "Trying to unassign operation \'";
743  msg += opName ;
744  msg += "\' not supported on FU!";
745  throw ModuleRunTimeError(__FILE__, __LINE__, __func__, msg);
746  }
747 
748  // Cannot trust size() since that one ignores empty pipeline
749  // and here we need to go up to the maximalLatency.
750  size_t fuEpSize = fuExecutionPipeline_.size();
751  if ((size_t)instructionIndex(cycle + resources->maximalLatency() - 1)
752  >= fuEpSize) {
753  std::string msg = "Unassigning operation longer then scope!";
754  msg += " - cycle:";
755  msg += Conversion::toString(cycle);
756  msg += " - scope:";
757  msg += Conversion::toString(fuEpSize);
758  msg += " - ii:";
760  throw ModuleRunTimeError(__FILE__, __LINE__, __func__, msg);
761  }
762  for (unsigned int i = 0; i < resources->maximalLatency(); i++) {
763  int modic = instructionIndex(cycle+i);
764  for (unsigned int j = 0 ; j < resources->numberOfResources(); j++) {
765  assert(
766  fuExecutionPipeline_[modic].size() != 0);
767  ResourceReservation& rr =
768  fuExecutionPipeline_[modic][j];
769  if (rr.first == &node) {
771  resources->operationIndex(opName),i,j) &&
772  "unassigning pipeline res not used by this op");
773 
774  rr.first = rr.second;
775  rr.second = NULL;
776  } else {
777  if (rr.second == &node) {
779  resources->operationIndex(opName),i,j) &&
780  "unassigning pipeline res not used by this op");
781 
782  rr.second = NULL;
783  }
784  }
785  }
786  }
787 }

References __func__, assert, assignedDestinationNodes_, MapTools::containsValue(), TTAProgram::Move::destination(), MoveNode::destinationOperation(), MoveNode::destinationOperationCount(), fuExecutionPipeline_, ExecutionPipelineResourceTable::hasOperation(), TTAProgram::Terminal::hintOperation(), SchedulingResource::initiationInterval_, SchedulingResource::instructionIndex(), MoveNode::isDestinationOperation(), TTAProgram::Terminal::isOpcodeSetting(), TTAProgram::Terminal::isTriggering(), ExecutionPipelineResourceTable::maximalLatency(), MoveNode::move(), Operation::name(), ExecutionPipelineResourceTable::numberOfResources(), operandPort(), operandShareCount_, operandsWriten_, TTAProgram::Terminal::operation(), ExecutionPipelineResourceTable::operationIndex(), ExecutionPipelineResourceTable::operationPipeline(), MapTools::removeItemsByValue(), resources, SparseVector< ValueType >::size(), size(), Conversion::toString(), MoveNode::toString(), unsetOperandsUsed(), and unsetResultWriten().

Referenced by InputFUResource::unassign().

Here is the call graph for this function:

◆ unassignSource()

void ExecutionPipelineResource::unassignSource ( const int  cycle,
MoveNode node 
)
virtual

Unassign resource from given node for given cycle.

Parameters
cycleCycle to remove assignment from
nodeMoveNode to remove assignment from
sourceIndicates if we want to unassign source part of move in case move is bypassed
Exceptions
Incase there was no previous assignment or wrong operation is unassigned

Unscheduling result read

Remove record of result beeing written to result register or decrease count in case there are more results

Remove record or decrease count of result read moves

Remove record or decrease count of result read moves

Definition at line 597 of file ExecutionPipelineResource.cc.

599  {
600  cachedSize_ = INT_MIN;
601 
602  int modCycle = instructionIndex(cycle);
603  unsigned int ii = initiationInterval_;
604  if (ii < 1) {
605  ii = INT_MAX;
606  }
607 
608  if (node.cycle() != cycle) {
609  throw InvalidData(__FILE__, __LINE__, __func__,
610  "Trying to unassign node from different cycle "
611  "then it was assigned to!");
612  }
613 
614  const TTAMachine::Port& port = resultPort(node);
615  ResultVector& resultRead = resultRead_[&port];
616  ProgramOperation& po = node.isSourceOperation() ?
617  node.sourceOperation() :
618  node.guardOperation();
619 
620  /// Unscheduling result read
623 
625  /// Remove record of result beeing written to result register
626  /// or decrease count in case there are more results
627  unsigned int resultReady =
628  MapTools::valueForKey<int>(storedResultCycles_, &node);
629 
630  unsetResultWriten(port, resultReady, po);
631  storedResultCycles_.erase(&node);
632 
633  // assert fail is much nicer than unknown exception.
634  assert(modCycle < (int)resultRead.size());
635  ResultHelperPair& resultReadPair = resultRead[modCycle];
636 
637  if (resultReadPair.first.po == &po) {
638  /// Remove record or decrease count of result read moves
639  resultReadPair.first.count--;
640  if (resultReadPair.first.count == 0) {
641  if (resultReadPair.second.count == 0) {
642  // erase from the bookkeeping, this is empty.
643  resultRead.erase(modCycle);
644  } else {
645  resultReadPair.first = resultReadPair.second;
646  resultReadPair.second.count = 0;
647  resultReadPair.second.realCycle = modCycle;
648  resultReadPair.second.po = NULL;
649  }
650  }
651  } else {
652  if (resultReadPair.second.po == &po) {
653  ///Remove record or decrease count of result read moves
654  resultReadPair.second.count--;
655  if (resultReadPair.second.count == 0) {
656  resultReadPair.second.realCycle = modCycle;
657  resultReadPair.second.po = NULL;
658  }
659  }
660  }
661  }
662  }
663 }

References __func__, assert, assignedSourceNodes_, cachedSize_, MapTools::containsKey(), MapTools::containsValue(), MoveNode::cycle(), MoveNode::guardOperation(), SchedulingResource::initiationInterval_, SchedulingResource::instructionIndex(), MoveNode::isSourceOperation(), MapTools::removeItemsByValue(), resultPort(), resultRead_, SparseVector< ValueType >::size(), MoveNode::sourceOperation(), storedResultCycles_, and unsetResultWriten().

Referenced by OutputFUResource::unassign().

Here is the call graph for this function:

◆ unsetOperandsUsed()

void ExecutionPipelineResource::unsetOperandsUsed ( const ProgramOperation po,
unsigned int  triggerCycle 
)
private

Definition at line 377 of file ExecutionPipelineResource.cc.

378  {
379 
380  const Operation& op = po.operation();
381  TTAMachine::HWOperation& hwop = *fu_.operation(op.name());
382 
383  // Loops over all output values produced by this
384  for (int i = 0; i < op.numberOfInputs(); i++) {
385  const TTAMachine::Port& port = *hwop.port(i+1);
386  int resultCycle = triggerCycle + hwop.slack(i+1);
387  unsetOperandUsed(port, resultCycle, po);
388  }
389 }

References fu_, Operation::name(), Operation::numberOfInputs(), TTAMachine::FunctionUnit::operation(), ProgramOperation::operation(), TTAMachine::HWOperation::port(), TTAMachine::HWOperation::slack(), and unsetOperandUsed().

Referenced by unassignDestination().

Here is the call graph for this function:

◆ unsetOperandUsed()

void ExecutionPipelineResource::unsetOperandUsed ( const TTAMachine::Port port,
unsigned int  realCycle,
const ProgramOperation po 
)
private

Definition at line 336 of file ExecutionPipelineResource.cc.

338  {
339  unsigned int modCycle = instructionIndex(realCycle);
340 
341  OperandUseVector& operandUsed = operandsUsed_[&port];
342  OperandUseVector::iterator i = operandUsed.find(modCycle);
343  assert(i != operandUsed.end());
344  OperandUsePair& mnpp = i->second;
345  if (mnpp.first.po == &po) {
346  if (mnpp.second.po == NULL) {
347  operandUsed.erase(i);
348  } else {
349  mnpp.first = mnpp.second;
350  mnpp.second.po = NULL;
351  }
352  } else {
353  if (mnpp.second.po == &po) {
354  mnpp.second.po = NULL;
355  }
356  }
357 }

References assert, SchedulingResource::instructionIndex(), and operandsUsed_.

Referenced by unsetOperandsUsed().

Here is the call graph for this function:

◆ unsetResultWriten() [1/2]

void ExecutionPipelineResource::unsetResultWriten ( const ProgramOperation po,
unsigned int  triggerCycle 
)
private

Definition at line 360 of file ExecutionPipelineResource.cc.

361  {
362 
363  const Operation& op = po.operation();
364  TTAMachine::HWOperation& hwop = *fu_.operation(op.name());
365 
366  // Loops over all output values produced by this
367  for (int i = 0; i < op.numberOfOutputs(); i++) {
368  int outIndex = op.numberOfInputs() + 1 + i;
369  const TTAMachine::Port& port = *hwop.port(outIndex);
370  int resultCycle = triggerCycle + hwop.latency(outIndex);
371 
372  unsetResultWriten(port, resultCycle, po);
373  }
374 }

References fu_, TTAMachine::HWOperation::latency(), Operation::name(), Operation::numberOfInputs(), Operation::numberOfOutputs(), TTAMachine::FunctionUnit::operation(), ProgramOperation::operation(), TTAMachine::HWOperation::port(), and unsetResultWriten().

Here is the call graph for this function:

◆ unsetResultWriten() [2/2]

void ExecutionPipelineResource::unsetResultWriten ( const TTAMachine::Port port,
unsigned int  realCycle,
const ProgramOperation po 
)
private

Definition at line 305 of file ExecutionPipelineResource.cc.

307  {
308  unsigned int rrMod = instructionIndex(realCycle);
309 
310  ResultVector& resultWriten = resultWriten_[&port];
311  ResultHelperPair& rhp = resultWriten[rrMod];
312 
313  if (rhp.first.po == &po) {
314  // Decrease counter of results written in
315  rhp.first.count--;
316  if (rhp.first.count == 0) {
317  if (rhp.second.count == 0) {
318  resultWriten.erase(rrMod);
319  } else {
320  // move second to first.
321  rhp.first = rhp.second;
322  rhp.second = ResultHelper(); // empty it.
323  }
324  }
325  } else {
326  assert(rhp.second.po == &po);
327  // Decrease counter of results written in
328  rhp.second.count--;
329  if (rhp.second.count == 0) {
330  rhp.second = ResultHelper(); // empty it.
331  }
332  }
333 }

References assert, SchedulingResource::instructionIndex(), and resultWriten_.

Referenced by unassignDestination(), unassignSource(), and unsetResultWriten().

Here is the call graph for this function:

◆ validateDependentGroups()

bool ExecutionPipelineResource::validateDependentGroups ( )
overrideprotectedvirtual

Tests if all referred resources in dependent groups are of proper types.

Returns
true Allways true, pipelines are internal to object.

Reimplemented from SchedulingResource.

Definition at line 1388 of file ExecutionPipelineResource.cc.

1388  {
1389  return true;
1390 }

◆ validateRelatedGroups()

bool ExecutionPipelineResource::validateRelatedGroups ( )
overrideprotectedvirtual

Tests if all resources in related resource groups are of proper types.

Returns
true If all resources in related resource groups are Triggering PSockets - for now InputPSockets

Reimplemented from SchedulingResource.

Definition at line 1399 of file ExecutionPipelineResource.cc.

1399  {
1400  for (int i = 0; i < relatedResourceGroupCount(); i++) {
1401  for (int j = 0, count = relatedResourceCount(i); j < count; j++) {
1403  return false;
1404  }
1405  }
1406  return true;
1407 }

References SchedulingResource::isInputPSocketResource(), SchedulingResource::relatedResource(), SchedulingResource::relatedResourceCount(), and SchedulingResource::relatedResourceGroupCount().

Here is the call graph for this function:

Member Data Documentation

◆ assignedDestinationNodes_

std::multimap<int, MoveNode*> ExecutionPipelineResource::assignedDestinationNodes_
private

◆ assignedSourceNodes_

std::multimap<int, MoveNode*> ExecutionPipelineResource::assignedSourceNodes_
private

◆ cachedSize_

int ExecutionPipelineResource::cachedSize_
mutableprivate

◆ ddg_

const DataDependenceGraph* ExecutionPipelineResource::ddg_
private

Definition at line 330 of file ExecutionPipelineResource.hh.

Referenced by clear(), exclusiveMoves(), isLoopBypass(), and setDDG().

◆ fu_

const TTAMachine::FunctionUnit& ExecutionPipelineResource::fu_
private

◆ fuExecutionPipeline_

ResourceReservationTable ExecutionPipelineResource::fuExecutionPipeline_
mutableprivate

Stores one resource vector per cycle of scope for whole FU.

Definition at line 298 of file ExecutionPipelineResource.hh.

Referenced by assignDestination(), clear(), isInUse(), resourcesAllowTrigger(), size(), and unassignDestination().

◆ maxCycle_

int ExecutionPipelineResource::maxCycle_
private

Definition at line 328 of file ExecutionPipelineResource.hh.

Referenced by resourcesAllowTrigger(), and setMaxCycle().

◆ operandShareCount_

int ExecutionPipelineResource::operandShareCount_
private

◆ operandsUsed_

OperandUseMap ExecutionPipelineResource::operandsUsed_
private

◆ operandsWriten_

OperandWriteMap ExecutionPipelineResource::operandsWriten_
private

◆ resources

const ExecutionPipelineResourceTable* ExecutionPipelineResource::resources
private

◆ resultRead_

ResultMap ExecutionPipelineResource::resultRead_
private

◆ resultWriten_

ResultMap ExecutionPipelineResource::resultWriten_
private

◆ storedResultCycles_

std::map<MoveNode*, int, MoveNode::Comparator> ExecutionPipelineResource::storedResultCycles_
private

Definition at line 321 of file ExecutionPipelineResource.hh.

Referenced by assignSource(), clear(), and unassignSource().

◆ triggerPort_

const TTAMachine::Port* ExecutionPipelineResource::triggerPort_
private

Definition at line 334 of file ExecutionPipelineResource.hh.


The documentation for this class was generated from the following files:
ProgramOperation::operation
const Operation & operation() const
Definition: ProgramOperation.cc:590
TTAProgram::Terminal::isFUPort
virtual bool isFUPort() const
Definition: Terminal.cc:118
ExecutionPipelineResource::OperandUsePair
std::pair< OperandUseHelper, OperandUseHelper > OperandUsePair
Definition: ExecutionPipelineResource.hh:149
TTAMachine::FUPort::noRegister
bool noRegister() const
Definition: FUPort.cc:469
ProgramOperation::outputIndexFromGuardOfMove
int outputIndexFromGuardOfMove(const MoveNode &node) const
Definition: ProgramOperation.cc:256
SchedulingResource::clear
virtual void clear()
Definition: SchedulingResource.cc:397
TTAProgram::Terminal::isTriggering
virtual bool isTriggering() const
Definition: Terminal.cc:298
ExecutionPipelineResource::resourcesAllowTrigger
bool resourcesAllowTrigger(int cycle, const MoveNode &move) const
Definition: ExecutionPipelineResource.cc:1244
ExecutionPipelineResource::resultAllowedAtCycle
bool resultAllowedAtCycle(int resultCycle, const ProgramOperation &po, const TTAMachine::Port &resultPort, const MoveNode &trigger, int triggerCycle) const
Definition: ExecutionPipelineResource.cc:1852
SchedulingResource::SchedulingResource
SchedulingResource(const std::string &name, const unsigned int ii=0)
Definition: SchedulingResource.cc:51
ExecutionPipelineResource::cyclesOverlap
bool cyclesOverlap(int rangeFirst, int rangeLast, int targetCycle) const
Definition: ExecutionPipelineResource.cc:2823
TTAMachine::Component::name
virtual TCEString name() const
Definition: MachinePart.cc:125
ExecutionPipelineResource::MoveNodePtrPair
std::pair< MoveNode *, MoveNode * > MoveNodePtrPair
Definition: ExecutionPipelineResource.hh:164
ExecutionPipelineResourceTable::operationIndex
int operationIndex(const std::string &opName) const
MoveNode::toString
std::string toString() const
Definition: MoveNode.cc:576
ExecutionPipelineResource::operandOverwritten
bool operandOverwritten(int operandWriteCycle, int triggerCycle, const ProgramOperation &po, const MoveNode &operand, const MoveNode &trigger) const
Definition: ExecutionPipelineResource.cc:1137
TTAMachine::HWOperation
Definition: HWOperation.hh:52
ExecutionPipelineResource::operandAllowedAtCycle
bool operandAllowedAtCycle(const TTAMachine::Port &port, const MoveNode &mn, int cycle) const
Definition: ExecutionPipelineResource.cc:2131
DataDependenceEdge::isBackEdge
bool isBackEdge() const
Definition: DataDependenceEdge.hh:118
ExecutionPipelineResource::operandSharePreventsTriggerForScheduledResult
bool operandSharePreventsTriggerForScheduledResult(const TTAMachine::Port &port, const MoveNode &mn, int cycle) const
Definition: ExecutionPipelineResource.cc:2605
MoveNode::isDestinationOperation
bool isDestinationOperation() const
ExecutionPipelineResource::operandsUsed_
OperandUseMap operandsUsed_
Definition: ExecutionPipelineResource.hh:310
ProgramOperation::outputNode
MoveNodeSet & outputNode(int out) const
Definition: ProgramOperation.cc:535
ExecutionPipelineResource::ddg_
const DataDependenceGraph * ddg_
Definition: ExecutionPipelineResource.hh:330
TTAProgram::Move::isUnconditional
bool isUnconditional() const
Definition: Move.cc:154
TTAMachine::BaseFUPort
Definition: BaseFUPort.hh:44
ExecutionPipelineResource::ResultHelperPair
std::pair< ResultHelper, ResultHelper > ResultHelperPair
Definition: ExecutionPipelineResource.hh:148
TTAProgram::Move::destination
Terminal & destination() const
Definition: Move.cc:323
ExecutionPipelineResource::setResultWriten
void setResultWriten(const TTAMachine::Port &port, unsigned int realCycle, const ProgramOperation &po)
Definition: ExecutionPipelineResource.cc:211
ProgramOperation::fuFromOutMove
const TTAMachine::FunctionUnit * fuFromOutMove(const MoveNode &outputNode) const
Definition: ProgramOperation.cc:844
TTAProgram::Terminal::hintOperation
virtual Operation & hintOperation() const
Definition: Terminal.cc:341
Operation::numberOfInputs
virtual int numberOfInputs() const
Definition: Operation.cc:192
ExecutionPipelineResource::OperandWriteVector
SparseVector< MoveNodePtrPair > OperandWriteVector
Definition: ExecutionPipelineResource.hh:166
ProgramOperation
Definition: ProgramOperation.hh:70
MoveNode
Definition: MoveNode.hh:65
ExecutionPipelineResource::unsetResultWriten
void unsetResultWriten(const TTAMachine::Port &port, unsigned int realCycle, const ProgramOperation &po)
Definition: ExecutionPipelineResource.cc:305
ExecutionPipelineResource::resultPort
const TTAMachine::Port & resultPort(const MoveNode &mn) const
Definition: ExecutionPipelineResource.cc:2010
TTAMachine::FunctionUnit::port
virtual BaseFUPort * port(const std::string &name) const
Definition: FunctionUnit.cc:145
SchedulingResource::initiationInterval_
int initiationInterval_
Definition: SchedulingResource.hh:132
ExecutionPipelineResource::cyclesConflict
bool cyclesConflict(const MoveNode *mn1, const MoveNode *mn2, int guardCycle, int rangeFirst, int rangeLast, int targetCycle) const
Definition: ExecutionPipelineResource.cc:2843
ExecutionPipelineResource::otherTriggerBeforeMyTrigger
bool otherTriggerBeforeMyTrigger(const TTAMachine::Port &port, const MoveNode &node, int cycle) const
Definition: ExecutionPipelineResource.cc:2425
Operation::name
virtual TCEString name() const
Definition: Operation.cc:93
SchedulingResource::isInputPSocketResource
virtual bool isInputPSocketResource() const
Conversion::toString
static std::string toString(const T &source)
ProgramOperation::triggeringMove
MoveNode * triggeringMove() const
Definition: ProgramOperation.cc:643
ExecutionPipelineResource::testTriggerResult
bool testTriggerResult(const MoveNode &trigger, int cycle) const
Definition: ExecutionPipelineResource.cc:1785
ExecutionPipelineResource::poConflictsWithInputPort
bool poConflictsWithInputPort(const TTAMachine::Port &port, const ProgramOperation &po, const MoveNode &mn) const
Definition: ExecutionPipelineResource.cc:2866
MoveNode::isPlaced
bool isPlaced() const
Definition: MoveNode.cc:352
TTAProgram::Terminal::operation
virtual Operation & operation() const
Definition: Terminal.cc:319
ExecutionPipelineResourceTable::operationPipeline
bool operationPipeline(int op, int cycle, int res) const
MapTools::removeItemsByValue
static bool removeItemsByValue(MapType &aMap, const ValueType &aValue)
SparseVector::size
size_t size() const
Definition: SparseVectorMap.hh:45
MoveNode::sourceOperation
ProgramOperation & sourceOperation() const
Definition: MoveNode.cc:453
assert
#define assert(condition)
Definition: Application.hh:86
TTAMachine::FunctionUnit
Definition: FunctionUnit.hh:55
TTAMachine::HWOperation::port
virtual FUPort * port(int operand) const
Definition: HWOperation.cc:320
TTAMachine::FUPort
Definition: FUPort.hh:46
MoveNode::isMove
bool isMove() const
SchedulingResource::relatedResource
virtual SchedulingResource & relatedResource(const int group, const int index) const
Definition: SchedulingResource.cc:120
MoveNode::isGuardOperation
bool isGuardOperation() const
Definition: MoveNode.cc:181
MoveNode::earliestResultReadCycle
int earliestResultReadCycle() const
Definition: MoveNode.cc:652
IllegalParameters
Definition: Exception.hh:113
ExecutionPipelineResource::size
unsigned int size() const
Definition: ExecutionPipelineResource.cc:1417
TTAProgram::Terminal::operationIndex
virtual int operationIndex() const
Definition: Terminal.cc:364
TTAMachine::HWOperation::io
int io(const FUPort &port) const
Definition: HWOperation.cc:364
abortWithError
#define abortWithError(message)
Definition: Application.hh:72
MoveNode::cycle
int cycle() const
Definition: MoveNode.cc:421
InvalidData
Definition: Exception.hh:149
MoveNodeSet::at
MoveNode & at(int index)
ExecutionPipelineResource::isLoopBypass
bool isLoopBypass(const MoveNode &node) const
Definition: ExecutionPipelineResource.cc:791
ExecutionPipelineResource::resultNotOverWritten
bool resultNotOverWritten(int resultReadCycle, int resultReadyCycle, const MoveNode &node, const TTAMachine::Port &port, const MoveNode *trigger, int triggerCycle) const
Definition: ExecutionPipelineResource.cc:2048
ExecutionPipelineResource::exclusiveMoves
bool exclusiveMoves(const MoveNode *mn1, const MoveNode *mn2, int cycle=INT_MAX) const
Definition: ExecutionPipelineResource.cc:1719
ExecutionPipelineResource::cachedSize_
int cachedSize_
Definition: ExecutionPipelineResource.hh:327
ExecutionPipelineResource::fuExecutionPipeline_
ResourceReservationTable fuExecutionPipeline_
Stores one resource vector per cycle of scope for whole FU.
Definition: ExecutionPipelineResource.hh:298
TTAMachine::Port
Definition: Port.hh:54
ExecutionPipelineResourceTable::hasOperation
bool hasOperation(const std::string &opName) const
ExecutionPipelineResource::hasConflictingResultsOnCycle
bool hasConflictingResultsOnCycle(const ProgramOperation &po, const TTAMachine::Port &port, int cycle) const
Definition: ExecutionPipelineResource.cc:1559
TTAProgram::Move::guard
MoveGuard & guard() const
Definition: Move.cc:345
DataDependenceEdge::EDGE_OPERATION
@ EDGE_OPERATION
Definition: DataDependenceEdge.hh:56
__func__
#define __func__
Definition: Application.hh:67
ExecutionPipelineResource::assignedDestinationNodes_
std::multimap< int, MoveNode * > assignedDestinationNodes_
Definition: ExecutionPipelineResource.hh:325
MoveNode::isSourceOperation
bool isSourceOperation() const
Definition: MoveNode.cc:168
TTAMachine::HWOperation::slack
int slack(int input) const
Definition: HWOperation.cc:248
ExecutionPipelineResource::fu_
const TTAMachine::FunctionUnit & fu_
Definition: ExecutionPipelineResource.hh:331
ExecutionPipelineResource::checkOperandAllowed
bool checkOperandAllowed(const MoveNode &currentMn, const TTAMachine::Port &port, int operandWriteCycle, const OperandUseHelper &operandUse, int operandUseModCycle, ProgramOperation &currOp) const
Definition: ExecutionPipelineResource.cc:2234
ExecutionPipelineResource::operandsOverwritten
bool operandsOverwritten(int triggerCycle, const MoveNode &trigger) const
Definition: ExecutionPipelineResource.cc:1216
ExecutionPipelineResource::OperandUseVector
SparseVector< OperandUsePair > OperandUseVector
Definition: ExecutionPipelineResource.hh:167
SchedulingResource::instructionIndex
int instructionIndex(int cycle) const
ModuleRunTimeError
Definition: Exception.hh:1043
ExecutionPipelineResourceTable::numberOfResources
unsigned int numberOfResources() const
MoveNode::destinationOperationCount
unsigned int destinationOperationCount() const
MoveNodeSet
Definition: MoveNodeSet.hh:41
ProgramOperation::inputMoveCount
int inputMoveCount() const
Definition: ProgramOperation.cc:600
ExecutionPipelineResource::operandPossibleAtCycle
bool operandPossibleAtCycle(const TTAMachine::Port &port, const MoveNode &mn, int cycle) const
Definition: ExecutionPipelineResource.cc:2106
BoostGraph::hasNode
bool hasNode(const Node &) const
ExecutionPipelineResource::resultRead_
ResultMap resultRead_
Definition: ExecutionPipelineResource.hh:316
ProgramOperation::findTriggerFromUnit
MoveNode * findTriggerFromUnit(const TTAMachine::Unit &unit) const
Definition: ProgramOperation.cc:677
TTAMachine::Unit::portCount
virtual int portCount() const
Definition: Unit.cc:135
Operation
Definition: Operation.hh:59
Exception::errorMessage
std::string errorMessage() const
Definition: Exception.cc:123
TTAProgram::Terminal::isOpcodeSetting
virtual bool isOpcodeSetting() const
Definition: Terminal.cc:285
ExecutionPipelineResource::resultWriten_
ResultMap resultWriten_
Definition: ExecutionPipelineResource.hh:313
BoostGraph::inEdges
virtual EdgeSet inEdges(const Node &node) const
SchedulingResource::initiationInterval
int initiationInterval() const
Definition: SchedulingResource.cc:385
ExecutionPipelineResource::triggerAllowedAtCycle
bool triggerAllowedAtCycle(int inputCount, const TTAMachine::HWOperation &hwop, const MoveNode &node, int cycle) const
Definition: ExecutionPipelineResource.cc:2369
ProgramOperation::outputMoveCount
int outputMoveCount() const
Definition: ProgramOperation.cc:610
SchedulingResource::relatedResourceCount
int relatedResourceCount(const int group) const
MoveNodeSet::count
int count() const
ExecutionPipelineResource::ResourceReservationVector
std::vector< ResourceReservation > ResourceReservationVector
Type for resource vector, represents one cycle of use. Includes the ownerships of the reservation.
Definition: ExecutionPipelineResource.hh:157
MoveNode::destinationOperation
ProgramOperation & destinationOperation(unsigned int index=0) const
TTAMachine::Guard::isOpposite
virtual bool isOpposite(const Guard &guard) const =0
MoveNode::move
TTAProgram::Move & move()
ExecutionPipelineResource::setOperandUsed
void setOperandUsed(const TTAMachine::Port &port, unsigned int realCycle, const ProgramOperation &po)
Definition: ExecutionPipelineResource.cc:241
ProgramOperation::toString
std::string toString() const
Definition: ProgramOperation.cc:746
ExecutionPipelineResource::setOperandsUsed
void setOperandsUsed(const ProgramOperation &po, unsigned int triggerCycle)
Definition: ExecutionPipelineResource.cc:283
ExecutionPipelineResource::resources
const ExecutionPipelineResourceTable * resources
Definition: ExecutionPipelineResource.hh:295
MapTools::containsKey
static bool containsKey(const MapType &aMap, const KeyType &aKey)
ExecutionPipelineResource::unsetOperandsUsed
void unsetOperandsUsed(const ProgramOperation &po, unsigned int triggerCycle)
Definition: ExecutionPipelineResource.cc:377
ExecutionPipelineResource::operandShareCount_
int operandShareCount_
Definition: ExecutionPipelineResource.hh:336
ExecutionPipelineResourceTable::maximalLatency
unsigned int maximalLatency() const
ExecutionPipelineResource::maxCycle_
int maxCycle_
Definition: ExecutionPipelineResource.hh:328
ExecutionPipelineResource::resultCausesTriggerBetweenOperandSharing
bool resultCausesTriggerBetweenOperandSharing(const MoveNode &mn, int cycle) const
Definition: ExecutionPipelineResource.cc:2488
MoveNodeSet::begin
std::vector< MoveNode * >::iterator begin()
Definition: MoveNodeSet.hh:51
ExecutionPipelineResource::operandsWriten_
OperandWriteMap operandsWriten_
Definition: ExecutionPipelineResource.hh:309
ExecutionPipelineResource::unsetOperandUsed
void unsetOperandUsed(const TTAMachine::Port &port, unsigned int realCycle, const ProgramOperation &po)
Definition: ExecutionPipelineResource.cc:336
DataDependenceGraph::exclusingGuards
bool exclusingGuards(const MoveNode &mn1, const MoveNode &mn2) const
Definition: DataDependenceGraph.cc:4480
MapTools::containsValue
static bool containsValue(const MapType &aMap, const ValueType &aValue)
TTAMachine::Port::name
virtual std::string name() const
Definition: Port.cc:141
ExecutionPipelineResource::nextResultCycle
int nextResultCycle(const TTAMachine::Port &port, int cycle, const MoveNode &node, const MoveNode *trigger=NULL, int triggerCycle=INT_MAX) const
Definition: ExecutionPipelineResource.cc:1602
ProgramOperation::inputNode
MoveNodeSet & inputNode(int in) const
Definition: ProgramOperation.cc:513
ExecutionPipelineResource::triggerTooEarly
bool triggerTooEarly(const MoveNode &trigger, int cycle) const
Definition: ExecutionPipelineResource.cc:2327
ExecutionPipelineResource::resultReadyCycle
int resultReadyCycle(const ProgramOperation &po, const TTAMachine::Port &resultPort) const
Definition: ExecutionPipelineResource.cc:1677
TTAProgram::Terminal
Definition: Terminal.hh:60
DataDependenceEdge
Definition: DataDependenceEdge.hh:43
MoveNode::isScheduled
bool isScheduled() const
Definition: MoveNode.cc:409
TTAProgram::Move::source
Terminal & source() const
Definition: Move.cc:302
ExecutionPipelineResourceTable::resourceTable
static const ExecutionPipelineResourceTable & resourceTable(const TTAMachine::FunctionUnit &fu)
Definition: ExecutionPipelineResourceTable.cc:164
ExecutionPipelineResource::storedResultCycles_
std::map< MoveNode *, int, MoveNode::Comparator > storedResultCycles_
Definition: ExecutionPipelineResource.hh:321
TTAProgram::Terminal::port
virtual const TTAMachine::Port & port() const
Definition: Terminal.cc:378
TTAMachine::PortGuard
Definition: Guard.hh:99
TTAMachine::FunctionUnit::operation
virtual HWOperation * operation(const std::string &name) const
Definition: FunctionUnit.cc:363
ExecutionPipelineResource::ResultVector
SparseVector< ResultHelperPair > ResultVector
Used for both result read and result written.
Definition: ExecutionPipelineResource.hh:160
SchedulingResource::name
virtual const std::string & name() const
TTAMachine::HWOperation::latency
int latency() const
Definition: HWOperation.cc:216
ExecutionPipelineResource::isDestOpOfMN
bool isDestOpOfMN(const MoveNode &mn, const ProgramOperation &po) const
Definition: ExecutionPipelineResource.cc:2477
TTAProgram::MoveGuard::guard
const TTAMachine::Guard & guard() const
Definition: MoveGuard.cc:86
SchedulingResource::relatedResourceGroupCount
virtual int relatedResourceGroupCount() const
Definition: SchedulingResource.cc:61
ExecutionPipelineResource::ResourceReservation
std::pair< const MoveNode *, const MoveNode * > ResourceReservation
Definition: ExecutionPipelineResource.hh:151
ExecutionPipelineResource::assignedSourceNodes_
std::multimap< int, MoveNode * > assignedSourceNodes_
Definition: ExecutionPipelineResource.hh:323
ProgramOperation::outputMove
MoveNode & outputMove(int index) const
Definition: ProgramOperation.cc:632
ExecutionPipelineResource::canAssign
virtual bool canAssign(const int cycle, const MoveNode &node) const override
Definition: ExecutionPipelineResource.cc:102
Operation::numberOfOutputs
virtual int numberOfOutputs() const
Definition: Operation.cc:202
ProgramOperation::outputIndexOfMove
int outputIndexOfMove(const MoveNode &mn) const
Definition: ProgramOperation.cc:886
DataDependenceEdge::edgeReason
EdgeReason edgeReason() const
Definition: DataDependenceEdge.hh:91
ExecutionPipelineResource::operandPort
const TTAMachine::Port & operandPort(const MoveNode &mn) const
Definition: ExecutionPipelineResource.cc:2027
ExecutionPipelineResource::latestTriggerWriteCycle
int latestTriggerWriteCycle(const MoveNode &mn) const
Definition: ExecutionPipelineResource.cc:2393
ProgramOperation::inputMove
MoveNode & inputMove(int index) const
Definition: ProgramOperation.cc:621
ExecutionPipelineResource::operandTooLate
bool operandTooLate(const MoveNode &node, int cycle) const
Definition: ExecutionPipelineResource.cc:2291
MoveNode::guardOperation
ProgramOperation & guardOperation() const
Definition: MoveNode.cc:479
TTAMachine::Port::parentUnit
Unit * parentUnit() const