OpenASIP 2.2
Loading...
Searching...
No Matches
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"
44#include "FUPort.hh"
45#include "HWOperation.hh"
46#include "Guard.hh"
48#include "Exception.hh"
49
50#include "Bus.hh"
51
52using namespace TPEF;
53using 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,
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 */
128UValue
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 */
139Section*
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*>(
188
189 assert(aSpaceSection_ != NULL);
190
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 */
248Chunk*
250
251 if (strings_ == NULL) {
252 strings_ = dynamic_cast<StringSection*>(
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 */
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*>(
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);
404 newRes->setName(stringToChunk(bus->name()));
405
407 }
408
410 }
411}
412
413
414/**
415 * Adds resource element to TPEF.
416 */
417void
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 */
445UValue
447
449 // create resource element and add its unit id to map
451
452 ResourceElement* newRes = new ResourceElement();
453
454 newRes->setId(lastFunctionUnitID_);
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 */
479UValue
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) {
492 } else {
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 */
517UValue
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) {
533 } else {
535 }
536
537 } else {
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 */
556std::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
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: " +
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: " +
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}
#define __func__
#define abortWithError(message)
#define assert(condition)
unsigned long UValue
void addWarning(UValue lineNumber, const std::string &message)
bool prev
Previous or next bus register.
static std::string toString(const T &source)
std::string errorMessage() const
Definition Exception.cc:123
void setCause(const Exception &cause)
Definition Exception.cc:75
std::string part3
Operation name.
std::string part2
Port name.
std::string part1
Unit name.
bool part3Used
Is operation part of the term used.
std::string part1
Unit name.
std::string part2
Port or operation name.
bool part2Used
Is port name used.
UValue index
Register or operand index.
TPEF::StringSection * strings_
The string section of TPEF.
std::map< std::string, UValue > opOrPortIDs_
Bookkeeping of already added ports, operations and special registers.
ResourceID & resourceID(UValue currentLine, const RegisterTerm &term, UValue slotNumber, RequestType type)
AssemblyParserDiagnostic * parent_
Assembler root class for adding warnings.
void addResourceElement(TPEF::ResourceElement *resource)
const TTAMachine::Machine & adf_
Machine where manager tries to find used resources.
UValue lastRegisterFileID_
For generating register file resource ids.
UValue functionUnitID(TTAMachine::FunctionUnit *unit)
std::map< TTAMachine::BaseRegisterFile *, UValue > registerFileIDs_
Bookkeeping of already added register files.
std::string requestTypeString(RequestType type) const
ResourceID rFPortOrFUIndexReference(TTAMachine::FunctionUnit *fu, TTAMachine::BaseRegisterFile *rf, UValue currentLine, const RegisterTerm &term, UValue slotNumber, RequestType type, std::string &resourceKeyString)
ResourceID functionUnitPortResource(const RegisterTerm &term)
TPEF::ResourceSection * resourceSection_
The resource section of TPEF.
UValue lastOpOrSpecRegisterID_
For generating shared ids for ports, operations or special registers.
ResourceID registerFileIndexReference(TTAMachine::BaseRegisterFile *rf, const RegisterTerm &term, UValue slotNumber, RequestType type, std::string &resourceKeyString)
std::map< std::string, TPEF::ASpaceElement * > addressSpaces_
Bookkeeping for already requested address spaces.
UValue findBusWidth(UValue slotNumber)
MachineResourceManager(TPEF::Binary &tpef, const TTAMachine::Machine &adf, AssemblyParserDiagnostic *parent_)
@ RQST_INVGUARD
Inverted register or port guard.
@ RQST_READ
Register of port for reading.
@ RQST_WRITE
Register or port for writing.
@ RQST_GUARD
Register or port guard.
UValue opOrPortID(std::string opOrPortString, const TTAMachine::Port *port)
TPEF::Binary & tpef_
Binary where all used resources are added.
TPEF::ASpaceSection * aSpaceSection_
The address space section of TPEF.
TPEF::StringSection * stringSection()
TPEF::ASpaceElement * findDataAddressSpace(std::string name)
ResourceID indexResource(UValue currentLine, const RegisterTerm &term, UValue slotNumber, RequestType type, std::string &resourceKeyString)
TPEF::ASpaceElement * codeASpace_
The instruction address space element of TPEF.
TPEF::ASpaceElement * undefinedAddressSpace()
TPEF::Chunk * stringToChunk(const std::string aStr)
std::map< TTAMachine::FunctionUnit *, UValue > functionUnitIDs_
Bookkeeping of already added function units.
TPEF::ASpaceElement * codeAddressSpace()
UValue lastFunctionUnitID_
For generating function unit resource ids.
UValue registerFileID(TTAMachine::BaseRegisterFile *rf)
TPEF::ASpaceElement * undefASpace_
The undefined address space element of TPEF.
TPEF::NullSection * nullSection_
The null section of TPEF.
std::map< ResourceKey, ResourceID > resourceMap_
Bookkeeping for already requested resources.
TPEF::ResourceSection * resourceSection()
static bool containsKey(const MapType &aMap, const KeyType &aKey)
@ BUS
Bus term.
@ FUNCTION_UNIT
FU term.
@ INDEX
Index term.
FUTerm fuTerm
The fu term, if type field is FUNCTION_UNIT. Otherwise not used.
IndexTerm indexTerm
The index term, if type field is INDEX. Otherwise not used.
TermType type
Type of terminal that is represented by this object.
BusTerm busTerm
The bus term, if type field is BUS. Otherwise not used.
void setName(const ReferenceManager::SafePointer *aName)
void setMAU(Byte aMAU)
void setUndefinedASpace(ASpaceElement *aSpace)
void addSection(Section *section)
void setStrings(StringSection *strTable)
virtual void addByte(Byte aByte)
@ MF_RF
Register file.
@ MF_IMM
Immediate.
@ MF_UNIT
Function unit.
void setId(HalfWord aId)
ResourceType type() const
void setName(ReferenceManager::SafePointer *aName)
HalfWord id() const
@ MRT_BUS
Transport bus.
@ MRT_IMM
Immediate unit.
@ MRT_SR
Special register.
@ MRT_UNIT
Function unit.
@ MRT_PORT
Function unit port.
@ MRT_OP
Operation operand or function unit register.
Chunk * name() const
void setType(ResourceType aType)
static Section * createSection(SectionType type)
Definition Section.cc:91
virtual void addElement(SectionElement *element)
Definition Section.cc:133
@ ST_STRTAB
String table.
Definition Section.hh:71
@ ST_ADDRSP
Address space section.
Definition Section.hh:77
@ ST_NULL
NULL Section.
Definition Section.hh:70
@ ST_MR
Machine resources section.
Definition Section.hh:78
void setLink(const ReferenceManager::SafePointer *aLink)
void setASpace(const ReferenceManager::SafePointer *addrSpace)
void setName(const ReferenceManager::SafePointer *sectionName)
std::string chunk2String(const Chunk *chunk) const
Chunk * string2Chunk(const std::string &str)
virtual int width() const
virtual int numberOfRegisters() const
virtual int width() const
virtual RFPort * port(const std::string &name) const
int width() const
Definition Bus.cc:149
Guard * guard(int index) const
Definition Bus.cc:456
int guardCount() const
Definition Bus.cc:441
virtual TCEString name() const
virtual AddressSpace * addressSpace() const
virtual HWOperation * operation(const std::string &name) const
virtual bool hasOperation(const std::string &name) const
virtual BaseFUPort * port(const std::string &name) const
virtual bool isInverted() const
virtual FUPort * port(int operand) const
int io(const FUPort &port) const
ComponentType * item(int index) const
bool hasItem(const std::string &name) const
virtual RegisterFileNavigator registerFileNavigator() const
Definition Machine.cc:450
virtual FunctionUnitNavigator functionUnitNavigator() const
Definition Machine.cc:380
virtual ImmediateUnitNavigator immediateUnitNavigator() const
Definition Machine.cc:416
virtual BusNavigator busNavigator() const
Definition Machine.cc:356
virtual AddressSpaceNavigator addressSpaceNavigator() const
Definition Machine.cc:392
virtual ControlUnit * controlUnit() const
Definition Machine.cc:345
FUPort * port() const
virtual Socket * outputSocket() const
Definition Port.cc:281
virtual int width() const =0
virtual Socket * inputSocket() const
Definition Port.cc:261
virtual std::string name() const
Definition Port.cc:141
const RegisterFile * registerFile() const
bool isConnectedTo(const Bus &bus) const
Definition Socket.cc:331
virtual bool hasPort(const std::string &name) const
Definition Unit.cc:96
virtual int portCount() const
Definition Unit.cc:135
UValue width
Width of accessed port or other resource.
TPEF::MoveElement::FieldType type
Resource type.
UValue index
TPEF Resource operand id or register file index.
std::string keyString
Key string for resource.
RequestType type
Was resource read or written or was it guard.