OpenASIP 2.2
Loading...
Searching...
No Matches
ITemplateBroker.cc
Go to the documentation of this file.
1/*
2 Copyright (c) 2002-2011 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 ITemplateBroker.cc
26 *
27 * Implementation of ITemplateBroker class.
28 *
29 * @author Ari Metsähalme 2006 (ari.metsahalme-no.spam-tut.fi)
30 * @author Vladimir Guzma 2007 (vladimir.guzma-no.spam-tut.fi)
31 * @note rating: red
32 */
33
34#include "CompilerWarnings.hh"
35IGNORE_CLANG_WARNING("-Wunused-local-typedef")
36#include <boost/lexical_cast.hpp>
38
39#include "ITemplateBroker.hh"
40#include "ITemplateResource.hh"
41#include "Machine.hh"
42#include "MachineInfo.hh"
45#include "ResourceMapper.hh"
46#include "Move.hh"
47#include "Instruction.hh"
48#include "MapTools.hh"
49#include "NullInstruction.hh"
50#include "POMDisassembler.hh"
51#include "MoveNode.hh"
53#include "MathTools.hh"
54#include "TerminalRegister.hh"
55#include "Immediate.hh"
57#include "TemplateSlot.hh"
58#include "BusBroker.hh"
59#include "ControlUnit.hh"
60
61using std::string;
62using namespace TTAMachine;
63using namespace TTAProgram;
64
65/**
66 * Constructor.
67 */
69 std::string name, BusBroker& busBroker, unsigned int initiationInterval) :
70 ResourceBroker(name, initiationInterval),
71 rm_(NULL), busBroker_(busBroker) {
72}
73
74/**
75 * Constructor.
76 */
78 std::string name,
79 BusBroker& busBroker,
81 unsigned int initiationInterval) :
82 ResourceBroker(name, initiationInterval),
83 rm_(rm), busBroker_(busBroker) {
84}
85
86/**
87 * Destructor.
88 */
90 for (std::map<int, TTAProgram::Instruction*>::iterator i =
91 instructions_.begin(); i != instructions_.end(); i++) {
92 std::map<int, bool>::iterator j = instructionsNotOwned_.find(i->first);
93 // not found = >owns, deletes.
94 if (j == instructionsNotOwned_.end() || j->second == false) {
95 delete i->second;
96 }
97 }
98
99}
100
101/**
102 * Return true if there's an instruction template available to be used
103 * on the given cycle for the given move.
104 *
105 * If the given node contains a long immediate register read, the
106 * instruction template must be able to encode required bits for it.
107 *
108 * @param cycle Cycle where instruction template is used.
109 * @param node Node which contains long immediate register read.
110 * @return True if there's an instruction template available to be used
111 * on the given cycle, and the template is able to encode bits for long
112 * immediate that is read in given node.
113 */
114bool
116 int cycle,
117 const MoveNode& node,
118 const TTAMachine::Bus* bus,
119 const TTAMachine::FunctionUnit* srcFU,
120 const TTAMachine::FunctionUnit* dstFU,
121 int immWriteCycle,
122 const TTAMachine::ImmediateUnit* immu,
123 int immRegIndex) const {
124 cycle = instructionIndex(cycle);
125 int resultCount = allAvailableResources(
126 cycle, node, bus, srcFU, dstFU, immWriteCycle, immu, immRegIndex).
127 count();
128 return resultCount > 0;
129}
130
131
132/**
133 * Return all resources managed by this broker that can be assigned to
134 * the given node in the given cycle.
135 *
136 * @param cycle Cycle.
137 * @param node Node.
138 * @return All resources managed by this broker that can be assigned to
139 * the given node in the given cycle.
140 * @note This method is called twice, first it check available resources
141 * for immediate write, second call checks resources for MoveNode
142 */
145 int cycle,
146 const MoveNode& node,
147 const TTAMachine::Bus*,
149 const TTAMachine::FunctionUnit*, int,
151 int) const {
152 cycle = instructionIndex(cycle);
153 Moves moves;
154 Immediates immediates;
155 MoveNode& testedNode = const_cast<MoveNode&>(node);
156 if (node.isMove()) {
157 moves.push_back(testedNode.movePtr());
158 } else if (node.isImmediate()) {
159 immediates.push_back(testedNode.immediatePtr());
160 }
161 return findITemplates(cycle, moves, immediates);
162}
163
164
165/**
166 * Assigns instruction template resource to the parent instruction of
167 * the given node.
168 *
169 * @param cycle Cycle of node.
170 * @param node Node.
171 * @param res Instruction template resource to assign.
172 * @exception WrongSubclass If this broker does not recognise the given
173 * type of resource.
174 * @exception InvalidData If he given resource cannot be assigned to
175 * given node or no corresponding machine part is found.
176 * @note Ownership of a Move in MoveNode will be passed to Instruction
177 * inside the broker.
178 */
179void
181 int cycle, MoveNode& node, SchedulingResource& res,int, int) {
182
183 cycle = instructionIndex(cycle);
184
185 ITemplateResource& templateRes =
186 static_cast<ITemplateResource&>(res);
187 const InstructionTemplate& iTemplate =
188 static_cast<const InstructionTemplate&>(machinePartOf(res));
189 TTAProgram::Instruction* ins = NULL;
192 instructions_, cycle);
193
194 // In case template was already assigned and it changes
195 if (ins->instructionTemplate().name() != iTemplate.name()) {
196 SchedulingResource& oldRes =
198 ITemplateResource& oldTemplateRes =
199 dynamic_cast<ITemplateResource&>(oldRes);
200 oldTemplateRes.unassign(cycle);
201
202 // In case the amount of transportable immediate bits decreases
203 // due to ITemplate change, update each immediate bit width to
204 // the new width. If this is not done, negative immediates ends up
205 // to take more bits than they really need in TPEF and later
206 // loading the TPEF fails in TPEFProgramFactory.
207 for (int i = 0; i < ins->immediateCount(); i++) {
208 // Can not change bit width of these.
209 if (ins->immediate(i).value().isInstructionAddress() ||
212 continue;
213 }
214 int currentWidth = ins->immediate(i).value().value().width();
215 const ImmediateUnit& destIU =
217 int newSupportedWidth = iTemplate.supportedWidth(destIU);
218 if (currentWidth > newSupportedWidth) {
219 SimValue sim(
220 (destIU.signExtends() ?
221 ins->immediate(i).value().value().intValue() :
222 ins->immediate(i).value().value().unsignedValue()),
223 newSupportedWidth);
225 ins->immediate(i).setValue(ti);
226 }
227 }
228
229 ins->setInstructionTemplate(iTemplate);
230 templateRes.assign(cycle);
231 }
232 } else {
233 ins = new TTAProgram::Instruction(iTemplate);
234 instructions_[cycle] = ins;
235 templateRes.assign(cycle);
236 }
237
238 Instruction* oldIn = NULL;
239 if (node.isImmediate()) {
240 oldIn = node.immediate().parent();
241 if (oldIn != NULL) {
242 oldIn->removeImmediate(node.immediate());
243 }
244 ins->addImmediate(node.immediatePtr());
245 } else {
246 if (node.move().isInInstruction()) {
247 oldIn = &node.move().parent();
248 oldIn->removeMove(node.move());
249 }
250 ins->addMove(node.movePtr());
251 }
253 std::pair<const MoveNode*, TTAProgram::Instruction*>
254 (&node, oldIn));
255
256 // TODO: refactor this away.
257 if (node.isSourceImmediateRegister()) {
258 // Gets data from Immediate Unit broker, indirectly
259
260 auto immValue = rm_->immediateValue(node);
261 if (immValue) {
262 TerminalImmediate* tempImm =
263 dynamic_cast<TerminalImmediate*>(
264 immValue->copy());
265 int defCycle = instructionIndex(rm_->immediateWriteCycle(node));
266 if (defCycle >= 0) {
267 TerminalRegister* tmpReg =
268 dynamic_cast<TerminalRegister*>(
269 node.move().source().copy());
270 auto imm = std::make_shared<Immediate>(tempImm, tmpReg);
271 if (!isImmediateInTemplate(defCycle,imm)) {
272 assignImmediate(defCycle, imm);
273 immediateCycles_.insert(
274 std::pair<const MoveNode*, int>(&node,defCycle));
275 immediateValues_.insert(
276 std::pair<const MoveNode*,
277 std::shared_ptr<TTAProgram::Immediate> >(
278 &node,imm));
279 } else {
280 abortWithError("Failed to assign immediate write");
281 }
282 }
283 }
284 }
285}
286
287
288/**
289 * Assigns instruction template resource to the given instruction located
290 * in given cycle.
291 *
292 * @param cycle Cycle where to store immediate write.
293 * @param immediate Immediate to be written in cycle
294 * @exception WrongSubclass If this broker does not recognise the given
295 * type of resource.
296 * @exception InvalidData If he given resource cannot be assigned to
297 * given node or no corresponding machine part is found.
298 */
299void
301 int cycle, std::shared_ptr<Immediate> immediate) {
302 cycle = instructionIndex(cycle);
303
304 try {
305 // Find a template for definition cycle
306 Moves moves;
307 Immediates immediates;
308 immediates.push_back(immediate);
309
311 findITemplates(cycle, moves, immediates);
312 assert(resources.count());
313 ITemplateResource& templateRes =
314 static_cast<ITemplateResource&>(resources.resource(0));
315 const InstructionTemplate& iTemplate =
316 static_cast<const InstructionTemplate&>(
317 machinePartOf(templateRes));
318
319 // Find instruction, if there is none, create new.
320 TTAProgram::Instruction* ins = NULL;
323 instructions_, cycle);
324 // Remove old template assignment
325 SchedulingResource& oldRes =
327 ITemplateResource& oldTemplateRes =
328 static_cast<ITemplateResource&>(oldRes);
329 oldTemplateRes.unassign(cycle);
330 } else {
331 ins = new TTAProgram::Instruction(iTemplate);
332 instructions_[cycle] = ins;
333 }
334
335 // Define new immediate, depending on supported bit width of
336 // template for given immediate unit
337 const ImmediateUnit& iu = immediate->destination().immediateUnit();
338 int neededBitWidth = iTemplate.supportedWidth(iu);
339 if (neededBitWidth <= INT_WORD_SIZE &&
340 (!immediate->value().isInstructionAddress() &&
341 !immediate->value().isBasicBlockReference() &&
342 !immediate->value().isCodeSymbolReference())) {
343 // If it is not floating point or instruction address
344 // we recreate SimValue with proper bit width based on destination
345 if (iu.extensionMode() == Machine::ZERO) {
346 SimValue sim(
347 immediate->value().value().unsignedValue(), neededBitWidth);
349 immediate->setValue(ti);
350 }
351 if (iu.extensionMode() == Machine::SIGN) {
352 SimValue sim(
353 immediate->value().value().intValue(), neededBitWidth);
355 immediate->setValue(ti);
356 }
357 }
358
359 templateRes.assign(cycle);
360 ins->setInstructionTemplate(iTemplate);
361 ins->addImmediate(immediate);
362
363 } catch (const std::bad_cast& e) {
364 string msg = "Resource is not of an instruction template resource.";
365 throw WrongSubclass(__FILE__, __LINE__, __func__, msg);
366 } catch (const KeyNotFound& e) {
367 string msg = "Broker does not contain given resource.";
368 throw InvalidData(__FILE__, __LINE__, __func__, msg);
369 }
370}
371
372/**
373 * Free the instruction template resource used in the parent instruction
374 * of the given node.
375 *
376 * @param node Node.
377 * @note Returns ownership of Move in MoveNode to the original parent
378 * instruction
379 */
380void
382 // Template not to be unassgined, it is just that there will be space
383 // left in this template for move
384
385 TTAProgram::Instruction& ins = node.isMove() ? node.move().parent() :
386 *node.immediate().parent();
388 if (node.isMove()) {
389 ins.removeMove(node.move());
390 TTAProgram::Instruction* oldParent =
392 oldParentInstruction_, &node);
393 if (oldParent != NULL) {
394 oldParent->addMove(node.movePtr());
395 }
396 oldParentInstruction_.erase(&node);
397 } else if (node.isImmediate()) {
398 ins.removeImmediate(node.immediate());
399 TTAProgram::Instruction* oldParent =
401 oldParentInstruction_, &node);
402 if (oldParent != NULL) {
403 oldParent->addImmediate(node.immediatePtr());
404 }
405 oldParentInstruction_.erase(&node);
406 reselectTemplate(ins, node.cycle());
407 return;
408 }
409 }
410 if (node.isSourceConstant() &&
412 int defCycle = MapTools::valueForKey<int>(immediateCycles_, &node);
413 auto imm =
415 immediateValues_, &node);
416
417 if (isImmediateInTemplate(defCycle, imm)) {
418 unassignImmediate(defCycle, imm->destination().immediateUnit());
419 } else {
420 abortWithError("Failed to remove Immediate from instruction");
421 }
422 immediateCycles_.erase(&node);
423 immediateValues_.erase(&node);
424 }
425 reselectTemplate(ins, node.cycle());
426}
427
428/**
429 * Free the Instruction template used at this cycle. Sets new instruction
430 * template that does not use freed immediate slot.
431 *
432 * If this broker is not applicable to the given node, or the node is
433 * not assigned a resource of the managed type, this method does
434 * nothing.
435 *
436 * @param cycle Cycle from where to unassign immediate
437 * @param immediate Immediate to remove from cycle
438 */
439void
441 int cycle,
442 const ImmediateUnit& immediateUnit) {
443 cycle = instructionIndex(cycle);
444
446 return;
447 }
448 Instruction* ins =
450 const InstructionTemplate& iTemplate = ins->instructionTemplate();
451 SchedulingResource& res = *resourceOf(iTemplate);
452 ITemplateResource& templateRes = dynamic_cast<ITemplateResource&>(res);
453
454 templateRes.unassign(cycle);
455 for (int i = 0; i < ins->immediateCount(); i++) {
456 if (ins->immediate(i).destination().immediateUnit().name() ==
457 immediateUnit.name()) {
458 ins->removeImmediate(ins->immediate(i));
459 break;
460 }
461 }
462 reselectTemplate(*ins, cycle);
463}
464
465/**
466 * Reselect the template to be the most optimal (most nop slots etc)
467 * Called always on unassign.
468 */
469void
471 // set new template that does not use immediate slot just unassigned
472 // moves and immediate will be filled from instruction in given cycle
473 // inside findITTemplates method
474 Moves moves;
475 Immediates immediates;
477 findITemplates(cycle, moves, immediates);
478 assert(resources.count() >0);
479 ITemplateResource& newTemplateRes = static_cast<ITemplateResource&>(
480 resources.resource(0));
481 const InstructionTemplate& newTemplate =
482 dynamic_cast<const InstructionTemplate&>(
483 machinePartOf(newTemplateRes));
484 ins.setInstructionTemplate(newTemplate);
485 newTemplateRes.assign(cycle);
486}
487
488/**
489 * Return the earliest cycle, starting from given cycle, where a
490 * resource of the type managed by this broker can be assigned to the
491 * given node.
492 *
493 * @param cycle Cycle.
494 * @param node Node.
495 * @return The earliest cycle, starting from given cycle, where a
496 * resource of the type managed by this broker can be assigned to the
497 * given node.
498 */
499int
501 const TTAMachine::Bus*,
503 const TTAMachine::FunctionUnit*, int,
504 const TTAMachine::ImmediateUnit*, int) const {
505 abortWithError("Not implemented.");
506 return -1;
507}
508
509/**
510 * Return the latest cycle, starting from given cycle, where a
511 * resource of the type managed by this broker can be assigned to the
512 * given node.
513 *
514 * @param cycle Cycle.
515 * @param node Node.
516 * @return The latest cycle, starting from given cycle, where a
517 * resource of the type managed by this broker can be assigned to the
518 * given node.
519 */
520int
522 const TTAMachine::Bus*,
524 const TTAMachine::FunctionUnit*, int,
525 const TTAMachine::ImmediateUnit*, int) const {
526 abortWithError("Not implemented.");
527 return -1;
528}
529
530/**
531 * Return true if the given node is already assigned a resource of the
532 * type managed by this broker, and the assignment appears valid (that
533 * is, the broker has marked that resource as in use in the given
534 * cycle).
535 *
536 * @param cycle Cycle.
537 * @param node Node.
538 * @return True if the given node is already assigned a resource of the
539 * type managed by this broker, and the assignment appears valid (that
540 * is, the broker has marked that resource as in use in the given
541 * cycle).
542 */
543bool
545 int cycle, const MoveNode& node, const TTAMachine::Bus*) const {
546 if (node.isImmediate()) {
547 return node.immediate().parent() != NULL;
548 }
549 Move& move = const_cast<MoveNode&>(node).move();
550
551 cycle = instructionIndex(cycle);
552 if (!move.isInInstruction()) {
553 return false;
554 }
555 const InstructionTemplate& iTemplate =
557
558 // Cannot be already assigned if template is null.
559 if (&iTemplate != &NullInstructionTemplate::instance()) {
560 // When node is assigned, it's old parent is stored, thus if the
561 // old parent is stored, node was assigned
563 SchedulingResource* res = resourceOf(iTemplate);
564 if ( res != NULL && res->isInUse(cycle)) {
565 return true;
566 }
567 }
568 }
569 return false;
570}
571
572/**
573 * Return true if the given node needs a resource of the type managed
574 * by this broker, false otherwise.
575 *
576 * @param node Node.
577 * @return True if the given node needs a resource of the type managed
578 * by this broker, false otherwise.
579 * @todo reconsider, should be applicable for all the MoveNodes
580 */
581bool
583 return true;
584}
585
586/**
587 * Build all resource objects of the controlled type required to model
588 * scheduling resources of the given target processor.
589 *
590 * This method cannot set up the resource links (dependent and related
591 * resources) of the constructed resource objects.
592 *
593 * @param target Target machine.
594 */
595void
597
600
601 for (int i = 0; i < templateNavi.count(); i++) {
602 InstructionTemplate* itemplate = templateNavi.item(i);
603 ITemplateResource* itemplateResource =
604 new ITemplateResource(*itemplate, initiationInterval_);
605 ResourceBroker::addResource(*itemplate, itemplateResource);
606 }
607
608 Machine::BusNavigator busNavi = target.busNavigator();
609
610 for (int i = 0; i < busNavi.count(); i++) {
611 slots_.push_back(busNavi.item(i));
612 }
613}
614
615/**
616 * Complete resource initialisation by creating the references to
617 * other resources due to a dependency or a relation.
618 *
619 * Use the given resource mapper to lookup dependent and related resources
620 * using machine parts as keys.
621 *
622 * @param mapper Resource mapper.
623 */
624void
626
627 setResourceMapper(mapper);
628
629 for (ResourceMap::iterator resIter = resMap_.begin();
630 resIter != resMap_.end(); resIter++) {
631
632 const InstructionTemplate* itemplate =
633 dynamic_cast<const InstructionTemplate*>((*resIter).first);
634 if (itemplate == NULL){
635 throw InvalidData(
636 __FILE__, __LINE__, __func__,
637 "Broker does not have necessary Template registered!");
638 }
639
640 SchedulingResource* templateResource = (*resIter).second;
641
642 for (unsigned int i = 0; i < slots_.size(); i++) {
643 if (itemplate->usesSlot(slots_[i]->name())) {
644 try {
645 SchedulingResource& depSlot =
646 mapper.resourceOf(*slots_[i]);
647 templateResource->addToDependentGroup(0, depSlot);
648 } catch (const KeyNotFound& e) {
649 std::string msg = "ITemplateBroker: finding ";
650 msg += " resource for Slot ";
651 msg += " failed with error: ";
652 msg += e.errorMessageStack();
653 throw KeyNotFound(
654 __FILE__, __LINE__, __func__, msg);
655 }
656
657 ImmediateUnit* iu =
658 itemplate->destinationOfSlot(slots_[i]->name());
659 try {
660 SchedulingResource& depIU = mapper.resourceOf(*iu);
661 templateResource->addToDependentGroup(1, depIU);
662 } catch (const KeyNotFound& e) {
663 std::string msg = "ITemplateBroker: finding ";
664 msg += " resource for IU ";
665 msg += " failed with error: ";
666 msg += e.errorMessageStack();
667 throw KeyNotFound(
668 __FILE__, __LINE__, __func__, msg);
669 }
670 }
671 }
672 }
673}
674
675/**
676 * Return true always.
677 *
678 * @return True always.
679 */
680bool
682 return true;
683}
684
685/**
686 * Returns an instruction at a given cycle.
687 *
688 * @param cycle Cycle for which to return instruction
689 * @return an instruction object for given cycle,
690 * empty instruction if there is no record.
691 */
694 cycle = instructionIndex(cycle);
696 Moves moves;
697 Immediates immediates;
698 SchedulingResourceSet defaultTemplates = findITemplates(
699 cycle, moves, immediates);
700 if (defaultTemplates.count() == 0) {
701 throw InvalidData(
702 __FILE__, __LINE__, __func__,
703 "No Instruction Template available!");
704 }
705 SchedulingResource& iTemp = defaultTemplates.resource(0);
706 const MachinePart& mp = machinePartOf(iTemp);
707 const InstructionTemplate& iTemplate =
708 dynamic_cast<const InstructionTemplate&>(mp);
709 ITemplateResource& templateRes =
710 dynamic_cast<ITemplateResource&>(iTemp);
711 templateRes.assign(cycle);
712 TTAProgram::Instruction* ins = NULL;
713 ins = new TTAProgram::Instruction(iTemplate);
714 instructions_[cycle] = ins;
715 ins->setInstructionTemplate(iTemplate);
716 return ins;
717 }
718 Instruction* ins =
720 instructions_, cycle);
721 return ins;
722}
723
724/**
725 * Helper function, finds all templates that are applicable
726 * for current status of instruction and new node that needs
727 * to be added
728 *
729 * @param moves A set of moves which has to fit into template
730 * @param immediates A set of immediates which has to fit into template
731 * @return A set of instruction templates that supports current instruction
732 * plus new instruction
733 * @note The test for Moves is done by checking if a bus Move uses
734 * is not allocated by template for immediate move. Immediate slots
735 * are not relevant here.
736 */
739 int cycle,
740 Moves& moves,
741 Immediates& immediates) const {
742
743 cycle = instructionIndex(cycle);
745 Instruction* ins = NULL;
746 // Read in content of instruction if there is something already
747 // stored in given cycle
750 instructions_, cycle);
751 for (int i = 0; i < ins->moveCount(); i++) {
752 moves.push_back(ins->movePtr(i));
753 }
754 for (int i = 0; i < ins->immediateCount(); i++) {
755 immediates.push_back(ins->immediatePtr(i));
756 }
757 }
758
759 for (ResourceMap::const_iterator resIter = resMap_.begin();
760 resIter != resMap_.end(); resIter++) {
761 bool addResult = true;
762 // bus resources (slots) are in dependent group 0
763 // immediate resources are in group 1
764 // trying to find template that has exactly same number or
765 // higher number of immediate writes as instruction
766 if ((*resIter).second->dependentResourceGroupCount() > 1 &&
767 immediates.size() > static_cast<unsigned int>(
768 (*resIter).second->dependentResourceCount(1))) {
769 continue;
770 }
771
772 const InstructionTemplate& iTemplate =
773 dynamic_cast<const InstructionTemplate&>(*(*resIter).first);
774
775 // For each of already assigned immediate writes, template
776 // has to have destination unit
777 std::vector<const TTAMachine::ImmediateUnit*> unitWriten;
778 for (unsigned int i = 0; i < immediates.size(); i++) {
779 const ImmediateUnit& unit =
780 immediates[i]->destination().immediateUnit();
781 if (ContainerTools::containsValue(unitWriten, &unit)) {
782 addResult = false;
783 break;
784 }
785 // immediate and immediate units has correct width, this checks
786 // if template can transport such a number of bits into the unit
787 // it is possible to have template which transport less bits
788 if (!iTemplate.isOneOfDestinations(unit)) {
789 addResult = false;
790 break;
791 }
792 // FIXME: hack to check if terminal is floating point value
793 if (immediates[i]->value().value().width() > INT_WORD_SIZE &&
794 (immediates[i]->value().value().width() >
795 iTemplate.supportedWidth(unit))) {
796 addResult = false;
797 break;
798 }
799 // FIXME: instruction addresses hold reference to instruction
800 // reference which computes the SimValue depending on target
801 // instruction's address. So it is not possible to modify the
802 // bit width of such SimValue
803 if (immediates[i]->value().isInstructionAddress() &&
804 !immediates[i]->value().isBasicBlockReference() &&
805 !immediates[i]->value().isCodeSymbolReference()) {
806
807 const AddressSpace& as =
809 int requiredBitWidth = unit.extensionMode() == Machine::SIGN ?
812 if (requiredBitWidth > iTemplate.supportedWidth(unit)) {
813 addResult = false;
814 break;
815 }
816 }
817 // Ignore instruction addresses, based on destination mode
818 // tests required bits of correct representation of SimValue
819 if (!immediates[i]->value().isInstructionAddress() &&
820 !immediates[i]->value().isBasicBlockReference() &&
821 !immediates[i]->value().isCodeSymbolReference() &&
822 unit.extensionMode() == Machine::ZERO &&
824 immediates[i]->value().value().unsignedValue()) >
825 iTemplate.supportedWidth(unit)) {
826 addResult = false;
827 break;
828 }
829 if (!immediates[i]->value().isInstructionAddress() &&
830 !immediates[i]->value().isBasicBlockReference() &&
831 !immediates[i]->value().isCodeSymbolReference() &&
832 unit.extensionMode() == Machine::SIGN &&
834 immediates[i]->value().value().intValue()) >
835 iTemplate.supportedWidth(unit)) {
836 addResult = false;
837 break;
838 }
839
840 if (immediates[i]->value().isCodeSymbolReference() &&
841 immediates[i]->value().toString() == "_end") {
842
843 AddressSpace* dataAS;
844 try {
845 dataAS =
847 } catch (Exception&) {
848 assert(false && "No default data address space");
849 }
850
851 int requiredBitWidth = unit.extensionMode() == Machine::SIGN ?
853 MathTools::requiredBits(dataAS->end());
854
855 if (requiredBitWidth > iTemplate.supportedWidth(unit)) {
856 addResult = false;
857 break;
858 }
859
860 } else if (immediates[i]->value().isBasicBlockReference() ||
861 immediates[i]->value().isCodeSymbolReference()) {
862
863 const AddressSpace& as
865 int requiredBitWidth = unit.extensionMode() == Machine::SIGN ?
868
869 if (requiredBitWidth > iTemplate.supportedWidth(unit)) {
870 addResult = false;
871 break;
872 }
873
874 }
875
876 unitWriten.push_back(&unit);
877 }
878 // For each of moves already assigned template
879 // should not use the bus for immediate transport or as
880 // a fixed NOP slot
881 for (unsigned int i = 0; i < moves.size(); i++) {
882
883 const bool isNOPSlot = false;
884
885 SchedulingResource* bus =
886 busBroker_.resourceOf(moves[i]->bus());
887 if ((*resIter).second->hasDependentResource(*bus) ||
888 isNOPSlot) {
889 addResult = false;
890 break;
891 }
892 }
893 if (addResult) {
894 result.insert(*(*resIter).second);
895 }
896 }
897 result.sort();
898 return result;
899}
900
901/**
902 * Transfer the instruction ownership away from this object,
903 *
904 * If this method is called, resource manager does not delete it's
905 * instructions when it it destroyed.
906 */
907void
911
912/*
913 * Tests if an immediate is already written into instruction template
914 *
915 * @param defCycle cycle which to test
916 * @param imm Immediate to test in defCycle
917 * @return True if immediate is already written in instruction template
918 */
919bool
921 int defCycle,
922 std::shared_ptr<Immediate> imm) const {
923
924 if (!MapTools::containsKey(instructions_, defCycle)) {
925 return false;
926 }
928 instructions_, defCycle);
929 for (int i = 0; i < ins->immediateCount(); i++){
930 if (ins->immediate(i).value().value() == imm->value().value() &&
931 ins->immediate(i).destination().equals(imm->destination())){
932 return true;
933 }
934 }
935 return false;
936}
937
938/**
939 * Tests if there is any instruction template available for immediate
940 * in given cycle
941 *
942 * @param defCycle cycle to test
943 * @param immediate Immediate to test
944 * @return True if there is instruction template for given cycle which can
945 * write given immediate
946 */
947bool
949 int defCycle,
950 std::shared_ptr<Immediate> immediate) const {
951
952 Immediates immediates;
953 Moves moves;
954 immediates.push_back(immediate);
955 int availableCount =
956 findITemplates(defCycle, moves, immediates).count();
957 return availableCount > 0;
958}
959
960/**
961 * Clears bookkeeping which is needed for unassigning previously assigned
962 * moves. After this call these cannot be unassigned, but new moves which
963 * are assigned after this call can still be unassigned.
964 */
965void
969
970/**
971 * Clears all bookkeeping for the broker.
972 *
973 * the RM can then be reused for another basic block.
974 */
975void
979
980 for (std::map<int, TTAProgram::Instruction*>::iterator i =
981 instructions_.begin(); i != instructions_.end(); i++) {
982 std::map<int, bool>::iterator j = instructionsNotOwned_.find(i->first);
983 // does not find => owns, delete.
984 if (j == instructionsNotOwned_.end() || j->second == false) {
985 delete i->second;
986 }
987 }
988 instructions_.clear();
989 instructionsNotOwned_.clear();
990 immediateCycles_.clear();
991 immediateValues_.clear();
992}
#define __func__
#define abortWithError(message)
#define assert(condition)
const Byte INT_WORD_SIZE
Definition BaseType.hh:154
long SLongWord
Definition BaseType.hh:52
#define POP_CLANG_DIAGS
#define IGNORE_CLANG_WARNING(X)
static bool containsValue(const ContainerType &aContainer, const ElementType &aKey)
std::string errorMessageStack(bool messagesOnly=false) const
Definition Exception.cc:138
virtual bool isAlreadyAssigned(int cycle, const MoveNode &node, const TTAMachine::Bus *preassignedBus) const override
void unassignImmediate(int, const TTAMachine::ImmediateUnit &)
virtual int earliestCycle(int cycle, const MoveNode &node, const TTAMachine::Bus *bus, const TTAMachine::FunctionUnit *srcUnit, const TTAMachine::FunctionUnit *dstUnit, int immWriteCycle, const TTAMachine::ImmediateUnit *immu, int immRegIndex) const override
void reselectTemplate(TTAProgram::Instruction &ins, int cycle)
BusBroker & busBroker_
virtual void unassign(MoveNode &node) override
virtual SchedulingResourceSet allAvailableResources(int, const MoveNode &, const TTAMachine::Bus *bus, const TTAMachine::FunctionUnit *srcUnit, const TTAMachine::FunctionUnit *dstUnit, int immWriteCycle, const TTAMachine::ImmediateUnit *immu, int immRegIndex) const override
SimpleResourceManager * rm_
virtual ~ITemplateBroker()
std::vector< std::shared_ptr< const TTAProgram::Move > > Moves
virtual bool isAnyResourceAvailable(int, const MoveNode &, const TTAMachine::Bus *bus, const TTAMachine::FunctionUnit *srcFU, const TTAMachine::FunctionUnit *dstFU, int immWriteCycle, const TTAMachine::ImmediateUnit *immu, int immRegIndex) const override
virtual int latestCycle(int cycle, const MoveNode &node, const TTAMachine::Bus *bus, const TTAMachine::FunctionUnit *srcUnit, const TTAMachine::FunctionUnit *dstUnit, int immWriteCycle, const TTAMachine::ImmediateUnit *immu, int immRegIndex) const override
std::vector< std::shared_ptr< const TTAProgram::Immediate > > Immediates
virtual void assign(int cycle, MoveNode &node, SchedulingResource &res, int immWriteCycle, int immRegIndex) override
std::vector< TTAMachine::Bus * > slots_
Move/immediate slots.
virtual bool isTemplateAvailable(int, std::shared_ptr< TTAProgram::Immediate >) const
ITemplateBroker(std::string, BusBroker &busBroker, unsigned int initiationInterval=0)
bool isImmediateInTemplate(int, std::shared_ptr< TTAProgram::Immediate >) const
std::map< int, bool > instructionsNotOwned_
virtual void setupResourceLinks(const ResourceMapper &mapper) override
virtual TTAProgram::Instruction * instruction(int cycle)
void assignImmediate(int, std::shared_ptr< TTAProgram::Immediate >)
virtual void buildResources(const TTAMachine::Machine &target) override
virtual bool isITemplateBroker() const override
virtual void loseInstructionOwnership(int cycle)
void clear() override
std::map< const MoveNode *, TTAProgram::Instruction *, MoveNode::Comparator > oldParentInstruction_
MoveNode/ original parent instruction.
virtual bool isApplicable(const MoveNode &node, const TTAMachine::Bus *) const override
SchedulingResourceSet findITemplates(int, Moves &, Immediates &) const
std::map< int, TTAProgram::Instruction * > instructions_
cycle/instruction
std::map< const MoveNode *, int, GraphNode::Comparator > immediateCycles_
Record cycle for MoveNodes that needed immediate writes, IU broker restores immediates before the tem...
std::map< const MoveNode *, std::shared_ptr< TTAProgram::Immediate >, GraphNode::Comparator > immediateValues_
virtual void assign(const int cycle, MoveNode &node) override
virtual void unassign(const int cycle, MoveNode &node) override
static TTAMachine::AddressSpace * defaultDataAddressSpace(const TTAMachine::Machine &mach)
static KeyType keyForValue(const MapType &aMap, const ValueType &aValue)
static bool containsKey(const MapType &aMap, const KeyType &aKey)
static int requiredBits(unsigned long int number)
static int requiredBitsSigned(SLongWord number)
bool isImmediate() const
Definition MoveNode.hh:143
int cycle() const
Definition MoveNode.cc:421
std::shared_ptr< TTAProgram::Immediate > immediatePtr()
Definition MoveNode.cc:846
bool isMove() const
std::shared_ptr< TTAProgram::Move > movePtr()
TTAProgram::Move & move()
bool isSourceImmediateRegister() const
Definition MoveNode.cc:223
bool isSourceConstant() const
Definition MoveNode.cc:238
TTAProgram::Immediate & immediate()
Definition MoveNode.cc:838
void addResource(const TTAMachine::MachinePart &mp, SchedulingResource *res)
SchedulingResource * resourceOf(const TTAMachine::MachinePart &mp) const
unsigned int instructionIndex(unsigned int) const
virtual void clear()
void setResourceMapper(const ResourceMapper &mapper)
unsigned int initiationInterval_
virtual const TTAMachine::MachinePart & machinePartOf(const SchedulingResource &r) const
void resources(ResourceSet &contents)
ResourceMap resMap_
const TTAMachine::Machine & machine() const
SchedulingResource & resourceOf(const TTAMachine::MachinePart &mp, int index=0) const
SchedulingResource & resource(int index) const
void insert(SchedulingResource &resource)
virtual void addToDependentGroup(const int group, SchedulingResource &resource)
virtual bool isInUse(const int cycle) const =0
int intValue() const
Definition SimValue.cc:895
unsigned int unsignedValue() const
Definition SimValue.cc:919
int width() const
Definition SimValue.cc:103
virtual std::shared_ptr< TTAProgram::TerminalImmediate > immediateValue(const MoveNode &)
virtual int immediateWriteCycle(const MoveNode &) const
virtual ULongWord end() const
virtual TCEString name() const
virtual AddressSpace * addressSpace() const
virtual Machine::Extension extensionMode() const
virtual bool usesSlot(const std::string &slotName) const
virtual ImmediateUnit * destinationOfSlot(const std::string &slotName) const
virtual bool isOneOfDestinations(const ImmediateUnit &dstUnit) const
ComponentType * item(int index) const
virtual InstructionTemplateNavigator instructionTemplateNavigator() const
Definition Machine.cc:428
virtual BusNavigator busNavigator() const
Definition Machine.cc:356
virtual ControlUnit * controlUnit() const
Definition Machine.cc:345
@ SIGN
Sign extension.
Definition Machine.hh:82
@ ZERO
Zero extension.
Definition Machine.hh:81
static NullInstructionTemplate & instance()
void setValue(TerminalImmediate *value)
Definition Immediate.cc:114
TerminalImmediate & value() const
Definition Immediate.cc:103
const Terminal & destination() const
Definition Immediate.cc:92
Instruction * parent() const
Definition Immediate.hh:67
void removeImmediate(Immediate &imm)
void addImmediate(std::shared_ptr< Immediate > imm)
std::shared_ptr< Move > movePtr(int i) const
std::shared_ptr< Immediate > immediatePtr(int i) const
Immediate & immediate(int i) const
void addMove(std::shared_ptr< Move > move)
void removeMove(Move &move)
void setInstructionTemplate(const TTAMachine::InstructionTemplate &insTemp)
const TTAMachine::InstructionTemplate & instructionTemplate() const
Instruction & parent() const
Definition Move.cc:115
Terminal & source() const
Definition Move.cc:302
bool isInInstruction() const
Definition Move.cc:144
virtual SimValue value() const
virtual bool isBasicBlockReference() const
Definition Terminal.cc:139
virtual bool isCodeSymbolReference() const
Definition Terminal.cc:154
virtual bool equals(const Terminal &other) const =0
virtual Terminal * copy() const =0
virtual bool isInstructionAddress() const
Definition Terminal.cc:87
virtual const TTAMachine::ImmediateUnit & immediateUnit() const
Definition Terminal.cc:240