calyx 0.7.1

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

component mac(in: 32) -> (out: 32) {
  cells {
    add = std_add(32);
    r = std_reg(32);
  }
  wires {
    static<1> group a {
      add.left = r.out;
      add.right = in;
      r.in = add.out;
      r.write_en = 1'd1;
    }
    out = r.out;
  }
  control {
    a;
  }
}

component main () -> () {
  cells {
    my_mac = mac();
    acc = std_reg(32);
    adder = std_add(32);
    counter = std_reg(32);
    my_lt = std_lt(32);
    @external out = comb_mem_d1(32, 1, 1);

    dummy = std_reg(32);
  }
  wires {
    group mac_five {
      my_mac.go = 1'd1;
      my_mac.in = 32'd5;
      mac_five[done] = my_mac.done;
    }
    group write_mem {
      out.write_data = my_mac.out;
      out.addr0 = 1'd0;
      out.write_en = 1'd1;
      write_mem[done] = out.done;
    }
    group incr_counter {
      // Very dumb, but we don't want to infer this as promotable
      // and this effects the promotion heuristics ... bottom line,
      // we need to check both static and dynamic contexts
      dummy.in = 32'd2;
      dummy.write_en = 1'd1;

      adder.left = 32'd1;
      adder.right = counter.out;
      counter.in = adder.out;
      counter.write_en = 1'd1;
      incr_counter[done] = counter.done & dummy.done ? 1'd1;
    }
    my_lt.left = counter.out;
    my_lt.right = 32'd10;
  }

  control {
    repeat 10 {
      // Should be promoted to static
      mac_five;
    }
    while my_lt.out {
      seq {
        // Should not be promoted to static, use done signal
        mac_five;
        incr_counter;
      }
    }
    write_mem;
  }
}