File: mixMerge.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 (192 lines) | stat: -rw-r--r-- 6,311 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
(****************************************************************************)
(*                           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.            *)
(****************************************************************************)

module Make(O:MixOption.S)(A:Arch_tools.S) : sig
  val merge : Name.t -> A.test -> Name.t -> A.test -> A.test
  val append : Name.t -> A.test -> Name.t -> A.test -> A.test
  val cat : Name.t -> A.test -> Name.t -> A.test -> A.test
end =
  struct

    open MiscParser
    module Alpha = Alpha.Make(O)(A)
    module MixPerm = MixPerm.Make(O)(A)


(* Merge of conditions *)
    open ConstrGen

    let or_cond c1 c2 = match c1,c2 with
    | ExistsState e1,ExistsState e2 -> ExistsState (Or [e1;e2])
    | ForallStates e1,ForallStates e2 -> ForallStates (Or [e1;e2])
    | NotExistsState e1,NotExistsState e2 -> NotExistsState (And [e1;e2])
    | _,_ ->
        let p1 = prop_of c1
        and p2 = prop_of c2 in
        ExistsState (Or [p1;p2])

    let and_cond c1 c2 = match c1,c2 with
    | ExistsState e1,ExistsState e2 -> ExistsState (And [e1;e2])
    | ForallStates e1,ForallStates e2 -> ForallStates (And [e1;e2])
    | NotExistsState e1,NotExistsState e2 -> NotExistsState (Or [e1;e2])
    | _,_ ->
        let p1 = prop_of c1
        and p2 = prop_of c2 in
        ExistsState (And [p1;p2])

    let choose_cond =
      let open MixOption in
      match O.cond with
      | Cond.Or -> fun _ -> or_cond
      | Cond.And -> fun _ -> and_cond
      | Cond.Auto -> fun c -> c
      | Cond.No ->  fun _ _ _ -> ForallStates (And [])

(* merge of locations *)

(*******)
(* Mix *)
(*******)

    let rec mix_list xs sx ys sy = match xs, ys with
    | [],[] -> []
    | x::rx, [] -> x::mix_list rx (sx-1) ys sy
    | [],y::ry -> y::mix_list xs sx ry (sy-1)
    | x::rx, y::ry ->
        if Random.int(sx+sy) < sx then
          x::mix_list rx (sx-1) ys sy
        else
          y::mix_list xs sx ry (sy-1)

    let clean_code =
      List.filter
        (fun i -> match i with
        | A.Nop -> false
        | A.Label _
        | A.Instruction _
	| A.Symbolic _
        | A.Macro _ -> true)

    let mix_code c1 c2 =
      let c1 = clean_code c1
      and c2 = clean_code c2 in
      mix_list c1 (List.length c1) c2 (List.length c2)

    let rec mix_prog p1 p2 = match p1,p2 with
    | ([],p)|(p,[]) -> p
    | (p,c1)::p1,(_,c2)::p2 -> (p,mix_code c1 c2)::mix_prog p1 p2


    let mix_cond = choose_cond or_cond

    let merge _doc1 t1 doc2 t2 =
      let t2 = MixPerm.perm doc2 t2 in
      let t2 = Alpha.alpha doc2 t1 t2 in
      { t1 with
        init = t1.init @ t2.init ;
        prog = mix_prog t1.prog t2.prog ;
        locations = t1.locations @ t2.locations ;
        condition = mix_cond t1.condition t2.condition ; }

(**********)
(* Append *)
(**********)

    let append_cond = choose_cond and_cond

    let append_code c1 c2 = c1@c2

    let rec append_prog p1 p2 = match p1,p2 with
    | ([],p)|(p,[]) -> p
    | (p,c1)::p1,(_,c2)::p2 -> (p,append_code c1 c2)::append_prog p1 p2


    let rec replicate x n = if n <= 0 then [] else x::replicate x (n-1)

    let rec add_end len = function
      | [] -> replicate A.Nop len
      | x::xs -> x::add_end (len-1) xs

    let same_length prg =
      let len =
        List.fold_left (fun m (_,c) -> max m (List.length c)) 0 prg in
      let prg =
        List.map
          (fun (p,c) -> p,add_end (len+1) c)
          prg in
      prg

    let append _doc1 t1 doc2 t2 =
      let t2 = MixPerm.perm doc2 t2 in
      let t2 = Alpha.alpha doc2 t1 t2 in
      { t1 with
        init = t1.init @ t2.init ;
        prog = append_prog (same_length t1.prog) t2.prog ;
        locations = t1.locations @ t2.locations ;
        condition = append_cond t1.condition t2.condition ; }

(********************************************)
(* Just concatenate in horizontal direction *)
(********************************************)

    let nprocs t = List.length t.prog

    let shift_location k loc = match loc with
    | A.Location_reg (i,r) -> A.Location_reg (i+k,r)
    | A.Location_global _ -> loc

    let shift_rloc k = ConstrGen.map_rloc (shift_location k)

    let shift_state_atom k (loc,v) = shift_location k loc,v

    let shift_state k = List.map (shift_state_atom k)

    let shift_locations k =
      let open LocationsItem in
      List.map
        (function
          | Loc (l,v) -> Loc (shift_rloc k l,v)
          | Fault ((i,lbls),x,ft) -> Fault ((i+k,lbls),x,ft))

    let shift_atom k a = match a with
    | LV (l,v) ->  LV (shift_rloc k l,v)
    | LL (a,b) -> LL (shift_location k a,shift_location k b)
    | FF ((i,lbls),x,ft) -> FF ((i+k,lbls),x,ft)

    let shift_constr k = ConstrGen.map_constr (shift_atom k)

    let shift_prog k prog =  List.map (fun ((i,ao,func),code) -> (i+k,ao,func),code) prog

    let shift k t =
      { t with
        init = shift_state k t.init;
        locations = shift_locations k t.locations;
        condition = shift_constr k t.condition;
        prog = shift_prog k t.prog;
      }

    let cat _doc1 t1 doc2 t2 =
      let t2 = Alpha.global doc2 t1 t2 in
      let n1 = nprocs t1 in
      let t2 = shift n1 t2 in
      { t1 with
        init = t1.init @ t2.init ;
        prog = t1.prog @ t2.prog ;
        locations = t1.locations @ t2.locations ;
        condition = append_cond t1.condition t2.condition ; }


end