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