base_dyn_inst.hh revision 2090
111986Sandreas.sandberg@arm.com/*
211986Sandreas.sandberg@arm.com * Copyright (c) 2004-2005 The Regents of The University of Michigan
312037Sandreas.sandberg@arm.com * All rights reserved.
412037Sandreas.sandberg@arm.com *
511986Sandreas.sandberg@arm.com * Redistribution and use in source and binary forms, with or without
611986Sandreas.sandberg@arm.com * modification, are permitted provided that the following conditions are
711986Sandreas.sandberg@arm.com * met: redistributions of source code must retain the above copyright
811986Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer;
911986Sandreas.sandberg@arm.com * redistributions in binary form must reproduce the above copyright
1011986Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer in the
1111986Sandreas.sandberg@arm.com * documentation and/or other materials provided with the distribution;
1211986Sandreas.sandberg@arm.com * neither the name of the copyright holders nor the names of its
1311986Sandreas.sandberg@arm.com * contributors may be used to endorse or promote products derived from
1411986Sandreas.sandberg@arm.com * this software without specific prior written permission.
1511986Sandreas.sandberg@arm.com *
1611986Sandreas.sandberg@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1711986Sandreas.sandberg@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1811986Sandreas.sandberg@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1911986Sandreas.sandberg@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2011986Sandreas.sandberg@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2111986Sandreas.sandberg@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2211986Sandreas.sandberg@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2311986Sandreas.sandberg@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2411986Sandreas.sandberg@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2511986Sandreas.sandberg@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2611986Sandreas.sandberg@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2711986Sandreas.sandberg@arm.com */
2812037Sandreas.sandberg@arm.com
2912037Sandreas.sandberg@arm.com#ifndef __CPU_BASE_DYN_INST_HH__
3012037Sandreas.sandberg@arm.com#define __CPU_BASE_DYN_INST_HH__
3112037Sandreas.sandberg@arm.com
3212037Sandreas.sandberg@arm.com#include <string>
3312037Sandreas.sandberg@arm.com#include <vector>
3412037Sandreas.sandberg@arm.com
3512037Sandreas.sandberg@arm.com#include "base/fast_alloc.hh"
3612037Sandreas.sandberg@arm.com#include "base/trace.hh"
3712037Sandreas.sandberg@arm.com#include "config/full_system.hh"
3812037Sandreas.sandberg@arm.com#include "cpu/exetrace.hh"
3912037Sandreas.sandberg@arm.com#include "cpu/inst_seq.hh"
4012037Sandreas.sandberg@arm.com#include "cpu/o3/comm.hh"
4112037Sandreas.sandberg@arm.com#include "cpu/static_inst.hh"
4211986Sandreas.sandberg@arm.com#include "encumbered/cpu/full/bpred_update.hh"
4311986Sandreas.sandberg@arm.com#include "encumbered/cpu/full/op_class.hh"
4411986Sandreas.sandberg@arm.com#include "encumbered/cpu/full/spec_memory.hh"
4511986Sandreas.sandberg@arm.com#include "encumbered/cpu/full/spec_state.hh"
4611986Sandreas.sandberg@arm.com#include "encumbered/mem/functional/main.hh"
4711986Sandreas.sandberg@arm.com
4811986Sandreas.sandberg@arm.com/**
4911986Sandreas.sandberg@arm.com * @file
5011986Sandreas.sandberg@arm.com * Defines a dynamic instruction context.
5111986Sandreas.sandberg@arm.com */
5211986Sandreas.sandberg@arm.com
5311986Sandreas.sandberg@arm.com// Forward declaration.
5411986Sandreas.sandberg@arm.comtemplate <class ISA>
5511986Sandreas.sandberg@arm.comclass StaticInstPtr;
5611986Sandreas.sandberg@arm.com
5711986Sandreas.sandberg@arm.comtemplate <class Impl>
5811986Sandreas.sandberg@arm.comclass BaseDynInst : public FastAlloc, public RefCounted
5911986Sandreas.sandberg@arm.com{
6011986Sandreas.sandberg@arm.com  public:
6111986Sandreas.sandberg@arm.com    // Typedef for the CPU.
6211986Sandreas.sandberg@arm.com    typedef typename Impl::FullCPU FullCPU;
6311986Sandreas.sandberg@arm.com
6411986Sandreas.sandberg@arm.com    //Typedef to get the ISA.
6511986Sandreas.sandberg@arm.com    typedef typename Impl::ISA ISA;
6611986Sandreas.sandberg@arm.com
6711986Sandreas.sandberg@arm.com    /// Binary machine instruction type.
6811986Sandreas.sandberg@arm.com    typedef typename ISA::MachInst MachInst;
6911986Sandreas.sandberg@arm.com    /// Memory address type.
7011986Sandreas.sandberg@arm.com    typedef typename ISA::Addr	   Addr;
7111986Sandreas.sandberg@arm.com    /// Logical register index type.
7211986Sandreas.sandberg@arm.com    typedef typename ISA::RegIndex RegIndex;
7311986Sandreas.sandberg@arm.com    /// Integer register index type.
7412037Sandreas.sandberg@arm.com    typedef typename ISA::IntReg   IntReg;
7512037Sandreas.sandberg@arm.com
7612037Sandreas.sandberg@arm.com    enum {
7712037Sandreas.sandberg@arm.com        MaxInstSrcRegs = ISA::MaxInstSrcRegs,	//< Max source regs
7812037Sandreas.sandberg@arm.com        MaxInstDestRegs = ISA::MaxInstDestRegs,	//< Max dest regs
7912037Sandreas.sandberg@arm.com    };
8012037Sandreas.sandberg@arm.com
8112037Sandreas.sandberg@arm.com    /** The static inst used by this dyn inst. */
8212037Sandreas.sandberg@arm.com    StaticInstPtr<ISA> staticInst;
8312037Sandreas.sandberg@arm.com
8412037Sandreas.sandberg@arm.com    ////////////////////////////////////////////
8512037Sandreas.sandberg@arm.com    //
8612037Sandreas.sandberg@arm.com    // INSTRUCTION EXECUTION
8712037Sandreas.sandberg@arm.com    //
8812037Sandreas.sandberg@arm.com    ////////////////////////////////////////////
8912037Sandreas.sandberg@arm.com    Trace::InstRecord *traceData;
9012037Sandreas.sandberg@arm.com
9112037Sandreas.sandberg@arm.com    template <class T>
9212037Sandreas.sandberg@arm.com    Fault * read(Addr addr, T &data, unsigned flags);
9312037Sandreas.sandberg@arm.com
9412037Sandreas.sandberg@arm.com    template <class T>
9512037Sandreas.sandberg@arm.com    Fault * write(T data, Addr addr, unsigned flags,
9612037Sandreas.sandberg@arm.com                        uint64_t *res);
9712037Sandreas.sandberg@arm.com
9812037Sandreas.sandberg@arm.com    void prefetch(Addr addr, unsigned flags);
9912037Sandreas.sandberg@arm.com    void writeHint(Addr addr, int size, unsigned flags);
10012037Sandreas.sandberg@arm.com    Fault * copySrcTranslate(Addr src);
10112037Sandreas.sandberg@arm.com    Fault * copy(Addr dest);
10212037Sandreas.sandberg@arm.com
10311986Sandreas.sandberg@arm.com    /** @todo: Consider making this private. */
10411986Sandreas.sandberg@arm.com  public:
10511986Sandreas.sandberg@arm.com    /** Is this instruction valid. */
10611986Sandreas.sandberg@arm.com    bool valid;
10711986Sandreas.sandberg@arm.com
10811986Sandreas.sandberg@arm.com    /** The sequence number of the instruction. */
10911986Sandreas.sandberg@arm.com    InstSeqNum seqNum;
11011986Sandreas.sandberg@arm.com
11111986Sandreas.sandberg@arm.com    /** How many source registers are ready. */
11211986Sandreas.sandberg@arm.com    unsigned readyRegs;
11311986Sandreas.sandberg@arm.com
11411986Sandreas.sandberg@arm.com    /** Is the instruction completed. */
11511986Sandreas.sandberg@arm.com    bool completed;
11611986Sandreas.sandberg@arm.com
11712037Sandreas.sandberg@arm.com    /** Can this instruction issue. */
11811986Sandreas.sandberg@arm.com    bool canIssue;
11912037Sandreas.sandberg@arm.com
12012037Sandreas.sandberg@arm.com    /** Has this instruction issued. */
12112037Sandreas.sandberg@arm.com    bool issued;
12212037Sandreas.sandberg@arm.com
12312037Sandreas.sandberg@arm.com    /** Has this instruction executed (or made it through execute) yet. */
12412037Sandreas.sandberg@arm.com    bool executed;
12512037Sandreas.sandberg@arm.com
12612037Sandreas.sandberg@arm.com    /** Can this instruction commit. */
12712037Sandreas.sandberg@arm.com    bool canCommit;
12812037Sandreas.sandberg@arm.com
12912037Sandreas.sandberg@arm.com    /** Is this instruction squashed. */
13012037Sandreas.sandberg@arm.com    bool squashed;
13112037Sandreas.sandberg@arm.com
13212037Sandreas.sandberg@arm.com    /** Is this instruction squashed in the instruction queue. */
13312037Sandreas.sandberg@arm.com    bool squashedInIQ;
13412037Sandreas.sandberg@arm.com
13512037Sandreas.sandberg@arm.com    /** Is this a recover instruction. */
13612037Sandreas.sandberg@arm.com    bool recoverInst;
13712037Sandreas.sandberg@arm.com
13812037Sandreas.sandberg@arm.com    /** Is this a thread blocking instruction. */
13912037Sandreas.sandberg@arm.com    bool blockingInst;	/* this inst has called thread_block() */
14012037Sandreas.sandberg@arm.com
14112037Sandreas.sandberg@arm.com    /** Is this a thread syncrhonization instruction. */
14212037Sandreas.sandberg@arm.com    bool threadsyncWait;
14312037Sandreas.sandberg@arm.com
14412037Sandreas.sandberg@arm.com    /** The thread this instruction is from. */
14512037Sandreas.sandberg@arm.com    short threadNumber;
14612037Sandreas.sandberg@arm.com
14712037Sandreas.sandberg@arm.com    /** data address space ID, for loads & stores. */
14812037Sandreas.sandberg@arm.com    short asid;
14912037Sandreas.sandberg@arm.com
15012037Sandreas.sandberg@arm.com    /** Pointer to the FullCPU object. */
15112037Sandreas.sandberg@arm.com    FullCPU *cpu;
15212037Sandreas.sandberg@arm.com
15312037Sandreas.sandberg@arm.com    /** Pointer to the exec context.  Will not exist in the final version. */
15412037Sandreas.sandberg@arm.com    ExecContext *xc;
15512037Sandreas.sandberg@arm.com
15612037Sandreas.sandberg@arm.com    /** The kind of fault this instruction has generated. */
15712037Sandreas.sandberg@arm.com    Fault * fault;
15812037Sandreas.sandberg@arm.com
15912037Sandreas.sandberg@arm.com    /** The effective virtual address (lds & stores only). */
16012037Sandreas.sandberg@arm.com    Addr effAddr;
16112037Sandreas.sandberg@arm.com
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