OpenASIP 2.2
Loading...
Searching...
No Matches
MachineInfo.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 MachineInfo.cc
26 *
27 * Implementation of MachineInfo class.
28 *
29 * @author Mikael Lepistö 2008 (mikael.lepisto-no.spam-tut.fi)
30 * @note rating: red
31 */
32
33#include "MachineInfo.hh"
34
35#include "StringTools.hh"
36#include "Machine.hh"
37#include "HWOperation.hh"
38#include "OperationPool.hh"
39#include "ControlUnit.hh"
40#include "RegisterFile.hh"
41#include "Guard.hh"
42#include "Operation.hh"
43#include "Operand.hh"
44#include "FUPort.hh"
47#include "MathTools.hh"
49#include "UniversalMachine.hh"
50
51using namespace TTAMachine;
52
53const TCEString MachineInfo::LOCK_READ_ = "lock_read";
54const TCEString MachineInfo::TRY_LOCK_ADDR_ = "try_lock_addr";
55const TCEString MachineInfo::UNLOCK_ADDR_ = "unlock_addr";
56
57/**
58 * Checks that the operands used in the operations of the given FU are
59 * bound to some port.
60 *
61 * @param mach The machine whose opset is requested.
62 * @return Opset supported by machine hardware.
63 */
66
68
71
72 OperationPool opPool;
73
74 for (int i = 0; i < fuNav.count(); i++) {
75 const TTAMachine::FunctionUnit* fu = fuNav.item(i);
76 for (int o = 0; o < fu->operationCount(); o++) {
77 const std::string opName = fu->operation(o)->name();
78 opNames.insert(StringTools::stringToLower(opName));
79 }
80 }
81
82 return opNames;
83}
84
85
86/**
87 * Returns opset used by Global Control Unit.
88 *
89 * @param gcu The Global Control Unit whose opset is requested.
90 * @return Opset used by the Global Control Unit.
91 */
95 for (int i = 0; i < gcu.operationCount(); i++) {
96 const std::string opName = gcu.operation(i)->name();
97 opNames.insert(StringTools::stringToLower(opName));
98 }
99 return opNames;
100}
101
102
103/**
104 * Return first occurrence of FUPorts that are bound to operation given by
105 * name.
106 *
107 * Returned list has FUPorts ordered in the order of operands. At index 1 is
108 * port bounded to operand 1, at index 2 port bounded to operand 2 and so on.
109 * List is empty if operation was not found from machine. Unbounded operands
110 * have NULL at the index of operand (0 is always NULL).
111 *
112 * @param mach The machine.
113 * @param operationStr The operation.
114 * @return The list of ordered bound ports.
115 */
118 const TTAMachine::Machine& mach,
119 const std::string& operationStr) {
120
121 ConstPortList bindedPorts;
122
123 const TTAMachine::FunctionUnit* found = NULL;
126 for (int i = 0; i < fuNav.count(); i++) {
127 const TTAMachine::FunctionUnit* fu = fuNav.item(i);
128 if (fu->hasOperation(operationStr)) {
129 found = fu;
130 break;
131 }
132 }
133
134 if (found == NULL) {
135 if (mach.controlUnit()->hasOperation(operationStr)) {
136 found = mach.controlUnit();
137 }
138 }
139 if (found != NULL) {
140 bindedPorts.push_back(NULL); // Shift indexing.
141 HWOperation* operation = found->operation(operationStr);
142 for (int i = 1; i <= operation->operandCount(); i++) {
143 bindedPorts.push_back(operation->port(i));
144 }
145 }
146 return bindedPorts;
147}
148
149/**
150 * Returns port that is bound to operand index of the operation in the FU.
151 *
152 * Returns the port, if the FU has the operation and operation has the operand
153 * bound to some port. Otherwise, returns nullptr.
154 */
157 const TTAMachine::FunctionUnit& fu,
158 const std::string& opName, int operandIndex) {
159
160 if (fu.hasOperation(opName)) {
161 const HWOperation* hwOp = fu.operation(opName);
162 if (hwOp->isBound(operandIndex)) {
163 return hwOp->port(operandIndex);
164 }
165 }
166 return nullptr;
167}
168
169/**
170 * Finds the default data address space for given machine.
171 *
172 * @param mach The machine whose default data address space is requested.
173 * @return Default data address space for given machine
174 */
177
178 const AddressSpace& instrAS = *mach.controlUnit()->addressSpace();
179
182 int asCount = asNav.count();
183 for (int i = 0; i < asCount; i++) {
184 // if there are more than two address spaces, choose one which
185 // contains numerical id 0
186 // otherwise choose the one which is not the instruction address space
187 if (asCount > 2) {
188 if (asNav.item(i)->hasNumericalId(0)) return asNav.item(i);
189 } else {
190 if (asNav.item(i) != &instrAS) return asNav.item(i);
191 }
192 }
193
194 // no data address space found
195 throw IllegalMachine(
196 __FILE__, __LINE__, __func__,
197 "Target machine has no data address space");
198 return NULL;
199}
200
201int
203 const TTAMachine::Machine& mach) {
204 int ggLatency = mach.controlUnit()->globalGuardLatency();
205
207 mach.busNavigator();
208
209 for (int i = 0; i < busNav.count(); i++) {
210 const TTAMachine::Bus* bus = busNav.item(i);
211 for (int j = 0; j < bus->guardCount(); j++) {
212 Guard* guard = bus->guard(j);
213 RegisterGuard* rg = dynamic_cast<RegisterGuard*>(guard);
214 if (rg != NULL) {
215 int rgLat = rg->registerFile()->guardLatency();
216 if (rgLat != 0) {
217 assert(rgLat == 1);
218 return ggLatency + 1;
219 }
220 } else {
221 if (dynamic_cast<PortGuard*>(guard) != NULL) {
222 return ggLatency + 1;
223 }
224 }
225 }
226 }
227 return ggLatency;
228}
229
230/**
231 * Returns Operand object for the given hardware operation attached to the port.
232 *
233 * InstanceNotFound exception is thrown, if the hardware operation doesn't have
234 * an operand in the given port.
235 *
236 * @param hwOp Hardware operation.
237 * @param port The port containing the desired Operand.
238 * @return Reference to the Operand object.
239 */
240Operand&
242 const TTAMachine::HWOperation& hwOp,
243 const TTAMachine::FUPort& port) {
244
245 const TCEString& opName = hwOp.name();
246 OperationPool opPool;
247 const Operation& op = opPool.operation(opName.c_str());
248
249 assert(&op != &NullOperation::instance() && "Invalid operation name.");
250
251 int opndIndex = hwOp.io(port);
252 return op.operand(opndIndex);
253}
254
255/**
256 * Returns byte width of the widest load/store operation.
257 *
258 * @return Maximum memory alignment according to the widest memory operation.
259 */
260int
262 int byteAlignment = 4; // Stack alignment is four bytes at minimum.
263
264 TTAMachine::FunctionUnit* fu = nullptr;
267 for (int i = 0; i < fuNav.count(); i++) {
268 fu = fuNav.item(i);
269 if (fu->hasAddressSpace()) {
270 if (fu->addressSpace()->hasNumericalId(0)) {
271 break;
272 }
273 }
274 }
275 assert(fu && "Didn't find the LSU with local AS");
276 for (int k = 0; k < fu->operationCount(); k++) {
277 TCEString operation = fu->operation(k)->name();
278
279 const TCEString opName = StringTools::stringToLower(operation);
280 if (opName.length() > 2 && isdigit(opName[2])) {
281 // Assume operations named ldNNxMM and stNNxMM are operations
282 // with alignment of NN (or ldNN / stNN).
283 // @todo fix this horrible hack by adding the alignment info explicitly
284 // to OSAL.
285
286 // At least check for the name string format to match the above
287 // before parsing the number.
288 size_t xpos = opName.find("x", 3);
289 if (xpos == std::string::npos) {
290 for (size_t pos = 2; pos < opName.size(); ++pos)
291 if (!isdigit(opName[pos])) continue;
292
293 if (opName.startsWith("ld")) {
294 int loadByteWidth = Conversion::toInt(opName.substr(2)) / 8;
295 if (loadByteWidth > byteAlignment) {
296 byteAlignment = loadByteWidth;
297 }
298 } else if (opName.startsWith("st")) {
299 int storeByteWidth = Conversion::toInt(opName.substr(2)) / 8;
300 if (storeByteWidth > byteAlignment) {
301 byteAlignment = storeByteWidth;
302 }
303 }
304 } else {
305 for (size_t pos = xpos + 1; pos < opName.size(); ++pos)
306 if (!isdigit(opName[pos])) continue;
307
308 if (opName.startsWith("ld")) {
309 int loadByteWidth = Conversion::toInt(opName.substr(2, xpos - 2)) / 8;
310 if (loadByteWidth > byteAlignment) {
311 byteAlignment = loadByteWidth;
312 }
313 } else if (opName.startsWith("st")) {
314 int storeByteWidth = Conversion::toInt(opName.substr(2, xpos - 2)) / 8;
315 if (storeByteWidth > byteAlignment) {
316 byteAlignment = storeByteWidth;
317 }
318 }
319 }
320 }
321 }
322
323 if (!(byteAlignment > 1 && !(byteAlignment & (byteAlignment - 1)))) {
324 std::cerr << "Stack alignment: " << byteAlignment << std::endl;
325 assert(false && "Error: stack alignment must be a power of 2.");
326 }
327
328 return byteAlignment;
329}
330
331/**
332 * Checks if slot is used in any of the instruction templates defined in ADF.
333 *
334 * @param mach The Machine.
335 * @param slotName The name of the slot.
336 * @return True if any template includes given slot. False otherwise.
337 */
338bool
340 const TTAMachine::Machine& mach,
341 const std::string& slotName) {
342
343 std::set<InstructionTemplate*> affectingInstTemplates;
346 for (int i = 0; i < itNav.count(); i++) {
347 InstructionTemplate* iTemp = itNav.item(i);
348 if (iTemp->usesSlot(slotName)) {
349 return true;
350 }
351 }
352
353 return false;
354}
355
356
357/**
358 * Returns set of pointers to instruction templates that uses the given slot.
359 *
360 * @param mach The Machine.
361 * @param slotName The name of the slot.
362 * @return List of found templates or empty none was found.
363 */
364std::set<TTAMachine::InstructionTemplate*>
366 const TTAMachine::Machine& mach,
367 const std::string& slotName) {
368 std::set<InstructionTemplate*> affectingInstTemplates;
371 for (int i = 0; i < itNav.count(); i++) {
372 InstructionTemplate* iTemp = itNav.item(i);
373 if (iTemp->usesSlot(slotName)) {
374 affectingInstTemplates.insert(iTemp);
375 }
376 }
377 return affectingInstTemplates;
378}
379
380
381bool
383 const TTAMachine::Machine& mach, TCEString operation) {
386 return opNames.find(operation.upper()) != opNames.end();
387}
388
389bool
391 const TTAMachine::Bus& bus, int64_t imm, unsigned destWidth) {
392
393 size_t requiredBitsSigned =
394 std::min((unsigned)MathTools::requiredBitsSigned((long int)imm), destWidth);
395 size_t requiredBitsUnsigned =
396 std::min((unsigned)MathTools::requiredBits(imm), destWidth);
397
398 size_t requiredBits = bus.signExtends() ?
399 requiredBitsSigned : requiredBitsUnsigned;
400 // In case the short immediate can write all bits in
401 // the bus, let's assume this is the word width to the
402 // target operation and the extension mode can be
403 // assumed to be 'signed' (the targeted operation can
404 // interpret the value in the bus either way), we
405 // just have to be sure there is no information loss
406 // in the upper bits. This breaks with
407 // multibitwidth scalar machines, e.g., ones with
408 // INT32 datapath combined with FLOAT64 because now
409 // it assumes the constant can be written in case
410 // there's a 32b immediate slot for the INT32 bus. (*)
411 if (bus.width() == bus.immediateWidth() &&
412 requiredBitsSigned < requiredBits)
413 requiredBits = requiredBitsSigned;
414 if (static_cast<size_t>(bus.immediateWidth()) >= requiredBits)
415 return true;
416 return false;
417}
418
419/**
420 * Checks if the given immediate can be transferred at all
421 * in the given machine.
422 *
423 * Takes in account the move slots' or the immediate unit's
424 * extension mode when considering the encoding of the given
425 * constant's bits. In case this function returns true,
426 * the register copy adder or similar pass should be able to
427 * route the constant to the wanted destination(s), in case
428 * no direct bus with the immediate support is found. In
429 * case the destination (port) is known, its width should
430 * be set to destWidth to constraint the required immediate
431 * extension width (in case the move tries to write to a port narrower
432 * than the immediate actually requires bits, the bug is earlier
433 * in the compilation).
434 *
435 * A complex example: a move where a negative constant with minimal
436 * encoding of 7b is transported through a 32b bus to a 8b destination
437 * with a 8b move slot that uses zero extension mode. The zero extension
438 * mode does not fill up the upper bits with 1, but it does not
439 * lead to information loss as the destination uses only the lower
440 * 8 bits which can be encoded directly to the immediate field,
441 * thus the extension is not needed.
442 */
443bool
445 const TTAMachine::Machine& mach, int64_t imm, unsigned destWidth) {
446
447 const Machine::BusNavigator& busNav = mach.busNavigator();
448
449 // first check the short immediate slots
450 for (int bi = 0; bi < busNav.count(); ++bi) {
451 const Bus& bus = *busNav.item(bi);
452 if (canEncodeImmediateInteger(bus, imm, destWidth))
453 return true;
454 }
455
456 // then the long immediate templates
458 if (canEncodeImmediateInteger(*temp, imm, destWidth))
459 return true;
460
461 return false;
462}
463
464bool
466 const TTAMachine::InstructionTemplate& temp, int64_t imm,
467 unsigned destWidth) {
468 size_t requiredBitsSigned =
469 std::min((unsigned)MathTools::requiredBitsSigned(
470 static_cast<SLongWord>(imm)), destWidth);
471 size_t requiredBitsUnsigned =
472 std::min((unsigned)MathTools::requiredBits(
473 static_cast<ULongWord>(imm)), destWidth);
474
475 const TTAMachine::Machine& mach = *temp.machine();
478 for (const TTAMachine::ImmediateUnit* iu: mach.immediateUnitNavigator()) {
479 size_t requiredBits = iu->signExtends() ?
480 requiredBitsSigned : requiredBitsUnsigned;
481 size_t supportedW = temp.supportedWidth(*iu);
482 // see above (*). Same applies here: if the template encodes
483 // as many bits as the buses that the IU can write to are wide,
484 // the extension mode is meaningless -> can interpret it as one wishes
485 // here.
486 size_t maxBusW = 0;
487 std::set<const TTAMachine::Bus*> buses;
489 *iu, buses);
490 for (auto bus: buses) {
491 if (static_cast<size_t>(bus->width()) > maxBusW)
492 maxBusW = bus->width();
493 }
494
495 if (supportedW == maxBusW &&
496 requiredBitsSigned < requiredBits)
497 requiredBits = requiredBitsSigned;
498 if (supportedW >= requiredBits)
499 return true;
500
501 }
502
503 return false;
504}
505
506int
508 const TTAMachine::FunctionUnit& fu, const Operation& op) {
509 if (fu.hasOperation(op.name())) {
511 fu.operation(op.name());
512 for (int j = 0; j < fu.operationPortCount(); j++) {
513 TTAMachine::FUPort* port = fu.operationPort(j);
514 if (port->isTriggering()) {
515 return hwop->io(*port);
516 }
517 }
518 }
519 // operation not found in this FU
520 return 0;
521}
522
523/**
524 * Finds the operand index of trigger of given operation in the machine.
525 *
526 * If the operation is not found from the machine, return 0.
527 * If the index is ambiguos return -1.
528 */
529int
531 const TTAMachine::Machine& machine, const Operation& op) {
535 return op.numberOfInputs(); // last input
536 }
537 int index = 0;
538 for (int i = 0; i < nav.count(); i++) {
539 TTAMachine::FunctionUnit* fu = nav.item(i);
540 int curIndex = triggerIndex(*fu, op);
541 if (curIndex > 0) {
542 if (index > 0 && curIndex != index) {
543 return -1;
544 } else {
545 index = curIndex;
546 }
547 }
548 }
549 int curIndex = triggerIndex(*machine.controlUnit(), op);
550 if (curIndex > 0) {
551 if (index > 0 && curIndex != index) {
552 return -1;
553 } else {
554 index = curIndex;
555 }
556 }
557 return index;
558}
559
560/**
561 * Finds the widest operand available in the machine.
562 *
563 * Helps finding the widest usable register in the machine.
564 */
565unsigned
568 bool) {
569 OperationPool pool;
570 unsigned widestOperand = 0;
571
574
577 for (TCETools::CIStringSet::iterator it = opNames.begin();
578 it != opNames.end(); ++it) {
579
580 const Operation& op = pool.operation(it->c_str());
581
582 for (int j = 1; j < op.operandCount() + 1; ++j) {
583 if ((unsigned)(op.operand(j).width()) > widestOperand)
584 widestOperand = (unsigned)(op.operand(j).width());
585 }
586 }
587 return widestOperand;
588}
589
590/**
591 * Counts registers of given width.
592 */
593unsigned
595 const TTAMachine::Machine& machine, unsigned width) {
596
597 unsigned numRegisters = 0;
600
601 // Search register files of desired width and count registers
602 for (int i = 0; i < RFNavigator.count(); i++) {
603 TTAMachine::RegisterFile *rf = RFNavigator.item(i);
604 if ((unsigned)(rf->width()) == width) {
605 numRegisters += rf->size();
606 }
607 }
608 return numRegisters;
609}
610
611/**
612 * Returns true if the machine has predicatable jump.
613 *
614 */
615bool
618 const ControlUnit* cu = machine.controlUnit();
619 if (cu == nullptr) {
620 return false;
621 }
622
623 if (!cu->hasOperation("jump")) {
624 return false;
625 }
626
627 const FUPort* jumpPort = getBoundPort(*cu, "jump", 1);
628 if (jumpPort == nullptr) {
629 return false;
630 }
631
632 std::vector<const Bus*> guardedBuses;
633 for (const Bus* bus : machine.busNavigator()) {
634 for (int i = 0; i < bus->guardCount(); i++) {
635
636 const TTAMachine::RegisterGuard *regGuard =
637 dynamic_cast<TTAMachine::RegisterGuard*>(bus->guard(i));
638 if (regGuard && regGuard->registerFile()->width() == 1) {
639 guardedBuses.push_back(bus);
640 break;
641 }
642 }
643 }
644
645 for (const Bus* bus : guardedBuses) {
647 return true;
648 }
649 // Todo: Check if bus has sufficient transport capability for jumping?
650 // That is, it is at least connected to a RF, IU or can transport
651 // short immediates.
652 }
653
654 return false;
655}
656
657
658/**
659 * Returns true if the machine has predicatable jump.
660 *
661 */
662bool
664 const ControlUnit* cu = machine.controlUnit();
665 if (cu == nullptr) {
666 return false;
667 }
668
669 if (!cu->hasOperation("jump")) {
670 return false;
671 }
672
673 const FUPort* jumpPort = getBoundPort(*cu, "jump", 1);
674 if (jumpPort == nullptr) {
675 return false;
676 }
677
678 std::vector<const Bus*> guardedBuses;
679 for (const Bus* bus : machine.busNavigator()) {
680 for (int i = 0; i < bus->guardCount(); i++) {
681 const TTAMachine::PortGuard *portGuard =
682 dynamic_cast<TTAMachine::PortGuard*>(bus->guard(i));
683 if (portGuard) {
684 // TODO: should check what ops found from the source FU
685 guardedBuses.push_back(bus);
686 }
687 }
688 }
689
690 for (const Bus* bus : guardedBuses) {
692 return true;
693 }
694 // Todo: Check if bus has sufficient transport capability for jumping?
695 // That is, it is at least connected to a RF, IU or can transport
696 // short immediates.
697 }
698
699 return false;
700}
701
702
704 const TTAMachine::Machine& machine, bool inverted, const TCEString& opName) {
705
706 const ControlUnit* cu = machine.controlUnit();
707 if (cu == nullptr) {
708 return false;
709 }
710
711 if (!cu->hasOperation("jump")) {
712 return false;
713 }
714
715 const FUPort* jumpPort = getBoundPort(*cu, "jump", 1);
716 if (jumpPort == nullptr) {
717 return false;
718 }
719
720 std::vector<const Bus*> guardedBuses;
721 for (const Bus* bus : machine.busNavigator()) {
722 for (int i = 0; i < bus->guardCount(); i++) {
723 TTAMachine::Guard* guard = bus->guard(i);
724 if (guard->isInverted() != inverted) continue;
725 const TTAMachine::PortGuard *portGuard =
726 dynamic_cast<TTAMachine::PortGuard*>(guard);
727 if (portGuard) {
728 TTAMachine::FUPort* fup = portGuard->port();
729 auto fu = fup->parentUnit();
730 if (fu->hasOperation(opName)) {
731 // TODO: should check what ops found from the source FU
732 guardedBuses.push_back(bus);
733 }
734 }
735 }
736 }
737
738 for (const Bus* bus : guardedBuses) {
740 return true;
741 }
742 // Todo: Check if bus has sufficient transport capability for jumping?
743 // That is, it is at least connected to a RF, IU or can transport
744 // short immediates.
745 }
746
747 return false;
748}
749
750/**
751 * Searches for lock unit FUs and returns them.
752 *
753 * Lock unit FU must have the correct operations and an address space
754 *
755 * @param machine Architecture to be searched
756 * @return Vector of found lock unit FUs
757 */
758std::vector<const TTAMachine::FunctionUnit*>
760 std::vector<TCEString> requiredOperations;
761 requiredOperations.push_back(LOCK_READ_);
762 requiredOperations.push_back(TRY_LOCK_ADDR_);
763 requiredOperations.push_back(UNLOCK_ADDR_);
764
765 std::vector<const FunctionUnit*> lockUnits;
767 for (int i = 0; i < fuNav.count(); i++) {
768 const FunctionUnit* fu = fuNav.item(i);
769 bool hasCorrectOperations = true;
770 for (unsigned int i = 0; i < requiredOperations.size(); i++) {
771 if (!fu->hasOperation(requiredOperations.at(i))) {
772 hasCorrectOperations = false;
773 break;
774 }
775 }
776 if (hasCorrectOperations) {
777 if (!fu->hasAddressSpace()) {
778 TCEString msg;
779 msg << "Lock Unit " << fu->name() << " has no address space";
780 throw InvalidData(__FILE__, __LINE__, __func__, msg);
781 }
782 lockUnits.push_back(fu);
783 }
784 }
785 return lockUnits;
786}
787
788/**
789 * Convenience function for getting OSAL operation from HWOperation description.
790 *
791 * Throws InstanceNotFound if OSAL operation is not found.
792 */
795 OperationPool opPool;
796
797 Operation& op = opPool.operation(hwOp.name().c_str());
798 if (op.isNull()) {
800 "Operation '" + hwOp.name() + "' was not found in OSAL.");
801 }
802 return op;
803}
804
805
807 int maxl = -1;
808 for (auto fu: mach.functionUnitNavigator()) {
809 if (fu->hasOperation(opName)) {
810 const auto op = fu->operation(opName);
811 maxl = std::max(maxl, op->latency());
812 }
813 }
814 if (mach.controlUnit()->hasOperation(opName)) {
815 const auto op = mach.controlUnit()->operation(opName);
816 maxl = std::max(maxl, op->latency());
817 }
818 return maxl;
819}
#define __func__
#define assert(condition)
unsigned long ULongWord
Definition BaseType.hh:51
long SLongWord
Definition BaseType.hh:52
TTAMachine::Machine * machine
the architecture definition of the estimated processor
#define THROW_EXCEPTION(exceptionType, message)
Exception wrapper macro that automatically includes file name, line number and function name where th...
Definition Exception.hh:39
static int toInt(const T &source)
static void appendConnectedDestinationBuses(const TTAMachine::Port &port, std::set< const TTAMachine::Bus * > &buses)
static bool busConnectedToPort(const TTAMachine::Bus &bus, const TTAMachine::Port &port)
static const TCEString LOCK_READ_
static ConstPortList getPortBindingsOfOperation(const TTAMachine::Machine &mach, const std::string &operation)
static Operand & operandFromPort(const TTAMachine::HWOperation &hwOp, const TTAMachine::FUPort &port)
static bool templatesUsesSlot(const TTAMachine::Machine &mach, const std::string &slotName)
static bool supportsPortGuardedJump(const TTAMachine::Machine &machine, bool inverted, const TCEString &opName)
static std::set< TTAMachine::InstructionTemplate * > templatesUsingSlot(const TTAMachine::Machine &mach, const std::string &slotName)
static int maxLatency(const TTAMachine::Machine &mach, TCEString &opName)
std::vector< const TTAMachine::FUPort * > ConstPortList
static unsigned numberOfRegisters(const TTAMachine::Machine &machine, unsigned width)
static TTAMachine::AddressSpace * defaultDataAddressSpace(const TTAMachine::Machine &mach)
static const TCEString UNLOCK_ADDR_
static int triggerIndex(const TTAMachine::Machine &machine, const Operation &op)
static unsigned findWidestOperand(const TTAMachine::Machine &machine, bool vector)
static const TCEString TRY_LOCK_ADDR_
static const TTAMachine::FUPort * getBoundPort(const TTAMachine::FunctionUnit &fu, const std::string &opName, int operandIndex)
static bool supportsPortGuardedJumps(const TTAMachine::Machine &machine)
static int maxMemoryAlignment(const TTAMachine::Machine &mach)
static OperationSet getOpset(const TTAMachine::Machine &mach)
static std::vector< const TTAMachine::FunctionUnit * > findLockUnits(const TTAMachine::Machine &machine)
static bool canEncodeImmediateInteger(const TTAMachine::Machine &mach, int64_t imm, unsigned destWidth=UINT_MAX)
static bool supportsBoolRegisterGuardedJumps(const TTAMachine::Machine &machine)
static int longestGuardLatency(const TTAMachine::Machine &mach)
static Operation & osalOperation(const TTAMachine::HWOperation &hwOp)
static bool supportsOperation(const TTAMachine::Machine &mach, TCEString operation)
static int requiredBits(unsigned long int number)
static int requiredBitsSigned(SLongWord number)
static NullOperation & instance()
virtual int width() const
Definition Operand.cc:318
TCETools::CIStringSet OperationSet
Operation & operation(const char *name)
virtual TCEString name() const
Definition Operation.cc:93
bool isNull() const
virtual int operandCount() const
Definition Operation.cc:212
virtual int numberOfInputs() const
Definition Operation.cc:192
virtual Operand & operand(int id) const
Definition Operation.cc:541
static std::string stringToLower(const std::string &source)
TCEString upper() const
Definition TCEString.cc:86
bool startsWith(const std::string &str) const
virtual bool hasNumericalId(unsigned id) const
FunctionUnit * parentUnit() const
Definition BaseFUPort.cc:96
virtual int size() const
virtual int width() const
int width() const
Definition Bus.cc:149
int immediateWidth() const
Definition Bus.cc:160
bool signExtends() const
Definition Bus.cc:171
Guard * guard(int index) const
Definition Bus.cc:456
int guardCount() const
Definition Bus.cc:441
virtual Machine * machine() const
virtual TCEString name() const
int globalGuardLatency() const
virtual bool isTriggering() const
Definition FUPort.cc:182
virtual AddressSpace * addressSpace() const
virtual HWOperation * operation(const std::string &name) const
virtual int operationCount() const
virtual FUPort * operationPort(const std::string &name) const
virtual bool hasOperation(const std::string &name) const
virtual int operationPortCount() const
virtual bool hasAddressSpace() const
virtual bool isInverted() const
virtual FUPort * port(int operand) const
int io(const FUPort &port) const
const std::string & name() const
bool isBound(const FUPort &port) const
virtual bool usesSlot(const std::string &slotName) const
ComponentType * item(int index) const
virtual RegisterFileNavigator registerFileNavigator() const
Definition Machine.cc:450
virtual FunctionUnitNavigator functionUnitNavigator() const
Definition Machine.cc:380
virtual InstructionTemplateNavigator instructionTemplateNavigator() const
Definition Machine.cc:428
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 int guardLatency() const
const RegisterFile * registerFile() const
static UniversalMachine & instance()