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