/*
 * Copyright 2020 Google, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef __DEV_REG_BANK_HH__
#define __DEV_REG_BANK_HH__

#include <algorithm>
#include <bitset>
#include <cassert>
#include <cstdint>
#include <cstring>
#include <functional>
#include <initializer_list>
#include <iostream>
#include <map>
#include <optional>
#include <sstream>
#include <utility>

#include "base/bitfield.hh"
#include "base/logging.hh"
#include "base/types.hh"
#include "sim/byteswap.hh"
#include "sim/serialize_handlers.hh"

/*
 * Device models often have contiguous banks of registers which can each
 * have unique and arbitrary behavior when they are completely or partially
 * read or written. Historically it's been up to each model to map an access
 * which covers an arbitrary portion of that register bank down to individual
 * registers. It must handle cases where registers are only partially accessed,
 * or where multiple registers are accessed at the same time, or a combination
 * of both.
 *
 *
 * == RegisterBank ==
 *
 * The RegisterBank class(es), defined below, handle that mapping, and let the
 * device model focus on defining what each of the registers actually do when
 * read or written. Once it's set up, it has two primary interfaces which
 * access the registers it contains:
 *
 * void read(Addr addr, void *buf, Addr bytes);
 * void write(Addr addr, const void *buf, Addr bytes);
 *
 * These two methods will handle a read or write contained within the register
 * bank starting at address "addr". The data that will be written or has been
 * read is pointed to by "buf", and is "bytes" bytes long.
 *
 * These methods are virtual, so if you need to implement extra rules, like
 * for instance that registers can only be accessed one at a time, that
 * accesses have to be aligned, have to access complete registers, etc, that
 * can be added in a subclass.
 *
 * Additionally, each RegisterBank has a name and a base address which is
 * passed into the constructor. The meaning of the "base" value can be whatever
 * makes sense for your device, and is considered the lowest address contained
 * in the bank. The value could be the offset of this bank of registers within
 * the device itself, with the device's own offset subtracted out before read
 * or write are called. It could alternatively be the base address of the
 * entire device, with the address from accesses passed into read or write
 * unmodified.
 *
 * The base(), size() and name() methods can be used to access each of those
 * read only properties of the RegisterBank instance.
 *
 * To add actual registers to the RegisterBank (discussed below), you can use
 * either the addRegister method which adds a single register, or addRegisters
 * which adds an initializer list of them all at once. The register will be
 * appended to the end of the bank as they're added, contiguous to the
 * existing registers. The size of the bank is automatically accumulated as
 * registers are added.
 *
 * When adding a lot of registers, you might accidentally add an extra,
 * or accidentally skip one in a long list. Because the offset is handled
 * automatically, some of your registers might end up shifted higher or lower
 * than you expect. To help mitigate this, you can set what offset you expect
 * a register to have by specifying it as an offset, register pair.
 *
 * addRegisters({{0x1000, reg0}, reg1, reg2});
 *
 * If the register would end up at a different offset, gem5 will panic. You
 * can also leave off the register if you want to just check the offset, for
 * instance between groups of registers.
 *
 * addRegisters({reg0, reg1, reg2, 0x100c})
 *
 * While the RegisterBank itself doesn't have any data in it directly and so
 * has no endianness, it's very likely all the registers within it will have
 * the same endinanness. The bank itself therefore has a default endianness
 * which, unless specified otherwise, will be passed on to the register types
 * within it. The RegisterBank class is templated on its endianness. There are
 * RegisterBankLE and RegisterBankBE aliases to make it a little easier to
 * refer to one or the other version.
 *
 * A RegisterBank also has a reset() method which will (by default) call the
 * reset() method on each register within it. This method is virtual, and so
 * can be overridden if something additional or different needs to be done to
 * reset the hardware model.
 *
 *
 * == Register interface ==
 *
 * Every register in a RegisterBank needs to inherit, directly or indirectly,
 * from the RegisterBase class. Each register must have a name (for debugging),
 * and a well defined size. The following methods define the interface the
 * register bank uses to access the register, and where the register can
 * implement its special behaviors:
 *
 * void read(void *buf);
 * void read(void *buf, off_t offset, size_t bytes);
 *
 * void write(const void *buf);
 * void write(const void *buf, off_t offset, size_t bytes);
 *
 * The single argument versions of these methods completely overwrite the
 * register's contents with whatever is pointed to by buf.
 *
 * The version which also takes "offset" and "bytes" arguments reads or writes
 * only a portion of the register, starting "offset" bytes from the start of
 * the register, and writing or reading the next "bytes" bytes.
 *
 * Each register also needs to implement serialize or unserialize methods
 * which make it accessible to the checkpointing mechanism. If a register
 * doesn't need to be serialized (for instance if it has a fixed value) then
 * it still has to implement these methods, but they don't have to actually do
 * anything.
 *
 * Each register also has a "reset" method, which will reset the register as
 * if its containing device is being reset. By default, this will just restore
 * the initial value of the register, but can be overridden to implement
 * additional behavior like resetting other aspects of the device which are
 * controlled by the value of the register.
 *
 *
 * == Basic Register types ==
 *
 * Some simple register types have been defined which handle basic, common
 * behaviors found in many devices:
 *
 * = RegisterRaz and RegisterRao =
 *
 * RegisterRaz (read as zero) and RegisterRao (read as one) will ignore writes,
 * and will return all zeroes or ones, respectively, when read. These can have
 * arbitrary alignment and size, and can be used for, for instance,
 * unimplemented registers that still need to take up a certain amount of
 * space, or for gaps between registers which still need to handle accesses
 * even though they don't do anything or hold any data.
 *
 * For instance, a device might have several regions of registers which are
 * aligned on different boundaries, but which might not take up all of the
 * space in each region. The extra space can be filled with a RegisterRaz or
 * RegisterRao, making it possible to implement all the registers as a single
 * bank.
 *
 * If you need a register with a different fill pattern, you can subclass the
 * RegisterRoFill type and implement its "fill" method. This should behave
 * like the three argument form of the read() method, described above.
 *
 * = RegisterBuf and RegisterLBuf =
 *
 * These two types act like inert blobs of storage. They don't have any
 * special behavior and can have any arbitrary size like the RegisterRao and
 * RegisterRaz types above, but these registers actually store what's written
 * to them.
 *
 * The RegisterBuf type acts as an interface to a buffer stored elsewhere. That
 * makes it possible to, for instance, alias the same buffer to different parts
 * of the register space, or to expose some other object which needs to exist
 * outside of the register bank for some reason.
 *
 * The RegisterLBuf does the same thing, except it uses a local buffer it
 * manages. That makes it a little easier to work with if you don't need the
 * flexibility of the RegisterBuf type.
 *
 *
 * == Typed Registers ==
 *
 * The Register template class is for more complex registers with side effects,
 * and/or which hold structured data. The template arguments define what type
 * the register should hold, and also its endianness.
 *
 * = Access handlers =
 *
 * Instead of subclassing the Register<Data> type and redefining its read/write
 * methods, reads and writes are implemented using replaceable handlers with
 * these signatures:
 *
 * Data read(Register<Data> &reg);
 * Data partialRead(Register<Data> &reg, int first, int last);
 * void write(Register<Data> &reg, const Data &value);
 * void partialWrite(Register<Data> &reg, const Data &value,
 *                   int first, int last);
 *
 * The "partial" version of these handlers take "first" and "last" arguments
 * which specify what bits of the register to modify. They should be
 * interpreted like the same arguments in base/bitfield.hh. The endianness
 * of the register will have already been dealt with by the time the handler
 * is called.
 *
 * The read and partialRead handlers should generate whatever value reading the
 * register should return, based on (or not based on) the state of "reg". The
 * partial handler should keep the bits it returns in place. For example, if
 * bits 15-8 are read from a 16 bit register with the value 0x1234, it should
 * return 0x1200, not 0x0012.
 *
 * The write and partialWrite handlers work the same way, except in they write
 * instead of read. They are responsible for updating the value in reg in
 * whatever way and to whatever value is appropriate, based on
 * (or not based on) the value of "value" and the state of "reg".
 *
 * The default implementations of the read and write handlers simply return or
 * update the value stored in reg. The default partial read calls the read
 * handler (which may not be the default), and trims down the data as required.
 * The default partial write handler calls the read handler (which may not be
 * the default), updates the value as requested, and then calls the write
 * handler (which may not be the default).
 *
 * Overriding the partial read or write methods might be necessary if reads or
 * writes have side effects which should affect only the part of the register
 * read or written. For instance, there might be some status bits which will
 * be cleared when accessed. Only the bits which were actually accessed should
 * be affected, even if they're grouped together logically with the other bits
 * in a single register.
 *
 * To set your own handlers, you can use the "reader", "writer",
 * "partialReader", and "partialWriter" methods. Each of these takes a single
 * callable argument (lambda, functor, function pointer, etc.) which will
 * replace the current corresponding handler.
 *
 * These methods all return a reference to the current Register so that they
 * can be strung together without having to respecify what object you're
 * modifying over and over again.
 *
 * There are also versions of these which will set up methods on some object as
 * the handlers. These take a pointer to whatever object will handle the call,
 * and a member function pointer to the method that will actually implement
 * the handler. This can be used if, for instance, the registers are all
 * members of a RegisterBank subclass, and need to call methods on their
 * parent class to actually implement the behavior. These methods must have
 * the same signature as above, with the exception that they are methods and
 * not bare functions.
 *
 * When updating the register's value in custom write or partialWrite handlers,
 * be sure to use the "update" method which will honor read only bits. There
 * is an alternative form of update which also takes a custom bitmask, if you
 * need to update bits other than the normally writeable ones.
 *
 * Similarly, you can set a "resetter" handler which is responsible for
 * resetting the register. It takes a reference to the current Register, and
 * no other parameters. The "initialValue" accessor can retrieve the value the
 * register was constructed with. The register is simply set to this value
 * in the default resetter implementation.
 *
 * = Read only bits =
 *
 * Often registers have bits which are fixed and not affected by writes. To
 * specify which bits are writeable, use the "writeable" method which takes a
 * single argument the same type as the type of the register. It should hold a
 * bitmask where a 1 bit can be written, and a 0 cannot. Calling writeable with
 * no arguments will return the current bitmask.
 *
 * A shorthand "readonly" method marks all bits as read only.
 *
 * Both methods return a reference to the current Register so they can be
 * strung together into a sequence when configuring it.
 *
 * = Underlying data and serialization =
 *
 * The "get" method returns a reference to the underlying storage inside the
 * register. That can be used to manually update the entire register, even bits
 * which are normally read only, or for structured data, to access members of
 * the underlying data type.
 *
 * For instance, if the register holds a BitUnion, you could use the get()
 * method to access the bitfields within it:
 *
 * reg.get().bitfieldA = reg.get().bitfieldB;
 *
 * The serialize and unserialize methods for these types will pass through the
 * underlying data within the register. For instance, when serializing a
 * Register<Foo>, the value in the checkpoint will be the same as if you had
 * serialized a Foo directly, with the value stored in the register.
 *
 * = Aliases =
 *
 * Some convenient aliases have been defined for frequently used versions of
 * the Register class. These are
 *
 * Register(8|16|32|64)(LE|BE|)
 *
 * Where the underlying type of the register is a uint8_t, uint16_t, etc, and
 * the endianness is little endian, big endian, or whatever the default is for
 * the RegisterBank.
 */

namespace gem5
{

// Common bases to make it easier to identify both endiannesses at once.
class RegisterBankBase
{
  public:
    class RegisterBaseBase {};
};

template <ByteOrder BankByteOrder>
class RegisterBank : public RegisterBankBase
{
  public:
    // Static helper methods for implementing register types.
    template <typename Data>
    static constexpr Data
    readWithMask(const Data &value, const Data &bitmask)
    {
        return value & bitmask;
    }

    template <typename Data>
    static constexpr Data
    writeWithMask(const Data &old, const Data &value, const Data &bitmask)
    {
        return readWithMask(
                old, (Data)~bitmask) | readWithMask(value, bitmask);
    }

    class RegisterBase : public RegisterBankBase::RegisterBaseBase
    {
      protected:
        const std::string _name;
        size_t _size = 0;

      public:
        constexpr RegisterBase(const std::string &new_name, size_t new_size) :
            _name(new_name), _size(new_size)
        {}
        virtual ~RegisterBase() {}

        // Read the register's name.
        virtual const std::string &name() const { return _name; }

        // Read the register's size in bytes.
        size_t size() const { return _size; }

        // Perform a read on the register.
        virtual void read(void *buf) = 0;
        virtual void read(void *buf, off_t offset, size_t bytes) = 0;

        // Perform a write on the register.
        virtual void write(const void *buf) = 0;
        virtual void write(const void *buf, off_t offset, size_t bytes) = 0;

        // Methods for implementing serialization for checkpoints.
        virtual void serialize(std::ostream &os) const = 0;
        virtual bool unserialize(const std::string &s) = 0;

        // Reset the register.
        virtual void reset() = 0;
    };

    // Filler registers which return a fixed pattern.
    class RegisterRoFill : public RegisterBase
    {
      protected:
        constexpr RegisterRoFill(
                const std::string &new_name, size_t new_size) :
            RegisterBase(new_name, new_size)
        {}

        virtual void fill(void *buf, off_t offset, size_t bytes) = 0;

      public:
        // Ignore writes.
        void write(const void *buf) override {}
        void write(const void *buf, off_t offset, size_t bytes) override {}

        // Use fill() to handle reads.
        void read(void *buf) override { fill(buf, 0, this->size()); }
        void
        read(void *buf, off_t offset, size_t bytes) override
        {
            fill(buf, offset, bytes);
        }

        void serialize(std::ostream &os) const override {}
        bool unserialize(const std::string &s) override { return true; }

        // Resetting a read only register doesn't need to do anything.
        void reset() override {}
    };

    // Register which reads as all zeroes.
    class RegisterRaz : public RegisterRoFill
    {
      protected:
        void
        fill(void *buf, off_t offset, size_t bytes) override
        {
            bzero(buf, bytes);
        }

      public:
        RegisterRaz(const std::string &new_name, size_t new_size) :
            RegisterRoFill(new_name, new_size)
        {}
    };

    // Register which reads as all ones.
    class RegisterRao : public RegisterRoFill
    {
      protected:
        void
        fill(void *buf, off_t offset, size_t bytes) override
        {
            memset(buf, 0xff, bytes);
        }

      public:
        RegisterRao(const std::string &new_name, size_t new_size) :
            RegisterRoFill(new_name, new_size)
        {}
    };

    // Register which acts as a simple buffer.
    class RegisterBuf : public RegisterBase
    {
      private:
        void *_ptr = nullptr;

      public:
        RegisterBuf(const std::string &new_name, void *ptr, size_t bytes) :
            RegisterBase(new_name, bytes), _ptr(ptr)
        {}

        void write(const void *buf) override { write(buf, 0, this->size()); }
        void
        write(const void *buf, off_t offset, size_t bytes) override
        {
            assert(offset + bytes <= this->size());
            memcpy((uint8_t *)_ptr + offset, buf, bytes);
        }

        void read(void *buf) override { read(buf, 0, this->size()); }
        void
        read(void *buf, off_t offset, size_t bytes) override
        {
            assert(offset + bytes <= this->size());
            memcpy(buf, (uint8_t *)_ptr + offset, bytes);
        }

        // The buffer's owner is responsible for serializing it.
        void serialize(std::ostream &os) const override {}
        bool unserialize(const std::string &s) override { return true; }

        // Assume since the buffer is managed externally, it will be reset
        // externally.
        void reset() override {}

      protected:
        /**
         * This method exists so that derived classes that need to initialize
         * their buffers before they can be set can do so.
         *
         * @param buf The pointer to the backing buffer.
         */
        void
        setBuffer(void *buf)
        {
            assert(_ptr == nullptr);
            assert(buf != nullptr);
            _ptr = buf;
        }
    };

    // Same as above, but which keeps its storage locally.
    template <int BufBytes>
    class RegisterLBuf : public RegisterBuf
    {
      public:
        std::array<uint8_t, BufBytes> buffer;

        RegisterLBuf(const std::string &new_name) :
            RegisterBuf(new_name, nullptr, BufBytes)
        {
            this->setBuffer(buffer.data());
        }

        void
        serialize(std::ostream &os) const override
        {
            if (BufBytes)
                ShowParam<uint8_t>::show(os, buffer[0]);
            for (int i = 1; i < BufBytes; i++) {
                os << " ";
                ShowParam<uint8_t>::show(os, buffer[i]);
            }
        }

        bool
        unserialize(const std::string &s) override
        {
            std::vector<std::string> tokens;
            std::istringstream is(s);

            std::string token;
            while (is >> token)
                tokens.push_back(token);

            if (tokens.size() != BufBytes) {
                warn("Size mismatch unserialing %s, expected %d, got %d",
                        this->name(), BufBytes, tokens.size());
                return false;
            }

            for (int i = 0; i < BufBytes; i++) {
                if (!ParseParam<uint8_t>::parse(tokens[i], buffer[i]))
                    return false;
            }

            return true;
        }

        void reset() override { buffer = std::array<uint8_t, BufBytes>{}; }
    };

    template <typename Data, ByteOrder RegByteOrder=BankByteOrder>
    class Register : public RegisterBase
    {
      protected:
        using This = Register<Data, RegByteOrder>;

      public:
        using ReadFunc = std::function<Data (This &reg)>;
        using PartialReadFunc = std::function<
            Data (This &reg, int first, int last)>;
        using WriteFunc = std::function<void (This &reg, const Data &value)>;
        using PartialWriteFunc = std::function<
            void (This &reg, const Data &value, int first, int last)>;
        using ResetFunc = std::function<void (This &reg)>;

      private:
        Data _data = {};
        Data _resetData = {};
        Data _writeMask = mask(sizeof(Data) * 8);

        ReadFunc _reader = defaultReader;
        WriteFunc _writer = defaultWriter;
        PartialWriteFunc _partialWriter = defaultPartialWriter;
        PartialReadFunc _partialReader = defaultPartialReader;
        ResetFunc _resetter = defaultResetter;

      protected:
        static Data defaultReader(This &reg) { return reg.get(); }

        static Data
        defaultPartialReader(This &reg, int first, int last)
        {
            return mbits(reg._reader(reg), first, last);
        }

        static void
        defaultWriter(This &reg, const Data &value)
        {
            reg.update(value);
        }

        static void
        defaultPartialWriter(This &reg, const Data &value, int first, int last)
        {
            reg._writer(reg, writeWithMask<Data>(reg._reader(reg), value,
                                                 mask(first, last)));
        }

        static void
        defaultResetter(This &reg)
        {
            reg.get() = reg.initialValue();
        }

        constexpr Data
        htoreg(Data data)
        {
            switch (RegByteOrder) {
              case ByteOrder::big:
                return htobe(data);
              case ByteOrder::little:
                return htole(data);
              default:
                panic("Unrecognized byte order %d.", (unsigned)RegByteOrder);
            }
        }

        constexpr Data
        regtoh(Data data)
        {
            switch (RegByteOrder) {
              case ByteOrder::big:
                return betoh(data);
              case ByteOrder::little:
                return letoh(data);
              default:
                panic("Unrecognized byte order %d.", (unsigned)RegByteOrder);
            }
        }

      public:

        /*
         * Interface for setting up the register.
         */

        // Constructor which lets data default initialize itself.
        constexpr Register(const std::string &new_name) :
            RegisterBase(new_name, sizeof(Data))
        {}

        // Constructor and move constructor with an initial data value.
        constexpr Register(const std::string &new_name, const Data &new_data) :
            RegisterBase(new_name, sizeof(Data)), _data(new_data),
            _resetData(new_data)
        {}
        constexpr Register(const std::string &new_name,
                           const Data &&new_data) :
            RegisterBase(new_name, sizeof(Data)), _data(new_data),
            _resetData(new_data)
        {}

        // Set which bits of the register are writeable.
        constexpr This &
        writeable(const Data &new_mask)
        {
            _writeMask = new_mask;
            return *this;
        }

        // Set the register as read only.
        constexpr This &readonly() { return writeable(0); }

        // Set the callables which handles reads or writes.
        // The default reader just returns the register value.
        // The default writer uses the write mask to update the register value.
        constexpr This &
        reader(const ReadFunc &new_reader)
        {
            _reader = new_reader;
            return *this;
        }
        template <class Parent, class... Args>
        constexpr This &
        reader(Parent *parent, Data (Parent::*nr)(Args... args))
        {
            auto wrapper = [parent, nr](Args&&... args) -> Data {
                return (parent->*nr)(std::forward<Args>(args)...);
            };
            return reader(wrapper);
        }
        constexpr This &
        writer(const WriteFunc &new_writer)
        {
            _writer = new_writer;
            return *this;
        }
        template <class Parent, class... Args>
        constexpr This &
        writer(Parent *parent, void (Parent::*nw)(Args... args))
        {
            auto wrapper = [parent, nw](Args&&... args) {
                (parent->*nw)(std::forward<Args>(args)...);
            };
            return writer(wrapper);
        }

        // Set the callables which handle reads or writes. These may need to
        // be handled specially if, for instance, accessing bits outside of
        // the enables would have side effects that shouldn't happen.
        //
        // The default partial reader just uses the byte enables to mask off
        // bits that are not being read.
        //
        // The default partial writer reads the current value of the register,
        // uses the byte enables to update only the bytes that are changing,
        // and then writes the result back to the register.
        constexpr This &
        partialReader(const PartialReadFunc &new_reader)
        {
            _partialReader = new_reader;
            return *this;
        }
        template <class Parent, class... Args>
        constexpr This &
        partialReader(Parent *parent, Data (Parent::*nr)(Args... args))
        {
            auto wrapper = [parent, nr](Args&&... args) -> Data {
                return (parent->*nr)(std::forward<Args>(args)...);
            };
            return partialReader(wrapper);
        }
        constexpr This &
        partialWriter(const PartialWriteFunc &new_writer)
        {
            _partialWriter = new_writer;
            return *this;
        }
        template <class Parent, class... Args>
        constexpr This &
        partialWriter(Parent *parent, void (Parent::*nw)(Args... args))
        {
            auto wrapper = [parent, nw](Args&&... args) {
                return (parent->*nw)(std::forward<Args>(args)...);
            };
            return partialWriter(wrapper);
        }

        // Set the callables which handle resetting.
        //
        // The default resetter restores the initial value used in the
        // constructor.
        constexpr This &
        resetter(const ResetFunc &new_resetter)
        {
            _resetter = new_resetter;
            return *this;
        }
        template <class Parent, class... Args>
        constexpr This &
        resetter(Parent *parent, void (Parent::*nr)(Args... args))
        {
            auto wrapper = [parent, nr](Args&&... args) {
                return (parent->*nr)(std::forward<Args>(args)...);
            };
            return resetter(wrapper);
        }

        // An accessor which returns the initial value as set in the
        // constructor. This is intended to be used in a resetter function.
        const Data &initialValue() const { return _resetData; }

        // Reset the initial value, which is normally set in the constructor,
        // to the register's current value.
        void resetInitialValue() { _resetData = _data; }

        /*
         * Interface for accessing the register's state, for use by the
         * register's helper functions and the register bank.
         */

        const Data &writeable() const { return _writeMask; }

        // Directly access the underlying data value.
        const Data &get() const { return _data; }
        Data &get() { return _data; }

        // Update data while applying a mask.
        void
        update(const Data &new_data, const Data &bitmask)
        {
            _data = writeWithMask(_data, new_data, bitmask);
        }
        // This version uses the default write mask.
        void
        update(const Data &new_data)
        {
            _data = writeWithMask(_data, new_data, _writeMask);
        }


        /*
         * Interface for reading/writing the register, for use by the
         * register bank.
         */

        // Perform a read on the register.
        void
        read(void *buf) override
        {
            Data data = htoreg(_reader(*this));
            memcpy(buf, (uint8_t *)&data, sizeof(data));
        }

        void
        read(void *buf, off_t offset, size_t bytes) override
        {
            // Move the region we're reading to be little endian, since that's
            // what gem5 uses internally in BitUnions, masks, etc.
            const off_t host_off = (RegByteOrder != ByteOrder::little) ?
                sizeof(Data) - (offset + bytes) : offset;

            const int first = (host_off + bytes) * 8 - 1;
            const int last = host_off * 8;
            Data data = htoreg(_partialReader(*this, first, last));

            memcpy(buf, (uint8_t *)&data + offset, bytes);
        }

        // Perform a write on the register.
        void
        write(const void *buf) override
        {
            Data data;
            memcpy((uint8_t *)&data, buf, sizeof(data));
            data = regtoh(data);
            _writer(*this, data);
        }

        void
        write(const void *buf, off_t offset, size_t bytes) override
        {
            Data data = {};
            memcpy((uint8_t *)&data + offset, buf, bytes);

            data = regtoh(data);

            // Move the region we're reading to be little endian, since that's
            // what gem5 uses internally in BitUnions, masks, etc.
            const off_t host_off = (RegByteOrder != ByteOrder::little) ?
                sizeof(Data) - (offset + bytes) : offset;

            const int first = (host_off + bytes) * 8 - 1;
            const int last = host_off * 8;
            _partialWriter(*this, data, first, last);
        }

        // Serialize our data using existing mechanisms.
        void
        serialize(std::ostream &os) const override
        {
            ShowParam<Data>::show(os, get());
        }

        bool
        unserialize(const std::string &s) override
        {
            return ParseParam<Data>::parse(s, get());
        }

        // Reset our data to its initial value.
        void reset() override { _resetter(*this); }
    };

  private:
    std::map<Addr, std::reference_wrapper<RegisterBase>> _offsetMap;

    Addr _base = 0;
    Addr _size = 0;
    const std::string _name;

  public:

    using Register8 = Register<uint8_t>;
    using Register8LE = Register<uint8_t, ByteOrder::little>;
    using Register8BE = Register<uint8_t, ByteOrder::big>;
    using Register16 = Register<uint16_t>;
    using Register16LE = Register<uint16_t, ByteOrder::little>;
    using Register16BE = Register<uint16_t, ByteOrder::big>;
    using Register32 = Register<uint32_t>;
    using Register32LE = Register<uint32_t, ByteOrder::little>;
    using Register32BE = Register<uint32_t, ByteOrder::big>;
    using Register64 = Register<uint64_t>;
    using Register64LE = Register<uint64_t, ByteOrder::little>;
    using Register64BE = Register<uint64_t, ByteOrder::big>;


    constexpr RegisterBank(const std::string &new_name, Addr new_base) :
        _base(new_base), _name(new_name)
    {}

    virtual ~RegisterBank() {}

    class RegisterAdder
    {
      private:
        std::optional<Addr> offset;
        std::optional<RegisterBase *> reg;

      public:
        // Nothing special to do for this register.
        RegisterAdder(RegisterBase &new_reg) : reg(&new_reg) {}
        // Ensure that this register is added at a particular offset.
        RegisterAdder(Addr new_offset, RegisterBase &new_reg) :
            offset(new_offset), reg(&new_reg)
        {}
        // No register, just check that the offset is what we expect.
        RegisterAdder(Addr new_offset) : offset(new_offset) {}

        friend class RegisterBank;
    };

    void
    addRegisters(std::initializer_list<RegisterAdder> adders)
    {
        panic_if(std::empty(adders),
                "Adding an empty list of registers to %s?", name());
        for (auto &adder: adders) {
            const Addr offset = _base + _size;

            if (adder.reg) {
                auto *reg = adder.reg.value();
                if (adder.offset && adder.offset.value() != offset) {
                    panic(
                        "Expected offset of register %s.%s to be %#x, is %#x.",
                        name(), reg->name(), adder.offset.value(), offset);
                }
                _offsetMap.emplace(offset, *reg);
                _size += reg->size();
            } else if (adder.offset) {
                if (adder.offset.value() != offset) {
                    panic("Expected current offset of %s to be %#x, is %#x.",
                        name(), adder.offset.value(), offset);
                }
            }
        }
    }

    void addRegister(RegisterAdder reg) { addRegisters({reg}); }

    Addr base() const { return _base; }
    Addr size() const { return _size; }
    const std::string &name() const { return _name; }

    virtual void
    read(Addr addr, void *buf, Addr bytes)
    {
        uint8_t *ptr = (uint8_t *)buf;
        // Number of bytes we've transferred.
        Addr done = 0;

        panic_if(addr - base() + bytes > size(),
            "Out of bounds read in register bank %s, address %#x, size %d.",
            name(), addr, bytes);

        auto it = _offsetMap.lower_bound(addr);
        if (it == _offsetMap.end() || it->first > addr)
            it--;

        if (it->first < addr) {
            RegisterBase &reg = it->second.get();
            // Skip at least the beginning of the first register.

            // Figure out what parts of it we're accessing.
            const off_t reg_off = addr - it->first;
            const size_t reg_bytes = std::min(reg.size() - reg_off,
                                              bytes - done);

            // Actually do the access.
            reg.read(ptr, reg_off, reg_bytes);
            done += reg_bytes;
            it++;

            // Was that everything?
            if (done == bytes)
                return;
        }

        while (true) {
            RegisterBase &reg = it->second.get();

            const size_t reg_size = reg.size();
            const size_t remaining = bytes - done;

            if (remaining == reg_size) {
                // A complete register read, and then we're done.
                reg.read(ptr + done);
                return;
            } else if (remaining > reg_size) {
                // A complete register read, with more to go.
                reg.read(ptr + done);
                done += reg_size;
                it++;
            } else {
                // Skip the end of the register, and then we're done.
                reg.read(ptr + done, 0, remaining);
                return;
            }
        }
    }

    virtual void
    write(Addr addr, const void *buf, Addr bytes)
    {
        const uint8_t *ptr = (const uint8_t *)buf;
        // Number of bytes we've transferred.
        Addr done = 0;

        panic_if(addr - base() + bytes > size(),
            "Out of bounds write in register bank %s, address %#x, size %d.",
            name(), addr, bytes);

        auto it = _offsetMap.lower_bound(addr);
        if (it == _offsetMap.end() || it->first > addr)
            it--;

        if (it->first < addr) {
            RegisterBase &reg = it->second.get();
            // Skip at least the beginning of the first register.

            // Figure out what parts of it we're accessing.
            const off_t reg_off = addr - it->first;
            const size_t reg_bytes = std::min(reg.size() - reg_off,
                                              bytes - done);

            // Actually do the access.
            reg.write(ptr, reg_off, reg_bytes);
            done += reg_bytes;
            it++;

            // Was that everything?
            if (done == bytes)
                return;
        }

        while (true) {
            RegisterBase &reg = it->second.get();

            const size_t reg_size = reg.size();
            const size_t remaining = bytes - done;

            if (remaining == reg_size) {
                // A complete register write, and then we're done.
                reg.write(ptr + done);
                return;
            } else if (remaining > reg_size) {
                // A complete register write, with more to go.
                reg.write(ptr + done);
                done += reg_size;
                it++;
            } else {
                // Skip the end of the register, and then we're done.
                reg.write(ptr + done, 0, remaining);
                return;
            }
        }
    }

    // By default, reset all the registers in the bank.
    virtual void
    reset()
    {
        for (auto &it: _offsetMap)
            it.second.get().reset();
    }
};

using RegisterBankLE = RegisterBank<ByteOrder::little>;
using RegisterBankBE = RegisterBank<ByteOrder::big>;

// Delegate serialization to the individual RegisterBase subclasses.
template <class T>
struct ParseParam<T, std::enable_if_t<std::is_base_of_v<
    typename RegisterBankBase::RegisterBaseBase, T>>>
{
    static bool
    parse(const std::string &s, T &value)
    {
        return value.unserialize(s);
    }
};

template <class T>
struct ShowParam<T, std::enable_if_t<std::is_base_of_v<
    typename RegisterBankBase::RegisterBaseBase, T>>>
{
    static void
    show(std::ostream &os, const T &value)
    {
        value.serialize(os);
    }
};

} // namespace gem5

#endif // __DEV_REG_BANK_HH__
