cpu.hh revision 2669
1/*
2 * Copyright (c) 2006 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef __CPU_CHECKER_CPU_HH__
30#define __CPU_CHECKER_CPU_HH__
31
32#include <list>
33#include <queue>
34#include <map>
35
36#include "arch/types.hh"
37#include "base/statistics.hh"
38#include "config/full_system.hh"
39#include "cpu/base.hh"
40#include "cpu/base_dyn_inst.hh"
41#include "cpu/cpu_exec_context.hh"
42#include "cpu/pc_event.hh"
43#include "cpu/static_inst.hh"
44#include "sim/eventq.hh"
45
46// forward declarations
47#if FULL_SYSTEM
48class Processor;
49class AlphaITB;
50class AlphaDTB;
51class PhysicalMemory;
52
53class RemoteGDB;
54class GDBListener;
55
56#else
57
58class Process;
59
60#endif // FULL_SYSTEM
61template <class>
62class BaseDynInst;
63class ExecContext;
64class MemInterface;
65class Checkpoint;
66class Request;
67class Sampler;
68
69class CheckerCPU : public BaseCPU
70{
71  protected:
72    typedef TheISA::MachInst MachInst;
73    typedef TheISA::FloatReg FloatReg;
74    typedef TheISA::FloatRegBits FloatRegBits;
75    typedef TheISA::MiscReg MiscReg;
76  public:
77    // main simulation loop (one cycle)
78    virtual void init();
79
80    struct Params : public BaseCPU::Params
81    {
82#if FULL_SYSTEM
83        AlphaITB *itb;
84        AlphaDTB *dtb;
85        FunctionalMemory *mem;
86#else
87        Process *process;
88#endif
89        bool exitOnError;
90    };
91
92  public:
93    CheckerCPU(Params *p);
94    virtual ~CheckerCPU();
95
96    void setMemory(MemObject *mem);
97
98    MemObject *memPtr;
99
100#if FULL_SYSTEM
101    void setSystem(System *system);
102
103    System *systemPtr;
104#endif
105  public:
106    // execution context
107    CPUExecContext *cpuXC;
108
109    ExecContext *xcProxy;
110
111    AlphaITB *itb;
112    AlphaDTB *dtb;
113
114#if FULL_SYSTEM
115    Addr dbg_vtophys(Addr addr);
116#endif
117
118    union Result {
119        uint64_t integer;
120        float fp;
121        double dbl;
122    };
123
124    Result result;
125
126    // current instruction
127    MachInst machInst;
128
129    // Refcounted pointer to the one memory request.
130    Request *memReq;
131
132    StaticInstPtr curStaticInst;
133
134    // number of simulated instructions
135    Counter numInst;
136    Counter startNumInst;
137
138    std::queue<int> miscRegIdxs;
139
140    virtual Counter totalInstructions() const
141    {
142        return numInst - startNumInst;
143    }
144
145    // number of simulated loads
146    Counter numLoad;
147    Counter startNumLoad;
148
149    virtual void serialize(std::ostream &os);
150    virtual void unserialize(Checkpoint *cp, const std::string &section);
151
152    template <class T>
153    Fault read(Addr addr, T &data, unsigned flags);
154
155    template <class T>
156    Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
157
158    // These functions are only used in CPU models that split
159    // effective address computation from the actual memory access.
160    void setEA(Addr EA) { panic("SimpleCPU::setEA() not implemented\n"); }
161    Addr getEA() 	{ panic("SimpleCPU::getEA() not implemented\n"); }
162
163    void prefetch(Addr addr, unsigned flags)
164    {
165        // need to do this...
166    }
167
168    void writeHint(Addr addr, int size, unsigned flags)
169    {
170        // need to do this...
171    }
172
173    Fault copySrcTranslate(Addr src);
174
175    Fault copy(Addr dest);
176
177    // The register accessor methods provide the index of the
178    // instruction's operand (e.g., 0 or 1), not the architectural
179    // register index, to simplify the implementation of register
180    // renaming.  We find the architectural register index by indexing
181    // into the instruction's own operand index table.  Note that a
182    // raw pointer to the StaticInst is provided instead of a
183    // ref-counted StaticInstPtr to redice overhead.  This is fine as
184    // long as these methods don't copy the pointer into any long-term
185    // storage (which is pretty hard to imagine they would have reason
186    // to do).
187
188    uint64_t readIntReg(const StaticInst *si, int idx)
189    {
190        return cpuXC->readIntReg(si->srcRegIdx(idx));
191    }
192
193    FloatReg readFloatReg(const StaticInst *si, int idx, int width)
194    {
195        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
196        return cpuXC->readFloatReg(reg_idx, width);
197    }
198
199    FloatReg readFloatReg(const StaticInst *si, int idx)
200    {
201        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
202        return cpuXC->readFloatReg(reg_idx);
203    }
204
205    FloatRegBits readFloatRegBits(const StaticInst *si, int idx, int width)
206    {
207        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
208        return cpuXC->readFloatRegBits(reg_idx, width);
209    }
210
211    FloatRegBits readFloatRegBits(const StaticInst *si, int idx)
212    {
213        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
214        return cpuXC->readFloatRegBits(reg_idx);
215    }
216
217    void setIntReg(const StaticInst *si, int idx, uint64_t val)
218    {
219        cpuXC->setIntReg(si->destRegIdx(idx), val);
220        result.integer = val;
221    }
222
223    void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width)
224    {
225        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
226        cpuXC->setFloatReg(reg_idx, val, width);
227        switch(width) {
228          case 32:
229            result.fp = val;
230            break;
231          case 64:
232            result.dbl = val;
233            break;
234        };
235    }
236
237    void setFloatReg(const StaticInst *si, int idx, FloatReg val)
238    {
239        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
240        cpuXC->setFloatReg(reg_idx, val);
241        result.fp = val;
242    }
243
244    void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val,
245                         int width)
246    {
247        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
248        cpuXC->setFloatRegBits(reg_idx, val, width);
249        result.integer = val;
250    }
251
252    void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val)
253    {
254        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
255        cpuXC->setFloatRegBits(reg_idx, val);
256        result.integer = val;
257    }
258
259    uint64_t readPC() { return cpuXC->readPC(); }
260
261    uint64_t readNextPC() { return cpuXC->readNextPC(); }
262
263    void setNextPC(uint64_t val) {
264        cpuXC->setNextPC(val);
265    }
266
267    MiscReg readMiscReg(int misc_reg)
268    {
269        return cpuXC->readMiscReg(misc_reg);
270    }
271
272    MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
273    {
274        return cpuXC->readMiscRegWithEffect(misc_reg, fault);
275    }
276
277    Fault setMiscReg(int misc_reg, const MiscReg &val)
278    {
279        result.integer = val;
280        miscRegIdxs.push(misc_reg);
281        return cpuXC->setMiscReg(misc_reg, val);
282    }
283
284    Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
285    {
286        miscRegIdxs.push(misc_reg);
287        return cpuXC->setMiscRegWithEffect(misc_reg, val);
288    }
289
290    void recordPCChange(uint64_t val) { changedPC = true; }
291    void recordNextPCChange(uint64_t val) { changedNextPC = true; }
292
293    bool translateInstReq(Request *req);
294    void translateDataWriteReq(Request *req);
295    void translateDataReadReq(Request *req);
296
297#if FULL_SYSTEM
298    Fault hwrei() { return cpuXC->hwrei(); }
299    int readIntrFlag() { return cpuXC->readIntrFlag(); }
300    void setIntrFlag(int val) { cpuXC->setIntrFlag(val); }
301    bool inPalMode() { return cpuXC->inPalMode(); }
302    void ev5_trap(Fault fault) { fault->invoke(xcProxy); }
303    bool simPalCheck(int palFunc) { return cpuXC->simPalCheck(palFunc); }
304#else
305    // Assume that the normal CPU's call to syscall was successful.
306    // The checker's state would have already been updated by the syscall.
307    void syscall(uint64_t callnum) { }
308#endif
309
310    void handleError()
311    {
312        if (exitOnError)
313            panic("Checker found error!");
314    }
315    bool checkFlags(Request *req);
316
317    ExecContext *xcBase() { return xcProxy; }
318    CPUExecContext *cpuXCBase() { return cpuXC; }
319
320    Result unverifiedResult;
321    Request *unverifiedReq;
322
323    bool changedPC;
324    bool willChangePC;
325    uint64_t newPC;
326    bool changedNextPC;
327    bool exitOnError;
328
329    InstSeqNum youngestSN;
330};
331
332template <class DynInstPtr>
333class Checker : public CheckerCPU
334{
335  public:
336    Checker(Params *p)
337        : CheckerCPU(p)
338    { }
339
340    void switchOut(Sampler *s);
341    void takeOverFrom(BaseCPU *oldCPU);
342
343    void tick(DynInstPtr &inst);
344
345    void validateInst(DynInstPtr &inst);
346    void validateExecution(DynInstPtr &inst);
347    void validateState();
348
349    std::list<DynInstPtr> instList;
350    typedef typename std::list<DynInstPtr>::iterator InstListIt;
351    void dumpInsts();
352};
353
354#endif // __CPU_CHECKER_CPU_HH__
355