\chapter[chap:description]{Hardware description}
  This chapter will provide an overview of the hardware description language
  that was created and the issues that have arisen in the process. It will
  focus on the issues of the language, not the implementation.

  When translating Haskell to hardware, we need to make choices in what kind
  of hardware to generate for what Haskell constructs. When faced with
  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.
   
  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
  element that needs translation, to provide a clear picture of what is
  supported and how.

  \section{Function application}
  The basic syntactic element of a functional program are functions and
  function application. These have a single obvious \small{VHDL} translation: Each
  function becomes a hardware component, where each argument is an input port
  and the result value is the output port.

  Each function application in turn becomes component instantiation. Here, the
  result of each argument expression is assigned to a signal, which is mapped
  to the corresponding input port. The output port of the function is also
  mapped to a signal, which is used as the result of the application.

  An example of a simple program using only function application would be:

  \starthaskell
  -- | A simple function that returns the and of three bits
  and3 :: Bit -> Bit -> Bit -> Bit
  and3 a b c = and (and a b) c
  \stophaskell

  This results in the following hardware:
  
  TODO: Pretty picture

  \subsection{Partial application}
  It should be obvious that we cannot generate hardware signals for all
  expressions we can express in Haskell. The most obvious criterium for this
  is the type of an expression. We will see more of this below, but for now it
  should be obvious that any expression of a function type cannot be
  represented as a signal or i/o port to a component.

  From this, we can see that the above translation rules do not apply to a
  partial application. Let's look at an example:

  \starthaskell
  -- | Multiply the input word by four.
  quadruple :: Word -> Word
  quadruple n = mul (mul n)
    where
      mul = (*) 2
  \stophaskell

  It should be clear that the above code describes the following hardware:

  TODO: Pretty picture

  Here, the definition of mul is a partial function application: It applies
  \hs{2 :: Word} to the function \hs{(*) :: Word -> Word -> Word} resulting in
  the expression \hs{(*) 2 :: Word -> Word}. Since this resulting expression
  is again a function, we can't generate hardware for it directly. This is
  because the hardware to generate for \hs{mul} depends completely on where
  and how it is used. In this example, it is even used twice!

  However, it is clear that the above hardware description actually describes
  valid hardware. In general, we can see that any partial applied function
  must eventually become completely applied, at which point we can generate
  hardware for it using the rules for function application above. It might
  mean that a partial application is passed around quite a bit (even beyond
  function boundaries), but eventually, the partial application will become
  completely applied.

  \section{Recursion}
  An import concept in functional languages is recursion. In it's most basic
  form, recursion is a function that is defined in terms of itself. This
  usually requires multiple evaluations of this function, with changing
  arguments, until eventually an evaluation of the function no longer requires
  itself.

  Recursion in a hardware description is a bit of a funny thing. Usually,
  recursion is associated with a lot of nondeterminism, stack overflows, but
  also flexibility and expressive power.

  Given the notion that each function application will translate to a
  component instantiation, we are presented with a problem. A recursive
  function would translate to a component that contains itself. Or, more
  precisely, that contains an instance of itself. This instance would again
  contain an instance of itself, and again, into infinity. This is obviously a
  problem for generating hardware.

  This is expected for functions that describe infinite recursion. In that
  case, we can't generate hardware that shows correct behaviour in a single
  cycle (at best, we could generate hardware that needs an infinite number of
  cycles to complete).
  
  However, most recursive hardware descriptions will describe finite
  recursion. This is because the recursive call is done conditionally. There
  is usually a case statement where at least one alternative does not contain
  the recursive call, which we call the "base case". If, for each call to the
  recursive function, we would be able to detect which alternative applies,
  we would be able to remove the case expression and leave only the base case
  when it applies. This will ensure that expanding the recursive functions
  will terminate after a bounded number of expansions.

  This does imply the extra requirement that the base case is detectable at
  compile time. In particular, this means that the decision between the base
  case and the recursive case must not depend on runtime data.

  \subsection{List recursion}
  The most common deciding factor in recursion is the length of a list that is
  passed in as an argument. Since we represent lists as vectors that encode
  the length in the vector type, it seems easy to determine the base case. We
  can simply look at the argument type for this. However, it turns out that
  this is rather non-trivial to write down in Haskell in the first place. As
  an example, we would like to write down something like this:
 
  \starthaskell
    sum :: Vector n Word -> Word
    sum xs = case null xs of
      True -> 0
      False -> head xs + sum (tail xs)
  \stophaskell

  However, the typechecker will now use the following reasoning (element type
  of the vector is left out):

  \startitemize
  \item tail has the type \hs{(n > 0) => Vector n -> Vector (n - 1)}
  \item This means that xs must have the type \hs{(n > 0) => Vector n}
  \item This means that sum must have the type \hs{(n > 0) => Vector n -> a}
  \item sum is called with the result of tail as an argument, which has the
  type \hs{Vector n} (since \hs{(n > 0) => n - 1 == m}).
  \item This means that sum must have the type \hs{Vector n -> a}
  \item This is a contradiction between the type deduced from the body of sum
  (the input vector must be non-empty) and the use of sum (the input vector
  could have any length).
  \stopitemize

  As you can see, using a simple case at value level causes the type checker
  to always typecheck both alternatives, which can't be done! This is a
  fundamental problem, that would seem perfectly suited for a type class.
  Considering that we need to switch between to implementations of the sum
  function, based on the type of the argument, this sounds like the perfect
  problem to solve with a type class. However, this approach has its own
  problems (not the least of them that you need to define a new typeclass for
  every recursive function you want to define).

  Another approach tried involved using GADTs to be able to do pattern
  matching on empty / non empty lists. While this worked partially, it also
  created problems with more complex expressions.

  TODO: How much detail should there be here? I can probably refer to
  Christiaan instead.

  Evaluating all possible (and non-possible) ways to add recursion to our
  descriptions, it seems better to leave out list recursion alltogether. This
  allows us to focus on other interesting areas instead. By including
  (builtin) support for a number of higher order functions like map and fold,
  we can still express most of the things we would use list recursion for.
 
  \subsection{General recursion}
  Of course there are other forms of recursion, that do not depend on the
  length (and thus type) of a list. For example, simple recursion using a
  counter could be expressed, but only translated to hardware for a fixed
  number of iterations. Also, this would require extensive support for compile
  time simplification (constant propagation) and compile time evaluation
  (evaluation constant comparisons), to ensure non-termination. Even then, it
  is hard to really guarantee termination, since the user (or GHC desugarer)
  might use some obscure notation that results in a corner case of the
  simplifier that is not caught and thus non-termination.

  Due to these complications, we leave other forms of recursion as
  future work as well.
