Source file cyclesim_clock_domain.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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
open! Core0

module Name = struct
  module T = struct
    type t = string [@@deriving bin_io, compare ~localize, sexp, hash]
  end

  include T
  include Comparable.Make_plain (T)

  let of_string n = n
  let to_string n = n
end

type t =
  { name : Name.t
  ; period : int
  }
[@@deriving sexp_of, compare]

let create ~name ~period = { name; period }
let create_list ls = List.map ls ~f:(fun (name, period) -> create ~name ~period)
let aligned { period; _ } ~cycle = cycle mod period = 0

type domain = t [@@deriving sexp_of]

type indexed =
  { domain : domain
  ; index : int
  }
[@@deriving sexp_of, fields ~getters]

module Group = struct
  type t =
    { keys : indexed iarray
    ; map : indexed Name.Map.t
    ; size : int
    }
  [@@deriving sexp_of, fields ~getters]

  let create elements =
    let size = List.length elements in
    let keys = List.mapi elements ~f:(fun index domain -> { domain; index }) in
    match
      List.map keys ~f:(fun indexed -> indexed.domain.name, indexed)
      |> Map.of_alist (module Name)
    with
    | `Ok map -> `Ok { keys = Iarray.of_list keys; map; size }
    | `Duplicate_key key -> `Duplicate_key key
  ;;

  let create_exn elements =
    match create elements with
    | `Ok t -> t
    | `Duplicate_key key -> raise_s [%message "Duplicate key" (key : Name.t)]
  ;;

  let get t name = Map.find t.map name
  let elements t = t.keys
end

module Table = struct
  type 'a t = 'a array [@@deriving sexp_of]

  let create (group : Group.t) default = Array.create ~len:group.size default

  let init (group : Group.t) ~f =
    Array.init group.size ~f:(fun i -> f (Iarray.get group.keys i))
  ;;

  let set t ~key ~data = Array.set t key.index data
  let get t key = Array.get t key.index
  let map t ~f = Array.map t ~f
  let fold_map t ~init ~f = Array.fold_map t ~init ~f
  let fold t ~init ~f = Array.fold t ~init ~f
  let map_inplace t ~f = Array.map_inplace t ~f
  let iter t ~f = Array.iter t ~f
  let concat t = Array.to_list t |> Array.concat
end

module Set = struct
  type t =
    { keys : indexed iarray
    ; data : bool Table.t
    }
  [@@deriving sexp_of]

  let create group ~default =
    { keys = Group.keys group; data = Table.create group default }
  ;;

  let to_string t =
    Iarray.filter t.keys ~f:(fun key -> Table.get t.data key)
    |> Iarray.map ~f:(fun key -> key.domain.name)
    |> Iarray.to_list
    |> List.to_string ~f:Fn.id
  ;;

  let clear t = Array.map_inplace t.data ~f:(Fn.const false)
  let add t key = Table.set t.data ~key ~data:true
  let remove t key = Table.set t.data ~key ~data:false
  let mem t key = Table.get t.data key
  let iter (t : t) ~f = Iarray.iter t.keys ~f:(fun key -> if mem t key then f key)
end