#pragma once
#include <stdint.h>
#include <stdio.h>
#include <cassert>
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>
#include "instr_types.h"
#include "tools_cuda_api_meta.h"
#define __CUDA_API_VERSION_INTERNAL
#include "cuda.h"
#include "generated_cuda_meta.h"
#define NVBIT_VERSION "1.5.5"
class Instr {
public:
const char* getSass();
uint32_t getOffset();
uint32_t getIdx();
bool hasPred();
int getPredNum();
bool isPredNeg();
bool isPredUniform();
const char* getOpcode();
const char* getOpcodeShort();
InstrType::MemorySpace getMemorySpace();
bool isLoad();
bool isStore();
bool isExtended();
int getSize();
int getNumOperands();
const InstrType::operand_t* getOperand(int num_operand);
void printDecoded();
void print(const char* prefix = NULL);
private:
Instr(const char* sass);
const void* reserved;
friend class Nvbit;
friend class Function;
};
typedef struct { std::vector<Instr*> instrs; } basic_block_t;
typedef struct {
bool is_degenerate;
std::vector<basic_block_t*> bbs;
} CFG_t;
#define DEFINE_ENUM_CBID_API_CUDA(area, id, name, params) API_CUDA_##name,
typedef enum {
API_CUDA_INVALID = 0,
CU_TOOLS_FOR_EACH_CUDA_API_FUNC(DEFINE_ENUM_CBID_API_CUDA)
} nvbit_api_cuda_t;
extern "C" {
void nvbit_at_init();
void nvbit_at_term();
void nvbit_at_ctx_init(CUcontext ctx);
void nvbit_at_ctx_term(CUcontext ctx);
void nvbit_at_cuda_event(CUcontext ctx, int is_exit, nvbit_api_cuda_t cbid,
const char* event_name, void* params,
CUresult* pStatus);
std::vector<CUfunction> nvbit_get_related_functions(CUcontext ctx,
CUfunction func);
const std::vector<Instr*>& nvbit_get_instrs(CUcontext ctx, CUfunction func);
const CFG_t& nvbit_get_CFG(CUcontext ctx, CUfunction func);
const char* nvbit_get_func_name(CUcontext ctx, CUfunction f,
bool mangled = false);
bool nvbit_get_line_info(CUcontext cuctx, CUfunction cufunc, uint32_t offset,
char** file_name, char** dir_name, uint32_t* line);
uint32_t nvbit_get_sm_family(CUcontext cuctx);
uint64_t nvbit_get_func_addr(CUfunction func);
bool nvbit_is_func_kernel(CUcontext ctx, CUfunction func);
std::vector<int> nvbit_get_kernel_argument_sizes(CUfunction func);
uint64_t nvbit_get_shmem_base_addr(CUcontext cuctx);
uint64_t nvbit_get_local_mem_base_addr(CUcontext cuctx);
typedef enum { IPOINT_BEFORE, IPOINT_AFTER } ipoint_t;
void nvbit_insert_call(const Instr* instr, const char* dev_func_name,
ipoint_t point);
void nvbit_add_call_arg_guard_pred_val(const Instr* instr,
bool is_variadic_arg = false);
void nvbit_add_call_arg_pred_val_at(const Instr* instr, int pred_num,
bool is_variadic_arg = false);
void nvbit_add_call_arg_upred_val_at(const Instr* instr, int upred_num,
bool is_variadic_arg = false);
void nvbit_add_call_arg_pred_reg(const Instr* instr,
bool is_variadic_arg = false);
void nvbit_add_call_arg_upred_reg(const Instr* instr,
bool is_variadic_arg = false);
void nvbit_add_call_arg_const_val32(const Instr* instr, uint32_t val,
bool is_variadic_arg = false);
void nvbit_add_call_arg_const_val64(const Instr* instr, uint64_t val,
bool is_variadic_arg = false);
void nvbit_add_call_arg_reg_val(const Instr* instr, int reg_num,
bool is_variadic_arg = false);
void nvbit_add_call_arg_ureg_val(const Instr* instr, int reg_num,
bool is_variadic_arg = false);
void nvbit_add_call_arg_launch_val32(const Instr* instr, int offset,
bool is_variadic_arg = false);
void nvbit_add_call_arg_launch_val64(const Instr* instr, int offset,
bool is_variadic_arg = false);
void nvbit_add_call_arg_cbank_val(const Instr* instr, int bankid,
int bankoffset, bool is_variadic_arg = false);
void nvbit_add_call_arg_mref_addr64(const Instr* instr, int id = 0,
bool is_variadic_arg = false);
void nvbit_remove_orig(const Instr* instr);
#ifdef __CUDACC__
__device__ __noinline__ int32_t nvbit_read_reg(uint64_t reg_num);
__device__ __noinline__ void nvbit_write_reg(uint64_t reg_num, int32_t reg_val);
__device__ __noinline__ int32_t nvbit_read_ureg(uint64_t reg_num);
__device__ __noinline__ void nvbit_write_ureg(uint64_t reg_num,
int32_t reg_val);
__device__ __noinline__ int32_t nvbit_read_pred_reg(void);
__device__ __noinline__ void nvbit_write_pred_reg(int32_t reg_val);
__device__ __noinline__ int32_t nvbit_read_upred_reg(void);
__device__ __noinline__ void nvbit_write_upred_reg(int32_t reg_val);
#endif
void nvbit_enable_instrumented(CUcontext ctx, CUfunction func, bool flag,
bool apply_to_related = true);
void nvbit_set_at_launch(CUcontext ctx, CUfunction func, void* buf,
uint32_t nbytes);
void nvbit_set_tool_pthread(pthread_t tool_pthread);
void nvbit_unset_tool_pthread(pthread_t tool_pthread);
void nvbit_set_nvdisasm(const char* nvdisasm);
}
#define PRINT_VAR(env_var, help, var) \
std::cout << std::setw(20) << env_var << " = " << var << " - " << help \
<< std::endl;
#define GET_VAR_INT(var, env_var, def, help) \
if (getenv(env_var)) { \
var = atoi(getenv(env_var)); \
} else { \
var = def; \
} \
PRINT_VAR(env_var, help, var)
#define GET_VAR_LONG(var, env_var, def, help) \
if (getenv(env_var)) { \
var = atol(getenv(env_var)); \
} else { \
var = def; \
} \
PRINT_VAR(env_var, help, var)
#define GET_VAR_STR(var, env_var, help) \
if (getenv(env_var)) { \
std::string s(getenv(env_var)); \
var = s; \
} \
PRINT_VAR(env_var, help, var)