diff options
author | Gabe Black <gabeblack@google.com> | 2019-09-06 17:14:59 -0700 |
---|---|---|
committer | Gabe Black <gabeblack@google.com> | 2019-09-18 06:26:35 +0000 |
commit | f3fd7469677ab1f25533d82c36460a700831ceec (patch) | |
tree | 4430edd76fd0b6d6a4ae38870d0d8771994f118e /src/arch/generic | |
parent | cd00a363f1dbb8eaf634154c6d5db9ad85278ee0 (diff) | |
download | gem5-f3fd7469677ab1f25533d82c36460a700831ceec.tar.xz |
arch, x86: Rework the debug faults and microops.
This makes the non-fatal microops advance the PC, and adds missing
functions. The *_once Faults now also can be run once per *something*.
They would previously be run once per Fault invoke function which is
common to all M5WarnOnceFaults. The warn_once microop will now warn
once per message.
Change-Id: I05974b93f3b2700077a411b243679c2ff0e8c2cb
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/20739
Reviewed-by: Gabe Black <gabeblack@google.com>
Reviewed-by: Brandon Potter <Brandon.Potter@amd.com>
Maintainer: Gabe Black <gabeblack@google.com>
Tested-by: kokoro <noreply+kokoro@google.com>
Diffstat (limited to 'src/arch/generic')
-rw-r--r-- | src/arch/generic/debugfaults.hh | 153 |
1 files changed, 100 insertions, 53 deletions
diff --git a/src/arch/generic/debugfaults.hh b/src/arch/generic/debugfaults.hh index 5c5aa01ea..1c8d882aa 100644 --- a/src/arch/generic/debugfaults.hh +++ b/src/arch/generic/debugfaults.hh @@ -50,78 +50,125 @@ namespace GenericISA class M5DebugFault : public FaultBase { - public: - enum DebugFunc - { - PanicFunc, - FatalFunc, - WarnFunc, - WarnOnceFunc - }; - protected: - std::string message; - DebugFunc func; + std::string _message; + virtual void debugFunc() = 0; + void + advancePC(ThreadContext *tc, const StaticInstPtr &inst) + { + if (inst) { + auto pc = tc->pcState(); + inst->advancePC(pc); + tc->pcState(pc); + } + } public: - M5DebugFault(DebugFunc _func, std::string _message) : - message(_message), func(_func) + M5DebugFault(std::string _m) : _message(_m) {} + + template <class ...Args> + M5DebugFault(const std::string &format, const Args &...args) : + _message(csprintf(format, args...)) {} - FaultName - name() const + std::string message() { return _message; } + + void + invoke(ThreadContext *tc, const StaticInstPtr &inst = + StaticInst::nullStaticInstPtr) override { - switch (func) { - case PanicFunc: - return "panic fault"; - case FatalFunc: - return "fatal fault"; - case WarnFunc: - return "warn fault"; - case WarnOnceFunc: - return "warn_once fault"; - default: - panic("unrecognized debug function number\n"); - } + debugFunc(); + advancePC(tc, inst); + } +}; + +// The "Flavor" template parameter is to keep warn, hack or inform messages +// with the same token from blocking each other. +template <class Flavor> +class M5DebugOnceFault : public M5DebugFault +{ + protected: + bool &once; + + template <class F, class OnceToken> + static bool & + lookUpToken(const OnceToken &token) + { + static std::map<OnceToken, bool> tokenMap; + return tokenMap[token]; } + public: + template <class OnceToken, class ...Args> + M5DebugOnceFault(const OnceToken &token, const std::string &format, + const Args &...args) : + M5DebugFault(format, args...), once(lookUpToken<Flavor>(token)) + {} + void invoke(ThreadContext *tc, const StaticInstPtr &inst = - StaticInst::nullStaticInstPtr) + StaticInst::nullStaticInstPtr) override { - switch (func) { - case PanicFunc: - panic(message); - break; - case FatalFunc: - fatal(message); - break; - case WarnFunc: - warn(message); - break; - case WarnOnceFunc: - warn_once(message); - break; - default: - panic("unrecognized debug function number\n"); + if (!once) { + once = true; + debugFunc(); } + advancePC(tc, inst); } }; -template <int Func> -class M5VarArgsFault : public M5DebugFault +class M5PanicFault : public M5DebugFault { public: - template<typename ...Args> - M5VarArgsFault(const std::string &format, const Args &...args) : - M5DebugFault((DebugFunc)Func, csprintf(format, args...)) - {} + using M5DebugFault::M5DebugFault; + void debugFunc() override { panic(message()); } + FaultName name() const override { return "panic fault"; } +}; + +class M5FatalFault : public M5DebugFault +{ + public: + using M5DebugFault::M5DebugFault; + void debugFunc() override { fatal(message()); } + FaultName name() const override { return "fatal fault"; } +}; + +template <class Base> +class M5WarnFaultBase : public Base +{ + public: + using Base::Base; + void debugFunc() override { warn(this->message()); } + FaultName name() const override { return "warn fault"; } +}; + +using M5WarnFault = M5WarnFaultBase<M5DebugFault>; +using M5WarnOnceFault = M5WarnFaultBase<M5DebugOnceFault<M5WarnFault>>; + +template <class Base> +class M5HackFaultBase : public Base +{ + public: + using Base::Base; + void debugFunc() override { hack(this->message()); } + FaultName name() const override { return "hack fault"; } +}; + +using M5HackFault = M5HackFaultBase<M5DebugFault>; +using M5HackOnceFault = M5HackFaultBase<M5DebugOnceFault<M5HackFault>>; + +template <class Base> +class M5InformFaultBase : public Base +{ + public: + using Base::Base; + void debugFunc() override { inform(this->message()); } + FaultName name() const override { return "inform fault"; } }; -typedef M5VarArgsFault<M5DebugFault::PanicFunc> M5PanicFault; -typedef M5VarArgsFault<M5DebugFault::FatalFunc> M5FatalFault; -typedef M5VarArgsFault<M5DebugFault::WarnFunc> M5WarnFault; -typedef M5VarArgsFault<M5DebugFault::WarnOnceFunc> M5WarnOnceFault; +using M5InformFault = M5InformFaultBase<M5DebugFault>; +using M5InformOnceFault = + M5InformFaultBase<M5DebugOnceFault<M5InformFault>>; } // namespace GenericISA |