11from typing import Sequence , Optional , List , Tuple
22
3+ import json
4+
35from sphinx .domains import Domain
46from sphinx .util .docutils import SphinxDirective
57from sphinx .util import logging
68from sphinx import addnodes
79
810from docutils import nodes
911from docutils .parsers .rst import directives
12+ from docutils .statemachine import StringList
1013
1114from systemrdl .node import Node , RegNode , AddressableNode , SignalNode , RootNode
1215from systemrdl .rdltypes .references import PropertyReference
1316from systemrdl .source_ref import FileSourceRef , DetailedFileSourceRef
1417
1518from ..utils import lookup_rdl_node , FieldList , Table , alpha_from_int
19+ from ..wavedrom import register_to_wavedrom
1620
1721from ..markdown .render import render_to_docutils
1822
@@ -200,8 +204,8 @@ def make_rdl_node_doc(self, rdl_node: Node) -> Sequence[nodes.Element]:
200204 ref_id = rdl_node .get_path (array_suffix = "" , empty_array_suffix = "" )
201205 heading = nodes .section ()
202206 heading .attributes ["ids" ] = [ref_id ]
203- # TODO: Include RDL name in title if it was set.
204- heading .append (nodes .title (text = rdl_node . inst_name ))
207+ display_name = rdl_node . get_property ( " name" ) or rdl_node . inst_name
208+ heading .append (nodes .title (text = display_name ))
205209 heading .extend (doc_nodes )
206210 doc_nodes = [heading ]
207211
@@ -210,13 +214,70 @@ def make_rdl_node_doc(self, rdl_node: Node) -> Sequence[nodes.Element]:
210214 return doc_nodes
211215
212216
217+ def _build_wavedrom_node (self , rdl_node : RegNode ) -> nodes .container :
218+ """Build a WaveDrom bitfield diagram via nested RST parsing."""
219+ wavedrom_dict = register_to_wavedrom (rdl_node )
220+ wavedrom_json = json .dumps (wavedrom_dict )
221+
222+ rst = StringList ()
223+ path = rdl_node .get_path (array_suffix = "" , empty_array_suffix = "" )
224+ image_name = f"regblock_{ path .replace ('.' , '_' )} "
225+ rst .append (f".. wavedrom:: { image_name } " , "<peakrdl>" )
226+ rst .append ("" , "<peakrdl>" )
227+ for line in wavedrom_json .splitlines ():
228+ rst .append (f" { line } " , "<peakrdl>" )
229+ rst .append ("" , "<peakrdl>" )
230+
231+ container = nodes .container (classes = ["peakrdl-bitfield" ])
232+ self .state .nested_parse (rst , 0 , container )
233+ return container
234+
235+ def _build_field_def_list (self , rdl_node : RegNode ) -> list [nodes .Element ]:
236+ """Build field descriptions as a definition list (compact style)."""
237+ def_list = nodes .definition_list ()
238+ for field in reversed (rdl_node .fields ()):
239+ desc = field .get_property ("desc" )
240+ if not desc :
241+ continue
242+
243+ dli = nodes .definition_list_item ()
244+ def_list .append (dli )
245+
246+ dl_term = nodes .term (text = field .inst_name )
247+ dl_def = nodes .definition ()
248+ dl_def_p = self .get_rdl_desc (field )
249+ dl_def .append (dl_def_p )
250+
251+ dli .append (dl_term )
252+ dli .append (dl_def )
253+ return [def_list ]
254+
255+ def _build_field_sections (self , rdl_node : RegNode ) -> list [nodes .Element ]:
256+ """Build field descriptions as individual sections with headings."""
257+ sections : list [nodes .Element ] = []
258+ for field in reversed (rdl_node .fields ()):
259+ desc = field .get_property ("desc" )
260+ if not desc :
261+ continue
262+
263+ path = field .get_path (array_suffix = "" , empty_array_suffix = "" )
264+ section_id = nodes .make_id (path )
265+ section = nodes .section (ids = [section_id ])
266+ section += nodes .title (text = field .inst_name )
267+ section += self .get_rdl_desc (field )
268+ sections .append (section )
269+ return sections
270+
213271 def make_rdl_reg_doc (self , rdl_node : RegNode ) -> Sequence [nodes .Element ]:
214272 # Info Field List Header
215273 fl = self .get_info_header (rdl_node )
216274
217275 # Description
218276 desc_paragraph = self .get_rdl_desc (rdl_node )
219277
278+ # WaveDrom bitfield diagram
279+ wavedrom_node = self ._build_wavedrom_node (rdl_node )
280+
220281 # Field Table
221282 table = Table (["Bits" , "Identifier" , "Access" , "Reset" , "Name" ])
222283 for field in reversed (rdl_node .fields ()):
@@ -255,24 +316,12 @@ def make_rdl_reg_doc(self, rdl_node: RegNode) -> Sequence[nodes.Element]:
255316 ])
256317
257318 # Field descriptions
258- def_list = nodes .definition_list ()
259- for field in reversed (rdl_node .fields ()):
260- desc = field .get_property ("desc" )
261- if not desc :
262- continue
263-
264- dli = nodes .definition_list_item ()
265- def_list .append (dli )
266-
267- dl_term = nodes .term (text = field .inst_name )
268- dl_def = nodes .definition ()
269- dl_def_p = self .get_rdl_desc (field )
270- dl_def .append (dl_def_p )
271-
272- dli .append (dl_term )
273- dli .append (dl_def )
319+ if self .config .peakrdl_doc_field_sections :
320+ field_descs = self ._build_field_sections (rdl_node )
321+ else :
322+ field_descs = self ._build_field_def_list (rdl_node )
274323
275- return [fl , desc_paragraph , table .as_node (), def_list ]
324+ return [fl , desc_paragraph , wavedrom_node , table .as_node (), * field_descs ]
276325
277326
278327 def make_rdl_grouplike_doc (self , rdl_node : AddressableNode ) -> Sequence [nodes .Element ]:
0 commit comments