xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="172.75"
- height="124.93002"
+ height="124.43002"
id="svg2"
version="1.1"
inkscape:version="0.47 r22583"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2.1106557"
- inkscape:cx="100.30358"
- inkscape:cy="11.570164"
+ inkscape:cx="228.11635"
+ inkscape:cy="26.631212"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
+ <dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
- transform="translate(-367.86,-538.2295)">
+ transform="translate(-367.86,-538.7295)">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
id="rect6192"
</g> </g>
<g
id="g5038"
- transform="matrix(1,0,0,-1,220.755,1202.4395)"
+ transform="matrix(1,0,0,-1,220.755,1202.9395)"
xml:space="preserve"
stroke-miterlimit="10.433"
font-style="normal"
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Mend)" />
<path
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
- d="m 421.2,585.15952 0.16,-27.5 29,0"
+ d="m 421.2,585.15952 0.16,-28.2 29.8,0"
id="path5138"
sodipodi:nodetypes="ccc" />
<path
sodipodi:nodetypes="cc"
id="path5148"
- d="m 474.36,573.65952 10,0"
+ d="m 474.36,573.65952 12,0"
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Mend)" />
<g
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;letter-spacing:normal;word-spacing:normal;text-anchor:start;fill:none;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10.43299961;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
style="fill:#000000;stroke-width:0" />
</g> <path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Mend)"
- d="m 471.36,562.65952 13,0"
+ d="m 471.36,562.65952 15,0"
id="path5338"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Mend)" />
<path
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
- d="m 415.2,595.90952 0.16,13.5 36,0"
+ d="m 415.2,595.90952 0.16,13.5 35.2,0"
id="path5422"
sodipodi:nodetypes="ccc" />
<path
sodipodi:nodetypes="ccc"
id="path5424"
- d="m 409.2,585.90952 0.16,33.5 41,0"
+ d="m 409.2,585.90952 0.16,33.5 41.1,0"
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Mend)" />
<path
transform="matrix(1.44,0,0,-1.44,358.24516,633.982)"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="211.09"
- height="134.41002"
+ height="134.71005"
id="svg2"
version="1.1"
inkscape:version="0.47 r22583"
inkscape:pageshadow="2"
inkscape:zoom="2"
inkscape:cx="110.13584"
- inkscape:cy="93.191981"
+ inkscape:cy="93.192008"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1091"
inkscape:window-height="778"
inkscape:window-x="112"
- inkscape:window-y="0"
+ inkscape:window-y="22"
inkscape:window-maximized="0"
inkscape:snap-center="false">
<inkscape:grid
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
- transform="translate(-368.36,-548.2495)">
+ transform="translate(-368.36,-547.9495)">
<rect
style="fill:#ffffff;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
id="rect5340"
sodipodi:nodetypes="cccc" />
<g
id="g5038"
- transform="matrix(1,0,0,-1,241.095,1212.4595)"
+ transform="matrix(1,0,0,-1,241.095,1212.1595)"
xml:space="preserve"
stroke-miterlimit="10.433"
font-style="normal"
sodipodi:cy="33.558914"
sodipodi:rx="0.79549515"
sodipodi:ry="0.79549515"
- d="m 36.150834,33.558914 a 0.79549515,0.79549515 0 1 1 -1.59099,0 0.79549515,0.79549515 0 1 1 1.59099,0 z"
+ d="m 36.150834,33.558914 c 0,0.43934 -0.356155,0.795495 -0.795495,0.795495 -0.43934,0 -0.795495,-0.356155 -0.795495,-0.795495 0,-0.43934 0.356155,-0.795495 0.795495,-0.795495 0.43934,0 0.795495,0.356155 0.795495,0.795495 z"
transform="matrix(1.44,0,0,1.44,354.96217,537.40097)" />
<path
transform="matrix(1.44,0,0,1.44,360.00009,547.50915)"
- d="m 36.150834,33.558914 a 0.79549515,0.79549515 0 1 1 -1.59099,0 0.79549515,0.79549515 0 1 1 1.59099,0 z"
+ d="m 36.150834,33.558914 c 0,0.43934 -0.356155,0.795495 -0.795495,0.795495 -0.43934,0 -0.795495,-0.356155 -0.795495,-0.795495 0,-0.43934 0.356155,-0.795495 0.795495,-0.795495 0.43934,0 0.795495,0.356155 0.795495,0.795495 z"
sodipodi:ry="0.79549515"
sodipodi:rx="0.79549515"
sodipodi:cy="33.558914"
sodipodi:cy="33.558914"
sodipodi:rx="0.79549515"
sodipodi:ry="0.79549515"
- d="m 36.150834,33.558914 a 0.79549515,0.79549515 0 1 1 -1.59099,0 0.79549515,0.79549515 0 1 1 1.59099,0 z"
+ d="m 36.150834,33.558914 c 0,0.43934 -0.356155,0.795495 -0.795495,0.795495 -0.43934,0 -0.795495,-0.356155 -0.795495,-0.795495 0,-0.43934 0.356155,-0.795495 0.795495,-0.795495 0.43934,0 0.795495,0.356155 0.795495,0.795495 z"
transform="matrix(1.44,0,0,1.44,370.16475,537.40097)" />
<path
transform="matrix(1.44,0,0,1.44,376.17516,547.21208)"
- d="m 36.150834,33.558914 a 0.79549515,0.79549515 0 1 1 -1.59099,0 0.79549515,0.79549515 0 1 1 1.59099,0 z"
+ d="m 36.150834,33.558914 c 0,0.43934 -0.356155,0.795495 -0.795495,0.795495 -0.43934,0 -0.795495,-0.356155 -0.795495,-0.795495 0,-0.43934 0.356155,-0.795495 0.795495,-0.795495 0.43934,0 0.795495,0.356155 0.795495,0.795495 z"
sodipodi:ry="0.79549515"
sodipodi:rx="0.79549515"
sodipodi:cy="33.558914"
sodipodi:cy="33.558914"
sodipodi:rx="0.79549515"
sodipodi:ry="0.79549515"
- d="m 36.150834,33.558914 a 0.79549515,0.79549515 0 1 1 -1.59099,0 0.79549515,0.79549515 0 1 1 1.59099,0 z"
+ d="m 36.150834,33.558914 c 0,0.43934 -0.356155,0.795495 -0.795495,0.795495 -0.43934,0 -0.795495,-0.356155 -0.795495,-0.795495 0,-0.43934 0.356155,-0.795495 0.795495,-0.795495 0.43934,0 0.795495,0.356155 0.795495,0.795495 z"
transform="matrix(1.44,0,0,1.44,364.94984,562.2381)" />
</g>
</svg>
netlist. This research also features a prototype translator called \CLaSH\
(pronounced: clash), which converts the Haskell code to equivalently behaving
synthesizable \VHDL\ code, ready to be converted to an actual netlist format
-by an optimizing \VHDL\ synthesis tools.
+by an optimizing \VHDL\ synthesis tool.
\section{Hardware description in Haskell}
As an example we can see the netlist of the |mac| function in
\Cref{img:mac-comb}; the |mac| function applies both the |mul| and |add|
function to calculate $a * b + c$:
+
\begin{code}
mac a b c = add (mul a b) c
\end{code}
+
\begin{figure}
\centerline{\includegraphics{mac}}
\caption{Combinatorial Multiply-Accumulate}
\label{img:mac-comb}
\end{figure}
+
The result of using a complex input type can be seen in
\cref{img:mac-comb-nocurry} where the |mac| function now uses a single
input tuple for the |a|, |b|, and |c| arguments:
+
\begin{code}
mac (a, b, c) = add (mul a b) c
\end{code}
+
\begin{figure}
\centerline{\includegraphics{mac-nocurry}}
\caption{Combinatorial Multiply-Accumulate (complex input)}
\label{img:mac-comb-nocurry}
\end{figure}
- \subsection{Choices}
- Although describing components and connections allows describing a
- lot of hardware designs already, there is an obvious thing missing:
- choice. We need some way to be able to choose between values based
- on another value. In Haskell, choice is achieved by \hs{case}
- expressions, \hs{if} expressions, pattern matching and guards.
-
- The easiest of these are of course case expressions (and \hs{if}
- expressions, which can be very directly translated to \hs{case}
- expressions). A \hs{case} expression can in turn simply be
- translated to a conditional assignment in \VHDL, where the
- conditions use equality comparisons against the constructors in the
- \hs{case} expressions.
-
- A slightly more complex (but very powerful) form of choice is
- pattern matching. A function can be defined in multiple clauses,
- where each clause specifies a pattern. When the arguments match the
- pattern, the corresponding clause will be used.
-
- A pattern match (with optional guards) can also be implemented using
- conditional assignments in \VHDL, where the condition is the logical
- and of comparison results of each part of the pattern as well as the
- guard.
-
- Contrived example that sums two values when they are equal or
- non-equal (depending on the predicate given) and returns 0
- otherwise. This shows three implementations, one using and if
- expression, one using only case expressions and one using pattern
- matching and guards.
-
+ \subsection{Choice}
+ In Haskell, choice can be achieved by a large set of language constructs,
+ consisting of: \hs{case} constructs, \hs{if-then-else} constructs,
+ pattern matching, and guards. The easiest of these are the \hs{case}
+ constructs (and \hs{if} expressions, which can be very directly translated
+ to \hs{case} expressions). A \hs{case} expression can in turn simply be
+ translated to a conditional assignment in \VHDL, where the conditions use
+ equality comparisons against the constructors in the \hs{case}
+ expressions. We can see two versions of a contrived example, the first
+ using a \hs{case} construct and the other using a \hs{if-then-else}
+ constructs, in the code below. The example sums two values when they are
+ equal or non-equal (depending on the predicate given) and returns 0
+ otherwise.
+
\begin{code}
- sumif pred a b = if pred == Eq && a == b ||
- pred == Neq && a != b
- then a + b
- else 0
-
sumif pred a b = case pred of
Eq -> case a == b of
True -> a + b
Neq -> case a != b of
True -> a + b
False -> 0
+ \end{code}
- sumif Eq a b | a == b = a + b
- sumif Neq a b | a != b = a + b
- sumif _ _ _ = 0
+ \begin{code}
+ sumif pred a b =
+ if pred == Eq then
+ if a == b then a + b else 0
+ else
+ if a != b then a + b else 0
\end{code}
- \begin{figure}
- \centerline{\includegraphics{choice-ifthenelse}}
- \caption{Choice - \emph{if-then-else}}
- \label{img:choice}
- \end{figure}
+ Both versions of the example correspond to the same netlist, which is
+ depicted in \Cref{img:choice}
\begin{figure}
\centerline{\includegraphics{choice-case}}
- \caption{Choice - \emph{case-statement / pattern matching}}
+ \caption{Choice - sumif}
\label{img:choice}
\end{figure}
+ A slightly more complex (but very powerful) form of choice is pattern
+ matching. A function can be defined in multiple clauses, where each clause
+ specifies a pattern. When the arguments match the pattern, the
+ corresponding clause will be used. Expressions can also contain guards,
+ where the expression is only executed if the guard evaluates to true. A
+ pattern match (with optional guards) can be to a conditional assignments
+ in \VHDL, where the conditions are an equality test of the argument and
+ one of the patterns (combined with the guard if was present). A third
+ version of the earlier example, using both pattern matching and guards,
+ can be seen below:
+
+ \begin{code}
+ sumif Eq a b | a == b = a + b
+ sumif Neq a b | a != b = a + b
+ sumif _ _ _ = 0
+ \end{code}
+
+ The version using pattern matching and guards has the same netlist
+ representation (\Cref{img:choice}) as the earlier two versions of the
+ example.
+
+ % \begin{figure}
+ % \centerline{\includegraphics{choice-ifthenelse}}
+ % \caption{Choice - \emph{if-then-else}}
+ % \label{img:choice}
+ % \end{figure}
+
\subsection{Types}
Translation of two most basic functional concepts has been
discussed: function application and choice. Before looking further
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="167.75"
- height="62.049969"
+ height="62.249371"
id="svg2"
version="1.1"
inkscape:version="0.47 r22583"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="4.3338301"
- inkscape:cx="83.875"
- inkscape:cy="31.024985"
+ inkscape:cx="41.187586"
+ inkscape:cy="31.224388"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:snap-grids="true"
inkscape:window-width="1091"
inkscape:window-height="838"
- inkscape:window-x="575"
- inkscape:window-y="194"
+ inkscape:window-x="253"
+ inkscape:window-y="212"
inkscape:window-maximized="0">
<inkscape:grid
type="xygrid"
id="layer1"
transform="translate(-342.5,-556.3198)">
<rect
- style="fill:#ffffff;stroke:#000000;stroke-width:0.60119492"
+ style="fill:#ffffff;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
id="rect2925"
width="115"
height="55.315327"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="131.25"
- height="61.984081"
+ height="62.203773"
id="svg2"
version="1.1"
inkscape:version="0.47 r22583"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="4.3090862"
- inkscape:cx="81.397466"
- inkscape:cy="60.202887"
+ inkscape:cx="38.46493"
+ inkscape:cy="60.422578"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
height="55.315327"
width="100"
id="rect2925"
- style="fill:#ffffff;stroke:#000000;stroke-width:0.56061715" />
+ style="fill:#ffffff;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none" />
<rect
style="fill:#ffffff;stroke:#000000;stroke-width:0.54772252"
id="rect5226"