# Calyx Language Tutorial
This tutorial will familiarize you with the Calyx language by writing a minimal program *by hand*.
Usually, Calyx code will be generated by a frontend.
However, by writing the program by hand, you can get familiar with all the
basic constructs you need to generate Calyx yourself!
Complete code for each example can be found in the [tutorial][] directory in
the Calyx repository.
## Get Started
The basic building block of Calyx programs is a *component* which corresponds
to hardware modules (or function definitions for the software-minded).
Here is an empty component definition for `main` along with an `import`
statement to import the standard library:
import "primitives/core.futil";
component main(@go go: 1) -> (@done done: 1) {
cells {}
wires {}
control {}
}
Put this in a file—you can call it `language-tutorial-mem.futil`, for example.
(The `futil` file extension comes from an old name for Calyx.)
You can think of a component as a unit of Calyx code roughly analogous to a function: it encapsulates a logical unit of hardware structures along with their control.
Every component definition has three sections:
* `cells`: The hardware subcomponents that make up this component.
* `wires`: A set of guarded connections between components, possibly organized into *groups*.
* `control`: The imperative program that defines the component's execution schedule: i.e., when each group executes.
We'll fill these sections up minimally in the next sections.
## A Memory Cell
Let's turn our skeleton into a tiny, nearly no-op Calyx program.
We'll start by adding a memory component to the cells:
```
{{#include ../../examples/tutorial/language-tutorial-mem.futil:cells}}
```
This new line declares a new cell called `mem` and the primitive component `comb_mem_d1` represents a 1D memory.
You can see the definition of `comb_mem_d1`, and all the other standard components, in the `primitives/core.futil` library we imported.
This one has three parameters:
the data width (here, 32 bits),
the number of elements (just one),
and the width of the address port (one bit).
The `@external` syntax is an [extra bit of magic][ext-attr] that allows us
to read and write to the memory.
Next, we'll add some assignments to the `wires` section to update the value in
the memory.
Insert these lines to put a constant value into the memory:
```
{{#include ../../examples/tutorial/language-tutorial-mem.futil:wires}}
```
These assignments refer to four *ports* on the memory component:
`addr0` (the address port),
`write_data` (the value we're putting into the memory),
`write_en` (the *write enable* signal, telling the memory that it's time to do a write), and
`done` (signals that the write was committed).
Constants like `32'd42` are Verilog-like literals that include the bit width (32), the base (`d` for decimal), and the value (42).
Assignments at the top level in the `wires` section, like these, are "continuous".
They always happen, without any need for `control` statements to orchestrate them.
We'll see later how to organize assignments into groups.
> The complete program for this section is available under [examples/tutorial/language-tutorial-mem.futil](https://github.com/calyxir/calyx/blob/master/examples/tutorial/language-tutorial-mem.futil).
## Compile & Run
We can almost run this program!
But first, we need to provide it with data.
The Calyx infrastructure can [provide data to programs][data-format] from [JSON][] files.
So make a file called something like `data.json` containing something along these lines:
```
{{#include ../../examples/tutorial/data.json}}
```
The `mem` key means we're providing the initial value for our memory called `mem`.
We have one (unsigned integer) data element, and we indicate the bit width (32 bits).
If you want to see how this Calyx program compiles to Verilog, here's the [fud][] incantation you need:
fud exec language-tutorial-mem.futil --to verilog
Not terribly interesting!
However, one nice thing you can do with programs is execute them.
To run our program using [Icarus Verilog][], do this:
fud exec language-tutorial-mem.futil --to dat --through icarus-verilog \
-s verilog.data data.json
Using `--to dat` asks fud to run the program, and the extra `-s verilog.data <filename>` argument tells it where to find the input data.
The `--through icarus-verilog` option tells fud which Verilog simulator to use (see [the chapter about fud][fud] for alternatives such as [Verilator][]).
Executing this program should print:
```
{{#include ../../examples/tutorial/language-tutorial-mem.expect}}
```
Meaning that, after the program finished, the final value in our memory was 42.
> **Note**: Verilator may report a different cycle count compared to the one above. As long as the final value in memory is correct, this does not matter.
## Add Control
Let's change our program to use an execution schedule.
First, we're going to wrap all the assignments in the `wires` section into a
name *group*:
```
{{#include ../../examples/tutorial/language-tutorial-control.futil:wires}}
```
We also need one extra line in the group: that assignment to `the_answer[done]`.
Here, we say that `the_answer`'s work is done once the update to `mem` has finished.
Calyx groups have *compilation holes* called `go` and `done` that the control program will use to orchestrate their execution.
The last thing we need is a control program.
Add one line to activate `the_answer` and then finish:
```
{{#include ../../examples/tutorial/language-tutorial-control.futil:control}}
```
If you execute this program, it should do the same thing as the original group-free version: `mem` ends up with 42 in it.
But now we're controlling things with an execution schedule.
If you're curious to see how the Calyx compiler lowers this program to a Verilog-like structural form of Calyx, you can do this:
fud exec language-tutorial-mem.futil --to calyx-lowered
Notably, you'll see `control {}` in the output, meaning that the compiler has eliminated all the control statements and replaced them with continuous assignments in `wires`.
> The complete program for this section is available under [examples/tutorial/language-tutorial-control.futil](https://github.com/calyxir/calyx/blob/master/examples/tutorial/language-tutorial-control.futil).
## Add an Adder
The next step is to actually do some computation.
In this version of the program, we'll read a value from the memory, increment it, and store the updated value back to the memory.
First, we will add two components to the `cells` section:
```
{{#include ../../examples/tutorial/language-tutorial-compute.futil:cells}}
```
We make a register `val` and an integer adder `add`, both configured to work on 32-bit values.
Next, we'll create three groups in the `wires` section for the three steps we want to run: read, increment, and write back to the memory.
Let's start with the last step, which looks pretty similar to our `the_answer` group from above, except that the value comes from the `val` register instead of a constant:
```
{{#include ../../examples/tutorial/language-tutorial-compute.futil:write}}
```
Next, let's create a group `read` that moves the value from the memory to our register `val`:
```
{{#include ../../examples/tutorial/language-tutorial-compute.futil:read}}
```
Here, we use the memory's `read_data` port to get the initial value out.
Finally, we need a third group to add and update the value in the register:
```
{{#include ../../examples/tutorial/language-tutorial-compute.futil:upd}}
```
The `std_add` component from the standard library has two input ports, `left` and `right`, and a single output port, `out`, which we hook up to the register's `in` port.
This group adds a constant 4 to the register's value, updating it in place.
We can enable the `val` register with a constant 1 because the `std_add` component is *combinational*, meaning its results are ready "instantly" without the need to wait for a done signal.
We need to extend our control program to orchestrate the execution of the three groups.
We will need a `seq` statement to say we want to the three steps sequentially:
```
{{#include ../../examples/tutorial/language-tutorial-compute.futil:control}}
```
Try running this program again.
The memory's initial value was 10, and its final value after execution should be 14.
> The complete program for this section is available under [examples/tutorial/language-tutorial-compute.futil](https://github.com/calyxir/calyx/blob/master/examples/tutorial/language-tutorial-compute.futil).
## Iterate
Next, we'd like to run our little computation in a loop.
The idea is to use Calyx's `while` control construct, which works like this:
while <value> with <group> {
<body>
}
A `while` loop runs the control statements in the body until `<value>`, which is some port on some component, becomes zero.
The `with <group>` bit means that we activate a given group in order to compute the condition value that determines whether the loop continues executing.
Let's run our memory-updating `seq` block in a while loop.
Change the control program to look like this:
```
{{#include ../../examples/tutorial/language-tutorial-iterate.futil:control}}
```
This version uses `while`, the parallel composition construct `par`, and a few new groups we will need to define.
The idea is that we'll use a counter register to make this loop run a fixed number of times, like a `for` loop.
First, we have an outer `seq` that invokes an `init` group that we will write to set the counter to zero.
The `while` loop then uses a new group `cond`, and it will run while a signal `lt.out` remains nonzero: this signal will compute `counter < 8`.
The body of the loop runs our old `seq` block in parallel with a new `incr` group to increment the counter.
Let's add some cells to our component:
```
{{#include ../../examples/tutorial/language-tutorial-iterate.futil:new_cells}}
```
We'll need a new register, an adder to do the incrementing, and a less-than comparator.
We can use these raw materials to build the new groups we need: `init`, `incr`, and `cond`.
First, the `init` group is pretty simple:
```
{{#include ../../examples/tutorial/language-tutorial-iterate.futil:init}}
```
This group just writes a zero into the counter and signals that it's done.
Next, the `incr` group adds one to the value in `counter` using `add2`:
```
{{#include ../../examples/tutorial/language-tutorial-iterate.futil:incr}}
```
And finally, `cond` uses our comparator `lt` to compute the signal we need for
our `while` loop. We use a `comb group` to denote that the assignments inside
the condition can be run combinationally:
```
{{#include ../../examples/tutorial/language-tutorial-iterate.futil:cond}}
```
By comparing with 8, we should now be running our loop body 8 times.
Try running this program again.
The output should be the result of adding 4 to the initial value 8 times, so 10 + 8 × 4.
> The complete program for this section is available under [examples/tutorial/language-tutorial-iterate.futil](https://github.com/calyxir/calyx/blob/master/examples/tutorial/language-tutorial-iterate.futil).
Take a look at the [full language reference][lang-ref] for details on the complete language.
[ext-attr]: ../lang/attributes.html#external
[json]: https://www.json.org/
[verilator]: https://www.veripool.org/wiki/verilator
[tutorial]: https://github.com/calyxir/calyx/tree/master/examples/tutorial
[icarus verilog]: http://iverilog.icarus.com
[fud]: ../fud/index.md
[data-format]: ../lang/data-format.md
[lang-ref]: ../lang/ref.md