File: semExtra.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 (517 lines) | stat: -rw-r--r-- 15,753 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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
(****************************************************************************)
(*                           the diy toolsuite                              *)
(*                                                                          *)
(* Jade Alglave, University College London, UK.                             *)
(* Luc Maranget, INRIA Paris-Rocquencourt, France.                          *)
(*                                                                          *)
(* Copyright 2010-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.            *)
(****************************************************************************)

(** Centralized definition for types to be included by the XXXSem *)

(* Some configuration *)
module type Config = sig
  val verbose : int
  val optace : OptAce.t
  val debug : Debug_herd.t
  val fault_handling : Fault.Handling.t
  val mte_precision : Precision.t
  val variant : Variant.t -> bool
  val endian : Endian.t option
  val unroll : int option
  module PC : PrettyConf.S
end


module type S = sig
  module O : Config (* Options, for Sem consumer *)
  module A   : Arch_herd.S
  module E : Event.S with module A = A and module Act.A = A
  module M  : Monad.S
  with module A = A and module E = E and type evt_struct = E.event_structure
  module Cons : Constraints.S with module A = A

(* Report some flags *)
  val do_deps : bool
(* A good place to (re)define all these types *)
  type cst = A.V.Cst.v
  type v = A.V.v
  type proc = A.proc
  type instruction = A.instruction
  type global_loc = A.global_loc
  type location = A.location
  type state = A.state
  type final_state = A.final_state
  type program = A.program

  type prop = A.prop

  type constr = A.constr

  type nice_prog = A.nice_prog
  type start_points = A.start_points
  type code_segment = A.code_segment
  type entry_points = A.entry_points

  type proc_info = Test_herd.proc_info
  type test =
      (program, nice_prog, start_points, code_segment, entry_points,
       state, A.size_env, A.type_env,
       prop, location, A.RLocSet.t, A.FaultAtomSet.t) Test_herd.t

  val size_env : test -> A.size_env
  val type_env : test -> A.type_env

(* Get sets of locations observed in outcomes *)
  type loc_set = A.LocSet.t
  type rloc_set = A.RLocSet.t
  val observed_rlocations : test -> rloc_set

(* Notice, array rlocations  are expanded to the locations of
   their elements *)
  val observed_locations : test -> loc_set
  val displayed_rlocations : test -> rloc_set
  val is_non_mixed_symbol : test -> Constant.symbol -> bool

(* "Exported" labels, i.e. labels that can find their way to registers *)
  (* In initial state *)
  val get_exported_labels_init : test -> Label.Full.Set.t
  (* In code *)
  val get_exported_labels_code : test -> Label.Full.Set.t
  (* Both of them *)
  val get_exported_labels : test -> Label.Full.Set.t

  type event = E.event
  type event_structure = E.event_structure
  type event_set = E.EventSet.t
  type event_rel = E.EventRel.t

  (* Abreviations *)
  val tr : event_rel -> event_rel
  val rt : event_rel -> event_rel
  val restrict :
      (event -> bool) -> (event -> bool) ->
        event_rel -> event_rel
  val doWW : event_rel -> event_rel
  val doWR : event_rel -> event_rel
  val doRR : event_rel -> event_rel
  val doRW : event_rel -> event_rel

  val seq : event_rel -> event_rel -> event_rel
  val seqs : event_rel list -> event_rel
  val union : event_rel -> event_rel -> event_rel
  val union3 : event_rel -> event_rel -> event_rel -> event_rel
  val unions : event_rel list -> event_rel

  (* relations packed to be shown on graphs *)
  type rel_pp = (string * event_rel) list
  type set_pp = event_set StringMap.t

  (* Dependencies : ie complement for ace *)
  type procrels =
      { addr : event_rel;
        data : event_rel;
        depend : event_rel;
        data_commit : event_rel;
        ctrl : event_rel;
        ctrlisync : event_rel;
        success : event_rel;
        rf : event_rel;
        tst: event_rel; }

(*********)
(* RFMap *)
(*********)

 type write_to =
   | Final of location
   | Load of event

 type read_from =
    | Init
    | Store of event


  val write_to_compare : write_to -> write_to -> int
  val read_from_compare : read_from -> read_from -> int
  val read_from_equal : read_from -> read_from -> bool
  val event_rf_equal : event -> read_from -> bool

  module RFMap : Map.S with type key = write_to

  type rfmap = read_from RFMap.t

(* For pretty print, string arg is like the one of String.concat *)
  val pp_rfmap :
      out_channel -> string ->
        (out_channel -> write_to -> read_from -> unit) ->
          rfmap ->  unit

  val for_all_in_rfmap : (write_to -> read_from -> bool) -> rfmap -> bool

  val simplify_vars_in_rfmap : A.V.solution -> rfmap -> rfmap

(**************************************)
(* Complete, concrete event structure *)
(**************************************)


type concrete =
    {
     str   : event_structure ; (* event structure proper *)
     rfmap : rfmap ;           (* rfmap *)
     fs    : state * A.FaultSet.t ;           (* final state *)
     po  : event_rel ;         (* program order (in fact po + iico) *)
     partial_po : event_rel ;
     pos : event_rel ;         (* Same location same processor accesses *)
(* Write serialization precursor ie uniproc induced constraints over writes *)
     pco : event_rel ;
(* View before relation deduced from rfmaps *)
     store_load_vbf : event_rel ; (* stores preceed their loads *)
     init_load_vbf : event_rel;   (* load from init preceed all stores *)
     last_store_vbf : event_rel;  (* stores to final state come last *)
     atomic_load_store : event_rel; (* eg load-and-link/store conditional *)
    }

  val conc_zero : concrete

(************)
(* Branches *)
(************)
  module B : Branch.S
  with type reg = A.reg and type v = v and type 'a monad = 'a M.t
  type branch = B.t

  val tgt2tgt : A.inst_instance_id -> BranchTarget.t -> B.tgt
  val tgt2offset : A.inst_instance_id -> BranchTarget.t -> int

  val find_cutoff : E.EventSet.t -> string option

(************)
(* Barriers *)
(************)

(* barrier + cumulativity *)
  type barrier = A.barrier
  type pp_barrier = { barrier:barrier ; pp:string; }

end

module Make(C:Config) (A:Arch_herd.S) (Act:Action.S with module A = A)
       : (S with module A = A and module E.Act = Act) =
  struct
    module O = C
    module A = A
    module V = A.V
    module E = Event.Make(C)(A)(Act)

    module CEM = struct (* Configure event monads *)
      let hexa =  C.PC.hexa
      let debug = C.debug
      let variant = C.variant
    end

    module M = EventsMonad.Make(CEM)(A)(E)
    module Cons = Constraints.Make (C.PC)(A)

    let do_deps = C.variant Variant.Deps

(* A good place to (re)define all these types *)
    type cst = A.V.Cst.v
    type v = A.V.v
    type proc = A.proc
    type instruction = A.instruction
    type global_loc = A.global_loc
    type location = A.location
    type state = A.state
    type final_state = A.final_state

    type prop = A.prop
    type constr = A.constr

    type program = A.program
    type nice_prog = A.nice_prog
    type start_points = A.start_points
    type code_segment = A.code_segment
    type entry_points = A.entry_points

    type proc_info = Test_herd.proc_info
    type test =
      (program, nice_prog, start_points, code_segment, entry_points, state,
       A.size_env, A.type_env,
       prop, location, A.RLocSet.t, A.FaultAtomSet.t) Test_herd.t

    let size_env t =  t.Test_herd.size_env
    and type_env t = t.Test_herd.type_env

(* Sets of relevant location *)
    type loc_set = A.LocSet.t
    type rloc_set = A.RLocSet.t

    let loc_of_rloc test rloc k =
      let locs = A.locs_of_rloc (type_env test) rloc in
      A.LocSet.union (A.LocSet.of_list locs) k

    let locs_of_rlocs test rlocs =
      A.RLocSet.fold
        (fun rloc k -> loc_of_rloc test rloc k)
        rlocs A.LocSet.empty

    let observed_rlocations t = t.Test_herd.observed

    let observed_locations t = locs_of_rlocs t (observed_rlocations t)

    let displayed_rlocations t = t.Test_herd.displayed

    let is_non_mixed_offset test s o = match o with
      | 0 -> true
      | _ ->
          o > 0 &&
            begin
              let sym0 = Constant.mk_sym_virtual s in
              let loc0 = A.Location_global (A.V.Val sym0) in
              let t = A.look_type (type_env test) loc0 in
              let open TestType in
              match t with
              | TyArray (t,sz) ->
                  let sz_elt = MachSize.nbytes (A.size_of_t t) in
                  o mod sz_elt = 0 && o < sz*sz_elt
              | _ -> false
            end
    let is_non_mixed_symbol_virtual test sym =
      let open Constant in
      match sym.offset with
      | 0 -> true
      | o -> is_non_mixed_offset test sym.name o

    let is_non_mixed_symbol test sym =
      let open Constant in
      match sym with
      | Virtual sd -> is_non_mixed_symbol_virtual test sd
      | Physical (s,o) -> is_non_mixed_offset test s o
      | TagAddr _
      | System ((PTE|PTE2|TLB),_)  -> true

(* Exported labels:
 *  1. Labels from init environments
 *  2. Labels from instructions that transfer labels into regs.
 *)

    let get_exported_labels_init test =
      let { Test_herd.init_state=st; _ } = test in
      A.state_fold
        (fun _ v k ->
          match v with
          | V.Val cst ->
              begin
                match Constant.as_label cst with
                | Some lbl -> Label.Full.Set.add lbl k
                | None -> k
              end
          | V.Var _ -> k)
        st Label.Full.Set.empty

    module AU = ArchUtils.Make(A)(V.Cst.Instr)

    let get_exported_labels_code test =
      let { Test_herd.nice_prog=prog; _ } = test in
      AU.get_exported_labels_code prog

    let get_exported_labels test =
      Label.Full.Set.union
        (get_exported_labels_init test)
        (get_exported_labels_code test)


(**********)
(* Events *)
(**********)

    type event = E.event

    let event_compare = E.event_compare

    type event_set = E.EventSet.t

    type event_structure = E.event_structure

    type event_rel = E.EventRel.t
  (* Abreviations *)
    let tr = E.EventRel.transitive_closure
    let rt = E.EventRel.remove_transitive_edges
    let restrict = E.EventRel.restrict_domains
    let doRR = restrict E.is_mem_load E.is_mem_load
    let doRW = restrict E.is_mem_load E.is_mem_store
    let doWW = restrict E.is_mem_store E.is_mem_store
    let doWR = restrict E.is_mem_store E.is_mem_load
    let seq = E.EventRel.sequence
    let seqs =  E.EventRel.sequences
    let union = E.EventRel.union
    let union3 = E.EventRel.union3
    let unions = E.EventRel.unions

 (* relations packed to be shown on graphs *)
    type rel_pp = (string * event_rel) list
    type set_pp = event_set StringMap.t

  (* Dependencies : ie complement for ace *)
  type procrels =
      { addr : event_rel;
        data : event_rel;
        depend : event_rel;
        data_commit : event_rel;
        ctrl : event_rel;
        ctrlisync : event_rel;
        success : event_rel;
        rf : event_rel;
        tst : event_rel; }

(* Read-From maps exploitation *)
    type write_to =
      | Final of location
      | Load of event

    type read_from =
      | Init
      | Store of event

    let write_to_compare wt1 wt2 =  match wt1,wt2 with
    | Final loc1, Final loc2 -> A.location_compare loc1 loc2
    | Final _, Load _ -> -1
    | Load _,Final _  -> 1
    | Load e1, Load e2 -> event_compare e1 e2

    let read_from_compare rf1 rf2 =  match rf1,rf2 with
    | Init, Init -> 0
    | Init, Store _ -> -1
    | Store _,Init  -> 1
    | Store e1, Store e2 -> event_compare e1 e2

    let read_from_equal rf1 rf2 = read_from_compare rf1 rf2 = 0

    let event_rf_equal e rf = match rf with
    | Init -> false
    | Store e' -> E.event_equal e e'

    module RFMap =
      Map.Make
        (struct
          type t = write_to
          let compare = write_to_compare
        end)

    type rfmap = read_from RFMap.t

    let pp_rfmap chan delim pp rfm =
      let first = ref true in
      RFMap.iter
        (fun wt rf ->
          if not !first then output_string chan delim
          else first := false ;
          pp chan wt rf)
        rfm

    let for_all_in_rfmap pred rfm =
      RFMap.fold
        (fun wt rf k -> pred wt rf && k)
        rfm true

    let simplify_rf solns = function
      | Init -> Init
      | Store e -> Store (E.simplify_vars_in_event solns e)
    and simplify_wt solns = function
      | Final loc -> Final (A.simplify_vars_in_loc solns loc)
      | Load e -> Load (E.simplify_vars_in_event solns e)

    let simplify_vars_in_rfmap solns rfm =
      if V.Solution.is_empty solns then rfm
      else
        RFMap.fold
          (fun wt rf k ->
            RFMap.add
              (simplify_wt solns wt)
              (simplify_rf solns rf)
              k)
          rfm RFMap.empty

(**************************************)
(* Complete, concrete event structure *)
(**************************************)
type concrete =
    {
     str   : event_structure ; (* event structure proper *)
     rfmap : rfmap ;           (* rfmap *)
     fs    : state * A.FaultSet.t ;           (* final state *)
     po : event_rel ;
     partial_po : event_rel ;
     pos : event_rel ;      (* Same location same processor accesses *)
     pco : event_rel ;
(* View before relation deduced from rfmaps *)
     store_load_vbf : event_rel ; (* stores preceed their loads *)
     init_load_vbf : event_rel;   (* load from init preceed all stores *)
     last_store_vbf : event_rel;  (* stores to final state come last *)
     atomic_load_store : event_rel; (* eg load-and-link/store conditional *)
    }

    let conc_zero =
      {
       str = E.empty_event_structure ;
       rfmap = RFMap.empty ;
       fs = A.state_empty,A.FaultSet.empty;
       partial_po = E.EventRel.empty;
       po = E.EventRel.empty ;
       pos = E.EventRel.empty ;
       pco = E.EventRel.empty ;
       store_load_vbf  = E.EventRel.empty ;
       init_load_vbf = E.EventRel.empty ;
       last_store_vbf = E.EventRel.empty ;
       atomic_load_store = E.EventRel.empty ;
     }
(************)
(* Branches *)
(************)
    module B = Branch.Make(M)
    type branch = B.t

    let tgt2tgt ii = function
      | BranchTarget.Lbl lbl -> B.Lbl lbl
      | BranchTarget.Offset o -> B.Addr (ii.A.addr + o)

    let tgt2offset ii = function
      | BranchTarget.Offset o -> o
      | BranchTarget.Lbl lbl ->
         let b =
           try Label.Map.find lbl ii.A.lbl2addr
           with Not_found -> assert false in
         b-ii.A.addr

    let find_cutoff es =
      Option.bind (E.EventSet.find_opt E.is_cutoff es) E.as_cutoff

(************)
(* Barriers *)
(************)

    type barrier = A.barrier

    type pp_barrier = { barrier:barrier ; pp:string; }

  end

module ConfigToArchConfig(C:Config) : ArchExtra_herd.Config =
  struct
    let verbose = C.verbose
    let texmacros = C.PC.texmacros
    let hexa = C.PC.hexa
    let brackets = C.PC.brackets
    let variant = C.variant
    let endian = C.endian
    let default_to_symb = false
  end