dev-arm: Add VRAM to VExpress_GEM5_Base
[gem5.git] / src / dev / reg_bank.hh
1 /*
2 * Copyright 2020 Google, Inc.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met: redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer;
8 * redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution;
11 * neither the name of the copyright holders nor the names of its
12 * contributors may be used to endorse or promote products derived from
13 * this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #ifndef __DEV_REG_BANK_HH__
29 #define __DEV_REG_BANK_HH__
30
31 #include <algorithm>
32 #include <bitset>
33 #include <cstring>
34 #include <functional>
35 #include <initializer_list>
36 #include <iostream>
37 #include <map>
38 #include <sstream>
39 #include <utility>
40
41 #include "base/bitfield.hh"
42 #include "base/logging.hh"
43 #include "base/types.hh"
44 #include "sim/byteswap.hh"
45 #include "sim/serialize_handlers.hh"
46
47 /*
48 * Device models often have contiguous banks of registers which can each
49 * have unique and arbitrary behavior when they are completely or partially
50 * read or written. Historically it's been up to each model to map an access
51 * which covers an arbitrary portion of that register bank down to individual
52 * registers. It must handle cases where registers are only partially accessed,
53 * or where multiple registers are accessed at the same time, or a combination
54 * of both.
55 *
56 *
57 * == RegisterBank ==
58 *
59 * The RegisterBank class(es), defined below, handle that mapping, and let the
60 * device model focus on defining what each of the registers actually do when
61 * read or written. Once it's set up, it has two primary interfaces which
62 * access the registers it contains:
63 *
64 * void read(Addr addr, void *buf, Addr bytes);
65 * void write(Addr addr, const void *buf, Addr bytes);
66 *
67 * These two methods will handle a read or write contained within the register
68 * bank starting at address "addr". The data that will be written or has been
69 * read is pointed to by "buf", and is "bytes" bytes long.
70 *
71 * These methods are virtual, so if you need to implement extra rules, like
72 * for instance that registers can only be accessed one at a time, that
73 * accesses have to be aligned, have to access complete registers, etc, that
74 * can be added in a subclass.
75 *
76 * Additionally, each RegisterBank has a name and a base address which is
77 * passed into the constructor. The meaning of the "base" value can be whatever
78 * makes sense for your device, and is considered the lowest address contained
79 * in the bank. The value could be the offset of this bank of registers within
80 * the device itself, with the device's own offset subtracted out before read
81 * or write are called. It could alternatively be the base address of the
82 * entire device, with the address from accesses passed into read or write
83 * unmodified.
84 *
85 * To add actual registers to the RegisterBank (discussed below), you can use
86 * either the addRegister method which adds a single register, or addRegisters
87 * which adds an initializer list of them all at once. The register will be
88 * appended to the end of the bank as they're added, contiguous to the
89 * existing registers. The size of the bank is automatically accumulated as
90 * registers are added.
91 *
92 * The base(), size() and name() methods can be used to access each of those
93 * read only properties of the RegisterBank instance.
94 *
95 * While the RegisterBank itself doesn't have any data in it directly and so
96 * has no endianness, it's very likely all the registers within it will have
97 * the same endinanness. The bank itself therefore has a default endianness
98 * which, unless specified otherwise, will be passed on to the register types
99 * within it. The RegisterBank class is templated on its endianness. There are
100 * RegisterBankLE and RegisterBankBE aliases to make it a little easier to
101 * refer to one or the other version.
102 *
103 *
104 * == Register interface ==
105 *
106 * Every register in a RegisterBank needs to inherit, directly or indirectly,
107 * from the RegisterBase class. Each register must have a name (for debugging),
108 * and a well defined size. The following methods define the interface the
109 * register bank uses to access the register, and where the register can
110 * implement its special behaviors:
111 *
112 * void read(void *buf);
113 * void read(void *buf, off_t offset, size_t bytes);
114 *
115 * void write(const void *buf);
116 * void write(const void *buf, off_t offset, size_t bytes);
117 *
118 * The single argument versions of these methods completely overwrite the
119 * register's contents with whatever is pointed to by buf.
120 *
121 * The version which also takes "offset" and "bytes" arguments reads or writes
122 * only a portion of the register, starting "offset" bytes from the start of
123 * the register, and writing or reading the next "bytes" bytes.
124 *
125 * Each register also needs to implement serialize or unserialize methods
126 * which make it accessible to the checkpointing mechanism. If a register
127 * doesn't need to be serialized (for instance if it has a fixed value) then
128 * it still has to implement these methods, but they don't have to actually do
129 * anything.
130 *
131 *
132 * == Basic Register types ==
133 *
134 * Some simple register types have been defined which handle basic, common
135 * behaviors found in many devices:
136 *
137 * = RegisterRaz and RegisterRao =
138 *
139 * RegisterRaz (read as zero) and RegisterRao (read as one) will ignore writes,
140 * and will return all zeroes or ones, respectively, when read. These can have
141 * arbitrary alignment and size, and can be used for, for instance,
142 * unimplemented registers that still need to take up a certain amount of
143 * space, or for gaps between registers which still need to handle accesses
144 * even though they don't do anything or hold any data.
145 *
146 * For instance, a device might have several regions of registers which are
147 * aligned on different boundaries, but which might not take up all of the
148 * space in each region. The extra space can be filled with a RegisterRaz or
149 * RegisterRao, making it possible to implement all the registers as a single
150 * bank.
151 *
152 * If you need a register with a different fill pattern, you can subclass the
153 * RegisterRoFill type and implement its "fill" method. This should behave
154 * like the three argument form of the read() method, described above.
155 *
156 * = RegisterBuf and RegisterLBuf =
157 *
158 * These two types act like inert blobs of storage. They don't have any
159 * special behavior and can have any arbitrary size like the RegisterRao and
160 * RegisterRaz types above, but these registers actually store what's written
161 * to them.
162 *
163 * The RegisterBuf type acts as an interface to a buffer stored elsewhere. That
164 * makes it possible to, for instance, alias the same buffer to different parts
165 * of the register space, or to expose some other object which needs to exist
166 * outside of the register bank for some reason.
167 *
168 * The RegisterLBuf does the same thing, except it uses a local buffer it
169 * manages. That makes it a little easier to work with if you don't need the
170 * flexibility of the RegisterBuf type.
171 *
172 *
173 * == Typed Registers ==
174 *
175 * The Register template class is for more complex registers with side effects,
176 * and/or which hold structured data. The template arguments define what type
177 * the register should hold, and also its endianness.
178 *
179 * = Access handlers =
180 *
181 * Instead of subclassing the Register<Data> type and redefining its read/write
182 * methods, reads and writes are implemented using replaceable handlers with
183 * these signatures:
184 *
185 * Data read(Register<Data> &reg);
186 * Data partialRead(Register<Data> &reg, int first, int last);
187 * void write(Register<Data> &reg, const Data &value);
188 * void partialWrite(Register<Data> &reg, const Data &value,
189 * int first, int last);
190 *
191 * The "partial" version of these handlers take "first" and "last" arguments
192 * which specify what bits of the register to modify. They should be
193 * interpreted like the same arguments in base/bitfield.hh. The endianness
194 * of the register will have already been dealt with by the time the handler
195 * is called.
196 *
197 * The read and partialRead handlers should generate whatever value reading the
198 * register should return, based on (or not based on) the state of "reg". The
199 * partial handler should keep the bits it returns in place. For example, if
200 * bits 15-8 are read from a 16 bit register with the value 0x1234, it should
201 * return 0x1200, not 0x0012.
202 *
203 * The write and partialWrite handlers work the same way, except in they write
204 * instead of read. They are responsible for updating the value in reg in
205 * whatever way and to whatever value is appropriate, based on
206 * (or not based on) the value of "value" and the state of "reg".
207 *
208 * The default implementations of the read and write handlers simply return or
209 * update the value stored in reg. The default partial read calls the read
210 * handler (which may not be the default), and trims down the data as required.
211 * The default partial write handler calls the read handler (which may not be
212 * the default), updates the value as requested, and then calls the write
213 * handler (which may not be the default).
214 *
215 * Overriding the partial read or write methods might be necessary if reads or
216 * writes have side effects which should affect only the part of the register
217 * read or written. For instance, there might be some status bits which will
218 * be cleared when accessed. Only the bits which were actually accessed should
219 * be affected, even if they're grouped together logically with the other bits
220 * in a single register.
221 *
222 * To set your own handlers, you can use the "reader", "writer",
223 * "partialReader", and "partialWriter" methods. Each of these takes a single
224 * callable argument (lambda, functor, function pointer, etc.) which will
225 * replace the current corresponding handler.
226 *
227 * These methods all return a reference to the current Register so that they
228 * can be strung together without having to respecify what object you're
229 * modifying over and over again.
230 *
231 * There are also versions of these which will set up methods on some object as
232 * the handlers. These take a pointer to whatever object will handle the call,
233 * and a member function pointer to the method that will actually implement
234 * the handler. This can be used if, for instance, the registers are all
235 * members of a RegisterBank subclass, and need to call methods on their
236 * parent class to actually implement the behavior. These methods must have
237 * the same signature as above, with the exception that they are methods and
238 * not bare functions.
239 *
240 * When updating the register's value in custom write or partialWrite handlers,
241 * be sure to use the "update" method which will honor read only bits. There
242 * is an alternative form of update which also takes a custom bitmask, if you
243 * need to update bits other than the normally writeable ones.
244 *
245 * = Read only bits =
246 *
247 * Often registers have bits which are fixed and not affected by writes. To
248 * specify which bits are writeable, use the "writeable" method which takes a
249 * single argument the same type as the type of the register. It should hold a
250 * bitmask where a 1 bit can be written, and a 0 cannot. Calling writeable with
251 * no arguments will return the current bitmask.
252 *
253 * A shorthand "readonly" method marks all bits as read only.
254 *
255 * Both methods return a reference to the current Register so they can be
256 * strung together into a sequence when configuring it.
257 *
258 * = Underlying data and serialization =
259 *
260 * The "get" method returns a reference to the underlying storage inside the
261 * register. That can be used to manually update the entire register, even bits
262 * which are normally read only, or for structured data, to access members of
263 * the underlying data type.
264 *
265 * For instance, if the register holds a BitUnion, you could use the get()
266 * method to access the bitfields within it:
267 *
268 * reg.get().bitfieldA = reg.get().bitfieldB;
269 *
270 * The serialize and unserialize methods for these types will pass through the
271 * underlying data within the register. For instance, when serializing a
272 * Register<Foo>, the value in the checkpoint will be the same as if you had
273 * serialized a Foo directly, with the value stored in the register.
274 *
275 * = Aliases =
276 *
277 * Some convenient aliases have been defined for frequently used versions of
278 * the Register class. These are
279 *
280 * Register(8|16|32|64)(LE|BE|)
281 *
282 * Where the underlying type of the register is a uint8_t, uint16_t, etc, and
283 * the endianness is little endian, big endian, or whatever the default is for
284 * the RegisterBank.
285 */
286
287 // Common bases to make it easier to identify both endiannesses at once.
288 class RegisterBankBase
289 {
290 public:
291 class RegisterBaseBase {};
292 };
293
294 template <ByteOrder BankByteOrder>
295 class RegisterBank : public RegisterBankBase
296 {
297 public:
298 // Static helper methods for implementing register types.
299 template <typename Data>
300 static constexpr Data
301 readWithMask(const Data &value, const Data &bitmask)
302 {
303 return value & bitmask;
304 }
305
306 template <typename Data>
307 static constexpr Data
308 writeWithMask(const Data &old, const Data &value, const Data &bitmask)
309 {
310 return readWithMask(
311 old, (Data)~bitmask) | readWithMask(value, bitmask);
312 }
313
314 class RegisterBase : public RegisterBankBase::RegisterBaseBase
315 {
316 protected:
317 const std::string _name;
318 size_t _size = 0;
319
320 public:
321 constexpr RegisterBase(const std::string &new_name, size_t new_size) :
322 _name(new_name), _size(new_size)
323 {}
324 virtual ~RegisterBase() {}
325
326 // Read the register's name.
327 virtual const std::string &name() const { return _name; }
328
329 // Read the register's size in bytes.
330 size_t size() const { return _size; }
331
332 // Perform a read on the register.
333 virtual void read(void *buf) = 0;
334 virtual void read(void *buf, off_t offset, size_t bytes) = 0;
335
336 // Perform a write on the register.
337 virtual void write(const void *buf) = 0;
338 virtual void write(const void *buf, off_t offset, size_t bytes) = 0;
339
340 // Methods for implementing serialization for checkpoints.
341 virtual void serialize(std::ostream &os) const = 0;
342 virtual bool unserialize(const std::string &s) = 0;
343 };
344
345 // Filler registers which return a fixed pattern.
346 class RegisterRoFill : public RegisterBase
347 {
348 protected:
349 constexpr RegisterRoFill(
350 const std::string &new_name, size_t new_size) :
351 RegisterBase(new_name, new_size)
352 {}
353
354 virtual void fill(void *buf, off_t offset, size_t bytes) = 0;
355
356 public:
357 // Ignore writes.
358 void write(const void *buf) override {}
359 void write(const void *buf, off_t offset, size_t bytes) override {}
360
361 // Use fill() to handle reads.
362 void read(void *buf) override { fill(buf, 0, this->size()); }
363 void
364 read(void *buf, off_t offset, size_t bytes) override
365 {
366 fill(buf, offset, bytes);
367 }
368
369 void serialize(std::ostream &os) const override {}
370 bool unserialize(const std::string &s) override { return true; }
371 };
372
373 // Register which reads as all zeroes.
374 class RegisterRaz : public RegisterRoFill
375 {
376 protected:
377 void
378 fill(void *buf, off_t offset, size_t bytes) override
379 {
380 bzero(buf, bytes);
381 }
382
383 public:
384 RegisterRaz(const std::string &new_name, size_t new_size) :
385 RegisterRoFill(new_name, new_size)
386 {}
387 };
388
389 // Register which reads as all ones.
390 class RegisterRao : public RegisterRoFill
391 {
392 protected:
393 void
394 fill(void *buf, off_t offset, size_t bytes) override
395 {
396 memset(buf, 0xff, bytes);
397 }
398
399 public:
400 RegisterRao(const std::string &new_name, size_t new_size) :
401 RegisterRoFill(new_name, new_size)
402 {}
403 };
404
405 // Register which acts as a simple buffer.
406 class RegisterBuf : public RegisterBase
407 {
408 private:
409 void *_ptr = nullptr;
410
411 public:
412 RegisterBuf(const std::string &new_name, void *ptr, size_t bytes) :
413 RegisterBase(new_name, bytes), _ptr(ptr)
414 {}
415
416 void write(const void *buf) override { write(buf, 0, this->size()); }
417 void
418 write(const void *buf, off_t offset, size_t bytes) override
419 {
420 assert(offset + bytes <= this->size());
421 memcpy((uint8_t *)_ptr + offset, buf, bytes);
422 }
423
424 void read(void *buf) override { read(buf, 0, this->size()); }
425 void
426 read(void *buf, off_t offset, size_t bytes) override
427 {
428 assert(offset + bytes <= this->size());
429 memcpy(buf, (uint8_t *)_ptr + offset, bytes);
430 }
431
432 // The buffer's owner is responsible for serializing it.
433 void serialize(std::ostream &os) const override {}
434 bool unserialize(const std::string &s) override { return true; }
435 };
436
437 // Same as above, but which keeps its storage locally.
438 template <int BufBytes>
439 class RegisterLBuf : public RegisterBuf
440 {
441 public:
442 std::array<uint8_t, BufBytes> buffer;
443
444 RegisterLBuf(const std::string &new_name) :
445 RegisterBuf(new_name, buffer.data(), BufBytes)
446 {}
447
448 void
449 serialize(std::ostream &os) const override
450 {
451 if (BufBytes)
452 ShowParam<uint8_t>::show(os, buffer[0]);
453 for (int i = 1; i < BufBytes; i++) {
454 os << " ";
455 ShowParam<uint8_t>::show(os, buffer[i]);
456 }
457 }
458
459 bool
460 unserialize(const std::string &s) override
461 {
462 std::vector<std::string> tokens;
463 std::istringstream is(s);
464
465 std::string token;
466 while (is >> token)
467 tokens.push_back(token);
468
469 if (tokens.size() != BufBytes) {
470 warn("Size mismatch unserialing %s, expected %d, got %d",
471 this->name(), BufBytes, tokens.size());
472 return false;
473 }
474
475 for (int i = 0; i < BufBytes; i++) {
476 if (!ParseParam<uint8_t>::parse(tokens[i], buffer[i]))
477 return false;
478 }
479
480 return true;
481 }
482 };
483
484 template <typename Data, ByteOrder RegByteOrder=BankByteOrder>
485 class Register : public RegisterBase
486 {
487 protected:
488 using This = Register<Data, RegByteOrder>;
489
490 public:
491 using ReadFunc = std::function<Data (This &reg)>;
492 using PartialReadFunc = std::function<
493 Data (This &reg, int first, int last)>;
494 using WriteFunc = std::function<void (This &reg, const Data &value)>;
495 using PartialWriteFunc = std::function<
496 void (This &reg, const Data &value, int first, int last)>;
497
498 private:
499 Data _data = {};
500 Data _writeMask = mask(sizeof(Data) * 8);
501
502 ReadFunc _reader = defaultReader;
503 WriteFunc _writer = defaultWriter;
504 PartialWriteFunc _partialWriter = defaultPartialWriter;
505 PartialReadFunc _partialReader = defaultPartialReader;
506
507 protected:
508 static Data defaultReader(This &reg) { return reg.get(); }
509
510 static Data
511 defaultPartialReader(This &reg, int first, int last)
512 {
513 return mbits(reg._reader(reg), first, last);
514 }
515
516 static void
517 defaultWriter(This &reg, const Data &value)
518 {
519 reg.update(value);
520 }
521
522 static void
523 defaultPartialWriter(This &reg, const Data &value, int first, int last)
524 {
525 reg._writer(reg, writeWithMask<Data>(reg._reader(reg), value,
526 mask(first, last)));
527 }
528
529 constexpr Data
530 htoreg(Data data)
531 {
532 switch (RegByteOrder) {
533 case ByteOrder::big:
534 return htobe(data);
535 case ByteOrder::little:
536 return htole(data);
537 default:
538 panic("Unrecognized byte order %d.", (unsigned)RegByteOrder);
539 }
540 }
541
542 constexpr Data
543 regtoh(Data data)
544 {
545 switch (RegByteOrder) {
546 case ByteOrder::big:
547 return betoh(data);
548 case ByteOrder::little:
549 return letoh(data);
550 default:
551 panic("Unrecognized byte order %d.", (unsigned)RegByteOrder);
552 }
553 }
554
555 public:
556
557 /*
558 * Interface for setting up the register.
559 */
560
561 // Constructor which lets data default initialize itself.
562 constexpr Register(const std::string &new_name) :
563 RegisterBase(new_name, sizeof(Data))
564 {}
565
566 // Constructor and move constructor with an initial data value.
567 constexpr Register(const std::string &new_name, const Data &new_data) :
568 RegisterBase(new_name, sizeof(Data)), _data(new_data)
569 {}
570 constexpr Register(const std::string &new_name,
571 const Data &&new_data) :
572 RegisterBase(new_name, sizeof(Data)), _data(new_data)
573 {}
574
575 // Set which bits of the register are writeable.
576 constexpr This &
577 writeable(const Data &new_mask)
578 {
579 _writeMask = new_mask;
580 return *this;
581 }
582
583 // Set the register as read only.
584 constexpr This &readonly() { return writeable(0); }
585
586 // Set the callables which handles reads or writes.
587 // The default reader just returns the register value.
588 // The default writer uses the write mask to update the register value.
589 constexpr This &
590 reader(const ReadFunc &new_reader)
591 {
592 _reader = new_reader;
593 return *this;
594 }
595 template <class Parent, class... Args>
596 constexpr This &
597 reader(Parent *parent, Data (Parent::*nr)(Args... args))
598 {
599 auto wrapper = [parent, nr](Args&&... args) -> Data {
600 return (parent->*nr)(std::forward<Args>(args)...);
601 };
602 return reader(wrapper);
603 }
604 constexpr This &
605 writer(const WriteFunc &new_writer)
606 {
607 _writer = new_writer;
608 return *this;
609 }
610 template <class Parent, class... Args>
611 constexpr This &
612 writer(Parent *parent, void (Parent::*nw)(Args... args))
613 {
614 auto wrapper = [parent, nw](Args&&... args) {
615 (parent->*nw)(std::forward<Args>(args)...);
616 };
617 return writer(wrapper);
618 }
619
620 // Set the callables which handle reads or writes. These may need to
621 // be handled specially if, for instance, accessing bits outside of
622 // the enables would have side effects that shouldn't happen.
623 //
624 // The default partial reader just uses the byte enables to mask off
625 // bits that are not being read.
626 //
627 // The default partial writer reads the current value of the register,
628 // uses the byte enables to update only the bytes that are changing,
629 // and then writes the result back to the register.
630 constexpr This &
631 partialReader(const PartialReadFunc &new_reader)
632 {
633 _partialReader = new_reader;
634 return *this;
635 }
636 template <class Parent, class... Args>
637 constexpr This &
638 partialReader(Parent *parent, Data (Parent::*nr)(Args... args))
639 {
640 auto wrapper = [parent, nr](Args&&... args) -> Data {
641 return (parent->*nr)(std::forward<Args>(args)...);
642 };
643 return partialReader(wrapper);
644 }
645 constexpr This &
646 partialWriter(const PartialWriteFunc &new_writer)
647 {
648 _partialWriter = new_writer;
649 return *this;
650 }
651 template <class Parent, class... Args>
652 constexpr This &
653 partialWriter(Parent *parent, void (Parent::*nw)(Args... args))
654 {
655 auto wrapper = [parent, nw](Args&&... args) {
656 return (parent->*nw)(std::forward<Args>(args)...);
657 };
658 return partialWriter(wrapper);
659 }
660
661
662 /*
663 * Interface for accessing the register's state, for use by the
664 * register's helper functions and the register bank.
665 */
666
667 const Data &writeable() const { return _writeMask; }
668
669 // Directly access the underlying data value.
670 const Data &get() const { return _data; }
671 Data &get() { return _data; }
672
673 // Update data while applying a mask.
674 void
675 update(const Data &new_data, const Data &bitmask)
676 {
677 _data = writeWithMask(_data, new_data, bitmask);
678 }
679 // This version uses the default write mask.
680 void
681 update(const Data &new_data)
682 {
683 _data = writeWithMask(_data, new_data, _writeMask);
684 }
685
686
687 /*
688 * Interface for reading/writing the register, for use by the
689 * register bank.
690 */
691
692 // Perform a read on the register.
693 void
694 read(void *buf) override
695 {
696 Data data = htoreg(_reader(*this));
697 memcpy(buf, (uint8_t *)&data, sizeof(data));
698 }
699
700 void
701 read(void *buf, off_t offset, size_t bytes) override
702 {
703 // Move the region we're reading to be little endian, since that's
704 // what gem5 uses internally in BitUnions, masks, etc.
705 const off_t host_off = (RegByteOrder != ByteOrder::little) ?
706 sizeof(Data) - (offset + bytes) : offset;
707
708 const int first = (host_off + bytes) * 8 - 1;
709 const int last = host_off * 8;
710 Data data = htoreg(_partialReader(*this, first, last));
711
712 memcpy(buf, (uint8_t *)&data + offset, bytes);
713 }
714
715 // Perform a write on the register.
716 void
717 write(const void *buf) override
718 {
719 Data data;
720 memcpy((uint8_t *)&data, buf, sizeof(data));
721 data = regtoh(data);
722 _writer(*this, data);
723 }
724
725 void
726 write(const void *buf, off_t offset, size_t bytes) override
727 {
728 Data data = {};
729 memcpy((uint8_t *)&data + offset, buf, bytes);
730
731 data = regtoh(data);
732
733 // Move the region we're reading to be little endian, since that's
734 // what gem5 uses internally in BitUnions, masks, etc.
735 const off_t host_off = (RegByteOrder != ByteOrder::little) ?
736 sizeof(Data) - (offset + bytes) : offset;
737
738 const int first = (host_off + bytes) * 8 - 1;
739 const int last = host_off * 8;
740 _partialWriter(*this, data, first, last);
741 }
742
743 // Serialize our data using existing mechanisms.
744 void
745 serialize(std::ostream &os) const override
746 {
747 ShowParam<Data>::show(os, get());
748 }
749
750 bool
751 unserialize(const std::string &s) override
752 {
753 return ParseParam<Data>::parse(s, get());
754 }
755 };
756
757 private:
758 std::map<Addr, std::reference_wrapper<RegisterBase>> _offsetMap;
759
760 Addr _base = 0;
761 Addr _size = 0;
762 const std::string _name;
763
764 public:
765
766 using Register8 = Register<uint8_t>;
767 using Register8LE = Register<uint8_t, ByteOrder::little>;
768 using Register8BE = Register<uint8_t, ByteOrder::big>;
769 using Register16 = Register<uint16_t>;
770 using Register16LE = Register<uint16_t, ByteOrder::little>;
771 using Register16BE = Register<uint16_t, ByteOrder::big>;
772 using Register32 = Register<uint32_t>;
773 using Register32LE = Register<uint32_t, ByteOrder::little>;
774 using Register32BE = Register<uint32_t, ByteOrder::big>;
775 using Register64 = Register<uint64_t>;
776 using Register64LE = Register<uint64_t, ByteOrder::little>;
777 using Register64BE = Register<uint64_t, ByteOrder::big>;
778
779
780 constexpr RegisterBank(const std::string &new_name, Addr new_base) :
781 _base(new_base), _name(new_name)
782 {}
783
784 virtual ~RegisterBank() {}
785
786 void
787 addRegisters(
788 std::initializer_list<std::reference_wrapper<RegisterBase>> regs)
789 {
790 panic_if(regs.size() == 0, "Adding an empty list of registers to %s?",
791 name());
792 for (auto &reg: regs) {
793 _offsetMap.emplace(_base + _size, reg);
794 _size += reg.get().size();
795 }
796 }
797
798 void addRegister(RegisterBase &reg) { addRegisters({reg}); }
799
800 Addr base() const { return _base; }
801 Addr size() const { return _size; }
802 const std::string &name() const { return _name; }
803
804 virtual void
805 read(Addr addr, void *buf, Addr bytes)
806 {
807 uint8_t *ptr = (uint8_t *)buf;
808 // Number of bytes we've transferred.
809 Addr done = 0;
810
811 panic_if(addr - base() + bytes > size(),
812 "Out of bounds read in register bank %s, address %#x, size %d.",
813 name(), addr, bytes);
814
815 auto it = _offsetMap.lower_bound(addr);
816 if (it == _offsetMap.end() || it->first > addr)
817 it--;
818
819 if (it->first < addr) {
820 RegisterBase &reg = it->second.get();
821 // Skip at least the beginning of the first register.
822
823 // Figure out what parts of it we're accessing.
824 const off_t reg_off = addr - it->first;
825 const size_t reg_bytes = std::min(reg.size() - reg_off,
826 bytes - done);
827
828 // Actually do the access.
829 reg.read(ptr, reg_off, reg_bytes);
830 done += reg_bytes;
831 it++;
832
833 // Was that everything?
834 if (done == bytes)
835 return;
836 }
837
838 while (true) {
839 RegisterBase &reg = it->second.get();
840
841 const size_t reg_size = reg.size();
842 const size_t remaining = bytes - done;
843
844 if (remaining == reg_size) {
845 // A complete register read, and then we're done.
846 reg.read(ptr + done);
847 return;
848 } else if (remaining > reg_size) {
849 // A complete register read, with more to go.
850 reg.read(ptr + done);
851 done += reg_size;
852 it++;
853 } else {
854 // Skip the end of the register, and then we're done.
855 reg.read(ptr + done, 0, remaining);
856 return;
857 }
858 }
859 }
860
861 virtual void
862 write(Addr addr, const void *buf, Addr bytes)
863 {
864 const uint8_t *ptr = (const uint8_t *)buf;
865 // Number of bytes we've transferred.
866 Addr done = 0;
867
868 panic_if(addr - base() + bytes > size(),
869 "Out of bounds write in register bank %s, address %#x, size %d.",
870 name(), addr, bytes);
871
872 auto it = _offsetMap.lower_bound(addr);
873 if (it == _offsetMap.end() || it->first > addr)
874 it--;
875
876 if (it->first < addr) {
877 RegisterBase &reg = it->second.get();
878 // Skip at least the beginning of the first register.
879
880 // Figure out what parts of it we're accessing.
881 const off_t reg_off = addr - it->first;
882 const size_t reg_bytes = std::min(reg.size() - reg_off,
883 bytes - done);
884
885 // Actually do the access.
886 reg.write(ptr, reg_off, reg_bytes);
887 done += reg_bytes;
888 it++;
889
890 // Was that everything?
891 if (done == bytes)
892 return;
893 }
894
895 while (true) {
896 RegisterBase &reg = it->second.get();
897
898 const size_t reg_size = reg.size();
899 const size_t remaining = bytes - done;
900
901 if (remaining == reg_size) {
902 // A complete register write, and then we're done.
903 reg.write(ptr + done);
904 return;
905 } else if (remaining > reg_size) {
906 // A complete register write, with more to go.
907 reg.write(ptr + done);
908 done += reg_size;
909 it++;
910 } else {
911 // Skip the end of the register, and then we're done.
912 reg.write(ptr + done, 0, remaining);
913 return;
914 }
915 }
916 }
917 };
918
919 using RegisterBankLE = RegisterBank<ByteOrder::little>;
920 using RegisterBankBE = RegisterBank<ByteOrder::big>;
921
922 // Delegate serialization to the individual RegisterBase subclasses.
923 template <class T>
924 struct ParseParam<T, std::enable_if_t<std::is_base_of<
925 typename RegisterBankBase::RegisterBaseBase, T>::value>>
926 {
927 static bool
928 parse(const std::string &s, T &value)
929 {
930 return value.unserialize(s);
931 }
932 };
933
934 template <class T>
935 struct ShowParam<T, std::enable_if_t<std::is_base_of<
936 typename RegisterBankBase::RegisterBaseBase, T>::value>>
937 {
938 static void
939 show(std::ostream &os, const T &value)
940 {
941 value.serialize(os);
942 }
943 };
944
945 #endif // __DEV_REG_BANK_HH__