base_dyn_inst.hh revision 1060
1/*
2 * Copyright (c) 2001-2004 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 __BASE_DYN_INST_HH__
30#define __BASE_DYN_INST_HH__
31
32#include <vector>
33#include <string>
34
35#include "base/fast_alloc.hh"
36#include "base/trace.hh"
37
38#include "cpu/static_inst.hh"
39#include "cpu/beta_cpu/comm.hh"
40#include "cpu/full_cpu/bpred_update.hh"
41#include "mem/functional_mem/main_memory.hh"
42#include "cpu/full_cpu/spec_memory.hh"
43#include "cpu/inst_seq.hh"
44#include "cpu/full_cpu/op_class.hh"
45#include "cpu/full_cpu/spec_state.hh"
46
47/**
48 * @file
49 * Defines a dynamic instruction context.
50 */
51
52namespace Trace {
53    class InstRecord;
54};
55
56class BaseInst
57{
58};
59
60template <class Impl>
61class BaseDynInst : public FastAlloc
62{
63  public:
64    // 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    /** Returns whether or not this instruction is ready to commit. */
434    bool readyToCommit() const { return canCommit; }
435
436    /** Sets this instruction as squashed. */
437    void setSquashed() { squashed = true; }
438
439    /** Returns whether or not this instruction is squashed. */
440    bool isSquashed() const { return squashed; }
441
442    /** Sets this instruction as squashed in the IQ. */
443    void setSquashedInIQ() { squashedInIQ = true; }
444
445    /** Returns whether or not this instruction is squashed in the IQ. */
446    bool isSquashedInIQ() { return squashedInIQ; }
447
448    /** Returns the opclass of this instruction. */
449    OpClass opClass() const { return staticInst->opClass(); }
450
451    /** Returns whether or not the BTB missed. */
452    bool btbMiss() const { return btbMissed; }
453
454    /** Returns the branch target address. */
455    Addr branchTarget() const { return staticInst->branchTarget(PC); }
456
457    // The register accessor methods provide the index of the
458    // instruction's operand (e.g., 0 or 1), not the architectural
459    // register index, to simplify the implementation of register
460    // renaming.  We find the architectural register index by indexing
461    // into the instruction's own operand index table.  Note that a
462    // raw pointer to the StaticInst is provided instead of a
463    // ref-counted StaticInstPtr to redice overhead.  This is fine as
464    // long as these methods don't copy the pointer into any long-term
465    // storage (which is pretty hard to imagine they would have reason
466    // to do).
467
468    uint64_t readIntReg(StaticInst<ISA> *si, int idx)
469    {
470        return cpu->readIntReg(_srcRegIdx[idx]);
471    }
472
473    float readFloatRegSingle(StaticInst<ISA> *si, int idx)
474    {
475        return cpu->readFloatRegSingle(_srcRegIdx[idx]);
476    }
477
478    double readFloatRegDouble(StaticInst<ISA> *si, int idx)
479    {
480        return cpu->readFloatRegDouble(_srcRegIdx[idx]);
481    }
482
483    uint64_t readFloatRegInt(StaticInst<ISA> *si, int idx)
484    {
485        return cpu->readFloatRegInt(_srcRegIdx[idx]);
486    }
487    /** @todo: Make results into arrays so they can handle multiple dest
488     *  registers.
489     */
490    void setIntReg(StaticInst<ISA> *si, int idx, uint64_t val)
491    {
492        cpu->setIntReg(_destRegIdx[idx], val);
493        intResult = val;
494    }
495
496    void setFloatRegSingle(StaticInst<ISA> *si, int idx, float val)
497    {
498        cpu->setFloatRegSingle(_destRegIdx[idx], val);
499        floatResult = val;
500    }
501
502    void setFloatRegDouble(StaticInst<ISA> *si, int idx, double val)
503    {
504        cpu->setFloatRegDouble(_destRegIdx[idx], val);
505        doubleResult = val;
506    }
507
508    void setFloatRegInt(StaticInst<ISA> *si, int idx, uint64_t val)
509    {
510        cpu->setFloatRegInt(_destRegIdx[idx], val);
511        intResult = val;
512    }
513
514    /** Read the PC of this instruction. */
515    Addr readPC() { return PC; }
516
517    /** Set the next PC of this instruction (its actual target). */
518    void setNextPC(uint64_t val) { nextPC = val; }
519
520//    bool misspeculating() { return cpu->misspeculating(); }
521    ExecContext *xcBase() { return xc; }
522};
523
524template<class Impl>
525template<class T>
526inline Fault
527BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
528{
529    MemReqPtr req = new MemReq(addr, xc, sizeof(T), flags);
530    req->asid = asid;
531
532    fault = cpu->translateDataReadReq(req);
533
534    // Record key MemReq parameters so we can generate another one
535    // just like it for the timing access without calling translate()
536    // again (which might mess up the TLB).
537    effAddr = req->vaddr;
538    physEffAddr = req->paddr;
539    memReqFlags = req->flags;
540
541    /**
542     * @todo
543     * Replace the disjoint functional memory with a unified one and remove
544     * this hack.
545     */
546#ifndef FULL_SYSTEM
547    req->paddr = req->vaddr;
548#endif
549
550    if (fault == No_Fault) {
551        fault = cpu->read(req, data);
552    }
553    else {
554        // Return a fixed value to keep simulation deterministic even
555        // along misspeculated paths.
556        data = (T)-1;
557    }
558
559    if (traceData) {
560        traceData->setAddr(addr);
561        traceData->setData(data);
562    }
563
564    return fault;
565}
566
567template<class Impl>
568template<class T>
569inline Fault
570BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res)
571{
572    if (traceData) {
573        traceData->setAddr(addr);
574        traceData->setData(data);
575    }
576
577    storeSize = sizeof(T);
578    storeData = data;
579    if (specMode)
580        specMemWrite = true;
581
582    MemReqPtr req = new MemReq(addr, xc, sizeof(T), flags);
583
584    req->asid = asid;
585
586    fault = cpu->translateDataWriteReq(req);
587
588    // Record key MemReq parameters so we can generate another one
589    // just like it for the timing access without calling translate()
590    // again (which might mess up the TLB).
591    effAddr = req->vaddr;
592    physEffAddr = req->paddr;
593    memReqFlags = req->flags;
594
595    /**
596     * @todo
597     * Replace the disjoint functional memory with a unified one and remove
598     * this hack.
599     */
600#ifndef FULL_SYSTEM
601    req->paddr = req->vaddr;
602#endif
603
604    if (fault == No_Fault) {
605        fault = cpu->write(req, data);
606    }
607
608    if (res) {
609        // always return some result to keep misspeculated paths
610        // (which will ignore faults) deterministic
611        *res = (fault == No_Fault) ? req->result : 0;
612    }
613
614    return fault;
615}
616
617#endif // __DYN_INST_HH__
618