theme: add lca2020 theme
Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
parent
6f8dcb1827
commit
0737480489
422
css/theme/lca2020.css
Normal file
422
css/theme/lca2020.css
Normal file
@ -0,0 +1,422 @@
|
|||||||
|
/**
|
||||||
|
* Black theme for reveal.js. This is the opposite of the 'white' theme.
|
||||||
|
*
|
||||||
|
* By Hakim El Hattab, http://hakim.se
|
||||||
|
*/
|
||||||
|
|
||||||
|
@import url(../../lib/font/space-mono/space-mono.css);
|
||||||
|
section.has-light-background,
|
||||||
|
section.has-light-background h1,
|
||||||
|
section.has-light-background h2,
|
||||||
|
section.has-light-background h3,
|
||||||
|
section.has-light-background h4,
|
||||||
|
section.has-light-background h5,
|
||||||
|
section.has-light-background h6 {
|
||||||
|
color: #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************
|
||||||
|
* GLOBAL STYLES
|
||||||
|
*********************************************/
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: #387A3B;
|
||||||
|
background-color: #387A3B;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal .footer {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 1em;
|
||||||
|
right: 2em;
|
||||||
|
text-align: right;
|
||||||
|
font-size: 0.5em;
|
||||||
|
width: 100%;
|
||||||
|
height: 96px;
|
||||||
|
background-image: url("lca2019-logo.svg");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: flex-end;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal .footer .url {
|
||||||
|
position: absolute;
|
||||||
|
padding-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal .footer .theme {
|
||||||
|
padding-right: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal .footer .hashtag {
|
||||||
|
padding-right: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width:800px) {
|
||||||
|
.reveal .footer .url {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width:550px) {
|
||||||
|
.reveal .footer {
|
||||||
|
background-image: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width:750px) {
|
||||||
|
.reveal .footer .twitter {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width:1050px) {
|
||||||
|
.reveal .footer .theme {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width:1300px) {
|
||||||
|
.reveal .footer .hashtag {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal {
|
||||||
|
font-family: "Space Mono", Helvetica, sans-serif;
|
||||||
|
font-size: 42px;
|
||||||
|
font-weight: normal;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
::selection {
|
||||||
|
color: #fff;
|
||||||
|
background: #bee4fd;
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-moz-selection {
|
||||||
|
color: #fff;
|
||||||
|
background: #bee4fd;
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal .slides section,
|
||||||
|
.reveal .slides section>section {
|
||||||
|
line-height: 1.3;
|
||||||
|
font-weight: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************
|
||||||
|
* HEADERS
|
||||||
|
*********************************************/
|
||||||
|
|
||||||
|
.reveal h1,
|
||||||
|
.reveal h2,
|
||||||
|
.reveal h3,
|
||||||
|
.reveal h4,
|
||||||
|
.reveal h5,
|
||||||
|
.reveal h6 {
|
||||||
|
margin: 0 0 20px 0;
|
||||||
|
color: #fff;
|
||||||
|
font-family: "Space Mono", Helvetica, sans-serif;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.2;
|
||||||
|
letter-spacing: normal;
|
||||||
|
text-transform: uppercase;
|
||||||
|
text-shadow: none;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal h1 {
|
||||||
|
font-size: 2.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal h2 {
|
||||||
|
font-size: 1.6em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal h3 {
|
||||||
|
font-size: 1.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal h4 {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal h1 {
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************
|
||||||
|
* OTHER
|
||||||
|
*********************************************/
|
||||||
|
|
||||||
|
.reveal p {
|
||||||
|
margin: 20px 0;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure certain elements are never larger than the slide itself */
|
||||||
|
|
||||||
|
.reveal img,
|
||||||
|
.reveal video,
|
||||||
|
.reveal iframe {
|
||||||
|
max-width: 95%;
|
||||||
|
max-height: 95%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal strong,
|
||||||
|
.reveal b {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal em {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal ol,
|
||||||
|
.reveal dl,
|
||||||
|
.reveal ul {
|
||||||
|
display: inline-block;
|
||||||
|
text-align: left;
|
||||||
|
margin: 0 0 0 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal ol {
|
||||||
|
list-style-type: decimal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal ul {
|
||||||
|
list-style-type: disc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal ul ul {
|
||||||
|
list-style-type: square;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal ul ul ul {
|
||||||
|
list-style-type: circle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal ul ul,
|
||||||
|
.reveal ul ol,
|
||||||
|
.reveal ol ol,
|
||||||
|
.reveal ol ul {
|
||||||
|
display: block;
|
||||||
|
margin-left: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal dt {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal dd {
|
||||||
|
margin-left: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal blockquote {
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
width: 70%;
|
||||||
|
margin: 20px auto;
|
||||||
|
padding: 5px;
|
||||||
|
font-style: italic;
|
||||||
|
background: rgba(255, 255, 255, 0.05);
|
||||||
|
box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal blockquote p:first-child,
|
||||||
|
.reveal blockquote p:last-child {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal q {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal pre {
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
width: 90%;
|
||||||
|
margin: 20px auto;
|
||||||
|
text-align: left;
|
||||||
|
font-size: 0.55em;
|
||||||
|
font-family: monospace;
|
||||||
|
line-height: 1.2em;
|
||||||
|
word-wrap: break-word;
|
||||||
|
box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal code {
|
||||||
|
font-family: monospace;
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal pre code {
|
||||||
|
display: block;
|
||||||
|
padding: 5px;
|
||||||
|
overflow: auto;
|
||||||
|
max-height: 400px;
|
||||||
|
word-wrap: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal table {
|
||||||
|
margin: auto;
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal table th {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal table th,
|
||||||
|
.reveal table td {
|
||||||
|
text-align: left;
|
||||||
|
padding: 0.2em 0.5em 0.2em 0.5em;
|
||||||
|
border-bottom: 1px solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal table th[align="center"],
|
||||||
|
.reveal table td[align="center"] {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal table th[align="right"],
|
||||||
|
.reveal table td[align="right"] {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal table tbody tr:last-child th,
|
||||||
|
.reveal table tbody tr:last-child td {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal sup {
|
||||||
|
vertical-align: super;
|
||||||
|
font-size: smaller;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal sub {
|
||||||
|
vertical-align: sub;
|
||||||
|
font-size: smaller;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal small {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 0.6em;
|
||||||
|
line-height: 1.2em;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal small * {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************
|
||||||
|
* LINKS
|
||||||
|
*********************************************/
|
||||||
|
|
||||||
|
.reveal a {
|
||||||
|
color: #42affa;
|
||||||
|
text-decoration: none;
|
||||||
|
-webkit-transition: color .15s ease;
|
||||||
|
-moz-transition: color .15s ease;
|
||||||
|
transition: color .15s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal a:hover {
|
||||||
|
color: #8dcffc;
|
||||||
|
text-shadow: none;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal .roll span:after {
|
||||||
|
color: #fff;
|
||||||
|
background: #068de9;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************
|
||||||
|
* IMAGES
|
||||||
|
*********************************************/
|
||||||
|
|
||||||
|
.reveal section img {
|
||||||
|
margin: 15px 0px;
|
||||||
|
background: rgba(255, 255, 255, 0.12);
|
||||||
|
border: 4px solid #fff;
|
||||||
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal section img.plain {
|
||||||
|
border: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal a img {
|
||||||
|
-webkit-transition: all .15s linear;
|
||||||
|
-moz-transition: all .15s linear;
|
||||||
|
transition: all .15s linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal a:hover img {
|
||||||
|
background: rgba(255, 255, 255, 0.2);
|
||||||
|
border-color: #42affa;
|
||||||
|
box-shadow: 0 0 20px rgba(0, 0, 0, 0.55);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************
|
||||||
|
* VIDEOS
|
||||||
|
*********************************************/
|
||||||
|
|
||||||
|
.reveal section video {
|
||||||
|
margin: 15px 0px;
|
||||||
|
background: rgba(255, 255, 255, 0.12);
|
||||||
|
border: 4px solid #fff;
|
||||||
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal section video.plain {
|
||||||
|
border: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal a video {
|
||||||
|
-webkit-transition: all .15s linear;
|
||||||
|
-moz-transition: all .15s linear;
|
||||||
|
transition: all .15s linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************
|
||||||
|
* NAVIGATION CONTROLS
|
||||||
|
*********************************************/
|
||||||
|
|
||||||
|
.reveal .controls {
|
||||||
|
color: #42affa;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************
|
||||||
|
* PROGRESS BAR
|
||||||
|
*********************************************/
|
||||||
|
|
||||||
|
.reveal .progress {
|
||||||
|
background: rgba(0, 0, 0, 0.2);
|
||||||
|
color: #42affa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal .progress span {
|
||||||
|
-webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
|
||||||
|
-moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
|
||||||
|
transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************
|
||||||
|
* PRINT BACKGROUND
|
||||||
|
*********************************************/
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
.backgrounds {
|
||||||
|
background-color: #222;
|
||||||
|
}
|
||||||
|
}
|
303
index.html
303
index.html
@ -15,7 +15,7 @@
|
|||||||
<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/lca2019.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">
|
||||||
@ -92,152 +92,205 @@
|
|||||||
<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>
|
||||||
<h1>Hardware is different</h1>
|
<aside class="notes">
|
||||||
<ol>
|
This is the Open ISA miniconf, which today tends to mean FPGAs. This means that
|
||||||
<li>Massively Parallel</li>
|
hardware and software are both extensible, and developers will be able to extend
|
||||||
</ol>
|
the hardware in addition to making modifications to your software package.
|
||||||
|
</aside>
|
||||||
</section>
|
</section>
|
||||||
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
|
|
||||||
the hardware in addition to making modifications to your software package.
|
|
||||||
|
|
||||||
Undocumented hardware is bad. There are all sorts of quirks, and even if you have
|
<section>
|
||||||
the source code, it can be very difficult to read. I'm the primary developer for
|
<aside class="notes">
|
||||||
the Fomu project, and this talk will cover some of the issues I've run into with
|
Undocumented hardware is bad. There are all sorts of quirks, and even if you have
|
||||||
respect to documentation. It is most directly related to the LiteX and Migen
|
the source code, it can be very difficult to read. I'm the primary developer for
|
||||||
projects, but the concepts will carry over into any other Hardware Description
|
the Fomu project, and this talk will cover some of the issues I've run into with
|
||||||
Language you may use.
|
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.
|
||||||
|
</aside>
|
||||||
|
</section>
|
||||||
|
|
||||||
I'll briefly cover various methods of writing HDL code, then cover the rationale
|
<section>
|
||||||
behind the approach we take with lxsocdoc, then give an example of how to use
|
<aside class="notes">
|
||||||
lxsocdoc and how you might apply it to your language. Finally, I'll cover the
|
I'll briefly cover various methods of writing HDL code, then cover the rationale
|
||||||
implications of having documented hardware and how this will help you pay it forward.
|
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>
|
||||||
|
|
||||||
Verilog and VHDL are kind of the C or assembly of the FPGA world. They're universal,
|
<section>
|
||||||
but somewhat unwieldy to use. You need to manually set up your address decoders,
|
<aside class="notes">
|
||||||
and documentation is very free-form. Common approaches today involve comments in
|
Verilog and VHDL are kind of the C or assembly of the FPGA world. They're universal,
|
||||||
the HDL and/or C header files. This works, but we can do better. We just need to
|
but somewhat unwieldy to use. You need to manually set up your address decoders,
|
||||||
describe the hardware better.
|
and documentation is very free-form. Common approaches today involve comments in
|
||||||
```//Hardware definitions of the SoC. Also is the main repo of documentation for the
|
the HDL and/or C header files. This works, but we can do better. We just need to
|
||||||
//programmer-centric view of the hardware.```
|
describe the hardware better.
|
||||||
|
```//Hardware definitions of the SoC. Also is the main repo of documentation for the
|
||||||
|
//programmer-centric view of the hardware.```
|
||||||
|
</aside>
|
||||||
|
</section>
|
||||||
|
|
||||||
Fomu uses LiteX, which is related to Migen. This is a hardware description language
|
<section>
|
||||||
written in Python. You write Python code and run the program, and it generates
|
<aside class="notes">
|
||||||
a design file -- either Verilog code, or a Yosys netlist. There are many other
|
Fomu uses LiteX, which is related to Migen. This is a hardware description language
|
||||||
alternatives such as SpinalHDL or Chisel. By writing in Python as opposed to
|
written in Python. You write Python code and run the program, and it generates
|
||||||
direct Verilog, we get a lot of nice primitives. The examples from this talk
|
a design file -- either Verilog code, or a Yosys netlist. There are many other
|
||||||
are taken from lxsocdoc and LiteX, but most higher-level hardware description
|
alternatives such as SpinalHDL or Chisel. By writing in Python as opposed to
|
||||||
languages can take similar approaches to documentation.
|
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>
|
||||||
|
|
||||||
In LiteX, two of the primitives used to expose hardware registers to the CPU softcore
|
<section>
|
||||||
are CSRStorage and CSRStatus. Instead of manually wiring up a crossbar and decoding
|
<aside class="notes">
|
||||||
the addresses ourselves, we just need to write `self.regname = CSRStatus(8)`,
|
In LiteX, two of the primitives used to expose hardware registers to the CPU softcore
|
||||||
and the build system will wire up 8 bits of read-only memory to the target CPU.
|
are CSRStorage and CSRStatus. Instead of manually wiring up a crossbar and decoding
|
||||||
Similarly, `self.othername = CSRStorage(8)` will give 8-bits of write-only memory.
|
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>
|
||||||
|
|
||||||
This works well, but exposes a new problem: Documentation. As an example, I was
|
<section>
|
||||||
working with the SPI Flash block in litex, and wanted to know how the bitbang
|
<h4>SPI Bitbang Module</h4>
|
||||||
driver worked. There wasn't any documentation except the source, which looked
|
<pre><code class="python" data-trim>self.bitbang = CSRStorage(4)
|
||||||
like this:
|
If(self.bitbang.storage[3],
|
||||||
|
dq.oe.eq(0)
|
||||||
|
).Else(
|
||||||
|
dq.oe.eq(1)
|
||||||
|
),
|
||||||
|
If(self.bitbang.storage[1], # CPOL=0/CPHA=0 or CPOL=1/CPHA=1 only.
|
||||||
|
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.
|
||||||
|
|
||||||
self.bitbang = CSRStorage(4)
|
You can kind of understand it, but it does take a lot of mental power to
|
||||||
If(self.bitbang.storage[3],
|
work through it. I started by creating aliases for the various elements
|
||||||
dq.oe.eq(0)
|
in the storage array, but then I thought: There has to be a better way!
|
||||||
).Else(
|
</aside>
|
||||||
dq.oe.eq(1)
|
</section>
|
||||||
),
|
|
||||||
If(self.bitbang.storage[1], # CPOL=0/CPHA=0 or CPOL=1/CPHA=1 only.
|
|
||||||
self.miso.status.eq(dq.i[1])
|
|
||||||
),
|
|
||||||
dq.o.eq(Cat(self.bitbang.storage[0], Replicate(1, spi_width-1)))
|
|
||||||
|
|
||||||
You can kind of understand it, but it does take a lot of mental power to
|
<section>
|
||||||
work through it. I started by creating aliases for the various elements
|
<aside class="notes">
|
||||||
in the storage array, but then I thought: There has to be a better way!
|
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>
|
||||||
|
|
||||||
As an aside, Python has something called Pydoc and Docstrings. These are
|
<section>
|
||||||
comments that go at the top of functions and classes that let you describe
|
<aside class="notes">
|
||||||
what a Python object is and how to use it. This is almost what we want,
|
This is when I hit upon the idea of `lxsocdoc`. The basic idea is that
|
||||||
except once the final SoC is generated we don't really care so much about
|
Python is really good at introspecting Python, so let's add a little bit
|
||||||
things like constructor arguments or method properties. Documentation for
|
more information to the CSR objects to make our life easier. And so, after
|
||||||
the end user is different from documentation for the module developer.
|
working with the LiteX creator Florent, we refactored the bitbang
|
||||||
|
definition to this:
|
||||||
|
|
||||||
This is when I hit upon the idea of `lxsocdoc`. The basic idea is that
|
self.bitbang = CSRStorage(4, fields=[
|
||||||
Python is really good at introspecting Python, so let's add a little bit
|
CSRField("mosi", description="Output value for MOSI pin, valid whenever ``dir`` is ``0``."),
|
||||||
more information to the CSR objects to make our life easier. And so, after
|
CSRField("clk", description="Output value for SPI CLK pin."),
|
||||||
working with the LiteX creator Florent, we refactored the bitbang
|
CSRField("cs_n", description="Output value for SPI CSn pin."),
|
||||||
definition to this:
|
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.
|
||||||
|
""")
|
||||||
|
</aside>
|
||||||
|
</section>
|
||||||
|
|
||||||
self.bitbang = CSRStorage(4, fields=[
|
<section>
|
||||||
CSRField("mosi", description="Output value for MOSI pin, valid whenever ``dir`` is ``0``."),
|
<aside class="notes">
|
||||||
CSRField("clk", description="Output value for SPI CLK pin."),
|
Now the actual bitbang logic looks like:
|
||||||
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.
|
|
||||||
""")
|
|
||||||
|
|
||||||
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)))
|
||||||
|
|
||||||
If(self.bitbang.fields.dir,
|
This is a little bit easier to understand -- no longer are we looking at indices
|
||||||
dq.oe.eq(0)
|
in an array to determine what field does what. Instead we get actual named fields.
|
||||||
).Else(
|
But because Python can introspect Python very easily, this is just the beginning.
|
||||||
dq.oe.eq(1)
|
</aside>
|
||||||
),
|
</section>
|
||||||
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)))
|
|
||||||
|
|
||||||
This is a little bit easier to understand -- no longer are we looking at indices
|
<section>
|
||||||
in an array to determine what field does what. Instead we get actual named fields.
|
<aside class="notes">
|
||||||
But because Python can introspect Python very easily, this is just the beginning.
|
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.
|
||||||
|
|
||||||
After the design is elaborated and the output file is generated, we can iterate
|
For example, this is what the start of the Fomu SPI Flash documentation looks like:
|
||||||
through the resulting tree and pick out any CSR objects and using any additional
|
[Register Listing for LXSPI]
|
||||||
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:
|
This is already pretty useful. You can hand this file to someone and show them
|
||||||
[Register Listing for LXSPI]
|
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>
|
||||||
|
|
||||||
This is already pretty useful. You can hand this file to someone and show them
|
<section>
|
||||||
how your design works. But the title of this talk is called "Paying it Forward",
|
<aside class="notes">
|
||||||
and I can tell you from experience that having such a reference manual for yourself
|
So now we have register documentation. Can we do better? Of course we can.
|
||||||
while developing software for your own hardware is still invaluable. Hardware
|
SoC reference manuals are more than just register definitions. They also include
|
||||||
designs are complex things, and not having to decode bitfield offsets in your
|
background information on protocols, as well as more elaboration on how the block
|
||||||
head or constantly referring to various sections of code to see how it's implemented
|
works. We can take a cue from CSRs themselves, and add module documentation
|
||||||
saves valuable time.
|
in a similar fashion.
|
||||||
|
</aside>
|
||||||
|
</section>
|
||||||
|
---ModuleDoc---
|
||||||
|
|
||||||
So now we have register documentation. Can we do better? Of course we can.
|
<section>
|
||||||
SoC reference manuals are more than just register definitions. They also include
|
<aside class="notes">
|
||||||
background information on protocols, as well as more elaboration on how the block
|
Having documentation for humans is great, but we can go one step further and
|
||||||
works. We can take a cue from CSRs themselves, and add module documentation
|
make documentation for computers. SVD is an XML format defined by ARM that
|
||||||
in a similar fashion.
|
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>
|
||||||
|
|
||||||
---ModuleDoc---
|
<section>
|
||||||
|
<aside class="notes">
|
||||||
Having documentation for humans is great, but we can go one step further and
|
In addition to generating a reference manual for humans, we can generate an SVD
|
||||||
make documentation for computers. SVD is an XML format defined by ARM that
|
file that's usable in a wide variety of areas. For example, we can turn an SVD
|
||||||
defines various aspects about a chip, including memory layout, interrupt map,
|
file into a Rust Peripheral Access Crate (PAC) using `SVD2Rust`, giving us an
|
||||||
and register sets. SVD includes information such as default values and field
|
easy way to safely access all peripherals on a device.
|
||||||
bits, all information we have thanks to the introspectability of Python.
|
</aside>
|
||||||
|
</section>
|
||||||
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.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<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
|
lxsocdoc
|
||||||
intro to litex/migen
|
intro to litex/migen
|
||||||
concept of mixins
|
concept of mixins
|
||||||
|
Loading…
Reference in New Issue
Block a user