base_dyn_inst.hh revision 2292
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
29#ifndef __CPU_BASE_DYN_INST_HH__
30#define __CPU_BASE_DYN_INST_HH__
31
32#include <list>
33#include <string>
34
35#include "base/fast_alloc.hh"
36#include "base/trace.hh"
37#include "config/full_system.hh"
38#include "cpu/exetrace.hh"
39#include "cpu/inst_seq.hh"
40#include "cpu/static_inst.hh"
41#include "encumbered/cpu/full/op_class.hh"
42#include "mem/functional/memory_control.hh"
43#include "sim/system.hh"
44/*
45#include "encumbered/cpu/full/bpred_update.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/**
52 * @file
53 * Defines a dynamic instruction context.
54 */
55
56// Forward declaration.
57class StaticInstPtr;
58
59template <class Impl>
60class BaseDynInst : public FastAlloc, public RefCounted
61{
62  public:
63    // Typedef for the CPU.
64    typedef typename Impl::FullCPU FullCPU;
65    typedef typename FullCPU::ImplState ImplState;
66
67    // Binary machine instruction type.
68    typedef TheISA::MachInst MachInst;
69    // Extended machine instruction type
70    typedef TheISA::ExtMachInst ExtMachInst;
71    // Logical register index type.
72    typedef TheISA::RegIndex RegIndex;
73    // Integer register index type.
74    typedef TheISA::IntReg IntReg;
75
76    // The DynInstPtr type.
77    typedef typename Impl::DynInstPtr DynInstPtr;
78
79    // The list of instructions iterator type.
80    typedef typename std::list<DynInstPtr>::iterator ListIt;
81
82    enum {
83        MaxInstSrcRegs = TheISA::MaxInstSrcRegs,	/// Max source regs
84        MaxInstDestRegs = TheISA::MaxInstDestRegs,	/// Max dest regs
85    };
86
87    /** The StaticInst used by this BaseDynInst. */
88    StaticInstPtr staticInst;
89
90    ////////////////////////////////////////////
91    //
92    // INSTRUCTION EXECUTION
93    //
94    ////////////////////////////////////////////
95    /** InstRecord that tracks this instructions. */
96    Trace::InstRecord *traceData;
97
98    /**
99     * Does a read to a given address.
100     * @param addr The address to read.
101     * @param data The read's data is written into this parameter.
102     * @param flags The request's flags.
103     * @return Returns any fault due to the read.
104     */
105    template <class T>
106    Fault read(Addr addr, T &data, unsigned flags);
107
108    /**
109     * Does a write to a given address.
110     * @param data The data to be written.
111     * @param addr The address to write to.
112     * @param flags The request's flags.
113     * @param res The result of the write (for load locked/store conditionals).
114     * @return Returns any fault due to the write.
115     */
116    template <class T>
117    Fault write(T data, Addr addr, unsigned flags,
118                        uint64_t *res);
119
120    void prefetch(Addr addr, unsigned flags);
121    void writeHint(Addr addr, int size, unsigned flags);
122    Fault copySrcTranslate(Addr src);
123    Fault copy(Addr dest);
124
125    /** @todo: Consider making this private. */
126  public:
127    /** The sequence number of the instruction. */
128    InstSeqNum seqNum;
129
130    /** Is the instruction in the IQ */
131    bool iqEntry;
132
133    /** Is the instruction in the ROB */
134    bool robEntry;
135
136    /** Is the instruction in the LSQ */
137    bool lsqEntry;
138
139    /** Is the instruction completed. */
140    bool completed;
141
142    /** Can this instruction issue. */
143    bool canIssue;
144
145    /** Has this instruction issued. */
146    bool issued;
147
148    /** Has this instruction executed (or made it through execute) yet. */
149    bool executed;
150
151    /** Can this instruction commit. */
152    bool canCommit;
153
154    /** Is this instruction committed. */
155    bool committed;
156
157    /** Is this instruction squashed. */
158    bool squashed;
159
160    /** Is this instruction squashed in the instruction queue. */
161    bool squashedInIQ;
162
163    /** Is this instruction squashed in the instruction queue. */
164    bool squashedInLSQ;
165
166    /** Is this instruction squashed in the instruction queue. */
167    bool squashedInROB;
168
169    /** Is this a recover instruction. */
170    bool recoverInst;
171
172    /** Is this a thread blocking instruction. */
173    bool blockingInst;	/* this inst has called thread_block() */
174
175    /** Is this a thread syncrhonization instruction. */
176    bool threadsyncWait;
177
178    /** The thread this instruction is from. */
179    short threadNumber;
180
181    /** data address space ID, for loads & stores. */
182    short asid;
183
184    /** How many source registers are ready. */
185    unsigned readyRegs;
186
187    /** Pointer to the FullCPU object. */
188    FullCPU *cpu;
189
190    /** Pointer to the exec context.  Will not exist in the final version. */
191    ImplState *thread;
192
193    /** The kind of fault this instruction has generated. */
194    Fault fault;
195
196    /** The memory request. */
197    MemReqPtr req;
198
199    /** The effective virtual address (lds & stores only). */
200    Addr effAddr;
201
202    /** The effective physical address. */
203    Addr physEffAddr;
204
205    /** Effective virtual address for a copy source. */
206    Addr copySrcEffAddr;
207
208    /** Effective physical address for a copy source. */
209    Addr copySrcPhysEffAddr;
210
211    /** The memory request flags (from translation). */
212    unsigned memReqFlags;
213
214    /** The size of the data to be stored. */
215    int storeSize;
216
217    /** The data to be stored. */
218    IntReg storeData;
219
220    union Result {
221        uint64_t integer;
222        float fp;
223        double dbl;
224    };
225
226    /** The result of the instruction; assumes for now that there's only one
227     *  destination register.
228     */
229    Result instResult;
230
231    /** PC of this instruction. */
232    Addr PC;
233
234    /** Next non-speculative PC.  It is not filled in at fetch, but rather
235     *  once the target of the branch is truly known (either decode or
236     *  execute).
237     */
238    Addr nextPC;
239
240    /** Predicted next PC. */
241    Addr predPC;
242
243    /** Count of total number of dynamic instructions. */
244    static int instcount;
245
246#ifdef DEBUG
247    void dumpSNList();
248#endif
249
250    /** Whether or not the source register is ready.
251     *  @todo: Not sure this should be here vs the derived class.
252     */
253    bool _readySrcRegIdx[MaxInstSrcRegs];
254
255  public:
256    /** BaseDynInst constructor given a binary instruction.
257     *  @param inst The binary instruction.
258     *  @param PC The PC of the instruction.
259     *  @param pred_PC The predicted next PC.
260     *  @param seq_num The sequence number of the instruction.
261     *  @param cpu Pointer to the instruction's CPU.
262     */
263    BaseDynInst(ExtMachInst inst, Addr PC, Addr pred_PC, InstSeqNum seq_num,
264                FullCPU *cpu);
265
266    /** BaseDynInst constructor given a StaticInst pointer.
267     *  @param _staticInst The StaticInst for this BaseDynInst.
268     */
269    BaseDynInst(StaticInstPtr &_staticInst);
270
271    /** BaseDynInst destructor. */
272    ~BaseDynInst();
273
274  private:
275    /** Function to initialize variables in the constructors. */
276    void initVars();
277
278  public:
279    /**
280     *  @todo: Make this function work; currently it is a dummy function.
281     *  @param fault Last fault.
282     *  @param cmd Last command.
283     *  @param addr Virtual address of access.
284     *  @param p Memory accessed.
285     *  @param nbytes Access size.
286     */
287    void
288    trace_mem(Fault fault,
289              MemCmd cmd,
290              Addr addr,
291              void *p,
292              int nbytes);
293
294    /** Dumps out contents of this BaseDynInst. */
295    void dump();
296
297    /** Dumps out contents of this BaseDynInst into given string. */
298    void dump(std::string &outstring);
299
300    /** Returns the fault type. */
301    Fault getFault() { return fault; }
302
303    /** Checks whether or not this instruction has had its branch target
304     *  calculated yet.  For now it is not utilized and is hacked to be
305     *  always false.
306     *  @todo: Actually use this instruction.
307     */
308    bool doneTargCalc() { return false; }
309
310    /** Returns the next PC.  This could be the speculative next PC if it is
311     *  called prior to the actual branch target being calculated.
312     */
313    Addr readNextPC() { return nextPC; }
314
315    /** Set the predicted target of this current instruction. */
316    void setPredTarg(Addr predicted_PC) { predPC = predicted_PC; }
317
318    /** Returns the predicted target of the branch. */
319    Addr readPredTarg() { return predPC; }
320
321    /** Returns whether the instruction was predicted taken or not. */
322    bool predTaken() { return predPC != (PC + sizeof(MachInst)); }
323
324    /** Returns whether the instruction mispredicted. */
325    bool mispredicted() { return predPC != nextPC; }
326
327    //
328    //  Instruction types.  Forward checks to StaticInst object.
329    //
330    bool isNop()	  const { return staticInst->isNop(); }
331    bool isMemRef()    	  const { return staticInst->isMemRef(); }
332    bool isLoad()	  const { return staticInst->isLoad(); }
333    bool isStore()	  const { return staticInst->isStore(); }
334    bool isInstPrefetch() const { return staticInst->isInstPrefetch(); }
335    bool isDataPrefetch() const { return staticInst->isDataPrefetch(); }
336    bool isCopy()         const { return staticInst->isCopy(); }
337    bool isInteger()	  const { return staticInst->isInteger(); }
338    bool isFloating()	  const { return staticInst->isFloating(); }
339    bool isControl()	  const { return staticInst->isControl(); }
340    bool isCall()	  const { return staticInst->isCall(); }
341    bool isReturn()	  const { return staticInst->isReturn(); }
342    bool isDirectCtrl()	  const { return staticInst->isDirectCtrl(); }
343    bool isIndirectCtrl() const { return staticInst->isIndirectCtrl(); }
344    bool isCondCtrl()	  const { return staticInst->isCondCtrl(); }
345    bool isUncondCtrl()	  const { return staticInst->isUncondCtrl(); }
346    bool isThreadSync()   const { return staticInst->isThreadSync(); }
347    bool isSerializing()  const { return staticInst->isSerializing(); }
348    bool isSerializeBefore() const
349    { return staticInst->isSerializeBefore() || serializeBefore; }
350    bool isSerializeAfter() const
351    { return staticInst->isSerializeAfter() || serializeAfter; }
352    bool isMemBarrier()   const { return staticInst->isMemBarrier(); }
353    bool isWriteBarrier() const { return staticInst->isWriteBarrier(); }
354    bool isNonSpeculative() const { return staticInst->isNonSpeculative(); }
355    bool isQuiesce() const { return staticInst->isQuiesce(); }
356
357    /** Temporarily sets this instruction as a serialize before instruction. */
358    void setSerializeBefore() { serializeBefore = true; }
359
360    /** Clears the serializeBefore part of this instruction. */
361    void clearSerializeBefore() { serializeBefore = false; }
362
363    /** Checks if this serializeBefore is only temporarily set. */
364    bool isTempSerializeBefore() { return serializeBefore; }
365
366    /** Tracks if instruction has been externally set as serializeBefore. */
367    bool serializeBefore;
368
369    /** Temporarily sets this instruction as a serialize after instruction. */
370    void setSerializeAfter() { serializeAfter = true; }
371
372    /** Clears the serializeAfter part of this instruction.*/
373    void clearSerializeAfter() { serializeAfter = false; }
374
375    /** Checks if this serializeAfter is only temporarily set. */
376    bool isTempSerializeAfter() { return serializeAfter; }
377
378    /** Tracks if instruction has been externally set as serializeAfter. */
379    bool serializeAfter;
380
381    /** Checks if the serialization part of this instruction has been
382     *  handled.  This does not apply to the temporary serializing
383     *  state; it only applies to this instruction's own permanent
384     *  serializing state.
385     */
386    bool isSerializeHandled() { return serializeHandled; }
387
388    /** Sets the serialization part of this instruction as handled. */
389    void setSerializeHandled() { serializeHandled = true; }
390
391    /** Whether or not the serialization of this instruction has been handled. */
392    bool serializeHandled;
393
394    /** Returns the opclass of this instruction. */
395    OpClass opClass() const { return staticInst->opClass(); }
396
397    /** Returns the branch target address. */
398    Addr branchTarget() const { return staticInst->branchTarget(PC); }
399
400    /** Returns the number of source registers. */
401    int8_t numSrcRegs()	const { return staticInst->numSrcRegs(); }
402
403    /** Returns the number of destination registers. */
404    int8_t numDestRegs() const { return staticInst->numDestRegs(); }
405
406    // the following are used to track physical register usage
407    // for machines with separate int & FP reg files
408    int8_t numFPDestRegs()  const { return staticInst->numFPDestRegs(); }
409    int8_t numIntDestRegs() const { return staticInst->numIntDestRegs(); }
410
411    /** Returns the logical register index of the i'th destination register. */
412    RegIndex destRegIdx(int i) const { return staticInst->destRegIdx(i); }
413
414    /** Returns the logical register index of the i'th source register. */
415    RegIndex srcRegIdx(int i) const { return staticInst->srcRegIdx(i); }
416
417    /** Returns the result of an integer instruction. */
418    uint64_t readIntResult() { return instResult.integer; }
419
420    /** Returns the result of a floating point instruction. */
421    float readFloatResult() { return instResult.fp; }
422
423    /** Returns the result of a floating point (double) instruction. */
424    double readDoubleResult() { return instResult.dbl; }
425
426    //Push to .cc file.
427    /** Records that one of the source registers is ready. */
428    void markSrcRegReady();
429
430    /** Marks a specific register as ready.
431     *  @todo: Move this to .cc file.
432     */
433    void markSrcRegReady(RegIndex src_idx);
434
435    /** Returns if a source register is ready. */
436    bool isReadySrcRegIdx(int idx) const
437    {
438        return this->_readySrcRegIdx[idx];
439    }
440
441    /** Sets this instruction as completed. */
442    void setCompleted() { completed = true; }
443
444    /** Returns whether or not this instruction is completed. */
445    bool isCompleted() const { return completed; }
446
447    /** Sets this instruction as ready to issue. */
448    void setCanIssue() { canIssue = true; }
449
450    /** Returns whether or not this instruction is ready to issue. */
451    bool readyToIssue() const { return canIssue; }
452
453    /** Sets this instruction as issued from the IQ. */
454    void setIssued() { issued = true; }
455
456    /** Returns whether or not this instruction has issued. */
457    bool isIssued() const { return issued; }
458
459    /** Sets this instruction as executed. */
460    void setExecuted() { executed = true; }
461
462    /** Returns whether or not this instruction has executed. */
463    bool isExecuted() const { return executed; }
464
465    /** Sets this instruction as ready to commit. */
466    void setCanCommit() { canCommit = true; }
467
468    /** Clears this instruction as being ready to commit. */
469    void clearCanCommit() { canCommit = false; }
470
471    /** Returns whether or not this instruction is ready to commit. */
472    bool readyToCommit() const { return canCommit; }
473
474    /** Sets this instruction as committed. */
475    void setCommitted() { committed = true; }
476
477    /** Returns whether or not this instruction is committed. */
478    bool isCommitted() const { return committed; }
479
480    /** Sets this instruction as squashed. */
481    void setSquashed() { squashed = true; }
482
483    /** Returns whether or not this instruction is squashed. */
484    bool isSquashed() const { return squashed; }
485
486    //Instruction Queue Entry
487    //-----------------------
488    /** Sets this instruction as a entry the IQ. */
489    void setInIQ() { iqEntry = true; }
490
491    /** Sets this instruction as a entry the IQ. */
492    void removeInIQ() { iqEntry = false; }
493
494    /** Sets this instruction as squashed in the IQ. */
495    void setSquashedInIQ() { squashedInIQ = true; squashed = true;}
496
497    /** Returns whether or not this instruction is squashed in the IQ. */
498    bool isSquashedInIQ() const { return squashedInIQ; }
499
500    /** Returns whether or not this instruction has issued. */
501    bool isInIQ() const { return iqEntry; }
502
503
504    //Load / Store Queue Functions
505    //-----------------------
506    /** Sets this instruction as a entry the LSQ. */
507    void setInLSQ() { lsqEntry = true; }
508
509    /** Sets this instruction as a entry the LSQ. */
510    void removeInLSQ() { lsqEntry = false; }
511
512    /** Sets this instruction as squashed in the LSQ. */
513    void setSquashedInLSQ() { squashedInLSQ = true;}
514
515    /** Returns whether or not this instruction is squashed in the LSQ. */
516    bool isSquashedInLSQ() const { return squashedInLSQ; }
517
518    /** Returns whether or not this instruction is in the LSQ. */
519    bool isInLSQ() const { return lsqEntry; }
520
521
522    //Reorder Buffer Functions
523    //-----------------------
524    /** Sets this instruction as a entry the ROB. */
525    void setInROB() { robEntry = true; }
526
527    /** Sets this instruction as a entry the ROB. */
528    void removeInROB() { robEntry = false; }
529
530    /** Sets this instruction as squashed in the ROB. */
531    void setSquashedInROB() { squashedInROB = true; }
532
533    /** Returns whether or not this instruction is squashed in the ROB. */
534    bool isSquashedInROB() const { return squashedInROB; }
535
536    /** Returns whether or not this instruction is in the ROB. */
537    bool isInROB() const { return robEntry; }
538
539    /** Read the PC of this instruction. */
540    const Addr readPC() const { return PC; }
541
542    /** Set the next PC of this instruction (its actual target). */
543    void setNextPC(uint64_t val) { nextPC = val; }
544
545    void setASID(short addr_space_id) { asid = addr_space_id; }
546
547    void setThread(unsigned tid) { threadNumber = tid; }
548
549    void setState(ImplState *state) { thread = state; }
550
551    /** Returns the exec context.
552     *  @todo: Remove this once the ExecContext is no longer used.
553     */
554    ExecContext *xcBase() { return thread->getXCProxy(); }
555
556  private:
557    /** Instruction effective address.
558     *  @todo: Consider if this is necessary or not.
559     */
560    Addr instEffAddr;
561
562    /** Whether or not the effective address calculation is completed.
563     *  @todo: Consider if this is necessary or not.
564     */
565    bool eaCalcDone;
566
567  public:
568    /** Sets the effective address. */
569    void setEA(Addr &ea) { instEffAddr = ea; eaCalcDone = true; }
570
571    /** Returns the effective address. */
572    const Addr &getEA() const { return req->vaddr; }
573
574    /** Returns whether or not the eff. addr. calculation has been completed. */
575    bool doneEACalc() { return eaCalcDone; }
576
577    /** Returns whether or not the eff. addr. source registers are ready. */
578    bool eaSrcsReady();
579
580    /** Whether or not the memory operation is done. */
581    bool memOpDone;
582
583  public:
584    /** Load queue index. */
585    int16_t lqIdx;
586
587    /** Store queue index. */
588    int16_t sqIdx;
589
590    bool reachedCommit;
591
592    /** Iterator pointing to this BaseDynInst in the list of all insts. */
593    ListIt instListIt;
594
595    /** Returns iterator to this instruction in the list of all insts. */
596    ListIt &getInstListIt() { return instListIt; }
597
598    /** Sets iterator for this instruction in the list of all insts. */
599    void setInstListIt(ListIt _instListIt) { instListIt = _instListIt; }
600};
601
602template<class Impl>
603template<class T>
604inline Fault
605BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
606{
607    if (executed) {
608        fault = cpu->read(req, data, lqIdx);
609        return fault;
610    }
611
612    req = new MemReq(addr, thread->getXCProxy(), sizeof(T), flags);
613    req->asid = asid;
614    req->thread_num = threadNumber;
615    req->pc = this->PC;
616
617    if ((req->vaddr & (TheISA::VMPageSize - 1)) + req->size >
618        TheISA::VMPageSize) {
619        return TheISA::genAlignmentFault();
620    }
621
622    fault = cpu->translateDataReadReq(req);
623
624    effAddr = req->vaddr;
625    physEffAddr = req->paddr;
626    memReqFlags = req->flags;
627
628    if (fault == NoFault) {
629#if FULL_SYSTEM
630        if (cpu->system->memctrl->badaddr(physEffAddr)) {
631            fault = TheISA::genMachineCheckFault();
632            data = (T)-1;
633            this->setExecuted();
634        } else {
635            fault = cpu->read(req, data, lqIdx);
636        }
637#else
638        fault = cpu->read(req, data, lqIdx);
639#endif
640    } else {
641        // Return a fixed value to keep simulation deterministic even
642        // along misspeculated paths.
643        data = (T)-1;
644
645        // Commit will have to clean up whatever happened.  Set this
646        // instruction as executed.
647        this->setExecuted();
648    }
649
650    if (traceData) {
651        traceData->setAddr(addr);
652        traceData->setData(data);
653    }
654
655    return fault;
656}
657
658template<class Impl>
659template<class T>
660inline Fault
661BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res)
662{
663    if (traceData) {
664        traceData->setAddr(addr);
665        traceData->setData(data);
666    }
667
668    req = new MemReq(addr, thread->getXCProxy(), sizeof(T), flags);
669
670    req->asid = asid;
671    req->thread_num = threadNumber;
672    req->pc = this->PC;
673
674    if ((req->vaddr & (TheISA::VMPageSize - 1)) + req->size >
675        TheISA::VMPageSize) {
676        return TheISA::genAlignmentFault();
677    }
678
679    fault = cpu->translateDataWriteReq(req);
680
681    effAddr = req->vaddr;
682    physEffAddr = req->paddr;
683    memReqFlags = req->flags;
684
685    if (fault == NoFault) {
686#if FULL_SYSTEM
687        if (cpu->system->memctrl->badaddr(physEffAddr)) {
688            fault = TheISA::genMachineCheckFault();
689        } else {
690            fault = cpu->write(req, data, sqIdx);
691        }
692#else
693        fault = cpu->write(req, data, sqIdx);
694#endif
695    }
696
697    if (res) {
698        // always return some result to keep misspeculated paths
699        // (which will ignore faults) deterministic
700        *res = (fault == NoFault) ? req->result : 0;
701    }
702
703    return fault;
704}
705
706#endif // __CPU_BASE_DYN_INST_HH__
707