index: add section headers

Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
Sean Cross 2020-01-02 14:58:41 +08:00
parent 0737480489
commit 073c9f7370

View File

@ -94,6 +94,7 @@
</section>
<section>
<h2>Introduction</h2>
<aside class="notes">
This is the Open ISA miniconf, which today tends to mean FPGAs. This means that
hardware and software are both extensible, and developers will be able to extend
@ -102,6 +103,21 @@
</section>
<section>
<h2>About Me</h2>
<aside class="notes">
My name is Sean Cross, also known as "xobs". I will be speaking later this week
on the Betrusted project, but many know me as the main developer behind the Fomu
project. Fomu is an FPGA that fits in your USB port. One of my goals with the
Fomu project was to allow people to treat it as just a RISC-V CPU in their USB
port, which means now we need to make documentation. This talk covers some of
the problems I ran into while working on this project, and the solutions I came
up with.
</aside>
</section>
<section>
<h2>Undocumented Hardware = Bad</h2>
<h4>(But so easy to do!)</h4>
<aside class="notes">
Undocumented hardware is bad. There are all sorts of quirks, and even if you have
the source code, it can be very difficult to read. I'm the primary developer for
@ -109,10 +125,15 @@
respect to documentation. It is most directly related to the LiteX and Migen
projects, but the concepts will carry over into any other Hardware Description
Language you may use.
The goal of this talk is to show how it's easy to document hardware with
the right framework, and how it's easier to have a project that's documented
than one that isn't.
</aside>
</section>
<section>
<h2>Talk Outline</h2>
<aside class="notes">
I'll briefly cover various methods of writing HDL code, then cover the rationale
behind the approach we take with lxsocdoc, then give an example of how to use
@ -122,6 +143,7 @@
</section>
<section>
<h2>Motivation</h2>
<aside class="notes">
Verilog and VHDL are kind of the C or assembly of the FPGA world. They're universal,
but somewhat unwieldy to use. You need to manually set up your address decoders,
@ -134,6 +156,7 @@
</section>
<section>
<h2>About LiteX and lxsocdoc</h2>
<aside class="notes">
Fomu uses LiteX, which is related to Migen. This is a hardware description language
written in Python. You write Python code and run the program, and it generates
@ -146,6 +169,7 @@
</section>
<section>
<h2>LiteX Primitives</h2>
<aside class="notes">
In LiteX, two of the primitives used to expose hardware registers to the CPU softcore
are CSRStorage and CSRStatus. Instead of manually wiring up a crossbar and decoding
@ -163,10 +187,13 @@ If(self.bitbang.storage[3],
).Else(
dq.oe.eq(1)
),
If(self.bitbang.storage[1], # CPOL=0/CPHA=0 or CPOL=1/CPHA=1 only.
# CPOL=0/CPHA=0 or CPOL=1/CPHA=1 only.
If(self.bitbang.storage[1],
self.miso.status.eq(dq.i[1])
),
dq.o.eq(Cat(self.bitbang.storage[0], Replicate(1, spi_width-1)))</code></pre>
dq.o.eq(
Cat(self.bitbang.storage[0], Replicate(1, spi_width-1))
)</code></pre>
<aside class="notes">
This works well, but exposes a new problem: Documentation. As an example, I was
working with the SPI Flash block in litex, and wanted to know how the bitbang
@ -180,6 +207,7 @@ dq.o.eq(Cat(self.bitbang.storage[0], Replicate(1, spi_width-1)))</code></pre>
</section>
<section>
<h2>Aside: Python Docstrings</h2>
<aside class="notes">
As an aside, Python has something called Pydoc and Docstrings. These are
comments that go at the top of functions and classes that let you describe
@ -191,42 +219,45 @@ dq.o.eq(Cat(self.bitbang.storage[0], Replicate(1, spi_width-1)))</code></pre>
</section>
<section>
<h4>New Register Definition</h4>
<pre><code class="python" data-trim>self.bitbang = CSRStorage(4, fields=[
CSRField("mosi", description="Output value for MOSI pin, valid whenever ``dir`` is ``0``."),
CSRField("clk", description="Output value for SPI CLK pin."),
CSRField("cs_n", description="Output value for SPI CSn pin."),
CSRField("dir", description="Sets the direction for *ALL* SPI data pins except CLK and CSn.", 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.
""")</code></pre>
<aside class="notes">
This is when I hit upon the idea of `lxsocdoc`. The basic idea is that
Python is really good at introspecting Python, so let's add a little bit
more information to the CSR objects to make our life easier. And so, after
working with the LiteX creator Florent, we refactored the bitbang
definition to this:
self.bitbang = CSRStorage(4, fields=[
CSRField("mosi", description="Output value for MOSI pin, valid whenever ``dir`` is ``0``."),
CSRField("clk", description="Output value for SPI CLK pin."),
CSRField("cs_n", description="Output value for SPI CSn pin."),
CSRField("dir", description="Sets the direction for *ALL* SPI data pins except CLK and CSn.", 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.
""")
definition to this.
</aside>
</section>
<section>
<h4>Refactored SPI Bitbang</h4>
<pre><code class="python" data-trim>If(self.bitbang.fields.dir,
dq.oe.eq(0)
).Else(
dq.oe.eq(1)
),
# CPOL=0/CPHA=0 or CPOL=1/CPHA=1 only.
If(self.bitbang.fields.clk,
self.miso.status.eq(dq.i[1])
),
dq.o.eq(
Cat(self.bitbang.fields.mosi, Replicate(1, spi_width-1))
)</code></pre>
<aside class="notes">
Now the actual bitbang logic looks like:
If(self.bitbang.fields.dir,
dq.oe.eq(0)
).Else(
dq.oe.eq(1)
),
If(self.bitbang.fields.clk, # CPOL=0/CPHA=0 or CPOL=1/CPHA=1 only.
self.miso.status.eq(dq.i[1])
),
dq.o.eq(Cat(self.bitbang.fields.mosi, Replicate(1, spi_width-1)))
Now the actual bitbang logic looks like this.
This is a little bit easier to understand -- no longer are we looking at indices
in an array to determine what field does what. Instead we get actual named fields.
@ -235,6 +266,7 @@ dq.o.eq(Cat(self.bitbang.storage[0], Replicate(1, spi_width-1)))</code></pre>
</section>
<section>
<h2>Generating a Manual</h2>
<aside class="notes">
After the design is elaborated and the output file is generated, we can iterate
through the resulting tree and pick out any CSR objects and using any additional
@ -255,6 +287,7 @@ dq.o.eq(Cat(self.bitbang.storage[0], Replicate(1, spi_width-1)))</code></pre>
</section>
<section>
<h2>More Documentation: ModuleDoc</h2>
<aside class="notes">
So now we have register documentation. Can we do better? Of course we can.
SoC reference manuals are more than just register definitions. They also include
@ -263,9 +296,19 @@ dq.o.eq(Cat(self.bitbang.storage[0], Replicate(1, spi_width-1)))</code></pre>
in a similar fashion.
</aside>
</section>
---ModuleDoc---
<section>
<h2>Protocol Documentation</h2>
<aside class="notes">
We can add additional documentation such as protocol waveforms. Here
we use WaveDrom to define the protocol of Wishbone-over-SPI. There
are multiple formats of the protocol depending on which version is
instantiated.
</aside>
</section>
<section>
<h2>SVD: Documentation for Machines</h2>
<aside class="notes">
Having documentation for humans is great, but we can go one step further and
make documentation for computers. SVD is an XML format defined by ARM that
@ -276,6 +319,7 @@ dq.o.eq(Cat(self.bitbang.storage[0], Replicate(1, spi_width-1)))</code></pre>
</section>
<section>
<h2>SVD2Rust: Generating Safe Accessors</h2>
<aside class="notes">
In addition to generating a reference manual for humans, we can generate an SVD
file that's usable in a wide variety of areas. For example, we can turn an SVD
@ -285,28 +329,13 @@ dq.o.eq(Cat(self.bitbang.storage[0], Replicate(1, spi_width-1)))</code></pre>
</section>
<section>
<h2>Renode: Fancy Register Logging</h2>
<aside class="notes">
We can also import this SVD file into an emulator such as Renode, which will
print out fields and flags that get accessed, giving us greater visibility into
what a program is doing.
</aside>
</section>
lxsocdoc
intro to litex/migen
concept of mixins
concept of documentation sections
what the output can look like
what's coming in the future
documenting interrupts
introspecting classes
other approaches
how you can help
why this helps you
Benefits:
* Generating reference manuals
* SVD
* SVD2Rust
</div>
</div> <!-- class="reveal" -->
<!-- End of main presentation -->