diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c05cdb088684064f59151439bea2cf0640edc2a7..04e690dc684a55be2f2c52130d59a9a90b82ef10 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -186,18 +186,16 @@ arm64v9: riscv64: # RISC-V vector extension are currently not supported by GCC. - # Also, the image is built without the libomp package which is not yet available on Ubuntu. extends: .multiarch_template image: i10git.cs.fau.de:5005/pycodegen/pycodegen/riscv64 variables: - # explicitly set SIMD as detection does not appear to work on QEMU + # explicitly set SIMD as detection requires QEMU >= 8.1 PYSTENCILS_SIMD: "rvv" - QEMU_CPU: "rv64,v=true" + QEMU_CPU: "rv64,v=true,zicboz=true" before_script: - *multiarch_before_script - - sed -i 's/march=native/march=rv64imfdv/g' ~/.config/pystencils/config.json - - sed -i s/g\+\+/clang++/g ~/.config/pystencils/config.json - - sed -i 's/fopenmp/fopenmp=libgomp -I\/usr\/include\/riscv64-linux-gnu/g' ~/.config/pystencils/config.json + - sed -i 's/march=native/march=rv64imfdvzicboz/g' ~/.config/pystencils/config.json + - sed -i s/g\+\+/clang++-15/g ~/.config/pystencils/config.json minimal-conda: stage: pretest diff --git a/src/pystencils/backends/riscv_instruction_sets.py b/src/pystencils/backends/riscv_instruction_sets.py index 948a645c945cfddf4800422b4d0b77fab7ee96aa..e456c2b8c05facda6f422d5061832331979c889f 100644 --- a/src/pystencils/backends/riscv_instruction_sets.py +++ b/src/pystencils/backends/riscv_instruction_sets.py @@ -98,9 +98,12 @@ def get_vector_instruction_set_riscv(data_type='double', instruction_set='rvv'): result['int'] = f'vint{bits["int"]}m1_t' result['bool'] = f'vbool{bits[data_type]}_t' - result['headers'] = ['<riscv_vector.h>'] + result['headers'] = ['<riscv_vector.h>', '"riscv_v_helpers.h"'] result['any'] += ' > 0x0' result['all'] += f' == vsetvl_e{bits[data_type]}m1({vl})' + result['cachelineSize'] = 'cachelineSize()' + result['cachelineZero'] = 'cachelineZero((void*) {0})' + return result diff --git a/src/pystencils/include/riscv_v_helpers.h b/src/pystencils/include/riscv_v_helpers.h new file mode 100644 index 0000000000000000000000000000000000000000..1969521ca273fa3f27ab86d164c6d3b3f070090d --- /dev/null +++ b/src/pystencils/include/riscv_v_helpers.h @@ -0,0 +1,49 @@ +inline void cachelineZero(void * p) { +#ifdef __riscv_zicboz + __asm__ volatile("cbo.zero (%0)"::"r"(p):"memory"); +#endif +} + +inline size_t _cachelineSize() { + // allocate and fill with ones + const size_t max_size = 0x100000; + uint8_t data[2*max_size]; + for (size_t i = 0; i < 2*max_size; ++i) { + data[i] = 0xff; + } + + // find alignment offset + size_t offset = max_size - ((uintptr_t) data) % max_size; + + // zero a cacheline + cachelineZero((void*) (data + offset)); + + // make sure that at least one byte was zeroed + if (data[offset] != 0) { + return SIZE_MAX; + } + + // make sure that nothing was zeroed before the pointer + if (data[offset-1] == 0) { + return SIZE_MAX; + } + + // find the last byte that was zeroed + for (size_t size = 1; size < max_size; ++size) { + if (data[offset + size] != 0) { + return size; + } + } + + // too much was zeroed + return SIZE_MAX; +} + +inline size_t cachelineSize() { +#ifdef __riscv_zicboz + static size_t size = _cachelineSize(); + return size; +#else + return SIZE_MAX; +#endif +} diff --git a/tests/test_vectorization.py b/tests/test_vectorization.py index 302d8cbd9de5c53e60bb0b43d24e2ab1d8155228..d3066e1dfb863d806ce151849b55641e0ba3f4e0 100644 --- a/tests/test_vectorization.py +++ b/tests/test_vectorization.py @@ -146,7 +146,7 @@ def test_aligned_and_nt_stores(openmp, instruction_set=instruction_set): if instruction_set in ['sse'] or instruction_set.startswith('avx'): assert 'stream' in ast.instruction_set assert 'streamFence' in ast.instruction_set - if instruction_set in ['neon', 'vsx'] or instruction_set.startswith('sve'): + if instruction_set in ['neon', 'vsx', 'rvv'] or instruction_set.startswith('sve'): assert 'cachelineZero' in ast.instruction_set if instruction_set in ['vsx']: assert 'storeAAndFlushCacheline' in ast.instruction_set