Multi-Component Designs
Calyx designs can define and instantiate other Calyx components that themselves
encode complex control
programs.
As an example, we'll build a Calyx design that uses a simple Calyx component to save a value in a register and use it in a different component.
We define a new component called identity
that has an input port in
and an output port out
.
component identity(in: 32) -> (out: 32) {
cells {
r = std_reg(32);
}
wires {
group save {
r.in = in;
r.write_en = 1'd1;
save[done] = r.done;
}
// This component always outputs the current value in r
out = r.out;
}
control {
save;
}
}
The following line defines a continuous assignment, i.e., an assignment
that is always kept active, regardless of the component's control
program
being active.
// This component always outputs the current value in r
out = r.out;
By defining this continuous assignment, we can execute our component and later observe any relevant values.
Next, we can instantiate this component in any other Calyx component.
The following Calyx program instantiates the id
component and uses it to
save a value and observe it.
component main() -> () {
cells {
// Instantiate the identity element
id = identity();
current_value = std_reg(32);
}
wires {
group run_id {
// We want to "save" the value 10 inside the identity group.
id.in = 32'd10;
// All components have a magic "go" and "done" port added to them.
// Execute the component.
id.go = 1'd1;
run_id[done] = id.done;
}
group use_id {
// We want to "observe" the current value saved in id.
// The out port on the `id` component always shows the last saved
// element. We don't need to set the `go` because we're not executing
// and control.
current_value.in = id.out;
current_value.write_en = 1'd1;
use_id[done] = current_value.done;
}
}
control {
seq { run_id; use_id; }
}
}
Our first group executes the component by setting the go
signal for the
component to high and placing the value 10
on the input port.
The second group simply saves the value on the output port. Importantly,
we don't have to set the go
signal of the component to high because we
don't need to save a new value into it.
The component executes the two groups in-order.
To see the output from running this component, run the command:
fud e examples/futil/multi-component.futil --to vcd