From 29d90a95ffa4287f58dc30a2e3488edf13d6c143 Mon Sep 17 00:00:00 2001 From: Davit Grigoryan Date: Sat, 11 Apr 2026 08:43:27 +0000 Subject: make operand collector mimd-aware --- src/gpgpu-sim/shader.cc | 104 +++++++++++++++++++++++++++++++++++++++--------- src/gpgpu-sim/shader.h | 40 ++++++++++++++++++- 2 files changed, 123 insertions(+), 21 deletions(-) diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index 0897107..ea2d9b3 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -4680,24 +4680,53 @@ unsigned register_bank(int regnum, int wid, unsigned num_banks, bool opndcoll_rfu_t::writeback(warp_inst_t &inst) { assert(!inst.empty()); + unsigned sched_id = inst.get_schd_id(); + + // Phase 1: Primary warp's destination registers std::list regs = m_shader->get_regs_written(inst); for (unsigned op = 0; op < MAX_REG_OPERANDS; op++) { - int reg_num = inst.arch_reg.dst[op]; // this math needs to match that used - // in function_info::ptx_decode_inst - if (reg_num >= 0) { // valid register + int reg_num = inst.arch_reg.dst[op]; + if (reg_num >= 0) { unsigned bank = register_bank(reg_num, inst.warp_id(), m_num_banks, sub_core_model, - m_num_banks_per_sched, inst.get_schd_id()); + m_num_banks_per_sched, sched_id); if (m_arbiter.bank_idle(bank)) { m_arbiter.allocate_bank_for_write( bank, op_t(&inst, reg_num, m_num_banks, sub_core_model, - m_num_banks_per_sched, inst.get_schd_id())); + m_num_banks_per_sched, sched_id)); inst.arch_reg.dst[op] = -1; } else { return false; } } } + + // Phase 2: Co-issued sets' destination registers (different instructions) + if (inst.has_simd_sets()) { + const std::vector &sets = inst.get_simd_sets(); + for (unsigned s = 0; s < sets.size(); s++) { + if (!sets[s].valid) continue; + if (sets[s].warp_id == inst.warp_id()) continue; + if (sets[s].source_inst == NULL) continue; + + for (unsigned op = 0; op < MAX_REG_OPERANDS; op++) { + int reg_num = sets[s].source_inst->arch_reg.dst[op]; + if (reg_num >= 0) { + unsigned bank = register_bank(reg_num, sets[s].warp_id, m_num_banks, + sub_core_model, m_num_banks_per_sched, + sched_id); + if (m_arbiter.bank_idle(bank)) { + m_arbiter.allocate_bank_for_write( + bank, op_t(sets[s].warp_id, reg_num, m_num_banks, + sub_core_model, m_num_banks_per_sched, sched_id)); + } else { + return false; + } + } + } + } + } + for (unsigned i = 0; i < (unsigned)regs.size(); i++) { if (m_shader->get_config()->gpgpu_clock_gated_reg_file) { unsigned active_count = 0; @@ -4714,7 +4743,7 @@ bool opndcoll_rfu_t::writeback(warp_inst_t &inst) { m_shader->incregfile_writes(active_count); } else { m_shader->incregfile_writes( - m_shader->get_config()->warp_size); // inst.active_count()); + m_shader->get_config()->warp_size); } } return true; @@ -4875,26 +4904,63 @@ bool opndcoll_rfu_t::collector_unit_t::allocate(register_set *pipeline_reg_set, warp_inst_t **pipeline_reg = pipeline_reg_set->get_ready(); if ((pipeline_reg) and !((*pipeline_reg)->empty())) { m_warp_id = (*pipeline_reg)->warp_id(); - std::vector prev_regs; // remove duplicate regs within same instr + m_has_simd_sets = (*pipeline_reg)->has_simd_sets(); + unsigned sched_id = (*pipeline_reg)->get_schd_id(); + unsigned op_idx = 0; + + // Phase 1: Primary warp's source registers + std::vector prev_regs; for (unsigned op = 0; op < MAX_REG_OPERANDS; op++) { - int reg_num = - (*pipeline_reg) - ->arch_reg.src[op]; // this math needs to match that used in - // function_info::ptx_decode_inst + int reg_num = (*pipeline_reg)->arch_reg.src[op]; bool new_reg = true; for (auto r : prev_regs) { if (r == reg_num) new_reg = false; } - if (reg_num >= 0 && new_reg) { // valid register + if (reg_num >= 0 && new_reg) { prev_regs.push_back(reg_num); - m_src_op[op] = - op_t(this, op, reg_num, m_num_banks, m_sub_core_model, - m_num_banks_per_sched, (*pipeline_reg)->get_schd_id()); - m_not_ready.set(op); - } else - m_src_op[op] = op_t(); + m_src_op[op_idx] = + op_t(this, op_idx, reg_num, m_num_banks, m_sub_core_model, + m_num_banks_per_sched, sched_id); + m_not_ready.set(op_idx); + } else { + m_src_op[op_idx] = op_t(); + } + op_idx++; } - // move_warp(m_warp,*pipeline_reg); + + // Phase 2: Co-issued sets' source registers (different instructions) + if (m_has_simd_sets) { + const std::vector &sets = + (*pipeline_reg)->get_simd_sets(); + for (unsigned s = 0; s < sets.size(); s++) { + if (!sets[s].valid) continue; + if (sets[s].warp_id == m_warp_id) continue; + if (sets[s].source_inst == NULL) continue; + + std::vector set_prev_regs; + for (unsigned op = 0; op < MAX_REG_OPERANDS && op_idx < MAX_REG_OPERANDS * 2; op++) { + int reg_num = sets[s].source_inst->arch_reg.src[op]; + bool new_reg = true; + for (auto r : set_prev_regs) { + if (r == reg_num) new_reg = false; + } + if (reg_num >= 0 && new_reg) { + set_prev_regs.push_back(reg_num); + m_src_op[op_idx] = + op_t(this, op_idx, reg_num, m_num_banks, m_sub_core_model, + m_num_banks_per_sched, sched_id, sets[s].warp_id); + m_not_ready.set(op_idx); + op_idx++; + } + } + } + } + + // Clear remaining slots + for (; op_idx < MAX_REG_OPERANDS * 2; op_idx++) { + m_src_op[op_idx] = op_t(); + } + pipeline_reg_set->move_out_to(m_warp); return true; } diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index c25f185..c01abf1 100644 --- a/src/gpgpu-sim/shader.h +++ b/src/gpgpu-sim/shader.h @@ -693,7 +693,7 @@ class opndcoll_rfu_t { // operand collector based register file unit class op_t { public: - op_t() { m_valid = false; } + op_t() { m_valid = false; m_set_warp_id = (unsigned)-1; } op_t(collector_unit_t *cu, unsigned op, unsigned reg, unsigned num_banks, bool sub_core_model, unsigned banks_per_sched, unsigned sched_id) { m_valid = true; @@ -702,9 +702,24 @@ class opndcoll_rfu_t { // operand collector based register file unit m_operand = op; m_register = reg; m_shced_id = sched_id; + m_set_warp_id = (unsigned)-1; m_bank = register_bank(reg, cu->get_warp_id(), num_banks, sub_core_model, banks_per_sched, sched_id); } + // Per-set variant: uses explicit warp_id for bank computation + op_t(collector_unit_t *cu, unsigned op, unsigned reg, unsigned num_banks, + bool sub_core_model, unsigned banks_per_sched, unsigned sched_id, + unsigned set_warp_id) { + m_valid = true; + m_warp = NULL; + m_cu = cu; + m_operand = op; + m_register = reg; + m_shced_id = sched_id; + m_set_warp_id = set_warp_id; + m_bank = register_bank(reg, set_warp_id, num_banks, sub_core_model, + banks_per_sched, sched_id); + } op_t(const warp_inst_t *warp, unsigned reg, unsigned num_banks, bool sub_core_model, unsigned banks_per_sched, unsigned sched_id) { m_valid = true; @@ -713,9 +728,23 @@ class opndcoll_rfu_t { // operand collector based register file unit m_cu = NULL; m_operand = -1; m_shced_id = sched_id; + m_set_warp_id = (unsigned)-1; m_bank = register_bank(reg, warp->warp_id(), num_banks, sub_core_model, banks_per_sched, sched_id); } + // Explicit warp_id variant for writeback of co-issued sets + op_t(unsigned explicit_warp_id, unsigned reg, unsigned num_banks, + bool sub_core_model, unsigned banks_per_sched, unsigned sched_id) { + m_valid = true; + m_warp = NULL; + m_cu = NULL; + m_operand = (unsigned)-1; + m_register = reg; + m_shced_id = sched_id; + m_set_warp_id = explicit_warp_id; + m_bank = register_bank(reg, explicit_warp_id, num_banks, sub_core_model, + banks_per_sched, sched_id); + } // accessors bool valid() const { return m_valid; } @@ -724,7 +753,9 @@ class opndcoll_rfu_t { // operand collector based register file unit return m_register; } unsigned get_wid() const { - if (m_warp) + if (m_set_warp_id != (unsigned)-1) + return m_set_warp_id; + else if (m_warp) return m_warp->warp_id(); else if (m_cu) return m_cu->get_warp_id(); @@ -784,6 +815,7 @@ class opndcoll_rfu_t { // operand collector based register file unit unsigned m_register; unsigned m_bank; unsigned m_shced_id; // scheduler id that has issued this inst + unsigned m_set_warp_id; // per-set warp_id override for SIMD partitioning }; enum alloc_t { @@ -946,6 +978,7 @@ class opndcoll_rfu_t { // operand collector based register file unit m_not_ready.reset(); m_warp_id = -1; m_num_banks = 0; + m_has_simd_sets = false; } // accessors bool ready() const; @@ -988,6 +1021,9 @@ class opndcoll_rfu_t { // operand collector based register file unit unsigned m_num_banks_per_sched; bool m_sub_core_model; unsigned m_reg_id; // if sub_core_model enabled, limit regs this cu can r/w + + // SIMD lane partitioning: tracks whether this CU holds a composite + bool m_has_simd_sets; }; class dispatch_unit_t { -- cgit v1.3