OpenASIP  2.0
MachineResourceManager.cc
Go to the documentation of this file.
1 /*
2  Copyright (c) 2002-2009 Tampere University.
3 
4  This file is part of TTA-Based Codesign Environment (TCE).
5 
6  Permission is hereby granted, free of charge, to any person obtaining a
7  copy of this software and associated documentation files (the "Software"),
8  to deal in the Software without restriction, including without limitation
9  the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  and/or sell copies of the Software, and to permit persons to whom the
11  Software is furnished to do so, subject to the following conditions:
12 
13  The above copyright notice and this permission notice shall be included in
14  all copies or substantial portions of the Software.
15 
16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  DEALINGS IN THE SOFTWARE.
23  */
24 /**
25  * @file MachineResourceManager.cc
26  *
27  * Implementation of MachineResourceManager class.
28  *
29  * @author Mikael Lepistö 2005 (tmlepist-no.spam-cs.tut.fi)
30  * @note rating: yellow
31  */
32 
34 
35 #include "Binary.hh"
36 #include "ASpaceSection.hh"
37 #include "AddressSpace.hh"
38 #include "ResourceSection.hh"
39 #include "NullSection.hh"
40 #include "MoveElement.hh"
41 
42 #include "ControlUnit.hh"
43 #include "SpecialRegisterPort.hh"
44 #include "FUPort.hh"
45 #include "HWOperation.hh"
46 #include "Guard.hh"
48 #include "Exception.hh"
49 
50 #include "Bus.hh"
51 
52 using namespace TPEF;
53 using namespace TTAMachine;
54 
55 
56 /**
57  * Constructor.
58  *
59  * @param tpef Binary where to generated resources are added.
60  * @param adf Machine where from requested resources are found.
61  * @param parent Assembler root class for adding warning information.
62  */
64  Binary& tpef,
65  const Machine& adf,
66  AssemblyParserDiagnostic* parent) :
67  tpef_(tpef), adf_(adf), aSpaceSection_(NULL), strings_(NULL),
68  undefASpace_(NULL), codeASpace_(NULL), nullSection_(NULL),
69  resourceSection_(NULL), lastFunctionUnitID_(0), lastRegisterFileID_(0),
70  lastOpOrSpecRegisterID_(0), parent_(parent) {
71 }
72 
73 
74 /**
75  * Finds data address space by name from ADF and adds it to TPEF.
76  *
77  * @param name Name of requested address space.
78  * @return ASpaceElement or NULL if not found.
79  * @exception IllegalMachine Address space was not found from ADF.
80  * @exception InvalidData Found address space is the code address space.
81  */
84  // check if address space is already created
86 
87  // try to find address space for name
89 
90  // Check that address space is found from machine and create address
91  // space section and address undef address space if needed to TPEF.
92  if (!aSpaces.hasItem(name)) {
93  throw IllegalMachine(
94  __FILE__, __LINE__, __func__,
95  "ADF doesn't contain address space: " + name);
96  }
97 
99 
100  // create new address space and add it to TPEF
101  AddressSpace* adfAddressSpace = aSpaces.item(name);
102  assert(adfAddressSpace != NULL);
103 
104  ASpaceElement* newASpace = new ASpaceElement();
105  newASpace->setMAU(adfAddressSpace->width());
106  newASpace->setName(stringToChunk(name));
107  addressSpaces_[name] = newASpace;
108 
109  aSpaceSection_->addElement(newASpace);
110  }
111 
112  if (addressSpaces_[name] == codeAddressSpace()) {
113  throw InvalidData(
114  __FILE__, __LINE__, __func__,
115  "Method can't be used for getting code address space.");
116  }
117 
118  return addressSpaces_[name];
119 }
120 
121 /**
122  * Returns bitwidth of requested bus.
123  *
124  * @param Slot number of requested bus.
125  * @return Bitwidth of requested bus.
126  * @exception OutOfRange If slot number is out of bounds.
127  */
128 UValue
130  Bus* bus = adf_.busNavigator().item(slotNumber);
131  return bus->width();
132 }
133 
134 /**
135  * Returns NullSection instance of TPEF.
136  *
137  * @return NullSection instance of TPEF.
138  */
139 Section*
141 
142  if (nullSection_ == NULL) {
143 
144  nullSection_ = dynamic_cast<NullSection*>(
145  Section::createSection(Section::ST_NULL));
146 
147  assert(nullSection_ != NULL);
148 
152 
154  }
155 
156  return nullSection_;
157 }
158 
159 
160 /**
161  * Returns string table of TPEF.
162  *
163  * @return String table of TPEF.
164  */
167  // makes sure that strings section is initialized
169  return strings_;
170 }
171 
172 
173 /**
174  * Returns undefined address space element.
175  *
176  * @return undefined address space element.
177  */
180 
181  // create address space section when needed
182  if (aSpaceSection_ == NULL) {
183 
184  // create address space section with undefined address space element
186  dynamic_cast<ASpaceSection*>(
187  Section::createSection(Section::ST_ADDRSP));
188 
189  assert(aSpaceSection_ != NULL);
190 
191  undefASpace_ = new ASpaceElement();
193 
198 
201  }
202 
203  return undefASpace_;
204 }
205 
206 
207 /**
208  * Returns the code address space.
209  *
210  * @return The code address space.
211  */
214 
215  if (codeASpace_ == NULL) {
216  // make sure that there is address space section created...
218 
219  // find codeAddressSpace, create tpef version and add it to section
220  AddressSpace* adfAddressSpace = adf_.controlUnit()->addressSpace();
221 
222  if (adfAddressSpace == NULL) {
223  throw IllegalMachine(
224  __FILE__, __LINE__, __func__,
225  "Control unit has no address space.");
226  }
227 
228  ASpaceElement* newASpace = new ASpaceElement();
229  newASpace->setMAU(0);
230  newASpace->setName(stringToChunk(adfAddressSpace->name()));
231 
232  addressSpaces_[adfAddressSpace->name()] = newASpace;
233  codeASpace_ = newASpace;
234 
235  aSpaceSection_->addElement(newASpace);
236  }
237 
238  return codeASpace_;
239 }
240 
241 /**
242  * Finds or adds string to TPEF string section and returns
243  * chunk pointing to it.
244  *
245  * @param aStr String whose chunk is needed.
246  * @return Chunk pointing to string stored in TPEF.
247  */
248 Chunk*
249 MachineResourceManager::stringToChunk(const std::string aStr) {
250 
251  if (strings_ == NULL) {
252  strings_ = dynamic_cast<StringSection*>(
253  Section::createSection(Section::ST_STRTAB));
254 
255  // first byte must be zero
256  strings_->addByte(0);
257 
260 
261  // start zero of string section must be added befor this, since
262  // undefined address space calls this function to get chunk(0)
265  }
266 
267  return strings_->string2Chunk(aStr);
268 }
269 
270 
271 /**
272  * Resolves type, unit and index fields, of given register term.
273  *
274  * Also checks if requested term is possible and creates machine
275  * resource section.
276  *
277  * @param currentLine line number where term is located in assembly code.
278  * @param term Term to resolve.
279  * @param slotNumber Number of move slot, that was used.
280  * @param type Is read, write or guard.
281  * @return Information of Term's type, unit and index for instruction element.
282  * @exception IllegalMachine There is problem to find or access the resource.
283  */
286  UValue currentLine, const RegisterTerm& term, UValue slotNumber,
287  RequestType type) {
288  // create resource key for reference
289  ResourceID newResID;
290 
291  ResourceKey resKey;
292  resKey.slotNumber = slotNumber;
293  resKey.type = type;
294 
295 #if 0
296  // Valuable debug info (currently resolved term)
297  term.clear();
298  std::cerr << "\ttype: " << term.type << std::endl;
299 #endif
300 
301  // create key for requested resource
302  if (term.type == RegisterTerm::INDEX) {
303  resKey.keyString = term.indexTerm.part1;
304 
305  if (term.indexTerm.part2Used) {
306  resKey.keyString += "." + term.indexTerm.part2;
307  }
308 
309  resKey.keyString += "." + Conversion::toString(term.indexTerm.index);
310 
311  } else if (term.type == RegisterTerm::FUNCTION_UNIT) {
312  resKey.keyString =
313  term.fuTerm.part1 + "." + term.fuTerm.part2;
314 
315  if (term.fuTerm.part3Used) {
316  resKey.keyString += "." + term.fuTerm.part3;
317  }
318 
319  } else if (term.type == RegisterTerm::BUS) {
320  if (term.busTerm.prev) {
321  resKey.keyString = "{prev}";
322  } else {
323  resKey.keyString = "{next}";
324  }
325 
326  } else {
328  "Unknown term type." + Conversion::toString(term.type));
329  }
330 
331  // check if resource is used before or do we have to
332  // retrieve it and add it to resource section
333  if (!MapTools::containsKey(resourceMap_, resKey)) {
334 
335  if (term.type == RegisterTerm::INDEX) {
336  // check if rf[.port].index or fu.operation.index
337  newResID = indexResource(
338  currentLine, term, slotNumber, type, resKey.keyString);
339 
340  } else if (term.type == RegisterTerm::FUNCTION_UNIT) {
341  // this is definately unit.port[.operation]
342  newResID = functionUnitPortResource(term);
343 
344  } else if (term.type == RegisterTerm::BUS) {
345  abortWithError("{prev} and {next} might never be supported.");
346 
347  } else {
348  assert(false);
349  }
350 
351 #if 0
352  // Very useful debugging information
353  std::cerr << "resKey: " << resKey.keyString
354  << "\ttype: " << resKey.type
355  << "\tslot:" << resKey.slotNumber
356  << std::endl;
357 #endif
358  // copy to map
359  resourceMap_[resKey] = newResID;
360  }
361 
362  // get resource id from map and give it away
364 
365  return resourceMap_[resKey];
366 }
367 
368 /**
369  * Returns the resource section of TPEF.
370  *
371  * @return The resource section of TPEF.
372  */
375  return resourceSection_;
376 }
377 
378 
379 /**
380  * Initialises resource section if its not initialised already.
381  */
383  // init resource section if needed and add new resource element.
384  if (resourceSection_ == NULL) {
385  resourceSection_ = dynamic_cast<ResourceSection*>(
386  Section::createSection(Section::ST_MR));
387 
388  assert(resourceSection_ != NULL);
389 
393 
394  // add all busses at once
396 
397  for (int i = 0; i < busNavi.count(); i++) {
398  Bus* bus = busNavi.item(i);
399 
400  ResourceElement* newRes = new ResourceElement();
401 
402  newRes->setId(i + 1);
403  newRes->setType(ResourceElement::MRT_BUS);
404  newRes->setName(stringToChunk(bus->name()));
405 
406  resourceSection_->addElement(newRes);
407  }
408 
410  }
411 }
412 
413 
414 /**
415  * Adds resource element to TPEF.
416  */
417 void
420  assert(resourceSection_ != NULL);
421 
422 #if 0
423  // Valuable debug info... about resources that are added to
424  // resource section
425  std::cerr << "Added resource element: "
426  << strings_->chunk2String(resource->name())
427  << "\t" << (int)resource->type()
428  << "\t" << (int)resource->id()
429  << std::endl;
430 #endif
431 
432  resourceSection_->addElement(resource);
433 }
434 
435 
436 /**
437  * Returns TPEF resource ID of function unit.
438  *
439  * If resource is not already in TPEF method creates
440  * resource and adds it.
441  *
442  * @param unit Function unit whose ID is needed.
443  * @return TPEF resource ID of function unit.
444  */
445 UValue
447 
449  // create resource element and add its unit id to map
451 
452  ResourceElement* newRes = new ResourceElement();
453 
454  newRes->setId(lastFunctionUnitID_);
455  newRes->setType(ResourceElement::MRT_UNIT);
456  newRes->setName(stringToChunk(unit->name()));
457 
458  addResourceElement(newRes);
459 
461  }
462 
464 
465  return functionUnitIDs_[unit];
466 }
467 
468 
469 /**
470  * Returns TPEF resource ID corresponding to a register file.
471  *
472  * If there is no resource entry in TPEF for the given register file, this
473  * method creates it, assigns a new unique ID code to it and adds it to the
474  * pool of managed TPEF resources.
475  *
476  * @param rf A register file.
477  * @return TPEF resource ID of the register file.
478  */
479 UValue
481 
483  // create resource element and add its unit id to map
485 
486  ResourceElement* newRes = new ResourceElement();
487 
488  newRes->setId(lastRegisterFileID_);
489 
490  if (dynamic_cast<ImmediateUnit*>(rf) == NULL) {
491  newRes->setType(ResourceElement::MRT_RF);
492  } else {
493  newRes->setType(ResourceElement::MRT_IMM);
494  }
495 
496  newRes->setName(stringToChunk(rf->name()));
497  addResourceElement(newRes);
498 
500  }
501 
503 
504  return registerFileIDs_[rf];
505 }
506 
507 /**
508  * Returns TPEF resource ID of operand or port.
509  *
510  * If resource is not already in TPEF method creates
511  * resource and adds it.
512  *
513  * @param opPortString TPEF resource string of port or operand.
514  * @param port Port that is connected with requested resource in ADF.
515  * @return TPEF resource ID of port or operand.
516  */
517 UValue
519  std::string opOrPortString, const TTAMachine::Port* port) {
520 
521  if (!MapTools::containsKey(opOrPortIDs_, opOrPortString)) {
522  // create resource element and add its unit id to map
524  UValue generatedID = lastOpOrSpecRegisterID_;
525 
526  ResourceElement* newRes = new ResourceElement();
527 
528  // check if string is port or operand by string format
529  if (opOrPortString.find('.') == std::string::npos) {
530 
531  if (dynamic_cast<const SpecialRegisterPort*>(port) != NULL) {
532  newRes->setType(ResourceElement::MRT_SR);
533  } else {
534  newRes->setType(ResourceElement::MRT_PORT);
535  }
536 
537  } else {
538  newRes->setType(ResourceElement::MRT_OP);
539  }
540 
541  newRes->setName(stringToChunk(opOrPortString));
542  newRes->setId(generatedID);
543  addResourceElement(newRes);
544  opOrPortIDs_[opOrPortString] = generatedID;
545  }
546 
547  return opOrPortIDs_[opOrPortString];
548 }
549 
550 /**
551  * Returns debug string for request type for error message generation.
552  *
553  * @param type Request type.
554  * @return Debug string for request type.
555  */
556 std::string
558  switch (type) {
559  case RQST_READ: return "read";
560  case RQST_WRITE: return "write";
561  case RQST_GUARD: return "guard";
562  case RQST_INVGUARD: return "inverted guard";
563  default: return "invalid request type";
564  }
565 }
566 
567 /**
568  * Finds resource for fu.port or fu.port.operation term.
569  *
570  * Helper method for resourceID method.
571  *
572  * @param term Requested term.
573  * @return TPEF resource information of requested term.
574  * @exception IllegalMachine There was problems finding resource from ADF.
575  */
578  ResourceID newResID;
579 
582 
583  FunctionUnit* fu = NULL;
584 
585  if (fuNavi.hasItem(term.fuTerm.part1)) {
586  fu = fuNavi.item(term.fuTerm.part1);
587 
588  } else if (adf_.controlUnit()->name() == term.fuTerm.part1) {
589  // NOTE: it would be easier, if control unit would be just
590  // same that any fu and it would exist in fuNavigator.
591  fu = adf_.controlUnit();
592 
593  } else {
594  throw IllegalMachine(
595  __FILE__, __LINE__, __func__,
596  "Can't find function unit from machine: " +
597  term.fuTerm.part1);
598  }
599 
600  assert(fu != NULL);
601 
602  // find out port
603  if (!fu->hasPort(term.fuTerm.part2)) {
604  throw IllegalMachine(
605  __FILE__, __LINE__, __func__,
606  "Can't find port: " +
607  term.fuTerm.part2);
608  }
609 
610  Port* port = fu->port(term.fuTerm.part2);
611 
612  std::string regString;
613 
614  if (term.fuTerm.part3Used) {
615  // find out operand
616  if (!fu->hasOperation(term.fuTerm.part3)) {
617  throw IllegalMachine(
618  __FILE__, __LINE__, __func__,
619  "Operation " + term.fuTerm.part3 +
620  " is not found from fu: " +
621  term.fuTerm.part1);
622  }
623 
624  HWOperation* oper = fu->operation(term.fuTerm.part3);
625 
626  TTAMachine::FUPort* fuPort =
627  dynamic_cast<TTAMachine::FUPort*>(port);
628 
629  try {
630  regString =
631  term.fuTerm.part3 + "." +
632  Conversion::toString(oper->io(*fuPort));
633 
634  } catch (InstanceNotFound& e) {
635 
636  throw IllegalMachine(
637  __FILE__, __LINE__, __func__,
638  "Operation " + term.fuTerm.part3 +
639  " is not bound to port: " +
640  term.fuTerm.part2);
641  }
642 
643  } else {
644  // plain port reference
645  regString = term.fuTerm.part2;
646  }
647 
648  newResID.width = port->width();
649  newResID.unit = functionUnitID(fu);
650  newResID.index = opOrPortID(regString, port);
651  newResID.type = MoveElement::MF_UNIT;
652 
653  return newResID;
654 }
655 
656 /**
657  * Finds resource for fu.operation.index, rf.index or rf.port.index term.
658  *
659  * Helper method for resourceID method.
660  *
661  * @param currentLine Line number information for warning messages.
662  * @param term Requested term.
663  * @param slotNumber Number of move slot, that was used.
664  * @param type Request type.
665  * @param resourceKeyString Resource key string for error messages.
666  * @return TPEF resource information of requested term.
667  * @exception IllegalMachine There was problems finding resource from ADF.
668  */
671  UValue currentLine, const RegisterTerm& term, UValue slotNumber,
672  RequestType type, std::string& resourceKeyString) {
673  ResourceID newResID;
674 
677 
680 
683 
684  BaseRegisterFile* rf = NULL;
685  FunctionUnit* fu = NULL;
686 
687  if (immNavi.hasItem(term.indexTerm.part1)) {
688  rf = immNavi.item(term.indexTerm.part1);
689  }
690 
691  // If the a unit is found in both immediate unit and register file
692  // navigators, the unit from the register file navigator is selected
693  // and a warning is displayed.
694  if (rfNavi.hasItem(term.indexTerm.part1)) {
695  if (rf != NULL) {
696  std::string warning = "Unit name '";
697  warning += term.indexTerm.part1;
698  warning += "' is ambiguous. Because of disambiguity rules, '";
699  warning += term.indexTerm.part1;
700  warning += "' is selected to refer the register file insread of";
701  warning += " the immediate unit.";
702  parent_->addWarning(currentLine, warning);
703  }
704  rf = rfNavi.item(term.indexTerm.part1);
705  }
706 
707  // if normal fu or gcu...
708  if (fuNavi.hasItem(term.indexTerm.part1)) {
709  fu = fuNavi.item(term.indexTerm.part1);
710  } else {
711  // NOTE: GCU isn't found by name with FunctionUnitNavigator,
712  // but it must be requested explicitely
713  fu = adf_.controlUnit();
714  if (fu->name() != term.indexTerm.part1) {
715  fu = NULL;
716  }
717  }
718 
719  if (term.indexTerm.part2Used) {
720  if (rf != NULL && fu != NULL) {
721  std::string warning = "Unit name '";
722  warning += term.indexTerm.part1;
723  warning += "' is ambiguous.";
724  parent_->addWarning(currentLine, warning);
725  }
726  // rf.port.index or fu.operation.index reference
727  newResID = rFPortOrFUIndexReference(
728  fu, rf, currentLine, term, slotNumber, type, resourceKeyString);
729 
730  } else {
731  // this must be rf.index reference
732  newResID = registerFileIndexReference(
733  rf, term, slotNumber, type, resourceKeyString);
734  }
735 
736  return newResID;
737 }
738 
739 /**
740  * Finds resource for fu.operation.index or rf.port.index term.
741  *
742  * Helper method for indexResource method.
743  *
744  * @param fu Function unit of term, might be NULL.
745  * @param rf Register file of term, might be NULL.
746  * @param currentLine Line number information for warning messages.
747  * @param term Requested term.
748  * @param slotNumber Number of move slot, that was used.
749  * @param type Request type.
750  * @param resourceKeyString Resource key string for error messages.
751  * @return TPEF resource information of requested term.
752  * @exception IllegalMachine There was problems finding resource from ADF.
753  */
756  FunctionUnit* fu, BaseRegisterFile* rf, UValue currentLine,
757  const RegisterTerm& term, UValue slotNumber, RequestType type,
758  std::string& resourceKeyString) {
759  ResourceID newResID;
760 
761  // NOTE: disambiguation rule says that rf.port.index has higher
762  // priority than fu.operation.index ...
763  if (rf != NULL) {
764 
765  // check defined if port can be used for current
766  // direction and bus
767  Bus* bus = NULL;
768  try {
769  bus = adf_.busNavigator().item(slotNumber);
770  } catch (OutOfRange &e) {
771  std::stringstream newErrorMsg;
772  newErrorMsg
773  << "Too few busses for all moves in instruction."
774  << std::endl;
775 
776  IllegalMachine error(
777  __FILE__, __LINE__, __func__,
778  newErrorMsg.str() + e.errorMessage());
779  error.setCause(e);
780  throw error;
781  }
782  bool isPossible = false;
783 
784  switch (type) {
785  case RQST_READ:
786  case RQST_WRITE: {
787  for (int i = 0; i < rf->portCount(); i++) {
788  Port* port = rf->port(i);
789 
790  Socket* sock =
791  (type == RQST_WRITE) ?
792  (port->inputSocket()) :
793  (port->outputSocket());
794 
795  if (sock != NULL && sock->isConnectedTo(*bus)) {
796  isPossible = true;
797 
798  // we never store information that which port of RF
799  // was used for reading or writing, since TPEF doesn't
800  // support storing that data :(
801  if (port->name() != term.indexTerm.part2) {
802 
804  currentLine,
805  "Selected different port for move"
806  "that was given by user.");
807  }
808 
809  newResID.width = port->width();
810  break;
811  }
812  }
813 
814  } break;
815 
816  case RQST_INVGUARD:
817  case RQST_GUARD: {
818  bool isInverted =
819  (type == RQST_GUARD) ?
820  (false) : (true);
821 
822  for (int i = 0; i < bus->guardCount(); i++) {
823  RegisterGuard* guard =
824  dynamic_cast<RegisterGuard*>(bus->guard(i));
825 
826  if (guard != NULL) {
827  if (guard->registerFile() == rf &&
828  guard->registerIndex() ==
829  static_cast<int>(term.indexTerm.index) &&
830  guard->isInverted() == isInverted) {
831 
832  isPossible = true;
833  break;
834  }
835  }
836  }
837 
838  } break;
839 
840  default:
841  abortWithError("Unknown request type: " +
842  Conversion::toString(type));
843  }
844 
845  // if request is possible
846  if (isPossible) {
847  newResID.unit = registerFileID(rf);
848  newResID.index = term.indexTerm.index;
849 
850  if (dynamic_cast<ImmediateUnit*>(rf) == NULL) {
851  newResID.type = MoveElement::MF_RF;
852  } else {
853  newResID.type = MoveElement::MF_IMM;
854  }
855 
856  } else {
857  rf = NULL;
858  }
859  }
860 
861  if (rf == NULL && fu != NULL) {
862  // check if operation is found from fu
863  if (fu->hasOperation(term.indexTerm.part2)) {
864 
865  // check that requested port is possible
866  HWOperation* oper =
867  fu->operation(term.indexTerm.part2);
868 
869 
870  Port* port = oper->port(term.indexTerm.index);
871 
872  if (port == NULL) {
873  throw IllegalMachine(
874  __FILE__, __LINE__, __func__,
875  "Can't find operand: " +
876  term.indexTerm.part2 + "." +
878  }
879 
880  Bus* bus = NULL;
881  try {
882  bus = adf_.busNavigator().item(slotNumber);
883  } catch (OutOfRange &e) {
884  std::stringstream newErrorMsg;
885  newErrorMsg
886  << "Too few busses for all moves in instruction."
887  << std::endl;
888 
889  IllegalMachine error(
890  __FILE__, __LINE__, __func__,
891  newErrorMsg.str() + e.errorMessage());
892  error.setCause(e);
893  throw error;
894  }
895  bool isPossible = false;
896 
897  switch (type) {
898  case RQST_WRITE:
899  case RQST_READ: {
900  Socket* sock =
901  (type == RQST_WRITE) ?
902  (port->inputSocket()) :
903  (port->outputSocket());
904 
905  if (sock != NULL && sock->isConnectedTo(*bus)) {
906  isPossible = true;
907  break;
908  }
909  } break;
910 
911  case RQST_GUARD:
912  case RQST_INVGUARD: {
913  bool isInverted =
914  (type == RQST_GUARD) ?
915  (false) : (true);
916 
917  for (int i = 0; i < bus->guardCount(); i++) {
918  PortGuard* guard =
919  dynamic_cast<PortGuard*>(bus->guard(i));
920 
921  if (guard != NULL) {
922  if (guard->port() == port &&
923  guard->isInverted() == isInverted) {
924 
925  isPossible = true;
926  break;
927  }
928  }
929  }
930  } break;
931 
932  default:
933  abortWithError("Unknown request type: " +
934  Conversion::toString(type));
935  }
936 
937  std::string operationRegisterStr =
938  term.indexTerm.part2 + "." +
940 
941  if (isPossible) {
942  newResID.width = port->width();
943  newResID.unit = functionUnitID(fu);
944  newResID.index = opOrPortID(operationRegisterStr, port);
945  newResID.type = MoveElement::MF_UNIT;
946 
947  } else {
948  fu = NULL;
949  }
950 
951  } else {
952  throw IllegalMachine(
953  __FILE__, __LINE__, __func__,
954  "Can't find operation: " + term.indexTerm.part2);
955  }
956  }
957 
958  // if both tests failed
959  if (rf == NULL && fu == NULL) {
960  throw IllegalMachine(
961  __FILE__, __LINE__, __func__,
962  "Can't find connection for " + requestTypeString(type) +
963  "fu term: " + resourceKeyString);
964  }
965 
966  return newResID;
967 }
968 
969 /**
970  * Finds resource for rf.index term.
971  *
972  * Helper method for indexResource method.
973  *
974  * @param rf Register file of term.
975  * @param term Requested term.
976  * @param slotNumber Number of move slot, that was used.
977  * @param type Request type.
978  * @param resourceKeyString Resource key string for error messages.
979  * @return TPEF resource information of requested term.
980  * @exception IllegalMachine There was problems finding resource from ADF.
981  */
984  BaseRegisterFile* rf, const RegisterTerm& term, UValue slotNumber,
985  RequestType type, std::string& resourceKeyString) {
986  ResourceID newResID;
987  // this is normal rf reference unless register is immediate unit...
988  newResID.type = MoveElement::MF_RF;
989 
990  if (rf == NULL) {
991  throw IllegalMachine(
992  __FILE__, __LINE__, __func__,
993  "Can't find connection for " + requestTypeString(type) +
994  " rf.index term: " + resourceKeyString);
995  }
996 
997  // check that there is enough registers in file
998  if(static_cast<UValue>(rf->numberOfRegisters()) <= term.indexTerm.index) {
999 
1000  throw IllegalMachine(
1001  __FILE__, __LINE__, __func__,
1002  "Not enough registers in registerfile.");
1003  }
1004 
1005  // check defined if port can be used for current direction
1006  // and bus
1007  Bus* bus = adf_.busNavigator().item(slotNumber);
1008  bool isPossible = false;
1009 
1010  switch (type) {
1011 
1012  case RQST_READ:
1013  case RQST_WRITE: {
1014  ImmediateUnit* immUnit = dynamic_cast<ImmediateUnit*>(rf);
1015 
1016  // Code section creator checks in the end if it's really possible...
1017  if (immUnit != NULL) {
1018  isPossible = true;
1019  newResID.type = MoveElement::MF_IMM;
1020  break;
1021  }
1022 
1023  for (int i = 0; i < rf->portCount(); i++) {
1024  Port* port = rf->port(i);
1025 
1026  Socket* sock =
1027  (type == RQST_WRITE) ?
1028  (port->inputSocket()) :
1029  (port->outputSocket());
1030 
1031  if (sock != NULL && sock->isConnectedTo(*bus)) {
1032  isPossible = true;
1033  break;
1034  }
1035  }
1036 
1037  } break;
1038 
1039  case RQST_INVGUARD:
1040  case RQST_GUARD: {
1041  bool invertedRequested = (type == RQST_INVGUARD);
1042 
1043  for (int i = 0; i < bus->guardCount(); i++) {
1044  RegisterGuard* guard =
1045  dynamic_cast<RegisterGuard*>(bus->guard(i));
1046 
1047  if (guard != NULL) {
1048  if (guard->registerFile() == rf &&
1049  guard->registerIndex() ==
1050  static_cast<int>(term.indexTerm.index) &&
1051  guard->isInverted() == invertedRequested) {
1052 
1053  isPossible = true;
1054  break;
1055  }
1056  }
1057  }
1058 
1059  } break;
1060 
1061  default:
1062  abortWithError("Unknown request type: " +
1063  Conversion::toString(type));
1064  }
1065 
1066  if (isPossible) {
1067  newResID.width = rf->width();
1068  newResID.unit = registerFileID(rf);
1069  newResID.index = term.indexTerm.index;
1070 
1071  } else {
1072  throw IllegalMachine(
1073  __FILE__, __LINE__, __func__,
1074  "Can't find connection for " + requestTypeString(type) +
1075  " term: " + resourceKeyString);
1076  }
1077 
1078  return newResID;
1079 }
MachineResourceManager.hh
MachineResourceManager::ResourceKey
Definition: MachineResourceManager.hh:136
TTAMachine::Port::inputSocket
virtual Socket * inputSocket() const
Definition: Port.cc:261
MachineResourceManager::stringToChunk
TPEF::Chunk * stringToChunk(const std::string aStr)
Definition: MachineResourceManager.cc:249
MachineResourceManager::requestTypeString
std::string requestTypeString(RequestType type) const
Definition: MachineResourceManager.cc:557
TPEF::ResourceSection
Definition: ResourceSection.hh:47
FUTerm::part2
std::string part2
Port name.
Definition: ParserStructs.hh:83
FUTerm::part3Used
bool part3Used
Is operation part of the term used.
Definition: ParserStructs.hh:79
TTAMachine::Component::name
virtual TCEString name() const
Definition: MachinePart.cc:125
MachineResourceManager::opOrPortIDs_
std::map< std::string, UValue > opOrPortIDs_
Bookkeeping of already added ports, operations and special registers.
Definition: MachineResourceManager.hh:239
TTAMachine::PortGuard::port
FUPort * port() const
MachineResourceManager::nullSection_
TPEF::NullSection * nullSection_
The null section of TPEF.
Definition: MachineResourceManager.hh:219
MachineResourceManager::ResourceID
Definition: MachineResourceManager.hh:91
MachineResourceManager::codeASpace_
TPEF::ASpaceElement * codeASpace_
The instruction address space element of TPEF.
Definition: MachineResourceManager.hh:214
TTAMachine::HWOperation
Definition: HWOperation.hh:52
TTAMachine::AddressSpace
Definition: AddressSpace.hh:51
Exception.hh
MachineResourceManager::lastRegisterFileID_
UValue lastRegisterFileID_
For generating register file resource ids.
Definition: MachineResourceManager.hh:232
MachineResourceManager::RequestType
RequestType
Definition: MachineResourceManager.hh:81
TTAMachine::RegisterGuard::registerIndex
int registerIndex() const
TPEF::ResourceElement::id
HalfWord id() const
MachineResourceManager::functionUnitID
UValue functionUnitID(TTAMachine::FunctionUnit *unit)
Definition: MachineResourceManager.cc:446
MachineResourceManager::resourceSection
TPEF::ResourceSection * resourceSection()
Definition: MachineResourceManager.cc:373
AssemblyParserDiagnostic.hh
BusTerm::prev
bool prev
Previous or next bus register.
Definition: ParserStructs.hh:56
TTAMachine::Bus::width
int width() const
Definition: Bus.cc:149
NullSection.hh
TPEF::Binary
Definition: Binary.hh:49
OutOfRange
Definition: Exception.hh:320
TTAMachine::Bus
Definition: Bus.hh:53
TPEF::ResourceElement::type
ResourceType type() const
TTAMachine::Port::width
virtual int width() const =0
MachineResourceManager::findBusWidth
UValue findBusWidth(UValue slotNumber)
Definition: MachineResourceManager.cc:129
AddressSpace.hh
TPEF::ResourceElement
Definition: ResourceElement.hh:47
MachineResourceManager::registerFileID
UValue registerFileID(TTAMachine::BaseRegisterFile *rf)
Definition: MachineResourceManager.cc:480
MachineResourceManager::adf_
const TTAMachine::Machine & adf_
Machine where manager tries to find used resources.
Definition: MachineResourceManager.hh:202
TPEF::Binary::addSection
void addSection(Section *section)
Exception::setCause
void setCause(const Exception &cause)
Definition: Exception.cc:75
RegisterTerm::busTerm
BusTerm busTerm
The bus term, if type field is BUS. Otherwise not used.
Definition: ParserStructs.hh:152
MachineResourceManager::stringSection
TPEF::StringSection * stringSection()
Definition: MachineResourceManager.cc:166
TTAMachine::FunctionUnit::port
virtual BaseFUPort * port(const std::string &name) const
Definition: FunctionUnit.cc:145
TTAMachine::FunctionUnit::addressSpace
virtual AddressSpace * addressSpace() const
Definition: FunctionUnit.cc:580
TPEF::StringSection::chunk2String
std::string chunk2String(const Chunk *chunk) const
Definition: StringSection.cc:72
MachineResourceManager::ResourceID::index
UValue index
TPEF Resource operand id or register file index.
Definition: MachineResourceManager.hh:102
MachineResourceManager::RQST_READ
@ RQST_READ
Register of port for reading.
Definition: MachineResourceManager.hh:82
TTAMachine::Machine::Navigator::count
int count() const
TPEF::DataSection::addByte
virtual void addByte(Byte aByte)
Definition: DataSection.cc:200
ResourceSection.hh
AssemblyParserDiagnostic
Definition: AssemblyParserDiagnostic.hh:68
MachineResourceManager::nullSection
TPEF::Section * nullSection()
Definition: MachineResourceManager.cc:140
RegisterTerm::INDEX
@ INDEX
Index term.
Definition: ParserStructs.hh:145
Conversion::toString
static std::string toString(const T &source)
TPEF::ResourceElement::setType
void setType(ResourceType aType)
TPEF::Section
Definition: Section.hh:64
TPEF::StringSection
Definition: StringSection.hh:48
IndexTerm::part2
std::string part2
Port or operation name.
Definition: ParserStructs.hh:112
MachineResourceManager::MachineResourceManager
MachineResourceManager(TPEF::Binary &tpef, const TTAMachine::Machine &adf, AssemblyParserDiagnostic *parent_)
Definition: MachineResourceManager.cc:63
MachineResourceManager::parent_
AssemblyParserDiagnostic * parent_
Assembler root class for adding warnings.
Definition: MachineResourceManager.hh:242
TTAMachine::BaseRegisterFile::numberOfRegisters
virtual int numberOfRegisters() const
TPEF::ResourceElement::name
Chunk * name() const
assert
#define assert(condition)
Definition: Application.hh:86
MachineResourceManager::ResourceKey::keyString
std::string keyString
Key string for resource.
Definition: MachineResourceManager.hh:138
TTAMachine::FunctionUnit
Definition: FunctionUnit.hh:55
MachineResourceManager::functionUnitIDs_
std::map< TTAMachine::FunctionUnit *, UValue > functionUnitIDs_
Bookkeeping of already added function units.
Definition: MachineResourceManager.hh:229
MachineResourceManager::indexResource
ResourceID indexResource(UValue currentLine, const RegisterTerm &term, UValue slotNumber, RequestType type, std::string &resourceKeyString)
Definition: MachineResourceManager.cc:670
TTAMachine::HWOperation::port
virtual FUPort * port(int operand) const
Definition: HWOperation.cc:320
TPEF::Section::addElement
virtual void addElement(SectionElement *element)
Definition: Section.cc:133
TTAMachine::FUPort
Definition: FUPort.hh:46
TPEF::NullSection
Definition: NullSection.hh:46
IndexTerm::part1
std::string part1
Unit name.
Definition: ParserStructs.hh:110
TTAMachine::BaseRegisterFile
Definition: BaseRegisterFile.hh:48
TTAMachine::Machine::controlUnit
virtual ControlUnit * controlUnit() const
Definition: Machine.cc:345
IndexTerm::index
UValue index
Register or operand index.
Definition: ParserStructs.hh:114
TTAMachine::HWOperation::io
int io(const FUPort &port) const
Definition: HWOperation.cc:364
abortWithError
#define abortWithError(message)
Definition: Application.hh:72
MachineResourceManager::ResourceID::type
TPEF::MoveElement::FieldType type
Resource type.
Definition: MachineResourceManager.hh:98
HWOperation.hh
UValue
unsigned long UValue
Definition: ParserStructs.hh:44
TTAMachine::SpecialRegisterPort
Definition: SpecialRegisterPort.hh:48
InvalidData
Definition: Exception.hh:149
IndexTerm::part2Used
bool part2Used
Is port name used.
Definition: ParserStructs.hh:108
MachineResourceManager::ResourceID::width
UValue width
Width of accessed port or other resource.
Definition: MachineResourceManager.hh:104
TPEF::ASpaceElement
Definition: ASpaceElement.hh:48
TTAMachine::Machine::immediateUnitNavigator
virtual ImmediateUnitNavigator immediateUnitNavigator() const
Definition: Machine.cc:416
MachineResourceManager::rFPortOrFUIndexReference
ResourceID rFPortOrFUIndexReference(TTAMachine::FunctionUnit *fu, TTAMachine::BaseRegisterFile *rf, UValue currentLine, const RegisterTerm &term, UValue slotNumber, RequestType type, std::string &resourceKeyString)
Definition: MachineResourceManager.cc:755
MachineResourceManager::RQST_INVGUARD
@ RQST_INVGUARD
Inverted register or port guard.
Definition: MachineResourceManager.hh:85
TTAMachine::RegisterGuard
Definition: Guard.hh:137
TTAMachine::Port
Definition: Port.hh:54
RegisterTerm::type
TermType type
Type of terminal that is represented by this object.
Definition: ParserStructs.hh:149
TTAMachine::Machine::Navigator::hasItem
bool hasItem(const std::string &name) const
RegisterTerm::BUS
@ BUS
Bus term.
Definition: ParserStructs.hh:143
TPEF::StringSection::string2Chunk
Chunk * string2Chunk(const std::string &str)
Definition: StringSection.cc:103
__func__
#define __func__
Definition: Application.hh:67
MachineResourceManager::registerFileIDs_
std::map< TTAMachine::BaseRegisterFile *, UValue > registerFileIDs_
Bookkeeping of already added register files.
Definition: MachineResourceManager.hh:234
MachineResourceManager::registerFileIndexReference
ResourceID registerFileIndexReference(TTAMachine::BaseRegisterFile *rf, const RegisterTerm &term, UValue slotNumber, RequestType type, std::string &resourceKeyString)
Definition: MachineResourceManager.cc:983
TTAMachine::Machine::functionUnitNavigator
virtual FunctionUnitNavigator functionUnitNavigator() const
Definition: Machine.cc:380
MachineResourceManager::tpef_
TPEF::Binary & tpef_
Binary where all used resources are added.
Definition: MachineResourceManager.hh:199
TTAMachine::Socket
Definition: Socket.hh:53
MachineResourceManager::ResourceKey::type
RequestType type
Was resource read or written or was it guard.
Definition: MachineResourceManager.hh:142
Guard.hh
TTAMachine::Unit::hasPort
virtual bool hasPort(const std::string &name) const
Definition: Unit.cc:96
MachineResourceManager::strings_
TPEF::StringSection * strings_
The string section of TPEF.
Definition: MachineResourceManager.hh:208
MachineResourceManager::lastOpOrSpecRegisterID_
UValue lastOpOrSpecRegisterID_
For generating shared ids for ports, operations or special registers.
Definition: MachineResourceManager.hh:237
MachineResourceManager::opOrPortID
UValue opOrPortID(std::string opOrPortString, const TTAMachine::Port *port)
Definition: MachineResourceManager.cc:518
MachineResourceManager::initResourceSection
void initResourceSection()
Definition: MachineResourceManager.cc:382
RegisterTerm::FUNCTION_UNIT
@ FUNCTION_UNIT
FU term.
Definition: ParserStructs.hh:144
TTAMachine::FunctionUnit::hasOperation
virtual bool hasOperation(const std::string &name) const
Definition: FunctionUnit.cc:330
TTAMachine::Machine::addressSpaceNavigator
virtual AddressSpaceNavigator addressSpaceNavigator() const
Definition: Machine.cc:392
Bus.hh
ASpaceSection.hh
MachineResourceManager::addressSpaces_
std::map< std::string, TPEF::ASpaceElement * > addressSpaces_
Bookkeeping for already requested address spaces.
Definition: MachineResourceManager.hh:216
TTAMachine::Bus::guardCount
int guardCount() const
Definition: Bus.cc:441
TTAMachine::Socket::isConnectedTo
bool isConnectedTo(const Bus &bus) const
Definition: Socket.cc:331
TPEF::Section::setName
void setName(const ReferenceManager::SafePointer *sectionName)
TTAMachine::Bus::guard
Guard * guard(int index) const
Definition: Bus.cc:456
TTAMachine::Unit::portCount
virtual int portCount() const
Definition: Unit.cc:135
Exception::errorMessage
std::string errorMessage() const
Definition: Exception.cc:123
MachineResourceManager::findDataAddressSpace
TPEF::ASpaceElement * findDataAddressSpace(std::string name)
Definition: MachineResourceManager.cc:83
TTAMachine::AddressSpace::width
virtual int width() const
Definition: AddressSpace.cc:155
MachineResourceManager::aSpaceSection_
TPEF::ASpaceSection * aSpaceSection_
The address space section of TPEF.
Definition: MachineResourceManager.hh:205
MachineResourceManager::ResourceID::unit
UValue unit
TPEF Resource unit id.
Definition: MachineResourceManager.hh:100
TTAMachine::BaseRegisterFile::port
virtual RFPort * port(const std::string &name) const
Definition: BaseRegisterFile.cc:129
TPEF::ASpaceElement::setMAU
void setMAU(Byte aMAU)
TTAMachine::Machine::registerFileNavigator
virtual RegisterFileNavigator registerFileNavigator() const
Definition: Machine.cc:450
MapTools::containsKey
static bool containsKey(const MapType &aMap, const KeyType &aKey)
RegisterTerm::indexTerm
IndexTerm indexTerm
The index term, if type field is INDEX. Otherwise not used.
Definition: ParserStructs.hh:156
IllegalMachine
Definition: Exception.hh:878
TTAMachine::Guard::isInverted
virtual bool isInverted() const
TPEF::Section::setASpace
void setASpace(const ReferenceManager::SafePointer *addrSpace)
TTAMachine::Port::name
virtual std::string name() const
Definition: Port.cc:141
RegisterTerm::fuTerm
FUTerm fuTerm
The fu term, if type field is FUNCTION_UNIT. Otherwise not used.
Definition: ParserStructs.hh:154
FUPort.hh
MachineResourceManager::RQST_GUARD
@ RQST_GUARD
Register or port guard.
Definition: MachineResourceManager.hh:84
ControlUnit.hh
TTAMachine::Machine::busNavigator
virtual BusNavigator busNavigator() const
Definition: Machine.cc:356
SpecialRegisterPort.hh
MachineResourceManager::resourceID
ResourceID & resourceID(UValue currentLine, const RegisterTerm &term, UValue slotNumber, RequestType type)
Definition: MachineResourceManager.cc:285
TPEF::Section::setLink
void setLink(const ReferenceManager::SafePointer *aLink)
TPEF::ASpaceElement::setName
void setName(const ReferenceManager::SafePointer *aName)
TTAMachine::Port::outputSocket
virtual Socket * outputSocket() const
Definition: Port.cc:281
TPEF::ASpaceSection::setUndefinedASpace
void setUndefinedASpace(ASpaceElement *aSpace)
Definition: ASpaceSection.cc:109
MachineResourceManager::resourceMap_
std::map< ResourceKey, ResourceID > resourceMap_
Bookkeeping for already requested resources.
Definition: MachineResourceManager.hh:224
MachineResourceManager::resourceSection_
TPEF::ResourceSection * resourceSection_
The resource section of TPEF.
Definition: MachineResourceManager.hh:222
MachineResourceManager::functionUnitPortResource
ResourceID functionUnitPortResource(const RegisterTerm &term)
Definition: MachineResourceManager.cc:577
TTAMachine::Machine::Navigator::item
ComponentType * item(int index) const
MachineResourceManager::undefinedAddressSpace
TPEF::ASpaceElement * undefinedAddressSpace()
Definition: MachineResourceManager.cc:179
TPEF::ResourceElement::setId
void setId(HalfWord aId)
TTAMachine::PortGuard
Definition: Guard.hh:99
TTAMachine::FunctionUnit::operation
virtual HWOperation * operation(const std::string &name) const
Definition: FunctionUnit.cc:363
RegisterTerm
Definition: ParserStructs.hh:136
TTAMachine
Definition: Assembler.hh:48
MachineResourceManager::codeAddressSpace
TPEF::ASpaceElement * codeAddressSpace()
Definition: MachineResourceManager.cc:213
TTAMachine::BaseRegisterFile::width
virtual int width() const
TPEF::Binary::setStrings
void setStrings(StringSection *strTable)
AssemblyParserDiagnostic::addWarning
void addWarning(UValue lineNumber, const std::string &message)
Definition: AssemblyParserDiagnostic.cc:56
TTAMachine::RegisterGuard::registerFile
const RegisterFile * registerFile() const
TPEF::ASpaceSection
Definition: ASpaceSection.hh:44
MoveElement.hh
MachineResourceManager::lastFunctionUnitID_
UValue lastFunctionUnitID_
For generating function unit resource ids.
Definition: MachineResourceManager.hh:227
TTAMachine::Machine::Navigator
Definition: Machine.hh:186
MachineResourceManager::undefASpace_
TPEF::ASpaceElement * undefASpace_
The undefined address space element of TPEF.
Definition: MachineResourceManager.hh:211
TPEF::ResourceElement::setName
void setName(ReferenceManager::SafePointer *aName)
MachineResourceManager::ResourceKey::slotNumber
UValue slotNumber
Bus that was used.
Definition: MachineResourceManager.hh:140
TPEF::Chunk
Definition: Chunk.hh:45
MachineResourceManager::addResourceElement
void addResourceElement(TPEF::ResourceElement *resource)
Definition: MachineResourceManager.cc:418
FUTerm::part1
std::string part1
Unit name.
Definition: ParserStructs.hh:81
InstanceNotFound
Definition: Exception.hh:304
MachineResourceManager::RQST_WRITE
@ RQST_WRITE
Register or port for writing.
Definition: MachineResourceManager.hh:83
TPEF
Definition: Assembler.hh:43
TTAMachine::Machine
Definition: Machine.hh:73
FUTerm::part3
std::string part3
Operation name.
Definition: ParserStructs.hh:85
Binary.hh
TTAMachine::ImmediateUnit
Definition: ImmediateUnit.hh:50