From 2e35f844aac74403fc3021682fab0231195a69d3 Mon Sep 17 00:00:00 2001 From: Davit Grigoryan Date: Fri, 1 May 2026 10:29:50 +0000 Subject: fix double sb from fifo rotations during intra coissue --- src/abstract_hardware_model.cc | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'src/abstract_hardware_model.cc') 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 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()); -- cgit v1.3