simple_thread.hh revision 13611:c8b7847b4171
1/*
2 * Copyright (c) 2011-2012, 2016-2018 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/VecPredRegs.hh"
62#include "debug/VecRegs.hh"
63#include "mem/page_table.hh"
64#include "mem/request.hh"
65#include "sim/byteswap.hh"
66#include "sim/eventq.hh"
67#include "sim/process.hh"
68#include "sim/serialize.hh"
69#include "sim/system.hh"
70
71class BaseCPU;
72class CheckerCPU;
73
74class FunctionProfile;
75class ProfileNode;
76
77namespace TheISA {
78    namespace Kernel {
79        class Statistics;
80    }
81}
82
83/**
84 * The SimpleThread object provides a combination of the ThreadState
85 * object and the ThreadContext interface. It implements the
86 * ThreadContext interface so that a ProxyThreadContext class can be
87 * made using SimpleThread as the template parameter (see
88 * thread_context.hh). It adds to the ThreadState object by adding all
89 * the objects needed for simple functional execution, including a
90 * simple architectural register file, and pointers to the ITB and DTB
91 * in full system mode. For CPU models that do not need more advanced
92 * ways to hold state (i.e. a separate physical register file, or
93 * separate fetch and commit PC's), this SimpleThread class provides
94 * all the necessary state for full architecture-level functional
95 * simulation.  See the AtomicSimpleCPU or TimingSimpleCPU for
96 * examples.
97 */
98
99class SimpleThread : public ThreadState
100{
101  protected:
102    typedef TheISA::MachInst MachInst;
103    typedef TheISA::CCReg CCReg;
104    using VecRegContainer = TheISA::VecRegContainer;
105    using VecElem = TheISA::VecElem;
106    using VecPredRegContainer = TheISA::VecPredRegContainer;
107  public:
108    typedef ThreadContext::Status Status;
109
110  protected:
111    RegVal floatRegs[TheISA::NumFloatRegs];
112    RegVal intRegs[TheISA::NumIntRegs];
113    VecRegContainer vecRegs[TheISA::NumVecRegs];
114    VecPredRegContainer vecPredRegs[TheISA::NumVecPredRegs];
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        for (int i = 0; i < TheISA::NumVecPredRegs; i++) {
235            vecPredRegs[i].reset();
236        }
237#ifdef ISA_HAS_CC_REGS
238        memset(ccRegs, 0, sizeof(ccRegs));
239#endif
240        isa->clear();
241    }
242
243    //
244    // New accessors for new decoder.
245    //
246    RegVal
247    readIntReg(int reg_idx)
248    {
249        int flatIndex = isa->flattenIntIndex(reg_idx);
250        assert(flatIndex < TheISA::NumIntRegs);
251        uint64_t regVal(readIntRegFlat(flatIndex));
252        DPRINTF(IntRegs, "Reading int reg %d (%d) as %#x.\n",
253                reg_idx, flatIndex, regVal);
254        return regVal;
255    }
256
257    RegVal
258    readFloatReg(int reg_idx)
259    {
260        int flatIndex = isa->flattenFloatIndex(reg_idx);
261        assert(flatIndex < TheISA::NumFloatRegs);
262        RegVal regVal(readFloatRegFlat(flatIndex));
263        DPRINTF(FloatRegs, "Reading float reg %d (%d) bits as %#x.\n",
264                reg_idx, flatIndex, regVal);
265        return regVal;
266    }
267
268    const VecRegContainer&
269    readVecReg(const RegId& reg) const
270    {
271        int flatIndex = isa->flattenVecIndex(reg.index());
272        assert(flatIndex < TheISA::NumVecRegs);
273        const VecRegContainer& regVal = readVecRegFlat(flatIndex);
274        DPRINTF(VecRegs, "Reading vector reg %d (%d) as %s.\n",
275                reg.index(), flatIndex, regVal.print());
276        return regVal;
277    }
278
279    VecRegContainer&
280    getWritableVecReg(const RegId& reg)
281    {
282        int flatIndex = isa->flattenVecIndex(reg.index());
283        assert(flatIndex < TheISA::NumVecRegs);
284        VecRegContainer& regVal = getWritableVecRegFlat(flatIndex);
285        DPRINTF(VecRegs, "Reading vector reg %d (%d) as %s for modify.\n",
286                reg.index(), flatIndex, regVal.print());
287        return regVal;
288    }
289
290    /** Vector Register Lane Interfaces. */
291    /** @{ */
292    /** Reads source vector <T> operand. */
293    template <typename T>
294    VecLaneT<T, true>
295    readVecLane(const RegId& reg) const
296    {
297        int flatIndex = isa->flattenVecIndex(reg.index());
298        assert(flatIndex < TheISA::NumVecRegs);
299        auto regVal = readVecLaneFlat<T>(flatIndex, reg.elemIndex());
300        DPRINTF(VecRegs, "Reading vector lane %d (%d)[%d] as %lx.\n",
301                reg.index(), flatIndex, reg.elemIndex(), regVal);
302        return regVal;
303    }
304
305    /** Reads source vector 8bit operand. */
306    virtual ConstVecLane8
307    readVec8BitLaneReg(const RegId& reg) const
308    { return readVecLane<uint8_t>(reg); }
309
310    /** Reads source vector 16bit operand. */
311    virtual ConstVecLane16
312    readVec16BitLaneReg(const RegId& reg) const
313    { return readVecLane<uint16_t>(reg); }
314
315    /** Reads source vector 32bit operand. */
316    virtual ConstVecLane32
317    readVec32BitLaneReg(const RegId& reg) const
318    { return readVecLane<uint32_t>(reg); }
319
320    /** Reads source vector 64bit operand. */
321    virtual ConstVecLane64
322    readVec64BitLaneReg(const RegId& reg) const
323    { return readVecLane<uint64_t>(reg); }
324
325    /** Write a lane of the destination vector register. */
326    template <typename LD>
327    void setVecLaneT(const RegId& reg, const LD& val)
328    {
329        int flatIndex = isa->flattenVecIndex(reg.index());
330        assert(flatIndex < TheISA::NumVecRegs);
331        setVecLaneFlat(flatIndex, reg.elemIndex(), val);
332        DPRINTF(VecRegs, "Reading vector lane %d (%d)[%d] to %lx.\n",
333                reg.index(), flatIndex, reg.elemIndex(), val);
334    }
335    virtual void setVecLane(const RegId& reg,
336            const LaneData<LaneSize::Byte>& val)
337    { return setVecLaneT(reg, val); }
338    virtual void setVecLane(const RegId& reg,
339            const LaneData<LaneSize::TwoByte>& val)
340    { return setVecLaneT(reg, val); }
341    virtual void setVecLane(const RegId& reg,
342            const LaneData<LaneSize::FourByte>& val)
343    { return setVecLaneT(reg, val); }
344    virtual void setVecLane(const RegId& reg,
345            const LaneData<LaneSize::EightByte>& val)
346    { return setVecLaneT(reg, val); }
347    /** @} */
348
349    const VecElem& readVecElem(const RegId& reg) const
350    {
351        int flatIndex = isa->flattenVecElemIndex(reg.index());
352        assert(flatIndex < TheISA::NumVecRegs);
353        const VecElem& regVal = readVecElemFlat(flatIndex, reg.elemIndex());
354        DPRINTF(VecRegs, "Reading element %d of vector reg %d (%d) as"
355                " %#x.\n", reg.elemIndex(), reg.index(), flatIndex, regVal);
356        return regVal;
357    }
358
359    const VecPredRegContainer&
360    readVecPredReg(const RegId& reg) const
361    {
362        int flatIndex = isa->flattenVecPredIndex(reg.index());
363        assert(flatIndex < TheISA::NumVecPredRegs);
364        const VecPredRegContainer& regVal = readVecPredRegFlat(flatIndex);
365        DPRINTF(VecPredRegs, "Reading predicate reg %d (%d) as %s.\n",
366                reg.index(), flatIndex, regVal.print());
367        return regVal;
368    }
369
370    VecPredRegContainer&
371    getWritableVecPredReg(const RegId& reg)
372    {
373        int flatIndex = isa->flattenVecPredIndex(reg.index());
374        assert(flatIndex < TheISA::NumVecPredRegs);
375        VecPredRegContainer& regVal = getWritableVecPredRegFlat(flatIndex);
376        DPRINTF(VecPredRegs,
377                "Reading predicate reg %d (%d) as %s for modify.\n",
378                reg.index(), flatIndex, regVal.print());
379        return regVal;
380    }
381
382    CCReg readCCReg(int reg_idx)
383    {
384#ifdef ISA_HAS_CC_REGS
385        int flatIndex = isa->flattenCCIndex(reg_idx);
386        assert(0 <= flatIndex);
387        assert(flatIndex < TheISA::NumCCRegs);
388        uint64_t regVal(readCCRegFlat(flatIndex));
389        DPRINTF(CCRegs, "Reading CC reg %d (%d) as %#x.\n",
390                reg_idx, flatIndex, regVal);
391        return regVal;
392#else
393        panic("Tried to read a CC register.");
394        return 0;
395#endif
396    }
397
398    void
399    setIntReg(int reg_idx, RegVal val)
400    {
401        int flatIndex = isa->flattenIntIndex(reg_idx);
402        assert(flatIndex < TheISA::NumIntRegs);
403        DPRINTF(IntRegs, "Setting int reg %d (%d) to %#x.\n",
404                reg_idx, flatIndex, val);
405        setIntRegFlat(flatIndex, val);
406    }
407
408    void
409    setFloatReg(int reg_idx, RegVal val)
410    {
411        int flatIndex = isa->flattenFloatIndex(reg_idx);
412        assert(flatIndex < TheISA::NumFloatRegs);
413        // XXX: Fix array out of bounds compiler error for gem5.fast
414        // when checkercpu enabled
415        if (flatIndex < TheISA::NumFloatRegs)
416            setFloatRegFlat(flatIndex, val);
417        DPRINTF(FloatRegs, "Setting float reg %d (%d) bits to %#x.\n",
418                reg_idx, flatIndex, val);
419    }
420
421    void
422    setVecReg(const RegId& reg, const VecRegContainer& val)
423    {
424        int flatIndex = isa->flattenVecIndex(reg.index());
425        assert(flatIndex < TheISA::NumVecRegs);
426        setVecRegFlat(flatIndex, val);
427        DPRINTF(VecRegs, "Setting vector reg %d (%d) to %s.\n",
428                reg.index(), flatIndex, val.print());
429    }
430
431    void
432    setVecElem(const RegId& reg, const VecElem& val)
433    {
434        int flatIndex = isa->flattenVecElemIndex(reg.index());
435        assert(flatIndex < TheISA::NumVecRegs);
436        setVecElemFlat(flatIndex, reg.elemIndex(), val);
437        DPRINTF(VecRegs, "Setting element %d of vector reg %d (%d) to"
438                " %#x.\n", reg.elemIndex(), reg.index(), flatIndex, val);
439    }
440
441    void
442    setVecPredReg(const RegId& reg, const VecPredRegContainer& val)
443    {
444        int flatIndex = isa->flattenVecPredIndex(reg.index());
445        assert(flatIndex < TheISA::NumVecPredRegs);
446        setVecPredRegFlat(flatIndex, val);
447        DPRINTF(VecPredRegs, "Setting predicate reg %d (%d) to %s.\n",
448                reg.index(), flatIndex, val.print());
449    }
450
451    void
452    setCCReg(int reg_idx, CCReg val)
453    {
454#ifdef ISA_HAS_CC_REGS
455        int flatIndex = isa->flattenCCIndex(reg_idx);
456        assert(flatIndex < TheISA::NumCCRegs);
457        DPRINTF(CCRegs, "Setting CC reg %d (%d) to %#x.\n",
458                reg_idx, flatIndex, val);
459        setCCRegFlat(flatIndex, val);
460#else
461        panic("Tried to set a CC register.");
462#endif
463    }
464
465    TheISA::PCState
466    pcState()
467    {
468        return _pcState;
469    }
470
471    void
472    pcState(const TheISA::PCState &val)
473    {
474        _pcState = val;
475    }
476
477    void
478    pcStateNoRecord(const TheISA::PCState &val)
479    {
480        _pcState = val;
481    }
482
483    Addr
484    instAddr()
485    {
486        return _pcState.instAddr();
487    }
488
489    Addr
490    nextInstAddr()
491    {
492        return _pcState.nextInstAddr();
493    }
494
495    void
496    setNPC(Addr val)
497    {
498        _pcState.setNPC(val);
499    }
500
501    MicroPC
502    microPC()
503    {
504        return _pcState.microPC();
505    }
506
507    bool readPredicate()
508    {
509        return predicate;
510    }
511
512    void setPredicate(bool val)
513    {
514        predicate = val;
515    }
516
517    RegVal
518    readMiscRegNoEffect(int misc_reg, ThreadID tid=0) const
519    {
520        return isa->readMiscRegNoEffect(misc_reg);
521    }
522
523    RegVal
524    readMiscReg(int misc_reg, ThreadID tid=0)
525    {
526        return isa->readMiscReg(misc_reg, tc);
527    }
528
529    void
530    setMiscRegNoEffect(int misc_reg, RegVal val, ThreadID tid = 0)
531    {
532        return isa->setMiscRegNoEffect(misc_reg, val);
533    }
534
535    void
536    setMiscReg(int misc_reg, RegVal val, ThreadID tid = 0)
537    {
538        return isa->setMiscReg(misc_reg, val, tc);
539    }
540
541    RegId
542    flattenRegId(const RegId& regId) const
543    {
544        return isa->flattenRegId(regId);
545    }
546
547    unsigned readStCondFailures() { return storeCondFailures; }
548
549    void setStCondFailures(unsigned sc_failures)
550    { storeCondFailures = sc_failures; }
551
552    void
553    syscall(int64_t callnum, Fault *fault)
554    {
555        process->syscall(callnum, tc, fault);
556    }
557
558    RegVal readIntRegFlat(int idx) { return intRegs[idx]; }
559    void setIntRegFlat(int idx, RegVal val) { intRegs[idx] = val; }
560
561    RegVal readFloatRegFlat(int idx) { return floatRegs[idx]; }
562    void setFloatRegFlat(int idx, RegVal val) { floatRegs[idx] = val; }
563
564    const VecRegContainer &
565    readVecRegFlat(const RegIndex& reg) const
566    {
567        return vecRegs[reg];
568    }
569
570    VecRegContainer &
571    getWritableVecRegFlat(const RegIndex& reg)
572    {
573        return vecRegs[reg];
574    }
575
576    void
577    setVecRegFlat(const RegIndex& reg, const VecRegContainer& val)
578    {
579        vecRegs[reg] = val;
580    }
581
582    template <typename T>
583    VecLaneT<T, true>
584    readVecLaneFlat(const RegIndex& reg, int lId) const
585    {
586        return vecRegs[reg].laneView<T>(lId);
587    }
588
589    template <typename LD>
590    void
591    setVecLaneFlat(const RegIndex& reg, int lId, const LD& val)
592    {
593        vecRegs[reg].laneView<typename LD::UnderlyingType>(lId) = val;
594    }
595
596    const VecElem &
597    readVecElemFlat(const RegIndex& reg, const ElemIndex& elemIndex) const
598    {
599        return vecRegs[reg].as<TheISA::VecElem>()[elemIndex];
600    }
601
602    void
603    setVecElemFlat(const RegIndex& reg, const ElemIndex& elemIndex,
604                   const VecElem val)
605    {
606        vecRegs[reg].as<TheISA::VecElem>()[elemIndex] = val;
607    }
608
609    const VecPredRegContainer& readVecPredRegFlat(const RegIndex& reg) const
610    {
611        return vecPredRegs[reg];
612    }
613
614    VecPredRegContainer& getWritableVecPredRegFlat(const RegIndex& reg)
615    {
616        return vecPredRegs[reg];
617    }
618
619    void setVecPredRegFlat(const RegIndex& reg, const VecPredRegContainer& val)
620    {
621        vecPredRegs[reg] = val;
622    }
623
624#ifdef ISA_HAS_CC_REGS
625    CCReg readCCRegFlat(int idx) { return ccRegs[idx]; }
626    void setCCRegFlat(int idx, CCReg val) { ccRegs[idx] = val; }
627#else
628    CCReg readCCRegFlat(int idx)
629    { panic("readCCRegFlat w/no CC regs!\n"); }
630
631    void setCCRegFlat(int idx, CCReg val)
632    { panic("setCCRegFlat w/no CC regs!\n"); }
633#endif
634};
635
636
637#endif // __CPU_CPU_EXEC_CONTEXT_HH__
638