simple_thread.hh revision 10934:5af8f40d8f2c
1/*
2 * Copyright (c) 2011-2012 ARM Limited
3 * Copyright (c) 2013 Advanced Micro Devices, Inc.
4 * All rights reserved
5 *
6 * The license below extends only to copyright in the software and shall
7 * not be construed as granting a license to any other intellectual
8 * property including but not limited to intellectual property relating
9 * to a hardware implementation of the functionality of the software
10 * licensed hereunder.  You may use the software subject to the license
11 * terms below provided that you ensure that this notice is replicated
12 * unmodified and in its entirety in all distributions of the software,
13 * modified or unmodified, in source code or in binary form.
14 *
15 * Copyright (c) 2001-2006 The Regents of The University of Michigan
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Authors: Steve Reinhardt
42 *          Nathan Binkert
43 */
44
45#ifndef __CPU_SIMPLE_THREAD_HH__
46#define __CPU_SIMPLE_THREAD_HH__
47
48#include "arch/decoder.hh"
49#include "arch/isa.hh"
50#include "arch/isa_traits.hh"
51#include "arch/registers.hh"
52#include "arch/tlb.hh"
53#include "arch/types.hh"
54#include "base/types.hh"
55#include "config/the_isa.hh"
56#include "cpu/thread_context.hh"
57#include "cpu/thread_state.hh"
58#include "debug/CCRegs.hh"
59#include "debug/FloatRegs.hh"
60#include "debug/IntRegs.hh"
61#include "debug/VectorRegs.hh"
62#include "mem/page_table.hh"
63#include "mem/request.hh"
64#include "sim/byteswap.hh"
65#include "sim/eventq.hh"
66#include "sim/process.hh"
67#include "sim/serialize.hh"
68#include "sim/system.hh"
69
70class BaseCPU;
71class CheckerCPU;
72
73class FunctionProfile;
74class ProfileNode;
75
76namespace TheISA {
77    namespace Kernel {
78        class Statistics;
79    }
80}
81
82/**
83 * The SimpleThread object provides a combination of the ThreadState
84 * object and the ThreadContext interface. It implements the
85 * ThreadContext interface so that a ProxyThreadContext class can be
86 * made using SimpleThread as the template parameter (see
87 * thread_context.hh). It adds to the ThreadState object by adding all
88 * the objects needed for simple functional execution, including a
89 * simple architectural register file, and pointers to the ITB and DTB
90 * in full system mode. For CPU models that do not need more advanced
91 * ways to hold state (i.e. a separate physical register file, or
92 * separate fetch and commit PC's), this SimpleThread class provides
93 * all the necessary state for full architecture-level functional
94 * simulation.  See the AtomicSimpleCPU or TimingSimpleCPU for
95 * examples.
96 */
97
98class SimpleThread : public ThreadState
99{
100  protected:
101    typedef TheISA::MachInst MachInst;
102    typedef TheISA::MiscReg MiscReg;
103    typedef TheISA::FloatReg FloatReg;
104    typedef TheISA::FloatRegBits FloatRegBits;
105    typedef TheISA::CCReg CCReg;
106    typedef TheISA::VectorReg VectorReg;
107
108  public:
109    typedef ThreadContext::Status Status;
110
111  protected:
112    union {
113        FloatReg f[TheISA::NumFloatRegs];
114        FloatRegBits i[TheISA::NumFloatRegs];
115    } floatRegs;
116    TheISA::IntReg intRegs[TheISA::NumIntRegs];
117
118#ifdef ISA_HAS_CC_REGS
119    TheISA::CCReg ccRegs[TheISA::NumCCRegs];
120#endif
121
122#ifdef ISA_HAS_VECTOR_REGS
123    TheISA::VectorReg vectorRegs[TheISA::NumVectorRegs];
124#endif
125
126    TheISA::ISA *const isa;    // one "instance" of the current ISA.
127
128    TheISA::PCState _pcState;
129
130    /** Did this instruction execute or is it predicated false */
131    bool predicate;
132
133  public:
134    std::string name() const
135    {
136        return csprintf("%s.[tid:%i]", baseCpu->name(), tc->threadId());
137    }
138
139    ProxyThreadContext<SimpleThread> *tc;
140
141    System *system;
142
143    TheISA::TLB *itb;
144    TheISA::TLB *dtb;
145
146    TheISA::Decoder decoder;
147
148    // constructor: initialize SimpleThread from given process structure
149    // FS
150    SimpleThread(BaseCPU *_cpu, int _thread_num, System *_system,
151                 TheISA::TLB *_itb, TheISA::TLB *_dtb, TheISA::ISA *_isa,
152                 bool use_kernel_stats = true);
153    // SE
154    SimpleThread(BaseCPU *_cpu, int _thread_num, System *_system,
155                 Process *_process, TheISA::TLB *_itb, TheISA::TLB *_dtb,
156                 TheISA::ISA *_isa);
157
158    virtual ~SimpleThread();
159
160    virtual void takeOverFrom(ThreadContext *oldContext);
161
162    void regStats(const std::string &name);
163
164    void copyState(ThreadContext *oldContext);
165
166    void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE;
167    void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE;
168    void startup();
169
170    /***************************************************************
171     *  SimpleThread functions to provide CPU with access to various
172     *  state.
173     **************************************************************/
174
175    /** Returns the pointer to this SimpleThread's ThreadContext. Used
176     *  when a ThreadContext must be passed to objects outside of the
177     *  CPU.
178     */
179    ThreadContext *getTC() { return tc; }
180
181    void demapPage(Addr vaddr, uint64_t asn)
182    {
183        itb->demapPage(vaddr, asn);
184        dtb->demapPage(vaddr, asn);
185    }
186
187    void demapInstPage(Addr vaddr, uint64_t asn)
188    {
189        itb->demapPage(vaddr, asn);
190    }
191
192    void demapDataPage(Addr vaddr, uint64_t asn)
193    {
194        dtb->demapPage(vaddr, asn);
195    }
196
197    void dumpFuncProfile();
198
199    Fault hwrei();
200
201    bool simPalCheck(int palFunc);
202
203    /*******************************************
204     * ThreadContext interface functions.
205     ******************************************/
206
207    BaseCPU *getCpuPtr() { return baseCpu; }
208
209    TheISA::TLB *getITBPtr() { return itb; }
210
211    TheISA::TLB *getDTBPtr() { return dtb; }
212
213    CheckerCPU *getCheckerCpuPtr() { return NULL; }
214
215    TheISA::Decoder *getDecoderPtr() { return &decoder; }
216
217    System *getSystemPtr() { return system; }
218
219    Status status() const { return _status; }
220
221    void setStatus(Status newStatus) { _status = newStatus; }
222
223    /// Set the status to Active.
224    void activate();
225
226    /// Set the status to Suspended.
227    void suspend();
228
229    /// Set the status to Halted.
230    void halt();
231
232    void copyArchRegs(ThreadContext *tc);
233
234    void clearArchRegs()
235    {
236        _pcState = 0;
237        memset(intRegs, 0, sizeof(intRegs));
238        memset(floatRegs.i, 0, sizeof(floatRegs.i));
239#ifdef ISA_HAS_CC_REGS
240        memset(ccRegs, 0, sizeof(ccRegs));
241#endif
242        isa->clear();
243    }
244
245    //
246    // New accessors for new decoder.
247    //
248    uint64_t readIntReg(int reg_idx)
249    {
250        int flatIndex = isa->flattenIntIndex(reg_idx);
251        assert(flatIndex < TheISA::NumIntRegs);
252        uint64_t regVal(readIntRegFlat(flatIndex));
253        DPRINTF(IntRegs, "Reading int reg %d (%d) as %#x.\n",
254                reg_idx, flatIndex, regVal);
255        return regVal;
256    }
257
258    FloatReg readFloatReg(int reg_idx)
259    {
260        int flatIndex = isa->flattenFloatIndex(reg_idx);
261        assert(flatIndex < TheISA::NumFloatRegs);
262        FloatReg regVal(readFloatRegFlat(flatIndex));
263        DPRINTF(FloatRegs, "Reading float reg %d (%d) as %f, %#x.\n",
264                reg_idx, flatIndex, regVal, floatRegs.i[flatIndex]);
265        return regVal;
266    }
267
268    FloatRegBits readFloatRegBits(int reg_idx)
269    {
270        int flatIndex = isa->flattenFloatIndex(reg_idx);
271        assert(flatIndex < TheISA::NumFloatRegs);
272        FloatRegBits regVal(readFloatRegBitsFlat(flatIndex));
273        DPRINTF(FloatRegs, "Reading float reg %d (%d) bits as %#x, %f.\n",
274                reg_idx, flatIndex, regVal, floatRegs.f[flatIndex]);
275        return regVal;
276    }
277
278    CCReg readCCReg(int reg_idx)
279    {
280#ifdef ISA_HAS_CC_REGS
281        int flatIndex = isa->flattenCCIndex(reg_idx);
282        assert(0 <= flatIndex);
283        assert(flatIndex < TheISA::NumCCRegs);
284        uint64_t regVal(readCCRegFlat(flatIndex));
285        DPRINTF(CCRegs, "Reading CC reg %d (%d) as %#x.\n",
286                reg_idx, flatIndex, regVal);
287        return regVal;
288#else
289        panic("Tried to read a CC register.");
290        return 0;
291#endif
292    }
293
294    const VectorReg &readVectorReg(int reg_idx)
295    {
296        int flatIndex = isa->flattenVectorIndex(reg_idx);
297        assert(0 <= flatIndex);
298        assert(flatIndex < TheISA::NumVectorRegs);
299        DPRINTF(VectorRegs, "Reading vector reg %d (%d).\n",
300                reg_idx, flatIndex);
301        return readVectorRegFlat(flatIndex);
302    }
303
304    void setIntReg(int reg_idx, uint64_t val)
305    {
306        int flatIndex = isa->flattenIntIndex(reg_idx);
307        assert(flatIndex < TheISA::NumIntRegs);
308        DPRINTF(IntRegs, "Setting int reg %d (%d) to %#x.\n",
309                reg_idx, flatIndex, val);
310        setIntRegFlat(flatIndex, val);
311    }
312
313    void setFloatReg(int reg_idx, FloatReg val)
314    {
315        int flatIndex = isa->flattenFloatIndex(reg_idx);
316        assert(flatIndex < TheISA::NumFloatRegs);
317        setFloatRegFlat(flatIndex, val);
318        DPRINTF(FloatRegs, "Setting float reg %d (%d) to %f, %#x.\n",
319                reg_idx, flatIndex, val, floatRegs.i[flatIndex]);
320    }
321
322    void setFloatRegBits(int reg_idx, FloatRegBits val)
323    {
324        int flatIndex = isa->flattenFloatIndex(reg_idx);
325        assert(flatIndex < TheISA::NumFloatRegs);
326        // XXX: Fix array out of bounds compiler error for gem5.fast
327        // when checkercpu enabled
328        if (flatIndex < TheISA::NumFloatRegs)
329            setFloatRegBitsFlat(flatIndex, val);
330        DPRINTF(FloatRegs, "Setting float reg %d (%d) bits to %#x, %#f.\n",
331                reg_idx, flatIndex, val, floatRegs.f[flatIndex]);
332    }
333
334    void setCCReg(int reg_idx, CCReg val)
335    {
336#ifdef ISA_HAS_CC_REGS
337        int flatIndex = isa->flattenCCIndex(reg_idx);
338        assert(flatIndex < TheISA::NumCCRegs);
339        DPRINTF(CCRegs, "Setting CC reg %d (%d) to %#x.\n",
340                reg_idx, flatIndex, val);
341        setCCRegFlat(flatIndex, val);
342#else
343        panic("Tried to set a CC register.");
344#endif
345    }
346
347    void setVectorReg(int reg_idx, const VectorReg &val)
348    {
349#ifdef ISA_HAS_VECTOR_REGS
350        int flatIndex = isa->flattenVectorIndex(reg_idx);
351        assert(flatIndex < TheISA::NumVectorRegs);
352        DPRINTF(VectorRegs, "Setting vector reg %d (%d).\n",
353                reg_idx, flatIndex);
354        setVectorRegFlat(flatIndex, val);
355#else
356        panic("Tried to set a vector register.");
357#endif
358    }
359
360    TheISA::PCState
361    pcState()
362    {
363        return _pcState;
364    }
365
366    void
367    pcState(const TheISA::PCState &val)
368    {
369        _pcState = val;
370    }
371
372    void
373    pcStateNoRecord(const TheISA::PCState &val)
374    {
375        _pcState = val;
376    }
377
378    Addr
379    instAddr()
380    {
381        return _pcState.instAddr();
382    }
383
384    Addr
385    nextInstAddr()
386    {
387        return _pcState.nextInstAddr();
388    }
389
390    MicroPC
391    microPC()
392    {
393        return _pcState.microPC();
394    }
395
396    bool readPredicate()
397    {
398        return predicate;
399    }
400
401    void setPredicate(bool val)
402    {
403        predicate = val;
404    }
405
406    MiscReg
407    readMiscRegNoEffect(int misc_reg, ThreadID tid = 0) const
408    {
409        return isa->readMiscRegNoEffect(misc_reg);
410    }
411
412    MiscReg
413    readMiscReg(int misc_reg, ThreadID tid = 0)
414    {
415        return isa->readMiscReg(misc_reg, tc);
416    }
417
418    void
419    setMiscRegNoEffect(int misc_reg, const MiscReg &val, ThreadID tid = 0)
420    {
421        return isa->setMiscRegNoEffect(misc_reg, val);
422    }
423
424    void
425    setMiscReg(int misc_reg, const MiscReg &val, ThreadID tid = 0)
426    {
427        return isa->setMiscReg(misc_reg, val, tc);
428    }
429
430    int
431    flattenIntIndex(int reg)
432    {
433        return isa->flattenIntIndex(reg);
434    }
435
436    int
437    flattenFloatIndex(int reg)
438    {
439        return isa->flattenFloatIndex(reg);
440    }
441
442    int
443    flattenCCIndex(int reg)
444    {
445        return isa->flattenCCIndex(reg);
446    }
447
448    int
449    flattenVectorIndex(int reg)
450    {
451        return isa->flattenVectorIndex(reg);
452    }
453
454    int
455    flattenMiscIndex(int reg)
456    {
457        return isa->flattenMiscIndex(reg);
458    }
459
460    unsigned readStCondFailures() { return storeCondFailures; }
461
462    void setStCondFailures(unsigned sc_failures)
463    { storeCondFailures = sc_failures; }
464
465    void syscall(int64_t callnum)
466    {
467        process->syscall(callnum, tc);
468    }
469
470    uint64_t readIntRegFlat(int idx) { return intRegs[idx]; }
471    void setIntRegFlat(int idx, uint64_t val) { intRegs[idx] = val; }
472
473    FloatReg readFloatRegFlat(int idx) { return floatRegs.f[idx]; }
474    void setFloatRegFlat(int idx, FloatReg val) { floatRegs.f[idx] = val; }
475
476    FloatRegBits readFloatRegBitsFlat(int idx) { return floatRegs.i[idx]; }
477    void setFloatRegBitsFlat(int idx, FloatRegBits val) {
478        floatRegs.i[idx] = val;
479    }
480
481#ifdef ISA_HAS_CC_REGS
482    CCReg readCCRegFlat(int idx) { return ccRegs[idx]; }
483    void setCCRegFlat(int idx, CCReg val) { ccRegs[idx] = val; }
484#else
485    CCReg readCCRegFlat(int idx)
486    { panic("readCCRegFlat w/no CC regs!\n"); }
487
488    void setCCRegFlat(int idx, CCReg val)
489    { panic("setCCRegFlat w/no CC regs!\n"); }
490#endif
491
492#ifdef ISA_HAS_VECTOR_REGS
493    const VectorReg &readVectorRegFlat(int idx) { return vectorRegs[idx]; }
494    void setVectorRegFlat(int idx, const VectorReg &val)
495    { vectorRegs[idx] = val; }
496#else
497    const VectorReg &readVectorRegFlat(int idx)
498    { panic("readVectorRegFlat w/no Vector regs!\n"); }
499
500    void setVectorRegFlat(int idx, const VectorReg &val)
501    { panic("setVectorRegFlat w/no Vector regs!\n"); }
502#endif
503};
504
505
506#endif // __CPU_CPU_EXEC_CONTEXT_HH__
507