diff options
Diffstat (limited to 'src/gpgpu-sim/scoreboard.cc')
| -rw-r--r-- | src/gpgpu-sim/scoreboard.cc | 144 |
1 files changed, 138 insertions, 6 deletions
diff --git a/src/gpgpu-sim/scoreboard.cc b/src/gpgpu-sim/scoreboard.cc index 09bb5b7..4c270b9 100644 --- a/src/gpgpu-sim/scoreboard.cc +++ b/src/gpgpu-sim/scoreboard.cc @@ -44,6 +44,7 @@ Scoreboard::Scoreboard(unsigned sid, unsigned n_warps, class gpgpu_t* gpu, sec_reg_table.resize(n_warps); mask_reg_table.resize(n_warps); slot_reg_table.resize(n_warps); + m_xslot_shadow_mask_table.resize(n_warps); m_gpu = gpu; @@ -132,9 +133,12 @@ void Scoreboard::reserveRegisters(const class warp_inst_t* inst) { // Slot-pinned: insert into the inst's owning ibuffer half's table. unsigned slot = inst->get_ibuffer_half_id(); assert(slot < NUM_SLOTS); + const active_mask_t &shadow_mask = inst->get_active_mask(); for (unsigned r = 0; r < MAX_OUTPUT_VALUES; r++) { if (inst->out[r] > 0) { reserveRegisterSlot(inst->warp_id(), slot, inst->out[r]); + // Mask-aware shadow for diag (sb=1-equivalent ground truth). + reserveShadowMask(inst->warp_id(), inst->out[r], shadow_mask); } } } else { @@ -178,9 +182,12 @@ void Scoreboard::releaseRegisters(const class warp_inst_t* inst) { } else if (m_mode == 2) { unsigned slot = inst->get_ibuffer_half_id(); assert(slot < NUM_SLOTS); + const active_mask_t &shadow_mask = inst->get_active_mask(); for (unsigned r = 0; r < MAX_OUTPUT_VALUES; r++) { if (inst->out[r] > 0) { releaseRegisterSlot(inst->warp_id(), slot, inst->out[r]); + // Mask-aware shadow release. + releaseShadowMask(inst->warp_id(), inst->out[r], shadow_mask); longopregs[inst->warp_id()].erase(inst->out[r]); } } @@ -350,6 +357,8 @@ void Scoreboard::releaseSetReg(unsigned wid, unsigned reg, releaseRegisterMask(wid, reg, mask); } else if (m_mode == 2) { releaseRegisterSlot(wid, slot_id, reg); + // Mask-aware shadow release (per-set writeback path). + releaseShadowMask(wid, reg, mask); } else if (is_intra_legacy) { releaseRegisterSecondary(wid, reg); } else { @@ -364,17 +373,118 @@ void Scoreboard::releaseSetReg(unsigned wid, unsigned reg, void Scoreboard::reserveRegisterSlot(unsigned wid, unsigned slot, unsigned regnum) { assert(slot < NUM_SLOTS); - // Idempotent insert: same slot may try to reserve same reg if a - // back-to-back write to the same dest is co-issued by the same split - // through this slot. Mode 2 keeps it as a flat set (not ref-counted) - // for simplicity — relies on writeback's idempotent erase semantics. - slot_reg_table[wid][slot].insert(regnum); + // Ref-counted: each pending write to (slot, reg) increments. Two + // back-to-back writes to the same reg from the same slot must both + // be tracked — the prior set-based impl's idempotent insert lost the + // second write's pending state when the first retired (same-slot + // RAW miss). Each releaseRegisterSlot decrements; entry erased at 0. + slot_reg_table[wid][slot][regnum]++; } void Scoreboard::releaseRegisterSlot(unsigned wid, unsigned slot, unsigned regnum) { assert(slot < NUM_SLOTS); - slot_reg_table[wid][slot].erase(regnum); + auto it = slot_reg_table[wid][slot].find(regnum); + if (it == slot_reg_table[wid][slot].end()) return; // idempotent + if (it->second > 1) { + it->second--; + } else { + slot_reg_table[wid][slot].erase(it); + } +} + +// ===================================================================== +// Mode 2 mask-aware shadow table (diagnostic only — not used for any +// hazard-detection or stalling decision). Mirrors mask_reg_table's +// semantics so we can compare slot-pinned check vs sb=1 ground truth +// at issue eligibility sites. +// ===================================================================== +void Scoreboard::reserveShadowMask(unsigned wid, unsigned reg, + const active_mask_t &mask) { + if (m_mode != 2) return; + for (auto &e : m_xslot_shadow_mask_table[wid]) { + if (e.reg == reg && e.mask == mask) { + e.ref_count++; + return; + } + } + mask_resv e; + e.reg = reg; + e.mask = mask; + e.ref_count = 1; + e.resv_cycle = m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle; + m_xslot_shadow_mask_table[wid].push_back(e); +} + +void Scoreboard::releaseShadowMask(unsigned wid, unsigned reg, + const active_mask_t &mask) { + if (m_mode != 2) return; + for (auto it = m_xslot_shadow_mask_table[wid].begin(); + it != m_xslot_shadow_mask_table[wid].end(); ++it) { + if (it->reg == reg && it->mask == mask) { + assert(it->ref_count > 0); + it->ref_count--; + if (it->ref_count == 0) { + m_xslot_shadow_mask_table[wid].erase(it); + } + return; + } + } + // Idempotent no-op on no match — mirrors releaseRegisterMask. +} + +bool Scoreboard::checkCollisionShadow(unsigned wid, + const class inst_t *inst, + const active_mask_t &mask) const { + if (m_mode != 2) return false; + std::set<int> inst_regs; + for (unsigned i = 0; i < inst->outcount; i++) inst_regs.insert(inst->out[i]); + for (unsigned j = 0; j < inst->incount; j++) inst_regs.insert(inst->in[j]); + if (inst->pred > 0) inst_regs.insert(inst->pred); + if (inst->ar1 > 0) inst_regs.insert(inst->ar1); + if (inst->ar2 > 0) inst_regs.insert(inst->ar2); + for (auto reg : inst_regs) { + if (reg <= 0) continue; + for (const auto &e : m_xslot_shadow_mask_table[wid]) { + if (e.reg == (unsigned)reg && (e.mask & mask).any()) { + return true; + } + } + } + return false; +} + +void Scoreboard::dumpShadowOverlap(unsigned wid, const class inst_t *inst, + const active_mask_t &mask, FILE *out, + const char *site, + unsigned long long cyc) const { + if (m_mode != 2) return; + std::set<int> inst_regs; + for (unsigned i = 0; i < inst->outcount; i++) inst_regs.insert(inst->out[i]); + for (unsigned j = 0; j < inst->incount; j++) inst_regs.insert(inst->in[j]); + if (inst->pred > 0) inst_regs.insert(inst->pred); + if (inst->ar1 > 0) inst_regs.insert(inst->ar1); + if (inst->ar2 > 0) inst_regs.insert(inst->ar2); + for (auto reg : inst_regs) { + if (reg <= 0) continue; + for (const auto &e : m_xslot_shadow_mask_table[wid]) { + if (e.reg == (unsigned)reg && (e.mask & mask).any()) { + // Lookup which slot has the reg (or both / neither). + auto it0 = slot_reg_table[wid][0].find((unsigned)reg); + auto it1 = slot_reg_table[wid][1].find((unsigned)reg); + unsigned cnt0 = (it0 == slot_reg_table[wid][0].end()) ? 0u : it0->second; + unsigned cnt1 = (it1 == slot_reg_table[wid][1].end()) ? 0u : it1->second; + fprintf(out, + "[XSLOT_RAW] cyc=%llu site=%s sid=%u wid=%u reg=%d " + "issue_mask=%s entry_mask=%s entry_resv_cyc=%llu " + "issue_count=%lu entry_count=%lu intersection_count=%lu " + "slot0_cnt=%u slot1_cnt=%u\n", + cyc, site, m_sid, wid, reg, mask.to_string().c_str(), + e.mask.to_string().c_str(), e.resv_cycle, mask.count(), + e.mask.count(), (e.mask & mask).count(), cnt0, cnt1); + } + } + } } bool Scoreboard::checkCollisionSlot(unsigned wid, unsigned slot, @@ -459,6 +569,28 @@ void Scoreboard::dumpAccounting(FILE* out) const { m_sid, m_mask_reserve_inserts, m_mask_reserve_inc_refcount, m_mask_release_match, m_mask_release_nomatch, m_mask_release_erase, mask_remaining_entries, mask_remaining_refcount); + // Mode 2 (slot-pinned) cross-slot hazard diagnostics. + // _would_stall : unmasked slot=1 reg-name match (over-counts; lane-disjoint + // cross-slot writes count too). + // _real_would_stall : mask-aware shadow-table check (sb=1 ground truth); + // counts only true RAWs that sb=2 missed. + unsigned long long shadow_remaining = 0; + for (unsigned w = 0; w < m_xslot_shadow_mask_table.size(); w++) { + shadow_remaining += m_xslot_shadow_mask_table[w].size(); + } + fprintf(out, + "xslot_hazard_diag sid=%u primary_checks=%llu primary_would_stall=%llu " + "primary_real_would_stall=%llu " + "inter_checks=%llu inter_would_stall=%llu inter_real_would_stall=%llu " + "intra_checks=%llu intra_would_stall=%llu " + "shadow_remaining_entries=%llu\n", + m_sid, m_xslot_primary_issue_checks, + m_xslot_primary_issue_would_stall, + m_xslot_primary_issue_real_would_stall, + m_xslot_inter_coissue_checks, m_xslot_inter_coissue_would_stall, + m_xslot_inter_coissue_real_would_stall, + m_xslot_intra_coissue_checks, m_xslot_intra_coissue_would_stall, + shadow_remaining); // If anything is leaked, dump per-warp leak details. if (mask_remaining_entries > 0) { for (unsigned w = 0; w < mask_reg_table.size(); w++) { |
