base.hh revision 1858
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_SIMPLE_CPU_SIMPLE_CPU_HH__
30#define __CPU_SIMPLE_CPU_SIMPLE_CPU_HH__
31
32#include "base/statistics.hh"
33#include "config/full_system.hh"
34#include "cpu/base.hh"
35#include "cpu/exec_context.hh"
36#include "cpu/pc_event.hh"
37#include "cpu/sampler/sampler.hh"
38#include "cpu/static_inst.hh"
39#include "sim/eventq.hh"
40
41// forward declarations
42#if FULL_SYSTEM
43class Processor;
44class AlphaITB;
45class AlphaDTB;
46class PhysicalMemory;
47
48class RemoteGDB;
49class GDBListener;
50
51#else
52
53class Process;
54
55#endif // FULL_SYSTEM
56
57class MemInterface;
58class Checkpoint;
59
60namespace Trace {
61    class InstRecord;
62}
63
64class SimpleCPU : public BaseCPU
65{
66  public:
67    // main simulation loop (one cycle)
68    void tick();
69
70  private:
71    struct TickEvent : public Event
72    {
73        SimpleCPU *cpu;
74        int width;
75
76        TickEvent(SimpleCPU *c, int w);
77        void process();
78        const char *description();
79    };
80
81    TickEvent tickEvent;
82
83    /// Schedule tick event, regardless of its current state.
84    void scheduleTickEvent(int numCycles)
85    {
86        if (tickEvent.squashed())
87            tickEvent.reschedule(curTick + cycles(numCycles));
88        else if (!tickEvent.scheduled())
89            tickEvent.schedule(curTick + cycles(numCycles));
90    }
91
92    /// Unschedule tick event, regardless of its current state.
93    void unscheduleTickEvent()
94    {
95        if (tickEvent.scheduled())
96            tickEvent.squash();
97    }
98
99  private:
100    Trace::InstRecord *traceData;
101
102  public:
103    //
104    enum Status {
105        Running,
106        Idle,
107        IcacheMissStall,
108        IcacheMissComplete,
109        DcacheMissStall,
110        DcacheMissSwitch,
111        SwitchedOut
112    };
113
114  private:
115    Status _status;
116
117  public:
118    void post_interrupt(int int_num, int index);
119
120    void zero_fill_64(Addr addr) {
121      static int warned = 0;
122      if (!warned) {
123        warn ("WH64 is not implemented");
124        warned = 1;
125      }
126    };
127
128  public:
129    struct Params : public BaseCPU::Params
130    {
131        MemInterface *icache_interface;
132        MemInterface *dcache_interface;
133        int width;
134#if FULL_SYSTEM
135        AlphaITB *itb;
136        AlphaDTB *dtb;
137        FunctionalMemory *mem;
138#else
139        Process *process;
140#endif
141    };
142    SimpleCPU(Params *params);
143    virtual ~SimpleCPU();
144
145  public:
146    // execution context
147    ExecContext *xc;
148
149    void switchOut(Sampler *s);
150    void takeOverFrom(BaseCPU *oldCPU);
151
152#if FULL_SYSTEM
153    Addr dbg_vtophys(Addr addr);
154
155    bool interval_stats;
156#endif
157
158    // L1 instruction cache
159    MemInterface *icacheInterface;
160
161    // L1 data cache
162    MemInterface *dcacheInterface;
163
164    // current instruction
165    MachInst inst;
166
167    // Refcounted pointer to the one memory request.
168    MemReqPtr memReq;
169
170    // Pointer to the sampler that is telling us to switchover.
171    // Used to signal the completion of the pipe drain and schedule
172    // the next switchover
173    Sampler *sampler;
174
175    StaticInstPtr<TheISA> curStaticInst;
176
177    class CacheCompletionEvent : public Event
178    {
179      private:
180        SimpleCPU *cpu;
181
182      public:
183        CacheCompletionEvent(SimpleCPU *_cpu);
184
185        virtual void process();
186        virtual const char *description();
187    };
188
189    CacheCompletionEvent cacheCompletionEvent;
190
191    Status status() const { return _status; }
192
193    virtual void activateContext(int thread_num, int delay);
194    virtual void suspendContext(int thread_num);
195    virtual void deallocateContext(int thread_num);
196    virtual void haltContext(int thread_num);
197
198    // statistics
199    virtual void regStats();
200    virtual void resetStats();
201
202    // number of simulated instructions
203    Counter numInst;
204    Counter startNumInst;
205    Stats::Scalar<> numInsts;
206
207    virtual Counter totalInstructions() const
208    {
209        return numInst - startNumInst;
210    }
211
212    // number of simulated memory references
213    Stats::Scalar<> numMemRefs;
214
215    // number of simulated loads
216    Counter numLoad;
217    Counter startNumLoad;
218
219    // number of idle cycles
220    Stats::Average<> notIdleFraction;
221    Stats::Formula idleFraction;
222
223    // number of cycles stalled for I-cache misses
224    Stats::Scalar<> icacheStallCycles;
225    Counter lastIcacheStall;
226
227    // number of cycles stalled for D-cache misses
228    Stats::Scalar<> dcacheStallCycles;
229    Counter lastDcacheStall;
230
231    void processCacheCompletion();
232
233    virtual void serialize(std::ostream &os);
234    virtual void unserialize(Checkpoint *cp, const std::string &section);
235
236    template <class T>
237    Fault read(Addr addr, T &data, unsigned flags);
238
239    template <class T>
240    Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
241
242    // These functions are only used in CPU models that split
243    // effective address computation from the actual memory access.
244    void setEA(Addr EA) { panic("SimpleCPU::setEA() not implemented\n"); }
245    Addr getEA() 	{ panic("SimpleCPU::getEA() not implemented\n"); }
246
247    void prefetch(Addr addr, unsigned flags)
248    {
249        // need to do this...
250    }
251
252    void writeHint(Addr addr, int size, unsigned flags)
253    {
254        // need to do this...
255    }
256
257    Fault copySrcTranslate(Addr src);
258
259    Fault copy(Addr dest);
260
261    // The register accessor methods provide the index of the
262    // instruction's operand (e.g., 0 or 1), not the architectural
263    // register index, to simplify the implementation of register
264    // renaming.  We find the architectural register index by indexing
265    // into the instruction's own operand index table.  Note that a
266    // raw pointer to the StaticInst is provided instead of a
267    // ref-counted StaticInstPtr to redice overhead.  This is fine as
268    // long as these methods don't copy the pointer into any long-term
269    // storage (which is pretty hard to imagine they would have reason
270    // to do).
271
272    uint64_t readIntReg(const StaticInst<TheISA> *si, int idx)
273    {
274        return xc->readIntReg(si->srcRegIdx(idx));
275    }
276
277    float readFloatRegSingle(const StaticInst<TheISA> *si, int idx)
278    {
279        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
280        return xc->readFloatRegSingle(reg_idx);
281    }
282
283    double readFloatRegDouble(const StaticInst<TheISA> *si, int idx)
284    {
285        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
286        return xc->readFloatRegDouble(reg_idx);
287    }
288
289    uint64_t readFloatRegInt(const StaticInst<TheISA> *si, int idx)
290    {
291        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
292        return xc->readFloatRegInt(reg_idx);
293    }
294
295    void setIntReg(const StaticInst<TheISA> *si, int idx, uint64_t val)
296    {
297        xc->setIntReg(si->destRegIdx(idx), val);
298    }
299
300    void setFloatRegSingle(const StaticInst<TheISA> *si, int idx, float val)
301    {
302        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
303        xc->setFloatRegSingle(reg_idx, val);
304    }
305
306    void setFloatRegDouble(const StaticInst<TheISA> *si, int idx, double val)
307    {
308        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
309        xc->setFloatRegDouble(reg_idx, val);
310    }
311
312    void setFloatRegInt(const StaticInst<TheISA> *si, int idx, uint64_t val)
313    {
314        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
315        xc->setFloatRegInt(reg_idx, val);
316    }
317
318    uint64_t readPC() { return xc->readPC(); }
319    void setNextPC(uint64_t val) { xc->setNextPC(val); }
320
321    uint64_t readUniq() { return xc->readUniq(); }
322    void setUniq(uint64_t val) { xc->setUniq(val); }
323
324    uint64_t readFpcr() { return xc->readFpcr(); }
325    void setFpcr(uint64_t val) { xc->setFpcr(val); }
326
327#if FULL_SYSTEM
328    uint64_t readIpr(int idx, Fault &fault) { return xc->readIpr(idx, fault); }
329    Fault setIpr(int idx, uint64_t val) { return xc->setIpr(idx, val); }
330    Fault hwrei() { return xc->hwrei(); }
331    int readIntrFlag() { return xc->readIntrFlag(); }
332    void setIntrFlag(int val) { xc->setIntrFlag(val); }
333    bool inPalMode() { return xc->inPalMode(); }
334    void ev5_trap(Fault fault) { xc->ev5_trap(fault); }
335    bool simPalCheck(int palFunc) { return xc->simPalCheck(palFunc); }
336#else
337    void syscall() { xc->syscall(); }
338#endif
339
340    bool misspeculating() { return xc->misspeculating(); }
341    ExecContext *xcBase() { return xc; }
342};
343
344#endif // __CPU_SIMPLE_CPU_SIMPLE_CPU_HH__
345