2024-01-27 04:25:03 +08:00
#!/bin/bash -e
# setup instructions for clang2py
if [ [ ! $( clang2py -V) ] ] ; then
pushd .
cd /tmp
sudo apt-get install -y --no-install-recommends clang
2024-03-22 23:50:50 +08:00
pip install --upgrade pip setuptools
2024-01-27 04:25:03 +08:00
pip install clang = = 14.0.6
git clone https://github.com/geohot/ctypeslib.git
cd ctypeslib
pip install --user .
clang2py -V
popd
fi
2024-01-27 04:44:19 +08:00
BASE = tinygrad/runtime/autogen/
2024-01-27 10:46:36 +08:00
fixup( ) {
sed -i '1s/^/# mypy: ignore-errors\n/' $1
sed -i 's/ *$//' $1
grep FIXME_STUB $1 || true
}
2024-06-15 03:12:18 +08:00
patch_dlopen( ) {
path = $1 ; shift
name = $1 ; shift
cat <<EOF | sed -i "/import ctypes.*/r /dev/stdin" $path
PATHS_TO_TRY = [
$( for p in " $@ " ; do echo " $p , " ; done )
]
def _try_dlopen_$name ( ) :
library = ctypes.util.find_library( " $name " )
if library: return ctypes.CDLL( library)
for candidate in PATHS_TO_TRY:
try: return ctypes.CDLL( candidate)
except OSError: pass
raise RuntimeError( " library $name not found " )
EOF
}
2024-07-17 22:09:34 +08:00
process_cdefines( ) {
local input_file = " $1 "
local output_file = " $2 "
sed -E '
# Remove single-line comments
s/[ [ :space:] ] *\/ \* .*\* \/ //g
# Remove multi-line comments
/\/ \* /,/\* \/ /d
/.*DT_MIPS_NUM.*/d
# Remove lines ending with backslash (multi-line macros)
/\\ $/d
# Convert C integer literals (remove U suffix)
s/\b ( [ 0-9] +) U\b /\1 /g
# Convert C types to Python ctypes
s/\b unsigned char\b /ctypes.c_ubyte/g
s/\b signed char\b /ctypes.c_byte/g
s/\b unsigned short\b /ctypes.c_ushort/g
s/\b short\b /ctypes.c_short/g
s/\b unsigned int\b /ctypes.c_uint/g
s/\b int\b /ctypes.c_int/g
s/\b unsigned long\b /ctypes.c_ulong/g
s/\b long\b /ctypes.c_long/g
s/\b float\b /ctypes.c_float/g
s/\b double\b /ctypes.c_double/g
# Function-like macros with parameters
/^#define[ [ :space:] ] +( [ [ :alnum:] _] +) [ [ :space:] ] *\( ( [ ^) ] *) \) [ [ :space:] ] +( .+) / {
s//def \1 ( \2 ) : return \3 /
p
d
}
# Simple #define statements (including those with parentheses)
/^#define[ [ :space:] ] +( [ [ :alnum:] _] +) [ [ :space:] ] +( .+) / {
s//\1 = \2 /
p
d
}
# Drop all other lines
d
' " $input_file " >> " $output_file "
}
2024-01-27 04:25:03 +08:00
generate_opencl( ) {
2024-01-27 04:44:19 +08:00
clang2py /usr/include/CL/cl.h -o $BASE /opencl.py -l /usr/lib/x86_64-linux-gnu/libOpenCL.so.1 -k cdefstum
2024-01-27 10:46:36 +08:00
fixup $BASE /opencl.py
2024-01-27 04:25:03 +08:00
# hot patches
2024-01-27 04:44:19 +08:00
sed -i "s\import ctypes\import ctypes, ctypes.util\g" $BASE /opencl.py
sed -i "s\ctypes.CDLL('/usr/lib/x86_64-linux-gnu/libOpenCL.so.1')\ctypes.CDLL(ctypes.util.find_library('OpenCL'))\g" $BASE /opencl.py
python3 -c "import tinygrad.runtime.autogen.opencl"
2024-01-27 04:25:03 +08:00
}
generate_hip( ) {
clang2py /opt/rocm/include/hip/hip_ext.h /opt/rocm/include/hip/hiprtc.h \
/opt/rocm/include/hip/hip_runtime_api.h /opt/rocm/include/hip/driver_types.h \
2024-01-27 04:44:19 +08:00
--clang-args= "-D__HIP_PLATFORM_AMD__ -I/opt/rocm/include -x c++" -o $BASE /hip.py -l /opt/rocm/lib/libamdhip64.so
echo "hipDeviceProp_t = hipDeviceProp_tR0600" >> $BASE /hip.py
echo "hipGetDeviceProperties = hipGetDevicePropertiesR0600" >> $BASE /hip.py
2024-01-27 10:46:36 +08:00
fixup $BASE /hip.py
2024-01-27 04:25:03 +08:00
# we can trust HIP is always at /opt/rocm/lib
2024-01-27 04:44:19 +08:00
#sed -i "s\import ctypes\import ctypes, ctypes.util\g" $BASE/hip.py
#sed -i "s\ctypes.CDLL('/opt/rocm/lib/libhiprtc.so')\ctypes.CDLL(ctypes.util.find_library('hiprtc'))\g" $BASE/hip.py
#sed -i "s\ctypes.CDLL('/opt/rocm/lib/libamdhip64.so')\ctypes.CDLL(ctypes.util.find_library('amdhip64'))\g" $BASE/hip.py
2024-03-12 19:06:43 +08:00
sed -i "s\import ctypes\import ctypes, os\g" $BASE /hip.py
sed -i "s\'/opt/rocm/\os.getenv('ROCM_PATH', '/opt/rocm/')+'/\g" $BASE /hip.py
2024-01-27 04:44:19 +08:00
python3 -c "import tinygrad.runtime.autogen.hip"
2024-03-22 23:50:50 +08:00
}
2024-01-27 04:25:03 +08:00
2024-03-22 23:50:50 +08:00
generate_comgr( ) {
2024-01-27 04:25:03 +08:00
clang2py /opt/rocm/include/amd_comgr/amd_comgr.h \
2024-01-27 04:44:19 +08:00
--clang-args= "-D__HIP_PLATFORM_AMD__ -I/opt/rocm/include -x c++" -o $BASE /comgr.py -l /opt/rocm/lib/libamd_comgr.so
2024-01-27 10:46:36 +08:00
fixup $BASE /comgr.py
2024-05-23 11:33:21 +08:00
sed -i "s\import ctypes\import ctypes, ctypes.util, os\g" $BASE /comgr.py
2024-06-15 03:12:18 +08:00
patch_dlopen $BASE /comgr.py amd_comgr "'/opt/rocm/lib/libamd_comgr.so'" "os.getenv('ROCM_PATH', '')+'/lib/libamd_comgr.so'"
sed -i "s\ctypes.CDLL('/opt/rocm/lib/libamd_comgr.so')\_try_dlopen_amd_comgr()\g" $BASE /comgr.py
2024-01-27 04:44:19 +08:00
python3 -c "import tinygrad.runtime.autogen.comgr"
2024-01-27 04:25:03 +08:00
}
2024-03-31 06:08:12 +08:00
generate_kfd( ) {
clang2py /usr/include/linux/kfd_ioctl.h -o $BASE /kfd.py -k cdefstum
2024-07-28 03:49:48 +08:00
awk ' /^#define AMDKFD_IOC_/ { if ( $0 ~ /\\ $/) { getline nextline; $0 = $0 nextline }
if ( match( $0 , /AMDKFD_IOC_( [ A-Z_] +) .*AMDKFD_( IOW?R?) \( 0x( [ 0-9A-F] +) ,.*struct ( [ a-z_] +) /, arr) ) {
print "AMDKFD_IOC_" arr[ 1] " = (\"" arr[ 2] "\", 0x" arr[ 3] ", struct_" arr[ 4] ")"
}
} ' /usr/include/linux/kfd_ioctl.h >> $BASE /kfd.py
2024-03-31 06:08:12 +08:00
fixup $BASE /kfd.py
sed -i "s\import ctypes\import ctypes, os\g" $BASE /kfd.py
python3 -c "import tinygrad.runtime.autogen.kfd"
}
2024-01-27 04:25:03 +08:00
generate_cuda( ) {
2024-06-29 15:46:29 +08:00
clang2py /usr/include/cuda.h -o $BASE /cuda.py -l /usr/lib/x86_64-linux-gnu/libcuda.so
2024-01-27 04:44:19 +08:00
sed -i "s\import ctypes\import ctypes, ctypes.util\g" $BASE /cuda.py
sed -i "s\ctypes.CDLL('/usr/lib/x86_64-linux-gnu/libcuda.so')\ctypes.CDLL(ctypes.util.find_library('cuda'))\g" $BASE /cuda.py
2024-01-27 10:46:36 +08:00
fixup $BASE /cuda.py
2024-01-27 04:44:19 +08:00
python3 -c "import tinygrad.runtime.autogen.cuda"
2024-01-27 04:25:03 +08:00
}
2024-06-29 15:46:29 +08:00
generate_nvrtc( ) {
clang2py /usr/local/cuda/include/nvrtc.h /usr/local/cuda/include/nvJitLink.h -o $BASE /nvrtc.py -l /usr/local/cuda/lib64/libnvrtc.so -l /usr/local/cuda/lib64/libnvJitLink.so
sed -i "s\import ctypes\import ctypes, ctypes.util\g" $BASE /nvrtc.py
sed -i "s\ctypes.CDLL('/usr/local/cuda/lib64/libnvrtc.so')\ctypes.CDLL(ctypes.util.find_library('nvrtc'))\g" $BASE /nvrtc.py
sed -i "s\ctypes.CDLL('/usr/local/cuda/lib64/libnvJitLink.so')\ctypes.CDLL(ctypes.util.find_library('nvJitLink'))\g" $BASE /nvrtc.py
fixup $BASE /nvrtc.py
python3 -c "import tinygrad.runtime.autogen.nvrtc"
}
2024-04-22 23:50:20 +08:00
generate_nv( ) {
NVKERN_COMMIT_HASH = d6b75a34094b0f56c2ccadf14e5d0bd515ed1ab6
NVKERN_SRC = /tmp/open-gpu-kernel-modules-$NVKERN_COMMIT_HASH
if [ ! -d " $NVKERN_SRC " ] ; then
git clone https://github.com/tinygrad/open-gpu-kernel-modules $NVKERN_SRC
pushd .
cd $NVKERN_SRC
git reset --hard $NVKERN_COMMIT_HASH
popd
fi
clang2py \
extra/nv_gpu_driver/clc6c0qmd.h \
$NVKERN_SRC /src/common/sdk/nvidia/inc/class/cl0080.h \
$NVKERN_SRC /src/common/sdk/nvidia/inc/class/cl2080_notification.h \
$NVKERN_SRC /src/common/sdk/nvidia/inc/class/clc56f.h \
$NVKERN_SRC /src/common/sdk/nvidia/inc/class/clc56f.h \
$NVKERN_SRC /src/common/sdk/nvidia/inc/class/clc56f.h \
$NVKERN_SRC /src/nvidia/generated/g_allclasses.h \
$NVKERN_SRC /src/common/sdk/nvidia/inc/class/clc6c0.h \
$NVKERN_SRC /kernel-open/nvidia-uvm/clc6b5.h \
$NVKERN_SRC /kernel-open/nvidia-uvm/uvm_ioctl.h \
$NVKERN_SRC /kernel-open/nvidia-uvm/uvm_linux_ioctl.h \
$NVKERN_SRC /src/nvidia/arch/nvalloc/unix/include/nv_escape.h \
$NVKERN_SRC /src/nvidia/arch/nvalloc/unix/include/nv-ioctl.h \
$NVKERN_SRC /src/nvidia/arch/nvalloc/unix/include/nv-ioctl-numbers.h \
$NVKERN_SRC /src/nvidia/arch/nvalloc/unix/include/nv-ioctl-numa.h \
$NVKERN_SRC /src/nvidia/arch/nvalloc/unix/include/nv-unix-nvos-params-wrappers.h \
$NVKERN_SRC /src/common/sdk/nvidia/inc/alloc/alloc_channel.h \
$NVKERN_SRC /src/common/sdk/nvidia/inc/nvos.h \
$NVKERN_SRC /src/common/sdk/nvidia/inc/ctrl/ctrl0000/*.h \
$NVKERN_SRC /src/common/sdk/nvidia/inc/ctrl/ctrl0080/*.h \
$NVKERN_SRC /src/common/sdk/nvidia/inc/ctrl/ctrl2080/*.h \
$NVKERN_SRC /src/common/sdk/nvidia/inc/ctrl/ctrl83de/*.h \
$NVKERN_SRC /src/common/sdk/nvidia/inc/ctrl/ctrlc36f.h \
$NVKERN_SRC /src/common/sdk/nvidia/inc/ctrl/ctrlcb33.h \
$NVKERN_SRC /src/common/sdk/nvidia/inc/ctrl/ctrla06c.h \
--clang-args= " -include $NVKERN_SRC /src/common/sdk/nvidia/inc/nvtypes.h -I $NVKERN_SRC /src/common/inc -I $NVKERN_SRC /kernel-open/nvidia-uvm -I $NVKERN_SRC /kernel-open/common/inc -I $NVKERN_SRC /src/common/sdk/nvidia/inc -I $NVKERN_SRC /src/nvidia/arch/nvalloc/unix/include -I $NVKERN_SRC /src/common/sdk/nvidia/inc/ctrl " \
-o $BASE /nv_gpu.py -k cdefstum
fixup $BASE /nv_gpu.py
sed -i "s\(0000000001)\1\g" $BASE /nv_gpu.py
sed -i "s\import ctypes\import ctypes, os\g" $BASE /nv_gpu.py
sed -i 's/#\?\s\([A-Za-z0-9_]\+\) = MW ( \([0-9]\+\) : \([0-9]\+\) )/\1 = (\2 , \3)/' $BASE /nv_gpu.py # NVC6C0_QMDV03_00 processing
sed -i 's/#\sdef NVC6C0_QMD\([A-Za-z0-9_()]\+\):/def NVC6C0_QMD\1:/' $BASE /nv_gpu.py
sed -i 's/#\s*return MW(\([0-9i()*+]\+\):\([0-9i()*+]\+\))/ return (\1 , \2)/' $BASE /nv_gpu.py
sed -i 's/#\?\s*\(.*\)\s*=\s*\(NV\)\?BIT\(32\)\?\s*(\s*\([0-9]\+\)\s*)/\1 = (1 << \4)/' $BASE /nv_gpu.py # name = BIT(x) -> name = (1 << x)
sed -i "s/UVM_\([A-Za-z0-9_]\+\) = \['i', '(', '\([0-9]\+\)', ')'\]/UVM_\1 = \2/" $BASE /nv_gpu.py # UVM_name = ['i', '(', '<num>', ')'] -> UVM_name = <num>
2024-06-10 21:01:50 +08:00
# Parse status codes
sed -n ' 1i\
nv_status_codes = { }
/^NV_STATUS_CODE/ { s/^NV_STATUS_CODE( \( [ ^,] *\) , *\( [ ^,] *\) , *"\([^" ] *\) " ) *.* $/\1 = \2\nnv_status_codes[\1] = " \3 " /; p }' $NVKERN_SRC /src/common/sdk/nvidia/inc/nvstatuscodes.h >> $BASE /nv_gpu.py
2024-04-22 23:50:20 +08:00
python3 -c "import tinygrad.runtime.autogen.nv_gpu"
}
2024-05-31 23:48:57 +08:00
generate_amd( ) {
# clang2py broken when pass -x c++ to prev headers
clang2py extra/hip_gpu_driver/sdma_registers.h \
--clang-args= "-I/opt/rocm/include -x c++" \
-o $BASE /amd_gpu.py
sed 's/^\(.*\)\(\s*\/\*\)\(.*\)$/\1 #\2\3/; s/^\(\s*\*\)\(.*\)$/#\1\2/' extra/hip_gpu_driver/nvd.h >> $BASE /amd_gpu.py # comments
2024-06-01 22:06:44 +08:00
sed 's/^\(.*\)\(\s*\/\*\)\(.*\)$/\1 #\2\3/; s/^\(\s*\*\)\(.*\)$/#\1\2/' extra/hip_gpu_driver/sdma_v6_0_0_pkt_open.h >> $BASE /amd_gpu.py # comments
2024-05-31 23:48:57 +08:00
sed -i 's/#\s*define\s*\([^ \t]*\)(\([^)]*\))\s*\(.*\)/def \1(\2): return \3/' $BASE /amd_gpu.py # #define name(x) (smth) -> def name(x): return (smth)
sed -i '/#\s*define\s\+\([^ \t]\+\)\s\+\([^ ]\+\)/s//\1 = \2/' $BASE /amd_gpu.py # #define name val -> name = val
sed -e '/^reg/s/^\(reg[^ ]*\) [^ ]* \([^ ]*\) .*/\1 = \2/' \
-e '/^ix/s/^\(ix[^ ]*\) [^ ]* \([^ ]*\) .*/\1 = \2/' \
-e '/^[ \t]/d' \
extra/hip_gpu_driver/gc_11_0_0.reg >> $BASE /amd_gpu.py
fixup $BASE /amd_gpu.py
sed -i "s\import ctypes\import ctypes, os\g" $BASE /amd_gpu.py
python3 -c "import tinygrad.runtime.autogen.amd_gpu"
}
2024-02-15 21:14:34 +08:00
generate_hsa( ) {
clang2py \
/opt/rocm/include/hsa/hsa.h \
/opt/rocm/include/hsa/hsa_ext_amd.h \
2024-03-31 06:08:12 +08:00
/opt/rocm/include/hsa/amd_hsa_signal.h \
/opt/rocm/include/hsa/amd_hsa_queue.h \
2024-04-23 12:31:27 +08:00
/opt/rocm/include/hsa/amd_hsa_kernel_code.h \
2024-02-15 21:14:34 +08:00
/opt/rocm/include/hsa/hsa_ext_finalize.h /opt/rocm/include/hsa/hsa_ext_image.h \
2024-04-02 06:50:58 +08:00
/opt/rocm/include/hsa/hsa_ven_amd_aqlprofile.h \
2024-02-15 21:14:34 +08:00
--clang-args= "-I/opt/rocm/include" \
-o $BASE /hsa.py -l /opt/rocm/lib/libhsa-runtime64.so
2024-03-31 06:08:12 +08:00
2024-02-15 21:14:34 +08:00
fixup $BASE /hsa.py
2024-05-23 11:33:21 +08:00
sed -i "s\import ctypes\import ctypes, ctypes.util, os\g" $BASE /hsa.py
sed -i "s\ctypes.CDLL('/opt/rocm/lib/libhsa-runtime64.so')\ctypes.CDLL(os.getenv('ROCM_PATH')+'/lib/libhsa-runtime64.so' if os.getenv('ROCM_PATH') else ctypes.util.find_library('hsa-runtime64'))\g" $BASE /hsa.py
2024-02-15 21:14:34 +08:00
python3 -c "import tinygrad.runtime.autogen.hsa"
}
2024-06-21 16:36:51 +08:00
generate_io_uring( ) {
clang2py \
/usr/include/liburing.h \
/usr/include/linux/io_uring.h \
-o $BASE /io_uring.py
# clang2py can't parse defines
sed -r '/^#define __NR_io_uring/ s/^#define __(NR_io_uring[^ ]+) (.*)$/\1 = \2/; t; d' /usr/include/asm-generic/unistd.h >> $BASE /io_uring.py # io_uring syscalls numbers
sed -r '/^#define\s+([^ \t]+)\s+([^ \t]+)/ s/^#define\s+([^ \t]+)\s*([^/]*).*$/\1 = \2/; s/1U/1/g; s/0ULL/0/g; t; d' /usr/include/linux/io_uring.h >> $BASE /io_uring.py # #define name (val) -> name = val
fixup $BASE /io_uring.py
}
2024-06-29 19:37:33 +08:00
generate_libc( ) {
clang2py \
$( dpkg -L libc6-dev | grep sys/mman.h) \
$( dpkg -L libc6-dev | grep sys/syscall.h) \
2024-07-17 22:09:34 +08:00
/usr/include/elf.h \
2024-06-29 19:37:33 +08:00
/usr/include/unistd.h \
-o $BASE /libc.py
2024-07-17 22:09:34 +08:00
process_cdefines "/usr/include/elf.h" " $BASE /libc.py "
2024-06-29 19:37:33 +08:00
sed -i "s\import ctypes\import ctypes, ctypes.util, os\g" $BASE /libc.py
sed -i "s\FIXME_STUB\libc\g" $BASE /libc.py
sed -i "s\FunctionFactoryStub()\ctypes.CDLL(ctypes.util.find_library('c'))\g" $BASE /libc.py
fixup $BASE /libc.py
}
2024-01-27 04:25:03 +08:00
if [ " $1 " = = "opencl" ] ; then generate_opencl
elif [ " $1 " = = "hip" ] ; then generate_hip
2024-03-22 23:50:50 +08:00
elif [ " $1 " = = "comgr" ] ; then generate_comgr
2024-01-27 04:25:03 +08:00
elif [ " $1 " = = "cuda" ] ; then generate_cuda
2024-06-29 15:46:29 +08:00
elif [ " $1 " = = "nvrtc" ] ; then generate_nvrtc
2024-02-15 21:14:34 +08:00
elif [ " $1 " = = "hsa" ] ; then generate_hsa
2024-03-31 06:08:12 +08:00
elif [ " $1 " = = "kfd" ] ; then generate_kfd
2024-04-22 23:50:20 +08:00
elif [ " $1 " = = "nv" ] ; then generate_nv
2024-05-31 23:48:57 +08:00
elif [ " $1 " = = "amd" ] ; then generate_amd
2024-06-21 16:36:51 +08:00
elif [ " $1 " = = "io_uring" ] ; then generate_io_uring
2024-06-29 19:37:33 +08:00
elif [ " $1 " = = "libc" ] ; then generate_libc
elif [ " $1 " = = "all" ] ; then generate_opencl; generate_hip; generate_comgr; generate_cuda; generate_nvrtc; generate_hsa; generate_kfd; generate_nv; generate_amd; generate_io_uring; generate_libc
2024-01-27 04:25:03 +08:00
else echo " usage: $0 <type> "
fi