Source file demultiplexer.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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
open Base
open Hardcaml
module type S = Demultiplexer_intf.S
module Make
(Master_to_slave : Internal_bus_ports.Master_to_slave)
(Slave_to_master : Internal_bus_ports.Slave_to_master) =
struct
open Signal
module Core = struct
type t =
(Signal.t Slave_to_master.t, Signal.t Master_to_slave.t list) Slave_with_data.t
let mux_and_register_slaves ?reg_spec ~slave_index ~slaves () =
let slave = Slave_to_master.Of_signal.mux slave_index slaves in
match reg_spec with
| None -> slave
| Some reg_spec ->
{ write_ready = reg reg_spec ~enable:vdd slave.write_ready
; read_ready = reg reg_spec ~enable:vdd slave.read_ready
; read_data = reg reg_spec ~enable:slave.read_ready slave.read_data
}
;;
let create
?reg_spec
_scope
~address_offset
~(master : Signal.t Master_to_slave.t)
~(slaves : Signal.t Slave_to_master.t list)
=
let address = master.address in
let address_bits = Int.ceil_log2 (List.length slaves) in
let slave_index =
select address (address_offset + address_bits - 1) address_offset
in
let slave = mux_and_register_slaves ?reg_spec ~slave_index ~slaves () in
let masters =
List.map
(bits_lsb (binary_to_onehot slave_index))
~f:(fun en ->
{ Master_to_slave.write_valid = master.write_valid &: en
; write_first = master.write_first &: en
; read_valid = master.read_valid &: en
; read_first = master.read_first &: en
; address = master.address
; write_data = master.write_data
; write_byte_en = master.write_byte_en
})
in
let masters = List.take masters (List.length slaves) in
{ Slave_with_data.slave; data = masters }
;;
end
module Builder = struct
module Slave_instance = struct
type t =
{ mutable master_is_set : bool
; master : Signal.t Master_to_slave.t
; mutable slave_is_set : bool
; slave : Signal.t Slave_to_master.t
}
let create () =
{ master_is_set = false
; master = Master_to_slave.Of_signal.wires ()
; slave_is_set = false
; slave = Slave_to_master.Of_signal.wires ()
}
;;
let get_master t = t.master
let set_master t master =
if t.master_is_set
then raise_s [%message "Slave_demultiplexer - master is already set"]
else (
Master_to_slave.iter2 t.master master ~f:Signal.( <== );
t.master_is_set <- true)
;;
let get_slave t = t.slave
let set_slave t slave =
if t.slave_is_set
then raise_s [%message "Slave_demultiplexer - slave is already set"]
else (
Slave_to_master.iter2 t.slave slave ~f:Signal.( <== );
t.slave_is_set <- true)
;;
end
type t =
{ mutable complete : bool
; log_size_in_bytes : int
; reg_spec : Reg_spec.t
; int_master : Signal.t Master_to_slave.t
; mutable slave_instances : Slave_instance.t list
; scope : Scope.t
}
let create scope ~log_size_in_bytes ~reg_spec ~int_master =
{ complete = false
; log_size_in_bytes
; reg_spec
; int_master
; slave_instances = []
; scope
}
;;
let add_slave t =
let slave = Slave_instance.create () in
t.slave_instances <- slave :: t.slave_instances;
slave
;;
let complete t =
if t.complete
then raise_s [%message "Slave_demultiplexer is already complete"]
else (
let slave_instances = List.rev t.slave_instances in
List.iteri slave_instances ~f:(fun index (slave_instance : Slave_instance.t) ->
if not slave_instance.slave_is_set
then
raise_s
[%message "Slave_demultiplexer - slave has not been set" (index : int)]);
t.complete <- true;
let ({ slave; data = masters } : Core.t) =
Core.create
t.scope
~reg_spec:t.reg_spec
~address_offset:t.log_size_in_bytes
~master:t.int_master
~slaves:(List.map slave_instances ~f:Slave_instance.get_slave)
in
List.iter2_exn slave_instances masters ~f:Slave_instance.set_master;
slave)
;;
let with_slave_demultiplexer scope ~log_size_in_bytes ~reg_spec ~int_master ~f =
let t = create scope ~log_size_in_bytes ~reg_spec ~int_master in
let result = f t in
let int_slave = complete t in
{ Slave_with_data.slave = int_slave; data = result }
;;
end
include Core
end