From 3f0688b74da81f4f5f6e7230a3ce89e2be89042a Mon Sep 17 00:00:00 2001 From: David Antliff Date: Wed, 14 Jan 2026 17:55:07 +1300 Subject: [PATCH 1/3] Add --reverse-fields option to show register fields in LSB to MSB order. --- README.md | 2 ++ src/peakrdl_html/__peakrdl__.py | 8 ++++++++ src/peakrdl_html/exporter.py | 16 ++++++++++++++-- src/peakrdl_html/templates/reg_base.html | 24 ++++++++++++++++++++---- 4 files changed, 44 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 910e02e..1da9760 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,8 @@ Constructor for the HTML exporter class * Additional context variables to load into the template namespace. * `show_signals` * Show signal components. Default is False +* `reverse-fields` + * Show fields in reverse order (LSB to MSB). Default is False * `extra_doc_properties` * List of properties to explicitly document. diff --git a/src/peakrdl_html/__peakrdl__.py b/src/peakrdl_html/__peakrdl__.py index 7d5d9ad..e3e69c4 100644 --- a/src/peakrdl_html/__peakrdl__.py +++ b/src/peakrdl_html/__peakrdl__.py @@ -46,6 +46,13 @@ def add_exporter_arguments(self, arg_group: 'argparse.ArgumentParser') -> None: help="Show signal components in generated doc pages" ) + arg_group.add_argument( + "--reverse-fields", + dest="reverse_fields", + default=False, + action="store_true", + help="Show fields in reverse order (LSB to MSB)" + ) def do_export(self, top_node: 'AddrmapNode', options: 'argparse.Namespace') -> None: generate_source_links = self.cfg['generate_source_links'] @@ -54,6 +61,7 @@ def do_export(self, top_node: 'AddrmapNode', options: 'argparse.Namespace') -> N html = HTMLExporter( show_signals=options.show_signals, + reverse_fields=options.reverse_fields, user_template_dir=self.cfg['user_template_dir'], user_static_dir=self.cfg['user_static_dir'], extra_doc_properties=self.cfg['extra_doc_properties'], diff --git a/src/peakrdl_html/exporter.py b/src/peakrdl_html/exporter.py index 96c0a65..ad2b260 100755 --- a/src/peakrdl_html/exporter.py +++ b/src/peakrdl_html/exporter.py @@ -45,6 +45,9 @@ def __init__(self, **kwargs: 'Any') -> None: Additional context variables to load into the template namespace. show_signals: bool Show signal components. Default is False + reverse_fields: bool + (optional) Control whether register fields are displayed in reverse + bit order (LSB to MSB). Default is False extra_doc_properties: List[str] List of properties to explicitly document. Nodes that have a property explicitly set will show its value in a @@ -60,10 +63,12 @@ def __init__(self, **kwargs: 'Any') -> None: self.title = "" # type: str self.home_url = None # type: Optional[str] self.skip_not_present = True + self.reverse_fields = False self.current_top_node = None # type: AddrmapNode self.user_static_dir = kwargs.pop("user_static_dir", None) # type: Optional[str] self.show_signals = kwargs.pop("show_signals", False) + self.reverse_fields = kwargs.pop("reverse_fields", False) self.user_context = kwargs.pop("user_context", {}) markdown_inst = kwargs.pop("markdown_inst", None) # type: Optional[markdown.Markdown] self.extra_properties = kwargs.pop("extra_doc_properties", []) # type: List[str] @@ -299,6 +304,12 @@ def write_ral_data(self) -> None: def write_page(self, this_id: int, node: Node, children: 'Dict[int, Node]') -> None: + def field_order(x): + if not self.reverse_fields: + return reversed(x) + else: + return x + view_source_url, view_source_filename= self.get_view_source_info(node) context = { 'this_id': this_id, @@ -318,13 +329,14 @@ def write_page(self, this_id: int, node: Node, children: 'Dict[int, Node]') -> N 'FieldNode': FieldNode, 'AddressableNode': AddressableNode, 'PropertyReference': rdltypes.PropertyReference, - 'reversed': reversed, + 'reversed': field_order, 'isinstance': isinstance, 'list': list, 'view_source_url': view_source_url, 'view_source_filename': view_source_filename, 'reg_fields_are_low_to_high': reg_fields_are_low_to_high, - 'skip_not_present': self.skip_not_present + 'skip_not_present': self.skip_not_present, + 'highest_fields_first': not self.reverse_fields } context.update(self.user_context) diff --git a/src/peakrdl_html/templates/reg_base.html b/src/peakrdl_html/templates/reg_base.html index 33d6491..53f0977 100644 --- a/src/peakrdl_html/templates/reg_base.html +++ b/src/peakrdl_html/templates/reg_base.html @@ -30,8 +30,16 @@ {%- for field in reversed(list(node.fields(skip_not_present=skip_not_present))) %} - {%- if loop.first and field.high < (node.get_property('regwidth') - 1) %} - {{reserved_field(node.get_property('regwidth') - 1, field.high + 1, reg_fields_are_low_to_high(node))}} + {%- if loop.first %} + {%- if highest_fields_first %} + {%- if field.high < (node.get_property('regwidth') - 1) %} + {{ reserved_field(node.get_property('regwidth') - 1, field.high + 1, reg_fields_are_low_to_high(node))}} + {%- endif %} + {%- else %} + {%- if field.low > 0 %} + {{ reserved_field(0, field.low - 1, reg_fields_are_low_to_high(node))}} + {%- endif %} + {%- endif %} {%- elif (not loop.first) and field.high < loop.previtem.low - 1 %} {{reserved_field(loop.previtem.low - 1, field.high + 1, reg_fields_are_low_to_high(node))}} {%- endif %} @@ -89,8 +97,16 @@ - {%- if loop.last and field.low != 0 %} - {{reserved_field(field.low - 1, 0, reg_fields_are_low_to_high(node))}} + {%- if loop.last %} + {%- if highest_fields_first %} + {%- if field.low != 0 %} + {{ reserved_field(field.low - 1, 0, reg_fields_are_low_to_high(node))}} + {%- endif %} + {%- else %} + {%- if field.high != node.get_property('regwidth') - 1 %} + {{ reserved_field(node.get_property('regwidth') - 1, field.high + 1, reg_fields_are_low_to_high(node))}} + {%- endif %} + {%- endif %} {%- endif %} {%- endfor %} From 7bc319ce7010c7ab75e793c9d1adf60b8902a8ce Mon Sep 17 00:00:00 2001 From: David Antliff Date: Wed, 14 Jan 2026 18:16:44 +1300 Subject: [PATCH 2/3] Add PeakRDL TOML config for 'reverse-fields' feature. --- src/peakrdl_html/__peakrdl__.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/peakrdl_html/__peakrdl__.py b/src/peakrdl_html/__peakrdl__.py index e3e69c4..e409e14 100644 --- a/src/peakrdl_html/__peakrdl__.py +++ b/src/peakrdl_html/__peakrdl__.py @@ -19,6 +19,7 @@ class Exporter(ExporterSubcommandPlugin): "user_static_dir": schema.DirectoryPath(), "extra_doc_properties": [schema.String()], "generate_source_links": schema.Boolean(), + "reverse_fields": schema.Boolean(), } @@ -49,7 +50,7 @@ def add_exporter_arguments(self, arg_group: 'argparse.ArgumentParser') -> None: arg_group.add_argument( "--reverse-fields", dest="reverse_fields", - default=False, + default=None, action="store_true", help="Show fields in reverse order (LSB to MSB)" ) @@ -59,9 +60,16 @@ def do_export(self, top_node: 'AddrmapNode', options: 'argparse.Namespace') -> N if generate_source_links is None: generate_source_links = True + # Command-line option takes precedence over config file + reverse_fields = False + if self.cfg['reverse_fields'] is not None: + reverse_fields = self.cfg['reverse_fields'] + if options.reverse_fields is not None: + reverse_fields = options.reverse_fields + html = HTMLExporter( show_signals=options.show_signals, - reverse_fields=options.reverse_fields, + reverse_fields=reverse_fields, user_template_dir=self.cfg['user_template_dir'], user_static_dir=self.cfg['user_static_dir'], extra_doc_properties=self.cfg['extra_doc_properties'], From 380aa56742e99cacb42fb9bb6d929130028a8d50 Mon Sep 17 00:00:00 2001 From: Alex Mykyta Date: Tue, 13 Jan 2026 21:29:10 -0800 Subject: [PATCH 3/3] Simplify reverse_fields logic --- src/peakrdl_html/__peakrdl__.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/peakrdl_html/__peakrdl__.py b/src/peakrdl_html/__peakrdl__.py index e409e14..f7d66d1 100644 --- a/src/peakrdl_html/__peakrdl__.py +++ b/src/peakrdl_html/__peakrdl__.py @@ -50,7 +50,7 @@ def add_exporter_arguments(self, arg_group: 'argparse.ArgumentParser') -> None: arg_group.add_argument( "--reverse-fields", dest="reverse_fields", - default=None, + default=False, action="store_true", help="Show fields in reverse order (LSB to MSB)" ) @@ -60,12 +60,7 @@ def do_export(self, top_node: 'AddrmapNode', options: 'argparse.Namespace') -> N if generate_source_links is None: generate_source_links = True - # Command-line option takes precedence over config file - reverse_fields = False - if self.cfg['reverse_fields'] is not None: - reverse_fields = self.cfg['reverse_fields'] - if options.reverse_fields is not None: - reverse_fields = options.reverse_fields + reverse_fields = options.reverse_fields or self.cfg['reverse_fields'] html = HTMLExporter( show_signals=options.show_signals,