gpu_dyn_inst.hh revision 12697
111308Santhony.gutierrez@amd.com/*
212697Santhony.gutierrez@amd.com * Copyright (c) 2015-2017 Advanced Micro Devices, Inc.
311308Santhony.gutierrez@amd.com * All rights reserved.
411308Santhony.gutierrez@amd.com *
511308Santhony.gutierrez@amd.com * For use for simulation and test purposes only
611308Santhony.gutierrez@amd.com *
711308Santhony.gutierrez@amd.com * Redistribution and use in source and binary forms, with or without
811308Santhony.gutierrez@amd.com * modification, are permitted provided that the following conditions are met:
911308Santhony.gutierrez@amd.com *
1011308Santhony.gutierrez@amd.com * 1. Redistributions of source code must retain the above copyright notice,
1111308Santhony.gutierrez@amd.com * this list of conditions and the following disclaimer.
1211308Santhony.gutierrez@amd.com *
1311308Santhony.gutierrez@amd.com * 2. Redistributions in binary form must reproduce the above copyright notice,
1411308Santhony.gutierrez@amd.com * this list of conditions and the following disclaimer in the documentation
1511308Santhony.gutierrez@amd.com * and/or other materials provided with the distribution.
1611308Santhony.gutierrez@amd.com *
1712697Santhony.gutierrez@amd.com * 3. Neither the name of the copyright holder nor the names of its
1812697Santhony.gutierrez@amd.com * contributors may be used to endorse or promote products derived from this
1912697Santhony.gutierrez@amd.com * software without specific prior written permission.
2011308Santhony.gutierrez@amd.com *
2111308Santhony.gutierrez@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2211308Santhony.gutierrez@amd.com * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2311308Santhony.gutierrez@amd.com * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2411308Santhony.gutierrez@amd.com * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
2511308Santhony.gutierrez@amd.com * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2611308Santhony.gutierrez@amd.com * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2711308Santhony.gutierrez@amd.com * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2811308Santhony.gutierrez@amd.com * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2911308Santhony.gutierrez@amd.com * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3011308Santhony.gutierrez@amd.com * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3111308Santhony.gutierrez@amd.com * POSSIBILITY OF SUCH DAMAGE.
3211308Santhony.gutierrez@amd.com *
3312697Santhony.gutierrez@amd.com * Authors: Anthony Gutierrez
3411308Santhony.gutierrez@amd.com */
3511308Santhony.gutierrez@amd.com
3611308Santhony.gutierrez@amd.com#ifndef __GPU_DYN_INST_HH__
3711308Santhony.gutierrez@amd.com#define __GPU_DYN_INST_HH__
3811308Santhony.gutierrez@amd.com
3911308Santhony.gutierrez@amd.com#include <cstdint>
4011308Santhony.gutierrez@amd.com#include <string>
4111308Santhony.gutierrez@amd.com
4211308Santhony.gutierrez@amd.com#include "enums/MemType.hh"
4311308Santhony.gutierrez@amd.com#include "enums/StorageClassType.hh"
4411308Santhony.gutierrez@amd.com#include "gpu-compute/compute_unit.hh"
4511308Santhony.gutierrez@amd.com#include "gpu-compute/gpu_exec_context.hh"
4611308Santhony.gutierrez@amd.com
4711308Santhony.gutierrez@amd.comclass GPUStaticInst;
4811308Santhony.gutierrez@amd.com
4911308Santhony.gutierrez@amd.comtemplate<typename T>
5011308Santhony.gutierrez@amd.comclass AtomicOpAnd : public TypedAtomicOpFunctor<T>
5111308Santhony.gutierrez@amd.com{
5211308Santhony.gutierrez@amd.com  public:
5311308Santhony.gutierrez@amd.com    T a;
5411308Santhony.gutierrez@amd.com
5511308Santhony.gutierrez@amd.com    AtomicOpAnd(T _a) : a(_a) { }
5611308Santhony.gutierrez@amd.com    void execute(T *b) { *b &= a; }
5711308Santhony.gutierrez@amd.com};
5811308Santhony.gutierrez@amd.com
5911308Santhony.gutierrez@amd.comtemplate<typename T>
6011308Santhony.gutierrez@amd.comclass AtomicOpOr : public TypedAtomicOpFunctor<T>
6111308Santhony.gutierrez@amd.com{
6211308Santhony.gutierrez@amd.com  public:
6311308Santhony.gutierrez@amd.com    T a;
6411308Santhony.gutierrez@amd.com    AtomicOpOr(T _a) : a(_a) { }
6511308Santhony.gutierrez@amd.com    void execute(T *b) { *b |= a; }
6611308Santhony.gutierrez@amd.com};
6711308Santhony.gutierrez@amd.com
6811308Santhony.gutierrez@amd.comtemplate<typename T>
6911308Santhony.gutierrez@amd.comclass AtomicOpXor : public TypedAtomicOpFunctor<T>
7011308Santhony.gutierrez@amd.com{
7111308Santhony.gutierrez@amd.com  public:
7211308Santhony.gutierrez@amd.com    T a;
7311308Santhony.gutierrez@amd.com    AtomicOpXor(T _a) : a(_a) {}
7411308Santhony.gutierrez@amd.com    void execute(T *b) { *b ^= a; }
7511308Santhony.gutierrez@amd.com};
7611308Santhony.gutierrez@amd.com
7711308Santhony.gutierrez@amd.comtemplate<typename T>
7811308Santhony.gutierrez@amd.comclass AtomicOpCAS : public TypedAtomicOpFunctor<T>
7911308Santhony.gutierrez@amd.com{
8011308Santhony.gutierrez@amd.com  public:
8111308Santhony.gutierrez@amd.com    T c;
8211308Santhony.gutierrez@amd.com    T s;
8311308Santhony.gutierrez@amd.com
8411308Santhony.gutierrez@amd.com    ComputeUnit *computeUnit;
8511308Santhony.gutierrez@amd.com
8611308Santhony.gutierrez@amd.com    AtomicOpCAS(T _c, T _s, ComputeUnit *compute_unit)
8711308Santhony.gutierrez@amd.com      : c(_c), s(_s), computeUnit(compute_unit) { }
8811308Santhony.gutierrez@amd.com
8911308Santhony.gutierrez@amd.com    void
9011308Santhony.gutierrez@amd.com    execute(T *b)
9111308Santhony.gutierrez@amd.com    {
9211308Santhony.gutierrez@amd.com        computeUnit->numCASOps++;
9311308Santhony.gutierrez@amd.com
9411308Santhony.gutierrez@amd.com        if (*b == c) {
9511308Santhony.gutierrez@amd.com            *b = s;
9611308Santhony.gutierrez@amd.com        } else {
9711308Santhony.gutierrez@amd.com            computeUnit->numFailedCASOps++;
9811308Santhony.gutierrez@amd.com        }
9911308Santhony.gutierrez@amd.com
10011308Santhony.gutierrez@amd.com        if (computeUnit->xact_cas_mode) {
10111308Santhony.gutierrez@amd.com            computeUnit->xactCasLoadMap.clear();
10211308Santhony.gutierrez@amd.com        }
10311308Santhony.gutierrez@amd.com    }
10411308Santhony.gutierrez@amd.com};
10511308Santhony.gutierrez@amd.com
10611308Santhony.gutierrez@amd.comtemplate<typename T>
10711308Santhony.gutierrez@amd.comclass AtomicOpExch : public TypedAtomicOpFunctor<T>
10811308Santhony.gutierrez@amd.com{
10911308Santhony.gutierrez@amd.com  public:
11011308Santhony.gutierrez@amd.com    T a;
11111308Santhony.gutierrez@amd.com    AtomicOpExch(T _a) : a(_a) { }
11211308Santhony.gutierrez@amd.com    void execute(T *b) { *b = a; }
11311308Santhony.gutierrez@amd.com};
11411308Santhony.gutierrez@amd.com
11511308Santhony.gutierrez@amd.comtemplate<typename T>
11611308Santhony.gutierrez@amd.comclass AtomicOpAdd : public TypedAtomicOpFunctor<T>
11711308Santhony.gutierrez@amd.com{
11811308Santhony.gutierrez@amd.com  public:
11911308Santhony.gutierrez@amd.com    T a;
12011308Santhony.gutierrez@amd.com    AtomicOpAdd(T _a) : a(_a) { }
12111308Santhony.gutierrez@amd.com    void execute(T *b) { *b += a; }
12211308Santhony.gutierrez@amd.com};
12311308Santhony.gutierrez@amd.com
12411308Santhony.gutierrez@amd.comtemplate<typename T>
12511308Santhony.gutierrez@amd.comclass AtomicOpSub : public TypedAtomicOpFunctor<T>
12611308Santhony.gutierrez@amd.com{
12711308Santhony.gutierrez@amd.com  public:
12811308Santhony.gutierrez@amd.com    T a;
12911308Santhony.gutierrez@amd.com    AtomicOpSub(T _a) : a(_a) { }
13011308Santhony.gutierrez@amd.com    void execute(T *b) { *b -= a; }
13111308Santhony.gutierrez@amd.com};
13211308Santhony.gutierrez@amd.com
13311308Santhony.gutierrez@amd.comtemplate<typename T>
13411308Santhony.gutierrez@amd.comclass AtomicOpInc : public TypedAtomicOpFunctor<T>
13511308Santhony.gutierrez@amd.com{
13611308Santhony.gutierrez@amd.com  public:
13711308Santhony.gutierrez@amd.com    AtomicOpInc() { }
13811308Santhony.gutierrez@amd.com    void execute(T *b) { *b += 1; }
13911308Santhony.gutierrez@amd.com};
14011308Santhony.gutierrez@amd.com
14111308Santhony.gutierrez@amd.comtemplate<typename T>
14211308Santhony.gutierrez@amd.comclass AtomicOpDec : public TypedAtomicOpFunctor<T>
14311308Santhony.gutierrez@amd.com{
14411308Santhony.gutierrez@amd.com  public:
14511308Santhony.gutierrez@amd.com    AtomicOpDec() {}
14611308Santhony.gutierrez@amd.com    void execute(T *b) { *b -= 1; }
14711308Santhony.gutierrez@amd.com};
14811308Santhony.gutierrez@amd.com
14911308Santhony.gutierrez@amd.comtemplate<typename T>
15011308Santhony.gutierrez@amd.comclass AtomicOpMax : public TypedAtomicOpFunctor<T>
15111308Santhony.gutierrez@amd.com{
15211308Santhony.gutierrez@amd.com  public:
15311308Santhony.gutierrez@amd.com    T a;
15411308Santhony.gutierrez@amd.com    AtomicOpMax(T _a) : a(_a) { }
15511308Santhony.gutierrez@amd.com
15611308Santhony.gutierrez@amd.com    void
15711308Santhony.gutierrez@amd.com    execute(T *b)
15811308Santhony.gutierrez@amd.com    {
15911308Santhony.gutierrez@amd.com        if (a > *b)
16011308Santhony.gutierrez@amd.com            *b = a;
16111308Santhony.gutierrez@amd.com    }
16211308Santhony.gutierrez@amd.com};
16311308Santhony.gutierrez@amd.com
16411308Santhony.gutierrez@amd.comtemplate<typename T>
16511308Santhony.gutierrez@amd.comclass AtomicOpMin : public TypedAtomicOpFunctor<T>
16611308Santhony.gutierrez@amd.com{
16711308Santhony.gutierrez@amd.com  public:
16811308Santhony.gutierrez@amd.com    T a;
16911308Santhony.gutierrez@amd.com    AtomicOpMin(T _a) : a(_a) {}
17011308Santhony.gutierrez@amd.com
17111308Santhony.gutierrez@amd.com    void
17211308Santhony.gutierrez@amd.com    execute(T *b)
17311308Santhony.gutierrez@amd.com    {
17411308Santhony.gutierrez@amd.com        if (a < *b)
17511308Santhony.gutierrez@amd.com            *b = a;
17611308Santhony.gutierrez@amd.com    }
17711308Santhony.gutierrez@amd.com};
17811308Santhony.gutierrez@amd.com
17911308Santhony.gutierrez@amd.comtypedef enum
18011308Santhony.gutierrez@amd.com{
18111308Santhony.gutierrez@amd.com    VT_32,
18211308Santhony.gutierrez@amd.com    VT_64,
18311308Santhony.gutierrez@amd.com} vgpr_type;
18411308Santhony.gutierrez@amd.com
18511308Santhony.gutierrez@amd.comclass GPUDynInst : public GPUExecContext
18611308Santhony.gutierrez@amd.com{
18711308Santhony.gutierrez@amd.com  public:
18811692Santhony.gutierrez@amd.com    GPUDynInst(ComputeUnit *_cu, Wavefront *_wf, GPUStaticInst *static_inst,
18911308Santhony.gutierrez@amd.com               uint64_t instSeqNum);
19011534Sjohn.kalamatianos@amd.com    ~GPUDynInst();
19111692Santhony.gutierrez@amd.com    void execute(GPUDynInstPtr gpuDynInst);
19211308Santhony.gutierrez@amd.com    int numSrcRegOperands();
19311308Santhony.gutierrez@amd.com    int numDstRegOperands();
19411308Santhony.gutierrez@amd.com    int getNumOperands();
19511308Santhony.gutierrez@amd.com    bool isVectorRegister(int operandIdx);
19611308Santhony.gutierrez@amd.com    bool isScalarRegister(int operandIdx);
19711699Santhony.gutierrez@amd.com    bool isCondRegister(int operandIdx);
19811699Santhony.gutierrez@amd.com    int getRegisterIndex(int operandIdx, GPUDynInstPtr gpuDynInst);
19911308Santhony.gutierrez@amd.com    int getOperandSize(int operandIdx);
20011308Santhony.gutierrez@amd.com    bool isDstOperand(int operandIdx);
20111308Santhony.gutierrez@amd.com    bool isSrcOperand(int operandIdx);
20211308Santhony.gutierrez@amd.com
20311308Santhony.gutierrez@amd.com    const std::string &disassemble() const;
20411308Santhony.gutierrez@amd.com
20511308Santhony.gutierrez@amd.com    uint64_t seqNum() const;
20611308Santhony.gutierrez@amd.com
20711308Santhony.gutierrez@amd.com    Enums::StorageClassType executedAs();
20811308Santhony.gutierrez@amd.com
20911308Santhony.gutierrez@amd.com    // The address of the memory operation
21011534Sjohn.kalamatianos@amd.com    std::vector<Addr> addr;
21111308Santhony.gutierrez@amd.com    Addr pAddr;
21211308Santhony.gutierrez@amd.com
21311308Santhony.gutierrez@amd.com    // The data to get written
21411534Sjohn.kalamatianos@amd.com    uint8_t *d_data;
21511308Santhony.gutierrez@amd.com    // Additional data (for atomics)
21611534Sjohn.kalamatianos@amd.com    uint8_t *a_data;
21711308Santhony.gutierrez@amd.com    // Additional data (for atomics)
21811534Sjohn.kalamatianos@amd.com    uint8_t *x_data;
21911308Santhony.gutierrez@amd.com    // The execution mask
22011308Santhony.gutierrez@amd.com    VectorMask exec_mask;
22111308Santhony.gutierrez@amd.com
22211308Santhony.gutierrez@amd.com    // The memory type (M_U32, M_S32, ...)
22311308Santhony.gutierrez@amd.com    Enums::MemType m_type;
22411308Santhony.gutierrez@amd.com
22511308Santhony.gutierrez@amd.com    // The equivalency class
22611308Santhony.gutierrez@amd.com    int equiv;
22711308Santhony.gutierrez@amd.com    // The return VGPR type (VT_32 or VT_64)
22811308Santhony.gutierrez@amd.com    vgpr_type v_type;
22911308Santhony.gutierrez@amd.com    // Number of VGPR's accessed (1, 2, or 4)
23011308Santhony.gutierrez@amd.com    int n_reg;
23111308Santhony.gutierrez@amd.com    // The return VGPR index
23211308Santhony.gutierrez@amd.com    int dst_reg;
23311308Santhony.gutierrez@amd.com    // There can be max 4 dest regs>
23411308Santhony.gutierrez@amd.com    int dst_reg_vec[4];
23511308Santhony.gutierrez@amd.com    // SIMD where the WF of the memory instruction has been mapped to
23611308Santhony.gutierrez@amd.com    int simdId;
23711308Santhony.gutierrez@amd.com    // unique id of the WF where the memory instruction belongs to
23811308Santhony.gutierrez@amd.com    int wfDynId;
23911308Santhony.gutierrez@amd.com    // The kernel id of the requesting wf
24011308Santhony.gutierrez@amd.com    int kern_id;
24111308Santhony.gutierrez@amd.com    // The CU id of the requesting wf
24211308Santhony.gutierrez@amd.com    int cu_id;
24311308Santhony.gutierrez@amd.com    // HW slot id where the WF is mapped to inside a SIMD unit
24411308Santhony.gutierrez@amd.com    int wfSlotId;
24511308Santhony.gutierrez@amd.com    // execution pipeline id where the memory instruction has been scheduled
24611308Santhony.gutierrez@amd.com    int pipeId;
24711308Santhony.gutierrez@amd.com    // The execution time of this operation
24811308Santhony.gutierrez@amd.com    Tick time;
24911308Santhony.gutierrez@amd.com    // The latency of this operation
25011308Santhony.gutierrez@amd.com    WaitClass latency;
25111308Santhony.gutierrez@amd.com    // A list of bank conflicts for the 4 cycles.
25211308Santhony.gutierrez@amd.com    uint32_t bc[4];
25311308Santhony.gutierrez@amd.com
25411308Santhony.gutierrez@amd.com    // A pointer to ROM
25511308Santhony.gutierrez@amd.com    uint8_t *rom;
25611308Santhony.gutierrez@amd.com    // The size of the READONLY segment
25711308Santhony.gutierrez@amd.com    int sz_rom;
25811308Santhony.gutierrez@amd.com
25911308Santhony.gutierrez@amd.com    // Initiate the specified memory operation, by creating a
26011308Santhony.gutierrez@amd.com    // memory request and sending it off to the memory system.
26111308Santhony.gutierrez@amd.com    void initiateAcc(GPUDynInstPtr gpuDynInst);
26211693Santhony.gutierrez@amd.com    // Complete the specified memory operation, by writing
26311693Santhony.gutierrez@amd.com    // value back to the RF in the case of a load or atomic
26411693Santhony.gutierrez@amd.com    // return or, in the case of a store, we do nothing
26511693Santhony.gutierrez@amd.com    void completeAcc(GPUDynInstPtr gpuDynInst);
26611308Santhony.gutierrez@amd.com
26711308Santhony.gutierrez@amd.com    void updateStats();
26811308Santhony.gutierrez@amd.com
26911692Santhony.gutierrez@amd.com    GPUStaticInst* staticInstruction() { return _staticInst; }
27011308Santhony.gutierrez@amd.com
27111692Santhony.gutierrez@amd.com    bool isALU() const;
27211692Santhony.gutierrez@amd.com    bool isBranch() const;
27311692Santhony.gutierrez@amd.com    bool isNop() const;
27411692Santhony.gutierrez@amd.com    bool isReturn() const;
27511692Santhony.gutierrez@amd.com    bool isUnconditionalJump() const;
27611692Santhony.gutierrez@amd.com    bool isSpecialOp() const;
27711692Santhony.gutierrez@amd.com    bool isWaitcnt() const;
27811692Santhony.gutierrez@amd.com
27911692Santhony.gutierrez@amd.com    bool isBarrier() const;
28011692Santhony.gutierrez@amd.com    bool isMemFence() const;
28111692Santhony.gutierrez@amd.com    bool isMemRef() const;
28211692Santhony.gutierrez@amd.com    bool isFlat() const;
28311692Santhony.gutierrez@amd.com    bool isLoad() const;
28411692Santhony.gutierrez@amd.com    bool isStore() const;
28511692Santhony.gutierrez@amd.com
28611692Santhony.gutierrez@amd.com    bool isAtomic() const;
28711692Santhony.gutierrez@amd.com    bool isAtomicNoRet() const;
28811692Santhony.gutierrez@amd.com    bool isAtomicRet() const;
28911692Santhony.gutierrez@amd.com
29011692Santhony.gutierrez@amd.com    bool isScalar() const;
29111692Santhony.gutierrez@amd.com    bool readsSCC() const;
29211692Santhony.gutierrez@amd.com    bool writesSCC() const;
29311692Santhony.gutierrez@amd.com    bool readsVCC() const;
29411692Santhony.gutierrez@amd.com    bool writesVCC() const;
29511692Santhony.gutierrez@amd.com
29611692Santhony.gutierrez@amd.com    bool isAtomicAnd() const;
29711692Santhony.gutierrez@amd.com    bool isAtomicOr() const;
29811692Santhony.gutierrez@amd.com    bool isAtomicXor() const;
29911692Santhony.gutierrez@amd.com    bool isAtomicCAS() const;
30011692Santhony.gutierrez@amd.com    bool isAtomicExch() const;
30111692Santhony.gutierrez@amd.com    bool isAtomicAdd() const;
30211692Santhony.gutierrez@amd.com    bool isAtomicSub() const;
30311692Santhony.gutierrez@amd.com    bool isAtomicInc() const;
30411692Santhony.gutierrez@amd.com    bool isAtomicDec() const;
30511692Santhony.gutierrez@amd.com    bool isAtomicMax() const;
30611692Santhony.gutierrez@amd.com    bool isAtomicMin() const;
30711692Santhony.gutierrez@amd.com
30811692Santhony.gutierrez@amd.com    bool isArgLoad() const;
30911692Santhony.gutierrez@amd.com    bool isGlobalMem() const;
31011692Santhony.gutierrez@amd.com    bool isLocalMem() const;
31111692Santhony.gutierrez@amd.com
31211692Santhony.gutierrez@amd.com    bool isArgSeg() const;
31311692Santhony.gutierrez@amd.com    bool isGlobalSeg() const;
31411692Santhony.gutierrez@amd.com    bool isGroupSeg() const;
31511692Santhony.gutierrez@amd.com    bool isKernArgSeg() const;
31611692Santhony.gutierrez@amd.com    bool isPrivateSeg() const;
31711692Santhony.gutierrez@amd.com    bool isReadOnlySeg() const;
31811692Santhony.gutierrez@amd.com    bool isSpillSeg() const;
31911692Santhony.gutierrez@amd.com
32011692Santhony.gutierrez@amd.com    bool isWorkitemScope() const;
32111692Santhony.gutierrez@amd.com    bool isWavefrontScope() const;
32211692Santhony.gutierrez@amd.com    bool isWorkgroupScope() const;
32311692Santhony.gutierrez@amd.com    bool isDeviceScope() const;
32411692Santhony.gutierrez@amd.com    bool isSystemScope() const;
32511692Santhony.gutierrez@amd.com    bool isNoScope() const;
32611692Santhony.gutierrez@amd.com
32711692Santhony.gutierrez@amd.com    bool isRelaxedOrder() const;
32811692Santhony.gutierrez@amd.com    bool isAcquire() const;
32911692Santhony.gutierrez@amd.com    bool isRelease() const;
33011692Santhony.gutierrez@amd.com    bool isAcquireRelease() const;
33111692Santhony.gutierrez@amd.com    bool isNoOrder() const;
33211692Santhony.gutierrez@amd.com
33311692Santhony.gutierrez@amd.com    bool isGloballyCoherent() const;
33411692Santhony.gutierrez@amd.com    bool isSystemCoherent() const;
33511308Santhony.gutierrez@amd.com
33611308Santhony.gutierrez@amd.com    /*
33711308Santhony.gutierrez@amd.com     * Loads/stores/atomics may have acquire/release semantics associated
33811308Santhony.gutierrez@amd.com     * withthem. Some protocols want to see the acquire/release as separate
33911308Santhony.gutierrez@amd.com     * requests from the load/store/atomic. We implement that separation
34011308Santhony.gutierrez@amd.com     * using continuations (i.e., a function pointer with an object associated
34111308Santhony.gutierrez@amd.com     * with it). When, for example, the front-end generates a store with
34211308Santhony.gutierrez@amd.com     * release semantics, we will first issue a normal store and set the
34311308Santhony.gutierrez@amd.com     * continuation in the GPUDynInst to a function that generate a
34411308Santhony.gutierrez@amd.com     * release request. That continuation will be called when the normal
34511308Santhony.gutierrez@amd.com     * store completes (in ComputeUnit::DataPort::recvTimingResponse). The
34611308Santhony.gutierrez@amd.com     * continuation will be called in the context of the same GPUDynInst
34711308Santhony.gutierrez@amd.com     * that generated the initial store.
34811308Santhony.gutierrez@amd.com     */
34911308Santhony.gutierrez@amd.com    std::function<void(GPUStaticInst*, GPUDynInstPtr)> execContinuation;
35011308Santhony.gutierrez@amd.com
35111308Santhony.gutierrez@amd.com    // when true, call execContinuation when response arrives
35211308Santhony.gutierrez@amd.com    bool useContinuation;
35311308Santhony.gutierrez@amd.com
35411308Santhony.gutierrez@amd.com    template<typename c0> AtomicOpFunctor*
35511692Santhony.gutierrez@amd.com    makeAtomicOpFunctor(c0 *reg0, c0 *reg1)
35611308Santhony.gutierrez@amd.com    {
35711692Santhony.gutierrez@amd.com        if (isAtomicAnd()) {
35811308Santhony.gutierrez@amd.com            return new AtomicOpAnd<c0>(*reg0);
35911692Santhony.gutierrez@amd.com        } else if (isAtomicOr()) {
36011308Santhony.gutierrez@amd.com            return new AtomicOpOr<c0>(*reg0);
36111692Santhony.gutierrez@amd.com        } else if (isAtomicXor()) {
36211308Santhony.gutierrez@amd.com            return new AtomicOpXor<c0>(*reg0);
36311692Santhony.gutierrez@amd.com        } else if (isAtomicCAS()) {
36411308Santhony.gutierrez@amd.com            return new AtomicOpCAS<c0>(*reg0, *reg1, cu);
36511692Santhony.gutierrez@amd.com        } else if (isAtomicExch()) {
36611308Santhony.gutierrez@amd.com            return new AtomicOpExch<c0>(*reg0);
36711692Santhony.gutierrez@amd.com        } else if (isAtomicAdd()) {
36811308Santhony.gutierrez@amd.com            return new AtomicOpAdd<c0>(*reg0);
36911692Santhony.gutierrez@amd.com        } else if (isAtomicSub()) {
37011308Santhony.gutierrez@amd.com            return new AtomicOpSub<c0>(*reg0);
37111692Santhony.gutierrez@amd.com        } else if (isAtomicInc()) {
37211308Santhony.gutierrez@amd.com            return new AtomicOpInc<c0>();
37311692Santhony.gutierrez@amd.com        } else if (isAtomicDec()) {
37411308Santhony.gutierrez@amd.com            return new AtomicOpDec<c0>();
37511692Santhony.gutierrez@amd.com        } else if (isAtomicMax()) {
37611308Santhony.gutierrez@amd.com            return new AtomicOpMax<c0>(*reg0);
37711692Santhony.gutierrez@amd.com        } else if (isAtomicMin()) {
37811308Santhony.gutierrez@amd.com            return new AtomicOpMin<c0>(*reg0);
37911692Santhony.gutierrez@amd.com        } else {
38011692Santhony.gutierrez@amd.com            fatal("Unrecognized atomic operation");
38111308Santhony.gutierrez@amd.com        }
38211308Santhony.gutierrez@amd.com    }
38311308Santhony.gutierrez@amd.com
38411308Santhony.gutierrez@amd.com    void
38511308Santhony.gutierrez@amd.com    setRequestFlags(Request *req, bool setMemOrder=true)
38611308Santhony.gutierrez@amd.com    {
38711308Santhony.gutierrez@amd.com        // currently these are the easy scopes to deduce
38811692Santhony.gutierrez@amd.com        if (isPrivateSeg()) {
38911308Santhony.gutierrez@amd.com            req->setMemSpaceConfigFlags(Request::PRIVATE_SEGMENT);
39011692Santhony.gutierrez@amd.com        } else if (isSpillSeg()) {
39111308Santhony.gutierrez@amd.com            req->setMemSpaceConfigFlags(Request::SPILL_SEGMENT);
39211692Santhony.gutierrez@amd.com        } else if (isGlobalSeg()) {
39311308Santhony.gutierrez@amd.com            req->setMemSpaceConfigFlags(Request::GLOBAL_SEGMENT);
39411692Santhony.gutierrez@amd.com        } else if (isReadOnlySeg()) {
39511308Santhony.gutierrez@amd.com            req->setMemSpaceConfigFlags(Request::READONLY_SEGMENT);
39611692Santhony.gutierrez@amd.com        } else if (isGroupSeg()) {
39711308Santhony.gutierrez@amd.com            req->setMemSpaceConfigFlags(Request::GROUP_SEGMENT);
39811692Santhony.gutierrez@amd.com        } else if (isFlat()) {
39911308Santhony.gutierrez@amd.com            // TODO: translate to correct scope
40011308Santhony.gutierrez@amd.com            assert(false);
40111692Santhony.gutierrez@amd.com        } else {
40211692Santhony.gutierrez@amd.com            fatal("%s has bad segment type\n", disassemble());
40311308Santhony.gutierrez@amd.com        }
40411308Santhony.gutierrez@amd.com
40511692Santhony.gutierrez@amd.com        if (isWavefrontScope()) {
40611308Santhony.gutierrez@amd.com            req->setMemSpaceConfigFlags(Request::SCOPE_VALID |
40711308Santhony.gutierrez@amd.com                                        Request::WAVEFRONT_SCOPE);
40811692Santhony.gutierrez@amd.com        } else if (isWorkgroupScope()) {
40911308Santhony.gutierrez@amd.com            req->setMemSpaceConfigFlags(Request::SCOPE_VALID |
41011308Santhony.gutierrez@amd.com                                        Request::WORKGROUP_SCOPE);
41111692Santhony.gutierrez@amd.com        } else if (isDeviceScope()) {
41211308Santhony.gutierrez@amd.com            req->setMemSpaceConfigFlags(Request::SCOPE_VALID |
41311308Santhony.gutierrez@amd.com                                        Request::DEVICE_SCOPE);
41411692Santhony.gutierrez@amd.com        } else if (isSystemScope()) {
41511308Santhony.gutierrez@amd.com            req->setMemSpaceConfigFlags(Request::SCOPE_VALID |
41611308Santhony.gutierrez@amd.com                                        Request::SYSTEM_SCOPE);
41711692Santhony.gutierrez@amd.com        } else if (!isNoScope() && !isWorkitemScope()) {
41811692Santhony.gutierrez@amd.com            fatal("%s has bad scope type\n", disassemble());
41911308Santhony.gutierrez@amd.com        }
42011308Santhony.gutierrez@amd.com
42111308Santhony.gutierrez@amd.com        if (setMemOrder) {
42211308Santhony.gutierrez@amd.com            // set acquire and release flags
42311692Santhony.gutierrez@amd.com            if (isAcquire()) {
42411308Santhony.gutierrez@amd.com                req->setFlags(Request::ACQUIRE);
42511692Santhony.gutierrez@amd.com            } else if (isRelease()) {
42611308Santhony.gutierrez@amd.com                req->setFlags(Request::RELEASE);
42711692Santhony.gutierrez@amd.com            } else if (isAcquireRelease()) {
42811308Santhony.gutierrez@amd.com                req->setFlags(Request::ACQUIRE | Request::RELEASE);
42911692Santhony.gutierrez@amd.com            } else if (!isNoOrder()) {
43011692Santhony.gutierrez@amd.com                fatal("%s has bad memory order\n", disassemble());
43111308Santhony.gutierrez@amd.com            }
43211308Santhony.gutierrez@amd.com        }
43311308Santhony.gutierrez@amd.com
43411308Santhony.gutierrez@amd.com        // set atomic type
43511308Santhony.gutierrez@amd.com        // currently, the instruction genenerator only produces atomic return
43611308Santhony.gutierrez@amd.com        // but a magic instruction can produce atomic no return
43711692Santhony.gutierrez@amd.com        if (isAtomicRet()) {
43811308Santhony.gutierrez@amd.com            req->setFlags(Request::ATOMIC_RETURN_OP);
43911692Santhony.gutierrez@amd.com        } else if (isAtomicNoRet()) {
44011308Santhony.gutierrez@amd.com            req->setFlags(Request::ATOMIC_NO_RETURN_OP);
44111308Santhony.gutierrez@amd.com        }
44211308Santhony.gutierrez@amd.com    }
44311308Santhony.gutierrez@amd.com
44411308Santhony.gutierrez@amd.com    // Map returned packets and the addresses they satisfy with which lane they
44511308Santhony.gutierrez@amd.com    // were requested from
44611308Santhony.gutierrez@amd.com    typedef std::unordered_map<Addr, std::vector<int>> StatusVector;
44711308Santhony.gutierrez@amd.com    StatusVector memStatusVector;
44811308Santhony.gutierrez@amd.com
44911308Santhony.gutierrez@amd.com    // Track the status of memory requests per lane, a bit per lane
45011308Santhony.gutierrez@amd.com    VectorMask statusBitVector;
45111308Santhony.gutierrez@amd.com    // for ld_v# or st_v#
45211308Santhony.gutierrez@amd.com    std::vector<int> statusVector;
45311308Santhony.gutierrez@amd.com    std::vector<int> tlbHitLevel;
45411308Santhony.gutierrez@amd.com
45511308Santhony.gutierrez@amd.com  private:
45611692Santhony.gutierrez@amd.com    GPUStaticInst *_staticInst;
45711308Santhony.gutierrez@amd.com    uint64_t _seqNum;
45811308Santhony.gutierrez@amd.com};
45911308Santhony.gutierrez@amd.com
46011308Santhony.gutierrez@amd.com#endif // __GPU_DYN_INST_HH__
461