Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | /* |
2 | * ========== Copyright Header Begin ========================================== | |
3 | * | |
4 | * OpenSPARC T2 Processor File: Register.h | |
5 | * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
6 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES. | |
7 | * | |
8 | * The above named program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public | |
10 | * License version 2 as published by the Free Software Foundation. | |
11 | * | |
12 | * The above named program is distributed in the hope that it will be | |
13 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public | |
18 | * License along with this work; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. | |
20 | * | |
21 | * ========== Copyright Header End ============================================ | |
22 | */ | |
23 | #ifndef __Register_h | |
24 | #define __Register_h | |
25 | ||
26 | #include <stddef.h> | |
27 | #include <assert.h> | |
28 | #include <iostream> | |
29 | #include <fstream> | |
30 | #include <string> | |
31 | #include "Block.h" | |
32 | #include "Object.h" | |
33 | #include "Datatype.h" | |
34 | #include "Signature.h" | |
35 | using namespace std; | |
36 | ||
37 | /** @file Register.h | |
38 | * Register.h provides a set of classes for representing registers. | |
39 | * | |
40 | * @see RegisterModule | |
41 | */ | |
42 | ||
43 | /** @defgroup RegisterModule The Register Module | |
44 | * | |
45 | * Registers are 8, 16, 32 or 64 bits wide, and are composed of Fields. | |
46 | * Fields are contiguous collections of bits within a Register. The value | |
47 | * of a Register can be accessed at the Register level or at the | |
48 | * Field level. Care is taken to ensure that large arrays of 64-bit registers | |
49 | * are implemented efficiently - in terms of memory usage and run-time | |
50 | * cost. Note that there is significant waste in the storage of narrower | |
51 | * registers since they are held in 64-bit containers (with unused upper bits | |
52 | * always zero). | |
53 | * | |
54 | * The classes and types defined here are: | |
55 | * - AccessType | |
56 | * - Register | |
57 | * - Field | |
58 | * | |
59 | * The following classes are also defined in this file, but are not | |
60 | * intended for use outside Register/Field implementation: | |
61 | * - RegisterType | |
62 | * - RegisterState | |
63 | * - RegisterInfo | |
64 | * - FieldType | |
65 | * | |
66 | * The "public" interface provided by this file consists of AccessType, | |
67 | * Register and Field. The other classes are internal and not intended | |
68 | * for use outside the Register/Field implementation. | |
69 | * | |
70 | * Note that there are no FieldState/FieldInfo classes. This is because | |
71 | * the register state and info are held in RegisterState/RegisterInfo | |
72 | * and the field-level mechanisms pull out the necessary bits from | |
73 | * the register. There are (too) many friendships | |
74 | * between the various register and field classes - they work together | |
75 | * very closely and this avoids having to define a lot more methods | |
76 | * to access the internal state. Originally, this class was implemented | |
77 | * as just Register and Field classes with simple array container | |
78 | * classes that replicated registers. This was very inefficient for | |
79 | * large register arrays, which turned out to be a significant problem at | |
80 | * run-time. The classes were then restructured and rewritten so that only | |
81 | * RegisterState/RegisterInfo had to be replicated for every element in a | |
82 | * RegisterArray, and the amount of overhead data in this class was | |
83 | * massively reduced. | |
84 | * | |
85 | * See also RegisterArray.h | |
86 | * | |
87 | * @{ | |
88 | */ | |
89 | ||
90 | /** AccessType is an enumerated type used to distinguish the various | |
91 | * supported access types. The access types are specified at the | |
92 | * Field level. Since a Register can contain more than one Field, | |
93 | * then a Register can have multiple access types associated with | |
94 | * its Fields. The access types are: | |
95 | * - Access_RC: read-to-clear. | |
96 | * - Access_RO: read-only. | |
97 | * - Access_RW: read-write. | |
98 | * - Access_RW1C: read, write-one-to-clear. | |
99 | * - Access_RW1S: read, write-one-to-set. | |
100 | * - Access_RCW1C: read-to-clear, write-one-to-clear. | |
101 | * - Access_RCW1S: read-to-clear, write-one-to-set. | |
102 | * - Access_WO: read undefined, write-only. | |
103 | * - Access_L: read as zero, write-only. | |
104 | */ | |
105 | ||
106 | typedef enum { | |
107 | Access_RC, /**< - READ: return value and clear. | |
108 | - WRITE: set value. */ | |
109 | Access_RO, /**< - READ: return value. | |
110 | - WRITE: ignored. */ | |
111 | Access_RW, /**< - READ: return value. | |
112 | - WRITE: set value. */ | |
113 | Access_RW1C, /**< - READ: return value. | |
114 | - WRITE: clear the bits written as "1". */ | |
115 | Access_RW1S, /**< - READ: return value. | |
116 | - WRITE: set the bits written as "1". */ | |
117 | Access_RCW1C, /**< - READ: return value and clear. | |
118 | - WRITE: clear the bits written as "1". */ | |
119 | Access_RCW1S, /**< - READ: return value and clear. | |
120 | - WRITE: set the bits written as "1". */ | |
121 | Access_WO, /**< - READ: undefined. | |
122 | - WRITE: set value. */ | |
123 | Access_L /**< - READ: return zero. | |
124 | - WRITE: set value. */ | |
125 | } AccessType; | |
126 | ||
127 | /** The static constant value used for an undefined Register value. */ | |
128 | // static const Data UNDEFINED_DATA = Data(0xCAFEBABEBEEFFACE); | |
129 | static const Data UNDEFINED_DATA = Data(0x0); | |
130 | ||
131 | class FieldType; // forward reference | |
132 | ||
133 | /** RegisterType contains the type information for a Register. These are | |
134 | * static properties of a Register that are not typically modified once | |
135 | * the Register has been created, and are consistent across all elements in a | |
136 | * RegisterArray. A number of the fields in RegisterType are used to | |
137 | * accelerate accesses to that Register by pre-calculating mask values, | |
138 | * and also collate relevant information from the FieldType classes for the | |
139 | * Register. Two booleans are used to keep track of whether the call-back | |
140 | * mechanism has been enabled for read and write accesses. It is possible | |
141 | * to enable/disable this mechanism on-the-fly but it is typically a | |
142 | * static property. The call-back flags for a RegisterArray apply to every | |
143 | * Register element in that array. | |
144 | * | |
145 | * Note that RegisterType is used in the implementation of the Register class. | |
146 | * There should be no reason to use this class from elsewhere since Register | |
147 | * provides a complete public interface to registers. Most of the state | |
148 | * inside RegisterType is private without any direct access methods. | |
149 | */ | |
150 | ||
151 | class RegisterType | |
152 | { | |
153 | friend class Register; | |
154 | friend class RegisterArray; | |
155 | friend class FieldType; | |
156 | ||
157 | public: | |
158 | /** Constructor for RegisterType. | |
159 | * @param w width of the Register in bytes (1, 2, 4 or 8 bytes). | |
160 | */ | |
161 | RegisterType(uint w=8); | |
162 | ||
163 | private: | |
164 | void check(string n); | |
165 | ||
166 | uint widthBits; | |
167 | uint widthBytes; | |
168 | Data widthMask; | |
169 | Data checkMask; | |
170 | Data writeMask; | |
171 | Data writeOneToClearMask; | |
172 | Data writeOneToSetMask; | |
173 | Data readMask; | |
174 | Data readAsUndefinedMask; | |
175 | Data readAsZeroMask; | |
176 | Data readToClearMask; | |
177 | Data resetValue; | |
178 | Data resetAssigned; | |
179 | bool writeBlockCB; | |
180 | bool readBlockCB; | |
181 | List<FieldType> fieldTypes; | |
182 | }; | |
183 | ||
184 | /** RegisterState holds the value for a particular Register in a 64-bit | |
185 | * container. | |
186 | * | |
187 | * The RegisterState class contains the value for an undefined Register, and | |
188 | * this is also used to derive the value for an undefined Field. This is | |
189 | * arranged so that if all Fields of a Register are given the undefined | |
190 | * Field value, then the value of the Register is the undefined Register | |
191 | * value. Note that a "randomized" undefined value is good for catching | |
192 | * discrepanies between hardware and software views of registers, but 0x0 | |
193 | * is more convenient when tracing or debugging. | |
194 | * | |
195 | * Note that RegisterState is used in the implementation of the Register | |
196 | * class. There should be no reason to use this class from elsewhere since | |
197 | * Register provides a complete public interface to registers. | |
198 | */ | |
199 | ||
200 | class RegisterState | |
201 | { | |
202 | friend class Register; | |
203 | friend class RegisterArray; | |
204 | friend class Field; | |
205 | ||
206 | public: | |
207 | /** Constructor for RegisterState. | |
208 | * @param v initial value of the Register (defaults to UNDEFINED_DATA). | |
209 | */ | |
210 | RegisterState(Data v=UNDEFINED_DATA) | |
211 | { | |
212 | value=v; | |
213 | } | |
214 | ||
215 | private: | |
216 | Data value; | |
217 | }; | |
218 | ||
219 | /** RegisterInfo holds other information associated with each RegisterState | |
220 | * instance. This includes fields to track whether this Register is | |
221 | * clean/dirty (used for tracing) and whether this Register has been | |
222 | * assigned a value (ie. initialized - this information is maintained | |
223 | * but not actually used for anything yet). The reason for separating | |
224 | * out RegisterInfo from RegisterInfo is to give more efficient memory | |
225 | * usage (smaller class size). | |
226 | * | |
227 | * TODO - one idea for the assigned bit is to ensure that unassigned | |
228 | * Register instances can take an UNDEFINED_DATA value without having | |
229 | * to set them to this value at construction or reset time. This could | |
230 | * be useful to reduce the amount of memory initialization | |
231 | * (and in-core memory) required for the simulation of very large | |
232 | * RegisterArrays. In fact, the RegisterState instance of an unassigned | |
233 | * RegisterArray could be allocated lazily (ie. on first write). This | |
234 | * would require modifications to all register and field access mechanisms | |
235 | * (get, set, read, write, etc) to catch accesses to unassigned state. | |
236 | * This potential optimization does not seem worthwhile yet and thus has | |
237 | * not been implemented. Note that care has been taken to minimize the amount | |
238 | * of overhead for large RegisterArrays and this has been sufficient so far. | |
239 | * | |
240 | * Note that RegisterInfo is used in the implementation of the Register | |
241 | * class. There should be no reason to use this class from elsewhere since | |
242 | * Register provides a complete public interface to registers. | |
243 | */ | |
244 | ||
245 | class RegisterInfo | |
246 | { | |
247 | friend class Register; | |
248 | friend class RegisterArray; | |
249 | friend class Field; | |
250 | ||
251 | public: | |
252 | /** Constructor for RegisterInfo. | |
253 | * @param a initial setting for the assigned bit (defaults to unassigned). | |
254 | * @param b initial setting of the clean bit (defaults to dirty). | |
255 | */ | |
256 | RegisterInfo(bool a=false, bool b=false) | |
257 | { | |
258 | assigned=a; | |
259 | clean=b; | |
260 | } | |
261 | ||
262 | /** Get the assigned boolean. */ | |
263 | bool getAssigned() const { return assigned; } | |
264 | ||
265 | /** Set the assigned boolean. | |
266 | * @param b the new value for the assigned boolean. */ | |
267 | void setAssigned(bool b) { assigned = b; } | |
268 | ||
269 | /** Get the clean boolean. */ | |
270 | bool getClean() const { return clean; } | |
271 | ||
272 | /** Set the clean boolean. | |
273 | * @param b the new value for the clean boolean. */ | |
274 | void setClean(bool b) { clean = b; } | |
275 | ||
276 | /** Get the dirty boolean. */ | |
277 | bool getDirty() const { return !clean; } | |
278 | ||
279 | /** Set the dirty boolean. | |
280 | * @param b the new value for the dirty boolean. */ | |
281 | void setDirty(bool b) { clean = !b; } | |
282 | ||
283 | private: | |
284 | bool assigned; | |
285 | bool clean; | |
286 | }; | |
287 | ||
288 | /** The Register class provides mechanisms to construct and access Register | |
289 | * instances. After a Register is constructed, it is necessary to construct | |
290 | * one or more instances of the Field class and associate them with the | |
291 | * Register. A Register must be populated with Fields to define how each | |
292 | * bit in the Register should behave for reads and writes, and to specify | |
293 | * any defined initial value for the Register. | |
294 | * | |
295 | * Internally, the Register class contains pointers to RegisterType and | |
296 | * RegisterState instances, which hold the type and state for this | |
297 | * Register respectively. For a RegisterArray, an array of Registers is | |
298 | * not allocated since this is too expensive. Instead one RegisterState | |
299 | * is allocated for each Register in the array, and one RegisterType is | |
300 | * allocated for the whole array. When a RegisterArray is subscripted to | |
301 | * yield a Register, an instance of the Register class is initialized | |
302 | * appropriately. This is returned-by-value so that the state is | |
303 | * provided by the caller of the RegisterArray subscription operator. | |
304 | * This Register instance gets destructed when it goes out of | |
305 | * scope or is deallocated by the caller. Additionally, the returned | |
306 | * Register refers to the correct RegisterState structure in the original | |
307 | * RegisterArray so that writes/sets to the returned Register structure | |
308 | * will correctly update the value in the array. In some ways it is more | |
309 | * appropriate to consider the Register structure as a register | |
310 | * handle, and not the register value itself. | |
311 | */ | |
312 | ||
313 | class Register | |
314 | { | |
315 | friend class Field; | |
316 | friend class RegisterArray; | |
317 | ||
318 | public: | |
319 | /** Constructor for Register. | |
320 | * @param n the basename for this Register. | |
321 | * @param b a pointer to the Block with which this Register is associated. | |
322 | * The fullname of this Register is scoped within that Block. | |
323 | * @param a the address of this Register. | |
324 | * @param w the width of this Register in bytes, defaults to 8 bytes. | |
325 | * | |
326 | * If the parent block is specified as NULL (which is its default), then | |
327 | * this Register will not be associated with any parent and will not | |
328 | * be included in any of the register mechanisms provided by the Block | |
329 | * class. In particular the Register will not be in the print, reset, | |
330 | * sign or trace trees, and the Register will not be included in the | |
331 | * address map of that Block. Additionally, the call-back mechanism | |
332 | * for side-effecting reads/writes cannnot be used. | |
333 | * | |
334 | * If there is no parent block then no interpretation will be placed on | |
335 | * the address by the Register class. This mechanism is convenient for | |
336 | * modelling structures that have similar structure to registers | |
337 | * (e.g. composed of fields) but that are not architectural state. | |
338 | * If the Register class is used in this way, then it is up to the | |
339 | * user to provide all required infrastructure (such as a call to | |
340 | * reset its state). The RegisterArray/FieldArray classes do not | |
341 | * support Blockless registers. | |
342 | */ | |
343 | Register(string n, Block *b=NULL, Addr a=Addr(0), uint w=8); | |
344 | ||
345 | /** The copy constructor for Register. The destination Register is marked | |
346 | * as derived so that destructing that Register does not deallocate the | |
347 | * heap state allocated by the source Register. It is assumed that | |
348 | * non-derived Register instances (the original source of one or more | |
349 | * copies) will out-live all copies. This is reasonable since non-derived | |
350 | * Register instances correspond to architectural state and should be | |
351 | * allocated for the entire simulation. | |
352 | * @param r the source Register for the copy construction. | |
353 | */ | |
354 | Register(const Register &r); | |
355 | ||
356 | /** Constructor for Register with no parameters to initialize the register | |
357 | * to a default state. This is provided for the RegisterArray::lookup() | |
358 | * mechanism. */ | |
359 | Register(); | |
360 | ||
361 | /** Destructor for Register. This is virtual so that the appropriate | |
362 | * destructor for any derived class is used. */ | |
363 | virtual ~Register(); | |
364 | ||
365 | /** The copy assignment operator for Register. The destination Register is | |
366 | * marked as derived so that destructing that Register does not deallocate | |
367 | * the heap state allocated by the source Register. It is assumed that | |
368 | * non-derived Register instances (the original source of one or more | |
369 | * copies) will out-live all copies. This is reasonable since non-derived | |
370 | * Register instances correspond to architectural state and should be | |
371 | * allocated for the entire simulation. | |
372 | * @param r the source Register for the copy assignment. | |
373 | */ | |
374 | Register &operator=(const Register &r); | |
375 | ||
376 | /** Clone a new copy of this Register. This creates a Register instance | |
377 | * using new and performs a shallow copy of this Register into the new | |
378 | * Register. The new Register is marked as derived so that deletion of | |
379 | * the new Register does not deallocate the heap state of this Register. | |
380 | * A pointer to the new Register is returned, and it is the responsibility | |
381 | * of the caller to delete the pointer when the new Register is no | |
382 | * longer required. This is a virtual function so that it can be | |
383 | * overloaded by sub-classes of Register as appropriate. */ | |
384 | virtual Register *clone() const { return new Register(*this); } | |
385 | ||
386 | /** Get the basename of this Register. */ | |
387 | string getBaseName() const; | |
388 | ||
389 | /** Get the fullname of this Register. */ | |
390 | string getFullName() const; | |
391 | ||
392 | /** Get the address of this Register. */ | |
393 | Addr getAddr() const { return addr; } | |
394 | ||
395 | /** Get the width in bytes of this Register. */ | |
396 | uint getWidth() const { return regType->widthBytes; } | |
397 | ||
398 | /** Get a pointer to the Data associated with this Register. */ | |
399 | Data *getPtr() { return ®State->value; } | |
400 | ||
401 | /** Return true if this Register is an element in a RegisterArray, | |
402 | * otherwise false. */ | |
403 | bool isElement() const { return element; } | |
404 | ||
405 | /** If this Register is an element in a RegisterArray, get the index | |
406 | * of this element. If this Register is not an element in a RegisterArray | |
407 | * the behavior of this method is undefined. */ | |
408 | uint getIndex() const { assert(element); return index; } | |
409 | ||
410 | /** Get the value of this Register. This returns the value of the full | |
411 | * width of the Register regardless of the AccessType settings of the | |
412 | * associated fields. For Registers that are narrower than 64 bits, the | |
413 | * upper unused bits will be returned as zero. This method is suitable | |
414 | * for simulator code that models internal hardware | |
415 | * accesses. It should not be used to model software accesses to the | |
416 | * architectural state - these should use the Register::read method. | |
417 | */ | |
418 | inline Data get() const | |
419 | { | |
420 | return regState->value; | |
421 | } | |
422 | ||
423 | /** Get the value of this Register. This returns the value of the full | |
424 | * width of the Register regardless of the AccessType settings of the | |
425 | * associated fields. For Registers that are narrower than 64 bits, the | |
426 | * upper unused bits will be returned as zero. This method is suitable | |
427 | * for simulator code that models internal hardware | |
428 | * accesses. It should not be used to model software accesses to the | |
429 | * architectural state - these should use the Register::read method. | |
430 | */ | |
431 | inline operator Data() const | |
432 | { | |
433 | return regState->value; | |
434 | } | |
435 | ||
436 | /** Get the reset value of this Register. For Registers that are narrower | |
437 | * than 64 bits, the upper unused bits will be returned as zero. */ | |
438 | Data getResetValue() const | |
439 | { | |
440 | return regType->resetValue; | |
441 | } | |
442 | ||
443 | /** Set the value of this Register. This sets the value for the full width | |
444 | * of the Register regardless of the AccessType settings of the associated | |
445 | * fields. For Registers that are narrower than 64 bits, the | |
446 | * upper unused bits will be forced to zero, regardless of the parameter d. | |
447 | * This method is suitable for simulator code that models internal | |
448 | * hardware accesses. It should not be used to model software accesses | |
449 | * to the architectural state - these should use the Register::write method. | |
450 | * @param d the new Data value for this Register. | |
451 | */ | |
452 | inline void set(Data d) | |
453 | { | |
454 | regState->value = d & regType->widthMask; | |
455 | regInfo->assigned = true; | |
456 | regInfo->clean = false; | |
457 | } | |
458 | ||
459 | /** Set the value of this Register. This sets the value for the full width | |
460 | * of the Register regardless of the AccessType settings of the associated | |
461 | * fields. For Registers that are narrower than 64 bits, the | |
462 | * upper unused bits will be forced to zero, regardless of the parameter d. | |
463 | * This method is suitable for simulator code that models internal | |
464 | * hardware accesses. It should not be used to model software accesses | |
465 | * to the architectural state - these should use the Register::write method. | |
466 | * @param d the new Data value for this Register. | |
467 | */ | |
468 | inline Register &operator=(Data d) | |
469 | { | |
470 | set(d); | |
471 | return *this; | |
472 | } | |
473 | ||
474 | /** Read the value of this Register. This returns from the value with | |
475 | * the AccessType of each Field applied appropriately. For Registers | |
476 | * that are narrower than 64 bits, the upper unused bits will be | |
477 | * returned as zero. There may be other hardware side-effects caused by the | |
478 | * act of reading, as required by the architecture specification for | |
479 | * this Register. This method is suitable to model software | |
480 | * accesses to the architectural state. Other uses should consider | |
481 | * the Register::get method. | |
482 | */ | |
483 | Data read() | |
484 | { | |
485 | Data original = regState->value; | |
486 | Data d = (original & regType->readMask) | | |
487 | (UNDEFINED_DATA & regType->readAsUndefinedMask); | |
488 | ||
489 | if (regType->readToClearMask != 0) { | |
490 | regState->value &= ~regType->readToClearMask; | |
491 | regInfo->assigned = true; | |
492 | regInfo->clean = false; | |
493 | } | |
494 | ||
495 | d = regReadCB(block, original, d); | |
496 | ||
497 | if (regType->readBlockCB) { | |
498 | assert(block != NULL); | |
499 | d = block->regReadBlockCB(this, original, d); | |
500 | } | |
501 | ||
502 | return d; | |
503 | } | |
504 | ||
505 | /** Write the value of this Register. This writes to the value with | |
506 | * the AccessType of each Field applied appropriately. For Registers | |
507 | * that are narrower than 64 bits, the upper unused bits will be | |
508 | * forced to zero, regardless of the parameter d. There may be other | |
509 | * hardware side-effects caused by the act of writing, as required by | |
510 | * the architecture specification for this Register. This method should | |
511 | * be used to model software accesses to the architectural state. Other | |
512 | * uses should consider the Register::set method. | |
513 | * @param d the new Data value for this Register. | |
514 | */ | |
515 | void write(Data d) | |
516 | { | |
517 | Data original = regState->value; | |
518 | ||
519 | if (regType->writeMask != 0) { | |
520 | regState->value = (original & ~regType->writeMask) | | |
521 | (d & regType->writeMask); | |
522 | regInfo->assigned = true; | |
523 | regInfo->clean = false; | |
524 | } | |
525 | ||
526 | if (regType->writeOneToClearMask != 0) { | |
527 | Data clearMask = d & regType->writeOneToClearMask; | |
528 | if (clearMask != 0) { | |
529 | regState->value &= ~clearMask; | |
530 | regInfo->assigned = true; | |
531 | regInfo->clean = false; | |
532 | } | |
533 | } | |
534 | ||
535 | if (regType->writeOneToSetMask != 0) { | |
536 | Data setMask = d & regType->writeOneToSetMask; | |
537 | if (setMask != 0) { | |
538 | regState->value |= setMask; | |
539 | regInfo->assigned = true; | |
540 | regInfo->clean = false; | |
541 | } | |
542 | } | |
543 | ||
544 | regWriteCB(block, original, d); | |
545 | ||
546 | if (regType->writeBlockCB) { | |
547 | assert(block != NULL); | |
548 | block->regWriteBlockCB(this, original, d); | |
549 | } | |
550 | } | |
551 | ||
552 | /** Call-back function for when a register is read from. | |
553 | * @param b the Block associated with this Register, or NULL if no Block. | |
554 | * @param origValue the value of this register prior to the read. | |
555 | * @param readValue the result of the read of this register (following | |
556 | * the conventions for the FieldType of each Field in the | |
557 | * Register). | |
558 | * @result the value that will be returned for this read. | |
559 | * | |
560 | * The regReadCB virtual method provides a call-back function called | |
561 | * upon any read from this register. This can be | |
562 | * be used to monitor accesses, trigger control side-effects or | |
563 | * over-ride the default access semantics. The call-back function is | |
564 | * called AFTER the architectural state of the register has been | |
565 | * accessed/updated for the access, though the call-back has the opportunity | |
566 | * to modify the architectural state if it needs to. | |
567 | * | |
568 | * Typically, the call-back will return readValue as the result. However, | |
569 | * the call-back code has the opportunity to return any value allowing | |
570 | * the FieldType conventions to be over-ridden if required. The value | |
571 | * of the Register after the read can be accessed via the Register pointer. | |
572 | * It must not be read/written as this will cause recursion into the | |
573 | * call-back mechanism!! Instead, use Register::get and Register::set to | |
574 | * access the register value directly. | |
575 | * | |
576 | * This is a virtual method, and its default implementation is to | |
577 | * return the expected read value with no side-effects. Subclasses | |
578 | * of Register can over-ride this method so that specific code is executed | |
579 | * when a register is read from. It is NOT necessary to enable the | |
580 | * Register-level call-back mechanism - providing a virtual method that | |
581 | * over-rides Register::regReadCB is sufficient to catch the call-back. | |
582 | * | |
583 | * See also Block::regReadCB(). Note that Register-level call-backs are | |
584 | * made before Block-level call-backs. | |
585 | */ | |
586 | virtual Data regReadCB(Block *b, Data origValue, Data readValue) | |
587 | { | |
588 | return readValue; | |
589 | } | |
590 | ||
591 | /** Call-back function for when a register is written to. | |
592 | * @param b the Block associated with this Register, or NULL if no Block. | |
593 | * @param origValue the value of this register prior to the write. | |
594 | * @param writeValue the value that is being written to the register. | |
595 | * | |
596 | * The regWriteCB virtual method provides a call-back function called | |
597 | * upon any write to this register. This can be | |
598 | * be used to monitor accesses, trigger control side-effects or | |
599 | * over-ride the default access semantics. The call-back function is | |
600 | * called AFTER the architectural state of the register has been | |
601 | * accessed/updated for the access, though the call-back has the opportunity | |
602 | * to modify the architectural state if it needs to. | |
603 | * | |
604 | * The value of the Register after the write can be accessed via the | |
605 | * Register pointer. It must not be read/written as this will cause | |
606 | * recursion into the call-back mechanism!! Instead, use Register::get | |
607 | * and Register::set to access the register value directly. | |
608 | * Typically, the call-back will not modify the register value. However, | |
609 | * the call-back code has the opportunity to write any value allowing | |
610 | * the FieldType conventions to be over-ridden if required. | |
611 | * | |
612 | * This is a virtual method, and its default implementation is empty | |
613 | * so that there are no side-effects. Subclasses of Register can over-ride | |
614 | * this method so that specific code is executed when a register is | |
615 | * written to. It is NOT necessary to enable the | |
616 | * Register-level call-back mechanism - providing a virtual method that | |
617 | * over-rides Register::regWriteCB is sufficient to catch the call-back. | |
618 | * | |
619 | * See also Block::regWriteCB(). Note that Register-level call-backs are | |
620 | * made before Block-level call-backs. | |
621 | */ | |
622 | virtual void regWriteCB(Block *b, Data origValue, Data writeValue) {} | |
623 | ||
624 | /** Mark this Register as unassigned and give this Register | |
625 | * an undefined value. */ | |
626 | void undefined() | |
627 | { | |
628 | regState->value = UNDEFINED_DATA & regType->widthMask; | |
629 | regInfo->assigned = false; | |
630 | regInfo->clean = false; | |
631 | } | |
632 | ||
633 | /** Make this Register dirty. */ | |
634 | void makeDirty() { regInfo->clean = false; } | |
635 | ||
636 | /** Make this Register clean. */ | |
637 | void makeClean() { regInfo->clean = true; } | |
638 | ||
639 | /** Return true if this Register is dirty, else false. */ | |
640 | bool isDirty() { return !regInfo->clean; } | |
641 | ||
642 | /** Return true if this Register is clean, else false. */ | |
643 | bool isClean() { return regInfo->clean; } | |
644 | ||
645 | /** Enable write Block-level call-backs for this Register. */ | |
646 | void enableWriteBlockCB() | |
647 | { | |
648 | assert(block != NULL); | |
649 | regType->writeBlockCB = true; | |
650 | } | |
651 | ||
652 | /** Disable write Block-level call-backs for this Register. */ | |
653 | void disableWriteBlockCB() | |
654 | { | |
655 | regType->writeBlockCB = false; | |
656 | } | |
657 | ||
658 | /** Enable read Block-level call-backs for this Register. */ | |
659 | void enableReadBlockCB() | |
660 | { | |
661 | assert(block != NULL); | |
662 | regType->readBlockCB = true; | |
663 | } | |
664 | ||
665 | /** Disable read Block-level call-backs for this Register. */ | |
666 | void disableReadBlockCB() | |
667 | { | |
668 | regType->readBlockCB = false; | |
669 | } | |
670 | ||
671 | /** Print this Register to the specified output stream. */ | |
672 | void printThis(ostream &os); | |
673 | ||
674 | /** Reset this Register to its initial value. */ | |
675 | void resetThis(); | |
676 | ||
677 | /** Create the Signature for this Register so that it can subsequently | |
678 | * be traced. | |
679 | * @param ofs the output file stream.*/ | |
680 | void signThis(ofstream &ofs); | |
681 | ||
682 | /** Trace this Register to the specified output stream. | |
683 | * @param ofs the output file stream.*/ | |
684 | void traceThis(ofstream &ofs); | |
685 | ||
686 | private: | |
687 | /** Initialize a derived Register to the specified values. | |
688 | * @param b a pointer to the Block with which this Register is associated. | |
689 | * @param a the address of this Register. | |
690 | * @param e true if the Register is an element in an array, else false. | |
691 | * @param i the index of the Register in the array if e is true. | |
692 | * @param rt the RegisterType for this Register. | |
693 | * @param rs the RegisterState for this Register. | |
694 | * @param ri the RegisterInfo for this Register. | |
695 | * @param s the Signature for this Register. | |
696 | */ | |
697 | void init(Block *b, Addr a, bool e, uint i, RegisterType *rt, | |
698 | RegisterState *rs, RegisterInfo *ri, Signature *s); | |
699 | ||
700 | string baseName; | |
701 | Block *block; | |
702 | Addr addr; | |
703 | bool derived; | |
704 | bool element; | |
705 | uint index; | |
706 | RegisterType *regType; | |
707 | RegisterState *regState; | |
708 | RegisterInfo *regInfo; | |
709 | Signature *mySignature; | |
710 | }; | |
711 | ||
712 | /** FieldType contains the type information for a Field. These are | |
713 | * static properties of a Field that cannot be modified once the Field | |
714 | * has been created, and are consistent across all elements in a FieldArray. | |
715 | * | |
716 | * Note that FieldType is used in the implementation of the Field class. | |
717 | * There should be no reason to use this class from elsewhere since Field | |
718 | * provides a complete public interface to fields. Most of the state | |
719 | * inside FieldType is private without any direct access methods. | |
720 | */ | |
721 | ||
722 | class FieldType | |
723 | { | |
724 | friend class Field; | |
725 | friend class FieldArray; | |
726 | friend class Register; | |
727 | ||
728 | public: | |
729 | /** Constructor for FieldType. | |
730 | * @param f the fullname of the associated Register. | |
731 | * @param n the basename of this field. | |
732 | * @param r the RegisterType to which this FieldType belongs. | |
733 | * @param a the AccessType of this field. | |
734 | * @param e the end bit position of this field (highest bit number). | |
735 | * @param s the start bit position of this field (lowest bit number). | |
736 | * @param b field has a defined initial value if true, otherwise | |
737 | * undefined. | |
738 | * @param d the initial value of the field (if it has one). | |
739 | */ | |
740 | FieldType(string f, string n, RegisterType *r, AccessType a, | |
741 | uint e, uint s, bool b=false, Data d=0); | |
742 | ||
743 | /** Get the basename of this FieldType. */ | |
744 | string getBaseName() const { return baseName; } | |
745 | ||
746 | /** Get the access type of this FieldType as a string. */ | |
747 | string getAccessType() const; | |
748 | ||
749 | private: | |
750 | bool overlap(FieldType *f); | |
751 | void check(RegisterType *r, string n); | |
752 | ||
753 | string baseName; | |
754 | RegisterType *regType; | |
755 | ||
756 | AccessType access; | |
757 | uint start; | |
758 | uint end; | |
759 | Data regMask; | |
760 | Data fieldMask; | |
761 | Data resetValue; | |
762 | }; | |
763 | ||
764 | /** The Field class provides mechanisms to construct and access Field | |
765 | * instances. When a Field is constructed, it is associated with a | |
766 | * Register instance. The Register provides the state for the field | |
767 | * (in the RegisterState class), while the Field provides the type | |
768 | * information which is then collated into the RegisterType class. | |
769 | * | |
770 | * Internally, the Field class contains pointers to FieldType, RegisterType | |
771 | * and RegisterState instances. For a FieldArray, an array of Fields is | |
772 | * not allocated since this is too expensive. Instead just one FieldType is | |
773 | * allocated for the whole array. When a FieldArray is subscripted to | |
774 | * yield a Field, an instance of the Field class is initialized | |
775 | * appropriately. This is returned-by-value so that the state is | |
776 | * provided by the caller of the FieldArray subscription operator. | |
777 | * This Field instance gets destructed when it goes out of | |
778 | * scope or is deallocated by the caller. Additionally, the returned | |
779 | * Field refers to the correct RegisterState structure in the original | |
780 | * RegisterArray so that writes/sets to the returned Field structure | |
781 | * will correctly update the value in the array. In some ways it is more | |
782 | * appropriate to consider the Field structure as a field | |
783 | * handle, and not the field value itself. | |
784 | */ | |
785 | ||
786 | class Field | |
787 | { | |
788 | friend class FieldArray; | |
789 | ||
790 | public: | |
791 | /** Constructor for Field. | |
792 | * @param n the basename of this field. | |
793 | * @param r the Register to which this Field belongs. | |
794 | * @param a the AccessType of this field. | |
795 | * @param e the end bit position of this field (highest bit number). | |
796 | * @param s the start bit position of this field (lowest bit number). | |
797 | * @param b field has a defined initial value if true, otherwise | |
798 | * undefined. | |
799 | * @param d the initial value of the field (if it has one). | |
800 | */ | |
801 | Field(string n, Register *r, AccessType a, | |
802 | uint e, uint s, bool b=false, Data d=0); | |
803 | ||
804 | /** The copy constructor for Field. The destination Field is marked | |
805 | * as derived so that destructing that Field does not deallocate the | |
806 | * heap state allocated by the source Field. It is assumed that | |
807 | * non-derived Field instances (the original source of one or more | |
808 | * copies) will out-live all copies. This is reasonable since non-derived | |
809 | * Field instances correspond to architectural state and should be | |
810 | * allocated for the entire simulation. | |
811 | */ | |
812 | Field(const Field &f); | |
813 | ||
814 | /** Constructor for Field with no parameters to initialize the field | |
815 | * to a default state. This is provided for the FieldArray::lookup() | |
816 | * mechanism. */ | |
817 | Field(); | |
818 | ||
819 | /** Destructor for Field */ | |
820 | ~Field(); | |
821 | ||
822 | /** The copy assignment operator for Field. The destination Field is | |
823 | * marked as derived so that destructing that Field does not deallocate | |
824 | * the heap state allocated by the source Field. It is assumed that | |
825 | * non-derived Field instances (the original source of one or more | |
826 | * copies) will out-live all copies. This is reasonable since non-derived | |
827 | * Field instances correspond to architectural state and should be | |
828 | * allocated for the entire simulation. | |
829 | * @param f the source Field for the copy assignment. | |
830 | */ | |
831 | Field &operator=(const Field &f); | |
832 | ||
833 | /** Get the basename of this Field. */ | |
834 | string getBaseName() const; | |
835 | ||
836 | /** Get the fullname of this Field. */ | |
837 | string getFullName() const; | |
838 | ||
839 | /** Get the access type of this field. */ | |
840 | AccessType getAccessType() const { return fieldType->access; } | |
841 | ||
842 | /** Get the start bit number of this field. */ | |
843 | uint getStartBit() const { return fieldType->start; } | |
844 | ||
845 | /** Get the end bit number of this field. */ | |
846 | uint getEndBit() const { return fieldType->end; } | |
847 | ||
848 | /** Get a bit-mask for masking the field when the field is held | |
849 | * in the appropriate bit positions in the associated Register. */ | |
850 | Data getRegMask() const { return fieldType->regMask; } | |
851 | ||
852 | /** Get a bit-mask for masking the field when the lowest bit of | |
853 | * field is held in bit 0 of a Data variable. */ | |
854 | Data getFieldMask() const { return fieldType->fieldMask; } | |
855 | ||
856 | /** Get the value of this Field. This returns the full field value | |
857 | * regardless of the AccessType setting. The value will be shifted | |
858 | * down to bit 0 and masked to the width of the field. This method | |
859 | * is suitable for simulator code that models internal hardware | |
860 | * accesses. | |
861 | */ | |
862 | inline Data get() const | |
863 | { | |
864 | return (reg->regState->value >> fieldType->start) & fieldType->fieldMask; | |
865 | } | |
866 | ||
867 | /** Get the value of this Field. This returns the full field value | |
868 | * regardless of the AccessType setting. The value will be shifted | |
869 | * down to bit 0 and masked to the width of the field. This method | |
870 | * is suitable for simulator code that models internal hardware | |
871 | * accesses. | |
872 | */ | |
873 | inline operator Data() const | |
874 | { | |
875 | return get(); | |
876 | } | |
877 | ||
878 | /** Get the value of this Field without shifting. This returns the full | |
879 | * field value regardless of the AccessType setting. The value will | |
880 | * NOT be shifted but will be left in the same bit position as the field | |
881 | * in the whole Register. The value will be masked to the width of the | |
882 | * field. This method is suitable for simulator code that models | |
883 | * internal hardware accesses. | |
884 | */ | |
885 | inline Data getNoShift() const | |
886 | { | |
887 | return reg->regState->value & fieldType->regMask; | |
888 | } | |
889 | ||
890 | /** Get the reset value of this Field. */ | |
891 | Data getResetValue() const | |
892 | { | |
893 | return fieldType->resetValue; | |
894 | } | |
895 | ||
896 | /** Set the value of this Field. This sets the full field value | |
897 | * regardless of the AccessType setting. The provided value will | |
898 | * be shifted up to the start bit position of the field and masked | |
899 | * to the width of the field. This method is suitable | |
900 | * for simulator code that models internal hardware accesses. | |
901 | * @param d the new Data value for the Field. | |
902 | */ | |
903 | inline void set(Data d) | |
904 | { | |
905 | reg->regState->value = (reg->regState->value & ~fieldType->regMask) | | |
906 | ((d & fieldType->fieldMask) << fieldType->start); | |
907 | reg->regInfo->assigned = true; | |
908 | reg->regInfo->clean = false; | |
909 | } | |
910 | ||
911 | /** Set the value of this Field. This sets the full field value | |
912 | * regardless of the AccessType setting. The provided value will | |
913 | * be shifted up to the start bit position of the field and masked | |
914 | * to the width of the field. This method is suitable | |
915 | * for simulator code that models internal hardware accesses. | |
916 | * @param d the new Data value for the Field. | |
917 | */ | |
918 | inline Field &operator=(Data d) | |
919 | { | |
920 | set(d); | |
921 | return *this; | |
922 | } | |
923 | ||
924 | /** Set the value of this Field without shifting. This sets the full field | |
925 | * value regardless of the AccessType setting. The provided value will | |
926 | * NOT be shifted and is required to already be in the same bit position | |
927 | * as the field in the whole Register. It will be masked to the width of | |
928 | * the field. This method is suitable for simulator code that models | |
929 | * internal hardware accesses. | |
930 | * @param d the new Data value for the Field. | |
931 | */ | |
932 | inline void setNoShift(Data d) | |
933 | { | |
934 | reg->regState->value = (reg->regState->value & ~fieldType->regMask) | | |
935 | (d & fieldType->regMask); | |
936 | reg->regInfo->assigned = true; | |
937 | reg->regInfo->clean = false; | |
938 | } | |
939 | ||
940 | /** Read the value of this Field. This returns the value with | |
941 | * the AccessType of each Field applied appropriately. Note that the | |
942 | * Register call-back mechanism is applied only to whole Register | |
943 | * reads/writes and not Field reads/writes. For this reason, architectural | |
944 | * reads of Register values should use Register::read, and not be broken | |
945 | * down into Field-level reads. | |
946 | */ | |
947 | Data read() | |
948 | { | |
949 | Data d; | |
950 | ||
951 | if (fieldType->access == Access_WO) | |
952 | d = (UNDEFINED_DATA >> fieldType->start) & fieldType->fieldMask; | |
953 | else if (fieldType->access == Access_L) | |
954 | d = 0; | |
955 | else | |
956 | d = (reg->regState->value >> fieldType->start) & fieldType->fieldMask; | |
957 | ||
958 | if (fieldType->access == Access_RC || | |
959 | fieldType->access == Access_RCW1C || | |
960 | fieldType->access == Access_RCW1S) { | |
961 | reg->regState->value &= ~fieldType->regMask; | |
962 | reg->regInfo->assigned = true; | |
963 | reg->regInfo->clean = false; | |
964 | } | |
965 | ||
966 | return d; | |
967 | } | |
968 | ||
969 | /** Write the value of this Field. This writes to the value with | |
970 | * the AccessType of each Field applied appropriately. Note that the | |
971 | * Register call-back mechanism is applied only to whole Register | |
972 | * reads/writes and not Field reads/writes. For this reason, architectural | |
973 | * writes to Register values should use Register::write, and not be broken | |
974 | * down into Field-level writes. | |
975 | * @param d the new Data value for the Field. | |
976 | */ | |
977 | void write(Data d) | |
978 | { | |
979 | if (fieldType->access == Access_RW1C || | |
980 | fieldType->access == Access_RCW1C) { | |
981 | Data clearMask = (d & fieldType->fieldMask) << fieldType->start; | |
982 | if (clearMask != 0) { | |
983 | reg->regState->value &= ~clearMask; | |
984 | reg->regInfo->assigned = true; | |
985 | reg->regInfo->clean = false; | |
986 | } | |
987 | } | |
988 | else if (fieldType->access == Access_RW1S || | |
989 | fieldType->access == Access_RCW1S) { | |
990 | Data setMask = (d & fieldType->fieldMask) << fieldType->start; | |
991 | if (setMask != 0) { | |
992 | reg->regState->value |= setMask; | |
993 | reg->regInfo->assigned = true; | |
994 | reg->regInfo->clean = false; | |
995 | } | |
996 | } | |
997 | else if (fieldType->access != Access_RO) { | |
998 | reg->regState->value = (reg->regState->value & ~fieldType->regMask) | | |
999 | ((d & fieldType->fieldMask) << fieldType->start); | |
1000 | reg->regInfo->assigned = true; | |
1001 | reg->regInfo->clean = false; | |
1002 | } | |
1003 | } | |
1004 | ||
1005 | private: | |
1006 | bool derived; | |
1007 | Register *reg; | |
1008 | FieldType *fieldType; | |
1009 | }; | |
1010 | ||
1011 | /** @} */ | |
1012 | ||
1013 | #endif |