How to Transpile MLIR to C
Prerequisites
-
uvinstalled (Python environment manager) -
A valid StableHLO MLIR file (see How to Export StableHLO from SKaiNET)
Understand the Generated Code
The transpiler produces C source following coralnpu_v2_binary conventions:
// Input arrays — placed in DTCM via section attribute
float input_0[48] __attribute__((section(".data")));
// Output arrays — also in DTCM
float output_0[16] __attribute__((section(".data")));
// Compile-time constants — placed in ITCM (.rodata)
static const float v0[3] = {0.2989f, 0.587f, 0.114f};
int main() {
// Generated loop nest
for (int i = 0; i < 16; i++) {
float sum = 0.0f;
for (int c = 0; c < 3; c++) {
sum += input_0[c * 16 + i] * v0[c];
}
output_0[i] = sum;
}
return 0;
}
Naming Conventions
| MLIR | C | Rule |
|---|---|---|
|
|
Function arguments become indexed input arrays |
Return values |
|
Return operands become indexed output arrays |
|
|
SSA names become C variable names (% stripped) |
|
|
Shape flattened to element count; f16/f32 → |
Supported StableHLO Operations
| Operation | C Translation |
|---|---|
|
|
|
No-op — aliased to the same C variable |
|
Optimized 2-loop nest |
|
7-deep loop nest with stride/dilation/padding |
|
|
|
|
|
|
|
|
Limitations
-
Only float32 computation (no quantized int8/int16)
-
No tiling for large tensors — all data must fit in DTCM
-
No SIMD intrinsics — relies on Clang
-O3auto-vectorization -
Regex-based MLIR parsing — may fail on non-standard formatting
Next Steps
-
How to Build an ELF for the NPU — compile the generated C to a RISC-V ELF