ncline(andb)(out);
\stopuseMPgraphic
+ \startbuffer[And3VHDL]
+ entity and3Component_0 is
+ port (\azMyG2\ : in std_logic;
+ \bzMyI2\ : in std_logic;
+ \czMyK2\ : in std_logic;
+ \foozMySzMyS2\ : out std_logic;
+ clock : in std_logic;
+ resetn : in std_logic);
+ end entity and3Component_0;
+
+
+ architecture structural of and3Component_0 is
+ signal \argzMyMzMyM2\ : std_logic;
+ begin
+ \argzMyMzMyM2\ <= \azMyG2\ and \bzMyI2\;
+
+ \foozMySzMyS2\ <= \argzMyMzMyM2\ and \czMyK2\;
+ end architecture structural;
+ \stopbuffer
+
\placeexample[][ex:And3]{Simple three input and gate.}
\startcombination[2*1]
{\typebufferhs{And3}}{Haskell description using function applications.}
{\boxedgraphic{And3}}{The architecture described by the Haskell description.}
\stopcombination
+ \placeexample[][ex:And3VHDL]{\VHDL\ generated for \hs{and3} from \in{example}[ex:And3]}
+ {\typebuffervhdl{And3VHDL}}
+
\placeintermezzo{}{
+ \defref{top level binding}
\defref{top level binder}
\defref{top level function}
\startframedtext[width=8cm,background=box,frame=no]
{\tfa Top level binders and functions}
\stopalignment
\blank[medium]
- A top level binder is any binder (variable) that is declared in
- the \quote{global} scope of a Haskell program (as opposed to a
- binder that is bound inside a function.
+ A \emph{top level binder} is any binder (variable) that is
+ declared in the \quote{global} scope of a Haskell program (as
+ opposed to a binder that is bound inside a function. The binder
+ together with its body is referred to as a \emph{top level
+ binding}.
In Haskell, there is no sharp distinction between a variable and a
function: a function is just a variable (binder) with a function
- type. This means that a top level function is just any top level
- binder with a function type.
+ type. This means that a \emph{top level function} is just any top
+ level binder with a function type. This also means that sometimes
+ top level function will be used when top level binder is really
+ meant.
As an example, consider the following Haskell snippet:
simply be translated to a conditional assignment, where the conditions use
equality comparisons against the constructors in the \hs{case} expressions.
- In \in{example}[ex:CaseInv] a simple \hs{case} expression is shown,
- scrutinizing a boolean value. The corresponding architecture has a
- comparator to determine which of the constructors is on the \hs{in}
- input. There is a multiplexer to select the output signal. The two options
- for the output signals are just constants, but these could have been more
- complex expressions (in which case also both of them would be working in
- parallel, regardless of which output would be chosen eventually).
+ In \in{example}[ex:Inv] two versions of an inverter are shown. The first
+ uses a simple \hs{case} expression, scrutinizing a boolean value. The
+ corresponding architecture has a comparator to determine which of the
+ constructors is on the \hs{in} input. There is a multiplexer to select the
+ output signal (which is just a conditional assignment in the generated
+ \VHDL). The two options for the output signals are just constants,
+ but these could have been more complex expressions (in which case also
+ both of them would be working in parallel, regardless of which output
+ would be chosen eventually). The \VHDL\ generated for (both versions of)
+ this inverter is shown in \in{example}[ex:InvVHDL].
If we would translate a Boolean to a bit value, we could of course remove
the comparator and directly feed 'in' into the multiplexer (or even use an
specifies a pattern. When the arguments match the pattern, the
corresponding clause will be used.
- 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
+ \in{Example}[ex:Inv] also shows an inverter that uses pattern matching.
+ The architecture it describes is of course the
+ same one as the description with a case expression. The general interpretation
of pattern matching is also similar to that of \hs{case} expressions: generate
hardware for each of the clauses (like each of the clauses of a \hs{case}
expression) and connect them to the function output through (a number of
False -> True
\stopbuffer
- \startuseMPgraphic{CaseInv}
+ \startbuffer[PatternInv]
+ inv :: Bool -> Bool
+ inv True = False
+ inv False = True
+ \stopbuffer
+
+ \startuseMPgraphic{Inv}
save in, truecmp, falseout, trueout, out, cmp, mux;
% I/O ports
ncline(trueout)(mux) "posB(inpb)";
ncline(mux)(out) "posA(out)";
\stopuseMPgraphic
-
- \placeexample[][ex:CaseInv]{Simple inverter.}
- \startcombination[2*1]
- {\typebufferhs{CaseInv}}{Haskell description using a Case expression.}
- {\boxedgraphic{CaseInv}}{The architecture described by the Haskell description.}
- \stopcombination
-
- \startbuffer[PatternInv]
- inv :: Bool -> Bool
- inv True = False
- inv False = True
+
+ \startbuffer[InvVHDL]
+ entity invComponent_0 is
+ port (\xzAMo2\ : in boolean;
+ \reszAMuzAMu2\ : out boolean;
+ clock : in std_logic;
+ resetn : in std_logic);
+ end entity invComponent_0;
+
+
+ architecture structural of invComponent_0 is
+ begin
+ \reszAMuzAMu2\ <= false when \xzAMo2\ = true else
+ true;
+ end architecture structural;
\stopbuffer
- \placeexample[][ex:PatternInv]{Simple inverter using pattern matching.
- Describes the same architecture as \in{example}[ex:CaseInv].}
- {\typebufferhs{PatternInv}}
+ \placeexample[][ex:Inv]{Simple inverter.}{
+ % Use placesidebyside, since nesting combinations doesn't seem to work
+ % here. This does break centering, but well...
+ \placesidebyside
+ % Use 2*2 instead of 1*2 to insert some extra space (\placesidebyside
+ % places stuff very close together)
+ {\startcombination[2*2]
+ {\typebufferhs{CaseInv}}{Haskell description using a Case expression.}
+ {}{}
+ {\typebufferhs{PatternInv}}{Haskell description using Pattern matching expression.}
+ {}{}
+ \stopcombination}
+ % Use a 1*1 combination to add a caption
+ {\startcombination[1*1]
+ {\boxedgraphic{Inv}}{The architecture described by the Haskell descriptions.}
+ \stopcombination}
+ }
+
+% \placeexample[][ex:Inv]{Simple inverter.}{
+% \startcombination[2*2]
+% {\typebufferhs{CaseInv}}{Haskell description using a Case expression.}
+% {}{}
+% {\typebufferhs{PatternInv}}{Haskell description using Pattern matching expression.}
+% {\boxedgraphic{Inv}}{The architecture described by the Haskell description.}
+% \stopcombination
+% }
+ \placeexample[][ex:InvVHDL]{\VHDL\ generated for (both versions of) \hs{inv} from \in{example}[ex:Inv]}
+ {\typebuffervhdl{InvVHDL}}
\section{Types}
Translation of two most basic functional concepts has been
This is the major downside of this approach: the separation between
interface and implementation is limited. However, since Cλash is not
- very suitable for separate compilation (see
- \in{section}[sec:prototype:separate]) this is not a big problem in
- practice.
+ very suitable for separate compilation this is not a big problem
+ in practice.
Additionally, when using a type synonym for the state type
of each function, we can still provide explicit type signatures