summaryrefslogtreecommitdiff
path: root/src/gpgpu-sim
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpgpu-sim')
-rw-r--r--src/gpgpu-sim/gpu-sim.cc11
-rw-r--r--src/gpgpu-sim/shader.cc114
-rw-r--r--src/gpgpu-sim/shader.h79
3 files changed, 185 insertions, 19 deletions
diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc
index b62524e..03aebf3 100644
--- a/src/gpgpu-sim/gpu-sim.cc
+++ b/src/gpgpu-sim/gpu-sim.cc
@@ -529,6 +529,17 @@ void shader_core_config::reg_options(class OptionParser *opp) {
option_parser_register(opp, "-gpgpu_reg_file_port_throughput", OPT_INT32,
&reg_file_port_throughput,
"the number ports of the register file", "1");
+
+ for (unsigned j = 0; j < SPECIALIZED_UNIT_NUM; ++j) {
+ std::stringstream ss;
+ ss << "-specialized_unit_" << j + 1;
+ option_parser_register(opp, ss.str().c_str(), OPT_CSTR,
+ &specialized_unit_string[j],
+ "specialized unit config"
+ " {<enabled>,<num_units>:<latency>:<initiation>,<ID_"
+ "OC_SPEC>:<OC_EX_SPEC>,<NAME>}",
+ "0,4,4,4,4,BRA");
+ }
}
void gpgpu_sim_config::reg_options(option_parser_t opp) {
diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc
index 8efb88b..8b226b6 100644
--- a/src/gpgpu-sim/shader.cc
+++ b/src/gpgpu-sim/shader.cc
@@ -82,11 +82,30 @@ void exec_shader_core_ctx::create_shd_warp() {
}
void shader_core_ctx::create_front_pipeline() {
- m_pipeline_reg.reserve(N_PIPELINE_STAGES);
+ // pipeline_stages is the sum of normal pipeline stages and specialized_unit
+ // stages * 2 (for ID and EX)
+ unsigned total_pipeline_stages =
+ N_PIPELINE_STAGES + m_config->m_specialized_unit.size() * 2;
+ m_pipeline_reg.reserve(total_pipeline_stages);
for (int j = 0; j < N_PIPELINE_STAGES; j++) {
m_pipeline_reg.push_back(
register_set(m_config->pipe_widths[j], pipeline_stage_name_decode[j]));
}
+ for (int j = 0; j < m_config->m_specialized_unit.size(); j++) {
+ m_pipeline_reg.push_back(
+ register_set(m_config->m_specialized_unit[j].id_oc_spec_reg_width,
+ m_config->m_specialized_unit[j].name));
+ m_config->m_specialized_unit[j].ID_OC_SPEC_ID = m_pipeline_reg.size() - 1;
+ m_specilized_dispatch_reg.push_back(
+ &m_pipeline_reg[m_pipeline_reg.size() - 1]);
+ }
+ for (int j = 0; j < m_config->m_specialized_unit.size(); j++) {
+ m_pipeline_reg.push_back(
+ register_set(m_config->m_specialized_unit[j].oc_ex_spec_reg_width,
+ m_config->m_specialized_unit[j].name));
+ m_config->m_specialized_unit[j].OC_EX_SPEC_ID = m_pipeline_reg.size() - 1;
+ }
+
if (m_config->sub_core_model) {
// in subcore model, each scheduler should has its own issue register, so
// num scheduler = reg width
@@ -168,37 +187,40 @@ void shader_core_ctx::create_schedulers() {
m_stats, this, m_scoreboard, m_simt_stack, &m_warp,
&m_pipeline_reg[ID_OC_SP], &m_pipeline_reg[ID_OC_DP],
&m_pipeline_reg[ID_OC_SFU], &m_pipeline_reg[ID_OC_INT],
- &m_pipeline_reg[ID_OC_TENSOR_CORE], &m_pipeline_reg[ID_OC_MEM], i));
+ &m_pipeline_reg[ID_OC_TENSOR_CORE], m_specilized_dispatch_reg,
+ &m_pipeline_reg[ID_OC_MEM], i));
break;
case CONCRETE_SCHEDULER_TWO_LEVEL_ACTIVE:
schedulers.push_back(new two_level_active_scheduler(
m_stats, this, m_scoreboard, m_simt_stack, &m_warp,
&m_pipeline_reg[ID_OC_SP], &m_pipeline_reg[ID_OC_DP],
&m_pipeline_reg[ID_OC_SFU], &m_pipeline_reg[ID_OC_INT],
- &m_pipeline_reg[ID_OC_TENSOR_CORE], &m_pipeline_reg[ID_OC_MEM], i,
- m_config->gpgpu_scheduler_string));
+ &m_pipeline_reg[ID_OC_TENSOR_CORE], m_specilized_dispatch_reg,
+ &m_pipeline_reg[ID_OC_MEM], i, m_config->gpgpu_scheduler_string));
break;
case CONCRETE_SCHEDULER_GTO:
schedulers.push_back(new gto_scheduler(
m_stats, this, m_scoreboard, m_simt_stack, &m_warp,
&m_pipeline_reg[ID_OC_SP], &m_pipeline_reg[ID_OC_DP],
&m_pipeline_reg[ID_OC_SFU], &m_pipeline_reg[ID_OC_INT],
- &m_pipeline_reg[ID_OC_TENSOR_CORE], &m_pipeline_reg[ID_OC_MEM], i));
+ &m_pipeline_reg[ID_OC_TENSOR_CORE], m_specilized_dispatch_reg,
+ &m_pipeline_reg[ID_OC_MEM], i));
break;
case CONCRETE_SCHEDULER_OLDEST_FIRST:
schedulers.push_back(new oldest_scheduler(
m_stats, this, m_scoreboard, m_simt_stack, &m_warp,
&m_pipeline_reg[ID_OC_SP], &m_pipeline_reg[ID_OC_DP],
&m_pipeline_reg[ID_OC_SFU], &m_pipeline_reg[ID_OC_INT],
- &m_pipeline_reg[ID_OC_TENSOR_CORE], &m_pipeline_reg[ID_OC_MEM], i));
+ &m_pipeline_reg[ID_OC_TENSOR_CORE], m_specilized_dispatch_reg,
+ &m_pipeline_reg[ID_OC_MEM], i));
break;
case CONCRETE_SCHEDULER_WARP_LIMITING:
schedulers.push_back(new swl_scheduler(
m_stats, this, m_scoreboard, m_simt_stack, &m_warp,
&m_pipeline_reg[ID_OC_SP], &m_pipeline_reg[ID_OC_DP],
&m_pipeline_reg[ID_OC_SFU], &m_pipeline_reg[ID_OC_INT],
- &m_pipeline_reg[ID_OC_TENSOR_CORE], &m_pipeline_reg[ID_OC_MEM], i,
- m_config->gpgpu_scheduler_string));
+ &m_pipeline_reg[ID_OC_TENSOR_CORE], m_specilized_dispatch_reg,
+ &m_pipeline_reg[ID_OC_MEM], i, m_config->gpgpu_scheduler_string));
break;
default:
abort();
@@ -248,6 +270,14 @@ void shader_core_ctx::create_exec_pipeline() {
in_ports.push_back(&m_pipeline_reg[ID_OC_INT]);
out_ports.push_back(&m_pipeline_reg[OC_EX_INT]);
}
+ if (m_config->m_specialized_unit.size() > 0) {
+ for (unsigned j = 0; j < m_config->m_specialized_unit.size(); ++j) {
+ in_ports.push_back(
+ &m_pipeline_reg[m_config->m_specialized_unit[j].ID_OC_SPEC_ID]);
+ out_ports.push_back(
+ &m_pipeline_reg[m_config->m_specialized_unit[j].OC_EX_SPEC_ID]);
+ }
+ }
cu_sets.push_back((unsigned)GEN_CUS);
m_operand_collector.add_port(in_ports, out_ports, cu_sets);
in_ports.clear(), out_ports.clear(), cu_sets.clear();
@@ -340,7 +370,7 @@ void shader_core_ctx::create_exec_pipeline() {
m_num_function_units =
m_config->gpgpu_num_sp_units + m_config->gpgpu_num_dp_units +
m_config->gpgpu_num_sfu_units + m_config->gpgpu_num_tensor_core_units +
- m_config->gpgpu_num_int_units +
+ m_config->gpgpu_num_int_units + m_config->m_specialized_unit_num +
1; // sp_unit, sfu, dp, tensor, int, ldst_unit
// m_dispatch_port = new enum pipeline_stage_name_t[ m_num_function_units ];
// m_issue_port = new enum pipeline_stage_name_t[ m_num_function_units ];
@@ -376,6 +406,17 @@ void shader_core_ctx::create_exec_pipeline() {
m_issue_port.push_back(OC_EX_TENSOR_CORE);
}
+ for (int j = 0; j < m_config->m_specialized_unit.size(); j++) {
+ for (unsigned k = 0; k < m_config->m_specialized_unit[j].num_units; k++) {
+ m_fu.push_back(new specialized_unit(
+ &m_pipeline_reg[EX_WB], m_config, this, SPEC_UNIT_START_ID + j,
+ m_config->m_specialized_unit[j].name,
+ m_config->m_specialized_unit[j].latency));
+ m_dispatch_port.push_back(m_config->m_specialized_unit[j].ID_OC_SPEC_ID);
+ m_issue_port.push_back(m_config->m_specialized_unit[j].OC_EX_SPEC_ID);
+ }
+ }
+
m_ldst_unit = new ldst_unit(m_icnt, m_mem_fetch_allocator, this,
&m_operand_collector, m_scoreboard, m_config,
m_memory_config, m_stats, m_sid, m_tpc);
@@ -1204,7 +1245,7 @@ void scheduler_unit::cycle() {
// This code need to be refactored
if (pI->op != TENSOR_CORE_OP && pI->op != SFU_OP &&
- pI->op != DP_OP) {
+ pI->op != DP_OP && !(pI->op >= SPEC_UNIT_START_ID)) {
bool execute_on_SP = false;
bool execute_on_INT = false;
@@ -1302,7 +1343,30 @@ void scheduler_unit::cycle() {
warp_inst_issued = true;
previous_issued_inst_exec_type = exec_unit_type_t::TENSOR;
}
+ } else if ((pI->op >= SPEC_UNIT_START_ID) &&
+ !(diff_exec_units &&
+ previous_issued_inst_exec_type ==
+ exec_unit_type_t::SPECIALIZED)) {
+ unsigned spec_id = pI->op - SPEC_UNIT_START_ID;
+ assert(spec_id < m_shader->m_config->m_specialized_unit.size());
+ register_set *spec_reg_set = m_spec_cores_out[spec_id];
+ bool spec_pipe_avail =
+ (m_shader->m_config->m_specialized_unit[spec_id].num_units >
+ 0) &&
+ spec_reg_set->has_free(m_shader->m_config->sub_core_model,
+ m_id);
+
+ if (spec_pipe_avail) {
+ m_shader->issue_warp(*spec_reg_set, pI, active_mask, warp_id,
+ m_id);
+ issued++;
+ issued_inst = true;
+ warp_inst_issued = true;
+ previous_issued_inst_exec_type =
+ exec_unit_type_t::SPECIALIZED;
+ }
}
+
} // end of else
} else {
SCHED_DPRINTF(
@@ -1475,9 +1539,11 @@ swl_scheduler::swl_scheduler(shader_core_stats *stats, shader_core_ctx *shader,
register_set *sp_out, register_set *dp_out,
register_set *sfu_out, register_set *int_out,
register_set *tensor_core_out,
+ std::vector<register_set *> &spec_cores_out,
register_set *mem_out, int id, char *config_string)
: scheduler_unit(stats, shader, scoreboard, simt, warp, sp_out, dp_out,
- sfu_out, int_out, tensor_core_out, mem_out, id) {
+ sfu_out, int_out, tensor_core_out, spec_cores_out, mem_out,
+ id) {
unsigned m_prioritization_readin;
int ret = sscanf(config_string, "warp_limiting:%d:%d",
&m_prioritization_readin, &m_num_warps_to_limit);
@@ -1599,7 +1665,7 @@ void shader_core_ctx::execute() {
unsigned multiplier = m_fu[n]->clock_multiplier();
for (unsigned c = 0; c < multiplier; c++) m_fu[n]->cycle();
m_fu[n]->active_lanes_in_pipeline();
- enum pipeline_stage_name_t issue_port = m_issue_port[n];
+ unsigned issue_port = m_issue_port[n];
register_set &issue_inst = m_pipeline_reg[issue_port];
warp_inst_t **ready_reg = issue_inst.get_ready();
if (issue_inst.has_ready() && m_fu[n]->can_issue(**ready_reg)) {
@@ -2108,6 +2174,13 @@ void dp_unit::active_lanes_in_pipeline() {
m_core->incfuactivelanes_stat(active_count);
m_core->incfumemactivelanes_stat(active_count);
}
+void specialized_unit::active_lanes_in_pipeline() {
+ unsigned active_count = pipelined_simd_unit::get_active_lanes_in_pipeline();
+ assert(active_count <= m_core->get_config()->warp_size);
+ m_core->incspactivelanes_stat(active_count);
+ m_core->incfuactivelanes_stat(active_count);
+ m_core->incfumemactivelanes_stat(active_count);
+}
void int_unit::active_lanes_in_pipeline() {
unsigned active_count = pipelined_simd_unit::get_active_lanes_in_pipeline();
@@ -2138,6 +2211,15 @@ sp_unit::sp_unit(register_set *result_port, const shader_core_config *config,
m_name = "SP ";
}
+specialized_unit::specialized_unit(register_set *result_port,
+ const shader_core_config *config,
+ shader_core_ctx *core, unsigned supported_op,
+ char *unit_name, unsigned latency)
+ : pipelined_simd_unit(result_port, config, latency, core) {
+ m_name = unit_name;
+ m_supported_op = supported_op;
+}
+
dp_unit::dp_unit(register_set *result_port, const shader_core_config *config,
shader_core_ctx *core)
: pipelined_simd_unit(result_port, config, config->max_dp_latency, core) {
@@ -2166,6 +2248,14 @@ void dp_unit ::issue(register_set &source_reg) {
pipelined_simd_unit::issue(source_reg);
}
+void specialized_unit ::issue(register_set &source_reg) {
+ warp_inst_t **ready_reg = source_reg.get_ready();
+ // m_core->incexecstat((*ready_reg));
+ (*ready_reg)->op_pipe = SPECIALIZED__OP;
+ m_core->incsp_stat(m_core->get_config()->warp_size, (*ready_reg)->latency);
+ pipelined_simd_unit::issue(source_reg);
+}
+
void int_unit ::issue(register_set &source_reg) {
warp_inst_t **ready_reg = source_reg.get_ready();
// m_core->incexecstat((*ready_reg));
diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h
index d77207d..65c8937 100644
--- a/src/gpgpu-sim/shader.h
+++ b/src/gpgpu-sim/shader.h
@@ -79,7 +79,8 @@ enum exec_unit_type_t {
MEM = 3,
DP = 4,
INT = 5,
- TENSOR = 6
+ TENSOR = 6,
+ SPECIALIZED = 7
};
class thread_ctx_t {
@@ -329,6 +330,7 @@ class scheduler_unit { // this can be copied freely, so can be used in std
std::vector<shd_warp_t *> *warp, register_set *sp_out,
register_set *dp_out, register_set *sfu_out,
register_set *int_out, register_set *tensor_core_out,
+ std::vector<register_set *> &spec_cores_out,
register_set *mem_out, int id)
: m_supervised_warps(),
m_stats(stats),
@@ -341,6 +343,7 @@ class scheduler_unit { // this can be copied freely, so can be used in std
m_sfu_out(sfu_out),
m_int_out(int_out),
m_tensor_core_out(tensor_core_out),
+ m_spec_cores_out(spec_cores_out),
m_mem_out(mem_out),
m_id(id) {}
virtual ~scheduler_unit() {}
@@ -422,6 +425,7 @@ class scheduler_unit { // this can be copied freely, so can be used in std
register_set *m_int_out;
register_set *m_tensor_core_out;
register_set *m_mem_out;
+ std::vector<register_set *> &m_spec_cores_out;
int m_id;
};
@@ -433,9 +437,11 @@ class lrr_scheduler : public scheduler_unit {
std::vector<shd_warp_t *> *warp, register_set *sp_out,
register_set *dp_out, register_set *sfu_out,
register_set *int_out, register_set *tensor_core_out,
+ std::vector<register_set *> &spec_cores_out,
register_set *mem_out, int id)
: scheduler_unit(stats, shader, scoreboard, simt, warp, sp_out, dp_out,
- sfu_out, int_out, tensor_core_out, mem_out, id) {}
+ sfu_out, int_out, tensor_core_out, spec_cores_out,
+ mem_out, id) {}
virtual ~lrr_scheduler() {}
virtual void order_warps();
virtual void done_adding_supervised_warps() {
@@ -450,9 +456,11 @@ class gto_scheduler : public scheduler_unit {
std::vector<shd_warp_t *> *warp, register_set *sp_out,
register_set *dp_out, register_set *sfu_out,
register_set *int_out, register_set *tensor_core_out,
+ std::vector<register_set *> &spec_cores_out,
register_set *mem_out, int id)
: scheduler_unit(stats, shader, scoreboard, simt, warp, sp_out, dp_out,
- sfu_out, int_out, tensor_core_out, mem_out, id) {}
+ sfu_out, int_out, tensor_core_out, spec_cores_out,
+ mem_out, id) {}
virtual ~gto_scheduler() {}
virtual void order_warps();
virtual void done_adding_supervised_warps() {
@@ -467,9 +475,11 @@ class oldest_scheduler : public scheduler_unit {
std::vector<shd_warp_t *> *warp, register_set *sp_out,
register_set *dp_out, register_set *sfu_out,
register_set *int_out, register_set *tensor_core_out,
+ std::vector<register_set *> &spec_cores_out,
register_set *mem_out, int id)
: scheduler_unit(stats, shader, scoreboard, simt, warp, sp_out, dp_out,
- sfu_out, int_out, tensor_core_out, mem_out, id) {}
+ sfu_out, int_out, tensor_core_out, spec_cores_out,
+ mem_out, id) {}
virtual ~oldest_scheduler() {}
virtual void order_warps();
virtual void done_adding_supervised_warps() {
@@ -485,9 +495,11 @@ class two_level_active_scheduler : public scheduler_unit {
register_set *sp_out, register_set *dp_out,
register_set *sfu_out, register_set *int_out,
register_set *tensor_core_out,
+ std::vector<register_set *> &spec_cores_out,
register_set *mem_out, int id, char *config_str)
: scheduler_unit(stats, shader, scoreboard, simt, warp, sp_out, dp_out,
- sfu_out, int_out, tensor_core_out, mem_out, id),
+ sfu_out, int_out, tensor_core_out, spec_cores_out,
+ mem_out, id),
m_pending_warps() {
unsigned inner_level_readin;
unsigned outer_level_readin;
@@ -533,6 +545,7 @@ class swl_scheduler : public scheduler_unit {
std::vector<shd_warp_t *> *warp, register_set *sp_out,
register_set *dp_out, register_set *sfu_out,
register_set *int_out, register_set *tensor_core_out,
+ std::vector<register_set *> &spec_cores_out,
register_set *mem_out, int id, char *config_string);
virtual ~swl_scheduler() {}
virtual void order_warps();
@@ -1211,6 +1224,24 @@ class sp_unit : public pipelined_simd_unit {
virtual void issue(register_set &source_reg);
};
+class specialized_unit : public pipelined_simd_unit {
+ public:
+ specialized_unit(register_set *result_port, const shader_core_config *config,
+ shader_core_ctx *core, unsigned supported_op,
+ char *unit_name, unsigned latency);
+ virtual bool can_issue(const warp_inst_t &inst) const {
+ if (inst.op != m_supported_op) {
+ return false;
+ }
+ return pipelined_simd_unit::can_issue(inst);
+ }
+ virtual void active_lanes_in_pipeline();
+ virtual void issue(register_set &source_reg);
+
+ private:
+ unsigned m_supported_op;
+};
+
class simt_core_cluster;
class shader_memory_interface;
class shader_core_mem_fetch_allocator;
@@ -1361,6 +1392,16 @@ const char *const pipeline_stage_name_decode[] = {
"OC_EX_SFU", "OC_EX_MEM", "EX_WB", "ID_OC_TENSOR_CORE",
"OC_EX_TENSOR_CORE", "N_PIPELINE_STAGES"};
+struct specialized_unit_params {
+ unsigned latency;
+ unsigned num_units;
+ unsigned id_oc_spec_reg_width;
+ unsigned oc_ex_spec_reg_width;
+ char name[20];
+ unsigned ID_OC_SPEC_ID;
+ unsigned OC_EX_SPEC_ID;
+};
+
class shader_core_config : public core_config {
public:
shader_core_config(gpgpu_context *ctx) : core_config(ctx) {
@@ -1419,6 +1460,24 @@ class shader_core_config : public core_config {
gpgpu_cache_texl1_linesize = m_L1T_config.get_line_sz();
gpgpu_cache_constl1_linesize = m_L1C_config.get_line_sz();
m_valid = true;
+
+ m_specialized_unit_num = 0;
+ // parse the specialized units
+ for (unsigned i = 0; i < SPECIALIZED_UNIT_NUM; ++i) {
+ unsigned enabled;
+ specialized_unit_params sparam;
+ sscanf(specialized_unit_string[i], "%u,%u,%u,%u,%u,%s", &enabled,
+ &sparam.num_units, &sparam.latency, &sparam.id_oc_spec_reg_width,
+ &sparam.oc_ex_spec_reg_width, &sparam.name);
+
+ if (enabled) {
+ m_specialized_unit.push_back(sparam);
+ strncpy(m_specialized_unit.back().name, sparam.name,
+ sizeof(m_specialized_unit.back().name));
+ m_specialized_unit_num += sparam.num_units;
+ } else
+ break; // we only accept continuous specialized_units, i.e., 1,2,3,4
+ }
}
void reg_options(class OptionParser *opp);
unsigned max_cta(const kernel_info_t &k) const;
@@ -1534,6 +1593,11 @@ class shader_core_config : public core_config {
bool perfect_inst_const_cache;
unsigned inst_fetch_throughput;
unsigned reg_file_port_throughput;
+
+ // specialized unit config strings
+ char *specialized_unit_string[SPECIALIZED_UNIT_NUM];
+ mutable std::vector<specialized_unit_params> m_specialized_unit;
+ unsigned m_specialized_unit_num;
};
struct shader_core_stats_pod {
@@ -2154,6 +2218,7 @@ class shader_core_ctx : public core_t {
Scoreboard *m_scoreboard;
opndcoll_rfu_t m_operand_collector;
int m_active_warps;
+ std::vector<register_set *> m_specilized_dispatch_reg;
// schedule
std::vector<scheduler_unit *> schedulers;
@@ -2163,8 +2228,8 @@ class shader_core_ctx : public core_t {
// execute
unsigned m_num_function_units;
- std::vector<pipeline_stage_name_t> m_dispatch_port;
- std::vector<pipeline_stage_name_t> m_issue_port;
+ std::vector<unsigned> m_dispatch_port;
+ std::vector<unsigned> m_issue_port;
std::vector<simd_function_unit *>
m_fu; // stallable pipelines should be last in this array
ldst_unit *m_ldst_unit;