OpenASIP 2.2
Loading...
Searching...
No Matches
RegisterFile.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 RegisterFile.cc
26 *
27 * Implementation of RegisterFile class.
28 *
29 * @author Lasse Laasonen 2003 (lasse.laasonen-no.spam-tut.fi)
30 * @note reviewed 17 Jun 2004 by jn, pj, jm, ll
31 * @note rating: red
32 */
33
34#include "RegisterFile.hh"
35#include "Machine.hh"
36#include "Port.hh"
37#include "Guard.hh"
38#include "ControlUnit.hh"
39#include "MOMTextGenerator.hh"
40#include "Application.hh"
41#include "ObjectState.hh"
42
43using std::string;
44using boost::format;
45
46namespace TTAMachine {
47
48// initialization of static data members
49const string RegisterFile::OSNAME_REGISTER_FILE = "reg_file";
50const string RegisterFile::OSKEY_TYPE = "type";
51const string RegisterFile::OSVALUE_NORMAL = "normal";
52const string RegisterFile::OSVALUE_RESERVED = "reserved";
53const string RegisterFile::OSVALUE_VOLATILE = "volatile";
54const string RegisterFile::OSKEY_MAX_READS = "max_r";
55const string RegisterFile::OSKEY_MAX_WRITES = "max_w";
56const string RegisterFile::OSKEY_GUARD_LATENCY = "g_latency";
57const string RegisterFile::OSKEY_ZERO_REGISTER = "zero_register";
58
59/**
60 * Constructor.
61 *
62 * @param name Name of the register file.
63 * @param size Number of registers in the register file.
64 * @param width Bit width of the registers in the register file.
65 * @param maxReads Maximum simultaneous reads of a register.
66 * @param maxWrites Maximum simultaneous writes of a register.
67 * @param maxRw Maximum simultaneous reads of a register in the same cycle
68 * the register is written.
69 * @param type Type of the register file, see RegisterFile::Type.
70 * @exception OutOfRange If some of the given parameters has an illegal
71 * value.
72 * @exception InvalidName If the given name is not a valid component name.
73 */
75 const std::string& name, unsigned int size, unsigned int width,
76 unsigned int maxReads, unsigned int maxWrites, unsigned int guardLatency,
77 Type type, bool zeroRegister)
78 : BaseRegisterFile(name, size, width),
79 maxReads_(0),
80 maxWrites_(0),
81 guardLatency_(0),
82 type_(type),
83 zeroRegister_(zeroRegister) {
87}
88
89/**
90 * Constructor.
91 *
92 * Loads the state of the register file from the given ObjectState instance.
93 * Does not load references to other components.
94 *
95 * @param state The ObjectState from which the name is taken.
96 * @exception ObjectStateLoadingException If the given ObjectState tree is
97 * invalid.
98 */
100 : BaseRegisterFile(state),
101 maxReads_(0),
102 maxWrites_(0),
103 guardLatency_(0),
104 type_(NORMAL),
105 zeroRegister_(false) {
107}
108
109/**
110 * Destructor.
111 */
115
116
117/**
118 * Returns the number of ports that can read a register all in same cycle.
119 *
120 * @return The number of ports that can read a register all in same cycle.
121 */
122int
127
128
129/**
130 * Returns the number of ports that can write a register all in same cycle.
131 *
132 * @return The number of ports that can write a register all in same cycle.
133 */
134int
139
140
141/**
142 * Returns the type of the register file.
143 *
144 * @return Type of the register file.
145 */
148 return type_;
149}
150
151
152/**
153 * Returns true if the type of the register file is normal, otherwise false.
154 *
155 * @return True if the type of the register file is normal, otherwise false.
156 */
157bool
159 return (type_ == NORMAL);
160}
161
162
163/**
164 * Returns true if the type of the register file is volatile,
165 * otherwise false.
166 *
167 * @return True if the type of the register file is volatile,
168 * otherwise false.
169 */
170bool
172 return (type_ == VOLATILE);
173}
174
175
176/**
177 * Returns true if the type of the register file is reserved,
178 * otherwise false.
179 *
180 * @return True if the type of the register file is reserved,
181 * otherwise false.
182 */
183bool
185 return (type_ == RESERVED);
186}
187
188
189/**
190 * Sets the name of the register file.
191 *
192 * @param name Name of the register file.
193 * @exception ComponentAlreadyExists If a register file with the given name
194 * is already in the same machine.
195 * @exception InvalidName If the given name is not a valid component name.
196 */
197void
198RegisterFile::setName(const std::string& name) {
199 if (name == this->name()) {
200 return;
201 }
202
203 if (machine() != NULL) {
204 if (machine()->registerFileNavigator().hasItem(name)) {
205 string procName = "RegisterFile::setName";
206 throw ComponentAlreadyExists(__FILE__, __LINE__, procName);
207 } else {
209 }
210 } else {
212 }
213}
214
215/**
216 * Sets the maximum number of ports that can read a register all in the same
217 * cycle. Note that this function is only needed if all of the ports are
218 * unconnected, otherwise this value is computed automatically.
219 *
220 * The given value must be at least zero.
221 *
222 * @param reads Maximum number of ports.
223 * @exception OutOfRange If the given number of maximum reads is out of
224 * range.
225 */
226void
228 if (reads < 0) {
229 std::string procName = "RegisterFile::setMaxReads";
230 throw OutOfRange(__FILE__, __LINE__, procName);
231 }
232 maxReads_ = reads;
233}
234
235/**
236 * Sets the maximum number of ports that can write a register all in the same
237 * cycle. Note that this function is only needed if all of the ports are
238 * unconnected, otherwise this value is computed automatically.
239 *
240 * The given value must be at least zero.
241 *
242 * @param writes Maximum number of ports.
243 * @exception OutOfRange If the given number of maximum writes is out of
244 * range.
245 */
246void
248 if (maxWrites < 0) {
249 std::string procName = "RegisterFile::setMaxWrites";
250 throw OutOfRange(__FILE__, __LINE__, procName);
251 }
253}
254
255/**
256 * Updates RFs max reads/writes according in/output ports.
257 *
258 * Port that is not assigned to a socket is considered to be a dead port,
259 * thus not counted towards the maximum number of reads or writes.
260 *
261 * @return True if max reads/writes changed
262 * @exception OutOfRange If setMaxReads/setMaxWrites throws outOfRange
263 * exception.
264 */
265bool
267 int reads = 0;
268 int writes = 0;
269 bool changed = false;
270
271 for (int p = 0; p < portCount(); ++p) {
272 if (!port(p)->isOutput() && !port(p)->isInput()) {
273
274 // do not count unconnected ports
275 //++reads;
276 //++writes;
277
278 } else {
279 if (port(p)->isOutput()) {
280 changed = true;
281 ++reads;
282 }
283 if (port(p)->isInput()) {
284 changed = true;
285 ++writes;
286 }
287 }
288 }
289
290 if (changed)
291 {
292 maxReads_ = reads;
293 maxWrites_ = writes;
294 }
295 return changed;
296}
297
298/**
299 * Sets the type of the register file.
300 *
301 * @param type Type of the register file.
302 */
303void
307
308
309/**
310 * Sets the number of registers in the register file.
311 *
312 * If the number of registers decreases, deletes the register guards that
313 * were referencing to the registers that are removed.
314 *
315 * @param registers The new amount of registers.
316 * @exception OutOfRange If the given number of registers is less or equal
317 * to zero.
318 */
319void
321 if (registers < numberOfRegisters()) {
322 deleteGuards(registers);
323 }
325}
326
327/**
328 * Returns the guard latency.
329 *
330 * @return The guard latency.
331 */
332int
334 return guardLatency_;
335}
336
337
338/**
339 * Sets the guard latency.
340 *
341 * @param latency The new guard latency.
342 * @exception OutOfRange If the given value is negative or if local + global
343 * guard latency would be zero.
344 */
345void
347 if (latency < 0) {
348 throw OutOfRange(__FILE__, __LINE__, __func__);
349 }
350
351 // check that local guard latency + global guard latency > 0
352 if (latency == 0 && isRegistered()) {
353 ControlUnit* gcu = machine()->controlUnit();
354 if (gcu != NULL) {
355 int oldLatency = guardLatency();
356 guardLatency_ = latency;
357 try {
358 // this throws OutOfRange if the local guard latency cannot
359 // be zero
361 } catch (const OutOfRange& exception) {
362 guardLatency_ = oldLatency;
363 throw exception;
364 }
365 }
366 }
367
368 guardLatency_ = latency;
369}
370
371/**
372 * Removes the register file from machine.
373 */
374void
376 Machine* mach = machine();
377 if (mach == NULL) {
378 return;
379 }
380 deleteGuards(0);
382 mach->removeRegisterFile(*this);
383}
384
385
386/**
387 * Saves the contents to an ObjectState tree.
388 *
389 * @return The newly created ObjectState tree.
390 */
393
396
397 // set type
398 switch(type_) {
399 case NORMAL: regFile->setAttribute(OSKEY_TYPE, OSVALUE_NORMAL); break;
401 break;
403 break;
404 default: assert(false);
405 }
406
407 // set max reads
409
410 // set max writes
412
413 // set guard latency
415
416 // set zero register
417 if (zeroRegister_) {
419 }
420
421 return regFile;
422}
423
424
425/**
426 * Loads its state from the given ObjectState instance.
427 *
428 * @param state The ObjectState instance.
429 * @exception ObjectStateLoadingException If the given ObjectState instance
430 * is invalid.
431 */
432void
434 const string procName = "RegisterFile::loadState";
437 MOMTextGenerator textGenerator;
438}
439
440/**
441 * Loads the state of the register file without references to other
442 * components.
443 *
444 * @param state The ObjectState instance from which the state is loaded.
445 * @exception ObjectStateLoadingException If the given ObjectState instance
446 * is invalid.
447 */
448void
450 const string procName = "RegisterFile::loadStateWithoutReferences";
451
452 if (! (state->name() == OSNAME_REGISTER_FILE ||
454 throw ObjectStateLoadingException(__FILE__, __LINE__, procName);
455 }
456
457 try {
458 string type = state->stringAttribute(OSKEY_TYPE);
459 if (type == OSVALUE_NORMAL) {
461 } else if (type == OSVALUE_RESERVED) {
463 } else if (type == OSVALUE_VOLATILE) {
465 } else {
466 const string errorMsg = "Unknown register file type in "
467 "ObjectState instance.";
469 __FILE__, __LINE__, procName, errorMsg);
470 }
471
475 if (state->hasAttribute(OSKEY_ZERO_REGISTER)) {
477 }
478
479 } catch (const Exception& e) {
481 __FILE__, __LINE__, procName, e.errorMessage());
482 }
483}
484
485/**
486 * Deletes the guards that refer to registers would not exist if there were
487 * the given number of registers in this register file.
488 *
489 * @param registers The number of registers.
490 */
491void
492RegisterFile::deleteGuards(int registers) const {
493
494 Machine* mach = machine();
495 if (mach == NULL) {
496 return;
497 }
498
499 // for each bus
500 Machine::BusNavigator navi = mach->busNavigator();
501 for (int busIndex = 0; busIndex < navi.count(); busIndex++) {
502 Bus* bus = navi.item(busIndex);
503 int guardIndex = 0;
504
505 // delete register guards that refer to non-existing registers
506 while (guardIndex < bus->guardCount()) {
507 Guard* guard = bus->guard(guardIndex);
508 RegisterGuard* regGuard =
509 dynamic_cast<RegisterGuard*>(guard);
510 if (regGuard != NULL && regGuard->registerFile() == this &&
511 regGuard->registerIndex() >= registers) {
512
513 // guard is removed from bus automatically
514 delete regGuard;
515 } else {
516 guardIndex++;
517 }
518 }
519 }
520}
521
522/**
523 * Checks is this register file architecture equal with the given register file.
524 *
525 * Architecture equality means that register files have same values, names and
526 * port names may differ.
527 *
528 * @param rf Register file to compare with.
529 * @return True if the register files are architecture equal.
530 */
531bool
533
534 if (size() != rf.size()) {
535 return false;
536 }
537 if (width() != rf.width()) {
538 return false;
539 }
540 if (maxReads_ != rf.maxReads()) {
541 return false;
542 }
543 if (maxWrites_ != rf.maxWrites()) {
544 return false;
545 }
546 if (type_ != rf.type()) {
547 return false;
548 }
549 if (guardLatency_ != rf.guardLatency()) {
550 return false;
551 }
552 if (portCount() != rf.portCount()) {
553 return false;
554 }
555 // ports have same width that the register file, so port widths are not
556 // needed to check
557
558 return true;
559}
560
561/**
562 * Returns true if the register file is used as a guard.
563 *
564 * @return True if the register file is used as a guard.
565 */
566bool
568
569 Machine* mach = machine();
570 if (mach == NULL) {
571 return false;
572 }
573
574 // for each bus
575 Machine::BusNavigator navi = mach->busNavigator();
576 for (int busIndex = 0; busIndex < navi.count(); busIndex++) {
577 Bus* bus = navi.item(busIndex);
578 int guardIndex = 0;
579
580 // check if there are register guards that refer to this register file
581 while (guardIndex < bus->guardCount()) {
582 Guard* guard = bus->guard(guardIndex);
583 RegisterGuard* regGuard =
584 dynamic_cast<RegisterGuard*>(guard);
585 if (regGuard != NULL && regGuard->registerFile() == this) {
586 return true;
587 } else {
588 guardIndex++;
589 }
590 }
591 }
592 return false;
593}
594
595/**
596 * Creates and returns a copy of the register file.
597 *
598 * @return Copy of register file.
599 */
602
603 return new RegisterFile(saveState());
604}
605
606Port*
608 for (int i = 0; i < portCount(); i++) {
609 Port* p = port(i);
610 if (p->outputSocket() != NULL) {
611 return p;
612 }
613 }
614 return NULL;
615}
616
617Port*
619 for (int i = 0; i < portCount(); i++) {
620 Port* p = port(i);
621 if (p->inputSocket() != NULL) {
622 return p;
623 }
624 }
625 return NULL;
626}
627
628bool
630 return zeroRegister_;
631}
632
633void
635 zeroRegister_ = value;
636}
637}
#define __func__
#define assert(condition)
find Finds info of the inner loops in the false
std::string errorMessage() const
Definition Exception.cc:123
bool hasAttribute(const std::string &name) const
void setName(const std::string &name)
void setAttribute(const std::string &name, const std::string &value)
std::string stringAttribute(const std::string &name) const
bool boolAttribute(const std::string &name) const
int intAttribute(const std::string &name) const
std::string name() const
virtual void setNumberOfRegisters(int registers)
virtual ObjectState * saveState() const
virtual int numberOfRegisters() const
virtual int size() const
virtual int width() const
virtual RFPort * port(const std::string &name) const
virtual void loadState(const ObjectState *state)
Guard * guard(int index) const
Definition Bus.cc:456
virtual void setName(const std::string &name)
virtual void unsetMachine()=0
virtual Machine * machine() const
virtual bool isRegistered() const
virtual TCEString name() const
void setGlobalGuardLatency(int latency)
int globalGuardLatency() const
static const std::string OSNAME_IMMEDIATE_UNIT
ObjectState name for ImmediateUnit.
ComponentType * item(int index) const
virtual BusNavigator busNavigator() const
Definition Machine.cc:356
virtual ControlUnit * controlUnit() const
Definition Machine.cc:345
virtual void removeRegisterFile(RegisterFile &unit)
Definition Machine.cc:554
virtual Socket * outputSocket() const
Definition Port.cc:281
virtual bool isInput() const
Definition Port.cc:298
virtual bool isOutput() const
Definition Port.cc:308
virtual Socket * inputSocket() const
Definition Port.cc:261
static const std::string OSKEY_MAX_WRITES
ObjectState attribute key for maximum simultaneous writers.
virtual void setType(RegisterFile::Type type)
virtual void loadState(const ObjectState *state)
virtual bool isArchitectureEqual(const RegisterFile &rf) const
virtual void setZeroRegister(const bool &value)
virtual RegisterFile * copy() const
static const std::string OSKEY_MAX_READS
ObjectState attribute key for maximum simultaneous readers.
virtual int maxReads() const
virtual ObjectState * saveState() const
Port * firstReadPort() const
int maxWrites_
Max number of ports that can read a register all in the same cycle.
Type type_
Type of the register file.
virtual bool isVolatile() const
virtual bool isReserved() const
virtual void setMaxWrites(int maxWrites)
virtual void setName(const std::string &name)
RegisterFile(const std::string &name, unsigned int size, unsigned int width, unsigned int maxReads, unsigned int maxwrites, unsigned int guardLatency, Type type, bool zeroRegister=false)
int maxReads_
Max number of ports that can read a register all in the same cycle.
static const std::string OSKEY_ZERO_REGISTER
ObjectState attribute key for zero register flag.
virtual bool zeroRegister() const
virtual void setMaxReads(int maxReads)
static const std::string OSKEY_GUARD_LATENCY
ObjectState attribute key for the guard latency.
void deleteGuards(int registers) const
Type
Type of the register file indicates how the RF is used.
@ VOLATILE
Used for user-controlled I/O communication.
@ NORMAL
Used for general register allocation.
@ RESERVED
Used for custom, user controlled register allocation.
virtual bool isNormal() const
virtual void setGuardLatency(int latency)
static const std::string OSVALUE_RESERVED
ObjectState attribute value for reserved register file type.
virtual int guardLatency() const
static const std::string OSVALUE_VOLATILE
ObjectState attribute value for volatile register file type.
static const std::string OSKEY_TYPE
ObjectState attribute key for register file type.
virtual RegisterFile::Type type() const
static const std::string OSNAME_REGISTER_FILE
ObjectState name for RegisterFile.
virtual bool isUsedAsGuard() const
virtual void setNumberOfRegisters(int registers)
virtual void unsetMachine()
virtual int maxWrites() const
void loadStateWithoutReferences(const ObjectState *state)
Port * firstWritePort() const
int guardLatency_
The guard latency of the register file.
static const std::string OSVALUE_NORMAL
ObjectState attribute value for normal register file type.
bool updateMaxReadsAndWrites() const
const RegisterFile * registerFile() const
virtual int portCount() const
Definition Unit.cc:135
@ NORMAL
Definition tceopgen.cc:45