1/*
2 * Copyright (c) 2010 Advanced Micro Devices, Inc.
3 * All rights reserved.
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Gabe Black
38 */
39
40#ifndef __ARCH_GENERIC_DEBUGFAULTS_HH__
41#define __ARCH_GENERIC_DEBUGFAULTS_HH__
42
43#include <string>
44
45#include "base/logging.hh"
46#include "sim/faults.hh"
47
48namespace GenericISA
49{
50
51class M5DebugFault : public FaultBase
52{
53  protected:
54    std::string _message;
55    virtual void debugFunc() = 0;
56    void
57    advancePC(ThreadContext *tc, const StaticInstPtr &inst)
58    {
59        if (inst) {
60            auto pc = tc->pcState();
61            inst->advancePC(pc);
62            tc->pcState(pc);
63        }
64    }
65
66  public:
67    M5DebugFault(std::string _m) : _message(_m) {}
68
69    template <class ...Args>
70    M5DebugFault(const std::string &format, const Args &...args) :
71        _message(csprintf(format, args...))
72    {}
73
74    std::string message() { return _message; }
75
76    void
77    invoke(ThreadContext *tc, const StaticInstPtr &inst =
78           StaticInst::nullStaticInstPtr) override
79    {
80        debugFunc();
81        advancePC(tc, inst);
82    }
83};
84
85// The "Flavor" template parameter is to keep warn, hack or inform messages
86// with the same token from blocking each other.
87template <class Flavor>
88class M5DebugOnceFault : public M5DebugFault
89{
90  protected:
91    bool &once;
92
93    template <class F, class OnceToken>
94    static bool &
95    lookUpToken(const OnceToken &token)
96    {
97        static std::map<OnceToken, bool> tokenMap;
98        return tokenMap[token];
99    }
100
101  public:
102    template <class OnceToken, class ...Args>
103    M5DebugOnceFault(const OnceToken &token, const std::string &format,
104            const Args &...args) :
105        M5DebugFault(format, args...), once(lookUpToken<Flavor>(token))
106    {}
107
108    void
109    invoke(ThreadContext *tc, const StaticInstPtr &inst =
110           StaticInst::nullStaticInstPtr) override
111    {
112        if (!once) {
113            once = true;
114            debugFunc();
115        }
116        advancePC(tc, inst);
117    }
118};
119
120class M5PanicFault : public M5DebugFault
121{
122  public:
123    using M5DebugFault::M5DebugFault;
124    void debugFunc() override { panic(message()); }
125    FaultName name() const override { return "panic fault"; }
126};
127
128class M5FatalFault : public M5DebugFault
129{
130  public:
131    using M5DebugFault::M5DebugFault;
132    void debugFunc() override { fatal(message()); }
133    FaultName name() const override { return "fatal fault"; }
134};
135
136template <class Base>
137class M5WarnFaultBase : public Base
138{
139  public:
140    using Base::Base;
141    void debugFunc() override { warn(this->message()); }
142    FaultName name() const override { return "warn fault"; }
143};
144
145using M5WarnFault = M5WarnFaultBase<M5DebugFault>;
146using M5WarnOnceFault = M5WarnFaultBase<M5DebugOnceFault<M5WarnFault>>;
147
148template <class Base>
149class M5HackFaultBase : public Base
150{
151  public:
152    using Base::Base;
153    void debugFunc() override { hack(this->message()); }
154    FaultName name() const override { return "hack fault"; }
155};
156
157using M5HackFault = M5HackFaultBase<M5DebugFault>;
158using M5HackOnceFault = M5HackFaultBase<M5DebugOnceFault<M5HackFault>>;
159
160template <class Base>
161class M5InformFaultBase : public Base
162{
163  public:
164    using Base::Base;
165    void debugFunc() override { inform(this->message()); }
166    FaultName name() const override { return "inform fault"; }
167};
168
169using M5InformFault = M5InformFaultBase<M5DebugFault>;
170using M5InformOnceFault =
171    M5InformFaultBase<M5DebugOnceFault<M5InformFault>>;
172
173} // namespace GenericISA
174
175#endif // __ARCH_GENERIC_DEBUGFAULTS_HH__
176