OpenASIP 2.2
Loading...
Searching...
No Matches
InputFUBroker.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 InputFUBroker.cc
26 *
27 * Implementation of InputFUBroker 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 "InputFUBroker.hh"
35#include "InputFUResource.hh"
36#include "ResourceMapper.hh"
37#include "Machine.hh"
38#include "ControlUnit.hh"
39#include "ExecutionPipeline.hh"
40#include "HWOperation.hh"
41#include "Move.hh"
42#include "Terminal.hh"
43#include "Operation.hh"
45#include "FUPort.hh"
46#include "ProgramOperation.hh"
47#include "MapTools.hh"
48#include "ProgramAnnotation.hh"
49#include "AssocTools.hh"
50#include "TCEString.hh"
51#include "StringTools.hh"
53#include "ResourceManager.hh"
54#include "SchedulingResource.hh"
55#include "TerminalFUPort.hh"
56#include "MoveNodeSet.hh"
60
61using std::string;
62using namespace TTAMachine;
63using namespace TTAProgram;
64
65/**
66 * Constructor.
67 */
69 unsigned int initiationInterval):
70 FUBroker(name, initiationInterval) {
71}
72
73/**
74 * Destructor.
75 */
78
79/**
80 * Return all resources managed by this broker that can be assigned to
81 * the given node in the given cycle.
82 *
83 * @param cycle Cycle.
84 * @param node Node.
85 * @return All resources managed by this broker that can be assigned to
86 * the given node in the given cycle.
87 */
90 const TTAMachine::Bus*,
92 const TTAMachine::FunctionUnit* dstFU,
93 int,
95 int) const {
96 if (!isApplicable(node)) {
97 string msg = "Broker not capable of assigning resources to node!";
98 throw ModuleRunTimeError(__FILE__, __LINE__, __func__, msg);
99 }
100
101 Move& move = const_cast<MoveNode&>(node).move();
102 TerminalFUPort& dst = static_cast<TerminalFUPort&>(move.destination());
103
104 SchedulingResourceSet resourceSet;
105 ResourceMap::const_iterator resIter = resMap_.begin();
106
107 if (dynamic_cast<const SpecialRegisterPort*>(&dst.port()) != NULL) {
108 // only gcu applies
109 while (resIter != resMap_.end()) {
110 const ControlUnit* gcu =
111 dynamic_cast<const ControlUnit*>((*resIter).first);
112 if (gcu != NULL) {
113 InputFUResource* fuRes =
114 static_cast<InputFUResource*>((*resIter).second);
115 if (fuRes->isAvailable(cycle)) {
116 resourceSet.insert(*fuRes);
117 }
118 return resourceSet;
119 }
120 resIter++;
121 }
122 abortWithError("No GCU found!");
123 }
124
125 int opIndex = dst.operationIndex();
126 Operation& op = dst.hintOperation();
127 std::string opName = StringTools::stringToLower(op.name());
128
129 // check if a unit has already been assigned to some node
130 // of the same operation and use it.
131 const FunctionUnit* foundFU = dstFU;
132
133 DataDependenceGraph::NodeSet processedInputNodes;
134 auto a = findDstFUOfMove(node, foundFU, processedInputNodes);
135 if (a.first) {
136 foundFU = a.second;
137 } else { // conflicting FUs, cannot schedule
138 if (foundFU != nullptr) {
139 return SchedulingResourceSet();
140 }
141 }
142
143 if (foundFU) {
144 InputFUResource& foundFURes =
145 static_cast<InputFUResource&>(*resourceOf(*foundFU));
146
147 // Find what is the port on a new FU for given
148 // operation index. Find a socket for testing.
149 HWOperation* hwOp = foundFU->operationLowercase(opName);
150 Socket* soc = hwOp->port(opIndex)->inputSocket();
151
152 FUPort* tempPort =
153 dynamic_cast<FUPort*>(hwOp->port(opIndex));
154 if (tempPort == NULL){
155 throw InvalidData(
156 __FILE__, __LINE__, __func__,
157 "Target is missing necessary FUPort!");
158 }
159 bool triggering = false;
160 if (tempPort->isTriggering()) {
161 triggering = true;
162 }
163
164 InputPSocketResource* pSocket = NULL;
165 try {
166 pSocket = &static_cast<InputPSocketResource&>(
167 resourceMapper().resourceOf(*soc));
168 } catch (const KeyNotFound& e) {
169 std::string msg = "InputFUBroker: finding ";
170 msg += " resource for Socket ";
171 msg += " failed with error: ";
172 msg += e.errorMessageStack();
173 throw KeyNotFound(
174 __FILE__, __LINE__, __func__, msg);
175 }
176 if (foundFURes.canAssign(
177 cycle, node, *pSocket, triggering)) {
178 resourceSet.insert(foundFURes);
179 }
180 return resourceSet;
181 }
182
183 std::set<TCEString> candidateFUs;
184 std::set<TCEString> allowedFUs;
185 std::set<TCEString> rejectedFUs;
186 // not all nodes have dest operation info set as the RM can be called
187 // for single moves
188 if (node.isDestinationOperation()) {
189 // check if the move or other moves in the same program operation have
190 // candidate FUs set which limits the choice of FU for the node
191 ProgramOperation& destOp = node.destinationOperation();
192 for (int in = 0; in < destOp.inputMoveCount(); ++in) {
193 MoveNode& n = destOp.inputMove(in);
195 candidateFUs, n.move(),
198 allowedFUs, n.move(),
201 rejectedFUs, n.move(),
203 }
204 }
205
206 // if the move has already the FU assigned, force it to be chosen
207 // kludge implementation that use the candidate set code
208 const TTAMachine::FunctionUnit& targetFU =
209 node.move().destination().functionUnit();
210 if (dynamic_cast<const UniversalFunctionUnit*>(&targetFU) == NULL &&
211 dynamic_cast<const TTAMachine::ControlUnit*>(&targetFU) == NULL) {
212 candidateFUs.clear();
213 candidateFUs.insert(node.move().destination().functionUnit().name());
215 TCEString("Added candidate FU duo pre-set fu") +
216 node.move().destination().functionUnit().name());
217 }
218
219 // find units that support operation and are available
220 while (resIter != resMap_.end()) {
221 const FunctionUnit* unit =
222 static_cast<const FunctionUnit*>((*resIter).first);
223
224 assert(unit != NULL);
225 // in case the unit is limited by a candidate set, skip FUs that are
226 // not in it
227 debugLogRM(TCEString("checking ") << unit->name());
228 if (candidateFUs.size() > 0 &&
229 !AssocTools::containsKey(candidateFUs, unit->name())) {
231 TCEString("skipped ") << unit->name() << " because it was not "
232 " in the candidate set.");
233 ++resIter;
234 continue;
235 }
236
237 if (allowedFUs.size() > 0 &&
238 !AssocTools::containsKey(allowedFUs, unit->name())) {
240 TCEString("skipped ") << unit->name() << " because it was not "
241 " in the allowed set.");
242 ++resIter;
243 continue;
244 }
245
246 if (AssocTools::containsKey(rejectedFUs, unit->name())) {
248 TCEString("skipped ") << unit->name() << " because it was"
249 " in the rejected set.");
250 ++resIter;
251 continue;
252 }
253
254 debugLogRM(TCEString("Found ") + unit->name());
255
256 const SchedulingResource& res = *resourceOf(*unit);
257 if (res.isInputFUResource()) {
258 const InputFUResource& fuRes =
259 static_cast<InputFUResource&>(*resourceOf(*unit));
260 if (unit->hasOperationLowercase(opName)) {
261 debugLogRM(TCEString("found FU with the op ") + opName);
262 HWOperation* hwOp = unit->operationLowercase(opName);
263 assert(hwOp != NULL);
264 Socket* soc = hwOp->port(opIndex)->inputSocket();
265
266 FUPort* tempPort =
267 dynamic_cast<FUPort*>(hwOp->port(opIndex));
268 if (tempPort == NULL){
269 throw InvalidData(
270 __FILE__, __LINE__, __func__,
271 "Target is missing necessary FUPort!");
272 }
273 bool triggering = false;
274 if (tempPort->isTriggering()) {
275 triggering = true;
276 }
277
278 InputPSocketResource* pSocket = NULL;
279 try {
280 pSocket = &static_cast<InputPSocketResource&>(
281 resourceMapper().resourceOf(*soc));
282 } catch (const KeyNotFound& e) {
283 std::string msg = "InputFUBroker: finding ";
284 msg += " resource for Socket ";
285 msg += " failed with error: ";
286 msg += e.errorMessageStack();
287 throw KeyNotFound(
288 __FILE__, __LINE__, __func__, msg);
289 }
290 if (fuRes.canAssign(cycle, node, *pSocket, triggering)) {
291 resourceSet.insert(*(*resIter).second);
292 } else {
293 debugLogRM("could not assign the fuRes to it.");
294 }
295 } else {
296 debugLogRM(TCEString("does not have operation ") + opName);
297 }
298 }
299 resIter++;
300 }
301 if (resourceSet.count() == 0) {
302 debugLogRM("InputFUBroker returned an empty resource set.");
303 }
304
305 return resourceSet;
306}
307
308/**
309 * Return the earliest cycle, starting from given cycle, where a
310 * resource of the type managed by this broker can be assigned to the
311 * given node.
312 *
313 * @param cycle Cycle.
314 * @param node Node.
315 * @return The earliest cycle, starting from given cycle, where a
316 * resource of the type managed by this broker can be assigned to the
317 * given node.
318 */
319int
321 const TTAMachine::Bus*,
323 const TTAMachine::FunctionUnit*, int,
324 const TTAMachine::ImmediateUnit*, int) const {
325 abortWithError("Not implemented.");
326 return -1;
327}
328
329/**
330 * Return the latest cycle, starting from given cycle, where a
331 * resource of the type managed by this broker can be assigned to the
332 * given node.
333 *
334 * @param cycle Cycle.
335 * @param node Node.
336 * @return The latest cycle, starting from given cycle, where a
337 * resource of the type managed by this broker can be assigned to the
338 * given node.
339 */
340int
342 const TTAMachine::Bus*,
344 const TTAMachine::FunctionUnit*, int,
345 const TTAMachine::ImmediateUnit*, int) const {
346 abortWithError("Not implemented.");
347 return -1;
348}
349
350/**
351 * Return true if the given node is already assigned a resource of the
352 * type managed by this broker, and the assignment appears valid (that
353 * is, the broker has marked that resource as in use in the given
354 * cycle).
355 *
356 * @param cycle Cycle. Not used.
357 * @param node Node.
358 * @return True if the given node is already assigned a resource of the
359 * type managed by this broker, and the assignment appears valid (that
360 * is, the broker has marked that resource as in use in the given
361 * cycle) and recorded for node that it is using it (could be inUse
362 * because some other operation is executed).
363 */
364bool
366 int cycle, const MoveNode& node, const TTAMachine::Bus*) const {
367 cycle = instructionIndex(cycle);
368 Terminal& dst = const_cast<MoveNode&>(node).move().destination();
369 if (dst.isFUPort()) {
370 const FunctionUnit& fu = dst.functionUnit();
371 if (hasResourceOf(fu)) {
373 return true;
374 }
375 }
376 }
377 return false;
378}
379
380/**
381 * Return true if the given node needs a resource of the type managed
382 * by this broker, false otherwise.
383 *
384 * @param node Node.
385 * @return True if the given node needs a resource of the type managed
386 * by this broker, false otherwise.
387 */
388bool
390 const MoveNode& node, const TTAMachine::Bus*) const {
391 if (!node.isMove()) {
392 return false;
393 }
394 Move& move = const_cast<MoveNode&>(node).move();
395 return move.destination().isFUPort();
396}
397
398/**
399 * Mark given resource as in use for the given node, and assign the
400 * corresponding machine part (if applicable) to the node's move.
401 *
402 * If the node is already assigned to given resource, this method does
403 * nothing.
404 *
405 * @param cycle Cycle.
406 * @param node Node to assign.
407 * @param res Resource representing Input of and FU
408 * @exception WrongSubclass If this broker does not recognise the given
409 * type of resource.
410 * @exception InvalidParameters If he given resource cannot be assigned to
411 * given node or no corresponding machine part is found.
412 */
413void
415 int cycle, MoveNode& node, SchedulingResource& res, int, int) {
416 if (!isApplicable(node)) {
417 string msg = "Broker not capable of assigning resources to node!";
418 throw WrongSubclass(__FILE__, __LINE__, __func__, msg);
419 }
420
421 if (!hasResource(res)) {
422 string msg = "Broker does not contain given resource.";
423 throw InvalidData(__FILE__, __LINE__, __func__, msg);
424 }
425
426 InputFUResource& fuRes = static_cast<InputFUResource&>(res);
427
428 Move& move = const_cast<MoveNode&>(node).move();
429 TerminalFUPort& dst = static_cast<TerminalFUPort&>(move.destination());
430
431 if (dynamic_cast<const SpecialRegisterPort*>(&dst.port()) != NULL) {
432
433 const ControlUnit* gcu =
434 dynamic_cast<const ControlUnit*>(&machinePartOf(fuRes));
435
436 if (gcu != NULL) {
437 TerminalFUPort* newDst =
439 move.setDestination(newDst);
440 fuRes.assign(cycle, node);
441 assignedResources_.insert(
442 std::pair<const MoveNode*, SchedulingResource*>(
443 &node,&fuRes));
444 return;
445 } else {
446 abortWithError("GCU required but tried to assign something else!");
447 }
448 }
449
450 int opIndex = dst.operationIndex();
451 Operation& op = dst.hintOperation();
452
453 const FunctionUnit& unit =
454 static_cast<const FunctionUnit&>(machinePartOf(fuRes));
455 HWOperation* hwOp = unit.operation(op.name());
456 TerminalFUPort* newDst = new TerminalFUPort(*hwOp, opIndex);
458 move.setDestination(newDst);
459 fuRes.assign(cycle, node);
460 assignedResources_.insert(
461 std::pair<const MoveNode*, SchedulingResource*>(&node, &fuRes));
462}
463
464/**
465 * Free the resource type managed by this broker and unassign it from
466 * given node.
467 *
468 * If this broker is not applicable to the given node, or the node is
469 * not assigned a resource of the managed type, this method does nothing.
470 *
471 * @param node Node.
472 */
473void
475 if (!isApplicable(node)) {
476 return;
477 }
479 return;
480 } else {
481 Move& move = const_cast<MoveNode&>(node).move();
482 TerminalFUPort& dst =
483 static_cast<TerminalFUPort&>(move.destination());
484 InputFUResource& res =
485 static_cast<InputFUResource&>(*resourceOf(dst.functionUnit()));
486 res.unassign(node.cycle(), node);
487 assignedResources_.erase(&node);
488 return;
489 }
490
491}
492
493/**
494 * Build all resource objects of the controlled type required to model
495 * scheduling resources of the given target processor.
496 *
497 * This method cannot set up the resource links (dependent and related
498 * resources) of the constructed resource objects.
499 *
500 * @param target Target machine.
501 */
502void
504
505 std::map<const TTAMachine::FunctionUnit*,int> nopWeights;
506
508 for (int i = 0; i < navi.count(); i++) {
509 FunctionUnit* fu = navi.item(i);
510 InputFUResource* fuResource = new InputFUResource(
511 fu->name(), fu->operationCount(), nopWeights[fu],
513 ResourceBroker::addResource(*fu, fuResource);
514 }
515
516 ControlUnit* gcu = target.controlUnit();
517 InputFUResource* fuResource = new InputFUResource(
518 gcu->name(), gcu->operationCount(), 0, initiationInterval_);
519 ResourceBroker::addResource(*gcu, fuResource);
520}
521
522/**
523 * Complete resource initialisation by creating the references to
524 * other resources due to a dependency or a relation. Use the given
525 * resource mapper to lookup dependent and related resources using
526 * machine parts as keys.
527 *
528 * @param mapper Resource mapper.
529 */
530void
532
533 setResourceMapper(mapper);
534
535 for (ResourceMap::iterator resIter = resMap_.begin();
536 resIter != resMap_.end(); resIter++) {
537
538 const FunctionUnit* fu =
539 dynamic_cast<const FunctionUnit*>((*resIter).first);
540 if (fu == NULL){
541 throw InvalidData(
542 __FILE__, __LINE__, __func__,
543 "Broker has other resource then FU registered!");
544 }
545
546 SchedulingResource* fuResource = (*resIter).second;
547
548 for (int i = 0; i < fu->portCount(); i++) {
549 Port* port = fu->port(i);
550 if (port->inputSocket() != NULL) {
551 SchedulingResource& depRes =
552 mapper.resourceOf(*port->inputSocket());
553 fuResource->addToDependentGroup(0, depRes);
554 }
555 }
556
557 int fuCount = mapper.resourceCount(*fu);
558 for (int i = 0; i < fuCount; i++) {
559 SchedulingResource* depRes = &mapper.resourceOf(*fu, i);
560 if (depRes->isExecutionPipelineResource()){
561 fuResource->addToDependentGroup(1, *depRes);
562 break;
563 }
564 }
565 }
566}
#define __func__
#define abortWithError(message)
#define assert(condition)
#define debugLogRM(__X)
static bool containsKey(const ContainerType &aContainer, const KeyType &aKey)
std::string errorMessageStack(bool messagesOnly=false) const
Definition Exception.cc:138
std::pair< bool, const TTAMachine::FunctionUnit * > findDstFUOfMove(const MoveNode &node, const TTAMachine::FunctionUnit *resFU, DataDependenceGraph::NodeSet &processedInputNodes) const
Definition FUBroker.cc:37
std::set< GraphNode *, typename GraphNode::Comparator > NodeSet
Definition Graph.hh:53
virtual void setupResourceLinks(const ResourceMapper &mapper) override
virtual int latestCycle(int cycle, const MoveNode &node, const TTAMachine::Bus *bus, const TTAMachine::FunctionUnit *srcFU, const TTAMachine::FunctionUnit *dstFU, int immWriteCycle, const TTAMachine::ImmediateUnit *immu, int immRegIndex) const override
virtual void buildResources(const TTAMachine::Machine &target) override
virtual bool isApplicable(const MoveNode &node, const TTAMachine::Bus *preAssigndBus=0) const override
virtual void assign(int cycle, MoveNode &node, SchedulingResource &res, int immWriteCycle, int immRegIndex) override
InputFUBroker(std::string, unsigned int initiationInterval=0)
virtual bool isAlreadyAssigned(int cycle, const MoveNode &node, const TTAMachine::Bus *preassignedBus) const override
virtual void unassign(MoveNode &node) override
virtual int earliestCycle(int cycle, const MoveNode &node, const TTAMachine::Bus *bus, const TTAMachine::FunctionUnit *srcFU, const TTAMachine::FunctionUnit *dstFU, int immWriteCycle, const TTAMachine::ImmediateUnit *immu, int immRegIndex) const override
virtual SchedulingResourceSet allAvailableResources(int cycle, const MoveNode &node, const TTAMachine::Bus *bus, const TTAMachine::FunctionUnit *srcFU, const TTAMachine::FunctionUnit *dstFU, int immWriteCycle, const TTAMachine::ImmediateUnit *immu, int immRegIndex) const override
virtual ~InputFUBroker()
virtual void assign(const int cycle, MoveNode &node) override
virtual void unassign(const int cycle, MoveNode &node) override
virtual bool canAssign(const int cycle, const MoveNode &node) const override
virtual bool isAvailable(const int cycle) const override
static void addAnnotatedFUs(std::set< TCEString > &candidateFUs, const TTAProgram::Move &m, TTAProgram::ProgramAnnotation::Id id)
static bool containsKey(const MapType &aMap, const KeyType &aKey)
int cycle() const
Definition MoveNode.cc:421
bool isMove() const
bool isDestinationOperation() const
TTAProgram::Move & move()
ProgramOperation & destinationOperation(unsigned int index=0) const
virtual TCEString name() const
Definition Operation.cc:93
int inputMoveCount() const
MoveNode & inputMove(int index) const
void addResource(const TTAMachine::MachinePart &mp, SchedulingResource *res)
MoveResMap assignedResources_
SchedulingResource * resourceOf(const TTAMachine::MachinePart &mp) const
unsigned int instructionIndex(unsigned int) const
const ResourceMapper & resourceMapper() const
bool hasResource(const SchedulingResource &r) const
void setResourceMapper(const ResourceMapper &mapper)
unsigned int initiationInterval_
bool hasResourceOf(const TTAMachine::MachinePart &mp) const
virtual const TTAMachine::MachinePart & machinePartOf(const SchedulingResource &r) const
ResourceMap resMap_
SchedulingResource & resourceOf(const TTAMachine::MachinePart &mp, int index=0) const
int resourceCount(const TTAMachine::MachinePart &mp) const
void insert(SchedulingResource &resource)
virtual void addToDependentGroup(const int group, SchedulingResource &resource)
virtual bool isInputFUResource() const
virtual bool isExecutionPipelineResource() const
static std::string stringToLower(const std::string &source)
virtual TCEString name() const
SpecialRegisterPort * returnAddressPort() const
virtual bool isTriggering() const
Definition FUPort.cc:182
virtual HWOperation * operation(const std::string &name) const
virtual int operationCount() const
virtual bool hasOperationLowercase(const std::string &name) const
virtual HWOperation * operationLowercase(const std::string &name) const
virtual BaseFUPort * port(const std::string &name) const
virtual FUPort * port(int operand) const
ComponentType * item(int index) const
virtual FunctionUnitNavigator functionUnitNavigator() const
Definition Machine.cc:380
virtual ControlUnit * controlUnit() const
Definition Machine.cc:345
virtual Socket * inputSocket() const
Definition Port.cc:261
virtual int portCount() const
Definition Unit.cc:135
Terminal & destination() const
Definition Move.cc:323
void setDestination(Terminal *dst)
Definition Move.cc:333
@ ANN_REJECTED_UNIT_DST
Dst. unit rejected.
@ ANN_ALLOWED_UNIT_DST
Dst. unit candidate.
@ ANN_CONN_CANDIDATE_UNIT_DST
Dst. unit candidate.
virtual const TTAMachine::FunctionUnit & functionUnit() const
virtual Operation & hintOperation() const
void setProgramOperation(ProgramOperationPtr po)
virtual const TTAMachine::Port & port() const
ProgramOperationPtr programOperation() const
virtual int operationIndex() const
virtual const TTAMachine::FunctionUnit & functionUnit() const
Definition Terminal.cc:251
virtual bool isFUPort() const
Definition Terminal.cc:118