hdl_registers.generator package

Subpackages

Submodules

hdl_registers.generator.register_code_generator module

class hdl_registers.generator.register_code_generator.RegisterCodeGenerator(register_list: RegisterList, output_folder: Path)

Bases: ABC, RegisterCodeGeneratorHelpers

Abstract interface and common functions for generating register code. Should be inherited by all custom code generators.

Note that this base class also inherits from RegisterCodeGeneratorHelpers, meaning some useful methods are available in subclasses.

COMMENT_END: str = ''
abstract property COMMENT_START: str

The character(s) that start a comment line in the programming language that we are generating code for.

Overload in subclass by setting e.g.

COMMENT_START = "#"

as a static class member at the top of the class.

DEFAULT_INDENTATION_LEVEL: int = 0
abstract property SHORT_DESCRIPTION: str

A short description of what this generator produces. Will be used when printing status messages.

Overload in subclass by setting e.g.

SHORT_DESCRIPTION = "C++ header"

as a static class member at the top of the class.

__init__(register_list: RegisterList, output_folder: Path)
Parameters:
  • register_list – Registers and constants from this register list will be included in the generated artifacts.

  • output_folder – Result file will be placed in this folder.

create(**kwargs: Any) Path

Generate the result artifact. I.e. create the output_file() containing the result from get_code() method.

Parameters:

kwargs – Further optional parameters that will be sent on to the get_code() method. See get_code() for details.

Returns:

The path to the created file, i.e. output_file().

create_if_needed(**kwargs: Any) tuple[bool, Path]

Generate the result file if needed. I.e. call create() if should_create() is True.

This method is recommended rather than create() in time-critical scenarios, such as before a user simulation run. The should_create() check is very fast (0.5 ms on a decent computer with a typical register list), while a typical register generator is quite slow by comparison. Hence it makes sense to run this method in order to save execution time. This increased speed gives a much nicer user experience.

Parameters:

kwargs – Further optional parameters that will be sent on to the get_code() method. See get_code() for details.

Returns:

Tuple, where first element is a boolean status, and second element is the path to the artifact that may or may not have been created.

The boolean is the return value of should_create().

The path is the output_file() and is set always, even if the file was not created.

property generated_source_info: list[str]

Return lines informing the user that the file is automatically generated. Containing info about the source of the generated register information.

abstract get_code(**kwargs: Any) str

Get the generated code as a string.

Overload in a subclass where the code generation is implemented.

Parameters:

kwargs – Further optional parameters that can be used. Can send any number of named arguments, per the requirements of get_code() of any custom generators that inherit this class.

property header: str

Get file header informing the user that the file is automatically generated. Basically the information from generated_source_info() formatted as a comment block.

abstract property output_file: Path

Result will be placed in this file.

Overload in a subclass to give the proper name to the code artifact. Probably using a combination of self.output_folder and self.name. For example:

@property
def output_file(self) -> Path:
    return self.output_folder / f"{self.name}_regs.html"
property should_create: bool

Indicates if a (re-)create of artifacts is needed. Will be True if any of these conditions are true:

  • Output file does not exist.

  • Generator version of artifact does not match current code version.

  • Artifact hash does not match RegisterList.object_hash() of the current register list. I.e. something in the register list has changed since the previous file was generated (e.g. a new register added).

The version and hash checks above are dependent on the artifact file having a header as given by header().

hdl_registers.generator.register_code_generator_helpers module

class hdl_registers.generator.register_code_generator_helpers.RegisterCodeGeneratorHelpers

Bases: object

Various helper methods that make register code generation easier.

COMMENT_END: str
COMMENT_START: str
DEFAULT_INDENTATION_LEVEL: int
comment(comment: str, indent: int | None = None) str

Create a one-line comment.

comment_block(text: list[str], indent: int | None = None) str

Create a comment block from a string with newlines.

field_description(register: Register, field: RegisterField, register_array: RegisterArray | None = None) str

Get a comment describing the field.

static field_setter_should_read_modify_write(register: Register) bool

Returns True if a field value setter should read-modify-write the register.

Is only true if the register is of a writeable type where the bus can also read back a previously-written value. Furthermore, read-modify-write only makes sense if there is more than one field, otherwise it is a waste of CPU cycles.

get_indentation(indent: int | None = None) str

Get the requested indentation in spaces. Will use the default indentation for this generator if not specified.

get_separator_line(indent: int | None = None) str

Get a separator line, e.g. # ---------------------------------.

iterate_constants() Iterator[Constant]

Iterate of all constants in the register list.

iterate_plain_registers() Iterator[Register]

Iterate over all plain registers (i.e. registers not in array) in the register list.

iterate_register_arrays() Iterator[RegisterArray]

Iterate over all register arrays in the register list.

iterate_register_objects() Iterator[Register | RegisterArray]

Iterate over all register objects in the register list. I.e. all plain registers and all register arrays.

iterate_registers() Iterator[tuple[Register, RegisterArray | None]]

Iterate over all registers, plain or in array, in the register list.

Returns:

If the register is plain, the array return value in the tuple will be None. If the register is in an array, the array return value will conversely be non-None.

name: str
qualified_field_name(register: Register, field: RegisterField, register_array: RegisterArray | None = None) str

Get the qualified field name, e.g. “<module name>_<register name>_<field_name>”. To be used where the scope requires it, i.e. outside of records.

qualified_register_array_name(register_array: RegisterArray) str

Get the qualified register array name, e.g. “<module name>_<register array name>”. To be used where the scope requires it, i.e. outside of records.

qualified_register_name(register: Register, register_array: RegisterArray | None = None) str

Get the qualified register name, e.g. “<module name>_<register name>”. To be used where the scope requires it, i.e. outside of records.

static register_description(register: Register, register_array: RegisterArray | None = None) str

Get a comment describing the register.

register_list: RegisterList
static to_pascal_case(snake_string: str) str

Converts e.g., “my_funny_string” to “MyFunnyString”.

Pascal case is like camel case but with the initial character being capitalized. I.e. how classes are named in Python, C and C++.

hdl_registers.generator.reserved_keywords module