Source file cyclesim_combine.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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
open Base
open Cyclesim0
module Combine_error = struct
type t =
{ cycle_no : int
; clock_edge : Side.t
; port_name : string
; value0 : Bits.t
; value1 : Bits.t
}
[@@deriving sexp_of]
end
let default_on_error error =
raise_s
[%message "[Cyclesim.combine] output port values differ" (error : Combine_error.t)]
;;
let combine
?(port_sets_may_differ = false)
?(on_error = default_on_error)
(s0 : _ t)
(s1 : _ t)
=
let si =
Set.to_list
(List.fold
(s0.in_ports @ s1.in_ports)
~init:(Set.empty (module String))
~f:(fun s (n, _) -> Set.add s n))
in
let out_port_set =
Set.to_list
(List.fold
(s0.out_ports_before_clock_edge @ s1.out_ports_before_clock_edge)
~init:(Set.empty (module String))
~f:(fun s (n, _) -> Set.add s n))
in
let try_find n s =
try Some (List.Assoc.find_exn s ~equal:String.equal n) with
| _ -> None
in
let _, copy_in_ports =
let l =
List.map si ~f:(fun n ->
match try_find n s0.in_ports, try_find n s1.in_ports with
| Some x, Some y -> (n, x), fun () -> y := !x
| Some x, None when port_sets_may_differ -> (n, x), fun () -> ()
| None, Some y when port_sets_may_differ -> (n, y), fun () -> ()
| _ -> raise_s [%message "Input port was not found" ~name:(n : string)])
in
List.map l ~f:fst, List.map l ~f:snd
in
let cycle_no = ref 0 in
let check edge n x y =
if not (Bits.equal !x !y)
then
on_error
{ Combine_error.cycle_no = !cycle_no
; clock_edge = edge
; port_name = n
; value0 = !x
; value1 = !y
}
in
let associate_and_check_out_ports edge out_ports =
let l =
List.map out_port_set ~f:(fun n ->
match try_find n (out_ports s0), try_find n (out_ports s1) with
| Some x, Some y -> (n, x), fun () -> check edge n x y
| Some x, None when port_sets_may_differ -> (n, x), fun () -> ()
| None, Some y when port_sets_may_differ -> (n, y), fun () -> ()
| _ -> raise_s [%message "Output port was not found" ~name:(n : string)])
in
List.map l ~f:fst, List.map l ~f:snd
in
let _, check_out_ports_after_clock_edge =
associate_and_check_out_ports After Cyclesim0.out_ports_after_clock_edge
and _, check_out_ports_before_clock_edge =
associate_and_check_out_ports Before Cyclesim0.out_ports_before_clock_edge
in
let copy_in_ports () = List.iter copy_in_ports ~f:(fun f -> f ()) in
let check_out_ports () =
List.iter check_out_ports_before_clock_edge ~f:(fun f -> f ());
List.iter check_out_ports_after_clock_edge ~f:(fun f -> f ())
in
let incr_cycle () = Int.incr cycle_no in
let cycle_check () =
s0.cycle_check ();
copy_in_ports ();
s1.cycle_check ()
in
let cycle_before_clock_edge () =
s0.cycle_before_clock_edge ();
s1.cycle_before_clock_edge ()
in
let cycle_at_clock_edge () =
s0.cycle_at_clock_edge ();
s1.cycle_at_clock_edge ()
in
let cycle_after_clock_edge () =
s0.cycle_after_clock_edge ();
s1.cycle_after_clock_edge ();
check_out_ports ();
incr_cycle ()
in
let reset () =
s0.reset ();
s1.reset ()
in
{ s0 with
reset
; cycle_check
; cycle_before_clock_edge
; cycle_at_clock_edge
; cycle_after_clock_edge
}
;;