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
open Base
open Hardcaml
let wrap ?cfg sim =
let cycle = ref 0 in
let compare =
match cfg with
| None -> String.compare
| Some s ->
let f =
let s = List.mapi ~f:(fun i (n, _) -> n, i) s in
fun x -> List.Assoc.find s x ~equal:String.equal
in
fun a b ->
(match f a, f b with
| None, None -> String.compare a b
| Some _, None -> -1
| None, Some _ -> 1
| Some a, Some b -> Int.compare a b)
in
let get_type = function
| None -> fun _ -> Wave_format.Binary
| Some l ->
fun n ->
(try List.Assoc.find_exn l n ~equal:String.equal with
| _ -> Wave_format.Binary)
in
let port (n, v) =
match n with
| "clock" | "clk" -> Wave.Clock n, fun _ -> ()
| "reset" | "rst" ->
let d = Data.create 1 in
Wave.Binary (n, d), fun v -> Data.set d !cycle (if v then Bits.vdd else Bits.gnd)
| _ ->
let t = get_type cfg n in
let width = Bits.width !v in
let d = Data.create width in
let wave =
if width = 1 && Poly.equal t Binary
then Wave.Binary (n, d)
else Wave.Data (n, d, t, Left)
in
wave, fun _ -> Data.set d !cycle !v
in
let ports =
List.concat
[ List.map (Cyclesim.in_ports sim) ~f:port
; List.map (Cyclesim.out_ports ~clock_edge:Before sim) ~f:port
; List.map (Cyclesim.internal_ports sim) ~f:port
]
in
let ports =
List.sort
~compare:(fun (w0, _) (w1, _) -> compare (Wave.get_name w0) (Wave.get_name w1))
ports
in
let waves = Array.of_list (List.map ~f:fst ports) in
let updates = Array.of_list (List.map ~f:snd ports) in
let tasks rst () =
Array.iter ~f:(fun f -> f rst) updates;
Int.incr cycle
in
let sim =
Cyclesim.Private.modify
sim
[ After, Reset, tasks true; After, At_clock_edge, tasks false ]
in
sim, waves
;;