Generates Zig bindings from CMSIS-SVD files.
svd2zig parses an SVD device description and emits Zig source for its
peripherals, registers, fields, and enumerated values. It can be run standalone
or wired into a downstream zig build.
Pick the output shape with --style (default conduit):
conduit— each peripheral is a struct holding a conduitMmio, with register accessor methods over packed-struct field types. Read-only registers get only a reader, write-only only a writer. The SVDbase_addressis exposed andfromBase()builds anMmio.directover it.regz— standalone, microzig-regz-like: each peripheral is anextern structof registers laid at their offsets, reached through a typed volatile pointer in aperipheralsnamespace. A smallMmiohelper is emitted inline.consts— plain offset/shift/mask/enum constants in nested namespaces. No structs or accessors.
All styles handle derivedFrom, dim arrays, clusters, and enumeratedValues.
Input that cannot be represented faithfully is a hard error, not a silent gap.
svd2zig [--style conduit|regz|consts] <input.svd> [-o output.zig]Writes to -o or stdout. Names are converted to Zig conventions (TitleCase
types, snake_case declarations), with Zig keywords escaped as @"...".
Add svd2zig as a dependency, then generate a module from your SVD:
// build.zig
const svd2zig = @import("svd2zig");
const svd2zig_dep = b.dependency("svd2zig", .{});
const regs = svd2zig.addGenerate(b, svd2zig_dep, .{
.svd = b.path("chip.svd"),
.style = .conduit,
.name = "regs",
});
exe.root_module.addImport("regs", regs);zig build test # unit, golden, and compile tests
nix flake check # the above, hermetically, plus formattingGolden output lives in test/golden/. When an emitter change is intentional,
regenerate it:
zig build
for s in consts regz conduit; do
./zig-out/bin/svd2zig --style "$s" test/fixtures/minimal.svd -o "test/golden/$s.zig"
done