Intermediate language and compiler construction kit for hardware accelerators.
Compiler dependencies:
- Install Rust (it should automatically install
cargo
).
Testing dependencies:
- runt by running
cargo install runt
- vcdump by running
cargo install vcdump
- Verilator:
- Ubuntu:
sudo apt install verilator
- Fedora:
sudo dnf install verilator
- Mac:
brew install verilator
- If none of these work for you, I refer you to the official Verilator install instructions.
- Ubuntu:
- jq:
- Ubuntu:
sudo apt install jq
- Fedora:
sudo dnf install jq
- Mac:
brew install jq
- If none of these work, here are the official install directions.
- Ubuntu:
Dahlia dependencies:
-
Install Dahlia.
-
Point the
DAHLIA
environment variable to the Dahlia compiler binaryexport DAHLIA=<path-to-dahlia>/fuse
Build the compiler:
- Run
cargo build
to build the compiler. - Run
./target/debug/futil --help
to get options from thefutil
binary.
Run the integration tests:
- Run
runt -x dahlia
(Optional) Run the full test suite (requires installation of the Dahlia compiler):
- Run
runt
The compiler can be run in two ways:
cargo run -- <options>
: Rebuild compiler and run the CLI../target/debug/futil <options>
: Run the compiler without rebuilding the CLI.
Compile an example FuTIL program: examples/simple.futil
cargo run -- examples/simple.futil
Compile a FuTIL program to Verilog for Verilator simulation
cargo run -- <file> -b verilog --verilator
The compiler source lives under calyx/src. While changing the compiler,
use cargo run -- <calyx options>
to rebuild the compiler and run files
at the same time.
Primitives Library: FuTIL can use customizable libraries based on the
backend. The libraries live under primitives. You probably want
to use primitives/std.lib
with the -l
flag, which tells the compiler to look for primitives/std.lib
.
You'll need to explicitly pass the flag if you're not in the root directory. Assuming the import statement is import primitives/std.lib
:
$ cd futil # Inside root directory.
$ cargo run -- examples/simple.futil -l primitives # WRONG: "Failed to read primitives/primitives/std.lib"
$ cargo run -- examples/simple.futil # RIGHT
$ cd benchmarks # Outside root directory.
$ cargo run -- ../examples/simple.futil -l .. # RIGHT
Debug mode: The -d
flag shows the FuTIL program after running a pass.
Use this to debug outputs from passes.
The general flow of the compiler is as follows:
- Build up
context::Context
- Parse FuTIL files + library file specified in CLI.
- Build an in memory representation of each Component specified using
the primitives defined in the library file to resolve and instantiate
subcomponents defined with
new-std
statements.
- Run passes that update the context. Passes are defined using the Visitor
framework defined in
src/passes/visitor.rs
. For now the passes to run are just specified insrc/main.rs
- Use a backend to emit code from the context. Backends must implement
backend::traits::Backend
.
We use the structopt library to implement the command line interface.
The tests/verilog
folder is dedicated to Verilator correctness testing.
A .futil
in this directory defines a new test. To get output we run the following steps:
- Use
verilog
backend to generate a Verilog file - Run Verilator using
sim/testbench.cpp
as the testbench.- This expects a toplevel component in Futil named
main
- We drive the
main
component by pulsing theclk
port onmain
- We simulate until the
ready
port onmain
is high.
- This expects a toplevel component in Futil named
- Convert the generated
vcd
file tojson
- Use
{filename}.jq
to choose a subset of signals to test - Compare this generated file to
{filename.expect}
Concretely, the things to do to create a new test are:
- make a new
{filename}.futil
file - make a
{filename}.jq
file to select the signals you are interested in testing. Note: This file can be blank, but needs to exist. - make a
{filename}.expect
file with the values that you expect to see
make [filename].futil
: Generate Futil program from Dahlia program. It
requires to install Dahlia first.
make [filename].v
: Generate Verilog RTL file from Futil program.
make [filename].vcd
: Generate vcd file from Verilog RTL file. One can use ventilator to visualize it.
make [filename].json
: Generate a json representation of the simulated Verilog file.
make [filename].res
: Use [filename].jq
to refine [filename].json
to subset of signals.
make clean
: Deletes all generated files.