import "primitives/core.futil";
import "primitives/memories/seq.futil";
import "primitives/binary_operators.futil";
component fifo_l(cmd: 2, value: 32) -> () {
cells {
mem = seq_mem_d1(32, 10, 32);
next_write = std_reg(32);
next_read = std_reg(32);
ref ans = std_reg(32);
ref err = std_reg(1);
len = std_reg(32);
eq_1 = std_eq(2);
eq_2 = std_eq(2);
eq_3 = std_eq(2);
eq_4 = std_eq(32);
eq_5 = std_eq(32);
eq_6 = std_eq(32);
eq_7 = std_eq(32);
next_write_incr = std_add(32);
next_read_incr = std_add(32);
len_incr = std_add(32);
len_decr = std_sub(32);
}
wires {
comb group eq_1_group {
eq_1.left = cmd;
eq_1.right = 2'd0;
}
comb group eq_2_group {
eq_2.left = cmd;
eq_2.right = 2'd1;
}
comb group eq_3_group {
eq_3.left = cmd;
eq_3.right = 2'd2;
}
comb group eq_4_group {
eq_4.left = next_write.out;
eq_4.right = 32'd10;
}
comb group eq_5_group {
eq_5.left = next_read.out;
eq_5.right = 32'd10;
}
comb group eq_6_group {
eq_6.left = len.out;
eq_6.right = 32'd0;
}
comb group eq_7_group {
eq_7.left = len.out;
eq_7.right = 32'd10;
}
group next_write_incr_group {
next_write_incr.left = next_write.out;
next_write_incr.right = 32'd1;
next_write.write_en = 1'd1;
next_write.in = next_write_incr.out;
next_write_incr_group[done] = next_write.done;
}
group next_read_incr_group {
next_read_incr.left = next_read.out;
next_read_incr.right = 32'd1;
next_read.write_en = 1'd1;
next_read.in = next_read_incr.out;
next_read_incr_group[done] = next_read.done;
}
group len_incr_group {
len_incr.left = len.out;
len_incr.right = 32'd1;
len.write_en = 1'd1;
len.in = len_incr.out;
len_incr_group[done] = len.done;
}
group len_decr_group {
len_decr.left = len.out;
len_decr.right = 32'd1;
len.write_en = 1'd1;
len.in = len_decr.out;
len_decr_group[done] = len.done;
}
group flash_write {
next_write.in = 32'd0;
next_write.write_en = 1'd1;
flash_write[done] = next_write.done;
}
group flash_read {
next_read.in = 32'd0;
next_read.write_en = 1'd1;
flash_read[done] = next_read.done;
}
group raise_err {
err.in = 1'd1;
err.write_en = 1'd1;
raise_err[done] = err.done;
}
group flash_ans {
ans.in = 32'd0;
ans.write_en = 1'd1;
flash_ans[done] = ans.done;
}
group write_payload_to_mem {
mem.addr0 = next_write.out;
mem.write_en = 1'd1;
mem.write_data = value;
write_payload_to_mem[done] = mem.write_done;
}
group read_payload_from_mem_phase1 {
mem.addr0 = next_read.out;
mem.read_en = 1'd1;
read_payload_from_mem_phase1[done] = mem.read_done;
}
group read_payload_from_mem_phase2 {
ans.write_en = 1'd1;
ans.in = mem.read_data;
read_payload_from_mem_phase2[done] = ans.done;
}
}
control {
par {
if eq_1.out with eq_1_group {
if eq_6.out with eq_6_group {
par {
raise_err;
flash_ans;
}
} else {
seq {
read_payload_from_mem_phase1;
read_payload_from_mem_phase2;
next_read_incr_group;
if eq_5.out with eq_5_group {
flash_read;
}
len_decr_group;
}
}
}
if eq_2.out with eq_2_group {
if eq_6.out with eq_6_group {
par {
raise_err;
flash_ans;
}
} else {
seq {
read_payload_from_mem_phase1;
read_payload_from_mem_phase2;
}
}
}
if eq_3.out with eq_3_group {
if eq_7.out with eq_7_group {
par {
raise_err;
flash_ans;
}
} else {
seq {
write_payload_to_mem;
next_write_incr_group;
if eq_4.out with eq_4_group {
flash_write;
}
len_incr_group;
}
}
}
}
}
}
component fifo_r(cmd: 2, value: 32) -> () {
cells {
mem = seq_mem_d1(32, 10, 32);
next_write = std_reg(32);
next_read = std_reg(32);
ref ans = std_reg(32);
ref err = std_reg(1);
len = std_reg(32);
eq_1 = std_eq(2);
eq_2 = std_eq(2);
eq_3 = std_eq(2);
eq_4 = std_eq(32);
eq_5 = std_eq(32);
eq_6 = std_eq(32);
eq_7 = std_eq(32);
next_write_incr = std_add(32);
next_read_incr = std_add(32);
len_incr = std_add(32);
len_decr = std_sub(32);
}
wires {
comb group eq_1_group {
eq_1.left = cmd;
eq_1.right = 2'd0;
}
comb group eq_2_group {
eq_2.left = cmd;
eq_2.right = 2'd1;
}
comb group eq_3_group {
eq_3.left = cmd;
eq_3.right = 2'd2;
}
comb group eq_4_group {
eq_4.left = next_write.out;
eq_4.right = 32'd10;
}
comb group eq_5_group {
eq_5.left = next_read.out;
eq_5.right = 32'd10;
}
comb group eq_6_group {
eq_6.left = len.out;
eq_6.right = 32'd0;
}
comb group eq_7_group {
eq_7.left = len.out;
eq_7.right = 32'd10;
}
group next_write_incr_group {
next_write_incr.left = next_write.out;
next_write_incr.right = 32'd1;
next_write.write_en = 1'd1;
next_write.in = next_write_incr.out;
next_write_incr_group[done] = next_write.done;
}
group next_read_incr_group {
next_read_incr.left = next_read.out;
next_read_incr.right = 32'd1;
next_read.write_en = 1'd1;
next_read.in = next_read_incr.out;
next_read_incr_group[done] = next_read.done;
}
group len_incr_group {
len_incr.left = len.out;
len_incr.right = 32'd1;
len.write_en = 1'd1;
len.in = len_incr.out;
len_incr_group[done] = len.done;
}
group len_decr_group {
len_decr.left = len.out;
len_decr.right = 32'd1;
len.write_en = 1'd1;
len.in = len_decr.out;
len_decr_group[done] = len.done;
}
group flash_write {
next_write.in = 32'd0;
next_write.write_en = 1'd1;
flash_write[done] = next_write.done;
}
group flash_read {
next_read.in = 32'd0;
next_read.write_en = 1'd1;
flash_read[done] = next_read.done;
}
group raise_err {
err.in = 1'd1;
err.write_en = 1'd1;
raise_err[done] = err.done;
}
group flash_ans {
ans.in = 32'd0;
ans.write_en = 1'd1;
flash_ans[done] = ans.done;
}
group write_payload_to_mem {
mem.addr0 = next_write.out;
mem.write_en = 1'd1;
mem.write_data = value;
write_payload_to_mem[done] = mem.write_done;
}
group read_payload_from_mem_phase1 {
mem.addr0 = next_read.out;
mem.read_en = 1'd1;
read_payload_from_mem_phase1[done] = mem.read_done;
}
group read_payload_from_mem_phase2 {
ans.write_en = 1'd1;
ans.in = mem.read_data;
read_payload_from_mem_phase2[done] = ans.done;
}
}
control {
par {
if eq_1.out with eq_1_group {
if eq_6.out with eq_6_group {
par {
raise_err;
flash_ans;
}
} else {
seq {
read_payload_from_mem_phase1;
read_payload_from_mem_phase2;
next_read_incr_group;
if eq_5.out with eq_5_group {
flash_read;
}
len_decr_group;
}
}
}
if eq_2.out with eq_2_group {
if eq_6.out with eq_6_group {
par {
raise_err;
flash_ans;
}
} else {
seq {
read_payload_from_mem_phase1;
read_payload_from_mem_phase2;
}
}
}
if eq_3.out with eq_3_group {
if eq_7.out with eq_7_group {
par {
raise_err;
flash_ans;
}
} else {
seq {
write_payload_to_mem;
next_write_incr_group;
if eq_4.out with eq_4_group {
flash_write;
}
len_incr_group;
}
}
}
}
}
}
component pifo(cmd: 2, value: 32) -> () {
cells {
queue_l = fifo_l();
queue_r = fifo_r();
flow = std_reg(1);
lt_1 = std_lt(32);
ref ans = std_reg(32);
ref err = std_reg(1);
len = std_reg(32);
hot = std_reg(1);
eq_2 = std_eq(1);
eq_3 = std_eq(32);
eq_4 = std_eq(32);
eq_5 = std_eq(2);
eq_6 = std_eq(2);
eq_7 = std_eq(2);
eq_8 = std_eq(1);
neq_9 = std_neq(1);
hot_not = std_not(1);
len_incr = std_add(32);
len_decr = std_sub(32);
}
wires {
group infer_flow {
lt_1.left = 32'd200;
lt_1.right = value;
flow.write_en = 1'd1;
flow.in = lt_1.out;
infer_flow[done] = flow.done;
}
comb group eq_2_group {
eq_2.left = hot.out;
eq_2.right = 1'd0;
}
comb group eq_3_group {
eq_3.left = len.out;
eq_3.right = 32'd0;
}
comb group eq_4_group {
eq_4.left = len.out;
eq_4.right = 32'd10;
}
comb group eq_5_group {
eq_5.left = cmd;
eq_5.right = 2'd0;
}
comb group eq_6_group {
eq_6.left = cmd;
eq_6.right = 2'd1;
}
comb group eq_7_group {
eq_7.left = cmd;
eq_7.right = 2'd2;
}
comb group eq_8_group {
eq_8.left = err.out;
eq_8.right = 1'd0;
}
comb group neq_9_group {
neq_9.left = err.out;
neq_9.right = 1'd0;
}
group hot_not_group {
hot_not.in = hot.out;
hot.write_en = 1'd1;
hot.in = hot_not.out;
hot_not_group[done] = hot.done;
}
group raise_err {
err.in = 1'd1;
err.write_en = 1'd1;
raise_err[done] = err.done;
}
group lower_err {
err.in = 1'd0;
err.write_en = 1'd1;
lower_err[done] = err.done;
}
group flash_ans {
ans.in = 32'd0;
ans.write_en = 1'd1;
flash_ans[done] = ans.done;
}
group len_incr_group {
len_incr.left = len.out;
len_incr.right = 32'd1;
len.write_en = 1'd1;
len.in = len_incr.out;
len_incr_group[done] = len.done;
}
group len_decr_group {
len_decr.left = len.out;
len_decr.right = 32'd1;
len.write_en = 1'd1;
len.in = len_decr.out;
len_decr_group[done] = len.done;
}
}
control {
par {
if eq_5.out with eq_5_group {
if eq_3.out with eq_3_group {
par {
raise_err;
flash_ans;
}
} else {
seq {
lower_err;
if eq_2.out with eq_2_group {
seq {
invoke queue_l[ans=ans, err=err](cmd=cmd, value=value)();
if neq_9.out with neq_9_group {
seq {
lower_err;
invoke queue_r[ans=ans, err=err](cmd=cmd, value=value)();
}
} else {
hot_not_group;
}
}
} else {
seq {
invoke queue_r[ans=ans, err=err](cmd=cmd, value=value)();
if neq_9.out with neq_9_group {
seq {
lower_err;
invoke queue_l[ans=ans, err=err](cmd=cmd, value=value)();
}
} else {
hot_not_group;
}
}
}
len_decr_group;
}
}
}
if eq_6.out with eq_6_group {
if eq_3.out with eq_3_group {
par {
raise_err;
flash_ans;
}
} else {
seq {
lower_err;
if eq_2.out with eq_2_group {
seq {
invoke queue_l[ans=ans, err=err](cmd=cmd, value=value)();
if neq_9.out with neq_9_group {
seq {
lower_err;
invoke queue_r[ans=ans, err=err](cmd=cmd, value=value)();
}
}
}
} else {
seq {
invoke queue_r[ans=ans, err=err](cmd=cmd, value=value)();
if neq_9.out with neq_9_group {
seq {
lower_err;
invoke queue_l[ans=ans, err=err](cmd=cmd, value=value)();
}
}
}
}
}
}
}
if eq_7.out with eq_7_group {
if eq_4.out with eq_4_group {
par {
raise_err;
flash_ans;
}
} else {
seq {
lower_err;
infer_flow;
if flow.out {
invoke queue_r[ans=ans, err=err](cmd=cmd, value=value)();
} else {
invoke queue_l[ans=ans, err=err](cmd=cmd, value=value)();
}
if eq_8.out with eq_8_group {
len_incr_group;
}
}
}
}
}
}
}
component main() -> () {
cells {
dataplane = dataplane();
has_ans = std_reg(1);
dataplane_ans = std_reg(32);
dataplane_err = std_reg(1);
@external commands = seq_mem_d1(2, 20000, 32);
@external values = seq_mem_d1(32, 20000, 32);
@external ans_mem = seq_mem_d1(32, 20000, 32);
neq_1 = std_neq(32);
j = std_reg(32);
j_incr = std_add(32);
not_2 = std_not(1);
}
wires {
comb group neq_1_group {
neq_1.left = dataplane_ans.out;
neq_1.right = 32'd0;
}
group j_incr_group {
j_incr.left = j.out;
j_incr.right = 32'd1;
j.write_en = 1'd1;
j.in = j_incr.out;
j_incr_group[done] = j.done;
}
group write_ans {
ans_mem.addr0 = j.out;
ans_mem.write_en = 1'd1;
ans_mem.write_data = dataplane_ans.out;
write_ans[done] = ans_mem.write_done;
}
group lower_has_ans {
has_ans.in = 1'd0;
has_ans.write_en = 1'd1;
lower_has_ans[done] = has_ans.done;
}
comb group not_2_group {
not_2.in = dataplane_err.out;
}
}
control {
while not_2.out with not_2_group {
seq {
lower_has_ans;
invoke dataplane[commands=commands, values=values, has_ans=has_ans, component_ans=dataplane_ans, component_err=dataplane_err]()();
if has_ans.out {
if neq_1.out with neq_1_group {
seq {
write_ans;
j_incr_group;
}
}
}
}
}
}
}
component dataplane() -> () {
cells {
myqueue = pifo();
ref commands = seq_mem_d1(2, 20000, 32);
ref values = seq_mem_d1(32, 20000, 32);
ref has_ans = std_reg(1);
ref component_ans = std_reg(32);
ref component_err = std_reg(1);
i = std_reg(32);
command = std_reg(2);
value = std_reg(32);
i_incr = std_add(32);
le_1 = std_le(2);
not_2 = std_not(1);
i_eq_MAX_CMDS = std_eq(32);
}
wires {
group i_incr_group {
i_incr.left = i.out;
i_incr.right = 32'd1;
i.write_en = 1'd1;
i.in = i_incr.out;
i_incr_group[done] = i.done;
}
comb group le_1_group {
le_1.left = command.out;
le_1.right = 2'd1;
}
group read_cmd_phase1 {
commands.addr0 = i.out;
commands.read_en = 1'd1;
read_cmd_phase1[done] = commands.read_done;
}
group write_cmd_phase2 {
command.write_en = 1'd1;
command.in = commands.read_data;
write_cmd_phase2[done] = command.done;
}
group read_value {
values.addr0 = i.out;
values.read_en = 1'd1;
read_value[done] = values.read_done;
}
group write_value_to_reg {
value.write_en = 1'd1;
value.in = values.read_data;
write_value_to_reg[done] = value.done;
}
group raise_has_ans {
has_ans.in = 1'd1;
has_ans.write_en = 1'd1;
raise_has_ans[done] = has_ans.done;
}
group lower_has_ans {
has_ans.in = 1'd0;
has_ans.write_en = 1'd1;
lower_has_ans[done] = has_ans.done;
}
comb group not_2_group {
not_2.in = component_err.out;
}
group i_eq_MAX_CMDS_group {
i_eq_MAX_CMDS.left = i.out;
i_eq_MAX_CMDS.right = 32'd20000;
component_err.write_en = 1'd1;
component_err.in = i_eq_MAX_CMDS.out;
i_eq_MAX_CMDS_group[done] = component_err.done;
}
}
control {
seq {
read_cmd_phase1;
write_cmd_phase2;
read_value;
write_value_to_reg;
invoke myqueue[ans=component_ans, err=component_err](cmd=command.out, value=value.out)();
if not_2.out with not_2_group {
seq {
if le_1.out with le_1_group {
raise_has_ans;
} else {
lower_has_ans;
}
}
}
i_incr_group;
i_eq_MAX_CMDS_group;
}
}
}