68 MachineCheck(
"Common helper functionality for connectivity checks.") {
83 const std::string& shortDesc_) :
MachineCheck(shortDesc_) {
92 for (PortSet::iterator i =
94 i != sourcePorts.end(); i++) {
96 for (PortSet::iterator j =
97 destinationPorts.begin();
98 j != destinationPorts.end(); j++) {
131 const Guard* guard) {
134 PortPortBoolMap::const_iterator
137 if (i->second ==
false || guard == NULL) {
141 std::set<const TTAMachine::Bus*> sourceBuses;
143 sourcePort, sourceBuses);
145 std::set<const TTAMachine::Bus*> destinationBuses;
147 destinationPort, destinationBuses);
149 std::set<const TTAMachine::Bus*> sharedBuses;
151 if (sharedBuses.size() > 0) {
158 for (std::set<const TTAMachine::Bus*>::iterator i = sharedBuses.begin();
159 i != sharedBuses.end(); i++) {
160 if ((*i)->hasGuard(*guard)) {
184 const Guard* guard) {
186 std::set<const TTAMachine::Bus*> buses;
189 for (
auto bus : buses) {
192 bus->signExtends(), immediate, *destRF.
machine());
193 if (bus->immediateWidth() < requiredBits) {
200 if (bus->hasGuard(*guard)) {
220 const Guard* guard) {
222 std::set<const TTAMachine::Bus*> buses;
224 destinationPort, buses);
226 for (
auto i = buses.begin(); i != buses.end(); ++i) {
247 const Guard* guard) {
249 for (PortSet::iterator i =
250 destinationPorts.begin();
251 i != destinationPorts.end(); i++) {
296 RfPortBoolMap::const_iterator
302 std::set<const TTAMachine::Bus*> srcBuses;
304 for (
int i = 0; i < sourceRF.
portCount(); i++) {
311 std::set<const TTAMachine::Bus*> sharedBuses;
313 srcBuses, destBuses, sharedBuses);
314 if (sharedBuses.size() > 0) {
339 RfRfBoolMap::const_iterator
342 if (i->second ==
false || guard == NULL) {
346 std::set<const TTAMachine::Bus*> srcBuses;
349 std::set<const TTAMachine::Bus*> dstBuses;
352 std::set<const TTAMachine::Bus*> sharedBuses;
354 if (sharedBuses.size() > 0) {
360 for (std::set<const TTAMachine::Bus*>::iterator i = sharedBuses.begin();
361 i != sharedBuses.end(); i++) {
362 if ((*i)->hasGuard(*guard)) {
388 std::set<const TTAMachine::Bus*> srcBuses;
391 std::set<const TTAMachine::Bus*> dstBuses;
394 std::set<const TTAMachine::Bus*> sharedBuses;
396 return (sharedBuses.size() > 0);
414 PortRfBoolMap::const_iterator
420 std::set<const TTAMachine::Bus*> sourceBuses =
422 std::set<const TTAMachine::Bus*> destBuses;
424 for (
int i = 0; i < destRF.
portCount(); i++) {
431 std::set<const TTAMachine::Bus*> sharedBuses;
434 if (sharedBuses.size() > 0) {
451 std::set<const TTAMachine::Bus*> dstBuses1, dstBuses2;
455 std::set<const TTAMachine::Bus*> srcBuses1, srcBuses2;
459 return dstBuses1 == dstBuses2 && srcBuses1 == srcBuses2;
465 auto fup =
dynamic_cast<const FUPort*
>(&port);
466 if (fup ==
nullptr) {
476 for (
int i = 0; i < fu->operationCount(); i++) {
478 if (!hwop->isBound(*fup))
481 int opIndex = hwop->io(*fup);
505 int width = brf.
width();
506 bool isVectorRegs = width > 32;
512 std::set<const TTAMachine::Bus*> rfBuses;
514 for (
int i = 0; i < brf.
portCount(); i++) {
521 std::set<int> widths;
522 widths.insert(brf.
width());
524 auto widthsExt = widths;
528 widthsExt.insert(16);
531 widthsExt.insert(32);
535 for (
auto fu: fuNav) {
536 for (
int j = 0; j < fu->portCount(); j++ ) {
537 Port& port = *fu->port(j);
541 std::set<const TTAMachine::Bus*> sharedBuses;
544 if (sharedBuses.size() == 0) {
558 for (
int i = 0; i < cu.
portCount(); i++ ) {
564 std::set<const TTAMachine::Bus*> sharedBuses;
567 if (sharedBuses.size() == 0) {
596 std::pair<int, int> rv;
597 std::set<const TTAMachine::Bus*> buses;
607 std::set<const TTAMachine::Bus*>& buses, std::pair<int, int>& immBits) {
609 for (
auto b: buses) {
610 int w = b->immediateWidth();
611 if (b->signExtends()) {
623 std::pair<int, int> rv(0,0);
624 std::set<const TTAMachine::Bus*> rfBuses;
626 if (mach ==
nullptr) {
630 for (
int i = 0; i < rf.
portCount(); i++) {
631 auto port = rf.
port(i);
632 if (port->inputSocket() != NULL) {
639 for (
auto iu: mach->immediateUnitNavigator()) {
641 for (
int j = 0; j < iu->portCount(); j++ ) {
642 Port& port = *iu->port(j);
646 std::set<const TTAMachine::Bus*> sharedBuses;
650 if (sharedBuses.size() != 0) {
651 if (iu->signExtends()) {
652 rv.first = std::max(rv.first, w);
654 rv.second = std::max(rv.second, w);
677 int width = rf.
width();
678 bool isVectorRF = width > 32;
685 std::set<const TTAMachine::Bus*> rfBuses;
687 std::set<int> widths;
688 widths.insert(rf.
width());
698 for (
int i = 0; i < rf.
portCount(); i++) {
706 for (
auto fu: fuNav) {
707 for (
int j = 0; j < fu->portCount(); j++ ) {
708 Port& port = *fu->port(j);
712 port.
width() >= width) {
713 std::set<const TTAMachine::Bus*> sharedBuses;
716 if (sharedBuses.size() == 0) {
730 for (
int i = 0; i < cu.
portCount(); i++ ) {
734 if (port.
width() == width) {
736 std::set<const TTAMachine::Bus*> sharedBuses;
739 if (sharedBuses.size() == 0) {
748 if (rfImmBits.first >= width || rfImmBits.second >= width) {
754 if (rfImmBits.first < allImmBits.first ||
755 (rfImmBits.second < allImmBits.second &&
756 (rfImmBits.first-1) < allImmBits.second)) {
768 std::set<const TTAMachine::Bus*>
772 std::set<const TTAMachine::Bus*> buses;
783 std::set<const TTAMachine::Bus*>
787 std::set<const TTAMachine::Bus*> buses;
804 if (inputS != NULL) {
823 if (outputS != NULL) {
842 for (
int p = 0; p < unit.
portCount(); ++p) {
860 for (
int p = 0; p < unit.
portCount(); ++p) {
878 for (
auto rf2: regNav) {
882 ((rf.
width() <= 32 && rf2->width() <= 32) ||
883 (rf.
width() == rf2->width()))) {
895 TCEString msg =
"ADF has unknown operation: "; msg << hwop.
name();
899 return operand.
width();
903 std::set<const RegisterFile*>
907 std::map<int, int> noRegInputCount;
911 std::set<const RegisterFile*> rv;
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())) {
922 myNoRegInputCount[w]++;
924 myNoRegInputCount[32]++;
925 }
else if (w == 32) {
926 myNoRegInputCount[1]++;
931 for(
auto mw : myNoRegInputCount) {
933 noRegInputCount[w] = std::max(noRegInputCount[w], mw.second);
937 for (
auto rf: regNav) {
939 if (rf->maxReads() < noRegInputCount[rf->width()]) {
950 std::set<int> scalarWidths = {1,32};
952 for (
int j = 0; j < fu->portCount(); j++ ) {
953 Port& port = *fu->port(j);
968 static bool spammed =
false;
974 auto port = jumpOp->
port(1);
977 std::cout <<
"Reserving registers for temp reg use because "
978 <<
"a connection is missing between the RA port "
979 <<
"and the address port of jump operation." << std::endl;
989 bool hasLoad =
false;
990 bool hasStore =
false;
991 bool raConnectedToLoad =
false;
992 bool raConnectedToStore =
false;
994 if (!fu->hasAddressSpace() ||
995 !fu->addressSpace()->hasNumericalId(0)) {
998 if (fu->hasOperation(ldOp)) {
1000 auto ldhwop = fu->operation(ldOp);
1001 auto port = ldhwop->port(2);
1003 raConnectedToLoad =
true;
1007 if (fu->hasOperation(stOp)) {
1009 auto sthwop = fu->operation(stOp);
1010 auto port = sthwop->port(2);
1012 raConnectedToStore =
true;
1017 if ((raConnectedToLoad || !hasLoad) &&
1018 (raConnectedToStore || !hasStore)) {
1022 std::cout <<
"Reserving registers for temp reg use because "
1023 <<
"a connection is missing between the RA port "
1024 <<
"and the LSU." << std::endl;
1037 std::set<const RegisterFile*, MachinePart::Comparator>
1040 static bool spammed =
false;
1042 std::set<const RegisterFile*, TTAMachine::MachinePart::Comparator> rfs;
1049 std::set<int> portConflictWidths;
1050 for (
auto rf: reducedConnRfs) {
1051 int w = rf->width();
1052 portConflictWidths.insert(w);
1055 bool portConflicts = !reducedConnRfs.empty();
1056 bool allConnected =
true;
1057 if (portConflicts) {
1059 std::cout <<
"Reserving registers for temp reg use because " <<
1060 "of possible RF port conflicts; There are operations " <<
1061 "on registerless FUs with more operations than there are " <<
1062 "read ports on some RFs." << std::endl;
1065 allConnected =
false;
1067 int widestRFWidth = 0;
1069 std::set<int> lackingConnectivityWidths;
1070 std::set<const TTAMachine::RegisterFile*> allConnectedRFs;
1071 std::map<int, const RegisterFile*> priorityConnectedRFs;
1072 std::map<int, int> regCounts;
1073 std::map<int, int> regFileCounts;
1078 lackingConnectivityWidths.insert(32);
1079 allConnected =
false;
1081 std::cout <<
"Reserving registers for temp reg use because " <<
1082 "all immediate operands are not possible to transfer " <<
1083 "directly. This reduces the number of registers available " <<
1084 "for storing usable values." << std::endl;
1089 for (
auto rf: regNav) {
1090 int w = rf->width();
1091 if (w > widestRFWidth) {
1094 regCounts[w] += rf->size();
1098 for (
auto rf: regNav) {
1099 int width = rf->width();
1101 reducedConnRfs.insert(rf);
1102 allConnected =
false;
1103 lackingConnectivityWidths.insert(width);
1105 std::cout <<
"Reserving registers for temp reg use because RF: "
1106 << rf->name() <<
" has reduced connectivity to FUs or "
1107 <<
"immediates." << std::endl;
1111 allConnectedRFs.insert(rf);
1114 auto connectedRF = priorityConnectedRFs[width];
1118 (connectedRF ==
nullptr ||
1119 rf->maxReads() * rf->maxWrites() >
1120 connectedRF->maxReads() * connectedRF->maxWrites())) {
1121 priorityConnectedRFs[width] = rf;
1127 allConnected =
false;
1128 lackingConnectivityWidths.insert(32);
1135 bool needNextBigger =
false;
1137 if (priorityConnectedRFs[1] !=
nullptr &&
1139 regFileCounts[1] > 1) {
1140 rfs.insert(priorityConnectedRFs[1]);
1142 needNextBigger =
true;
1146 if (needNextBigger ||
1149 if (!portConflicts && priorityConnectedRFs[32] !=
nullptr) {
1150 rfs.insert(priorityConnectedRFs[32]);
1152 for (
auto rf: regNav) {
1153 if (rf->width() == 32 &&
1163 for (
int w = 64; w <= widestRFWidth; w*=2) {
1166 if (!portConflicts && priorityConnectedRFs[w] !=
nullptr) {
1167 rfs.insert(priorityConnectedRFs[w]);
1169 for (
auto rf: regNav) {
1170 if (rf->width() == w &&
1193 int portWidth = destPort.
width();
1203 if (bus->signExtends()) {
1204 sextImm = std::max(immw, sextImm);
1206 zextImm = std::max(immw, zextImm);
1208 if (immw >= portWidth) {
1218 for (
int i = 0; i < iuNav.
count(); i++) {
1220 int immw = iu.
width();
1223 sextImm = std::max(immw, sextImm);
1225 zextImm = std::max(immw, zextImm);
1230 auto widestImms =
immBits(mach);
1232 if (widestImms.first > sextImm ||
1233 (widestImms.second > zextImm && (sextImm-1) < widestImms.second)) {
1259 assert(
false &&
"No default data address space");
1262 return signExtension ?
1266 return signExtension ?
1273 return signExtension ?
1279 if (signExtension) {
1282 }
else if (!signExtension) {
1293 if (inputS != NULL) {
1308 for (
int i = 0; i < destRF.
portCount(); i++) {
1331 "Target is missing operand bindings for: "
1394 std::set<TCEString> candidateFUs;
1395 std::set<TCEString> allowedFUs;
1406 candidateFUs,gcu->
name())) {
1415 for (
int i = 0; i < fuNav.
count(); i++) {
1418 candidateFUs,fu.
name())) {
1422 allowedFUs,fu.
name())) {
1464 for (
int bi = 0; bi < mach.
busNavigator().count(); ++bi) {
1487 std::set<TCEString> allowedFUNames;
1493 allowedFUNames.insert(
1502 allowedFUNames.insert(
1513 allowedFUNames.insert(u->
name());
1520 std::set<TCEString> candidateFUs;
1521 std::set<TCEString> allowedFUs;
1524 candidateFUs, node.
move(),
1527 allowedFUs, node.
move(),
1530 if (!candidateFUs.empty()) {
1531 if (allowedFUNames.empty()) {
1532 allowedFUNames = candidateFUs;
1534 std::set<TCEString> tmp;
1536 allowedFUNames = tmp;
1541 if (!allowedFUs.empty()) {
1542 if (allowedFUNames.empty()) {
1543 allowedFUNames = allowedFUs;
1545 std::set<TCEString> tmp;
1547 allowedFUNames = tmp;
1551 for (
int i = 0; i <= nav.
count(); i++) {
1553 if (i == nav.
count()) {
1560 allowedFUNames, fu->
name())) {
1580 std::cerr <<
"node should have dest as reg: " <<
1591 for (
int i = 0; i < rf.
portCount(); i++) {
1603 for (
int i = 0; i < rf.
portCount(); i++) {
1619 std::vector<const Socket*> sockets{
1622 for (
const Socket* socket : sockets) {
1623 if (socket !=
nullptr && socket->isConnectedTo(bus)) {
1645 const std::set<TTAMachine::Port*> ports,
const TTAMachine::Bus& bus) {
1646 for (
const auto& port : ports) {
1686 std::set<TCEString> candidateFUs;
1687 std::set<TCEString> allowedFUs;
1694 for (
int i = 0; i < nav.
count(); i++) {
1697 allowedFUs, fu->
name())) {
1701 candidateFUs, fu->
name())) {
1727 for (
int i = 0; i < nav.
count(); i++) {
1732 for (
int i = 0; i < iu->
portCount(); i++) {
1758 if (destinationPorts.empty()) {
1767 *imm, destinationPorts)) {
1775 *(*destinationPorts.begin())->parentUnit()->machine(), src);
1780 sourcePorts, destinationPorts,
1795 targetMachine, user);
1798 if (destinationPorts.empty()) {
1807 *imm, destinationPorts)) {
1820 sourcePorts, destinationPorts,
1833 if (sourcePorts.empty()) {
1838 *(*sourcePorts.begin())->parentUnit()->machine(), dest);
1852 moveNode, destinationPorts, ignoreGuard);
1857 std::set<TCEString>& candidateFUs,
1862 for (
int i = 0; i < annotationCount; ++i) {
1864 candidateFUs.insert(candidateFU);
1882 std::set<std::pair<const RegisterFile*,int> > allGuardRegs;
1886 for (
int bi = 0; bi < busNav.
count(); ++bi) {
1888 for (
int gi = 0; gi < bus->
guardCount(); gi++) {
1893 allGuardRegs.insert(
1900 if (allGuardRegs.empty()) {
1905 for (
int i = 0; i < regNav.
count(); i++) {
1907 for (
int j = 0; j < regNav.
count(); j++) {
1909 int width = drf->
width();
1912 if (!rfWidths.empty() &&
1917 for (std::set<std::pair<const RegisterFile*,int> >::iterator k =
1918 allGuardRegs.begin(); k != allGuardRegs.end(); k++) {
1949 std::pair<const RegisterFile*,int> guardReg) {
1951 RfRfBoolMap::const_iterator
1954 if (i->second ==
false) {
1958 std::set<const TTAMachine::Bus*> srcBuses;
1961 std::set<const TTAMachine::Bus*> dstBuses;
1964 std::set<const TTAMachine::Bus*> sharedBuses;
1967 bool trueOK =
false;
1968 bool falseOK =
false;
1969 if (sharedBuses.size() > 0) {
1971 for (
auto bus: sharedBuses) {
1972 std::pair<bool, bool> guardsOK =
hasBothGuards(bus, guardReg);
1973 trueOK |= guardsOK.first;
1974 falseOK |= guardsOK.second;
1975 if (trueOK && falseOK) {
1984 const TTAMachine::Bus* bus, std::pair<const RegisterFile*,int> guardReg) {
1985 bool trueOK =
false;
1986 bool falseOK =
false;
1988 for (
int gi = 0; gi < bus->
guardCount(); gi++) {
2000 if (falseOK && trueOK) {
2001 return std::pair<bool, bool>(
true,
true);
2006 return std::pair<bool, bool>(trueOK, falseOK);
2013 for (
auto iu : iuNav) {
2014 limmCount += iu->maxReads();
2024 for (
auto bus : busNav) {
2025 if (bus->immediateWidth() > 0) {
2047 FUSet partiallySuitableFUs;
2049 std::string opName =
"COPY";
2056 if (fu->hasOperation(opName)) {
2058 copyOutPorts.insert(hwop->
port(2));
2059 copyTriggerPorts.insert(hwop->
port(1));
2061 copyOutPorts, destinationPorts,
2064 partiallySuitableFUs.insert(fu);
2066 mn, copyTriggerPorts)) {
2067 suitableFUs.insert(fu);
2072 return suitableFUs.empty() ? partiallySuitableFUs : suitableFUs;
2085 for (
auto fu: fuNav) {
2086 if (fu->hasOperation(opName)) {
2088 sourcePorts.insert(hwop->
port(outIndex));
2097 sourcePorts, destinationPorts,