PeakRDL C-Header Generator
PeakRDL C-Header is a Python package used to generate a C Header file, typically representing a register abstraction layer, from a SystemRDL register model. It enables direct C-language access to hardware registers by generating C struct definitions that mirror the hardware address space. The library is currently active, with its latest version being 1.1.0, and maintains a regular release cadence, with updates addressing features and fixes.
Common errors
-
Generated C header has incorrect bitfield packing order, leading to wrong register accesses.
cause C struct bitfield packing order (Low-to-High vs High-to-Low) is implementation-defined by the C compiler and target architecture. The `peakrdl-cheader` tool requires explicit direction for this.fixWhen using `generate_bitfields=True`, ensure `bitfield_order_ltoh` is set correctly to `True` or `False` based on your C compiler's behavior. Example: `exporter = CHeaderExporter(generate_bitfields=True, bitfield_order_ltoh=True)`. -
Generated C struct names or typedefs collide, or do not reflect the desired hierarchy.
cause SystemRDL allows names to be reused in different scopes, and the C exporter's default naming style (`type_style`) might not prevent collisions or match your preferred naming convention.fixAdjust the `type_style` parameter in `CHeaderExporter`. Use `type_style="hierarchical"` to derive names from the full SystemRDL component hierarchy for uniqueness, or `type_style="lexical"` to use RDL lexical scope names. -
My SystemRDL file compiles, but the generated C header for wide registers (>64 bits) is malformed or inaccessible.
cause Standard C integer types are limited to 64 bits. For wider registers, `peakrdl-cheader` generates an array of smaller types, and this behavior needs to be explicitly configured.fixSet the `wide_reg_subword_size` parameter in `CHeaderExporter` to specify how larger registers should be broken down (e.g., `wide_reg_subword_size=32` for an array of 32-bit words).
Warnings
- breaking The project license was changed from Apache-2.0 to LGPLv3 in version 1.1.0. While not a code-breaking change, this is a significant alteration in licensing terms that affects how the software can be incorporated into other projects.
- gotcha The packing order of C struct bitfields is implementation-defined (compiler and architecture dependent). If `generate_bitfields` is enabled, you *must* explicitly specify `bitfield_order_ltoh` (Low-to-High) or `bitfield_order_htol` (High-to-Low) to match your target environment, or the generated header may lead to incorrect hardware access.
- gotcha SystemRDL allows identifiers to be repeated in different lexical scopes. If your exporter flattens hierarchy or relies on simple type names, this can lead to C identifier collisions in the generated header.
- gotcha C's `<stdint.h>` types typically only extend up to 64 bits. For SystemRDL registers wider than 64 bits, `peakrdl-cheader` will represent them as an array of smaller sub-words in the C header. Failure to configure the `wide_reg_subword_size` parameter will result in default behavior which might not align with expectations.
Install
-
pip install peakrdl-cheader -
pip install peakrdl
Imports
- CHeaderExporter
from peakrdl_cheader.exporter import CHeaderExporter
- RDLCompiler
from systemrdl import RDLCompiler
Quickstart
import os
from systemrdl import RDLCompiler
from peakrdl_cheader.exporter import CHeaderExporter
# Create a dummy RDL file for demonstration
rdl_content = '''
addrmap my_device {
reg { field {} my_reg[31:0] = 0; } control_reg;
regfile my_block[8] {
reg { field {} status_field[7:0]; } status_reg;
}
};
'''
with open('example.rdl', 'w') as f:
f.write(rdl_content)
# 1. Compile the SystemRDL file
rdlc = RDLCompiler()
rdlc.compile_file('example.rdl')
top_node = rdlc.elaborate()
# 2. Configure and generate the C header
exporter = CHeaderExporter(
std="gnu11", # Specify C standard, e.g., gnu11, c99
generate_bitfields=True, # Enable bitfield structs
bitfield_order_ltoh=True # Specify bitfield packing order
)
output_path = 'example.h'
exporter.export(node=top_node, path=output_path)
print(f"C header generated successfully at {output_path}")
# Clean up dummy RDL file
os.remove('example.rdl')
# Example of how to use from CLI:
# peakrdl c-header example.rdl -o example.h --std gnu11 --bitfields ltoh