Created
May 10, 2018 10:56
-
-
Save expipiplus1/d3a5e36e2af7e2fbfc5e3a280e9549f9 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta name="generator" content="pandoc"> | |
<meta name="author" content="Joe Hermaszewski"> | |
<title>FPGA Programming with Clash</title> | |
<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, minimal-ui"> | |
<link rel="stylesheet" href="http://cdn.rawgit.com/hakimel/reveal.js/3.5.0//css/reveal.css"> | |
<style type="text/css"> | |
code{white-space: pre-wrap;} | |
span.smallcaps{font-variant: small-caps;} | |
span.underline{text-decoration: underline;} | |
div.column{display: inline-block; vertical-align: top; width: 50%;} | |
</style> | |
<style type="text/css"> | |
a.sourceLine { display: inline-block; line-height: 1.25; } | |
a.sourceLine { pointer-events: none; color: inherit; text-decoration: inherit; } | |
a.sourceLine:empty { height: 1.2em; position: absolute; } | |
.sourceCode { overflow: visible; } | |
code.sourceCode { white-space: pre; position: relative; } | |
div.sourceCode { margin: 1em 0; } | |
pre.sourceCode { margin: 0; } | |
@media screen { | |
div.sourceCode { overflow: auto; } | |
} | |
@media print { | |
code.sourceCode { white-space: pre-wrap; } | |
a.sourceLine { text-indent: -1em; padding-left: 1em; } | |
} | |
pre.numberSource a.sourceLine | |
{ position: relative; } | |
pre.numberSource a.sourceLine:empty | |
{ position: absolute; } | |
pre.numberSource a.sourceLine::before | |
{ content: attr(data-line-number); | |
position: absolute; left: -5em; text-align: right; vertical-align: baseline; | |
border: none; pointer-events: all; | |
-webkit-touch-callout: none; -webkit-user-select: none; | |
-khtml-user-select: none; -moz-user-select: none; | |
-ms-user-select: none; user-select: none; | |
padding: 0 4px; width: 4em; | |
color: #aaaaaa; | |
} | |
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; } | |
div.sourceCode | |
{ } | |
@media screen { | |
a.sourceLine::before { text-decoration: underline; } | |
} | |
code span.al { color: #ff0000; font-weight: bold; } /* Alert */ | |
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */ | |
code span.at { color: #7d9029; } /* Attribute */ | |
code span.bn { color: #40a070; } /* BaseN */ | |
code span.bu { } /* BuiltIn */ | |
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */ | |
code span.ch { color: #4070a0; } /* Char */ | |
code span.cn { color: #880000; } /* Constant */ | |
code span.co { color: #60a0b0; font-style: italic; } /* Comment */ | |
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */ | |
code span.do { color: #ba2121; font-style: italic; } /* Documentation */ | |
code span.dt { color: #902000; } /* DataType */ | |
code span.dv { color: #40a070; } /* DecVal */ | |
code span.er { color: #ff0000; font-weight: bold; } /* Error */ | |
code span.ex { } /* Extension */ | |
code span.fl { color: #40a070; } /* Float */ | |
code span.fu { color: #06287e; } /* Function */ | |
code span.im { } /* Import */ | |
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */ | |
code span.kw { color: #007020; font-weight: bold; } /* Keyword */ | |
code span.op { color: #666666; } /* Operator */ | |
code span.ot { color: #007020; } /* Other */ | |
code span.pp { color: #bc7a00; } /* Preprocessor */ | |
code span.sc { color: #4070a0; } /* SpecialChar */ | |
code span.ss { color: #bb6688; } /* SpecialString */ | |
code span.st { color: #4070a0; } /* String */ | |
code span.va { color: #19177c; } /* Variable */ | |
code span.vs { color: #4070a0; } /* VerbatimString */ | |
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */ | |
</style> | |
<link rel="stylesheet" href="http://cdn.rawgit.com/hakimel/reveal.js/3.5.0//css/theme/beige.css" id="theme"> | |
<!-- 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 ) ? 'http://cdn.rawgit.com/hakimel/reveal.js/3.5.0//css/print/pdf.css' : 'http://cdn.rawgit.com/hakimel/reveal.js/3.5.0//css/print/paper.css'; | |
document.getElementsByTagName( 'head' )[0].appendChild( link ); | |
</script> | |
<!--[if lt IE 9]> | |
<script src="http://cdn.rawgit.com/hakimel/reveal.js/3.5.0//lib/js/html5shiv.js"></script> | |
<![endif]--> | |
</head> | |
<body> | |
<div class="reveal"> | |
<div class="slides"> | |
<section id="title-slide"> | |
<h1 class="title">FPGA Programming with Clash</h1> | |
<p class="author">Joe Hermaszewski</p> | |
<p class="date">May 10 2018</p> | |
</section> | |
<section class="slide level3"> | |
<ul> | |
<li>Motivation behind Clash</li> | |
<li>Basic concepts used</li> | |
<li>CPU for interpreting a very simple language</li> | |
</ul> | |
<aside class="notes"> | |
<p>This is what we are going to discuss</p> | |
</aside> | |
</section> | |
<section><section id="the-motivation" class="title-slide slide level2"><h2>The motivation</h2></section><section class="slide level3"> | |
<blockquote> | |
<p>HDLs were not developed for use with logic-synthesis tools.</p> | |
</blockquote> | |
<p>– Application-Specific Integrated Circuits - June 1997</p> | |
<aside class="notes"> | |
<p>Basically: VHDL and Verilog are just terrible</p> | |
<p>Logic synthesis provides a link between an HDL (Verilog or VHDL) and a netlist similarly to the way that a C compiler provides a link between C code and machine language. However, the parallel is not exact. C was developed for use with compilers, but <em>HDLs were not developed for use with logic-synthesis tools</em>.</p> | |
</aside> | |
</section><section class="slide level3"> | |
<blockquote> | |
<p>Both Verilog and VHDL were developed well before the introduction of commercial logic-synthesis software</p> | |
</blockquote> | |
<p>– Application-Specific Integrated Circuits - June 1997</p> | |
<aside class="notes"> | |
<p>Verilog was designed as a simulation language and VHDL was designed as a documentation and description language. <em>Both Verilog and VHDL were developed in the early 1980s, well before the introduction of commercial logic-synthesis software</em>.</p> | |
</aside> | |
</section><section class="slide level3"> | |
<blockquote> | |
<p>The current state of synthesis software is rather like learning a foreign language, and then having to talk to a five-year-old.</p> | |
</blockquote> | |
<p>– Application-Specific Integrated Circuits - June 1997</p> | |
<aside class="notes"> | |
<p>Because these HDLs are now being used for purposes for which they were not intended, the state of the art in logic synthesis falls far short of that for computer-language compilers. Logic synthesis forces designers to use a subset of both Verilog and VHDL. This makes using logic synthesis more difficult rather than less difficult. <em>The current state of synthesis software is rather like learning a foreign language, and then having to talk to a five-year-old.</em></p> | |
</aside> | |
</section><section class="slide level3"> | |
<blockquote> | |
<p>This situation should improve in the next five years, as logic synthesizers mature.</p> | |
</blockquote> | |
<p>– Application-Specific Integrated Circuits - June 1997</p> | |
<aside class="notes"> | |
<p>When talking to a logic-synthesis tool using an HDL, it is necessary to think like hardware, anticipating the netlist that logic synthesis will produce. <em>This situation should improve in the next five years, as logic synthesizers mature.</em></p> | |
</aside> | |
</section><section class="slide level3"> | |
<p>It did not improve</p> | |
<aside class="notes"> | |
<p>I’m sure that nobody here needs convincing that terrible programming languages exist.</p> | |
<p>As much fun as it would be to keep talking about how much VHDL and Verilog suck I’m here to talk about Clash</p> | |
</aside> | |
</section><section class="slide level3"> | |
<ul> | |
<li>Great type system and inference</li> | |
<li>Great at abstracting</li> | |
<li>…</li> | |
</ul> | |
<aside class="notes"> | |
<p>Similarly I don’t need to espouse the benefits of Haskell here.</p> | |
<p>blah blah blah</p> | |
<p>Wouldn’t it be nice to be able to use Haskell</p> | |
</aside> | |
</section><section class="slide level3"> | |
<ul> | |
<li>Haskell runs on commodity hardware</li> | |
</ul> | |
<aside class="notes"> | |
<p>you may not know it but…</p> | |
<p>This means that we can run our FPGA code on regular CPUs at quite a high level of abstraction,</p> | |
<p>simulating Gates on the FPGA is very slow, Haskell is pretty fast</p> | |
<p>space leaks</p> | |
</aside> | |
</section></section> | |
<section><section id="clash-types" class="title-slide slide level2"><h2>Clash types</h2></section><section class="slide level3"> | |
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb1-1" data-line-number="1"><span class="kw">data</span> <span class="dt">Signal</span> (<span class="ot">domain ::</span> <span class="dt">Domain</span>) a <span class="fu">=</span> a <span class="fu">:-</span> <span class="dt">Signal</span> domain a</a></code></pre></div> | |
<aside class="notes"> | |
<p>The <code>Signal</code> type is prevalent in Clash code.</p> | |
<ul> | |
<li>It maps to a bundle of wires on the hardware</li> | |
<li>It is an infinite stream of values, one for every cycle in <code>domain</code></li> | |
<li>It has an <code>Applicative</code> instance</li> | |
</ul> | |
</aside> | |
</section><section class="slide level3"> | |
<ul> | |
<li><code>pure a</code> is a <code>Signal</code> where the values never change</li> | |
<li><code>f <*> x</code> zips the two <code>Signals</code> together with <code>$</code></li> | |
</ul> | |
<aside class="notes"> | |
<p>This is the applicative instance for Signals</p> | |
<p>It’s exactly what one would expect for infinite lists</p> | |
</aside> | |
</section><section class="slide level3"> | |
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb2-1" data-line-number="1"><span class="ot">register ::</span> a <span class="ot">-></span> <span class="dt">Signal</span> domain a <span class="ot">-></span> <span class="dt">Signal</span> domain a</a></code></pre></div> | |
<aside class="notes"> | |
<p>This maps (unsurprisingly) to a register (or D-type flip-flop) in the hardware</p> | |
<p>What this does is to “delay” a signal by one cycle, and on the very first cycle return the first argument of type <code>a</code>.</p> | |
</aside> | |
</section><section id="example" class="slide level3"> | |
<h3>Example</h3> | |
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb3-1" data-line-number="1"><span class="ot">foo ::</span> <span class="dt">Signal</span> domain <span class="dt">String</span></a> | |
<a class="sourceLine" id="cb3-2" data-line-number="2">foo <span class="fu">=</span> register <span class="st">"hello"</span> (register <span class="st">"world"</span> (pure <span class="st">"!"</span>))</a></code></pre></div> | |
<div class="fragment"> | |
<pre><code>>>> sample foo | |
["hello","world","!","!","!","!","!","!","!","!","!",...</code></pre> | |
<aside class="notes"> | |
<p>Strings don’t synthesize to hardware, but we can run this example in ghci</p> | |
<p>Haskell’s Lazyness makes this work just as one expects</p> | |
</aside> | |
</div> | |
</section><section id="counter-example" class="slide level3"> | |
<h3>Counter Example</h3> | |
<div class="sourceCode" id="cb5"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb5-1" data-line-number="1"><span class="ot">counter ::</span> <span class="dt">Signal</span> domain <span class="dt">Word32</span></a> | |
<a class="sourceLine" id="cb5-2" data-line-number="2">counter <span class="fu">=</span> register <span class="dv">0</span> (counter <span class="fu">+</span> <span class="dv">1</span>)</a></code></pre></div> | |
<div class="fragment"> | |
<pre><code>>>> sample counter | |
[0,1,2,3,4,5,6,7,8,9..</code></pre> | |
<aside class="notes"> | |
<p>Every example should have a counter-example!</p> | |
<p>Note the use of the <code>Num</code> instance for Signals, it’s just the <code>Num</code> functions lifted into an Applicative.</p> | |
</aside> | |
</div> | |
</section><section class="slide level3"> | |
<p>That’s basically it</p> | |
<aside class="notes"> | |
<p>With these primitives one can construct computation graphs which map sensibly to hardware</p> | |
</aside> | |
</section><section id="how-does-it-map-to-hardware" class="slide level3"> | |
<h3>How does it map to hardware</h3> | |
<ul> | |
<li>Function application -> combinatorial expressions the hardware (LUTs on FPGAs)</li> | |
<li>Pattern matching -> muxes</li> | |
<li>Constants -> constants</li> | |
</ul> | |
<aside class="notes"> | |
<p>Everything is a LUT on FPGAs</p> | |
</aside> | |
</section><section class="slide level3"> | |
<div class="sourceCode" id="cb7"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb7-1" data-line-number="1">blockRam</a> | |
<a class="sourceLine" id="cb7-2" data-line-number="2"><span class="ot"> ::</span> <span class="dt">Enum</span> addr</a> | |
<a class="sourceLine" id="cb7-3" data-line-number="3"> <span class="ot">=></span> <span class="dt">Vec</span> n a</a> | |
<a class="sourceLine" id="cb7-4" data-line-number="4"> <span class="co">-- ^ Initial content of the BRAM</span></a> | |
<a class="sourceLine" id="cb7-5" data-line-number="5"> <span class="ot">-></span> <span class="dt">Signal</span> dom addr</a> | |
<a class="sourceLine" id="cb7-6" data-line-number="6"> <span class="co">-- ^ Read address @r@</span></a> | |
<a class="sourceLine" id="cb7-7" data-line-number="7"> <span class="ot">-></span> <span class="dt">Signal</span> dom (<span class="dt">Maybe</span> (addr, a))</a> | |
<a class="sourceLine" id="cb7-8" data-line-number="8"> <span class="co">-- ^ (write address @w@, value to write)</span></a> | |
<a class="sourceLine" id="cb7-9" data-line-number="9"> <span class="ot">-></span> <span class="dt">Signal</span> dom a</a> | |
<a class="sourceLine" id="cb7-10" data-line-number="10"> <span class="co">-- ^ The @blockRAM@ at address @r@ from the previous cycle</span></a></code></pre></div> | |
<aside class="notes"> | |
<p>one more primitive to cover</p> | |
</aside> | |
</section></section> | |
<section><section id="brainfuck-cpu" class="title-slide slide level2"><h2>BrainFuck cpu</h2></section><section class="slide level3"> | |
<ul> | |
<li>Implement as a simple state machine</li> | |
</ul> | |
</section><section class="slide level3"> | |
<div class="sourceCode" id="cb8"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb8-1" data-line-number="1"><span class="kw">data</span> <span class="dt">Instruction</span></a> | |
<a class="sourceLine" id="cb8-2" data-line-number="2"> <span class="fu">=</span> <span class="dt">IncPtr</span></a> | |
<a class="sourceLine" id="cb8-3" data-line-number="3"> <span class="fu">|</span> <span class="dt">DecPtr</span></a> | |
<a class="sourceLine" id="cb8-4" data-line-number="4"> <span class="fu">|</span> <span class="dt">Inc</span></a> | |
<a class="sourceLine" id="cb8-5" data-line-number="5"> <span class="fu">|</span> <span class="dt">Dec</span></a> | |
<a class="sourceLine" id="cb8-6" data-line-number="6"> <span class="fu">|</span> <span class="dt">Output</span></a> | |
<a class="sourceLine" id="cb8-7" data-line-number="7"> <span class="fu">|</span> <span class="dt">Input</span></a> | |
<a class="sourceLine" id="cb8-8" data-line-number="8"> <span class="fu">|</span> <span class="dt">Open</span></a> | |
<a class="sourceLine" id="cb8-9" data-line-number="9"> <span class="fu">|</span> <span class="dt">Close</span></a></code></pre></div> | |
<aside class="notes"> | |
<p>Instructions are a regular ADT</p> | |
<p>Clash compiles these to an 8 bit representation</p> | |
<p>(may not be optimal)</p> | |
</aside> | |
</section><section class="slide level3"> | |
<div class="sourceCode" id="cb9"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb9-1" data-line-number="1"><span class="kw">type</span> <span class="dt">MaxNesting</span> <span class="fu">=</span> <span class="dv">256</span></a> | |
<a class="sourceLine" id="cb9-2" data-line-number="2"><span class="kw">type</span> <span class="dt">WordSize</span> <span class="fu">=</span> <span class="dv">8</span></a> | |
<a class="sourceLine" id="cb9-3" data-line-number="3"><span class="kw">type</span> <span class="dt">Word</span> <span class="fu">=</span> <span class="dt">Unsigned</span> <span class="dt">WordSize</span></a> | |
<a class="sourceLine" id="cb9-4" data-line-number="4"><span class="kw">type</span> <span class="dt">DataAddrSize</span> <span class="fu">=</span> <span class="dv">10</span></a> | |
<a class="sourceLine" id="cb9-5" data-line-number="5"><span class="kw">type</span> <span class="dt">DataAddr</span> <span class="fu">=</span> <span class="dt">Unsigned</span> <span class="dt">DataAddrSize</span></a> | |
<a class="sourceLine" id="cb9-6" data-line-number="6"><span class="kw">type</span> <span class="dt">InstAddrSize</span> <span class="fu">=</span> <span class="dv">11</span></a> | |
<a class="sourceLine" id="cb9-7" data-line-number="7"><span class="kw">type</span> <span class="dt">InstAddr</span> <span class="fu">=</span> <span class="dt">Unsigned</span> <span class="dt">InstAddrSize</span></a> | |
<a class="sourceLine" id="cb9-8" data-line-number="8"></a> | |
<a class="sourceLine" id="cb9-9" data-line-number="9"><span class="kw">data</span> <span class="dt">Pop</span> <span class="fu">=</span> <span class="dt">DoNotPop</span> <span class="fu">|</span> <span class="dt">Pop</span></a> | |
<a class="sourceLine" id="cb9-10" data-line-number="10"> <span class="kw">deriving</span> (<span class="dt">Show</span>)</a></code></pre></div> | |
<aside class="notes"> | |
<p>Some types we’ll be using</p> | |
</aside> | |
</section><section class="slide level3"> | |
<div class="sourceCode" id="cb10"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb10-1" data-line-number="1">cpu</a> | |
<a class="sourceLine" id="cb10-2" data-line-number="2"><span class="ot"> ::</span> <span class="dt">Signal</span> d <span class="dt">Word</span></a> | |
<a class="sourceLine" id="cb10-3" data-line-number="3"> <span class="ot">-></span> <span class="dt">Signal</span> d (<span class="dt">Maybe</span> <span class="dt">Word</span>, <span class="dt">Pop</span>)</a></code></pre></div> | |
<aside class="notes"> | |
<p>inputs are moved on whenever we pop</p> | |
</aside> | |
</section><section class="slide level3"> | |
<div class="sourceCode" id="cb11"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb11-1" data-line-number="1"><span class="kw">data</span> <span class="dt">State</span></a> | |
<a class="sourceLine" id="cb11-2" data-line-number="2"> <span class="fu">=</span> <span class="dt">Running</span> <span class="dt">DataAddr</span> <span class="dt">InstAddr</span></a> | |
<a class="sourceLine" id="cb11-3" data-line-number="3"> <span class="fu">|</span> <span class="dt">FindMatching</span> <span class="dt">DataAddr</span> <span class="dt">InstAddr</span> <span class="dt">Direction</span> (<span class="dt">Index</span> <span class="dt">MaxNesting</span>)</a> | |
<a class="sourceLine" id="cb11-4" data-line-number="4"></a> | |
<a class="sourceLine" id="cb11-5" data-line-number="5"><span class="kw">data</span> <span class="dt">Direction</span> <span class="fu">=</span> <span class="dt">Forwards</span> <span class="fu">|</span> <span class="dt">Backwards</span></a></code></pre></div> | |
</section><section class="slide level3"> | |
<div class="sourceCode" id="cb12"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb12-1" data-line-number="1">advanceState</a> | |
<a class="sourceLine" id="cb12-2" data-line-number="2"><span class="ot"> ::</span> <span class="dt">Word</span></a> | |
<a class="sourceLine" id="cb12-3" data-line-number="3"> <span class="co">-- ^ The data at the previously requested address</span></a> | |
<a class="sourceLine" id="cb12-4" data-line-number="4"> <span class="ot">-></span> <span class="dt">Instruction</span></a> | |
<a class="sourceLine" id="cb12-5" data-line-number="5"> <span class="co">-- ^ The instruction at the previously requested address</span></a> | |
<a class="sourceLine" id="cb12-6" data-line-number="6"> <span class="ot">-></span> <span class="dt">Word</span></a> | |
<a class="sourceLine" id="cb12-7" data-line-number="7"> <span class="co">-- ^ The input data</span></a> | |
<a class="sourceLine" id="cb12-8" data-line-number="8"> <span class="ot">-></span> <span class="dt">State</span></a> | |
<a class="sourceLine" id="cb12-9" data-line-number="9"> <span class="co">-- ^ The previous state</span></a> | |
<a class="sourceLine" id="cb12-10" data-line-number="10"> <span class="ot">-></span> (<span class="dt">Maybe</span> <span class="dt">DataOp</span>, <span class="dt">Maybe</span> <span class="dt">Word</span>, <span class="dt">Pop</span>, <span class="dt">State</span>)</a> | |
<a class="sourceLine" id="cb12-11" data-line-number="11"> <span class="co">-- ^ (The op to perform on the current cell, output value, did we consume input, the next state)</span></a></code></pre></div> | |
<aside class="notes"> | |
<p>the definition is pretty pedestrian</p> | |
</aside> | |
</section><section class="slide level3"> | |
<div class="sourceCode" id="cb13"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb13-1" data-line-number="1">cpu input</a> | |
<a class="sourceLine" id="cb13-2" data-line-number="2"> <span class="fu">=</span> <span class="kw">let</span></a> | |
<a class="sourceLine" id="cb13-3" data-line-number="3"> (dataOp, output, pop, state) <span class="fu">=</span></a> | |
<a class="sourceLine" id="cb13-4" data-line-number="4"> unbundle</a> | |
<a class="sourceLine" id="cb13-5" data-line-number="5"> <span class="fu">$</span> advanceState</a> | |
<a class="sourceLine" id="cb13-6" data-line-number="6"> <span class="fu"><$></span> data_</a> | |
<a class="sourceLine" id="cb13-7" data-line-number="7"> <span class="fu"><*></span> instruction</a> | |
<a class="sourceLine" id="cb13-8" data-line-number="8"> <span class="fu"><*></span> input</a> | |
<a class="sourceLine" id="cb13-9" data-line-number="9"> <span class="fu"><*></span> prevState</a> | |
<a class="sourceLine" id="cb13-10" data-line-number="10"><span class="fu">...</span></a></code></pre></div> | |
</section><section class="slide level3"> | |
<div class="sourceCode" id="cb14"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb14-1" data-line-number="1"><span class="fu">...</span></a> | |
<a class="sourceLine" id="cb14-2" data-line-number="2"> dataAddr <span class="fu">=</span> stateDataAddr <span class="fu"><$></span> state</a> | |
<a class="sourceLine" id="cb14-3" data-line-number="3"> instAddr <span class="fu">=</span> stateInstAddr <span class="fu"><$></span> state</a> | |
<a class="sourceLine" id="cb14-4" data-line-number="4"> data_ <span class="fu">=</span> poker dataAddr dataOp</a> | |
<a class="sourceLine" id="cb14-5" data-line-number="5"></a> | |
<a class="sourceLine" id="cb14-6" data-line-number="6"> instruction <span class="fu">=</span> blockRam program instAddr (pure <span class="dt">Nothing</span>)</a> | |
<a class="sourceLine" id="cb14-7" data-line-number="7"></a> | |
<a class="sourceLine" id="cb14-8" data-line-number="8"> initialState <span class="fu">=</span> <span class="dt">Running</span> <span class="dv">0</span> <span class="dv">0</span></a> | |
<a class="sourceLine" id="cb14-9" data-line-number="9"> prevState <span class="fu">=</span> register initialState state</a> | |
<a class="sourceLine" id="cb14-10" data-line-number="10"> <span class="kw">in</span></a> | |
<a class="sourceLine" id="cb14-11" data-line-number="11"> bundle (output, pop)</a></code></pre></div> | |
</section><section class="slide level3"> | |
<div class="sourceCode" id="cb15"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb15-1" data-line-number="1">poker</a> | |
<a class="sourceLine" id="cb15-2" data-line-number="2"><span class="ot"> ::</span> <span class="dt">Signal</span> d <span class="dt">DataAddr</span></a> | |
<a class="sourceLine" id="cb15-3" data-line-number="3"> <span class="co">-- ^ The address we would like the data for</span></a> | |
<a class="sourceLine" id="cb15-4" data-line-number="4"> <span class="ot">-></span> <span class="dt">Signal</span> d (<span class="dt">Maybe</span> <span class="dt">DataOp</span>)</a> | |
<a class="sourceLine" id="cb15-5" data-line-number="5"> <span class="co">-- ^ An operation to perform on the data</span></a> | |
<a class="sourceLine" id="cb15-6" data-line-number="6"> <span class="ot">-></span> <span class="dt">Signal</span> d <span class="dt">Word</span></a> | |
<a class="sourceLine" id="cb15-7" data-line-number="7"> <span class="co">-- ^ The requested data, delayed by one</span></a> | |
<a class="sourceLine" id="cb15-8" data-line-number="8"> <span class="co">-- cycle</span></a> | |
<a class="sourceLine" id="cb15-9" data-line-number="9">poker dataPtr op <span class="fu">=</span> <span class="kw">let</span> <span class="fu">...</span></a></code></pre></div> | |
<aside class="notes"> | |
<p>This handles manipulating the memory</p> | |
<p>the most interesting bit</p> | |
</aside> | |
</section><section class="slide level3"> | |
<div class="sourceCode" id="cb16"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb16-1" data-line-number="1">initialContents <span class="fu">=</span> replicate (<span class="dt">SNat</span> <span class="fu">@</span>(<span class="dv">2</span> <span class="fu">^</span> <span class="dt">DataAddrSize</span>)) <span class="dv">0</span></a> | |
<a class="sourceLine" id="cb16-2" data-line-number="2">ram <span class="fu">=</span> blockRam initialContents dataPtr write</a></code></pre></div> | |
<aside class="notes"> | |
<p>write is defined later all a bit circular</p> | |
</aside> | |
</section><section class="slide level3"> | |
<div class="sourceCode" id="cb17"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb17-1" data-line-number="1"><span class="ot">delayedOp ::</span> <span class="dt">Signal</span> d (<span class="dt">Maybe</span> <span class="dt">DataOp</span>)</a> | |
<a class="sourceLine" id="cb17-2" data-line-number="2">delayedOp <span class="fu">=</span> register <span class="dt">Nothing</span> op</a></code></pre></div> | |
<aside class="notes"> | |
<p>just to avoid repetition</p> | |
<p>there is type system machinery to keep this delaying safe</p> | |
<p>Omitted for this talk for conciseness</p> | |
</aside> | |
</section><section class="slide level3"> | |
<div class="sourceCode" id="cb18"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb18-1" data-line-number="1"><span class="ot">applyOp ::</span> <span class="dt">Maybe</span> <span class="dt">DataOp</span> <span class="ot">-></span> <span class="dt">Word</span> <span class="ot">-></span> <span class="dt">Word</span></a> | |
<a class="sourceLine" id="cb18-2" data-line-number="2">applyOp <span class="fu">=</span> \<span class="kw">case</span></a> | |
<a class="sourceLine" id="cb18-3" data-line-number="3"> <span class="dt">Just</span> (<span class="dt">Store</span> x) <span class="ot">-></span> const x</a> | |
<a class="sourceLine" id="cb18-4" data-line-number="4"> <span class="dt">Just</span> <span class="dt">Increment</span> <span class="ot">-></span> succ</a> | |
<a class="sourceLine" id="cb18-5" data-line-number="5"> <span class="dt">Just</span> <span class="dt">Decrement</span> <span class="ot">-></span> pred</a> | |
<a class="sourceLine" id="cb18-6" data-line-number="6"> <span class="dt">Nothing</span> <span class="ot">-></span> id</a></code></pre></div> | |
<aside class="notes"> | |
<p>Clash handles returning a function here with no problem</p> | |
</aside> | |
</section><section class="slide level3"> | |
<div class="sourceCode" id="cb19"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb19-1" data-line-number="1"><span class="ot">operatedData ::</span> <span class="dt">Signal</span> d (<span class="dt">DataAddr</span>, <span class="dt">Word</span>)</a> | |
<a class="sourceLine" id="cb19-2" data-line-number="2">operatedData <span class="fu">=</span> (fmap <span class="fu">.</span> applyOp) <span class="fu"><$></span> delayedOp <span class="fu"><*></span> readData</a></code></pre></div> | |
<aside class="notes"> | |
<p>The data after the operation, along with its address</p> | |
</aside> | |
</section><section class="slide level3"> | |
<div class="sourceCode" id="cb20"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb20-1" data-line-number="1"><span class="co">-- If we have performed an operation, write the result into the RAM</span></a> | |
<a class="sourceLine" id="cb20-2" data-line-number="2"><span class="ot">write ::</span> <span class="dt">Signal</span> d (<span class="dt">Maybe</span> (<span class="dt">DataAddr</span>, <span class="dt">Word</span>))</a> | |
<a class="sourceLine" id="cb20-3" data-line-number="3">write <span class="fu">=</span> liftA2 (<span class="fu">$></span>) delayedOp operatedData</a></code></pre></div> | |
<aside class="notes"> | |
<p>Write to ram when the data has changed, just for power saving</p> | |
</aside> | |
</section><section class="slide level3"> | |
<div class="sourceCode" id="cb21"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb21-1" data-line-number="1"><span class="co">-- The value we wrote to RAM on the previous cycle</span></a> | |
<a class="sourceLine" id="cb21-2" data-line-number="2"><span class="ot">writeBack ::</span> <span class="dt">Signal</span> d (<span class="dt">Maybe</span> (<span class="dt">DataAddr</span>, <span class="dt">Word</span>))</a> | |
<a class="sourceLine" id="cb21-3" data-line-number="3">writeBack <span class="fu">=</span> register <span class="dt">Nothing</span> write</a></code></pre></div> | |
</section><section class="slide level3"> | |
<div class="sourceCode" id="cb22"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb22-1" data-line-number="1"><span class="co">-- If we have written back to the same address, use that value, otherwise</span></a> | |
<a class="sourceLine" id="cb22-2" data-line-number="2"><span class="co">-- use the one we read last cycle</span></a> | |
<a class="sourceLine" id="cb22-3" data-line-number="3"><span class="ot">readData ::</span> <span class="dt">Signal</span> d (<span class="dt">DataAddr</span>, <span class="dt">Word</span>)</a> | |
<a class="sourceLine" id="cb22-4" data-line-number="4">readData <span class="fu">=</span> liftA3</a> | |
<a class="sourceLine" id="cb22-5" data-line-number="5"> (\read readAddr written <span class="ot">-></span> <span class="kw">case</span> written <span class="kw">of</span></a> | |
<a class="sourceLine" id="cb22-6" data-line-number="6"> <span class="dt">Just</span> (writtenAddr, d) <span class="fu">|</span> writtenAddr <span class="fu">==</span> readAddr <span class="ot">-></span> (writtenAddr, d)</a> | |
<a class="sourceLine" id="cb22-7" data-line-number="7"> _ <span class="ot">-></span> (readAddr, read)</a> | |
<a class="sourceLine" id="cb22-8" data-line-number="8"> )</a> | |
<a class="sourceLine" id="cb22-9" data-line-number="9"> ram</a> | |
<a class="sourceLine" id="cb22-10" data-line-number="10"> (register undefined <span class="fu">$</span> dataPtr)</a> | |
<a class="sourceLine" id="cb22-11" data-line-number="11"> writeBack</a></code></pre></div> | |
</section><section class="slide level3"> | |
<div class="sourceCode" id="cb23"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb23-1" data-line-number="1">poker dataPtr op</a> | |
<a class="sourceLine" id="cb23-2" data-line-number="2"> <span class="fu">=</span> <span class="kw">let</span></a> | |
<a class="sourceLine" id="cb23-3" data-line-number="3"> <span class="co">-- If we have performed an operation, write the result into the RAM</span></a> | |
<a class="sourceLine" id="cb23-4" data-line-number="4"><span class="ot"> write ::</span> <span class="dt">Signal</span> d (<span class="dt">Maybe</span> (<span class="dt">DataAddr</span>, <span class="dt">Word</span>))</a> | |
<a class="sourceLine" id="cb23-5" data-line-number="5"> write <span class="fu">=</span> liftA2 (<span class="fu">$></span>) delayedOp operatedData</a> | |
<a class="sourceLine" id="cb23-6" data-line-number="6"></a> | |
<a class="sourceLine" id="cb23-7" data-line-number="7"> <span class="co">-- The value we wrote to RAM on the previous cycle</span></a> | |
<a class="sourceLine" id="cb23-8" data-line-number="8"><span class="ot"> writeBack ::</span> <span class="dt">Signal</span> d (<span class="dt">Maybe</span> (<span class="dt">DataAddr</span>, <span class="dt">Word</span>))</a> | |
<a class="sourceLine" id="cb23-9" data-line-number="9"> writeBack <span class="fu">=</span> register <span class="dt">Nothing</span> write</a> | |
<a class="sourceLine" id="cb23-10" data-line-number="10"></a> | |
<a class="sourceLine" id="cb23-11" data-line-number="11"> initialContents <span class="fu">=</span> replicate (<span class="dt">SNat</span> <span class="fu">@</span>(<span class="dv">2</span> <span class="fu">^</span> <span class="dt">DataAddrSize</span>)) <span class="dv">0</span></a> | |
<a class="sourceLine" id="cb23-12" data-line-number="12"><span class="ot"> ram ::</span> <span class="dt">Signal</span> d <span class="dt">Word</span></a> | |
<a class="sourceLine" id="cb23-13" data-line-number="13"> ram <span class="fu">=</span> blockRam initialContents dataPtr write</a> | |
<a class="sourceLine" id="cb23-14" data-line-number="14"></a> | |
<a class="sourceLine" id="cb23-15" data-line-number="15"> <span class="co">-- If we have written back to the same address, use that value, otherwise</span></a> | |
<a class="sourceLine" id="cb23-16" data-line-number="16"> <span class="co">-- use the one we read last cycle</span></a> | |
<a class="sourceLine" id="cb23-17" data-line-number="17"> <span class="co">-- Delayed by 1</span></a> | |
<a class="sourceLine" id="cb23-18" data-line-number="18"><span class="ot"> readData ::</span> <span class="dt">Signal</span> d (<span class="dt">DataAddr</span>, <span class="dt">Word</span>)</a> | |
<a class="sourceLine" id="cb23-19" data-line-number="19"> readData <span class="fu">=</span> liftA3</a> | |
<a class="sourceLine" id="cb23-20" data-line-number="20"> (\read readAddr written <span class="ot">-></span> <span class="kw">case</span> written <span class="kw">of</span></a> | |
<a class="sourceLine" id="cb23-21" data-line-number="21"> <span class="dt">Just</span> (writtenAddr, d) <span class="fu">|</span> writtenAddr <span class="fu">==</span> readAddr <span class="ot">-></span> (writtenAddr, d)</a> | |
<a class="sourceLine" id="cb23-22" data-line-number="22"> _ <span class="ot">-></span> (readAddr, read)</a> | |
<a class="sourceLine" id="cb23-23" data-line-number="23"> )</a> | |
<a class="sourceLine" id="cb23-24" data-line-number="24"> ram</a> | |
<a class="sourceLine" id="cb23-25" data-line-number="25"> (register undefined <span class="fu">$</span> dataPtr)</a> | |
<a class="sourceLine" id="cb23-26" data-line-number="26"> writeBack</a> | |
<a class="sourceLine" id="cb23-27" data-line-number="27"></a> | |
<a class="sourceLine" id="cb23-28" data-line-number="28"><span class="ot"> delayedOp ::</span> <span class="dt">Signal</span> d (<span class="dt">Maybe</span> <span class="dt">DataOp</span>)</a> | |
<a class="sourceLine" id="cb23-29" data-line-number="29"> delayedOp <span class="fu">=</span> register <span class="dt">Nothing</span> op</a> | |
<a class="sourceLine" id="cb23-30" data-line-number="30"></a> | |
<a class="sourceLine" id="cb23-31" data-line-number="31"> <span class="co">-- The data with the given operation applied to it</span></a> | |
<a class="sourceLine" id="cb23-32" data-line-number="32"> <span class="co">-- Delayed by 1</span></a> | |
<a class="sourceLine" id="cb23-33" data-line-number="33"><span class="ot"> operatedData ::</span> <span class="dt">Signal</span> d (<span class="dt">DataAddr</span>, <span class="dt">Word</span>)</a> | |
<a class="sourceLine" id="cb23-34" data-line-number="34"> operatedData <span class="fu">=</span> (fmap <span class="fu">.</span> applyOp) <span class="fu"><$></span> delayedOp <span class="fu"><*></span> readData</a> | |
<a class="sourceLine" id="cb23-35" data-line-number="35"></a> | |
<a class="sourceLine" id="cb23-36" data-line-number="36"> <span class="co">-- How to apply a BF instruction to some data</span></a> | |
<a class="sourceLine" id="cb23-37" data-line-number="37"><span class="ot"> applyOp ::</span> <span class="dt">Maybe</span> <span class="dt">DataOp</span> <span class="ot">-></span> <span class="dt">Word</span> <span class="ot">-></span> <span class="dt">Word</span></a> | |
<a class="sourceLine" id="cb23-38" data-line-number="38"> applyOp <span class="fu">=</span> \<span class="kw">case</span></a> | |
<a class="sourceLine" id="cb23-39" data-line-number="39"> <span class="dt">Just</span> (<span class="dt">Store</span> x) <span class="ot">-></span> const x</a> | |
<a class="sourceLine" id="cb23-40" data-line-number="40"> <span class="dt">Just</span> <span class="dt">Increment</span> <span class="ot">-></span> succ</a> | |
<a class="sourceLine" id="cb23-41" data-line-number="41"> <span class="dt">Just</span> <span class="dt">Decrement</span> <span class="ot">-></span> pred</a> | |
<a class="sourceLine" id="cb23-42" data-line-number="42"> <span class="dt">Nothing</span> <span class="ot">-></span> id</a> | |
<a class="sourceLine" id="cb23-43" data-line-number="43"> <span class="kw">in</span></a> | |
<a class="sourceLine" id="cb23-44" data-line-number="44"> replaceFirst <span class="dv">0</span> (snd <span class="fu"><$></span> operatedData)</a></code></pre></div> | |
</section><section class="slide level3"> | |
<p>!</p> | |
<aside class="notes"> | |
<p>That’s it, the CPU is defined</p> | |
</aside> | |
</section><section class="slide level3"> | |
<div class="sourceCode" id="cb24"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb24-1" data-line-number="1"><span class="ot">program ::</span> <span class="dt">Vec</span> (<span class="dv">2</span> <span class="fu">^</span> <span class="dt">InstAddrSize</span>) <span class="dt">Instruction</span></a> | |
<a class="sourceLine" id="cb24-2" data-line-number="2">program <span class="fu">=</span> <span class="fu">$</span>(listToVecTH (parseBF</a> | |
<a class="sourceLine" id="cb24-3" data-line-number="3"> <span class="st">".++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++."</span></a> | |
<a class="sourceLine" id="cb24-4" data-line-number="4"> )) <span class="fu">++</span> loop <span class="fu">++</span> repeat <span class="dt">Inc</span></a> | |
<a class="sourceLine" id="cb24-5" data-line-number="5"></a> | |
<a class="sourceLine" id="cb24-6" data-line-number="6">loop <span class="fu">=</span> <span class="fu">$</span>(listToVecTH (parseBF <span class="st">"[]+[]"</span>))</a></code></pre></div> | |
</section><section class="slide level3"> | |
<p>Testing is very easy with Clash</p> | |
<div class="sourceCode" id="cb25"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb25-1" data-line-number="1">sample_lazy <span class="fu">$</span> cpu (pure <span class="dv">0</span>)</a></code></pre></div> | |
<div class="fragment"> | |
<div class="sourceCode" id="cb26"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb26-1" data-line-number="1">fmap (chr <span class="fu">.</span> fromIntegral) <span class="fu">.</span> catMaybes <span class="fu">.</span> fmap fst <span class="fu">$</span> go</a> | |
<a class="sourceLine" id="cb26-2" data-line-number="2"><span class="st">"Hello World!\n</span></a></code></pre></div> | |
</div> | |
</section><section id="improvement" class="slide level3"> | |
<h3>Improvement</h3> | |
<ul> | |
<li>Keeping track of matching parentheses</li> | |
<li>Consuming multiple instructions per cycle</li> | |
</ul> | |
</section><section class="slide level3"> | |
<pre><code>-[--->+<]>-.[---->+++++<] | |
>-.-------.+++++++++++++. | |
>---.++++++++.+[---->+<]> | |
>+++.++[->+++<]>.++++++++ | |
>+.+++.[-->+++++<]>+++.++ | |
>[--->++<]>.---.+++++++++ | |
>+.+.+++[->+++<]>.+++++++ | |
>++.-----.+++++.-------.-</code></pre> | |
</section><section class="slide level3"> | |
<!-- | |
```haskell | |
fib :: Signal domain Word32 | |
fib = | |
let delayed1 = register 0 fib | |
delayed2 = register 0 (register 1 fib) | |
in (+) <$> delayed1 <*> delayed2 | |
``` | |
::: notes | |
::: | |
--> | |
</section></section> | |
</div> | |
</div> | |
<script src="http://cdn.rawgit.com/hakimel/reveal.js/3.5.0//lib/js/head.min.js"></script> | |
<script src="http://cdn.rawgit.com/hakimel/reveal.js/3.5.0//js/reveal.js"></script> | |
<script> | |
// Full list of configuration options available at: | |
// https://github.com/hakimel/reveal.js#configuration | |
Reveal.initialize({ | |
// Push each slide change to the browser history | |
history: true, | |
// Optional reveal.js plugins | |
dependencies: [ | |
{ src: 'http://cdn.rawgit.com/hakimel/reveal.js/3.5.0//lib/js/classList.js', condition: function() { return !document.body.classList; } }, | |
{ src: 'http://cdn.rawgit.com/hakimel/reveal.js/3.5.0//plugin/zoom-js/zoom.js', async: true }, | |
{ src: 'http://cdn.rawgit.com/hakimel/reveal.js/3.5.0//plugin/notes/notes.js', async: true } | |
] | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment