index: tabs -> spaces

Tabs were causing formatting issues with <code> blocks, so just set the
entire file to indent using spaces.

Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
Sean Cross 2020-01-02 16:45:42 +08:00
parent 04d15f7970
commit c83c36f456

View File

@ -2,155 +2,155 @@
<html> <html>
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>Paying It Forward: Documenting your Hardware</title> <title>Paying It Forward: Documenting your Hardware</title>
<meta name="description" content="A framework for easily creating beautiful presentations using HTML"> <meta name="description" content="A framework for easily creating beautiful presentations using HTML">
<meta name="author" content="Sean &quot;xobs&quot; Cross"> <meta name="author" content="Sean &quot;xobs&quot; Cross">
<meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> <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"> <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/reveal.css">
<link rel="stylesheet" href="css/theme/lca2020.css" id="theme"> <link rel="stylesheet" href="css/theme/lca2020.css" id="theme">
<!-- Theme used for syntax highlighting of code --> <!-- Theme used for syntax highlighting of code -->
<link rel="stylesheet" href="lib/css/zenburn.css"> <link rel="stylesheet" href="lib/css/zenburn.css">
<!-- Printing and PDF exports --> <!-- Printing and PDF exports -->
<script> <script>
var link = document.createElement('link'); var link = document.createElement('link');
link.rel = 'stylesheet'; link.rel = 'stylesheet';
link.type = 'text/css'; link.type = 'text/css';
link.href = window.location.search.match(/print-pdf/gi) ? 'css/print/pdf.css' : 'css/print/paper.css'; link.href = window.location.search.match(/print-pdf/gi) ? 'css/print/pdf.css' : 'css/print/paper.css';
document.getElementsByTagName('head')[0].appendChild(link); document.getElementsByTagName('head')[0].appendChild(link);
</script> </script>
<!--[if lt IE 9]> <!--[if lt IE 9]>
<script src="lib/js/html5shiv.js"></script> <script src="lib/js/html5shiv.js"></script>
<![endif]--> <![endif]-->
<style> <style>
/********************************************* /*********************************************
* ZOOM REVERSE TRANSITION (i.e. zoom out) * ZOOM REVERSE TRANSITION (i.e. zoom out)
*********************************************/ *********************************************/
.reveal .slides section[data-transition=zoomrev], .reveal .slides section[data-transition=zoomrev],
.reveal.zoomrev .slides section:not([data-transition]) { .reveal.zoomrev .slides section:not([data-transition]) {
transition-timing-function: ease; transition-timing-function: ease;
} }
.reveal .slides > section[data-transition=zoomrev].past, .reveal .slides > section[data-transition=zoomrev].past,
.reveal .slides > section[data-transition~=zoomrev-out].past, .reveal .slides > section[data-transition~=zoomrev-out].past,
.reveal.zoomrev .slides > section:not([data-transition]).past { .reveal.zoomrev .slides > section:not([data-transition]).past {
visibility: hidden; visibility: hidden;
-webkit-transform: scale(0.2); -webkit-transform: scale(0.2);
transform: scale(0.2); transform: scale(0.2);
} }
.reveal .slides > section[data-transition=zoomrev].future, .reveal .slides > section[data-transition=zoomrev].future,
.reveal .slides > section[data-transition~=zoomrev-in].future, .reveal .slides > section[data-transition~=zoomrev-in].future,
.reveal.zoomrev .slides > section:not([data-transition]).future { .reveal.zoomrev .slides > section:not([data-transition]).future {
visibility: hidden; visibility: hidden;
-webkit-transform: scale(16); -webkit-transform: scale(16);
transform: scale(16); transform: scale(16);
} }
.reveal .slides > section > section[data-transition=zoomrev].past, .reveal .slides > section > section[data-transition=zoomrev].past,
.reveal .slides > section > section[data-transition~=zoomrev-out].past, .reveal .slides > section > section[data-transition~=zoomrev-out].past,
.reveal.zoomrev .slides > section > section:not([data-transition]).past { .reveal.zoomrev .slides > section > section:not([data-transition]).past {
-webkit-transform: translate(0, 150%); -webkit-transform: translate(0, 150%);
transform: translate(0, 150%); transform: translate(0, 150%);
} }
.reveal .slides > section > section[data-transition=zoomrev].future, .reveal .slides > section > section[data-transition=zoomrev].future,
.reveal .slides > section > section[data-transition~=zoomrev-in].future, .reveal .slides > section > section[data-transition~=zoomrev-in].future,
.reveal.zoomrev .slides > section > section:not([data-transition]).future { .reveal.zoomrev .slides > section > section:not([data-transition]).future {
-webkit-transform: translate(0, -150%); -webkit-transform: translate(0, -150%);
transform: translate(0, -150%); transform: translate(0, -150%);
} }
</style> </style>
</head> </head>
<body> <body>
<!-- Start of main presentation --> <!-- Start of main presentation -->
<div class="reveal"> <div class="reveal">
<div class="footer"> <div class="footer">
<a class="url" href="https://p.xobs.io/lca20-pif/">p.xobs.io/lca20-pif</a> <a class="url" href="https://p.xobs.io/lca20-pif/">p.xobs.io/lca20-pif</a>
<span class="theme">The Linux of Things</span><span class="hashtag"> | #LCA2020</span><span class="twitter"> | <span class="theme">The Linux of Things</span><span class="hashtag"> | #LCA2020</span><span class="twitter"> |
@linuxconfau</span> @linuxconfau</span>
</div> </div>
<div class="slides"> <div class="slides">
<section data-background-image="css/theme/lca2019-title-bg-transparent.svg"> <section data-background-image="css/theme/lca2019-title-bg-transparent.svg">
<h1>Paying it Forward: Documenting Your Hardware Project</h1> <h1>Paying it Forward: Documenting Your Hardware Project</h1>
<h4>Approaches to documenting a hardware description language using lxsocdoc</h4> <h4>Approaches to documenting a hardware description language using lxsocdoc</h4>
<p align="right"> <p align="right">
<small>Sean Cross - <a href="https://xobs.io/">https://xobs.io/</a> - @xobs</small> <small>Sean Cross - <a href="https://xobs.io/">https://xobs.io/</a> - @xobs</small>
</p> </p>
</section> </section>
<section> <section>
<h2>Introduction</h2> <h2>Introduction</h2>
<aside class="notes"> <aside class="notes">
This is the Open ISA miniconf, which today tends to mean FPGAs. This means that 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 hardware and software are both extensible, and developers will be able to extend
the hardware in addition to making modifications to your software package. the hardware in addition to making modifications to your software package.
</aside> </aside>
</section> </section>
<section> <section>
<h2>About Me</h2> <h2>About Me</h2>
<aside class="notes"> <aside class="notes">
My name is Sean Cross, also known as "xobs". I will be speaking later this week 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 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 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 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 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 the problems I ran into while working on this project, and the solutions I came
up with. up with.
</aside> </aside>
</section> </section>
<section> <section>
<h2>Undocumented Hardware = Bad</h2> <h2>Undocumented Hardware = Bad</h2>
<h4>(But so easy to do!)</h4> <h4>(But so easy to do!)</h4>
<aside class="notes"> <aside class="notes">
Undocumented hardware is bad. There are all sorts of quirks, and even if you have 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 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 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 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 projects, but the concepts will carry over into any other Hardware Description
Language you may use. Language you may use.
The goal of this talk is to show how it's easy to document hardware with 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 the right framework, and how it's easier to have a project that's documented
than one that isn't. than one that isn't.
</aside> </aside>
</section> </section>
<section> <section>
<h2>Talk Outline</h2> <h2>Talk Outline</h2>
<ol> <ol>
<li>How to write HDL Code</li> <li>How to write HDL Code</li>
<li>Rationale behind <tt>lxsocdoc</tt></li> <li>Rationale behind <tt>lxsocdoc</tt></li>
<li>Examples of <tt>lxsocdoc</tt></li> <li>Examples of <tt>lxsocdoc</tt></li>
<li>Benefits of this approach</li> <li>Benefits of this approach</li>
</ol> </ol>
<aside class="notes"> <aside class="notes">
I'll briefly cover various methods of writing HDL code, then cover the rationale 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 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 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. implications of having documented hardware and how this will help you pay it forward.
</aside> </aside>
</section> </section>
<section> <section>
<h2>Motivation</h2> <h2>Motivation</h2>
<pre><code class="hljs cpp">// Hardware definitions of the SoC. Also is the main repo of <pre><code class="hljs cpp">// Hardware definitions of the SoC. Also is the main repo of
// documentation for the programmer-centric view // documentation for the programmer-centric view
// of the hardware. // of the hardware.
/* Start of memory range for the UART peripheral */ /* Start of memory range for the UART peripheral */
@ -165,46 +165,55 @@
The debug UART is always configured as 8N1. */ The debug UART is always configured as 8N1. */
#define UART_DATA_REG 0x00</code></pre> #define UART_DATA_REG 0x00</code></pre>
<p><tt>mach_defines.h</tt>, Hackaday 2019 Con Badge</p> <p><tt>mach_defines.h</tt>, Hackaday 2019 Con Badge</p>
<aside class="notes"> <aside class="notes">
Verilog and VHDL are kind of the C or assembly of the FPGA world. They're universal, 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, 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 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 the HDL and/or C header files. This works, but we can do better. We just need to
describe the hardware better. describe the hardware better.
</aside> </aside>
</section> </section>
<section> <section>
<h2>About LiteX and lxsocdoc</h2> <h2>About LiteX</h2>
<aside class="notes"> <ol>
Fomu uses LiteX, which is related to Migen. This is a hardware description language <li>Hardware Description Language embedded in Python</li>
written in Python. You write Python code and run the program, and it generates <ol>
a design file -- either Verilog code, or a Yosys netlist. There are many other <li>Doesn't run Python in hardware!</li>
alternatives such as SpinalHDL or Chisel. By writing in Python as opposed to </ol>
direct Verilog, we get a lot of nice primitives. The examples from this talk <li>Emits Verilog (or Yosys netlists)</li>
are taken from lxsocdoc and LiteX, but most higher-level hardware description <li>Makes it easy to create a SoC</li>
languages can take similar approaches to documentation. <li>Powers the LCA2020 video production setup</li>
</aside> </ol>
</section> <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> <section>
<h2>LiteX Primitives</h2> <h2>LiteX Primitives</h2>
<pre><code class="python" data-trim>class GPIOOut(Module, AutoCSR): <pre><code class="python" data-trim>class GPIOOut(Module, AutoCSR):
def __init__(self, signal): def __init__(self, signal):
self._out = CSRStorage(len(signal)) self._out = CSRStorage(len(signal))
self.comb += signal.eq(self._out.storage)</code></pre> self.comb += signal.eq(self._out.storage)</code></pre>
<aside class="notes"> <aside class="notes">
In LiteX, two of the primitives used to expose hardware registers to the CPU softcore 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 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)`, 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. 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. Similarly, `self.othername = CSRStorage(8)` will give 8-bits of write-only memory.
</aside> </aside>
</section> </section>
<section> <section>
<h4>SPI Bitbang Module</h4> <h4>Case Study: SPI Bitbang Module</h4>
<pre><code class="python" data-trim>self.bitbang = CSRStorage(4) <pre><code class="python" data-trim>self.bitbang = CSRStorage(4)
If(self.bitbang.storage[3], If(self.bitbang.storage[3],
dq.oe.eq(0) dq.oe.eq(0)
).Else( ).Else(
@ -217,33 +226,47 @@ If(self.bitbang.storage[1],
dq.o.eq( dq.o.eq(
Cat(self.bitbang.storage[0], Replicate(1, spi_width-1)) Cat(self.bitbang.storage[0], Replicate(1, spi_width-1))
)</code></pre> )</code></pre>
<aside class="notes"> <aside class="notes">
This works well, but exposes a new problem: Documentation. As an example, I was 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 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 driver worked. There wasn't any documentation except the source, which looked
like this. like this.
You can kind of understand it, but it does take a lot of mental power to 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 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! in the storage array, but then I thought: There has to be a better way!
</aside> </aside>
</section> </section>
<section> <section>
<h2>Aside: Python Docstrings</h2> <h2>Aside: Python Docstrings</h2>
<aside class="notes"> <pre><code class="python" data-trim>def _format_cmd(cmd, spi_width):
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 `cmd` is the read instruction. Since everything is
what a Python object is and how to use it. This is almost what we want, transmitted on all dq lines (cmd, adr and data), extend/
except once the final SoC is generated we don't really care so much about interleave cmd to full pads.dq width even if dq1-dq3 are
things like constructor arguments or method properties. Documentation for don't care during the command phase: For example, for
the end user is different from documentation for the module developer. N25Q128, 0xeb is the quad i/o fast read, and extended
</aside> to 4 bits (dq1,dq2,dq3 high) is: 0xfffefeff
</section> """
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> <section>
<h4>New Register Definition</h4> <h2>New Register Definition</h2>
<pre><code class="python" data-trim>self.bitbang = CSRStorage(4, fields=[ <pre><code class="python" data-trim>self.bitbang = CSRStorage(4, fields=[
CSRField("mosi", description="Output value for MOSI..." CSRField("mosi", description="Output value for MOSI..."
CSRField("clk", description="Output value for SPI CLK..." CSRField("clk", description="Output value for SPI CLK..."
CSRField("cs_n", description="Output value for SPI C..." CSRField("cs_n", description="Output value for SPI C..."
@ -252,22 +275,22 @@ dq.o.eq(
("1", "IN", "SPI pins are all input"), ("1", "IN", "SPI pins are all input"),
]) ])
], description="""Bitbang controls for SPI output. Only ], description="""Bitbang controls for SPI output. Only
standard 1x SPI is supported, and as a result all standard 1x SPI is supported, and as a result all
four wires are ganged together. This means that it four wires are ganged together. This means that it
is only possible to perform half-duplex operations, is only possible to perform half-duplex operations,
using this SPI core.""")</code></pre> using this SPI core.""")</code></pre>
<aside class="notes"> <aside class="notes">
This is when I hit upon the idea of `lxsocdoc`. The basic idea is that 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 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 more information to the CSR objects to make our life easier. And so, after
working with the LiteX creator Florent, we refactored the bitbang working with the LiteX creator Florent, we refactored the bitbang
definition to this. definition to this.
</aside> </aside>
</section> </section>
<section> <section>
<h4>Refactored SPI Bitbang</h4> <h2>Refactored SPI Bitbang</h2>
<pre><code class="python" data-trim>If(self.bitbang.fields.dir, <pre><code class="python" data-trim>If(self.bitbang.fields.dir,
dq.oe.eq(0) dq.oe.eq(0)
).Else( ).Else(
dq.oe.eq(1) dq.oe.eq(1)
@ -279,198 +302,198 @@ If(self.bitbang.fields.clk,
dq.o.eq( dq.o.eq(
Cat(self.bitbang.fields.mosi, Replicate(1, spi_width-1)) Cat(self.bitbang.fields.mosi, Replicate(1, spi_width-1))
)</code></pre> )</code></pre>
<aside class="notes"> <aside class="notes">
Now the actual bitbang logic looks like this. Now the actual bitbang logic looks like this.
This is a little bit easier to understand -- no longer are we looking at indices 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. 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. But because Python can introspect Python very easily, this is just the beginning.
</aside> </aside>
</section> </section>
<section> <section>
<h2>Generating a Manual</h2> <h2>Generating a Manual</h2>
<img data-src="img/lxspi_bitbang.png"> <img data-src="img/lxspi_bitbang.png">
<aside class="notes"> <aside class="notes">
After the design is elaborated and the output file is generated, we can iterate 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 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 information. We can actually generate a full reference manual, just like one you
would receive from a SoC Vendor. would receive from a SoC Vendor.
For example, this is what the start of the Fomu SPI Flash documentation looks like: For example, this is what the start of the Fomu SPI Flash documentation looks like:
[Register Listing for LXSPI] [Register Listing for LXSPI]
This is already pretty useful. You can hand this file to someone and show them 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", 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 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 while developing software for your own hardware is still invaluable. Hardware
designs are complex things, and not having to decode bitfield offsets in your 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 head or constantly referring to various sections of code to see how it's implemented
saves valuable time. saves valuable time.
</aside> </aside>
</section> </section>
<section> <section>
<h2>Undocumented Fields</h2> <h2>Undocumented Fields</h2>
<aside class="notes"> <aside class="notes">
It turns out that there is enough information that we can extract that It turns out that there is enough information that we can extract that
even undocumented fields are somewhat useful. even undocumented fields are somewhat useful.
</aside> </aside>
</section> </section>
<section> <section>
<h2>Interrupts</h2> <h2>Interrupts</h2>
<img data-src="img/interrupts.png"> <img data-src="img/interrupts.png">
<aside class="notes"> <aside class="notes">
We can even extract interrupt information, including which bits inside an We can even extract interrupt information, including which bits inside an
interrupt register map to which event, and which interrupt number is assigned interrupt register map to which event, and which interrupt number is assigned
to a given module. to a given module.
</aside> </aside>
</section> </section>
<section> <section>
<h2>More Documentation: ModuleDoc</h2> <h2>More Documentation: ModuleDoc</h2>
<img data-src="img/timer0-doc.png"> <img data-src="img/timer0-doc.png">
<aside class="notes"> <aside class="notes">
So now we have register documentation. Can we do better? Of course we can. 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 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 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 works. We can take a cue from CSRs themselves, and add module documentation
in a similar fashion. in a similar fashion.
</aside> </aside>
</section> </section>
<section> <section>
<h2>Protocol Documentation</h2> <h2>Protocol Documentation</h2>
<img data-src="img/usb-wishbone.png"> <img data-src="img/usb-wishbone.png">
<aside class="notes"> <aside class="notes">
We can add additional documentation such as protocol waveforms. Here We can add additional documentation such as protocol waveforms. Here
we use WaveDrom to define the protocol of Wishbone-over-SPI. There we use WaveDrom to define the protocol of Wishbone-over-SPI. There
are multiple formats of the protocol depending on which version is are multiple formats of the protocol depending on which version is
instantiated. instantiated.
</aside> </aside>
</section> </section>
<section> <section>
<h2>SVD: Documentation for Machines</h2> <h2>SVD: Documentation for Machines</h2>
<aside class="notes"> <aside class="notes">
Having documentation for humans is great, but we can go one step further and 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 make documentation for computers. SVD is an XML format defined by ARM that
defines various aspects about a chip, including memory layout, interrupt map, defines various aspects about a chip, including memory layout, interrupt map,
and register sets. SVD includes information such as default values and field and register sets. SVD includes information such as default values and field
bits, all information we have thanks to the introspectability of Python. bits, all information we have thanks to the introspectability of Python.
</aside> </aside>
</section> </section>
<section> <section>
<h2>SVD2Rust: Generating Safe Accessors</h2> <h2>SVD2Rust: Generating Safe Accessors</h2>
<aside class="notes"> <aside class="notes">
In addition to generating a reference manual for humans, we can generate an SVD 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 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 file into a Rust Peripheral Access Crate (PAC) using `SVD2Rust`, giving us an
easy way to safely access all peripherals on a device. easy way to safely access all peripherals on a device.
</aside> </aside>
</section> </section>
<section> <section>
<h2>Renode: Fancy Register Logging</h2> <h2>Renode: Fancy Register Logging</h2>
<aside class="notes"> <aside class="notes">
We can also import this SVD file into an emulator such as Renode, which will 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 print out fields and flags that get accessed, giving us greater visibility into
what a program is doing. what a program is doing.
</aside> </aside>
</section> </section>
<section> <section>
<h2>Benefits of Higher Level Languages</h2> <h2>Benefits of Higher Level Languages</h2>
<aside class="notes"> <aside class="notes">
By using a higher level language, we are able to describe the hardware 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 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 fields to our register definition fields to provide nice, human-readable
documentation. This also allows us to generate machine-readable formats documentation. This also allows us to generate machine-readable formats
such as SVD, which opens up a whole world of software. such as SVD, which opens up a whole world of software.
</aside> </aside>
</section> </section>
<section> <section>
<h2>Documentation helps you</h2> <h2>Documentation helps you</h2>
<h2>Documentation helps others</h2> <h2>Documentation helps others</h2>
<aside class="notes"> <aside class="notes">
Documenting your hardware is important because it is necessary for you to 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 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 others when it comes time to share your design with the world. By
properly documenting various fields within your module, you make it easier 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 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 get up to speed in the future. By documenting your hardware, you're helping
to pay it forward. to pay it forward.
</aside> </aside>
</section> </section>
<section> <section>
<h2>Thank you</h2> <h2>Thank you</h2>
<h3>Questions</h3> <h3>Questions</h3>
</section> </section>
</div> </div>
</div> <!-- class="reveal" --> </div> <!-- class="reveal" -->
<!-- End of main presentation --> <!-- End of main presentation -->
<!-- Start of configuration section --> <!-- Start of configuration section -->
<script src="lib/js/head.min.js"></script> <script src="lib/js/head.min.js"></script>
<script src="js/reveal.js"></script> <script src="js/reveal.js"></script>
<script> <script>
var presenter = !!Reveal.getQueryHash().s; var presenter = !!Reveal.getQueryHash().s;
// More info https://github.com/hakimel/reveal.js#configuration // More info https://github.com/hakimel/reveal.js#configuration
Reveal.initialize({ Reveal.initialize({
controls: presenter ? false : true, controls: presenter ? false : true,
progress: true, progress: true,
history: true, history: true,
center: true, center: true,
controlsTutorial: presenter ? false : true, controlsTutorial: presenter ? false : true,
slideNumber: presenter ? null : 'c/t', slideNumber: presenter ? null : 'c/t',
// The "normal" size of the presentation, aspect ratio will be preserved // The "normal" size of the presentation, aspect ratio will be preserved
// when the presentation is scaled to fit different resolutions. Can be // when the presentation is scaled to fit different resolutions. Can be
// specified using percentage units. // specified using percentage units.
width: 960, width: 960,
height: 700, height: 700,
// Factor of the display size that should remain empty around the content // Factor of the display size that should remain empty around the content
margin: 0.1, margin: 0.1,
multiplex: { multiplex: {
url: 'https://p.xobs.io/', url: 'https://p.xobs.io/',
id: '631bb3db6fbaea78', id: '631bb3db6fbaea78',
secret: Reveal.getQueryHash().s || null secret: Reveal.getQueryHash().s || null
}, },
// Bounds for smallest/largest possible scale to apply to content // Bounds for smallest/largest possible scale to apply to content
minScale: 0.02, minScale: 0.02,
maxScale: 5.5, maxScale: 5.5,
transition: 'slide', // none/fade/slide/convex/concave/zoom transition: 'slide', // none/fade/slide/convex/concave/zoom
// More info https://github.com/hakimel/reveal.js#dependencies // More info https://github.com/hakimel/reveal.js#dependencies
dependencies: [ dependencies: [
{ src: 'lib/js/classList.js', condition: function () { return !document.body.classList; } }, { 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/marked.js', condition: function () { return !!document.querySelector('[data-markdown]'); } },
{ src: 'plugin/markdown/markdown.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/highlight/highlight.js', async: true, callback: function () { hljs.initHighlightingOnLoad(); } },
{ src: 'plugin/search/search.js', async: true }, { src: 'plugin/search/search.js', async: true },
{ src: 'plugin/zoom-js/zoom.js', async: true }, { src: 'plugin/zoom-js/zoom.js', async: true },
{ src: 'plugin/notes/notes.js', async: true }, { src: 'plugin/notes/notes.js', async: true },
{ src: 'lib/js/socket.io.js', async: true }, { src: 'lib/js/socket.io.js', async: true },
{ {
src: presenter ? src: presenter ?
'plugin/multiplex/master.js' : 'plugin/multiplex/master.js' :
'plugin/multiplex/client.js', async: true 'plugin/multiplex/client.js', async: true
}, },
] ]
}); });
</script> </script>
</body> </body>
</html> </html>