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