<!doctype html>
<html>

<head>
    <meta charset="utf-8">

    <title>Paying It Forward: Documenting your Hardware</title>

    <meta name="description" content="A framework for easily creating beautiful presentations using HTML">
    <meta name="author" content="Sean &quot;xobs&quot; Cross">

    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">

    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

    <link rel="stylesheet" href="css/reveal.css">
    <link rel="stylesheet" href="css/theme/lca2020.css" id="theme">

    <!-- Theme used for syntax highlighting of code -->
    <link rel="stylesheet" href="lib/css/zenburn.css">

    <!-- Printing and PDF exports -->
    <script>
        var link = document.createElement('link');
        link.rel = 'stylesheet';
        link.type = 'text/css';
        link.href = window.location.search.match(/print-pdf/gi) ? 'css/print/pdf.css' : 'css/print/paper.css';
        document.getElementsByTagName('head')[0].appendChild(link);
    </script>

    <!--[if lt IE 9]>
        <script src="lib/js/html5shiv.js"></script>
        <![endif]-->

    <style>
        /*********************************************
            * ZOOM REVERSE TRANSITION (i.e. zoom out)
            *********************************************/
            .reveal .slides section[data-transition=zoomrev],
            .reveal.zoomrev .slides section:not([data-transition]) {
                transition-timing-function: ease;
            }

            .reveal .slides > section[data-transition=zoomrev].past,
            .reveal .slides > section[data-transition~=zoomrev-out].past,
            .reveal.zoomrev .slides > section:not([data-transition]).past {
                       visibility: hidden;
                -webkit-transform: scale(0.2);
                        transform: scale(0.2);
            }

            .reveal .slides > section[data-transition=zoomrev].future,
            .reveal .slides > section[data-transition~=zoomrev-in].future,
            .reveal.zoomrev .slides > section:not([data-transition]).future {
                       visibility: hidden;
                -webkit-transform: scale(16);
                        transform: scale(16);
            }

            .reveal .slides > section > section[data-transition=zoomrev].past,
            .reveal .slides > section > section[data-transition~=zoomrev-out].past,
            .reveal.zoomrev .slides > section > section:not([data-transition]).past {
                -webkit-transform: translate(0, 150%);
                        transform: translate(0, 150%);
            }

            .reveal .slides > section > section[data-transition=zoomrev].future,
            .reveal .slides > section > section[data-transition~=zoomrev-in].future,
            .reveal.zoomrev .slides > section > section:not([data-transition]).future {
                -webkit-transform: translate(0, -150%);
                        transform: translate(0, -150%);
            }
        </style>

</head>

<body>

    <!-- Start of main presentation -->
    <div class="reveal">
        <div class="footer">
            <a class="url" href="https://p.xobs.io/lca20-pif/">p.xobs.io/lca20-pif</a>
            <span class="theme">Who’s Watching</span><span class="hashtag"> | #LCA2020</span><span class="twitter"> |
                @linuxconfau</span>
        </div>
        <div class="slides">
            <section data-background-image="css/theme/lca2019-title-bg-transparent.svg">
                <h2 style="background-color: transparent;">Paying it Forward: Documenting Your Hardware Project</h2>
                <h5 style="background-color: transparent;">Approaches to documenting a hardware description language using lxsocdoc</h5>
                <p align="right">
                    <small>Sean Cross - <a href="https://xobs.io/">https://xobs.io/</a> - @xobs</small>
                </p>
            </section>

            <section>
                <h2>Undocumented Hardware = Bad</h2>
                <h4 class="fragment">(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
                    the Fomu project, and this talk will cover some of the issues I've run into with
                    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>About Me</h2>
                <table>
                    <tr>
                        <td><img data-src="img/me.jpg"></td>
                        <td><img data-src="img/fomu.png"></td>
                    </tr>
                </table>
                <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>Reference Manuals</h2>
                <img class="fragment" data-src="img/rm-example.png">
                <h6 class="fragment">Datasheet &ne; Reference Manual</h6>
                <aside class="notes">
                    How many people here know what a reference manual is?  These are documents that
                    you hopefully get from the manufacutrer of a chip that tell you how to use it.
                    These are the single most important part of developing a chip the normal way, as
                    they give you all of the information on how to use a chip.  They can include
                    everything from which memory addresses to poke to cause a pin to become an output,
                    or how to set up the video block to output data.  Here is the first page from
                    the reference manual for the i.MX6 used in the Novena.  You'll note that "Chapter
                    1: Introduction" starts on page 197 -- everything before it was a table of contents
                    -- and is almost 6000 pages long.  As an aside, reference manuals
                    aren't datasheets -- datasheets tend to include electrical and operating
                    information, and tend to be much shorter.
                </aside>
            </section>
            <section>
                <h2>Enterprise Documentation</h2>
                <table>
                    <tr>
                        <td>
                            <img height="400" class="fragment" data-src="img/Microsoft_Office_Word.svg" type="image/svg+xml"/>
                        </td>
                        <td width="50%">
                            <div class="fragment">
                                <img data-src="img/Git-logo.svg" type="image/svg+xml"/>
                                <img data-src="img/Travis_CI_Logo.svg" type="img/svg+xml"/>
                            </div>
                        </td>
                    </tr>
                </table>
                <aside class="notes">
                    So how is this monster of a document written?  I've asked several documentation
                    writers from professional chip vendors, and they say that they have a whole team
                    of people using a very advanced piece of realtime typesetting software.
                    Most enterprise documentation is written by a team of writers using Microsoft Word.
                    We're open source developers, and we prefer to use our own tools such as Git and CI
                    to create documentation for us.  Because we're lazy.  And prone to making mistakes.
                </aside>
            </section>

            <section>
                <h2>Talk Outline</h2>
                <ol>
                    <li>How to write HDL Code</li>
                    <li>Rationale behind <tt>lxsocdoc</tt></li>
                    <li>Examples of <tt>lxsocdoc</tt></li>
                    <li>Benefits of this approach</li>
                </ol>
                <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
                    lxsocdoc and how you might apply it to your language.  Finally, I'll cover the
                    implications of having documented hardware and how this will help you pay it forward.
                </aside>
            </section>

            <section>
                <h2>Motivation</h2>
                <pre><code class="hljs cpp">// Hardware definitions of the SoC. Also is the main repo of
// documentation for the programmer-centric view
// of the hardware.
/* Start of memory range for the UART peripheral */
#define UART_OFFSET     0x10000000
/* Offset of the data register for the debug UART. A write
   here will send the data out of the UART. A write when a
   send is going on will halt the processor until the send is
   completed. A read will receive any byte that was received
   by the UART since the last read, or 0xFFFFFFFF when none
   was. There is no receive buffer, so it's possible to miss
   data if you don't poll frequently enough.
   The debug UART is always configured as 8N1. */
#define UART_DATA_REG   0x00</code></pre>
                    <p><tt>mach_defines.h</tt>, Hackaday 2019 Con Badge</p>
                <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,
                    and documentation is very free-form.  Common approaches today involve comments in
                    the HDL and/or C header files.  This works, but we can do better.  We just need to
                    describe the hardware better.
                </aside>
            </section>

            <section>
                <h2>Lots of Documentation</h2>
                <img data-src="img/rm-page-numbers.png">
                <aside class="notes">
                    This documentation is very extensive.  The start of Chapter 1 is on page 197, with all
                    previous pages being the Table of Contents.  It's almost 6000 pages.  It's very
                    extensive, because it's a very complicated chip.
                </aside>
            </section>

            <section>
                <h2>About LiteX</h2>
                <ul>
                    <li>Hardware Description Language embedded in Python</li>
                    <ul>
                        <li>Doesn't run Python in hardware!</li>
                    </ul>
                    <li>Emits Verilog (or Yosys netlists)</li>
                    <li>Makes it easy to create a SoC</li>
                    <li>Powers the LCA2020 video production setup</li>
                </ul>
                <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
                    a design file -- either Verilog code, or a Yosys netlist.  There are many other
                    alternatives such as SpinalHDL or Chisel.  By writing in Python as opposed to
                    direct Verilog, we get a lot of nice primitives.  The examples from this talk
                    are taken from lxsocdoc and LiteX, but most higher-level hardware description
                    languages can take similar approaches to documentation.
                </aside>
            </section>

            <section>
                <h2>LiteX Primitives</h2>
                <pre><code class="python" data-trim>class GPIOOut(Module, AutoCSR):
    def __init__(self, signal):
        self._out = CSRStorage(len(signal))
        self.comb += signal.eq(self._out.storage)</code></pre>
                <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
                    the addresses ourselves, we just need to write `self.regname = CSRStatus(8)`,
                    and the build system will wire up 8 bits of read-only memory to the target CPU.
                    Similarly, `self.othername = CSRStorage(8)` will give 8-bits of write-only memory.
                </aside>
            </section>

            <section>
                <h4>Case Study: SPI Bitbang Module</h4>
                <pre><code class="python" data-trim>self.bitbang = CSRStorage(4)
If(self.bitbang.storage[3],
    dq.oe.eq(0)
).Else(
    dq.oe.eq(1)
),
# 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>
                <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
                    driver worked.  There wasn't any documentation except the source, which looked
                    like this.

                    You can kind of understand it, but it does take a lot of mental power to
                    work through it.  I started by creating aliases for the various elements
                    in the storage array, but then I thought: There has to be a better way!
                </aside>
            </section>

            <section>
                <h2>Aside: Python Docstrings</h2>
                <pre><code class="python" data-trim>def _format_cmd(cmd, spi_width):
    """
    `cmd` is the read instruction. Since everything is
    transmitted on all dq lines (cmd, adr and data), extend/
    interleave cmd to full pads.dq width even if dq1-dq3 are
    don't care during the command phase: For example, for
    N25Q128, 0xeb is the quad i/o fast read, and extended
    to 4 bits (dq1,dq2,dq3 high) is: 0xfffefeff
    """
    c = 2**(8*spi_width)-1
    for b in range(8):
        if not (cmd>>b)%2:
            c &= ~(1<<(b*spi_width))
    return c</code></pre>
                <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
                    what a Python object is and how to use it.  This is almost what we want,
                    except once the final SoC is generated we don't really care so much about
                    things like constructor arguments or method properties.  Documentation for
                    the end user is different from documentation for the module developer.
                </aside>
            </section>

            <section>
                <h2>New Register Definition</h2>
                <pre><code class="python" data-trim>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.""")</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.
                </aside>
            </section>

            <section>
                <h2>Refactored SPI Bitbang</h2>
                <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 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.
                    But because Python can introspect Python very easily, this is just the beginning.
                </aside>
            </section>

            <section>
                <h2>Generating a Manual</h2>
                <img data-src="img/lxspi_bitbang.png">
                <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
                    information.  We can actually generate a full reference manual, just like one you
                    would receive from a SoC Vendor.

                    For example, this is what the start of the Fomu SPI Flash documentation looks like:
                    [Register Listing for LXSPI]

                    This is already pretty useful.  You can hand this file to someone and show them
                    how your design works.  But the title of this talk is called "Paying it Forward",
                    and I can tell you from experience that having such a reference manual for yourself
                    while developing software for your own hardware is still invaluable.  Hardware
                    designs are complex things, and not having to decode bitfield offsets in your
                    head or constantly referring to various sections of code to see how it's implemented
                    saves valuable time.
                </aside>
            </section>

            <section>
                <h2>Interrupts</h2>
                <img data-src="img/interrupts.png">
                <aside class="notes">
                    We can even extract interrupt information, including which bits inside an
                    interrupt register map to which event, and which interrupt number is assigned
                    to a given module.
                </aside>
            </section>

            <section>
                <h2>Undocumented Fields</h2>
                <img data-src="img/timer0-event.png">
                <aside class="notes">
                    It turns out that there is enough information that we can extract that
                    even undocumented fields are somewhat useful.  This is an undocumented
                    interrupt register, but lxsocdoc has pulled out the field names and
                    is giving useful documentation anyway.
                </aside>
            </section>

            <section>
                <h2>More Documentation: ModuleDoc</h2>
                <img data-src="img/timer0-doc.png">
                <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
                    background information on protocols, as well as more elaboration on how the block
                    works.  We can take a cue from CSRs themselves, and add module documentation
                    in a similar fashion.
                </aside>
            </section>

            <section>
                <h2>Protocol Documentation</h2>
                <img data-src="img/usb-wishbone.png">
                <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>
                <table>
                    <tr>
                        <td>
                            <ul>
                                <li>XML description file</li>
                                <li>Interrupt numbers</li>
                                <li>Memory layout</li>
                                <li>Register definitions</li>
                                <li>Register fields</li>
                            </ul>
                        </td>
                        <td>
                            <img data-src="img/CMSIS_SVD_Schema_Gen.png">
                            <br/><small>Source: keil.com</small>
                        </td>
                    </tr>
                </table>
                <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
                    defines various aspects about a chip, including memory layout, interrupt map,
                    and register sets.  SVD includes information such as default values and field
                    bits, all information we have thanks to the introspectability of Python.
                </aside>
            </section>

            <section>
                <h2>SVD2Rust: Generating Safe Accessors</h2>
                <pre><code class="rust">fn init(&mut self) {
    self.registers
        .ctrl
        .write(|w| w.exe().bit(true).curren().bit(true).rgbleden().bit(true));
    self.write(LEDDEN | FR250 | QUICK_STOP, LedRegister::LEDDCR0);

    // Set clock register to 12 MHz / 64 kHz - 1
    self.write(((12_000_000u32 / 64_000u32) - 1) as u8, LedRegister::LEDDBR);

    self.write(
        BREATHE_ENABLE | BREATHE_MODE_FIXED | breathe_rate_ms(128),
        LedRegister::LEDDBCRR,
    );
}</code></pre>
                <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
                    file into a Rust Peripheral Access Crate (PAC) using `SVD2Rust`, giving us an
                    easy way to safely access all peripherals on a device.
                </aside>
            </section>

            <section>
                <h2>Renode: Fancy Register Logging</h2>
                <table width="100%">
                    <tr style="padding-right: 0px; padding-left: 0px;">
                        <td width="75%" style="padding-right: 0px; padding-left: 0px; text-align: center">
                            <img style="padding-right: 0px; padding-left: 0px;" width="100%" data-src="img/renode-debug.png"/>
                        </td>
                        <td style="padding-right: 0px; padding-left: 0px; text-align: center">
                            <img data-src="img/renode-ui-tall.png">
                        </td>
                    </tr>
                </table>
                <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>

            <section>
                <h2>Benefits of Higher Level Languages</h2>
                <ul>
                    <li>Greater code reuse</li>
                    <li>More hardware description</li>
                    <li>Better interoperability</li>
                    <li>Automatic document generation</li>
                    <li>Automatic SVD</li>
                </ul>
                <aside class="notes">
                    By using a higher level language, we are able to describe the hardware
                    in greater detail than if we used Verilog or VHDL.  We can add additional
                    fields to our register definition fields to provide nice, human-readable
                    documentation.  This also allows us to generate machine-readable formats
                    such as SVD, which opens up a whole world of software.
                </aside>
            </section>

            <section>
                <h2>Documentation helps others</h2>
                <h2 class="fragment">Documentation helps you</h2>
                <aside class="notes">
                    Documenting your hardware is important because it is necessary for you to
                    write software that interfaces with it today, and it helps you work with
                    others when it comes time to share your design with the world.  By
                    properly documenting various fields within your module, you make it easier
                    on yourself to interact with today, and you make it easier to let others
                    get up to speed in the future.  By documenting your hardware, you're helping
                    to pay it forward.
                </aside>
            </section>

            <section>
                <h2>Thank you</h2>
                <h3>Questions</h3>
            </section>
        </div>
    </div> <!-- class="reveal" -->
    <!-- End of main presentation -->

    <!-- Start of configuration section -->
    <script src="lib/js/head.min.js"></script>
    <script src="js/reveal.js"></script>

    <script>
        var presenter = !!Reveal.getQueryHash().s;

        // More info https://github.com/hakimel/reveal.js#configuration
        Reveal.initialize({
            controls: presenter ? false : true,
            progress: true,
            history: true,
            center: true,
            controlsTutorial: presenter ? false : true,

            slideNumber: presenter ? null : 'c/t',

            // The "normal" size of the presentation, aspect ratio will be preserved
            // when the presentation is scaled to fit different resolutions. Can be
            // specified using percentage units.
            width: "100%",
            height: 700,

            // Factor of the display size that should remain empty around the content
            margin: 0.1,

            multiplex: {
                url: 'https://p.xobs.io/',
                id: '17b0ef733e56a4aa',
                secret: Reveal.getQueryHash().s || null
            },

            // Bounds for smallest/largest possible scale to apply to content
            minScale: 0.02,
            maxScale: 5.5,

            transition: 'slide', // none/fade/slide/convex/concave/zoom

            // More info https://github.com/hakimel/reveal.js#dependencies
            dependencies: [
                { src: 'lib/js/classList.js', condition: function () { return !document.body.classList; } },
                { src: 'plugin/markdown/marked.js', condition: function () { return !!document.querySelector('[data-markdown]'); } },
                { src: 'plugin/markdown/markdown.js', condition: function () { return !!document.querySelector('[data-markdown]'); } },
                { src: 'plugin/highlight/highlight.js', async: true, callback: function () { hljs.initHighlightingOnLoad(); } },
                { src: 'plugin/search/search.js', async: true },
                { src: 'plugin/zoom-js/zoom.js', async: true },
                { src: 'plugin/notes/notes.js', async: true },

                { src: 'lib/js/socket.io.js', async: true },
                {
                    src: presenter ?
                        'plugin/multiplex/master.js' :
                        'plugin/multiplex/client.js', async: true
                },
            ]
        });
    </script>
</body>

</html>