summaryrefslogtreecommitdiff
path: root/src/gpgpu-sim/shader.cc
diff options
context:
space:
mode:
authorMahmoud <[email protected]>2020-05-30 22:17:04 -0400
committerMahmoud <[email protected]>2020-05-30 22:17:04 -0400
commit3f051d4e5e24943575ac4c19c358e1a0e6de621c (patch)
tree45148f663962117f006b1da67e0ffeb743714a16 /src/gpgpu-sim/shader.cc
parent6b72554af7018a8dc42e607f6983a070fe5e5a42 (diff)
adding new specialization units
Diffstat (limited to 'src/gpgpu-sim/shader.cc')
-rw-r--r--src/gpgpu-sim/shader.cc114
1 files changed, 102 insertions, 12 deletions
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));