exec_context.hh revision 13611:c8b7847b4171
1/*
2 * Copyright (c) 2014-2017 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: Kevin Lim
41 *          Andreas Sandberg
42 *          Mitch Hayenga
43 */
44
45#ifndef __CPU_SIMPLE_EXEC_CONTEXT_HH__
46#define __CPU_SIMPLE_EXEC_CONTEXT_HH__
47
48#include "arch/registers.hh"
49#include "base/types.hh"
50#include "config/the_isa.hh"
51#include "cpu/base.hh"
52#include "cpu/exec_context.hh"
53#include "cpu/reg_class.hh"
54#include "cpu/simple/base.hh"
55#include "cpu/static_inst_fwd.hh"
56#include "cpu/translation.hh"
57#include "mem/request.hh"
58
59class BaseSimpleCPU;
60
61class SimpleExecContext : public ExecContext {
62  protected:
63    typedef TheISA::CCReg CCReg;
64    using VecRegContainer = TheISA::VecRegContainer;
65    using VecElem = TheISA::VecElem;
66
67  public:
68    BaseSimpleCPU *cpu;
69    SimpleThread* thread;
70
71    // This is the offset from the current pc that fetch should be performed
72    Addr fetchOffset;
73    // This flag says to stay at the current pc. This is useful for
74    // instructions which go beyond MachInst boundaries.
75    bool stayAtPC;
76
77    // Branch prediction
78    TheISA::PCState predPC;
79
80    /** PER-THREAD STATS */
81
82    // Number of simulated instructions
83    Counter numInst;
84    Stats::Scalar numInsts;
85    Counter numOp;
86    Stats::Scalar numOps;
87
88    // Number of integer alu accesses
89    Stats::Scalar numIntAluAccesses;
90
91    // Number of float alu accesses
92    Stats::Scalar numFpAluAccesses;
93
94    // Number of vector alu accesses
95    Stats::Scalar numVecAluAccesses;
96
97    // Number of function calls/returns
98    Stats::Scalar numCallsReturns;
99
100    // Conditional control instructions;
101    Stats::Scalar numCondCtrlInsts;
102
103    // Number of int instructions
104    Stats::Scalar numIntInsts;
105
106    // Number of float instructions
107    Stats::Scalar numFpInsts;
108
109    // Number of vector instructions
110    Stats::Scalar numVecInsts;
111
112    // Number of integer register file accesses
113    Stats::Scalar numIntRegReads;
114    Stats::Scalar numIntRegWrites;
115
116    // Number of float register file accesses
117    Stats::Scalar numFpRegReads;
118    Stats::Scalar numFpRegWrites;
119
120    // Number of vector register file accesses
121    mutable Stats::Scalar numVecRegReads;
122    Stats::Scalar numVecRegWrites;
123
124    // Number of predicate register file accesses
125    mutable Stats::Scalar numVecPredRegReads;
126    Stats::Scalar numVecPredRegWrites;
127
128    // Number of condition code register file accesses
129    Stats::Scalar numCCRegReads;
130    Stats::Scalar numCCRegWrites;
131
132    // Number of simulated memory references
133    Stats::Scalar numMemRefs;
134    Stats::Scalar numLoadInsts;
135    Stats::Scalar numStoreInsts;
136
137    // Number of idle cycles
138    Stats::Formula numIdleCycles;
139
140    // Number of busy cycles
141    Stats::Formula numBusyCycles;
142
143    // Number of simulated loads
144    Counter numLoad;
145
146    // Number of idle cycles
147    Stats::Average notIdleFraction;
148    Stats::Formula idleFraction;
149
150    // Number of cycles stalled for I-cache responses
151    Stats::Scalar icacheStallCycles;
152    Counter lastIcacheStall;
153
154    // Number of cycles stalled for D-cache responses
155    Stats::Scalar dcacheStallCycles;
156    Counter lastDcacheStall;
157
158    /// @{
159    /// Total number of branches fetched
160    Stats::Scalar numBranches;
161    /// Number of branches predicted as taken
162    Stats::Scalar numPredictedBranches;
163    /// Number of misprediced branches
164    Stats::Scalar numBranchMispred;
165    /// @}
166
167   // Instruction mix histogram by OpClass
168   Stats::Vector statExecutedInstType;
169
170  public:
171    /** Constructor */
172    SimpleExecContext(BaseSimpleCPU* _cpu, SimpleThread* _thread)
173        : cpu(_cpu), thread(_thread), fetchOffset(0), stayAtPC(false),
174        numInst(0), numOp(0), numLoad(0), lastIcacheStall(0), lastDcacheStall(0)
175    { }
176
177    /** Reads an integer register. */
178    RegVal
179    readIntRegOperand(const StaticInst *si, int idx) override
180    {
181        numIntRegReads++;
182        const RegId& reg = si->srcRegIdx(idx);
183        assert(reg.isIntReg());
184        return thread->readIntReg(reg.index());
185    }
186
187    /** Sets an integer register to a value. */
188    void
189    setIntRegOperand(const StaticInst *si, int idx, RegVal val) override
190    {
191        numIntRegWrites++;
192        const RegId& reg = si->destRegIdx(idx);
193        assert(reg.isIntReg());
194        thread->setIntReg(reg.index(), val);
195    }
196
197    /** Reads a floating point register in its binary format, instead
198     * of by value. */
199    RegVal
200    readFloatRegOperandBits(const StaticInst *si, int idx) override
201    {
202        numFpRegReads++;
203        const RegId& reg = si->srcRegIdx(idx);
204        assert(reg.isFloatReg());
205        return thread->readFloatReg(reg.index());
206    }
207
208    /** Sets the bits of a floating point register of single width
209     * to a binary value. */
210    void
211    setFloatRegOperandBits(const StaticInst *si, int idx, RegVal val) override
212    {
213        numFpRegWrites++;
214        const RegId& reg = si->destRegIdx(idx);
215        assert(reg.isFloatReg());
216        thread->setFloatReg(reg.index(), val);
217    }
218
219    /** Reads a vector register. */
220    const VecRegContainer &
221    readVecRegOperand(const StaticInst *si, int idx) const override
222    {
223        numVecRegReads++;
224        const RegId& reg = si->srcRegIdx(idx);
225        assert(reg.isVecReg());
226        return thread->readVecReg(reg);
227    }
228
229    /** Reads a vector register for modification. */
230    VecRegContainer &
231    getWritableVecRegOperand(const StaticInst *si, int idx) override
232    {
233        numVecRegWrites++;
234        const RegId& reg = si->destRegIdx(idx);
235        assert(reg.isVecReg());
236        return thread->getWritableVecReg(reg);
237    }
238
239    /** Sets a vector register to a value. */
240    void
241    setVecRegOperand(const StaticInst *si, int idx,
242                     const VecRegContainer& val) override
243    {
244        numVecRegWrites++;
245        const RegId& reg = si->destRegIdx(idx);
246        assert(reg.isVecReg());
247        thread->setVecReg(reg, val);
248    }
249
250    /** Vector Register Lane Interfaces. */
251    /** @{ */
252    /** Reads source vector lane. */
253    template <typename VecElem>
254    VecLaneT<VecElem, true>
255    readVecLaneOperand(const StaticInst *si, int idx) const
256    {
257        numVecRegReads++;
258        const RegId& reg = si->srcRegIdx(idx);
259        assert(reg.isVecReg());
260        return thread->readVecLane<VecElem>(reg);
261    }
262    /** Reads source vector 8bit operand. */
263    virtual ConstVecLane8
264    readVec8BitLaneOperand(const StaticInst *si, int idx) const
265                            override
266    { return readVecLaneOperand<uint8_t>(si, idx); }
267
268    /** Reads source vector 16bit operand. */
269    virtual ConstVecLane16
270    readVec16BitLaneOperand(const StaticInst *si, int idx) const
271                            override
272    { return readVecLaneOperand<uint16_t>(si, idx); }
273
274    /** Reads source vector 32bit operand. */
275    virtual ConstVecLane32
276    readVec32BitLaneOperand(const StaticInst *si, int idx) const
277                            override
278    { return readVecLaneOperand<uint32_t>(si, idx); }
279
280    /** Reads source vector 64bit operand. */
281    virtual ConstVecLane64
282    readVec64BitLaneOperand(const StaticInst *si, int idx) const
283                            override
284    { return readVecLaneOperand<uint64_t>(si, idx); }
285
286    /** Write a lane of the destination vector operand. */
287    template <typename LD>
288    void
289    setVecLaneOperandT(const StaticInst *si, int idx,
290            const LD& val)
291    {
292        numVecRegWrites++;
293        const RegId& reg = si->destRegIdx(idx);
294        assert(reg.isVecReg());
295        return thread->setVecLane(reg, val);
296    }
297    /** Write a lane of the destination vector operand. */
298    virtual void
299    setVecLaneOperand(const StaticInst *si, int idx,
300            const LaneData<LaneSize::Byte>& val) override
301    { return setVecLaneOperandT(si, idx, val); }
302    /** Write a lane of the destination vector operand. */
303    virtual void
304    setVecLaneOperand(const StaticInst *si, int idx,
305            const LaneData<LaneSize::TwoByte>& val) override
306    { return setVecLaneOperandT(si, idx, val); }
307    /** Write a lane of the destination vector operand. */
308    virtual void
309    setVecLaneOperand(const StaticInst *si, int idx,
310            const LaneData<LaneSize::FourByte>& val) override
311    { return setVecLaneOperandT(si, idx, val); }
312    /** Write a lane of the destination vector operand. */
313    virtual void
314    setVecLaneOperand(const StaticInst *si, int idx,
315            const LaneData<LaneSize::EightByte>& val) override
316    { return setVecLaneOperandT(si, idx, val); }
317    /** @} */
318
319    /** Reads an element of a vector register. */
320    VecElem
321    readVecElemOperand(const StaticInst *si, int idx) const override
322    {
323        numVecRegReads++;
324        const RegId& reg = si->srcRegIdx(idx);
325        assert(reg.isVecElem());
326        return thread->readVecElem(reg);
327    }
328
329    /** Sets an element of a vector register to a value. */
330    void
331    setVecElemOperand(const StaticInst *si, int idx,
332                      const VecElem val) override
333    {
334        numVecRegWrites++;
335        const RegId& reg = si->destRegIdx(idx);
336        assert(reg.isVecElem());
337        thread->setVecElem(reg, val);
338    }
339
340    const VecPredRegContainer&
341    readVecPredRegOperand(const StaticInst *si, int idx) const override
342    {
343        numVecPredRegReads++;
344        const RegId& reg = si->srcRegIdx(idx);
345        assert(reg.isVecPredReg());
346        return thread->readVecPredReg(reg);
347    }
348
349    VecPredRegContainer&
350    getWritableVecPredRegOperand(const StaticInst *si, int idx) override
351    {
352        numVecPredRegWrites++;
353        const RegId& reg = si->destRegIdx(idx);
354        assert(reg.isVecPredReg());
355        return thread->getWritableVecPredReg(reg);
356    }
357
358    void
359    setVecPredRegOperand(const StaticInst *si, int idx,
360                         const VecPredRegContainer& val) override
361    {
362        numVecPredRegWrites++;
363        const RegId& reg = si->destRegIdx(idx);
364        assert(reg.isVecPredReg());
365        thread->setVecPredReg(reg, val);
366    }
367
368    CCReg
369    readCCRegOperand(const StaticInst *si, int idx) override
370    {
371        numCCRegReads++;
372        const RegId& reg = si->srcRegIdx(idx);
373        assert(reg.isCCReg());
374        return thread->readCCReg(reg.index());
375    }
376
377    void
378    setCCRegOperand(const StaticInst *si, int idx, CCReg val) override
379    {
380        numCCRegWrites++;
381        const RegId& reg = si->destRegIdx(idx);
382        assert(reg.isCCReg());
383        thread->setCCReg(reg.index(), val);
384    }
385
386    RegVal
387    readMiscRegOperand(const StaticInst *si, int idx) override
388    {
389        numIntRegReads++;
390        const RegId& reg = si->srcRegIdx(idx);
391        assert(reg.isMiscReg());
392        return thread->readMiscReg(reg.index());
393    }
394
395    void
396    setMiscRegOperand(const StaticInst *si, int idx, RegVal val) override
397    {
398        numIntRegWrites++;
399        const RegId& reg = si->destRegIdx(idx);
400        assert(reg.isMiscReg());
401        thread->setMiscReg(reg.index(), val);
402    }
403
404    /**
405     * Reads a miscellaneous register, handling any architectural
406     * side effects due to reading that register.
407     */
408    RegVal
409    readMiscReg(int misc_reg) override
410    {
411        numIntRegReads++;
412        return thread->readMiscReg(misc_reg);
413    }
414
415    /**
416     * Sets a miscellaneous register, handling any architectural
417     * side effects due to writing that register.
418     */
419    void
420    setMiscReg(int misc_reg, RegVal val) override
421    {
422        numIntRegWrites++;
423        thread->setMiscReg(misc_reg, val);
424    }
425
426    PCState
427    pcState() const override
428    {
429        return thread->pcState();
430    }
431
432    void
433    pcState(const PCState &val) override
434    {
435        thread->pcState(val);
436    }
437
438
439    Fault
440    readMem(Addr addr, uint8_t *data, unsigned int size,
441            Request::Flags flags) override
442    {
443        return cpu->readMem(addr, data, size, flags);
444    }
445
446    Fault
447    initiateMemRead(Addr addr, unsigned int size,
448                    Request::Flags flags) override
449    {
450        return cpu->initiateMemRead(addr, size, flags);
451    }
452
453    Fault
454    writeMem(uint8_t *data, unsigned int size, Addr addr,
455             Request::Flags flags, uint64_t *res) override
456    {
457        return cpu->writeMem(data, size, addr, flags, res);
458    }
459
460    /**
461     * Sets the number of consecutive store conditional failures.
462     */
463    void
464    setStCondFailures(unsigned int sc_failures) override
465    {
466        thread->setStCondFailures(sc_failures);
467    }
468
469    /**
470     * Returns the number of consecutive store conditional failures.
471     */
472    unsigned int
473    readStCondFailures() const override
474    {
475        return thread->readStCondFailures();
476    }
477
478    /**
479     * Executes a syscall specified by the callnum.
480     */
481    void
482    syscall(int64_t callnum, Fault *fault) override
483    {
484        if (FullSystem)
485            panic("Syscall emulation isn't available in FS mode.");
486
487        thread->syscall(callnum, fault);
488    }
489
490    /** Returns a pointer to the ThreadContext. */
491    ThreadContext *tcBase() override { return thread->getTC(); }
492
493    /**
494     * Somewhat Alpha-specific function that handles returning from an
495     * error or interrupt.
496     */
497    Fault hwrei() override { return thread->hwrei(); }
498
499    /**
500     * Check for special simulator handling of specific PAL calls.  If
501     * return value is false, actual PAL call will be suppressed.
502     */
503    bool
504    simPalCheck(int palFunc) override
505    {
506        return thread->simPalCheck(palFunc);
507    }
508
509    bool
510    readPredicate() const override
511    {
512        return thread->readPredicate();
513    }
514
515    void
516    setPredicate(bool val) override
517    {
518        thread->setPredicate(val);
519
520        if (cpu->traceData) {
521            cpu->traceData->setPredicate(val);
522        }
523    }
524
525    /**
526     * Invalidate a page in the DTLB <i>and</i> ITLB.
527     */
528    void
529    demapPage(Addr vaddr, uint64_t asn) override
530    {
531        thread->demapPage(vaddr, asn);
532    }
533
534    void
535    armMonitor(Addr address) override
536    {
537        cpu->armMonitor(thread->threadId(), address);
538    }
539
540    bool
541    mwait(PacketPtr pkt) override
542    {
543        return cpu->mwait(thread->threadId(), pkt);
544    }
545
546    void
547    mwaitAtomic(ThreadContext *tc) override
548    {
549        cpu->mwaitAtomic(thread->threadId(), tc, thread->dtb);
550    }
551
552    AddressMonitor *
553    getAddrMonitor() override
554    {
555        return cpu->getCpuAddrMonitor(thread->threadId());
556    }
557
558#if THE_ISA == MIPS_ISA
559    RegVal
560    readRegOtherThread(const RegId& reg, ThreadID tid=InvalidThreadID)
561        override
562    {
563        panic("Simple CPU models do not support multithreaded "
564              "register access.");
565    }
566
567    void
568    setRegOtherThread(const RegId& reg, RegVal val,
569                      ThreadID tid=InvalidThreadID) override
570    {
571        panic("Simple CPU models do not support multithreaded "
572              "register access.");
573    }
574#endif
575
576};
577
578#endif // __CPU_EXEC_CONTEXT_HH__
579