diff options
| author | Mahmoud <[email protected]> | 2020-05-23 20:06:25 -0400 |
|---|---|---|
| committer | Mahmoud <[email protected]> | 2020-05-23 20:06:25 -0400 |
| commit | d610fd81420979e956bf37100f7e1c7f1d153831 (patch) | |
| tree | 392a841f21fec5136339ff36ad9b5c7b1b4cb480 /src/abstract_hardware_model.h | |
| parent | 6cedd3ef4973f3785757413db89a7c5d0ee2b58b (diff) | |
| parent | e9e9fcf5957530ecb927aecb5ea238e4b78a4f45 (diff) | |
Merge branch 'dev' of https://github.com/purdue-aalp/gpgpu-sim_distribution into dev-traces
Diffstat (limited to 'src/abstract_hardware_model.h')
| -rw-r--r-- | src/abstract_hardware_model.h | 2125 |
1 files changed, 1082 insertions, 1043 deletions
diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 6c19e2d..a640ba3 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -7,23 +7,24 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, this -// list of conditions and the following disclaimer in the documentation and/or -// other materials provided with the distribution. -// Neither the name of The University of British Columbia nor the names of its -// contributors may be used to endorse or promote products derived from this -// software without specific prior written permission. +// Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. Neither the name of +// The University of British Columbia nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. #ifndef ABSTRACT_HARDWARE_MODEL_INCLUDED #define ABSTRACT_HARDWARE_MODEL_INCLUDED @@ -33,35 +34,32 @@ class gpgpu_sim; class kernel_info_t; class gpgpu_context; - -//Set a hard limit of 32 CTAs per shader [cuda only has 8] +// Set a hard limit of 32 CTAs per shader [cuda only has 8] #define MAX_CTA_PER_SHADER 32 #define MAX_BARRIERS_PER_CTA 16 -//After expanding the vector input and output operands +// After expanding the vector input and output operands #define MAX_INPUT_VALUES 24 #define MAX_OUTPUT_VALUES 8 enum _memory_space_t { - undefined_space=0, - reg_space, - local_space, - shared_space, - sstarr_space, - param_space_unclassified, - param_space_kernel, /* global to all threads in a kernel : read-only */ - param_space_local, /* local to a thread : read-writable */ - const_space, - tex_space, - surf_space, - global_space, - generic_space, - instruction_space + undefined_space = 0, + reg_space, + local_space, + shared_space, + sstarr_space, + param_space_unclassified, + param_space_kernel, /* global to all threads in a kernel : read-only */ + param_space_local, /* local to a thread : read-writable */ + const_space, + tex_space, + surf_space, + global_space, + generic_space, + instruction_space }; - -enum FuncCache -{ +enum FuncCache { FuncCachePreferNone = 0, FuncCachePreferShared = 1, FuncCachePreferL1 = 2 @@ -75,8 +73,8 @@ enum AdaptiveCache #ifdef __cplusplus -#include <string.h> #include <stdio.h> +#include <string.h> #include <set> typedef unsigned long long new_addr_type; @@ -84,374 +82,360 @@ typedef unsigned long long cudaTextureObject_t; typedef unsigned address_type; typedef unsigned addr_t; -// the following are operations the timing model can see +// the following are operations the timing model can see enum uarch_op_t { - NO_OP=-1, - ALU_OP=1, - SFU_OP, - TENSOR_CORE_OP, - DP_OP, - SP_OP, - INTP_OP, - ALU_SFU_OP, - LOAD_OP, - TENSOR_CORE_LOAD_OP, - TENSOR_CORE_STORE_OP, - STORE_OP, - BRANCH_OP, - BARRIER_OP, - MEMORY_BARRIER_OP, - CALL_OPS, + NO_OP = -1, + ALU_OP = 1, + SFU_OP, + TENSOR_CORE_OP, + DP_OP, + SP_OP, + INTP_OP, + ALU_SFU_OP, + LOAD_OP, + TENSOR_CORE_LOAD_OP, + TENSOR_CORE_STORE_OP, + STORE_OP, + BRANCH_OP, + BARRIER_OP, + MEMORY_BARRIER_OP, + CALL_OPS, RET_OPS, EXIT_OPS }; typedef enum uarch_op_t op_type; - -enum uarch_bar_t { - NOT_BAR=-1, - SYNC=1, - ARRIVE, - RED -}; +enum uarch_bar_t { NOT_BAR = -1, SYNC = 1, ARRIVE, RED }; typedef enum uarch_bar_t barrier_type; -enum uarch_red_t { - NOT_RED=-1, - POPC_RED=1, - AND_RED, - OR_RED -}; +enum uarch_red_t { NOT_RED = -1, POPC_RED = 1, AND_RED, OR_RED }; typedef enum uarch_red_t reduction_type; - -enum uarch_operand_type_t { - UN_OP=-1, - INT_OP, - FP_OP -}; +enum uarch_operand_type_t { UN_OP = -1, INT_OP, FP_OP }; typedef enum uarch_operand_type_t types_of_operands; enum special_operations_t { - OTHER_OP, - INT__OP, - INT_MUL24_OP, - INT_MUL32_OP, - INT_MUL_OP, - INT_DIV_OP, - FP_MUL_OP, - FP_DIV_OP, - FP__OP, - FP_SQRT_OP, - FP_LG_OP, - FP_SIN_OP, - FP_EXP_OP + OTHER_OP, + INT__OP, + INT_MUL24_OP, + INT_MUL32_OP, + INT_MUL_OP, + INT_DIV_OP, + FP_MUL_OP, + FP_DIV_OP, + FP__OP, + FP_SQRT_OP, + FP_LG_OP, + FP_SIN_OP, + FP_EXP_OP }; -typedef enum special_operations_t special_ops; // Required to identify for the power model +typedef enum special_operations_t + special_ops; // Required to identify for the power model enum operation_pipeline_t { - UNKOWN_OP, - SP__OP, - DP__OP, - INTP__OP, - SFU__OP, - TENSOR_CORE__OP, - MEM__OP + UNKOWN_OP, + SP__OP, + DP__OP, + INTP__OP, + SFU__OP, + TENSOR_CORE__OP, + MEM__OP }; typedef enum operation_pipeline_t operation_pipeline; -enum mem_operation_t { - NOT_TEX, - TEX -}; +enum mem_operation_t { NOT_TEX, TEX }; typedef enum mem_operation_t mem_operation; -enum _memory_op_t { - no_memory_op = 0, - memory_load, - memory_store -}; +enum _memory_op_t { no_memory_op = 0, memory_load, memory_store }; -#include <bitset> -#include <list> -#include <vector> #include <assert.h> #include <stdlib.h> -#include <map> -#include <deque> #include <algorithm> +#include <bitset> +#include <deque> +#include <list> +#include <map> +#include <vector> #if !defined(__VECTOR_TYPES_H__) #include "vector_types.h" #endif struct dim3comp { - bool operator() (const dim3 & a, const dim3 & b) const - { - if(a.z < b.z) - return true; - else if(a.y < b.y) - return true; - else if (a.x < b.x) - return true; - else - return false; - } + bool operator()(const dim3 &a, const dim3 &b) const { + if (a.z < b.z) + return true; + else if (a.y < b.y) + return true; + else if (a.x < b.x) + return true; + else + return false; + } }; -void increment_x_then_y_then_z( dim3 &i, const dim3 &bound); +void increment_x_then_y_then_z(dim3 &i, const dim3 &bound); -//Jin: child kernel information for CDP +// Jin: child kernel information for CDP #include "stream_manager.h" class stream_manager; struct CUstream_st; -//extern stream_manager * g_stream_manager; -//support for pinned memories added -extern std::map<void *,void **> pinned_memory; +// extern stream_manager * g_stream_manager; +// support for pinned memories added +extern std::map<void *, void **> pinned_memory; extern std::map<void *, size_t> pinned_memory_size; class kernel_info_t { -public: -// kernel_info_t() -// { -// m_valid=false; -// m_kernel_entry=NULL; -// m_uid=0; -// m_num_cores_running=0; -// m_param_mem=NULL; -// } - kernel_info_t( dim3 gridDim, dim3 blockDim, class function_info *entry); - kernel_info_t( dim3 gridDim, dim3 blockDim, class function_info *entry, std::map<std::string, const struct cudaArray*> nameToCudaArray, std::map<std::string, const struct textureInfo*> nameToTextureInfo); - ~kernel_info_t(); + public: + // kernel_info_t() + // { + // m_valid=false; + // m_kernel_entry=NULL; + // m_uid=0; + // m_num_cores_running=0; + // m_param_mem=NULL; + // } + kernel_info_t(dim3 gridDim, dim3 blockDim, class function_info *entry); + kernel_info_t( + dim3 gridDim, dim3 blockDim, class function_info *entry, + std::map<std::string, const struct cudaArray *> nameToCudaArray, + std::map<std::string, const struct textureInfo *> nameToTextureInfo); + ~kernel_info_t(); - void inc_running() { m_num_cores_running++; } - void dec_running() - { - assert( m_num_cores_running > 0 ); - m_num_cores_running--; - } - bool running() const { return m_num_cores_running>0; } - bool done() const - { - return no_more_ctas_to_run() && !running(); - } - class function_info *entry() { return m_kernel_entry; } - const class function_info *entry() const { return m_kernel_entry; } + void inc_running() { m_num_cores_running++; } + void dec_running() { + assert(m_num_cores_running > 0); + m_num_cores_running--; + } + bool running() const { return m_num_cores_running > 0; } + bool done() const { return no_more_ctas_to_run() && !running(); } + class function_info *entry() { + return m_kernel_entry; + } + const class function_info *entry() const { return m_kernel_entry; } - size_t num_blocks() const - { - return m_grid_dim.x * m_grid_dim.y * m_grid_dim.z; - } + size_t num_blocks() const { + return m_grid_dim.x * m_grid_dim.y * m_grid_dim.z; + } - size_t threads_per_cta() const - { - return m_block_dim.x * m_block_dim.y * m_block_dim.z; - } + size_t threads_per_cta() const { + return m_block_dim.x * m_block_dim.y * m_block_dim.z; + } - dim3 get_grid_dim() const { return m_grid_dim; } - dim3 get_cta_dim() const { return m_block_dim; } + dim3 get_grid_dim() const { return m_grid_dim; } + dim3 get_cta_dim() const { return m_block_dim; } - void increment_cta_id() - { - increment_x_then_y_then_z(m_next_cta,m_grid_dim); - m_next_tid.x=0; - m_next_tid.y=0; - m_next_tid.z=0; - } - dim3 get_next_cta_id() const { return m_next_cta; } - unsigned get_next_cta_id_single() const - { - return m_next_cta.x + m_grid_dim.x*m_next_cta.y + m_grid_dim.x*m_grid_dim.y*m_next_cta.z; - } - bool no_more_ctas_to_run() const - { - return (m_next_cta.x >= m_grid_dim.x || m_next_cta.y >= m_grid_dim.y || m_next_cta.z >= m_grid_dim.z ); - } + void increment_cta_id() { + increment_x_then_y_then_z(m_next_cta, m_grid_dim); + m_next_tid.x = 0; + m_next_tid.y = 0; + m_next_tid.z = 0; + } + dim3 get_next_cta_id() const { return m_next_cta; } + unsigned get_next_cta_id_single() const { + return m_next_cta.x + m_grid_dim.x * m_next_cta.y + + m_grid_dim.x * m_grid_dim.y * m_next_cta.z; + } + bool no_more_ctas_to_run() const { + return (m_next_cta.x >= m_grid_dim.x || m_next_cta.y >= m_grid_dim.y || + m_next_cta.z >= m_grid_dim.z); + } - void increment_thread_id() { increment_x_then_y_then_z(m_next_tid,m_block_dim); } - dim3 get_next_thread_id_3d() const { return m_next_tid; } - unsigned get_next_thread_id() const - { - return m_next_tid.x + m_block_dim.x*m_next_tid.y + m_block_dim.x*m_block_dim.y*m_next_tid.z; - } - bool more_threads_in_cta() const - { - return m_next_tid.z < m_block_dim.z && m_next_tid.y < m_block_dim.y && m_next_tid.x < m_block_dim.x; - } - unsigned get_uid() const { return m_uid; } - std::string name() const; + void increment_thread_id() { + increment_x_then_y_then_z(m_next_tid, m_block_dim); + } + dim3 get_next_thread_id_3d() const { return m_next_tid; } + unsigned get_next_thread_id() const { + return m_next_tid.x + m_block_dim.x * m_next_tid.y + + m_block_dim.x * m_block_dim.y * m_next_tid.z; + } + bool more_threads_in_cta() const { + return m_next_tid.z < m_block_dim.z && m_next_tid.y < m_block_dim.y && + m_next_tid.x < m_block_dim.x; + } + unsigned get_uid() const { return m_uid; } + std::string name() const; - std::list<class ptx_thread_info *> &active_threads() { return m_active_threads; } - class memory_space *get_param_memory() { return m_param_mem; } + std::list<class ptx_thread_info *> &active_threads() { + return m_active_threads; + } + class memory_space *get_param_memory() { + return m_param_mem; + } - - //The following functions access texture bindings present at the kernel's launch - - const struct cudaArray* get_texarray( const std::string &texname ) const - { - std::map<std::string,const struct cudaArray*>::const_iterator t=m_NameToCudaArray.find(texname); - assert(t != m_NameToCudaArray.end()); - return t->second; - } + // The following functions access texture bindings present at the kernel's + // launch - const struct textureInfo* get_texinfo( const std::string &texname ) const - { - std::map<std::string, const struct textureInfo*>::const_iterator t=m_NameToTextureInfo.find(texname); - assert(t != m_NameToTextureInfo.end()); - return t->second; - } + const struct cudaArray *get_texarray(const std::string &texname) const { + std::map<std::string, const struct cudaArray *>::const_iterator t = + m_NameToCudaArray.find(texname); + assert(t != m_NameToCudaArray.end()); + return t->second; + } -private: - kernel_info_t( const kernel_info_t & ); // disable copy constructor - void operator=( const kernel_info_t & ); // disable copy operator + const struct textureInfo *get_texinfo(const std::string &texname) const { + std::map<std::string, const struct textureInfo *>::const_iterator t = + m_NameToTextureInfo.find(texname); + assert(t != m_NameToTextureInfo.end()); + return t->second; + } - class function_info *m_kernel_entry; + private: + kernel_info_t(const kernel_info_t &); // disable copy constructor + void operator=(const kernel_info_t &); // disable copy operator - unsigned m_uid; - - //These maps contain the snapshot of the texture mappings at kernel launch - std::map<std::string, const struct cudaArray*> m_NameToCudaArray; - std::map<std::string, const struct textureInfo*> m_NameToTextureInfo; + class function_info *m_kernel_entry; - dim3 m_grid_dim; - dim3 m_block_dim; - dim3 m_next_cta; - dim3 m_next_tid; + unsigned m_uid; - unsigned m_num_cores_running; + // These maps contain the snapshot of the texture mappings at kernel launch + std::map<std::string, const struct cudaArray *> m_NameToCudaArray; + std::map<std::string, const struct textureInfo *> m_NameToTextureInfo; - std::list<class ptx_thread_info *> m_active_threads; - class memory_space *m_param_mem; + dim3 m_grid_dim; + dim3 m_block_dim; + dim3 m_next_cta; + dim3 m_next_tid; -public: - //Jin: parent and child kernel management for CDP - void set_parent(kernel_info_t * parent, dim3 parent_ctaid, dim3 parent_tid); - void set_child(kernel_info_t * child); - void remove_child(kernel_info_t * child); - bool is_finished(); - bool children_all_finished(); - void notify_parent_finished(); - CUstream_st * create_stream_cta(dim3 ctaid); - CUstream_st * get_default_stream_cta(dim3 ctaid); - bool cta_has_stream(dim3 ctaid, CUstream_st* stream); - void destroy_cta_streams(); - void print_parent_info(); - kernel_info_t * get_parent() { return m_parent_kernel; } + unsigned m_num_cores_running; -private: - kernel_info_t * m_parent_kernel; - dim3 m_parent_ctaid; - dim3 m_parent_tid; - std::list<kernel_info_t *> m_child_kernels; //child kernel launched - std::map< dim3, std::list<CUstream_st *>, dim3comp > m_cta_streams; //streams created in each CTA + std::list<class ptx_thread_info *> m_active_threads; + class memory_space *m_param_mem; -//Jin: kernel timing -public: - unsigned long long launch_cycle; - unsigned long long start_cycle; - unsigned long long end_cycle; - unsigned m_launch_latency; //this used for CDP kernel latency + public: + // Jin: parent and child kernel management for CDP + void set_parent(kernel_info_t *parent, dim3 parent_ctaid, dim3 parent_tid); + void set_child(kernel_info_t *child); + void remove_child(kernel_info_t *child); + bool is_finished(); + bool children_all_finished(); + void notify_parent_finished(); + CUstream_st *create_stream_cta(dim3 ctaid); + CUstream_st *get_default_stream_cta(dim3 ctaid); + bool cta_has_stream(dim3 ctaid, CUstream_st *stream); + void destroy_cta_streams(); + void print_parent_info(); + kernel_info_t *get_parent() { return m_parent_kernel; } - mutable bool cache_config_set; + private: + kernel_info_t *m_parent_kernel; + dim3 m_parent_ctaid; + dim3 m_parent_tid; + std::list<kernel_info_t *> m_child_kernels; // child kernel launched + std::map<dim3, std::list<CUstream_st *>, dim3comp> + m_cta_streams; // streams created in each CTA + + // Jin: kernel timing + public: + unsigned long long launch_cycle; + unsigned long long start_cycle; + unsigned long long end_cycle; + unsigned m_launch_latency; + + mutable bool cache_config_set; unsigned m_kernel_TB_latency; //this used for any CPU-GPU kernel latency and counted in the gpu_cycle }; class core_config { - public: - core_config(gpgpu_context* ctx) - { - gpgpu_ctx = ctx; - m_valid = false; - num_shmem_bank=16; - shmem_limited_broadcast = false; - gpgpu_shmem_sizeDefault=(unsigned)-1; - gpgpu_shmem_sizePrefL1=(unsigned)-1; - gpgpu_shmem_sizePrefShared=(unsigned)-1; - } - virtual void init() = 0; + public: + core_config(gpgpu_context *ctx) { + gpgpu_ctx = ctx; + m_valid = false; + num_shmem_bank = 16; + shmem_limited_broadcast = false; + gpgpu_shmem_sizeDefault = (unsigned)-1; + gpgpu_shmem_sizePrefL1 = (unsigned)-1; + gpgpu_shmem_sizePrefShared = (unsigned)-1; + } + virtual void init() = 0; - bool m_valid; - unsigned warp_size; - // backward pointer - class gpgpu_context* gpgpu_ctx; + bool m_valid; + unsigned warp_size; + // backward pointer + class gpgpu_context *gpgpu_ctx; - // off-chip memory request architecture parameters - int gpgpu_coalesce_arch; + // off-chip memory request architecture parameters + int gpgpu_coalesce_arch; - // shared memory bank conflict checking parameters - bool shmem_limited_broadcast; - static const address_type WORD_SIZE=4; - unsigned num_shmem_bank; - unsigned shmem_bank_func(address_type addr) const - { - return ((addr/WORD_SIZE) % num_shmem_bank); - } - unsigned mem_warp_parts; - mutable unsigned gpgpu_shmem_size; - unsigned gpgpu_shmem_sizeDefault; - unsigned gpgpu_shmem_sizePrefL1; - unsigned gpgpu_shmem_sizePrefShared; - unsigned mem_unit_ports; + // shared memory bank conflict checking parameters + bool shmem_limited_broadcast; + static const address_type WORD_SIZE = 4; + unsigned num_shmem_bank; + unsigned shmem_bank_func(address_type addr) const { + return ((addr / WORD_SIZE) % num_shmem_bank); + } + unsigned mem_warp_parts; + mutable unsigned gpgpu_shmem_size; + unsigned gpgpu_shmem_sizeDefault; + unsigned gpgpu_shmem_sizePrefL1; + unsigned gpgpu_shmem_sizePrefShared; + unsigned mem_unit_ports; - // texture and constant cache line sizes (used to determine number of memory accesses) - unsigned gpgpu_cache_texl1_linesize; - unsigned gpgpu_cache_constl1_linesize; + // texture and constant cache line sizes (used to determine number of memory + // accesses) + unsigned gpgpu_cache_texl1_linesize; + unsigned gpgpu_cache_constl1_linesize; - unsigned gpgpu_max_insn_issue_per_warp; - bool gmem_skip_L1D; // on = global memory access always skip the L1 cache + unsigned gpgpu_max_insn_issue_per_warp; + bool gmem_skip_L1D; // on = global memory access always skip the L1 cache - unsigned adaptive_cache_config; + bool adaptive_cache_config; }; -// bounded stack that implements simt reconvergence using pdom mechanism from MICRO'07 paper +// bounded stack that implements simt reconvergence using pdom mechanism from +// MICRO'07 paper const unsigned MAX_WARP_SIZE = 32; typedef std::bitset<MAX_WARP_SIZE> active_mask_t; -#define MAX_WARP_SIZE_SIMT_STACK MAX_WARP_SIZE +#define MAX_WARP_SIZE_SIMT_STACK MAX_WARP_SIZE typedef std::bitset<MAX_WARP_SIZE_SIMT_STACK> simt_mask_t; typedef std::vector<address_type> addr_vector_t; class simt_stack { -public: - simt_stack( unsigned wid, unsigned warpSize, class gpgpu_sim * gpu); - - void reset(); - void launch( address_type start_pc, const simt_mask_t &active_mask ); - void update( simt_mask_t &thread_done, addr_vector_t &next_pc, address_type recvg_pc, op_type next_inst_op,unsigned next_inst_size, address_type next_inst_pc ); + public: + simt_stack(unsigned wid, unsigned warpSize, class gpgpu_sim *gpu); - const simt_mask_t &get_active_mask() const; - void get_pdom_stack_top_info( unsigned *pc, unsigned *rpc ) const; - unsigned get_rp() const; - void print(FILE *fp) const; - void resume(char * fname) ; - void print_checkpoint (FILE *fout) const; + void reset(); + void launch(address_type start_pc, const simt_mask_t &active_mask); + void update(simt_mask_t &thread_done, addr_vector_t &next_pc, + address_type recvg_pc, op_type next_inst_op, + unsigned next_inst_size, address_type next_inst_pc); -protected: - unsigned m_warp_id; - unsigned m_warp_size; + const simt_mask_t &get_active_mask() const; + void get_pdom_stack_top_info(unsigned *pc, unsigned *rpc) const; + unsigned get_rp() const; + void print(FILE *fp) const; + void resume(char *fname); + void print_checkpoint(FILE *fout) const; + protected: + unsigned m_warp_id; + unsigned m_warp_size; - enum stack_entry_type { - STACK_ENTRY_TYPE_NORMAL = 0, - STACK_ENTRY_TYPE_CALL - }; + enum stack_entry_type { STACK_ENTRY_TYPE_NORMAL = 0, STACK_ENTRY_TYPE_CALL }; - struct simt_stack_entry { - address_type m_pc; - unsigned int m_calldepth; - simt_mask_t m_active_mask; - address_type m_recvg_pc; - unsigned long long m_branch_div_cycle; - stack_entry_type m_type; - simt_stack_entry() : - m_pc(-1), m_calldepth(0), m_active_mask(), m_recvg_pc(-1), m_branch_div_cycle(0), m_type(STACK_ENTRY_TYPE_NORMAL) { }; - }; + struct simt_stack_entry { + address_type m_pc; + unsigned int m_calldepth; + simt_mask_t m_active_mask; + address_type m_recvg_pc; + unsigned long long m_branch_div_cycle; + stack_entry_type m_type; + simt_stack_entry() + : m_pc(-1), + m_calldepth(0), + m_active_mask(), + m_recvg_pc(-1), + m_branch_div_cycle(0), + m_type(STACK_ENTRY_TYPE_NORMAL){}; + }; - std::deque<simt_stack_entry> m_stack; + std::deque<simt_stack_entry> m_stack; - class gpgpu_sim * m_gpu; + class gpgpu_sim *m_gpu; }; // Let's just upgrade to C++11 so we can use constexpr here... -// start allocating from this address (lower values used for allocating globals in .ptx file) +// start allocating from this address (lower values used for allocating globals +// in .ptx file) const unsigned long long GLOBAL_HEAP_START = 0xC0000000; // Volta max shmem size is 96kB const unsigned long long SHARED_MEM_SIZE_MAX = 96 * (1 << 10); @@ -463,873 +447,928 @@ const unsigned MAX_STREAMING_MULTIPROCESSORS = 80; const unsigned MAX_THREAD_PER_SM = 1 << 11; // MAX 64 warps / SM const unsigned MAX_WARP_PER_SM = 1 << 6; -const unsigned long long TOTAL_LOCAL_MEM_PER_SM = MAX_THREAD_PER_SM * LOCAL_MEM_SIZE_MAX; -const unsigned long long TOTAL_SHARED_MEM = MAX_STREAMING_MULTIPROCESSORS * SHARED_MEM_SIZE_MAX; -const unsigned long long TOTAL_LOCAL_MEM = MAX_STREAMING_MULTIPROCESSORS * MAX_THREAD_PER_SM * LOCAL_MEM_SIZE_MAX; -const unsigned long long SHARED_GENERIC_START = GLOBAL_HEAP_START - TOTAL_SHARED_MEM; -const unsigned long long LOCAL_GENERIC_START = SHARED_GENERIC_START - TOTAL_LOCAL_MEM; -const unsigned long long STATIC_ALLOC_LIMIT = GLOBAL_HEAP_START - (TOTAL_LOCAL_MEM + TOTAL_SHARED_MEM); +const unsigned long long TOTAL_LOCAL_MEM_PER_SM = + MAX_THREAD_PER_SM * LOCAL_MEM_SIZE_MAX; +const unsigned long long TOTAL_SHARED_MEM = + MAX_STREAMING_MULTIPROCESSORS * SHARED_MEM_SIZE_MAX; +const unsigned long long TOTAL_LOCAL_MEM = + MAX_STREAMING_MULTIPROCESSORS * MAX_THREAD_PER_SM * LOCAL_MEM_SIZE_MAX; +const unsigned long long SHARED_GENERIC_START = + GLOBAL_HEAP_START - TOTAL_SHARED_MEM; +const unsigned long long LOCAL_GENERIC_START = + SHARED_GENERIC_START - TOTAL_LOCAL_MEM; +const unsigned long long STATIC_ALLOC_LIMIT = + GLOBAL_HEAP_START - (TOTAL_LOCAL_MEM + TOTAL_SHARED_MEM); #if !defined(__CUDA_RUNTIME_API_H__) #include "builtin_types.h" struct cudaArray { - void *devPtr; - int devPtr32; - struct cudaChannelFormatDesc desc; - int width; - int height; - int size; //in bytes - unsigned dimensions; + void *devPtr; + int devPtr32; + struct cudaChannelFormatDesc desc; + int width; + int height; + int size; // in bytes + unsigned dimensions; }; #endif -// Struct that record other attributes in the textureReference declaration +// Struct that record other attributes in the textureReference declaration // - These attributes are passed thru __cudaRegisterTexture() struct textureReferenceAttr { - const struct textureReference *m_texref; - int m_dim; - enum cudaTextureReadMode m_readmode; - int m_ext; - textureReferenceAttr(const struct textureReference *texref, - int dim, - enum cudaTextureReadMode readmode, - int ext) - : m_texref(texref), m_dim(dim), m_readmode(readmode), m_ext(ext) - { } + const struct textureReference *m_texref; + int m_dim; + enum cudaTextureReadMode m_readmode; + int m_ext; + textureReferenceAttr(const struct textureReference *texref, int dim, + enum cudaTextureReadMode readmode, int ext) + : m_texref(texref), m_dim(dim), m_readmode(readmode), m_ext(ext) {} }; -class gpgpu_functional_sim_config -{ -public: - void reg_options(class OptionParser * opp); +class gpgpu_functional_sim_config { + public: + void reg_options(class OptionParser *opp); - void ptx_set_tex_cache_linesize(unsigned linesize); + void ptx_set_tex_cache_linesize(unsigned linesize); - unsigned get_forced_max_capability() const { return m_ptx_force_max_capability; } - bool convert_to_ptxplus() const { return m_ptx_convert_to_ptxplus; } - bool use_cuobjdump() const { return m_ptx_use_cuobjdump; } - bool experimental_lib_support() const { return m_experimental_lib_support; } + unsigned get_forced_max_capability() const { + return m_ptx_force_max_capability; + } + bool convert_to_ptxplus() const { return m_ptx_convert_to_ptxplus; } + bool use_cuobjdump() const { return m_ptx_use_cuobjdump; } + bool experimental_lib_support() const { return m_experimental_lib_support; } - int get_ptx_inst_debug_to_file() const { return g_ptx_inst_debug_to_file; } - const char* get_ptx_inst_debug_file() const { return g_ptx_inst_debug_file; } - int get_ptx_inst_debug_thread_uid() const { return g_ptx_inst_debug_thread_uid; } - unsigned get_texcache_linesize() const { return m_texcache_linesize; } - int get_checkpoint_option() const {return checkpoint_option; } - int get_checkpoint_kernel() const {return checkpoint_kernel; } - int get_checkpoint_CTA() const {return checkpoint_CTA; } - int get_resume_option() const {return resume_option; } - int get_resume_kernel() const {return resume_kernel; } - int get_resume_CTA() const {return resume_CTA; } - int get_checkpoint_CTA_t() const {return checkpoint_CTA_t; } - int get_checkpoint_insn_Y() const {return checkpoint_insn_Y; } -private: - // PTX options - int m_ptx_convert_to_ptxplus; - int m_ptx_use_cuobjdump; - int m_experimental_lib_support; - unsigned m_ptx_force_max_capability; - int checkpoint_option; - int checkpoint_kernel; - int checkpoint_CTA; - unsigned resume_option; - unsigned resume_kernel; - unsigned resume_CTA; - unsigned checkpoint_CTA_t; - int checkpoint_insn_Y; - int g_ptx_inst_debug_to_file; - char* g_ptx_inst_debug_file; - int g_ptx_inst_debug_thread_uid; + int get_ptx_inst_debug_to_file() const { return g_ptx_inst_debug_to_file; } + const char *get_ptx_inst_debug_file() const { return g_ptx_inst_debug_file; } + int get_ptx_inst_debug_thread_uid() const { + return g_ptx_inst_debug_thread_uid; + } + unsigned get_texcache_linesize() const { return m_texcache_linesize; } + int get_checkpoint_option() const { return checkpoint_option; } + int get_checkpoint_kernel() const { return checkpoint_kernel; } + int get_checkpoint_CTA() const { return checkpoint_CTA; } + int get_resume_option() const { return resume_option; } + int get_resume_kernel() const { return resume_kernel; } + int get_resume_CTA() const { return resume_CTA; } + int get_checkpoint_CTA_t() const { return checkpoint_CTA_t; } + int get_checkpoint_insn_Y() const { return checkpoint_insn_Y; } - unsigned m_texcache_linesize; -}; + private: + // PTX options + int m_ptx_convert_to_ptxplus; + int m_ptx_use_cuobjdump; + int m_experimental_lib_support; + unsigned m_ptx_force_max_capability; + int checkpoint_option; + int checkpoint_kernel; + int checkpoint_CTA; + unsigned resume_option; + unsigned resume_kernel; + unsigned resume_CTA; + unsigned checkpoint_CTA_t; + int checkpoint_insn_Y; + int g_ptx_inst_debug_to_file; + char *g_ptx_inst_debug_file; + int g_ptx_inst_debug_thread_uid; + unsigned m_texcache_linesize; +}; class gpgpu_t { -public: - gpgpu_t( const gpgpu_functional_sim_config &config, gpgpu_context* ctx ); - // backward pointer - class gpgpu_context* gpgpu_ctx; - int checkpoint_option; - int checkpoint_kernel; - int checkpoint_CTA; - unsigned resume_option; - unsigned resume_kernel; - unsigned resume_CTA; - unsigned checkpoint_CTA_t; - int checkpoint_insn_Y; + public: + gpgpu_t(const gpgpu_functional_sim_config &config, gpgpu_context *ctx); + // backward pointer + class gpgpu_context *gpgpu_ctx; + int checkpoint_option; + int checkpoint_kernel; + int checkpoint_CTA; + unsigned resume_option; + unsigned resume_kernel; + unsigned resume_CTA; + unsigned checkpoint_CTA_t; + int checkpoint_insn_Y; - //Move some cycle core stats here instead of being global - unsigned long long gpu_sim_cycle; - unsigned long long gpu_tot_sim_cycle; + // Move some cycle core stats here instead of being global + unsigned long long gpu_sim_cycle; + unsigned long long gpu_tot_sim_cycle; + void *gpu_malloc(size_t size); + void *gpu_mallocarray(size_t count); + void gpu_memset(size_t dst_start_addr, int c, size_t count); + void memcpy_to_gpu(size_t dst_start_addr, const void *src, size_t count); + void memcpy_from_gpu(void *dst, size_t src_start_addr, size_t count); + void memcpy_gpu_to_gpu(size_t dst, size_t src, size_t count); - void* gpu_malloc( size_t size ); - void* gpu_mallocarray( size_t count ); - void gpu_memset( size_t dst_start_addr, int c, size_t count ); - void memcpy_to_gpu( size_t dst_start_addr, const void *src, size_t count ); - void memcpy_from_gpu( void *dst, size_t src_start_addr, size_t count ); - void memcpy_gpu_to_gpu( size_t dst, size_t src, size_t count ); - - class memory_space *get_global_memory() { return m_global_mem; } - class memory_space *get_tex_memory() { return m_tex_mem; } - class memory_space *get_surf_memory() { return m_surf_mem; } + class memory_space *get_global_memory() { + return m_global_mem; + } + class memory_space *get_tex_memory() { + return m_tex_mem; + } + class memory_space *get_surf_memory() { + return m_surf_mem; + } - void gpgpu_ptx_sim_bindTextureToArray(const struct textureReference* texref, const struct cudaArray* array); - void gpgpu_ptx_sim_bindNameToTexture(const char* name, const struct textureReference* texref, int dim, int readmode, int ext); - void gpgpu_ptx_sim_unbindTexture(const struct textureReference* texref); - const char* gpgpu_ptx_sim_findNamefromTexture(const struct textureReference* texref); + void gpgpu_ptx_sim_bindTextureToArray(const struct textureReference *texref, + const struct cudaArray *array); + void gpgpu_ptx_sim_bindNameToTexture(const char *name, + const struct textureReference *texref, + int dim, int readmode, int ext); + void gpgpu_ptx_sim_unbindTexture(const struct textureReference *texref); + const char *gpgpu_ptx_sim_findNamefromTexture( + const struct textureReference *texref); - const struct textureReference* get_texref( const std::string &texname ) const - { - std::map<std::string, std::set<const struct textureReference*> >::const_iterator t=m_NameToTextureRef.find(texname); - assert( t != m_NameToTextureRef.end() ); - return *(t->second.begin()); - } + const struct textureReference *get_texref(const std::string &texname) const { + std::map<std::string, + std::set<const struct textureReference *> >::const_iterator t = + m_NameToTextureRef.find(texname); + assert(t != m_NameToTextureRef.end()); + return *(t->second.begin()); + } - const struct cudaArray* get_texarray( const std::string &texname ) const - { - std::map<std::string,const struct cudaArray*>::const_iterator t=m_NameToCudaArray.find(texname); - assert(t != m_NameToCudaArray.end()); - return t->second; - } + const struct cudaArray *get_texarray(const std::string &texname) const { + std::map<std::string, const struct cudaArray *>::const_iterator t = + m_NameToCudaArray.find(texname); + assert(t != m_NameToCudaArray.end()); + return t->second; + } - const struct textureInfo* get_texinfo( const std::string &texname ) const - { - std::map<std::string, const struct textureInfo*>::const_iterator t=m_NameToTextureInfo.find(texname); - assert(t != m_NameToTextureInfo.end()); - return t->second; - } + const struct textureInfo *get_texinfo(const std::string &texname) const { + std::map<std::string, const struct textureInfo *>::const_iterator t = + m_NameToTextureInfo.find(texname); + assert(t != m_NameToTextureInfo.end()); + return t->second; + } - const struct textureReferenceAttr* get_texattr( const std::string &texname ) const - { - std::map<std::string, const struct textureReferenceAttr*>::const_iterator t=m_NameToAttribute.find(texname); - assert(t != m_NameToAttribute.end()); - return t->second; - } + const struct textureReferenceAttr *get_texattr( + const std::string &texname) const { + std::map<std::string, const struct textureReferenceAttr *>::const_iterator + t = m_NameToAttribute.find(texname); + assert(t != m_NameToAttribute.end()); + return t->second; + } - const gpgpu_functional_sim_config &get_config() const { return m_function_model_config; } - FILE* get_ptx_inst_debug_file() { return ptx_inst_debug_file; } - - // These maps return the current texture mappings for the GPU at any given time. - std::map<std::string, const struct cudaArray*> getNameArrayMapping() {return m_NameToCudaArray;} - std::map<std::string, const struct textureInfo*> getNameInfoMapping() {return m_NameToTextureInfo;} + const gpgpu_functional_sim_config &get_config() const { + return m_function_model_config; + } + FILE *get_ptx_inst_debug_file() { return ptx_inst_debug_file; } -protected: - const gpgpu_functional_sim_config &m_function_model_config; - FILE* ptx_inst_debug_file; + // These maps return the current texture mappings for the GPU at any given + // time. + std::map<std::string, const struct cudaArray *> getNameArrayMapping() { + return m_NameToCudaArray; + } + std::map<std::string, const struct textureInfo *> getNameInfoMapping() { + return m_NameToTextureInfo; + } - class memory_space *m_global_mem; - class memory_space *m_tex_mem; - class memory_space *m_surf_mem; + protected: + const gpgpu_functional_sim_config &m_function_model_config; + FILE *ptx_inst_debug_file; - unsigned long long m_dev_malloc; - // These maps contain the current texture mappings for the GPU at any given time. - std::map<std::string, std::set<const struct textureReference*> > m_NameToTextureRef; - std::map<const struct textureReference*, std::string> m_TextureRefToName; - std::map<std::string, const struct cudaArray*> m_NameToCudaArray; - std::map<std::string, const struct textureInfo*> m_NameToTextureInfo; - std::map<std::string, const struct textureReferenceAttr*> m_NameToAttribute; -}; + class memory_space *m_global_mem; + class memory_space *m_tex_mem; + class memory_space *m_surf_mem; -struct gpgpu_ptx_sim_info -{ - // Holds properties of the kernel (Kernel's resource use). - // These will be set to zero if a ptxinfo file is not present. - int lmem; - int smem; - int cmem; - int gmem; - int regs; - unsigned maxthreads; - unsigned ptx_version; - unsigned sm_target; + unsigned long long m_dev_malloc; + // These maps contain the current texture mappings for the GPU at any given + // time. + std::map<std::string, std::set<const struct textureReference *> > + m_NameToTextureRef; + std::map<const struct textureReference *, std::string> m_TextureRefToName; + std::map<std::string, const struct cudaArray *> m_NameToCudaArray; + std::map<std::string, const struct textureInfo *> m_NameToTextureInfo; + std::map<std::string, const struct textureReferenceAttr *> m_NameToAttribute; }; +struct gpgpu_ptx_sim_info { + // Holds properties of the kernel (Kernel's resource use). + // These will be set to zero if a ptxinfo file is not present. + int lmem; + int smem; + int cmem; + int gmem; + int regs; + unsigned maxthreads; + unsigned ptx_version; + unsigned sm_target; +}; struct gpgpu_ptx_sim_arg { - gpgpu_ptx_sim_arg() { m_start=NULL; } - gpgpu_ptx_sim_arg(const void *arg, size_t size, size_t offset) - { - m_start=arg; - m_nbytes=size; - m_offset=offset; - } - const void *m_start; - size_t m_nbytes; - size_t m_offset; + gpgpu_ptx_sim_arg() { m_start = NULL; } + gpgpu_ptx_sim_arg(const void *arg, size_t size, size_t offset) { + m_start = arg; + m_nbytes = size; + m_offset = offset; + } + const void *m_start; + size_t m_nbytes; + size_t m_offset; }; typedef std::list<gpgpu_ptx_sim_arg> gpgpu_ptx_sim_arg_list_t; class memory_space_t { -public: - memory_space_t() { m_type = undefined_space; m_bank=0; } - memory_space_t( const enum _memory_space_t &from ) { m_type = from; m_bank = 0; } - bool operator==( const memory_space_t &x ) const { return (m_bank == x.m_bank) && (m_type == x.m_type); } - bool operator!=( const memory_space_t &x ) const { return !(*this == x); } - bool operator<( const memory_space_t &x ) const - { - if(m_type < x.m_type) - return true; - else if(m_type > x.m_type) - return false; - else if( m_bank < x.m_bank ) - return true; + public: + memory_space_t() { + m_type = undefined_space; + m_bank = 0; + } + memory_space_t(const enum _memory_space_t &from) { + m_type = from; + m_bank = 0; + } + bool operator==(const memory_space_t &x) const { + return (m_bank == x.m_bank) && (m_type == x.m_type); + } + bool operator!=(const memory_space_t &x) const { return !(*this == x); } + bool operator<(const memory_space_t &x) const { + if (m_type < x.m_type) + return true; + else if (m_type > x.m_type) return false; - } - enum _memory_space_t get_type() const { return m_type; } - void set_type( enum _memory_space_t t ) { m_type = t; } - unsigned get_bank() const { return m_bank; } - void set_bank( unsigned b ) { m_bank = b; } - bool is_const() const { return (m_type == const_space) || (m_type == param_space_kernel); } - bool is_local() const { return (m_type == local_space) || (m_type == param_space_local); } - bool is_global() const { return (m_type == global_space); } + else if (m_bank < x.m_bank) + return true; + return false; + } + enum _memory_space_t get_type() const { return m_type; } + void set_type(enum _memory_space_t t) { m_type = t; } + unsigned get_bank() const { return m_bank; } + void set_bank(unsigned b) { m_bank = b; } + bool is_const() const { + return (m_type == const_space) || (m_type == param_space_kernel); + } + bool is_local() const { + return (m_type == local_space) || (m_type == param_space_local); + } + bool is_global() const { return (m_type == global_space); } -private: - enum _memory_space_t m_type; - unsigned m_bank; // n in ".const[n]"; note .const == .const[0] (see PTX 2.1 manual, sec. 5.1.3) + private: + enum _memory_space_t m_type; + unsigned m_bank; // n in ".const[n]"; note .const == .const[0] (see PTX 2.1 + // manual, sec. 5.1.3) }; const unsigned MAX_MEMORY_ACCESS_SIZE = 128; typedef std::bitset<MAX_MEMORY_ACCESS_SIZE> mem_access_byte_mask_t; -const unsigned SECTOR_CHUNCK_SIZE = 4; //four sectors -const unsigned SECTOR_SIZE = 32 ; //sector is 32 bytes width +const unsigned SECTOR_CHUNCK_SIZE = 4; // four sectors +const unsigned SECTOR_SIZE = 32; // sector is 32 bytes width typedef std::bitset<SECTOR_CHUNCK_SIZE> mem_access_sector_mask_t; #define NO_PARTIAL_WRITE (mem_access_byte_mask_t()) -#define MEM_ACCESS_TYPE_TUP_DEF \ -MA_TUP_BEGIN( mem_access_type ) \ - MA_TUP( GLOBAL_ACC_R ), \ - MA_TUP( LOCAL_ACC_R ), \ - MA_TUP( CONST_ACC_R ), \ - MA_TUP( TEXTURE_ACC_R ), \ - MA_TUP( GLOBAL_ACC_W ), \ - MA_TUP( LOCAL_ACC_W ), \ - MA_TUP( L1_WRBK_ACC ), \ - MA_TUP( L2_WRBK_ACC ), \ - MA_TUP( INST_ACC_R ), \ - MA_TUP( L1_WR_ALLOC_R ), \ - MA_TUP( L2_WR_ALLOC_R ), \ - MA_TUP( NUM_MEM_ACCESS_TYPE ) \ -MA_TUP_END( mem_access_type ) +#define MEM_ACCESS_TYPE_TUP_DEF \ + MA_TUP_BEGIN(mem_access_type) \ + MA_TUP(GLOBAL_ACC_R), MA_TUP(LOCAL_ACC_R), MA_TUP(CONST_ACC_R), \ + MA_TUP(TEXTURE_ACC_R), MA_TUP(GLOBAL_ACC_W), MA_TUP(LOCAL_ACC_W), \ + MA_TUP(L1_WRBK_ACC), MA_TUP(L2_WRBK_ACC), MA_TUP(INST_ACC_R), \ + MA_TUP(L1_WR_ALLOC_R), MA_TUP(L2_WR_ALLOC_R), \ + MA_TUP(NUM_MEM_ACCESS_TYPE) MA_TUP_END(mem_access_type) #define MA_TUP_BEGIN(X) enum X { #define MA_TUP(X) X -#define MA_TUP_END(X) }; +#define MA_TUP_END(X) \ + } \ + ; MEM_ACCESS_TYPE_TUP_DEF #undef MA_TUP_BEGIN #undef MA_TUP #undef MA_TUP_END -const char * mem_access_type_str(enum mem_access_type access_type); +const char *mem_access_type_str(enum mem_access_type access_type); enum cache_operator_type { - CACHE_UNDEFINED, + CACHE_UNDEFINED, + + // loads + CACHE_ALL, // .ca + CACHE_LAST_USE, // .lu + CACHE_VOLATILE, // .cv + CACHE_L1, // .nc - // loads - CACHE_ALL, // .ca - CACHE_LAST_USE, // .lu - CACHE_VOLATILE, // .cv - CACHE_L1, // .nc - - // loads and stores - CACHE_STREAMING, // .cs - CACHE_GLOBAL, // .cg + // loads and stores + CACHE_STREAMING, // .cs + CACHE_GLOBAL, // .cg - // stores - CACHE_WRITE_BACK, // .wb - CACHE_WRITE_THROUGH // .wt + // stores + CACHE_WRITE_BACK, // .wb + CACHE_WRITE_THROUGH // .wt }; class mem_access_t { -public: - mem_access_t(gpgpu_context* ctx) { init(ctx); } - mem_access_t( mem_access_type type, - new_addr_type address, - unsigned size, - bool wr, - gpgpu_context* ctx) - { - init(ctx); - m_type = type; - m_addr = address; - m_req_size = size; - m_write = wr; - } - mem_access_t( mem_access_type type, - new_addr_type address, - unsigned size, - bool wr, - const active_mask_t &active_mask, - const mem_access_byte_mask_t &byte_mask, - const mem_access_sector_mask_t §or_mask, - gpgpu_context* ctx) - : m_warp_mask(active_mask), m_byte_mask(byte_mask), m_sector_mask(sector_mask) - { - init(ctx); - m_type = type; - m_addr = address; - m_req_size = size; - m_write = wr; - } + public: + mem_access_t(gpgpu_context *ctx) { init(ctx); } + mem_access_t(mem_access_type type, new_addr_type address, unsigned size, + bool wr, gpgpu_context *ctx) { + init(ctx); + m_type = type; + m_addr = address; + m_req_size = size; + m_write = wr; + } + mem_access_t(mem_access_type type, new_addr_type address, unsigned size, + bool wr, const active_mask_t &active_mask, + const mem_access_byte_mask_t &byte_mask, + const mem_access_sector_mask_t §or_mask, gpgpu_context *ctx) + : m_warp_mask(active_mask), + m_byte_mask(byte_mask), + m_sector_mask(sector_mask) { + init(ctx); + m_type = type; + m_addr = address; + m_req_size = size; + m_write = wr; + } - new_addr_type get_addr() const { return m_addr; } - void set_addr(new_addr_type addr) {m_addr=addr;} - unsigned get_size() const { return m_req_size; } - const active_mask_t &get_warp_mask() const { return m_warp_mask; } - bool is_write() const { return m_write; } - enum mem_access_type get_type() const { return m_type; } - mem_access_byte_mask_t get_byte_mask() const { return m_byte_mask; } - mem_access_sector_mask_t get_sector_mask() const { return m_sector_mask; } + new_addr_type get_addr() const { return m_addr; } + void set_addr(new_addr_type addr) { m_addr = addr; } + unsigned get_size() const { return m_req_size; } + const active_mask_t &get_warp_mask() const { return m_warp_mask; } + bool is_write() const { return m_write; } + enum mem_access_type get_type() const { return m_type; } + mem_access_byte_mask_t get_byte_mask() const { return m_byte_mask; } + mem_access_sector_mask_t get_sector_mask() const { return m_sector_mask; } + + void print(FILE *fp) const { + fprintf(fp, "addr=0x%llx, %s, size=%u, ", m_addr, + m_write ? "store" : "load ", m_req_size); + switch (m_type) { + case GLOBAL_ACC_R: + fprintf(fp, "GLOBAL_R"); + break; + case LOCAL_ACC_R: + fprintf(fp, "LOCAL_R "); + break; + case CONST_ACC_R: + fprintf(fp, "CONST "); + break; + case TEXTURE_ACC_R: + fprintf(fp, "TEXTURE "); + break; + case GLOBAL_ACC_W: + fprintf(fp, "GLOBAL_W"); + break; + case LOCAL_ACC_W: + fprintf(fp, "LOCAL_W "); + break; + case L2_WRBK_ACC: + fprintf(fp, "L2_WRBK "); + break; + case INST_ACC_R: + fprintf(fp, "INST "); + break; + case L1_WRBK_ACC: + fprintf(fp, "L1_WRBK "); + break; + default: + fprintf(fp, "unknown "); + break; + } + } - void print(FILE *fp) const - { - fprintf(fp,"addr=0x%llx, %s, size=%u, ", m_addr, m_write?"store":"load ", m_req_size ); - switch(m_type) { - case GLOBAL_ACC_R: fprintf(fp,"GLOBAL_R"); break; - case LOCAL_ACC_R: fprintf(fp,"LOCAL_R "); break; - case CONST_ACC_R: fprintf(fp,"CONST "); break; - case TEXTURE_ACC_R: fprintf(fp,"TEXTURE "); break; - case GLOBAL_ACC_W: fprintf(fp,"GLOBAL_W"); break; - case LOCAL_ACC_W: fprintf(fp,"LOCAL_W "); break; - case L2_WRBK_ACC: fprintf(fp,"L2_WRBK "); break; - case INST_ACC_R: fprintf(fp,"INST "); break; - case L1_WRBK_ACC: fprintf(fp,"L1_WRBK "); break; - default: fprintf(fp,"unknown "); break; - } - } + gpgpu_context *gpgpu_ctx; - gpgpu_context* gpgpu_ctx; -private: - void init(gpgpu_context* ctx); + private: + void init(gpgpu_context *ctx); - unsigned m_uid; - new_addr_type m_addr; // request address - bool m_write; - unsigned m_req_size; // bytes - mem_access_type m_type; - active_mask_t m_warp_mask; - mem_access_byte_mask_t m_byte_mask; - mem_access_sector_mask_t m_sector_mask; + unsigned m_uid; + new_addr_type m_addr; // request address + bool m_write; + unsigned m_req_size; // bytes + mem_access_type m_type; + active_mask_t m_warp_mask; + mem_access_byte_mask_t m_byte_mask; + mem_access_sector_mask_t m_sector_mask; }; class mem_fetch; class mem_fetch_interface { -public: - virtual bool full( unsigned size, bool write ) const = 0; - virtual void push( mem_fetch *mf ) = 0; + public: + virtual bool full(unsigned size, bool write) const = 0; + virtual void push(mem_fetch *mf) = 0; }; class mem_fetch_allocator { -public: - virtual mem_fetch *alloc( new_addr_type addr, mem_access_type type, unsigned size, bool wr, unsigned long long cycle ) const = 0; - virtual mem_fetch *alloc( const class warp_inst_t &inst, const mem_access_t &access, unsigned long long cycle ) const = 0; + public: + virtual mem_fetch *alloc(new_addr_type addr, mem_access_type type, + unsigned size, bool wr, + unsigned long long cycle) const = 0; + virtual mem_fetch *alloc(const class warp_inst_t &inst, + const mem_access_t &access, + unsigned long long cycle) const = 0; }; -// the maximum number of destination, source, or address uarch operands in a instruction -#define MAX_REG_OPERANDS 32 +// the maximum number of destination, source, or address uarch operands in a +// instruction +#define MAX_REG_OPERANDS 32 struct dram_callback_t { - dram_callback_t() { function=NULL; instruction=NULL; thread=NULL; } - void (*function)(const class inst_t*, class ptx_thread_info*); + dram_callback_t() { + function = NULL; + instruction = NULL; + thread = NULL; + } + void (*function)(const class inst_t *, class ptx_thread_info *); - const class inst_t* instruction; - class ptx_thread_info *thread; + const class inst_t *instruction; + class ptx_thread_info *thread; }; class inst_t { -public: - inst_t() - { - m_decoded=false; - pc=(address_type)-1; - reconvergence_pc=(address_type)-1; - op=NO_OP; - bar_type=NOT_BAR; - red_type=NOT_RED; - bar_id=(unsigned)-1; - bar_count=(unsigned)-1; - oprnd_type=UN_OP; - sp_op=OTHER_OP; - op_pipe=UNKOWN_OP; - mem_op=NOT_TEX; - num_operands=0; - num_regs=0; - memset(out, 0, sizeof(unsigned)); - memset(in, 0, sizeof(unsigned)); - is_vectorin=0; - is_vectorout=0; - space = memory_space_t(); - cache_op = CACHE_UNDEFINED; - latency = 1; - initiation_interval = 1; - for( unsigned i=0; i < MAX_REG_OPERANDS; i++ ) { - arch_reg.src[i] = -1; - arch_reg.dst[i] = -1; - } - isize=0; - } - bool valid() const { return m_decoded; } - virtual void print_insn( FILE *fp ) const - { - fprintf(fp," [inst @ pc=0x%04x] ", pc ); + public: + inst_t() { + m_decoded = false; + pc = (address_type)-1; + reconvergence_pc = (address_type)-1; + op = NO_OP; + bar_type = NOT_BAR; + red_type = NOT_RED; + bar_id = (unsigned)-1; + bar_count = (unsigned)-1; + oprnd_type = UN_OP; + sp_op = OTHER_OP; + op_pipe = UNKOWN_OP; + mem_op = NOT_TEX; + num_operands = 0; + num_regs = 0; + memset(out, 0, sizeof(unsigned)); + memset(in, 0, sizeof(unsigned)); + is_vectorin = 0; + is_vectorout = 0; + space = memory_space_t(); + cache_op = CACHE_UNDEFINED; + latency = 1; + initiation_interval = 1; + for (unsigned i = 0; i < MAX_REG_OPERANDS; i++) { + arch_reg.src[i] = -1; + arch_reg.dst[i] = -1; } - bool is_load() const { return (op == LOAD_OP ||op==TENSOR_CORE_LOAD_OP || memory_op == memory_load); } - bool is_store() const { return (op == STORE_OP ||op==TENSOR_CORE_STORE_OP || memory_op == memory_store); } - unsigned get_num_operands() const {return num_operands;} - unsigned get_num_regs() const {return num_regs;} - void set_num_regs(unsigned num) {num_regs=num;} - void set_num_operands(unsigned num) {num_operands=num;} - void set_bar_id(unsigned id) {bar_id=id;} - void set_bar_count(unsigned count) {bar_count=count;} + isize = 0; + } + bool valid() const { return m_decoded; } + virtual void print_insn(FILE *fp) const { + fprintf(fp, " [inst @ pc=0x%04x] ", pc); + } + bool is_load() const { + return (op == LOAD_OP || op == TENSOR_CORE_LOAD_OP || + memory_op == memory_load); + } + bool is_store() const { + return (op == STORE_OP || op == TENSOR_CORE_STORE_OP || + memory_op == memory_store); + } + unsigned get_num_operands() const { return num_operands; } + unsigned get_num_regs() const { return num_regs; } + void set_num_regs(unsigned num) { num_regs = num; } + void set_num_operands(unsigned num) { num_operands = num; } + void set_bar_id(unsigned id) { bar_id = id; } + void set_bar_count(unsigned count) { bar_count = count; } - address_type pc; // program counter address of instruction - unsigned isize; // size of instruction in bytes - op_type op; // opcode (uarch visible) + address_type pc; // program counter address of instruction + unsigned isize; // size of instruction in bytes + op_type op; // opcode (uarch visible) - barrier_type bar_type; - reduction_type red_type; - unsigned bar_id; - unsigned bar_count; + barrier_type bar_type; + reduction_type red_type; + unsigned bar_id; + unsigned bar_count; - types_of_operands oprnd_type; // code (uarch visible) identify if the operation is an interger or a floating point - special_ops sp_op; // code (uarch visible) identify if int_alu, fp_alu, int_mul .... - operation_pipeline op_pipe; // code (uarch visible) identify the pipeline of the operation (SP, SFU or MEM) - mem_operation mem_op; // code (uarch visible) identify memory type - _memory_op_t memory_op; // memory_op used by ptxplus - unsigned num_operands; - unsigned num_regs; // count vector operand as one register operand + types_of_operands oprnd_type; // code (uarch visible) identify if the + // operation is an interger or a floating point + special_ops + sp_op; // code (uarch visible) identify if int_alu, fp_alu, int_mul .... + operation_pipeline op_pipe; // code (uarch visible) identify the pipeline of + // the operation (SP, SFU or MEM) + mem_operation mem_op; // code (uarch visible) identify memory type + _memory_op_t memory_op; // memory_op used by ptxplus + unsigned num_operands; + unsigned num_regs; // count vector operand as one register operand - address_type reconvergence_pc; // -1 => not a branch, -2 => use function return address - - unsigned out[8]; - unsigned outcount; - unsigned in[24]; - unsigned incount; - unsigned char is_vectorin; - unsigned char is_vectorout; - int pred; // predicate register number - int ar1, ar2; - // register number for bank conflict evaluation - struct { - int dst[MAX_REG_OPERANDS]; - int src[MAX_REG_OPERANDS]; - } arch_reg; - //int arch_reg[MAX_REG_OPERANDS]; // register number for bank conflict evaluation - unsigned latency; // operation latency - unsigned initiation_interval; + address_type reconvergence_pc; // -1 => not a branch, -2 => use function + // return address - unsigned data_size; // what is the size of the word being operated on? - memory_space_t space; - cache_operator_type cache_op; + unsigned out[8]; + unsigned outcount; + unsigned in[24]; + unsigned incount; + unsigned char is_vectorin; + unsigned char is_vectorout; + int pred; // predicate register number + int ar1, ar2; + // register number for bank conflict evaluation + struct { + int dst[MAX_REG_OPERANDS]; + int src[MAX_REG_OPERANDS]; + } arch_reg; + // int arch_reg[MAX_REG_OPERANDS]; // register number for bank conflict + // evaluation + unsigned latency; // operation latency + unsigned initiation_interval; -protected: - bool m_decoded; - virtual void pre_decode() {} -}; + unsigned data_size; // what is the size of the word being operated on? + memory_space_t space; + cache_operator_type cache_op; -enum divergence_support_t { - POST_DOMINATOR = 1, - NUM_SIMD_MODEL + protected: + bool m_decoded; + virtual void pre_decode() {} }; +enum divergence_support_t { POST_DOMINATOR = 1, NUM_SIMD_MODEL }; + const unsigned MAX_ACCESSES_PER_INSN_PER_THREAD = 8; -class warp_inst_t: public inst_t { -public: - // constructors - warp_inst_t() - { - m_uid=0; - m_empty=true; - m_config=NULL; - } - warp_inst_t( const core_config *config ) - { - m_uid=0; - assert(config->warp_size<=MAX_WARP_SIZE); - m_config=config; - m_empty=true; - m_isatomic=false; - m_per_scalar_thread_valid=false; - m_mem_accesses_created=false; - m_cache_hit=false; - m_is_printf=false; - m_is_cdp = 0; - } - virtual ~warp_inst_t(){ - } +class warp_inst_t : public inst_t { + public: + // constructors + warp_inst_t() { + m_uid = 0; + m_empty = true; + m_config = NULL; + } + warp_inst_t(const core_config *config) { + m_uid = 0; + assert(config->warp_size <= MAX_WARP_SIZE); + m_config = config; + m_empty = true; + m_isatomic = false; + m_per_scalar_thread_valid = false; + m_mem_accesses_created = false; + m_cache_hit = false; + m_is_printf = false; + m_is_cdp = 0; + } + virtual ~warp_inst_t() {} - // modifiers - void broadcast_barrier_reduction( const active_mask_t& access_mask); - void do_atomic(bool forceDo=false); - void do_atomic( const active_mask_t& access_mask, bool forceDo=false ); - void clear() - { - m_empty=true; - } + // modifiers + void broadcast_barrier_reduction(const active_mask_t &access_mask); + void do_atomic(bool forceDo = false); + void do_atomic(const active_mask_t &access_mask, bool forceDo = false); + void clear() { m_empty = true; } - void issue( const active_mask_t &mask, unsigned warp_id, unsigned long long cycle, int dynamic_warp_id, int sch_id ); + void issue(const active_mask_t &mask, unsigned warp_id, + unsigned long long cycle, int dynamic_warp_id, int sch_id); - const active_mask_t & get_active_mask() const - { - return m_warp_active_mask; - } - void completed( unsigned long long cycle ) const; // stat collection: called when the instruction is completed + const active_mask_t &get_active_mask() const { return m_warp_active_mask; } + void completed(unsigned long long cycle) + const; // stat collection: called when the instruction is completed - void set_addr( unsigned n, new_addr_type addr ) - { - if( !m_per_scalar_thread_valid ) { - m_per_scalar_thread.resize(m_config->warp_size); - m_per_scalar_thread_valid=true; - } - m_per_scalar_thread[n].memreqaddr[0] = addr; + void set_addr(unsigned n, new_addr_type addr) { + if (!m_per_scalar_thread_valid) { + m_per_scalar_thread.resize(m_config->warp_size); + m_per_scalar_thread_valid = true; } - void set_addr( unsigned n, new_addr_type* addr, unsigned num_addrs ) - { - if( !m_per_scalar_thread_valid ) { - m_per_scalar_thread.resize(m_config->warp_size); - m_per_scalar_thread_valid=true; - } - assert(num_addrs <= MAX_ACCESSES_PER_INSN_PER_THREAD); - for(unsigned i=0; i<num_addrs; i++) - m_per_scalar_thread[n].memreqaddr[i] = addr[i]; + m_per_scalar_thread[n].memreqaddr[0] = addr; + } + void set_addr(unsigned n, new_addr_type *addr, unsigned num_addrs) { + if (!m_per_scalar_thread_valid) { + m_per_scalar_thread.resize(m_config->warp_size); + m_per_scalar_thread_valid = true; } - void print_m_accessq(){ - - if(accessq_empty()) - return; - else{ - printf("Printing mem access generated\n"); - std::list<mem_access_t>::iterator it; - for (it = m_accessq.begin(); it != m_accessq.end(); ++it){ - printf("MEM_TXN_GEN:%s:%llx, Size:%d \n",mem_access_type_str(it->get_type()), it->get_addr(),it->get_size()); - } - } - } - struct transaction_info { - std::bitset<4> chunks; // bitmask: 32-byte chunks accessed - mem_access_byte_mask_t bytes; - active_mask_t active; // threads in this transaction - - bool test_bytes(unsigned start_bit, unsigned end_bit) { - for( unsigned i=start_bit; i<=end_bit; i++ ) - if(bytes.test(i)) - return true; - return false; - } - }; - - void generate_mem_accesses(); - void memory_coalescing_arch( bool is_write, mem_access_type access_type ); - void memory_coalescing_arch_atomic( bool is_write, mem_access_type access_type ); - void memory_coalescing_arch_reduce_and_send( bool is_write, mem_access_type access_type, const transaction_info &info, new_addr_type addr, unsigned segment_size ); - - void add_callback( unsigned lane_id, - void (*function)(const class inst_t*, class ptx_thread_info*), - const inst_t *inst, - class ptx_thread_info *thread, - bool atomic) - { - if( !m_per_scalar_thread_valid ) { - m_per_scalar_thread.resize(m_config->warp_size); - m_per_scalar_thread_valid=true; - if(atomic) m_isatomic=true; - } - m_per_scalar_thread[lane_id].callback.function = function; - m_per_scalar_thread[lane_id].callback.instruction = inst; - m_per_scalar_thread[lane_id].callback.thread = thread; + assert(num_addrs <= MAX_ACCESSES_PER_INSN_PER_THREAD); + for (unsigned i = 0; i < num_addrs; i++) + m_per_scalar_thread[n].memreqaddr[i] = addr[i]; + } + void print_m_accessq() { + if (accessq_empty()) + return; + else { + printf("Printing mem access generated\n"); + std::list<mem_access_t>::iterator it; + for (it = m_accessq.begin(); it != m_accessq.end(); ++it) { + printf("MEM_TXN_GEN:%s:%llx, Size:%d \n", + mem_access_type_str(it->get_type()), it->get_addr(), + it->get_size()); + } } - void set_active( const active_mask_t &active ); - - void clear_active( const active_mask_t &inactive ); - void set_not_active( unsigned lane_id ); + } + struct transaction_info { + std::bitset<4> chunks; // bitmask: 32-byte chunks accessed + mem_access_byte_mask_t bytes; + active_mask_t active; // threads in this transaction - // accessors - virtual void print_insn(FILE *fp) const - { - fprintf(fp," [inst @ pc=0x%04x] ", pc ); - for (int i=(int)m_config->warp_size-1; i>=0; i--) - fprintf(fp, "%c", ((m_warp_active_mask[i])?'1':'0') ); - } - bool active( unsigned thread ) const { return m_warp_active_mask.test(thread); } - unsigned active_count() const { return m_warp_active_mask.count(); } - unsigned issued_count() const { assert(m_empty == false); return m_warp_issued_mask.count(); } // for instruction counting - bool empty() const { return m_empty; } - unsigned warp_id() const - { - assert( !m_empty ); - return m_warp_id; - } - unsigned warp_id_func() const // to be used in functional simulations only - { - return m_warp_id; - } - unsigned dynamic_warp_id() const - { - assert( !m_empty ); - return m_dynamic_warp_id; - } - bool has_callback( unsigned n ) const - { - return m_warp_active_mask[n] && m_per_scalar_thread_valid && - (m_per_scalar_thread[n].callback.function!=NULL); - } - new_addr_type get_addr( unsigned n ) const - { - assert( m_per_scalar_thread_valid ); - return m_per_scalar_thread[n].memreqaddr[0]; + bool test_bytes(unsigned start_bit, unsigned end_bit) { + for (unsigned i = start_bit; i <= end_bit; i++) + if (bytes.test(i)) return true; + return false; } + }; - bool isatomic() const { return m_isatomic; } - - unsigned warp_size() const { return m_config->warp_size; } - - bool accessq_empty() const { return m_accessq.empty(); } - unsigned accessq_count() const { return m_accessq.size(); } - const mem_access_t &accessq_back() { return m_accessq.back(); } - void accessq_pop_back() { m_accessq.pop_back(); } + void generate_mem_accesses(); + void memory_coalescing_arch(bool is_write, mem_access_type access_type); + void memory_coalescing_arch_atomic(bool is_write, + mem_access_type access_type); + void memory_coalescing_arch_reduce_and_send(bool is_write, + mem_access_type access_type, + const transaction_info &info, + new_addr_type addr, + unsigned segment_size); - bool dispatch_delay() - { - if( cycles > 0 ) - cycles--; - return cycles > 0; + void add_callback(unsigned lane_id, + void (*function)(const class inst_t *, + class ptx_thread_info *), + const inst_t *inst, class ptx_thread_info *thread, + bool atomic) { + if (!m_per_scalar_thread_valid) { + m_per_scalar_thread.resize(m_config->warp_size); + m_per_scalar_thread_valid = true; + if (atomic) m_isatomic = true; } + m_per_scalar_thread[lane_id].callback.function = function; + m_per_scalar_thread[lane_id].callback.instruction = inst; + m_per_scalar_thread[lane_id].callback.thread = thread; + } + void set_active(const active_mask_t &active); - bool has_dispatch_delay(){ - return cycles > 0; - } + void clear_active(const active_mask_t &inactive); + void set_not_active(unsigned lane_id); - void print( FILE *fout ) const; - unsigned get_uid() const { return m_uid; } - unsigned get_schd_id() const { return m_scheduler_id; } + // accessors + virtual void print_insn(FILE *fp) const { + fprintf(fp, " [inst @ pc=0x%04x] ", pc); + for (int i = (int)m_config->warp_size - 1; i >= 0; i--) + fprintf(fp, "%c", ((m_warp_active_mask[i]) ? '1' : '0')); + } + bool active(unsigned thread) const { return m_warp_active_mask.test(thread); } + unsigned active_count() const { return m_warp_active_mask.count(); } + unsigned issued_count() const { + assert(m_empty == false); + return m_warp_issued_mask.count(); + } // for instruction counting + bool empty() const { return m_empty; } + unsigned warp_id() const { + assert(!m_empty); + return m_warp_id; + } + unsigned warp_id_func() const // to be used in functional simulations only + { + return m_warp_id; + } + unsigned dynamic_warp_id() const { + assert(!m_empty); + return m_dynamic_warp_id; + } + bool has_callback(unsigned n) const { + return m_warp_active_mask[n] && m_per_scalar_thread_valid && + (m_per_scalar_thread[n].callback.function != NULL); + } + new_addr_type get_addr(unsigned n) const { + assert(m_per_scalar_thread_valid); + return m_per_scalar_thread[n].memreqaddr[0]; + } -protected: + bool isatomic() const { return m_isatomic; } - unsigned m_uid; - bool m_empty; - bool m_cache_hit; - unsigned long long issue_cycle; - unsigned cycles; // used for implementing initiation interval delay - bool m_isatomic; - bool m_is_printf; - unsigned m_warp_id; - unsigned m_dynamic_warp_id; - const core_config *m_config; - active_mask_t m_warp_active_mask; // dynamic active mask for timing model (after predication) - active_mask_t m_warp_issued_mask; // active mask at issue (prior to predication test) -- for instruction counting + unsigned warp_size() const { return m_config->warp_size; } - struct per_thread_info { - per_thread_info() { - for(unsigned i=0; i<MAX_ACCESSES_PER_INSN_PER_THREAD; i++) - memreqaddr[i] = 0; - } - dram_callback_t callback; - new_addr_type memreqaddr[MAX_ACCESSES_PER_INSN_PER_THREAD]; // effective address, upto 8 different requests (to support 32B access in 8 chunks of 4B each) - }; - bool m_per_scalar_thread_valid; - std::vector<per_thread_info> m_per_scalar_thread; - bool m_mem_accesses_created; - std::list<mem_access_t> m_accessq; + bool accessq_empty() const { return m_accessq.empty(); } + unsigned accessq_count() const { return m_accessq.size(); } + const mem_access_t &accessq_back() { return m_accessq.back(); } + void accessq_pop_back() { m_accessq.pop_back(); } - unsigned m_scheduler_id; //the scheduler that issues this inst + bool dispatch_delay() { + if (cycles > 0) cycles--; + return cycles > 0; + } - //Jin: cdp support -public: - int m_is_cdp; - -}; + bool has_dispatch_delay() { return cycles > 0; } -void move_warp( warp_inst_t *&dst, warp_inst_t *&src ); + void print(FILE *fout) const; + unsigned get_uid() const { return m_uid; } + unsigned get_schd_id() const { return m_scheduler_id; } -size_t get_kernel_code_size( class function_info *entry ); -class checkpoint -{ -public: + protected: + unsigned m_uid; + bool m_empty; + bool m_cache_hit; + unsigned long long issue_cycle; + unsigned cycles; // used for implementing initiation interval delay + bool m_isatomic; + bool m_is_printf; + unsigned m_warp_id; + unsigned m_dynamic_warp_id; + const core_config *m_config; + active_mask_t m_warp_active_mask; // dynamic active mask for timing model + // (after predication) + active_mask_t + m_warp_issued_mask; // active mask at issue (prior to predication test) + // -- for instruction counting - checkpoint(); - ~checkpoint(){ - printf("clasfsfss destructed\n"); + struct per_thread_info { + per_thread_info() { + for (unsigned i = 0; i < MAX_ACCESSES_PER_INSN_PER_THREAD; i++) + memreqaddr[i] = 0; } + dram_callback_t callback; + new_addr_type + memreqaddr[MAX_ACCESSES_PER_INSN_PER_THREAD]; // effective address, + // upto 8 different + // requests (to support + // 32B access in 8 chunks + // of 4B each) + }; + bool m_per_scalar_thread_valid; + std::vector<per_thread_info> m_per_scalar_thread; + bool m_mem_accesses_created; + std::list<mem_access_t> m_accessq; - void load_global_mem(class memory_space *temp_mem, char * f1name); - void store_global_mem(class memory_space *mem, char * fname , char * format); - unsigned radnom; + unsigned m_scheduler_id; // the scheduler that issues this inst + // Jin: cdp support + public: + int m_is_cdp; +}; + +void move_warp(warp_inst_t *&dst, warp_inst_t *&src); + +size_t get_kernel_code_size(class function_info *entry); +class checkpoint { + public: + checkpoint(); + ~checkpoint() { printf("clasfsfss destructed\n"); } + void load_global_mem(class memory_space *temp_mem, char *f1name); + void store_global_mem(class memory_space *mem, char *fname, char *format); + unsigned radnom; }; /* - * This abstract class used as a base for functional and performance and simulation, it has basic functional simulation - * data structures and procedures. + * This abstract class used as a base for functional and performance and + * simulation, it has basic functional simulation data structures and + * procedures. */ class core_t { - public: - core_t( gpgpu_sim *gpu, - kernel_info_t *kernel, - unsigned warp_size, - unsigned threads_per_shader ) - : m_gpu( gpu ), - m_kernel( kernel ), - m_simt_stack( NULL ), - m_thread( NULL ), - m_warp_size( warp_size ) - { - m_warp_count = threads_per_shader/m_warp_size; - // Handle the case where the number of threads is not a - // multiple of the warp size - if ( threads_per_shader % m_warp_size != 0 ) { - m_warp_count += 1; - } - assert( m_warp_count * m_warp_size > 0 ); - m_thread = ( ptx_thread_info** ) - calloc( m_warp_count * m_warp_size, - sizeof( ptx_thread_info* ) ); - initilizeSIMTStack(m_warp_count,m_warp_size); + public: + core_t(gpgpu_sim *gpu, kernel_info_t *kernel, unsigned warp_size, + unsigned threads_per_shader) + : m_gpu(gpu), + m_kernel(kernel), + m_simt_stack(NULL), + m_thread(NULL), + m_warp_size(warp_size) { + m_warp_count = threads_per_shader / m_warp_size; + // Handle the case where the number of threads is not a + // multiple of the warp size + if (threads_per_shader % m_warp_size != 0) { + m_warp_count += 1; + } + assert(m_warp_count * m_warp_size > 0); + m_thread = (ptx_thread_info **)calloc(m_warp_count * m_warp_size, + sizeof(ptx_thread_info *)); + initilizeSIMTStack(m_warp_count, m_warp_size); - for(unsigned i=0; i<MAX_CTA_PER_SHADER; i++){ - for(unsigned j=0; j<MAX_BARRIERS_PER_CTA; j++){ - reduction_storage[i][j]=0; - } - } + for (unsigned i = 0; i < MAX_CTA_PER_SHADER; i++) { + for (unsigned j = 0; j < MAX_BARRIERS_PER_CTA; j++) { + reduction_storage[i][j] = 0; + } + } + } + virtual ~core_t() { free(m_thread); } + virtual void warp_exit(unsigned warp_id) = 0; + virtual bool warp_waiting_at_barrier(unsigned warp_id) const = 0; + virtual void checkExecutionStatusAndUpdate(warp_inst_t &inst, unsigned t, + unsigned tid) = 0; + class gpgpu_sim *get_gpu() { + return m_gpu; + } + void execute_warp_inst_t(warp_inst_t &inst, unsigned warpId = (unsigned)-1); + bool ptx_thread_done(unsigned hw_thread_id) const; + void updateSIMTStack(unsigned warpId, warp_inst_t *inst); + void initilizeSIMTStack(unsigned warp_count, unsigned warps_size); + void deleteSIMTStack(); + warp_inst_t getExecuteWarp(unsigned warpId); + void get_pdom_stack_top_info(unsigned warpId, unsigned *pc, + unsigned *rpc) const; + kernel_info_t *get_kernel_info() { return m_kernel; } + class ptx_thread_info **get_thread_info() { + return m_thread; + } + unsigned get_warp_size() const { return m_warp_size; } + void and_reduction(unsigned ctaid, unsigned barid, bool value) { + reduction_storage[ctaid][barid] &= value; + } + void or_reduction(unsigned ctaid, unsigned barid, bool value) { + reduction_storage[ctaid][barid] |= value; + } + void popc_reduction(unsigned ctaid, unsigned barid, bool value) { + reduction_storage[ctaid][barid] += value; + } + unsigned get_reduction_value(unsigned ctaid, unsigned barid) { + return reduction_storage[ctaid][barid]; + } - } - virtual ~core_t() { free(m_thread); } - virtual void warp_exit( unsigned warp_id ) = 0; - virtual bool warp_waiting_at_barrier( unsigned warp_id ) const = 0; - virtual void checkExecutionStatusAndUpdate(warp_inst_t &inst, unsigned t, unsigned tid)=0; - class gpgpu_sim * get_gpu() {return m_gpu;} - void execute_warp_inst_t(warp_inst_t &inst, unsigned warpId =(unsigned)-1); - bool ptx_thread_done( unsigned hw_thread_id ) const ; - void updateSIMTStack(unsigned warpId, warp_inst_t * inst); - void initilizeSIMTStack(unsigned warp_count, unsigned warps_size); - void deleteSIMTStack(); - warp_inst_t getExecuteWarp(unsigned warpId); - void get_pdom_stack_top_info( unsigned warpId, unsigned *pc, unsigned *rpc ) const; - kernel_info_t * get_kernel_info(){ return m_kernel;} - class ptx_thread_info ** get_thread_info() { return m_thread; } - unsigned get_warp_size() const { return m_warp_size; } - void and_reduction(unsigned ctaid, unsigned barid, bool value) { reduction_storage[ctaid][barid] &= value; } - void or_reduction(unsigned ctaid, unsigned barid, bool value) { reduction_storage[ctaid][barid] |= value; } - void popc_reduction(unsigned ctaid, unsigned barid, bool value) { reduction_storage[ctaid][barid] += value;} - unsigned get_reduction_value(unsigned ctaid, unsigned barid) {return reduction_storage[ctaid][barid];} - protected: - class gpgpu_sim *m_gpu; - kernel_info_t *m_kernel; - simt_stack **m_simt_stack; // pdom based reconvergence context for each warp - class ptx_thread_info ** m_thread; - unsigned m_warp_size; - unsigned m_warp_count; - unsigned reduction_storage[MAX_CTA_PER_SHADER][MAX_BARRIERS_PER_CTA]; + protected: + class gpgpu_sim *m_gpu; + kernel_info_t *m_kernel; + simt_stack **m_simt_stack; // pdom based reconvergence context for each warp + class ptx_thread_info **m_thread; + unsigned m_warp_size; + unsigned m_warp_count; + unsigned reduction_storage[MAX_CTA_PER_SHADER][MAX_BARRIERS_PER_CTA]; }; - -//register that can hold multiple instructions. +// register that can hold multiple instructions. class register_set { -public: - register_set(unsigned num, const char* name){ - for( unsigned i = 0; i < num; i++ ) { - regs.push_back(new warp_inst_t()); - } - m_name = name; - } - bool has_free(){ - for( unsigned i = 0; i < regs.size(); i++ ) { - if( regs[i]->empty() ) { - return true; - } - } - return false; - } - bool has_free(bool sub_core_model, unsigned reg_id){ - //in subcore model, each sched has a one specific reg to use (based on sched id) - if(!sub_core_model) - return has_free(); + public: + register_set(unsigned num, const char *name) { + for (unsigned i = 0; i < num; i++) { + regs.push_back(new warp_inst_t()); + } + m_name = name; + } + bool has_free() { + for (unsigned i = 0; i < regs.size(); i++) { + if (regs[i]->empty()) { + return true; + } + } + return false; + } + bool has_free(bool sub_core_model, unsigned reg_id) { + // in subcore model, each sched has a one specific reg to use (based on + // sched id) + if (!sub_core_model) return has_free(); - assert(reg_id < regs.size()); - return regs[reg_id]->empty(); - } - bool has_ready(){ - for( unsigned i = 0; i < regs.size(); i++ ) { - if( not regs[i]->empty() ) { - return true; - } - } - return false; - } + assert(reg_id < regs.size()); + return regs[reg_id]->empty(); + } + bool has_ready() { + for (unsigned i = 0; i < regs.size(); i++) { + if (not regs[i]->empty()) { + return true; + } + } + return false; + } - void move_in( warp_inst_t *&src ){ - warp_inst_t** free = get_free(); - move_warp(*free, src); - } - //void copy_in( warp_inst_t* src ){ - // src->copy_contents_to(*get_free()); - //} - void move_out_to( warp_inst_t *&dest ){ - warp_inst_t **ready=get_ready(); - move_warp(dest, *ready); - } + void move_in(warp_inst_t *&src) { + warp_inst_t **free = get_free(); + move_warp(*free, src); + } + // void copy_in( warp_inst_t* src ){ + // src->copy_contents_to(*get_free()); + //} + void move_out_to(warp_inst_t *&dest) { + warp_inst_t **ready = get_ready(); + move_warp(dest, *ready); + } - warp_inst_t** get_ready(){ - warp_inst_t** ready; - ready = NULL; - for( unsigned i = 0; i < regs.size(); i++ ) { - if( not regs[i]->empty() ) { - if( ready and (*ready)->get_uid() < regs[i]->get_uid() ) { - // ready is oldest - } else { - ready = ®s[i]; - } - } - } - return ready; - } + warp_inst_t **get_ready() { + warp_inst_t **ready; + ready = NULL; + for (unsigned i = 0; i < regs.size(); i++) { + if (not regs[i]->empty()) { + if (ready and (*ready)->get_uid() < regs[i]->get_uid()) { + // ready is oldest + } else { + ready = ®s[i]; + } + } + } + return ready; + } - void print(FILE* fp) const{ - fprintf(fp, "%s : @%p\n", m_name, this); - for( unsigned i = 0; i < regs.size(); i++ ) { - fprintf(fp, " "); - regs[i]->print(fp); - fprintf(fp, "\n"); - } - } + void print(FILE *fp) const { + fprintf(fp, "%s : @%p\n", m_name, this); + for (unsigned i = 0; i < regs.size(); i++) { + fprintf(fp, " "); + regs[i]->print(fp); + fprintf(fp, "\n"); + } + } - warp_inst_t ** get_free(){ - for( unsigned i = 0; i < regs.size(); i++ ) { - if( regs[i]->empty() ) { - return ®s[i]; - } - } - assert(0 && "No free registers found"); - return NULL; - } + warp_inst_t **get_free() { + for (unsigned i = 0; i < regs.size(); i++) { + if (regs[i]->empty()) { + return ®s[i]; + } + } + assert(0 && "No free registers found"); + return NULL; + } - warp_inst_t ** get_free(bool sub_core_model, unsigned reg_id){ - //in subcore model, each sched has a one specific reg to use (based on sched id) - if(!sub_core_model) - return get_free(); + warp_inst_t **get_free(bool sub_core_model, unsigned reg_id) { + // in subcore model, each sched has a one specific reg to use (based on + // sched id) + if (!sub_core_model) return get_free(); - assert(reg_id < regs.size()); - if( regs[reg_id]->empty() ) { - return ®s[reg_id]; - } - assert(0 && "No free register found"); - return NULL; - } + assert(reg_id < regs.size()); + if (regs[reg_id]->empty()) { + return ®s[reg_id]; + } + assert(0 && "No free register found"); + return NULL; + } - unsigned get_size(){ - return regs.size(); - } + unsigned get_size() { return regs.size(); } -private: - std::vector<warp_inst_t*> regs; - const char* m_name; + private: + std::vector<warp_inst_t *> regs; + const char *m_name; }; -#endif // #ifdef __cplusplus +#endif // #ifdef __cplusplus -#endif // #ifndef ABSTRACT_HARDWARE_MODEL_INCLUDED +#endif // #ifndef ABSTRACT_HARDWARE_MODEL_INCLUDED |
