simple_thread.hh revision 13501:ce73744918e7
1/*
2 * Copyright (c) 2011-2012, 2016 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/generic/tlb.hh"
50#include "arch/isa.hh"
51#include "arch/isa_traits.hh"
52#include "arch/registers.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/VecRegs.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    using VecRegContainer = TheISA::VecRegContainer;
107    using VecElem = TheISA::VecElem;
108  public:
109    typedef ThreadContext::Status Status;
110
111  protected:
112    FloatRegBits floatRegs[TheISA::NumFloatRegs];
113    TheISA::IntReg intRegs[TheISA::NumIntRegs];
114    VecRegContainer vecRegs[TheISA::NumVecRegs];
115#ifdef ISA_HAS_CC_REGS
116    TheISA::CCReg ccRegs[TheISA::NumCCRegs];
117#endif
118    TheISA::ISA *const isa;    // one "instance" of the current ISA.
119
120    TheISA::PCState _pcState;
121
122    /** Did this instruction execute or is it predicated false */
123    bool predicate;
124
125  public:
126    std::string name() const
127    {
128        return csprintf("%s.[tid:%i]", baseCpu->name(), tc->threadId());
129    }
130
131    ProxyThreadContext<SimpleThread> *tc;
132
133    System *system;
134
135    BaseTLB *itb;
136    BaseTLB *dtb;
137
138    TheISA::Decoder decoder;
139
140    // constructor: initialize SimpleThread from given process structure
141    // FS
142    SimpleThread(BaseCPU *_cpu, int _thread_num, System *_system,
143                 BaseTLB *_itb, BaseTLB *_dtb, TheISA::ISA *_isa,
144                 bool use_kernel_stats = true);
145    // SE
146    SimpleThread(BaseCPU *_cpu, int _thread_num, System *_system,
147                 Process *_process, BaseTLB *_itb, BaseTLB *_dtb,
148                 TheISA::ISA *_isa);
149
150    virtual ~SimpleThread();
151
152    virtual void takeOverFrom(ThreadContext *oldContext);
153
154    void regStats(const std::string &name);
155
156    void copyState(ThreadContext *oldContext);
157
158    void serialize(CheckpointOut &cp) const override;
159    void unserialize(CheckpointIn &cp) override;
160    void startup();
161
162    /***************************************************************
163     *  SimpleThread functions to provide CPU with access to various
164     *  state.
165     **************************************************************/
166
167    /** Returns the pointer to this SimpleThread's ThreadContext. Used
168     *  when a ThreadContext must be passed to objects outside of the
169     *  CPU.
170     */
171    ThreadContext *getTC() { return tc; }
172
173    void demapPage(Addr vaddr, uint64_t asn)
174    {
175        itb->demapPage(vaddr, asn);
176        dtb->demapPage(vaddr, asn);
177    }
178
179    void demapInstPage(Addr vaddr, uint64_t asn)
180    {
181        itb->demapPage(vaddr, asn);
182    }
183
184    void demapDataPage(Addr vaddr, uint64_t asn)
185    {
186        dtb->demapPage(vaddr, asn);
187    }
188
189    void dumpFuncProfile();
190
191    Fault hwrei();
192
193    bool simPalCheck(int palFunc);
194
195    /*******************************************
196     * ThreadContext interface functions.
197     ******************************************/
198
199    BaseCPU *getCpuPtr() { return baseCpu; }
200
201    BaseTLB *getITBPtr() { return itb; }
202
203    BaseTLB *getDTBPtr() { return dtb; }
204
205    CheckerCPU *getCheckerCpuPtr() { return NULL; }
206
207    TheISA::Decoder *getDecoderPtr() { return &decoder; }
208
209    System *getSystemPtr() { return system; }
210
211    Status status() const { return _status; }
212
213    void setStatus(Status newStatus) { _status = newStatus; }
214
215    /// Set the status to Active.
216    void activate();
217
218    /// Set the status to Suspended.
219    void suspend();
220
221    /// Set the status to Halted.
222    void halt();
223
224    void copyArchRegs(ThreadContext *tc);
225
226    void clearArchRegs()
227    {
228        _pcState = 0;
229        memset(intRegs, 0, sizeof(intRegs));
230        memset(floatRegs, 0, sizeof(floatRegs));
231        for (int i = 0; i < TheISA::NumVecRegs; i++) {
232            vecRegs[i].zero();
233        }
234#ifdef ISA_HAS_CC_REGS
235        memset(ccRegs, 0, sizeof(ccRegs));
236#endif
237        isa->clear();
238    }
239
240    //
241    // New accessors for new decoder.
242    //
243    uint64_t readIntReg(int reg_idx)
244    {
245        int flatIndex = isa->flattenIntIndex(reg_idx);
246        assert(flatIndex < TheISA::NumIntRegs);
247        uint64_t regVal(readIntRegFlat(flatIndex));
248        DPRINTF(IntRegs, "Reading int reg %d (%d) as %#x.\n",
249                reg_idx, flatIndex, regVal);
250        return regVal;
251    }
252
253    FloatRegBits readFloatRegBits(int reg_idx)
254    {
255        int flatIndex = isa->flattenFloatIndex(reg_idx);
256        assert(flatIndex < TheISA::NumFloatRegs);
257        FloatRegBits regVal(readFloatRegBitsFlat(flatIndex));
258        DPRINTF(FloatRegs, "Reading float reg %d (%d) bits as %#x.\n",
259                reg_idx, flatIndex, regVal);
260        return regVal;
261    }
262
263    const VecRegContainer&
264    readVecReg(const RegId& reg) const
265    {
266        int flatIndex = isa->flattenVecIndex(reg.index());
267        assert(flatIndex < TheISA::NumVecRegs);
268        const VecRegContainer& regVal = readVecRegFlat(flatIndex);
269        DPRINTF(VecRegs, "Reading vector reg %d (%d) as %s.\n",
270                reg.index(), flatIndex, regVal.as<TheISA::VecElem>().print());
271        return regVal;
272    }
273
274    VecRegContainer&
275    getWritableVecReg(const RegId& reg)
276    {
277        int flatIndex = isa->flattenVecIndex(reg.index());
278        assert(flatIndex < TheISA::NumVecRegs);
279        VecRegContainer& regVal = getWritableVecRegFlat(flatIndex);
280        DPRINTF(VecRegs, "Reading vector reg %d (%d) as %s for modify.\n",
281                reg.index(), flatIndex, regVal.as<TheISA::VecElem>().print());
282        return regVal;
283    }
284
285    /** Vector Register Lane Interfaces. */
286    /** @{ */
287    /** Reads source vector <T> operand. */
288    template <typename T>
289    VecLaneT<T, true>
290    readVecLane(const RegId& reg) const
291    {
292        int flatIndex = isa->flattenVecIndex(reg.index());
293        assert(flatIndex < TheISA::NumVecRegs);
294        auto regVal = readVecLaneFlat<T>(flatIndex, reg.elemIndex());
295        DPRINTF(VecRegs, "Reading vector lane %d (%d)[%d] as %lx.\n",
296                reg.index(), flatIndex, reg.elemIndex(), regVal);
297        return regVal;
298    }
299
300    /** Reads source vector 8bit operand. */
301    virtual ConstVecLane8
302    readVec8BitLaneReg(const RegId& reg) const
303    { return readVecLane<uint8_t>(reg); }
304
305    /** Reads source vector 16bit operand. */
306    virtual ConstVecLane16
307    readVec16BitLaneReg(const RegId& reg) const
308    { return readVecLane<uint16_t>(reg); }
309
310    /** Reads source vector 32bit operand. */
311    virtual ConstVecLane32
312    readVec32BitLaneReg(const RegId& reg) const
313    { return readVecLane<uint32_t>(reg); }
314
315    /** Reads source vector 64bit operand. */
316    virtual ConstVecLane64
317    readVec64BitLaneReg(const RegId& reg) const
318    { return readVecLane<uint64_t>(reg); }
319
320    /** Write a lane of the destination vector register. */
321    template <typename LD>
322    void setVecLaneT(const RegId& reg, const LD& val)
323    {
324        int flatIndex = isa->flattenVecIndex(reg.index());
325        assert(flatIndex < TheISA::NumVecRegs);
326        setVecLaneFlat(flatIndex, reg.elemIndex(), val);
327        DPRINTF(VecRegs, "Reading vector lane %d (%d)[%d] to %lx.\n",
328                reg.index(), flatIndex, reg.elemIndex(), val);
329    }
330    virtual void setVecLane(const RegId& reg,
331            const LaneData<LaneSize::Byte>& val)
332    { return setVecLaneT(reg, val); }
333    virtual void setVecLane(const RegId& reg,
334            const LaneData<LaneSize::TwoByte>& val)
335    { return setVecLaneT(reg, val); }
336    virtual void setVecLane(const RegId& reg,
337            const LaneData<LaneSize::FourByte>& val)
338    { return setVecLaneT(reg, val); }
339    virtual void setVecLane(const RegId& reg,
340            const LaneData<LaneSize::EightByte>& val)
341    { return setVecLaneT(reg, val); }
342    /** @} */
343
344    const VecElem& readVecElem(const RegId& reg) const
345    {
346        int flatIndex = isa->flattenVecElemIndex(reg.index());
347        assert(flatIndex < TheISA::NumVecRegs);
348        const VecElem& regVal = readVecElemFlat(flatIndex, reg.elemIndex());
349        DPRINTF(VecRegs, "Reading element %d of vector reg %d (%d) as"
350                " %#x.\n", reg.elemIndex(), reg.index(), flatIndex, regVal);
351        return regVal;
352    }
353
354
355    CCReg readCCReg(int reg_idx)
356    {
357#ifdef ISA_HAS_CC_REGS
358        int flatIndex = isa->flattenCCIndex(reg_idx);
359        assert(0 <= flatIndex);
360        assert(flatIndex < TheISA::NumCCRegs);
361        uint64_t regVal(readCCRegFlat(flatIndex));
362        DPRINTF(CCRegs, "Reading CC reg %d (%d) as %#x.\n",
363                reg_idx, flatIndex, regVal);
364        return regVal;
365#else
366        panic("Tried to read a CC register.");
367        return 0;
368#endif
369    }
370
371    void setIntReg(int reg_idx, uint64_t val)
372    {
373        int flatIndex = isa->flattenIntIndex(reg_idx);
374        assert(flatIndex < TheISA::NumIntRegs);
375        DPRINTF(IntRegs, "Setting int reg %d (%d) to %#x.\n",
376                reg_idx, flatIndex, val);
377        setIntRegFlat(flatIndex, val);
378    }
379
380    void setFloatRegBits(int reg_idx, FloatRegBits val)
381    {
382        int flatIndex = isa->flattenFloatIndex(reg_idx);
383        assert(flatIndex < TheISA::NumFloatRegs);
384        // XXX: Fix array out of bounds compiler error for gem5.fast
385        // when checkercpu enabled
386        if (flatIndex < TheISA::NumFloatRegs)
387            setFloatRegBitsFlat(flatIndex, val);
388        DPRINTF(FloatRegs, "Setting float reg %d (%d) bits to %#x.\n",
389                reg_idx, flatIndex, val);
390    }
391
392    void setVecReg(const RegId& reg, const VecRegContainer& val)
393    {
394        int flatIndex = isa->flattenVecIndex(reg.index());
395        assert(flatIndex < TheISA::NumVecRegs);
396        setVecRegFlat(flatIndex, val);
397        DPRINTF(VecRegs, "Setting vector reg %d (%d) to %s.\n",
398                reg.index(), flatIndex, val.print());
399    }
400
401    void setVecElem(const RegId& reg, const VecElem& val)
402    {
403        int flatIndex = isa->flattenVecElemIndex(reg.index());
404        assert(flatIndex < TheISA::NumVecRegs);
405        setVecElemFlat(flatIndex, reg.elemIndex(), val);
406        DPRINTF(VecRegs, "Setting element %d of vector reg %d (%d) to"
407                " %#x.\n", reg.elemIndex(), reg.index(), flatIndex, val);
408    }
409
410    void setCCReg(int reg_idx, CCReg val)
411    {
412#ifdef ISA_HAS_CC_REGS
413        int flatIndex = isa->flattenCCIndex(reg_idx);
414        assert(flatIndex < TheISA::NumCCRegs);
415        DPRINTF(CCRegs, "Setting CC reg %d (%d) to %#x.\n",
416                reg_idx, flatIndex, val);
417        setCCRegFlat(flatIndex, val);
418#else
419        panic("Tried to set a CC register.");
420#endif
421    }
422
423    TheISA::PCState
424    pcState()
425    {
426        return _pcState;
427    }
428
429    void
430    pcState(const TheISA::PCState &val)
431    {
432        _pcState = val;
433    }
434
435    void
436    pcStateNoRecord(const TheISA::PCState &val)
437    {
438        _pcState = val;
439    }
440
441    Addr
442    instAddr()
443    {
444        return _pcState.instAddr();
445    }
446
447    Addr
448    nextInstAddr()
449    {
450        return _pcState.nextInstAddr();
451    }
452
453    void
454    setNPC(Addr val)
455    {
456        _pcState.setNPC(val);
457    }
458
459    MicroPC
460    microPC()
461    {
462        return _pcState.microPC();
463    }
464
465    bool readPredicate()
466    {
467        return predicate;
468    }
469
470    void setPredicate(bool val)
471    {
472        predicate = val;
473    }
474
475    MiscReg
476    readMiscRegNoEffect(int misc_reg, ThreadID tid = 0) const
477    {
478        return isa->readMiscRegNoEffect(misc_reg);
479    }
480
481    MiscReg
482    readMiscReg(int misc_reg, ThreadID tid = 0)
483    {
484        return isa->readMiscReg(misc_reg, tc);
485    }
486
487    void
488    setMiscRegNoEffect(int misc_reg, const MiscReg &val, ThreadID tid = 0)
489    {
490        return isa->setMiscRegNoEffect(misc_reg, val);
491    }
492
493    void
494    setMiscReg(int misc_reg, const MiscReg &val, ThreadID tid = 0)
495    {
496        return isa->setMiscReg(misc_reg, val, tc);
497    }
498
499    RegId
500    flattenRegId(const RegId& regId) const
501    {
502        return isa->flattenRegId(regId);
503    }
504
505    unsigned readStCondFailures() { return storeCondFailures; }
506
507    void setStCondFailures(unsigned sc_failures)
508    { storeCondFailures = sc_failures; }
509
510    void syscall(int64_t callnum, Fault *fault)
511    {
512        process->syscall(callnum, tc, fault);
513    }
514
515    uint64_t readIntRegFlat(int idx) { return intRegs[idx]; }
516    void setIntRegFlat(int idx, uint64_t val) { intRegs[idx] = val; }
517
518    FloatRegBits readFloatRegBitsFlat(int idx) { return floatRegs[idx]; }
519    void setFloatRegBitsFlat(int idx, FloatRegBits val) {
520        floatRegs[idx] = val;
521    }
522
523    const VecRegContainer& readVecRegFlat(const RegIndex& reg) const
524    {
525        return vecRegs[reg];
526    }
527
528    VecRegContainer& getWritableVecRegFlat(const RegIndex& reg)
529    {
530        return vecRegs[reg];
531    }
532
533    void setVecRegFlat(const RegIndex& reg, const VecRegContainer& val)
534    {
535        vecRegs[reg] = val;
536    }
537
538    template <typename T>
539    VecLaneT<T, true> readVecLaneFlat(const RegIndex& reg, int lId) const
540    {
541        return vecRegs[reg].laneView<T>(lId);
542    }
543
544    template <typename LD>
545    void setVecLaneFlat(const RegIndex& reg, int lId, const LD& val)
546    {
547        vecRegs[reg].laneView<typename LD::UnderlyingType>(lId) = val;
548    }
549
550    const VecElem& readVecElemFlat(const RegIndex& reg,
551                                   const ElemIndex& elemIndex) const
552    {
553        return vecRegs[reg].as<TheISA::VecElem>()[elemIndex];
554    }
555
556    void setVecElemFlat(const RegIndex& reg, const ElemIndex& elemIndex,
557                        const VecElem val)
558    {
559        vecRegs[reg].as<TheISA::VecElem>()[elemIndex] = val;
560    }
561
562#ifdef ISA_HAS_CC_REGS
563    CCReg readCCRegFlat(int idx) { return ccRegs[idx]; }
564    void setCCRegFlat(int idx, CCReg val) { ccRegs[idx] = val; }
565#else
566    CCReg readCCRegFlat(int idx)
567    { panic("readCCRegFlat w/no CC regs!\n"); }
568
569    void setCCRegFlat(int idx, CCReg val)
570    { panic("setCCRegFlat w/no CC regs!\n"); }
571#endif
572};
573
574
575#endif // __CPU_CPU_EXEC_CONTEXT_HH__
576