summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configs/tested-cfgs/SM75_RTX2060/trace.config20
-rw-r--r--configs/tested-cfgs/SM7_QV100/trace.config13
-rw-r--r--configs/tested-cfgs/SM7_TITANV/trace.config13
-rw-r--r--src/abstract_hardware_model.h15
-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
-rw-r--r--src/trace-driven/ISA_Def/turing_opcode.h113
-rw-r--r--src/trace-driven/ISA_Def/volta_opcode.h50
-rw-r--r--src/trace-driven/trace_driven.cc15
-rw-r--r--src/trace-driven/trace_driven.h3
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,
&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;
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 {