Skip to content
MrModelOSPublic

About

A compiler that translates CUDA PTX into native code. PTX -> LLVM IR -> native, no emulation.

Topics

Resources

Contributing

Stars

2 stars

Watchers

1 watching

Forks

Repository files navigation

ROUGE-V

A compiler that translates CUDA PTX into native code for RISC-V.

CI Tests Language License

English · Русский · 中文


nvcc does not produce machine code for a GPU. It produces PTX — a textual assembly with a published specification. Anything that can read PTX can compile it for a different target.

ROUGE-V does that: PTX → LLVM IR → native code, for RISC-V and its vector extension rv64gcv. It is a compiler, not an emulator — the translated kernel is compiled, not interpreted instruction by instruction.

Install

git clone https://github.com/MrModelOS/ROUGE-V.git
cd ROUGE-V
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build build
ctest --test-dir build --output-on-failure

Requires CMake ≥ 3.20, a C++17 compiler, and clang. nvcc is optional — it enables the vendor-PTX test.

Use

No build needed — two binaries with no dependencies beyond system libc:

curl -fsSL https://github.com/MrModelOS/ROUGE-V/releases/download/v0.1/rouge-v-0.1-linux-x86_64.tar.gz | tar xz -C ~/.local
export PATH="$HOME/.local/bin:$PATH"
ptx2ir kernel.ptx kernel.ll

Run it on an NVIDIA GPU (sm_75+, driver only, no toolkit needed at run time):

rouge-run --target nvptx64-nvidia-cuda kernel.ptx --emit-ptx kernel_gpu.ptx
# then fill the 3 EDIT points in software/rouge-compiler/examples/run_on_gpu.c
# (PTX path, kernel name, buffers/launch) and build it against libcuda

(Arch Linux: packaging/PKGBUILD for a manual build. packaging/install.sh does the above.)

The question a user has is "will you translate my kernel?". One command answers it:

./build/rouge-compiler/rouge-run kernel.ptx
input: kernel.ptx
kernels found: 1
  @gemm_tile  params=3  instructions=67
  shared memory: 1024 bytes in 2 variable(s)
    shA          @   0     512 bytes  (.b16 x 256)
    shB          @ 512     512 bytes  (.b16 x 256)
translation: ok (10869 bytes of LLVM IR)

OK

Outside the supported subset you get a refusal, not a wrong answer:

rouge-run: REFUSED: unsupported PTX op 'mma.sync.aligned.m16n8k16...' @ 4
This instruction is outside the supported subset. Nothing was emitted;
nothing was approximated.

Emit a native object, or inspect the IR directly:

./build/rouge-compiler/rouge-run kernel.ptx -o kernel.o --print-ir
./build/rouge-compiler/ptx2ir kernel.ptx kernel.ll

Target RISC-V instead of the host:

clang --target=riscv64-unknown-elf -march=rv64gcv -c kernel.ll -o kernel-rv64.o

The triple itself is chosen on the translator side with --target, which is just a prefix of ptx2ir's arguments — the rest of the command is unchanged. The same PTX therefore builds for four platforms:

./build/rouge-compiler/ptx2ir --target amdgcn-amd-amdhsa kernel.ptx kernel-amd.ll
clang --target=amdgcn-amd-amdhsa -mcpu=gfx1100 -c kernel-amd.ll -o kernel-amd.o
--target Platform Backend flags What is actually verified
(default) x86_64-pc-linux-gnu host x86-64 — compiles and executes — the aot_native_* ctest suite
riscv64-unknown-elf RISC-V + Vector -march=rv64gcv compiles to a native object — ctest compiler_rvv_backend_*
amdgcn-amd-amdhsa AMD RDNA 3 -mcpu=gfx1100 compiles to a native object — never executed
nvptx64-nvidia-cuda NVIDIA -march=sm_75 compiles and executes on a real GPU — see below

All seven canonical kernels in software/rouge-compiler/tests/kernels/ — vadd, block_reduce, atomic_reduce, fp16_reduce, gemm_tile, shfl_reduce, atom_cas — build for all four triples.

Executed on real hardware

The NVIDIA kernels do not just compile: ctest compiler_nvptx_gpu_exec* loads the generated PTX through the CUDA Driver API (driver-side JIT) on a real GeForce MX450 (sm_75) and checks every output bit-exactly against a host reference — all seven canonical kernels, two datasets for fp16_reduce/gemm_tile, plus a two-block grid proving the multi-block path. compiler_nvcc_gpu_exec additionally runs genuine vendor output (nvcc real_nvcc.cu) end to end. On machines without an sm_75+ NVIDIA GPU the tests report SKIP, never failure.

The AMD row stays a compile-time claim: no AMD device is involved anywhere in the project. Neither row says anything about performance — only bit-identity against the host reference was measured. The target changes the address spaces in the emitted IR, which is what lets those backends emit global_load/ global_store instead of scalar accesses — see docs/06-compiler-architecture.md.

Where the PTX comes from:

nvcc -arch=sm_75 -ptx kernel.cu -o kernel.ptx   # build from CUDA source
cuobjdump -ptx ./my_app > kernel.ptx             # extract from a fatbin

QUICKSTART.md covers the rest, including the minimal host driver needed to launch a translated kernel.

$ ctest --test-dir build
...
 7/21 aot_native_block_reduce ..............   Passed
 8/21 aot_native_atomic_reduce .............   Passed
13/21 compiler_nvcc_ptx ....................   Passed
19/21 compiler_nvptx_gpu_exec ..............   Passed
21/21 compiler_nvcc_gpu_exec ...............   Passed
100% tests passed out of 21

Note

compiler_nvcc_ptx compiles real CUDA C with the vendor's own nvcc and pushes the resulting PTX through the whole pipeline. It skips when nvcc is not installed.

Important

Instructions outside the supported subset fail with an error naming the instruction. There is no silent miscompilation — a wrong answer is worse than a refusal.

Components

Component What it is
rouge-ptx Shared PTX front-end: parser + reference interpreter
rouge-compiler ptx2ir, the AOT translator; host runtime; MLIR contour
rouge-cuda CUDA Driver/Runtime API interposition and fallback execution path

Both execution paths are built on the same parser. That is deliberate: one grammar, one set of rules for registers, parameters, .shared layout and labels, so the paths cannot drift apart. The suite is built around the requirement that they agree bit-for-bit on every kernel.

Supported PTX

Group Instructions
Parameters ld.param.{u32,u64} and signed/bit variants
Moves mov.*, cvta.to.global.*, cvta.to.shared.*
Arithmetic add sub mul div rem, mad.lo mad.hi, mul.wide.*
Bitwise / shift and or xor not, shl, shr.{u,s}, bfi bfe
Compare setp.{ge,gt,lt,le,eq,ne}.{u32,s32,f32}
Select selp.*, slct.*, predicate and or not
Min / max / unary min max.*, neg, abs, popc, clz, bfind.shiftamt
Floating point f16 / bf16 arithmetic, fma.rn, sqrt, rcp, rsqrt, fneg
Memory ld/st global and shared: f32 u32 u64 u8/s8 u16/s16 f16 bf16 v2.f32
Shared memory .shared declarations, cvta.to.shared, [reg+offset] indexing
Synchronization bar.sync → runtime barrier
Warp shfl.{idx,bfly,up,down} (incl. predicated destinations), vote.*, activemask
Atomics atom.add cas exch min max, red.add.* → atomicrmw / cmpxchg

Tensor instructions (mma), warp f16x2 vector forms, and cvt.sat rounding modes are not implemented yet and are reported as errors.

Documentation

docs/06-compiler-architecture.md — launch descriptor, shared-memory layout, bar.sync model, atomics, FP16/BF16 lowering, and the planned SIMT → RVV path.

Building on ROUGE-V

If you maintain a project that uses ROUGE-V — a fork, a binding, a backend — please note in your README that it is not built by the ROUGE-V team and is not affiliated with it.

Legal

ROUGE-V contains no NVIDIA source code, headers, or binaries, and performs no reverse engineering of them. The PTX it compiles is produced by the user's own nvcc installation, under the user's NVIDIA license, from a published specification. The CUDA API headers under software/rouge-cuda/include/ are written from scratch against public API documentation. The clean-room rule is enforced in CONTRIBUTING.md.

ROUGE-V is not affiliated with, endorsed by, or supported by NVIDIA. CUDA and other trademarks are the property of their respective owners and are used here only to describe compatibility.

Contributing

Read CONTRIBUTING.md first — it covers the build, the test workflow, and the clean-room requirement that applies to all contributions. Issues and pull requests are open.

Acknowledgements

  • LLVM / MLIR — the IR, backend, and pass infrastructure this is written against
  • RISC-V International — the rv64gcv ISA and Vector Extension specifications
  • NVIDIA — the published PTX ISA and CUDA API documentation, which define the input format

License

Apache 2.0 WITH LLVM-exception — the same license as LLVM, so this code can live inside LLVM and MLIR without friction.

About

A compiler that translates CUDA PTX into native code. PTX -> LLVM IR -> native, no emulation.

Topics

Resources

Contributing

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages