docs: Add component diagram generator
Replaces Symbolator with custom component diagram generator for more reliable diagrams. It uses the IP-XACT file, if it is not found, a placeholder is added instead. Signed-off-by: Jorge Marques <jorge.marques@analog.com>main
parent
9f4d5ff71f
commit
940c3ccd35
|
@ -20,7 +20,6 @@ extensions = [
|
||||||
"sphinx.ext.todo",
|
"sphinx.ext.todo",
|
||||||
"sphinx.ext.viewcode",
|
"sphinx.ext.viewcode",
|
||||||
"sphinxcontrib.wavedrom",
|
"sphinxcontrib.wavedrom",
|
||||||
"symbolator_sphinx",
|
|
||||||
"adi_links",
|
"adi_links",
|
||||||
"adi_hdl_parser"
|
"adi_hdl_parser"
|
||||||
]
|
]
|
||||||
|
|
|
@ -13,6 +13,7 @@ from sphinx.util.nodes import nested_parse_with_titles
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
from adi_hdl_static import hdl_strings
|
from adi_hdl_static import hdl_strings
|
||||||
|
from adi_hdl_render import hdl_component
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
from hashlib import sha1
|
from hashlib import sha1
|
||||||
|
|
||||||
|
@ -343,7 +344,7 @@ class directive_interfaces(directive_base):
|
||||||
if tag not in bs and tag not in pr:
|
if tag not in bs and tag not in pr:
|
||||||
logger.warning(f"Signal {tag} defined in the directive does not exist in the IP-XACT (component.xml)!")
|
logger.warning(f"Signal {tag} defined in the directive does not exist in the IP-XACT (component.xml)!")
|
||||||
|
|
||||||
return subnode
|
return subnode
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
env = self.state.document.settings.env
|
env = self.state.document.settings.env
|
||||||
|
@ -414,7 +415,7 @@ class directive_regmap(directive_base):
|
||||||
subnode += section
|
subnode += section
|
||||||
|
|
||||||
if 'no-type-info' in self.options:
|
if 'no-type-info' in self.options:
|
||||||
return subnode
|
return subnode
|
||||||
|
|
||||||
tgroup = nodes.tgroup(cols=3)
|
tgroup = nodes.tgroup(cols=3)
|
||||||
for _ in range(3):
|
for _ in range(3):
|
||||||
|
@ -438,7 +439,7 @@ class directive_regmap(directive_base):
|
||||||
tgroup += tbody
|
tgroup += tbody
|
||||||
section += table
|
section += table
|
||||||
|
|
||||||
return subnode
|
return subnode
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
env = self.state.document.settings.env
|
env = self.state.document.settings.env
|
||||||
|
@ -534,10 +535,9 @@ class directive_parameters(directive_base):
|
||||||
|
|
||||||
node = node_div()
|
node = node_div()
|
||||||
|
|
||||||
if 'path' in self.options:
|
if 'path' not in self.options:
|
||||||
lib_name = self.options['path']
|
self.options['path'] = env.docname.replace('/index', '')
|
||||||
else:
|
lib_name = self.options['path']
|
||||||
lib_name = env.docname.replace('/index', '')
|
|
||||||
|
|
||||||
subnode = nodes.section(ids=["hdl-parameters"])
|
subnode = nodes.section(ids=["hdl-parameters"])
|
||||||
if lib_name in env.component:
|
if lib_name in env.component:
|
||||||
|
@ -549,6 +549,47 @@ class directive_parameters(directive_base):
|
||||||
|
|
||||||
return [ node ]
|
return [ node ]
|
||||||
|
|
||||||
|
class directive_component_diagram(directive_base):
|
||||||
|
option_spec = {'path': directives.unchanged}
|
||||||
|
required_arguments = 0
|
||||||
|
optional_arguments = 0
|
||||||
|
|
||||||
|
def missing_diagram(self):
|
||||||
|
svg_raw = hdl_component.render_placeholder(self.options['path'])
|
||||||
|
|
||||||
|
svg = nodes.raw('', svg_raw, format='html')
|
||||||
|
return [ svg ]
|
||||||
|
|
||||||
|
def diagram(self):
|
||||||
|
name = hdl_component.get_name(self.options['path'])
|
||||||
|
path = '_build/managed'
|
||||||
|
f = open(os.path.join(path, name))
|
||||||
|
svg_raw = f.read()
|
||||||
|
|
||||||
|
svg = nodes.raw('', svg_raw, format='html')
|
||||||
|
return [ svg ]
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
env = self.state.document.settings.env
|
||||||
|
self.current_doc = env.doc2path(env.docname)
|
||||||
|
|
||||||
|
node = node_div()
|
||||||
|
|
||||||
|
if 'path' not in self.options:
|
||||||
|
self.options['path'] = env.docname.replace('/index', '')
|
||||||
|
lib_name = self.options['path']
|
||||||
|
|
||||||
|
subnode = nodes.section(ids=["hdl-component-diagram"])
|
||||||
|
if lib_name in env.component:
|
||||||
|
subnode += self.diagram()
|
||||||
|
else:
|
||||||
|
subnode += self.missing_diagram()
|
||||||
|
|
||||||
|
node += subnode
|
||||||
|
|
||||||
|
return [ node ]
|
||||||
|
|
||||||
|
|
||||||
def parse_hdl_component(path, ctime):
|
def parse_hdl_component(path, ctime):
|
||||||
component = {
|
component = {
|
||||||
'bus_interface':{},
|
'bus_interface':{},
|
||||||
|
@ -651,8 +692,16 @@ def parse_hdl_component(path, ctime):
|
||||||
dm[signal_name].append(bus_name[0:bus_name.find('_signal_reset')])
|
dm[signal_name].append(bus_name[0:bus_name.find('_signal_reset')])
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if get(bus_interface, 'slave') is not None:
|
||||||
|
bus_role = 'slave'
|
||||||
|
elif get(bus_interface, 'master') is not None:
|
||||||
|
bus_role = 'master'
|
||||||
|
else:
|
||||||
|
bus_role = None
|
||||||
|
|
||||||
bs[bus_name] = {
|
bs[bus_name] = {
|
||||||
'name': sattrib(get(bus_interface, 'busType'), 'name'),
|
'name': sattrib(get(bus_interface, 'busType'), 'name'),
|
||||||
|
'role': bus_role,
|
||||||
'dependency': get_dependency(bus_interface, 'busInterface'),
|
'dependency': get_dependency(bus_interface, 'busInterface'),
|
||||||
'port_map': {}
|
'port_map': {}
|
||||||
}
|
}
|
||||||
|
@ -747,6 +796,7 @@ def manage_hdl_components(env, docnames, libraries):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
cp[lib] = parse_hdl_component(f, ctime)
|
cp[lib] = parse_hdl_component(f, ctime)
|
||||||
|
hdl_component.render(env, lib, cp[lib])
|
||||||
docnames.append(doc)
|
docnames.append(doc)
|
||||||
|
|
||||||
# From https://github.com/tfcollins/vger/blob/main/vger/hdl_reg_map.py
|
# From https://github.com/tfcollins/vger/blob/main/vger/hdl_reg_map.py
|
||||||
|
@ -923,6 +973,7 @@ def manage_hdl_artifacts(app, env, docnames):
|
||||||
def setup(app):
|
def setup(app):
|
||||||
app.add_directive('collapsible', directive_collapsible)
|
app.add_directive('collapsible', directive_collapsible)
|
||||||
app.add_directive('hdl-parameters', directive_parameters)
|
app.add_directive('hdl-parameters', directive_parameters)
|
||||||
|
app.add_directive('hdl-component-diagram', directive_component_diagram)
|
||||||
app.add_directive('hdl-interfaces', directive_interfaces)
|
app.add_directive('hdl-interfaces', directive_interfaces)
|
||||||
app.add_directive('hdl-regmap', directive_regmap)
|
app.add_directive('hdl-regmap', directive_regmap)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,230 @@
|
||||||
|
import os.path
|
||||||
|
from lxml import etree
|
||||||
|
|
||||||
|
font_size = 16
|
||||||
|
margin = 18
|
||||||
|
line_length = 16
|
||||||
|
text_vertical_margin = 8
|
||||||
|
color_main = '#0067b9'
|
||||||
|
color_bg1 = '#c4e5ff'
|
||||||
|
color_bg2 = '#ebf6ff'
|
||||||
|
stroke_width = 3
|
||||||
|
|
||||||
|
class hdl_component():
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_name(lib_name):
|
||||||
|
return f"{lib_name.replace('/','-')}.svg"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def render(env, lib_name, item):
|
||||||
|
#ports, bus_interface
|
||||||
|
dest_dir = os.path.join(env.srcdir, '_build/managed')
|
||||||
|
dest_file = os.path.join(dest_dir, hdl_component.get_name(lib_name))
|
||||||
|
|
||||||
|
def make_style(parent):
|
||||||
|
style = etree.SubElement(parent, 'style').text = """
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
def make_gradient(parent):
|
||||||
|
defs = etree.SubElement(parent, 'defs')
|
||||||
|
gradient = etree.SubElement(defs, 'linearGradient', attrib={
|
||||||
|
'id':'ip_background',
|
||||||
|
'x1':'0', 'x2':'1', 'y1':'0', 'y2':'1'
|
||||||
|
})
|
||||||
|
etree.SubElement(gradient, 'stop', attrib={'offset':'0%', 'stop-color':color_bg1})
|
||||||
|
etree.SubElement(gradient, 'stop', attrib={'offset':'100%', 'stop-color':color_bg2})
|
||||||
|
|
||||||
|
def symbol_bus(parent):
|
||||||
|
rect_height = font_size
|
||||||
|
one_fifth_x = line_length/5
|
||||||
|
one_fifth_y = rect_height/5
|
||||||
|
x = 0; y = 0
|
||||||
|
pattern = [[0,1,0,1,0],[0,0,0,0,0],[0,1,0,1,0],[0,0,0,0,0],[0,1,0,1,0]]
|
||||||
|
etree.SubElement(parent, "rect", attrib={
|
||||||
|
'x':'0', 'y':'0',
|
||||||
|
'width':str(line_length), 'height':str(font_size),
|
||||||
|
'fill':color_bg1,
|
||||||
|
})
|
||||||
|
for i in pattern:
|
||||||
|
for j in i:
|
||||||
|
if j:
|
||||||
|
etree.SubElement(parent, "rect", attrib={
|
||||||
|
'x':str(x), 'y':str(y),
|
||||||
|
'width':str(one_fifth_x), 'height':str(one_fifth_y),
|
||||||
|
'fill':color_main,
|
||||||
|
})
|
||||||
|
x = x+one_fifth_x
|
||||||
|
x = 0
|
||||||
|
y = y+one_fifth_y
|
||||||
|
def symbol_port(parent):
|
||||||
|
etree.SubElement(parent, "line", attrib={
|
||||||
|
'stroke':'black',
|
||||||
|
'stroke-width':str(stroke_width),
|
||||||
|
'x1':'0', 'y1':str(font_size/2),
|
||||||
|
'x2':str(line_length), 'y2':str(font_size/2)
|
||||||
|
})
|
||||||
|
|
||||||
|
def create_text(items, side):
|
||||||
|
y_pos = margin*4
|
||||||
|
if side == 'out':
|
||||||
|
text_anchor = 'end'
|
||||||
|
x_pos = margin*4 + aux_width
|
||||||
|
line_x1 = x_pos+(margin)
|
||||||
|
line_x2 = x_pos+(margin+line_length)
|
||||||
|
x_pos_group = x_pos+margin
|
||||||
|
scale_group = 'scale(1,1)'
|
||||||
|
else:
|
||||||
|
text_anchor = 'start'
|
||||||
|
x_pos = margin*3
|
||||||
|
line_x1 = x_pos-(margin+line_length)
|
||||||
|
line_x2 = x_pos-(margin)
|
||||||
|
x_pos_group = x_pos-margin
|
||||||
|
scale_group = 'scale(-1,1)'
|
||||||
|
|
||||||
|
for elem in items:
|
||||||
|
if elem[1] == 'bus':
|
||||||
|
link_anchor = f"#bus-interface-{elem[0]}"
|
||||||
|
else:
|
||||||
|
link_anchor = "#ports"
|
||||||
|
link = etree.SubElement(root, "a", attrib={
|
||||||
|
'href':link_anchor,
|
||||||
|
})
|
||||||
|
etree.SubElement(link, "text", attrib={
|
||||||
|
'style':f"font: {font_size}px sans-serif",
|
||||||
|
'text-anchor':text_anchor,
|
||||||
|
'dominant-baseline':'middle',
|
||||||
|
'x':str(x_pos), 'y':str(y_pos)
|
||||||
|
}).text = elem[0]
|
||||||
|
group = etree.SubElement(root, "g", attrib={
|
||||||
|
'transform':f"translate({x_pos_group},{y_pos-font_size/2}) {scale_group}"}
|
||||||
|
)
|
||||||
|
if elem[1] == 'bus':
|
||||||
|
symbol_bus(group)
|
||||||
|
else:
|
||||||
|
symbol_port(group)
|
||||||
|
y_pos += font_size+text_vertical_margin
|
||||||
|
|
||||||
|
ins = []
|
||||||
|
outs = []
|
||||||
|
for key in item['bus_interface']:
|
||||||
|
if item['bus_interface'][key]['role'] == 'master':
|
||||||
|
outs.append((key, 'bus'))
|
||||||
|
else:
|
||||||
|
ins.append((key, 'bus'))
|
||||||
|
for key in item['ports']:
|
||||||
|
if item['ports'][key]['direction'] == 'out':
|
||||||
|
outs.append((key, 'port'))
|
||||||
|
else:
|
||||||
|
ins.append((key, 'port'))
|
||||||
|
|
||||||
|
max_len_in = 0
|
||||||
|
for elem in ins:
|
||||||
|
max_len_in = len(elem[0]) if len(elem[0]) > max_len_in else max_len_in
|
||||||
|
|
||||||
|
max_len_out = 0
|
||||||
|
for elem in outs:
|
||||||
|
max_len_out = len(elem[0]) if len(elem[0]) > max_len_out else max_len_out
|
||||||
|
|
||||||
|
aux_width = (max_len_in+max_len_out)*font_size*.6
|
||||||
|
|
||||||
|
num_outs = len(outs)
|
||||||
|
num_ins = len(ins)
|
||||||
|
max_num = max(num_outs, num_ins)
|
||||||
|
|
||||||
|
root = etree.Element('svg', xmlns="http://www.w3.org/2000/svg")
|
||||||
|
|
||||||
|
make_style(root)
|
||||||
|
make_gradient(root)
|
||||||
|
|
||||||
|
ip_width = aux_width + margin*3
|
||||||
|
ip_height = max_num*(font_size+text_vertical_margin) + margin*2
|
||||||
|
etree.SubElement(root, "rect", attrib={
|
||||||
|
'x':str(margin*2), 'y':str(margin*2),
|
||||||
|
'width':str(ip_width), 'height':str(ip_height),
|
||||||
|
'rx':str(margin),
|
||||||
|
'fill':'url(#ip_background)'
|
||||||
|
})
|
||||||
|
|
||||||
|
create_text(ins,'in')
|
||||||
|
create_text(outs,'out')
|
||||||
|
|
||||||
|
viewbox_x = margin*7 + aux_width
|
||||||
|
viewbox_y = margin*7 + max_num*(font_size+text_vertical_margin)
|
||||||
|
root.set('viewBox', f"0 0 {viewbox_x} {viewbox_y}")
|
||||||
|
root.set('width', str(viewbox_x))
|
||||||
|
root.set('height', str(viewbox_y))
|
||||||
|
|
||||||
|
etree.SubElement(root, "rect", attrib={
|
||||||
|
'x':str(margin*2), 'y':str(margin*2),
|
||||||
|
'width':str(ip_width), 'height':str(ip_height),
|
||||||
|
'rx':str(margin),
|
||||||
|
'fill':'none',
|
||||||
|
'stroke':color_main,
|
||||||
|
'stroke-width':str(stroke_width)
|
||||||
|
})
|
||||||
|
|
||||||
|
ipname_y = viewbox_y-font_size-margin
|
||||||
|
ipname_x = viewbox_x/2
|
||||||
|
etree.SubElement(root, "text", attrib={
|
||||||
|
'style':f"font: {font_size}px sans-serif",
|
||||||
|
'fill': color_main,
|
||||||
|
'text-anchor':'middle',
|
||||||
|
'dominant-baseline':'middle',
|
||||||
|
'x':str(ipname_x), 'y':str(ipname_y)
|
||||||
|
}).text = lib_name[lib_name.rfind('/')+1:]
|
||||||
|
|
||||||
|
tree = etree.ElementTree(root)
|
||||||
|
|
||||||
|
if not os.path.exists(dest_dir):
|
||||||
|
os.makedirs(dest_dir)
|
||||||
|
tree.write(dest_file)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def render_placeholder(lib_name):
|
||||||
|
root = etree.Element('svg', xmlns="http://www.w3.org/2000/svg")
|
||||||
|
|
||||||
|
def text_element(text, fs, x, y, font='sans-serif'):
|
||||||
|
etree.SubElement(root, "text", attrib={
|
||||||
|
'style':f"font: {font_size*fs}px {font}",
|
||||||
|
'fill': '#666',
|
||||||
|
'text-anchor':'middle',
|
||||||
|
'dominant-baseline':'middle',
|
||||||
|
'x':str(x), 'y':str(y)
|
||||||
|
}).text = text
|
||||||
|
|
||||||
|
ip_width = font_size*30
|
||||||
|
ip_height = font_size*15
|
||||||
|
etree.SubElement(root, "rect", attrib={
|
||||||
|
'x':str(margin*2), 'y':str(margin*2),
|
||||||
|
'width':str(ip_width), 'height':str(ip_height),
|
||||||
|
'rx':str(margin),
|
||||||
|
'stroke':'#666',
|
||||||
|
'fill':'none',
|
||||||
|
'stroke-width':str(stroke_width),
|
||||||
|
'stroke-dasharray':'8 16',
|
||||||
|
'stroke-linecap':'round'
|
||||||
|
})
|
||||||
|
|
||||||
|
viewbox_x = ip_width + 4*margin
|
||||||
|
viewbox_y = ip_height + 4*margin
|
||||||
|
root.set('viewBox', f"0 0 {viewbox_x} {viewbox_y}")
|
||||||
|
root.set('width', str(viewbox_x))
|
||||||
|
root.set('height', str(viewbox_y))
|
||||||
|
|
||||||
|
text_y = viewbox_y/2.5
|
||||||
|
text_x = viewbox_x/2
|
||||||
|
text_element("🧐", 4, text_x, text_y-text_vertical_margin*2)
|
||||||
|
text_element(f"{lib_name[lib_name.rfind('/')+1:]} IP-XACT not found.",
|
||||||
|
1, text_x, text_y+font_size*2+text_vertical_margin)
|
||||||
|
text_element("Generate it and the documentation:",
|
||||||
|
.75, text_x, text_y+font_size*3+text_vertical_margin*2.5)
|
||||||
|
text_element(f"(cd {lib_name}; make)",
|
||||||
|
.75, text_x, text_y+font_size*4+text_vertical_margin*3, 'monospace')
|
||||||
|
text_element("(cd docs; make html)",
|
||||||
|
.75, text_x, text_y+font_size*5+text_vertical_margin*3.5, 'monospace')
|
||||||
|
|
||||||
|
tree = etree.ElementTree(root)
|
||||||
|
return etree.tostring(tree, encoding="utf-8", method="xml").decode("utf-8")
|
|
@ -3,8 +3,7 @@
|
||||||
High-Speed DMA Controller
|
High-Speed DMA Controller
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|
||||||
.. symbolator:: ../../../library/axi_dmac/axi_dmac.v
|
.. hdl-component-diagram::
|
||||||
:caption: axi_dmac
|
|
||||||
|
|
||||||
The AXI DMAC is a high-speed, high-throughput, general purpose DMA controller
|
The AXI DMAC is a high-speed, high-throughput, general purpose DMA controller
|
||||||
intended to be used to transfer data between system memory and other peripherals
|
intended to be used to transfer data between system memory and other peripherals
|
||||||
|
@ -71,7 +70,6 @@ Configuration Parameters
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
.. hdl-parameters::
|
.. hdl-parameters::
|
||||||
:path: library/axi_dmac
|
|
||||||
|
|
||||||
* - ID
|
* - ID
|
||||||
- Instance identification number.
|
- Instance identification number.
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
AXI SPI Engine Module
|
AXI SPI Engine Module
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|
||||||
.. symbolator:: ../../../library/spi_engine/axi_spi_engine/axi_spi_engine.v
|
.. hdl-component-diagram::
|
||||||
:caption: axi_spi_engine
|
|
||||||
|
|
||||||
The AXI SPI Engine peripheral allows asynchronous interrupt-driven memory-mapped
|
The AXI SPI Engine peripheral allows asynchronous interrupt-driven memory-mapped
|
||||||
access to a SPI Engine Control Interface.
|
access to a SPI Engine Control Interface.
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
SPI Engine Execution Module
|
SPI Engine Execution Module
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|
||||||
.. symbolator:: ../../../library/spi_engine/spi_engine_execution/spi_engine_execution.v
|
.. hdl-component-diagram::
|
||||||
:caption: spi_engine_execution
|
|
||||||
|
|
||||||
The SPI Engine Execution peripheral forms the heart of the SPI Engine framework.
|
The SPI Engine Execution peripheral forms the heart of the SPI Engine framework.
|
||||||
It is responsible for handling a SPI Engine control stream and translates it
|
It is responsible for handling a SPI Engine control stream and translates it
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
SPI Engine Interconnect Module
|
SPI Engine Interconnect Module
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|
||||||
.. symbolator:: ../../../library/spi_engine/spi_engine_interconnect/spi_engine_interconnect.v
|
.. hdl-component-diagram::
|
||||||
:caption: axi_spi_engine
|
|
||||||
|
|
||||||
The SPI Engine Interconnect module allows connecting multiple
|
The SPI Engine Interconnect module allows connecting multiple
|
||||||
:ref:`spi_engine control-interface` masters to a single
|
:ref:`spi_engine control-interface` masters to a single
|
||||||
|
@ -38,7 +37,6 @@ Configuration Parameters
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
.. hdl-parameters::
|
.. hdl-parameters::
|
||||||
:path: library/spi_engine/spi_engine_interconnect
|
|
||||||
|
|
||||||
* - DATA_WIDTH
|
* - DATA_WIDTH
|
||||||
- Data width of the parallel SDI/SDO data interfaces.
|
- Data width of the parallel SDI/SDO data interfaces.
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
SPI Engine Offload Module
|
SPI Engine Offload Module
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|
||||||
.. symbolator:: ../../../library/spi_engine/spi_engine_offload/spi_engine_offload.v
|
.. hdl-component-diagram::
|
||||||
|
|
||||||
The SPI Engine Offload peripheral allows to store a SPI Engine command and SDO
|
The SPI Engine Offload peripheral allows to store a SPI Engine command and SDO
|
||||||
data stream in a RAM or ROM module. The command stream is executed when the
|
data stream in a RAM or ROM module. The command stream is executed when the
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
Template Module
|
Template Module
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|
||||||
.. symbolator:: ../../../library/spi_engine/spi_engine_execution/spi_engine_execution.v
|
.. hdl-component-diagram::
|
||||||
:caption: spi_engine_execution
|
:path: library/spi_engine/spi_engine_execution
|
||||||
|
|
||||||
The {module name} is responsible for {brief description}.
|
The {module name} is responsible for {brief description}.
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
IP Template
|
IP Template
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|
||||||
.. symbolator:: ../../../library/spi_engine/spi_engine_execution/spi_engine_execution.v
|
.. hdl-component-diagram::
|
||||||
:caption: spi_engine_execution
|
:path: library/spi_engine/spi_engine_execution
|
||||||
|
|
||||||
Features
|
Features
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
|
@ -7,5 +7,3 @@ aiohttp
|
||||||
aiodns
|
aiodns
|
||||||
sphinxcontrib-wavedrom
|
sphinxcontrib-wavedrom
|
||||||
sphinxcontrib-svg2pdfconverter
|
sphinxcontrib-svg2pdfconverter
|
||||||
https://github.com/hdl/pyhdlparser/tarball/master
|
|
||||||
https://github.com/hdl/symbolator/tarball/master
|
|
||||||
|
|
|
@ -145,3 +145,11 @@ td.description {
|
||||||
.default .pre {
|
.default .pre {
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#hdl-component-diagram {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#hdl-component-diagram svg {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
|
@ -241,12 +241,6 @@ do:
|
||||||
|
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
|
|
||||||
Symbolator directive
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
`Symbolator <https://kevinpt.github.io/symbolator/>`_ is a tool to generate
|
|
||||||
component diagrams.
|
|
||||||
|
|
||||||
Custom directives and roles
|
Custom directives and roles
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -450,6 +444,39 @@ You can provide description to a port or a bus, but not for a bus port.
|
||||||
The ``:path:`` option is optional, and should **not** be included if the
|
The ``:path:`` option is optional, and should **not** be included if the
|
||||||
documentation file path matches the *component.xml* hierarchically.
|
documentation file path matches the *component.xml* hierarchically.
|
||||||
|
|
||||||
|
HDL component diagram directive
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The HDL component diagram directive gets information parsed from *component.xml*
|
||||||
|
library and generates a component diagram for the IP with buses and ports
|
||||||
|
information.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
The *component.xml* files are generated by Vivado during the library build
|
||||||
|
and not by the documentation tooling.
|
||||||
|
|
||||||
|
The directive syntax is:
|
||||||
|
|
||||||
|
.. code:: rst
|
||||||
|
|
||||||
|
.. hdl-component-diagram::
|
||||||
|
:path: <ip_path>
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
.. code:: rst
|
||||||
|
|
||||||
|
.. hdl-component-diagram::
|
||||||
|
:path: library/spi_engine/spi_engine_interconnect
|
||||||
|
|
||||||
|
The ``:path:`` option is optional, and should **not** be included if the
|
||||||
|
documentation file path matches the *component.xml* hierarchically.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
This directive replaces the deprecated ``symbolator`` directive.
|
||||||
|
|
||||||
HDL regmap directive
|
HDL regmap directive
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue