summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavit Grigoryan <[email protected]>2026-04-30 11:34:12 +0000
committerDavit Grigoryan <[email protected]>2026-04-30 11:34:12 +0000
commit54dafa606530557799a8db307e9eff410343fb89 (patch)
tree2f2927430bc9220e860589d84caa694366e8fa41 /src
parent208024b4007eba568d3787e72a345b3137e89ade (diff)
fix no compaction sb deadlock
Diffstat (limited to 'src')
-rw-r--r--src/abstract_hardware_model.cc21
-rw-r--r--src/gpgpu-sim/shader.cc72
2 files changed, 76 insertions, 17 deletions
diff --git a/src/abstract_hardware_model.cc b/src/abstract_hardware_model.cc
index 1010d00..b164c73 100644
--- a/src/abstract_hardware_model.cc
+++ b/src/abstract_hardware_model.cc
@@ -181,6 +181,16 @@ void warp_inst_t::compute_simd_sets(unsigned num_sets, unsigned set_width) {
info.set_active_mask.reset();
info.active_mask_in_warp.reset();
info.num_active_threads = 0;
+ // Pipeline-register warp_inst_t objects are reused, so the per-set
+ // coissuer-tracking fields can be stale from a prior issue. The LSU
+ // gates on (!valid || source_inst == NULL); without these resets a
+ // primary's set inherits a previous coissue's source_inst != NULL
+ // and split_id, causing m_pending_writes_secondary to be incremented
+ // on a key no future decrement targets → deadlock under sb1.
+ info.split_id = (unsigned)-1;
+ info.source_inst = NULL;
+ info.source_mask.reset();
+ info.source_slot_id = (unsigned)-1;
for (unsigned lane = 0; lane < set_width; lane++) {
unsigned tid = s * set_width + lane;
info.thread_ids[lane] = tid;
@@ -208,6 +218,11 @@ void warp_inst_t::compute_simd_sets_compacted(unsigned num_sets,
info.num_active_threads = 0;
info.valid = false;
info.source_inst = NULL;
+ // Clear remaining coissuer-tracking state stale from prior reuse.
+ // (source_inst=NULL alone defends LSU; reset the rest for symmetry.)
+ info.split_id = (unsigned)-1;
+ info.source_mask.reset();
+ info.source_slot_id = (unsigned)-1;
for (unsigned i = 0; i < MAX_WARP_SIZE; i++) info.thread_ids[i] = 0;
}
@@ -251,6 +266,12 @@ void warp_inst_t::compute_simd_sets_xor_static(unsigned num_sets,
info.set_active_mask.reset();
info.active_mask_in_warp.reset();
info.num_active_threads = 0;
+ // See compute_simd_sets — clear coissuer-tracking state stale from
+ // prior issues on this reused pipeline-register slot.
+ info.split_id = (unsigned)-1;
+ info.source_inst = NULL;
+ info.source_mask.reset();
+ info.source_slot_id = (unsigned)-1;
}
// xor_key = reverse of the low log2(warp_size) bits of m_warp_id
diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc
index e9c2e19..a86393c 100644
--- a/src/gpgpu-sim/shader.cc
+++ b/src/gpgpu-sim/shader.cc
@@ -2477,8 +2477,18 @@ void scheduler_unit::try_utilization_max_coissue(
continue;
}
unsigned sec_active = sec_mask_eff.count();
- unsigned sec_needed = (sec_active + set_width - 1) / set_width;
- if (sec_needed > available_sets) {
+ // Use the same feasibility test as inter coissue. Under
+ // compaction != 2 partitions are fixed by thread_id, so the
+ // coissuer's set positions can overlap the composite's even
+ // when (active/set_width) <= available_sets. merge_simd_sets
+ // silently drops overlapping coissuer sets while the access
+ // was already injected, leaving m_pending_writes_secondary
+ // unincremented but later decremented at writeback (underflow
+ // on sb0/sb2, deadlock on sb1).
+ unsigned sec_needed = 0;
+ if (!check_coissue_feasibility(co_issue_composite, sec_inst,
+ sec_mask_eff, cand_warp_id,
+ available_sets, &sec_needed)) {
m_stats->coissue_denied_by_no_sets[get_sid()]++;
continue;
}
@@ -2517,16 +2527,14 @@ void scheduler_unit::try_utilization_max_coissue(
it != pool.end() && available_sets > 0; it++) {
coissue_cand_t &c = *it;
// Re-check feasibility: prior picks may have filled sets that this
- // candidate overlaps (only matters for compaction_mode != 2).
+ // candidate overlaps (only matters for compaction_mode != 2). Both
+ // intra and inter must re-evaluate against the *current* composite
+ // — the cached c.sets_needed from admission can be stale once an
+ // earlier pool entry has merged its sets in.
unsigned needed = 0;
- if (c.is_intra) {
- if (c.sets_needed > available_sets) continue;
- needed = c.sets_needed;
- } else {
- if (!check_coissue_feasibility(co_issue_composite, c.inst, c.mask,
- c.warp_id, available_sets, &needed))
- continue;
- }
+ if (!check_coissue_feasibility(co_issue_composite, c.inst, c.mask,
+ c.warp_id, available_sets, &needed))
+ continue;
if (c.is_intra) {
if (m_shader->m_config->gpgpu_simd_partitioning_debug) {
@@ -2798,8 +2806,18 @@ void scheduler_unit::try_utilization_max_coissue_window(
continue;
}
unsigned sec_active = sec_mask_eff.count();
- unsigned sec_needed = (sec_active + set_width - 1) / set_width;
- if (sec_needed > available_sets) {
+ // Use the same feasibility test as inter coissue. Under
+ // compaction != 2 partitions are fixed by thread_id, so the
+ // coissuer's set positions can overlap the composite's even
+ // when (active/set_width) <= available_sets. merge_simd_sets
+ // silently drops overlapping coissuer sets while the access
+ // was already injected, leaving m_pending_writes_secondary
+ // unincremented but later decremented at writeback (underflow
+ // on sb0/sb2, deadlock on sb1).
+ unsigned sec_needed = 0;
+ if (!check_coissue_feasibility(co_issue_composite, sec_inst,
+ sec_mask_eff, cand_warp_id,
+ available_sets, &sec_needed)) {
m_stats->coissue_denied_by_no_sets[get_sid()]++;
continue;
}
@@ -3120,8 +3138,18 @@ void scheduler_unit::try_utilization_max_coissue_window_centered(
continue;
}
unsigned sec_active = sec_mask_eff.count();
- unsigned sec_needed = (sec_active + set_width - 1) / set_width;
- if (sec_needed > available_sets) {
+ // Use the same feasibility test as inter coissue. Under
+ // compaction != 2 partitions are fixed by thread_id, so the
+ // coissuer's set positions can overlap the composite's even
+ // when (active/set_width) <= available_sets. merge_simd_sets
+ // silently drops overlapping coissuer sets while the access
+ // was already injected, leaving m_pending_writes_secondary
+ // unincremented but later decremented at writeback (underflow
+ // on sb0/sb2, deadlock on sb1).
+ unsigned sec_needed = 0;
+ if (!check_coissue_feasibility(co_issue_composite, sec_inst,
+ sec_mask_eff, cand_warp_id,
+ available_sets, &sec_needed)) {
m_stats->coissue_denied_by_no_sets[get_sid()]++;
continue;
}
@@ -3435,8 +3463,18 @@ void scheduler_unit::try_utilization_max_coissue_window_before(
continue;
}
unsigned sec_active = sec_mask_eff.count();
- unsigned sec_needed = (sec_active + set_width - 1) / set_width;
- if (sec_needed > available_sets) {
+ // Use the same feasibility test as inter coissue. Under
+ // compaction != 2 partitions are fixed by thread_id, so the
+ // coissuer's set positions can overlap the composite's even
+ // when (active/set_width) <= available_sets. merge_simd_sets
+ // silently drops overlapping coissuer sets while the access
+ // was already injected, leaving m_pending_writes_secondary
+ // unincremented but later decremented at writeback (underflow
+ // on sb0/sb2, deadlock on sb1).
+ unsigned sec_needed = 0;
+ if (!check_coissue_feasibility(co_issue_composite, sec_inst,
+ sec_mask_eff, cand_warp_id,
+ available_sets, &sec_needed)) {
m_stats->coissue_denied_by_no_sets[get_sid()]++;
continue;
}