diff options
| author | Amruth <[email protected]> | 2018-04-03 11:43:46 -0700 |
|---|---|---|
| committer | Amruth <[email protected]> | 2018-04-03 11:43:46 -0700 |
| commit | 26476592e3650e796b51c94dd1a25c162eb1aa64 (patch) | |
| tree | a12f4f25ba9d6a554c3e95cb189f1f4264ed8db0 /libcuda | |
| parent | deee9038d3d67e60f106776be3dd0a846dd11df9 (diff) | |
crash when print() is sent to pdom analysis
Diffstat (limited to 'libcuda')
| -rw-r--r-- | libcuda/cuda_runtime_api.cc | 15 | ||||
| -rw-r--r-- | libcuda/cuda_runtime_api.cc~ | 2515 |
2 files changed, 2523 insertions, 7 deletions
diff --git a/libcuda/cuda_runtime_api.cc b/libcuda/cuda_runtime_api.cc index 6cf21dd..ded1aee 100644 --- a/libcuda/cuda_runtime_api.cc +++ b/libcuda/cuda_runtime_api.cc @@ -1499,6 +1499,12 @@ void extract_code_using_cuobjdump(){ no_of_ptx = no_of_ptx + 1; fclose(fp); } + if(no_of_ptx==0){ + printf("WARNING: Number of ptx in the executable file are 0. One of the reasons might be\n"); + printf("\t1. CDP is enabled\n"); + printf("\t2. cuobjdump -lptx doesnt recognize sm_%u\n",forced_max_capability); + printf("\t3. the application was not compiled with nvcc flag sm_%u\n",forced_max_capability); + } } if(!g_cdp_enabled) { //based on the list above, dump ptx files individually. Format of dumped ptx file is prog_name.unique_no.sm_<>.ptx @@ -1520,15 +1526,10 @@ void extract_code_using_cuobjdump(){ snprintf(fname,1024,"_cuobjdump_complete_output_XXXXXX"); int fd=mkstemp(fname); close(fd); - if(!g_cdp_enabled) { -#if (CUDART_VERSION >= 6000) - snprintf(command,1000,"$CUDA_INSTALL_PATH/bin/cuobjdump -ptx -elf -sass -arch=sm_%u %s > %s", forced_max_capability, app_binary.c_str(), fname); -#else + if(!g_cdp_enabled) snprintf(command,1000,"$CUDA_INSTALL_PATH/bin/cuobjdump -ptx -elf -sass %s > %s", app_binary.c_str(), fname); -#endif - } else { + else snprintf(command,1000,"$CUDA_INSTALL_PATH/bin/cuobjdump -ptx -elf -sass -all %s > %s", app_binary.c_str(), fname); - } bool parse_output = true; result = system(command); if(result) { diff --git a/libcuda/cuda_runtime_api.cc~ b/libcuda/cuda_runtime_api.cc~ new file mode 100644 index 0000000..de7f5e9 --- /dev/null +++ b/libcuda/cuda_runtime_api.cc~ @@ -0,0 +1,2515 @@ +// This file created from cuda_runtime_api.h distributed with CUDA 1.1 +// Changes Copyright 2009, Tor M. Aamodt, Ali Bakhoda and George L. Yuan +// University of British Columbia + +/* + * cuda_runtime_api.cc + * + * Copyright © 2009 by Tor M. Aamodt, Wilson W. L. Fung, Ali Bakhoda, + * George L. Yuan and the University of British Columbia, Vancouver, + * BC V6T 1Z4, All Rights Reserved. + * + * THIS IS A LEGAL DOCUMENT BY DOWNLOADING GPGPU-SIM, YOU ARE AGREEING TO THESE + * TERMS AND CONDITIONS. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * NOTE: The files libcuda/cuda_runtime_api.c and src/cuda-sim/cuda-math.h + * are derived from the CUDA Toolset available from http://www.nvidia.com/cuda + * (property of NVIDIA). The files benchmarks/BlackScholes/ and + * benchmarks/template/ are derived from the CUDA SDK available from + * http://www.nvidia.com/cuda (also property of NVIDIA). The files from + * src/intersim/ are derived from Booksim (a simulator provided with the + * textbook "Principles and Practices of Interconnection Networks" available + * from http://cva.stanford.edu/books/ppin/). As such, those files are bound by + * the corresponding legal terms and conditions set forth separately (original + * copyright notices are left in files from these sources and where we have + * modified a file our copyright notice appears before the original copyright + * notice). + * + * Using this version of GPGPU-Sim requires a complete installation of CUDA + * which is distributed seperately by NVIDIA under separate terms and + * conditions. To use this version of GPGPU-Sim with OpenCL requires a + * recent version of NVIDIA's drivers which support OpenCL. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the University of British Columbia nor the names of + * its contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * 4. This version of GPGPU-SIM is distributed freely for non-commercial use only. + * + * 5. No nonprofit user may place any restrictions on the use of this software, + * including as modified by the user, by any other authorized user. + * + * 6. GPGPU-SIM was developed primarily by Tor M. Aamodt, Wilson W. L. Fung, + * Ali Bakhoda, George L. Yuan, at the University of British Columbia, + * Vancouver, BC V6T 1Z4 + */ + +/* + * Copyright 1993-2007 NVIDIA Corporation. All rights reserved. + * + * NOTICE TO USER: + * + * This source code is subject to NVIDIA ownership rights under U.S. and + * international Copyright laws. Users and possessors of this source code + * are hereby granted a nonexclusive, royalty-free license to use this code + * in individual and commercial software. + * + * NVIDIA MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOURCE + * CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR + * IMPLIED WARRANTY OF ANY KIND. NVIDIA DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOURCE CODE, INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE. + * IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL, + * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE + * OR PERFORMANCE OF THIS SOURCE CODE. + * + * U.S. Government End Users. This source code is a "commercial item" as + * that term is defined at 48 C.F.R. 2.101 (OCT 1995), consisting of + * "commercial computer software" and "commercial computer software + * documentation" as such terms are used in 48 C.F.R. 12.212 (SEPT 1995) + * and is provided to the U.S. Government only as a commercial end item. + * Consistent with 48 C.F.R.12.212 and 48 C.F.R. 227.7202-1 through + * 227.7202-4 (JUNE 1995), all U.S. Government End Users acquire the + * source code with only those rights set forth herein. + * + * Any use of this source code in individual and commercial software must + * include, in the user documentation and internal comments to the code, + * the above Disclaimer and U.S. Government End Users Notice. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> +#include <time.h> +#include <stdarg.h> +#include <iostream> +#include <string> +#include <regex> +#include <sstream> +#include <fstream> +#ifdef OPENGL_SUPPORT +#define GL_GLEXT_PROTOTYPES +#ifdef __APPLE__ +#include <GLUT/glut.h> // Apple's version of GLUT is here +#else +#include <GL/gl.h> +#endif +#endif + +#define __CUDA_RUNTIME_API_H__ + +#include "host_defines.h" +#include "builtin_types.h" +#include "driver_types.h" +#if (CUDART_VERSION < 8000) +#include "__cudaFatFormat.h" +#endif +#include "../src/gpgpu-sim/gpu-sim.h" +#include "../src/cuda-sim/ptx_loader.h" +#include "../src/cuda-sim/cuda-sim.h" +#include "../src/cuda-sim/ptx_ir.h" +#include "../src/cuda-sim/ptx_parser.h" +#include "../src/gpgpusim_entrypoint.h" +#include "../src/stream_manager.h" +#include "../src/abstract_hardware_model.h" + +#include <pthread.h> +#include <semaphore.h> + +#ifdef __APPLE__ +#include <mach-o/dyld.h> +#endif + +std::map<void *,void **> pinned_memory; //support for pinned memories added +std::map<void *, size_t> pinned_memory_size; +int no_of_ptx=0; + +extern void synchronize(); +extern void exit_simulation(); + +static int load_static_globals( symbol_table *symtab, unsigned min_gaddr, unsigned max_gaddr, gpgpu_t *gpu ); +static int load_constants( symbol_table *symtab, addr_t min_gaddr, gpgpu_t *gpu ); + +static kernel_info_t *gpgpu_cuda_ptx_sim_init_grid( const char *kernel_key, + gpgpu_ptx_sim_arg_list_t args, + struct dim3 gridDim, + struct dim3 blockDim, + struct CUctx_st* context ); + +/*DEVICE_BUILTIN*/ +struct cudaArray +{ + void *devPtr; + int devPtr32; + struct cudaChannelFormatDesc desc; + int width; + int height; + int size; //in bytes + unsigned dimensions; +}; + +#if !defined(__dv) +#if defined(__cplusplus) +#define __dv(v) \ + = v +#else /* __cplusplus */ +#define __dv(v) +#endif /* __cplusplus */ +#endif /* !__dv */ + +cudaError_t g_last_cudaError = cudaSuccess; + +extern stream_manager *g_stream_manager; + +void register_ptx_function( const char *name, function_info *impl ) +{ + // no longer need this +} + +#if defined __APPLE__ +# define __my_func__ __PRETTY_FUNCTION__ +#else +# if defined __cplusplus ? __GNUC_PREREQ (2, 6) : __GNUC_PREREQ (2, 4) +# define __my_func__ __PRETTY_FUNCTION__ +# else +# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L +# define __my_func__ __func__ +# else +# define __my_func__ ((__const char *) 0) +# endif +# endif +#endif + +struct _cuda_device_id { + _cuda_device_id(gpgpu_sim* gpu) {m_id = 0; m_next = NULL; m_gpgpu=gpu;} + struct _cuda_device_id *next() { return m_next; } + unsigned num_shader() const { return m_gpgpu->get_config().num_shader(); } + int num_devices() const { + if( m_next == NULL ) return 1; + else return 1 + m_next->num_devices(); + } + struct _cuda_device_id *get_device( unsigned n ) + { + assert( n < (unsigned)num_devices() ); + struct _cuda_device_id *p=this; + for(unsigned i=0; i<n; i++) + p = p->m_next; + return p; + } + const struct cudaDeviceProp *get_prop() const + { + return m_gpgpu->get_prop(); + } + unsigned get_id() const { return m_id; } + + gpgpu_sim *get_gpgpu() { return m_gpgpu; } +private: + unsigned m_id; + class gpgpu_sim *m_gpgpu; + struct _cuda_device_id *m_next; +}; + +struct CUctx_st { + CUctx_st( _cuda_device_id *gpu ) + { + m_gpu = gpu; + m_binary_info.cmem = 0; + m_binary_info.gmem = 0; + } + + _cuda_device_id *get_device() { return m_gpu; } + + void add_binary( symbol_table *symtab, unsigned fat_cubin_handle ) + { + m_code[fat_cubin_handle] = symtab; + m_last_fat_cubin_handle = fat_cubin_handle; + } + + void add_ptxinfo( const char *deviceFun, const struct gpgpu_ptx_sim_info &info ) + { + symbol *s = m_code[m_last_fat_cubin_handle]->lookup(deviceFun); + assert( s != NULL ); + function_info *f = s->get_pc(); + assert( f != NULL ); + f->set_kernel_info(info); + } + + void add_ptxinfo( const struct gpgpu_ptx_sim_info &info ) + { + m_binary_info = info; + } + + void register_function( unsigned fat_cubin_handle, const char *hostFun, const char *deviceFun ) + { + if( m_code.find(fat_cubin_handle) != m_code.end() ) { + symbol *s = m_code[fat_cubin_handle]->lookup(deviceFun); + if(s != NULL) { + function_info *f = s->get_pc(); + assert( f != NULL ); + m_kernel_lookup[hostFun] = f; + } + else { + printf("Warning: cannot find deviceFun %s\n", deviceFun); + m_kernel_lookup[hostFun] = NULL; + } + // assert( s != NULL ); + // function_info *f = s->get_pc(); + // assert( f != NULL ); + // m_kernel_lookup[hostFun] = f; + } else { + m_kernel_lookup[hostFun] = NULL; + } + } + + function_info *get_kernel(const char *hostFun) + { + std::map<const void*,function_info*>::iterator i=m_kernel_lookup.find(hostFun); + assert( i != m_kernel_lookup.end() ); + return i->second; + } + +private: + _cuda_device_id *m_gpu; // selected gpu + std::map<unsigned,symbol_table*> m_code; // fat binary handle => global symbol table + unsigned m_last_fat_cubin_handle; + std::map<const void*,function_info*> m_kernel_lookup; // unique id (CUDA app function address) => kernel entry point + struct gpgpu_ptx_sim_info m_binary_info; + +}; + +class kernel_config { +public: + kernel_config( dim3 GridDim, dim3 BlockDim, size_t sharedMem, struct CUstream_st *stream ) + { + m_GridDim=GridDim; + m_BlockDim=BlockDim; + m_sharedMem=sharedMem; + m_stream = stream; + } + void set_arg( const void *arg, size_t size, size_t offset ) + { + m_args.push_front( gpgpu_ptx_sim_arg(arg,size,offset) ); + } + dim3 grid_dim() const { return m_GridDim; } + dim3 block_dim() const { return m_BlockDim; } + gpgpu_ptx_sim_arg_list_t get_args() { return m_args; } + struct CUstream_st *get_stream() { return m_stream; } + +private: + dim3 m_GridDim; + dim3 m_BlockDim; + size_t m_sharedMem; + struct CUstream_st *m_stream; + gpgpu_ptx_sim_arg_list_t m_args; +}; + +class _cuda_device_id *GPGPUSim_Init() +{ + static _cuda_device_id *the_device = NULL; + if( !the_device ) { + gpgpu_sim *the_gpu = gpgpu_ptx_sim_init_perf(); + + cudaDeviceProp *prop = (cudaDeviceProp *) calloc(sizeof(cudaDeviceProp),1); + snprintf(prop->name,256,"GPGPU-Sim_v%s", g_gpgpusim_version_string ); + prop->major = 5; + prop->minor = 2; + prop->totalGlobalMem = 0x80000000 /* 2 GB */; + prop->memPitch = 0; + prop->maxThreadsPerBlock = 512; + prop->maxThreadsDim[0] = 512; + prop->maxThreadsDim[1] = 512; + prop->maxThreadsDim[2] = 512; + prop->maxGridSize[0] = 0x40000000; + prop->maxGridSize[1] = 0x40000000; + prop->maxGridSize[2] = 0x40000000; + prop->totalConstMem = 0x40000000; + prop->textureAlignment = 0; + prop->sharedMemPerBlock = the_gpu->shared_mem_size(); + prop->regsPerBlock = the_gpu->num_registers_per_core(); + prop->warpSize = the_gpu->wrp_size(); + prop->clockRate = the_gpu->shader_clock(); +#if (CUDART_VERSION >= 2010) + prop->multiProcessorCount = the_gpu->get_config().num_shader(); +#endif + the_gpu->set_prop(prop); + the_device = new _cuda_device_id(the_gpu); + } + start_sim_thread(1); + return the_device; +} + +static CUctx_st* GPGPUSim_Context() +{ + static CUctx_st *the_context = NULL; + if( the_context == NULL ) { + _cuda_device_id *the_gpu = GPGPUSim_Init(); + the_context = new CUctx_st(the_gpu); + } + return the_context; +} + + void ptxinfo_addinfo() +{ + if(!get_ptxinfo_kname()){ + /* This info is not per kernel (since CUDA 5.0 some info (e.g. gmem, and cmem) is added at the beginning for the whole binary ) */ + CUctx_st *context = GPGPUSim_Context(); + print_ptxinfo(); + context->add_ptxinfo(get_ptxinfo()); + clear_ptxinfo(); + return; + } + if( !strcmp("__cuda_dummy_entry__",get_ptxinfo_kname()) ) { + // this string produced by ptxas for empty ptx files (e.g., bandwidth test) + clear_ptxinfo(); + return; + } + CUctx_st *context = GPGPUSim_Context(); + print_ptxinfo(); + context->add_ptxinfo( get_ptxinfo_kname(), get_ptxinfo() ); + clear_ptxinfo(); +} + +void cuda_not_implemented( const char* func, unsigned line ) +{ + fflush(stdout); + fflush(stderr); + printf("\n\nGPGPU-Sim PTX: Execution error: CUDA API function \"%s()\" has not been implemented yet.\n" + " [$GPGPUSIM_ROOT/libcuda/%s around line %u]\n\n\n", + func,__FILE__, line ); + fflush(stdout); + abort(); +} + + +#define gpgpusim_ptx_error(msg, ...) gpgpusim_ptx_error_impl(__func__, __FILE__,__LINE__, msg, ##__VA_ARGS__) +#define gpgpusim_ptx_assert(cond,msg, ...) gpgpusim_ptx_assert_impl((cond),__func__, __FILE__,__LINE__, msg, ##__VA_ARGS__) + +void gpgpusim_ptx_error_impl( const char *func, const char *file, unsigned line, const char *msg, ... ) +{ + va_list ap; + char buf[1024]; + va_start(ap,msg); + vsnprintf(buf,1024,msg,ap); + va_end(ap); + + printf("GPGPU-Sim CUDA API: %s\n", buf); + printf(" [%s:%u : %s]\n", file, line, func ); + abort(); +} + +void gpgpusim_ptx_assert_impl( int test_value, const char *func, const char *file, unsigned line, const char *msg, ... ) +{ + va_list ap; + char buf[1024]; + va_start(ap,msg); + vsnprintf(buf,1024,msg,ap); + va_end(ap); + + if ( test_value == 0 ) + gpgpusim_ptx_error_impl(func, file, line, msg); +} + + +typedef std::map<unsigned,CUevent_st*> event_tracker_t; + +int CUevent_st::m_next_event_uid; +event_tracker_t g_timer_events; +int g_active_device = 0; //active gpu that runs the code +std::list<kernel_config> g_cuda_launch_stack; + +/******************************************************************************* + * * + * * + * * + *******************************************************************************/ + +extern "C" { + +/******************************************************************************* + * * + * * + * * + *******************************************************************************/ +cudaError_t cudaPeekAtLastError(void) +{ + return g_last_cudaError; +} + +__host__ cudaError_t CUDARTAPI cudaMalloc(void **devPtr, size_t size) +{ + CUctx_st* context = GPGPUSim_Context(); + *devPtr = context->get_device()->get_gpgpu()->gpu_malloc(size); + if(g_debug_execution >= 3) + printf("GPGPU-Sim PTX: cudaMallocing %zu bytes starting at 0x%llx..\n",size, (unsigned long long) *devPtr); + if ( *devPtr ) { + return g_last_cudaError = cudaSuccess; + } else { + return g_last_cudaError = cudaErrorMemoryAllocation; + } +} + +__host__ cudaError_t CUDARTAPI cudaMallocHost(void **ptr, size_t size) +{ + GPGPUSim_Context(); + *ptr = malloc(size); + if ( *ptr ) { + //track pinned memory size allocated in the host so that same amount of memory is also allocated in GPU. + pinned_memory_size[*ptr]=size; + return g_last_cudaError = cudaSuccess; + } else { + return g_last_cudaError = cudaErrorMemoryAllocation; + } +} +__host__ cudaError_t CUDARTAPI cudaMallocPitch(void **devPtr, size_t *pitch, size_t width, size_t height) +{ + unsigned malloc_width_inbytes = width; + printf("GPGPU-Sim PTX: cudaMallocPitch (width = %d)\n", malloc_width_inbytes); + CUctx_st* ctx = GPGPUSim_Context(); + *devPtr = ctx->get_device()->get_gpgpu()->gpu_malloc(malloc_width_inbytes*height); + pitch[0] = malloc_width_inbytes; + if ( *devPtr ) { + return g_last_cudaError = cudaSuccess; + } else { + return g_last_cudaError = cudaErrorMemoryAllocation; + } +} + +__host__ cudaError_t CUDARTAPI cudaMallocArray(struct cudaArray **array, const struct cudaChannelFormatDesc *desc, size_t width, size_t height __dv(1)) +{ + unsigned size = width * height * ((desc->x + desc->y + desc->z + desc->w)/8); + CUctx_st* context = GPGPUSim_Context(); + (*array) = (struct cudaArray*) malloc(sizeof(struct cudaArray)); + (*array)->desc = *desc; + (*array)->width = width; + (*array)->height = height; + (*array)->size = size; + (*array)->dimensions = 2; + ((*array)->devPtr32)= (int) (long long)context->get_device()->get_gpgpu()->gpu_mallocarray(size); + printf("GPGPU-Sim PTX: cudaMallocArray: devPtr32 = %d\n", ((*array)->devPtr32)); + ((*array)->devPtr) = (void*) (long long) ((*array)->devPtr32); + if ( ((*array)->devPtr) ) { + return g_last_cudaError = cudaSuccess; + } else { + return g_last_cudaError = cudaErrorMemoryAllocation; + } +} + +__host__ cudaError_t CUDARTAPI cudaFree(void *devPtr) +{ + // TODO... manage g_global_mem space? + return g_last_cudaError = cudaSuccess; +} +__host__ cudaError_t CUDARTAPI cudaFreeHost(void *ptr) +{ + free (ptr); // this will crash the system if called twice + return g_last_cudaError = cudaSuccess; +} + +__host__ cudaError_t CUDARTAPI cudaFreeArray(struct cudaArray *array) +{ + // TODO... manage g_global_mem space? + return g_last_cudaError = cudaSuccess; +}; + + +/******************************************************************************* + * * + * * + * * + *******************************************************************************/ + +__host__ cudaError_t CUDARTAPI cudaMemcpy(void *dst, const void *src, size_t count, enum cudaMemcpyKind kind) +{ + //CUctx_st *context = GPGPUSim_Context(); + //gpgpu_t *gpu = context->get_device()->get_gpgpu(); + if(g_debug_execution >= 3) + printf("GPGPU-Sim PTX: cudaMemcpy(): devPtr = %p\n", dst); + if( kind == cudaMemcpyHostToDevice ) + g_stream_manager->push( stream_operation(src,(size_t)dst,count,0) ); + else if( kind == cudaMemcpyDeviceToHost ) + g_stream_manager->push( stream_operation((size_t)src,dst,count,0) ); + else if( kind == cudaMemcpyDeviceToDevice ) + g_stream_manager->push( stream_operation((size_t)src,(size_t)dst,count,0) ); + else if ( kind == cudaMemcpyDefault ) { + if ((size_t)src >= GLOBAL_HEAP_START) { + if ((size_t)dst >= GLOBAL_HEAP_START) + g_stream_manager->push( stream_operation((size_t)src,(size_t)dst,count,0) ); // device to device + else + g_stream_manager->push( stream_operation((size_t)src,dst,count,0) ); // device to host + } + else { + if ((size_t)dst >= GLOBAL_HEAP_START) + g_stream_manager->push( stream_operation(src,(size_t)dst,count,0) ); + else { + printf("GPGPU-Sim PTX: cudaMemcpy - ERROR : unsupported transfer: host to host\n"); + abort(); + } + } + } + else { + printf("GPGPU-Sim PTX: cudaMemcpy - ERROR : unsupported cudaMemcpyKind\n"); + abort(); + } + return g_last_cudaError = cudaSuccess; +} + +__host__ cudaError_t CUDARTAPI cudaMemcpyToArray(struct cudaArray *dst, size_t wOffset, size_t hOffset, const void *src, size_t count, enum cudaMemcpyKind kind) +{ + CUctx_st *context = GPGPUSim_Context(); + gpgpu_t *gpu = context->get_device()->get_gpgpu(); + size_t size = count; + printf("GPGPU-Sim PTX: cudaMemcpyToArray\n"); + if( kind == cudaMemcpyHostToDevice ) + gpu->memcpy_to_gpu( (size_t)(dst->devPtr), src, size); + else if( kind == cudaMemcpyDeviceToHost ) + gpu->memcpy_from_gpu( dst->devPtr, (size_t)src, size); + else if( kind == cudaMemcpyDeviceToDevice ) + gpu->memcpy_gpu_to_gpu( (size_t)(dst->devPtr), (size_t)src, size); + else { + printf("GPGPU-Sim PTX: cudaMemcpyToArray - ERROR : unsupported cudaMemcpyKind\n"); + abort(); + } + dst->devPtr32 = (unsigned) (size_t)(dst->devPtr); + return g_last_cudaError = cudaSuccess; +} + + +__host__ cudaError_t CUDARTAPI cudaMemcpyFromArray(void *dst, const struct cudaArray *src, size_t wOffset, size_t hOffset, size_t count, enum cudaMemcpyKind kind) +{ + cuda_not_implemented(__my_func__,__LINE__); + return g_last_cudaError = cudaErrorUnknown; +} + + +__host__ cudaError_t CUDARTAPI cudaMemcpyArrayToArray(struct cudaArray *dst, size_t wOffsetDst, size_t hOffsetDst, const struct cudaArray *src, size_t wOffsetSrc, size_t hOffsetSrc, size_t count, enum cudaMemcpyKind kind __dv(cudaMemcpyDeviceToDevice)) +{ + cuda_not_implemented(__my_func__,__LINE__); + return g_last_cudaError = cudaErrorUnknown; +} + + +__host__ cudaError_t CUDARTAPI cudaMemcpy2D(void *dst, size_t dpitch, const void *src, size_t spitch, size_t width, size_t height, enum cudaMemcpyKind kind) +{ + CUctx_st *context = GPGPUSim_Context(); + gpgpu_t *gpu = context->get_device()->get_gpgpu(); + size_t size = spitch*height; + gpgpusim_ptx_assert( (dpitch==spitch), "different src and dst pitch not supported yet" ); + if( kind == cudaMemcpyHostToDevice ) + gpu->memcpy_to_gpu( (size_t)dst, src, size ); + else if( kind == cudaMemcpyDeviceToHost ) + gpu->memcpy_from_gpu( dst, (size_t)src, size ); + else if( kind == cudaMemcpyDeviceToDevice ) + gpu->memcpy_gpu_to_gpu( (size_t)dst, (size_t)src, size); + else { + printf("GPGPU-Sim PTX: cudaMemcpy2D - ERROR : unsupported cudaMemcpyKind\n"); + abort(); + } + return g_last_cudaError = cudaSuccess; +} + + +__host__ cudaError_t CUDARTAPI cudaMemcpy2DToArray(struct cudaArray *dst, size_t wOffset, size_t hOffset, const void *src, size_t spitch, size_t width, size_t height, enum cudaMemcpyKind kind) +{ + CUctx_st *context = GPGPUSim_Context(); + gpgpu_t *gpu = context->get_device()->get_gpgpu(); + size_t size = spitch*height; + size_t channel_size = dst->desc.w+dst->desc.x+dst->desc.y+dst->desc.z; + gpgpusim_ptx_assert( ((channel_size%8) == 0), "none byte multiple destination channel size not supported (sz=%u)", channel_size ); + unsigned elem_size = channel_size/8; + gpgpusim_ptx_assert( (dst->dimensions==2), "copy to none 2D array not supported" ); + gpgpusim_ptx_assert( (wOffset==0), "non-zero wOffset not yet supported" ); + gpgpusim_ptx_assert( (hOffset==0), "non-zero hOffset not yet supported" ); + gpgpusim_ptx_assert( (dst->height == (int)height), "partial copy not supported" ); + gpgpusim_ptx_assert( (elem_size*dst->width == width), "partial copy not supported" ); + gpgpusim_ptx_assert( (spitch == width), "spitch != width not supported" ); + if( kind == cudaMemcpyHostToDevice ) + gpu->memcpy_to_gpu( (size_t)(dst->devPtr), src, size); + else if( kind == cudaMemcpyDeviceToHost ) + gpu->memcpy_from_gpu( dst->devPtr, (size_t)src, size); + else if( kind == cudaMemcpyDeviceToDevice ) + gpu->memcpy_gpu_to_gpu( (size_t)dst->devPtr, (size_t)src, size); + else { + printf("GPGPU-Sim PTX: cudaMemcpy2D - ERROR : unsupported cudaMemcpyKind\n"); + abort(); + } + dst->devPtr32 = (unsigned) (size_t)(dst->devPtr); + return g_last_cudaError = cudaSuccess; +} + + +__host__ cudaError_t CUDARTAPI cudaMemcpy2DFromArray(void *dst, size_t dpitch, const struct cudaArray *src, size_t wOffset, size_t hOffset, size_t width, size_t height, enum cudaMemcpyKind kind) +{ + cuda_not_implemented(__my_func__,__LINE__); + return g_last_cudaError = cudaErrorUnknown; +} + + +__host__ cudaError_t CUDARTAPI cudaMemcpy2DArrayToArray(struct cudaArray *dst, size_t wOffsetDst, size_t hOffsetDst, const struct cudaArray *src, size_t wOffsetSrc, size_t hOffsetSrc, size_t width, size_t height, enum cudaMemcpyKind kind __dv(cudaMemcpyDeviceToDevice)) +{ + cuda_not_implemented(__my_func__,__LINE__); + return g_last_cudaError = cudaErrorUnknown; +} + + +__host__ cudaError_t CUDARTAPI cudaMemcpyToSymbol(const char *symbol, const void *src, size_t count, size_t offset __dv(0), enum cudaMemcpyKind kind __dv(cudaMemcpyHostToDevice)) +{ + //CUctx_st *context = GPGPUSim_Context(); + assert(kind == cudaMemcpyHostToDevice); + printf("GPGPU-Sim PTX: cudaMemcpyToSymbol: symbol = %p\n", symbol); + //stream_operation( const char *symbol, const void *src, size_t count, size_t offset ) + g_stream_manager->push( stream_operation(src,symbol,count,offset,0) ); + //gpgpu_ptx_sim_memcpy_symbol(symbol,src,count,offset,1,context->get_device()->get_gpgpu()); + return g_last_cudaError = cudaSuccess; +} + + +__host__ cudaError_t CUDARTAPI cudaMemcpyFromSymbol(void *dst, const char *symbol, size_t count, size_t offset __dv(0), enum cudaMemcpyKind kind __dv(cudaMemcpyDeviceToHost)) +{ + //CUctx_st *context = GPGPUSim_Context(); + assert(kind == cudaMemcpyDeviceToHost); + printf("GPGPU-Sim PTX: cudaMemcpyFromSymbol: symbol = %p\n", symbol); + g_stream_manager->push( stream_operation(symbol,dst,count,offset,0) ); + //gpgpu_ptx_sim_memcpy_symbol(symbol,dst,count,offset,0,context->get_device()->get_gpgpu()); + return g_last_cudaError = cudaSuccess; +} + + + +/******************************************************************************* + * * + * * + * * + *******************************************************************************/ + +__host__ cudaError_t CUDARTAPI cudaMemcpyAsync(void *dst, const void *src, size_t count, enum cudaMemcpyKind kind, cudaStream_t stream) +{ + struct CUstream_st *s = (struct CUstream_st *)stream; + switch( kind ) { + case cudaMemcpyHostToDevice: g_stream_manager->push( stream_operation(src,(size_t)dst,count,s) ); break; + case cudaMemcpyDeviceToHost: g_stream_manager->push( stream_operation((size_t)src,dst,count,s) ); break; + case cudaMemcpyDeviceToDevice: g_stream_manager->push( stream_operation((size_t)src,(size_t)dst,count,s) ); break; + default: + abort(); + } + return g_last_cudaError = cudaSuccess; +} + + +__host__ cudaError_t CUDARTAPI cudaMemcpyToArrayAsync(struct cudaArray *dst, size_t wOffset, size_t hOffset, const void *src, size_t count, enum cudaMemcpyKind kind, cudaStream_t stream) +{ + cuda_not_implemented(__my_func__,__LINE__); + return g_last_cudaError = cudaErrorUnknown; +} + + +__host__ cudaError_t CUDARTAPI cudaMemcpyFromArrayAsync(void *dst, const struct cudaArray *src, size_t wOffset, size_t hOffset, size_t count, enum cudaMemcpyKind kind, cudaStream_t stream) +{ + cuda_not_implemented(__my_func__,__LINE__); + return g_last_cudaError = cudaErrorUnknown; +} + + +__host__ cudaError_t CUDARTAPI cudaMemcpy2DAsync(void *dst, size_t dpitch, const void *src, size_t spitch, size_t width, size_t height, enum cudaMemcpyKind kind, cudaStream_t stream) +{ + cuda_not_implemented(__my_func__,__LINE__); + return g_last_cudaError = cudaErrorUnknown; +} + + +__host__ cudaError_t CUDARTAPI cudaMemcpy2DToArrayAsync(struct cudaArray *dst, size_t wOffset, size_t hOffset, const void *src, size_t spitch, size_t width, size_t height, enum cudaMemcpyKind kind, cudaStream_t stream) +{ + cuda_not_implemented(__my_func__,__LINE__); + return g_last_cudaError = cudaErrorUnknown; +} + + +__host__ cudaError_t CUDARTAPI cudaMemcpy2DFromArrayAsync(void *dst, size_t dpitch, const struct cudaArray *src, size_t wOffset, size_t hOffset, size_t width, size_t height, enum cudaMemcpyKind kind, cudaStream_t stream) +{ + cuda_not_implemented(__my_func__,__LINE__); + return g_last_cudaError = cudaErrorUnknown; +} + + + +/******************************************************************************* + * * + * * + * * + *******************************************************************************/ + +__host__ cudaError_t CUDARTAPI cudaMemset(void *mem, int c, size_t count) +{ + CUctx_st *context = GPGPUSim_Context(); + gpgpu_t *gpu = context->get_device()->get_gpgpu(); + gpu->gpu_memset((size_t)mem, c, count); + return g_last_cudaError = cudaSuccess; +} + +//memset operation is done but i think its not async? +__host__ cudaError_t CUDARTAPI cudaMemsetAsync(void *mem, int c, size_t count, cudaStream_t stream=0) +{ + printf("GPGPU-Sim PTX: WARNING: Asynchronous memset not supported (%s)\n", __my_func__); + CUctx_st *context = GPGPUSim_Context(); + gpgpu_t *gpu = context->get_device()->get_gpgpu(); + gpu->gpu_memset((size_t)mem, c, count); + return g_last_cudaError = cudaSuccess; +} + +__host__ cudaError_t CUDARTAPI cudaMemset2D(void *mem, size_t pitch, int c, size_t width, size_t height) +{ + cuda_not_implemented(__my_func__,__LINE__); + return g_last_cudaError = cudaErrorUnknown; +} + + + +/******************************************************************************* + * * + * * + * * + *******************************************************************************/ + +__host__ cudaError_t CUDARTAPI cudaGetSymbolAddress(void **devPtr, const char *symbol) +{ + cuda_not_implemented(__my_func__,__LINE__); + return g_last_cudaError = cudaErrorUnknown; +} + + +__host__ cudaError_t CUDARTAPI cudaGetSymbolSize(size_t *size, const char *symbol) +{ + cuda_not_implemented(__my_func__,__LINE__); + return g_last_cudaError = cudaErrorUnknown; +} + + + +/******************************************************************************* + * * + * * + * * + *******************************************************************************/ +__host__ cudaError_t CUDARTAPI cudaGetDeviceCount(int *count) +{ + _cuda_device_id *dev = GPGPUSim_Init(); + *count = dev->num_devices(); + return g_last_cudaError = cudaSuccess; +} + +__host__ cudaError_t CUDARTAPI cudaGetDeviceProperties(struct cudaDeviceProp *prop, int device) +{ + _cuda_device_id *dev = GPGPUSim_Init(); + if (device <= dev->num_devices() ) { + *prop= *dev->get_prop(); + return g_last_cudaError = cudaSuccess; + } else { + return g_last_cudaError = cudaErrorInvalidDevice; + } +} + +#if (CUDART_VERSION > 5000) +__host__ cudaError_t CUDARTAPI cudaDeviceGetAttribute(int *value, enum cudaDeviceAttr attr, int device) +{ + const struct cudaDeviceProp *prop; + _cuda_device_id *dev = GPGPUSim_Init(); + if (device <= dev->num_devices() ) { + prop = dev->get_prop(); + switch (attr) { + case 5: + *value= prop->maxGridSize[0]; + break; + case 6: + *value= prop->maxGridSize[1]; + break; + case 7: + *value= prop->maxGridSize[2]; + break; + case 10: + *value= prop->warpSize; + break; + case 12: + *value= prop->regsPerBlock; + break; + case 14: + *value= prop->textureAlignment ; + break; + case 16: + *value= prop->multiProcessorCount ; + break; + case 39: + *value= dev->get_gpgpu()->threads_per_core(); + break; + case 75: + *value= 8 ; + break; + case 76: + *value= 3 ; + break; + case 78: + *value= 0 ; //TODO: as of now, we dont support stream priorities. + break; + default: + printf("ERROR: implement the attribute numbered %d \n",attr); + abort(); + } + return g_last_cudaError = cudaSuccess; + } else { + return g_last_cudaError = cudaErrorInvalidDevice; + } +} +#endif + +__host__ cudaError_t CUDARTAPI cudaChooseDevice(int *device, const struct cudaDeviceProp *prop) +{ + _cuda_device_id *dev = GPGPUSim_Init(); + *device = dev->get_id(); + return g_last_cudaError = cudaSuccess; +} + +__host__ cudaError_t CUDARTAPI cudaSetDevice(int device) +{ + //set the active device to run cuda + if ( device <= GPGPUSim_Init()->num_devices() ) { + g_active_device = device; + return g_last_cudaError = cudaSuccess; + } else { + return g_last_cudaError = cudaErrorInvalidDevice; + } +} + +__host__ cudaError_t CUDARTAPI cudaGetDevice(int *device) +{ + *device = g_active_device; + return g_last_cudaError = cudaSuccess; +} + + +/******************************************************************************* + * * + * * + * * + *******************************************************************************/ + +__host__ cudaError_t CUDARTAPI cudaBindTexture(size_t *offset, + const struct textureReference *texref, + const void *devPtr, + const struct cudaChannelFormatDesc *desc, + size_t size __dv(UINT_MAX)) +{ + CUctx_st *context = GPGPUSim_Context(); + gpgpu_t *gpu = context->get_device()->get_gpgpu(); + printf("GPGPU-Sim PTX: in cudaBindTexture: sizeof(struct textureReference) = %zu\n", sizeof(struct textureReference)); + struct cudaArray *array; + array = (struct cudaArray*) malloc(sizeof(struct cudaArray)); + array->desc = *desc; + array->size = size; + array->width = size; + array->height = 1; + array->dimensions = 1; + array->devPtr = (void*)devPtr; + array->devPtr32 = (int)(long long)devPtr; + offset = 0; + printf("GPGPU-Sim PTX: size = %zu\n", size); + printf("GPGPU-Sim PTX: texref = %p, array = %p\n", texref, array); + printf("GPGPU-Sim PTX: devPtr32 = %x\n", array->devPtr32); + printf("GPGPU-Sim PTX: Name corresponding to textureReference: %s\n", gpu->gpgpu_ptx_sim_findNamefromTexture(texref)); + printf("GPGPU-Sim PTX: ChannelFormatDesc: x=%d, y=%d, z=%d, w=%d\n", desc->x, desc->y, desc->z, desc->w); + printf("GPGPU-Sim PTX: Texture Normalized? = %d\n", texref->normalized); + gpu->gpgpu_ptx_sim_bindTextureToArray(texref, array); + devPtr = (void*)(long long)array->devPtr32; + printf("GPGPU-Sim PTX: devPtr = %p\n", devPtr); + return g_last_cudaError = cudaSuccess; +} + + +__host__ cudaError_t CUDARTAPI cudaBindTextureToArray(const struct textureReference *texref, const struct cudaArray *array, const struct cudaChannelFormatDesc *desc) +{ + CUctx_st *context = GPGPUSim_Context(); + gpgpu_t *gpu = context->get_device()->get_gpgpu(); + printf("GPGPU-Sim PTX: in cudaBindTextureToArray: %p %p\n", texref, array); + printf("GPGPU-Sim PTX: devPtr32 = %x\n", array->devPtr32); + printf("GPGPU-Sim PTX: Name corresponding to textureReference: %s\n", gpu->gpgpu_ptx_sim_findNamefromTexture(texref)); + printf("GPGPU-Sim PTX: Texture Normalized? = %d\n", texref->normalized); + gpu->gpgpu_ptx_sim_bindTextureToArray(texref, array); + return g_last_cudaError = cudaSuccess; +} + +__host__ cudaError_t CUDARTAPI cudaUnbindTexture(const struct textureReference *texref) +{ + return g_last_cudaError = cudaSuccess; +} + +__host__ cudaError_t CUDARTAPI cudaGetTextureAlignmentOffset(size_t *offset, const struct textureReference *texref) +{ + cuda_not_implemented(__my_func__,__LINE__); + return g_last_cudaError = cudaErrorUnknown; +} + +__host__ cudaError_t CUDARTAPI cudaGetTextureReference(const struct textureReference **texref, const char *symbol) +{ + cuda_not_implemented(__my_func__,__LINE__); + return g_last_cudaError = cudaErrorUnknown; +} + +__host__ cudaError_t CUDARTAPI cudaGetChannelDesc(struct cudaChannelFormatDesc *desc, const struct cudaArray *array) +{ + *desc = array->desc; + return g_last_cudaError = cudaSuccess; +} + + +__host__ struct cudaChannelFormatDesc CUDARTAPI cudaCreateChannelDesc(int x, int y, int z, int w, enum cudaChannelFormatKind f) +{ + struct cudaChannelFormatDesc dummy; + dummy.x = x; + dummy.y = y; + dummy.z = z; + dummy.w = w; + dummy.f = f; + return dummy; +} + +__host__ cudaError_t CUDARTAPI cudaGetLastError(void) +{ + return g_last_cudaError; +} + +__host__ const char* CUDARTAPI cudaGetErrorString(cudaError_t error) +{ + if( g_last_cudaError == cudaSuccess ) + return "no error"; + char buf[1024]; + snprintf(buf,1024,"<<GPGPU-Sim PTX: there was an error (code = %d)>>", g_last_cudaError); + return strdup(buf); +} + +__host__ cudaError_t CUDARTAPI cudaConfigureCall(dim3 gridDim, dim3 blockDim, size_t sharedMem, cudaStream_t stream) +{ + struct CUstream_st *s = (struct CUstream_st *)stream; + g_cuda_launch_stack.push_back( kernel_config(gridDim,blockDim,sharedMem,s) ); + return g_last_cudaError = cudaSuccess; +} + +__host__ cudaError_t CUDARTAPI cudaSetupArgument(const void *arg, size_t size, size_t offset) +{ + gpgpusim_ptx_assert( !g_cuda_launch_stack.empty(), "empty launch stack" ); + kernel_config &config = g_cuda_launch_stack.back(); + config.set_arg(arg,size,offset); + + return g_last_cudaError = cudaSuccess; +} + + +__host__ cudaError_t CUDARTAPI cudaLaunch( const char *hostFun ) +{ + CUctx_st* context = GPGPUSim_Context(); + char *mode = getenv("PTX_SIM_MODE_FUNC"); + if( mode ) + sscanf(mode,"%u", &g_ptx_sim_mode); + gpgpusim_ptx_assert( !g_cuda_launch_stack.empty(), "empty launch stack" ); + kernel_config config = g_cuda_launch_stack.back(); + struct CUstream_st *stream = config.get_stream(); + printf("\nGPGPU-Sim PTX: cudaLaunch for 0x%p (mode=%s) on stream %u\n", hostFun, + g_ptx_sim_mode?"functional simulation":"performance simulation", stream?stream->get_uid():0 ); + kernel_info_t *grid = gpgpu_cuda_ptx_sim_init_grid(hostFun,config.get_args(),config.grid_dim(),config.block_dim(),context); + //do dynamic PDOM analysis for performance simulation scenario + std::string kname = grid->name(); + function_info *kernel_func_info = grid->entry(); + if (kernel_func_info->is_pdom_set()) { + printf("GPGPU-Sim PTX: PDOM analysis already done for %s \n", kname.c_str() ); + } else { + printf("GPGPU-Sim PTX: finding reconvergence points for \'%s\'...\n", kname.c_str() ); + kernel_func_info->do_pdom(); + kernel_func_info->set_pdom(); + } + dim3 gridDim = config.grid_dim(); + dim3 blockDim = config.block_dim(); + printf("GPGPU-Sim PTX: pushing kernel \'%s\' to stream %u, gridDim= (%u,%u,%u) blockDim = (%u,%u,%u) \n", + kname.c_str(), stream?stream->get_uid():0, gridDim.x,gridDim.y,gridDim.z,blockDim.x,blockDim.y,blockDim.z ); + stream_operation op(grid,g_ptx_sim_mode,stream); + g_stream_manager->push(op); + g_cuda_launch_stack.pop_back(); + return g_last_cudaError = cudaSuccess; +} + +/******************************************************************************* + * * + * * + * * + *******************************************************************************/ + +__host__ cudaError_t CUDARTAPI cudaStreamCreate(cudaStream_t *stream) +{ + printf("GPGPU-Sim PTX: cudaStreamCreate\n"); +#if (CUDART_VERSION >= 3000) + *stream = new struct CUstream_st(); + g_stream_manager->add_stream(*stream); +#else + *stream = 0; + printf("GPGPU-Sim PTX: WARNING: Asynchronous kernel execution not supported (%s)\n", __my_func__); +#endif + return g_last_cudaError = cudaSuccess; +} + +//TODO: introduce priorities +__host__ cudaError_t CUDARTAPI cudaStreamCreateWithPriority(cudaStream_t *stream, unsigned int flags, int priority) { + return cudaStreamCreate(stream); +} + +__host__ cudaError_t CUDARTAPI cudaDeviceGetStreamPriorityRange(int* leastPriority, int* greatestPriority) { + return cudaSuccess; +} + +__host__ __device__ cudaError_t CUDARTAPI cudaStreamCreateWithFlags(cudaStream_t *pStream, unsigned int flags) { + return cudaStreamCreate(pStream); +} + +__host__ cudaError_t CUDARTAPI cudaStreamDestroy(cudaStream_t stream) +{ +#if (CUDART_VERSION >= 3000) + g_stream_manager->destroy_stream(stream); +#endif + return g_last_cudaError = cudaSuccess; +} + +__host__ cudaError_t CUDARTAPI cudaStreamSynchronize(cudaStream_t stream) +{ +#if (CUDART_VERSION >= 3000) + if( stream == NULL ) + synchronize(); + return g_last_cudaError = cudaSuccess; + stream->synchronize(); +#else + printf("GPGPU-Sim PTX: WARNING: Asynchronous kernel execution not supported (%s)\n", __my_func__); +#endif + return g_last_cudaError = cudaSuccess; +} + +__host__ cudaError_t CUDARTAPI cudaStreamQuery(cudaStream_t stream) +{ +#if (CUDART_VERSION >= 3000) + if( stream == NULL ) + return g_last_cudaError = cudaErrorInvalidResourceHandle; + return g_last_cudaError = stream->empty()?cudaSuccess:cudaErrorNotReady; +#else + printf("GPGPU-Sim PTX: WARNING: Asynchronous kernel execution not supported (%s)\n", __my_func__); + return g_last_cudaError = cudaSuccess; // it is always success because all cuda calls are synchronous +#endif +} + +/******************************************************************************* + * * + * * + * * + *******************************************************************************/ + +__host__ cudaError_t CUDARTAPI cudaEventCreate(cudaEvent_t *event) +{ + CUevent_st *e = new CUevent_st(false); + g_timer_events[e->get_uid()] = e; +#if CUDART_VERSION >= 3000 + *event = e; +#else + *event = e->get_uid(); +#endif + return g_last_cudaError = cudaSuccess; +} + +CUevent_st *get_event(cudaEvent_t event) +{ + unsigned event_uid; +#if CUDART_VERSION >= 3000 + event_uid = event->get_uid(); +#else + event_uid = event; +#endif + event_tracker_t::iterator e = g_timer_events.find(event_uid); + if( e == g_timer_events.end() ) + return NULL; + return e->second; +} + +__host__ cudaError_t CUDARTAPI cudaEventRecord(cudaEvent_t event, cudaStream_t stream) +{ + CUevent_st *e = get_event(event); + if( !e ) return g_last_cudaError = cudaErrorUnknown; + struct CUstream_st *s = (struct CUstream_st *)stream; + stream_operation op(e,s); + g_stream_manager->push(op); + return g_last_cudaError = cudaSuccess; +} + +__host__ cudaError_t CUDARTAPI cudaEventQuery(cudaEvent_t event) +{ + CUevent_st *e = get_event(event); + if( e == NULL ) { + return g_last_cudaError = cudaErrorInvalidValue; + } else if( e->done() ) { + return g_last_cudaError = cudaSuccess; + } else { + return g_last_cudaError = cudaErrorNotReady; + } +} + +__host__ cudaError_t CUDARTAPI cudaEventSynchronize(cudaEvent_t event) +{ + printf("GPGPU-Sim API: cudaEventSynchronize ** waiting for event\n"); + fflush(stdout); + CUevent_st *e = (CUevent_st*) event; + while( !e->done() ) + ; + printf("GPGPU-Sim API: cudaEventSynchronize ** event detected\n"); + fflush(stdout); + return g_last_cudaError = cudaSuccess; +} + +__host__ cudaError_t CUDARTAPI cudaEventDestroy(cudaEvent_t event) +{ + CUevent_st *e = get_event(event); + unsigned event_uid = e->get_uid(); + event_tracker_t::iterator pe = g_timer_events.find(event_uid); + if( pe == g_timer_events.end() ) + return g_last_cudaError = cudaErrorInvalidValue; + g_timer_events.erase(pe); + return g_last_cudaError = cudaSuccess; +} + + +__host__ cudaError_t CUDARTAPI cudaEventElapsedTime(float *ms, cudaEvent_t start, cudaEvent_t end) +{ + time_t elapsed_time; + CUevent_st *s = get_event(start); + CUevent_st *e = get_event(end); + if( s==NULL || e==NULL ) + return g_last_cudaError = cudaErrorUnknown; + elapsed_time = e->clock() - s->clock(); + *ms = 1000*elapsed_time; + return g_last_cudaError = cudaSuccess; +} + + + +/******************************************************************************* + * * + * * + * * + *******************************************************************************/ + +__host__ cudaError_t CUDARTAPI cudaThreadExit(void) +{ + exit_simulation(); + return g_last_cudaError = cudaSuccess; +} + +__host__ cudaError_t CUDARTAPI cudaThreadSynchronize(void) +{ + //Called on host side + synchronize(); + return g_last_cudaError = cudaSuccess; +}; + +int CUDARTAPI __cudaSynchronizeThreads(void**, void*) +{ + return cudaThreadExit(); +} + + + +/******************************************************************************* + * * + * * + * * + *******************************************************************************/ + +#if (CUDART_VERSION >= 3010) + +typedef struct CUuuid_st { /**< CUDA definition of UUID */ + char bytes[16]; +} CUuuid; + +/** + * CUDA UUID types + */ +// typedef __device_builtin__ struct CUuuid_st cudaUUID_t; + +__host__ cudaError_t CUDARTAPI cudaGetExportTable(const void **ppExportTable, const cudaUUID_t *pExportTableId) +{ + printf("cudaGetExportTable: UUID = "); + for (int s = 0; s < 16; s++) { + printf("%#2x ", (unsigned char) (pExportTableId->bytes[s])); + } + printf("\n"); + return g_last_cudaError = cudaSuccess; +} + +#endif + + +/******************************************************************************* + * * + * * + * * + *******************************************************************************/ + +//#include "../../cuobjdump_to_ptxplus/cuobjdump_parser.h" + +enum cuobjdumpSectionType { + PTXSECTION=0, + ELFSECTION +}; + + +class cuobjdumpSection { +public: + //Constructor + cuobjdumpSection() { + arch = 0; + identifier = ""; + } + virtual ~cuobjdumpSection() {} + unsigned getArch() {return arch;} + void setArch(unsigned a) {arch = a;} + std::string getIdentifier() {return identifier;} + void setIdentifier(std::string i) {identifier = i;} + virtual void print(){std::cout << "cuobjdump Section: unknown type" << std::endl;} +private: + unsigned arch; + std::string identifier; +}; + +class cuobjdumpELFSection : public cuobjdumpSection +{ +public: + cuobjdumpELFSection() {} + virtual ~cuobjdumpELFSection() { + elffilename = ""; + sassfilename = ""; + } + std::string getELFfilename() {return elffilename;} + void setELFfilename(std::string f) {elffilename = f;} + std::string getSASSfilename() {return sassfilename;} + void setSASSfilename(std::string f) {sassfilename = f;} + virtual void print() { + std::cout << "ELF Section:" << std::endl; + std::cout << "arch: sm_" << getArch() << std::endl; + std::cout << "identifier: " << getIdentifier() << std::endl; + std::cout << "elf filename: " << getELFfilename() << std::endl; + std::cout << "sass filename: " << getSASSfilename() << std::endl; + std::cout << std::endl; + } +private: + std::string elffilename; + std::string sassfilename; +}; + +class cuobjdumpPTXSection : public cuobjdumpSection +{ +public: + cuobjdumpPTXSection(){ + ptxfilename = ""; + } + std::string getPTXfilename() {return ptxfilename;} + void setPTXfilename(std::string f) {ptxfilename = f;} + virtual void print() { + std::cout << "PTX Section:" << std::endl; + std::cout << "arch: sm_" << getArch() << std::endl; + std::cout << "identifier: " << getIdentifier() << std::endl; + std::cout << "ptx filename: " << getPTXfilename() << std::endl; + std::cout << std::endl; + } +private: + std::string ptxfilename; +}; + +std::list<cuobjdumpSection*> cuobjdumpSectionList; +std::list<cuobjdumpSection*> libSectionList; + +// sectiontype: 0 for ptx, 1 for elf +void addCuobjdumpSection(int sectiontype){ + if (sectiontype) + cuobjdumpSectionList.push_front(new cuobjdumpELFSection()); + else + cuobjdumpSectionList.push_front(new cuobjdumpPTXSection()); + printf("## Adding new section %s\n", sectiontype?"ELF":"PTX"); +} + +void setCuobjdumparch(const char* arch){ + unsigned archnum; + sscanf(arch, "sm_%u", &archnum); + assert (archnum && "cannot have sm_0"); + printf("Adding arch: %s\n", arch); + cuobjdumpSectionList.front()->setArch(archnum); +} + +void setCuobjdumpidentifier(const char* identifier){ + printf("Adding identifier: %s\n", identifier); + cuobjdumpSectionList.front()->setIdentifier(identifier); +} + +void setCuobjdumpptxfilename(const char* filename){ + printf("Adding ptx filename: %s\n", filename); + cuobjdumpSection* x = cuobjdumpSectionList.front(); + if (dynamic_cast<cuobjdumpPTXSection*>(x) == NULL){ + assert (0 && "You shouldn't be trying to add a ptxfilename to an elf section"); + } + (dynamic_cast<cuobjdumpPTXSection*>(x))->setPTXfilename(filename); +} + +void setCuobjdumpelffilename(const char* filename){ + if (dynamic_cast<cuobjdumpELFSection*>(cuobjdumpSectionList.front()) == NULL){ + assert (0 && "You shouldn't be trying to add a elffilename to an ptx section"); + } + (dynamic_cast<cuobjdumpELFSection*>(cuobjdumpSectionList.front()))->setELFfilename(filename); +} + +void setCuobjdumpsassfilename(const char* filename){ + if (dynamic_cast<cuobjdumpELFSection*>(cuobjdumpSectionList.front()) == NULL){ + assert (0 && "You shouldn't be trying to add a sassfilename to an ptx section"); + } + (dynamic_cast<cuobjdumpELFSection*>(cuobjdumpSectionList.front()))->setSASSfilename(filename); +} +extern int cuobjdump_parse(); +extern FILE *cuobjdump_in; + +//! Return the executable file of the process containing the PTX/SASS code +//! +//! This Function returns the executable file ran by the process. This +//! executable is supposed to contain the PTX/SASS code. It provides workaround +//! for processes running on valgrind by dereferencing /proc/<pid>/exe within the +//! GPGPU-Sim process before calling cuobjdump to extract PTX/SASS. This is +//! needed because valgrind uses x86 emulation to detect memory leak. Other +//! processes (e.g. cuobjdump) reading /proc/<pid>/exe will see the emulator +//! executable instead of the application binary. +//! +std::string get_app_binary(){ + char self_exe_path[1025]; +#ifdef __APPLE__ + uint32_t size = sizeof(self_exe_path); + if( _NSGetExecutablePath(self_exe_path,&size) != 0 ) { + printf("GPGPU-Sim ** ERROR: _NSGetExecutablePath input buffer too small\n"); + exit(1); + } +#else + std::stringstream exec_link; + exec_link << "/proc/self/exe"; + + ssize_t path_length = readlink(exec_link.str().c_str(), self_exe_path, 1024); + assert(path_length != -1); + self_exe_path[path_length] = '\0'; +#endif + + printf("self exe links to: %s\n", self_exe_path); + return self_exe_path; +} + +//above func gives abs path whereas this give just the name of application. +char* get_app_binary_name(std::string abs_path){ + char *self_exe_path; +#ifdef __APPLE__ + //TODO: get apple device and check the result. + printf("WARNING: not tested for Apple-mac devices \n"); + abort(); +#else + char* buf = strdup(abs_path.c_str()); + char *token = strtok(buf, "/"); + while(token !=NULL){ + self_exe_path = token; + token = strtok(NULL,"/"); + } +#endif + self_exe_path = strtok(self_exe_path, "."); + printf("self exe links to: %s\n", self_exe_path); + return self_exe_path; +} + +//! Call cuobjdump to extract everything (-elf -sass -ptx) +/*! + * This Function extract the whole PTX (for all the files) using cuobjdump + * to _cuobjdump_complete_output_XXXXXX then runs a parser to chop it up with each binary in + * its own file + * It is also responsible for extracting the libraries linked to the binary if the option is + * enabled + * */ +void extract_code_using_cuobjdump(){ + CUctx_st *context = GPGPUSim_Context(); + unsigned forced_max_capability = context->get_device()->get_gpgpu()->get_config().get_forced_max_capability(); + + //prevent the dumping by cuobjdump everytime we execute the code! + const char *override_cuobjdump = getenv("CUOBJDUMP_SIM_FILE"); + char command[1000], ptx_file[1000]; + std::string app_binary = get_app_binary(); + //Running cuobjdump using dynamic link to current process + snprintf(command,1000,"md5sum %s ", app_binary.c_str()); + printf("Running md5sum using \"%s\"\n", command); + system(command); + // Running cuobjdump using dynamic link to current process + // Needs the option '-all' to extract PTX from CDP-enabled binary + extern bool g_cdp_enabled; + + //dump ptx for all individial ptx files into sepearte files which is later used by ptxas. + int result=0; +#if (CUDART_VERSION >= 6000) + char fname2[1024]; + snprintf(fname2,1024,"_cuobjdump_list_ptx_XXXXXX"); + int fd2=mkstemp(fname2); + close(fd2); + snprintf(command,1000,"$CUDA_INSTALL_PATH/bin/cuobjdump -lptx -arch=sm_%u %s > %s", forced_max_capability, app_binary.c_str(), fname2); + result = system(command); + if( result != 0 ) { + printf("WARNING: Failed to execute cuobjdump to get list of ptx files \n"); + exit(0); + } else { + /* + as we got list of ptx files, we need to extract one by one into seperate files so that ptxas can understand it. + In this way, the duplicate definitions in a single embedded file can be prevented. + No of lines in the file is equal to no of ptx fileis available. + */ + FILE *fp = fopen(fname2,"r"); + if (fp==NULL) { + printf("WARNING: cuobjdump file error! Could not open file %s \n", fname2); + exit(0); + } else { + for (char c = getc(fp); c != EOF; c = getc(fp)) + if (c == '\n') + no_of_ptx = no_of_ptx + 1; + fclose(fp); + } + if(no_of_ptx==0){ + printf("WARNING: Number of ptx in the executable file are 0. One of the reasons might be\n"); + printf("\t1. CDP is enabled\n"); + printf("\t2. cuobjdump -lptx doesnt recognize sm_%u\n",forced_max_capability); + printf("\t3. the application was not compiled iwth nvcc flag sm_%u\n",forced_max_capability); + } + } + if(!g_cdp_enabled) { + //based on the list above, dump ptx files individually. Format of dumped ptx file is prog_name.unique_no.sm_<>.ptx + for (int index=1; index<= no_of_ptx; index++){ + snprintf(ptx_file, 1000, "%s.%d.sm_%u.ptx", get_app_binary_name(app_binary), index, forced_max_capability); + printf("Extracting specific PTX file named %s \n",ptx_file); + snprintf(command,1000,"$CUDA_INSTALL_PATH/bin/cuobjdump -arch=sm_%u -xptx %s %s", forced_max_capability, ptx_file, app_binary.c_str()); + if (system(command)!=0) { + printf("ERROR: command: %s failed \n",command); + exit(0); + } + } + } +#endif + //TODO: redundant to dump twice. how can it be prevented? + //dump only for specific arch + char fname[1024]; + if ((override_cuobjdump == NULL) || (strlen(override_cuobjdump)==0)) { + snprintf(fname,1024,"_cuobjdump_complete_output_XXXXXX"); + int fd=mkstemp(fname); + close(fd); + if(!g_cdp_enabled) + snprintf(command,1000,"$CUDA_INSTALL_PATH/bin/cuobjdump -ptx -elf -sass %s > %s", app_binary.c_str(), fname); + else + snprintf(command,1000,"$CUDA_INSTALL_PATH/bin/cuobjdump -ptx -elf -sass -all %s > %s", app_binary.c_str(), fname); + bool parse_output = true; + result = system(command); + if(result) { + if (context->get_device()->get_gpgpu()->get_config().experimental_lib_support() && (result == 65280)) { + // Some CUDA application may exclusively use kernels provided by CUDA + // libraries (e.g. CUBLAS). Skipping cuobjdump extraction from the + // executable for this case. + // 65280 is the return code from cuobjdump denoting the specific error (tested on CUDA 4.0/4.1/4.2) + printf("WARNING: Failed to execute: %s\n", command); + printf(" Executable binary does not contain any GPU kernel.\n"); + parse_output = false; + } else { + printf("ERROR: Failed to execute: %s\n", command); + exit(1); + } + } + + if (parse_output) { + printf("Parsing file %s\n", fname); + cuobjdump_in = fopen(fname, "r"); + + cuobjdump_parse(); + fclose(cuobjdump_in); + printf("Done parsing!!!\n"); + } else { + printf("Parsing skipped for %s\n", fname); + } + + if (context->get_device()->get_gpgpu()->get_config().experimental_lib_support()){ + //Experimental library support + //Currently only for cufft + + std::stringstream cmd; + cmd << "ldd " << app_binary << " | grep $CUDA_INSTALL_PATH | awk \'{print $3}\' > _tempfile_.txt"; + int result = system(cmd.str().c_str()); + if(result){ + std::cout << "Failed to execute: " << cmd.str() << std::endl; + exit(1); + } + std::ifstream libsf; + libsf.open("_tempfile_.txt"); + if(!libsf.is_open()) { + std::cout << "Failed to open: _tempfile_.txt" << std::endl; + exit(1); + } + + //Save the original section list + std::list<cuobjdumpSection*> tmpsl = cuobjdumpSectionList; + cuobjdumpSectionList.clear(); + + std::string line; + std::getline(libsf, line); + std::cout << "DOING: " << line << std::endl; + int cnt=1; + while(libsf.good()){ + std::stringstream libcodfn; + libcodfn << "_cuobjdump_complete_lib_" << cnt << "_"; + cmd.str(""); //resetting + cmd << "$CUDA_INSTALL_PATH/bin/cuobjdump -ptx -elf -sass "; + cmd << line; + cmd << " > "; + cmd << libcodfn.str(); + std::cout << "Running cuobjdump on " << line << std::endl; + std::cout << "Using command: " << cmd.str() << std::endl; + result = system(cmd.str().c_str()); + if(result) {printf("ERROR: Failed to execute: %s\n", command); exit(1);} + std::cout << "Done" << std::endl; + + std::cout << "Trying to parse " << libcodfn.str() << std::endl; + cuobjdump_in = fopen(libcodfn.str().c_str(), "r"); + cuobjdump_parse(); + fclose(cuobjdump_in); + std::getline(libsf, line); + } + libSectionList = cuobjdumpSectionList; + + //Restore the original section list + cuobjdumpSectionList = tmpsl; + } + } else { + printf("GPGPU-Sim PTX: overriding cuobjdump with '%s' (CUOBJDUMP_SIM_FILE is set)\n", override_cuobjdump); + snprintf(fname,1024, "%s",override_cuobjdump); + } +} + +//! Read file into char* +//TODO: convert this to C++ streams, will be way cleaner +char* readfile (const std::string filename){ + assert (filename != ""); + FILE* fp = fopen(filename.c_str(),"r"); + if (!fp) { + std::cout << "ERROR: Could not open file %s for reading\n" << filename << std::endl; + assert (0); + } + // finding size of the file + int filesize= 0; + fseek (fp , 0 , SEEK_END); + + filesize = ftell (fp); + fseek (fp, 0, SEEK_SET); + // allocate and copy the entire ptx + char* ret = (char*)malloc((filesize +1)* sizeof(char)); + fread(ret,1,filesize,fp); + ret[filesize]='\0'; + fclose(fp); + return ret; +} + +//! Function that helps debugging +void printSectionList(std::list<cuobjdumpSection*> sl) { + std::list<cuobjdumpSection*>::iterator iter; + for ( iter = sl.begin(); + iter != sl.end(); + iter++ + ){ + (*iter)->print(); + } +} + +//! Remove unecessary sm versions from the section list +std::list<cuobjdumpSection*> pruneSectionList(std::list<cuobjdumpSection*> cuobjdumpSectionList, CUctx_st *context) { + unsigned forced_max_capability = context->get_device()->get_gpgpu()->get_config().get_forced_max_capability(); + + //For ptxplus, force the max capability to 19 if it's higher or unspecified(0) + if (context->get_device()->get_gpgpu()->get_config().convert_to_ptxplus()){ + if ( (forced_max_capability == 0) || + (forced_max_capability >= 20)){ + printf("GPGPU-Sim: WARNING: Capability >= 20 are not supported in PTXPlus\n\tSetting forced_max_capability to 19\n"); + forced_max_capability = 19; + } + } + + std::list<cuobjdumpSection*> prunedList; + + //Find the highest capability (that is lower than the forced maximum) for each cubin file + //and set it in cuobjdumpSectionMap. Do this only for ptx sections + std::map<std::string, unsigned> cuobjdumpSectionMap; + int min_ptx_capability_found=0; + for ( std::list<cuobjdumpSection*>::iterator iter = cuobjdumpSectionList.begin(); + iter != cuobjdumpSectionList.end(); + iter++){ + unsigned capability = (*iter)->getArch(); + if(dynamic_cast<cuobjdumpPTXSection*>(*iter) != NULL){ + if(capability<min_ptx_capability_found || min_ptx_capability_found==0) + min_ptx_capability_found=capability; + if (capability <= forced_max_capability || forced_max_capability==0) { + if((cuobjdumpSectionMap.find((*iter)->getIdentifier())==cuobjdumpSectionMap.end()) + || (cuobjdumpSectionMap[(*iter)->getIdentifier()] < capability)) + cuobjdumpSectionMap[(*iter)->getIdentifier()] = capability; + } + } + } + + //Throw away the sections with the lower capabilites and push those with the highest in + //the pruned list + for ( std::list<cuobjdumpSection*>::iterator iter = cuobjdumpSectionList.begin(); + iter != cuobjdumpSectionList.end(); + iter++){ + unsigned capability = (*iter)->getArch(); + if(capability == cuobjdumpSectionMap[(*iter)->getIdentifier()]){ + prunedList.push_back(*iter); + } else { + delete *iter; + } + } + if(prunedList.empty()){ + printf("Error: No PTX sections found with sm capability that is lower than current forced maximum capability \n minimum ptx capability found = %u, maximum forced ptx capability = %u \n User might want to change either the forced maximum capability from gpgpusim configuration or update the compilation to generate the required PTX version\n",min_ptx_capability_found,forced_max_capability); + abort(); + } + return prunedList; +} + +//! Merge all PTX sections that have a specific identifier into one file +std::list<cuobjdumpSection*> mergeMatchingSections(std::list<cuobjdumpSection*> cuobjdumpSectionList, std::string identifier){ + const char *ptxcode = ""; + std::list<cuobjdumpSection*>::iterator old_iter; + cuobjdumpPTXSection* old_ptxsection = NULL; + cuobjdumpPTXSection* ptxsection; + std::list<cuobjdumpSection*> mergedList; + + for ( std::list<cuobjdumpSection*>::iterator iter = cuobjdumpSectionList.begin(); + iter != cuobjdumpSectionList.end(); + iter++){ + if((ptxsection=dynamic_cast<cuobjdumpPTXSection*>(*iter)) != NULL && + strcmp(ptxsection->getIdentifier().c_str(), identifier.c_str()) == 0){ + // Read and remove the last PTX section + if (old_ptxsection != NULL) { + ptxcode = readfile(old_ptxsection->getPTXfilename()); + // remove ptx file? + delete *old_iter; + } + + // Append all the PTX from the last PTX section into the current PTX section + // Add 50 to ptxcode to ignore the information regarding version/target/address_size + if (strlen(ptxcode) >= 50) { + FILE *ptxfile = fopen((ptxsection->getPTXfilename()).c_str(), "a"); + fprintf(ptxfile, "%s", ptxcode + 50); + fclose(ptxfile); + } + + old_iter = iter; + old_ptxsection = ptxsection; + } + // Store all non-PTX sections and PTX sections with non-matching identifiers + else { + mergedList.push_back(*iter); + } + } + + // Store the final PTX section + mergedList.push_back(*old_iter); + + return mergedList; +} + +//! Merge any PTX sections with matching identifiers +std::list<cuobjdumpSection*> mergeSections(std::list<cuobjdumpSection*> cuobjdumpSectionList){ + std::vector<std::string> identifier; + cuobjdumpPTXSection* ptxsection; + + // Add all identifiers present in PTX sections to a vector + for ( std::list<cuobjdumpSection*>::iterator iter = cuobjdumpSectionList.begin(); + iter != cuobjdumpSectionList.end(); + iter++){ + if((ptxsection=dynamic_cast<cuobjdumpPTXSection*>(*iter)) != NULL){ + std::string current_id = ptxsection->getIdentifier(); + + // If we haven't yet seen a given identifier, add it to the vector + if (std::find(identifier.begin(), identifier.end(), current_id) == identifier.end()) { + identifier.push_back(current_id); + } + } + } + + // Call mergeMatchingSections on all identifiers in the vector + for ( std::vector<std::string>::iterator iter = identifier.begin(); + iter != identifier.end(); + iter++) { + cuobjdumpSectionList = mergeMatchingSections(cuobjdumpSectionList, *iter); + } + + return cuobjdumpSectionList; +} + + +//! Within the section list, find the ELF section corresponding to a given identifier +cuobjdumpELFSection* findELFSectionInList(std::list<cuobjdumpSection*> sectionlist, const std::string identifier){ + + std::list<cuobjdumpSection*>::iterator iter; + for ( iter = sectionlist.begin(); + iter != sectionlist.end(); + iter++ + ){ + cuobjdumpELFSection* elfsection; + if((elfsection=dynamic_cast<cuobjdumpELFSection*>(*iter)) != NULL){ + if(elfsection->getIdentifier() == identifier) + return elfsection; + } + } + return NULL; +} + +//! Find an ELF section in all the known lists +cuobjdumpELFSection* findELFSection(const std::string identifier){ + cuobjdumpELFSection* sec = findELFSectionInList(cuobjdumpSectionList, identifier); + if (sec!=NULL)return sec; + sec = findELFSectionInList(libSectionList, identifier); + if (sec!=NULL)return sec; + std::cout << "Could not find " << identifier << std::endl; + assert(0 && "Could not find the required ELF section"); + return NULL; +} + +//! Within the section list, find the PTX section corresponding to a given identifier +cuobjdumpPTXSection* findPTXSectionInList(std::list<cuobjdumpSection*> sectionlist, const std::string identifier){ + std::list<cuobjdumpSection*>::iterator iter; + for ( iter = sectionlist.begin(); + iter != sectionlist.end(); + iter++ + ){ + cuobjdumpPTXSection* ptxsection; + if((ptxsection=dynamic_cast<cuobjdumpPTXSection*>(*iter)) != NULL){ + if(ptxsection->getIdentifier() == identifier) + return ptxsection; + else { + extern bool g_cdp_enabled; + if(g_cdp_enabled) { + printf("Warning: __cudaRegisterFatBinary needs %s, but find PTX section with %s\n", + identifier.c_str(), ptxsection->getIdentifier().c_str()); + return ptxsection; + } + } + } + } + return NULL; +} + +//! Find an PTX section in all the known lists +cuobjdumpPTXSection* findPTXSection(const std::string identifier){ + cuobjdumpPTXSection* sec = findPTXSectionInList(cuobjdumpSectionList, identifier); + if (sec!=NULL)return sec; + sec = findPTXSectionInList(libSectionList, identifier); + if (sec!=NULL)return sec; + std::cout << "Could not find " << identifier << std::endl; + assert(0 && "Could not find the required PTX section"); + return NULL; +} + + + +//! Extract the code using cuobjdump and remove unnecessary sections +void cuobjdumpInit(){ + CUctx_st *context = GPGPUSim_Context(); + extract_code_using_cuobjdump(); //extract all the output of cuobjdump to _cuobjdump_*.* + const char* pre_load = getenv("CUOBJDUMP_SIM_FILE"); + if (pre_load ==NULL || strlen(pre_load)==0){ + cuobjdumpSectionList = pruneSectionList(cuobjdumpSectionList, context); + cuobjdumpSectionList = mergeSections(cuobjdumpSectionList); + } +} + +std::map<int, std::string> fatbinmap; +std::map<int, bool>fatbin_registered; +std::map<std::string, symbol_table*> name_symtab; + +//! Keep track of the association between filename and cubin handle +void cuobjdumpRegisterFatBinary(unsigned int handle, const char* filename){ + fatbinmap[handle] = filename; +} + +//! Either submit PTX for simulation or convert SASS to PTXPlus and submit it +void cuobjdumpParseBinary(unsigned int handle){ + + if(fatbin_registered[handle]) return; + fatbin_registered[handle] = true; + CUctx_st *context = GPGPUSim_Context(); + std::string fname = fatbinmap[handle]; + + if (name_symtab.find(fname) != name_symtab.end()) { + symbol_table *symtab = name_symtab[fname]; + context->add_binary(symtab, handle); + return; + } + + unsigned max_capability = 0; + for ( std::list<cuobjdumpSection*>::iterator iter = cuobjdumpSectionList.begin(); + iter != cuobjdumpSectionList.end(); + iter++){ + unsigned capability = (*iter)->getArch(); + if (capability > max_capability) max_capability = capability; + } + if (max_capability > 20) printf("WARNING: No guarantee that PTX will be parsed for SM version %u\n", max_capability); + + cuobjdumpPTXSection* ptx = NULL; + const char* pre_load = getenv("CUOBJDUMP_SIM_FILE"); + if(pre_load==NULL || strlen(pre_load)==0) + ptx = findPTXSection(fname); + symbol_table *symtab; + char *ptxcode; + const char *override_ptx_name = getenv("PTX_SIM_KERNELFILE"); + if (override_ptx_name == NULL or getenv("PTX_SIM_USE_PTX_FILE") == NULL or strlen(getenv("PTX_SIM_USE_PTX_FILE"))==0) { + ptxcode = readfile(ptx->getPTXfilename()); + } else { + printf("GPGPU-Sim PTX: overriding embedded ptx with '%s' (PTX_SIM_USE_PTX_FILE is set)\n", override_ptx_name); + ptxcode = readfile(override_ptx_name); + } + if(context->get_device()->get_gpgpu()->get_config().convert_to_ptxplus() ) { + cuobjdumpELFSection* elfsection = findELFSection(ptx->getIdentifier()); + assert (elfsection!= NULL); + char *ptxplus_str = gpgpu_ptx_sim_convert_ptx_and_sass_to_ptxplus( + ptx->getPTXfilename(), + elfsection->getELFfilename(), + elfsection->getSASSfilename()); + symtab=gpgpu_ptx_sim_load_ptx_from_string(ptxplus_str, handle); + printf("Adding %s with cubin handle %u\n", ptx->getPTXfilename().c_str(), handle); + context->add_binary(symtab, handle); + gpgpu_ptxinfo_load_from_string( ptxcode, handle, max_capability ); + delete[] ptxplus_str; + } else { + symtab=gpgpu_ptx_sim_load_ptx_from_string(ptxcode, handle); + //if CUOBJDUMP_SIM_FILE is not set, ptx is NULL. So comment below. + //printf("Adding %s with cubin handle %u\n", ptx->getPTXfilename().c_str(), handle); + context->add_binary(symtab, handle); + gpgpu_ptxinfo_load_from_string( ptxcode, handle, max_capability ); + } + load_static_globals(symtab,STATIC_ALLOC_LIMIT,0xFFFFFFFF,context->get_device()->get_gpgpu()); + load_constants(symtab,STATIC_ALLOC_LIMIT,context->get_device()->get_gpgpu()); + name_symtab[fname] = symtab; + + //TODO: Remove temporarily files as per configurations +} + +void** CUDARTAPI __cudaRegisterFatBinary( void *fatCubin ) +{ +#if (CUDART_VERSION < 2010) + printf("GPGPU-Sim PTX: ERROR ** this version of GPGPU-Sim requires CUDA 2.1 or higher\n"); + exit(1); +#endif + CUctx_st *context = GPGPUSim_Context(); + static unsigned next_fat_bin_handle = 1; + if(context->get_device()->get_gpgpu()->get_config().use_cuobjdump()) { + // The following workaround has only been verified on 64-bit systems. + if (sizeof(void*) == 4) + printf("GPGPU-Sim PTX: FatBin file name extraction has not been tested on 32-bit system.\n"); + + #if (CUDART_VERSION <= 6000) + // FatBin handle from the .fatbin.c file (one of the intermediate files generated by NVCC) + typedef struct {int m; int v; const unsigned long long* d; char* f;} __fatDeviceText __attribute__ ((aligned (8))); + __fatDeviceText * fatDeviceText = (__fatDeviceText *) fatCubin; + + // Extract the source code file name that generate the given FatBin. + // - Obtains the pointer to the actual fatbin structure from the FatBin handle (fatCubin). + // - An integer inside the fatbin structure contains the relative offset to the source code file name. + // - This offset differs among different CUDA and GCC versions. + char * pfatbin = (char*) fatDeviceText->d; + int offset = *((int*)(pfatbin+48)); + char * filename = (pfatbin+16+offset); + #else + const char * filename = "default"; + #endif + // The extracted file name is associated with a fat_cubin_handle passed + // into cudaLaunch(). Inside cudaLaunch(), the associated file name is + // used to find the PTX/SASS section from cuobjdump, which contains the + // PTX/SASS code for the launched kernel function. + // This allows us to work around the fact that cuobjdump only outputs the + // file name associated with each section. + unsigned long long fat_cubin_handle = next_fat_bin_handle; + next_fat_bin_handle++; + printf("GPGPU-Sim PTX: __cudaRegisterFatBinary, fat_cubin_handle = %llu, filename=%s\n", fat_cubin_handle, filename); + /*! + * This function extracts all data from all files in first call + * then for next calls, only returns the appropriate number + */ + assert(fat_cubin_handle >= 1); + if (fat_cubin_handle==1) cuobjdumpInit(); + cuobjdumpRegisterFatBinary(fat_cubin_handle, filename); + + return (void**)fat_cubin_handle; + } +#if (CUDART_VERSION < 8000) + else { + static unsigned source_num=1; + unsigned long long fat_cubin_handle = next_fat_bin_handle++; + __cudaFatCudaBinary *info = (__cudaFatCudaBinary *)fatCubin; + assert( info->version >= 3 ); + unsigned num_ptx_versions=0; + unsigned max_capability=0; + unsigned selected_capability=0; + bool found=false; + unsigned forced_max_capability = context->get_device()->get_gpgpu()->get_config().get_forced_max_capability(); + if (!info->ptx){ + printf("ERROR: Cannot find ptx code in cubin file\n" + "\tIf you are using CUDA 4.0 or higher, please enable -gpgpu_ptx_use_cuobjdump or downgrade to CUDA 3.1\n"); + exit(1); + } + while( info->ptx[num_ptx_versions].gpuProfileName != NULL ) { + unsigned capability=0; + sscanf(info->ptx[num_ptx_versions].gpuProfileName,"compute_%u",&capability); + printf("GPGPU-Sim PTX: __cudaRegisterFatBinary found PTX versions for '%s', ", info->ident); + printf("capability = %s\n", info->ptx[num_ptx_versions].gpuProfileName ); + if( forced_max_capability ) { + if( capability > max_capability && capability <= forced_max_capability ) { + found = true; + max_capability=capability; + selected_capability = num_ptx_versions; + } + } else { + if( capability > max_capability ) { + found = true; + max_capability=capability; + selected_capability = num_ptx_versions; + } + } + num_ptx_versions++; + } + if( found ) { + printf("GPGPU-Sim PTX: Loading PTX for %s, capability = %s\n", + info->ident, info->ptx[selected_capability].gpuProfileName ); + symbol_table *symtab; + const char *ptx = info->ptx[selected_capability].ptx; + if(context->get_device()->get_gpgpu()->get_config().convert_to_ptxplus() ) { + printf("GPGPU-Sim PTX: ERROR ** PTXPlus is only supported through cuobjdump\n" + "\tEither enable cuobjdump or disable PTXPlus in your configuration file\n"); + exit(1); + } else { + symtab=gpgpu_ptx_sim_load_ptx_from_string(ptx,source_num); + context->add_binary(symtab,fat_cubin_handle); + gpgpu_ptxinfo_load_from_string( ptx, source_num, max_capability ); + } + source_num++; + load_static_globals(symtab,STATIC_ALLOC_LIMIT,0xFFFFFFFF,context->get_device()->get_gpgpu()); + load_constants(symtab,STATIC_ALLOC_LIMIT,context->get_device()->get_gpgpu()); + } else { + printf("GPGPU-Sim PTX: warning -- did not find an appropriate PTX in cubin\n"); + } + return (void**)fat_cubin_handle; + } +#else + else { + printf("ERROR ** __cudaRegisterFatBinary() needs to be updated\n"); + abort(); + } +#endif +} + +void __cudaUnregisterFatBinary(void **fatCubinHandle) +{ + ; +} + +cudaError_t cudaDeviceReset ( void ) { + // Should reset the simulated GPU + return g_last_cudaError = cudaSuccess; +} +cudaError_t CUDARTAPI cudaDeviceSynchronize(void){ + // I don't know what this should do + return g_last_cudaError = cudaSuccess; +} + + +void CUDARTAPI __cudaRegisterFunction( + void **fatCubinHandle, + const char *hostFun, + char *deviceFun, + const char *deviceName, + int thread_limit, + uint3 *tid, + uint3 *bid, + dim3 *bDim, + dim3 *gDim +) +{ + CUctx_st *context = GPGPUSim_Context(); + unsigned fat_cubin_handle = (unsigned)(unsigned long long)fatCubinHandle; + printf("GPGPU-Sim PTX: __cudaRegisterFunction %s : hostFun 0x%p, fat_cubin_handle = %u\n", + deviceFun, hostFun, fat_cubin_handle); + if(context->get_device()->get_gpgpu()->get_config().use_cuobjdump()) + cuobjdumpParseBinary(fat_cubin_handle); + context->register_function( fat_cubin_handle, hostFun, deviceFun ); +} + +extern void __cudaRegisterVar( + void **fatCubinHandle, + char *hostVar, //pointer to...something + char *deviceAddress, //name of variable + const char *deviceName, //name of variable (same as above) + int ext, + int size, + int constant, + int global ) +{ + printf("GPGPU-Sim PTX: __cudaRegisterVar: hostVar = %p; deviceAddress = %s; deviceName = %s\n", hostVar, deviceAddress, deviceName); + printf("GPGPU-Sim PTX: __cudaRegisterVar: Registering const memory space of %d bytes\n", size); + if(GPGPUSim_Context()->get_device()->get_gpgpu()->get_config().use_cuobjdump()) + cuobjdumpParseBinary((unsigned)(unsigned long long)fatCubinHandle); + fflush(stdout); + if ( constant && !global && !ext ) { + gpgpu_ptx_sim_register_const_variable(hostVar,deviceName,size); + } else if ( !constant && !global && !ext ) { + gpgpu_ptx_sim_register_global_variable(hostVar,deviceName,size); + } else cuda_not_implemented(__my_func__,__LINE__); +} + + +void __cudaRegisterShared( + void **fatCubinHandle, + void **devicePtr +) +{ + // we don't do anything here + printf("GPGPU-Sim PTX: __cudaRegisterShared\n" ); +} + +void CUDARTAPI __cudaRegisterSharedVar( + void **fatCubinHandle, + void **devicePtr, + size_t size, + size_t alignment, + int storage +) +{ + // we don't do anything here + printf("GPGPU-Sim PTX: __cudaRegisterSharedVar\n" ); +} + +void __cudaRegisterTexture( + void **fatCubinHandle, + const struct textureReference *hostVar, + const void **deviceAddress, + const char *deviceName, + int dim, + int norm, + int ext +) //passes in a newly created textureReference +{ + std::string devStr (deviceName); + #if (CUDART_VERSION > 4020) + if (devStr.size() > 2 && devStr.data()[0] == ':' && devStr.data()[1] == ':') + devStr = devStr.replace(0, 2, ""); + #endif + CUctx_st *context = GPGPUSim_Context(); + gpgpu_t *gpu = context->get_device()->get_gpgpu(); + printf("GPGPU-Sim PTX: in __cudaRegisterTexture:\n"); + gpu->gpgpu_ptx_sim_bindNameToTexture(devStr.data(), hostVar, dim, norm, ext); + printf("GPGPU-Sim PTX: int dim = %d\n", dim); + printf("GPGPU-Sim PTX: int norm = %d\n", norm); + printf("GPGPU-Sim PTX: int ext = %d\n", ext); + printf("GPGPU-Sim PTX: Execution warning: Not finished implementing \"%s\"\n", __my_func__ ); +} + +#ifndef OPENGL_SUPPORT +typedef unsigned long GLuint; +#endif + +cudaError_t cudaGLRegisterBufferObject(GLuint bufferObj) +{ + printf("GPGPU-Sim PTX: Execution warning: ignoring call to \"%s\"\n", __my_func__ ); + return g_last_cudaError = cudaSuccess; +} + +struct glbmap_entry { + GLuint m_bufferObj; + void *m_devPtr; + size_t m_size; + struct glbmap_entry *m_next; +}; +typedef struct glbmap_entry glbmap_entry_t; + +glbmap_entry_t* g_glbmap = NULL; + +cudaError_t cudaGLMapBufferObject(void** devPtr, GLuint bufferObj) +{ +#ifdef OPENGL_SUPPORT + GLint buffer_size=0; + CUctx_st* ctx = GPGPUSim_Context(); + + glbmap_entry_t *p = g_glbmap; + while ( p && p->m_bufferObj != bufferObj ) + p = p->m_next; + if ( p == NULL ) { + glBindBuffer(GL_ARRAY_BUFFER,bufferObj); + glGetBufferParameteriv(GL_ARRAY_BUFFER,GL_BUFFER_SIZE,&buffer_size); + assert( buffer_size != 0 ); + *devPtr = ctx->get_device()->get_gpgpu()->gpu_malloc(buffer_size); + + // create entry and insert to front of list + glbmap_entry_t *n = (glbmap_entry_t *) calloc(1,sizeof(glbmap_entry_t)); + n->m_next = g_glbmap; + g_glbmap = n; + + // initialize entry + n->m_bufferObj = bufferObj; + n->m_devPtr = *devPtr; + n->m_size = buffer_size; + + p = n; + } else { + buffer_size = p->m_size; + *devPtr = p->m_devPtr; + } + + if ( *devPtr ) { + char *data = (char *) calloc(p->m_size,1); + glGetBufferSubData(GL_ARRAY_BUFFER,0,buffer_size,data); + memcpy_to_gpu( (size_t) *devPtr, data, buffer_size ); + free(data); + printf("GPGPU-Sim PTX: cudaGLMapBufferObject %zu bytes starting at 0x%llx..\n", (size_t)buffer_size, + (unsigned long long) *devPtr); + return g_last_cudaError = cudaSuccess; + } else { + return g_last_cudaError = cudaErrorMemoryAllocation; + } + + return g_last_cudaError = cudaSuccess; +#else + fflush(stdout); + fflush(stderr); + printf("GPGPU-Sim PTX: GPGPU-Sim support for OpenGL integration disabled -- exiting\n"); + fflush(stdout); + exit(50); +#endif +} + +cudaError_t cudaGLUnmapBufferObject(GLuint bufferObj) +{ +#ifdef OPENGL_SUPPORT + glbmap_entry_t *p = g_glbmap; + while ( p && p->m_bufferObj != bufferObj ) + p = p->m_next; + if ( p == NULL ) + return g_last_cudaError = cudaErrorUnknown; + + char *data = (char *) calloc(p->m_size,1); + memcpy_from_gpu( data,(size_t)p->m_devPtr,p->m_size ); + glBufferSubData(GL_ARRAY_BUFFER,0,p->m_size,data); + free(data); + + return g_last_cudaError = cudaSuccess; +#else + fflush(stdout); + fflush(stderr); + printf("GPGPU-Sim PTX: support for OpenGL integration disabled -- exiting\n"); + fflush(stdout); + exit(50); +#endif +} + +cudaError_t cudaGLUnregisterBufferObject(GLuint bufferObj) +{ + printf("GPGPU-Sim PTX: Execution warning: ignoring call to \"%s\"\n", __my_func__ ); + return g_last_cudaError = cudaSuccess; +} + +#if (CUDART_VERSION >= 2010) + +cudaError_t CUDARTAPI cudaHostAlloc(void **pHost, size_t bytes, unsigned int flags) +{ + *pHost = malloc(bytes); + //need to track the size allocated so that cudaHostGetDevicePointer() can function properly. + //TODO: vary this function behavior based on flags value (following nvidia documentation) + pinned_memory_size[*pHost]=bytes; + if( *pHost ) + return g_last_cudaError = cudaSuccess; + else + return g_last_cudaError = cudaErrorMemoryAllocation; +} + +cudaError_t CUDARTAPI cudaHostGetDevicePointer(void **pDevice, void *pHost, unsigned int flags) +{ + //only cpu memory allocation happens in cudaHostAlloc. Linking with device pointer to pinned memory happens here. + //TODO: once kernel is executed, the contents in global pointer of GPU must be copied back to CPU host pointer! + flags=0; + CUctx_st* context = GPGPUSim_Context(); + gpgpu_t *gpu = context->get_device()->get_gpgpu(); + std::map<void *, size_t>::const_iterator i = pinned_memory_size.find(pHost); + assert(i != pinned_memory_size.end()); + size_t size = i->second; + *pDevice = gpu->gpu_malloc(size); + if(g_debug_execution >= 3) + printf("GPGPU-Sim PTX: cudaMallocing %zu bytes starting at 0x%llx..\n",size, (unsigned long long) *pDevice); + if ( *pDevice ) { + pinned_memory[pHost]=pDevice; + //Copy contents in cpu to gpu + gpu->memcpy_to_gpu((size_t)*pDevice,pHost,size); + return g_last_cudaError = cudaSuccess; + } else { + return g_last_cudaError = cudaErrorMemoryAllocation; + } +} + +cudaError_t CUDARTAPI cudaSetValidDevices(int *device_arr, int len) +{ + cuda_not_implemented(__my_func__,__LINE__); + return g_last_cudaError = cudaErrorUnknown; +} + +cudaError_t CUDARTAPI cudaSetDeviceFlags( int flags ) +{ + cuda_not_implemented(__my_func__,__LINE__); + return g_last_cudaError = cudaErrorUnknown; +} + +cudaError_t CUDARTAPI cudaFuncGetAttributes(struct cudaFuncAttributes *attr, const char *hostFun ) +{ + CUctx_st *context = GPGPUSim_Context(); + function_info *entry = context->get_kernel(hostFun); + if( entry ) { + const struct gpgpu_ptx_sim_info *kinfo = entry->get_kernel_info(); + attr->sharedSizeBytes = kinfo->smem; + attr->constSizeBytes = kinfo->cmem; + attr->localSizeBytes = kinfo->lmem; + attr->numRegs = kinfo->regs; + attr->maxThreadsPerBlock = 0; // from pragmas? +#if CUDART_VERSION >= 3000 + attr->ptxVersion = kinfo->ptx_version; + attr->binaryVersion = kinfo->sm_target; +#endif + } + return g_last_cudaError = cudaSuccess; +} + +cudaError_t CUDARTAPI cudaEventCreateWithFlags(cudaEvent_t *event, int flags) +{ + CUevent_st *e = new CUevent_st(flags==cudaEventBlockingSync); + g_timer_events[e->get_uid()] = e; +#if CUDART_VERSION >= 3000 + *event = e; +#else + *event = e->get_uid(); +#endif + return g_last_cudaError = cudaSuccess; +} + +cudaError_t CUDARTAPI cudaDriverGetVersion(int *driverVersion) +{ + *driverVersion = CUDART_VERSION; + return g_last_cudaError = cudaErrorUnknown; +} + +cudaError_t CUDARTAPI cudaRuntimeGetVersion(int *runtimeVersion) +{ + *runtimeVersion = CUDART_VERSION; + return g_last_cudaError = cudaErrorUnknown; +} + +#if CUDART_VERSION >= 3000 +__host__ cudaError_t CUDARTAPI cudaFuncSetCacheConfig(const char *func, enum cudaFuncCache cacheConfig ) +{ + CUctx_st *context = GPGPUSim_Context(); + context->get_device()->get_gpgpu()->set_cache_config(context->get_kernel(func)->get_name(), (FuncCache)cacheConfig); + return g_last_cudaError = cudaSuccess; +} + +//Jin: hack for cdp +__host__ cudaError_t CUDARTAPI cudaDeviceSetLimit(enum cudaLimit limit, size_t value) { + return g_last_cudaError = cudaSuccess; +} +#endif + +#endif + +cudaError_t CUDARTAPI cudaGLSetGLDevice(int device) +{ + printf("GPGPU-Sim PTX: Execution warning: ignoring call to \"%s\"\n", __my_func__ ); + return g_last_cudaError = cudaErrorUnknown; +} + +typedef void* HGPUNV; + +cudaError_t CUDARTAPI cudaWGLGetDevice(int *device, HGPUNV hGpu) +{ + cuda_not_implemented(__my_func__,__LINE__); + return g_last_cudaError = cudaErrorUnknown; +} + +void CUDARTAPI __cudaMutexOperation(int lock) +{ + cuda_not_implemented(__my_func__,__LINE__); +} + +void CUDARTAPI __cudaTextureFetch(const void *tex, void *index, int integer, void *val) +{ + cuda_not_implemented(__my_func__,__LINE__); +} + +} + +namespace cuda_math { + +void CUDARTAPI __cudaMutexOperation(int lock) +{ + cuda_not_implemented(__my_func__,__LINE__); +} + +void CUDARTAPI __cudaTextureFetch(const void *tex, void *index, int integer, void *val) +{ + cuda_not_implemented(__my_func__,__LINE__); +} + +int CUDARTAPI __cudaSynchronizeThreads(void**, void*) +{ + //TODO This function should syncronize if we support Asyn kernel calls + return g_last_cudaError = cudaSuccess; +} + +} + +//////// + +extern int ptx_parse(); +extern int ptx__scan_string(const char*); +extern FILE *ptx_in; + +extern int ptxinfo_parse(); +extern int ptxinfo_debug; +extern FILE *ptxinfo_in; + +/// static functions + +static int load_static_globals( symbol_table *symtab, unsigned min_gaddr, unsigned max_gaddr, gpgpu_t *gpu ) +{ + printf( "GPGPU-Sim PTX: loading globals with explicit initializers... \n" ); + fflush(stdout); + int ng_bytes=0; + symbol_table::iterator g=symtab->global_iterator_begin(); + + for ( ; g!=symtab->global_iterator_end(); g++) { + symbol *global = *g; + if ( global->has_initializer() ) { + printf( "GPGPU-Sim PTX: initializing '%s' ... ", global->name().c_str() ); + unsigned addr=global->get_address(); + const type_info *type = global->type(); + type_info_key ti=type->get_key(); + size_t size; + int t; + ti.type_decode(size,t); + int nbytes = size/8; + int offset=0; + std::list<operand_info> init_list = global->get_initializer(); + for ( std::list<operand_info>::iterator i=init_list.begin(); i!=init_list.end(); i++ ) { + operand_info op = *i; + ptx_reg_t value = op.get_literal_value(); + assert( (addr+offset+nbytes) < min_gaddr ); // min_gaddr is start of "heap" for cudaMalloc + gpu->get_global_memory()->write(addr+offset,nbytes,&value,NULL,NULL); // assuming little endian here + offset+=nbytes; + ng_bytes+=nbytes; + } + printf(" wrote %u bytes\n", offset ); + } + } + printf( "GPGPU-Sim PTX: finished loading globals (%u bytes total).\n", ng_bytes ); + fflush(stdout); + return ng_bytes; +} + +static int load_constants( symbol_table *symtab, addr_t min_gaddr, gpgpu_t *gpu ) +{ + printf( "GPGPU-Sim PTX: loading constants with explicit initializers... " ); + fflush(stdout); + int nc_bytes = 0; + symbol_table::iterator g=symtab->const_iterator_begin(); + + for ( ; g!=symtab->const_iterator_end(); g++) { + symbol *constant = *g; + if ( constant->is_const() && constant->has_initializer() ) { + + // get the constant element data size + int basic_type; + size_t num_bits; + constant->type()->get_key().type_decode(num_bits,basic_type); + + std::list<operand_info> init_list = constant->get_initializer(); + int nbytes_written = 0; + for ( std::list<operand_info>::iterator i=init_list.begin(); i!=init_list.end(); i++ ) { + operand_info op = *i; + ptx_reg_t value = op.get_literal_value(); + int nbytes = num_bits/8; + switch ( op.get_type() ) { + case int_t: assert(nbytes >= 1); break; + case float_op_t: assert(nbytes == 4); break; + case double_op_t: assert(nbytes >= 4); break; // account for double DEMOTING + default: + abort(); + } + unsigned addr=constant->get_address() + nbytes_written; + assert( addr+nbytes < min_gaddr ); + + gpu->get_global_memory()->write(addr,nbytes,&value,NULL,NULL); // assume little endian (so u8 is the first byte in u32) + nc_bytes+=nbytes; + nbytes_written += nbytes; + } + } + } + printf( " done.\n"); + fflush(stdout); + return nc_bytes; +} + +kernel_info_t *gpgpu_cuda_ptx_sim_init_grid( const char *hostFun, + gpgpu_ptx_sim_arg_list_t args, + struct dim3 gridDim, + struct dim3 blockDim, + CUctx_st* context ) +{ + function_info *entry = context->get_kernel(hostFun); + kernel_info_t *result = new kernel_info_t(gridDim,blockDim,entry); + if( entry == NULL ) { + printf("GPGPU-Sim PTX: ERROR launching kernel -- no PTX implementation found for %p\n", hostFun); + abort(); + } + unsigned argcount=args.size(); + unsigned argn=1; + for( gpgpu_ptx_sim_arg_list_t::iterator a = args.begin(); a != args.end(); a++ ) { + entry->add_param_data(argcount-argn,&(*a)); + argn++; + } + + entry->finalize(result->get_param_memory()); + g_ptx_kernel_count++; + fflush(stdout); + + return result; +} |
