summaryrefslogtreecommitdiff
path: root/src/abstract_hardware_model.cc
diff options
context:
space:
mode:
authorDavit Grigoryan <[email protected]>2026-05-01 10:29:50 +0000
committerDavit Grigoryan <[email protected]>2026-05-01 10:29:50 +0000
commit2e35f844aac74403fc3021682fab0231195a69d3 (patch)
tree4fa0e341a20565a20e53e29ef2c6496d931ace46 /src/abstract_hardware_model.cc
parent8ccb5a12c97bfbe04b783b779e518ac7cf08d91a (diff)
fix double sb from fifo rotations during intra coissue
Diffstat (limited to 'src/abstract_hardware_model.cc')
-rw-r--r--src/abstract_hardware_model.cc18
1 files changed, 18 insertions, 0 deletions
diff --git a/src/abstract_hardware_model.cc b/src/abstract_hardware_model.cc
index b164c73..970cc62 100644
--- a/src/abstract_hardware_model.cc
+++ b/src/abstract_hardware_model.cc
@@ -2792,6 +2792,12 @@ void simt_tables::update(simt_mask_t &thread_done, addr_vector_t &next_pc,
std::map<address_type, simt_mask_t> divergent_paths;
bool do_invalidate = false;
+ // Mode 2 (slot-pinned scoreboard) drain gate: set true if this update
+ // actually mutates FIFO membership (divergence, reconvergence, CALL,
+ // RET). Plain linear advance / branch-taken with no divergence does NOT
+ // set this. Co-issue's move_split_to_front does not go through update()
+ // at all, so it cannot set this.
+ bool fifo_membership_changed = false;
while (top_active_mask.any()) {
address_type tmp_next_pc = null_pc;
@@ -2860,12 +2866,14 @@ void simt_tables::update(simt_mask_t &thread_done, addr_vector_t &next_pc,
new_st_entry.m_branch_div_cycle = gpgpusim_total_cycles;
new_st_entry.m_type = SPLITS_TABLE_TYPE_CALL;
m_simt_splits_table->insert_new_entry(new_st_entry);
+ m_div_recv_drain_pending = true; // CALL changes FIFO membership
return;
} else if (next_inst_op == RET_OPS &&
top_type == SPLITS_TABLE_TYPE_CALL) {
assert(num_divergent_paths == 1);
top_recvg_entry = m_simt_splits_table->get_rpc_entry();
m_simt_splits_table->invalidate();
+ fifo_membership_changed = true; // RET changes FIFO membership
simt_mask_t active_mask =
m_simt_recvg_table->get_active_mask(new_recvg_entry);
@@ -2901,6 +2909,7 @@ void simt_tables::update(simt_mask_t &thread_done, addr_vector_t &next_pc,
m_simt_recvg_table->get_type(top_recvg_entry);
m_simt_splits_table->insert_new_entry(pc, rpc, rpc_entry, active_mask,
type, true);
+ fifo_membership_changed = true; // reconvergence inserts merged split
}
if (num_divergent_paths == 1) {
if (!do_invalidate) {
@@ -2936,6 +2945,7 @@ void simt_tables::update(simt_mask_t &thread_done, addr_vector_t &next_pc,
m_simt_recvg_table->get_type(new_recvg_entry);
m_simt_splits_table->insert_new_entry(pc, rpc, rpc_entry, active_mask,
type);
+ fifo_membership_changed = true; // reconvergence inserts merged split
}
continue;
}
@@ -2957,6 +2967,14 @@ void simt_tables::update(simt_mask_t &thread_done, addr_vector_t &next_pc,
if (do_invalidate) m_simt_splits_table->update_active_entry();
+ // Mode 2 drain gate: divergence (>1 paths) or any reconvergence/CALL/RET
+ // path observed above sets the flag so the next fetch into either ibuffer
+ // half for this warp waits for both slot scoreboards to drain. CALL_OPS
+ // already returned with the flag set; reach here only for normal paths.
+ if (warp_diverged || fifo_membership_changed) {
+ m_div_recv_drain_pending = true;
+ }
+
check_simt_tables();
m_shader->update_st_size(m_simt_splits_table->num_entries());