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