import "primitives/core.futil";
import "primitives/memories.futil";
component func(@go go: 1, @clk clk: 1, @reset reset: 1, in_out: 32, in_done: 1) -> (@stable processed: 32, @done done: 1, in_in: 32, in_write_en: 1) {
cells {
acc_r = std_reg(32);
incr = std_add(32);
add = std_add(32);
}
wires {
group apply {
incr.left = in_out;
incr.right = 32'd10;
in_in = incr.out;
in_write_en = 1'd1;
apply[done] = in_done;
}
group bump_proc {
add.left = acc_r.out;
add.right = 32'd1;
acc_r.in = add.out;
acc_r.write_en = 1'd1;
bump_proc[done] = acc_r.done;
}
processed = acc_r.out;
}
control {
seq {
apply;
bump_proc;
}
}
}
component map_f(@go go: 1, @clk clk: 1, @reset reset: 1, func_processed: 32, func_done: 1, func_in_in: 32, func_in_write_en: 1, in_read_data: 32, in_write_done: 1, in_read_done: 1, out_read_data: 32, out_write_done: 1, out_read_done: 1) -> (@done done: 1, func_go: 1, func_in_done: 1, func_in_out: 32, in_addr0: 4, in_write_en: 1, in_write_data: 32, in_read_en: 1, out_addr0: 4, out_write_en: 1, out_write_data: 32, out_read_en: 1) {
cells {
idx = std_reg(4);
lt = std_lt(4);
add = std_add(4);
r = std_reg(32);
}
wires {
group init {
idx.write_en = 1'd1;
idx.in = 4'd0;
init[done] = idx.done;
}
group incr {
add.left = idx.out;
add.right = 4'd1;
idx.in = add.out;
idx.write_en = 1'd1;
incr[done] = idx.done;
}
group read_in {
in_read_en = 1'd1;
in_addr0 = idx.out;
read_in[done] = in_read_done;
}
group write_r {
r.write_en = 1'd1;
r.in = in_read_data;
write_r[done] = r.done;
}
group write_out {
out_write_en = 1'd1;
out_addr0 = idx.out;
out_write_data = r.out;
write_out[done] = out_write_done;
}
group invoke0 {
r.in = func_in_in;
r.write_en = func_in_write_en;
func_in_out = r.out;
func_in_done = r.done;
func_go = 1'd1;
invoke0[done] = func_done;
}
comb group cmp {
lt.left = idx.out;
lt.right = 4'd10;
}
}
control {
seq {
init;
while lt.out with cmp {
seq {
read_in;
write_r;
invoke0;
write_out;
incr;
}
}
}
}
}
component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) {
cells {
@external A = seq_mem_d1(32, 10, 4);
@external B = seq_mem_d1(32, 10, 4);
@external stats = seq_mem_d1(32, 2, 2);
f1 = func();
f2 = func();
map = map_f();
}
wires {
group invoke0 {
A.addr0 = map.in_addr0;
A.write_en = map.in_write_en;
A.write_data = map.in_write_data;
A.read_en = map.in_read_en;
map.in_read_data = A.read_data;
map.in_write_done = A.write_done;
map.in_read_done = A.read_done;
map.func_processed = f2.processed;
f2.go = map.func_go;
map.func_done = f2.done;
f2.in_done = map.func_in_done;
f2.in_out = map.func_in_out;
map.func_in_in = f2.in_in;
map.func_in_write_en = f2.in_write_en;
A.addr0 = map.out_addr0;
A.write_en = map.out_write_en;
A.write_data = map.out_write_data;
A.read_en = map.out_read_en;
map.out_read_data = A.read_data;
map.out_write_done = A.write_done;
map.out_read_done = A.read_done;
map.go = 1'd1;
invoke0[done] = map.done;
}
static<1> group f1_stats {
stats.addr0 = 2'd0;
stats.write_data = f1.processed;
stats.write_en = 1'd1;
}
static<1> group f2_stats {
stats.addr0 = 2'd1;
stats.write_data = f2.processed;
stats.write_en = 1'd1;
}
}
control {
seq {
invoke0;
f1_stats;
f2_stats;
}
}
}