C code generator

A C header with register and field definitions can be generated with a call to RegisterList.create_c_header(). Below is the resulting code from the TOML format example:

example_regs.h
// This file is automatically generated by hdl_registers.
// Generated 2022-05-11 06:40 from file regs_example.toml at commit f957ef89efba5ca6.

#ifndef EXAMPLE_REGS_H
#define EXAMPLE_REGS_H

// Register constant "axi_data_width".
// Data width of the AXI port used by this module.
#define EXAMPLE_AXI_DATA_WIDTH (64)
// Register constant "address_alignment".
// The required address alignment for memory buffers.
#define EXAMPLE_ADDRESS_ALIGNMENT (4096)

// Number of registers within this register map.
#define EXAMPLE_NUM_REGS (9u)

// Type for the "base_addresses" register array.
typedef struct example_base_addresses_t
{
  // Mode "Read, Write".
  uint32_t read_address;
  // Mode "Read, Write".
  uint32_t write_address;
} example_base_addresses_t;

// Type for this register map.
typedef struct example_regs_t
{
  // This is the description of my register.
  // 
  // Rudimentary RST formatting can be used, such as **boldface** and *italics*.
  // Mode "Read, Write".
  uint32_t configuration;
  // Mode "Read".
  uint32_t status;
  // The value written to this register will be asserted for one clock cycle in the FPGA fabric.
  // Mode "Write-pulse".
  uint32_t command;
  example_base_addresses_t base_addresses[3];
} example_regs_t;

// Address of the "configuration" register. Mode "Read, Write".
// This is the description of my register.
// 
// Rudimentary RST formatting can be used, such as **boldface** and *italics*.
#define EXAMPLE_CONFIGURATION_INDEX (0u)
#define EXAMPLE_CONFIGURATION_ADDR (4u * EXAMPLE_CONFIGURATION_INDEX)
// Mask and shift for the "enable" field in the "configuration" register.
// Description of the **enable** bit field.
#define EXAMPLE_CONFIGURATION_ENABLE_SHIFT (0u)
#define EXAMPLE_CONFIGURATION_ENABLE_MASK (0b1u << 0u)
// Mask and shift for the "data_tag" field in the "configuration" register.
// Description of my **data_tag** bit vector field.
#define EXAMPLE_CONFIGURATION_DATA_TAG_SHIFT (1u)
#define EXAMPLE_CONFIGURATION_DATA_TAG_MASK (0b1111u << 1u)

// Address of the "status" register. Mode "Read".
#define EXAMPLE_STATUS_INDEX (1u)
#define EXAMPLE_STATUS_ADDR (4u * EXAMPLE_STATUS_INDEX)
// Mask and shift for the "idle" field in the "status" register.
// '1' when the module is inactive and a new run can be launched.
// 
// '0' when the module is working.
#define EXAMPLE_STATUS_IDLE_SHIFT (0u)
#define EXAMPLE_STATUS_IDLE_MASK (0b1u << 0u)
// Mask and shift for the "stalling" field in the "status" register.
// '1' if the module is currently being stalled.
#define EXAMPLE_STATUS_STALLING_SHIFT (1u)
#define EXAMPLE_STATUS_STALLING_MASK (0b1u << 1u)
// Mask and shift for the "counter" field in the "status" register.
// Number of bursts that have finished.
#define EXAMPLE_STATUS_COUNTER_SHIFT (2u)
#define EXAMPLE_STATUS_COUNTER_MASK (0b11111111u << 2u)

// Address of the "command" register. Mode "Write-pulse".
// The value written to this register will be asserted for one clock cycle in the FPGA fabric.
#define EXAMPLE_COMMAND_INDEX (2u)
#define EXAMPLE_COMMAND_ADDR (4u * EXAMPLE_COMMAND_INDEX)
// Mask and shift for the "start" field in the "command" register.
// Write this bit to start operation.
#define EXAMPLE_COMMAND_START_SHIFT (0u)
#define EXAMPLE_COMMAND_START_MASK (0b1u << 0u)
// Mask and shift for the "flush" field in the "command" register.
// Write this bit to flush data in progress.
#define EXAMPLE_COMMAND_FLUSH_SHIFT (1u)
#define EXAMPLE_COMMAND_FLUSH_MASK (0b1u << 1u)

// Address of the "read_address" register within the "base_addresses" register array (array_index < 3). Mode "Read, Write".
#define EXAMPLE_BASE_ADDRESSES_READ_ADDRESS_INDEX(array_index) (3u + (array_index) * 2u + 0u)
#define EXAMPLE_BASE_ADDRESSES_READ_ADDRESS_ADDR(array_index) (4u * EXAMPLE_BASE_ADDRESSES_READ_ADDRESS_INDEX(array_index))
// Mask and shift for the "address" field in the "read_address" register within the "base_addresses" register array.
// Read address for a 256 MiB address space.
#define EXAMPLE_BASE_ADDRESSES_READ_ADDRESS_ADDRESS_SHIFT (0u)
#define EXAMPLE_BASE_ADDRESSES_READ_ADDRESS_ADDRESS_MASK (0b1111111111111111111111111111u << 0u)

// Address of the "write_address" register within the "base_addresses" register array (array_index < 3). Mode "Read, Write".
#define EXAMPLE_BASE_ADDRESSES_WRITE_ADDRESS_INDEX(array_index) (3u + (array_index) * 2u + 1u)
#define EXAMPLE_BASE_ADDRESSES_WRITE_ADDRESS_ADDR(array_index) (4u * EXAMPLE_BASE_ADDRESSES_WRITE_ADDRESS_INDEX(array_index))
// Mask and shift for the "address" field in the "write_address" register within the "base_addresses" register array.
// Write address for a 256 MiB address space.
#define EXAMPLE_BASE_ADDRESSES_WRITE_ADDRESS_ADDRESS_SHIFT (0u)
#define EXAMPLE_BASE_ADDRESSES_WRITE_ADDRESS_ADDRESS_MASK (0b1111111111111111111111111111u << 0u)

#endif // EXAMPLE_REGS_H

It provides two methods for usage: A struct that can be memory mapped, or address definitions that can be offset a base address. For the addresses, array registers use a macro with an array index argument.