Source file vec.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
open Base
open Hardcaml
open Signal

module type Arg = Vec_intf.Arg
module type S = Vec_intf.S

let noop (type a) (module S : Comb.S with type t = a) : a = S.of_string "00"
let insert (type a) (module S : Comb.S with type t = a) : a = S.of_string "10"
let remove (type a) (module S : Comb.S with type t = a) : a = S.of_string "11"

module Make (Arg : Arg) = struct
  type t =
    { vec_size : int
    ; regs : Signal.t Arg.Interface.t array
    }
  [@@deriving fields ~getters]

  type op =
    { slot : Signal.t
    ; op : Signal.t
    ; insert_data : Signal.t Arg.Interface.t
    ; delete_data : Signal.t Arg.Interface.t
    }

  let create spec ~vec_size ~next op =
    let do_insert = op.op ==: insert (module Signal) in
    let do_remove = op.op ==: remove (module Signal) in
    let reg_wires = Array.init vec_size ~f:(fun _ -> Arg.Interface.Of_signal.wires ()) in
    let regs =
      Array.init vec_size ~f:(fun index ->
        Arg.Interface.map2 (Arg.spec ~index spec) reg_wires.(index) ~f:(reg ~enable:vdd))
    in
    let op_index_1h = binary_to_onehot op.slot in
    let shifted_up =
      Array.init vec_size ~f:(fun index ->
        if index = 0 then regs.(0) else regs.(index - 1))
    in
    let shifted_down =
      Array.init vec_size ~f:(fun index ->
        if index = vec_size - 1 then op.delete_data else regs.(index + 1))
    in
    let shift = log_shift sll (ones vec_size) op.slot in
    for index = 0 to vec_size - 1 do
      let shift = shift.:(index) in
      Arg.Interface.iter2
        reg_wires.(index)
        (let mux2 = Arg.Interface.Of_signal.mux2 in
         mux2
           (do_insert &: shift)
           (mux2 op_index_1h.:(index) op.insert_data shifted_up.(index))
           (mux2 (do_remove &: shift) shifted_down.(index) (next ~index regs.(index))))
        ~f:( <== )
    done;
    { vec_size; regs }
  ;;

  let get t ~index = t.regs.(index)
  let read_mux t ~index = Arg.Interface.Of_signal.mux index (Array.to_list t.regs)
end