From 8b1688da340e5573a0c6f00c835f08ac5f73f963 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 10 Dec 2022 02:29:43 -0800 Subject: [PATCH] dev: Introduce a reset() method on RegisterBank and Register classes. This will make it much easier to implement reset behaviors on devices which have RegisterBanks in them. Change-Id: I73fe9874fcb69feed33611a320dcca85c0de2d0e Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/66671 Tested-by: kokoro Maintainer: Gabe Black Reviewed-by: Yu-hsin Wang Reviewed-by: Jui-min Lee --- src/dev/reg_bank.hh | 41 ++++++++++++++++++++++++++++++++++++-- src/dev/serial/uart8250.hh | 7 +++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/dev/reg_bank.hh b/src/dev/reg_bank.hh index 31c0ce5b66..66d668b338 100644 --- a/src/dev/reg_bank.hh +++ b/src/dev/reg_bank.hh @@ -117,6 +117,11 @@ * 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 == * @@ -145,6 +150,12 @@ * 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 == * @@ -360,6 +371,9 @@ class RegisterBank : public RegisterBankBase // 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. @@ -388,6 +402,9 @@ class RegisterBank : public RegisterBankBase 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. @@ -453,6 +470,10 @@ class RegisterBank : public RegisterBankBase 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 @@ -516,6 +537,8 @@ class RegisterBank : public RegisterBankBase return true; } + + void reset() override { buffer = std::array{}; } }; template @@ -534,6 +557,7 @@ class RegisterBank : public RegisterBankBase private: Data _data = {}; + Data _resetData = {}; Data _writeMask = mask(sizeof(Data) * 8); ReadFunc _reader = defaultReader; @@ -602,11 +626,13 @@ class RegisterBank : public RegisterBankBase // 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) + 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) + RegisterBase(new_name, sizeof(Data)), _data(new_data), + _resetData(new_data) {} // Set which bits of the register are writeable. @@ -789,6 +815,9 @@ class RegisterBank : public RegisterBankBase { return ParseParam::parse(s, get()); } + + // Reset our data to its initial value. + void reset() override { get() = _resetData; } }; private: @@ -984,6 +1013,14 @@ class RegisterBank : public RegisterBankBase } } } + + // By default, reset all the registers in the bank. + virtual void + reset() + { + for (auto &[offset, reg]: _offsetMap) + reg.get().reset(); + } }; using RegisterBankLE = RegisterBank; diff --git a/src/dev/serial/uart8250.hh b/src/dev/serial/uart8250.hh index c55d889c82..5774f78aab 100644 --- a/src/dev/serial/uart8250.hh +++ b/src/dev/serial/uart8250.hh @@ -113,6 +113,13 @@ class Uart8250 : public Uart void serialize(std::ostream &os) const override {} bool unserialize(const std::string &s) override { return true; } + + void + reset() override + { + _reg1.reset(); + _reg2.reset(); + } }; class BankedRegister : public PairedRegister