exec_context.hh revision 13598:39220222740c
1/*
2 * Copyright (c) 2014-2016 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 condition code register file accesses
125    Stats::Scalar numCCRegReads;
126    Stats::Scalar numCCRegWrites;
127
128    // Number of simulated memory references
129    Stats::Scalar numMemRefs;
130    Stats::Scalar numLoadInsts;
131    Stats::Scalar numStoreInsts;
132
133    // Number of idle cycles
134    Stats::Formula numIdleCycles;
135
136    // Number of busy cycles
137    Stats::Formula numBusyCycles;
138
139    // Number of simulated loads
140    Counter numLoad;
141
142    // Number of idle cycles
143    Stats::Average notIdleFraction;
144    Stats::Formula idleFraction;
145
146    // Number of cycles stalled for I-cache responses
147    Stats::Scalar icacheStallCycles;
148    Counter lastIcacheStall;
149
150    // Number of cycles stalled for D-cache responses
151    Stats::Scalar dcacheStallCycles;
152    Counter lastDcacheStall;
153
154    /// @{
155    /// Total number of branches fetched
156    Stats::Scalar numBranches;
157    /// Number of branches predicted as taken
158    Stats::Scalar numPredictedBranches;
159    /// Number of misprediced branches
160    Stats::Scalar numBranchMispred;
161    /// @}
162
163   // Instruction mix histogram by OpClass
164   Stats::Vector statExecutedInstType;
165
166  public:
167    /** Constructor */
168    SimpleExecContext(BaseSimpleCPU* _cpu, SimpleThread* _thread)
169        : cpu(_cpu), thread(_thread), fetchOffset(0), stayAtPC(false),
170        numInst(0), numOp(0), numLoad(0), lastIcacheStall(0), lastDcacheStall(0)
171    { }
172
173    /** Reads an integer register. */
174    RegVal
175    readIntRegOperand(const StaticInst *si, int idx) override
176    {
177        numIntRegReads++;
178        const RegId& reg = si->srcRegIdx(idx);
179        assert(reg.isIntReg());
180        return thread->readIntReg(reg.index());
181    }
182
183    /** Sets an integer register to a value. */
184    void
185    setIntRegOperand(const StaticInst *si, int idx, RegVal val) override
186    {
187        numIntRegWrites++;
188        const RegId& reg = si->destRegIdx(idx);
189        assert(reg.isIntReg());
190        thread->setIntReg(reg.index(), val);
191    }
192
193    /** Reads a floating point register in its binary format, instead
194     * of by value. */
195    RegVal
196    readFloatRegOperandBits(const StaticInst *si, int idx) override
197    {
198        numFpRegReads++;
199        const RegId& reg = si->srcRegIdx(idx);
200        assert(reg.isFloatReg());
201        return thread->readFloatRegBits(reg.index());
202    }
203
204    /** Sets the bits of a floating point register of single width
205     * to a binary value. */
206    void
207    setFloatRegOperandBits(const StaticInst *si, int idx, RegVal val) override
208    {
209        numFpRegWrites++;
210        const RegId& reg = si->destRegIdx(idx);
211        assert(reg.isFloatReg());
212        thread->setFloatRegBits(reg.index(), val);
213    }
214
215    /** Reads a vector register. */
216    const VecRegContainer &
217    readVecRegOperand(const StaticInst *si, int idx) const override
218    {
219        numVecRegReads++;
220        const RegId& reg = si->srcRegIdx(idx);
221        assert(reg.isVecReg());
222        return thread->readVecReg(reg);
223    }
224
225    /** Reads a vector register for modification. */
226    VecRegContainer &
227    getWritableVecRegOperand(const StaticInst *si, int idx) override
228    {
229        numVecRegWrites++;
230        const RegId& reg = si->destRegIdx(idx);
231        assert(reg.isVecReg());
232        return thread->getWritableVecReg(reg);
233    }
234
235    /** Sets a vector register to a value. */
236    void
237    setVecRegOperand(const StaticInst *si, int idx,
238                     const VecRegContainer& val) override
239    {
240        numVecRegWrites++;
241        const RegId& reg = si->destRegIdx(idx);
242        assert(reg.isVecReg());
243        thread->setVecReg(reg, val);
244    }
245
246    /** Vector Register Lane Interfaces. */
247    /** @{ */
248    /** Reads source vector lane. */
249    template <typename VecElem>
250    VecLaneT<VecElem, true>
251    readVecLaneOperand(const StaticInst *si, int idx) const
252    {
253        numVecRegReads++;
254        const RegId& reg = si->srcRegIdx(idx);
255        assert(reg.isVecReg());
256        return thread->readVecLane<VecElem>(reg);
257    }
258    /** Reads source vector 8bit operand. */
259    virtual ConstVecLane8
260    readVec8BitLaneOperand(const StaticInst *si, int idx) const
261                            override
262    { return readVecLaneOperand<uint8_t>(si, idx); }
263
264    /** Reads source vector 16bit operand. */
265    virtual ConstVecLane16
266    readVec16BitLaneOperand(const StaticInst *si, int idx) const
267                            override
268    { return readVecLaneOperand<uint16_t>(si, idx); }
269
270    /** Reads source vector 32bit operand. */
271    virtual ConstVecLane32
272    readVec32BitLaneOperand(const StaticInst *si, int idx) const
273                            override
274    { return readVecLaneOperand<uint32_t>(si, idx); }
275
276    /** Reads source vector 64bit operand. */
277    virtual ConstVecLane64
278    readVec64BitLaneOperand(const StaticInst *si, int idx) const
279                            override
280    { return readVecLaneOperand<uint64_t>(si, idx); }
281
282    /** Write a lane of the destination vector operand. */
283    template <typename LD>
284    void
285    setVecLaneOperandT(const StaticInst *si, int idx,
286            const LD& val)
287    {
288        numVecRegWrites++;
289        const RegId& reg = si->destRegIdx(idx);
290        assert(reg.isVecReg());
291        return thread->setVecLane(reg, val);
292    }
293    /** Write a lane of the destination vector operand. */
294    virtual void
295    setVecLaneOperand(const StaticInst *si, int idx,
296            const LaneData<LaneSize::Byte>& val) override
297    { return setVecLaneOperandT(si, idx, val); }
298    /** Write a lane of the destination vector operand. */
299    virtual void
300    setVecLaneOperand(const StaticInst *si, int idx,
301            const LaneData<LaneSize::TwoByte>& val) override
302    { return setVecLaneOperandT(si, idx, val); }
303    /** Write a lane of the destination vector operand. */
304    virtual void
305    setVecLaneOperand(const StaticInst *si, int idx,
306            const LaneData<LaneSize::FourByte>& val) override
307    { return setVecLaneOperandT(si, idx, val); }
308    /** Write a lane of the destination vector operand. */
309    virtual void
310    setVecLaneOperand(const StaticInst *si, int idx,
311            const LaneData<LaneSize::EightByte>& val) override
312    { return setVecLaneOperandT(si, idx, val); }
313    /** @} */
314
315    /** Reads an element of a vector register. */
316    VecElem
317    readVecElemOperand(const StaticInst *si, int idx) const override
318    {
319        numVecRegReads++;
320        const RegId& reg = si->srcRegIdx(idx);
321        assert(reg.isVecElem());
322        return thread->readVecElem(reg);
323    }
324
325    /** Sets an element of a vector register to a value. */
326    void
327    setVecElemOperand(const StaticInst *si, int idx,
328                      const VecElem val) override
329    {
330        numVecRegWrites++;
331        const RegId& reg = si->destRegIdx(idx);
332        assert(reg.isVecElem());
333        thread->setVecElem(reg, val);
334    }
335
336    CCReg
337    readCCRegOperand(const StaticInst *si, int idx) override
338    {
339        numCCRegReads++;
340        const RegId& reg = si->srcRegIdx(idx);
341        assert(reg.isCCReg());
342        return thread->readCCReg(reg.index());
343    }
344
345    void
346    setCCRegOperand(const StaticInst *si, int idx, CCReg val) override
347    {
348        numCCRegWrites++;
349        const RegId& reg = si->destRegIdx(idx);
350        assert(reg.isCCReg());
351        thread->setCCReg(reg.index(), val);
352    }
353
354    RegVal
355    readMiscRegOperand(const StaticInst *si, int idx) override
356    {
357        numIntRegReads++;
358        const RegId& reg = si->srcRegIdx(idx);
359        assert(reg.isMiscReg());
360        return thread->readMiscReg(reg.index());
361    }
362
363    void
364    setMiscRegOperand(const StaticInst *si, int idx, RegVal val) override
365    {
366        numIntRegWrites++;
367        const RegId& reg = si->destRegIdx(idx);
368        assert(reg.isMiscReg());
369        thread->setMiscReg(reg.index(), val);
370    }
371
372    /**
373     * Reads a miscellaneous register, handling any architectural
374     * side effects due to reading that register.
375     */
376    RegVal
377    readMiscReg(int misc_reg) override
378    {
379        numIntRegReads++;
380        return thread->readMiscReg(misc_reg);
381    }
382
383    /**
384     * Sets a miscellaneous register, handling any architectural
385     * side effects due to writing that register.
386     */
387    void
388    setMiscReg(int misc_reg, RegVal val) override
389    {
390        numIntRegWrites++;
391        thread->setMiscReg(misc_reg, val);
392    }
393
394    PCState
395    pcState() const override
396    {
397        return thread->pcState();
398    }
399
400    void
401    pcState(const PCState &val) override
402    {
403        thread->pcState(val);
404    }
405
406
407    Fault
408    readMem(Addr addr, uint8_t *data, unsigned int size,
409            Request::Flags flags) override
410    {
411        return cpu->readMem(addr, data, size, flags);
412    }
413
414    Fault
415    initiateMemRead(Addr addr, unsigned int size,
416                    Request::Flags flags) override
417    {
418        return cpu->initiateMemRead(addr, size, flags);
419    }
420
421    Fault
422    writeMem(uint8_t *data, unsigned int size, Addr addr,
423             Request::Flags flags, uint64_t *res) override
424    {
425        return cpu->writeMem(data, size, addr, flags, res);
426    }
427
428    /**
429     * Sets the number of consecutive store conditional failures.
430     */
431    void
432    setStCondFailures(unsigned int sc_failures) override
433    {
434        thread->setStCondFailures(sc_failures);
435    }
436
437    /**
438     * Returns the number of consecutive store conditional failures.
439     */
440    unsigned int
441    readStCondFailures() const override
442    {
443        return thread->readStCondFailures();
444    }
445
446    /**
447     * Executes a syscall specified by the callnum.
448     */
449    void
450    syscall(int64_t callnum, Fault *fault) override
451    {
452        if (FullSystem)
453            panic("Syscall emulation isn't available in FS mode.");
454
455        thread->syscall(callnum, fault);
456    }
457
458    /** Returns a pointer to the ThreadContext. */
459    ThreadContext *tcBase() override { return thread->getTC(); }
460
461    /**
462     * Somewhat Alpha-specific function that handles returning from an
463     * error or interrupt.
464     */
465    Fault hwrei() override { return thread->hwrei(); }
466
467    /**
468     * Check for special simulator handling of specific PAL calls.  If
469     * return value is false, actual PAL call will be suppressed.
470     */
471    bool
472    simPalCheck(int palFunc) override
473    {
474        return thread->simPalCheck(palFunc);
475    }
476
477    bool
478    readPredicate() const override
479    {
480        return thread->readPredicate();
481    }
482
483    void
484    setPredicate(bool val) override
485    {
486        thread->setPredicate(val);
487
488        if (cpu->traceData) {
489            cpu->traceData->setPredicate(val);
490        }
491    }
492
493    /**
494     * Invalidate a page in the DTLB <i>and</i> ITLB.
495     */
496    void
497    demapPage(Addr vaddr, uint64_t asn) override
498    {
499        thread->demapPage(vaddr, asn);
500    }
501
502    void
503    armMonitor(Addr address) override
504    {
505        cpu->armMonitor(thread->threadId(), address);
506    }
507
508    bool
509    mwait(PacketPtr pkt) override
510    {
511        return cpu->mwait(thread->threadId(), pkt);
512    }
513
514    void
515    mwaitAtomic(ThreadContext *tc) override
516    {
517        cpu->mwaitAtomic(thread->threadId(), tc, thread->dtb);
518    }
519
520    AddressMonitor *
521    getAddrMonitor() override
522    {
523        return cpu->getCpuAddrMonitor(thread->threadId());
524    }
525
526#if THE_ISA == MIPS_ISA
527    RegVal
528    readRegOtherThread(const RegId& reg, ThreadID tid=InvalidThreadID)
529        override
530    {
531        panic("Simple CPU models do not support multithreaded "
532              "register access.");
533    }
534
535    void
536    setRegOtherThread(const RegId& reg, RegVal val,
537                      ThreadID tid=InvalidThreadID) override
538    {
539        panic("Simple CPU models do not support multithreaded "
540              "register access.");
541    }
542#endif
543
544};
545
546#endif // __CPU_EXEC_CONTEXT_HH__
547