base_dyn_inst.hh revision 1061
12207SN/A/*
22207SN/A * Copyright (c) 2001-2004 The Regents of The University of Michigan
32207SN/A * All rights reserved.
42207SN/A *
52207SN/A * Redistribution and use in source and binary forms, with or without
62207SN/A * modification, are permitted provided that the following conditions are
72207SN/A * met: redistributions of source code must retain the above copyright
82207SN/A * notice, this list of conditions and the following disclaimer;
92207SN/A * redistributions in binary form must reproduce the above copyright
102207SN/A * notice, this list of conditions and the following disclaimer in the
112207SN/A * documentation and/or other materials provided with the distribution;
122207SN/A * neither the name of the copyright holders nor the names of its
132207SN/A * contributors may be used to endorse or promote products derived from
142207SN/A * this software without specific prior written permission.
152207SN/A *
162207SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172207SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182207SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192207SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202207SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212207SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222207SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232207SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242207SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252207SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262207SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu */
282665Ssaidi@eecs.umich.edu
292665Ssaidi@eecs.umich.edu#ifndef __BASE_DYN_INST_HH__
302207SN/A#define __BASE_DYN_INST_HH__
312207SN/A
325569Snate@binkert.org#include <vector>
335569Snate@binkert.org#include <string>
342207SN/A
3511800Sbrandon.potter@amd.com#include "base/fast_alloc.hh"
362474SN/A#include "base/trace.hh"
372207SN/A
3811851Sbrandon.potter@amd.com#include "cpu/static_inst.hh"
392207SN/A#include "cpu/beta_cpu/comm.hh"
407532Ssteve.reinhardt@amd.com#include "cpu/full_cpu/bpred_update.hh"
417532Ssteve.reinhardt@amd.com#include "mem/functional_mem/main_memory.hh"
427532Ssteve.reinhardt@amd.com#include "cpu/full_cpu/spec_memory.hh"
432474SN/A#include "cpu/inst_seq.hh"
4411851Sbrandon.potter@amd.com#include "cpu/full_cpu/op_class.hh"
452207SN/A#include "cpu/full_cpu/spec_state.hh"
4612186Sgabeblack@google.com
4711169Sandreas.hansson@arm.com/**
485759Shsul@eecs.umich.edu * @file
495759Shsul@eecs.umich.edu * Defines a dynamic instruction context.
505958Sgblack@eecs.umich.edu */
515958Sgblack@eecs.umich.edu
5213614Sgabeblack@google.comnamespace Trace {
539552Sandreas.hansson@arm.com    class InstRecord;
5411851Sbrandon.potter@amd.com};
5513614Sgabeblack@google.com
5611169Sandreas.hansson@arm.com// Forward declaration.
5711169Sandreas.hansson@arm.comtemplate <class blah>
5811386Ssteve.reinhardt@amd.comclass StaticInstPtr;
5911851Sbrandon.potter@amd.com
6011386Ssteve.reinhardt@amd.comtemplate <class Impl>
6111386Ssteve.reinhardt@amd.comclass BaseDynInst : public FastAlloc, public RefCounted
622474SN/A{
632474SN/A  public:
645569Snate@binkert.org    // Typedef for the CPU.
65    typedef typename Impl::FullCPU FullCPU;
66
67    //Typedef to get the ISA.
68    typedef typename Impl::ISA ISA;
69
70    /// Binary machine instruction type.
71    typedef typename ISA::MachInst MachInst;
72    /// Memory address type.
73    typedef typename ISA::Addr	   Addr;
74    /// Logical register index type.
75    typedef typename ISA::RegIndex RegIndex;
76    /// Integer register index type.
77    typedef typename ISA::IntReg   IntReg;
78
79    enum {
80        MaxInstSrcRegs = ISA::MaxInstSrcRegs,	//< Max source regs
81        MaxInstDestRegs = ISA::MaxInstDestRegs,	//< Max dest regs
82    };
83
84    StaticInstPtr<ISA> staticInst;
85
86    ////////////////////////////////////////////
87    //
88    // INSTRUCTION EXECUTION
89    //
90    ////////////////////////////////////////////
91    Trace::InstRecord *traceData;
92
93//    void setCPSeq(InstSeqNum seq);
94
95    template <class T>
96    Fault read(Addr addr, T &data, unsigned flags);
97
98    template <class T>
99    Fault write(T data, Addr addr, unsigned flags,
100                        uint64_t *res);
101
102
103    IntReg *getIntegerRegs(void);
104    FunctionalMemory *getMemory(void);
105
106    void prefetch(Addr addr, unsigned flags);
107    void writeHint(Addr addr, int size, unsigned flags);
108    Fault copySrcTranslate(Addr src);
109    Fault copy(Addr dest);
110
111  public:
112    /** Is this instruction valid. */
113    bool valid;
114
115    /** The sequence number of the instruction. */
116    InstSeqNum seqNum;
117
118    /** How many source registers are ready. */
119    unsigned readyRegs;
120
121    /** Can this instruction issue. */
122    bool canIssue;
123
124    /** Has this instruction issued. */
125    bool issued;
126
127    /** Has this instruction executed (or made it through execute) yet. */
128    bool executed;
129
130    /** Can this instruction commit. */
131    bool canCommit;
132
133    /** Is this instruction squashed. */
134    bool squashed;
135
136    /** Is this instruction squashed in the instruction queue. */
137    bool squashedInIQ;
138
139    /** Is this a recover instruction. */
140    bool recoverInst;
141
142    /** Is this a thread blocking instruction. */
143    bool blockingInst;	/* this inst has called thread_block() */
144
145    /** Is this a thread syncrhonization instruction. */
146    bool threadsyncWait;
147
148    /** If the BTB missed. */
149    bool btbMissed;
150
151    /** The thread this instruction is from. */
152    short threadNumber;
153
154    /** If instruction is speculative. */
155    short specMode;
156
157    /** data address space ID, for loads & stores. */
158    short asid;
159
160    /** Pointer to the FullCPU object. */
161    FullCPU *cpu;
162
163    /** Pointer to the exec context.  Will not exist in the final version. */
164    ExecContext *xc;
165
166    /** The kind of fault this instruction has generated. */
167    Fault fault;
168
169    /** The effective virtual address (lds & stores only). */
170    Addr effAddr;
171
172    /** The effective physical address. */
173    Addr physEffAddr;
174
175    /** Effective virtual address for a copy source. */
176    Addr copySrcEffAddr;
177
178    /** Effective physical address for a copy source. */
179    Addr copySrcPhysEffAddr;
180
181    /** The memory request flags (from translation). */
182    unsigned memReqFlags;
183
184    /** The size of the data to be stored. */
185    int storeSize;
186
187    /** The data to be stored. */
188    IntReg storeData;
189
190    /** Result of this instruction, if an integer. */
191    uint64_t intResult;
192
193    /** Result of this instruction, if a float. */
194    float floatResult;
195
196    /** Result of this instruction, if a double. */
197    double doubleResult;
198
199    /** PC of this instruction. */
200    Addr PC;
201
202    /** Next non-speculative PC.  It is not filled in at fetch, but rather
203     *  once the target of the branch is truly known (either decode or
204     *  execute).
205     */
206    Addr nextPC;
207
208    /** Predicted next PC. */
209    Addr predPC;
210
211    /** Count of total number of dynamic instructions. */
212    static int instcount;
213
214    /** Did this instruction do a spec write? */
215    bool specMemWrite;
216
217  private:
218    /** Physical register index of the destination registers of this
219     *  instruction.
220     */
221    PhysRegIndex _destRegIdx[MaxInstDestRegs];
222
223    /** Physical register index of the source registers of this
224     *  instruction.
225     */
226    PhysRegIndex _srcRegIdx[MaxInstSrcRegs];
227
228    /** Whether or not the source register is ready. */
229    bool _readySrcRegIdx[MaxInstSrcRegs];
230
231    /** Physical register index of the previous producers of the
232     *  architected destinations.
233     */
234    PhysRegIndex _prevDestRegIdx[MaxInstDestRegs];
235
236  public:
237    /** BaseDynInst constructor given a binary instruction. */
238    BaseDynInst(MachInst inst, Addr PC, Addr Pred_PC, InstSeqNum seq_num,
239                FullCPU *cpu);
240
241    /** BaseDynInst constructor given a static inst pointer. */
242    BaseDynInst(StaticInstPtr<ISA> &_staticInst);
243
244    /** BaseDynInst destructor. */
245    ~BaseDynInst();
246
247#if 0
248    Fault
249    mem_access(MemCmd cmd,	// Read or Write access cmd
250               Addr addr,	// virtual address of access
251               void *p,		// input/output buffer
252               int nbytes);	// access size
253#endif
254
255    void
256    trace_mem(Fault fault,      // last fault
257              MemCmd cmd,       // last command
258              Addr addr,        // virtual address of access
259              void *p,          // memory accessed
260              int nbytes);      // access size
261
262    /** Dumps out contents of this BaseDynInst. */
263    void dump();
264
265    /** Dumps out contents of this BaseDynInst into given string. */
266    void dump(std::string &outstring);
267
268    /** Returns the fault type. */
269    Fault getFault() { return fault; }
270
271    /** Checks whether or not this instruction has had its branch target
272     *  calculated yet.  For now it is not utilized and is hacked to be
273     *  always false.
274     */
275    bool doneTargCalc() { return false; }
276
277    /** Returns the calculated target of the branch. */
278    Addr readCalcTarg() { return nextPC; }
279
280    Addr readNextPC() { return nextPC; }
281
282    /** Set the predicted target of this current instruction. */
283    void setPredTarg(Addr predicted_PC) { predPC = predicted_PC; }
284
285    /** Returns the predicted target of the branch. */
286    Addr readPredTarg() { return predPC; }
287
288    /** Returns whether the instruction was predicted taken or not. */
289    bool predTaken() {
290//        DPRINTF(FullCPU, "PC: %08p\n", PC);
291//        DPRINTF(FullCPU, "predPC: %08p\n", predPC);
292
293        return( predPC != (PC + sizeof(MachInst) ) );
294    }
295
296    /** Returns whether the instruction mispredicted. */
297    bool mispredicted() { return (predPC != nextPC); }
298
299    //
300    //  Instruction types.  Forward checks to StaticInst object.
301    //
302    bool isNop()	  const { return staticInst->isNop(); }
303    bool isMemRef()    	  const { return staticInst->isMemRef(); }
304    bool isLoad()	  const { return staticInst->isLoad(); }
305    bool isStore()	  const { return staticInst->isStore(); }
306    bool isInstPrefetch() const { return staticInst->isInstPrefetch(); }
307    bool isDataPrefetch() const { return staticInst->isDataPrefetch(); }
308    bool isCopy()         const { return staticInst->isCopy(); }
309    bool isInteger()	  const { return staticInst->isInteger(); }
310    bool isFloating()	  const { return staticInst->isFloating(); }
311    bool isControl()	  const { return staticInst->isControl(); }
312    bool isCall()	  const { return staticInst->isCall(); }
313    bool isReturn()	  const { return staticInst->isReturn(); }
314    bool isDirectCtrl()	  const { return staticInst->isDirectCtrl(); }
315    bool isIndirectCtrl() const { return staticInst->isIndirectCtrl(); }
316    bool isCondCtrl()	  const { return staticInst->isCondCtrl(); }
317    bool isUncondCtrl()	  const { return staticInst->isUncondCtrl(); }
318    bool isThreadSync()   const { return staticInst->isThreadSync(); }
319    bool isSerializing()  const { return staticInst->isSerializing(); }
320    bool isMemBarrier()   const { return staticInst->isMemBarrier(); }
321    bool isWriteBarrier() const { return staticInst->isWriteBarrier(); }
322    bool isNonSpeculative() const { return staticInst->isNonSpeculative(); }
323
324    int8_t numSrcRegs()	 const { return staticInst->numSrcRegs(); }
325    int8_t numDestRegs() const { return staticInst->numDestRegs(); }
326
327    // the following are used to track physical register usage
328    // for machines with separate int & FP reg files
329    int8_t numFPDestRegs()  const { return staticInst->numFPDestRegs(); }
330    int8_t numIntDestRegs() const { return staticInst->numIntDestRegs(); }
331
332    /** Returns the logical register index of the i'th destination register. */
333    RegIndex destRegIdx(int i) const
334    {
335        return staticInst->destRegIdx(i);
336    }
337
338    /** Returns the logical register index of the i'th source register. */
339    RegIndex srcRegIdx(int i) const
340    {
341        return staticInst->srcRegIdx(i);
342    }
343
344    /** Returns the physical register index of the i'th destination
345     *  register.
346     */
347    PhysRegIndex renamedDestRegIdx(int idx) const
348    {
349        return _destRegIdx[idx];
350    }
351
352    /** Returns the physical register index of the i'th source register. */
353    PhysRegIndex renamedSrcRegIdx(int idx) const
354    {
355        return _srcRegIdx[idx];
356    }
357
358    bool isReadySrcRegIdx(int idx) const
359    {
360        return _readySrcRegIdx[idx];
361    }
362
363    /** Returns the physical register index of the previous physical register
364     *  that remapped to the same logical register index.
365     */
366    PhysRegIndex prevDestRegIdx(int idx) const
367    {
368        return _prevDestRegIdx[idx];
369    }
370
371    /** Renames a destination register to a physical register.  Also records
372     *  the previous physical register that the logical register mapped to.
373     */
374    void renameDestReg(int idx,
375                       PhysRegIndex renamed_dest,
376                       PhysRegIndex previous_rename)
377    {
378        _destRegIdx[idx] = renamed_dest;
379        _prevDestRegIdx[idx] = previous_rename;
380    }
381
382    /** Renames a source logical register to the physical register which
383     *  has/will produce that logical register's result.
384     *  @todo: add in whether or not the source register is ready.
385     */
386    void renameSrcReg(int idx, PhysRegIndex renamed_src)
387    {
388        _srcRegIdx[idx] = renamed_src;
389    }
390
391    //Push to .cc file.
392    /** Records that one of the source registers is ready. */
393    void markSrcRegReady()
394    {
395        ++readyRegs;
396        if(readyRegs == numSrcRegs()) {
397            canIssue = true;
398        }
399    }
400
401    void markSrcRegReady(RegIndex src_idx)
402    {
403        ++readyRegs;
404
405        _readySrcRegIdx[src_idx] = 1;
406
407        if(readyRegs == numSrcRegs()) {
408            canIssue = true;
409        }
410    }
411
412    /** Sets this instruction as ready to issue. */
413    void setCanIssue() { canIssue = true; }
414
415    /** Returns whether or not this instruction is ready to issue. */
416    bool readyToIssue() const { return canIssue; }
417
418    /** Sets this instruction as issued from the IQ. */
419    void setIssued() { issued = true; }
420
421    /** Returns whether or not this instruction has issued. */
422    bool isIssued() { return issued; }
423
424    /** Sets this instruction as executed. */
425    void setExecuted() { executed = true; }
426
427    /** Returns whether or not this instruction has executed. */
428    bool isExecuted() { return executed; }
429
430    /** Sets this instruction as ready to commit. */
431    void setCanCommit() { canCommit = true; }
432
433    /** Clears this instruction as being ready to commit. */
434    void clearCanCommit() { canCommit = false; }
435
436    /** Returns whether or not this instruction is ready to commit. */
437    bool readyToCommit() const { return canCommit; }
438
439    /** Sets this instruction as squashed. */
440    void setSquashed() { squashed = true; }
441
442    /** Returns whether or not this instruction is squashed. */
443    bool isSquashed() const { return squashed; }
444
445    /** Sets this instruction as squashed in the IQ. */
446    void setSquashedInIQ() { squashedInIQ = true; }
447
448    /** Returns whether or not this instruction is squashed in the IQ. */
449    bool isSquashedInIQ() { return squashedInIQ; }
450
451    /** Returns the opclass of this instruction. */
452    OpClass opClass() const { return staticInst->opClass(); }
453
454    /** Returns whether or not the BTB missed. */
455    bool btbMiss() const { return btbMissed; }
456
457    /** Returns the branch target address. */
458    Addr branchTarget() const { return staticInst->branchTarget(PC); }
459
460    // The register accessor methods provide the index of the
461    // instruction's operand (e.g., 0 or 1), not the architectural
462    // register index, to simplify the implementation of register
463    // renaming.  We find the architectural register index by indexing
464    // into the instruction's own operand index table.  Note that a
465    // raw pointer to the StaticInst is provided instead of a
466    // ref-counted StaticInstPtr to redice overhead.  This is fine as
467    // long as these methods don't copy the pointer into any long-term
468    // storage (which is pretty hard to imagine they would have reason
469    // to do).
470
471    uint64_t readIntReg(StaticInst<ISA> *si, int idx)
472    {
473        return cpu->readIntReg(_srcRegIdx[idx]);
474    }
475
476    float readFloatRegSingle(StaticInst<ISA> *si, int idx)
477    {
478        return cpu->readFloatRegSingle(_srcRegIdx[idx]);
479    }
480
481    double readFloatRegDouble(StaticInst<ISA> *si, int idx)
482    {
483        return cpu->readFloatRegDouble(_srcRegIdx[idx]);
484    }
485
486    uint64_t readFloatRegInt(StaticInst<ISA> *si, int idx)
487    {
488        return cpu->readFloatRegInt(_srcRegIdx[idx]);
489    }
490    /** @todo: Make results into arrays so they can handle multiple dest
491     *  registers.
492     */
493    void setIntReg(StaticInst<ISA> *si, int idx, uint64_t val)
494    {
495        cpu->setIntReg(_destRegIdx[idx], val);
496        intResult = val;
497    }
498
499    void setFloatRegSingle(StaticInst<ISA> *si, int idx, float val)
500    {
501        cpu->setFloatRegSingle(_destRegIdx[idx], val);
502        floatResult = val;
503    }
504
505    void setFloatRegDouble(StaticInst<ISA> *si, int idx, double val)
506    {
507        cpu->setFloatRegDouble(_destRegIdx[idx], val);
508        doubleResult = val;
509    }
510
511    void setFloatRegInt(StaticInst<ISA> *si, int idx, uint64_t val)
512    {
513        cpu->setFloatRegInt(_destRegIdx[idx], val);
514        intResult = val;
515    }
516
517    /** Read the PC of this instruction. */
518    Addr readPC() { return PC; }
519
520    /** Set the next PC of this instruction (its actual target). */
521    void setNextPC(uint64_t val) { nextPC = val; }
522
523//    bool misspeculating() { return cpu->misspeculating(); }
524    ExecContext *xcBase() { return xc; }
525};
526
527template<class Impl>
528template<class T>
529inline Fault
530BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
531{
532    MemReqPtr req = new MemReq(addr, xc, sizeof(T), flags);
533    req->asid = asid;
534
535    fault = cpu->translateDataReadReq(req);
536
537    // Record key MemReq parameters so we can generate another one
538    // just like it for the timing access without calling translate()
539    // again (which might mess up the TLB).
540    effAddr = req->vaddr;
541    physEffAddr = req->paddr;
542    memReqFlags = req->flags;
543
544    /**
545     * @todo
546     * Replace the disjoint functional memory with a unified one and remove
547     * this hack.
548     */
549#ifndef FULL_SYSTEM
550    req->paddr = req->vaddr;
551#endif
552
553    if (fault == No_Fault) {
554        fault = cpu->read(req, data);
555    }
556    else {
557        // Return a fixed value to keep simulation deterministic even
558        // along misspeculated paths.
559        data = (T)-1;
560    }
561
562    if (traceData) {
563        traceData->setAddr(addr);
564        traceData->setData(data);
565    }
566
567    return fault;
568}
569
570template<class Impl>
571template<class T>
572inline Fault
573BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res)
574{
575    if (traceData) {
576        traceData->setAddr(addr);
577        traceData->setData(data);
578    }
579
580    storeSize = sizeof(T);
581    storeData = data;
582    if (specMode)
583        specMemWrite = true;
584
585    MemReqPtr req = new MemReq(addr, xc, sizeof(T), flags);
586
587    req->asid = asid;
588
589    fault = cpu->translateDataWriteReq(req);
590
591    // Record key MemReq parameters so we can generate another one
592    // just like it for the timing access without calling translate()
593    // again (which might mess up the TLB).
594    effAddr = req->vaddr;
595    physEffAddr = req->paddr;
596    memReqFlags = req->flags;
597
598    /**
599     * @todo
600     * Replace the disjoint functional memory with a unified one and remove
601     * this hack.
602     */
603#ifndef FULL_SYSTEM
604    req->paddr = req->vaddr;
605#endif
606
607    if (fault == No_Fault) {
608        fault = cpu->write(req, data);
609    }
610
611    if (res) {
612        // always return some result to keep misspeculated paths
613        // (which will ignore faults) deterministic
614        *res = (fault == No_Fault) ? req->result : 0;
615    }
616
617    return fault;
618}
619
620#endif // __DYN_INST_HH__
621