choices, we've tried to stick with the most obvious choice wherever
possible. In a lot of cases, when you look at a hardware description it is
comletely clear what hardware is described. We want our translator to
- generate exactly that hardware whenever possible, to minimize the amount of
- surprise for people working with it.
+ generate exactly that hardware whenever possible, to make working with Cλash
+ as intuitive as possible.
In this chapter we try to describe how we interpret a Haskell program from a
hardware perspective. We provide a description of each Haskell language
\startbuffer[CaseInv]
inv :: Bool -> Bool
- inv True = False
- inv False = True
+ inv x = case x of
+ True -> False
+ False -> True
\stopbuffer
\startuseMPgraphic{CaseInv}
\placeexample[here][ex:PatternInv]{Simple inverter using pattern matching.
Describes the same architecture as \in{example}[ex:CaseInv].}
- {\typebufferhs{CaseInv}}
+ {\typebufferhs{PatternInv}}
The architecture described by \in{example}[ex:PatternInv] is of course the
same one as the one in \in{example}[ex:CaseInv]. The general interpretation
To define an index for the 8 element vector above, we would do:
\starthaskell
- type Register = RangedWord D7
+ type RegisterIndex = RangedWord D7
\stophaskell
Here, a type synonym \hs{RegisterIndex} is defined that is equal to
\subsection{User-defined types}
There are three ways to define new types in Haskell: Algebraic
datatypes with the \hs{data} keyword, type synonyms with the \hs{type}
- keyword and type renamings with the \hs{newtype} keyword. This
- explicitly excludes more advanced type creation from \GHC extensions
- such as type families, existential typing, \small{GADT}s, etc.
-
- The first of these actually introduces a new type, for which we provide
- the \VHDL translation below. The latter two only define new names for
+ keyword and type renamings with the \hs{newtype} keyword. \GHC
+ offers a few more advanced ways to introduce types (type families,
+ existential typing, \small{GADT}s, etc.) which are not standard
+ Haskell. These will be left outside the scope of this research.
+
+ Only an algebraic datatype declaration actually introduces a
+ completely new type, for which we provide the \VHDL translation
+ below. Type synonyms and renamings only define new names for
existing types (where synonyms are completely interchangeable and
- renamings need explicit conversion). Therefore, these don't need any
- particular \VHDL translation, a synonym or renamed type will just use
- the same representation as the equivalent type.
+ renamings need explicit conversion). Therefore, these don't need
+ any particular \VHDL translation, a synonym or renamed type will
+ just use the same representation as the original type. The
+ distinction between a renaming and a synonym does no longer matter
+ in hardware and can be disregarded in the generated \VHDL.
For algebraic types, we can make the following distinction:
structure. In fact, the builtin tuple types are just algebraic product
types (and are thus supported in exactly the same way).
- The "product" in its name refers to the collection of values belonging
+ The \quote{product} in its name refers to the collection of values belonging
to this type. The collection for a product type is the cartesian
product of the collections for the types of its fields.
- These types are translated to \VHDL, record types, with one field for
+ These types are translated to \VHDL record types, with one field for
every field in the constructor. This translation applies to all single
- constructor algebraic datatypes, including those with no fields (unit
- types) and just one field (which are technically not a product).
+ constructor algebraic datatypes, including those with just one
+ field (which are technically not a product, but generate a VHDL
+ record for implementation simplicity).
\stopdesc
\startdesc{Enumerated types}
\defref{enumerated types}
for our purposes this distinction does not really make a difference,
so we'll leave it out.
+ The \quote{sum} in its name refers again to the collection of values
+ belonging to this type. The collection for a sum type is the
+ union of the the collections for each of the constructors.
+
Sum types are currently not supported by the prototype, since there is
no obvious \VHDL alternative. They can easily be emulated, however, as
we will see from an example:
connected to one of the adder inputs).
This notation has a number of downsides, amongst which are limited
- readability and ambiguity in the interpretation. \note{Reference
+ readability and ambiguity in the interpretation. \todo{Reference
Christiaan, who has done further investigation}
\subsubsection{Explicit state arguments and results}
has to somehow know the current state for these called functions. The
only way to do this, is to put these \emph{substates} inside the
caller's state. This means that a function's state is the sum of the
- states of all functions it calls, and its own state.
+ states of all functions it calls, and its own state. This sum
+ can be obtained using something simple like a tuple, or possibly
+ custom algebraic types for clarity.
This also means that the type of a function (at least the "state"
part) is dependent on its own implementation and of the functions it
\todo{Sidenote: One or more state arguments?}
- \subsection{Explicit state annotation}
+ \subsection[sec:description:stateann]{Explicit state annotation}
To make our stateful descriptions unambigious and easier to translate,
we need some way for the developer to describe which arguments and
results are intended to become stateful.