summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavit Grigoryan <[email protected]>2026-04-08 07:14:50 +0000
committerDavit Grigoryan <[email protected]>2026-04-08 07:14:50 +0000
commit6fe5349343b27a8919734fb4900dd2324cdf6c60 (patch)
treecdb60316dd273893375f876a367f9e17a7604f82
parent56550cce3389357bf0bb2c1fdc7d9a6edbc319ab (diff)
add simple simd lane set partitioning
-rw-r--r--src/abstract_hardware_model.cc30
-rw-r--r--src/abstract_hardware_model.h34
-rw-r--r--src/gpgpu-sim/gpu-sim.cc8
-rw-r--r--src/gpgpu-sim/shader.cc34
-rw-r--r--src/gpgpu-sim/shader.h18
5 files changed, 122 insertions, 2 deletions
diff --git a/src/abstract_hardware_model.cc b/src/abstract_hardware_model.cc
index dde9d28..316b02b 100644
--- a/src/abstract_hardware_model.cc
+++ b/src/abstract_hardware_model.cc
@@ -66,6 +66,36 @@ void warp_inst_t::issue(const active_mask_t &mask, unsigned warp_id,
m_scheduler_id = sch_id;
}
+void warp_inst_t::compute_simd_sets(unsigned num_sets, unsigned set_width) {
+ m_simd_sets.resize(num_sets);
+ for (unsigned s = 0; s < num_sets; s++) {
+ simd_set_info &info = m_simd_sets[s];
+ info.set_id = s;
+ info.warp_id = m_warp_id;
+ info.set_active_mask.reset();
+ info.active_mask_in_warp.reset();
+ info.num_active_threads = 0;
+ for (unsigned lane = 0; lane < set_width; lane++) {
+ unsigned tid = s * set_width + lane;
+ info.thread_ids[lane] = tid;
+ if (m_warp_active_mask.test(tid)) {
+ info.set_active_mask.set(lane);
+ info.active_mask_in_warp.set(tid);
+ info.num_active_threads++;
+ }
+ }
+ info.valid = (info.num_active_threads > 0);
+ }
+}
+
+unsigned warp_inst_t::num_active_simd_sets() const {
+ unsigned count = 0;
+ for (unsigned i = 0; i < m_simd_sets.size(); i++) {
+ if (m_simd_sets[i].valid) count++;
+ }
+ return count;
+}
+
checkpoint::checkpoint() {
struct stat st = {0};
diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h
index e96ddc4..948e226 100644
--- a/src/abstract_hardware_model.h
+++ b/src/abstract_hardware_model.h
@@ -1109,6 +1109,24 @@ enum divergence_support_t {
const unsigned MAX_ACCESSES_PER_INSN_PER_THREAD = 8;
+// SIMD lane partitioning: per-set execution data
+struct simd_set_info {
+ unsigned set_id; // Set index (0 to num_sets-1)
+ unsigned warp_id; // Owning warp
+ simt_mask_t set_active_mask; // Active lanes within this set (lower set_width bits)
+ active_mask_t active_mask_in_warp; // Active mask in original 32-bit warp thread domain
+ unsigned thread_ids[MAX_WARP_SIZE]; // Original thread IDs for each lane (max set_width used)
+ unsigned num_active_threads; // popcount of set_active_mask
+ bool valid; // Whether this set has any active threads
+
+ simd_set_info()
+ : set_id(0), warp_id(0), num_active_threads(0), valid(false) {
+ set_active_mask.reset();
+ active_mask_in_warp.reset();
+ for (unsigned i = 0; i < MAX_WARP_SIZE; i++) thread_ids[i] = 0;
+ }
+};
+
class warp_inst_t : public inst_t {
public:
// constructors
@@ -1152,12 +1170,23 @@ class warp_inst_t : public inst_t {
void broadcast_barrier_reduction(const active_mask_t &access_mask);
void do_atomic(bool forceDo = false);
void do_atomic(const active_mask_t &access_mask, bool forceDo = false);
- void clear() { m_empty = true; }
+ void clear() {
+ m_empty = true;
+ m_simd_sets.clear();
+ }
void issue(const active_mask_t &mask, unsigned warp_id,
unsigned long long cycle, int dynamic_warp_id, int sch_id,
unsigned long long streamID);
+ // SIMD lane partitioning
+ void compute_simd_sets(unsigned num_sets, unsigned set_width);
+ const std::vector<simd_set_info> &get_simd_sets() const {
+ return m_simd_sets;
+ }
+ unsigned num_active_simd_sets() const;
+ bool has_simd_sets() const { return !m_simd_sets.empty(); }
+
const active_mask_t &get_active_mask() const { return m_warp_active_mask; }
void completed(unsigned long long cycle)
const; // stat collection: called when the instruction is completed
@@ -1333,6 +1362,9 @@ class warp_inst_t : public inst_t {
unsigned m_scheduler_id; // the scheduler that issues this inst
+ // SIMD lane partitioning data
+ std::vector<simd_set_info> m_simd_sets;
+
// Jin: cdp support
public:
int m_is_cdp;
diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc
index 1f7de38..17c7247 100644
--- a/src/gpgpu-sim/gpu-sim.cc
+++ b/src/gpgpu-sim/gpu-sim.cc
@@ -674,6 +674,14 @@ void shader_core_config::reg_options(class OptionParser *opp) {
&reg_file_port_throughput,
"the number ports of the register file", "1");
+ // SIMD lane partitioning options
+ option_parser_register(
+ opp, "-gpgpu_simd_partitioning", OPT_BOOL, &gpgpu_simd_partitioning,
+ "Enable SIMD lane partitioning into sets (default = disabled)", "0");
+ option_parser_register(
+ opp, "-gpgpu_num_simd_sets", OPT_UINT32, &gpgpu_num_simd_sets,
+ "Number of SIMD sets to partition lanes into (default = 1)", "1");
+
for (unsigned j = 0; j < SPECIALIZED_UNIT_NUM; ++j) {
std::stringstream ss;
ss << "-specialized_unit_" << j + 1;
diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc
index bcf38d3..9f92215 100644
--- a/src/gpgpu-sim/shader.cc
+++ b/src/gpgpu-sim/shader.cc
@@ -1052,8 +1052,35 @@ void shader_core_ctx::fetch() {
m_L1I->cycle();
}
+void exec_shader_core_ctx::execute_warp_inst_per_set(warp_inst_t &inst) {
+ // Execute each SIMD set's threads independently
+ const std::vector<simd_set_info> &sets = inst.get_simd_sets();
+ unsigned warp_id = inst.warp_id();
+ unsigned set_width = m_config->simd_set_width;
+
+ for (unsigned s = 0; s < sets.size(); s++) {
+ const simd_set_info &set = sets[s];
+ if (!set.valid) continue;
+
+ // Execute each active thread in this set
+ for (unsigned lane = 0; lane < set_width; lane++) {
+ if (set.set_active_mask.test(lane)) {
+ unsigned t = set.thread_ids[lane]; // original thread position (0-31)
+ unsigned hw_tid = m_warp_size * warp_id + t;
+ assert(inst.active(t)); // thread must be active in original mask
+ m_thread[hw_tid]->ptx_exec_inst(inst, t);
+ checkExecutionStatusAndUpdate(inst, t, hw_tid);
+ }
+ }
+ }
+}
+
void exec_shader_core_ctx::func_exec_inst(warp_inst_t &inst) {
- execute_warp_inst_t(inst);
+ if (m_config->gpgpu_simd_partitioning && inst.has_simd_sets()) {
+ execute_warp_inst_per_set(inst);
+ } else {
+ execute_warp_inst_t(inst);
+ }
if (inst.is_load() || inst.is_store()) {
inst.generate_mem_accesses();
// inst.print_m_accessq();
@@ -1076,6 +1103,11 @@ void shader_core_ctx::issue_warp(register_set &pipe_reg_set,
m_warp[warp_id]->get_dynamic_warp_id(), sch_id,
m_warp[warp_id]->get_streamID()); // dynamic instruction information
m_stats->shader_cycle_distro[2 + (*pipe_reg)->active_count()]++;
+ // Compute SIMD set assignments before functional execution
+ if (m_config->gpgpu_simd_partitioning) {
+ (*pipe_reg)->compute_simd_sets(m_config->gpgpu_num_simd_sets,
+ m_config->simd_set_width);
+ }
func_exec_inst(**pipe_reg);
// Add LDGSTS instructions into a buffer
diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h
index bb2ac33..01dd92c 100644
--- a/src/gpgpu-sim/shader.h
+++ b/src/gpgpu-sim/shader.h
@@ -1572,6 +1572,18 @@ class shader_core_config : public core_config {
max_warps_per_shader = n_thread_per_shader / warp_size;
assert(!(n_thread_per_shader % warp_size));
+ // Validate and compute SIMD partitioning derived values
+ if (gpgpu_simd_partitioning) {
+ assert(gpgpu_num_simd_sets > 0 && gpgpu_num_simd_sets <= warp_size);
+ assert(warp_size % gpgpu_num_simd_sets == 0);
+ simd_set_width = warp_size / gpgpu_num_simd_sets;
+ printf("SIMD Partitioning: %u sets of %u lanes\n", gpgpu_num_simd_sets,
+ simd_set_width);
+ } else {
+ gpgpu_num_simd_sets = 1;
+ simd_set_width = warp_size;
+ }
+
set_pipeline_latency();
m_L1I_config.init(m_L1I_config.m_config_string, FuncCachePreferNone);
@@ -1714,6 +1726,11 @@ class shader_core_config : public core_config {
unsigned max_dp_latency;
unsigned max_tensor_core_latency;
+ // SIMD lane partitioning
+ bool gpgpu_simd_partitioning;
+ unsigned gpgpu_num_simd_sets;
+ unsigned simd_set_width; // derived: warp_size / num_simd_sets
+
unsigned n_simt_cores_per_cluster;
unsigned n_simt_clusters;
unsigned n_simt_ejection_buffer_size;
@@ -2630,6 +2647,7 @@ class exec_shader_core_ctx : public shader_core_ctx {
virtual void checkExecutionStatusAndUpdate(warp_inst_t &inst, unsigned t,
unsigned tid);
virtual void func_exec_inst(warp_inst_t &inst);
+ void execute_warp_inst_per_set(warp_inst_t &inst);
virtual unsigned sim_init_thread(kernel_info_t &kernel,
ptx_thread_info **thread_info, int sid,
unsigned tid, unsigned threads_left,