import "primitives/core.futil";
import "primitives/memories/comb.futil";
import "primitives/binary_operators.futil";
component exponent(base: 32, exp: 4) -> (out: 32) {
cells {
pow = std_reg(32);
count = std_reg(4);
mul = std_mult_pipe(32);
lt = std_lt(4);
incr = std_add(4);
const0 = std_const(4, 3);
}
wires {
group init<"static"=1> {
pow.in = 32'd1;
pow.write_en = 1'd1;
count.in = 4'd0;
count.write_en = 1'd1;
init[done] = pow.done & count.done ? 1'd1;
}
group do_mul {
mul.left = base;
mul.right = pow.out;
mul.go = !mul.done ? 1'd1;
pow.in = mul.out;
pow.write_en = mul.done;
do_mul[done] = pow.done;
}
group incr_count<"static"=1> {
incr.left = 4'd1;
incr.right = count.out;
count.in = incr.out;
count.write_en = 1'd1;
incr_count[done] = count.done;
}
comb group cond {
lt.right = exp;
lt.left = count.out;
}
out = pow.out;
}
control {
seq {
init;
while lt.out with cond {
par { do_mul; incr_count; }
}
}
}
}
component main() -> () {
cells {
@external(1) a0 = comb_mem_d1(32,10,4);
a_read0_0 = std_reg(32);
add0 = std_add(4);
const0 = std_const(4,0);
const1 = std_const(4,9);
const2 = std_const(4,1);
const3 = std_const(4,3);
exp0 = exponent();
i0 = std_reg(4);
le0 = std_le(4);
tmp_0 = std_reg(32);
}
wires {
comb group cond0 {
le0.left = i0.out;
le0.right = const1.out;
}
group let0 {
i0.in = const0.out;
i0.write_en = 1'd1;
let0[done] = i0.done;
}
group let1 {
tmp_0.in = exp0.out;
tmp_0.write_en = 1'd1;
let1[done] = tmp_0.done;
}
group upd0 {
a_read0_0.write_en = 1'd1;
a0.addr0 = i0.out;
a_read0_0.in = 1'd1 ? a0.read_data;
upd0[done] = a_read0_0.done ? 1'd1;
}
group upd1 {
a0.addr0 = i0.out;
a0.write_en = 1'd1;
a0.write_data = 1'd1 ? tmp_0.out;
upd1[done] = a0.done ? 1'd1;
}
group upd2 {
i0.write_en = 1'd1;
add0.left = i0.out;
add0.right = const2.out;
i0.in = 1'd1 ? add0.out;
upd2[done] = i0.done ? 1'd1;
}
}
control {
seq {
let0;
while le0.out with cond0 {
seq {
upd0;
invoke exp0(base = a_read0_0.out, exp = const3.out)();
let1;
upd1;
upd2;
}
}
}
}
}