summaryrefslogtreecommitdiff
path: root/src/gpgpu-sim/shader.cc
diff options
context:
space:
mode:
authorDavit Grigoryan <[email protected]>2026-04-28 22:06:08 +0000
committerDavit Grigoryan <[email protected]>2026-04-28 22:06:08 +0000
commitfbb90ef3a76cd6c469782c84668d25c5f3bfdd22 (patch)
tree08d320b6da8f5c6c5e276c94ba19a8d5d5bc9216 /src/gpgpu-sim/shader.cc
parent3d4d274eb3a6a23a5924b557d010590e219c5256 (diff)
critical fix - add option to have masks for SB entries
Diffstat (limited to 'src/gpgpu-sim/shader.cc')
-rw-r--r--src/gpgpu-sim/shader.cc277
1 files changed, 206 insertions, 71 deletions
diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc
index a2a77a7..ec764aa 100644
--- a/src/gpgpu-sim/shader.cc
+++ b/src/gpgpu-sim/shader.cc
@@ -191,7 +191,8 @@ void shader_core_ctx::create_front_pipeline() {
}
void shader_core_ctx::create_schedulers() {
- m_scoreboard = new Scoreboard(m_sid, m_config->max_warps_per_shader, m_gpu);
+ m_scoreboard = new Scoreboard(m_sid, m_config->max_warps_per_shader, m_gpu,
+ m_config->gpgpu_scoreboard_mode);
// scedulers
// must currently occur after all inputs have been initialized.
@@ -1528,21 +1529,31 @@ void shader_core_ctx::co_issue_warp(warp_inst_t *composite,
}
// Reserve scoreboard for the co-issued warp.
- // For intra-warp co-issue (same warp_id), skip reservation — the primary
- // instruction already reserved for this warp, and the scoreboard tracks at
- // warp granularity. Both splits may write to the same register number
- // (which is safe since they operate on exclusive threads), but the
- // scoreboard would abort on a duplicate reservation.
- if (split_id == (unsigned)-1) {
- // Inter-warp co-issue: different warp_id, always safe to reserve
+ if (m_config->gpgpu_scoreboard_mode == 1) {
+ // Mode 1 (mask-aware): both inter-warp and intra-warp use the unified
+ // mask-aware scoreboard. The active_mask carried in temp_inst already
+ // differentiates the two splits' reservations — disjoint-lane writes
+ // get distinct (reg, mask) entries even when they share warp_id.
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]);
+ // Mode 0 (legacy):
+ // For intra-warp co-issue (same warp_id), skip primary reservation —
+ // the primary instruction already reserved for this warp, and the
+ // scoreboard tracks at warp granularity. Both splits may write to the
+ // same register number (which is safe since they operate on exclusive
+ // threads), but the scoreboard would abort on a duplicate reservation.
+ 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]);
+ }
}
}
}
@@ -1555,6 +1566,10 @@ void shader_core_ctx::co_issue_warp(warp_inst_t *composite,
// between primary and secondary-split sets that share warp_id).
temp_inst.set_source_inst_on_sets(next_inst);
temp_inst.set_split_id_on_sets(split_id);
+ // Mode 1: stamp the source's full issue mask so per-set writeback can
+ // release the matching mask-aware reservation. Cheap and harmless in
+ // mode 0 (field is unused there).
+ temp_inst.set_source_mask_on_sets(active_mask);
// Mixed-space MEM co-issue (v2): for SHARED coissuers, capture per-lane
// memreqaddr + temp_inst.cycles into each valid set BEFORE merge. The
@@ -1948,7 +1963,20 @@ void scheduler_unit::try_inter_warp_coissue(
}
// Scoreboard check.
- if (m_scoreboard->checkCollision(cand_warp_id, cand_inst)) {
+ // Mode 1 needs the candidate's active mask for hazard intersection;
+ // hoist its lookup before the legacy/mode-1 dispatch.
+ bool sb_collision_inter;
+ if (m_shader->m_config->gpgpu_scoreboard_mode == 1) {
+ const active_mask_t &cand_mask_pre =
+ m_shader->get_active_mask(cand_warp_id, cand_inst);
+ sb_collision_inter = m_scoreboard->checkCollisionMask(cand_warp_id,
+ cand_inst,
+ cand_mask_pre);
+ } else {
+ sb_collision_inter = m_scoreboard->checkCollision(cand_warp_id,
+ cand_inst);
+ }
+ if (sb_collision_inter) {
m_stats->coissue_denied_by_scoreboard[get_sid()]++;
continue;
}
@@ -2091,21 +2119,30 @@ void scheduler_unit::try_intra_warp_coissue(
}
}
- if (m_scoreboard->checkCollisionSecondary(primary_warp_id, sec_inst)) {
- m_stats->coissue_denied_by_scoreboard[get_sid()]++;
- continue;
- }
-
// Stale-mask guard: see commentary on the same fix in
// try_utilization_max_coissue. Cached `sec_mask` may diverge from
// current `split_mask` (lane re-bucketing or split-ID reuse). Dispatch
// only the intersection — lanes in BOTH masks are guaranteed to have
- // their per-thread PC at sec_inst->pc.
+ // their per-thread PC at sec_inst->pc. Hoisted before the scoreboard
+ // check so mode 1 can use the effective mask for hazard detection.
active_mask_t sec_mask_eff;
for (unsigned t = 0; t < MAX_WARP_SIZE; t++) {
if (sec_mask.test(t) && split_mask.test(t)) sec_mask_eff.set(t);
}
if (!sec_mask_eff.any()) continue;
+
+ bool sb_collision;
+ if (m_shader->m_config->gpgpu_scoreboard_mode == 1) {
+ sb_collision = m_scoreboard->checkCollisionMask(primary_warp_id,
+ sec_inst, sec_mask_eff);
+ } else {
+ sb_collision = m_scoreboard->checkCollisionSecondary(primary_warp_id,
+ sec_inst);
+ }
+ if (sb_collision) {
+ m_stats->coissue_denied_by_scoreboard[get_sid()]++;
+ continue;
+ }
unsigned sec_active = sec_mask_eff.count();
unsigned sec_sets_needed = (sec_active + set_width - 1) / set_width;
if (sec_sets_needed > available_sets) {
@@ -2190,7 +2227,18 @@ void scheduler_unit::try_utilization_max_coissue(
&cand_rpc);
if (cand_pc != cand_inst->pc) continue;
- if (m_scoreboard->checkCollision(cand_warp_id, cand_inst)) {
+ bool sb_collision_inter2;
+ if (m_shader->m_config->gpgpu_scoreboard_mode == 1) {
+ const active_mask_t &cand_mask_pre =
+ m_shader->get_active_mask(cand_warp_id, cand_inst);
+ sb_collision_inter2 = m_scoreboard->checkCollisionMask(cand_warp_id,
+ cand_inst,
+ cand_mask_pre);
+ } else {
+ sb_collision_inter2 = m_scoreboard->checkCollision(cand_warp_id,
+ cand_inst);
+ }
+ if (sb_collision_inter2) {
m_stats->coissue_denied_by_scoreboard[get_sid()]++;
continue;
}
@@ -2326,11 +2374,6 @@ void scheduler_unit::try_utilization_max_coissue(
continue;
}
}
- if (m_scoreboard->checkCollisionSecondary(cand_warp_id, sec_inst)) {
- m_stats->coissue_denied_by_scoreboard[get_sid()]++;
- continue;
- }
-
// Stale-mask guard: the cached `sec_mask` is from secondary-fetch
// time and may not match the current splits-table mask. Two
// failure modes:
@@ -2344,12 +2387,27 @@ void scheduler_unit::try_utilization_max_coissue(
// cached mask is stale.
// Both reduce to: trust only lanes present in BOTH masks. The
// ibuffer slot ownership invariant guarantees lanes in `split_mask`
- // are at `split_pc == sec_inst->pc`.
+ // are at `split_pc == sec_inst->pc`. Hoisted before the scoreboard
+ // check so mode 1 can use the effective mask for hazard detection.
active_mask_t sec_mask_eff;
for (unsigned t = 0; t < MAX_WARP_SIZE; t++) {
if (sec_mask.test(t) && split_mask.test(t)) sec_mask_eff.set(t);
}
if (!sec_mask_eff.any()) continue;
+
+ bool sb_collision;
+ if (m_shader->m_config->gpgpu_scoreboard_mode == 1) {
+ sb_collision = m_scoreboard->checkCollisionMask(cand_warp_id,
+ sec_inst,
+ sec_mask_eff);
+ } else {
+ sb_collision = m_scoreboard->checkCollisionSecondary(cand_warp_id,
+ sec_inst);
+ }
+ if (sb_collision) {
+ m_stats->coissue_denied_by_scoreboard[get_sid()]++;
+ continue;
+ }
unsigned sec_active = sec_mask_eff.count();
unsigned sec_needed = (sec_active + set_width - 1) / set_width;
if (sec_needed > available_sets) {
@@ -2548,15 +2606,23 @@ void scheduler_unit::cycle() {
m_scoreboard->clearSecondary(warp_id);
} else {
valid_inst = true;
- if (!m_scoreboard->checkCollision(warp_id, pI)) {
+ // Mode 1 needs the warp's active mask for hazard intersection;
+ // hoist it before the scoreboard check.
+ const active_mask_t &active_mask =
+ m_shader->get_active_mask(warp_id, pI);
+ bool sb_collision_primary;
+ if (m_shader->m_config->gpgpu_scoreboard_mode == 1) {
+ sb_collision_primary =
+ m_scoreboard->checkCollisionMask(warp_id, pI, active_mask);
+ } else {
+ sb_collision_primary = m_scoreboard->checkCollision(warp_id, pI);
+ }
+ if (!sb_collision_primary) {
SCHED_DPRINTF(
"Warp (warp_id %u, dynamic_warp_id %u) passes scoreboard\n",
(*iter)->get_warp_id(), (*iter)->get_dynamic_warp_id());
ready_inst = true;
- const active_mask_t &active_mask =
- m_shader->get_active_mask(warp_id, pI);
-
assert(warp(warp_id).inst_in_pipeline());
if ((pI->op == LOAD_OP) || (pI->op == STORE_OP) ||
@@ -3330,14 +3396,19 @@ void shader_core_ctx::writeback() {
}
// Release scoreboard for primary instruction (covers the outer warp_id)
m_scoreboard->releaseRegisters(pipe_reg);
- // Release scoreboard for ALL co-issued sets (inter-warp AND intra-warp)
+ // Release scoreboard for ALL co-issued sets (inter-warp AND intra-warp).
+ // Dispatcher: mode 0 -> primary release; mode 1 -> mask-aware release
+ // using the set's stamped source_mask. Idempotent; safe to call once
+ // per set even when multiple sets share the same source_inst.
for (unsigned s = 0; s < sets.size(); s++) {
if (!sets[s].valid || sets[s].source_inst == NULL) continue;
unsigned set_wid = sets[s].warp_id;
for (unsigned r = 0; r < MAX_OUTPUT_VALUES; r++) {
if (sets[s].source_inst->out[r] > 0) {
- m_scoreboard->releaseRegister(set_wid,
- sets[s].source_inst->out[r]);
+ m_scoreboard->releaseSetReg(set_wid,
+ sets[s].source_inst->out[r],
+ sets[s].source_mask,
+ /*is_intra_legacy=*/false);
}
}
}
@@ -3359,12 +3430,14 @@ void shader_core_ctx::writeback() {
co_issued_warps_decremented.insert(sets[s].warp_id);
}
} else {
- // Intra-warp: release from secondary scoreboard and dec once
+ // Intra-warp: release from secondary scoreboard (mode 0) or
+ // mask-aware (mode 1) 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_scoreboard->releaseSetReg(
+ sets[s].warp_id, sets[s].source_inst->out[r],
+ sets[s].source_mask, /*is_intra_legacy=*/true);
}
}
m_warp[warp_id]->dec_inst_in_pipeline();
@@ -3532,6 +3605,11 @@ mem_stage_stall_type ldst_unit::process_cache_access(
[src.out_inst->out[r]]--;
else
m_pending_writes[src.wid][src.out_inst->out[r]]--;
+ // Mode 1: per-mask decrement + release when the inst's own
+ // accesses fully drain (independent of other in-flight insts'
+ // contributions to the aggregate counter).
+ dec_mask_pw_and_maybe_release(src.wid, src.out_inst->out[r],
+ src.source_mask);
}
// release LDGSTS (primary-only: LDGSTS is excluded from MEM co-issue)
@@ -3695,7 +3773,8 @@ void ldst_unit::L1_latency_queue_cycle() {
if (!still_pending) {
m_pending_writes_secondary[src.wid][src_split_mf].erase(
reg);
- m_scoreboard->releaseRegisterSecondary(src.wid, reg);
+ m_scoreboard->releaseSetReg(src.wid, reg, src.source_mask,
+ /*is_intra_legacy=*/true);
any_completed = true;
}
} else {
@@ -3703,10 +3782,14 @@ void ldst_unit::L1_latency_queue_cycle() {
unsigned still_pending = --m_pending_writes[src.wid][reg];
if (!still_pending) {
m_pending_writes[src.wid].erase(reg);
- m_scoreboard->releaseRegister(src.wid, reg);
+ m_scoreboard->releaseSetReg(src.wid, reg, src.source_mask,
+ /*is_intra_legacy=*/false);
any_completed = true;
}
}
+ // Mode 1: per-mask release fires per inst, decoupled from
+ // the aggregate counter above.
+ dec_mask_pw_and_maybe_release(src.wid, reg, src.source_mask);
}
}
if (any_completed) m_core->warp_inst_complete(mf_next->get_inst());
@@ -4259,17 +4342,41 @@ ldst_unit::ldst_unit(mem_fetch_interface *icnt,
mem_config, stats, sid, tpc);
}
+void ldst_unit::dec_mask_pw_and_maybe_release(unsigned wid, unsigned reg,
+ const active_mask_t &mask) {
+ if (m_core->get_config()->gpgpu_scoreboard_mode != 1) return;
+ unsigned long mk = mask.to_ulong();
+ auto wit = m_pending_writes_mask.find(wid);
+ if (wit == m_pending_writes_mask.end()) return;
+ auto rit = wit->second.find(reg);
+ if (rit == wit->second.end()) return;
+ auto mit = rit->second.find(mk);
+ if (mit == rit->second.end()) return;
+ assert(mit->second > 0);
+ if (--(mit->second) == 0) {
+ rit->second.erase(mit);
+ if (rit->second.empty()) {
+ wit->second.erase(rit);
+ if (wit->second.empty()) m_pending_writes_mask.erase(wit);
+ }
+ m_scoreboard->releaseRegisterMask(wid, reg, mask);
+ }
+}
+
ldst_unit::mem_src_t ldst_unit::resolve_source(
const warp_inst_t &inst, unsigned access_src_wid,
unsigned access_src_split_id) const {
mem_src_t r;
r.wid = (access_src_wid == (unsigned)-1) ? inst.warp_id() : access_src_wid;
r.out_inst = &inst;
+ r.source_mask.reset();
// Primary access: (wid == primary AND split_id == -1). Return early with
// out_inst = composite (primary's out[]). Note: split_id is the
// discriminator — a coissuer can have the same warp_id as primary when
// it came from the primary warp's own secondary ibuffer slot.
if (r.wid == inst.warp_id() && access_src_split_id == (unsigned)-1) {
+ // Primary's own mask is on the composite itself.
+ r.source_mask = inst.get_active_mask();
return r;
}
if (!inst.has_simd_sets()) return r;
@@ -4280,6 +4387,7 @@ ldst_unit::mem_src_t ldst_unit::resolve_source(
if (sets[s].warp_id == r.wid &&
sets[s].split_id == access_src_split_id) {
r.out_inst = sets[s].source_inst;
+ r.source_mask = sets[s].source_mask;
break;
}
}
@@ -4487,9 +4595,19 @@ void ldst_unit::issue(register_set &reg_set) {
unsigned n_primary =
n_acc_per_src[std::make_pair(primary_wid, (unsigned)-1)];
if (n_primary > 0) {
+ const bool mode1 =
+ (m_core->get_config()->gpgpu_scoreboard_mode == 1);
+ unsigned long pri_mask_key =
+ mode1 ? inst->get_active_mask().to_ulong() : 0;
for (unsigned r = 0; r < MAX_OUTPUT_VALUES; r++) {
unsigned reg_id = inst->out[r];
- if (reg_id > 0) m_pending_writes[primary_wid][reg_id] += n_primary;
+ if (reg_id > 0) {
+ m_pending_writes[primary_wid][reg_id] += n_primary;
+ if (mode1) {
+ m_pending_writes_mask[primary_wid][reg_id][pri_mask_key] +=
+ n_primary;
+ }
+ }
}
}
}
@@ -4513,6 +4631,10 @@ void ldst_unit::issue(register_set &reg_set) {
// is_intra = "uses secondary scoreboard map" = split came from a
// secondary ibuffer slot. Not tied to warp_id == primary_wid.
bool is_intra = (sets[s].split_id != (unsigned)-1);
+ const bool mode1 =
+ (m_core->get_config()->gpgpu_scoreboard_mode == 1);
+ unsigned long set_mask_key =
+ mode1 ? sets[s].source_mask.to_ulong() : 0;
for (unsigned r = 0; r < MAX_OUTPUT_VALUES; r++) {
unsigned reg_id = sets[s].source_inst->out[r];
if (reg_id > 0) {
@@ -4522,15 +4644,29 @@ void ldst_unit::issue(register_set &reg_set) {
} else {
m_pending_writes[sets[s].warp_id][reg_id] += n_src;
}
+ if (mode1) {
+ m_pending_writes_mask[sets[s].warp_id][reg_id][set_mask_key] +=
+ n_src;
+ }
}
}
}
} else if (primary_is_tracked_load) {
// Legacy (non-co-issue) path: single-warp pending_writes.
unsigned n_accesses = inst->accessq_count();
+ const bool mode1 =
+ (m_core->get_config()->gpgpu_scoreboard_mode == 1);
+ unsigned long pri_mask_key =
+ mode1 ? inst->get_active_mask().to_ulong() : 0;
for (unsigned r = 0; r < MAX_OUTPUT_VALUES; r++) {
unsigned reg_id = inst->out[r];
- if (reg_id > 0) m_pending_writes[primary_wid][reg_id] += n_accesses;
+ if (reg_id > 0) {
+ m_pending_writes[primary_wid][reg_id] += n_accesses;
+ if (mode1) {
+ m_pending_writes_mask[primary_wid][reg_id][pri_mask_key] +=
+ n_accesses;
+ }
+ }
}
}
@@ -4631,7 +4767,9 @@ void ldst_unit::writeback() {
if (!still_pending) {
m_pending_writes_secondary[src_i.wid][src_split_i]
.erase(reg);
- m_scoreboard->releaseRegisterSecondary(src_i.wid, reg);
+ m_scoreboard->releaseSetReg(src_i.wid, reg,
+ src_i.source_mask,
+ /*is_intra_legacy=*/true);
insn_completed = true;
}
} else {
@@ -4640,10 +4778,14 @@ void ldst_unit::writeback() {
--m_pending_writes[src_i.wid][reg];
if (!still_pending) {
m_pending_writes[src_i.wid].erase(reg);
- m_scoreboard->releaseRegister(src_i.wid, reg);
+ m_scoreboard->releaseSetReg(src_i.wid, reg,
+ src_i.source_mask,
+ /*is_intra_legacy=*/false);
insn_completed = true;
}
}
+ // Mode 1: per-mask release fires per inst.
+ dec_mask_pw_and_maybe_release(src_i.wid, reg, src_i.source_mask);
} else if (m_next_wb.m_is_ldgsts) {
// LDGSTS excluded from co-issue; source_list always size<=1
m_pending_ldgsts[primary_wid][m_next_wb.pc]
@@ -4663,7 +4805,9 @@ void ldst_unit::writeback() {
(void)is_intra_coissued; // unused on shared path
for (unsigned r = 0; r < MAX_OUTPUT_VALUES; r++) {
if (src.out_inst->out[r] > 0) {
- m_scoreboard->releaseRegister(src.wid, src.out_inst->out[r]);
+ m_scoreboard->releaseSetReg(src.wid, src.out_inst->out[r],
+ src.source_mask,
+ /*is_intra_legacy=*/false);
insn_completed = true;
}
}
@@ -4682,16 +4826,13 @@ void ldst_unit::writeback() {
sets[s].split_id);
if (released.count(key)) continue;
released.insert(key);
- // Secondary slot coissuer → secondary scoreboard map.
+ // Secondary slot coissuer → secondary scoreboard map (mode 0).
bool coissued_intra = (sets[s].split_id != (unsigned)-1);
for (unsigned r = 0; r < MAX_OUTPUT_VALUES; r++) {
if (sets[s].source_inst->out[r] > 0) {
- if (coissued_intra)
- m_scoreboard->releaseRegisterSecondary(
- sets[s].warp_id, sets[s].source_inst->out[r]);
- else
- m_scoreboard->releaseRegister(
- sets[s].warp_id, sets[s].source_inst->out[r]);
+ m_scoreboard->releaseSetReg(
+ sets[s].warp_id, sets[s].source_inst->out[r],
+ sets[s].source_mask, /*is_intra_legacy=*/coissued_intra);
insn_completed = true;
}
}
@@ -5013,10 +5154,9 @@ void ldst_unit::cycle() {
for (unsigned r = 0; r < MAX_OUTPUT_VALUES; r++) {
unsigned reg = sets[s].source_inst->out[r];
if (reg == 0) continue;
- if (is_intra)
- m_scoreboard->releaseRegisterSecondary(sets[s].warp_id, reg);
- else
- m_scoreboard->releaseRegister(sets[s].warp_id, reg);
+ m_scoreboard->releaseSetReg(sets[s].warp_id, reg,
+ sets[s].source_mask,
+ /*is_intra_legacy=*/is_intra);
}
}
pipe_reg.set_shared_side_released(true);
@@ -5188,10 +5328,9 @@ void ldst_unit::cycle() {
for (unsigned r = 0; r < MAX_OUTPUT_VALUES; r++) {
unsigned reg_id = sets[s].source_inst->out[r];
if (reg_id == 0) continue;
- if (is_intra)
- m_scoreboard->releaseRegisterSecondary(sets[s].warp_id, reg_id);
- else
- m_scoreboard->releaseRegister(sets[s].warp_id, reg_id);
+ m_scoreboard->releaseSetReg(sets[s].warp_id, reg_id,
+ sets[s].source_mask,
+ /*is_intra_legacy=*/is_intra);
}
}
}
@@ -5331,16 +5470,14 @@ void ldst_unit::cycle() {
sets[s].split_id);
if (released.count(key)) continue;
released.insert(key);
- // Secondary slot → secondary scoreboard map.
+ // Secondary slot → secondary scoreboard map (mode 0).
bool is_intra = (sets[s].split_id != (unsigned)-1);
for (unsigned r = 0; r < MAX_OUTPUT_VALUES; r++) {
unsigned reg_id = sets[s].source_inst->out[r];
if (reg_id == 0) continue;
- if (is_intra)
- m_scoreboard->releaseRegisterSecondary(sets[s].warp_id,
- reg_id);
- else
- m_scoreboard->releaseRegister(sets[s].warp_id, reg_id);
+ m_scoreboard->releaseSetReg(sets[s].warp_id, reg_id,
+ sets[s].source_mask,
+ /*is_intra_legacy=*/is_intra);
}
}
}
@@ -5423,11 +5560,9 @@ void ldst_unit::cycle() {
for (unsigned r = 0; r < MAX_OUTPUT_VALUES; r++) {
unsigned reg_id = sets[s].source_inst->out[r];
if (reg_id == 0) continue;
- if (is_intra)
- m_scoreboard->releaseRegisterSecondary(sets[s].warp_id,
- reg_id);
- else
- m_scoreboard->releaseRegister(sets[s].warp_id, reg_id);
+ m_scoreboard->releaseSetReg(sets[s].warp_id, reg_id,
+ sets[s].source_mask,
+ /*is_intra_legacy=*/is_intra);
}
}
}