OpenASIP 2.2
Loading...
Searching...
No Matches
IUResource.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 IUResource.cc
26 *
27 * Implementation of prototype of Resource Model:
28 * implementation of the abstract IUResource.
29 *
30 * @author Vladimir Guzma 2006 (vladimir.guzma-no.spam-tut.fi)
31 * @note rating: red
32 */
33
34#include "IUResource.hh"
35#include "Application.hh"
36#include "Conversion.hh"
37#include "Move.hh"
38#include "SequenceTools.hh"
39#include "MoveNode.hh"
40#include "MathTools.hh"
41#include "TerminalImmediate.hh"
42#include "Machine.hh"
44
45/**
46 * Constructor defining resource name, register count and register width
47 *
48 * @param name Name of resource
49 * @param registers Number of registers in IU
50 * @param width Bit width of registers in immediate unit
51 * @param latency Latency of Immediate unit, defaults to 1 in TCE
52 * @param signExtension Indicates if IU is using Zero or Sign extend
53 */
55 const TTAMachine::Machine& mach,
56 const std::string& name,
57 const int registers,
58 const int width,
59 const int latency,
60 const bool signExtension,
61 unsigned int initiationInterval)
62 : SchedulingResource(name, initiationInterval),
63 registerCount_(registers), width_(width),
64 latency_(latency) , signExtension_(signExtension), machine_(mach) {
65 for (int i = 0; i < registerCount(); i++) {
67 resourceRecord_.push_back(vt);
68 }
69}
70
71/**
72 * Empty destructor
73 */
75 for (int i = 0; i < registerCount(); i++) {
77 }
78}
79
80/**
81 * Test if resource IUResource is used in given cycle
82 * @param cycle Cycle which to test
83 * @return True if any (at least one) register of IU is already used in cycle
84 */
85bool
86IUResource::isInUse(const int cycle) const {
87 int modCycle = instructionIndex(cycle);
88 for (int i = 0; i < registerCount(); i++) {
89 for (int j = 0;
90 j < static_cast<int>(resourceRecord_.at(i).size());
91 j++) {
92 int otherDef = resourceRecord_.at(i).at(j)->definition_;
93 int modOtherDef = instructionIndex(otherDef + latency_);
94 int otherUse = resourceRecord_.at(i).at(j)->use_;
95 int modOtherUse = instructionIndex(otherUse);
96
97 // no overlap in old.
98 if (modOtherUse >= modOtherDef) {
99 // ordinary comparison, use between old def and use?
100 if (modCycle >= modOtherDef && modCycle < modOtherUse) {
101 return true;
102 }
103 } else {
104 // before use before use, or after def of other
105 if (modCycle >= modOtherDef || modCycle <= modOtherUse) {
106 return true;
107 }
108 }
109 }
110 }
111 return false;
112}
113
114/**
115 * Test if resource IUResource is available
116 * @param cycle Cycle which to test
117 * @return False if all registers in IU are used in cycle
118 */
119bool
120IUResource::isAvailable(const int cycle) const {
121 return isAvailable(cycle, -1);
122}
123
124/**
125 * Test if resource IUResource is available
126 * @param cycle Cycle which to test
127 * @param register to test. If -1, any reg ok.
128 * @return False if all registers in IU are used in cycle
129 */
130bool
131IUResource::isAvailable(const int cycle, int immRegIndex) const {
132 int modCycle = instructionIndex(cycle);
133 for (int i = 0; i < registerCount(); i++) {
134 if (immRegIndex != -1 && i != immRegIndex) continue;
135 bool marker = false;
136 for (int j = 0 ;
137 j < static_cast<int>(resourceRecord_.at(i).size());
138 j++) {
139 int otherDef = resourceRecord_.at(i).at(j)->definition_;
140 int modOtherDef = instructionIndex(otherDef + latency_);
141 int otherUse = resourceRecord_.at(i).at(j)->use_;
142 int modOtherUse = instructionIndex(otherUse);
143
144 // no overlap in old.
145 if (modOtherUse >= modOtherDef) {
146 // ordinary comparison, use between old def and use?
147 if (modCycle > modOtherDef && modCycle < modOtherUse) {
148 marker = true;
149 break;
150 }
151 } else {
152 // before use before use, or after def of other
153 if (modCycle >= modOtherDef || modCycle <= modOtherUse) {
154 marker = true;
155 break;
156 }
157 }
158 }
159 // None of the intervals for registers overlapped cycle, register
160 // is available for use -> unit is available too
161 if (marker == false) {
162 return true;
163 }
164 }
165 return false;
166}
167
168/**
169 * Implementation of abstract method from base class.
170 * IUResource requires different api (definition and use cycle)
171 * This method is not to be used!
172 */
173
174void
175IUResource::assign(const int cycle, MoveNode& mn) {
176
178 int index = mn.move().source().index();
181 -1,cycle,nullptr);
182
183 resourceRecord_.at(index).push_back(rc);
184 return;
185 std::string msg = "IUResource: called assign with \'cycle\'";
186 msg += " and \'node\'. Use assign with \'defCycle\',";
187 msg += " \'useCycle\', \'node\' and \'index\' reference!";
188 abortWithError(msg);
189}
190
191/**
192 * Assign resource to given node for given cycle
193 * @param defCycle Cycle in which the value of immediate register will be
194 * written using instruction template
195 * @param useCycle Cycle in which the value of immediate register will be
196 * read by MoveNode
197 * @param node MoveNode that reads the immediate register
198 * @param index Will be used to return index of register assigned
199 */
200void
202 const int defCycle, const int useCycle, MoveNode& node, int& index) {
203
204 if (defCycle > useCycle) {
205 std::string msg =
206 "Long immediate definition cycle later than use cycle: ";
207 msg += Conversion::toString(defCycle);
208 msg += " > ";
209 msg += Conversion::toString(useCycle);
210 msg += "!";
211 throw ModuleRunTimeError(__FILE__, __LINE__, __func__, msg);
212 }
213 if ((useCycle - defCycle) < latency_) {
214 std::string msg = "Definition and use too close(";
215 msg += Conversion::toString(useCycle - defCycle) + "). ";
216 msg += name() + " has latency of " + Conversion::toString(latency_);
217 throw ModuleRunTimeError(__FILE__, __LINE__, __func__, msg);
218 }
219 int i = findAvailable(defCycle, useCycle, index);
220 if (i != -1) {
221 index = i;
224 defCycle,useCycle,static_cast<TTAProgram::TerminalImmediate*>(
225 node.move().source().copy()));
226 resourceRecord_.at(i).push_back(rc);
227 return;
228 }
229 std::string msg = "Assignment for immediate impossible!";
230 throw KeyNotFound(__FILE__, __LINE__, __func__, msg);
231}
232
233/**
234 * Unassign resource from given node for given cycle
235 * @param cycle Cycle in which immediate is read which we want
236 * unassign.
237 * @param node MoveNode to remove assignment from
238 */
239void
241
242 if (!node.move().source().isImmediateRegister()) {
243 std::string msg = "Trying to unassign move that is not immediate\
244 register read!";
245 throw KeyNotFound(__FILE__, __LINE__, __func__, msg);
246 }
247 // Find which register in given IU is assigned to node
248 int regIndex = node.move().source().index();
249 if (resourceRecord_.at(regIndex).size() == 0) {
250 std::string msg = "The register is not assigned!";
251 throw KeyNotFound(__FILE__, __LINE__, __func__, msg);
252 }
253 std::vector<ResourceRecordType*>::iterator itr =
254 resourceRecord_.at(regIndex).begin();
255 // From given IU register delete record about
256 // assignment to node and restore node source
257 while (itr != resourceRecord_.at(regIndex).end()) {
258 if (node.cycle() == (*itr)->use_) {
259 std::shared_ptr<TTAProgram::TerminalImmediate> originalTerminal =
260 ((*itr)->immediateValue_);
261 if (originalTerminal) {
262 TTAProgram::Terminal* toSet = originalTerminal->copy();
263 node.move().setSource(toSet);
264 }
265 delete *itr;
266 resourceRecord_.at(regIndex).erase(itr);
267
268 return;
269 }
270 itr++;
271 }
272 std::string msg = "Register is not assigned for given cycle!";
273 throw KeyNotFound(__FILE__, __LINE__, __func__, msg);
274}
275
276/**
277 * Implementation of abstract method from base class.
278 * IUResource requires different api (definition and use cycle)
279 * This method is not to be used!
280 */
281bool
282IUResource::canAssign(const int cycle, const MoveNode& mn) const {
283 if (mn.isMove()) {
284 return canAssignUse(cycle);
285 }
286 std::string msg = "IUResource: called canAssign with \'cycle\'";
287 msg += " and \'node\'. Use canAssign with \'defCycle\',";
288 msg += " \'useCycle\' and \'node\'!";
289 abortWithError(msg);
290 return false;
291}
292
293/**
294 * Checks that a immediate value can be read in the given cycle
295 */
296bool
297IUResource::canAssignUse(int useCycle) const {
298 for (int i = 0; i < relatedResourceGroupCount(); i++) {
299 for (int j = 0, count = relatedResourceCount(i); j < count; j++) {
300 SchedulingResource& relRes = relatedResource(i,j);
301 // related res is counted as modcycles.
302 if (relRes.isOutputPSocketResource()) {
303 if (!relRes.isInUse(instructionIndex(useCycle))) {
304 return true;
305 }
306 }
307 }
308 }
309 return false;
310}
311
312
313/**
314 * Return true if resource can be assigned for given resource in given cycle
315 * @param defCycle definition cycle
316 * @param useCycle use of register cycle
317 * @param node MoveNode to test
318 * @return true if node can be assigned to cycle
319 */
320bool
322 const int defCycle,
323 const int useCycle,
324 const MoveNode& node,
325 int immRegIndex) const {
326
327 if (defCycle > useCycle) {
328 return false;
329 }
330 if ((useCycle - defCycle) < latency_) {
331 return false;
332 }
333
334 MoveNode& mNode = const_cast<MoveNode&>(node);
335 if (!mNode.move().source().isImmediate()) {
336 return false;
337 }
338
340 static_cast<TTAProgram::TerminalImmediate*>(&mNode.move().source());
341 if (findAvailable(defCycle, useCycle, immRegIndex) != -1) {
343 signExtension_, *iTerm, machine_);
344 if (reqWidth > width_) {
345 return false;
346 }
347
348 for (int i = 0; i < relatedResourceGroupCount(); i++) {
349 for (int j = 0, count = relatedResourceCount(i); j < count; j++) {
350 SchedulingResource& relRes = relatedResource(i,j);
351 // related res is counted as modcycles.
352 if (relRes.isOutputPSocketResource()) {
353 if (!relRes.isInUse(instructionIndex(useCycle))) {
354 return true;
355 }
356 }
357 }
358 }
359 }
360 return false;
361}
362
363/**
364 * Allways return true
365 * @return true
366 */
367bool
369 return true;
370}
371
372/**
373 * Set the number of registers available in IU
374 * @param registers Number of registers in this particular IU
375 */
376void
377IUResource::setRegisterCount(const int registers) {
378 // We shell not provide API for decreasing size of existing IU
379 if (registers < registerCount()) {
380 throw InvalidData(__FILE__, __LINE__, __func__,
381 "Can not decrease number of registers in IMM unit!");
382 }
383 for (int i = registerCount_; i < registers; i++) {
385 resourceRecord_.push_back(vt);
386 }
387 registerCount_ = registers;
388}
389
390/**
391 * Get number of registers in IU
392 * @return Number of registers in IU
393 */
394int
396 return registerCount_;
397}
398
399/**
400 * Returns a constant that should be written to immediate register
401 * used by MoveNode in cycle
402 * @param cycle Cycle in which immediate register is read
403 * @param node MoveNode which is reading the register
404 * @return Long immediate constant that is expected to be in register
405 */
406std::shared_ptr<TTAProgram::TerminalImmediate>
408 MoveNode& testNode = const_cast<MoveNode&>(node);
409 if (!testNode.move().source().isImmediateRegister()) {
410 std::string msg = "Immediate register was not assigned!";
411 throw KeyNotFound(__FILE__, __LINE__, __func__, msg);
412 }
413 int regIndex = testNode.move().source().index();
414 for (int j = 0;
415 j < static_cast<int>(resourceRecord_.at(regIndex).size());
416 j++) {
417 if (node.cycle() == resourceRecord_.at(regIndex).at(j)->use_) {
418 // Test if cycle equal to use of value
419 // for register, if it is we return original terminal
420 return resourceRecord_.at(regIndex).at(j)->immediateValue_;
421 }
422 }
423 std::string msg = "Immediate register was not recorded in resource!";
424 throw KeyNotFound(__FILE__, __LINE__, __func__, msg);
425}
426/**
427 * Returns a cycle in which immediate register used by MoveNode is written
428 *
429 * @param node MoveNode which is reading the register
430 * @return cycle in which register is written, or -1 if not found.
431 */
432int
434
435 MoveNode& testNode = const_cast<MoveNode&>(node);
436 if (!testNode.move().source().isImmediateRegister()) {
437 return -1;
438 //std::string msg = "Immediate register was not assigned!";
439 //throw KeyNotFound(__FILE__, __LINE__, __func__, msg);
440 }
441 int regIndex = testNode.move().source().index();
442 for (int j = 0;
443 j < static_cast<int>(resourceRecord_.at(regIndex).size());
444 j++) {
445 if (node.cycle() == resourceRecord_.at(regIndex).at(j)->use_) {
446 // Test if cycle equal to use of value
447 // for register, if it is we return definition cycle
448 return resourceRecord_.at(regIndex).at(j)->definition_;
449 }
450 }
451 return -1;
452 //std::string msg = "Immediate register was not recorded in resource!";
453 //throw KeyNotFound(__FILE__, __LINE__, __func__, msg);
454}
455/**
456 * Tests if all referred resources in dependent groups are of
457 * proper types
458 * @return true If all resources in dependent groups are
459 * Immediate Registers
460 */
461bool
463 return true;
464}
465
466/**
467 * Tests if all referred resources in related groups are of
468 * proper types
469 * @return true If all resources in related groups are
470 * Instruction Templates or P-Sockets
471 */
472bool
474 for (int i = 0; i < relatedResourceGroupCount(); i++) {
475 for (int j = 0, count = relatedResourceCount(i); j < count; j++) {
479 return false;
480 }
481 }
482 }
483 return true;
484}
485
486/**
487 * Internal helper method, find available register for given pair of
488 * definition and use cycles.
489 */
490int
492 const int defCycle, const int useCycle, int immRegIndex) const {
493 int modDef = instructionIndex(defCycle + latency_);
494 int modUse = instructionIndex(useCycle);
495 for (int i = 0; i < registerCount(); i++) {
496 if (immRegIndex != -1 && i != immRegIndex) continue;
497 bool marker = false;
498 const ResourceRecordVectorType& resVec = resourceRecord_.at(i);
499 int size = resVec.size();
500 for (int j = 0; j < size; j++) {
501 int otherDef = resVec[j]->definition_;
502 int modOtherDef = instructionIndex(otherDef + latency_);
503 int otherUse = resVec[j]->use_;
504 int modOtherUse = instructionIndex(otherUse);
505
506 // no overlap in old.
507 if (modOtherUse >= modOtherDef) {
508 // ordinary comparison, use between old def and use?
509 if (modUse >= modOtherDef && modUse <= modOtherUse) {
510 marker = true;
511 break;
512 }
513
514 if (modDef >= modOtherDef && modDef <= modOtherUse) {
515 marker = true;
516 break;
517 }
518
519 } else {
520 // before use before use, or after def of other
521 if (modUse >= modOtherDef || modUse <= modOtherUse) {
522 marker = true;
523 break;
524 }
525
526 if (modDef >= modOtherDef || modDef <= modOtherUse) {
527 marker = true;
528 break;
529 }
530 }
531
532 // other def between these. case when other completely
533 // iside this range. can be detected be either other
534 // use or other def. checks above handle cases where
535 // tries to def, def, use, use
536
537 if (modDef <= modUse) {
538 // no overlap in this. ordinary check.
539 if (modOtherDef >= modDef && modOtherDef <= modUse) {
540 marker = true;
541 break;
542 }
543 } else {
544 // we have overlap.
545
546 if (modOtherDef >= modDef || modOtherDef <= modUse) {
547 marker = true;
548 break;
549 }
550 }
551 }
552 if (marker == false) {
553 return i;
554 }
555 }
556 return -1;
557}
558
559void
561 for (int i = 0; i < registerCount(); i++) {
562 for (int j = 0;
563 j < static_cast<int>(resourceRecord_.at(i).size()); j++) {
564 ResourceRecordType* rec = resourceRecord_.at(i).at(j);
565 rec->immediateValue_ = NULL;
566 }
567 }
568}
569
570/**
571 * Returns a width of registers in Immediate Unit.
572 *
573 * @return Width of registers in Immediate Unit.
574 */
575int
577 return width_;
578}
579
580/**
581 * Clears bookkeeping of the scheduling resource.
582 *
583 * After this call the state of the resource should be identical to a
584 * newly-created and initialized resource.
585 */
586void
589 for (int i = 0; i < registerCount(); i++) {
591 }
592}
593
595 int definition, int use, TTAProgram::TerminalImmediate* val) :
596 definition_(definition), use_(use), immediateValue_(val) {}
#define __func__
#define abortWithError(message)
#define assert(condition)
static std::string toString(const T &source)
virtual bool canAssign(const int, const MoveNode &) const override
virtual void unassign(const int cycle, MoveNode &node) override
virtual bool validateDependentGroups() override
virtual void assign(const int cycle, MoveNode &node) override
void setRegisterCount(const int registers)
virtual bool validateRelatedGroups() override
std::vector< ResourceRecordType * > ResourceRecordVectorType
virtual bool isIUResource() const override
std::shared_ptr< TTAProgram::TerminalImmediate > immediateValue(const MoveNode &node) const
int registerCount_
const TTAMachine::Machine & machine_
virtual bool isAvailable(const int cycle, int immRegIndex) const
void clearOldResources()
virtual bool isInUse(const int cycle) const override
Definition IUResource.cc:86
bool signExtension_
void clear() override
virtual ~IUResource()
Definition IUResource.cc:74
int findAvailable(const int defCycle, const int useCycle, int immRegIndex) const
int width() const
int immediateWriteCycle(const MoveNode &node) const
bool canAssignUse(int useCycle) const
std::vector< ResourceRecordVectorType > resourceRecord_
int registerCount() const
IUResource(const TTAMachine::Machine &mach, const std::string &name, const int registers, const int width, const int latency, const bool signExtension, unsigned int initiationInterval=0)
Definition IUResource.cc:54
static int requiredImmediateWidth(bool signExtension, const TTAProgram::TerminalImmediate &source, const TTAMachine::Machine &mach)
int cycle() const
Definition MoveNode.cc:421
bool isMove() const
TTAProgram::Move & move()
virtual SchedulingResource & relatedResource(const int group, const int index) const
int instructionIndex(int cycle) const
virtual bool isITemplateResource() const
int relatedResourceCount(const int group) const
virtual bool isInputPSocketResource() const
virtual const std::string & name() const
virtual bool isOutputPSocketResource() const
virtual int relatedResourceGroupCount() const
virtual bool isInUse(const int cycle) const =0
static void deleteAllItems(SequenceType &aSequence)
void setSource(Terminal *src)
Definition Move.cc:312
Terminal & source() const
Definition Move.cc:302
virtual int index() const
Definition Terminal.cc:274
virtual Terminal * copy() const =0
virtual bool isImmediateRegister() const
Definition Terminal.cc:97
virtual bool isImmediate() const
Definition Terminal.cc:63
std::shared_ptr< TTAProgram::TerminalImmediate > immediateValue_
ResourceRecordType(int definition, int use, TTAProgram::TerminalImmediate *val)