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; } } }