aboutsummaryrefslogtreecommitdiff
path: root/src/cuda-sim
diff options
context:
space:
mode:
Diffstat (limited to 'src/cuda-sim')
-rw-r--r--src/cuda-sim/cuda-sim.cc2
-rw-r--r--src/cuda-sim/cuda_device_runtime.h1
-rw-r--r--src/cuda-sim/instructions.cc138
-rw-r--r--src/cuda-sim/opcodes.def1
-rw-r--r--src/cuda-sim/ptx-stats.cc34
-rw-r--r--src/cuda-sim/ptx.l1
-rw-r--r--src/cuda-sim/ptx_ir.cc3
-rw-r--r--src/cuda-sim/ptx_ir.h14
-rw-r--r--src/cuda-sim/ptx_loader.cc3
-rw-r--r--src/cuda-sim/ptx_parser.cc10
10 files changed, 177 insertions, 30 deletions
diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc
index 75dd3c8..71f0703 100644
--- a/src/cuda-sim/cuda-sim.cc
+++ b/src/cuda-sim/cuda-sim.cc
@@ -1741,7 +1741,7 @@ void ptx_thread_info::ptx_exec_inst(warp_inst_t &inst, unsigned lane_id) {
} else {
const ptx_instruction *pI_saved = pI;
ptx_instruction *pJ = NULL;
- if (pI->get_opcode() == VOTE_OP) {
+ if (pI->get_opcode() == VOTE_OP || pI->get_opcode() == ACTIVEMASK_OP) {
pJ = new ptx_instruction(*pI);
*((warp_inst_t *)pJ) = inst; // copy active mask information
pI = pJ;
diff --git a/src/cuda-sim/cuda_device_runtime.h b/src/cuda-sim/cuda_device_runtime.h
index 1d661b2..b06dd24 100644
--- a/src/cuda-sim/cuda_device_runtime.h
+++ b/src/cuda-sim/cuda_device_runtime.h
@@ -43,6 +43,7 @@ class cuda_device_runtime {
std::map<void*, device_launch_config_t> g_cuda_device_launch_param_map;
std::list<device_launch_operation_t> g_cuda_device_launch_op;
unsigned g_kernel_launch_latency;
+ unsigned g_TB_launch_latency;
unsigned long long g_max_total_param_size;
bool g_cdp_enabled;
diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc
index bf9a040..8936fa8 100644
--- a/src/cuda-sim/instructions.cc
+++ b/src/cuda-sim/instructions.cc
@@ -166,6 +166,8 @@ void inst_not_implemented(const ptx_instruction *pI);
ptx_reg_t srcOperandModifiers(ptx_reg_t opData, operand_info opInfo,
operand_info dstInfo, unsigned type,
ptx_thread_info *thread);
+
+void video_mem_instruction(const ptx_instruction *pI, ptx_thread_info *thread, int op_code);
void sign_extend(ptx_reg_t &data, unsigned src_size, const operand_info &dst);
@@ -1709,8 +1711,40 @@ void bfi_impl(const ptx_instruction *pI, ptx_thread_info *thread) {
}
thread->set_operand_value(dst, data, i_type, thread, pI);
}
-void bfind_impl(const ptx_instruction *pI, ptx_thread_info *thread) {
- inst_not_implemented(pI);
+void bfind_impl(const ptx_instruction *pI, ptx_thread_info *thread)
+{
+ const operand_info &dst = pI->dst();
+ const operand_info &src1 = pI->src1();
+ const unsigned i_type = pI->get_type();
+
+ const ptx_reg_t src1_data = thread->get_operand_value(src1, dst, i_type, thread, 1);
+ const int msb = ( i_type == U32_TYPE || i_type == S32_TYPE) ? 31 : 63;
+
+ unsigned long a = 0;
+ switch (i_type)
+ {
+ case S32_TYPE: a = src1_data.s32; break;
+ case U32_TYPE: a = src1_data.u32; break;
+ case S64_TYPE: a = src1_data.s64; break;
+ case U64_TYPE: a = src1_data.u64; break;
+ default: assert(false); abort();
+ }
+
+ // negate negative signed inputs
+ if ( ( i_type == S32_TYPE || i_type == S64_TYPE ) && ( a & ( 1 << msb ) ) ) {
+ a = ~a;
+ }
+ uint32_t d_data = 0xffffffff;
+ for (uint32_t i = msb; i >= 0; i--) {
+ if (a & (1<<i)) { d_data = i; break; }
+ }
+
+ // if (.shiftamt && d != 0xffffffff) { d = msb - d; }
+
+ // store d
+ thread->set_operand_value(dst, d_data, U32_TYPE, thread, pI);
+
+
}
void bra_impl(const ptx_instruction *pI, ptx_thread_info *thread) {
@@ -6301,11 +6335,17 @@ void vadd_impl(const ptx_instruction *pI, ptx_thread_info *thread) {
void vmad_impl(const ptx_instruction *pI, ptx_thread_info *thread) {
inst_not_implemented(pI);
}
-void vmax_impl(const ptx_instruction *pI, ptx_thread_info *thread) {
- inst_not_implemented(pI);
+
+#define VMAX 0
+#define VMIN 1
+
+void vmax_impl(const ptx_instruction *pI, ptx_thread_info *thread)
+{
+ video_mem_instruction(pI, thread, VMAX);
}
-void vmin_impl(const ptx_instruction *pI, ptx_thread_info *thread) {
- inst_not_implemented(pI);
+void vmin_impl(const ptx_instruction *pI, ptx_thread_info *thread)
+{
+ video_mem_instruction(pI, thread, VMIN);
}
void vset_impl(const ptx_instruction *pI, ptx_thread_info *thread) {
inst_not_implemented(pI);
@@ -6400,6 +6440,15 @@ void vote_impl(const ptx_instruction *pI, ptx_thread_info *thread) {
}
}
+void activemask_impl( const ptx_instruction *pI, ptx_thread_info *thread )
+{
+ active_mask_t l_activemask_bitset = pI->get_warp_active_mask();
+ uint32_t l_activemask_uint = static_cast<uint32_t>(l_activemask_bitset.to_ulong());
+
+ const operand_info &dst = pI->dst();
+ thread->set_operand_value(dst, l_activemask_uint, U32_TYPE, thread, pI);
+}
+
void xor_impl(const ptx_instruction *pI, ptx_thread_info *thread) {
ptx_reg_t src1_data, src2_data, data;
@@ -6477,3 +6526,80 @@ ptx_reg_t srcOperandModifiers(ptx_reg_t opData, operand_info opInfo,
return result;
}
+
+void video_mem_instruction(const ptx_instruction *pI, ptx_thread_info *thread, int op_code)
+{
+ const operand_info &dst = pI->dst(); // d
+ const operand_info &src1 = pI->src1(); // a
+ const operand_info &src2 = pI->src2(); // b
+ const operand_info &src3 = pI->src3(); // c
+
+ const unsigned i_type = pI->get_type();
+
+ std::list<int> scalar_type;
+ std::list<int> options;
+
+ ptx_reg_t a, b, ta, tb, c, data;
+
+ a = thread->get_operand_value(src1, dst, i_type, thread, 1);
+ b = thread->get_operand_value(src2, dst, i_type, thread, 1);
+ c = thread->get_operand_value(src3, dst, i_type, thread, 1);
+
+ // TODO: implement this
+ // ta = partSelectSignExtend( a, atype );
+ // tb = partSelectSignExtend( b, btype );
+ ta = a;
+ tb = b;
+
+ options = pI->get_options();
+ assert(options.size() == 1);
+
+ auto option = options.begin();
+ assert(*option == ATOMIC_MAX || *option == ATOMIC_MIN);
+
+ switch ( i_type ) {
+ case S32_TYPE: {
+ // assert all operands are S32_TYPE:
+ scalar_type = pI->get_scalar_type();
+ for (std::list<int>::iterator scalar = scalar_type.begin(); scalar != scalar_type.end(); scalar++)
+ {
+ assert(*scalar == S32_TYPE);
+ }
+ assert(scalar_type.size() == 3);
+ scalar_type.clear();
+
+ switch (op_code)
+ {
+ case VMAX:
+ data.s32 = MY_MAX_I(ta.s32, tb.s32);
+ break;
+ case VMIN:
+ data.s32 = MY_MIN_I(ta.s32, tb.s32);
+ break;
+ default:
+ assert(0);
+ }
+
+ switch (*option)
+ {
+ case ATOMIC_MAX:
+ data.s32 = MY_MAX_I(data.s32, c.s32);
+ break;
+ case ATOMIC_MIN:
+ data.s32 = MY_MIN_I(data.s32, c.s32);
+ break;
+ default:
+ assert(0); // not yet implemented
+ }
+ break;
+
+ }
+ default:
+ assert(0); // not yet implemented
+ }
+
+ thread->set_operand_value(dst, data, i_type, thread, pI);
+
+ return;
+}
+
diff --git a/src/cuda-sim/opcodes.def b/src/cuda-sim/opcodes.def
index c4d6a83..f5bf156 100644
--- a/src/cuda-sim/opcodes.def
+++ b/src/cuda-sim/opcodes.def
@@ -129,6 +129,7 @@ OP_DEF(VSHL_OP,vshl_impl,"vshl",0,11)
OP_DEF(VSHR_OP,vshr_impl,"vshr",0,11)
OP_DEF(VSUB_OP,vsub_impl,"vsub",0,11)
OP_DEF(VOTE_OP,vote_impl,"vote",0,3)
+OP_DEF(ACTIVEMASK_OP,activemask_impl,"activemask",1,3)
OP_DEF(XOR_OP,xor_impl,"xor",1,1)
OP_DEF(NOP_OP,nop_impl,"nop",0,7)
OP_DEF(BREAK_OP,break_impl,"break",0,3)
diff --git a/src/cuda-sim/ptx-stats.cc b/src/cuda-sim/ptx-stats.cc
index 9f7e760..3e96984 100644
--- a/src/cuda-sim/ptx-stats.cc
+++ b/src/cuda-sim/ptx-stats.cc
@@ -168,9 +168,10 @@ void ptx_file_line_stats_add_exec_count(const ptx_instruction *pInsn) {
void ptx_stats::ptx_file_line_stats_add_latency(unsigned pc, unsigned latency) {
const ptx_instruction *pInsn = gpgpu_ctx->pc_to_instruction(pc);
- ptx_file_line_stats_tracker[ptx_file_line(pInsn->source_file(),
- pInsn->source_line())]
- .latency += latency;
+ if (pInsn != NULL)
+ ptx_file_line_stats_tracker[ptx_file_line(pInsn->source_file(),
+ pInsn->source_line())]
+ .latency += latency;
}
// attribute dram traffic to this ptx instruction (specified by the pc)
@@ -179,9 +180,10 @@ void ptx_stats::ptx_file_line_stats_add_dram_traffic(unsigned pc,
unsigned dram_traffic) {
const ptx_instruction *pInsn = gpgpu_ctx->pc_to_instruction(pc);
- ptx_file_line_stats_tracker[ptx_file_line(pInsn->source_file(),
- pInsn->source_line())]
- .dram_traffic += dram_traffic;
+ if (pInsn != NULL)
+ ptx_file_line_stats_tracker[ptx_file_line(pInsn->source_file(),
+ pInsn->source_line())]
+ .dram_traffic += dram_traffic;
}
// attribute the number of shared memory access cycles to a ptx instruction
@@ -191,10 +193,12 @@ void ptx_stats::ptx_file_line_stats_add_smem_bank_conflict(
unsigned pc, unsigned n_way_bkconflict) {
const ptx_instruction *pInsn = gpgpu_ctx->pc_to_instruction(pc);
- ptx_file_line_stats &line_stats = ptx_file_line_stats_tracker[ptx_file_line(
- pInsn->source_file(), pInsn->source_line())];
- line_stats.smem_n_way_bank_conflict_total += n_way_bkconflict;
- line_stats.smem_warp_count += 1;
+ if (pInsn != NULL) {
+ ptx_file_line_stats &line_stats = ptx_file_line_stats_tracker[ptx_file_line(
+ pInsn->source_file(), pInsn->source_line())];
+ line_stats.smem_n_way_bank_conflict_total += n_way_bkconflict;
+ line_stats.smem_warp_count += 1;
+ }
}
// attribute a non-coalesced mem access to a ptx instruction
@@ -204,10 +208,12 @@ void ptx_stats::ptx_file_line_stats_add_uncoalesced_gmem(unsigned pc,
unsigned n_access) {
const ptx_instruction *pInsn = gpgpu_ctx->pc_to_instruction(pc);
- ptx_file_line_stats &line_stats = ptx_file_line_stats_tracker[ptx_file_line(
- pInsn->source_file(), pInsn->source_line())];
- line_stats.gmem_n_access_total += n_access;
- line_stats.gmem_warp_count += 1;
+ if (pInsn != NULL) {
+ ptx_file_line_stats &line_stats = ptx_file_line_stats_tracker[ptx_file_line(
+ pInsn->source_file(), pInsn->source_line())];
+ line_stats.gmem_n_access_total += n_access;
+ line_stats.gmem_warp_count += 1;
+ }
}
// a class that tracks the inflight memory instructions of a shader core
diff --git a/src/cuda-sim/ptx.l b/src/cuda-sim/ptx.l
index 2dadda4..6754045 100644
--- a/src/cuda-sim/ptx.l
+++ b/src/cuda-sim/ptx.l
@@ -158,6 +158,7 @@ vshl TC; yylval->int_value = VSHL_OP; return OPCODE;
vshr TC; yylval->int_value = VSHR_OP; return OPCODE;
vsub TC; yylval->int_value = VSUB_OP; return OPCODE;
vote TC; yylval->int_value = VOTE_OP; return OPCODE;
+activemask TC; yylval->int_value = ACTIVEMASK_OP; return OPCODE;
xor TC; yylval->int_value = XOR_OP; return OPCODE;
nop TC; yylval->int_value = NOP_OP; return OPCODE;
break TC; yylval->int_value = BREAK_OP; return OPCODE;
diff --git a/src/cuda-sim/ptx_ir.cc b/src/cuda-sim/ptx_ir.cc
index aa1c25a..e5b5fb7 100644
--- a/src/cuda-sim/ptx_ir.cc
+++ b/src/cuda-sim/ptx_ir.cc
@@ -1147,7 +1147,8 @@ static std::list<operand_info> check_operands(
const std::list<operand_info> &operands, gpgpu_context *ctx) {
static int g_warn_literal_operands_two_type_inst;
if ((opcode == CVT_OP) || (opcode == SET_OP) || (opcode == SLCT_OP) ||
- (opcode == TEX_OP) || (opcode == MMA_OP) || (opcode == DP4A_OP)) {
+ (opcode == TEX_OP) || (opcode == MMA_OP) || (opcode == DP4A_OP) ||
+ (opcode == VMIN_OP) || (opcode == VMAX_OP) ) {
// just make sure these do not have have const operands...
if (!g_warn_literal_operands_two_type_inst) {
std::list<operand_info>::const_iterator o;
diff --git a/src/cuda-sim/ptx_ir.h b/src/cuda-sim/ptx_ir.h
index 6627847..4243941 100644
--- a/src/cuda-sim/ptx_ir.h
+++ b/src/cuda-sim/ptx_ir.h
@@ -966,6 +966,9 @@ class ptx_instruction : public warp_inst_t {
int get_pred_mod() const { return m_pred_mod; }
const char *get_source() const { return m_source.c_str(); }
+ const std::list<int> get_scalar_type() const {return m_scalar_type;}
+ const std::list<int> get_options() const {return m_options;}
+
typedef std::vector<operand_info>::const_iterator const_iterator;
const_iterator op_iter_begin() const { return m_operands.begin(); }
@@ -1336,12 +1339,12 @@ class function_info {
memory_space *param_mem, gpgpu_t *gpu, dim3 gridDim,
dim3 blockDim);
- const struct gpgpu_ptx_sim_info *get_kernel_info() const {
+ virtual const struct gpgpu_ptx_sim_info *get_kernel_info() const {
assert(m_kernel_info.maxthreads == maxnt_id);
return &m_kernel_info;
}
- const void set_kernel_info(const struct gpgpu_ptx_sim_info &info) {
+ virtual const void set_kernel_info(const struct gpgpu_ptx_sim_info &info) {
m_kernel_info = info;
m_kernel_info.ptx_version = 10 * get_ptx_version().ver();
m_kernel_info.sm_target = get_ptx_version().target();
@@ -1377,6 +1380,11 @@ class function_info {
// backward pointer
class gpgpu_context *gpgpu_ctx;
+ protected:
+ // Registers/shmem/etc. used (from ptxas -v), loaded from ___.ptxinfo along
+ // with ___.ptx
+ struct gpgpu_ptx_sim_info m_kernel_info;
+
private:
unsigned maxnt_id;
unsigned m_uid;
@@ -1402,7 +1410,7 @@ class function_info {
// Registers/shmem/etc. used (from ptxas -v), loaded from ___.ptxinfo along
// with ___.ptx
- struct gpgpu_ptx_sim_info m_kernel_info;
+ // with ___.ptx
symbol_table *m_symtab;
diff --git a/src/cuda-sim/ptx_loader.cc b/src/cuda-sim/ptx_loader.cc
index 372bda4..4e91763 100644
--- a/src/cuda-sim/ptx_loader.cc
+++ b/src/cuda-sim/ptx_loader.cc
@@ -38,7 +38,8 @@
/// extern prototypes
-extern int ptx_error(yyscan_t yyscanner, const char *s);
+extern int ptx_error(yyscan_t yyscanner, ptx_recognizer *recognizer,
+ const char *s);
extern int ptx_lex_init(yyscan_t *scanner);
extern void ptx_set_in(FILE *_in_str, yyscan_t yyscanner);
extern int ptx_parse(yyscan_t scanner, ptx_recognizer *recognizer);
diff --git a/src/cuda-sim/ptx_parser.cc b/src/cuda-sim/ptx_parser.cc
index 3ae8de3..afdb41b 100644
--- a/src/cuda-sim/ptx_parser.cc
+++ b/src/cuda-sim/ptx_parser.cc
@@ -36,7 +36,8 @@ typedef void *yyscan_t;
extern int ptx_get_lineno(yyscan_t yyscanner);
extern YYSTYPE *ptx_get_lval(yyscan_t yyscanner);
-extern int ptx_error(yyscan_t yyscanner, const char *s);
+extern int ptx_error(yyscan_t yyscanner, ptx_recognizer *recognizer,
+ const char *s);
extern int ptx_lex_init(yyscan_t *scanner);
extern void ptx_set_in(FILE *_in_str, yyscan_t yyscanner);
extern FILE *ptx_get_in(yyscan_t yyscanner);
@@ -225,7 +226,7 @@ void ptx_recognizer::parse_error_impl(const char *file, unsigned line,
g_error_detected = 1;
printf("%s:%u: Parse error: %s (%s:%u)\n\n", gpgpu_ctx->g_filename,
ptx_get_lineno(scanner), buf, file, line);
- ptx_error(scanner, NULL);
+ ptx_error(scanner, this, NULL);
abort();
exit(1);
}
@@ -624,8 +625,9 @@ void ptx_recognizer::add_scalar_type_spec(int type_spec) {
parse_assert((g_opcode == -1) || (g_opcode == CVT_OP) ||
(g_opcode == SET_OP) || (g_opcode == SLCT_OP) ||
(g_opcode == TEX_OP) || (g_opcode == MMA_OP) ||
- (g_opcode == DP4A_OP),
- "only cvt, set, slct, tex and dp4a can have more than one "
+ (g_opcode == DP4A_OP) || (g_opcode == VMIN_OP) ||
+ (g_opcode == VMAX_OP),
+ "only cvt, set, slct, tex, vmin, vmax and dp4a can have more than one "
"type specifier.");
}
g_scalar_type_spec = type_spec;