diff options
| author | Tor Aamodt <[email protected]> | 2010-07-29 21:54:23 -0800 |
|---|---|---|
| committer | Tor Aamodt <[email protected]> | 2010-07-29 21:54:23 -0800 |
| commit | 503cda930217158d43d136aea1893f0d30df32a6 (patch) | |
| tree | 8197fc8c5051f853fc05c63ae26a7062baf65e1e /src | |
| parent | 01c9871c9dc18825aa6d582bfae5353c0d3923b3 (diff) | |
integrate operand collector (not compiling yet)
[git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 7105]
Diffstat (limited to 'src')
| -rw-r--r-- | src/abstract_hardware_model.h | 2 | ||||
| -rw-r--r-- | src/cuda-sim/ptx_sim.h | 2 | ||||
| -rw-r--r-- | src/gpgpu-sim/gpu-sim.cc | 12 | ||||
| -rw-r--r-- | src/gpgpu-sim/shader.cc | 194 | ||||
| -rw-r--r-- | src/gpgpu-sim/shader.h | 387 |
5 files changed, 576 insertions, 21 deletions
diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 528b120..3b3d07e 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -11,6 +11,8 @@ public: virtual bool warp_waiting_at_barrier( unsigned warp_id ) = 0; }; +#define MAX_REG_OPERANDS 8 +extern unsigned int warp_size; #endif typedef unsigned address_type; diff --git a/src/cuda-sim/ptx_sim.h b/src/cuda-sim/ptx_sim.h index 7851dc6..8de4127 100644 --- a/src/cuda-sim/ptx_sim.h +++ b/src/cuda-sim/ptx_sim.h @@ -488,6 +488,4 @@ memory_space_t whichspace( addr_t addr ); #endif -#define MAX_REG_OPERANDS 8 - #endif diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc index cda7517..5615801 100644 --- a/src/gpgpu-sim/gpu-sim.cc +++ b/src/gpgpu-sim/gpu-sim.cc @@ -264,6 +264,10 @@ extern int gpgpu_cache_port_per_bank; extern int gpgpu_const_port_per_bank; extern int gpgpu_shmem_pipe_speedup; extern int gpgpu_reg_bank_conflict_model; +extern unsigned int gpgpu_num_reg_banks; +extern int gpgpu_reg_bank_use_warp_id; +extern int gpgpu_operand_collector; +extern int gpgpu_operand_collector_num_units; extern int gpgpu_num_reg_banks; extern unsigned int gpu_max_cta_per_shader; @@ -566,7 +570,13 @@ void gpu_reg_options(option_parser_t opp) option_parser_register(opp, "-gpgpu_num_reg_banks", OPT_INT32, &gpgpu_num_reg_banks, "Number of register banks (default = 8)", "8"); - option_parser_register(opp, "-gpgpu_coalesce_arch", OPT_INT32, &gpgpu_coalesce_arch, + option_parser_register(opp, "-gpgpu_operand_collector", OPT_BOOL, &gpgpu_operand_collector, + "Enable operand collector model (default = off)", + "0"); + option_parser_register(opp, "-gpgpu_operand_collector_num_units", OPT_INT32, &gpgpu_operand_collector_num_units, + "number of collecture units (default = 4)", + "4"); + option_parser_register(opp, "-gpgpu_coalesce_arch", OPT_INT32, &gpgpu_coalesce_arch, "Coalescing arch (default = 13, anything else is off for now)", "13"); addrdec_setoption(opp); diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index 7a31d15..8ebf655 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -213,6 +213,8 @@ unsigned int gpu_padded_cta_size = 32; int gpgpu_local_mem_map = 1; +int gpgpu_operand_collector_num_units = 4; + extern int pdom_sched_type; extern int n_pdom_sc_orig_stat; extern int n_pdom_sc_single_stat; @@ -518,11 +520,46 @@ inst_t create_nop_inst() // just because C++ does not have designated initialize nop_inst.id_cycle = 0; nop_inst.ex_cycle = 0; nop_inst.mm_cycle = 0; + nop_inst.space = 0; return nop_inst; } static inst_t nop_inst = create_nop_inst(); +inst_t *first_valid_thread( inst_t *warp ) +{ + for(unsigned t=0; t < ::warp_size; t++ ) + if( warp[t].hw_thread_id != -1 ) + return warp+t; + return NULL; +} + +void move_warp( inst_t *dst, inst_t *src ) +{ + memcpy(dst,src,::warp_size * sizeof(inst_t)); + for( unsigned t=0; t < ::warp_size; t++) + src[t] = nop_inst; +} + +bool pipeline_regster_empty( inst_t *reg ) +{ + return first_valid_thread(reg) == NULL; +} + +std::list<unsigned> get_regs_written( inst_t *warp ) +{ + std::list<unsigned> result; + inst_t *fvi = first_valid_thread(warp); + if( fvi == NULL ) + return result; + for( unsigned op=0; op < 4; op++ ) { + int reg_num = fvi->arch_reg[op]; // this math needs to match that used in function_info::ptx_decode_inst + if( reg_num >= 0 ) // valid register + result.push_back(reg_num); + } + return result; +} + int log2i(int n) { int lg; lg = -1; @@ -597,6 +634,7 @@ shader_core_ctx_t* shader_create( const char *name, int sid, } } } + sc->last_cta_finished = 0; sc->n_threads = n_threads; sc->thread = (thread_ctx_t*) calloc(sizeof(thread_ctx_t), n_threads); sc->not_completed = 0; @@ -1740,6 +1778,19 @@ reg_bank_access g_reg_bank_access[MAX_REG_BANKS]; static const struct reg_bank_access empty_reg_bank_access; unsigned int gpu_reg_bank_conflict_stalls = 0; + +void shader_opnd_collect_read(shader_core_ctx_t* shader) +{ + const int prevstage = ID_OC; + const int nextstage = shader->using_rrstage ? ID_RR : ID_EX; + shader->m_opndcoll_new.step(shader->pipeline_reg[prevstage],shader->pipeline_reg[nextstage]); +} + +void shader_opnd_collect_write(shader_core_ctx_t* shader) +{ + shader->m_opndcoll_new.writeback(shader->pipeline_reg[WB_RT]); +} + ///////////////////////////////////////////////////////////////////////////////////////// void shader_decode( shader_core_ctx_t *shader, @@ -3283,30 +3334,28 @@ void shader_print_l1_miss_stat( FILE *fout ) { } -void shader_print_stage(shader_core_ctx_t *shader, unsigned int stage, - FILE *fout, int stage_width, int print_mem, int mask ) +void shader_print_warp( const shader_core_ctx_t *shader, inst_t *warp, FILE *fout, int stage_width, int print_mem, int mask ) { int i, j, warp_id = -1; - for (i=0; i<stage_width; i++) { - if (shader->pipeline_reg[stage][i].hw_thread_id > -1) { - warp_id = shader->pipeline_reg[stage][i].hw_thread_id / warp_size; + if (warp[i].hw_thread_id > -1) { + warp_id = warp[i].hw_thread_id / warp_size; break; } } i = (i>=stage_width)? 0 : i; - fprintf(fout,"0x%04x ", shader->pipeline_reg[stage][i].pc ); + fprintf(fout,"0x%04x ", warp[i].pc ); if( mask & 2 ) { fprintf(fout, "(" ); for (j=0; j<stage_width; j++) - fprintf(fout, "%03d ", shader->pipeline_reg[stage][j].hw_thread_id); + fprintf(fout, "%03d ", warp[j].hw_thread_id); fprintf(fout, "): "); } else { fprintf(fout, "w%02d[", warp_id); for (j=0; j<stage_width; j++) - fprintf(fout, "%c", ((shader->pipeline_reg[stage][j].hw_thread_id != -1)?'1':'0') ); + fprintf(fout, "%c", ((warp[j].hw_thread_id != -1)?'1':'0') ); fprintf(fout, "]: "); } @@ -3319,16 +3368,23 @@ void shader_print_stage(shader_core_ctx_t *shader, unsigned int stage, } } - ptx_print_insn( shader->pipeline_reg[stage][i].pc, fout ); + ptx_print_insn( warp[i].pc, fout ); if( mask & 0x10 ) { - if ( (shader->pipeline_reg[stage][i].op == STORE_OP || - shader->pipeline_reg[stage][i].op == LOAD_OP) && print_mem ) - fprintf(fout, " mem: 0x%016llx", shader->pipeline_reg[stage][i].memreqaddr); + if ( (warp[i].op == STORE_OP || + warp[i].op == LOAD_OP) && print_mem ) + fprintf(fout, " mem: 0x%016llx", warp[i].memreqaddr); } fprintf(fout, "\n"); } +void shader_print_stage(shader_core_ctx_t *shader, unsigned int stage, + FILE *fout, int stage_width, int print_mem, int mask ) +{ + inst_t *warp = shader->pipeline_reg[stage]; + shader_print_warp(shader,warp,fout,stage_width,print_mem,mask); +} + void shader_print_pre_mem_stages(shader_core_ctx_t *shader, FILE *fout, int print_mem, int mask ) { int i, j; @@ -3451,6 +3507,9 @@ void shader_display_pipeline(shader_core_ctx_t *shader, FILE *fout, int print_me fprintf(fout, "IF/ID = "); shader_print_stage(shader, IF_ID, fout, pipe_simd_width, print_mem, mask ); + if (gpgpu_operand_collector) + shader->m_opndcoll_new.dump(fout); + if (shader->using_rrstage) { fprintf(fout, "ID/RR = "); shader_print_stage(shader, ID_RR, fout, pipe_simd_width, print_mem, mask); @@ -3561,6 +3620,9 @@ void shader_cycle( shader_core_ctx_t *shader, int grid_num ) { + if (gpgpu_operand_collector) + shader_opnd_collect_write(shader); + // last pipeline stage shader_writeback(shader, shader_number, grid_num); @@ -3580,6 +3642,9 @@ void shader_cycle( shader_core_ctx_t *shader, shader_preexecute (shader, shader_number); } + if (gpgpu_operand_collector) + shader_opnd_collect_read(shader); + shader_decode (shader, shader_number, grid_num); shader_fetch (shader, shader_number, grid_num); @@ -3672,6 +3737,109 @@ void shader_cache_flush(shader_core_ctx_t* sc) } } +static int *_inmatch; +static int *_outmatch; +static int **_request; + +// modifiers +std::list<opndcoll_rfu_t::op_t> opndcoll_rfu_t::arbiter_t::allocate_reads() +{ + std::list<op_t> result; // a list of registers that (a) are in different register banks, (b) do not go to the same operand collector + + int input; + int output; + int _inputs = m_num_banks; + int _outputs = m_num_collectors; + int _square = ( _inputs > _outputs ) ? _inputs : _outputs; + int _pri = (int)m_last_cu; + + if( _inmatch == NULL ) { + _inmatch = new int[ _inputs ]; + _outmatch = new int[ _outputs ]; + _request = new int*[ _inputs ]; + for(int i=0; i<_outputs;i++) + _request[i] = new int[_outputs]; + } + + // Clear matching + for ( int i = 0; i < _inputs; ++i ) + _inmatch[i] = -1; + for ( int j = 0; j < _outputs; ++j ) + _outmatch[j] = -1; + + for( unsigned i=0; i<m_num_banks; i++) { + for( unsigned j=0; j<m_num_collectors; j++) + _request[i][j] = 0; + if( !m_queue[i].empty() ) { + const op_t &op = m_queue[i].front(); + int oc_id = op.get_oc_id(); + _request[i][oc_id] = 1; + } + if( m_allocated_bank[i].is_write() ) + _inmatch[i] = 0; // write gets priority + } + + ///// wavefront allocator from booksim... ---> + + // Loop through diagonals of request matrix + + for ( int p = 0; p < _square; ++p ) { + output = ( _pri + p ) % _square; + + // Step through the current diagonal + for ( input = 0; input < _inputs; ++input ) { + if ( ( output < _outputs ) && + ( _inmatch[input] == -1 ) && + ( _outmatch[output] == -1 ) && + ( _request[input][output]/*.label != -1*/ ) ) { + // Grant! + _inmatch[input] = output; + _outmatch[output] = input; + } + + output = ( output + 1 ) % _square; + } + } + + // Round-robin the priority diagonal + _pri = ( _pri + 1 ) % _square; + + /// <--- end code from booksim + + m_last_cu = _pri; + for( unsigned i=0; i < m_num_banks; i++ ) { + if( _inmatch[i] != -1 ) { + if( !m_allocated_bank[i].is_write() ) { + unsigned bank = (unsigned)i; + op_t &op = m_queue[bank].front(); + result.push_back(op); + m_queue[bank].pop_front(); + } + } + } + + +/* + for( unsigned c=0; c < m_num_collectors; c++ ) { + unsigned cu = (m_last_cu+c+1)%m_num_collectors; + for( unsigned b=0; b < m_num_banks; b++ ) { + unsigned bank = (m_allocator_rr_head[cu]+b+1)%m_num_banks; + if( (!m_queue[bank].empty()) && m_allocated_bank[bank].is_free() ) { + op_t &op = m_queue[bank].front(); + result.push_back(op); + m_allocated_bank[bank].alloc_read(op); + m_queue[bank].pop_front(); + m_allocator_rr_head[cu] = bank; + m_last_cu = cu; + break; // skip to next collector unit + } + } + } +*/ + return result; +} + + barrier_set_t::barrier_set_t( unsigned max_warps_per_core, unsigned max_cta_per_core ) { m_max_warps_per_core = max_warps_per_core; @@ -3777,7 +3945,7 @@ void barrier_set_t::dump() const } shader_core_ctx::shader_core_ctx( unsigned max_warps_per_cta, unsigned max_cta_per_core ) - : m_barriers( max_warps_per_cta, max_cta_per_core ) + : m_barriers( max_warps_per_cta, max_cta_per_core ), m_opndcoll_new( gpgpu_operand_collector_num_units, gpgpu_num_reg_banks, this ) { } diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index f67e8fd..702046d 100644 --- a/src/gpgpu-sim/shader.h +++ b/src/gpgpu-sim/shader.h @@ -70,6 +70,7 @@ #include <limits.h> #include <assert.h> #include <map> +#include <list> #include "../cuda-sim/ptx.tab.h" #include "../cuda-sim/dram_callback.h" @@ -133,7 +134,7 @@ typedef struct { unsigned in[4]; unsigned char is_vectorin; unsigned char is_vectorout; - int arch_reg[8]; // register number for bank conflict evaluation + 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? int reg_bank_access_pending; @@ -312,6 +313,380 @@ typedef unsigned char (*fq_has_buffer_t)(unsigned long long int addr, int bsize, 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); +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 +public: + // constructors + opndcoll_rfu_t( unsigned num_collectors, unsigned num_banks, const shader_core_ctx *shader ) + : m_arbiter(num_collectors,num_banks) + { + m_num_collectors=num_collectors; + m_num_banks = num_banks; + m_cu = new collector_unit_t[num_collectors]; + m_last_cu=0; + m_shader=shader; + for(unsigned c=0; c<num_collectors; c++) { + m_cu[c].set_cuid(c); + m_free_cu.push_back(&m_cu[c]); + } + } + + // modifiers + void writeback( inst_t *warp ) + { + // 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)); + } + } + + void step( inst_t *id_oc_reg, inst_t *oc_ex_reg ) + { + dispatch_ready_cu(oc_ex_reg); + allocate_reads(); + allocate_cu(id_oc_reg); + process_banks(); + } + + void dump( FILE *fp ) const + { + fprintf(fp,"\n"); + fprintf(fp,"Operand Collector State:\n"); + for( unsigned n=0; n < m_num_collectors; n++ ) { + fprintf(fp," CU-%u: ", n); + m_cu[n].dump(fp,m_shader); + } + m_arbiter.dump(fp); + } + +private: + + void process_banks() + { + m_arbiter.reset_alloction(); + } + + void dispatch_ready_cu( inst_t *oc_ex_reg ) + { + if( !pipeline_regster_empty(oc_ex_reg) ) + return; + for( unsigned n=0; n < m_num_collectors; n++ ) { + unsigned c=(m_last_cu+n+1)%m_num_collectors; + if( m_cu[c].ready() ) { + m_cu[c].dispatch(oc_ex_reg); + m_free_cu.push_back(&m_cu[c]); + m_last_cu=c; + break; + } + } + } + + void allocate_cu( inst_t *id_oc_reg ) + { + inst_t *fvi = first_valid_thread(id_oc_reg); + if( fvi && !m_free_cu.empty() ) { + collector_unit_t *cu = m_free_cu.back(); + m_free_cu.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); + } + } + + // types + + class collector_unit_t; + + class op_t { + public: + + op_t() { m_valid = false; } + op_t( collector_unit_t *cu, unsigned op, unsigned reg ) + { + m_valid = true; + m_fvi=NULL; + m_cu = cu; + m_operand = op; + m_register = reg; + m_tid = cu->get_tid(); + m_bank = register_bank(reg,m_tid); + } + op_t( inst_t *fvi, unsigned reg ) + { + 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); + } + + // accessors + bool valid() const { return m_valid; } + unsigned get_reg() const + { + assert( m_valid ); + return m_register; + } + unsigned get_oc_id() const { return m_cu->get_id(); } + unsigned get_tid() const { return m_tid; } + unsigned get_bank() const { return m_bank; } + unsigned get_operand() const { return m_operand; } + void dump(FILE *fp) const + { + 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); + } + std::string get_reg_string() const + { + char buffer[64]; + snprintf(buffer,64,"R%u", m_register); + return std::string(buffer); + } + + // modifiers + void reset() { m_valid = false; } + private: + bool m_valid; + collector_unit_t *m_cu; + 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; + unsigned m_tid; + }; + + enum alloc_t { + NO_ALLOC, + READ_ALLOC, + WRITE_ALLOC, + }; + + class allocation_t { + public: + allocation_t() { m_allocation = NO_ALLOC; } + bool is_read() const { return m_allocation==READ_ALLOC; } + bool is_write() const {return m_allocation==WRITE_ALLOC; } + bool is_free() const {return m_allocation==NO_ALLOC; } + void dump(FILE *fp) const { + if( m_allocation == NO_ALLOC ) { fprintf(fp,"<free>"); } + else if( m_allocation == READ_ALLOC ) { fprintf(fp,"rd: "); m_op.dump(fp); } + else if( m_allocation == WRITE_ALLOC ) { fprintf(fp,"wr: "); m_op.dump(fp); } + fprintf(fp,"\n"); + } + void alloc_read( const op_t &op ) { assert(is_free()); m_allocation=READ_ALLOC; m_op=op; } + void alloc_write( const op_t &op ) { assert(is_free()); m_allocation=WRITE_ALLOC; m_op=op; } + void reset() { m_allocation = NO_ALLOC; } + private: + enum alloc_t m_allocation; + op_t m_op; + }; + + class arbiter_t { + public: + // constructors + arbiter_t( unsigned num_cu, unsigned num_banks ) + { + m_num_collectors = num_cu; + m_num_banks = num_banks; + m_queue = new std::list<op_t>[num_banks]; + m_allocated_bank = new allocation_t[num_banks]; + m_allocator_rr_head = new unsigned[num_cu]; + for( unsigned n=0; n<num_cu;n++ ) + m_allocator_rr_head[n] = n%num_banks; + reset_alloction(); + } + + // accessors + void dump(FILE *fp) const + { + fprintf(fp,"\n"); + fprintf(fp," Arbiter State:\n"); + fprintf(fp," requests:\n"); + for( unsigned b=0; b<m_num_banks; b++ ) { + fprintf(fp," bank %u : ", b ); + std::list<op_t>::const_iterator o = m_queue[b].begin(); + for(; o != m_queue[b].end(); o++ ) { + o->dump(fp); + } + fprintf(fp,"\n"); + } + fprintf(fp," grants:\n"); + for(unsigned b=0;b<m_num_banks;b++) { + fprintf(fp," bank %u : ", b ); + m_allocated_bank[b].dump(fp); + } + fprintf(fp,"\n"); + } + + // modifiers + std::list<op_t> allocate_reads(); + + void add_read_requests( collector_unit_t *cu ) + { + const op_t *src = cu->get_operands(); + for( unsigned i=0; i<MAX_REG_OPERANDS; i++) { + const op_t &op = src[i]; + if( op.valid() ) { + unsigned bank = op.get_bank(); + m_queue[bank].push_back(op); + } + } + } + void allocate_bank_for_write( unsigned bank, const op_t &op ) + { + m_allocated_bank[bank].alloc_write(op); + } + void allocate_for_read( unsigned bank, const op_t &op ) + { + m_allocated_bank[bank].alloc_read(op); + } + void reset_alloction() + { + for( unsigned b=0; b < m_num_banks; b++ ) + m_allocated_bank[b].reset(); + } + + private: + unsigned m_num_banks; + unsigned m_num_collectors; + + allocation_t *m_allocated_bank; // bank # -> register that wins + std::list<op_t> *m_queue; + + unsigned *m_allocator_rr_head; // cu # -> next bank to check for request (rr-arb) + unsigned m_last_cu; // first cu to check while arb-ing banks (rr) + }; + + class collector_unit_t { + public: + // constructors + collector_unit_t() + { + m_free = true; + m_warp = (inst_t*)calloc(sizeof(inst_t),::warp_size); + m_src_op = new op_t[MAX_REG_OPERANDS]; + m_not_ready.reset(); + m_tid = -1; + m_warp_id = -1; + } + // accessors + bool ready() const { return (!m_free) && m_not_ready.none(); } + 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() ); + } + } + } + } + + 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 set_cuid(unsigned n) { m_cuid=n; } + 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 collect_operand( unsigned op ) + { + m_not_ready.reset(op); + } + + void dispatch( inst_t *pipeline_reg ) + { + assert( m_not_ready.none() ); + move_warp(pipeline_reg,m_warp); + m_free=true; + for( unsigned i=0; i<MAX_REG_OPERANDS;i++) + m_src_op[i].reset(); + } + + private: + bool m_free; + unsigned m_tid; + unsigned m_cuid; // collector unit hw id + unsigned m_warp_id; + inst_t *m_warp; + op_t *m_src_op; + std::bitset<MAX_REG_OPERANDS> m_not_ready; + }; + + // data members + + unsigned m_num_collectors; + unsigned m_num_banks; + collector_unit_t *m_cu; + unsigned m_last_cu; // dispatch ready cu's rr + arbiter_t m_arbiter; + std::list<collector_unit_t*> m_free_cu; + const shader_core_ctx *m_shader; +}; + class barrier_set_t { public: barrier_set_t( unsigned max_warps_per_core, unsigned max_cta_per_core ); @@ -350,10 +725,9 @@ private: class mshr_shader_unit; -extern unsigned int warp_size; - -typedef struct shader_core_ctx : public core_t +class shader_core_ctx : public core_t { +public: shader_core_ctx( unsigned max_warps_per_cta, unsigned max_cta_per_core ); virtual void set_at_barrier( unsigned cta_id, unsigned warp_id ); @@ -390,6 +764,7 @@ typedef struct shader_core_ctx : public core_t // 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 @@ -447,7 +822,9 @@ typedef struct shader_core_ctx : public core_t unsigned int n_cta; //Limit on number of concurrent CTAs in shader core mshr_shader_unit *mshr_unit; -} shader_core_ctx_t; +}; + +typedef shader_core_ctx shader_core_ctx_t; shader_core_ctx_t* shader_create( const char *name, int sid, unsigned int n_threads, |
