Documentation guidelines
A brief set-of-rules for the documentation.
Note
The old wiki uses dokuwiki. When importing text from there, consider the automated options that are provided in this page to convert it to reST.
Indentation
Directives are indented with 3 space, which is Sphinx’s default. At code directives, the code keeps its original indentation (e.g. 2 spaces for Verilog code), but is offset by 3 spaces at the beginning of every line, to instruct Sphinx the beginning and end of the code directive.
Table of contents
The relation between pages are created with the toctree directive,
which allows to generate the table of contents and navigation bars.
Each page may have only one toctree, since they are the equivalent of the volumes of a book, and it does not make sense to have multiple “volumes” at the repository level.
The only exception is the ADI System Level Documentation repository, which indeed contains various
types of documentation (eval-boards, university program, Linux drivers, etc.);
and it uses the topic field at lut.py to keep track of
each.
The toctree directive has the following format:
.. toctree::
:maxdepth: <depth>
Custom title <path/to/page>
For pages with shorter titles, such as libraries, the label is inherited from the page itself, for example:
.. toctree::
library/axi_dmac/index
library/spi_engine/index
And for pages with long titles, such as projects, overwrite the full title with a custom title, e.g:
.. toctree::
AD7616-SDZ <projects/ad7616_sdz/index>
This way, only “AD7616-SDZ” will be displayed in the page navigation bar instead of “AD7616-SDZ HDL project”.
Also, it is recommended to wrap the toctree in a “Contents” section:
Contents
========
.. toctree::
some_page
Versioning
To avoid having the version set in multiple places or having to tweak conf.py
to obtain it from somewhere else, continuous integration can set the environment
variable ADOC_DOC_VERSION to set the version value.
Still, the version value on conf.py has higher precedence, and
ADOC_DOC_VERSION will be ignored if the variable is already set.
The CI, in general, should set ADOC_DOC_VERSION as the current checkout branch
in the pipeline (e.g. main, v1.0.0).
Tip
If creating a branch or PR output, consider using GitHub short reference
${{ github.ref_name }}.
If both environment variable and version on conf.py are unset, it defaults
to an empty string.
Also, set ADOC_TARGET_DEPTH to match the final destination depth, for example,
if the target directory is:
./:
0or unset./v2.2:
1./prs/1234:
2./staging/user/branch:
3
References
References have the format library/project context, e.g.
:ref:`vivado block-diagrams` renders as Vivado block-diagrams.
Notice how neither library nor project are present in the label, since there is no
naming collision between libraries or projects (no project will ever be named
axi_dmac).
Also, for project, libraries and IPs, the names should be exactly the
name of its folders, e.g. axi_pwm_gen and not axi-pwm-gen or AXI_PWM_GEN,
this helps avoid broken references.
Attention
Do not break reference role between lines! Even though Sphinx allows breaking line inside the reference role, it makes pattern matching really hard.
For resources without a particular source code file/folder, prefer hyphen -
separation, for example, spi_engine control-interface instead of
spi_engine control_interface.
In organization references
For references to Sphinx docs inside the organization (repos listed in the repotoc),
the ref role is extended with the syntax
:ref-<external>:`label` where external is a mapped source,
for example, :ref-hdl:`spi_engine control-interface`.
It is also possible to customize the text, e.g.
:ref-hdl:`Custom text <spi_engine control-interface>`.
A warning is thrown when a reference is not found.
Repository mappings are enabled to the conf.py file with the following format:
interref_repos = [external...]
For example:
interref_repos = ['hdl', 'no-OS', 'pyadi-iio/main']
Notice that in the example main suffixes pyadi-iio, this means that will
look for the build at path main of this repo instead of at root.
This can be used to target a specific version, if the target repository stores
multiple, for example, v1.1, more about that Versioned.
Resolved the path, the mappings are obtained from the InterSphinx mapping file.
To show all links of an InterSphinx mapping file, use the built-in tool:
python3 -m sphinx.ext.intersphinx https://analogdevicesinc.github.io/hdl/objects.inv
The previous syntax applies only for references/label links (domain ref/label),
for every other domain, set it explicitly,
e.g. :ref-hdl:doc:`user_guide/docs_guidelines`.
The domains are also listed in the sphinx.ext.intersphinx output.
Others options:
ADOC_INTERREF_URI: uri for the inventory and links, default ishttps://analogdevicesinc.github.io/; it can be set to a local path, e.g.../../.
Outside organization Sphinx references
To create references to other Sphinx documentations, sphinx.ext.intersphinx
can be added to the conf.py extension list.
The syntax is :external+<external>:<domain>:`label`, where external
is a mapped source and the domain is the reference type,
for example, :external+sphinx:doc:`development/theming`.
It is also possible to customize the text, e.g.
:external+sphinx:ref:`Custom text <examples>`.
A warning is thrown when a reference is not found.
Mappings are included to the conf.py file with the following format:
intersphinx_mapping = {
'<name>': ('<path/to/external>', None)
}
For example:
intersphinx_mapping = {
'sphinx': ('https://www.sphinx-doc.org/en/master', None)
}
And new mappings can be included as needed.
To show all links of an InterSphinx mapping file, use the built-in tool:
python3 -m sphinx.ext.intersphinx https://www.sphinx-doc.org/en/master/objects.inv
Text width
Each line must be less than 80 columns wide.
You can use the fold command to break the lines of the imported text
while respecting word-breaks:
cat imported.txt | fold -sw 80 > imported.rst
Or use pandoc:
pandoc imported.txt -f dokuwiki -t rst --columns=80 -s -o imported.rst
Tables
Prefer list-tables and imported csv-tables (using the file option), because they are faster to create, easier to maintain and the 80 column-width rule can be respected with list-tables.
You can use the following command:
pandoc imported.txt -f dokuwiki -t rst --columns=80 -s -o imported.rst --list-tables
The list-tables parameter requires pandoc-types >= 1.23, included in any
recent pandoc release;
if it is not an option, you shall remove it and export in the grid table format.
Now you only have to adjust the widths and give the final touches, like using the correct directives and roles.
Lists
Unordered lists use * or - and ordered lists #..
Child items must be aligned with the first letter of the parent item, that means, 2 spaces for unordered list and 3 spaces for ordered lists, for example:
#. Parent ordered item.
* Child unordeded item.
#. Child ordered item.
#. Child ordered item.
Renders as:
Parent numbered item.
Child unordered item.
Child ordered item.
Child ordered item.
Code
Prefer code-blocks to code directives, because code-blocks have more options, such as showing line numbers and emphasizing lines.
For example,
.. code-block:: python
:linenos:
:emphasize-lines: 2
def hello_world():
string = "Hello world"
print(string)
Renders as
1def hello_world():
2 string = "Hello world"
3 print(string)
Images
Prefer the SVG format for images, and save it as Optimized SVG in inkscape to use less space.
Store them in a hierarchically, do not use images subdirectories.
The idea is to have simpler relative paths, for example, e.g.:
.. image:: ad2234_sdz_schematic.svg
Instead of over complicated paths like:
.. image:: ../../project/images/ad2234_sdz/ad2234_sdz_schematic.svg
In general, this avoids dangling artifacts and keeps the documentation simple.
Git Large File Storage
Where applicable, Git Large File Storage (LFS) is used to replace large files with text pointers inside Git, reducing cloning time.
To setup, install from your package manager and init:
apt install git-lfs
git lfs install
The files that will use Git LFS are tracked at .gitattributes, to add new
files use a pattern at the repo root, for example:
git lfs track *.jpg
Or edit .gitattributes directly.
Vivado block-diagrams
Vivado block-diagrams can be exported as PDF and then converted to SVG with Inkscape.
Vivado waveform data
There is no way to export Vivado waveform data as vectors. Therefore, the recommended method is to take a PNG screenshot and use GIMP to export as 8bpc RGB with all metadata options disabled.
Note
Always use the Export As.. Ctrl+Shift+E option.
To reduce even further the size, you can use Color > Dither.. to reduce the number of colors in the PNG. Saving as greyscale also reduces the PNG size, but might reduce readability and it is not recommended.
Third-party directives and roles
Third-party tools are used to expand Sphinx functionality, if you haven’t already, do:
pip install -r requirements.txt
Custom directives and roles
To expand Sphinx functionality beyond existing tools, custom directives and roles have been written, which are located in the docs/extensions folder. Extensions are straight forward to create, if some functionality is missing, consider requesting or creating one.
Note
Link-like roles use the :role:`text <link>` synthax, like external
links, but without the undescore in the end.
Color role
To print text in red or green, use :red:`text` and :green:`text`.
Link roles
The link roles are a group of roles defined by adi_links.py.
The validate_links global option is used to validate each link during build.
These links are not managed, that means, only links from changed files are checked.
You can run a build with it set to False, then touch the desired files to check
the links of only these files.
Git role
The Git role allows to create links to the Git repository with a shorter syntax.
The role syntax is :git-repo:`text <branch:path>`, for example:
:git-hdl:`main:docs/user_guide/docs_guidelines.rst`renders as docs/user_guide/docs_guidelines.rst.:git-hdl:`Guidelines <docs/user_guide/docs_guidelines.rst>`renders as Guidelines.
Important
The repository name is case sensitive.
When the branch field is not present, it will be filled with the current branch.
It is recommended to not provide this field when it is a link to its own repository,
because it is useful to auto-fill it for documentation releases
(e.g. hdl_2023_r2).
A scenario where it is recommended to provide the branch is when linking others
repositories.
The text field is optional and will be filled with the full path.
Finally, you can do :git-repo:`/` for a link to the root of the
repository with pretty naming, for example, :git-hdl:`/` is rendered
as ADI HDL repository.
ADI role
The adi role creates links for a webpage to the Analog Devices Inc. website.
The role syntax is :adi:`text <webpage>`, for example,
:adi:`AD7175-2 <ad7175-2>`.
Since links are case insensitive, you can also reduce it to
:adi:`AD7175-2`, when webpage is the same as text and will render
as AD7175-2.
Dokuwiki role
The dokuwiki role creates links to the Analog Devices Inc. wiki website.
The role syntax is :dokuwiki:`text <path>`, for example,
:dokuwiki:`pulsar-adc-pmods <resources/eval/user-guides/circuits-from-the-lab/pulsar-adc-pmods>`
gets rendered as
pulsar-adc-pmods.
EngineerZone role
The ez role creates links to the Analog Devices Inc. EngineerZone support website.
The role syntax is :ez:`community`, for example, :ez:`fpga`
gets rendered as EngineerZone.
For Linux Software Drivers, it is :ez:`linux-software-drivers`.
For Microcontroller no-OS Drivers it is :ez:`microcontroller-no-os-drivers`.
Vendor role
The vendor role creates links to the vendor’s website.
The role syntax is :vendor:`text <path>`, for example,
:xilinx:`Zynq-7000 SoC Overview <support/documentation/data_sheets/ds190-Zynq-7000-Overview.pdf>`
gets rendered
Zynq-7000 SoC Overview.
The text parameter is optional, if absent, the file name will be used as the text,
for example,
:intel:`content/www/us/en/docs/programmable/683780/22-4/general-purpose-i-o-overview.html`
gets rendered
general-purpose-i-o-overview.html
(not very readable).
Supported vendors are: xilinx (AMD Xilinx), intel (Intel Altera) and
mw (MathWorks).
HDL build status directive
The HDL build status directive gets information from a markdown formatted status table (output.md) and generates a table with the build statuses.
The directive syntax is:
.. hdl-build-status::
:file: <build_status_file>
The :path: option is optional, in the sense that if it’s not provided, no table
is generated.
If provided, but the build status file does not exist, an error is
thrown.
Note
The :path: option is meant to be “filled” during a CI procedure.
HDL parameters directive
The HDL parameters directive gets information parsed from IP-XACT (component.xml) library and generates a table with the IP parameters.
Note
The IP-XACT files are generated by Vivado during the library build and not by the documentation tooling.
The directive syntax is:
.. hdl-parameters::
:path: <ip_path>
* - <parameter>
- <description>
For example:
.. hdl-parameters::
:path: library/spi_engine/spi_engine_interconnect
* - DATA_WIDTH
- Data width of the parallel SDI/SDO data interfaces.
* - NUM_OF_SDI
- Number of SDI lines on the physical SPI interface.
Descriptions in the directive have higher precedence than in the component.xml file.
The :path: option is optional, and should not be included if the
documentation file path matches the component.xml hierarchically.
HDL interface directive
The HDL interfaces directive gets information parsed from component.xml library and generates tables with the IP interfaces, both buses and ports.
Note
The component.xml files are generated by Vivado during the library build and not by the documentation tooling.
The directive syntax is:
.. hdl-interfaces::
:path: <ip_path>
* - <port/bus>
- <description>
For example:
.. hdl-interfaces::
:path: library/spi_engine/spi_engine_interconnect
Descriptions in the directive have higher precedence than in the component.xml file. You can provide description to a port or a bus, but not for a bus port. Ports/buses that are consecutive are squashed into a single instance to avoid repetition, for example:
{data_tx_12_p, data_tx_23_p} -> data_tx_*_p
{data_tx_12, data_tx_23} -> data_tx_*
{adc_data_i0, adc_data_i0} -> adc_data_i*
{adc_data_q0, adc_data_q0} -> adc_data_q*
{rx_phy2, rx_phy4} -> rx_phy*
To provide a description to the squashed signals/buses, write, for example,
data_tx_* once instead of the original name of all.
Warning
Do not create new IP with signals named as _phy*, it was added for
legacy puporses, instead suffix with _*, e.g. mysignal_phy_4.
The :path: option is optional, and should not be included if the
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:
.. hdl-component-diagram::
:path: <ip_path>
For example:
.. 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
The HDL regmap directive gets information from docs/regmap/adi_regmap_*.txt files and generates tables with the register maps.
The directive syntax is:
.. hdl-regmap::
:name: <regmap_name>
:no-type-info:
For example:
.. hdl-regmap::
:name: DMAC
Note
The register map name is the title-tool, the value above ENDTITLE in the
source file.
This directive does not support content for descriptions, since the source file already have proper descriptions.
The :name: option is required, because the title tool does not match
the IP name and one single docs/regmap/adi_regmap_*.txt file can have more than
one register map.
The :no-type-info: option is optional, and should not be included if it is
in the main IP documentation page. It appends an auxiliary table explaining the
register access types.
Collapsible directive
The collapsible directive creates a collapsible/dropdown/”HTML details”.
The directive syntax is:
.. collapsible:: <label>
<content>
For example:
.. collapsible:: Python code example.
.. code:: python
print("Hello World!")
Renders as:
print("Hello World!")
Notice how you can use any Sphinx syntax, even nest other directives.
Video directive
The video directive creates a embedded video. Currently, direct MP4 and youtube embed links are supported, but could be easily expanded to support third-party services.
The directive syntax is:
.. video:: <url>
For example:
.. video:: http://ftp.fau.de/fosdem/2015/devroom-software_defined_radio/iiosdr.mp4
Renders as:
And:
.. video:: https://www.youtube.com/watch?v=p_VntEwUe24
Renders as:
ESD warning directive
The ESD warning directive creates a ESD warning, for example:
.. esd-warning::
Renders as:
All the products described on this page include ESD (electrostatic discharge) sensitive devices. Electrostatic charges as high as 4000V readily accumulate on the human body or test equipment and can discharge without detection. Although the boards feature ESD protection circuitry, permanent damage may occur on devices subjected to high-energy electrostatic discharges. Therefore, proper ESD precautions are recommended to avoid performance degradation or loss of functionality. This includes removing static charge on external equipment, cables, or antennas before connecting to the device.
Global options for directives
Set hide_collapsible_content to True to hide the collapsibles by default.
Set monolithic to True prefix paths with repos/<repo>.
This is meant for the System Top Documentation repository only.
Common sections
HDL common sections
The More information and Support sections that are present in the HDL project documentation, are actually separate pages inserted as links. They’re located at hdl/projects/common/more_information.rst and /support.rst, and cannot be referenced here because they don’t have an ID at the beginning of the page, so not to have warnings when the documentation is rendered that they’re not included in any toctree.
They are inserted like this:
.. include:: ../common/more_information.rst
.. include:: ../common/support.rst
And will be rendered as sections of the page.
Dynamic elements
Dynamic elements refer to sections of the generated webpage that updates when
loaded online from a source of truth, in general, doctools/*.json files;
it uses a concept similar to “react components”.
These *.json files are generated when doctools_export_metadata is true
in the conf.py.
From the JavaScript side, it fetches from
{content_root}[../versioned]/../doctools/[versioned]/metadata.json.
Note
path version is present and set if latest exists at
{content_root}/../doctools and the stored version can be extracted.
The dynamic elements are:
The navigation bar at the top is updated using the
repotocentry indoctools/metadata.json.A banner at the top is present/updated when the
bannerentry indoctools/metadata.jsonexists.