cpu.hh revision 2315
1/*
2 * Copyright (c) 2002-2005 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 "base/statistics.hh"
37#include "config/full_system.hh"
38#include "cpu/base.hh"
39#include "cpu/base_dyn_inst.hh"
40#include "cpu/cpu_exec_context.hh"
41#include "cpu/pc_event.hh"
42#include "cpu/sampler/sampler.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;
66
67class CheckerCPU : public BaseCPU
68{
69  protected:
70    typedef TheISA::MachInst MachInst;
71    typedef TheISA::MiscReg MiscReg;
72  public:
73    // main simulation loop (one cycle)
74    virtual void init();
75
76    struct Params : public BaseCPU::Params
77    {
78#if FULL_SYSTEM
79        AlphaITB *itb;
80        AlphaDTB *dtb;
81        FunctionalMemory *mem;
82#else
83        Process *process;
84#endif
85        bool exitOnError;
86    };
87
88  public:
89    void post_interrupt(int int_num, int index);
90
91    CheckerCPU(Params *p);
92    virtual ~CheckerCPU();
93
94    void setMemory(FunctionalMemory *mem);
95
96    FunctionalMemory *memPtr;
97
98#if FULL_SYSTEM
99    void setSystem(System *system);
100
101    System *systemPtr;
102#endif
103  public:
104    // execution context
105    CPUExecContext *cpuXC;
106
107    ExecContext *xcProxy;
108
109    AlphaITB *itb;
110    AlphaDTB *dtb;
111
112#if FULL_SYSTEM
113    Addr dbg_vtophys(Addr addr);
114
115    bool interval_stats;
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    MemReqPtr memReq;
131
132    // Pointer to the sampler that is telling us to switchover.
133    // Used to signal the completion of the pipe drain and schedule
134    // the next switchover
135    Sampler *sampler;
136
137    StaticInstPtr curStaticInst;
138
139    // number of simulated instructions
140    Counter numInst;
141    Counter startNumInst;
142
143    std::queue<int> miscRegIdxs;
144
145    virtual Counter totalInstructions() const
146    {
147        return numInst - startNumInst;
148    }
149
150    // number of simulated loads
151    Counter numLoad;
152    Counter startNumLoad;
153
154    virtual void serialize(std::ostream &os);
155    virtual void unserialize(Checkpoint *cp, const std::string &section);
156
157    template <class T>
158    Fault read(Addr addr, T &data, unsigned flags);
159
160    template <class T>
161    Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
162
163    // These functions are only used in CPU models that split
164    // effective address computation from the actual memory access.
165    void setEA(Addr EA) { panic("SimpleCPU::setEA() not implemented\n"); }
166    Addr getEA() 	{ panic("SimpleCPU::getEA() not implemented\n"); }
167
168    void prefetch(Addr addr, unsigned flags)
169    {
170        // need to do this...
171    }
172
173    void writeHint(Addr addr, int size, unsigned flags)
174    {
175        // need to do this...
176    }
177
178    Fault copySrcTranslate(Addr src);
179
180    Fault copy(Addr dest);
181
182    // The register accessor methods provide the index of the
183    // instruction's operand (e.g., 0 or 1), not the architectural
184    // register index, to simplify the implementation of register
185    // renaming.  We find the architectural register index by indexing
186    // into the instruction's own operand index table.  Note that a
187    // raw pointer to the StaticInst is provided instead of a
188    // ref-counted StaticInstPtr to redice overhead.  This is fine as
189    // long as these methods don't copy the pointer into any long-term
190    // storage (which is pretty hard to imagine they would have reason
191    // to do).
192
193    uint64_t readIntReg(const StaticInst *si, int idx)
194    {
195        return cpuXC->readIntReg(si->srcRegIdx(idx));
196    }
197
198    float readFloatRegSingle(const StaticInst *si, int idx)
199    {
200        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
201        return cpuXC->readFloatRegSingle(reg_idx);
202    }
203
204    double readFloatRegDouble(const StaticInst *si, int idx)
205    {
206        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
207        return cpuXC->readFloatRegDouble(reg_idx);
208    }
209
210    uint64_t readFloatRegInt(const StaticInst *si, int idx)
211    {
212        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
213        return cpuXC->readFloatRegInt(reg_idx);
214    }
215
216    void setIntReg(const StaticInst *si, int idx, uint64_t val)
217    {
218        cpuXC->setIntReg(si->destRegIdx(idx), val);
219        result.integer = val;
220    }
221
222    void setFloatRegSingle(const StaticInst *si, int idx, float val)
223    {
224        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
225        cpuXC->setFloatRegSingle(reg_idx, val);
226        result.fp = val;
227    }
228
229    void setFloatRegDouble(const StaticInst *si, int idx, double val)
230    {
231        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
232        cpuXC->setFloatRegDouble(reg_idx, val);
233        result.dbl = val;
234    }
235
236    void setFloatRegInt(const StaticInst *si, int idx, uint64_t val)
237    {
238        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
239        cpuXC->setFloatRegInt(reg_idx, val);
240        result.integer = val;
241    }
242
243    uint64_t readPC() { return cpuXC->readPC(); }
244    void setNextPC(uint64_t val) {
245        cpuXC->setNextPC(val);
246    }
247
248    MiscReg readMiscReg(int misc_reg)
249    {
250        return cpuXC->readMiscReg(misc_reg);
251    }
252
253    MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
254    {
255        return cpuXC->readMiscRegWithEffect(misc_reg, fault);
256    }
257
258    Fault setMiscReg(int misc_reg, const MiscReg &val)
259    {
260        result.integer = val;
261        miscRegIdxs.push(misc_reg);
262        return cpuXC->setMiscReg(misc_reg, val);
263    }
264
265    Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
266    {
267        miscRegIdxs.push(misc_reg);
268        return cpuXC->setMiscRegWithEffect(misc_reg, val);
269    }
270
271    void recordPCChange(uint64_t val) { changedPC = true; }
272    void recordNextPCChange(uint64_t val) { changedNextPC = true; }
273
274    bool translateInstReq(MemReqPtr &req);
275    void translateDataWriteReq(MemReqPtr &req);
276    void translateDataReadReq(MemReqPtr &req);
277
278#if FULL_SYSTEM
279    Fault hwrei() { return cpuXC->hwrei(); }
280    int readIntrFlag() { return cpuXC->readIntrFlag(); }
281    void setIntrFlag(int val) { cpuXC->setIntrFlag(val); }
282    bool inPalMode() { return cpuXC->inPalMode(); }
283    void ev5_trap(Fault fault) { fault->invoke(xcProxy); }
284    bool simPalCheck(int palFunc) { return cpuXC->simPalCheck(palFunc); }
285#else
286    // Assume that the normal CPU's call to syscall was successful.
287    void syscall() { }
288#endif
289
290    void handleError()
291    {
292        if (exitOnError)
293            panic("Checker found error!");
294    }
295    bool checkFlags(MemReqPtr &req);
296
297    ExecContext *xcBase() { return xcProxy; }
298    CPUExecContext *cpuXCBase() { return cpuXC; }
299
300    Result unverifiedResult;
301    MemReqPtr unverifiedReq;
302
303    bool changedPC;
304    bool willChangePC;
305    uint64_t newPC;
306    bool changedNextPC;
307    bool exitOnError;
308
309    InstSeqNum youngestSN;
310//    std::map<Addr, uint64_t> storeBuff;
311//    typedef std::map<Addr, uint64_t>::iterator map_it;
312};
313
314template <class DynInstPtr>
315class Checker : public CheckerCPU
316{
317  public:
318    Checker(Params *p)
319        : CheckerCPU(p)
320    { }
321
322    void switchOut(Sampler *s);
323    void takeOverFrom(BaseCPU *oldCPU);
324
325    void tick(DynInstPtr &inst);
326
327    void validateInst(DynInstPtr &inst);
328    void validateExecution(DynInstPtr &inst);
329    void validateState();
330
331    std::list<DynInstPtr> instList;
332    typedef typename std::list<DynInstPtr>::iterator InstListIt;
333    void dumpInsts();
334};
335
336#endif // __CPU_CHECKER_CPU_HH__
337