OpenASIP 2.2
Loading...
Searching...
No Matches
MachineConnectivityCheck.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 MachineConnectivityCheck.cc
26 *
27 * Implementation of MachineConnectivityCheck class.
28 *
29 * @author Pekka Jääskeläinen 2007 (pjaaskel-no.spam-cs.tut.fi)
30 * @author Heikki Kultala 2008 (hkultala-no.spam-cs.tut.fi)
31 * @note rating: red
32 */
33
34#include <set>
35
37#include "MachineInfo.hh"
38#include "Application.hh"
39#include "Bus.hh"
40#include "Segment.hh"
41#include "SetTools.hh"
42#include "RegisterFile.hh"
43#include "ControlUnit.hh"
45#include "MathTools.hh"
46#include "TerminalImmediate.hh"
47#include "Move.hh"
48#include "TerminalFUPort.hh"
49#include "HWOperation.hh"
50#include "TCEString.hh"
51#include "Operation.hh"
52#include "FUPort.hh"
53#include "ProgramOperation.hh"
54#include "AssocTools.hh"
55#include "StringTools.hh"
56#include "MoveNode.hh"
57#include "MoveGuard.hh"
58#include "TemplateSlot.hh"
59#include "Guard.hh"
60#include "OperationPool.hh"
61#include "Operand.hh"
62
63using namespace TTAMachine;
64/**
65 * Constructor for using this generic class directly.
66 */
68 MachineCheck("Common helper functionality for connectivity checks.") {
69}
70
71/**
72 * Destructor.
73 */
76
77/**
78 * Constructor for deriving.
79 *
80 * @param shortDesc The short description of the check.
81 */
83 const std::string& shortDesc_) : MachineCheck(shortDesc_) {
84}
85
86
87bool
89 PortSet sourcePorts,
90 PortSet destinationPorts,
91 const Guard* guard) {
92 for (PortSet::iterator i =
93 sourcePorts.begin();
94 i != sourcePorts.end(); i++) {
95 const TTAMachine::Port& sport = **i;
96 for (PortSet::iterator j =
97 destinationPorts.begin();
98 j != destinationPorts.end(); j++) {
99 if (isConnected(sport, **j, guard)) {
100 return true;
101 }
102 }
103 }
104 return false;
105}
106
107/**
108 * Dummy implementation for the pure virtual method MachineCheck::check().
109 *
110 * The implementation is needed for generation of Python bindings, as
111 * Boost.Python cannot create instances of abstract base classes.
112 */
113
114bool
119
120/**
121 * Checks whether there is a connection between two ports.
122 *
123 * @param sourcePort The source (rf/fu) port.
124 * @param destinationPort The destination (rf/fu) port.
125 * @return True if there is at least one path between the given ports.
126 */
127bool
129 const TTAMachine::Port& sourcePort,
130 const TTAMachine::Port& destinationPort,
131 const Guard* guard) {
132
133 // TODO: replace this cache's second value(bool) with set of buses.
134 PortPortBoolMap::const_iterator
135 i = portPortCache_.find(PortPortPair(&sourcePort, &destinationPort));
136 if (i != portPortCache_.end()) {
137 if (i->second == false || guard == NULL) {
138 return i->second;
139 }
140 }
141 std::set<const TTAMachine::Bus*> sourceBuses;
143 sourcePort, sourceBuses);
144
145 std::set<const TTAMachine::Bus*> destinationBuses;
147 destinationPort, destinationBuses);
148
149 std::set<const TTAMachine::Bus*> sharedBuses;
150 SetTools::intersection(sourceBuses, destinationBuses, sharedBuses);
151 if (sharedBuses.size() > 0) {
152 portPortCache_[PortPortPair(&sourcePort,&destinationPort)] = true;
153
154 if (guard == NULL) {
155 return true;
156 }
157
158 for (std::set<const TTAMachine::Bus*>::iterator i = sharedBuses.begin();
159 i != sharedBuses.end(); i++) {
160 if ((*i)->hasGuard(*guard)) {
161 return true;
162 }
163 }
164
165 return false; // bus found but lacks the guards
166 } else {
167 portPortCache_[PortPortPair(&sourcePort,&destinationPort)] = false;
168 return false;
169 }
170}
171
172/**
173 * Checks whether an immediate with given width can be transported to the
174 * destination register file.
175 *
176 * @param destRF The destination RF.
177 * @param immediate The immediate to transport.
178 * @return True if there is at least one path between the given ports.
179 */
180bool
182 const TTAProgram::TerminalImmediate& immediate,
183 const TTAMachine::BaseRegisterFile& destRF,
184 const Guard* guard) {
185
186 std::set<const TTAMachine::Bus*> buses;
188
189 for (auto bus : buses) {
190 int requiredBits =
192 bus->signExtends(), immediate, *destRF.machine());
193 if (bus->immediateWidth() < requiredBits) {
194 continue;
195 }
196
197 if (guard == NULL) {
198 return true;
199 } else {
200 if (bus->hasGuard(*guard)) {
201 return true;
202 }
203 }
204 }
205 return false;
206}
207
208/**
209 * Checks whether an immediate with given width can be transported to the
210 * destination port.
211 *
212 * @param immediate The immediate to transport.
213 * @param destinationPort The destination port.
214 * @return True if there is at least one path between the given ports.
215 */
216bool
218 const TTAProgram::TerminalImmediate& immediate,
219 const TTAMachine::Port& destinationPort,
220 const Guard* guard) {
221
222 std::set<const TTAMachine::Bus*> buses;
224 destinationPort, buses);
225
226 for (auto i = buses.begin(); i != buses.end(); ++i) {
227 const TTAMachine::Bus& bus = **i;
228
229 if (!canTransportImmediate(immediate, bus)) {
230 continue;
231 }
232 if (guard == NULL) {
233 return true;
234 } else {
235 if (bus.hasGuard(*guard)) {
236 return true;
237 }
238 }
239 }
240 return false;
241}
242
243bool
245 const TTAProgram::TerminalImmediate& immediate,
246 PortSet destinationPorts,
247 const Guard* guard) {
248
249 for (PortSet::iterator i =
250 destinationPorts.begin();
251 i != destinationPorts.end(); i++) {
252 if (canTransportImmediate(immediate, **i, guard)) {
253 return true;
254 }
255 }
256 return false;
257}
258
259/**
260 * Checks whether an immediate with given width can be transported on the
261 * bus.
262 *
263 * @param immediate The immediate to transport.
264 * @param bus The bus.
265 * @return True if the bus can transport the immediate as inline.
266 */
267bool
269 const TTAProgram::TerminalImmediate& immediate,
270 const TTAMachine::Bus& bus) {
271
272 int requiredBits =
274 bus.signExtends(), immediate, *bus.machine());
275 if (bus.immediateWidth() >= requiredBits) {
276 return true;
277 } else {
278 return false;
279 }
280}
281
282/**
283 * Checks whether there is a connection from some outport port of a
284 * register file or immediate unit into the specified port.
285 *
286 * @param sourceRF Source RF/Immediate unit.
287 * @param destPort The destination port.
288 * @return True if there is at least one connection from any of the output
289 * ports of the source RF/Imm unit into the destination port.
290 */
291bool
293 const TTAMachine::BaseRegisterFile& sourceRF,
294 const TTAMachine::Port& destPort) {
295
296 RfPortBoolMap::const_iterator
297 i = rfPortCache_.find(RfPortPair(&sourceRF, &destPort));
298 if (i != rfPortCache_.end()) {
299 return i->second;
300 }
301 std::set<const TTAMachine::Bus*> destBuses = connectedSourceBuses(destPort);
302 std::set<const TTAMachine::Bus*> srcBuses;
303
304 for (int i = 0; i < sourceRF.portCount(); i++) {
305 const TTAMachine::Port& port = *sourceRF.port(i);
306 if (port.outputSocket() != NULL) {
307 appendConnectedDestinationBuses(port, srcBuses);
308 }
309 }
310
311 std::set<const TTAMachine::Bus*> sharedBuses;
313 srcBuses, destBuses, sharedBuses);
314 if (sharedBuses.size() > 0) {
315 rfPortCache_[RfPortPair(&sourceRF,&destPort)] = true;
316 return true;
317 } else {
318 rfPortCache_[RfPortPair(&sourceRF,&destPort)] = false;
319 return false;
320 }
321}
322
323/**
324 * Checks whether there is a connection from some outport port of a
325 * register file or immediate unit into some input port of the given
326 * target register file or immediate unit.
327 *
328 * @param sourceRF Source RF/Immediate unit.
329 * @param destRF Source RF/Immediate unit.
330 * @return True if there is at least one connection from any of the output
331 * ports of the source RF/Imm unit into the destination RF.
332 */
333bool
335 const TTAMachine::BaseRegisterFile& sourceRF,
336 const TTAMachine::BaseRegisterFile& destRF,
337 const TTAMachine::Guard* guard) {
338
339 RfRfBoolMap::const_iterator
340 i = rfRfCache_.find(RfRfPair(&sourceRF, &destRF));
341 if (i != rfRfCache_.end()) {
342 if (i->second == false || guard == NULL) {
343 return i->second;
344 }
345 }
346 std::set<const TTAMachine::Bus*> srcBuses;
347 appendConnectedDestinationBuses(sourceRF, srcBuses);
348
349 std::set<const TTAMachine::Bus*> dstBuses;
350 appendConnectedSourceBuses(destRF, dstBuses);
351
352 std::set<const TTAMachine::Bus*> sharedBuses;
353 SetTools::intersection(srcBuses, dstBuses, sharedBuses);
354 if (sharedBuses.size() > 0) {
355 rfRfCache_[RfRfPair(&sourceRF,&destRF)] = true;
356 if (guard == NULL) {
357 return true;
358 }
359
360 for (std::set<const TTAMachine::Bus*>::iterator i = sharedBuses.begin();
361 i != sharedBuses.end(); i++) {
362 if ((*i)->hasGuard(*guard)) {
363 return true;
364 }
365 }
366 return false; // bus found but lacks the guards
367 } else {
368 rfRfCache_[RfRfPair(&sourceRF,&destRF)] = false;
369 return false;
370 }
371}
372
373/**
374 * Checks whether there is a connection from some outport port of a
375 * register file or immediate unit into some input port of the given
376 * target function unit.
377 *
378 * @param sourceRF Source RF/Immediate unit.
379 * @param destFU Destination FU.
380 * @return True if there is at least one connection from any of the output
381 * ports of the source RF/Imm unit into the destination FU.
382 */
383bool
385 const TTAMachine::BaseRegisterFile& sourceRF,
386 const TTAMachine::FunctionUnit& destFU) {
387
388 std::set<const TTAMachine::Bus*> srcBuses;
389 appendConnectedDestinationBuses(sourceRF, srcBuses);
390
391 std::set<const TTAMachine::Bus*> dstBuses;
392 appendConnectedSourceBuses(destFU, dstBuses);
393
394 std::set<const TTAMachine::Bus*> sharedBuses;
395 SetTools::intersection(srcBuses, dstBuses, sharedBuses);
396 return (sharedBuses.size() > 0);
397}
398
399
400/**
401 * Checks whether there is a connection from specified port into some
402 * input port of a register file.
403 *
404 * @param sourcePort The source port.
405 * @param destRF Destination register file.
406 * @return True if there exists at least one connection from source to
407 * any input port of destination register file.
408 */
409bool
411 const TTAMachine::Port& sourcePort,
412 const TTAMachine::RegisterFile& destRF) {
413
414 PortRfBoolMap::const_iterator
415 i = portRfCache_.find(PortRfPair(&sourcePort, &destRF));
416 if (i != portRfCache_.end()) {
417 return i->second;
418 }
419
420 std::set<const TTAMachine::Bus*> sourceBuses =
421 connectedDestinationBuses(sourcePort);
422 std::set<const TTAMachine::Bus*> destBuses;
423
424 for (int i = 0; i < destRF.portCount(); i++) {
425 const TTAMachine::Port& port = *destRF.port(i);
426 if (port.inputSocket() != NULL) {
427 appendConnectedSourceBuses(port, destBuses);
428 }
429 }
430
431 std::set<const TTAMachine::Bus*> sharedBuses;
432 SetTools::intersection(sourceBuses, destBuses, sharedBuses);
433
434 if (sharedBuses.size() > 0) {
435 portRfCache_[PortRfPair(&sourcePort,&destRF)] = true;
436 return true;
437 } else {
438 portRfCache_[PortRfPair(&sourcePort,&destRF)] = false;
439 return false;
440 }
441}
442
443/**
444 * Checks whether the two RFs are connected to the exact same buses.
445 */
446bool
449 const TTAMachine::BaseRegisterFile& RF2) {
450
451 std::set<const TTAMachine::Bus*> dstBuses1, dstBuses2;
452 appendConnectedDestinationBuses(RF1, dstBuses1);
453 appendConnectedDestinationBuses(RF2, dstBuses2);
454
455 std::set<const TTAMachine::Bus*> srcBuses1, srcBuses2;
456 appendConnectedSourceBuses(RF1, srcBuses1);
457 appendConnectedSourceBuses(RF2, srcBuses2);
458
459 return dstBuses1 == dstBuses2 && srcBuses1 == srcBuses2;
460}
461
462bool
464 const TTAMachine::Port& port, std::set<int> widths) {
465 auto fup = dynamic_cast<const FUPort*>(&port);
466 if (fup == nullptr) {
467 return false;
468 }
469 auto fu = dynamic_cast<const FunctionUnit*>(port.parentUnit());
470 if (fu == nullptr) {
471 return false;
472 }
473
474 OperationPool opPool;
475
476 for (int i = 0; i < fu->operationCount(); i++) {
477 auto hwop = fu->operation(i);
478 if (!hwop->isBound(*fup))
479 continue;
480
481 int opIndex = hwop->io(*fup);
482 int oprWidth = operandWidth(*hwop, opIndex);
483 if (AssocTools::containsKey(widths, oprWidth)) {
484 return true;
485 }
486 }
487 return false;
488}
489
490/**
491 * Checks whether there is a connection from the given Register file
492 * or Immediate unit to all FU's and control unit of the machine.
493 *
494 * It both this and toRfConnected() returns true,
495 * then this FU can be used as the only register file
496 * to be used for reduced connectivity-register copying.
497 *
498 * @param brf Register file or immediate unit being checked.
499 * @return true if this RF can write to all ports af all FU's.
500 */
501bool
503 const TTAMachine::BaseRegisterFile& brf) {
504
505 int width = brf.width();
506 bool isVectorRegs = width > 32;
507 TTAMachine::Machine& mach = *brf.machine();
510
511
512 std::set<const TTAMachine::Bus*> rfBuses;
513
514 for (int i = 0; i < brf.portCount(); i++) {
515 const TTAMachine::Port& port = *brf.port(i);
516 if (port.outputSocket() != NULL) {
517 appendConnectedDestinationBuses(port, rfBuses);
518 }
519 }
520
521 std::set<int> widths;
522 widths.insert(brf.width());
523
524 auto widthsExt = widths;
525 if (width == 32) {
526 widthsExt.insert(1);
527 widthsExt.insert(8);
528 widthsExt.insert(16);
529 }
530 if (width == 1) {
531 widthsExt.insert(32);
532 }
533
534 // check connections to function units
535 for (auto fu: fuNav) {
536 for (int j = 0; j < fu->portCount(); j++ ) {
537 Port& port = *fu->port(j);
538 // connections from RF to FU's
539 if (port.inputSocket() != NULL &&
540 isPortApplicableToWidths(port, widthsExt)) {
541 std::set<const TTAMachine::Bus*> sharedBuses;
543 rfBuses, connectedSourceBuses(port), sharedBuses);
544 if (sharedBuses.size() == 0) {
545 return false;
546 }
547 }
548 }
549 }
550
551 // no need to transfer data from vector regs to control unit.
552 if (isVectorRegs) {
553 return true;
554 }
555
556 // check connections to control unit
558 for (int i = 0; i < cu.portCount(); i++ ) {
559 Port& port = *cu.port(i);
560
561 // connections from RF to CU
562 if (port.inputSocket() != NULL &&
563 isPortApplicableToWidths(port, widths)) {
564 std::set<const TTAMachine::Bus*> sharedBuses;
566 rfBuses, connectedSourceBuses(port), sharedBuses);
567 if (sharedBuses.size() == 0) {
568 return false;
569 }
570 }
571 }
572 return true;
573}
574
575/**
576 * Checks if an RF is connected to all other units
577 *
578 * It this returns true,
579 * then this FU can be used as the only register file
580 * to be used for reduced connectivity-register copying.
581 *
582 * @param rf Register file to be checked.
583 * @return Returns true if the given RF is connected to all ports in all FU's
584 * and at least to some output port in all immediate units.
585 */
586bool
592
593std::pair<int, int>
595 const TTAMachine::Machine& mach) {
596 std::pair<int, int> rv;
597 std::set<const TTAMachine::Bus*> buses;
598 for (auto b: mach.busNavigator()) {
599 buses.insert(b);
600 }
601 shortImmBits(buses, rv);
602 return rv;
603}
604
605void
607 std::set<const TTAMachine::Bus*>& buses, std::pair<int, int>& immBits) {
608
609 for (auto b: buses) {
610 int w = b->immediateWidth();
611 if (b->signExtends()) {
612 immBits.first = std::max(immBits.first, w);
613 } else {
614 immBits.second = std::max(immBits.second,w);
615 }
616 }
617}
618
619std::pair<int, int>
621 const TTAMachine::RegisterFile& rf) {
622 auto mach = rf.machine();
623 std::pair<int, int> rv(0,0);
624 std::set<const TTAMachine::Bus*> rfBuses;
625
626 if (mach == nullptr) {
627 return rv;
628 }
629
630 for (int i = 0; i < rf.portCount(); i++) {
631 auto port = rf.port(i);
632 if (port->inputSocket() != NULL) {
633 appendConnectedSourceBuses(*port, rfBuses);
634 }
635 }
636 shortImmBits(rfBuses, rv);
637
638 // then check LIMM connections.
639 for (auto iu: mach->immediateUnitNavigator()) {
640 int w = iu->width();
641 for (int j = 0; j < iu->portCount(); j++ ) {
642 Port& port = *iu->port(j);
643 if (port.outputSocket() == nullptr)
644 continue;
645
646 std::set<const TTAMachine::Bus*> sharedBuses;
648 rfBuses, connectedDestinationBuses(port),sharedBuses);
649 // TODO: check bus widths.
650 if (sharedBuses.size() != 0) {
651 if (iu->signExtends()) {
652 rv.first = std::max(rv.first, w);
653 } else {
654 rv.second = std::max(rv.second, w);
655 }
656 }
657 }
658 }
659 return rv;
660}
661
662/**
663 * Checks whether there is a connection to the given Register file
664 * from all FU's and control unit of the machine.
665 *
666 * It both this and fromRfConnected() returns true,
667 * then this FU can be used as the only register file
668 * to be used for reduced connectivity-register copying.
669 *
670 * @param brf Register file or immediate unit being checked.
671 * @return true if this RF can write to all ports af all FU's.
672 */
673bool
675 const TTAMachine::RegisterFile& rf) {
676
677 int width = rf.width();
678 bool isVectorRF = width > 32;
679 TTAMachine::Machine& mach = *rf.machine();
684
685 std::set<const TTAMachine::Bus*> rfBuses;
686
687 std::set<int> widths;
688 widths.insert(rf.width());
689 if (width == 32) {
690 widths.insert(1);
691 widths.insert(16); // Needed for half-floats?
692
693 }
694 if (width == 1) {
695 widths.insert(32);
696 }
697
698 for (int i = 0; i < rf.portCount(); i++) {
699 const TTAMachine::Port& port = *rf.port(i);
700 if (port.inputSocket() != NULL) {
701 appendConnectedSourceBuses(port, rfBuses);
702 }
703 }
704
705 // check connections from function units
706 for (auto fu: fuNav) {
707 for (int j = 0; j < fu->portCount(); j++ ) {
708 Port& port = *fu->port(j);
709 // connections from FU to RF
710 if (port.outputSocket() != NULL &&
711 isPortApplicableToWidths(port, widths) &&
712 port.width() >= width) {
713 std::set<const TTAMachine::Bus*> sharedBuses;
715 rfBuses, connectedDestinationBuses(port), sharedBuses);
716 if (sharedBuses.size() == 0) {
717 return false;
718 }
719 }
720 }
721 }
722
723 // no need to check for imms or cu connections for vector RFs
724 if (isVectorRF) {
725 return true;
726 }
727
728 // check connections from control unit
730 for (int i = 0; i < cu.portCount(); i++ ) {
731 Port& port = *cu.port(i);
732
733 // connections from CU to RF
734 if (port.width() == width) {
735 if (port.outputSocket() != NULL) {
736 std::set<const TTAMachine::Bus*> sharedBuses;
738 rfBuses, connectedDestinationBuses(port), sharedBuses);
739 if (sharedBuses.size() == 0) {
740 return false;
741 }
742 }
743 }
744 }
745
746 // if all immediates can be written to the RF?
747 auto rfImmBits = immBits(rf);
748 if (rfImmBits.first >= width || rfImmBits.second >= width) {
749 return true;
750 }
751
752 // if there are wider imms in the adf, not ok
753 auto allImmBits = immBits(*rf.machine());
754 if (rfImmBits.first < allImmBits.first ||
755 (rfImmBits.second < allImmBits.second &&
756 (rfImmBits.first-1) < allImmBits.second)) {
757 return false;
758 }
759 return true;
760}
761
762/**
763 * Returns all buses the given port can read from.
764 *
765 * @param port The port to check.
766 * @return The set of buses connected to the port.
767 */
768std::set<const TTAMachine::Bus*>
770 const TTAMachine::Port& port) {
771
772 std::set<const TTAMachine::Bus*> buses;
773 appendConnectedSourceBuses(port,buses);
774 return buses;
775}
776
777/**
778 * Returns all buses the given port can write to
779 *
780 * @param port The port to check.
781 * @return The set of buses connected to the port.
782 */
783std::set<const TTAMachine::Bus*>
785 const TTAMachine::Port& port) {
786
787 std::set<const TTAMachine::Bus*> buses;
789 return buses;
790}
791
792/**
793 * Appends source buses connected to a given (input) port.
794 *
795 * @param port The port to check
796 * @param buses Set where the connected buses are appended.
797 */
798void
800 const TTAMachine::Port& port, std::set<const TTAMachine::Bus*>& buses) {
801
802 const TTAMachine::Socket* inputS = port.inputSocket();
803
804 if (inputS != NULL) {
805 for (int i = 0; i < inputS->segmentCount(); ++i) {
806 buses.insert(inputS->segment(i)->parentBus());
807 }
808 }
809}
810
811/**
812 * Appends destination buses connected to a given (output) port.
813 *
814 * @param port The port to check
815 * @param buses Set where the connected buses are appended.
816 */
817void
819 const TTAMachine::Port& port, std::set<const TTAMachine::Bus*>& buses) {
820
821 const TTAMachine::Socket* outputS = port.outputSocket();
822
823 if (outputS != NULL) {
824 for (int i = 0; i < outputS->segmentCount(); ++i) {
825 buses.insert(outputS->segment(i)->parentBus());
826 }
827 }
828}
829
830/**
831 * Appends source buses connected to a given unit.
832 *
833 * Source buses are the buses the unit can read data from.
834 *
835 * @param unit The unit to check
836 * @param buses Set where the connected buses are appended.
837 */
838void
840 const TTAMachine::Unit& unit, std::set<const TTAMachine::Bus*>& buses) {
841
842 for (int p = 0; p < unit.portCount(); ++p) {
843 const TTAMachine::Port& port = *unit.port(p);
844 appendConnectedSourceBuses(port, buses);
845 }
846}
847
848/**
849 * Appends destination buses connected to a given unit.
850 *
851 * Destination buses are the buses the unit can write data to.
852 *
853 * @param unit The unit to check
854 * @param buses Set where the connected buses are appended.
855 */
856void
858 const TTAMachine::Unit& unit, std::set<const TTAMachine::Bus*>& buses) {
859
860 for (int p = 0; p < unit.portCount(); ++p) {
861 appendConnectedDestinationBuses(*unit.port(p), buses);
862 }
863}
864
865/**
866 * Checks if given RF is connected to differently connected RFs,
867 * to know if we need to reserve temp registers for transfers between
868 * the two RFs.
869 *
870 * TODO: This isn't always needed: there is no need to reserve a register
871 * from an RF if it is only connected to RFs with a subset of the
872 * connectivity it offers.
873 */
874bool
876 const TTAMachine::RegisterFile& rf) {
877 auto regNav = rf.machine()->registerFileNavigator();
878 for (auto rf2: regNav) {
879 if ((rf2 != &rf) &&
880 (isConnected(rf,*rf2) || isConnected(*rf2,rf)) &&
881 !isEquallyConnected(rf, *rf2) &&
882 ((rf.width() <= 32 && rf2->width() <= 32) ||
883 (rf.width() == rf2->width()))) {
884 return true;
885 }
886 }
887 return false;
888}
889
891 const TTAMachine::HWOperation& hwop, int index) {
892 OperationPool opPool;
893 Operation& op = opPool.operation(hwop.name().c_str());
894 if (&op == &NullOperation::instance()) {
895 TCEString msg = "ADF has unknown operation: "; msg << hwop.name();
896 throw Exception(__FILE__, __LINE__, __func__, msg);
897 }
898 Operand& operand = op.operand(index);
899 return operand.width();
900}
901
902
903std::set<const RegisterFile*>
906
907 std::map<int, int> noRegInputCount;
908 auto fuNav = machine.functionUnitNavigator();
909 auto regNav = machine.registerFileNavigator();
910
911 std::set<const RegisterFile*> rv;
912
913 for (auto fu : fuNav) {
914 for (int j = 0; j < fu->operationCount(); j++) {
915 auto hwop = fu->operation(j);
916 std::map<int, int> myNoRegInputCount;
917 for (int k = 1; k <= hwop->operandCount(); k++) {
918 auto p = hwop->port(k);
919 if (p->inputSocket() != NULL &&
920 (p->noRegister() || p->isTriggering())) {
921 int w = operandWidth(*hwop, k);
922 myNoRegInputCount[w]++;
923 if (w == 1) {
924 myNoRegInputCount[32]++;
925 } else if (w == 32) {
926 myNoRegInputCount[1]++;
927 }
928 }
929 }
930
931 for(auto mw : myNoRegInputCount) {
932 int w = mw.first;
933 noRegInputCount[w] = std::max(noRegInputCount[w], mw.second);
934 }
935 }
936 }
937 for (auto rf: regNav) {
938 // one read needed for trigger so <= instead of <
939 if (rf->maxReads() < noRegInputCount[rf->width()]) {
940 rv.insert(rf);
941 }
942 }
943 return rv;
944}
945
946bool
948 const TTAMachine::Machine& mach) {
949
950 std::set<int> scalarWidths = {1,32};
951 for (auto fu: mach.functionUnitNavigator()) {
952 for (int j = 0; j < fu->portCount(); j++ ) {
953 Port& port = *fu->port(j);
954 // connections from RF to FU's
955 if (port.inputSocket() != NULL &&
956 isPortApplicableToWidths(port, scalarWidths)) {
957 if (!canWriteAllImmediates(port)) {
958 return true;
959 }
960 }
961 }
962 }
963 return false;
964}
965
967
968 static bool spammed = false;
969 // check connection from RA to jump for fn return.
971
972 if (cu.returnAddressPort() == nullptr) return true;
973
975 if (cu.hasOperation("jump")) {
976 auto jumpOp = cu.operation("jump");
977 auto port = jumpOp->port(1);
978 if (!isConnected(ra, *port)) {
979 if (Application::verboseLevel() > 0 && !spammed) {
980 std::cout << "Reserving registers for temp reg use because "
981 << "a connection is missing between the RA port "
982 << "and the address port of jump operation." << std::endl;
983 spammed = true;
984 }
985 return false;
986 }
987 }
988
989 // check that RA can be loaded and stored
990 TCEString ldOp = machine.isLittleEndian() ? "LD32" : "LDW";
991 TCEString stOp = machine.isLittleEndian() ? "ST32" : "STW";
992 bool hasLoad = false;
993 bool hasStore = false;
994 bool raConnectedToLoad = false;
995 bool raConnectedToStore = false;
996 for (auto fu: machine.functionUnitNavigator()) {
997 if (!fu->hasAddressSpace() ||
998 !fu->addressSpace()->hasNumericalId(0)) {
999 continue;
1000 }
1001 if (fu->hasOperation(ldOp)) {
1002 hasLoad = true;
1003 auto ldhwop = fu->operation(ldOp);
1004 auto port = ldhwop->port(2);
1005 if (isConnected(*port, ra)) {
1006 raConnectedToLoad = true;
1007 }
1008 }
1009
1010 if (fu->hasOperation(stOp)) {
1011 hasStore = true;
1012 auto sthwop = fu->operation(stOp);
1013 auto port = sthwop->port(2);
1014 if (isConnected(ra, *port)) {
1015 raConnectedToStore = true;
1016 }
1017 }
1018 }
1019
1020 if ((raConnectedToLoad || !hasLoad) &&
1021 (raConnectedToStore || !hasStore)) {
1022 return true;
1023 } else {
1024 if (Application::verboseLevel() > 0 && !spammed) {
1025 std::cout << "Reserving registers for temp reg use because "
1026 << "a connection is missing between the RA port "
1027 << "and the LSU." << std::endl;
1028 spammed = true;
1029 }
1030 return false;
1031 }
1032}
1033
1034/**
1035 * Gets all register files needed for limited connectivity temp registers
1036 *
1037 * @param machine machine we are checking
1038 * @return vector of registerfiles whose last register is to be used for
1039 */
1040std::set<const RegisterFile*, MachinePart::Comparator>
1043 static bool spammed = false;
1044
1045 std::set<const RegisterFile*, TTAMachine::MachinePart::Comparator> rfs;
1046
1047 auto regNav = machine.registerFileNavigator();
1048 auto iuNav = machine.immediateUnitNavigator();
1049 auto fuNav = machine.functionUnitNavigator();
1050
1051 auto reducedConnRfs = needRegCopiesDueReadPortConflicts(machine);
1052 std::set<int> portConflictWidths;
1053 for (auto rf: reducedConnRfs) {
1054 int w = rf->width();
1055 portConflictWidths.insert(w);
1056 }
1057
1058 bool portConflicts = !reducedConnRfs.empty();
1059 bool allConnected = true;
1060 if (portConflicts) {
1061 if (Application::verboseLevel() > 0 && !spammed) {
1062 std::cout << "Reserving registers for temp reg use because " <<
1063 "of possible RF port conflicts; There are operations " <<
1064 "on registerless FUs with more operations than there are " <<
1065 "read ports on some RFs." << std::endl;
1066 spammed = true;
1067 }
1068 allConnected = false;
1069 }
1070 int widestRFWidth = 0;
1071
1072 std::set<int> lackingConnectivityWidths;
1073 std::set<const TTAMachine::RegisterFile*> allConnectedRFs;
1074 std::map<int, const RegisterFile*> priorityConnectedRFs;
1075 std::map<int, int> regCounts;
1076 std::map<int, int> regFileCounts;
1077
1078 // may need temp reg copies because immediate operands cannto be
1079 // transferred to all operations directly.
1080 if (allConnected && needsRegisterCopiesDueImmediateOperands(machine)) {
1081 lackingConnectivityWidths.insert(32);
1082 allConnected = false;
1083 if (Application::verboseLevel() > 0 && !spammed) {
1084 std::cout << "Reserving registers for temp reg use because " <<
1085 "all immediate operands are not possible to transfer " <<
1086 "directly. This reduces the number of registers available " <<
1087 "for storing usable values." << std::endl;
1088 spammed = true;
1089 }
1090 }
1091
1092 for (auto rf: regNav) {
1093 int w = rf->width();
1094 if (w > widestRFWidth) {
1095 widestRFWidth = w;
1096 }
1097 regCounts[w] += rf->size();
1098 regFileCounts[w]++;
1099 }
1100
1101 for (auto rf: regNav) {
1102 int width = rf->width();
1103 if (!rfConnected(*rf)) {
1104 reducedConnRfs.insert(rf);
1105 allConnected = false;
1106 lackingConnectivityWidths.insert(width);
1107 if (Application::verboseLevel() > 0 && !spammed) {
1108 std::cout << "Reserving registers for temp reg use because RF: "
1109 << rf->name() << " has reduced connectivity to FUs or "
1110 << "immediates." << std::endl;
1111 spammed = true;
1112 }
1113 } else {
1114 allConnectedRFs.insert(rf);
1115 // we have at least on RF connected to everywhere so use it.
1116 // but only if it's wide enough (as wide as the widest RF)
1117 auto connectedRF = priorityConnectedRFs[width];
1118
1119 // ra/imm/narrowed connectivity for 32bit
1120 if ((width <= 32 || isConnectedToDifferentlyConnectedRFs(*rf)) &&
1121 (connectedRF == nullptr ||
1122 rf->maxReads() * rf->maxWrites() >
1123 connectedRF->maxReads() * connectedRF->maxWrites())) {
1124 priorityConnectedRFs[width] = rf;
1125 }
1126 }
1127 }
1128
1129 if (!raConnected(machine)) {
1130 allConnected = false;
1131 lackingConnectivityWidths.insert(32);
1132 }
1133
1134 if (allConnected) {
1135 return rfs;
1136 }
1137
1138 bool needNextBigger = false;
1139 if (AssocTools::containsKey(lackingConnectivityWidths, 1)) {
1140 if (priorityConnectedRFs[1] != nullptr &&
1141 regCounts[1] > 2 &&
1142 regFileCounts[1] > 1) {
1143 rfs.insert(priorityConnectedRFs[1]);
1144 } else {
1145 needNextBigger = true;
1146 }
1147 }
1148 // 32-bit.
1149 if (needNextBigger ||
1150 AssocTools::containsKey(lackingConnectivityWidths, 32) ||
1151 portConflicts) {
1152 if (!portConflicts && priorityConnectedRFs[32] != nullptr) {
1153 rfs.insert(priorityConnectedRFs[32]);
1154 } else {
1155 for (auto rf: regNav) {
1156 if (rf->width() == 32 &&
1158 portConflicts)) {
1159 rfs.insert(rf);
1160 }
1161 }
1162 }
1163 }
1164
1165 // vector.
1166 for (int w = 64; w <= widestRFWidth; w*=2) {
1167 if (AssocTools::containsKey(lackingConnectivityWidths, w) ||
1168 portConflicts) {
1169 if (!portConflicts && priorityConnectedRFs[w] != nullptr) {
1170 rfs.insert(priorityConnectedRFs[w]);
1171 } else {
1172 for (auto rf: regNav) {
1173 if (rf->width() == w &&
1175 portConflicts)) {
1176 rfs.insert(rf);
1177 }
1178 }
1179 }
1180 }
1181 }
1182
1183 return rfs;
1184}
1185
1186
1187/**
1188 * Checks if there is a way to write immediate directly from bus or from immu
1189 * to the given port
1190 *
1191 * @param port Port where to check immediate write ability.
1192 */
1193bool
1195 /** First check if there is a bus that can transfer the immediates */
1196 int portWidth = destPort.width();
1197 int sextImm = 0;
1198 int zextImm = 0;
1199
1200 Socket& socket = *destPort.inputSocket();
1201
1202 // check immediates from buses
1203 for (int i = 0; i < socket.segmentCount(); ++i) {
1204 auto bus = socket.segment(i)->parentBus();
1205 int immw = bus->immediateWidth();
1206 if (bus->signExtends()) {
1207 sextImm = std::max(immw, sextImm);
1208 } else {
1209 zextImm = std::max(immw, zextImm);
1210 }
1211 if (immw >= portWidth) {
1212 return true;
1213 }
1214 }
1215
1216 // then check directly connected imm units
1217 const TTAMachine::Machine& mach = *destPort.parentUnit()->machine();
1220
1221 for (int i = 0; i < iuNav.count(); i++) {
1222 ImmediateUnit& iu = *iuNav.item(i);
1223 int immw = iu.width();
1224 if (isConnected(iu, destPort)) {
1225 if (iu.signExtends()) {
1226 sextImm = std::max(immw, sextImm);
1227 } else {
1228 zextImm = std::max(immw, zextImm);
1229 }
1230 }
1231 }
1232
1233 auto widestImms = immBits(mach);
1234 // wide zext imm not needed if has one bit wider sext imm.
1235 if (widestImms.first > sextImm ||
1236 (widestImms.second > zextImm && (sextImm-1) < widestImms.second)) {
1237 return false;
1238 }
1239 return true;
1240}
1241
1242/**
1243 * Returns the bit width the immediate requires.
1244 *
1245 * @param signExtension Whether sign extension is used.
1246 * @param source The immediate terminal.
1247 * @return Bitwidth required for the immediate.
1248 */
1249int
1251 bool signExtension,
1252 const TTAProgram::TerminalImmediate& source,
1253 const TTAMachine::Machine& mach) {
1254
1255 if (source.isCodeSymbolReference()) {
1256 const AddressSpace& instrAS = *mach.controlUnit()->addressSpace();
1257 if (source.toString() == "_end") {
1258 AddressSpace* dataAS;
1259 try {
1261 } catch (Exception&) {
1262 assert(false && "No default data address space");
1263 }
1264
1265 return signExtension ?
1267 MathTools::requiredBits(dataAS->end());
1268 } else {
1269 return signExtension ?
1271 MathTools::requiredBits(instrAS.end());
1272 }
1273 }
1274 if (source.isInstructionAddress() || source.isBasicBlockReference()) {
1275 const AddressSpace& as = *mach.controlUnit()->addressSpace();
1276 return signExtension ?
1279 }
1280
1281 int bits = -1;
1282 if (signExtension) {
1283 bits =
1285 } else if (!signExtension) {
1286 bits =
1288 }
1289
1290 return bits;
1291}
1292
1294 const TTAMachine::Bus& bus, const TTAMachine::Port& port) {
1295 const TTAMachine::Socket* inputS = port.inputSocket();
1296 if (inputS != NULL) {
1297 for (int i = 0; i < inputS->segmentCount(); ++i) {
1298 if (inputS->segment(i)->parentBus() == &bus) {
1299 return true;
1300 }
1301 }
1302 }
1303 return false;
1304}
1305
1306/**
1307 * Returns true if bus is connected to the RF's any writing port.
1308 */
1310 const TTAMachine::Bus& bus, const TTAMachine::Unit& destRF) {
1311 for (int i = 0; i < destRF.portCount(); i++) {
1312 const TTAMachine::Port& port = *destRF.port(i);
1314 return true;
1315 }
1316 }
1317 return false;
1318}
1319
1320
1321bool
1323 const TTAMachine::Bus& bus, const FunctionUnit& fu,
1324 const TCEString& opName, int opIndex) {
1325
1326 if (fu.hasOperationLowercase(opName)) {
1327 const TTAMachine::HWOperation& hwop =
1328 *fu.operationLowercase(opName);
1329
1330 TTAMachine::FUPort* port = hwop.port(opIndex);
1331 if (port == NULL){
1332 throw IllegalMachine(
1333 __FILE__, __LINE__, __func__,
1334 "Target is missing operand bindings for: "
1335 + opName);
1336 }
1338 }
1339 return false;
1340}
1341
1342
1343bool
1345 const TTAMachine::Bus& bus, const MoveNode& moveNode) {
1346
1347 const TTAProgram::Move& move = moveNode.move();
1349 static_cast<TTAProgram::TerminalFUPort*>(&move.destination());
1350 int opIndex = tfp->operationIndex();
1351
1352 ProgramOperation& po = moveNode.destinationOperation();
1353 auto fu = po.scheduledFU();
1354/*
1355 for (int i = 0; i < po.inputMoveCount(); i++ ) {
1356 MoveNode& inputNode = po.inputMove(i);
1357 if (inputNode.isAssigned()) {
1358 unit = inputNode.move().destination().port().parentUnit();
1359 break;
1360 }
1361 }
1362 if (unit == NULL) { // goto over this would have been better
1363 for (int i = 0; i < po.outputMoveCount(); i++ ) {
1364 MoveNode& outputNode = po.outputMove(i);
1365 if (outputNode.isAssigned()) {
1366 if (outputNode.isSourceOperation() &&
1367 &outputNode.sourceOperation() == &po) {
1368 unit = outputNode.move().source().port().parentUnit();
1369 break;
1370 } else {
1371 assert (!outputNode.move().isUnconditional());
1372 assert (&outputNode.guardOperation() == &po);
1373 const TTAMachine::Guard& guard =
1374 outputNode.move().guard().guard();
1375 const TTAMachine::PortGuard* pg =
1376 dynamic_cast<const TTAMachine::PortGuard*>(&guard);
1377 assert(pg); // todo: throw?
1378 unit = pg->port()->parentUnit();
1379 break;
1380 }
1381 }
1382 }
1383 }
1384*/
1385
1386 Operation& op = move.destination().hintOperation();
1388
1389 if (fu != NULL) {
1390// const FunctionUnit* fu = dynamic_cast<const FunctionUnit*>(unit);
1391 assert(fu != NULL);
1392 return busConnectedToFU(bus, *fu, opName, opIndex);
1393 }
1394
1395 // check if the move has a candidate FU set which limits the
1396 // choice of FU for the node
1397 std::set<TCEString> candidateFUs;
1398 std::set<TCEString> allowedFUs;
1399
1401 candidateFUs, move,
1404 allowedFUs, move,
1406
1408 if (candidateFUs.empty() || AssocTools::containsKey(
1409 candidateFUs,gcu->name())) {
1410 if (busConnectedToFU(bus, *gcu, opName, opIndex)) {
1411 return true;
1412 }
1413 }
1414
1415
1418 for (int i = 0; i < fuNav.count(); i++) {
1419 TTAMachine::FunctionUnit& fu = *fuNav.item(i);
1420 if (!candidateFUs.empty() && !AssocTools::containsKey(
1421 candidateFUs,fu.name())) {
1422 continue;
1423 }
1424 if (!allowedFUs.empty() && !AssocTools::containsKey(
1425 allowedFUs,fu.name())) {
1426 continue;
1427 }
1428 if (busConnectedToFU(bus, fu, opName, opIndex)) {
1429 return true;
1430 }
1431 }
1432 return false;
1433}
1434
1435bool
1437 const TTAMachine::Bus& bus,
1438 const MoveNode& moveNode) {
1439 const TTAProgram::Move& move = moveNode.move();
1440 if (move.destination().isGPR()) {
1441 TTAMachine::Unit& destRF =
1442 *move.destination().port().parentUnit();
1444
1445 }
1446 if (move.destination().isFUPort()) {
1447 if (move.destination().isRA()) {
1448 const TTAMachine::ControlUnit* gcu = bus.machine()->controlUnit();
1450 gcu->returnAddressPort();
1451 // TODO:: machineconcctivitycheck, bus connected to port?
1453 return true;
1454 }
1455 } else {
1457 bus, moveNode);
1458 }
1459 }
1460 return false;
1461}
1462
1463int
1465 const TTAMachine::Machine& mach) {
1466 int totalFound = 0;
1467 for (int bi = 0; bi < mach.busNavigator().count(); ++bi) {
1468 const TTAMachine::Segment& s =
1469 *mach.busNavigator().item(bi)->segment(0);
1470 totalFound += s.connectionCount();
1471 }
1472 return totalFound;
1473}
1474
1475
1478 const TTAMachine::Machine& mach,
1479 const MoveNode& node) {
1480 PortSet res;
1481 if (node.isScheduled()) {
1482 res.insert(&node.move().destination().port());
1483 return res;
1484 }
1485
1486 if (node.isDestinationOperation()) {
1488 mach.functionUnitNavigator();
1490 std::set<TCEString> allowedFUNames;
1491
1492 if (po.isAnyNodeAssigned()) {
1493 for (int i = 0; i < po.inputMoveCount(); i++) {
1494 MoveNode& mn = po.inputMove(i);
1495 if (mn.isScheduled()) {
1496 allowedFUNames.insert(
1497 mn.move().destination().port().parentUnit()->name());
1498 }
1499 }
1500
1501 for (int i = 0; i < po.outputMoveCount(); i++) {
1502 MoveNode& mn = po.outputMove(i);
1503 if (mn.isScheduled()) {
1504 if (mn.isSourceOperation() && &mn.sourceOperation() == &po) {
1505 allowedFUNames.insert(
1506 mn.move().source().port().parentUnit()->name());
1507 } else {
1508 if (mn.isGuardOperation() &&
1509 &mn.guardOperation() == &po) {
1510 const TTAMachine::Guard& guard =
1511 mn.move().guard().guard();
1512 const TTAMachine::PortGuard* pg =
1513 dynamic_cast<const TTAMachine::PortGuard*>(&guard);
1514 assert(pg); // todo: throw?
1515 const TTAMachine::Unit* u = pg->port()->parentUnit();
1516 allowedFUNames.insert(u->name());
1517 }
1518 }
1519 }
1520 }
1521 }
1522
1523 std::set<TCEString> candidateFUs;
1524 std::set<TCEString> allowedFUs;
1525
1527 candidateFUs, node.move(),
1530 allowedFUs, node.move(),
1532
1533 if (!candidateFUs.empty()) {
1534 if (allowedFUNames.empty()) {
1535 allowedFUNames = candidateFUs;
1536 } else {
1537 std::set<TCEString> tmp;
1538 SetTools::intersection(allowedFUNames, candidateFUs,tmp);
1539 allowedFUNames = tmp;
1540 }
1541
1542 }
1543
1544 if (!allowedFUs.empty()) {
1545 if (allowedFUNames.empty()) {
1546 allowedFUNames = allowedFUs;
1547 } else {
1548 std::set<TCEString> tmp;
1549 SetTools::intersection(allowedFUNames, allowedFUs,tmp);
1550 allowedFUNames = tmp;
1551 }
1552 }
1553
1554 for (int i = 0; i <= nav.count(); i++) {
1556 if (i == nav.count()) { // GCU is not on fu navigator
1557 fu = mach.controlUnit();
1558 } else {
1559 fu = nav.item(i);
1560 }
1561
1562 if (!allowedFUNames.empty() && !AssocTools::containsKey(
1563 allowedFUNames, fu->name())) {
1564 continue;
1565 }
1566 if (fu->hasOperation(po.operation().name())) {
1568 fu->operation(po.operation().name());
1569 res.insert(
1570 hwop->port(node.move().destination().operationIndex()));
1571 }
1572 }
1573 return res;
1574 }
1575
1576 if (node.move().destination().isRA()) {
1577 res.insert(mach.controlUnit()->returnAddressPort());
1578 return res;
1579 }
1580
1581 // destination is register
1582 if (!node.move().destination().isGPR()) {
1583 std::cerr << "node should have dest as reg: " <<
1584 node.toString() << std::endl;
1585 }
1586 assert(node.move().destination().isGPR());
1587 return findWritePorts(
1588 *node.move().destination().port().parentUnit());
1589}
1590
1593 PortSet res;
1594 for (int i = 0; i < rf.portCount(); i++) {
1595 const TTAMachine::Port* port = rf.port(i);
1596 if (port->isInput()) {
1597 res.insert(port);
1598 }
1599 }
1600 return res;
1601}
1602
1605 PortSet res;
1606 for (int i = 0; i < rf.portCount(); i++) {
1607 TTAMachine::Port* port = rf.port(i);
1608 if (port->isOutput()) {
1609 res.insert(port);
1610 }
1611 }
1612 return res;
1613}
1614
1615/**
1616 * Returns true if there is connection between the port and the bus.
1617 */
1618 bool
1620 const TTAMachine::Bus& bus,
1621 const TTAMachine::Port& port) {
1622 std::vector<const Socket*> sockets{
1623 port.inputSocket(), port.outputSocket()};
1624
1625 for (const Socket* socket : sockets) {
1626 if (socket != nullptr && socket->isConnectedTo(bus)) {
1627 return true;
1628 }
1629 }
1630 return false;
1631 }
1632
1633 /**
1634 * Returns true if there is connection between the port and the bus.
1635 */
1636 bool
1638 const TTAMachine::Port& port,
1639 const TTAMachine::Bus& bus) {
1640 return isConnected(bus, port);
1641 }
1642
1643 /**
1644 * Returns true if all ports are connected to the bus.
1645 */
1646 bool
1648 const std::set<TTAMachine::Port*> ports, const TTAMachine::Bus& bus) {
1649 for (const auto& port : ports) {
1650 if (!isConnected(bus, *port)) {
1651 return false;
1652 }
1653 }
1654 return true;
1655 }
1656
1657/**
1658 * Returns busses that connects the given ports.
1659 */
1662 TTAMachine::Port& port1,
1663 TTAMachine::Port& port2) {
1664
1666 const Machine& mach = *port1.parentUnit()->machine();
1667 for (Bus* bus : mach.busNavigator()) {
1668 if (isConnected(port1, *bus) && isConnected(port2, *bus)) {
1669 result.insert(bus);
1670 }
1671 }
1672 return result;
1673}
1674
1677 const TTAMachine::Machine& mach, const MoveNode& node) {
1678 PortSet res;
1679 if (node.isScheduled() && !node.isSourceConstant()) {
1680 res.insert(&node.move().source().port());
1681 return res;
1682 }
1683
1684 if (node.isSourceOperation()) {
1686 mach.functionUnitNavigator();
1687 ProgramOperation& po = node.sourceOperation();
1688
1689 std::set<TCEString> candidateFUs;
1690 std::set<TCEString> allowedFUs;
1691
1692 addAnnotatedFUs(candidateFUs, node.move(),
1694 addAnnotatedFUs(allowedFUs, node.move(),
1696
1697 for (int i = 0; i < nav.count(); i++) {
1698 TTAMachine::FunctionUnit* fu = nav.item(i);
1699 if (!allowedFUs.empty() && !AssocTools::containsKey(
1700 allowedFUs, fu->name())) {
1701 continue;
1702 }
1703 if (!candidateFUs.empty() && !AssocTools::containsKey(
1704 candidateFUs, fu->name())) {
1705 continue;
1706 }
1707
1708 if (fu->hasOperation(po.operation().name())) {
1710 fu->operation(po.operation().name());
1711 res.insert(
1712 hwop->port(node.move().source().operationIndex()));
1713 }
1714 }
1715 return res;
1716 }
1717
1718 if (node.isSourceVariable()) {
1719 // source is register
1720 return findReadPorts(
1721 *node.move().source().port().parentUnit());
1722 }
1723
1724 // consider only long immediates here.
1725 if (node.isSourceConstant()) {
1727 static_cast<TTAProgram::TerminalImmediate&>(node.move().source());
1730 for (int i = 0; i < nav.count(); i++) {
1731 TTAMachine::ImmediateUnit* iu = nav.item(i);
1732 if (iu->width() >=
1734 iu->extensionMode() == Machine::SIGN, imm, mach)) {
1735 for (int i = 0; i < iu->portCount(); i++) {
1736 TTAMachine::Port* port = iu->port(i);
1737 assert(port->isOutput());
1738 res.insert(port);
1739 }
1740 }
1741 }
1742 return res;
1743 }
1744
1745 if (node.move().source().isRA()) {
1746 res.insert(mach.controlUnit()->returnAddressPort());
1747 }
1748
1749 return res;
1750}
1751
1752/**
1753 * 1 = can write
1754 * 0 = cannot write
1755 * -1 = can write through limm
1756 */
1758 const MoveNode& src, PortSet& destinationPorts, bool ignoreGuard) {
1759
1760 int trueVal = 1;
1761 if (destinationPorts.empty()) {
1762 return false;
1763 }
1764
1765 if (src.isSourceConstant()) {
1767 static_cast<TTAProgram::TerminalImmediate*>(
1768 &src.move().source());
1770 *imm, destinationPorts)) {
1771 return true; // can transfer via short imm.
1772 } else {
1773 trueVal = -1; // mayby through LIMM?
1774 }
1775 }
1776
1777 PortSet sourcePorts = findPossibleSourcePorts(
1778 *(*destinationPorts.begin())->parentUnit()->machine(), src);
1779
1780 // TODO: Why cannot move.guard return pointer which is NULL if unconditional?
1781 const TTAProgram::Move& move = src.move();
1783 sourcePorts, destinationPorts,
1784 (ignoreGuard || move.isUnconditional()) ?
1785 NULL : &move.guard().guard())) {
1786 return trueVal;
1787 }
1788
1789 return false;
1790}
1791
1793 const MoveNode& src, const MoveNode& user,
1794 const TTAMachine::Machine& targetMachine) {
1795
1796 MachineConnectivityCheck::PortSet destinationPorts =
1798 targetMachine, user);
1799
1800 int trueVal = 1;
1801 if (destinationPorts.empty()) {
1802 return false;
1803 }
1804
1805 if (src.isSourceConstant()) {
1807 static_cast<TTAProgram::TerminalImmediate*>(
1808 &src.move().source());
1810 *imm, destinationPorts)) {
1811 return true; // can transfer via short imm.
1812 } else {
1813 trueVal = -1; // mayby through LIMM?
1814 }
1815 }
1816
1817 PortSet sourcePorts = findPossibleSourcePorts(targetMachine, src);
1818
1819 // TODO: Why cannot move.guard return pointer which is NULL if
1820 // unconditional?
1821 const TTAProgram::Move& userMove = user.move();
1823 sourcePorts, destinationPorts,
1824 userMove.isUnconditional() ? NULL : &userMove.guard().guard())) {
1825 return trueVal;
1826 }
1827
1828 return false;
1829}
1830
1831
1832bool
1834 PortSet& sourcePorts, const MoveNode& dest) {
1835
1836 if (sourcePorts.empty()) {
1837 return false;
1838 }
1839
1841 *(*sourcePorts.begin())->parentUnit()->machine(), dest);
1842 return MachineConnectivityCheck::isConnected(sourcePorts, destPorts);
1843}
1844
1845bool
1847 const MoveNode& moveNode,
1849 bool ignoreGuard) {
1850 PortSet destinationPorts =
1852 machine,moveNode);
1853
1855 moveNode, destinationPorts, ignoreGuard);
1856}
1857
1858void
1860 std::set<TCEString>& candidateFUs,
1861 const TTAProgram::Move& m,
1863
1864 const int annotationCount = m.annotationCount(id);
1865 for (int i = 0; i < annotationCount; ++i) {
1866 std::string candidateFU = m.annotation(i, id).stringValue();
1867 candidateFUs.insert(candidateFU);
1868 }
1869}
1870
1871/* These are static */
1876
1877
1878bool
1880 const TTAMachine::Machine& mach, const std::set<int>& rfWidths) {
1881
1882 const Machine::RegisterFileNavigator regNav =
1883 mach.registerFileNavigator();
1884
1885 std::set<std::pair<const RegisterFile*,int> > allGuardRegs;
1886 const Machine::BusNavigator& busNav = mach.busNavigator();
1887
1888 // first just collect all guard registers.
1889 for (int bi = 0; bi < busNav.count(); ++bi) {
1890 Bus* bus = busNav.item(bi);
1891 for (int gi = 0; gi < bus->guardCount(); gi++) {
1892 const Guard* guard = bus->guard(gi);
1893 const TTAMachine::RegisterGuard* rg =
1894 dynamic_cast<const RegisterGuard*>(guard);
1895 if (rg != NULL) {
1896 allGuardRegs.insert(
1897 std::pair<const RegisterFile*,int>(rg->registerFile(),
1898 rg->registerIndex()));
1899 }
1900 }
1901 }
1902
1903 if (allGuardRegs.empty()) {
1904 return false;
1905 }
1906
1907 // then check for the connections.
1908 for (int i = 0; i < regNav.count(); i++) {
1909 const TTAMachine::RegisterFile* srf = regNav.item(i);
1910 for (int j = 0; j < regNav.count(); j++) {
1911 const TTAMachine::RegisterFile* drf = regNav.item(i);
1912 int width = drf->width();
1913
1914 // if we do not care about RFs of this size
1915 if (!rfWidths.empty() &&
1916 !AssocTools::containsKey(rfWidths, width)) {
1917 continue;
1918 }
1919
1920 for (std::set<std::pair<const RegisterFile*,int> >::iterator k =
1921 allGuardRegs.begin(); k != allGuardRegs.end(); k++) {
1922 if (!isConnectedWithBothGuards(*srf, *drf, *k)) {
1923 return false;
1924 }
1925 }
1926 }
1927 }
1928 return true;
1929}
1930/*
1931bool
1932MachineConnectivityCheck::hasConditionalOperations(
1933 const TTAMachine::Machine& mach) {
1934
1935}
1936*/
1937
1938/**
1939 * Checks whether there is a connection from some outport port of a
1940 * register file or immediate unit into some input port of the given
1941 * target register file or immediate unit.
1942 *
1943 * @param sourceRF Source RF/Immediate unit.
1944 * @param destRF Source RF/Immediate unit.
1945 * @return True if there is at least one connection from any of the output
1946 * ports of the source RF/Imm unit into the destination RF.
1947 */
1948bool
1950 const TTAMachine::BaseRegisterFile& sourceRF,
1951 const TTAMachine::BaseRegisterFile& destRF,
1952 std::pair<const RegisterFile*,int> guardReg) {
1953
1954 RfRfBoolMap::const_iterator
1955 i = rfRfCache_.find(RfRfPair(&sourceRF, &destRF));
1956 if (i != rfRfCache_.end()) {
1957 if (i->second == false) {
1958 return false;
1959 }
1960 }
1961 std::set<const TTAMachine::Bus*> srcBuses;
1962 appendConnectedDestinationBuses(sourceRF, srcBuses);
1963
1964 std::set<const TTAMachine::Bus*> dstBuses;
1965 appendConnectedSourceBuses(destRF, dstBuses);
1966
1967 std::set<const TTAMachine::Bus*> sharedBuses;
1968 SetTools::intersection(srcBuses, dstBuses, sharedBuses);
1969
1970 bool trueOK = false;
1971 bool falseOK = false;
1972 if (sharedBuses.size() > 0) {
1973 rfRfCache_[RfRfPair(&sourceRF,&destRF)] = true;
1974 for (auto bus: sharedBuses) {
1975 std::pair<bool, bool> guardsOK = hasBothGuards(bus, guardReg);
1976 trueOK |= guardsOK.first;
1977 falseOK |= guardsOK.second;
1978 if (trueOK && falseOK) {
1979 return true;
1980 }
1981 }
1982 }
1983 return false;
1984}
1985
1987 const TTAMachine::Bus* bus, std::pair<const RegisterFile*,int> guardReg) {
1988 bool trueOK = false;
1989 bool falseOK = false;
1990
1991 for (int gi = 0; gi < bus->guardCount(); gi++) {
1992 const TTAMachine::Guard* guard = bus->guard(gi);
1993 const TTAMachine::RegisterGuard* rg =
1994 dynamic_cast<const TTAMachine::RegisterGuard*>(guard);
1995 if (rg != NULL) {
1996 if (rg->registerFile() == guardReg.first &&
1997 rg->registerIndex() == guardReg.second) {
1998 if (rg->isInverted()) {
1999 falseOK = true;
2000 } else {
2001 trueOK = true;
2002 }
2003 if (falseOK && trueOK) {
2004 return std::pair<bool, bool>(true, true);
2005 }
2006 }
2007 }
2008 }
2009 return std::pair<bool, bool>(trueOK, falseOK);
2010}
2011
2013 const TTAMachine::Machine& targetMachine) {
2014 auto iuNav = targetMachine.immediateUnitNavigator();
2015 int limmCount = 0;
2016 for (auto iu : iuNav) {
2017 limmCount += iu->maxReads();
2018 }
2019 return limmCount;
2020}
2021
2023 const TTAMachine::Machine& targetMachine) {
2024
2025 auto busNav = targetMachine.busNavigator();
2026 int simmCount = 0;
2027 for (auto bus : busNav) {
2028 if (bus->immediateWidth() > 0) {
2029 simmCount++;
2030 }
2031 }
2032 return simmCount;
2033}
2034
2035/**
2036 * Find FU which has copy op that can be used to schedule this move.
2037 *
2038 * Prioritizes FUs which can schedule the move directly with one
2039 * copy op. If none found, then fives FU which has copy op and
2040 * can recursively be used with later copy.
2041 * If none found at all, returns empty set.
2042 */
2044 const TTAMachine::Machine& mach,
2045 const MoveNode& mn) {
2046
2047 // with these, single copy op is enough
2048 FUSet suitableFUs;
2049 // with these, have to use multiple copy ops or copy+regcopy
2050 FUSet partiallySuitableFUs;
2051
2052 std::string opName = "COPY";
2053 const TTAProgram::Move& move = mn.move();
2054 auto destinationPorts = findPossibleDestinationPorts(mach, mn);
2055
2056 for (auto fu: mach.functionUnitNavigator()) {
2057 PortSet copyOutPorts;
2058 PortSet copyTriggerPorts;
2059 if (fu->hasOperation(opName)) {
2060 TTAMachine::HWOperation* hwop = fu->operation(opName);
2061 copyOutPorts.insert(hwop->port(2));
2062 copyTriggerPorts.insert(hwop->port(1));
2064 copyOutPorts, destinationPorts,
2065 (move.isUnconditional()) ?
2066 nullptr : &move.guard().guard())) {
2067 partiallySuitableFUs.insert(fu);
2069 mn, copyTriggerPorts)) {
2070 suitableFUs.insert(fu);
2071 }
2072 }
2073 }
2074 }
2075 return suitableFUs.empty() ? partiallySuitableFUs : suitableFUs;
2076}
2077
2079 const TTAMachine::Machine& mach,
2080 const TCEString& opName,
2081 int outIndex,
2082 const MoveNode& mn) {
2083
2084 PortSet sourcePorts;
2085
2087 mach.functionUnitNavigator();
2088 for (auto fu: fuNav) {
2089 if (fu->hasOperation(opName)) {
2090 TTAMachine::HWOperation* hwop = fu->operation(opName);
2091 sourcePorts.insert(hwop->port(outIndex));
2092 }
2093 }
2094
2095 MachineConnectivityCheck::PortSet destinationPorts =
2097
2098 const TTAProgram::Move& move = mn.move();
2100 sourcePorts, destinationPorts,
2101 (move.isUnconditional()) ?
2102 nullptr : &move.guard().guard());
2103}
#define __func__
#define assert(condition)
TTAMachine::Machine * machine
the architecture definition of the estimated processor
static int verboseLevel()
static bool containsKey(const ContainerType &aContainer, const KeyType &aKey)
static bool busConnectedToRF(const TTAMachine::Bus &bus, const TTAMachine::Unit &destRF)
std::pair< const TTAMachine::Port *, const TTAMachine::Port * > PortPortPair
static void appendConnectedDestinationBuses(const TTAMachine::Port &port, std::set< const TTAMachine::Bus * > &buses)
static bool busConnectedToAnyFU(const TTAMachine::Bus &bus, const MoveNode &moveNode)
static bool needsRegisterCopiesDueImmediateOperands(const TTAMachine::Machine &mach)
std::map< PortRfPair, bool > PortRfBoolMap
static std::set< const TTAMachine::RegisterFile *, TTAMachine::MachinePart::Comparator > tempRegisterFiles(const TTAMachine::Machine &machine)
static void appendConnectedSourceBuses(const TTAMachine::Port &port, std::set< const TTAMachine::Bus * > &buses)
static std::pair< int, int > immBits(const TTAMachine::RegisterFile &rf)
static std::set< const TTAMachine::Bus * > connectedSourceBuses(const TTAMachine::Port &port)
static PortPortBoolMap portPortCache_
std::pair< const TTAMachine::Port *, const TTAMachine::BaseRegisterFile * > PortRfPair
static void addAnnotatedFUs(std::set< TCEString > &candidateFUs, const TTAProgram::Move &m, TTAProgram::ProgramAnnotation::Id id)
static std::set< const TTAMachine::Bus * > connectedDestinationBuses(const TTAMachine::Port &port)
static BusSet findRoutes(TTAMachine::Port &port1, TTAMachine::Port &port2)
static bool canBypass(const MoveNode &src, const MoveNode &user, const TTAMachine::Machine &targetMachine)
std::pair< const TTAMachine::BaseRegisterFile *, const TTAMachine::Port * > RfPortPair
static PortSet findWritePorts(const TTAMachine::Unit &rf)
std::map< PortPortPair, bool > PortPortBoolMap
static int canSourceWriteToAnyDestinationPort(const MoveNode &src, PortSet &ports, bool ignoreGuard=false)
static bool toRfConnected(const TTAMachine::RegisterFile &brf)
static bool busConnectedToFU(const TTAMachine::Bus &bus, const TTAMachine::FunctionUnit &fu, const TCEString &opName, int opIndex)
static bool raConnected(const TTAMachine::Machine &machine)
static bool rfConnected(const TTAMachine::RegisterFile &rf)
static bool isConnectedWithBothGuards(const TTAMachine::BaseRegisterFile &sourceRF, const TTAMachine::BaseRegisterFile &destRF, std::pair< const TTAMachine::RegisterFile *, int > guardReg)
static PortSet findReadPorts(const TTAMachine::Unit &rf)
static bool fromRfConnected(const TTAMachine::BaseRegisterFile &brf)
static bool canTransportMove(const MoveNode &moveNode, const TTAMachine::Machine &machine, bool ignoreGuard=false)
std::set< const TTAMachine::FunctionUnit *, const TTAMachine::MachinePart::Comparator > FUSet
static int requiredImmediateWidth(bool signExtension, const TTAProgram::TerminalImmediate &source, const TTAMachine::Machine &mach)
static bool isConnected(const TTAMachine::Port &sourcePort, const TTAMachine::Port &destinationPort, const TTAMachine::Guard *guard=NULL)
static int maxLIMMCount(const TTAMachine::Machine &targetMachine)
static PortSet findPossibleDestinationPorts(const TTAMachine::Machine &mach, const MoveNode &node)
static std::pair< bool, bool > hasBothGuards(const TTAMachine::Bus *bus, std::pair< const TTAMachine::RegisterFile *, int > guardReg)
virtual bool check(const TTAMachine::Machine &mach, MachineCheckResults &results) const
static bool busConnectedToDestination(const TTAMachine::Bus &bus, const MoveNode &moveNode)
static bool canBypassOpToDst(const TTAMachine::Machine &mach, const TCEString &opName, int outIndex, const MoveNode &mn)
static bool isPortApplicableToWidths(const TTAMachine::Port &port, std::set< int > widths)
static std::pair< int, int > shortImmBits(std::set< const TTAMachine::Bus * > &buses)
std::set< TTAMachine::Bus *, const TTAMachine::MachinePart::Comparator > BusSet
static bool isConnectedToDifferentlyConnectedRFs(const TTAMachine::RegisterFile &rf)
static bool canTransportImmediate(const TTAProgram::TerminalImmediate &immediate, const TTAMachine::BaseRegisterFile &destRF, const TTAMachine::Guard *guard=NULL)
static bool busConnectedToPort(const TTAMachine::Bus &bus, const TTAMachine::Port &port)
static bool canWriteAllImmediates(TTAMachine::Port &destPort)
static int operandWidth(const TTAMachine::HWOperation &hwop, int index)
static int totalConnectionCount(const TTAMachine::Machine &mach)
static PortSet findPossibleSourcePorts(const TTAMachine::Machine &mach, const MoveNode &node)
static FUSet copyOpFUs(const TTAMachine::Machine &mach, const MoveNode &mn)
std::map< RfPortPair, bool > RfPortBoolMap
std::pair< const TTAMachine::BaseRegisterFile *, const TTAMachine::BaseRegisterFile * > RfRfPair
static bool canAnyPortWriteToDestination(PortSet &ports, const MoveNode &dest)
static std::set< const TTAMachine::RegisterFile * > needRegCopiesDueReadPortConflicts(const TTAMachine::Machine &machine)
std::map< RfRfPair, bool > RfRfBoolMap
static int maxSIMMCount(const TTAMachine::Machine &targetMachine)
static bool isEquallyConnected(const TTAMachine::BaseRegisterFile &RF1, const TTAMachine::BaseRegisterFile &RF2)
std::set< const TTAMachine::Port *, const TTAMachine::MachinePart::Comparator > PortSet
static bool hasConditionalMoves(const TTAMachine::Machine &mach, const std::set< int > &rfWidths)
static TTAMachine::AddressSpace * defaultDataAddressSpace(const TTAMachine::Machine &mach)
static int requiredBits(unsigned long int number)
static int requiredBitsSigned(SLongWord number)
bool isGuardOperation() const
Definition MoveNode.cc:181
bool isSourceVariable() const
Definition MoveNode.cc:196
ProgramOperation & sourceOperation() const
Definition MoveNode.cc:453
bool isDestinationOperation() const
std::string toString() const
Definition MoveNode.cc:576
ProgramOperation & guardOperation() const
Definition MoveNode.cc:479
TTAProgram::Move & move()
bool isSourceOperation() const
Definition MoveNode.cc:168
bool isScheduled() const
Definition MoveNode.cc:409
bool isSourceConstant() const
Definition MoveNode.cc:238
ProgramOperation & destinationOperation(unsigned int index=0) const
static NullOperation & instance()
virtual int width() const
Definition Operand.cc:318
Operation & operation(const char *name)
virtual TCEString name() const
Definition Operation.cc:93
virtual Operand & operand(int id) const
Definition Operation.cc:541
int outputMoveCount() const
const Operation & operation() const
const TTAMachine::FunctionUnit * scheduledFU() const
int inputMoveCount() const
MoveNode & inputMove(int index) const
MoveNode & outputMove(int index) const
static void intersection(const std::set< ValueType > &firstContainer, const std::set< ValueType > &secondContainer, std::set< ValueType > &intersection)
ULongWord uLongWordValue() const
Definition SimValue.cc:1027
SLongWord sLongWordValue() const
Definition SimValue.cc:997
static std::string stringToLower(const std::string &source)
virtual ULongWord end() const
FunctionUnit * parentUnit() const
Definition BaseFUPort.cc:96
virtual int width() const
virtual RFPort * port(const std::string &name) const
int immediateWidth() const
Definition Bus.cc:160
bool signExtends() const
Definition Bus.cc:171
bool hasGuard(const Guard &guard) const
Definition Bus.cc:393
Guard * guard(int index) const
Definition Bus.cc:456
int guardCount() const
Definition Bus.cc:441
virtual Machine * machine() const
virtual TCEString name() const
SpecialRegisterPort * returnAddressPort() const
virtual AddressSpace * addressSpace() const
virtual HWOperation * operation(const std::string &name) const
virtual bool hasOperationLowercase(const std::string &name) const
virtual HWOperation * operationLowercase(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
const std::string & name() const
virtual Machine::Extension extensionMode() const
ComponentType * item(int index) const
virtual RegisterFileNavigator registerFileNavigator() const
Definition Machine.cc:450
virtual FunctionUnitNavigator functionUnitNavigator() const
Definition Machine.cc:380
bool isLittleEndian() const
Definition Machine.hh:258
virtual ImmediateUnitNavigator immediateUnitNavigator() const
Definition Machine.cc:416
virtual BusNavigator busNavigator() const
Definition Machine.cc:356
virtual ControlUnit * controlUnit() const
Definition Machine.cc:345
@ SIGN
Sign extension.
Definition Machine.hh:82
FUPort * port() const
virtual Socket * outputSocket() const
Definition Port.cc:281
virtual bool isInput() const
Definition Port.cc:298
virtual bool isOutput() const
Definition Port.cc:308
virtual int width() const =0
Unit * parentUnit() const
virtual Socket * inputSocket() const
Definition Port.cc:261
const RegisterFile * registerFile() const
int connectionCount() const
Bus * parentBus() const
Segment * segment(int index) const
Definition Socket.cc:401
int segmentCount() const
virtual int portCount() const
Definition Unit.cc:135
virtual Port * port(const std::string &name) const
Definition Unit.cc:116
int annotationCount(ProgramAnnotation::Id id=ProgramAnnotation::ANN_UNDEF_ID) const
ProgramAnnotation annotation(int index, ProgramAnnotation::Id id=ProgramAnnotation::ANN_UNDEF_ID) const
const TTAMachine::Guard & guard() const
Definition MoveGuard.cc:86
MoveGuard & guard() const
Definition Move.cc:345
bool isUnconditional() const
Definition Move.cc:154
Terminal & source() const
Definition Move.cc:302
Terminal & destination() const
Definition Move.cc:323
Id
the ID in TPEF is 24 bits, here enum
@ ANN_ALLOWED_UNIT_DST
Dst. unit candidate.
@ ANN_CONN_CANDIDATE_UNIT_DST
Dst. unit candidate.
@ ANN_CONN_CANDIDATE_UNIT_SRC
Src. unit candidate.
@ ANN_ALLOWED_UNIT_SRC
Candidate units can be passed for resource manager for choosing the source/destination unit of the mo...
virtual int operationIndex() const
virtual TCEString toString() const
virtual SimValue value() const
virtual bool isRA() const
Definition Terminal.cc:129
virtual Operation & hintOperation() const
Definition Terminal.cc:341
virtual bool isBasicBlockReference() const
Definition Terminal.cc:139
virtual bool isCodeSymbolReference() const
Definition Terminal.cc:154
virtual bool isGPR() const
Definition Terminal.cc:107
virtual int operationIndex() const
Definition Terminal.cc:364
virtual bool isInstructionAddress() const
Definition Terminal.cc:87
virtual const TTAMachine::Port & port() const
Definition Terminal.cc:378
virtual bool isFUPort() const
Definition Terminal.cc:118