File: BellSem.ml

package info (click to toggle)
herdtools7 7.58-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 19,732 kB
  • sloc: ml: 128,583; ansic: 3,827; makefile: 670; python: 407; sh: 212; awk: 14
file content (190 lines) | stat: -rw-r--r-- 7,125 bytes parent folder | download
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
179
180
181
182
183
184
185
186
187
188
189
190
(****************************************************************************)
(*                           the diy toolsuite                              *)
(*                                                                          *)
(* Jade Alglave, University College London, UK.                             *)
(* Luc Maranget, INRIA Paris-Rocquencourt, France.                          *)
(*                                                                          *)
(* Copyright 2013-present Institut National de Recherche en Informatique et *)
(* en Automatique and the authors. All rights reserved.                     *)
(*                                                                          *)
(* This software is governed by the CeCILL-B license under French law and   *)
(* abiding by the rules of distribution of free software. You can use,      *)
(* modify and/ or redistribute the software under the terms of the CeCILL-B *)
(* license as circulated by CEA, CNRS and INRIA at the following URL        *)
(* "http://www.cecill.info". We also give a copy in LICENSE.txt.            *)
(****************************************************************************)

(** Semantics of Bell *)

module
  Make
    (C:Sem.Config)
    (V:Value.S with type Cst.Instr.t = BellBase.instruction)
    =
  struct
    module Bell = BellArch_herd.Make(SemExtra.ConfigToArchConfig(C))(V)
    module Act = BellAction.Make(Bell)
    include SemExtra.Make(C)(Bell)(Act)

    let compat = C.variant Variant.BackCompat

(* Not doing barrier pretty print *)
    let barriers = []
    let isync = None

(* Simple size *)
    let reg_sz = V.Cst.Scalar.machsize
    and nat_sz = V.Cst.Scalar.machsize

    let atomic_pair_allowed _ _ = true

(****************************)
(* Build semantics function *)
(****************************)

    module Mixed(SZ : ByteSize.S) = struct

      let (>>=) = M.(>>=)
      let (>>*=) = M.(>>*=)
      let (>>|) = M.(>>|)
      let (>>::) = M.(>>::)
      let (>>!) = M.(>>!)

      let mk_read sz ato s loc v = Act.Access (Dir.R, loc, v, ato, s, sz)

      let read_reg is_data ?(stack=[]) r ii =
        try
          let v = List.assoc r stack in (M.unitT v)
        with Not_found ->
          M.read_loc is_data (mk_read reg_sz false []) (A.Location_reg (ii.A.proc,r)) ii

      let read_reg_ord = read_reg false
      and read_reg_data = read_reg true

      let read_mem sz a s ii =
        M.read_loc false (mk_read sz false s) (A.Location_global a) ii

      let read_mem_atom sz a s ii =
        M.read_loc false (mk_read sz true s) (A.Location_global a) ii


(*    let read_mem_atom cop a ii =
      M.read_loc (mk_read true cop) (A.Location_global a) ii *)

      let write_reg r v ii =
        M.mk_singleton_es (Act.Access (Dir.W, (A.Location_reg (ii.A.proc,r)), v, false, [], reg_sz)) ii

      let write_mem sz a v s ii =
        M.mk_singleton_es (Act.Access (Dir.W, A.Location_global a, v, false, s, sz)) ii

      let write_mem_atom sz a v s ii =
        M.mk_singleton_es (Act.Access (Dir.W, A.Location_global a, v, true, s, sz)) ii


      let commit ii =  M.mk_singleton_es (Act.Commit) ii


      let create_barrier b o ii =
        M.mk_singleton_es (Act.Barrier(b,o)) ii

      let read_roa is_data ?(stack=[]) roa ii =
        match roa with
        | BellBase.Rega r -> read_reg is_data ~stack:stack r ii
        | BellBase.Abs a -> (M.unitT (V.nameToV a))

      let read_roi is_data roi ii =
        match roi with
        | BellBase.Regi r -> read_reg is_data r ii
        | BellBase.Imm i -> (M.unitT (V.intToV i))

      let read_iar is_data ?(stack=[]) roi ii =
        match roi with
        | BellBase.IAR_roa roa -> read_roa is_data ~stack:stack roa ii
        | BellBase.IAR_imm i -> (M.unitT (V.intToV i))

      let solve_addr_op ao ii = match ao with
      | BellBase.Addr_op_atom roa -> read_roa false roa ii
      | BellBase.Addr_op_add(roa,roi) ->
          (read_roa false roa ii >>|
          read_roi false roi ii) >>=
          (fun (v1,v2) -> M.op Op.Add v1 v2)

      let tr_op ?(stack=[]) ii = function
        | BellBase.OP(bell_op,x,y) ->
            let op = match bell_op with
            | BellBase.Xor -> Op.Xor
            | BellBase.Add -> Op.Add
            | BellBase.And -> Op.And
            | BellBase.Eq -> Op.Eq
            | BellBase.Neq -> Op.Ne
            in
            ((read_iar false ~stack:stack x ii) >>| (read_iar false ~stack:stack y ii)) >>=
            (fun (v1,v2) -> M.op op v1 v2)
        | BellBase.RAI(i) -> (read_iar false ~stack:stack i ii)

      let tr_mov r op ii =
        (tr_op ii op) >>= (fun v -> write_reg r v ii)

      let build_semantics _ ii =
        let build_semantics_inner ii =
          match ii.A.inst with
          | BellBase.Pnop -> B.nextT
          | BellBase.Pld(r,addr_op,[("deref"|"lderef")]) when compat ->
              solve_addr_op addr_op ii >>=
              fun addr -> read_mem nat_sz addr ["once"] ii >>=
                fun v -> write_reg r v ii >>*=
                  fun () -> create_barrier ["rb_dep"] None ii >>= B.next1T
          | BellBase.Pld(r,addr_op,s) ->
              solve_addr_op addr_op ii >>=
              (fun addr -> read_mem nat_sz addr s ii) >>=
              (fun v -> write_reg r v ii) >>= B.next1T

          | BellBase.Pst(addr_op, roi, s) ->
              let s = match s with
              | ["assign"] when compat -> ["release"]
              | _ -> s in
              (solve_addr_op addr_op ii >>| read_roi true roi ii)
              >>= fun (addr,v) -> write_mem nat_sz addr v s ii
              >>= B.next1T


          | BellBase.Pfence(BellBase.Fence (s,o)) ->
              create_barrier s o ii >>= B.next1T

          | BellBase.Pcall _ ->
              Warn.fatal "Obsolete 'call' instruction in BellSem\n"

          | BellBase.Prmw(r,op,addr_op,s) ->
              let rloc = solve_addr_op addr_op ii in
              if BellBase.r_in_op r op then
                rloc >>=
                (fun x -> (read_mem_atom nat_sz x s ii) >>=
                  (fun v_read ->
                    (tr_op ~stack:[(r,v_read)] ii op) >>=
                      (fun v ->
                        write_reg r v_read ii >>|
                          write_mem_atom nat_sz x v s ii)))
                >>= fun ((),()) -> B.nextT
              else begin
                rloc >>=
                (fun x ->
                  let r1 = read_mem_atom nat_sz x s ii
                  and r2 = tr_op ii op
                  and w1 = fun v -> write_mem_atom nat_sz x v s ii
                  and w2 = fun v -> write_reg r v ii in
                  M.exch r1 r2 w1 w2) >>= fun ((),()) -> B.nextT
              end
          | BellBase.Pbranch(Some r,lbl,_) ->
              (read_reg false r ii) >>=
              (fun v -> commit ii >>= fun () -> B.bccT v lbl)

          | BellBase.Pbranch(None ,lbl,_) ->  B.branchT lbl

          | BellBase.Pmov(r,op) ->
              (tr_mov r op ii) >>= B.next1T

        in
        M.addT (A.next_po_index ii.A.program_order_index) (build_semantics_inner ii)
      let spurious_setaf _ = assert false
    end
  end