summaryrefslogtreecommitdiff
path: root/src/gpgpu-sim/shader.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpgpu-sim/shader.cc')
-rw-r--r--src/gpgpu-sim/shader.cc70
1 files changed, 62 insertions, 8 deletions
diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc
index 43e86b6..bf6c9c0 100644
--- a/src/gpgpu-sim/shader.cc
+++ b/src/gpgpu-sim/shader.cc
@@ -1350,10 +1350,16 @@ void shader_core_ctx::co_issue_warp(warp_inst_t *composite,
if (split_id == (unsigned)-1) {
// Inter-warp co-issue: different warp_id, always safe to reserve
m_scoreboard->reserveRegisters(&temp_inst);
+ } else {
+ // Intra-warp co-issue: reserve on secondary scoreboard to track
+ // dependencies within the secondary split's instruction stream.
+ // Cannot use primary scoreboard (would abort on duplicate register names).
+ for (unsigned r = 0; r < MAX_OUTPUT_VALUES; r++) {
+ if (temp_inst.out[r] > 0) {
+ m_scoreboard->reserveRegisterSecondary(warp_id, temp_inst.out[r]);
+ }
+ }
}
- // For intra-warp: we skip reservation. The primary's reservation covers
- // shared registers, and non-shared registers will still be released at
- // writeback (the release tolerates releasing non-reserved registers).
// Set next PC for the co-issued warp
m_warp[warp_id]->set_next_pc(next_inst->pc + next_inst->isize);
@@ -1363,6 +1369,11 @@ void shader_core_ctx::co_issue_warp(warp_inst_t *composite,
// Merge the co-issued instruction's valid sets into the composite
composite->merge_simd_sets(temp_inst.get_simd_sets());
+
+ // Use max latency across all co-issued instructions for result bus reservation
+ if (temp_inst.latency > composite->latency) {
+ composite->latency = temp_inst.latency;
+ }
}
void shader_core_ctx::issue() {
@@ -1584,6 +1595,7 @@ void scheduler_unit::cycle() {
// control hazard
warp(warp_id).set_next_pc(pc);
warp(warp_id).ibuffer_flush();
+ m_scoreboard->clearSecondary(warp_id);
} else {
valid_inst = true;
if (!m_scoreboard->checkCollision(warp_id, pI)) {
@@ -1800,6 +1812,7 @@ void scheduler_unit::cycle() {
(*iter)->get_warp_id(), (*iter)->get_dynamic_warp_id());
warp(warp_id).set_next_pc(pc);
warp(warp_id).ibuffer_flush();
+ m_scoreboard->clearSecondary(warp_id);
}
if (warp_inst_issued) {
SCHED_DPRINTF(
@@ -2008,6 +2021,7 @@ void scheduler_unit::cycle() {
// Verify the split is still valid in the splits table
if (!m_shader->is_split_valid(primary_warp_id, sec_split_id)) {
warp(primary_warp_id).ibuffer_flush_half(1);
+ m_scoreboard->clearSecondary(primary_warp_id);
break;
}
@@ -2018,6 +2032,7 @@ void scheduler_unit::cycle() {
&split_mask);
if (split_pc != sec_inst->pc) {
warp(primary_warp_id).ibuffer_flush_half(1);
+ m_scoreboard->clearSecondary(primary_warp_id);
break;
}
@@ -2052,6 +2067,10 @@ void scheduler_unit::cycle() {
}
if (sec_fu_type != co_issue_fu_type) continue;
+ // Secondary scoreboard check: dependencies within secondary stream
+ if (m_scoreboard->checkCollisionSecondary(primary_warp_id, sec_inst))
+ continue;
+
// Compute sets needed
unsigned sec_active = sec_mask.count();
unsigned sec_sets_needed = (sec_active + set_width - 1) / set_width;
@@ -2080,6 +2099,7 @@ void scheduler_unit::cycle() {
if (!m_shader->is_split_valid(primary_warp_id, sec_split_id)) {
// Split was invalidated by the update — flush the entire secondary half
warp(primary_warp_id).ibuffer_flush_half(1);
+ m_scoreboard->clearSecondary(primary_warp_id);
break;
}
}
@@ -2541,8 +2561,14 @@ void shader_core_ctx::writeback() {
co_issued_warps_decremented.insert(sets[s].warp_id);
}
} else {
- // Intra-warp: dec once for the co-issued split (same warp_id)
+ // Intra-warp: release from secondary scoreboard and dec once
if (!intra_warp_decremented) {
+ for (unsigned r = 0; r < MAX_OUTPUT_VALUES; r++) {
+ if (sets[s].source_inst->out[r] > 0) {
+ m_scoreboard->releaseRegisterSecondary(
+ sets[s].warp_id, sets[s].source_inst->out[r]);
+ }
+ }
m_warp[warp_id]->dec_inst_in_pipeline();
intra_warp_decremented = true;
}
@@ -2554,6 +2580,35 @@ void shader_core_ctx::writeback() {
}
warp_inst_complete(*pipe_reg);
+
+ // Count additional co-issued instructions (not counted by warp_inst_complete)
+ if (m_config->gpgpu_simd_partitioning && pipe_reg->has_simd_sets()) {
+ const std::vector<simd_set_info> &sets = pipe_reg->get_simd_sets();
+ // Accumulate active threads per unique co-issued warp/split
+ std::map<unsigned, unsigned> inter_warp_threads; // warp_id -> thread count
+ unsigned intra_threads = 0;
+ for (unsigned s = 0; s < sets.size(); s++) {
+ if (!sets[s].valid || sets[s].source_inst == NULL) continue;
+ if (sets[s].warp_id != warp_id) {
+ inter_warp_threads[sets[s].warp_id] += sets[s].num_active_threads;
+ } else {
+ intra_threads += sets[s].num_active_threads;
+ }
+ }
+ // Inter-warp: one warp-instruction per unique co-issued warp
+ for (auto &entry : inter_warp_threads) {
+ m_stats->m_num_sim_winsn[m_sid]++;
+ m_gpu->gpu_sim_insn += entry.second;
+ m_stats->m_num_sim_insn[m_sid] += entry.second;
+ }
+ // Intra-warp: one warp-instruction for the co-issued split
+ if (intra_threads > 0) {
+ m_stats->m_num_sim_winsn[m_sid]++;
+ m_gpu->gpu_sim_insn += intra_threads;
+ m_stats->m_num_sim_insn[m_sid] += intra_threads;
+ }
+ }
+
m_gpu->gpu_sim_insn_last_update_sid = m_sid;
m_gpu->gpu_sim_insn_last_update = m_gpu->gpu_sim_cycle;
m_last_inst_gpu_sim_cycle = m_gpu->gpu_sim_cycle;
@@ -4985,8 +5040,7 @@ bool opndcoll_rfu_t::writeback(warp_inst_t &inst) {
const std::vector<simd_set_info> &sets = inst.get_simd_sets();
for (unsigned s = 0; s < sets.size(); s++) {
if (!sets[s].valid) continue;
- if (sets[s].warp_id == inst.warp_id()) continue;
- if (sets[s].source_inst == NULL) continue;
+ if (sets[s].source_inst == NULL) continue; // primary sets have NULL source_inst
for (unsigned op = 0; op < MAX_REG_OPERANDS; op++) {
int reg_num = sets[s].source_inst->arch_reg.dst[op];
@@ -5213,8 +5267,7 @@ bool opndcoll_rfu_t::collector_unit_t::allocate(register_set *pipeline_reg_set,
(*pipeline_reg)->get_simd_sets();
for (unsigned s = 0; s < sets.size(); s++) {
if (!sets[s].valid) continue;
- if (sets[s].warp_id == m_warp_id) continue;
- if (sets[s].source_inst == NULL) continue;
+ if (sets[s].source_inst == NULL) continue; // primary sets have NULL source_inst
std::vector<int> set_prev_regs;
for (unsigned op = 0; op < MAX_REG_OPERANDS && op_idx < MAX_REG_OPERANDS * 2; op++) {
@@ -5702,6 +5755,7 @@ void exec_shader_core_ctx::checkExecutionStatusAndUpdate(warp_inst_t &inst,
if (ptx_thread_done(tid)) {
m_warp[inst.warp_id()]->set_completed(t);
m_warp[inst.warp_id()]->ibuffer_flush();
+ m_scoreboard->clearSecondary(inst.warp_id());
}
// PC-Histogram Update