}
Considering that we required a prototype which should be working quickly,
and that implementing parsers, semantic checkers and especially
- type-checkers is not exactly the Core of this research (but it is lots and
- lots of work!), using an existing language is the obvious choice. This
+ type-checkers is not exactly the core of this research (but it is lots and
+ lots of work, using an existing language is the obvious choice. This
also has the advantage that a large set of language features is available
to experiment with and it is easy to find which features apply well and
- which do not. Another import advantage of using an existing language, is
+ which do not. Another important advantage of using an existing language, is
that simulation of the code becomes trivial. Since there are existing
compilers and interpreters that can run the hardware description directly,
it can be simulated without also having to write an interpreter for the
and Verilog are on the higher level, while we will be using \small{VHDL}
mainly to write low level, netlist-like descriptions anyway.
- An added advantage of using VHDL is that we can profit from existing
- optimizations in VHDL synthesizers. A lot of optimizations are done on the
- VHDL level by existing tools. These tools have been under
+ An added advantage of using \VHDL\ is that we can profit from existing
+ optimizations in \VHDL\ synthesizers. A lot of optimizations are done on the
+ \VHDL\ level by existing tools. These tools have been under
development for years, so it would not be reasonable to assume we
could achieve a similar amount of optimization in our prototype (nor
should it be a goal, considering this is just a prototype).
simple, structural descriptions, without any complex behavioral
descriptions like arbitrary sequential statements (which might not
be supported by all tools). This ensures that any tool that works
- with \VHDL\ will understand our output (most tools do not support
- synthesis of more complex \VHDL). This also leaves open the option
- to switch to \small{EDIF} in the future, with minimal changes to the
- prototype.
+ with \VHDL\ will understand our output. This also leaves open the
+ option to switch to \small{EDIF} in the future, with minimal changes
+ to the prototype.
\section{Simulation and synthesis}
As mentioned above, by using the Haskell language, we get simulation of
\section[sec:prototype:design]{Prototype design}
As suggested above, we will use the Glasgow Haskell Compiler (\small{GHC}) to
implement our prototype compiler. To understand the design of the
- compiler, we will first dive into the \small{GHC} compiler a bit. Its
- compilation consists of the following steps (slightly simplified):
+ prototype, we will first dive into the \small{GHC} compiler a bit. Its
+ compilatprototype consists of the following steps (slightly simplified):
\startuseMPgraphic{ghc-pipeline}
% Create objects
type-checker.
\stopdesc
\startdesc{Desugaring}
- This steps takes the full \small{AST} and translates it to the
+ This step takes the full \small{AST} and translates it to the
\emph{Core} language. Core is a very small functional language with lazy
semantics, that can still express everything Haskell can express. Its
simpleness makes Core very suitable for further simplification and
\startdesc{Backend}
This step takes the simplified Core program and generates an actual
runnable program for it. This is a big and complicated step we will not
- discuss it any further, since it is not required for our prototype.
+ discuss it any further, since it is not relevant to our prototype.
\stopdesc
In this process, there are a number of places where we can start our work.
binder name should of course be bound in a containing scope
(including top level scope, so a reference to a top level function
is also a variable reference). Additionally, constructors from
- algebraic data-types also become variable references.
+ algebraic data-types also become variable references (\eg\
+ \lam{True}).
In our examples, binders will commonly consist of a single
characters, but they can have any length.
Each binder also carries around its type (explicitly shown above), but
this is usually not shown in the Core expressions. Only when the type is
relevant (when a new binder is introduced, for example) will it be
- shown. In other cases, the binder is either not relevant, or easily
+ shown. In other cases, the type is either not relevant, or easily
derived from the context of the expression. \todo{Ref sidenote on type
annotations}
\stopdesc
normal Haskell versions (but there are built-in conversion
functions). Without going into detail about these types, note that
a few conversion functions exist to convert these to the normal
- (boxed) Haskell equivalents.
+ (boxed) Haskell equivalents. See
+ \in{section}[sec:normalization:literals] for an example.
\stopdesc
\startdesc{Application}
for normal function \quote{calls}, but also for applying type
abstractions and data constructors.
+ The value of an application is the value of the function part, with the
+ first argument binder bound to the argument part.
+
In Core, there is no distinction between an operator and a
function. This means that, for example the addition of two numbers
looks like the following in Core:
\startlambda
1 + 2
\stoplambda
-
- The value of an application is the value of the function part, with the
- first argument binder bound to the argument part.
\stopdesc
\startdesc{Lambda abstraction}