base.hh revision 5712:199d31b47f7b
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 * Authors: Steve Reinhardt
29 *          Dave Greene
30 *          Nathan Binkert
31 */
32
33#ifndef __CPU_SIMPLE_BASE_HH__
34#define __CPU_SIMPLE_BASE_HH__
35
36#include "arch/predecoder.hh"
37#include "base/statistics.hh"
38#include "config/full_system.hh"
39#include "cpu/base.hh"
40#include "cpu/simple_thread.hh"
41#include "cpu/pc_event.hh"
42#include "cpu/static_inst.hh"
43#include "mem/packet.hh"
44#include "mem/port.hh"
45#include "mem/request.hh"
46#include "sim/eventq.hh"
47#include "sim/system.hh"
48
49// forward declarations
50#if FULL_SYSTEM
51class Processor;
52namespace TheISA
53{
54    class ITB;
55    class DTB;
56}
57class MemObject;
58
59#else
60
61class Process;
62
63#endif // FULL_SYSTEM
64
65class RemoteGDB;
66class GDBListener;
67
68namespace TheISA
69{
70    class Predecoder;
71}
72class ThreadContext;
73class Checkpoint;
74
75namespace Trace {
76    class InstRecord;
77}
78
79class BaseSimpleCPUParams;
80
81
82class BaseSimpleCPU : public BaseCPU
83{
84  protected:
85    typedef TheISA::MiscReg MiscReg;
86    typedef TheISA::FloatReg FloatReg;
87    typedef TheISA::FloatRegBits FloatRegBits;
88
89  protected:
90    Trace::InstRecord *traceData;
91
92    inline void checkPcEventQueue() {
93        Addr oldpc;
94        do {
95            oldpc = thread->readPC();
96            system->pcEventQueue.service(tc);
97        } while (oldpc != thread->readPC());
98    }
99
100  public:
101    void postInterrupt(int int_num, int index);
102
103    void zero_fill_64(Addr addr) {
104      static int warned = 0;
105      if (!warned) {
106        warn ("WH64 is not implemented");
107        warned = 1;
108      }
109    };
110
111  public:
112    BaseSimpleCPU(BaseSimpleCPUParams *params);
113    virtual ~BaseSimpleCPU();
114
115  public:
116    /** SimpleThread object, provides all the architectural state. */
117    SimpleThread *thread;
118
119    /** ThreadContext object, provides an interface for external
120     * objects to modify this thread's state.
121     */
122    ThreadContext *tc;
123  protected:
124
125    enum Status {
126        Idle,
127        Running,
128        IcacheRetry,
129        IcacheWaitResponse,
130        IcacheWaitSwitch,
131        DcacheRetry,
132        DcacheWaitResponse,
133        DcacheWaitSwitch,
134        SwitchedOut
135    };
136
137    Status _status;
138
139  public:
140
141#if FULL_SYSTEM
142    Addr dbg_vtophys(Addr addr);
143
144    bool interval_stats;
145#endif
146
147    // current instruction
148    TheISA::MachInst inst;
149
150    // The predecoder
151    TheISA::Predecoder predecoder;
152
153    StaticInstPtr curStaticInst;
154    StaticInstPtr curMacroStaticInst;
155
156    //This is the offset from the current pc that fetch should be performed at
157    Addr fetchOffset;
158    //This flag says to stay at the current pc. This is useful for
159    //instructions which go beyond MachInst boundaries.
160    bool stayAtPC;
161
162    void checkForInterrupts();
163    Fault setupFetchRequest(Request *req);
164    void preExecute();
165    void postExecute();
166    void advancePC(Fault fault);
167
168    virtual void deallocateContext(int thread_num);
169    virtual void haltContext(int thread_num);
170
171    // statistics
172    virtual void regStats();
173    virtual void resetStats();
174
175    // number of simulated instructions
176    Counter numInst;
177    Counter startNumInst;
178    Stats::Scalar<> numInsts;
179
180    void countInst()
181    {
182        numInst++;
183        numInsts++;
184
185        thread->funcExeInst++;
186    }
187
188    virtual Counter totalInstructions() const
189    {
190        return numInst - startNumInst;
191    }
192
193    // Mask to align PCs to MachInst sized boundaries
194    static const Addr PCMask = ~((Addr)sizeof(TheISA::MachInst) - 1);
195
196    // number of simulated memory references
197    Stats::Scalar<> numMemRefs;
198
199    // number of simulated loads
200    Counter numLoad;
201    Counter startNumLoad;
202
203    // number of idle cycles
204    Stats::Average<> notIdleFraction;
205    Stats::Formula idleFraction;
206
207    // number of cycles stalled for I-cache responses
208    Stats::Scalar<> icacheStallCycles;
209    Counter lastIcacheStall;
210
211    // number of cycles stalled for I-cache retries
212    Stats::Scalar<> icacheRetryCycles;
213    Counter lastIcacheRetry;
214
215    // number of cycles stalled for D-cache responses
216    Stats::Scalar<> dcacheStallCycles;
217    Counter lastDcacheStall;
218
219    // number of cycles stalled for D-cache retries
220    Stats::Scalar<> dcacheRetryCycles;
221    Counter lastDcacheRetry;
222
223    virtual void serialize(std::ostream &os);
224    virtual void unserialize(Checkpoint *cp, const std::string &section);
225
226    // These functions are only used in CPU models that split
227    // effective address computation from the actual memory access.
228    void setEA(Addr EA) { panic("BaseSimpleCPU::setEA() not implemented\n"); }
229    Addr getEA()        { panic("BaseSimpleCPU::getEA() not implemented\n");
230        M5_DUMMY_RETURN}
231
232    void prefetch(Addr addr, unsigned flags)
233    {
234        // need to do this...
235    }
236
237    void writeHint(Addr addr, int size, unsigned flags)
238    {
239        // need to do this...
240    }
241
242
243    Fault copySrcTranslate(Addr src);
244
245    Fault copy(Addr dest);
246
247    // The register accessor methods provide the index of the
248    // instruction's operand (e.g., 0 or 1), not the architectural
249    // register index, to simplify the implementation of register
250    // renaming.  We find the architectural register index by indexing
251    // into the instruction's own operand index table.  Note that a
252    // raw pointer to the StaticInst is provided instead of a
253    // ref-counted StaticInstPtr to redice overhead.  This is fine as
254    // long as these methods don't copy the pointer into any long-term
255    // storage (which is pretty hard to imagine they would have reason
256    // to do).
257
258    uint64_t readIntRegOperand(const StaticInst *si, int idx)
259    {
260        return thread->readIntReg(si->srcRegIdx(idx));
261    }
262
263    FloatReg readFloatRegOperand(const StaticInst *si, int idx, int width)
264    {
265        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
266        return thread->readFloatReg(reg_idx, width);
267    }
268
269    FloatReg readFloatRegOperand(const StaticInst *si, int idx)
270    {
271        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
272        return thread->readFloatReg(reg_idx);
273    }
274
275    FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx,
276                                         int width)
277    {
278        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
279        return thread->readFloatRegBits(reg_idx, width);
280    }
281
282    FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx)
283    {
284        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
285        return thread->readFloatRegBits(reg_idx);
286    }
287
288    void setIntRegOperand(const StaticInst *si, int idx, uint64_t val)
289    {
290        thread->setIntReg(si->destRegIdx(idx), val);
291    }
292
293    void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val,
294                            int width)
295    {
296        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
297        thread->setFloatReg(reg_idx, val, width);
298    }
299
300    void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val)
301    {
302        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
303        thread->setFloatReg(reg_idx, val);
304    }
305
306    void setFloatRegOperandBits(const StaticInst *si, int idx,
307                                FloatRegBits val, int width)
308    {
309        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
310        thread->setFloatRegBits(reg_idx, val, width);
311    }
312
313    void setFloatRegOperandBits(const StaticInst *si, int idx,
314                                FloatRegBits val)
315    {
316        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
317        thread->setFloatRegBits(reg_idx, val);
318    }
319
320    uint64_t readPC() { return thread->readPC(); }
321    uint64_t readMicroPC() { return thread->readMicroPC(); }
322    uint64_t readNextPC() { return thread->readNextPC(); }
323    uint64_t readNextMicroPC() { return thread->readNextMicroPC(); }
324    uint64_t readNextNPC() { return thread->readNextNPC(); }
325
326    void setPC(uint64_t val) { thread->setPC(val); }
327    void setMicroPC(uint64_t val) { thread->setMicroPC(val); }
328    void setNextPC(uint64_t val) { thread->setNextPC(val); }
329    void setNextMicroPC(uint64_t val) { thread->setNextMicroPC(val); }
330    void setNextNPC(uint64_t val) { thread->setNextNPC(val); }
331
332    MiscReg readMiscRegNoEffect(int misc_reg)
333    {
334        return thread->readMiscRegNoEffect(misc_reg);
335    }
336
337    MiscReg readMiscReg(int misc_reg)
338    {
339        return thread->readMiscReg(misc_reg);
340    }
341
342    void setMiscRegNoEffect(int misc_reg, const MiscReg &val)
343    {
344        return thread->setMiscRegNoEffect(misc_reg, val);
345    }
346
347    void setMiscReg(int misc_reg, const MiscReg &val)
348    {
349        return thread->setMiscReg(misc_reg, val);
350    }
351
352    MiscReg readMiscRegOperandNoEffect(const StaticInst *si, int idx)
353    {
354        int reg_idx = si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag;
355        return thread->readMiscRegNoEffect(reg_idx);
356    }
357
358    MiscReg readMiscRegOperand(const StaticInst *si, int idx)
359    {
360        int reg_idx = si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag;
361        return thread->readMiscReg(reg_idx);
362    }
363
364    void setMiscRegOperandNoEffect(const StaticInst *si, int idx, const MiscReg &val)
365    {
366        int reg_idx = si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag;
367        return thread->setMiscRegNoEffect(reg_idx, val);
368    }
369
370    void setMiscRegOperand(
371            const StaticInst *si, int idx, const MiscReg &val)
372    {
373        int reg_idx = si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag;
374        return thread->setMiscReg(reg_idx, val);
375    }
376
377    void demapPage(Addr vaddr, uint64_t asn)
378    {
379        thread->demapPage(vaddr, asn);
380    }
381
382    void demapInstPage(Addr vaddr, uint64_t asn)
383    {
384        thread->demapInstPage(vaddr, asn);
385    }
386
387    void demapDataPage(Addr vaddr, uint64_t asn)
388    {
389        thread->demapDataPage(vaddr, asn);
390    }
391
392    unsigned readStCondFailures() {
393        return thread->readStCondFailures();
394    }
395
396    void setStCondFailures(unsigned sc_failures) {
397        thread->setStCondFailures(sc_failures);
398    }
399
400     MiscReg readRegOtherThread(int regIdx, int tid = -1)
401     {
402        panic("Simple CPU models do not support multithreaded "
403              "register access.\n");
404     }
405
406     void setRegOtherThread(int regIdx, const MiscReg &val, int tid = -1)
407     {
408        panic("Simple CPU models do not support multithreaded "
409              "register access.\n");
410     }
411
412    //Fault CacheOp(uint8_t Op, Addr EA);
413
414#if FULL_SYSTEM
415    Fault hwrei() { return thread->hwrei(); }
416    void ev5_trap(Fault fault) { fault->invoke(tc); }
417    bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); }
418#else
419    void syscall(int64_t callnum) { thread->syscall(callnum); }
420#endif
421
422    bool misspeculating() { return thread->misspeculating(); }
423    ThreadContext *tcBase() { return tc; }
424};
425
426#endif // __CPU_SIMPLE_BASE_HH__
427