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 | |
| parent | 6b72554af7018a8dc42e607f6983a070fe5e5a42 (diff) | |
adding new specialization units
| -rw-r--r-- | configs/tested-cfgs/SM75_RTX2060/trace.config | 20 | ||||
| -rw-r--r-- | configs/tested-cfgs/SM7_QV100/trace.config | 13 | ||||
| -rw-r--r-- | configs/tested-cfgs/SM7_TITANV/trace.config | 13 | ||||
| -rw-r--r-- | src/abstract_hardware_model.h | 15 | ||||
| -rw-r--r-- | src/gpgpu-sim/gpu-sim.cc | 11 | ||||
| -rw-r--r-- | src/gpgpu-sim/shader.cc | 114 | ||||
| -rw-r--r-- | src/gpgpu-sim/shader.h | 79 | ||||
| -rw-r--r-- | src/trace-driven/ISA_Def/turing_opcode.h | 113 | ||||
| -rw-r--r-- | src/trace-driven/ISA_Def/volta_opcode.h | 50 | ||||
| -rw-r--r-- | src/trace-driven/trace_driven.cc | 15 | ||||
| -rw-r--r-- | src/trace-driven/trace_driven.h | 3 |
11 files changed, 347 insertions, 99 deletions
diff --git a/configs/tested-cfgs/SM75_RTX2060/trace.config b/configs/tested-cfgs/SM75_RTX2060/trace.config index 41987cf..17b6cc7 100644 --- a/configs/tested-cfgs/SM75_RTX2060/trace.config +++ b/configs/tested-cfgs/SM75_RTX2060/trace.config @@ -3,3 +3,23 @@ -trace_opcode_latency_initiation_dp 8,4 -trace_opcode_latency_initiation_sfu 20,8 -trace_opcode_latency_initiation_tensor 8,4 + +#execute branch insts on spec unit 1 +#in Turing, there is a dedicated branch unit +#<enabled>,<num_units>,<max_latency>,<ID_OC_SPEC>,<OC_EX_SPEC>,<NAME> +-specialized_unit_1 1,4,4,4,4,BRA +#<latency>,<initiation> +-trace_opcode_latency_initiation_spec_op_1 4,4 + +#TEX unit, make fixed latency for all tex insts +-specialized_unit_2 1,1,200,4,4,TEX +-trace_opcode_latency_initiation_spec_op_2 200,4 + +#tensor unit +-specialized_unit_3 1,4,8,4,4,TENSOR +-trace_opcode_latency_initiation_spec_op_3 8,4 + +#UDP unit +#for more info about UDP, see https://www.hotchips.org/hc31/HC31_2.12_NVIDIA_final.pdf +-specialized_unit_4 1,4,4,4,4,UDP +-trace_opcode_latency_initiation_spec_op_4 4,2 diff --git a/configs/tested-cfgs/SM7_QV100/trace.config b/configs/tested-cfgs/SM7_QV100/trace.config index 04ac009..88f5706 100644 --- a/configs/tested-cfgs/SM7_QV100/trace.config +++ b/configs/tested-cfgs/SM7_QV100/trace.config @@ -4,3 +4,16 @@ -trace_opcode_latency_initiation_sfu 20,8 -trace_opcode_latency_initiation_tensor 8,4 +#execute branch insts on spec unit 1 +#in Volta, there is a dedicated branch unit +#<enabled>,<num_units>,<max_latency>,<ID_OC_SPEC>,<OC_EX_SPEC>,<NAME> +-specialized_unit_1 1,4,4,4,4,BRA +-trace_opcode_latency_initiation_spec_op_1 4,4 + +#TEX unit, make fixed latency for all tex insts +-specialized_unit_2 1,4,200,4,4,TEX +-trace_opcode_latency_initiation_spec_op_2 200,4 + +#tensor unit +-specialized_unit_3 1,4,8,4,4,TENSOR +-trace_opcode_latency_initiation_spec_op_3 8,4 diff --git a/configs/tested-cfgs/SM7_TITANV/trace.config b/configs/tested-cfgs/SM7_TITANV/trace.config index 04ac009..88f5706 100644 --- a/configs/tested-cfgs/SM7_TITANV/trace.config +++ b/configs/tested-cfgs/SM7_TITANV/trace.config @@ -4,3 +4,16 @@ -trace_opcode_latency_initiation_sfu 20,8 -trace_opcode_latency_initiation_tensor 8,4 +#execute branch insts on spec unit 1 +#in Volta, there is a dedicated branch unit +#<enabled>,<num_units>,<max_latency>,<ID_OC_SPEC>,<OC_EX_SPEC>,<NAME> +-specialized_unit_1 1,4,4,4,4,BRA +-trace_opcode_latency_initiation_spec_op_1 4,4 + +#TEX unit, make fixed latency for all tex insts +-specialized_unit_2 1,4,200,4,4,TEX +-trace_opcode_latency_initiation_spec_op_2 200,4 + +#tensor unit +-specialized_unit_3 1,4,8,4,4,TENSOR +-trace_opcode_latency_initiation_spec_op_3 8,4 diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index c58d39c..b22b5c4 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -79,6 +79,8 @@ typedef unsigned address_type; typedef unsigned addr_t; // the following are operations the timing model can see +#define SPECIALIZED_UNIT_NUM 8 +#define SPEC_UNIT_START_ID 100 enum uarch_op_t { NO_OP = -1, @@ -98,7 +100,15 @@ enum uarch_op_t { MEMORY_BARRIER_OP, CALL_OPS, RET_OPS, - EXIT_OPS + EXIT_OPS, + SPECIALIZED_UNIT_1_OP = SPEC_UNIT_START_ID, + SPECIALIZED_UNIT_2_OP, + SPECIALIZED_UNIT_3_OP, + SPECIALIZED_UNIT_4_OP, + SPECIALIZED_UNIT_5_OP, + SPECIALIZED_UNIT_6_OP, + SPECIALIZED_UNIT_7_OP, + SPECIALIZED_UNIT_8_OP }; typedef enum uarch_op_t op_type; @@ -135,7 +145,8 @@ enum operation_pipeline_t { INTP__OP, SFU__OP, TENSOR_CORE__OP, - MEM__OP + MEM__OP, + SPECIALIZED__OP, }; typedef enum operation_pipeline_t operation_pipeline; enum mem_operation_t { NOT_TEX, TEX }; 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, ®_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; diff --git a/src/trace-driven/ISA_Def/turing_opcode.h b/src/trace-driven/ISA_Def/turing_opcode.h index 0374bdd..12bbe76 100644 --- a/src/trace-driven/ISA_Def/turing_opcode.h +++ b/src/trace-driven/ISA_Def/turing_opcode.h @@ -43,7 +43,8 @@ static const std::unordered_map<std::string, OpcodeChar> Turing_OpcodeMap = { {"HSETP2", OpcodeChar(OP_HSETP2, SP_OP)}, // Tensor Core Instructions - {"HMMA", OpcodeChar(OP_HMMA, TENSOR_CORE_OP)}, + // Execute Tensor Core Instructions on SPECIALIZED_UNIT_3 + {"HMMA", OpcodeChar(OP_HMMA, SPECIALIZED_UNIT_3_OP)}, // Double Point Instructions {"DADD", OpcodeChar(OP_DADD, DP_OP)}, @@ -128,43 +129,46 @@ static const std::unordered_map<std::string, OpcodeChar> Turing_OpcodeMap = { {"MEMBAR", OpcodeChar(OP_MEMBAR, MEMORY_BARRIER_OP)}, {"CCTLT", OpcodeChar(OP_CCTLT, ALU_OP)}, - // Uniform Datapath Instruction // - {"R2UR", OpcodeChar(OP_R2UR, ALU_OP)}, - {"S2UR", OpcodeChar(OP_S2UR, ALU_OP)}, - {"UBMSK", OpcodeChar(OP_UBMSK, ALU_OP)}, - {"UBREV", OpcodeChar(OP_UBREV, ALU_OP)}, - {"UCLEA", OpcodeChar(OP_UCLEA, ALU_OP)}, - {"UFLO", OpcodeChar(OP_UFLO, ALU_OP)}, - {"UIADD3", OpcodeChar(OP_UIADD3, ALU_OP)}, - {"UIMAD", OpcodeChar(OP_UIMAD, ALU_OP)}, - {"UISETP", OpcodeChar(OP_UISETP, ALU_OP)}, - {"ULDC", OpcodeChar(OP_ULDC, ALU_OP)}, - {"ULEA", OpcodeChar(OP_ULEA, ALU_OP)}, - {"ULOP", OpcodeChar(OP_ULOP, ALU_OP)}, - {"ULOP3", OpcodeChar(OP_ULOP3, ALU_OP)}, - {"ULOP32I", OpcodeChar(OP_ULOP32I, ALU_OP)}, - {"UMOV", OpcodeChar(OP_UMOV, ALU_OP)}, - {"UP2UR", OpcodeChar(OP_UP2UR, ALU_OP)}, - {"UPLOP3", OpcodeChar(OP_UPLOP3, ALU_OP)}, - {"UPOPC", OpcodeChar(OP_UPOPC, ALU_OP)}, - {"UPRMT", OpcodeChar(OP_UPRMT, ALU_OP)}, - {"UPSETP", OpcodeChar(OP_UPSETP, ALU_OP)}, - {"UR2UP", OpcodeChar(OP_UR2UP, ALU_OP)}, - {"USEL", OpcodeChar(OP_USEL, ALU_OP)}, - {"USGXT", OpcodeChar(OP_USGXT, ALU_OP)}, - {"USHF", OpcodeChar(OP_USHF, ALU_OP)}, - {"USHL", OpcodeChar(OP_USHL, ALU_OP)}, - {"USHR", OpcodeChar(OP_USHR, ALU_OP)}, - {"VOTEU", OpcodeChar(OP_VOTEU, ALU_OP)}, + // Uniform Datapath Instruction + // UDP unit + // for more info about UDP, see + // https://www.hotchips.org/hc31/HC31_2.12_NVIDIA_final.pdf + {"R2UR", OpcodeChar(OP_R2UR, SPECIALIZED_UNIT_4_OP)}, + {"S2UR", OpcodeChar(OP_S2UR, SPECIALIZED_UNIT_4_OP)}, + {"UBMSK", OpcodeChar(OP_UBMSK, SPECIALIZED_UNIT_4_OP)}, + {"UBREV", OpcodeChar(OP_UBREV, SPECIALIZED_UNIT_4_OP)}, + {"UCLEA", OpcodeChar(OP_UCLEA, SPECIALIZED_UNIT_4_OP)}, + {"UFLO", OpcodeChar(OP_UFLO, SPECIALIZED_UNIT_4_OP)}, + {"UIADD3", OpcodeChar(OP_UIADD3, SPECIALIZED_UNIT_4_OP)}, + {"UIMAD", OpcodeChar(OP_UIMAD, SPECIALIZED_UNIT_4_OP)}, + {"UISETP", OpcodeChar(OP_UISETP, SPECIALIZED_UNIT_4_OP)}, + {"ULDC", OpcodeChar(OP_ULDC, SPECIALIZED_UNIT_4_OP)}, + {"ULEA", OpcodeChar(OP_ULEA, SPECIALIZED_UNIT_4_OP)}, + {"ULOP", OpcodeChar(OP_ULOP, SPECIALIZED_UNIT_4_OP)}, + {"ULOP3", OpcodeChar(OP_ULOP3, SPECIALIZED_UNIT_4_OP)}, + {"ULOP32I", OpcodeChar(OP_ULOP32I, SPECIALIZED_UNIT_4_OP)}, + {"UMOV", OpcodeChar(OP_UMOV, SPECIALIZED_UNIT_4_OP)}, + {"UP2UR", OpcodeChar(OP_UP2UR, SPECIALIZED_UNIT_4_OP)}, + {"UPLOP3", OpcodeChar(OP_UPLOP3, SPECIALIZED_UNIT_4_OP)}, + {"UPOPC", OpcodeChar(OP_UPOPC, SPECIALIZED_UNIT_4_OP)}, + {"UPRMT", OpcodeChar(OP_UPRMT, SPECIALIZED_UNIT_4_OP)}, + {"UPSETP", OpcodeChar(OP_UPSETP, SPECIALIZED_UNIT_4_OP)}, + {"UR2UP", OpcodeChar(OP_UR2UP, SPECIALIZED_UNIT_4_OP)}, + {"USEL", OpcodeChar(OP_USEL, SPECIALIZED_UNIT_4_OP)}, + {"USGXT", OpcodeChar(OP_USGXT, SPECIALIZED_UNIT_4_OP)}, + {"USHF", OpcodeChar(OP_USHF, SPECIALIZED_UNIT_4_OP)}, + {"USHL", OpcodeChar(OP_USHL, SPECIALIZED_UNIT_4_OP)}, + {"USHR", OpcodeChar(OP_USHR, SPECIALIZED_UNIT_4_OP)}, + {"VOTEU", OpcodeChar(OP_VOTEU, SPECIALIZED_UNIT_4_OP)}, // Texture Instructions // For now, we ignore texture loads, consider it as ALU_OP - {"TEX", OpcodeChar(OP_TEX, ALU_OP)}, - {"TLD", OpcodeChar(OP_TLD, ALU_OP)}, - {"TLD4", OpcodeChar(OP_TLD4, ALU_OP)}, - {"TMML", OpcodeChar(OP_TMML, ALU_OP)}, - {"TXD", OpcodeChar(OP_TXD, ALU_OP)}, - {"TXQ", OpcodeChar(OP_TXQ, ALU_OP)}, + {"TEX", OpcodeChar(OP_TEX, SPECIALIZED_UNIT_2_OP)}, + {"TLD", OpcodeChar(OP_TLD, SPECIALIZED_UNIT_2_OP)}, + {"TLD4", OpcodeChar(OP_TLD4, SPECIALIZED_UNIT_2_OP)}, + {"TMML", OpcodeChar(OP_TMML, SPECIALIZED_UNIT_2_OP)}, + {"TXD", OpcodeChar(OP_TXD, SPECIALIZED_UNIT_2_OP)}, + {"TXQ", OpcodeChar(OP_TXQ, SPECIALIZED_UNIT_2_OP)}, // Surface Instructions // {"SUATOM", OpcodeChar(OP_SUATOM, ALU_OP)}, @@ -173,26 +177,27 @@ static const std::unordered_map<std::string, OpcodeChar> Turing_OpcodeMap = { {"SUST", OpcodeChar(OP_SUST, ALU_OP)}, // Control Instructions - {"BMOV", OpcodeChar(OP_BMOV, BRANCH_OP)}, - {"BPT", OpcodeChar(OP_BPT, BRANCH_OP)}, - {"BRA", OpcodeChar(OP_BRA, BRANCH_OP)}, - {"BREAK", OpcodeChar(OP_BREAK, BRANCH_OP)}, - {"BRX", OpcodeChar(OP_BRX, BRANCH_OP)}, - {"BRXU", OpcodeChar(OP_BRXU, BRANCH_OP)}, // - {"BSSY", OpcodeChar(OP_BSSY, BRANCH_OP)}, - {"BSYNC", OpcodeChar(OP_BSYNC, BRANCH_OP)}, - {"CALL", OpcodeChar(OP_CALL, CALL_OPS)}, + // execute branch insts on a dedicated branch unit (SPECIALIZED_UNIT_1) + {"BMOV", OpcodeChar(OP_BMOV, SPECIALIZED_UNIT_1_OP)}, + {"BPT", OpcodeChar(OP_BPT, SPECIALIZED_UNIT_1_OP)}, + {"BRA", OpcodeChar(OP_BRA, SPECIALIZED_UNIT_1_OP)}, + {"BREAK", OpcodeChar(OP_BREAK, SPECIALIZED_UNIT_1_OP)}, + {"BRX", OpcodeChar(OP_BRX, SPECIALIZED_UNIT_1_OP)}, + {"BRXU", OpcodeChar(OP_BRXU, SPECIALIZED_UNIT_1_OP)}, // + {"BSSY", OpcodeChar(OP_BSSY, SPECIALIZED_UNIT_1_OP)}, + {"BSYNC", OpcodeChar(OP_BSYNC, SPECIALIZED_UNIT_1_OP)}, + {"CALL", OpcodeChar(OP_CALL, SPECIALIZED_UNIT_1_OP)}, {"EXIT", OpcodeChar(OP_EXIT, EXIT_OPS)}, - {"JMP", OpcodeChar(OP_JMP, BRANCH_OP)}, - {"JMX", OpcodeChar(OP_JMX, BRANCH_OP)}, - {"JMXU", OpcodeChar(OP_JMXU, BRANCH_OP)}, /// - {"KILL", OpcodeChar(OP_KILL, BRANCH_OP)}, - {"NANOSLEEP", OpcodeChar(OP_NANOSLEEP, BRANCH_OP)}, - {"RET", OpcodeChar(OP_RET, RET_OPS)}, - {"RPCMOV", OpcodeChar(OP_RPCMOV, BRANCH_OP)}, - {"RTT", OpcodeChar(OP_RTT, RET_OPS)}, - {"WARPSYNC", OpcodeChar(OP_WARPSYNC, BRANCH_OP)}, - {"YIELD", OpcodeChar(OP_YIELD, BRANCH_OP)}, + {"JMP", OpcodeChar(OP_JMP, SPECIALIZED_UNIT_1_OP)}, + {"JMX", OpcodeChar(OP_JMX, SPECIALIZED_UNIT_1_OP)}, + {"JMXU", OpcodeChar(OP_JMXU, SPECIALIZED_UNIT_1_OP)}, /// + {"KILL", OpcodeChar(OP_KILL, SPECIALIZED_UNIT_3_OP)}, + {"NANOSLEEP", OpcodeChar(OP_NANOSLEEP, SPECIALIZED_UNIT_1_OP)}, + {"RET", OpcodeChar(OP_RET, SPECIALIZED_UNIT_1_OP)}, + {"RPCMOV", OpcodeChar(OP_RPCMOV, SPECIALIZED_UNIT_1_OP)}, + {"RTT", OpcodeChar(OP_RTT, SPECIALIZED_UNIT_1_OP)}, + {"WARPSYNC", OpcodeChar(OP_WARPSYNC, SPECIALIZED_UNIT_1_OP)}, + {"YIELD", OpcodeChar(OP_YIELD, SPECIALIZED_UNIT_1_OP)}, // Miscellaneous Instructions {"B2R", OpcodeChar(OP_B2R, ALU_OP)}, diff --git a/src/trace-driven/ISA_Def/volta_opcode.h b/src/trace-driven/ISA_Def/volta_opcode.h index 7bd6904..3358211 100644 --- a/src/trace-driven/ISA_Def/volta_opcode.h +++ b/src/trace-driven/ISA_Def/volta_opcode.h @@ -43,7 +43,8 @@ static const std::unordered_map<std::string, OpcodeChar> Volta_OpcodeMap = { {"HSETP2", OpcodeChar(OP_HSETP2, SP_OP)}, // Tensor Core Instructions - {"HMMA", OpcodeChar(OP_HMMA, TENSOR_CORE_OP)}, + // Execute Tensor Core Instructions on SPECIALIZED_UNIT_3 + {"HMMA", OpcodeChar(OP_HMMA, SPECIALIZED_UNIT_3_OP)}, // Double Point Instructions {"DADD", OpcodeChar(OP_DADD, DP_OP)}, @@ -126,32 +127,33 @@ static const std::unordered_map<std::string, OpcodeChar> Volta_OpcodeMap = { // Texture Instructions // For now, we ignore texture loads, consider it as ALU_OP - {"TEX", OpcodeChar(OP_TEX, ALU_OP)}, - {"TLD", OpcodeChar(OP_TLD, ALU_OP)}, - {"TLD4", OpcodeChar(OP_TLD4, ALU_OP)}, - {"TMML", OpcodeChar(OP_TMML, ALU_OP)}, - {"TXD", OpcodeChar(OP_TXD, ALU_OP)}, - {"TXQ", OpcodeChar(OP_TXQ, ALU_OP)}, + {"TEX", OpcodeChar(OP_TEX, SPECIALIZED_UNIT_2_OP)}, + {"TLD", OpcodeChar(OP_TLD, SPECIALIZED_UNIT_2_OP)}, + {"TLD4", OpcodeChar(OP_TLD4, SPECIALIZED_UNIT_2_OP)}, + {"TMML", OpcodeChar(OP_TMML, SPECIALIZED_UNIT_2_OP)}, + {"TXD", OpcodeChar(OP_TXD, SPECIALIZED_UNIT_2_OP)}, + {"TXQ", OpcodeChar(OP_TXQ, SPECIALIZED_UNIT_2_OP)}, // Control Instructions - {"BMOV", OpcodeChar(OP_BMOV, BRANCH_OP)}, - {"BPT", OpcodeChar(OP_BPT, BRANCH_OP)}, - {"BRA", OpcodeChar(OP_BRA, BRANCH_OP)}, - {"BREAK", OpcodeChar(OP_BREAK, BRANCH_OP)}, - {"BRX", OpcodeChar(OP_BRX, BRANCH_OP)}, - {"BSSY", OpcodeChar(OP_BSSY, BRANCH_OP)}, - {"BSYNC", OpcodeChar(OP_BSYNC, BRANCH_OP)}, - {"CALL", OpcodeChar(OP_CALL, CALL_OPS)}, + // execute branch insts on a dedicated branch unit (SPECIALIZED_UNIT_1) + {"BMOV", OpcodeChar(OP_BMOV, SPECIALIZED_UNIT_1_OP)}, + {"BPT", OpcodeChar(OP_BPT, SPECIALIZED_UNIT_1_OP)}, + {"BRA", OpcodeChar(OP_BRA, SPECIALIZED_UNIT_1_OP)}, + {"BREAK", OpcodeChar(OP_BREAK, SPECIALIZED_UNIT_1_OP)}, + {"BRX", OpcodeChar(OP_BRX, SPECIALIZED_UNIT_1_OP)}, + {"BSSY", OpcodeChar(OP_BSSY, SPECIALIZED_UNIT_1_OP)}, + {"BSYNC", OpcodeChar(OP_BSYNC, SPECIALIZED_UNIT_1_OP)}, + {"CALL", OpcodeChar(OP_CALL, SPECIALIZED_UNIT_1_OP)}, {"EXIT", OpcodeChar(OP_EXIT, EXIT_OPS)}, - {"JMP", OpcodeChar(OP_JMP, BRANCH_OP)}, - {"JMX", OpcodeChar(OP_JMX, BRANCH_OP)}, - {"KILL", OpcodeChar(OP_KILL, BRANCH_OP)}, - {"NANOSLEEP", OpcodeChar(OP_NANOSLEEP, BRANCH_OP)}, - {"RET", OpcodeChar(OP_RET, RET_OPS)}, - {"RPCMOV", OpcodeChar(OP_RPCMOV, BRANCH_OP)}, - {"RTT", OpcodeChar(OP_RTT, RET_OPS)}, - {"WARPSYNC", OpcodeChar(OP_WARPSYNC, BRANCH_OP)}, - {"YIELD", OpcodeChar(OP_YIELD, BRANCH_OP)}, + {"JMP", OpcodeChar(OP_JMP, SPECIALIZED_UNIT_1_OP)}, + {"JMX", OpcodeChar(OP_JMX, SPECIALIZED_UNIT_1_OP)}, + {"KILL", OpcodeChar(OP_KILL, SPECIALIZED_UNIT_1_OP)}, + {"NANOSLEEP", OpcodeChar(OP_NANOSLEEP, SPECIALIZED_UNIT_1_OP)}, + {"RET", OpcodeChar(OP_RET, SPECIALIZED_UNIT_1_OP)}, + {"RPCMOV", OpcodeChar(OP_RPCMOV, SPECIALIZED_UNIT_1_OP)}, + {"RTT", OpcodeChar(OP_RTT, SPECIALIZED_UNIT_1_OP)}, + {"WARPSYNC", OpcodeChar(OP_WARPSYNC, SPECIALIZED_UNIT_1_OP)}, + {"YIELD", OpcodeChar(OP_YIELD, SPECIALIZED_UNIT_1_OP)}, // Miscellaneous Instructions {"B2R", OpcodeChar(OP_B2R, ALU_OP)}, diff --git a/src/trace-driven/trace_driven.cc b/src/trace-driven/trace_driven.cc index d42ee65..0b1e24b 100644 --- a/src/trace-driven/trace_driven.cc +++ b/src/trace-driven/trace_driven.cc @@ -608,6 +608,16 @@ void trace_config::reg_options(option_parser_t opp) { "Opcode latencies and initiation for tensor in trace " "driven mode <latency,initiation>", "4,1"); + + for (unsigned j = 0; j < SPECIALIZED_UNIT_NUM; ++j) { + std::stringstream ss; + ss << "-trace_opcode_latency_initiation_spec_op_" << j + 1; + option_parser_register(opp, ss.str().c_str(), OPT_CSTR, + &trace_opcode_latency_initiation_specialized_op[j], + "specialized unit config" + " <latency,initiation>", + "4,4"); + } } void trace_config::parse_config() { @@ -617,6 +627,11 @@ void trace_config::parse_config() { sscanf(trace_opcode_latency_initiation_sfu, "%u,%u", &sfu_latency, &sfu_init); sscanf(trace_opcode_latency_initiation_tensor, "%u,%u", &tensor_latency, &tensor_init); + + for (unsigned j = 0; j < SPECIALIZED_UNIT_NUM; ++j) { + sscanf(trace_opcode_latency_initiation_specialized_op[j], "%u,%u", + &specialized_unit_latency[j], &specialized_unit_initiation[j]); + } } void trace_config::set_latency(unsigned category, unsigned& latency, unsigned& initiation_interval) { diff --git a/src/trace-driven/trace_driven.h b/src/trace-driven/trace_driven.h index ea315a1..3af99c3 100644 --- a/src/trace-driven/trace_driven.h +++ b/src/trace-driven/trace_driven.h @@ -93,6 +93,8 @@ class trace_config { private: unsigned int_latency, fp_latency, dp_latency, sfu_latency, tensor_latency; unsigned int_init, fp_init, dp_init, sfu_init, tensor_init; + unsigned specialized_unit_latency[SPECIALIZED_UNIT_NUM]; + unsigned specialized_unit_initiation[SPECIALIZED_UNIT_NUM]; char* g_traces_filename; char* trace_opcode_latency_initiation_int; @@ -100,6 +102,7 @@ class trace_config { char* trace_opcode_latency_initiation_dp; char* trace_opcode_latency_initiation_sfu; char* trace_opcode_latency_initiation_tensor; + char* trace_opcode_latency_initiation_specialized_op[SPECIALIZED_UNIT_NUM]; }; class trace_parser { |
