Skip to content

Registers Domain

The Registers domain generates code from hardware register map definitions, typically used for MCU peripherals, FPGA interfaces, or other memory-mapped hardware.

YAML Schema

name: string              # Required: Name for the register map
file: string              # Optional: Output filename (defaults to lowercase name)
regmap:                   # Required: List of registers
  - name: string          # Register name
    address: integer      # Register address (hex or decimal)
    description: string   # Optional: Human-readable description
    access: string        # Optional: Access type (default: "rw")
    bitfields:            # Required: List of bitfields
      - name: string
        width: integer    # Bit width
        offset: integer   # Bit offset from LSB
        reset: integer    # Reset value
        description: string
        enums:            # Optional: Enumeration values
          - name: string
            value: integer
            description: string

Access Types

Type Description
rw Read-write (default)
ro Read-only
wo Write-only
rw1c Read-write, write-1-to-clear
wosc Write-only, self-clearing
rolh Read-only, latch high

Example Configuration

name: SimpleRegmap
file: simple

regmap:
  - name: CONTROL
    description: Control register
    address: 0x00
    access: rw
    bitfields:
      - name: ENABLE
        description: Enable bit
        width: 1
        offset: 0
        reset: 0
      - name: MODE
        description: Operating mode
        width: 3
        offset: 1
        reset: 1
        enums:
          - { name: POWER_OFF, value: 0, description: "Device is off" }
          - { name: NORMAL, value: 1, description: "Normal operation" }
          - { name: STANDBY, value: 2, description: "Standby mode" }
          - { name: SLEEP, value: 3, description: "Sleep mode" }
      - name: RESET
        description: Software reset
        width: 1
        offset: 4
        reset: 0

  - name: STATUS
    description: Status register
    address: 0x04
    access: ro
    bitfields:
      - name: READY
        description: Ready status
        width: 1
        offset: 0
        reset: 1
      - name: BUSY
        description: Busy status
        width: 1
        offset: 1
        reset: 0
      - name: ERROR
        description: Error flag
        width: 1
        offset: 2
        reset: 0

  - name: DATA
    description: Data register
    address: 0x08
    bitfields:
      - name: VALUE
        description: Data value
        width: 16
        offset: 0
        reset: 0

Generated Outputs

C Header (--h)

embgen registers config.yml -o output/ --h

Generates:

  • <name>.h — Main header with:
    • Register addresses
    • Bitfield masks and offsets
    • Accessor macros
  • reg_common.h — Common register utilities
  • reg_common.c — Common register functions
// simple.h - Generated by embgen
#ifndef SIMPLE_H
#define SIMPLE_H

#include <stdint.h>
#include "reg_common.h"

// Register addresses
#define REG_CONTROL_ADDR    0x00
#define REG_STATUS_ADDR     0x04
#define REG_DATA_ADDR       0x08

// CONTROL register bitfields
#define CONTROL_ENABLE_OFFSET   0
#define CONTROL_ENABLE_MASK     0x00000001
#define CONTROL_MODE_OFFSET     1
#define CONTROL_MODE_MASK       0x0000000E
#define CONTROL_RESET_OFFSET    4
#define CONTROL_RESET_MASK      0x00000010

// MODE enumeration
typedef enum {
    CONTROL_MODE_POWER_OFF = 0,
    CONTROL_MODE_NORMAL = 1,
    CONTROL_MODE_STANDBY = 2,
    CONTROL_MODE_SLEEP = 3,
} ControlMode;

// Accessor macros
#define CONTROL_GET_ENABLE(reg) \
    (((reg) & CONTROL_ENABLE_MASK) >> CONTROL_ENABLE_OFFSET)
#define CONTROL_SET_ENABLE(reg, val) \
    (((reg) & ~CONTROL_ENABLE_MASK) | (((val) << CONTROL_ENABLE_OFFSET) & CONTROL_ENABLE_MASK))

// ... etc

#endif // SIMPLE_H

Python Module (--py)

embgen registers config.yml -o output/ --py

Generates Python classes with:

  • Register classes with address constants
  • Bitfield accessors as properties
  • Enumeration classes
# simple.py - Generated by embgen
from dataclasses import dataclass
from enum import IntEnum

class ControlMode(IntEnum):
    POWER_OFF = 0
    NORMAL = 1
    STANDBY = 2
    SLEEP = 3

@dataclass
class ControlRegister:
    ADDRESS = 0x00

    value: int = 0

    @property
    def enable(self) -> int:
        return (self.value >> 0) & 0x1

    @enable.setter
    def enable(self, val: int):
        self.value = (self.value & ~0x1) | ((val & 0x1) << 0)

    @property
    def mode(self) -> ControlMode:
        return ControlMode((self.value >> 1) & 0x7)

    @mode.setter
    def mode(self, val: ControlMode):
        self.value = (self.value & ~0xE) | ((val & 0x7) << 1)

# ... etc

Markdown Documentation (--md)

embgen registers config.yml -o output/ --md

Generates documentation with:

  • Register summary table
  • Detailed bitfield layouts
  • Visual bit diagrams
  • Enumeration value tables

Register Bit Layout Diagram

The Markdown output includes visual bit diagrams:

CONTROL (0x00) - Control register [RW]
┌────┬────┬────┬────┬────┬────┬────┬────┐
│ 7  │ 6  │ 5  │ 4  │ 3  │ 2  │ 1  │ 0  │
├────┴────┴────┼────┼────┴────┴────┼────┤
│   reserved   │RST │     MODE     │ EN │
└──────────────┴────┴──────────────┴────┘

CLI Usage

# Generate C header only
embgen registers config.yml -o output/ --h

# Generate all formats  
embgen registers config.yml -o output/ --h --py --md

# With debug output
embgen -d registers config.yml -o output/ --h

Python API Usage

from pathlib import Path
from embgen.discovery import discover_domains
from embgen.generator import CodeGenerator

domains = discover_domains()
code_gen = CodeGenerator(domains["registers"], Path("output"))

templates = {"h": "template.h.j2"}
code_gen.generate_from_file(Path("registers.yml"), templates)

Post-Generation Files

When generating C header output (--h), the Registers domain automatically copies these utility files:

  • reg_common.h — Common macros and type definitions
  • reg_common.c — Common register manipulation functions

These files provide platform-independent register access utilities.