diff options
| author | Mahmoud <[email protected]> | 2020-05-30 22:17:04 -0400 |
|---|---|---|
| committer | Mahmoud <[email protected]> | 2020-05-30 22:17:04 -0400 |
| commit | 3f051d4e5e24943575ac4c19c358e1a0e6de621c (patch) | |
| tree | 45148f663962117f006b1da67e0ffeb743714a16 /src/gpgpu-sim/shader.cc | |
| parent | 6b72554af7018a8dc42e607f6983a070fe5e5a42 (diff) | |
adding new specialization units
Diffstat (limited to 'src/gpgpu-sim/shader.cc')
| -rw-r--r-- | src/gpgpu-sim/shader.cc | 114 |
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)); |
