Peter Yuen has uploaded this change for review. ( https://gem5-review.googlesource.com/c/public/gem5/+/40595 )

Change subject: arch-riscv,dev: Extended Register class to contain property
......................................................................

arch-riscv,dev: Extended Register class to contain property

This is an extension of the templated Register class to
include an arbitrary property object associated with
the register. This allows for pre- and post-processing
before reads and after writes based on the register
property (using callbacks).

This register class is used in CLINT and PLIC to post
interrupts based on the register index.

Currently it is put under src/dev/riscv. If there are
more use cases in the future it might be useful to merge
it into the src/dev/reg_bank.hh file.

Change-Id: Ife58f4e89549e60c840a9e991e0041e83e479d4a
---
A src/dev/riscv/reg_bank.hh
1 file changed, 203 insertions(+), 0 deletions(-)



diff --git a/src/dev/riscv/reg_bank.hh b/src/dev/riscv/reg_bank.hh
new file mode 100644
index 0000000..8e72e37
--- /dev/null
+++ b/src/dev/riscv/reg_bank.hh
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2021 Huawei International
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * 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_RISCV_REG_BANK_HH__
+#define __DEV_RISCV_REG_BANK_HH__
+#include "dev/reg_bank.hh"
+
+template <ByteOrder BankByteOrder>
+class PropRegisterBank : public RegisterBank<BankByteOrder> {
+
+  public:
+
+ constexpr PropRegisterBank(const std::string &new_name, Addr new_base) :
+        RegisterBank<BankByteOrder>(new_name, new_base)
+    {}
+
+    template <typename Prop, typename Data,
+        ByteOrder RegByteOrder = BankByteOrder>
+    class PropRegister : public PropRegisterBank::RegisterBase
+    {
+    public:
+        /**
+         * Type definitions for template deduction
+         */
+        using This = PropRegister<Prop, Data, RegByteOrder>;
+        typedef typename RegisterBank<RegByteOrder>::template
+            Register<Data, RegByteOrder> Register;
+ typedef typename RegisterBank<RegByteOrder>::RegisterBase RegisterBase;
+        using CallBackFunc = std::function<void(This &reg)>;
+
+        /**
+         * Class variables
+         */
+        Register reg;
+
+    private:
+        Prop _prop = {};
+        CallBackFunc _readCallBack = emptyCallBack;
+        CallBackFunc _writeCallBack = emptyCallBack;
+
+    public:
+        // Constructors
+        constexpr PropRegister(const std::string &new_name,
+            const Prop &new_prop, const Data &new_data) :
+            RegisterBase(new_name, sizeof(new_data)),
+            reg(new_name, new_data),
+            _prop(new_prop) {}
+
+        constexpr PropRegister(const std::string &new_name,
+            const Prop &&new_prop, const Data &&new_data) :
+            RegisterBase(new_name, sizeof(new_data)),
+            reg(new_name, new_data),
+            _prop(new_prop) {}
+
+        // Callback functions
+        static void emptyCallBack(This &reg) {}
+
+        template <class Parent, class... Args>
+        constexpr This &
+        beforeRead(Parent *parent, void (Parent::*nr)(Args... args)) {
+            auto wrapper = [parent, nr](Args &&... args) {
+                return (parent->*nr)(std::forward<Args>(args)...);
+            };
+            _readCallBack = wrapper;
+            return *this;
+        }
+
+        template <class Parent, class... Args>
+        constexpr This &
+        afterWrite(Parent *parent, void (Parent::*nw)(Args... args)) {
+            auto wrapper = [parent, nw](Args &&... args) {
+                (parent->*nw)(std::forward<Args>(args)...);
+            };
+            _writeCallBack = wrapper;
+            return *this;
+        }
+
+        /**
+         * Public access functions
+         */
+        const Prop &getProp() const { return _prop; }
+
+        const Data &get() const { return reg.get(); }
+        Data &get() { return reg.get(); }
+
+        void
+        update(const Data &new_data) {
+            reg.update(new_data);
+        }
+
+        void
+        update(const Data &new_data, const Data &bitmask) {
+            reg.update(new_data, bitmask);
+        }
+
+        /**
+         * RegisterBase interface
+         */
+
+        void read(void *buf) override {
+            _readCallBack(*this);
+            reg.read(buf);
+        }
+        void
+        read(void *buf, off_t offset, size_t bytes) override {
+            _readCallBack(*this);
+            reg.read(buf, offset, bytes);
+        }
+        void write(const void *buf) override {
+            reg.write(buf);
+            _writeCallBack(*this);
+        }
+        void
+        write(const void *buf, off_t offset, size_t bytes) override {
+            reg.write(buf, offset, bytes);
+            _writeCallBack(*this);
+        }
+
+        /**
+         * Serialization
+         */
+        void
+        serialize(std::ostream &os) const override {
+            uint8_t *prop_ptr = const_cast<uint8_t *>(
+                reinterpret_cast<const uint8_t *>(&_prop));
+            size_t prop_size = sizeof(_prop);
+            if (prop_size)
+                ShowParam<uint8_t>::show(os, prop_ptr[0]);
+            for (int i = 1; i < prop_size; i++) {
+                os << " ";
+                ShowParam<uint8_t>::show(os, prop_ptr[i]);
+            }
+
+            os << " ";
+            ShowParam<Data>::show(os, reg.get());
+        }
+
+        bool
+        unserialize(const std::string &s) override {
+            uint8_t *prop_ptr = const_cast<uint8_t *>(
+                reinterpret_cast<const uint8_t *>(&_prop));
+            size_t prop_size = sizeof(_prop);
+            std::vector<std::string> tokens;
+            std::istringstream is(s);
+
+            std::string token;
+            while (is >> token)
+                tokens.push_back(token);
+
+            if (tokens.size() != prop_size + 1) {
+                warn("Size mismatch unserialing %s, expected %d, got %d",
+                        this->name(), prop_size + 1, tokens.size());
+                return false;
+            }
+
+            for (int i = 0; i < prop_size; i++) {
+                if (!ParseParam<uint8_t>::parse(tokens[i], prop_ptr[i]))
+                    return false;
+            }
+
+            return ParseParam<Data>::parse(tokens[prop_size], reg.get());
+        }
+    };
+};
+
+using PropRegisterBankLE = PropRegisterBank<ByteOrder::little>;
+using PropRegisterBankBE = PropRegisterBank<ByteOrder::big>;
+
+#endif

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/40595
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: Ife58f4e89549e60c840a9e991e0041e83e479d4a
Gerrit-Change-Number: 40595
Gerrit-PatchSet: 1
Gerrit-Owner: Peter Yuen <petery....@huawei.com>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- gem5-dev@gem5.org
To unsubscribe send an email to gem5-dev-le...@gem5.org
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s

Reply via email to