summaryrefslogtreecommitdiff
path: root/src/gpgpu-sim
diff options
context:
space:
mode:
authorDavit Grigoryan <[email protected]>2026-04-11 08:43:27 +0000
committerDavit Grigoryan <[email protected]>2026-04-11 08:43:27 +0000
commit29d90a95ffa4287f58dc30a2e3488edf13d6c143 (patch)
tree2c1b97112991b34a2e3d304f804cbcae723ae914 /src/gpgpu-sim
parent8b3b5bbf710302ad3a835626477dc1bf2d317952 (diff)
make operand collector mimd-aware
Diffstat (limited to 'src/gpgpu-sim')
-rw-r--r--src/gpgpu-sim/shader.cc104
-rw-r--r--src/gpgpu-sim/shader.h40
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<unsigned> 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<simd_set_info> &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<int> 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<int> 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<simd_set_info> &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<int> 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 {