summaryrefslogtreecommitdiff
path: root/src/gpgpu-sim
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpgpu-sim')
-rw-r--r--src/gpgpu-sim/gpu-sim.cc21
-rw-r--r--src/gpgpu-sim/shader.cc260
-rw-r--r--src/gpgpu-sim/shader.h38
3 files changed, 279 insertions, 40 deletions
diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc
index 9055502..1f7de38 100644
--- a/src/gpgpu-sim/gpu-sim.cc
+++ b/src/gpgpu-sim/gpu-sim.cc
@@ -327,7 +327,26 @@ void memory_config::reg_options(class OptionParser *opp) {
void shader_core_config::reg_options(class OptionParser *opp) {
option_parser_register(opp, "-gpgpu_simd_model", OPT_INT32, &model,
- "1 = post-dominator", "1");
+ "1 = post-dominator, 2 = AWARE reconvergence (ITS)",
+ "1");
+ option_parser_register(opp, "-gpgpu_simd_rec_time_out", OPT_INT32,
+ &rec_time_out,
+ "reconvergence timeout (-1 = disabled)", "-1");
+ option_parser_register(opp, "-gpgpu_simd_rec_size", OPT_INT32,
+ &num_rec_entries,
+ "number of physical reconvergence table entries",
+ "32");
+ option_parser_register(opp, "-gpgpu_simd_st_size", OPT_INT32,
+ &num_st_entries,
+ "number of physical splits table entries", "32");
+ option_parser_register(opp, "-gpgpu_simd_rec_replacement", OPT_INT32,
+ &rec_replacement,
+ "reconvergence table replacement policy (1 = LRU)",
+ "1");
+ option_parser_register(opp, "-gpgpu_simd_st_replacement", OPT_INT32,
+ &st_replacement,
+ "splits table replacement policy (1 = FIFO_BACK)",
+ "1");
option_parser_register(
opp, "-gpgpu_shader_core_pipeline", OPT_CSTR,
&gpgpu_shader_core_pipeline_opt,
diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc
index 7a4ff37..bcf38d3 100644
--- a/src/gpgpu-sim/shader.cc
+++ b/src/gpgpu-sim/shader.cc
@@ -465,6 +465,9 @@ void shader_core_ctx::create_exec_pipeline() {
for (unsigned i = 0; i < num_result_bus; i++) {
this->m_result_bus.push_back(new std::bitset<MAX_ALU_LATENCY>());
}
+
+ if (m_config->model == AWARE_RECONVERGENCE)
+ updateSIMTDivergenceStructuresInitialization();
}
shader_core_ctx::shader_core_ctx(class gpgpu_sim *gpu,
@@ -526,7 +529,11 @@ void shader_core_ctx::reinit(unsigned start_thread, unsigned end_thread,
for (unsigned i = start_thread / m_config->warp_size;
i < end_thread / m_config->warp_size; ++i) {
m_warp[i]->reset();
- m_simt_stack[i]->reset();
+ if (m_config->model == POST_DOMINATOR) {
+ m_simt_stack[i]->reset();
+ } else {
+ m_simt_tables[i]->reset();
+ }
}
}
@@ -535,23 +542,24 @@ void shader_core_ctx::init_warps(unsigned cta_id, unsigned start_thread,
int cta_size, kernel_info_t &kernel) {
address_type start_pc = next_pc(start_thread);
unsigned kernel_id = kernel.get_uid();
- if (m_config->model == POST_DOMINATOR) {
- unsigned start_warp = start_thread / m_config->warp_size;
- unsigned warp_per_cta = cta_size / m_config->warp_size;
- unsigned end_warp = end_thread / m_config->warp_size +
- ((end_thread % m_config->warp_size) ? 1 : 0);
- for (unsigned i = start_warp; i < end_warp; ++i) {
- unsigned n_active = 0;
- simt_mask_t active_threads;
- for (unsigned t = 0; t < m_config->warp_size; t++) {
- unsigned hwtid = i * m_config->warp_size + t;
- if (hwtid < end_thread) {
- n_active++;
- assert(!m_active_threads.test(hwtid));
- m_active_threads.set(hwtid);
- active_threads.set(t);
- }
+ unsigned start_warp = start_thread / m_config->warp_size;
+ unsigned warp_per_cta = cta_size / m_config->warp_size;
+ unsigned end_warp = end_thread / m_config->warp_size +
+ ((end_thread % m_config->warp_size) ? 1 : 0);
+ for (unsigned i = start_warp; i < end_warp; ++i) {
+ unsigned n_active = 0;
+ simt_mask_t active_threads;
+ for (unsigned t = 0; t < m_config->warp_size; t++) {
+ unsigned hwtid = i * m_config->warp_size + t;
+ if (hwtid < end_thread) {
+ n_active++;
+ assert(!m_active_threads.test(hwtid));
+ m_active_threads.set(hwtid);
+ active_threads.set(t);
}
+ }
+
+ if (m_config->model == POST_DOMINATOR) {
m_simt_stack[i]->launch(start_pc, active_threads);
if (m_gpu->resume_option == 1 && kernel_id == m_gpu->resume_kernel &&
@@ -570,13 +578,15 @@ void shader_core_ctx::init_warps(unsigned cta_id, unsigned start_thread,
}
start_pc = pc;
}
-
- m_warp[i]->init(start_pc, cta_id, i, active_threads, m_dynamic_warp_id,
- kernel.get_streamID());
- ++m_dynamic_warp_id;
- m_not_completed += n_active;
- ++m_active_warps;
+ } else {
+ m_simt_tables[i]->launch(start_pc, active_threads);
}
+
+ m_warp[i]->init(start_pc, cta_id, i, active_threads, m_dynamic_warp_id,
+ kernel.get_streamID());
+ ++m_dynamic_warp_id;
+ m_not_completed += n_active;
+ ++m_active_warps;
}
}
@@ -599,7 +609,11 @@ void gpgpu_sim::get_pdom_stack_top_info(unsigned sid, unsigned tid,
void shader_core_ctx::get_pdom_stack_top_info(unsigned tid, unsigned *pc,
unsigned *rpc) const {
unsigned warp_id = tid / m_config->warp_size;
- m_simt_stack[warp_id]->get_pdom_stack_top_info(pc, rpc);
+ if (m_config->model == POST_DOMINATOR) {
+ m_simt_stack[warp_id]->get_pdom_stack_top_info(pc, rpc);
+ } else {
+ m_simt_tables[warp_id]->get_pdom_active_split_info(pc, rpc);
+ }
}
float shader_core_ctx::get_current_occupancy(unsigned long long &active,
@@ -879,12 +893,20 @@ void exec_shader_core_ctx::get_pdom_stack_top_info(unsigned warp_id,
const warp_inst_t *pI,
unsigned *pc,
unsigned *rpc) {
- m_simt_stack[warp_id]->get_pdom_stack_top_info(pc, rpc);
+ if (m_config->model == POST_DOMINATOR) {
+ m_simt_stack[warp_id]->get_pdom_stack_top_info(pc, rpc);
+ } else {
+ m_simt_tables[warp_id]->get_pdom_active_split_info(pc, rpc);
+ }
}
const active_mask_t &exec_shader_core_ctx::get_active_mask(
unsigned warp_id, const warp_inst_t *pI) {
- return m_simt_stack[warp_id]->get_active_mask();
+ if (m_config->model == POST_DOMINATOR) {
+ return m_simt_stack[warp_id]->get_active_mask();
+ } else {
+ return m_simt_tables[warp_id]->get_active_mask();
+ }
}
void shader_core_ctx::decode() {
@@ -974,7 +996,11 @@ void shader_core_ctx::fetch() {
}
// this code fetches instructions from the i-cache or generates memory
- if (!m_warp[warp_id]->functional_done() &&
+ bool simt_conditions = true;
+ if (m_config->model == AWARE_RECONVERGENCE)
+ simt_conditions = !is_virtualized(warp_id);
+
+ if (simt_conditions && !m_warp[warp_id]->functional_done() &&
!m_warp[warp_id]->imiss_pending() &&
m_warp[warp_id]->ibuffer_empty()) {
address_type pc;
@@ -1070,11 +1096,31 @@ void shader_core_ctx::issue_warp(register_set &pipe_reg_set,
}
}
+ bool split_reaches_barrier = false;
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));
-
+ if (m_config->model == POST_DOMINATOR) {
+ m_barriers.warp_reaches_barrier(m_warp[warp_id]->get_cta_id(), warp_id,
+ const_cast<warp_inst_t *>(next_inst));
+ } else {
+ // AWARE_RECONVERGENCE: warp reaches barrier only when all its splits do
+ split_reaches_barrier = true;
+ bool warp_reaches_barrier =
+ m_simt_tables[warp_id]->split_reaches_barrier(next_inst->pc);
+ if (warp_reaches_barrier) {
+ split_reaches_barrier = false;
+ m_barriers.warp_reaches_barrier(m_warp[warp_id]->get_cta_id(), warp_id,
+ const_cast<warp_inst_t *>(next_inst));
+ if (m_barriers.warps_count_at_barrier(m_warp[warp_id]->get_cta_id()) ==
+ 0) {
+ unsigned n = m_config->n_thread_per_shader / m_config->warp_size;
+ for (unsigned i = 0; i < n; i++) {
+ if (m_warp[i]->get_cta_id() == m_warp[warp_id]->get_cta_id())
+ m_simt_tables[i]->release_barrier();
+ }
+ }
+ }
+ }
} else if (next_inst->op == MEMORY_BARRIER_OP) {
m_warp[warp_id]->set_membar();
} else if (next_inst->m_is_ldgdepbar) { // Add for LDGDEPBAR
@@ -1120,10 +1166,11 @@ void shader_core_ctx::issue_warp(register_set &pipe_reg_set,
}
}
- updateSIMTStack(warp_id, *pipe_reg);
+ updateSIMTDivergenceStructures(warp_id, *pipe_reg);
m_scoreboard->reserveRegisters(*pipe_reg);
m_warp[warp_id]->set_next_pc(next_inst->pc + next_inst->isize);
+ if (split_reaches_barrier) m_simt_tables[warp_id]->push_back();
}
void shader_core_ctx::issue() {
@@ -1299,9 +1346,17 @@ void scheduler_unit::cycle() {
"barrier\n",
(*iter)->get_warp_id(), (*iter)->get_dynamic_warp_id());
- while (!warp(warp_id).waiting() && !warp(warp_id).ibuffer_empty() &&
- (checked < max_issue) && (checked <= issued) &&
- (issued < max_issue)) {
+ bool simt_conditions = true;
+ if (m_shader->m_config->model == AWARE_RECONVERGENCE) {
+ simt_conditions = warp(warp_id).valid() &&
+ !warp(warp_id).blocked() &&
+ !warp(warp_id).pending_reconvergence() &&
+ !warp(warp_id).virtualized();
+ }
+
+ while (simt_conditions && !warp(warp_id).waiting() &&
+ !warp(warp_id).ibuffer_empty() && (checked < max_issue) &&
+ (checked <= issued) && (issued < max_issue)) {
const warp_inst_t *pI = warp(warp_id).ibuffer_next_inst();
// Jin: handle cdp latency;
if (pI && pI->m_is_cdp && warp(warp_id).m_cdp_latency > 0) {
@@ -1415,12 +1470,18 @@ void scheduler_unit::cycle() {
}
if (execute_on_SP) {
+ bool bru_avail = true;
+ if (m_shader->m_config->model == AWARE_RECONVERGENCE &&
+ pI->op == BRANCH_OP)
+ bru_avail = m_shader->branch_unit_avail(warp_id);
+ if (bru_avail) {
m_shader->issue_warp(*m_sp_out, pI, active_mask, warp_id,
m_id);
issued++;
issued_inst = true;
warp_inst_issued = true;
previous_issued_inst_exec_type = exec_unit_type_t::SP;
+ }
} else if (execute_on_INT) {
m_shader->issue_warp(*m_int_out, pI, active_mask, warp_id,
m_id);
@@ -1836,6 +1897,14 @@ void shader_core_ctx::execute() {
}
}
}
+
+ // ITS: advance spill/fill state machines for all warps
+ if (m_config->model == AWARE_RECONVERGENCE) {
+ for (unsigned i = 0; i < m_warp_count; ++i) {
+ AWARE_DPRINTF("Cycling SIMT tables for Shader %d: Warp %d...\n", m_sid, i);
+ m_simt_tables[i]->cycle();
+ }
+ }
}
void ldst_unit::print_cache_stats(FILE *fp, unsigned &dl1_accesses,
@@ -2013,7 +2082,9 @@ mem_stage_stall_type ldst_unit::process_cache_access(
if (status == HIT) {
assert(!read_sent);
inst.accessq_pop_back();
- if (inst.is_load()) {
+ if (inst.is_bru_st_fill_request() || inst.is_bru_rt_fill_request()) {
+ release_virtual_entries(inst);
+ } else if (inst.is_load()) {
for (unsigned r = 0; r < MAX_OUTPUT_VALUES; r++)
if (inst.out[r] > 0) m_pending_writes[inst.warp_id()][inst.out[r]]--;
@@ -2698,10 +2769,41 @@ void ldst_unit::issue(register_set &reg_set) {
pipelined_simd_unit::issue(reg_set);
}
+void ldst_unit::release_virtual_entries(warp_inst_t &inst) {
+ if (inst.is_bru_st_fill_request()) {
+ unsigned wid = inst.warp_id();
+ address_type addr = inst.pc;
+ unsigned entry = (addr - BRU_VIR_START -
+ (wid * m_config->warp_size) * MAX_BRU_VIR_PER_SPLIT) /
+ MAX_BRU_VIR_PER_SPLIT;
+ bool done = m_core->push_to_st_response_fifo(wid, entry);
+ if (done) {
+ inst.clear();
+ inst.clear_pending_mem_requests();
+ }
+ } else {
+ assert(inst.is_bru_rt_fill_request());
+ unsigned wid = inst.warp_id();
+ address_type addr = inst.pc;
+ unsigned entry = (addr - BRU_VIR_START -
+ (wid * m_config->warp_size) * MAX_BRU_VIR_PER_SPLIT -
+ MAX_BRU_VIR_PER_SPLIT / 2) /
+ MAX_BRU_VIR_PER_SPLIT;
+ bool done = m_core->push_to_rt_response_fifo(wid, entry);
+ if (done) {
+ inst.clear();
+ inst.clear_pending_mem_requests();
+ }
+ }
+}
+
void ldst_unit::writeback() {
// process next instruction that is going to writeback
if (!m_next_wb.empty()) {
- if (m_operand_collector->writeback(m_next_wb)) {
+ if (m_next_wb.is_bru_st_fill_request() ||
+ m_next_wb.is_bru_rt_fill_request()) {
+ release_virtual_entries(m_next_wb);
+ } else if (m_operand_collector->writeback(m_next_wb)) {
bool insn_completed = false;
for (unsigned r = 0; r < MAX_OUTPUT_VALUES; r++) {
if (m_next_wb.out[r] > 0) {
@@ -3357,7 +3459,10 @@ void shader_core_ctx::display_simt_state(FILE *fout, int mask) const {
if (nactive == 0) {
continue;
}
- m_simt_stack[i]->print(fout);
+ if (m_config->model == POST_DOMINATOR)
+ m_simt_stack[i]->print(fout);
+ else
+ m_simt_tables[i]->print(fout);
}
fprintf(fout, "\n");
}
@@ -3673,6 +3778,12 @@ void shader_core_config::set_pipeline_latency() {
void shader_core_ctx::cycle() {
if (!isactive() && get_not_completed() == 0) return;
+ if (m_config->model == AWARE_RECONVERGENCE && m_config->rec_time_out > 0) {
+ unsigned long long total_cycles =
+ m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle;
+ if (total_cycles % 10000 == 0) check_time_out();
+ }
+
m_stats->shader_cycles[m_sid]++;
writeback();
execute();
@@ -4114,6 +4225,81 @@ bool shd_warp_t::waiting() {
return false;
}
+// ITS (AWARE Reconvergence) warp eligibility helpers
+bool shd_warp_t::virtualized() {
+ return m_shader->is_virtualized(m_warp_id);
+}
+
+bool shd_warp_t::pending_reconvergence() {
+ return m_shader->pending_reconvergence(m_warp_id);
+}
+
+bool shd_warp_t::blocked() {
+ return m_shader->warp_blocked(m_warp_id);
+}
+
+bool shd_warp_t::valid() {
+ return m_shader->warp_valid(m_warp_id);
+}
+
+// ITS (AWARE Reconvergence) shader_core_ctx methods
+void shader_core_ctx::updateSIMTDivergenceStructuresInitialization() {
+ unsigned n = m_config->n_thread_per_shader / m_config->warp_size;
+ for (unsigned i = 0; i < n; i++) {
+ m_simt_tables[i]->set_shader(this);
+ }
+}
+
+bool shader_core_ctx::push_to_st_response_fifo(unsigned wid, unsigned entry) {
+ return m_simt_tables[wid]->push_to_st_response_fifo(entry);
+}
+
+bool shader_core_ctx::push_to_rt_response_fifo(unsigned wid, unsigned entry) {
+ return m_simt_tables[wid]->push_to_rt_response_fifo(entry);
+}
+
+bool shader_core_ctx::is_virtualized(unsigned wid) {
+ return m_simt_tables[wid]->is_virtualized();
+}
+
+bool shader_core_ctx::pending_reconvergence(unsigned wid) {
+ return m_simt_tables[wid]->is_pending_reconvergence();
+}
+
+bool shader_core_ctx::warp_blocked(unsigned wid) {
+ return m_simt_tables[wid]->blocked();
+}
+
+bool shader_core_ctx::warp_valid(unsigned wid) {
+ return m_simt_tables[wid]->valid();
+}
+
+void shader_core_ctx::update_st_size(unsigned n) {
+ // Stats not tracked in gpgpu-sim base; no-op.
+ (void)n;
+}
+
+void shader_core_ctx::update_rt_size(unsigned n) {
+ // Stats not tracked in gpgpu-sim base; no-op.
+ (void)n;
+}
+
+bool shader_core_ctx::branch_unit_avail(unsigned wid) {
+ return m_simt_tables[wid]->branch_unit_avail();
+}
+
+void shader_core_ctx::check_time_out() {
+ for (unsigned w = 0; w < m_config->max_warps_per_shader; w++) {
+ m_simt_tables[w]->check_time_out();
+ }
+}
+
+bool shader_core_ctx::memory_cycle(warp_inst_t &inst,
+ mem_stage_stall_type &rc_fail,
+ mem_stage_access_type &fail_type) {
+ return m_ldst_unit->memory_cycle(inst, rc_fail, fail_type);
+}
+
void shd_warp_t::print(FILE *fout) const {
if (!done_exit()) {
fprintf(fout,
diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h
index 5922d24..bb2ac33 100644
--- a/src/gpgpu-sim/shader.h
+++ b/src/gpgpu-sim/shader.h
@@ -177,6 +177,12 @@ class shd_warp_t {
bool waiting(); // not const due to membar
bool hardware_done() const;
+ // ITS (AWARE Reconvergence) warp eligibility helpers
+ bool virtualized();
+ bool pending_reconvergence();
+ bool blocked();
+ bool valid();
+
bool done_exit() const { return m_done_exit; }
void set_done_exit() { m_done_exit = true; }
@@ -1081,6 +1087,12 @@ class barrier_set_t {
// assertions
bool warp_waiting_at_barrier(unsigned warp_id) const;
+ // ITS: count warps from a given CTA that are at barrier
+ unsigned warps_count_at_barrier(int cta_id) {
+ warp_set_t t = m_cta_to_warps[cta_id] & m_warp_at_barrier;
+ return t.count();
+ }
+
// debug
void dump();
@@ -1371,6 +1383,9 @@ class ldst_unit : public pipelined_simd_unit {
void flush();
void invalidate();
void writeback();
+ void release_virtual_entries(warp_inst_t &inst);
+ bool memory_cycle(warp_inst_t &inst, mem_stage_stall_type &rc_fail,
+ mem_stage_access_type &fail_type);
// accessors
virtual unsigned clock_multiplier() const;
@@ -1429,8 +1444,6 @@ class ldst_unit : public pipelined_simd_unit {
mem_stage_access_type &fail_type);
bool texture_cycle(warp_inst_t &inst, mem_stage_stall_type &rc_fail,
mem_stage_access_type &fail_type);
- bool memory_cycle(warp_inst_t &inst, mem_stage_stall_type &rc_fail,
- mem_stage_access_type &fail_type);
virtual mem_stage_stall_type process_cache_access(
cache_t *cache, new_addr_type address, warp_inst_t &inst,
@@ -1622,6 +1635,12 @@ class shader_core_config : public core_config {
bool gpgpu_clock_gated_reg_file;
bool gpgpu_clock_gated_lanes;
enum divergence_support_t model;
+ // ITS (AWARE Reconvergence) config
+ int rec_time_out; // -1 = no reconvergence timeout
+ int num_rec_entries; // physical entries in reconvergence table
+ int num_st_entries; // physical entries in splits table
+ int rec_replacement; // reconvergence table replacement policy
+ int st_replacement; // splits table replacement policy
unsigned n_thread_per_shader;
unsigned n_regfile_gating_group;
unsigned max_warps_per_shader;
@@ -2423,6 +2442,21 @@ class shader_core_ctx : public core_t {
}
bool check_if_non_released_reduction_barrier(warp_inst_t &inst);
+ // ITS (AWARE Reconvergence) methods
+ bool is_virtualized(unsigned wid);
+ bool pending_reconvergence(unsigned wid);
+ bool warp_blocked(unsigned wid);
+ bool warp_valid(unsigned wid);
+ bool push_to_st_response_fifo(unsigned wid, unsigned entry);
+ bool push_to_rt_response_fifo(unsigned wid, unsigned entry);
+ void update_st_size(unsigned n);
+ void update_rt_size(unsigned n);
+ void check_time_out();
+ bool branch_unit_avail(unsigned wid);
+ bool memory_cycle(warp_inst_t &inst, mem_stage_stall_type &rc_fail,
+ mem_stage_access_type &fail_type);
+ void updateSIMTDivergenceStructuresInitialization();
+
protected:
unsigned inactive_lanes_accesses_sfu(unsigned active_count, double latency) {
return (((32 - active_count) >> 1) * latency) +