diff options
| author | Ahmed El-Shafiey <[email protected]> | 2014-08-06 16:57:40 -0800 |
|---|---|---|
| committer | Andrew Boktor <[email protected]> | 2014-08-14 13:50:59 -0700 |
| commit | fd3c208f3c51c5520dcd7150d8a521a61577a9d5 (patch) | |
| tree | d17d3c9f47c67e1f56c9e567f51fe7f56dd599c3 /src/gpgpu-sim/shader.cc | |
| parent | 94a6b6c513c0afaf86770d2af0e41c8d7d0da3f5 (diff) | |
Support for named bariers + bar.red + bar.arrive instructions
[git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 18452]
Diffstat (limited to 'src/gpgpu-sim/shader.cc')
| -rw-r--r-- | src/gpgpu-sim/shader.cc | 150 |
1 files changed, 122 insertions, 28 deletions
diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index 3692c01..2fddadd 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -73,7 +73,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, const struct memory_config *mem_config, shader_core_stats *stats ) : core_t( gpu, NULL, config->warp_size, config->n_thread_per_shader ), - m_barriers( config->max_warps_per_shader, config->max_cta_per_core ), + m_barriers( this, config->max_warps_per_shader, config->max_cta_per_core, config->max_barriers_per_cta, config->warp_size ), m_dynamic_warp_id(0) { m_cluster = cluster; @@ -687,10 +687,13 @@ void shader_core_ctx::issue_warp( register_set& pipe_reg_set, const warp_inst_t* (*pipe_reg)->issue( active_mask, warp_id, gpu_tot_sim_cycle + gpu_sim_cycle, m_warp[warp_id].get_dynamic_warp_id() ); // dynamic instruction information m_stats->shader_cycle_distro[2+(*pipe_reg)->active_count()]++; func_exec_inst( **pipe_reg ); - if( next_inst->op == BARRIER_OP ) - m_barriers.warp_reaches_barrier(m_warp[warp_id].get_cta_id(),warp_id); - else if( next_inst->op == MEMORY_BARRIER_OP ) + if( next_inst->op == BARRIER_OP ){ + m_warp[warp_id].store_info_of_last_inst_at_barrier(*pipe_reg); + m_barriers.warp_reaches_barrier(m_warp[warp_id].get_cta_id(),warp_id,const_cast<warp_inst_t*> (next_inst)); + + }else if( next_inst->op == MEMORY_BARRIER_OP ){ m_warp[warp_id].set_membar(); + } updateSIMTStack(warp_id,*pipe_reg); m_scoreboard->reserveRegisters(*pipe_reg); @@ -865,8 +868,7 @@ void scheduler_unit::cycle() issued_inst=true; warp_inst_issued = true; } - } - } + } } } else { SCHED_DPRINTF( "Warp (warp_id %u, dynamic_warp_id %u) fails scoreboard\n", (*iter)->get_warp_id(), (*iter)->get_dynamic_warp_id() ); @@ -1153,7 +1155,7 @@ void shader_core_ctx::execute() m_fu[n]->active_lanes_in_pipeline(); enum pipeline_stage_name_t issue_port = m_issue_port[n]; register_set& issue_inst = m_pipeline_reg[ issue_port ]; - warp_inst_t** ready_reg = issue_inst.get_ready(); + warp_inst_t** ready_reg = issue_inst.get_ready(); if( issue_inst.has_ready() && m_fu[n]->can_issue( **ready_reg ) ) { bool schedule_wb_now = !m_fu[n]->stallable(); int resbus = -1; @@ -1234,7 +1236,7 @@ void shader_core_ctx::writeback() warp_inst_t** preg = m_pipeline_reg[EX_WB].get_ready(); warp_inst_t* pipe_reg = (preg==NULL)? NULL:*preg; - while( preg and !pipe_reg->empty() ) { + while( preg and !pipe_reg->empty()) { /* * Right now, the writeback stage drains all waiting instructions * assuming there are enough ports in the register file or the @@ -1251,6 +1253,7 @@ void shader_core_ctx::writeback() * To handle this case, we ignore the return value (thus allowing * no stalling). */ + m_operand_collector.writeback(*pipe_reg); unsigned warp_id = pipe_reg->warp_id(); m_scoreboard->releaseRegisters( pipe_reg ); @@ -1514,6 +1517,22 @@ pipelined_simd_unit::pipelined_simd_unit( register_set* result_port, const shade m_core=core; } +void pipelined_simd_unit::cycle() +{ + if( !m_pipeline_reg[0]->empty() ){ + m_result_port->move_in(m_pipeline_reg[0]); + } + for( unsigned stage=0; (stage+1)<m_pipeline_depth; stage++ ) + move_warp(m_pipeline_reg[stage], m_pipeline_reg[stage+1]); + if( !m_dispatch_reg->empty() ) { + if( !m_dispatch_reg->dispatch_delay()){ + int start_stage = m_dispatch_reg->latency - m_dispatch_reg->initiation_interval; + move_warp(m_pipeline_reg[start_stage],m_dispatch_reg); + } + } + occupied >>=1; +} + void pipelined_simd_unit::issue( register_set& source_reg ) { @@ -2520,17 +2539,28 @@ std::list<opndcoll_rfu_t::op_t> opndcoll_rfu_t::arbiter_t::allocate_reads() return result; } -barrier_set_t::barrier_set_t( unsigned max_warps_per_core, unsigned max_cta_per_core ) +barrier_set_t::barrier_set_t(shader_core_ctx *shader,unsigned max_warps_per_core, unsigned max_cta_per_core, unsigned max_barriers_per_cta, unsigned warp_size) { m_max_warps_per_core = max_warps_per_core; m_max_cta_per_core = max_cta_per_core; + m_max_barriers_per_cta = max_barriers_per_cta; + m_warp_size = warp_size; + m_shader = shader; if( max_warps_per_core > WARP_PER_CTA_MAX ) { printf("ERROR ** increase WARP_PER_CTA_MAX in shader.h from %u to >= %u or warps per cta in gpgpusim.config\n", WARP_PER_CTA_MAX, max_warps_per_core ); exit(1); } + if(max_barriers_per_cta > MAX_BARRIERS_PER_CTA){ + printf("ERROR ** increase MAX_BARRIERS_PER_CTA in abstract_hardware_model.h from %u to >= %u or barriers per cta in gpgpusim.config\n", + MAX_BARRIERS_PER_CTA, max_barriers_per_cta ); + exit(1); + } m_warp_active.reset(); m_warp_at_barrier.reset(); + for(unsigned i=0; i<max_barriers_per_cta; i++){ + m_bar_id_to_warps[i].reset(); + } } // during cta allocation @@ -2544,6 +2574,10 @@ void barrier_set_t::allocate_barrier( unsigned cta_id, warp_set_t warps ) m_warp_active |= warps; m_warp_at_barrier &= ~warps; + for(unsigned i=0; i<m_max_barriers_per_cta; i++){ + m_bar_id_to_warps[i] &=~warps; + } + } // during cta deallocation @@ -2559,12 +2593,23 @@ void barrier_set_t::deallocate_barrier( unsigned cta_id ) assert( active.any() == false ); // no warps in CTA still running m_warp_active &= ~warps; m_warp_at_barrier &= ~warps; + + for(unsigned i=0; i<m_max_barriers_per_cta; i++){ + warp_set_t at_a_specific_barrier = warps & m_bar_id_to_warps[i]; + assert( at_a_specific_barrier.any() == false ); // no warps stuck at barrier + m_bar_id_to_warps[i] &=~warps; + } m_cta_to_warps.erase(w); } // individual warp hits barrier -void barrier_set_t::warp_reaches_barrier( unsigned cta_id, unsigned warp_id ) +void barrier_set_t::warp_reaches_barrier(unsigned cta_id,unsigned warp_id,warp_inst_t* inst) { + barrier_type bar_type = inst->bar_type; + reduction_type red_type = inst->red_type; + unsigned bar_id = inst->bar_id; + unsigned bar_count = inst->bar_count; + assert(bar_id!=(unsigned)-1); cta_to_warp_t::iterator w=m_cta_to_warps.find(cta_id); if( w == m_cta_to_warps.end() ) { // cta is active @@ -2574,24 +2619,42 @@ void barrier_set_t::warp_reaches_barrier( unsigned cta_id, unsigned warp_id ) } assert( w->second.test(warp_id) == true ); // warp is in cta - m_warp_at_barrier.set(warp_id); - + m_bar_id_to_warps[bar_id].set(warp_id); + if(bar_type==SYNC || bar_type==RED){ + m_warp_at_barrier.set(warp_id); + } warp_set_t warps_in_cta = w->second; - warp_set_t at_barrier = warps_in_cta & m_warp_at_barrier; + warp_set_t at_barrier = warps_in_cta & m_bar_id_to_warps[bar_id]; warp_set_t active = warps_in_cta & m_warp_active; + if(bar_count==(unsigned)-1){ + if( at_barrier == active ) { + printf("Barrier should be released\n"); + // all warps have reached barrier, so release waiting warps... + m_bar_id_to_warps[bar_id] &= ~at_barrier; + m_warp_at_barrier &= ~at_barrier; + if(bar_type==RED){ + printf("broadcast_barrier\n"); + m_shader->broadcast_barrier_reduction(cta_id, bar_id,at_barrier); + } + printf("warps at barrier = %u\n",m_warp_at_barrier.count()); + } + }else{ + // TODO: check on the hardware if the count should include warp that exited + if ((at_barrier.count() * m_warp_size) == bar_count){ + // required number of warps have reached barrier, so release waiting warps... + m_bar_id_to_warps[bar_id] &= ~at_barrier; + m_warp_at_barrier &= ~at_barrier; + if(bar_type==RED){ + printf("REDUCTION CALLED-2\n"); + m_shader->broadcast_barrier_reduction(cta_id, bar_id,at_barrier); + } + } + } - if( at_barrier == active ) { - // all warps have reached barrier, so release waiting warps... - m_warp_at_barrier &= ~at_barrier; - } -} -// fetching a warp -bool barrier_set_t::available_for_fetch( unsigned warp_id ) const -{ - return m_warp_active.test(warp_id) && m_warp_at_barrier.test(warp_id); } + // warp reaches exit void barrier_set_t::warp_exit( unsigned warp_id ) { @@ -2605,12 +2668,15 @@ void barrier_set_t::warp_exit( unsigned warp_id ) if (w->second.test(warp_id) == true) break; } warp_set_t warps_in_cta = w->second; - warp_set_t at_barrier = warps_in_cta & m_warp_at_barrier; warp_set_t active = warps_in_cta & m_warp_active; - if( at_barrier == active ) { - // all warps have reached barrier, so release waiting warps... - m_warp_at_barrier &= ~at_barrier; + for(unsigned i=0; i<m_max_barriers_per_cta; i++){ + warp_set_t at_a_specific_barrier = warps_in_cta & m_bar_id_to_warps[i]; + if( at_a_specific_barrier == active ) { + // all warps have reached barrier, so release waiting warps... + m_bar_id_to_warps[i] &= ~at_a_specific_barrier; + m_warp_at_barrier &= ~at_a_specific_barrier; + } } } @@ -2620,11 +2686,12 @@ bool barrier_set_t::warp_waiting_at_barrier( unsigned warp_id ) const return m_warp_at_barrier.test(warp_id); } -void barrier_set_t::dump() const +void barrier_set_t::dump() { printf( "barrier set information\n"); printf( " m_max_cta_per_core = %u\n", m_max_cta_per_core ); printf( " m_max_warps_per_core = %u\n", m_max_warps_per_core ); + printf( " m_max_barriers_per_cta =%u\n", m_max_barriers_per_cta); printf( " cta_to_warps:\n"); cta_to_warp_t::const_iterator i; @@ -2635,6 +2702,10 @@ void barrier_set_t::dump() const } printf(" warp_active: %s\n", m_warp_active.to_string().c_str() ); printf(" warp_at_barrier: %s\n", m_warp_at_barrier.to_string().c_str() ); + for( unsigned i=0; i<m_max_barriers_per_cta; i++){ + warp_set_t warps_reached_barrier = m_bar_id_to_warps[i]; + printf(" warp_at_barrier %u: %s\n", i, warps_reached_barrier.to_string().c_str() ); + } fflush(stdout); } @@ -2658,6 +2729,18 @@ void shader_core_ctx::warp_exit( unsigned warp_id ) m_barriers.warp_exit( warp_id ); } +bool shader_core_ctx::check_if_non_released_reduction_barrier(warp_inst_t &inst) +{ + unsigned warp_id = inst.warp_id(); + bool bar_red_op = (inst.op == BARRIER_OP) && (inst.bar_type == RED); + bool non_released_barrier_reduction = false; + bool warp_stucked_at_barrier = warp_waiting_at_barrier(warp_id); + bool single_inst_in_pipeline = (m_warp[warp_id].num_issued_inst_in_pipeline()==1); + non_released_barrier_reduction = single_inst_in_pipeline and warp_stucked_at_barrier and bar_red_op; + printf("non_released_barrier_reduction=%u\n",non_released_barrier_reduction); + return non_released_barrier_reduction; +} + bool shader_core_ctx::warp_waiting_at_barrier( unsigned warp_id ) const { return m_barriers.warp_waiting_at_barrier(warp_id); @@ -2690,6 +2773,17 @@ void shader_core_ctx::decrement_atomic_count( unsigned wid, unsigned n ) m_warp[wid].dec_n_atomic(n); } +void shader_core_ctx::broadcast_barrier_reduction(unsigned cta_id,unsigned bar_id,warp_set_t warps) +{ + unsigned value = get_reduction_value(cta_id,bar_id); + for(unsigned i=0; i<m_config->max_warps_per_shader;i++){ + if(warps.test(i)){ + printf("braodcast for i=%u\n",i); + const warp_inst_t * inst = m_warp[i].restore_info_of_last_inst_at_barrier(); + const_cast<warp_inst_t *> (inst)->broadcast_barrier_reduction(inst->get_active_mask()); + } + } +} bool shader_core_ctx::fetch_unit_response_buffer_full() const { @@ -3340,7 +3434,7 @@ void simt_core_cluster::get_L1T_sub_stats(struct cache_sub_stats &css) const{ void shader_core_ctx::checkExecutionStatusAndUpdate(warp_inst_t &inst, unsigned t, unsigned tid) { - if( inst.has_callback(t) ) + if(inst.isatomic()) m_warp[inst.warp_id()].inc_n_atomic(); if (inst.space.is_local() && (inst.is_load() || inst.is_store())) { new_addr_type localaddrs[MAX_ACCESSES_PER_INSN_PER_THREAD]; |
