OpenASIP 2.2
Loading...
Searching...
No Matches
OutputFUBroker.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 OutputFUBroker.cc
26 *
27 * Implementation of OutputFUBroker 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 "OutputFUBroker.hh"
35#include "OutputFUResource.hh"
36#include "ResourceMapper.hh"
37#include "ControlUnit.hh"
38#include "Machine.hh"
39#include "Operation.hh"
41#include "FUPort.hh"
42#include "HWOperation.hh"
43#include "ProgramOperation.hh"
44#include "MapTools.hh"
45#include "AssocTools.hh"
46#include "ProgramAnnotation.hh"
47#include "TCEString.hh"
48#include "TerminalFUPort.hh"
49#include "MoveNodeSet.hh"
51#include "ResourceManager.hh"
52#include "Move.hh"
55#include "MoveGuard.hh"
56#include "Guard.hh"
57
58using std::string;
59using namespace TTAMachine;
60using namespace TTAProgram;
61
62/**
63 * Constructor.
64 */
65OutputFUBroker::OutputFUBroker(std::string name, unsigned int initiationInterval) :
66 FUBroker(name, initiationInterval) {
67}
68
69/**
70 * Destructor.
71 */
74
75/**
76 * Return all resources managed by this broker that can be assigned to
77 * the given node in the given cycle.
78 *
79 * @param cycle Cycle.
80 * @param node Node.
81 * @return All resources managed by this broker that can be assigned to
82 * the given node in the given cycle.
83 */
86 int cycle,
87 const MoveNode& node,
88 const TTAMachine::Bus*,
89 const TTAMachine::FunctionUnit* srcFU,
90 const TTAMachine::FunctionUnit*, int,
92 int) const {
93
94 int modCycle = instructionIndex(cycle);
95 if (!isApplicable(node)) {
96 string msg = "Broker not capable of assigning resources to node: "
97 + node.toString();
98 throw ModuleRunTimeError(__FILE__, __LINE__, __func__, msg);
99 }
100
101 const TTAMachine::FunctionUnit* foundFU = srcFU;
102 int opIndex = -1;
103 ProgramOperation* PO = nullptr;
104 SchedulingResourceSet resourceSet;
105 ResourceMap::const_iterator resIter = resMap_.begin();
106
107 const Operation* op = nullptr;
108
109 if (node.move().source().isFUPort()) {
110 TerminalFUPort& src =
111 static_cast<TerminalFUPort&>(node.move().source());
112
113 if (dynamic_cast<const SpecialRegisterPort*>(&src.port()) != NULL) {
114 // only gcu applies
115 while (resIter != resMap_.end()) {
116 const ControlUnit* gcu =
117 dynamic_cast<const ControlUnit*>((*resIter).first);
118 if (gcu != NULL) {
119 if ((*resIter).second->isAvailable(modCycle)) {
120 resourceSet.insert(*(*resIter).second);
121 }
122 return resourceSet;
123 }
124 resIter++;
125 }
126 abortWithError("No GCU found!");
127 }
128
129 op = &src.hintOperation();
130 opIndex = src.operationIndex();
131
132 // check if a unit has already been assigned to some node
133 // of the same operation and use it.
134 if (node.isSourceOperation()) {
135 PO = &node.sourceOperation();
136 } else {
137 assert(false);
138 }
139 } else {
140 // port guard?
141 PO = &node.guardOperation();
142 opIndex = PO->outputIndexFromGuardOfMove(node);
143 op = &PO->operation();
144 }
145
146 auto a = findFUOfPO(*PO, foundFU);
147 if (a.first) {
148 foundFU = a.second;
149 } else { // conflicting FUs, cannot schedule
150 return SchedulingResourceSet();
151 }
152
153 if (foundFU) {
154 OutputFUResource& fuRes =
155 static_cast<OutputFUResource&>(*resourceOf(*foundFU));
156 // Find what is the port on a new FU for given
157 // operation index. Find a socket for testing.
158 HWOperation* hwOp = foundFU->operation(op->name());
159 assert(hwOp != nullptr);
160 Port* resultPort = hwOp->port(opIndex);
161 assert (resultPort != nullptr);
162 if (fuRes.canAssign(cycle, node, *resultPort)) {
163 resourceSet.insert(fuRes);
164 }
165 return resourceSet;
166 }
167
168 // check if the move has a candidate FU set which limits the
169 // choice of FU for the node
170 std::set<TCEString> candidateFUs;
171 std::set<TCEString> allowedFUs;
172 std::set<TCEString> rejectedFUs;
173
174 // TODO: why is this in loop for operands but not in loop for results?
175 // do multiple return values break or work?
177 candidateFUs, node.move(),
180 allowedFUs, node.move(),
183 rejectedFUs, node.move(),
185
186 // find units that support operation and are available at given cycle
187 while (resIter != resMap_.end()) {
188 const FunctionUnit* unit =
189 static_cast<const FunctionUnit*>((*resIter).first);
190 if (srcFU != NULL && unit != srcFU) {
191 debugLogRM(TCEString("Skipping unit") << unit->name()
192 << " because it's not the pre-set one: "
193 << srcFU->name());
194 resIter++;
195 continue;
196 }
197 // in case the unit is limited by a candidate set, skip FUs that are
198 // not in it
199 debugLogRM(TCEString("checking ") << unit->name());
200 if (candidateFUs.size() > 0 &&
201 !AssocTools::containsKey(candidateFUs, unit->name())) {
202 ++resIter;
203 continue;
204 }
205 if (allowedFUs.size() > 0 &&
206 !AssocTools::containsKey(allowedFUs, unit->name())) {
208 TCEString("skipped ") << unit->name() << " because it was not"
209 " in the allowed set. The set contents: ");
210 for (auto allowedUnit : allowedFUs)
211 debugLogRM(allowedUnit + "\n");
212 ++resIter;
213 continue;
214 }
215
216 if (AssocTools::containsKey(rejectedFUs, unit->name())) {
218 TCEString("skipped ") << unit->name() << " because it was"
219 " in the rejected set.");
220 ++resIter;
221 continue;
222 }
223
224 if (unit->hasOperation(op->name())) {
225 OutputFUResource& fuRes =
226 static_cast<OutputFUResource&>(*resourceOf(*unit));
227 // Find what is the port on a new FU for given
228 // operation index. Find a socket for testing.
229 HWOperation* hwOp = unit->operation(op->name());
230 Port* resultPort = hwOp->port(opIndex);
231 if (fuRes.canAssign(cycle, node, *resultPort)) {
232 debugLogRM("testing " + op->name());
233 resourceSet.insert(*(*resIter).second);
234 } else {
235 debugLogRM("could not assign the fuRes to it.");
236 }
237 } else {
238 debugLogRM(TCEString("does not have operation ") + op->name());
239 }
240 resIter++;
241 }
242 return resourceSet;
243}
244
245/**
246 * Mark given resource as in use for the given node, and assign the
247 * corresponding machine part (if applicable) to the node's move.
248 *
249 * If the node is already assigned to given resource, this method does
250 * nothing.
251 *
252 * @param cycle Cycle.
253 * @param node Node to assign.
254 * @param res Resource representing Output of FU
255 * @exception WrongSubclass If this broker does not recognise the given
256 * type of resource.
257 * @exception InvalidParameters If he given resource cannot be assigned to
258 * given node or no corresponding machine part is found.
259 */
260void
262 int cycle, MoveNode& node, SchedulingResource& res, int, int) {
263 // TODO: this breaks execpipeline
264// cycle = instructionIndex(cycle);
265 if (!isApplicable(node)) {
266 string msg = "Broker not capable of assigning resources to node!";
267 throw WrongSubclass(__FILE__, __LINE__, __func__, msg);
268 }
269
270 if (!hasResource(res)) {
271 string msg = "Broker does not contain given resource.";
272 throw InvalidData(__FILE__, __LINE__, __func__, msg);
273 }
274 OutputFUResource& fuRes = static_cast<OutputFUResource&>(res);
275 Move& move = const_cast<MoveNode&>(node).move();
276
277 int opIndex = -1;
278 const Operation* op = nullptr;
279 TerminalFUPort* src = dynamic_cast<TerminalFUPort*>(&move.source());
280 if (src != nullptr &&
281 dynamic_cast<const SpecialRegisterPort*>(&src->port()) != NULL) {
282 const ControlUnit* gcu =
283 dynamic_cast<const ControlUnit*>(&machinePartOf(res));
284 if (gcu != NULL) {
285 // output of GCU is ra read
286 TerminalFUPort* newSrc =
288 move.setSource(newSrc);
289 Socket* outputSocket = newSrc->port().outputSocket();
290
291 if (outputSocket == NULL) {
292 throw InvalidData(
293 __FILE__, __LINE__, __func__, "GCU is missing RA port - "
294 "socket connection!");
295 }
296 assignedResources_.insert(
297 std::pair<const MoveNode*, SchedulingResource*>(
298 &node, &fuRes));
299 return;
300 } else {
302 "GCU required but tried to assign something else!");
303 }
304 }
305
306 if (node.isSourceOperation()) {
307
308 opIndex = src->operationIndex();
309 op = &src->hintOperation();
310 const FunctionUnit& unit =
311 static_cast<const FunctionUnit&>(machinePartOf(res));
312 HWOperation* hwOp = unit.operation(op->name());
313 TerminalFUPort* newSrc = new TerminalFUPort(*hwOp, opIndex);
314 move.setSource(newSrc);
315 fuRes.assign(cycle, node);
316 assignedResources_.insert(
317 std::pair<const MoveNode*, SchedulingResource*>(
318 &node, &fuRes));
319 } else {
320 assert(node.isGuardOperation());
321 ProgramOperation& po = node.guardOperation();
322 opIndex = po.outputIndexOfMove(node);
323 op = &po.operation();
324
325 fuRes.assign(cycle, node);
326 assignedResources_.insert(
327 std::pair<const MoveNode*, SchedulingResource*>(
328 &node, &fuRes));
329 }
330}
331
332/**
333 * Free the resource type managed by this broker and unassign it from
334 * given node.
335 *
336 * If this broker is not applicable to the given node, or the node is
337 * not assigned a resource of the managed type, this method does
338 * nothing.
339 *
340 * @param node Node.
341 */
342void
344 if (!isApplicable(node)) {
345 return;
346 }
348
349 TTAProgram::Move& move = node.move();
350 const TerminalFUPort* src = dynamic_cast<const TerminalFUPort*>(&move.source());
351 if (src) {
352 const TerminalFUPort* src = dynamic_cast<const TerminalFUPort*>(&move.source());
353 assert(src);
355 const ControlUnit* gcu =
356 dynamic_cast<const ControlUnit*>(&machinePartOf(res));
357
358 // not ra read? unassign from fu
359 if (gcu == NULL) {
360 OutputFUResource* fuRes = dynamic_cast<OutputFUResource*>(&res);
361 fuRes->unassign(node.cycle(), node);
362 }
363 } else {
364 if (node.isGuardOperation()) {
365 ProgramOperation& gop = node.guardOperation();
366 SchedulingResource& res = *resourceOf(*gop.fuFromOutMove(node));
367 res.unassign(node.cycle(), node);
368 }
369 }
370 // removed from assigned resources also if ra read
371 assignedResources_.erase(&node);
372 }
373}
374
375/**
376 * Return the earliest cycle, starting from given cycle, where a
377 * resource of the type managed by this broker can be assigned to the
378 * given node.
379 *
380 * @param cycle Cycle.
381 * @param node Node.
382 * @return The earliest cycle, starting from given cycle, where a
383 * resource of the type managed by this broker can be assigned to the
384 * given node.
385 */
386int
388 const TTAMachine::Bus*,
390 const TTAMachine::FunctionUnit*, int,
392 int) const {
393 abortWithError("Not implemented.");
394 return -1;
395}
396
397/**
398 * Return the latest cycle, starting from given cycle, where a
399 * resource of the type managed by this broker can be assigned to the
400 * given node.
401 *
402 * @param cycle Cycle.
403 * @param node Node.
404 * @return The latest cycle, starting from given cycle, where a
405 * resource of the type managed by this broker can be assigned to the
406 * given node.
407 */
408int
411 const TTAMachine::FunctionUnit*,int,
413 int) const {
414 abortWithError("Not implemented.");
415 return -1;
416}
417
418/**
419 * Return true if the given node is already assigned a resource of the
420 * type managed by this broker, and the assignment appears valid (that
421 * is, the broker has marked that resource as in use in the given
422 * cycle).
423 *
424 * @param cycle Cycle. not used.
425 * @param node Node.
426 * @return True if the given node is already assigned a resource of the
427 * type managed by this broker, and the assignment appears valid (that
428 * is, the broker has marked that resource as in use in the given
429 * cycle).
430 */
431bool
433 int cycle, const MoveNode& node, const TTAMachine::Bus*) const {
434 cycle = instructionIndex(cycle);
435 Terminal& src = const_cast<MoveNode&>(node).move().source();
436 if (src.isFUPort()) {
437 const FunctionUnit& fu = src.functionUnit();
438 if (hasResourceOf(fu)) {
440 return true;
441 }
442 }
443 }
444 if (node.isGuardOperation()) {
445 const FunctionUnit* fu = node.guardOperation().fuFromOutMove(node);
446 if (fu && hasResourceOf(*fu)) {
448 return true;
449 }
450 }
451 }
452 return false;
453}
454
455/**
456 * Return true if the given node needs a resource of the type managed
457 * by this broker, false otherwise.
458 *
459 * @param node Node.
460 * @return True if the given node needs a resource of the type managed
461 * by this broker, false otherwise.
462 */
463bool
465 const MoveNode& node, const TTAMachine::Bus*) const {
466 if (!node.isMove()) {
467 return false;
468 }
469 Move& move = const_cast<MoveNode&>(node).move();
470 if (move.source().isFUPort() ||
471 (!move.isUnconditional() &&
472 dynamic_cast<const TTAMachine::PortGuard*>(&move.guard().guard()))) {
473 return true;
474 } else {
475 return false;
476 }
477}
478
479/**
480 * Build all resource objects of the controlled type required to model
481 * scheduling resources of the given target processor.
482 *
483 * This method cannot set up the resource links (dependent and related
484 * resources) of the constructed resource objects.
485 *
486 * @param target Target machine.
487 */
488void
490
491 std::map<const TTAMachine::FunctionUnit*,int> nopWeights;
492
494 for (int i = 0; i < navi.count(); i++) {
495 FunctionUnit* fu = navi.item(i);
496 OutputFUResource* fuResource = new OutputFUResource(
497 fu->name(), fu->operationCount(), nopWeights[fu]);
498 ResourceBroker::addResource(*fu, fuResource);
499 }
500 ControlUnit* gcu = target.controlUnit();
501 OutputFUResource* fuResource = new OutputFUResource(
502 gcu->name(), gcu->operationCount(),0);
503 ResourceBroker::addResource(*gcu, fuResource);
504}
505
506/**
507 * Complete resource initialisation by creating the references to
508 * other resources due to a dependency or a relation. Use the given
509 * resource mapper to lookup dependent and related resources using
510 * machine parts as keys.
511 *
512 * @param mapper Resource mapper.
513 */
514void
516
517 setResourceMapper(mapper);
518
519 for (ResourceMap::iterator resIter = resMap_.begin();
520 resIter != resMap_.end(); resIter++) {
521
522 const FunctionUnit* fu =
523 dynamic_cast<const FunctionUnit*>((*resIter).first);
524
525 SchedulingResource* fuResource = (*resIter).second;
526 for (int i = 0; i < fu->portCount(); i++) {
527 Port* port = fu->port(i);
528 if (port->outputSocket() != NULL) {
529 try {
530 SchedulingResource& depRes =
531 mapper.resourceOf(*port->outputSocket());
532 fuResource->addToDependentGroup(0, depRes);
533 } catch (const KeyNotFound& e) {
534 std::string msg = "OutputFUBroker: finding ";
535 msg += " resource for Socket ";
536 msg += " failed with error: ";
537 msg += e.errorMessageStack();
538 throw KeyNotFound(
539 __FILE__, __LINE__, __func__, msg);
540 }
541 }
542 }
543
544 int fuCount = mapper.resourceCount(*fu);
545 for (int i = 0; i < fuCount; i++) {
546 SchedulingResource* depRes = &mapper.resourceOf(*fu, i);
547 if (depRes->isExecutionPipelineResource()){
548 fuResource->addToDependentGroup(1, *depRes);
549 break;
550 }
551 }
552 }
553 // todo: dependent execution pipeline to support trigger-on-result
554}
#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 * > findFUOfPO(ProgramOperation &po, const TTAMachine::FunctionUnit *resFU) const
Definition FUBroker.cc:77
static void addAnnotatedFUs(std::set< TCEString > &candidateFUs, const TTAProgram::Move &m, TTAProgram::ProgramAnnotation::Id id)
static bool containsKey(const MapType &aMap, const KeyType &aKey)
bool isGuardOperation() const
Definition MoveNode.cc:181
int cycle() const
Definition MoveNode.cc:421
bool isMove() const
ProgramOperation & sourceOperation() const
Definition MoveNode.cc:453
std::string toString() const
Definition MoveNode.cc:576
ProgramOperation & guardOperation() const
Definition MoveNode.cc:479
TTAProgram::Move & move()
bool isSourceOperation() const
Definition MoveNode.cc:168
virtual TCEString name() const
Definition Operation.cc:93
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 void assign(int cycle, MoveNode &node, SchedulingResource &res, int immWriteCycle, int immRegIndex) override
virtual bool isAlreadyAssigned(int cycle, const MoveNode &node, const TTAMachine::Bus *preassignedBus) const override
virtual void unassign(MoveNode &node) override
virtual bool isApplicable(const MoveNode &node, const TTAMachine::Bus *b=0) const override
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 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
OutputFUBroker(std::string, unsigned int initiationInterval=0)
virtual void buildResources(const TTAMachine::Machine &target) override
virtual ~OutputFUBroker()
virtual bool canAssign(const int cycle, const MoveNode &node) const override
virtual void unassign(const int cycle, MoveNode &node) override
virtual void assign(const int cycle, MoveNode &node) override
const Operation & operation() const
int outputIndexFromGuardOfMove(const MoveNode &node) const
const TTAMachine::FunctionUnit * fuFromOutMove(const MoveNode &outputNode) const
int outputIndexOfMove(const MoveNode &mn) const
void addResource(const TTAMachine::MachinePart &mp, SchedulingResource *res)
MoveResMap assignedResources_
SchedulingResource * resourceOf(const TTAMachine::MachinePart &mp) const
unsigned int instructionIndex(unsigned int) const
bool hasResource(const SchedulingResource &r) const
void setResourceMapper(const ResourceMapper &mapper)
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 void unassign(const int cycle, MoveNode &node)=0
virtual bool isExecutionPipelineResource() const
virtual TCEString name() const
SpecialRegisterPort * returnAddressPort() const
virtual HWOperation * operation(const std::string &name) const
virtual int operationCount() const
virtual bool hasOperation(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 * outputSocket() const
Definition Port.cc:281
virtual int portCount() const
Definition Unit.cc:135
const TTAMachine::Guard & guard() const
Definition MoveGuard.cc:86
void setSource(Terminal *src)
Definition Move.cc:312
MoveGuard & guard() const
Definition Move.cc:345
bool isUnconditional() const
Definition Move.cc:154
Terminal & source() const
Definition Move.cc:302
@ ANN_REJECTED_UNIT_SRC
Src. unit rejected.
@ ANN_CONN_CANDIDATE_UNIT_SRC
Src. unit candidate.
@ ANN_ALLOWED_UNIT_SRC
Candidate units can be passed for resource manager for choosing the source/destination unit of the mo...
virtual const TTAMachine::FunctionUnit & functionUnit() const
virtual Operation & hintOperation() const
virtual const TTAMachine::Port & port() const
virtual int operationIndex() const
virtual const TTAMachine::FunctionUnit & functionUnit() const
Definition Terminal.cc:251
virtual bool isFUPort() const
Definition Terminal.cc:118