gem5  [DEVELOP-FOR-23.0]
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
reg_bank.hh
Go to the documentation of this file.
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 <cassert>
34 #include <cstdint>
35 #include <cstring>
36 #include <functional>
37 #include <initializer_list>
38 #include <iostream>
39 #include <map>
40 #include <optional>
41 #include <sstream>
42 #include <utility>
43 
44 #include "base/bitfield.hh"
45 #include "base/logging.hh"
46 #include "base/types.hh"
47 #include "sim/byteswap.hh"
49 
50 /*
51  * Device models often have contiguous banks of registers which can each
52  * have unique and arbitrary behavior when they are completely or partially
53  * read or written. Historically it's been up to each model to map an access
54  * which covers an arbitrary portion of that register bank down to individual
55  * registers. It must handle cases where registers are only partially accessed,
56  * or where multiple registers are accessed at the same time, or a combination
57  * of both.
58  *
59  *
60  * == RegisterBank ==
61  *
62  * The RegisterBank class(es), defined below, handle that mapping, and let the
63  * device model focus on defining what each of the registers actually do when
64  * read or written. Once it's set up, it has two primary interfaces which
65  * access the registers it contains:
66  *
67  * void read(Addr addr, void *buf, Addr bytes);
68  * void write(Addr addr, const void *buf, Addr bytes);
69  *
70  * These two methods will handle a read or write contained within the register
71  * bank starting at address "addr". The data that will be written or has been
72  * read is pointed to by "buf", and is "bytes" bytes long.
73  *
74  * These methods are virtual, so if you need to implement extra rules, like
75  * for instance that registers can only be accessed one at a time, that
76  * accesses have to be aligned, have to access complete registers, etc, that
77  * can be added in a subclass.
78  *
79  * Additionally, each RegisterBank has a name and a base address which is
80  * passed into the constructor. The meaning of the "base" value can be whatever
81  * makes sense for your device, and is considered the lowest address contained
82  * in the bank. The value could be the offset of this bank of registers within
83  * the device itself, with the device's own offset subtracted out before read
84  * or write are called. It could alternatively be the base address of the
85  * entire device, with the address from accesses passed into read or write
86  * unmodified.
87  *
88  * The base(), size() and name() methods can be used to access each of those
89  * read only properties of the RegisterBank instance.
90  *
91  * To add actual registers to the RegisterBank (discussed below), you can use
92  * either the addRegister method which adds a single register, or addRegisters
93  * which adds an initializer list of them all at once. The register will be
94  * appended to the end of the bank as they're added, contiguous to the
95  * existing registers. The size of the bank is automatically accumulated as
96  * registers are added.
97  *
98  * When adding a lot of registers, you might accidentally add an extra,
99  * or accidentally skip one in a long list. Because the offset is handled
100  * automatically, some of your registers might end up shifted higher or lower
101  * than you expect. To help mitigate this, you can set what offset you expect
102  * a register to have by specifying it as an offset, register pair.
103  *
104  * addRegisters({{0x1000, reg0}, reg1, reg2});
105  *
106  * If the register would end up at a different offset, gem5 will panic. You
107  * can also leave off the register if you want to just check the offset, for
108  * instance between groups of registers.
109  *
110  * addRegisters({reg0, reg1, reg2, 0x100c})
111  *
112  * While the RegisterBank itself doesn't have any data in it directly and so
113  * has no endianness, it's very likely all the registers within it will have
114  * the same endinanness. The bank itself therefore has a default endianness
115  * which, unless specified otherwise, will be passed on to the register types
116  * within it. The RegisterBank class is templated on its endianness. There are
117  * RegisterBankLE and RegisterBankBE aliases to make it a little easier to
118  * refer to one or the other version.
119  *
120  * A RegisterBank also has a reset() method which will (by default) call the
121  * reset() method on each register within it. This method is virtual, and so
122  * can be overridden if something additional or different needs to be done to
123  * reset the hardware model.
124  *
125  *
126  * == Register interface ==
127  *
128  * Every register in a RegisterBank needs to inherit, directly or indirectly,
129  * from the RegisterBase class. Each register must have a name (for debugging),
130  * and a well defined size. The following methods define the interface the
131  * register bank uses to access the register, and where the register can
132  * implement its special behaviors:
133  *
134  * void read(void *buf);
135  * void read(void *buf, off_t offset, size_t bytes);
136  *
137  * void write(const void *buf);
138  * void write(const void *buf, off_t offset, size_t bytes);
139  *
140  * The single argument versions of these methods completely overwrite the
141  * register's contents with whatever is pointed to by buf.
142  *
143  * The version which also takes "offset" and "bytes" arguments reads or writes
144  * only a portion of the register, starting "offset" bytes from the start of
145  * the register, and writing or reading the next "bytes" bytes.
146  *
147  * Each register also needs to implement serialize or unserialize methods
148  * which make it accessible to the checkpointing mechanism. If a register
149  * doesn't need to be serialized (for instance if it has a fixed value) then
150  * it still has to implement these methods, but they don't have to actually do
151  * anything.
152  *
153  * Each register also has a "reset" method, which will reset the register as
154  * if its containing device is being reset. By default, this will just restore
155  * the initial value of the register, but can be overridden to implement
156  * additional behavior like resetting other aspects of the device which are
157  * controlled by the value of the register.
158  *
159  *
160  * == Basic Register types ==
161  *
162  * Some simple register types have been defined which handle basic, common
163  * behaviors found in many devices:
164  *
165  * = RegisterRaz and RegisterRao =
166  *
167  * RegisterRaz (read as zero) and RegisterRao (read as one) will ignore writes,
168  * and will return all zeroes or ones, respectively, when read. These can have
169  * arbitrary alignment and size, and can be used for, for instance,
170  * unimplemented registers that still need to take up a certain amount of
171  * space, or for gaps between registers which still need to handle accesses
172  * even though they don't do anything or hold any data.
173  *
174  * For instance, a device might have several regions of registers which are
175  * aligned on different boundaries, but which might not take up all of the
176  * space in each region. The extra space can be filled with a RegisterRaz or
177  * RegisterRao, making it possible to implement all the registers as a single
178  * bank.
179  *
180  * If you need a register with a different fill pattern, you can subclass the
181  * RegisterRoFill type and implement its "fill" method. This should behave
182  * like the three argument form of the read() method, described above.
183  *
184  * = RegisterBuf and RegisterLBuf =
185  *
186  * These two types act like inert blobs of storage. They don't have any
187  * special behavior and can have any arbitrary size like the RegisterRao and
188  * RegisterRaz types above, but these registers actually store what's written
189  * to them.
190  *
191  * The RegisterBuf type acts as an interface to a buffer stored elsewhere. That
192  * makes it possible to, for instance, alias the same buffer to different parts
193  * of the register space, or to expose some other object which needs to exist
194  * outside of the register bank for some reason.
195  *
196  * The RegisterLBuf does the same thing, except it uses a local buffer it
197  * manages. That makes it a little easier to work with if you don't need the
198  * flexibility of the RegisterBuf type.
199  *
200  *
201  * == Typed Registers ==
202  *
203  * The Register template class is for more complex registers with side effects,
204  * and/or which hold structured data. The template arguments define what type
205  * the register should hold, and also its endianness.
206  *
207  * = Access handlers =
208  *
209  * Instead of subclassing the Register<Data> type and redefining its read/write
210  * methods, reads and writes are implemented using replaceable handlers with
211  * these signatures:
212  *
213  * Data read(Register<Data> &reg);
214  * Data partialRead(Register<Data> &reg, int first, int last);
215  * void write(Register<Data> &reg, const Data &value);
216  * void partialWrite(Register<Data> &reg, const Data &value,
217  * int first, int last);
218  *
219  * The "partial" version of these handlers take "first" and "last" arguments
220  * which specify what bits of the register to modify. They should be
221  * interpreted like the same arguments in base/bitfield.hh. The endianness
222  * of the register will have already been dealt with by the time the handler
223  * is called.
224  *
225  * The read and partialRead handlers should generate whatever value reading the
226  * register should return, based on (or not based on) the state of "reg". The
227  * partial handler should keep the bits it returns in place. For example, if
228  * bits 15-8 are read from a 16 bit register with the value 0x1234, it should
229  * return 0x1200, not 0x0012.
230  *
231  * The write and partialWrite handlers work the same way, except in they write
232  * instead of read. They are responsible for updating the value in reg in
233  * whatever way and to whatever value is appropriate, based on
234  * (or not based on) the value of "value" and the state of "reg".
235  *
236  * The default implementations of the read and write handlers simply return or
237  * update the value stored in reg. The default partial read calls the read
238  * handler (which may not be the default), and trims down the data as required.
239  * The default partial write handler calls the read handler (which may not be
240  * the default), updates the value as requested, and then calls the write
241  * handler (which may not be the default).
242  *
243  * Overriding the partial read or write methods might be necessary if reads or
244  * writes have side effects which should affect only the part of the register
245  * read or written. For instance, there might be some status bits which will
246  * be cleared when accessed. Only the bits which were actually accessed should
247  * be affected, even if they're grouped together logically with the other bits
248  * in a single register.
249  *
250  * To set your own handlers, you can use the "reader", "writer",
251  * "partialReader", and "partialWriter" methods. Each of these takes a single
252  * callable argument (lambda, functor, function pointer, etc.) which will
253  * replace the current corresponding handler.
254  *
255  * These methods all return a reference to the current Register so that they
256  * can be strung together without having to respecify what object you're
257  * modifying over and over again.
258  *
259  * There are also versions of these which will set up methods on some object as
260  * the handlers. These take a pointer to whatever object will handle the call,
261  * and a member function pointer to the method that will actually implement
262  * the handler. This can be used if, for instance, the registers are all
263  * members of a RegisterBank subclass, and need to call methods on their
264  * parent class to actually implement the behavior. These methods must have
265  * the same signature as above, with the exception that they are methods and
266  * not bare functions.
267  *
268  * When updating the register's value in custom write or partialWrite handlers,
269  * be sure to use the "update" method which will honor read only bits. There
270  * is an alternative form of update which also takes a custom bitmask, if you
271  * need to update bits other than the normally writeable ones.
272  *
273  * Similarly, you can set a "resetter" handler which is responsible for
274  * resetting the register. It takes a reference to the current Register, and
275  * no other parameters. The "initialValue" accessor can retrieve the value the
276  * register was constructed with. The register is simply set to this value
277  * in the default resetter implementation.
278  *
279  * = Read only bits =
280  *
281  * Often registers have bits which are fixed and not affected by writes. To
282  * specify which bits are writeable, use the "writeable" method which takes a
283  * single argument the same type as the type of the register. It should hold a
284  * bitmask where a 1 bit can be written, and a 0 cannot. Calling writeable with
285  * no arguments will return the current bitmask.
286  *
287  * A shorthand "readonly" method marks all bits as read only.
288  *
289  * Both methods return a reference to the current Register so they can be
290  * strung together into a sequence when configuring it.
291  *
292  * = Underlying data and serialization =
293  *
294  * The "get" method returns a reference to the underlying storage inside the
295  * register. That can be used to manually update the entire register, even bits
296  * which are normally read only, or for structured data, to access members of
297  * the underlying data type.
298  *
299  * For instance, if the register holds a BitUnion, you could use the get()
300  * method to access the bitfields within it:
301  *
302  * reg.get().bitfieldA = reg.get().bitfieldB;
303  *
304  * The serialize and unserialize methods for these types will pass through the
305  * underlying data within the register. For instance, when serializing a
306  * Register<Foo>, the value in the checkpoint will be the same as if you had
307  * serialized a Foo directly, with the value stored in the register.
308  *
309  * = Aliases =
310  *
311  * Some convenient aliases have been defined for frequently used versions of
312  * the Register class. These are
313  *
314  * Register(8|16|32|64)(LE|BE|)
315  *
316  * Where the underlying type of the register is a uint8_t, uint16_t, etc, and
317  * the endianness is little endian, big endian, or whatever the default is for
318  * the RegisterBank.
319  */
320 
321 namespace gem5
322 {
323 
324 // Common bases to make it easier to identify both endiannesses at once.
326 {
327  public:
329 };
330 
331 template <ByteOrder BankByteOrder>
333 {
334  public:
335  // Static helper methods for implementing register types.
336  template <typename Data>
337  static constexpr Data
338  readWithMask(const Data &value, const Data &bitmask)
339  {
340  return value & bitmask;
341  }
342 
343  template <typename Data>
344  static constexpr Data
345  writeWithMask(const Data &old, const Data &value, const Data &bitmask)
346  {
347  return readWithMask(
348  old, (Data)~bitmask) | readWithMask(value, bitmask);
349  }
350 
352  {
353  protected:
354  const std::string _name;
355  size_t _size = 0;
356 
357  public:
358  constexpr RegisterBase(const std::string &new_name, size_t new_size) :
359  _name(new_name), _size(new_size)
360  {}
361  virtual ~RegisterBase() {}
362 
363  // Read the register's name.
364  virtual const std::string &name() const { return _name; }
365 
366  // Read the register's size in bytes.
367  size_t size() const { return _size; }
368 
369  // Perform a read on the register.
370  virtual void read(void *buf) = 0;
371  virtual void read(void *buf, off_t offset, size_t bytes) = 0;
372 
373  // Perform a write on the register.
374  virtual void write(const void *buf) = 0;
375  virtual void write(const void *buf, off_t offset, size_t bytes) = 0;
376 
377  // Methods for implementing serialization for checkpoints.
378  virtual void serialize(std::ostream &os) const = 0;
379  virtual bool unserialize(const std::string &s) = 0;
380 
381  // Reset the register.
382  virtual void reset() = 0;
383  };
384 
385  // Filler registers which return a fixed pattern.
387  {
388  protected:
389  constexpr RegisterRoFill(
390  const std::string &new_name, size_t new_size) :
391  RegisterBase(new_name, new_size)
392  {}
393 
394  virtual void fill(void *buf, off_t offset, size_t bytes) = 0;
395 
396  public:
397  // Ignore writes.
398  void write(const void *buf) override {}
399  void write(const void *buf, off_t offset, size_t bytes) override {}
400 
401  // Use fill() to handle reads.
402  void read(void *buf) override { fill(buf, 0, this->size()); }
403  void
404  read(void *buf, off_t offset, size_t bytes) override
405  {
406  fill(buf, offset, bytes);
407  }
408 
409  void serialize(std::ostream &os) const override {}
410  bool unserialize(const std::string &s) override { return true; }
411 
412  // Resetting a read only register doesn't need to do anything.
413  void reset() override {}
414  };
415 
416  // Register which reads as all zeroes.
418  {
419  protected:
420  void
421  fill(void *buf, off_t offset, size_t bytes) override
422  {
423  bzero(buf, bytes);
424  }
425 
426  public:
427  RegisterRaz(const std::string &new_name, size_t new_size) :
428  RegisterRoFill(new_name, new_size)
429  {}
430  };
431 
432  // Register which reads as all ones.
434  {
435  protected:
436  void
437  fill(void *buf, off_t offset, size_t bytes) override
438  {
439  memset(buf, 0xff, bytes);
440  }
441 
442  public:
443  RegisterRao(const std::string &new_name, size_t new_size) :
444  RegisterRoFill(new_name, new_size)
445  {}
446  };
447 
448  // Register which acts as a simple buffer.
449  class RegisterBuf : public RegisterBase
450  {
451  private:
452  void *_ptr = nullptr;
453 
454  public:
455  RegisterBuf(const std::string &new_name, void *ptr, size_t bytes) :
456  RegisterBase(new_name, bytes), _ptr(ptr)
457  {}
458 
459  void write(const void *buf) override { write(buf, 0, this->size()); }
460  void
461  write(const void *buf, off_t offset, size_t bytes) override
462  {
463  assert(offset + bytes <= this->size());
464  memcpy((uint8_t *)_ptr + offset, buf, bytes);
465  }
466 
467  void read(void *buf) override { read(buf, 0, this->size()); }
468  void
469  read(void *buf, off_t offset, size_t bytes) override
470  {
471  assert(offset + bytes <= this->size());
472  memcpy(buf, (uint8_t *)_ptr + offset, bytes);
473  }
474 
475  // The buffer's owner is responsible for serializing it.
476  void serialize(std::ostream &os) const override {}
477  bool unserialize(const std::string &s) override { return true; }
478 
479  // Assume since the buffer is managed externally, it will be reset
480  // externally.
481  void reset() override {}
482 
483  protected:
490  void
491  setBuffer(void *buf)
492  {
493  assert(_ptr == nullptr);
494  assert(buf != nullptr);
495  _ptr = buf;
496  }
497  };
498 
499  // Same as above, but which keeps its storage locally.
500  template <int BufBytes>
501  class RegisterLBuf : public RegisterBuf
502  {
503  public:
504  std::array<uint8_t, BufBytes> buffer;
505 
506  RegisterLBuf(const std::string &new_name) :
507  RegisterBuf(new_name, nullptr, BufBytes)
508  {
509  this->setBuffer(buffer.data());
510  }
511 
512  void
513  serialize(std::ostream &os) const override
514  {
515  if (BufBytes)
517  for (int i = 1; i < BufBytes; i++) {
518  os << " ";
520  }
521  }
522 
523  bool
524  unserialize(const std::string &s) override
525  {
527  std::istringstream is(s);
528 
529  std::string token;
530  while (is >> token)
531  tokens.push_back(token);
532 
533  if (tokens.size() != BufBytes) {
534  warn("Size mismatch unserialing %s, expected %d, got %d",
535  this->name(), BufBytes, tokens.size());
536  return false;
537  }
538 
539  for (int i = 0; i < BufBytes; i++) {
540  if (!ParseParam<uint8_t>::parse(tokens[i], buffer[i]))
541  return false;
542  }
543 
544  return true;
545  }
546 
547  void reset() override { buffer = std::array<uint8_t, BufBytes>{}; }
548  };
549 
550  template <typename Data, ByteOrder RegByteOrder=BankByteOrder>
551  class Register : public RegisterBase
552  {
553  protected:
555 
556  public:
557  using ReadFunc = std::function<Data (This &reg)>;
558  using PartialReadFunc = std::function<
559  Data (This &reg, int first, int last)>;
560  using WriteFunc = std::function<void (This &reg, const Data &value)>;
561  using PartialWriteFunc = std::function<
562  void (This &reg, const Data &value, int first, int last)>;
563  using ResetFunc = std::function<void (This &reg)>;
564 
565  private:
566  Data _data = {};
567  Data _resetData = {};
568  Data _writeMask = mask(sizeof(Data) * 8);
569 
575 
576  protected:
577  static Data defaultReader(This &reg) { return reg.get(); }
578 
579  static Data
580  defaultPartialReader(This &reg, int first, int last)
581  {
582  return mbits(reg._reader(reg), first, last);
583  }
584 
585  static void
586  defaultWriter(This &reg, const Data &value)
587  {
588  reg.update(value);
589  }
590 
591  static void
592  defaultPartialWriter(This &reg, const Data &value, int first, int last)
593  {
594  reg._writer(reg, writeWithMask<Data>(reg._reader(reg), value,
595  mask(first, last)));
596  }
597 
598  static void
600  {
601  reg.get() = reg.initialValue();
602  }
603 
604  constexpr Data
605  htoreg(Data data)
606  {
607  switch (RegByteOrder) {
608  case ByteOrder::big:
609  return htobe(data);
610  case ByteOrder::little:
611  return htole(data);
612  default:
613  panic("Unrecognized byte order %d.", (unsigned)RegByteOrder);
614  }
615  }
616 
617  constexpr Data
618  regtoh(Data data)
619  {
620  switch (RegByteOrder) {
621  case ByteOrder::big:
622  return betoh(data);
623  case ByteOrder::little:
624  return letoh(data);
625  default:
626  panic("Unrecognized byte order %d.", (unsigned)RegByteOrder);
627  }
628  }
629 
630  public:
631 
632  /*
633  * Interface for setting up the register.
634  */
635 
636  // Constructor which lets data default initialize itself.
637  constexpr Register(const std::string &new_name) :
638  RegisterBase(new_name, sizeof(Data))
639  {}
640 
641  // Constructor and move constructor with an initial data value.
642  constexpr Register(const std::string &new_name, const Data &new_data) :
643  RegisterBase(new_name, sizeof(Data)), _data(new_data),
644  _resetData(new_data)
645  {}
646  constexpr Register(const std::string &new_name,
647  const Data &&new_data) :
648  RegisterBase(new_name, sizeof(Data)), _data(new_data),
649  _resetData(new_data)
650  {}
651 
652  // Set which bits of the register are writeable.
653  constexpr This &
654  writeable(const Data &new_mask)
655  {
656  _writeMask = new_mask;
657  return *this;
658  }
659 
660  // Set the register as read only.
661  constexpr This &readonly() { return writeable(0); }
662 
663  // Set the callables which handles reads or writes.
664  // The default reader just returns the register value.
665  // The default writer uses the write mask to update the register value.
666  constexpr This &
667  reader(const ReadFunc &new_reader)
668  {
669  _reader = new_reader;
670  return *this;
671  }
672  template <class Parent, class... Args>
673  constexpr This &
674  reader(Parent *parent, Data (Parent::*nr)(Args... args))
675  {
676  auto wrapper = [parent, nr](Args&&... args) -> Data {
677  return (parent->*nr)(std::forward<Args>(args)...);
678  };
679  return reader(wrapper);
680  }
681  constexpr This &
682  writer(const WriteFunc &new_writer)
683  {
684  _writer = new_writer;
685  return *this;
686  }
687  template <class Parent, class... Args>
688  constexpr This &
689  writer(Parent *parent, void (Parent::*nw)(Args... args))
690  {
691  auto wrapper = [parent, nw](Args&&... args) {
692  (parent->*nw)(std::forward<Args>(args)...);
693  };
694  return writer(wrapper);
695  }
696 
697  // Set the callables which handle reads or writes. These may need to
698  // be handled specially if, for instance, accessing bits outside of
699  // the enables would have side effects that shouldn't happen.
700  //
701  // The default partial reader just uses the byte enables to mask off
702  // bits that are not being read.
703  //
704  // The default partial writer reads the current value of the register,
705  // uses the byte enables to update only the bytes that are changing,
706  // and then writes the result back to the register.
707  constexpr This &
708  partialReader(const PartialReadFunc &new_reader)
709  {
710  _partialReader = new_reader;
711  return *this;
712  }
713  template <class Parent, class... Args>
714  constexpr This &
715  partialReader(Parent *parent, Data (Parent::*nr)(Args... args))
716  {
717  auto wrapper = [parent, nr](Args&&... args) -> Data {
718  return (parent->*nr)(std::forward<Args>(args)...);
719  };
720  return partialReader(wrapper);
721  }
722  constexpr This &
723  partialWriter(const PartialWriteFunc &new_writer)
724  {
725  _partialWriter = new_writer;
726  return *this;
727  }
728  template <class Parent, class... Args>
729  constexpr This &
730  partialWriter(Parent *parent, void (Parent::*nw)(Args... args))
731  {
732  auto wrapper = [parent, nw](Args&&... args) {
733  return (parent->*nw)(std::forward<Args>(args)...);
734  };
735  return partialWriter(wrapper);
736  }
737 
738  // Set the callables which handle resetting.
739  //
740  // The default resetter restores the initial value used in the
741  // constructor.
742  constexpr This &
743  resetter(const ResetFunc &new_resetter)
744  {
745  _resetter = new_resetter;
746  return *this;
747  }
748  template <class Parent, class... Args>
749  constexpr This &
750  resetter(Parent *parent, void (Parent::*nr)(Args... args))
751  {
752  auto wrapper = [parent, nr](Args&&... args) {
753  return (parent->*nr)(std::forward<Args>(args)...);
754  };
755  return resetter(wrapper);
756  }
757 
758  // An accessor which returns the initial value as set in the
759  // constructor. This is intended to be used in a resetter function.
760  const Data &initialValue() const { return _resetData; }
761 
762  // Reset the initial value, which is normally set in the constructor,
763  // to the register's current value.
765 
766  /*
767  * Interface for accessing the register's state, for use by the
768  * register's helper functions and the register bank.
769  */
770 
771  const Data &writeable() const { return _writeMask; }
772 
773  // Directly access the underlying data value.
774  const Data &get() const { return _data; }
775  Data &get() { return _data; }
776 
777  // Update data while applying a mask.
778  void
779  update(const Data &new_data, const Data &bitmask)
780  {
781  _data = writeWithMask(_data, new_data, bitmask);
782  }
783  // This version uses the default write mask.
784  void
785  update(const Data &new_data)
786  {
787  _data = writeWithMask(_data, new_data, _writeMask);
788  }
789 
790 
791  /*
792  * Interface for reading/writing the register, for use by the
793  * register bank.
794  */
795 
796  // Perform a read on the register.
797  void
798  read(void *buf) override
799  {
800  Data data = htoreg(_reader(*this));
801  memcpy(buf, (uint8_t *)&data, sizeof(data));
802  }
803 
804  void
805  read(void *buf, off_t offset, size_t bytes) override
806  {
807  // Move the region we're reading to be little endian, since that's
808  // what gem5 uses internally in BitUnions, masks, etc.
809  const off_t host_off = (RegByteOrder != ByteOrder::little) ?
810  sizeof(Data) - (offset + bytes) : offset;
811 
812  const int first = (host_off + bytes) * 8 - 1;
813  const int last = host_off * 8;
814  Data data = htoreg(_partialReader(*this, first, last));
815 
816  memcpy(buf, (uint8_t *)&data + offset, bytes);
817  }
818 
819  // Perform a write on the register.
820  void
821  write(const void *buf) override
822  {
823  Data data;
824  memcpy((uint8_t *)&data, buf, sizeof(data));
825  data = regtoh(data);
826  _writer(*this, data);
827  }
828 
829  void
830  write(const void *buf, off_t offset, size_t bytes) override
831  {
832  Data data = {};
833  memcpy((uint8_t *)&data + offset, buf, bytes);
834 
835  data = regtoh(data);
836 
837  // Move the region we're reading to be little endian, since that's
838  // what gem5 uses internally in BitUnions, masks, etc.
839  const off_t host_off = (RegByteOrder != ByteOrder::little) ?
840  sizeof(Data) - (offset + bytes) : offset;
841 
842  const int first = (host_off + bytes) * 8 - 1;
843  const int last = host_off * 8;
844  _partialWriter(*this, data, first, last);
845  }
846 
847  // Serialize our data using existing mechanisms.
848  void
849  serialize(std::ostream &os) const override
850  {
852  }
853 
854  bool
855  unserialize(const std::string &s) override
856  {
857  return ParseParam<Data>::parse(s, get());
858  }
859 
860  // Reset our data to its initial value.
861  void reset() override { _resetter(*this); }
862  };
863 
864  private:
865  std::map<Addr, std::reference_wrapper<RegisterBase>> _offsetMap;
866 
867  Addr _base = 0;
868  Addr _size = 0;
869  const std::string _name;
870 
871  public:
872 
873  using Register8 = Register<uint8_t>;
874  using Register8LE = Register<uint8_t, ByteOrder::little>;
875  using Register8BE = Register<uint8_t, ByteOrder::big>;
876  using Register16 = Register<uint16_t>;
877  using Register16LE = Register<uint16_t, ByteOrder::little>;
878  using Register16BE = Register<uint16_t, ByteOrder::big>;
879  using Register32 = Register<uint32_t>;
880  using Register32LE = Register<uint32_t, ByteOrder::little>;
881  using Register32BE = Register<uint32_t, ByteOrder::big>;
882  using Register64 = Register<uint64_t>;
883  using Register64LE = Register<uint64_t, ByteOrder::little>;
884  using Register64BE = Register<uint64_t, ByteOrder::big>;
885 
886 
887  constexpr RegisterBank(const std::string &new_name, Addr new_base) :
888  _base(new_base), _name(new_name)
889  {}
890 
891  virtual ~RegisterBank() {}
892 
894  {
895  private:
896  std::optional<Addr> offset;
897  std::optional<RegisterBase *> reg;
898 
899  public:
900  // Nothing special to do for this register.
901  RegisterAdder(RegisterBase &new_reg) : reg(&new_reg) {}
902  // Ensure that this register is added at a particular offset.
903  RegisterAdder(Addr new_offset, RegisterBase &new_reg) :
904  offset(new_offset), reg(&new_reg)
905  {}
906  // No register, just check that the offset is what we expect.
907  RegisterAdder(Addr new_offset) : offset(new_offset) {}
908 
909  friend class RegisterBank;
910  };
911 
912  void
913  addRegisters(std::initializer_list<RegisterAdder> adders)
914  {
915  panic_if(std::empty(adders),
916  "Adding an empty list of registers to %s?", name());
917  for (auto &adder: adders) {
918  const Addr offset = _base + _size;
919 
920  if (adder.reg) {
921  auto *reg = adder.reg.value();
922  if (adder.offset && adder.offset.value() != offset) {
923  panic(
924  "Expected offset of register %s.%s to be %#x, is %#x.",
925  name(), reg->name(), adder.offset.value(), offset);
926  }
927  _offsetMap.emplace(offset, *reg);
928  _size += reg->size();
929  } else if (adder.offset) {
930  if (adder.offset.value() != offset) {
931  panic("Expected current offset of %s to be %#x, is %#x.",
932  name(), adder.offset.value(), offset);
933  }
934  }
935  }
936  }
937 
938  void addRegister(RegisterAdder reg) { addRegisters({reg}); }
939 
940  Addr base() const { return _base; }
941  Addr size() const { return _size; }
942  const std::string &name() const { return _name; }
943 
944  virtual void
945  read(Addr addr, void *buf, Addr bytes)
946  {
947  uint8_t *ptr = (uint8_t *)buf;
948  // Number of bytes we've transferred.
949  Addr done = 0;
950 
951  panic_if(addr - base() + bytes > size(),
952  "Out of bounds read in register bank %s, address %#x, size %d.",
953  name(), addr, bytes);
954 
955  auto it = _offsetMap.lower_bound(addr);
956  if (it == _offsetMap.end() || it->first > addr)
957  it--;
958 
959  if (it->first < addr) {
960  RegisterBase &reg = it->second.get();
961  // Skip at least the beginning of the first register.
962 
963  // Figure out what parts of it we're accessing.
964  const off_t reg_off = addr - it->first;
965  const size_t reg_bytes = std::min(reg.size() - reg_off,
966  bytes - done);
967 
968  // Actually do the access.
969  reg.read(ptr, reg_off, reg_bytes);
970  done += reg_bytes;
971  it++;
972 
973  // Was that everything?
974  if (done == bytes)
975  return;
976  }
977 
978  while (true) {
979  RegisterBase &reg = it->second.get();
980 
981  const size_t reg_size = reg.size();
982  const size_t remaining = bytes - done;
983 
984  if (remaining == reg_size) {
985  // A complete register read, and then we're done.
986  reg.read(ptr + done);
987  return;
988  } else if (remaining > reg_size) {
989  // A complete register read, with more to go.
990  reg.read(ptr + done);
991  done += reg_size;
992  it++;
993  } else {
994  // Skip the end of the register, and then we're done.
995  reg.read(ptr + done, 0, remaining);
996  return;
997  }
998  }
999  }
1000 
1001  virtual void
1002  write(Addr addr, const void *buf, Addr bytes)
1003  {
1004  const uint8_t *ptr = (const uint8_t *)buf;
1005  // Number of bytes we've transferred.
1006  Addr done = 0;
1007 
1008  panic_if(addr - base() + bytes > size(),
1009  "Out of bounds write in register bank %s, address %#x, size %d.",
1010  name(), addr, bytes);
1011 
1012  auto it = _offsetMap.lower_bound(addr);
1013  if (it == _offsetMap.end() || it->first > addr)
1014  it--;
1015 
1016  if (it->first < addr) {
1017  RegisterBase &reg = it->second.get();
1018  // Skip at least the beginning of the first register.
1019 
1020  // Figure out what parts of it we're accessing.
1021  const off_t reg_off = addr - it->first;
1022  const size_t reg_bytes = std::min(reg.size() - reg_off,
1023  bytes - done);
1024 
1025  // Actually do the access.
1026  reg.write(ptr, reg_off, reg_bytes);
1027  done += reg_bytes;
1028  it++;
1029 
1030  // Was that everything?
1031  if (done == bytes)
1032  return;
1033  }
1034 
1035  while (true) {
1036  RegisterBase &reg = it->second.get();
1037 
1038  const size_t reg_size = reg.size();
1039  const size_t remaining = bytes - done;
1040 
1041  if (remaining == reg_size) {
1042  // A complete register write, and then we're done.
1043  reg.write(ptr + done);
1044  return;
1045  } else if (remaining > reg_size) {
1046  // A complete register write, with more to go.
1047  reg.write(ptr + done);
1048  done += reg_size;
1049  it++;
1050  } else {
1051  // Skip the end of the register, and then we're done.
1052  reg.write(ptr + done, 0, remaining);
1053  return;
1054  }
1055  }
1056  }
1057 
1058  // By default, reset all the registers in the bank.
1059  virtual void
1061  {
1062  for (auto &it: _offsetMap)
1063  it.second.get().reset();
1064  }
1065 };
1066 
1069 
1070 // Delegate serialization to the individual RegisterBase subclasses.
1071 template <class T>
1072 struct ParseParam<T, std::enable_if_t<std::is_base_of_v<
1073  typename RegisterBankBase::RegisterBaseBase, T>>>
1074 {
1075  static bool
1076  parse(const std::string &s, T &value)
1077  {
1078  return value.unserialize(s);
1079  }
1080 };
1081 
1082 template <class T>
1083 struct ShowParam<T, std::enable_if_t<std::is_base_of_v<
1084  typename RegisterBankBase::RegisterBaseBase, T>>>
1085 {
1086  static void
1087  show(std::ostream &os, const T &value)
1088  {
1089  value.serialize(os);
1090  }
1091 };
1092 
1093 } // namespace gem5
1094 
1095 #endif // __DEV_REG_BANK_HH__
gem5::RegisterBank::Register::defaultWriter
static void defaultWriter(This &reg, const Data &value)
Definition: reg_bank.hh:586
gem5::RegisterBank< ByteOrder::little >::Register8
Register< uint8_t > Register8
Definition: reg_bank.hh:873
gem5::VegaISA::s
Bitfield< 1 > s
Definition: pagetable.hh:64
gem5::RegisterBank::Register::resetter
constexpr This & resetter(Parent *parent, void(Parent::*nr)(Args... args))
Definition: reg_bank.hh:750
gem5::RegisterBank::addRegister
void addRegister(RegisterAdder reg)
Definition: reg_bank.hh:938
gem5::RegisterBank::RegisterBase::~RegisterBase
virtual ~RegisterBase()
Definition: reg_bank.hh:361
warn
#define warn(...)
Definition: logging.hh:256
gem5::RegisterBank::RegisterBuf
Definition: reg_bank.hh:449
gem5::RegisterBank< ByteOrder::little >::Register64LE
Register< uint64_t, ByteOrder::little > Register64LE
Definition: reg_bank.hh:883
data
const char data[]
Definition: circlebuf.test.cc:48
gem5::RegisterBankBase::RegisterBaseBase
Definition: reg_bank.hh:328
gem5::RegisterBank::RegisterBuf::read
void read(void *buf, off_t offset, size_t bytes) override
Definition: reg_bank.hh:469
gem5::ParseParam< T, std::enable_if_t< std::is_base_of_v< typename RegisterBankBase::RegisterBaseBase, T > > >::parse
static bool parse(const std::string &s, T &value)
Definition: reg_bank.hh:1076
gem5::RegisterBank::RegisterBase
Definition: reg_bank.hh:351
gem5::RegisterBank::RegisterRoFill::read
void read(void *buf, off_t offset, size_t bytes) override
Definition: reg_bank.hh:404
gem5::RegisterBank::RegisterRoFill::serialize
void serialize(std::ostream &os) const override
Definition: reg_bank.hh:409
gem5::RegisterBank::RegisterBuf::write
void write(const void *buf) override
Definition: reg_bank.hh:459
gem5::RegisterBank::RegisterRoFill::RegisterRoFill
constexpr RegisterRoFill(const std::string &new_name, size_t new_size)
Definition: reg_bank.hh:389
gem5::RegisterBank::RegisterBase::unserialize
virtual bool unserialize(const std::string &s)=0
gem5::RegisterBank::Register::partialReader
constexpr This & partialReader(const PartialReadFunc &new_reader)
Definition: reg_bank.hh:708
gem5::RegisterBank::RegisterAdder::RegisterAdder
RegisterAdder(RegisterBase &new_reg)
Definition: reg_bank.hh:901
gem5::RegisterBank::RegisterLBuf
Definition: reg_bank.hh:501
gem5::RegisterBank::Register::get
const Data & get() const
Definition: reg_bank.hh:774
gem5::betoh
T betoh(T value)
Definition: byteswap.hh:175
gem5::RegisterBank::RegisterBuf::read
void read(void *buf) override
Definition: reg_bank.hh:467
gem5::ShowParam::show
static void show(std::ostream &os, const T &value)
Definition: serialize_handlers.hh:127
gem5::RegisterBank::RegisterBuf::_ptr
void * _ptr
Definition: reg_bank.hh:452
gem5::RegisterBank::RegisterBase::_size
size_t _size
Definition: reg_bank.hh:355
gem5::RegisterBank::RegisterRao::RegisterRao
RegisterRao(const std::string &new_name, size_t new_size)
Definition: reg_bank.hh:443
gem5::RegisterBank::RegisterBase::size
size_t size() const
Definition: reg_bank.hh:367
gem5::RegisterBank::write
virtual void write(Addr addr, const void *buf, Addr bytes)
Definition: reg_bank.hh:1002
gem5::RegisterBank::RegisterRaz::RegisterRaz
RegisterRaz(const std::string &new_name, size_t new_size)
Definition: reg_bank.hh:427
gem5::RegisterBank::Register::initialValue
const Data & initialValue() const
Definition: reg_bank.hh:760
gem5::RegisterBank::RegisterBuf::setBuffer
void setBuffer(void *buf)
This method exists so that derived classes that need to initialize their buffers before they can be s...
Definition: reg_bank.hh:491
gem5::RegisterBank::Register::partialReader
constexpr This & partialReader(Parent *parent, Data(Parent::*nr)(Args... args))
Definition: reg_bank.hh:715
std::vector< std::string >
gem5::RegisterBank::RegisterRoFill::reset
void reset() override
Definition: reg_bank.hh:413
gem5::RegisterBank::Register::defaultPartialReader
static Data defaultPartialReader(This &reg, int first, int last)
Definition: reg_bank.hh:580
gem5::RegisterBank::RegisterBuf::unserialize
bool unserialize(const std::string &s) override
Definition: reg_bank.hh:477
gem5::RegisterBank::readWithMask
static constexpr Data readWithMask(const Data &value, const Data &bitmask)
Definition: reg_bank.hh:338
gem5::RegisterBank::_offsetMap
std::map< Addr, std::reference_wrapper< RegisterBase > > _offsetMap
Definition: reg_bank.hh:865
gem5::RegisterBankBase
Definition: reg_bank.hh:325
gem5::mbits
constexpr T mbits(T val, unsigned first, unsigned last)
Mask off the given bits in place like bits() but without shifting.
Definition: bitfield.hh:103
gem5::htobe
T htobe(T value)
Definition: byteswap.hh:174
gem5::RegisterBank::_size
Addr _size
Definition: reg_bank.hh:868
gem5::RegisterBank::Register::Register
constexpr Register(const std::string &new_name, const Data &new_data)
Definition: reg_bank.hh:642
gem5::RegisterBank::RegisterLBuf::RegisterLBuf
RegisterLBuf(const std::string &new_name)
Definition: reg_bank.hh:506
gem5::ArmISA::i
Bitfield< 7 > i
Definition: misc_types.hh:67
gem5::RegisterBank::addRegisters
void addRegisters(std::initializer_list< RegisterAdder > adders)
Definition: reg_bank.hh:913
gem5::scmi::token
token
Definition: scmi_platform.hh:80
gem5::RegisterBank::Register::_resetData
Data _resetData
Definition: reg_bank.hh:567
gem5::RegisterBank::RegisterLBuf::serialize
void serialize(std::ostream &os) const override
Definition: reg_bank.hh:513
gem5::ShowParam< T, std::enable_if_t< std::is_base_of_v< typename RegisterBankBase::RegisterBaseBase, T > > >::show
static void show(std::ostream &os, const T &value)
Definition: reg_bank.hh:1087
gem5::ShowParam
Definition: serialize_handlers.hh:125
gem5::RegisterBank::Register::writeable
const Data & writeable() const
Definition: reg_bank.hh:771
gem5::MipsISA::is
Bitfield< 24, 22 > is
Definition: pra_constants.hh:235
gem5::RegisterBank::RegisterRoFill::write
void write(const void *buf, off_t offset, size_t bytes) override
Definition: reg_bank.hh:399
gem5::RegisterBank::size
Addr size() const
Definition: reg_bank.hh:941
gem5::letoh
T letoh(T value)
Definition: byteswap.hh:173
gem5::mask
constexpr uint64_t mask(unsigned nbits)
Generate a 64-bit mask of 'nbits' 1s, right justified.
Definition: bitfield.hh:63
gem5::RegisterBank::RegisterBase::read
virtual void read(void *buf)=0
gem5::RegisterBank::base
Addr base() const
Definition: reg_bank.hh:940
gem5::RegisterBank::Register::writer
constexpr This & writer(Parent *parent, void(Parent::*nw)(Args... args))
Definition: reg_bank.hh:689
gem5::RegisterBank::Register::partialWriter
constexpr This & partialWriter(const PartialWriteFunc &new_writer)
Definition: reg_bank.hh:723
gem5::RegisterBank::RegisterBase::name
virtual const std::string & name() const
Definition: reg_bank.hh:364
gem5::RegisterBank::RegisterBuf::serialize
void serialize(std::ostream &os) const override
Definition: reg_bank.hh:476
gem5::RegisterBank::RegisterBuf::reset
void reset() override
Definition: reg_bank.hh:481
gem5::RegisterBank::Register::Register
constexpr Register(const std::string &new_name, const Data &&new_data)
Definition: reg_bank.hh:646
gem5::RegisterBank::RegisterLBuf::buffer
std::array< uint8_t, BufBytes > buffer
Definition: reg_bank.hh:504
gem5::RegisterBank::RegisterRaz
Definition: reg_bank.hh:417
gem5::RegisterBank::Register::read
void read(void *buf, off_t offset, size_t bytes) override
Definition: reg_bank.hh:805
gem5::RegisterBank::Register< BackingType >::PartialWriteFunc
std::function< void(This &reg, const BackingType &value, int first, int last)> PartialWriteFunc
Definition: reg_bank.hh:562
bitfield.hh
gem5::RegisterBank::~RegisterBank
virtual ~RegisterBank()
Definition: reg_bank.hh:891
gem5::RegisterBank::Register::_writeMask
Data _writeMask
Definition: reg_bank.hh:568
gem5::RegisterBank< ByteOrder::little >::Register8LE
Register< uint8_t, ByteOrder::little > Register8LE
Definition: reg_bank.hh:874
gem5::RegisterBank::Register::resetter
constexpr This & resetter(const ResetFunc &new_resetter)
Definition: reg_bank.hh:743
gem5::RegisterBank::RegisterBase::reset
virtual void reset()=0
gem5::RegisterBank::Register::This
Register< Data, RegByteOrder > This
Definition: reg_bank.hh:554
gem5::RegisterBank::Register::read
void read(void *buf) override
Definition: reg_bank.hh:798
gem5::RegisterBank< ByteOrder::little >::Register8BE
Register< uint8_t, ByteOrder::big > Register8BE
Definition: reg_bank.hh:875
gem5::RegisterBank::Register::unserialize
bool unserialize(const std::string &s) override
Definition: reg_bank.hh:855
gem5::RegisterBank::Register::_partialWriter
PartialWriteFunc _partialWriter
Definition: reg_bank.hh:572
gem5::RegisterBank::RegisterRoFill::unserialize
bool unserialize(const std::string &s) override
Definition: reg_bank.hh:410
gem5::RegisterBank::RegisterRoFill::fill
virtual void fill(void *buf, off_t offset, size_t bytes)=0
gem5::RegisterBank::RegisterLBuf::reset
void reset() override
Definition: reg_bank.hh:547
gem5::RegisterBank::RegisterAdder
Definition: reg_bank.hh:893
gem5::RegisterBank::Register::_partialReader
PartialReadFunc _partialReader
Definition: reg_bank.hh:573
gem5::RegisterBank::Register::_data
Data _data
Definition: reg_bank.hh:566
gem5::ArmISA::offset
Bitfield< 23, 0 > offset
Definition: types.hh:144
gem5::RegisterBank::Register::writeable
constexpr This & writeable(const Data &new_mask)
Definition: reg_bank.hh:654
gem5::RegisterBank::RegisterRao::fill
void fill(void *buf, off_t offset, size_t bytes) override
Definition: reg_bank.hh:437
gem5::RegisterBank::RegisterRoFill::read
void read(void *buf) override
Definition: reg_bank.hh:402
gem5::RegisterBank::Register::Register
constexpr Register(const std::string &new_name)
Definition: reg_bank.hh:637
gem5::RegisterBank::RegisterRao
Definition: reg_bank.hh:433
gem5::RegisterBank::Register::_reader
ReadFunc _reader
Definition: reg_bank.hh:570
gem5::RegisterBank::RegisterRoFill::write
void write(const void *buf) override
Definition: reg_bank.hh:398
gem5::RegisterBank::Register::update
void update(const Data &new_data)
Definition: reg_bank.hh:785
gem5::RegisterBank::RegisterBuf::RegisterBuf
RegisterBuf(const std::string &new_name, void *ptr, size_t bytes)
Definition: reg_bank.hh:455
gem5::Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
gem5::RegisterBank::Register::reset
void reset() override
Definition: reg_bank.hh:861
gem5::RegisterBank::RegisterBank
constexpr RegisterBank(const std::string &new_name, Addr new_base)
Definition: reg_bank.hh:887
gem5::RegisterBank::Register< BackingType >::WriteFunc
std::function< void(This &reg, const BackingType &value)> WriteFunc
Definition: reg_bank.hh:560
gem5::RegisterBank::Register::resetInitialValue
void resetInitialValue()
Definition: reg_bank.hh:764
gem5::RegisterBank::RegisterBase::write
virtual void write(const void *buf)=0
gem5::RegisterBank::Register::_writer
WriteFunc _writer
Definition: reg_bank.hh:571
gem5::X86ISA::reg
Bitfield< 5, 3 > reg
Definition: types.hh:92
gem5::RegisterBank::RegisterBase::RegisterBase
constexpr RegisterBase(const std::string &new_name, size_t new_size)
Definition: reg_bank.hh:358
gem5::RegisterBank::Register::reader
constexpr This & reader(Parent *parent, Data(Parent::*nr)(Args... args))
Definition: reg_bank.hh:674
gem5::RegisterBank::writeWithMask
static constexpr Data writeWithMask(const Data &old, const Data &value, const Data &bitmask)
Definition: reg_bank.hh:345
panic_if
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:214
gem5::RegisterBank::read
virtual void read(Addr addr, void *buf, Addr bytes)
Definition: reg_bank.hh:945
gem5::RegisterBank::Register::readonly
constexpr This & readonly()
Definition: reg_bank.hh:661
serialize_handlers.hh
std
Overload hash function for BasicBlockRange type.
Definition: misc.hh:2909
types.hh
gem5::RegisterBank::Register::write
void write(const void *buf) override
Definition: reg_bank.hh:821
gem5::RegisterBank::name
const std::string & name() const
Definition: reg_bank.hh:942
gem5::X86ISA::os
Bitfield< 17 > os
Definition: misc.hh:810
gem5::RegisterBank::Register::_resetter
ResetFunc _resetter
Definition: reg_bank.hh:574
gem5::RegisterBank::RegisterRaz::fill
void fill(void *buf, off_t offset, size_t bytes) override
Definition: reg_bank.hh:421
gem5::RegisterBank< ByteOrder::little >::Register32BE
Register< uint32_t, ByteOrder::big > Register32BE
Definition: reg_bank.hh:881
gem5::RegisterBank::Register::reader
constexpr This & reader(const ReadFunc &new_reader)
Definition: reg_bank.hh:667
gem5::RegisterBank::RegisterBuf::write
void write(const void *buf, off_t offset, size_t bytes) override
Definition: reg_bank.hh:461
gem5::htole
T htole(T value)
Definition: byteswap.hh:172
gem5::RegisterBank
Definition: reg_bank.hh:332
gem5::RegisterBank::RegisterBase::_name
const std::string _name
Definition: reg_bank.hh:354
gem5::RegisterBank::Register
Definition: reg_bank.hh:551
logging.hh
gem5::RegisterBank::Register< BackingType >::PartialReadFunc
std::function< BackingType(This &reg, int first, int last)> PartialReadFunc
Definition: reg_bank.hh:559
gem5::RegisterBank::Register::write
void write(const void *buf, off_t offset, size_t bytes) override
Definition: reg_bank.hh:830
gem5::RegisterBank::_name
const std::string _name
Definition: reg_bank.hh:869
gem5::RegisterBank::Register::defaultResetter
static void defaultResetter(This &reg)
Definition: reg_bank.hh:599
gem5::RegisterBank< ByteOrder::little >::Register64BE
Register< uint64_t, ByteOrder::big > Register64BE
Definition: reg_bank.hh:884
gem5::RegisterBank::Register::get
Data & get()
Definition: reg_bank.hh:775
gem5::RegisterBank::Register::partialWriter
constexpr This & partialWriter(Parent *parent, void(Parent::*nw)(Args... args))
Definition: reg_bank.hh:730
gem5::RegisterBank::RegisterRoFill
Definition: reg_bank.hh:386
gem5::RegisterBank::RegisterAdder::RegisterAdder
RegisterAdder(Addr new_offset, RegisterBase &new_reg)
Definition: reg_bank.hh:903
gem5::RegisterBank::Register::defaultPartialWriter
static void defaultPartialWriter(This &reg, const Data &value, int first, int last)
Definition: reg_bank.hh:592
gem5::RegisterBank::RegisterAdder::RegisterAdder
RegisterAdder(Addr new_offset)
Definition: reg_bank.hh:907
gem5::RegisterBank::Register< BackingType >::ReadFunc
std::function< BackingType(This &reg)> ReadFunc
Definition: reg_bank.hh:557
gem5::X86ISA::nw
Bitfield< 29 > nw
Definition: misc.hh:601
gem5::RegisterBank::RegisterBase::serialize
virtual void serialize(std::ostream &os) const =0
gem5::RegisterBank< ByteOrder::little >::Register16LE
Register< uint16_t, ByteOrder::little > Register16LE
Definition: reg_bank.hh:877
gem5::RegisterBank::RegisterAdder::reg
std::optional< RegisterBase * > reg
Definition: reg_bank.hh:897
gem5::RegisterBank::Register< BackingType >::ResetFunc
std::function< void(This &reg)> ResetFunc
Definition: reg_bank.hh:563
gem5::RegisterBank::reset
virtual void reset()
Definition: reg_bank.hh:1060
gem5::RegisterBank::Register::update
void update(const Data &new_data, const Data &bitmask)
Definition: reg_bank.hh:779
gem5::RegisterBank< ByteOrder::little >::Register16
Register< uint16_t > Register16
Definition: reg_bank.hh:876
gem5::ParseParam
Definition: serialize_handlers.hh:78
gem5::RegisterBank< ByteOrder::little >::Register32
Register< uint32_t > Register32
Definition: reg_bank.hh:879
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: gpu_translation_state.hh:37
gem5::RegisterBank::Register::htoreg
constexpr Data htoreg(Data data)
Definition: reg_bank.hh:605
gem5::RegisterBank::RegisterLBuf::unserialize
bool unserialize(const std::string &s) override
Definition: reg_bank.hh:524
gem5::RegisterBank< ByteOrder::little >::Register64
Register< uint64_t > Register64
Definition: reg_bank.hh:882
gem5::RegisterBank::Register::serialize
void serialize(std::ostream &os) const override
Definition: reg_bank.hh:849
gem5::RegisterBank< ByteOrder::little >::Register16BE
Register< uint16_t, ByteOrder::big > Register16BE
Definition: reg_bank.hh:878
gem5::RegisterBank::RegisterAdder::offset
std::optional< Addr > offset
Definition: reg_bank.hh:896
gem5::RegisterBank::Register::regtoh
constexpr Data regtoh(Data data)
Definition: reg_bank.hh:618
gem5::RegisterBank::Register::writer
constexpr This & writer(const WriteFunc &new_writer)
Definition: reg_bank.hh:682
byteswap.hh
gem5::RegisterBank::Register::defaultReader
static Data defaultReader(This &reg)
Definition: reg_bank.hh:577
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:188
gem5::RegisterBank::_base
Addr _base
Definition: reg_bank.hh:867
gem5::X86ISA::addr
Bitfield< 3 > addr
Definition: types.hh:84
gem5::RegisterBank< ByteOrder::little >::Register32LE
Register< uint32_t, ByteOrder::little > Register32LE
Definition: reg_bank.hh:880

Generated on Sun Jul 30 2023 01:56:56 for gem5 by doxygen 1.8.17