calyx 0.7.1

Compiler Infrastructure for Hardware Accelerator Generation
import "primitives/core.futil";
import "primitives/memories/comb.futil";
import "primitives/sync.futil";

// Sum up all values from two arrays.
// Expected resolution order for arbitration:
// below we denote 1 is written to the synchronized register as 1W, and
// 6 is read from the synchronized register as 6R.
// 1W 1R 6W 6R 5W 5R 2W 2R 3W 3R 4W 4R 3W 3R 4W 4R 5W 5R 2W 2R 1W 1R 6W 6R
component main() -> () {
  cells {
    @external in_0 = comb_mem_d1(32, 6, 3);
    @external in_1 = comb_mem_d1(32, 6, 3);
    @external out = comb_mem_d1(32, 1, 3);
    lt = std_lt(3);
    sum = std_add(32);
    add = std_add(3);

    // Sync register used to communicate between threads
    imm = std_sync_reg(32);
    // Index of the input and output memory
    idx = std_reg(3);
    // temporary storage for partial sum
    temp = std_reg(32);
  }
  wires {
    group reg_init {
      temp.in = 32'd0;
      temp.write_en = 1'd1;
      reg_init[done] = temp.done;
    }

    // Write value from `in[idx]` to sync intermediate.
    group write_imm_0 {
      imm.write_en_0 = 1'd1;
      imm.in_0 = in_0.read_data;
      in_0.addr0 = idx.out;
      write_imm_0[done] = imm.write_done_0;
    }

    group write_imm_1 {
      imm.write_en_1 = 1'd1;
      imm.in_1 = in_1.read_data;
      in_1.addr0 = idx.out;
      write_imm_1[done] = imm.write_done_1;
    }

    // Read value from sync intermediate and write to temp.
    group read_imm {
      imm.read_en_0 = 1'd1;
      sum.left = imm.read_done_0 ? imm.out_0;
      sum.right = temp.out;
      temp.in = imm.read_done_0? sum.out;
      temp.write_en =  imm.read_done_0? 1'd1;
      read_imm[done] = temp.done;
    }

    group incr_idx {
      add.left = 3'd1;
      add.right = idx.out;
      idx.in = add.out;
      idx.write_en = 1'd1;
      incr_idx[done] = idx.done;
    }

    group reg_to_mem {
      out.write_en = 1'd1;
      out.write_data = temp.out;
      out.addr0 = 3'd0;
      reg_to_mem[done] = out.done;
    }

    comb group cmp {
      lt.left = idx.out;
      lt.right = 3'd6;
    }
  }
  control {
    seq {
      reg_init;
      while lt.out with cmp {
        seq {
          par {
            read_imm;
            write_imm_0;
            write_imm_1;
          }
          read_imm;
          incr_idx;
        }
      }
    reg_to_mem;
    }
  }
}