base.hh revision 8834
1/*
2 * Copyright (c) 2011 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2002-2005 The Regents of The University of Michigan
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Steve Reinhardt
41 *          Dave Greene
42 *          Nathan Binkert
43 */
44
45#ifndef __CPU_SIMPLE_BASE_HH__
46#define __CPU_SIMPLE_BASE_HH__
47
48#include "arch/predecoder.hh"
49#include "base/statistics.hh"
50#include "config/the_isa.hh"
51#include "config/use_checker.hh"
52#include "cpu/base.hh"
53#include "cpu/decode.hh"
54#include "cpu/pc_event.hh"
55#include "cpu/simple_thread.hh"
56#include "cpu/static_inst.hh"
57#include "mem/packet.hh"
58#include "mem/port.hh"
59#include "mem/request.hh"
60#include "sim/eventq.hh"
61#include "sim/full_system.hh"
62#include "sim/system.hh"
63
64#if USE_CHECKER
65#include "cpu/checker/cpu.hh"
66#endif
67
68// forward declarations
69class Checkpoint;
70class MemObject;
71class Process;
72class Processor;
73class ThreadContext;
74
75namespace TheISA
76{
77    class DTB;
78    class ITB;
79    class Predecoder;
80}
81
82namespace Trace {
83    class InstRecord;
84}
85
86struct BaseSimpleCPUParams;
87
88
89class BaseSimpleCPU : public BaseCPU
90{
91  protected:
92    typedef TheISA::MiscReg MiscReg;
93    typedef TheISA::FloatReg FloatReg;
94    typedef TheISA::FloatRegBits FloatRegBits;
95
96  protected:
97    Trace::InstRecord *traceData;
98
99    inline void checkPcEventQueue() {
100        Addr oldpc, pc = thread->instAddr();
101        do {
102            oldpc = pc;
103            system->pcEventQueue.service(tc);
104            pc = thread->instAddr();
105        } while (oldpc != pc);
106    }
107
108  public:
109    void wakeup();
110
111    void zero_fill_64(Addr addr) {
112      static int warned = 0;
113      if (!warned) {
114        warn ("WH64 is not implemented");
115        warned = 1;
116      }
117    };
118
119  public:
120    BaseSimpleCPU(BaseSimpleCPUParams *params);
121    virtual ~BaseSimpleCPU();
122
123  public:
124    /** SimpleThread object, provides all the architectural state. */
125    SimpleThread *thread;
126
127    /** ThreadContext object, provides an interface for external
128     * objects to modify this thread's state.
129     */
130    ThreadContext *tc;
131
132#if USE_CHECKER
133    CheckerCPU *checker;
134#endif
135  protected:
136
137    enum Status {
138        Idle,
139        Running,
140        Faulting,
141        ITBWaitResponse,
142        IcacheRetry,
143        IcacheWaitResponse,
144        IcacheWaitSwitch,
145        DTBWaitResponse,
146        DcacheRetry,
147        DcacheWaitResponse,
148        DcacheWaitSwitch,
149        SwitchedOut
150    };
151
152    Status _status;
153
154  public:
155
156    Addr dbg_vtophys(Addr addr);
157
158    bool interval_stats;
159
160    // current instruction
161    TheISA::MachInst inst;
162
163    // The predecoder
164    TheISA::Predecoder predecoder;
165
166    StaticInstPtr curStaticInst;
167    StaticInstPtr curMacroStaticInst;
168
169    //This is the offset from the current pc that fetch should be performed at
170    Addr fetchOffset;
171    //This flag says to stay at the current pc. This is useful for
172    //instructions which go beyond MachInst boundaries.
173    bool stayAtPC;
174
175    void checkForInterrupts();
176    void setupFetchRequest(Request *req);
177    void preExecute();
178    void postExecute();
179    void advancePC(Fault fault);
180
181    virtual void deallocateContext(ThreadID thread_num);
182    virtual void haltContext(ThreadID thread_num);
183
184    // statistics
185    virtual void regStats();
186    virtual void resetStats();
187
188    // number of simulated instructions
189    Counter numInst;
190    Counter startNumInst;
191    Stats::Scalar numInsts;
192    Counter numOp;
193    Counter startNumOp;
194    Stats::Scalar numOps;
195
196    void countInst()
197    {
198        if (!curStaticInst->isMicroop() || curStaticInst->isLastMicroop()) {
199            numInst++;
200            numInsts++;
201        }
202        numOp++;
203        numOps++;
204
205        system->totalNumInsts++;
206        thread->funcExeInst++;
207    }
208
209    virtual Counter totalInsts() const
210    {
211        return numInst - startNumInst;
212    }
213
214    virtual Counter totalOps() const
215    {
216        return numOp - startNumOp;
217    }
218
219    //number of integer alu accesses
220    Stats::Scalar numIntAluAccesses;
221
222    //number of float alu accesses
223    Stats::Scalar numFpAluAccesses;
224
225    //number of function calls/returns
226    Stats::Scalar numCallsReturns;
227
228    //conditional control instructions;
229    Stats::Scalar numCondCtrlInsts;
230
231    //number of int instructions
232    Stats::Scalar numIntInsts;
233
234    //number of float instructions
235    Stats::Scalar numFpInsts;
236
237    //number of integer register file accesses
238    Stats::Scalar numIntRegReads;
239    Stats::Scalar numIntRegWrites;
240
241    //number of float register file accesses
242    Stats::Scalar numFpRegReads;
243    Stats::Scalar numFpRegWrites;
244
245    // number of simulated memory references
246    Stats::Scalar numMemRefs;
247    Stats::Scalar numLoadInsts;
248    Stats::Scalar numStoreInsts;
249
250    // number of idle cycles
251    Stats::Formula numIdleCycles;
252
253    // number of busy cycles
254    Stats::Formula numBusyCycles;
255
256    // number of simulated loads
257    Counter numLoad;
258    Counter startNumLoad;
259
260    // number of idle cycles
261    Stats::Average notIdleFraction;
262    Stats::Formula idleFraction;
263
264    // number of cycles stalled for I-cache responses
265    Stats::Scalar icacheStallCycles;
266    Counter lastIcacheStall;
267
268    // number of cycles stalled for I-cache retries
269    Stats::Scalar icacheRetryCycles;
270    Counter lastIcacheRetry;
271
272    // number of cycles stalled for D-cache responses
273    Stats::Scalar dcacheStallCycles;
274    Counter lastDcacheStall;
275
276    // number of cycles stalled for D-cache retries
277    Stats::Scalar dcacheRetryCycles;
278    Counter lastDcacheRetry;
279
280    virtual void serialize(std::ostream &os);
281    virtual void unserialize(Checkpoint *cp, const std::string &section);
282
283    // These functions are only used in CPU models that split
284    // effective address computation from the actual memory access.
285    void setEA(Addr EA) { panic("BaseSimpleCPU::setEA() not implemented\n"); }
286    Addr getEA()        { panic("BaseSimpleCPU::getEA() not implemented\n");
287        M5_DUMMY_RETURN}
288
289    // The register accessor methods provide the index of the
290    // instruction's operand (e.g., 0 or 1), not the architectural
291    // register index, to simplify the implementation of register
292    // renaming.  We find the architectural register index by indexing
293    // into the instruction's own operand index table.  Note that a
294    // raw pointer to the StaticInst is provided instead of a
295    // ref-counted StaticInstPtr to redice overhead.  This is fine as
296    // long as these methods don't copy the pointer into any long-term
297    // storage (which is pretty hard to imagine they would have reason
298    // to do).
299
300    uint64_t readIntRegOperand(const StaticInst *si, int idx)
301    {
302        numIntRegReads++;
303        return thread->readIntReg(si->srcRegIdx(idx));
304    }
305
306    FloatReg readFloatRegOperand(const StaticInst *si, int idx)
307    {
308        numFpRegReads++;
309        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
310        return thread->readFloatReg(reg_idx);
311    }
312
313    FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx)
314    {
315        numFpRegReads++;
316        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
317        return thread->readFloatRegBits(reg_idx);
318    }
319
320    void setIntRegOperand(const StaticInst *si, int idx, uint64_t val)
321    {
322        numIntRegWrites++;
323        thread->setIntReg(si->destRegIdx(idx), val);
324    }
325
326    void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val)
327    {
328        numFpRegWrites++;
329        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
330        thread->setFloatReg(reg_idx, val);
331    }
332
333    void setFloatRegOperandBits(const StaticInst *si, int idx,
334                                FloatRegBits val)
335    {
336        numFpRegWrites++;
337        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
338        thread->setFloatRegBits(reg_idx, val);
339    }
340
341    bool readPredicate() { return thread->readPredicate(); }
342    void setPredicate(bool val)
343    {
344        thread->setPredicate(val);
345        if (traceData) {
346            traceData->setPredicate(val);
347        }
348    }
349    TheISA::PCState pcState() { return thread->pcState(); }
350    void pcState(const TheISA::PCState &val) { thread->pcState(val); }
351    Addr instAddr() { return thread->instAddr(); }
352    Addr nextInstAddr() { return thread->nextInstAddr(); }
353    MicroPC microPC() { return thread->microPC(); }
354
355    MiscReg readMiscRegNoEffect(int misc_reg)
356    {
357        return thread->readMiscRegNoEffect(misc_reg);
358    }
359
360    MiscReg readMiscReg(int misc_reg)
361    {
362        numIntRegReads++;
363        return thread->readMiscReg(misc_reg);
364    }
365
366    void setMiscReg(int misc_reg, const MiscReg &val)
367    {
368        numIntRegWrites++;
369        return thread->setMiscReg(misc_reg, val);
370    }
371
372    MiscReg readMiscRegOperand(const StaticInst *si, int idx)
373    {
374        numIntRegReads++;
375        int reg_idx = si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag;
376        return thread->readMiscReg(reg_idx);
377    }
378
379    void setMiscRegOperand(
380            const StaticInst *si, int idx, const MiscReg &val)
381    {
382        numIntRegWrites++;
383        int reg_idx = si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag;
384        return thread->setMiscReg(reg_idx, val);
385    }
386
387    void demapPage(Addr vaddr, uint64_t asn)
388    {
389        thread->demapPage(vaddr, asn);
390    }
391
392    void demapInstPage(Addr vaddr, uint64_t asn)
393    {
394        thread->demapInstPage(vaddr, asn);
395    }
396
397    void demapDataPage(Addr vaddr, uint64_t asn)
398    {
399        thread->demapDataPage(vaddr, asn);
400    }
401
402    unsigned readStCondFailures() {
403        return thread->readStCondFailures();
404    }
405
406    void setStCondFailures(unsigned sc_failures) {
407        thread->setStCondFailures(sc_failures);
408    }
409
410     MiscReg readRegOtherThread(int regIdx, ThreadID tid = InvalidThreadID)
411     {
412        panic("Simple CPU models do not support multithreaded "
413              "register access.\n");
414     }
415
416     void setRegOtherThread(int regIdx, const MiscReg &val,
417                            ThreadID tid = InvalidThreadID)
418     {
419        panic("Simple CPU models do not support multithreaded "
420              "register access.\n");
421     }
422
423    //Fault CacheOp(uint8_t Op, Addr EA);
424
425    Fault hwrei() { return thread->hwrei(); }
426    bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); }
427
428    void
429    syscall(int64_t callnum)
430    {
431        if (FullSystem)
432            panic("Syscall emulation isn't available in FS mode.\n");
433
434        thread->syscall(callnum);
435    }
436
437    bool misspeculating() { return thread->misspeculating(); }
438    ThreadContext *tcBase() { return tc; }
439};
440
441#endif // __CPU_SIMPLE_BASE_HH__
442