|
2 | 2 |
|
3 | 3 |  |
4 | 4 |
|
5 | | -A systems language and compiler for RISC-V bare metal. No LLVM, no runtime, no external toolchain. Source code goes in, firmware binary comes out. |
| 5 | +a risc-v compiler. no llvm, no gcc, no runtime. source goes in, firmware comes out. |
6 | 6 |
|
7 | | -## why |
| 7 | +**[try it in your browser](https://kov.dev/playground)** -- no install needed. |
8 | 8 |
|
9 | | -Rust's embedded ecosystem gets peripheral ownership right, but it's a library pattern on top of a general-purpose language with a 2GB LLVM toolchain. RTIC and Embassy are good frameworks, but they're macros, not language features. WCET analysis exists as separate tools (aiT, WCC) that run after compilation, not during it. Zig has a self-hosted backend but no hardware awareness. Every embedded developer I've talked to spends more time fighting toolchains than writing application logic. |
| 9 | +## what is this |
10 | 10 |
|
11 | | -I want all of these things in one language, designed together from the start: peripheral ownership as a language primitive, cycle counting and stack proofs integrated into the compiler, interrupts as syntax not macros, board definitions as source code not linker scripts, and a compiler small enough to embed in a browser or hand to an AI agent. |
| 11 | +i wanted a language where the compiler knows about hardware. where claiming a gpio pin twice is a compile error. where the compiler can tell you your interrupt handler takes 47 cycles before you flash it. where the whole toolchain fits in 400KB of wasm and runs in a browser tab. |
12 | 12 |
|
13 | | -No single tool does all of this, so I'm building one that does. Mostly for myself, because I want it to exist. If other people find it useful, that's a bonus. |
| 13 | +nothing did all of that, so i built it. |
14 | 14 |
|
15 | | -## what it does (eventually) |
16 | | - |
17 | | -- Compiles a Rust-like language directly to RISC-V machine code |
18 | | -- Peripheral ownership as a language primitive, not a library pattern |
19 | | -- Cycle counting integrated into the compiler, not a separate analysis tool |
20 | | -- Stack depth proofs across the whole call graph, not per-function |
21 | | -- Interrupt handlers as language syntax with priority ceiling enforcement |
22 | | -- Board definitions as part of the grammar, not external config files |
23 | | -- No LLVM, no GCC, no external assembler, no external linker |
24 | | -- Sub-5ms compile times |
25 | | -- Agent-native: library API, JSON errors, deterministic output |
26 | | - |
27 | | -## where it is now |
28 | | - |
29 | | -The compiler works end-to-end. It compiles Kov source to RISC-V machine code and runs it in a built-in emulator that verifies GPIO register writes. |
| 15 | +## what it actually does |
30 | 16 |
|
31 | 17 | ``` |
32 | 18 | $ kov run examples/blink.kov |
33 | | - compiled: 416 bytes in 0.3ms |
34 | | - executed: 2000 cycles in 0.2ms |
35 | | - io: 215 writes |
36 | | - [0x60004004] ← 0x4 ← GPIO pin 2 HIGH |
37 | | - [0x60004008] ← 0x4 ← GPIO pin 2 LOW |
| 19 | + compiled: 492 bytes (400 compressed) in 0.6ms |
| 20 | + executed: 10000 cycles in 1.0ms |
| 21 | + io: 1214 writes |
| 22 | + [0x60004004] <- 0x4 GPIO pin 2 HIGH |
| 23 | + [0x60004008] <- 0x4 GPIO pin 2 LOW |
38 | 24 | ...repeating |
39 | 25 | ``` |
40 | 26 |
|
41 | | -80 tests, 4 example programs, ~4,500 lines of Rust. |
42 | | - |
43 | | -## try it |
| 27 | +``` |
| 28 | +$ kov wcet examples/blink.kov |
| 29 | + wcet analysis (2 functions): |
| 30 | + main(): 23 cycles |
| 31 | + on_tick(): 3 cycles |
| 32 | + stack analysis: |
| 33 | + main(): 16 bytes (frame: 16) |
| 34 | + on_tick(): 16 bytes (frame: 16) |
| 35 | + energy estimate: |
| 36 | + main(): 0.003 uJ (3400 pJ) |
| 37 | + on_tick(): 0.000 uJ (300 pJ) |
| 38 | +``` |
44 | 39 |
|
45 | 40 | ``` |
46 | | -cargo build |
47 | | -cargo run -- run examples/blink.kov |
48 | | -cargo run -- run examples/counter.kov |
49 | | -cargo run -- run examples/pattern.kov |
50 | | -cargo run -- build examples/blink.kov -o firmware.elf |
51 | | -cargo test |
| 41 | +$ kov repl |
| 42 | +kov> 3 + 4 |
| 43 | + = 7 (0x7) |
| 44 | +kov> 100 / 3 |
| 45 | + = 33 (0x21) |
52 | 46 | ``` |
53 | 47 |
|
54 | | -## example |
| 48 | +## the language |
55 | 49 |
|
56 | 50 | ``` |
57 | 51 | board esp32c3 { |
@@ -80,6 +74,40 @@ interrupt(timer0, priority = 2) fn on_tick() { |
80 | 74 | } |
81 | 75 | ``` |
82 | 76 |
|
| 77 | +peripheral ownership is a language feature. claim `gpio.pin(2)` twice and the compiler rejects it. the board definition is syntax, not a linker script. `#[stack(512)]` is a compile error if the call graph exceeds 512 bytes. |
| 78 | + |
| 79 | +## features that exist right now |
| 80 | + |
| 81 | +**language:** structs, enums with data, generics, traits, impl blocks, match with exhaustiveness, error unions + try, labeled loops, inline assembly, cast expressions, short-circuit && || |
| 82 | + |
| 83 | +**compiler:** 8 optimizer passes (constant folding, dce, cse, copy propagation, strength reduction, function inlining, tail call, rv32c compression), linear scan register allocator with liveness analysis, reproducible builds |
| 84 | + |
| 85 | +**safety:** `#[stack(N)]` and `#[max_cycles(N)]` enforced as compile errors, peripheral double-claim detection, interrupt safety (shared global detection), dma buffer typestate, no implicit integer promotion, match exhaustiveness |
| 86 | + |
| 87 | +**analysis:** wcet per function, stack depth across call graph, automatic loop bound derivation, energy estimation in microjoules |
| 88 | + |
| 89 | +**tooling:** 17 cli commands, built-in rv32im emulator, time-travel debugger (per-cycle trace), risc-v disassembler, lsp server, vs code extension, wasm playground (400KB), repl, c header import, svd parser, package manager |
| 90 | + |
| 91 | +**targets:** esp32c3, ch32v003, gd32vf103, fe310, stm32f4, nrf52840, rp2040 |
| 92 | + |
| 93 | +## try it |
| 94 | + |
| 95 | +``` |
| 96 | +cargo build |
| 97 | +cargo run -- run examples/blink.kov |
| 98 | +cargo run -- asm examples/blink.kov |
| 99 | +cargo run -- wcet examples/blink.kov |
| 100 | +cargo run -- repl |
| 101 | +cargo run -- check examples/blink.kov |
| 102 | +cargo test |
| 103 | +``` |
| 104 | + |
| 105 | +or just go to [kov.dev/playground](https://kov.dev/playground). |
| 106 | + |
| 107 | +## numbers |
| 108 | + |
| 109 | +210 tests. 15,500 lines of rust. 400KB wasm. 0.6ms compile time. 492 bytes for blink. 7 board targets. 17 cli commands. |
| 110 | + |
83 | 111 | ## license |
84 | 112 |
|
85 | 113 | Apache-2.0 |
0 commit comments