package hardcaml_axi

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
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 =
        match slaves with
        | [ hd ] -> hd
        | _ -> Slave_to_master.Of_signal.mux (Option.value_exn 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)
      =
      (* get address selection bits *)
      let address = master.address in
      let address_bits = Int.ceil_log2 (List.length slaves) in
      let slave_index =
        match address_bits with
        | 0 -> None
        | _ -> Some (select address (address_offset + address_bits - 1) address_offset)
      in
      let address_out_of_range =
        let top_bits = address_offset + address_bits in
        if width address <= top_bits then gnd else drop_bottom address top_bits <>:. 0
      in
      (* mux slave to master interfaces *)
      let slave = mux_and_register_slaves ?reg_spec ~slave_index ~slaves () in
      let masters =
        List.map
          (bits_lsb
             ((match slave_index with
               | None -> vdd
               | Some slave_index -> binary_to_onehot slave_index)
              &: ~:(repeat address_out_of_range (1 lsl address_bits))))
          ~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 =
                uresize
                  (sel_bottom master.address address_offset)
                  Master_to_slave.addr_bits
            ; write_data = master.write_data
            ; write_byte_en = master.write_byte_en
            })
      in
      (* We create [ceil_pow2 number_of_slaves] masters above by mapping over the onehot
         representation of the [slave_index]. This ensures there are equal numbers of
         slave and master interfaces. *)
      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
      }
    ;;

    (* return the interface for the new slave *)
    let add_slave t =
      let slave = Slave_instance.create () in
      t.slave_instances <- slave :: t.slave_instances;
      (* added backwards *)
      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
        (* put into order added *)
        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
OCaml

Innovation. Community. Security.