diff options
| author | Tor Aamodt <[email protected]> | 2010-10-01 08:55:28 -0800 |
|---|---|---|
| committer | Tor Aamodt <[email protected]> | 2010-10-01 08:55:28 -0800 |
| commit | 11b308e7363e937966b035b4891db32b4eece3bf (patch) | |
| tree | 50ca4c9ad6f163ac4acb2bf505e64dfebed66947 /src/gpgpu-sim/shader.h | |
| parent | bb820c116764d7a1b8e071137d32b74e7f34dd2f (diff) | |
integrating recent changes from fermi-test into fermi
(i'll use "fermi" for more disruptive changes to the pipeline model such
as updating the MSHRs and getting rid of the warp tracker, ripping out DWF, etc...)
[git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 7805]
Diffstat (limited to 'src/gpgpu-sim/shader.h')
| -rw-r--r-- | src/gpgpu-sim/shader.h | 1186 |
1 files changed, 714 insertions, 472 deletions
diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index 1e62995..44206af 100644 --- a/src/gpgpu-sim/shader.h +++ b/src/gpgpu-sim/shader.h @@ -72,6 +72,10 @@ #include <set> #include <vector> #include <list> +#include <bitset> +#include <utility> +#include <algorithm> +#include <deque> #include "../cuda-sim/ptx.tab.h" #include "../cuda-sim/dram_callback.h" @@ -82,148 +86,238 @@ #include "dram.h" #include "../abstract_hardware_model.h" #include "scoreboard.h" +#include "mem_fetch.h" +#include "stats.h" #ifndef SHADER_H #define SHADER_H #define NO_OP_FLAG 0xFF -//READ_PACKET_SIZE: bytes: 6 address (flit can specify chanel so this gives up to ~2GB/channel, so good for now), 2 bytes [shaderid + mshrid](14 bits) + req_size(0-2 bits (if req_size variable) - so up to 2^14 = 16384 mshr total +/* READ_PACKET_SIZE: + bytes: 6 address (flit can specify chanel so this gives up to ~2GB/channel, so good for now), + 2 bytes [shaderid + mshrid](14 bits) + req_size(0-2 bits if req_size variable) - so up to 2^14 = 16384 mshr total + */ + #define READ_PACKET_SIZE 8 + //WRITE_PACKET_SIZE: bytes: 6 address, 2 miscelaneous. #define WRITE_PACKET_SIZE 8 -#include <bitset> -const unsigned partial_write_mask_bits = 128; //must be at least size of largest memory access. -typedef std::bitset<partial_write_mask_bits> partial_write_mask_t; - #define WRITE_MASK_SIZE 8 #define NO_PARTIAL_WRITE (partial_write_mask_t()) -//this is used a lot of places where it maybe should be more variable? #define WORD_SIZE 4 //Set a hard limit of 32 CTAs per shader [cuda only has 8] #define MAX_CTA_PER_SHADER 32 -typedef unsigned op_type; - -enum { - NO_RECONVERGE = 0, - POST_DOMINATOR = 1, - MIMD = 2, - DWF = 3, - NUM_SIMD_MODEL -}; - -//Defines number of threads grouped together to be executed together - +class thread_ctx_t { +public: + class ptx_thread_info *m_functional_model_thread_state; + unsigned m_cta_id; // hardware CTA this thread belongs -typedef struct { + // used for controlling fetch + bool m_avail4fetch; // false if instruction from thread is in pipeline + bool m_in_scheduler; // DWF error checking + bool m_waiting_at_barrier; // DWF and MIMD models + bool m_reached_barrier; // DWF only - address_type pc; + // per thread stats (ac stands for accumulative). + unsigned n_insn; + unsigned n_insn_ac; + unsigned n_l1_mis_ac; + unsigned n_l1_mrghit_ac; + unsigned n_l1_access_ac; +}; - op_type op; - memory_space_t space; +class shd_warp_t { +public: + shd_warp_t( class shader_core_ctx *shader, unsigned warp_size) + : m_shader(shader), m_warp_size(warp_size) + { + m_stores_outstanding=0; + m_inst_in_pipeline=0; + reset(); + } + void reset() + { + assert( m_stores_outstanding==0); + assert( m_inst_in_pipeline==0); + m_imiss_pending=false; + m_warp_id=(unsigned)-1; + n_completed = m_warp_size; + n_avail4fetch = n_waiting_at_barrier = 0; + m_n_atomic=0; + m_membar=false; + m_done_exit=false; + m_last_fetch=0; + m_next=0; + for(unsigned i=0;i<IBUFFER_SIZE;i++) + m_ibuffer[i]=NULL; + } + void init( address_type start_pc, unsigned wid, unsigned active ) + { + m_warp_id=wid; + m_next_pc=start_pc; + assert( n_completed >= active ); + assert( n_completed <= m_warp_size); + assert( n_avail4fetch < m_warp_size ); + n_completed -= active; // active threads are not yet completed + n_avail4fetch += active; // number of threads in warp available to be fetched + } - unsigned long long int memreqaddr; - //Each instruction keeps track of which hardware thread it came from - short hw_thread_id; - short wlane; + bool done(); + bool waiting(); - /* reg label of the instruction */ - unsigned out[4]; - unsigned in[4]; - unsigned char is_vectorin; - unsigned char is_vectorout; - int pred; - int ar1, ar2; - int arch_reg[MAX_REG_OPERANDS]; // register number for bank conflict evaluation - unsigned data_size; // what is the size of the word being operated on? - unsigned cycles; // number of cycles taken by current instruction + bool done_exit() const { return m_done_exit; } + void set_done_exit() { m_done_exit=true; } - int reg_bank_access_pending; - int reg_bank_conflict_stall_checked; // flag to turn off register bank conflict checker to avoid double stalling + void print( FILE *fout ) const; + void print_ibuffer( FILE *fout ) const; - unsigned inst_type; + unsigned get_avail4fetch() const { return n_avail4fetch; } + void inc_avail4fetch() { n_avail4fetch++; } + void dec_avail4fetch() { n_avail4fetch--; } - unsigned priority; + unsigned get_n_completed() const { return n_completed; } + void inc_n_completed() { n_completed++; } - unsigned uid; + void set_last_fetch( unsigned long long sim_cycle ) { m_last_fetch=sim_cycle; } - void *ptx_thd_info; - dram_callback_t callback; - unsigned warp_active_mask; - unsigned long long ts_cycle; - unsigned long long if_cycle; - unsigned long long id_cycle; - unsigned long long ex_cycle; - unsigned long long mm_cycle; + unsigned get_n_atomic() const { return m_n_atomic; } + void inc_n_atomic() { m_n_atomic++; } + void dec_n_atomic() { m_n_atomic--; } - bool cache_miss; + void inc_waiting_at_barrier() { n_waiting_at_barrier++; } + void clear_waiting_at_barrier() { n_waiting_at_barrier=0; } -} inst_t; + void set_membar() { m_membar=true; } + void clear_membar() { m_membar=false; } + bool get_membar() const { return m_membar; } + address_type get_pc() const { return m_next_pc; } + void set_next_pc( address_type pc ) { m_next_pc = pc; } -typedef struct { + void ibuffer_fill( unsigned slot, const inst_t *pI ) + { + assert(slot < IBUFFER_SIZE ); + m_ibuffer[slot]=pI; + m_next=0; + } + bool ibuffer_empty() const + { + for( unsigned i=0; i < IBUFFER_SIZE; i++) + if(m_ibuffer[i]) + return false; + return true; + } + void ibuffer_flush() + { + for(unsigned i=0;i<IBUFFER_SIZE;i++) { + if( m_ibuffer[i] ) + dec_inst_in_pipeline(); + m_ibuffer[i]=NULL; + } + } + const inst_t *ibuffer_next() + { + const inst_t *result = m_ibuffer[m_next]; + return result; + } + void ibuffer_free() + { + m_ibuffer[m_next] = NULL; + } + void ibuffer_step() + { + m_next = (m_next+1)%IBUFFER_SIZE; + } + bool imiss_pending() const { return m_imiss_pending!=NULL; } + void set_imiss_pending( class mshr_entry *mshr ) + { + m_imiss_pending=mshr; + } + void clear_imiss_pending() { m_imiss_pending=NULL; } - class ptx_thread_info *ptx_thd_info; // pointer to the functional state of the thread in cuda-sim + bool stores_done() const { return m_stores_outstanding == 0; } + void inc_store_req() { m_stores_outstanding++; } + void dec_store_req() + { + assert( m_stores_outstanding > 0 ); + m_stores_outstanding--; + } - int avail4fetch; // 1 if its instrucion can be fetch into the pipeline, 0 otherwise - int warp_priority; + bool inst_in_pipeline() const { return m_inst_in_pipeline > 0; } - int id; + void inc_inst_in_pipeline() { m_inst_in_pipeline++; } + void dec_inst_in_pipeline() + { + assert( m_inst_in_pipeline > 0 ); + m_inst_in_pipeline--; + } - //unsigned n_completed; // number of threads in warp completed -- set for first thread in each warp - //unsigned n_avail4fetch; // number of threads in warp available to fetch -- set for first thread in each warp - //int n_waiting_at_barrier; // number of threads in warp that have reached the barrier - unsigned in_scheduler; // used by dynamic warp formation for error check +private: + static const unsigned IBUFFER_SIZE=2; + class shader_core_ctx *m_shader; + unsigned m_warp_id; + unsigned m_warp_size; - int m_waiting_at_barrier; - int m_reached_barrier; + address_type m_next_pc; + unsigned n_completed; // number of threads in warp completed + unsigned n_avail4fetch; // number of threads in warp available to fetch - unsigned n_insn; - unsigned n_insn_ac; - unsigned n_l1_mis_ac, - n_l1_mrghit_ac, - n_l1_access_ac; //used to collect "per thread" l1 miss statistics - // ac stands for accumulative. - unsigned cta_id; // which hardware CTA does this thread belong to? -} thread_ctx_t; + class mshr_entry *m_imiss_pending; + + const inst_t *m_ibuffer[IBUFFER_SIZE]; + unsigned m_next; + + int n_waiting_at_barrier; // number of threads in warp that have reached the barrier + unsigned m_n_atomic; // number of outstanding atomic operations + bool m_membar; // if true, warp is waiting at memory barrier -struct shd_warp_t -{ - shd_warp_t(unsigned warp_size){reset(warp_size); assert(warp_size <= bitset_size);} - void reset(unsigned warp_size){n_completed = warp_size; n_avail4fetch = n_waiting_at_barrier = 0; threads_completed.reset(); threads_functionally_executed.reset();} + bool m_done_exit; // true once thread exit has been registered for threads in this warp - unsigned wid; - unsigned n_completed; // number of threads in warp completed - unsigned n_avail4fetch; // number of threads in warp available to fetch - int n_waiting_at_barrier; // number of threads in warp that have reached the barrier + unsigned long long m_last_fetch; - const static unsigned bitset_size = 32; - std::bitset<bitset_size> threads_completed; - std::bitset<bitset_size> threads_functionally_executed; + unsigned m_stores_outstanding; // number of store requests sent but not yet acknowledged + unsigned m_inst_in_pipeline; }; inline unsigned hw_tid_from_wid(unsigned wid, unsigned warp_size, unsigned i){return wid * warp_size + i;}; inline unsigned wid_from_hw_tid(unsigned tid, unsigned warp_size){return tid/warp_size;}; -typedef struct { - - int m_stack_top; +// bounded stack that implements pdom reconvergence (see MICRO'07 paper) +class pdom_warp_ctx_t { +public: + pdom_warp_ctx_t( unsigned wid, class shader_core_ctx *shdr ); - address_type *m_pc; - unsigned int *m_active_mask; - address_type *m_recvg_pc; - unsigned int *m_calldepth; + void reset(); + void launch( address_type start_pc, unsigned active_mask ); + void pdom_update_warp_mask(); - unsigned long long *m_branch_div_cycle; + unsigned get_active_mask() const; + void get_pdom_stack_top_info( unsigned *pc, unsigned *rpc ); + unsigned get_rp() const; + void print(FILE*fp) const; -} pdom_warp_ctx_t; // bounded stack that implements pdom reconvergence (see MICRO'07 paper) +private: + unsigned m_warp_id; + class shader_core_ctx *m_shader; + unsigned m_stack_top; + unsigned m_warp_size; + + address_type *m_pc; + unsigned int *m_active_mask; + address_type *m_recvg_pc; + unsigned int *m_calldepth; + + unsigned long long *m_branch_div_cycle; +}; enum mshr_status { INITIALIZED = 0, + INVALID, IN_ICNT2MEM, IN_CBTOL2QUEUE, IN_L2TODRAMQUEUE, @@ -257,78 +351,113 @@ enum mem_req_stat { NUM_MEM_REQ_STAT }; #include <vector> -typedef struct mshr_entry_t { -#ifdef _GLIBCXX_DEBUG - //satisfy cxx debug conditions on iterators, needs to be nonsingular to copy, which messes completely with structures containing them. - mshr_entry_t(){ - static std::vector<mshr_entry_t> dummy_vector; - this_mshr = dummy_vector.begin(); //initialize it to something nonsingular so it can be copied. - } -#endif -private: - friend class mshr_shader_unit; - std::vector<mshr_entry_t>::iterator this_mshr; //to ease tracking and update. -public: - unsigned request_uid; - - /* memory address of the data */ - unsigned long long int addr; - - // instructions are stored here. - std::vector<inst_t> insts; - - /* Current stage of the load: fetched or not? */ - bool fetched(){return status == FETCHED;}; - - bool iswrite; - - bool merged_on_other_reqest; //true if waiting for another mshr - this mshr doesn't send a memory request - struct mshr_entry_t *merged_requests; //mshrs waiting on this mshr - enum mshr_status status; - - void *mf; // link to corresponding memory fetch structure - - //unsigned space; //does below. - bool istexture; //if it's a request from the texture cache - bool isconst; //if it's a request from the constant cache - bool islocal; //if it's a request to the local memory of a thread +class mshr_entry { +public: + mshr_entry() + { + m_status = INVALID; + m_merged_requests=NULL; + m_mf=NULL; + m_id=0; + } + void set_id( unsigned n ) { m_id = n; } + void init( new_addr_type address, bool wr, memory_space_t space, unsigned warp_id ); + void clear() { m_insts.clear(); } + void set_mf( class mem_fetch *mf ) { m_mf=mf; } + void add_inst( inst_t inst ) { m_insts.push_back(inst); } + void set_status( enum mshr_status status ); + void merge( mshr_entry *mshr ) + { + //merge this request; + m_merged_requests = mshr; + mshr->m_merged_on_other_reqest = true; + } - bool wt_no_w2cache; //in write_through, sometimes need to prevent writing back returning data into cache, because its been written in the meantime. -} mshr_entry; + dram_callback_t &get_atomic_callback() + { + assert(isatomic()); + return m_insts[0].callback; + } + mshr_entry *get_last_merged() + { + assert(m_status!=INVALID); + mshr_entry *mshr_hit = this; + while (mshr_hit->m_merged_requests) + mshr_hit = mshr_hit->m_merged_requests; + return mshr_hit; + } + void get_insts( std::vector<inst_t> &done_insts ) + { + done_insts.insert(done_insts.end(),m_insts.begin(),m_insts.end()); + } + void add_to_queue( std::deque<mshr_entry*> &q ) + { + // place all merged requests in return queue + mshr_entry *req = this; + while (req) { + q.push_back(req); + req = req->m_merged_requests; + } + } -enum mem_access_type { - GLOBAL_ACC_R = 0, - LOCAL_ACC_R = 1, - CONST_ACC_R = 2, - TEXTURE_ACC_R = 3, - GLOBAL_ACC_W = 4, - LOCAL_ACC_W = 5, - L2_WRBK_ACC = 6, - NUM_MEM_ACCESS_TYPE = 7 + unsigned get_warp_id() const { return m_warp_id; } + bool ismerged() const { return m_merged_on_other_reqest; } + bool fetched() const { return m_status == FETCHED;}; + bool iswrite() const { return m_iswrite; } + bool isinst() const { return m_isinst; } + bool istexture() const { return m_istexture; } + bool isconst() const { return m_isconst; } + bool islocal() const { return m_islocal; } + bool has_inst() const { return m_insts.size()>0; } + unsigned num_inst() const { return m_insts.size(); } + inst_t &get_inst(unsigned n) + { + assert(m_status!=INVALID&&m_insts.size()>0); + return m_insts[n]; + } + unsigned get_insts_uid() const + { + assert(m_status!=INVALID&&m_insts.size()>0); + return m_insts[0].uid; + } + bool isatomic() const + { + assert(m_status!=INVALID); + if( isinst() ) + return false; + assert(m_insts.size()>0); + return (m_insts[0].callback.function != NULL); + } + new_addr_type get_addr() const { return m_addr; } + void print(FILE *fp, unsigned mask) const; + +private: + unsigned m_id; + unsigned m_request_uid; + unsigned m_warp_id; + new_addr_type m_addr; // address being fetched + std::vector<inst_t> m_insts; + bool m_iswrite; + bool m_merged_on_other_reqest; //true if waiting for another mshr - this mshr doesn't send a memory request + struct mshr_entry *m_merged_requests; //mshrs waiting on this mshr + enum mshr_status m_status; + class mem_fetch *m_mf; // link to corresponding memory fetch structure + bool m_isinst; //if it's a request from the instruction cache + bool m_istexture; //if it's a request from the texture cache + bool m_isconst; //if it's a request from the constant cache + bool m_islocal; //if it's a request to the local memory of a thread + bool m_wt_no_w2cache; //in write_through, sometimes need to prevent writing back returning data into cache, because its been written in the meantime. }; - -/* A pointer to the function that glues the shader with the memory hiearchy */ -typedef unsigned char (*fq_push_t)(unsigned long long int addr, int bsize, unsigned char readwrite, - partial_write_mask_t, - int sid, int wid, mshr_entry* mshr, int cache_hits_waiting, - enum mem_access_type mem_acc, address_type pc); - -typedef unsigned char (*fq_has_buffer_t)(unsigned long long int addr, int bsize, bool write, int sid); - const unsigned WARP_PER_CTA_MAX = 32; typedef std::bitset<WARP_PER_CTA_MAX> warp_set_t; -inst_t *first_valid_thread( inst_t *warp ); -void move_warp( inst_t *dst, inst_t *src ); -bool pipeline_regster_empty( inst_t *reg ); -std::list<unsigned> get_regs_written( inst_t *warp ); -int register_bank(int regnum, int tid); +int register_bank(int regnum, int tid, unsigned num_banks, unsigned bank_warp_shift); + class shader_core_ctx; -void shader_print_warp( const shader_core_ctx *shader, inst_t *warp, FILE *fout, int stage_width, int print_mem, int mask ) ; -class opndcoll_rfu_t{ // operand collector based register file unit +class opndcoll_rfu_t { // operand collector based register file unit public: // constructors opndcoll_rfu_t() @@ -343,29 +472,28 @@ public: void init( unsigned num_collectors_alu, unsigned num_collectors_sfu, unsigned num_banks, - const shader_core_ctx *shader ); + shader_core_ctx *shader, + inst_t **alu_port, + inst_t **sfu_port ); // modifiers - void writeback( inst_t *warp ) + bool writeback( const inst_t &fvt ); + bool writeback( inst_t *warp ); // might cause stall + + void step( inst_t *&id_oc_reg ) { - // prefer not to stall writeback - inst_t *fvt=first_valid_thread(warp); - if (!fvt) return; - unsigned tid = fvt->hw_thread_id; - std::list<unsigned> regs = get_regs_written(fvt); - std::list<unsigned>::iterator r; - for( r=regs.begin(); r!=regs.end();r++ ) { - unsigned reg = *r; - unsigned bank = register_bank(reg,tid); - m_arbiter.allocate_bank_for_write(bank,op_t(fvt,reg)); - } + dispatch_ready_cu(); + allocate_reads(); + allocate_cu(id_oc_reg); + process_banks(); } - void step( inst_t *id_oc_reg ) + void step( inst_t *&alu_issue_port, inst_t *&sfu_issue_port ) { dispatch_ready_cu(); allocate_reads(); - allocate_cu(id_oc_reg); + allocate_cu(alu_issue_port); + allocate_cu(sfu_issue_port); process_banks(); } @@ -374,12 +502,14 @@ public: fprintf(fp,"\n"); fprintf(fp,"Operand Collector State:\n"); for( unsigned n=0; n < m_num_collectors; n++ ) { - fprintf(fp," CU-%u: ", n); + fprintf(fp," CU-%2u: ", n); m_cu[n].dump(fp,m_shader); } m_arbiter.dump(fp); } + shader_core_ctx *shader_core() { return m_shader; } + private: void process_banks() @@ -387,61 +517,9 @@ private: m_arbiter.reset_alloction(); } - void dispatch_ready_cu() - { - port_to_du_t::iterator p; - for( p=m_dispatch_units.begin(); p!=m_dispatch_units.end(); ++p ) { - inst_t *port = p->first; - if( !pipeline_regster_empty(port) ) - continue; - dispatch_unit_t &du = p->second; - collector_unit_t *cu = du.find_ready(); - if( cu ) { - cu->dispatch(); - m_free_cu[port].push_back(cu); - } - } - } - - void allocate_cu( inst_t *id_oc_reg ) - { - inst_t *fvi = first_valid_thread(id_oc_reg); - if( fvi ) { - inst_t *port = NULL; - if( fvi->op == SFU_OP ) - port = m_sfu_port; - else - port = m_alu_port; - if( !m_free_cu[port].empty() ) { - collector_unit_t *cu = m_free_cu[port].back(); - m_free_cu[port].pop_back(); - cu->allocate(id_oc_reg); - m_arbiter.add_read_requests(cu); - } - } - } - - void allocate_reads() - { - // process read requests that do not have conflicts - std::list<op_t> allocated = m_arbiter.allocate_reads(); - std::map<unsigned,op_t> read_ops; - for( std::list<op_t>::iterator r=allocated.begin(); r!=allocated.end(); r++ ) { - const op_t &rr = *r; - unsigned reg = rr.get_reg(); - unsigned tid = rr.get_tid(); - unsigned bank = register_bank(reg,tid); - m_arbiter.allocate_for_read(bank,rr); - read_ops[bank] = rr; - } - std::map<unsigned,op_t>::iterator r; - for(r=read_ops.begin();r!=read_ops.end();++r ) { - op_t &op = r->second; - unsigned cu = op.get_oc_id(); - unsigned operand = op.get_operand(); - m_cu[cu].collect_operand(operand); - } - } + void dispatch_ready_cu(); + void allocate_cu( inst_t *&id_oc_reg ); + void allocate_reads(); // types @@ -451,7 +529,7 @@ private: public: op_t() { m_valid = false; } - op_t( collector_unit_t *cu, unsigned op, unsigned reg ) + op_t( collector_unit_t *cu, unsigned op, unsigned reg, unsigned num_banks, unsigned bank_warp_shift ) { m_valid = true; m_fvi=NULL; @@ -459,16 +537,17 @@ private: m_operand = op; m_register = reg; m_tid = cu->get_tid(); - m_bank = register_bank(reg,m_tid); + m_bank = register_bank(reg,m_tid,num_banks,bank_warp_shift); } - op_t( inst_t *fvi, unsigned reg ) + op_t( const inst_t *fvi, unsigned reg, unsigned num_banks, unsigned bank_warp_shift ) { + m_valid=true; m_fvi=fvi; m_register=reg; m_cu=NULL; m_operand = -1; m_tid = fvi->hw_thread_id; - m_bank = register_bank(reg,m_tid); + m_bank = register_bank(reg,m_tid,num_banks,bank_warp_shift); } // accessors @@ -487,7 +566,7 @@ private: if(m_cu) fprintf(fp," <R%u, CU:%u, w:%02u> ", m_register,m_cu->get_id(),m_cu->get_warp_id()); else if( m_fvi ) - fprintf(fp," <R%u, w:%02u> ", m_register,m_tid/::warp_size); + fprintf(fp," <R%u, fvi tid:%02u> ", m_register,m_fvi->hw_thread_id ); } std::string get_reg_string() const { @@ -501,7 +580,7 @@ private: private: bool m_valid; collector_unit_t *m_cu; - inst_t *m_fvi; + const inst_t *m_fvi; unsigned m_operand; // operand offset in instruction. e.g., add r1,r2,r3; r2 is oprd 0, r3 is 1 (r1 is dst) unsigned m_register; unsigned m_bank; @@ -591,12 +670,18 @@ private: } } } + bool bank_idle( unsigned bank ) const + { + return m_allocated_bank[bank].is_free(); + } void allocate_bank_for_write( unsigned bank, const op_t &op ) { + assert( bank < m_num_banks ); m_allocated_bank[bank].alloc_write(op); } void allocate_for_read( unsigned bank, const op_t &op ) { + assert( bank < m_num_banks ); m_allocated_bank[bank].alloc_read(op); } void reset_alloction() @@ -622,83 +707,51 @@ private: collector_unit_t() { m_free = true; - m_warp = (inst_t*)calloc(sizeof(inst_t),::warp_size); + m_warp = NULL; m_src_op = new op_t[MAX_REG_OPERANDS]; m_not_ready.reset(); m_tid = -1; m_warp_id = -1; + m_num_banks = 0; + m_bank_warp_shift = 0; } // accessors - bool ready() const - { - return (!m_free) && m_not_ready.none() && pipeline_regster_empty(m_port); - } + bool ready() const; const op_t *get_operands() const { return m_src_op; } - void dump(FILE *fp, const shader_core_ctx *shader ) const - { - if( m_free ) { - fprintf(fp," <free>\n"); - } else { - shader_print_warp(shader,m_warp,fp,::warp_size,0,0); - for( unsigned i=0; i < MAX_REG_OPERANDS; i++ ) { - if( m_not_ready.test(i) ) { - std::string r = m_src_op[i].get_reg_string(); - fprintf(fp," '%s' not ready\n", r.c_str() ); - } - } - } - } + void dump(FILE *fp, const shader_core_ctx *shader ) const; unsigned get_tid() const { return m_tid; } // returns hw id of first valid instruction unsigned get_warp_id() const { return m_warp_id; } unsigned get_id() const { return m_cuid; } // returns CU hw id // modifiers - void init(unsigned n, inst_t *port) { m_cuid=n; m_port=port; } - void allocate( inst_t *pipeline_reg ) - { - assert(m_free); - assert(m_not_ready.none()); - m_free = false; - inst_t *fvi = first_valid_thread(pipeline_reg); - if( fvi ) { - m_tid = fvi->hw_thread_id; - m_warp_id = m_tid/::warp_size; - for( unsigned op=0; op < 4; op++ ) { - int reg_num = fvi->arch_reg[4+op]; // this math needs to match that used in function_info::ptx_decode_inst - if( reg_num >= 0 ) { // valid register - m_src_op[op] = op_t( this, op, reg_num ); - m_not_ready.set(op); - } else - m_src_op[op] = op_t(); - } - move_warp(m_warp,pipeline_reg); - } - } + void init(unsigned n, + inst_t **port, + unsigned num_banks, + unsigned log2_warp_size, + unsigned warp_size, + opndcoll_rfu_t *rfu ); + void allocate( inst_t *&pipeline_reg ); void collect_operand( unsigned op ) { m_not_ready.reset(op); } - void dispatch() - { - assert( m_not_ready.none() ); - move_warp(m_port,m_warp); - m_free=true; - for( unsigned i=0; i<MAX_REG_OPERANDS;i++) - m_src_op[i].reset(); - } + void dispatch(); private: bool m_free; unsigned m_tid; unsigned m_cuid; // collector unit hw id - inst_t *m_port; // pipeline register to issue to when ready + inst_t **m_port; // pipeline register to issue to when ready unsigned m_warp_id; inst_t *m_warp; op_t *m_src_op; std::bitset<MAX_REG_OPERANDS> m_not_ready; + unsigned m_num_banks; + unsigned m_bank_warp_shift; + opndcoll_rfu_t *m_rfu; }; class dispatch_unit_t { @@ -748,16 +801,18 @@ private: unsigned m_num_collectors; unsigned m_num_banks; + unsigned m_bank_warp_shift; + unsigned m_warp_size; collector_unit_t *m_cu; arbiter_t m_arbiter; - inst_t *m_alu_port; - inst_t *m_sfu_port; + inst_t **m_alu_port; + inst_t **m_sfu_port; - typedef std::map<inst_t*/*port*/,dispatch_unit_t> port_to_du_t; + typedef std::map<inst_t**/*port*/,dispatch_unit_t> port_to_du_t; port_to_du_t m_dispatch_units; - std::map<inst_t*,std::list<collector_unit_t*> > m_free_cu; - const shader_core_ctx *m_shader; + std::map<inst_t**,std::list<collector_unit_t*> > m_free_cu; + shader_core_ctx *m_shader; }; class barrier_set_t { @@ -782,7 +837,7 @@ public: void warp_exit( unsigned warp_id ); // assertions - bool warp_waiting_at_barrier( unsigned warp_id ); + bool warp_waiting_at_barrier( unsigned warp_id ) const; // debug void dump() const; @@ -796,213 +851,431 @@ private: warp_set_t m_warp_at_barrier; }; -class mshr_shader_unit; class warp_tracker; class warp_tracker_pool; +enum memory_pipe_t { + NO_MEM_PATH = 0, + SHARED_MEM_PATH, + GLOBAL_MEM_PATH, + TEXTURE_MEM_PATH, + CONSTANT_MEM_PATH, + NUM_MEM_PATHS //not a mem path +}; + +class mem_access_t { +public: + mem_access_t() : space(undefined_space) + { + init(); + } + mem_access_t(address_type a, memory_space_t s, memory_pipe_t p, bool atomic, bool w, unsigned r, unsigned quarter, unsigned idx ) + { + init(); + addr = a; + space = s; + mem_pipe = p; + isatomic = atomic; + iswrite = w; + req_size = r; + quarter_count[quarter]++; + warp_indices.push_back(idx); + } + + bool operator<(const mem_access_t &other) const {return (order > other.order);}//this is reverse + +private: + void init() + { + uid=++next_access_uid; + addr=0; + req_size=0; + order=0; + _quarter_count_all=0; + mem_pipe = NO_MEM_PATH; + isatomic = false; + cache_hit = false; + cache_checked = false; + recheck_cache = false; + iswrite = false; + need_wb = false; + wb_addr = 0; + reserved_mshr = NULL; + } + +public: + + unsigned uid; + address_type addr; //address of the segment to load. + unsigned req_size; //bytes + unsigned order; // order of accesses, based on banks. + union{ + unsigned _quarter_count_all; + char quarter_count[4]; //access counts to each quarter of segment, for compaction; + }; + std::vector<unsigned> warp_indices; // warp indicies for this request. + memory_space_t space; + memory_pipe_t mem_pipe; + bool isatomic; + bool cache_hit; + bool cache_checked; + bool recheck_cache; + bool iswrite; + bool need_wb; + address_type wb_addr; // writeback address (if necessary). + mshr_entry* reserved_mshr; + +private: + static unsigned next_access_uid; +}; + +class mshr_lookup { +public: + mshr_lookup( const struct shader_core_config *config ) { m_shader_config = config; } + bool can_merge(mshr_entry * mshr); + void mshr_fast_lookup_insert(mshr_entry* mshr); + void mshr_fast_lookup_remove(mshr_entry* mshr); + mshr_entry* shader_get_mergeable_mshr(mshr_entry* mshr); + +private: + void insert(mshr_entry* mshr); + mshr_entry* lookup(new_addr_type addr) const; + void remove(mshr_entry* mshr); + + typedef std::multimap<new_addr_type, mshr_entry*> mshr_lut_t; // multimap since multiple mshr entries can have the same tag + + const shader_core_config *m_shader_config; + mshr_lut_t m_lut; +}; + +class mshr_shader_unit { +public: + mshr_shader_unit( const shader_core_config *config ); + + bool has_mshr(unsigned num) + { + return (num <= m_free_list.size()); + } + + //return queue access; (includes texture pipeline return) + mshr_entry* return_head(); + + //return queue pop; (includes texture pipeline return) + void pop_return_head(); + + mshr_entry* add_mshr(mem_access_t &access, inst_t* warp); + void mshr_return_from_mem(mshr_entry *mshr); + unsigned get_max_mshr_used() const {return m_max_mshr_used;} + void print(FILE* fp, class shader_core_ctx* shader,unsigned mask); + +private: + mshr_entry *alloc_free_mshr(bool istexture); + void free_mshr( mshr_entry *mshr ); + unsigned mshr_used() const; + bool has_return() + { + return (not m_mshr_return_queue.empty()) or + ((not m_texture_mshr_pipeline.empty()) and m_texture_mshr_pipeline.front()->fetched()); + } + std::deque<mshr_entry*> &choose_return_queue(); + + const struct shader_core_config *m_shader_config; + + typedef std::vector<mshr_entry> mshr_storage_type; + mshr_storage_type m_mshrs; + std::deque<mshr_entry*> m_free_list; + std::deque<mshr_entry*> m_mshr_return_queue; + std::deque<mshr_entry*> m_texture_mshr_pipeline; + unsigned m_max_mshr_used; + mshr_lookup m_mshr_lookup; +}; + +struct shader_queues_t { + std::vector<mem_access_t> shared; + std::vector<mem_access_t> constant; + std::vector<mem_access_t> texture; + std::vector<mem_access_t> local_global; +}; + +struct insn_latency_info { + unsigned pc; + unsigned long latency; +}; + +struct ifetch_buffer_t { + ifetch_buffer_t() { m_valid=false; } + + ifetch_buffer_t( address_type pc, unsigned nbytes, unsigned warp_id ) + { + m_valid=true; + m_pc=pc; + m_nbytes=nbytes; + m_warp_id=warp_id; + } + + bool m_valid; + address_type m_pc; + unsigned m_nbytes; + unsigned m_warp_id; +}; + +// Struct for storing warp information in fixeddelay_queue +struct fixeddelay_queue_warp_t { + unsigned long long ready_cycle; + std::vector<int> tids; // list of tid's in this warp (to unlock) + inst_t inst; +}; + +struct fixeddelay_queue_warp_comp { + inline bool operator()(const fixeddelay_queue_warp_t& left,const fixeddelay_queue_warp_t& right) const + { + return left.ready_cycle < right.ready_cycle; + } +}; + +typedef address_type (*tag_func_t)(address_type add, unsigned line_size); + class shader_core_ctx : public core_t { public: - shader_core_ctx( const char *name, int sid, - unsigned int n_threads, - unsigned int n_mshr, - fq_push_t fq_push, - fq_has_buffer_t fq_has_buffer, - unsigned model, - unsigned max_warps_per_cta, unsigned max_cta_per_core ); + shader_core_ctx( class gpgpu_sim *gpu, + const char *name, + unsigned shader_id, + unsigned tpc_id, + const struct shader_core_config *config, + struct shader_core_stats *stats ); + + void issue_block2core( class kernel_info_t &kernel ); + void get_pdom_stack_top_info( unsigned tid, unsigned *pc, unsigned *rpc ); + void new_cache_window(); + bool ptx_thread_done( unsigned hw_thread_id ) const; + class ptx_thread_info *get_thread_state( unsigned hw_thread_id ); - virtual void set_at_barrier( unsigned cta_id, unsigned warp_id ); + virtual void set_at_barrier( unsigned cta_id, unsigned warp_id ); virtual void warp_exit( unsigned warp_id ); - virtual bool warp_waiting_at_barrier( unsigned warp_id ); + virtual bool warp_waiting_at_barrier( unsigned warp_id ) const; + virtual bool warp_waiting_for_atomics( unsigned warp_id ) const; + virtual class gpgpu_sim *get_gpu(); + void set_at_memory_barrier( unsigned warp_id ); + bool warp_waiting_at_mem_barrier( unsigned warp_id ); void allocate_barrier( unsigned cta_id, warp_set_t warps ); void deallocate_barrier( unsigned cta_id ); + void decrement_atomic_count( unsigned wid ); -//// - - const char *name; - int sid; + void cycle(); + void cycle_gt200(); - // array of the threads running on this shader core - thread_ctx_t *thread; - unsigned int n_threads; - unsigned int last_issued_thread; + void reinit(unsigned start_thread, unsigned end_thread, bool reset_not_completed ); + void init_warps(unsigned start_thread, unsigned end_thread); - //per warp information array - std::vector<shd_warp_t> warp; + unsigned max_cta( class function_info *kernel ); + void cache_flush(); + void display_pdom_state(FILE *fout, int mask ); + void display_pipeline( FILE *fout, int print_mem, int mask3bit ); + void register_cta_thread_exit(int cta_num ); + void fill_shd_L1_with_new_line( class mem_fetch * mf ); + void store_ack( class mem_fetch *mf ); + void dump_istream_state( FILE *fout ); + void mshr_print(FILE* fp, unsigned mask); + inst_t *first_valid_thread( inst_t *warp ); + inst_t *first_valid_thread( unsigned stage ); + class ptx_thread_info* get_functional_thread( unsigned tid ) { return m_thread[tid].m_functional_model_thread_state; } + void move_warp( inst_t *&dst, inst_t *&src ); + void print_warp( inst_t *warp, FILE *fout, int print_mem, int mask ) const; + void clear_stage(inst_t *warp); + std::list<unsigned> get_regs_written( const inst_t &fvt ) const; + bool pipeline_regster_empty( inst_t *reg ); + const shader_core_config *get_config() const { return m_config; } + unsigned get_num_sim_insn() const { return m_num_sim_insn; } + int get_not_completed() const { return m_not_completed; } + unsigned get_n_diverge() const { return m_n_diverge; } + unsigned get_thread_n_insn( unsigned tid ) const { return m_thread[tid].n_insn; } + unsigned get_thread_n_insn_ac( unsigned tid ) const { return m_thread[tid].n_insn_ac; } + unsigned get_thread_n_l1_mis_ac( unsigned tid ) const { return m_thread[tid].n_l1_mis_ac; } + unsigned get_thread_n_l1_mrghit_ac( unsigned tid ) const { return m_thread[tid].n_l1_mrghit_ac; } + unsigned get_thread_n_l1_access_ac( unsigned tid ) const { return m_thread[tid].n_l1_access_ac; } + unsigned get_max_mshr_used() const { return m_mshr_unit->get_max_mshr_used(); } + void L1cache_print( FILE *fp, unsigned &total_accesses, unsigned &total_misses) const; + void L1texcache_print( FILE *fp, unsigned &total_accesses, unsigned &total_misses) const; + void L1constcache_print( FILE *fp, unsigned &total_accesses, unsigned &total_misses) const; + unsigned get_n_active_cta() const { return m_n_active_cta; } + float L1_windowed_cache_miss_rate( int x ) const { return shd_cache_windowed_cache_miss_rate(m_L1D,x); } + float L1tex_windowed_cache_miss_rate( int x ) const { return shd_cache_windowed_cache_miss_rate(m_L1T,x); } + float L1const_windowed_cache_miss_rate( int x ) const { return shd_cache_windowed_cache_miss_rate(m_L1C,x); } + +private: - barrier_set_t m_barriers; + void clear_stage_reg(int stage); - //Keeps track of which warp of instructions to fetch/execute - int next_warp; + address_type next_pc( int tid ) const; - // number of threads to be completed ( ==0 when all thread on this core completed) - int not_completed; - // number of Cuda Thread Arrays (blocks) currently running on this shader. - int n_active_cta; - //Keep track of multiple CTAs in shader - int cta_status[MAX_CTA_PER_SHADER]; - // registers holding the instruction between pipeline stages. - // see below for definition of pipeline stages - inst_t** pipeline_reg; - inst_t** pre_mem_pipeline; - opndcoll_rfu_t m_opndcoll_new; - int warp_part2issue; // which part of warp to issue to pipeline - int new_warp_TS; // new warp at TS pipeline register + void ptx_exec_inst( inst_t &inst ); + void fetch_new(); + void issue_warp(const inst_t *pI, unsigned active_mask, inst_t *&warp, unsigned warp_id ); + void decode_new(); - shd_cache_t *L1cache; - shd_cache_t *L1texcache; - shd_cache_t *L1constcache; + void fetch(); - // pointer to memory access wrapping function - fq_push_t fq_push; - fq_has_buffer_t fq_has_buffer; + void fetch_mimd(); + void fetch_simd_dwf(); + void fetch_simd_postdominator(); + int pdom_sched_find_next_warp (int ready_warp_count); + bool fetch_stalled(); + void shader_issue_thread(int tid, int wlane, unsigned active_mask ); + int warp_reached_barrier(int *tid_in); - // simulation cycles happened to the shader, kept for cacheline replacement - unsigned int gpu_cycle; - // number of instructions committed by this shader core - unsigned int num_sim_insn; + void decode(); - // reconvergence - unsigned int model; + void preexecute(); - // Structure is used to keep track of the branching within the warp of instructions. - // As a group of instructions is grouped together from different threads to be executed, when - // a branch does occur, then the sub-set that does not get run will be given the value of warp_priority, - // and warp_priority will increase. Each time a sub-set branches further, a similar scheme is used. - // When a sub-set completes fully, then this table will determine which next sub-set to finish, which - // will be the next largest value in the table. - int branch_priority; - int* max_branch_priority; //Keeps track of the maximum priority of the threads running within a warp. need n_threads number of these + void execute(); + void execute_pipe( unsigned pipeline, unsigned next_stage ); - // pdom reconvergence context for each warp - pdom_warp_ctx_t *pdom_warp; + void pre_memory(); - int waiting_at_barrier; // number of threads current waiting at a barrier in this shader. - int RR_k; //counter for register read pipeline + void memory(); // advance memory pipeline stage + void memory_queue(); + void memory_shared_process_warp(); + void memory_const_process_warp(); + void memory_texture_process_warp(); + void memory_global_process_warp(); + bool memory_shared_cycle( mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type); + bool memory_constant_cycle( mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type); + bool memory_texture_cycle( mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type); + bool memory_cycle( mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type); + address_type translate_local_memaddr(address_type localaddr, int tid, unsigned num_shader ); - int using_dwf; //is the scheduler using dynamic warp formation - int using_rrstage; //is the pipeline using an extra stage for register read - int using_commit_queue; //is the scheduler using commit_queue? + mem_stage_stall_type ccache_check(mem_access_t& access){ return NO_RC_FAIL;} + mem_stage_stall_type tcache_check(mem_access_t& access){ return NO_RC_FAIL;} + mem_stage_stall_type dcache_check(mem_access_t& access); - delay_queue *thd_commit_queue; + typedef mem_stage_stall_type (shader_core_ctx::*cache_check_t)(mem_access_t&); - int pending_shmem_bkacc; // 0 = check conflict for new insn - int pending_cache_bkacc; // 0 = check conflict for new insn + mem_stage_stall_type process_memory_access_queue( shader_core_ctx::cache_check_t cache_check, + unsigned ports_per_bank, + unsigned memory_send_max, + std::vector<mem_access_t> &accessq ); - bool shader_memory_new_instruction_processed; + typedef int (shader_core_ctx::*bank_func_t)(address_type add, unsigned line_size); + + int null_bank_func(address_type add, unsigned line_size); + int shmem_bank_func(address_type add, unsigned line_size); + int dcache_bank_func(address_type add, unsigned line_size); - int pending_mem_access; // number of memory access to be serviced (use for W0 classification) + void get_memory_access_list( bank_func_t bank_func, + tag_func_t tag_func, + memory_pipe_t mem_pipe, + unsigned warp_parts, + unsigned line_size, + bool limit_broadcast, + std::vector<mem_access_t> &accessq ); + mem_stage_stall_type send_mem_request(mem_access_t &access); - int pending_cmem_acc; //number of accesses to differrnt addresses in the constant memory cache + void check_stage_pcs( unsigned stage ); + void check_pm_stage_pcs( unsigned stage ); - unsigned int n_diverge; // number of divergence occurred in this shader + void writeback(); + int split_warp_by_pc(int *tid_in, int **tid_split, address_type *pc); + int split_warp_by_cta(int *tid_in, int **tid_split, address_type *pc, int *cta); - //Shader core resources - unsigned int shmem_size; - unsigned int n_registers; //registers available in the shader core - unsigned int n_cta; //Limit on number of concurrent CTAs in shader core + unsigned char fq_push( unsigned long long int addr, + int bsize, + unsigned char write, + partial_write_mask_t partial_write_mask, + int wid, mshr_entry* mshr, + int cache_hits_waiting, + enum mem_access_type mem_acc, + address_type pc ); - mshr_shader_unit *mshr_unit; + bool warp_scoreboard_hazard(int warp_id); + mshr_entry* check_mshr4tag(unsigned long long int addr,int mem_type); + void update_mshr(unsigned long long int fetched_addr, unsigned int mshr_idx, int mem_type ); + void visualizer_dump(FILE *fp); + void clean(unsigned int n_threads); + void call_thread_done(inst_t &done_inst ); + void queue_warp_unlocking(int *tids, const inst_t &inst ); + void process_delay_queue(); + void unlock_warp(std::vector<int> tids ); - // - // Fixed-delay queue for locked warps - // + void print_pre_mem_stages( FILE *fout, int print_mem, int mask ); + void print_stage(unsigned int stage, FILE *fout, int print_mem, int mask ); + void print_shader_cycle_distro( FILE *fout ); - // Struct for storing warp information in fixeddelay_queue - struct fixeddelay_queue_warp_t { - int grid_num; - unsigned long long ready_cycle; - std::vector<int> tids; // list of tid's in this warp (to unlock) - }; - struct fixeddelay_queue_warp_comp { - inline bool operator()(const fixeddelay_queue_warp_t& left,const fixeddelay_queue_warp_t& right) const - { - return left.ready_cycle < right.ready_cycle; - } - }; + // general information + unsigned m_sid; // shader id + unsigned m_tpc; // texture processor cluster id (aka, node id when using interconnect concentration) + const char *m_name; + const shader_core_config *m_config; + class gpgpu_sim *m_gpu; - // The queue - std::multiset<fixeddelay_queue_warp_t, fixeddelay_queue_warp_comp> fixeddelay_queue; + // statistics + struct shader_core_stats *m_stats; // pointer to single object shared by all shader cores in GPU + unsigned int m_num_sim_insn; // number of instructions committed by this shader core + unsigned int m_n_diverge; // number of divergence occurred in this shader - // Scoreboard - Scoreboard *scrb; -}; + // CTA scheduling / hardware thread allocation + int m_n_active_cta; // number of Cooperative Thread Arrays (blocks) currently running on this shader. + int m_cta_status[MAX_CTA_PER_SHADER]; // CTAs status + int m_not_completed; // number of threads to be completed (==0 when all thread on this core completed) -typedef shader_core_ctx shader_core_ctx_t; + // thread contexts + thread_ctx_t *m_thread; // functional state, per thread fetch state + std::vector<shd_warp_t> m_warp; // per warp information array + barrier_set_t m_barriers; + ifetch_buffer_t m_inst_fetch_buffer; + pdom_warp_ctx_t **m_pdom_warp; // pdom reconvergence context for each warp -typedef struct { - unsigned pc; - unsigned long latency; - void *ptx_thd_info; -} insn_latency_info; + class warp_tracker_pool *m_warp_tracker; + inst_t** m_pipeline_reg; + inst_t** pre_mem_pipeline; + Scoreboard *m_scoreboard; + opndcoll_rfu_t m_operand_collector; + mshr_shader_unit *m_mshr_unit; + shader_queues_t m_memory_queue; + fifo_pipeline<std::vector<int> > *m_thd_commit_queue; + std::multiset<fixeddelay_queue_warp_t, fixeddelay_queue_warp_comp> m_fixeddelay_queue; + // fetch + int m_last_warp_fetched; + int m_last_warp_issued; -shader_core_ctx_t* shader_create( const char *name, int sid, unsigned int n_threads, - unsigned int n_mshr, fq_push_t fq_push, fq_has_buffer_t fq_has_buffer, unsigned int model); -unsigned shader_reinit(shader_core_ctx_t *sc, int start_thread, int end_thread); -void shader_init_CTA(shader_core_ctx_t *shader, int start_thread, int end_thread); + bool m_new_warp_TS; // new warp at TS pipeline register + int m_last_warp; // SIMT: last warp issued + int m_next_warp; // SIMT: Keeps track of which warp of instructions to fetch/execute + unsigned m_last_issued_thread; // MIMD -void shader_fetch( shader_core_ctx_t *shader, - unsigned int shader_number, - int grid_num ); -void shader_decode( shader_core_ctx_t *shader, - unsigned int shader_number, - unsigned int grid_num ); -void shader_preexecute( shader_core_ctx_t *shader, - unsigned int shader_number ); -void shader_execute( shader_core_ctx_t *shader, - unsigned int shader_number ); -void shader_pre_memory( shader_core_ctx_t *shader, - unsigned int shader_number ); -void shader_const_memory( shader_core_ctx_t *shader, - unsigned int shader_number ); -void shader_texture_memory( shader_core_ctx_t *shader, - unsigned int shader_number ); -void shader_memory( shader_core_ctx_t *shader, - unsigned int shader_number ); -void shader_writeback( shader_core_ctx_t *shader, - unsigned int shader_number, - int grid_num ); + int *m_ready_warps; + int *m_tmp_ready_warps; + int *m_fetch_tid_out; -bool shader_warp_scoreboard_hazard(shader_core_ctx_t *shader, int warp_id); -void shader_pdom_update_warp_mask(shader_core_ctx_t *shader, int warp_id); + // pre-execute stage + int m_dwf_RR_k; // counter for register read pipeline + int *m_dwf_rrstage_bank_access_counter; -void shader_display_pipeline(shader_core_ctx_t *shader, FILE *fout, int print_mem, int mask3bit ); -void shader_dump_thread_state(shader_core_ctx_t *shader, FILE *fout ); -void shader_cycle( shader_core_ctx_t *shader, - unsigned int shader_number, - int grid_num ); + shd_cache_t *m_L1I; // instruction cache + shd_cache_t *m_L1D; // data cache (global/local memory accesses) + shd_cache_t *m_L1T; // texture cache + shd_cache_t *m_L1C; // constant cache -void mshr_print(FILE *fp, shader_core_ctx_t *shader); + bool m_shader_memory_new_instruction_processed; + int m_pending_mem_access; // number of memory access to be serviced (use for W0 classification) -void mshr_update_status(mshr_entry* mshr, enum mshr_status new_status); + // used in writeback + int *m_pl_tid; + insn_latency_info *m_mshr_lat_info; + insn_latency_info *m_pl_lat_info; -mshr_entry* fetchMSHR(delay_queue** mshr, shader_core_ctx_t* sc); -mshr_entry* shader_check_mshr4tag(shader_core_ctx_t* sc, unsigned long long int addr,int mem_type); -void shader_update_mshr(shader_core_ctx_t* sc, unsigned long long int fetched_addr, unsigned int mshr_idx, int mem_type ); -void shader_visualizer_dump(FILE *fp, shader_core_ctx_t* sc); + class thread_pc_tracker *m_thread_pc_tracker; +}; void init_mshr_pool(); mshr_entry* alloc_mshr_entry(); void free_mshr_entry( mshr_entry * ); -void shader_clean(shader_core_ctx_t *sc, unsigned int n_threads); -void shader_cache_flush(shader_core_ctx_t* sc); - -void shader_call_thread_done( shader_core_ctx_t *shader, int grid_num, inst_t &done_inst ); -void shader_queue_warp_unlocking(shader_core_ctx_t *shader, int *tids, memory_space_t space, int grid_num); -void shader_process_delay_queue(shader_core_ctx_t *shader); -void shader_unlock_warp(shader_core_ctx_t *shd, std::vector<int> tids, int grid_num); - // print out the accumulative statistics for shaders (those that are not local to one shader) -void shader_print_accstats( FILE* fout ); void shader_print_runtime_stat( FILE *fout ); void shader_print_l1_miss_stat( FILE *fout ); -//return the maximum CTAs that can be running at the same on shader -//based on on the current kernel's CTA size and is 1 if mutiple CTA per block is not supported -unsigned int max_cta_per_shader( shader_core_ctx_t *shader); - #define TS_IF 0 #define IF_ID 1 #define ID_RR 2 @@ -1011,45 +1284,14 @@ unsigned int max_cta_per_shader( shader_core_ctx_t *shader); #define EX_MM 4 #define MM_WB 5 #define WB_RT 6 - #define ID_OC 7 -#define OC_EX_SFU 8 +#define ID_OC_SFU 8 +#define OC_EX_SFU 9 +#define N_PIPELINE_STAGES 10 -#define N_PIPELINE_STAGES 9 - -extern shader_core_ctx_t **sc; -extern unsigned int gpgpu_n_load_insn; -extern unsigned int gpgpu_n_store_insn; -extern unsigned int gpgpu_n_shmem_insn; -extern unsigned int gpgpu_n_tex_insn; -extern unsigned int gpgpu_n_const_insn; -extern unsigned int gpgpu_multi_unq_fetches; -extern unsigned int gpgpu_n_cache_bkconflict; -extern unsigned int gpgpu_n_shmem_bkconflict; -extern int gpgpu_warpdistro_shader; extern unsigned int *shader_cycle_distro; -extern int gpgpu_interwarp_mshr_merge; -extern unsigned int gpgpu_shmem_size; -extern unsigned int gpgpu_shader_registers; -extern unsigned int gpgpu_shader_cta; -extern bool gpgpu_shmem_bkconflict; -extern bool gpgpu_cache_bkconflict; -extern int gpgpu_n_cache_bank; -extern int pipe_simd_width; -extern int gpgpu_shmem_port_per_bank; -extern int gpgpu_cache_port_per_bank; -extern int gpgpu_const_port_per_bank; -extern int gpgpu_shmem_pipe_speedup; -extern bool gpgpu_reg_bank_conflict_model; -extern unsigned int gpgpu_num_reg_banks; -extern bool gpgpu_reg_bank_use_warp_id; -extern unsigned int gpu_max_cta_per_shader; -extern unsigned int gpu_padded_cta_size; -extern int gpgpu_local_mem_map; extern unsigned int n_regconflict_stall; -extern int gpgpu_coalesce_arch; -extern unsigned get_max_mshr_used(shader_core_ctx_t* shader); -extern void mshr_return_from_mem(shader_core_ctx_t * shader, mshr_entry_t* mshr); -void get_pdom_stack_top_info( unsigned sid, unsigned tid, unsigned *pc, unsigned *rpc ); + +int is_store ( const inst_t &op ); #endif /* SHADER_H */ |
