Register arrays

A register list, i.e. the register set of one module, can contain register arrays. Meaning, a set of registers within the register list that are repeated a number of times.

This page will show you how to set up register arrays, and will showcase all the code that can be generated from it.

Usage in TOML

The TOML file below shows how to set up a register array. See comments for rules about the different properties.

TOML that sets up a register array.
 1[base_addresses]
 2
 3# The "type" property MUST be present and set to "register_array".
 4type = "register_array"
 5
 6# The "array_length" property MUST be present for a register array.
 7# The value specified MUST be a positive integer.
 8# The registers within the array will be repeated this many times.
 9array_length = 3
10
11# The "description" property is OPTIONAL for a register array.
12# Will default to "" if not specified.
13# The value specified MUST be a string.
14description = "One set of base addresses for each feature."
15
16
17# ------------------------------------------------------------------------------
18# This will allocate a register "read_address" in the "base_addresses" array.
19[base_addresses.read_address]
20
21# Registers in a register array follow the exact same rules as "plain" registers.
22# The properties that MUST be set or are OPTIONAL are the same.
23# Just as with plain registers, the "type" property can be left out or explicitly set to "register".
24# Fields (bits, bit vectors, ...) can be added to array registers in the same way.
25mode = "r_w"
26
27# This will allocate a bit vector field named "address" in the "read_address" register within
28# the "base_addresses" array.
29address.type = "bit_vector"
30address.width = 28
31address.description = "Read address for a 256 MiB address space."
32
33
34# ------------------------------------------------------------------------------
35[base_addresses.write_address]
36
37mode = "r_w"
38
39address.type = "bit_vector"
40address.width = 28
41address.description = "Write address for a 256 MiB address space."

Below you will see how you can parse this TOML file and generate artifacts from it.

Usage with Python API

The Python code below shows

  1. How to parse the TOML file listed above.

  2. How to create an identical register list when instead using the Python API.

  3. How to generate register artifacts.

Note that the result of the create_from_api call is identical to that of the parse_toml call. Meaning that using a TOML file or using the Python API is completely equivalent. You choose yourself which method you want to use in your code base.

Python code that sets up a register array.
 1# Standard libraries
 2import sys
 3from pathlib import Path
 4
 5# First party libraries
 6from hdl_registers.generator.c.header import CHeaderGenerator
 7from hdl_registers.generator.cpp.implementation import CppImplementationGenerator
 8from hdl_registers.generator.cpp.interface import CppInterfaceGenerator
 9from hdl_registers.generator.html.page import HtmlPageGenerator
10from hdl_registers.generator.vhdl.record_package import VhdlRecordPackageGenerator
11from hdl_registers.generator.vhdl.register_package import VhdlRegisterPackageGenerator
12from hdl_registers.parser.toml import from_toml
13from hdl_registers.register_list import RegisterList
14from hdl_registers.register_modes import REGISTER_MODES
15
16THIS_DIR = Path(__file__).parent
17
18
19def parse_toml() -> RegisterList:
20    """
21    Create the register list by parsing a TOML data file.
22    """
23    return from_toml(
24        name="caesar",
25        toml_file=THIS_DIR.parent / "toml" / "basic_feature_register_array.toml",
26    )
27
28
29def create_from_api() -> RegisterList:
30    """
31    Alternative method: Create the register list by using the Python API.
32    """
33    register_list = RegisterList(name="caesar")
34
35    register_array = register_list.append_register_array(
36        name="base_addresses", length=3, description="One set of base addresses for each feature."
37    )
38
39    register = register_array.append_register(
40        name="read_address", mode=REGISTER_MODES["r_w"], description=""
41    )
42
43    register.append_bit_vector(
44        name="address",
45        description="Read address for a 256 MiB address space.",
46        width=28,
47        default_value="0000000000000000000000000000",
48    )
49
50    register = register_array.append_register(
51        name="write_address", mode=REGISTER_MODES["r_w"], description=""
52    )
53
54    register.append_bit_vector(
55        name="address",
56        description="Write address for a 256 MiB address space.",
57        width=28,
58        default_value="0000000000000000000000000000",
59    )
60
61    return register_list
62
63
64def generate(register_list: RegisterList, output_folder: Path):
65    """
66    Generate the artifacts that we are interested in.
67    """
68    CHeaderGenerator(register_list=register_list, output_folder=output_folder).create()
69
70    CppImplementationGenerator(register_list=register_list, output_folder=output_folder).create()
71    CppInterfaceGenerator(register_list=register_list, output_folder=output_folder).create()
72
73    HtmlPageGenerator(register_list=register_list, output_folder=output_folder).create()
74
75    VhdlRegisterPackageGenerator(register_list=register_list, output_folder=output_folder).create()
76    VhdlRecordPackageGenerator(register_list=register_list, output_folder=output_folder).create()
77
78
79def main(output_folder: Path):
80    generate(register_list=parse_toml(), output_folder=output_folder / "toml")
81    generate(register_list=create_from_api(), output_folder=output_folder / "api")
82
83
84if __name__ == "__main__":
85    main(output_folder=Path(sys.argv[1]))

See RegisterList.append_register_array() for more Python API details.

Generated code

See below for a description of the code that can be generated when using register arrays.

HTML page

See HTML file below for the human-readable documentation that is produced by the generate() call in the Python example above.

See HTML code generator for more details about the HTML generator and its capabilities.

HTML page

VHDL package

The VHDL code below is produced by the generate() call in the Python example above. Click the button to expand and view the code. See VHDL code generator for instructions on how it can be used in your VHDL project.

Base register package

Note how the register indexes are functions here, as opposed to constants as they usually are for plain registers. The argument to the function decides which array index to use. There is an assertion that the array index argument does not exceed the number of times the register array is repeated.

Click to expand/collapse code.
Generated VHDL register package.
  1-- This file is automatically generated by hdl-registers version 6.1.1-dev.
  2-- Code generator VhdlRegisterPackageGenerator version 1.0.0.
  3-- Generated 2024-12-01 20:51 at commit 2ca830a4377d1e32.
  4-- Register hash d398508c05f52d1800bf8d33954a99a6ebc864d8.
  5
  6library ieee;
  7use ieee.std_logic_1164.all;
  8use ieee.numeric_std.all;
  9use ieee.fixed_pkg.all;
 10
 11library reg_file;
 12use reg_file.reg_file_pkg.all;
 13
 14
 15package caesar_regs_pkg is
 16
 17  -- ---------------------------------------------------------------------------
 18  -- The valid range of register indexes.
 19  subtype caesar_reg_range is natural range 0 to 5;
 20
 21  -- Number of times the 'base_addresses' register array is repeated.
 22  constant caesar_base_addresses_array_length : natural := 3;
 23  -- Range for indexing 'base_addresses' register array repetitions.
 24  subtype caesar_base_addresses_range is natural range 0 to 2;
 25
 26  -- Register indexes, within the list of registers.
 27  function caesar_base_addresses_read_address(
 28    array_index : caesar_base_addresses_range
 29  ) return caesar_reg_range;
 30  function caesar_base_addresses_write_address(
 31    array_index : caesar_base_addresses_range
 32  ) return caesar_reg_range;
 33
 34  -- Declare 'reg_map' and 'regs_init' constants here but define them in body (deferred constants).
 35  -- So that functions have been elaborated when they are called.
 36  -- Needed for ModelSim compilation to pass.
 37
 38  -- To be used as the 'regs' generic of 'axi_lite_reg_file.vhd'.
 39  constant caesar_reg_map : reg_definition_vec_t(caesar_reg_range);
 40
 41  -- To be used for the 'regs_up' and 'regs_down' ports of 'axi_lite_reg_file.vhd'.
 42  subtype caesar_regs_t is reg_vec_t(caesar_reg_range);
 43  -- To be used as the 'default_values' generic of 'axi_lite_reg_file.vhd'.
 44  constant caesar_regs_init : caesar_regs_t;
 45
 46  -- To be used for the 'reg_was_read' and 'reg_was_written' ports of 'axi_lite_reg_file.vhd'.
 47  subtype caesar_reg_was_accessed_t is std_ulogic_vector(caesar_reg_range);
 48
 49  -- -----------------------------------------------------------------------------
 50  -- Fields in the 'read_address' register within the 'base_addresses' register array.
 51  -- Range of the 'address' field.
 52  subtype caesar_base_addresses_read_address_address is natural range 27 downto 0;
 53  -- Width of the 'address' field.
 54  constant caesar_base_addresses_read_address_address_width : positive := 28;
 55  -- Type for the 'address' field.
 56  subtype caesar_base_addresses_read_address_address_t is u_unsigned(27 downto 0);
 57  -- Default value of the 'address' field.
 58  constant caesar_base_addresses_read_address_address_init : caesar_base_addresses_read_address_address_t := "0000000000000000000000000000";
 59
 60  -- -----------------------------------------------------------------------------
 61  -- Fields in the 'write_address' register within the 'base_addresses' register array.
 62  -- Range of the 'address' field.
 63  subtype caesar_base_addresses_write_address_address is natural range 27 downto 0;
 64  -- Width of the 'address' field.
 65  constant caesar_base_addresses_write_address_address_width : positive := 28;
 66  -- Type for the 'address' field.
 67  subtype caesar_base_addresses_write_address_address_t is u_unsigned(27 downto 0);
 68  -- Default value of the 'address' field.
 69  constant caesar_base_addresses_write_address_address_init : caesar_base_addresses_write_address_address_t := "0000000000000000000000000000";
 70
 71end package;
 72
 73package body caesar_regs_pkg is
 74
 75  function caesar_base_addresses_read_address(
 76    array_index : caesar_base_addresses_range
 77  ) return caesar_reg_range is
 78  begin
 79    return 0 + array_index * 2 + 0;
 80  end function;
 81
 82  function caesar_base_addresses_write_address(
 83    array_index : caesar_base_addresses_range
 84  ) return caesar_reg_range is
 85  begin
 86    return 0 + array_index * 2 + 1;
 87  end function;
 88
 89  constant caesar_reg_map : reg_definition_vec_t(caesar_reg_range) := (
 90    0 => (idx => caesar_base_addresses_read_address(0), reg_type => r_w),
 91    1 => (idx => caesar_base_addresses_write_address(0), reg_type => r_w),
 92    2 => (idx => caesar_base_addresses_read_address(1), reg_type => r_w),
 93    3 => (idx => caesar_base_addresses_write_address(1), reg_type => r_w),
 94    4 => (idx => caesar_base_addresses_read_address(2), reg_type => r_w),
 95    5 => (idx => caesar_base_addresses_write_address(2), reg_type => r_w)
 96  );
 97
 98  constant caesar_regs_init : caesar_regs_t := (
 99    0 => "00000000000000000000000000000000",
100    1 => "00000000000000000000000000000000",
101    2 => "00000000000000000000000000000000",
102    3 => "00000000000000000000000000000000",
103    4 => "00000000000000000000000000000000",
104    5 => "00000000000000000000000000000000"
105  );
106
107end package body;

Record package

The record package is quite hard to understand in this example, but lets try:

  • The caesar_regs_down_t type is a record with a member base_addresses, which is the name of the register array.

  • The type of this member is a ranged array of another record with two members: read_address and write_address, which are the names of the registers in the array.

  • Both of these are of a record type that contain the address bit vector field set up in this example.

So in our VHDL code we can access a field value for example like this:

job.address <= regs_down.base_addresses[1].read_address.address;
Click to expand/collapse code.
Generated VHDL record package.
  1-- This file is automatically generated by hdl-registers version 6.1.1-dev.
  2-- Code generator VhdlRecordPackageGenerator version 1.0.0.
  3-- Generated 2024-12-01 20:51 at commit 2ca830a4377d1e32.
  4-- Register hash d398508c05f52d1800bf8d33954a99a6ebc864d8.
  5
  6library ieee;
  7use ieee.fixed_pkg.all;
  8use ieee.std_logic_1164.all;
  9use ieee.numeric_std.all;
 10
 11library reg_file;
 12use reg_file.reg_file_pkg.reg_t;
 13
 14use work.caesar_regs_pkg.all;
 15
 16
 17package caesar_register_record_pkg is
 18
 19  -- -----------------------------------------------------------------------------
 20  -- Record with correctly-typed members for each field in each register.
 21  -- Fields in the 'read_address' register within the 'base_addresses' register array as a record.
 22  type caesar_base_addresses_read_address_t is record
 23    address : caesar_base_addresses_read_address_address_t;
 24  end record;
 25  -- Default value for the 'read_address' register within the 'base_addresses' register array as a record.
 26  constant caesar_base_addresses_read_address_init : caesar_base_addresses_read_address_t := (
 27    address => caesar_base_addresses_read_address_address_init
 28  );
 29  -- Convert a record of the 'read_address' register within the 'base_addresses' register array to SLV.
 30  function to_slv(data : caesar_base_addresses_read_address_t) return reg_t;
 31  -- Convert an SLV register value to the record for the 'read_address' register within the 'base_addresses' register array.
 32  function to_caesar_base_addresses_read_address(data : reg_t) return caesar_base_addresses_read_address_t;
 33
 34  -- Fields in the 'write_address' register within the 'base_addresses' register array as a record.
 35  type caesar_base_addresses_write_address_t is record
 36    address : caesar_base_addresses_write_address_address_t;
 37  end record;
 38  -- Default value for the 'write_address' register within the 'base_addresses' register array as a record.
 39  constant caesar_base_addresses_write_address_init : caesar_base_addresses_write_address_t := (
 40    address => caesar_base_addresses_write_address_address_init
 41  );
 42  -- Convert a record of the 'write_address' register within the 'base_addresses' register array to SLV.
 43  function to_slv(data : caesar_base_addresses_write_address_t) return reg_t;
 44  -- Convert an SLV register value to the record for the 'write_address' register within the 'base_addresses' register array.
 45  function to_caesar_base_addresses_write_address(data : reg_t) return caesar_base_addresses_write_address_t;
 46
 47  -- -----------------------------------------------------------------------------
 48  -- Below is a record with correctly typed and ranged members for all registers, register arrays
 49  -- and fields that are in the 'down' direction.
 50  -- But first, records for the registers of each register array the are in the 'down' direction.
 51  -- Registers of the 'base_addresses' array that are in the 'down' direction.
 52  type caesar_base_addresses_down_t is record
 53    read_address : caesar_base_addresses_read_address_t;
 54    write_address : caesar_base_addresses_write_address_t;
 55  end record;
 56  -- Default value of the above record.
 57  constant caesar_base_addresses_down_init : caesar_base_addresses_down_t := (
 58    read_address => caesar_base_addresses_read_address_init,
 59    write_address => caesar_base_addresses_write_address_init
 60  );
 61  -- VHDL array of the above record, ranged per the length of the 'base_addresses' register array.
 62  type caesar_base_addresses_down_vec_t is array (0 to 2) of caesar_base_addresses_down_t;
 63
 64  -- Record with everything in the 'down' direction.
 65  type caesar_regs_down_t is record
 66    base_addresses : caesar_base_addresses_down_vec_t;
 67  end record;
 68  -- Default value of the above record.
 69  constant caesar_regs_down_init : caesar_regs_down_t := (
 70    base_addresses => (others => caesar_base_addresses_down_init)
 71  );
 72  -- Convert SLV register list to record with everything in the 'down' direction.
 73  function to_caesar_regs_down(data : caesar_regs_t) return caesar_regs_down_t;
 74
 75  -- ---------------------------------------------------------------------------
 76  -- Below is a record with a status bit for each readable register in the register map.
 77  -- It can be used for the 'reg_was_read' port of a register file wrapper.
 78  -- One status bit for each readable register in the 'base_addresses' register array.
 79  type caesar_base_addresses_was_read_t is record
 80    read_address : std_ulogic;
 81    write_address : std_ulogic;
 82  end record;
 83  -- Default value of the above record.
 84  constant caesar_base_addresses_was_read_init : caesar_base_addresses_was_read_t := (others => '0');
 85  -- Vector of the above record, ranged per the length of the 'base_addresses' register array.
 86  type caesar_base_addresses_was_read_vec_t is array (0 to 2) of caesar_base_addresses_was_read_t;
 87
 88  -- Combined status mask record for all readable register.
 89  type caesar_reg_was_read_t is record
 90    base_addresses : caesar_base_addresses_was_read_vec_t;
 91  end record;
 92  -- Default value for the above record.
 93  constant caesar_reg_was_read_init : caesar_reg_was_read_t := (
 94    base_addresses => (others => caesar_base_addresses_was_read_init)
 95  );
 96  -- Convert an SLV 'reg_was_read' from generic register file to the record above.
 97  function to_caesar_reg_was_read(
 98    data : caesar_reg_was_accessed_t
 99  ) return caesar_reg_was_read_t;
100
101  -- ---------------------------------------------------------------------------
102  -- Below is a record with a status bit for each writeable register in the register map.
103  -- It can be used for the 'reg_was_written' port of a register file wrapper.
104  -- One status bit for each writeable register in the 'base_addresses' register array.
105  type caesar_base_addresses_was_written_t is record
106    read_address : std_ulogic;
107    write_address : std_ulogic;
108  end record;
109  -- Default value of the above record.
110  constant caesar_base_addresses_was_written_init : caesar_base_addresses_was_written_t := (others => '0');
111  -- Vector of the above record, ranged per the length of the 'base_addresses' register array.
112  type caesar_base_addresses_was_written_vec_t is array (0 to 2) of caesar_base_addresses_was_written_t;
113
114  -- Combined status mask record for all writeable register.
115  type caesar_reg_was_written_t is record
116    base_addresses : caesar_base_addresses_was_written_vec_t;
117  end record;
118  -- Default value for the above record.
119  constant caesar_reg_was_written_init : caesar_reg_was_written_t := (
120    base_addresses => (others => caesar_base_addresses_was_written_init)
121  );
122  -- Convert an SLV 'reg_was_written' from generic register file to the record above.
123  function to_caesar_reg_was_written(
124    data : caesar_reg_was_accessed_t
125  ) return caesar_reg_was_written_t;
126
127end package;
128
129package body caesar_register_record_pkg is
130
131  function to_slv(data : caesar_base_addresses_read_address_t) return reg_t is
132    variable result : reg_t := (others => '-');
133  begin
134    result(caesar_base_addresses_read_address_address) := std_ulogic_vector(data.address);
135
136    return result;
137  end function;
138
139  function to_caesar_base_addresses_read_address(data : reg_t) return caesar_base_addresses_read_address_t is
140    variable result : caesar_base_addresses_read_address_t := caesar_base_addresses_read_address_init;
141  begin
142    result.address := caesar_base_addresses_read_address_address_t(data(caesar_base_addresses_read_address_address));
143
144    return result;
145  end function;
146
147  function to_slv(data : caesar_base_addresses_write_address_t) return reg_t is
148    variable result : reg_t := (others => '-');
149  begin
150    result(caesar_base_addresses_write_address_address) := std_ulogic_vector(data.address);
151
152    return result;
153  end function;
154
155  function to_caesar_base_addresses_write_address(data : reg_t) return caesar_base_addresses_write_address_t is
156    variable result : caesar_base_addresses_write_address_t := caesar_base_addresses_write_address_init;
157  begin
158    result.address := caesar_base_addresses_write_address_address_t(data(caesar_base_addresses_write_address_address));
159
160    return result;
161  end function;
162
163  function to_caesar_regs_down(data : caesar_regs_t) return caesar_regs_down_t is
164    variable result : caesar_regs_down_t := caesar_regs_down_init;
165  begin
166    result.base_addresses(0).read_address := to_caesar_base_addresses_read_address(data(caesar_base_addresses_read_address(0)));
167    result.base_addresses(1).read_address := to_caesar_base_addresses_read_address(data(caesar_base_addresses_read_address(1)));
168    result.base_addresses(2).read_address := to_caesar_base_addresses_read_address(data(caesar_base_addresses_read_address(2)));
169    result.base_addresses(0).write_address := to_caesar_base_addresses_write_address(data(caesar_base_addresses_write_address(0)));
170    result.base_addresses(1).write_address := to_caesar_base_addresses_write_address(data(caesar_base_addresses_write_address(1)));
171    result.base_addresses(2).write_address := to_caesar_base_addresses_write_address(data(caesar_base_addresses_write_address(2)));
172
173    return result;
174  end function;
175
176  function to_caesar_reg_was_read(
177    data : caesar_reg_was_accessed_t
178  ) return caesar_reg_was_read_t is
179    variable result : caesar_reg_was_read_t := caesar_reg_was_read_init;
180  begin
181    result.base_addresses(0).read_address := data(caesar_base_addresses_read_address(array_index=>0));
182    result.base_addresses(1).read_address := data(caesar_base_addresses_read_address(array_index=>1));
183    result.base_addresses(2).read_address := data(caesar_base_addresses_read_address(array_index=>2));
184    result.base_addresses(0).write_address := data(caesar_base_addresses_write_address(array_index=>0));
185    result.base_addresses(1).write_address := data(caesar_base_addresses_write_address(array_index=>1));
186    result.base_addresses(2).write_address := data(caesar_base_addresses_write_address(array_index=>2));
187
188    return result;
189  end function;
190
191  function to_caesar_reg_was_written(
192    data : caesar_reg_was_accessed_t
193  ) return caesar_reg_was_written_t is
194    variable result : caesar_reg_was_written_t := caesar_reg_was_written_init;
195  begin
196    result.base_addresses(0).read_address := data(caesar_base_addresses_read_address(array_index=>0));
197    result.base_addresses(1).read_address := data(caesar_base_addresses_read_address(array_index=>1));
198    result.base_addresses(2).read_address := data(caesar_base_addresses_read_address(array_index=>2));
199    result.base_addresses(0).write_address := data(caesar_base_addresses_write_address(array_index=>0));
200    result.base_addresses(1).write_address := data(caesar_base_addresses_write_address(array_index=>1));
201    result.base_addresses(2).write_address := data(caesar_base_addresses_write_address(array_index=>2));
202
203    return result;
204  end function;
205
206end package body;

C++

The C++ interface header and implementation code below is produced by the generate() call in the Python example above. Click the button to expand and view each code block.

The class header is skipped here, since its inclusion would make this page very long. See C++ code generator for more details and an example of how the excluded file might look.

C++ interface header

Note how setters and getters for register and field values have a new argument for the array index.

Click to expand/collapse code.
Generated C++ interface class code.
  1// This file is automatically generated by hdl-registers version 6.1.1-dev.
  2// Code generator CppInterfaceGenerator version 1.0.0.
  3// Generated 2024-12-01 20:51 at commit 2ca830a4377d1e32.
  4// Register hash d398508c05f52d1800bf8d33954a99a6ebc864d8.
  5
  6#pragma once
  7
  8#include <cassert>
  9#include <cstdint>
 10#include <cstdlib>
 11
 12namespace fpga_regs
 13{
 14
 15  // Attributes for the 'address' field in the 'read_address' register within the 'base_addresses' register array.
 16  namespace caesar::base_addresses::read_address::address
 17  {
 18    static const auto width = 28;
 19    static const auto default_value = 0b0000000000000000000000000000;
 20  }
 21
 22  // Attributes for the 'address' field in the 'write_address' register within the 'base_addresses' register array.
 23  namespace caesar::base_addresses::write_address::address
 24  {
 25    static const auto width = 28;
 26    static const auto default_value = 0b0000000000000000000000000000;
 27  }
 28
 29  // Attributes for the "base_addresses" register array.
 30  namespace caesar::base_addresses
 31  {
 32    // Number of times the registers of the array are repeated.
 33    static const auto array_length = 3;
 34  };
 35
 36  class ICaesar
 37  {
 38  public:
 39    // Number of registers within this register map.
 40    static const size_t num_registers = 6uL;
 41
 42    virtual ~ICaesar() {}
 43
 44    // -------------------------------------------------------------------------
 45    // Methods for the 'read_address' register within the 'base_addresses' register array. Mode 'Read, Write'.
 46
 47    // Getter that will read the whole register's value over the register bus.
 48    virtual uint32_t get_base_addresses_read_address(
 49      size_t array_index
 50    ) const = 0;
 51
 52    // Setter that will write the whole register's value over the register bus.
 53    virtual void set_base_addresses_read_address(
 54      size_t array_index,
 55      uint32_t register_value
 56    ) const = 0;
 57
 58    // Getter for the 'address' field in the 'read_address' register within the 'base_addresses' register array,
 59    // which will read register value over the register bus.
 60    virtual uint32_t get_base_addresses_read_address_address(
 61      size_t array_index
 62    ) const = 0;
 63    // Getter for the 'address' field in the 'read_address' register within the 'base_addresses' register array,
 64    // given a register value.
 65    virtual uint32_t get_base_addresses_read_address_address_from_value(
 66      uint32_t register_value
 67    ) const = 0;
 68    // Setter for the 'address' field in the 'read_address' register within the 'base_addresses' register array,
 69    // which will set the field to the given value, and everything else to default.
 70    virtual void set_base_addresses_read_address_address(
 71      size_t array_index,
 72      uint32_t field_value
 73    ) const = 0;
 74    // Setter for the 'address' field in the 'read_address' register within the 'base_addresses' register array,
 75    // given a register value, which will return an updated value.
 76    virtual uint32_t set_base_addresses_read_address_address_from_value(
 77      uint32_t register_value,
 78      uint32_t field_value
 79    ) const = 0;
 80
 81    // -------------------------------------------------------------------------
 82    // Methods for the 'write_address' register within the 'base_addresses' register array. Mode 'Read, Write'.
 83
 84    // Getter that will read the whole register's value over the register bus.
 85    virtual uint32_t get_base_addresses_write_address(
 86      size_t array_index
 87    ) const = 0;
 88
 89    // Setter that will write the whole register's value over the register bus.
 90    virtual void set_base_addresses_write_address(
 91      size_t array_index,
 92      uint32_t register_value
 93    ) const = 0;
 94
 95    // Getter for the 'address' field in the 'write_address' register within the 'base_addresses' register array,
 96    // which will read register value over the register bus.
 97    virtual uint32_t get_base_addresses_write_address_address(
 98      size_t array_index
 99    ) const = 0;
100    // Getter for the 'address' field in the 'write_address' register within the 'base_addresses' register array,
101    // given a register value.
102    virtual uint32_t get_base_addresses_write_address_address_from_value(
103      uint32_t register_value
104    ) const = 0;
105    // Setter for the 'address' field in the 'write_address' register within the 'base_addresses' register array,
106    // which will set the field to the given value, and everything else to default.
107    virtual void set_base_addresses_write_address_address(
108      size_t array_index,
109      uint32_t field_value
110    ) const = 0;
111    // Setter for the 'address' field in the 'write_address' register within the 'base_addresses' register array,
112    // given a register value, which will return an updated value.
113    virtual uint32_t set_base_addresses_write_address_address_from_value(
114      uint32_t register_value,
115      uint32_t field_value
116    ) const = 0;
117
118  };
119
120} /* namespace fpga_regs */

C++ implementation

The C++ implementation code below is produced by the generate() call in the Python example above. Click the button to expand and view the code.

Note that there is an assertion in every setter and getter that the provided array index does not exceed the number of times the register array is repeated. This will catch calculation errors during testing and at run-time.

Click to expand/collapse code.
Generated C++ interface class code.
  1// This file is automatically generated by hdl-registers version 6.1.1-dev.
  2// Code generator CppInterfaceGenerator version 1.0.0.
  3// Generated 2024-12-01 20:51 at commit 2ca830a4377d1e32.
  4// Register hash d398508c05f52d1800bf8d33954a99a6ebc864d8.
  5
  6#pragma once
  7
  8#include <cassert>
  9#include <cstdint>
 10#include <cstdlib>
 11
 12namespace fpga_regs
 13{
 14
 15  // Attributes for the 'address' field in the 'read_address' register within the 'base_addresses' register array.
 16  namespace caesar::base_addresses::read_address::address
 17  {
 18    static const auto width = 28;
 19    static const auto default_value = 0b0000000000000000000000000000;
 20  }
 21
 22  // Attributes for the 'address' field in the 'write_address' register within the 'base_addresses' register array.
 23  namespace caesar::base_addresses::write_address::address
 24  {
 25    static const auto width = 28;
 26    static const auto default_value = 0b0000000000000000000000000000;
 27  }
 28
 29  // Attributes for the "base_addresses" register array.
 30  namespace caesar::base_addresses
 31  {
 32    // Number of times the registers of the array are repeated.
 33    static const auto array_length = 3;
 34  };
 35
 36  class ICaesar
 37  {
 38  public:
 39    // Number of registers within this register map.
 40    static const size_t num_registers = 6uL;
 41
 42    virtual ~ICaesar() {}
 43
 44    // -------------------------------------------------------------------------
 45    // Methods for the 'read_address' register within the 'base_addresses' register array. Mode 'Read, Write'.
 46
 47    // Getter that will read the whole register's value over the register bus.
 48    virtual uint32_t get_base_addresses_read_address(
 49      size_t array_index
 50    ) const = 0;
 51
 52    // Setter that will write the whole register's value over the register bus.
 53    virtual void set_base_addresses_read_address(
 54      size_t array_index,
 55      uint32_t register_value
 56    ) const = 0;
 57
 58    // Getter for the 'address' field in the 'read_address' register within the 'base_addresses' register array,
 59    // which will read register value over the register bus.
 60    virtual uint32_t get_base_addresses_read_address_address(
 61      size_t array_index
 62    ) const = 0;
 63    // Getter for the 'address' field in the 'read_address' register within the 'base_addresses' register array,
 64    // given a register value.
 65    virtual uint32_t get_base_addresses_read_address_address_from_value(
 66      uint32_t register_value
 67    ) const = 0;
 68    // Setter for the 'address' field in the 'read_address' register within the 'base_addresses' register array,
 69    // which will set the field to the given value, and everything else to default.
 70    virtual void set_base_addresses_read_address_address(
 71      size_t array_index,
 72      uint32_t field_value
 73    ) const = 0;
 74    // Setter for the 'address' field in the 'read_address' register within the 'base_addresses' register array,
 75    // given a register value, which will return an updated value.
 76    virtual uint32_t set_base_addresses_read_address_address_from_value(
 77      uint32_t register_value,
 78      uint32_t field_value
 79    ) const = 0;
 80
 81    // -------------------------------------------------------------------------
 82    // Methods for the 'write_address' register within the 'base_addresses' register array. Mode 'Read, Write'.
 83
 84    // Getter that will read the whole register's value over the register bus.
 85    virtual uint32_t get_base_addresses_write_address(
 86      size_t array_index
 87    ) const = 0;
 88
 89    // Setter that will write the whole register's value over the register bus.
 90    virtual void set_base_addresses_write_address(
 91      size_t array_index,
 92      uint32_t register_value
 93    ) const = 0;
 94
 95    // Getter for the 'address' field in the 'write_address' register within the 'base_addresses' register array,
 96    // which will read register value over the register bus.
 97    virtual uint32_t get_base_addresses_write_address_address(
 98      size_t array_index
 99    ) const = 0;
100    // Getter for the 'address' field in the 'write_address' register within the 'base_addresses' register array,
101    // given a register value.
102    virtual uint32_t get_base_addresses_write_address_address_from_value(
103      uint32_t register_value
104    ) const = 0;
105    // Setter for the 'address' field in the 'write_address' register within the 'base_addresses' register array,
106    // which will set the field to the given value, and everything else to default.
107    virtual void set_base_addresses_write_address_address(
108      size_t array_index,
109      uint32_t field_value
110    ) const = 0;
111    // Setter for the 'address' field in the 'write_address' register within the 'base_addresses' register array,
112    // given a register value, which will return an updated value.
113    virtual uint32_t set_base_addresses_write_address_address_from_value(
114      uint32_t register_value,
115      uint32_t field_value
116    ) const = 0;
117
118  };
119
120} /* namespace fpga_regs */

C header

The C code below is produced by the generate() call in the Python example above. The index and address of each register are given by a macro where the array index is supplied as an argument.

Click to expand/collapse code.
Generated C code.
 1// This file is automatically generated by hdl-registers version 6.1.1-dev.
 2// Code generator CHeaderGenerator version 1.0.0.
 3// Generated 2024-12-01 20:51 at commit 2ca830a4377d1e32.
 4// Register hash d398508c05f52d1800bf8d33954a99a6ebc864d8.
 5
 6#ifndef CAESAR_REGS_H
 7#define CAESAR_REGS_H
 8
 9
10// Number of registers within this register map.
11#define CAESAR_NUM_REGS (6u)
12
13// Type for the 'base_addresses' register array.
14typedef struct caesar_base_addresses_t
15{
16  // Mode 'Read, Write'.
17  uint32_t read_address;
18  // Mode 'Read, Write'.
19  uint32_t write_address;
20} caesar_base_addresses_t;
21
22// Type for this register map.
23typedef struct caesar_regs_t
24{
25  caesar_base_addresses_t base_addresses[3];
26} caesar_regs_t;
27
28// Address of the 'read_address' register within the 'base_addresses' register array (array_index < 3).
29// Mode 'Read, Write'.
30#define CAESAR_BASE_ADDRESSES_READ_ADDRESS_INDEX(array_index) (0u + (array_index) * 2u + 0u)
31#define CAESAR_BASE_ADDRESSES_READ_ADDRESS_ADDR(array_index) (4u * CAESAR_BASE_ADDRESSES_READ_ADDRESS_INDEX(array_index))
32// Attributes for the 'address' field in the 'read_address' register within the 'base_addresses' register array.
33#define CAESAR_BASE_ADDRESSES_READ_ADDRESS_ADDRESS_SHIFT (0u)
34#define CAESAR_BASE_ADDRESSES_READ_ADDRESS_ADDRESS_MASK (0b1111111111111111111111111111u << 0u)
35#define CAESAR_BASE_ADDRESSES_READ_ADDRESS_ADDRESS_MASK_INVERSE (~CAESAR_BASE_ADDRESSES_READ_ADDRESS_ADDRESS_MASK)
36
37// Address of the 'write_address' register within the 'base_addresses' register array (array_index < 3).
38// Mode 'Read, Write'.
39#define CAESAR_BASE_ADDRESSES_WRITE_ADDRESS_INDEX(array_index) (0u + (array_index) * 2u + 1u)
40#define CAESAR_BASE_ADDRESSES_WRITE_ADDRESS_ADDR(array_index) (4u * CAESAR_BASE_ADDRESSES_WRITE_ADDRESS_INDEX(array_index))
41// Attributes for the 'address' field in the 'write_address' register within the 'base_addresses' register array.
42#define CAESAR_BASE_ADDRESSES_WRITE_ADDRESS_ADDRESS_SHIFT (0u)
43#define CAESAR_BASE_ADDRESSES_WRITE_ADDRESS_ADDRESS_MASK (0b1111111111111111111111111111u << 0u)
44#define CAESAR_BASE_ADDRESSES_WRITE_ADDRESS_ADDRESS_MASK_INVERSE (~CAESAR_BASE_ADDRESSES_WRITE_ADDRESS_ADDRESS_MASK)
45
46#endif // CAESAR_REGS_H