Integer fields
Register fields can be of the type integer. Meaning, a numeric field, as opposed to a bit vector, that has a defined upper and lower range.
This page will show you how the set up integer fields in a register, 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 with three integer fields. See comments for rules about the different properties.
1[config]
2
3mode = "r_w"
4description = "Configuration register."
5
6# This will allocate an integer field named "burst_length_bytes" in the "config" register.
7[config.burst_length_bytes]
8
9# The "type" property MUST be present and set to "integer".
10type = "integer"
11
12# The "min_value" property is OPTIONAL for an integer field.
13# Will default to 0 if not specified.
14# The value specified MUST be an integer.
15min_value = 1
16
17# The "max_value" property MUST be present for an integer field.
18# The value specified MUST be an integer, and greater than or equal to the
19# "min_value" parameter value.
20max_value = 256
21
22# The "description" property is OPTIONAL for an integer field.
23# Will default to "" if not specified.
24# The value specified MUST be a string.
25description = "The number of bytes to request."
26
27# The "default_value" property is OPTIONAL for a integer field.
28# Will default to the "min_value" parameter value if not specified.
29# The value specified MUST be an integer within the specified min/max range.
30default_value = 64
31
32
33[config.increment]
34
35type = "integer"
36min_value = -4
37max_value = 3
38description = "Offset that will be added to data."
39default_value = 0
40
41
42[config.retry_count]
43
44type = "integer"
45max_value = 5
46description = "Number of retry attempts before giving up."
Note that the second field has a negative range, which is fully supported. Note also that the third field does not any lower bound specified, meaning it will default to zero. It furthermore does not have any default value, meaning it will automatically default to the lower bound, i.e. zero.
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
How to parse the TOML file listed above.
How to create an identical register list when instead using the Python API.
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.
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(name="caesar", toml_file=THIS_DIR.parent / "toml" / "field_integer.toml")
24
25
26def create_from_api() -> RegisterList:
27 """
28 Alternative method: Create the register list by using the Python API.
29 """
30 register_list = RegisterList(name="caesar")
31
32 register = register_list.append_register(
33 name="config", mode=REGISTER_MODES["r_w"], description="Configuration register."
34 )
35
36 register.append_integer(
37 name="burst_length_bytes",
38 description="The number of bytes to request.",
39 min_value=1,
40 max_value=256,
41 default_value=64,
42 )
43
44 register.append_integer(
45 name="increment",
46 description="Offset that will be added to data.",
47 min_value=-4,
48 max_value=3,
49 default_value=0,
50 )
51
52 register.append_integer(
53 name="retry_count",
54 description="Number of retry attempts before giving up.",
55 min_value=0,
56 max_value=5,
57 default_value=0,
58 )
59
60 return register_list
61
62
63def generate(register_list: RegisterList, output_folder: Path):
64 """
65 Generate the artifacts that we are interested in.
66 """
67 CHeaderGenerator(register_list=register_list, output_folder=output_folder).create()
68
69 CppImplementationGenerator(register_list=register_list, output_folder=output_folder).create()
70 CppInterfaceGenerator(register_list=register_list, output_folder=output_folder).create()
71
72 HtmlPageGenerator(register_list=register_list, output_folder=output_folder).create()
73
74 VhdlRegisterPackageGenerator(register_list=register_list, output_folder=output_folder).create()
75 VhdlRecordPackageGenerator(register_list=register_list, output_folder=output_folder).create()
76
77
78def main(output_folder: Path):
79 generate(register_list=parse_toml(), output_folder=output_folder / "toml")
80 generate(register_list=create_from_api(), output_folder=output_folder / "api")
81
82
83if __name__ == "__main__":
84 main(output_folder=Path(sys.argv[1]))
See Register.append_integer()
for more Python API details.
Generated code
See below for a description of the code that can be generated when using integer fields.
HTML page
See HTML file below for the human-readable documentation that is produced by the
generate()
call in the Python example above.
Each integer field is documented with its valid range.
See HTML code generator for more details about the HTML generator and its capabilities.
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
Some interesting things to notice:
There is only one register, at index 0.
VHDL supports integer types natively. For each field there is a sub-type that is a properly ranged
integer
.For each integer field, there are conversion functions for
Converting from the integer type to
std_logic_vector
.Slicing a register value at the correct range and converting from
std_logic_vector
to integer.
Record package
The caesar_regs_down_t
type is a record with a member config
, the only register in
this example.
The type of the config
member is another record with the three integers set up in
our example: burst_length_bytes
, increment
and retry_count
.
These are of integer types defined in the base register package above.
In our VHDL code we can access a field value for example like this:
result_data <= input_data + regs_down.config.increment;
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 that the setters and getters for each field value use integer types as argument or
return value.
The signed field uses int32_t
while the unsigned fields use uint32_t
.
C++ implementation
Note that each setter and getter perform assertions that the supplied argument is withing the legal range of the field. This will catch calculation errors during testing and at run-time.
C header
The C code below is produced by the generate()
call in the Python example above.
The range and mask of the each field are available as constants.