doc: add lxsocdoc.md (README from lxsocdoc repository)
This commit is contained in:
parent
5ff02e23a0
commit
ae085782ae
|
@ -0,0 +1,147 @@
|
|||
# lxsocdoc: Document your LiteX SoC Automatically
|
||||
|
||||
`lxsocdoc` lets you take a synthesized LiteX SoC and generate full
|
||||
register-level documentation. Additionally, it will generate `.svd` files,
|
||||
suitable for use with various header generation programs.
|
||||
|
||||
## Required Software
|
||||
|
||||
You must have `sphinx` and `sphinx.wavedrom` installed in order to build
|
||||
the documentation. These can be installed with pip:
|
||||
|
||||
```
|
||||
$ pip3 install sphinxcontrib-wavedrom sphinx
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
To use `lxsocdoc`, import the module and call `lxsocdoc.generate_docs(soc, path)`.
|
||||
You can also generate an SVD file. For example:
|
||||
|
||||
```python
|
||||
import lxsocdoc
|
||||
|
||||
...
|
||||
soc = BaseSoC(platform)
|
||||
builder = Builder(soc)
|
||||
vns = builder.build()
|
||||
soc.do_exit(vns)
|
||||
lxsocdoc.generate_docs(soc, "build/documentation")
|
||||
lxsocdoc.generate_svd(soc, "build/software")
|
||||
```
|
||||
|
||||
After you build your design, you will have a Sphinx documentation source available
|
||||
in the above directory. To build this into a target document, use `sphinx-build`.
|
||||
|
||||
For example, if `sphinx-build` is in your path, you can run:
|
||||
|
||||
`sphinx-build -M html build/documentation/ build/documentation/_build`
|
||||
|
||||
`sphinx-build` may be located in `~/.local/bin/` depending on your installation environment.
|
||||
|
||||
You can then verify the contents by starting a local webserver and opening a web
|
||||
browser to [localhost:8000](http://localhost:8000):
|
||||
|
||||
`python3 -m http.server --directory build/documentation/_build/html`
|
||||
|
||||
## Documenting your Registers
|
||||
|
||||
You can add documentation to your registers by defining your `CSRStorage` and `CSRStatus` registers with an additional `field` list. For example:
|
||||
|
||||
```python
|
||||
self.bitbang = CSRStorage(4, fields=[
|
||||
CSRField("mosi", description="Output value for MOSI..."
|
||||
CSRField("clk", description="Output value for SPI CLK..."
|
||||
CSRField("cs_n", description="Output value for SPI C..."
|
||||
CSRField("dir", description="Sets the dir...", values=[
|
||||
("0", "OUT", "SPI pins are all output"),
|
||||
("1", "IN", "SPI pins are all input"),
|
||||
])
|
||||
], description="""Bitbang controls for SPI output. Only
|
||||
standard 1x SPI is supported, and as a result all
|
||||
four wires are ganged together. This means that it
|
||||
is only possible to perform half-duplex operations,
|
||||
using this SPI core.""")
|
||||
```
|
||||
|
||||
There are several interesting properties here:
|
||||
|
||||
* The first argument to a `CSRStorage` or `CSRStatus` is the bit width.
|
||||
* You can pass a list of `CSRField` objects, which will get turned into bit fields
|
||||
* Both `CSRStorage` and `CSRStatus` support a freeform `description` property that will be used to describe the overall register.
|
||||
|
||||
A `CSRField` object has the following properties:
|
||||
|
||||
* `name`: The short name of the register. This should be just a few characters long, as it will be used in the register diagram as well as accessor objects. **Required**
|
||||
* `size`: The size of this field. This is optional, and defaults to `1`
|
||||
* `offset`: The offset of this particular field. If unspecified, defaults to following the previous field. Use this to add gaps to your register definitions, for example to have reserved fields.
|
||||
* `reset`: If specified, the value of this field at reset. Defaults to `0`.
|
||||
* `description`: A textual description of this register. This is optional, but should be specified because it provides critical information to the user about what this field does.
|
||||
* `pulse`: If `True`, then this value is `1` only for one clock cycle after the user writes a `1` to this field. This is especially useful for `START` bits used to initiate operations, or `RESET` bits used to clear an operation.
|
||||
* `access`: The accessibility of this field. One of `CSRAccess.ReadWrite`, `CSRAccess.WriteOnly`, or `CSRAccess.ReadOnly`
|
||||
* `values`: If present, a list of tuples of values. The first field is the numeric value, with `x` for `don't care`. The second field, if present, is the short name of the value. The final field is a textual description of the value. For example:
|
||||
|
||||
```python
|
||||
[
|
||||
("0b0000", "disable the timer"),
|
||||
("0b0001", "slow", "slow timer"),
|
||||
("0b1xxx", "fast timer"),
|
||||
]
|
||||
```
|
||||
|
||||
## Further Module Documentation
|
||||
|
||||
You can add additional documentation to your module with the `ModuleDoc` class. Add it to your base object.
|
||||
|
||||
**To use further Module Documentation, your Module must inherit from `AutoDoc`**. For example:
|
||||
|
||||
```python
|
||||
from litex.soc.integration.doc import AutoDoc, ModuleDoc
|
||||
class DocExample(Module, AutoCSR, AutoDoc):
|
||||
def __init__(self):
|
||||
self.mydoc = ModuleDoc("Some documentation")
|
||||
```
|
||||
|
||||
You may pass a single string to the constructor, in which case the first line becomes the title, or you may pass a separate `title` and `body` parameters to the constructor. For example:
|
||||
|
||||
```python
|
||||
self.intro = ModuleDoc("""Introduce ModuleDoc
|
||||
|
||||
This is an example of how to document using ModuleDoc. An additional
|
||||
section will get added to the output documentation for this module,
|
||||
with the title ``Introduce ModuleDoc`` and with this paragraph
|
||||
as a body""")
|
||||
```
|
||||
|
||||
Note that the default documentatino format is `rst`. You can switch to markdown by passing `format="markdown"` to the constructor, however support is not very good.
|
||||
|
||||
### External Documentation
|
||||
|
||||
You can have external documentation by passing `file` to the constructor.
|
||||
For example:
|
||||
|
||||
```python
|
||||
self.extra_doc = ModuleDoc(file="extra_doc.rst")
|
||||
```
|
||||
|
||||
This will be included at build-time.
|
||||
|
||||
### Using Python Docstrings
|
||||
|
||||
You can also simply have your module inherit from `ModuleDoc`, in which case
|
||||
the documentation will be taken from the docstring. For example:
|
||||
|
||||
```python
|
||||
from litex.soc.integration.doc import AutoDoc, ModuleDoc
|
||||
class DocExample(Module, AutoCSR, AutoDoc, ModuleDoc):
|
||||
"""
|
||||
Automatically Documented Module
|
||||
|
||||
This module will be automatically documented, and included in the
|
||||
generated module documentation output. You can add additional
|
||||
ModuleDoc objects to this module, in order to add further subsections
|
||||
to the output docs.
|
||||
"""
|
||||
def __init__(self):
|
||||
pass
|
||||
```
|
Loading…
Reference in New Issue