base_dyn_inst.hh revision 2665:a124942bacb8
1/*
2 * Copyright (c) 2004-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Kevin Lim
29 */
30
31#ifndef __CPU_BASE_DYN_INST_HH__
32#define __CPU_BASE_DYN_INST_HH__
33
34#include <string>
35#include <vector>
36
37#include "base/fast_alloc.hh"
38#include "base/trace.hh"
39#include "config/full_system.hh"
40#include "cpu/exetrace.hh"
41#include "cpu/inst_seq.hh"
42#include "cpu/o3/comm.hh"
43#include "cpu/static_inst.hh"
44#include "encumbered/cpu/full/bpred_update.hh"
45#include "encumbered/cpu/full/op_class.hh"
46#include "encumbered/cpu/full/spec_memory.hh"
47#include "encumbered/cpu/full/spec_state.hh"
48#include "encumbered/mem/functional/main.hh"
49
50/**
51 * @file
52 * Defines a dynamic instruction context.
53 */
54
55// Forward declaration.
56class StaticInstPtr;
57
58template <class Impl>
59class BaseDynInst : public FastAlloc, public RefCounted
60{
61  public:
62    // Typedef for the CPU.
63    typedef typename Impl::FullCPU FullCPU;
64
65    /// Binary machine instruction type.
66    typedef TheISA::MachInst MachInst;
67    /// Logical register index type.
68    typedef TheISA::RegIndex RegIndex;
69    /// Integer register index type.
70    typedef TheISA::IntReg IntReg;
71
72    enum {
73        MaxInstSrcRegs = TheISA::MaxInstSrcRegs,        //< Max source regs
74        MaxInstDestRegs = TheISA::MaxInstDestRegs,      //< Max dest regs
75    };
76
77    /** The static inst used by this dyn inst. */
78    StaticInstPtr staticInst;
79
80    ////////////////////////////////////////////
81    //
82    // INSTRUCTION EXECUTION
83    //
84    ////////////////////////////////////////////
85    Trace::InstRecord *traceData;
86
87    template <class T>
88    Fault read(Addr addr, T &data, unsigned flags);
89
90    template <class T>
91    Fault write(T data, Addr addr, unsigned flags,
92                        uint64_t *res);
93
94    void prefetch(Addr addr, unsigned flags);
95    void writeHint(Addr addr, int size, unsigned flags);
96    Fault copySrcTranslate(Addr src);
97    Fault copy(Addr dest);
98
99    /** @todo: Consider making this private. */
100  public:
101    /** Is this instruction valid. */
102    bool valid;
103
104    /** The sequence number of the instruction. */
105    InstSeqNum seqNum;
106
107    /** How many source registers are ready. */
108    unsigned readyRegs;
109
110    /** Is the instruction completed. */
111    bool completed;
112
113    /** Can this instruction issue. */
114    bool canIssue;
115
116    /** Has this instruction issued. */
117    bool issued;
118
119    /** Has this instruction executed (or made it through execute) yet. */
120    bool executed;
121
122    /** Can this instruction commit. */
123    bool canCommit;
124
125    /** Is this instruction squashed. */
126    bool squashed;
127
128    /** Is this instruction squashed in the instruction queue. */
129    bool squashedInIQ;
130
131    /** Is this a recover instruction. */
132    bool recoverInst;
133
134    /** Is this a thread blocking instruction. */
135    bool blockingInst;	/* this inst has called thread_block() */
136
137    /** Is this a thread syncrhonization instruction. */
138    bool threadsyncWait;
139
140    /** The thread this instruction is from. */
141    short threadNumber;
142
143    /** data address space ID, for loads & stores. */
144    short asid;
145
146    /** Pointer to the FullCPU object. */
147    FullCPU *cpu;
148
149    /** Pointer to the exec context.  Will not exist in the final version. */
150    CPUExecContext *cpuXC;
151
152    /** The kind of fault this instruction has generated. */
153    Fault fault;
154
155    /** The effective virtual address (lds & stores only). */
156    Addr effAddr;
157
158    /** The effective physical address. */
159    Addr physEffAddr;
160
161    /** Effective virtual address for a copy source. */
162    Addr copySrcEffAddr;
163
164    /** Effective physical address for a copy source. */
165    Addr copySrcPhysEffAddr;
166
167    /** The memory request flags (from translation). */
168    unsigned memReqFlags;
169
170    /** The size of the data to be stored. */
171    int storeSize;
172
173    /** The data to be stored. */
174    IntReg storeData;
175
176    union Result {
177        uint64_t integer;
178        float fp;
179        double dbl;
180    };
181
182    /** The result of the instruction; assumes for now that there's only one
183     *  destination register.
184     */
185    Result instResult;
186
187    /** PC of this instruction. */
188    Addr PC;
189
190    /** Next non-speculative PC.  It is not filled in at fetch, but rather
191     *  once the target of the branch is truly known (either decode or
192     *  execute).
193     */
194    Addr nextPC;
195
196    /** Predicted next PC. */
197    Addr predPC;
198
199    /** Count of total number of dynamic instructions. */
200    static int instcount;
201
202    /** Whether or not the source register is ready.  Not sure this should be
203     *  here vs. the derived class.
204     */
205    bool _readySrcRegIdx[MaxInstSrcRegs];
206
207  public:
208    /** BaseDynInst constructor given a binary instruction. */
209    BaseDynInst(MachInst inst, Addr PC, Addr Pred_PC, InstSeqNum seq_num,
210                FullCPU *cpu);
211
212    /** BaseDynInst constructor given a static inst pointer. */
213    BaseDynInst(StaticInstPtr &_staticInst);
214
215    /** BaseDynInst destructor. */
216    ~BaseDynInst();
217
218  private:
219    /** Function to initialize variables in the constructors. */
220    void initVars();
221
222  public:
223    void
224    trace_mem(Fault fault,      // last fault
225              MemCmd cmd,       // last command
226              Addr addr,        // virtual address of access
227              void *p,          // memory accessed
228              int nbytes);      // access size
229
230    /** Dumps out contents of this BaseDynInst. */
231    void dump();
232
233    /** Dumps out contents of this BaseDynInst into given string. */
234    void dump(std::string &outstring);
235
236    /** Returns the fault type. */
237    Fault getFault() { return fault; }
238
239    /** Checks whether or not this instruction has had its branch target
240     *  calculated yet.  For now it is not utilized and is hacked to be
241     *  always false.
242     */
243    bool doneTargCalc() { return false; }
244
245    /** Returns the next PC.  This could be the speculative next PC if it is
246     *  called prior to the actual branch target being calculated.
247     */
248    Addr readNextPC() { return nextPC; }
249
250    /** Set the predicted target of this current instruction. */
251    void setPredTarg(Addr predicted_PC) { predPC = predicted_PC; }
252
253    /** Returns the predicted target of the branch. */
254    Addr readPredTarg() { return predPC; }
255
256    /** Returns whether the instruction was predicted taken or not. */
257    bool predTaken() {
258        return( predPC != (PC + sizeof(MachInst) ) );
259    }
260
261    /** Returns whether the instruction mispredicted. */
262    bool mispredicted() { return (predPC != nextPC); }
263
264    //
265    //  Instruction types.  Forward checks to StaticInst object.
266    //
267    bool isNop()	  const { return staticInst->isNop(); }
268    bool isMemRef()    	  const { return staticInst->isMemRef(); }
269    bool isLoad()	  const { return staticInst->isLoad(); }
270    bool isStore()	  const { return staticInst->isStore(); }
271    bool isInstPrefetch() const { return staticInst->isInstPrefetch(); }
272    bool isDataPrefetch() const { return staticInst->isDataPrefetch(); }
273    bool isCopy()         const { return staticInst->isCopy(); }
274    bool isInteger()	  const { return staticInst->isInteger(); }
275    bool isFloating()	  const { return staticInst->isFloating(); }
276    bool isControl()	  const { return staticInst->isControl(); }
277    bool isCall()	  const { return staticInst->isCall(); }
278    bool isReturn()	  const { return staticInst->isReturn(); }
279    bool isDirectCtrl()	  const { return staticInst->isDirectCtrl(); }
280    bool isIndirectCtrl() const { return staticInst->isIndirectCtrl(); }
281    bool isCondCtrl()	  const { return staticInst->isCondCtrl(); }
282    bool isUncondCtrl()	  const { return staticInst->isUncondCtrl(); }
283    bool isThreadSync()   const { return staticInst->isThreadSync(); }
284    bool isSerializing()  const { return staticInst->isSerializing(); }
285    bool isMemBarrier()   const { return staticInst->isMemBarrier(); }
286    bool isWriteBarrier() const { return staticInst->isWriteBarrier(); }
287    bool isNonSpeculative() const { return staticInst->isNonSpeculative(); }
288
289    /** Returns the opclass of this instruction. */
290    OpClass opClass() const { return staticInst->opClass(); }
291
292    /** Returns the branch target address. */
293    Addr branchTarget() const { return staticInst->branchTarget(PC); }
294
295    /** Number of source registers. */
296    int8_t numSrcRegs()	 const { return staticInst->numSrcRegs(); }
297
298    /** Number of destination registers. */
299    int8_t numDestRegs() const { return staticInst->numDestRegs(); }
300
301    // the following are used to track physical register usage
302    // for machines with separate int & FP reg files
303    int8_t numFPDestRegs()  const { return staticInst->numFPDestRegs(); }
304    int8_t numIntDestRegs() const { return staticInst->numIntDestRegs(); }
305
306    /** Returns the logical register index of the i'th destination register. */
307    RegIndex destRegIdx(int i) const
308    {
309        return staticInst->destRegIdx(i);
310    }
311
312    /** Returns the logical register index of the i'th source register. */
313    RegIndex srcRegIdx(int i) const
314    {
315        return staticInst->srcRegIdx(i);
316    }
317
318    /** Returns the result of an integer instruction. */
319    uint64_t readIntResult() { return instResult.integer; }
320
321    /** Returns the result of a floating point instruction. */
322    float readFloatResult() { return instResult.fp; }
323
324    /** Returns the result of a floating point (double) instruction. */
325    double readDoubleResult() { return instResult.dbl; }
326
327    //Push to .cc file.
328    /** Records that one of the source registers is ready. */
329    void markSrcRegReady()
330    {
331        ++readyRegs;
332        if(readyRegs == numSrcRegs()) {
333            canIssue = true;
334        }
335    }
336
337    /** Marks a specific register as ready.
338     *  @todo: Move this to .cc file.
339     */
340    void markSrcRegReady(RegIndex src_idx)
341    {
342        ++readyRegs;
343
344        _readySrcRegIdx[src_idx] = 1;
345
346        if(readyRegs == numSrcRegs()) {
347            canIssue = true;
348        }
349    }
350
351    /** Returns if a source register is ready. */
352    bool isReadySrcRegIdx(int idx) const
353    {
354        return this->_readySrcRegIdx[idx];
355    }
356
357    /** Sets this instruction as completed. */
358    void setCompleted() { completed = true; }
359
360    /** Returns whethe or not this instruction is completed. */
361    bool isCompleted() const { return completed; }
362
363    /** Sets this instruction as ready to issue. */
364    void setCanIssue() { canIssue = true; }
365
366    /** Returns whether or not this instruction is ready to issue. */
367    bool readyToIssue() const { return canIssue; }
368
369    /** Sets this instruction as issued from the IQ. */
370    void setIssued() { issued = true; }
371
372    /** Returns whether or not this instruction has issued. */
373    bool isIssued() const { return issued; }
374
375    /** Sets this instruction as executed. */
376    void setExecuted() { executed = true; }
377
378    /** Returns whether or not this instruction has executed. */
379    bool isExecuted() const { return executed; }
380
381    /** Sets this instruction as ready to commit. */
382    void setCanCommit() { canCommit = true; }
383
384    /** Clears this instruction as being ready to commit. */
385    void clearCanCommit() { canCommit = false; }
386
387    /** Returns whether or not this instruction is ready to commit. */
388    bool readyToCommit() const { return canCommit; }
389
390    /** Sets this instruction as squashed. */
391    void setSquashed() { squashed = true; }
392
393    /** Returns whether or not this instruction is squashed. */
394    bool isSquashed() const { return squashed; }
395
396    /** Sets this instruction as squashed in the IQ. */
397    void setSquashedInIQ() { squashedInIQ = true; }
398
399    /** Returns whether or not this instruction is squashed in the IQ. */
400    bool isSquashedInIQ() const { return squashedInIQ; }
401
402    /** Read the PC of this instruction. */
403    const Addr readPC() const { return PC; }
404
405    /** Set the next PC of this instruction (its actual target). */
406    void setNextPC(uint64_t val) { nextPC = val; }
407
408    /** Returns the exec context.
409     *  @todo: Remove this once the ExecContext is no longer used.
410     */
411    ExecContext *xcBase() { return cpuXC->getProxy(); }
412
413  private:
414    /** Instruction effective address.
415     *  @todo: Consider if this is necessary or not.
416     */
417    Addr instEffAddr;
418    /** Whether or not the effective address calculation is completed.
419     *  @todo: Consider if this is necessary or not.
420     */
421    bool eaCalcDone;
422
423  public:
424    /** Sets the effective address. */
425    void setEA(Addr &ea) { instEffAddr = ea; eaCalcDone = true; }
426
427    /** Returns the effective address. */
428    const Addr &getEA() const { return instEffAddr; }
429
430    /** Returns whether or not the eff. addr. calculation has been completed. */
431    bool doneEACalc() { return eaCalcDone; }
432
433    /** Returns whether or not the eff. addr. source registers are ready. */
434    bool eaSrcsReady();
435
436  public:
437    /** Load queue index. */
438    int16_t lqIdx;
439
440    /** Store queue index. */
441    int16_t sqIdx;
442};
443
444template<class Impl>
445template<class T>
446inline Fault
447BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
448{
449    MemReqPtr req = new MemReq(addr, cpuXC->getProxy(), sizeof(T), flags);
450    req->asid = asid;
451
452    fault = cpu->translateDataReadReq(req);
453
454    // Record key MemReq parameters so we can generate another one
455    // just like it for the timing access without calling translate()
456    // again (which might mess up the TLB).
457    // Do I ever really need this? -KTL 3/05
458    effAddr = req->vaddr;
459    physEffAddr = req->paddr;
460    memReqFlags = req->flags;
461
462    /**
463     * @todo
464     * Replace the disjoint functional memory with a unified one and remove
465     * this hack.
466     */
467#if !FULL_SYSTEM
468    req->paddr = req->vaddr;
469#endif
470
471    if (fault == NoFault) {
472        fault = cpu->read(req, data, lqIdx);
473    } else {
474        // Return a fixed value to keep simulation deterministic even
475        // along misspeculated paths.
476        data = (T)-1;
477    }
478
479    if (traceData) {
480        traceData->setAddr(addr);
481        traceData->setData(data);
482    }
483
484    return fault;
485}
486
487template<class Impl>
488template<class T>
489inline Fault
490BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res)
491{
492    if (traceData) {
493        traceData->setAddr(addr);
494        traceData->setData(data);
495    }
496
497    MemReqPtr req = new MemReq(addr, cpuXC->getProxy(), sizeof(T), flags);
498
499    req->asid = asid;
500
501    fault = cpu->translateDataWriteReq(req);
502
503    // Record key MemReq parameters so we can generate another one
504    // just like it for the timing access without calling translate()
505    // again (which might mess up the TLB).
506    effAddr = req->vaddr;
507    physEffAddr = req->paddr;
508    memReqFlags = req->flags;
509
510    /**
511     * @todo
512     * Replace the disjoint functional memory with a unified one and remove
513     * this hack.
514     */
515#if !FULL_SYSTEM
516    req->paddr = req->vaddr;
517#endif
518
519    if (fault == NoFault) {
520        fault = cpu->write(req, data, sqIdx);
521    }
522
523    if (res) {
524        // always return some result to keep misspeculated paths
525        // (which will ignore faults) deterministic
526        *res = (fault == NoFault) ? req->result : 0;
527    }
528
529    return fault;
530}
531
532#endif // __CPU_BASE_DYN_INST_HH__
533