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
|
(****************************************************************************)
(* 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, ARM Ltd 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. *)
(****************************************************************************)
(** Closed signature for basic view of architectures *)
let func_size = 1000
(* Restricted signature, for dumping *)
module type Types = sig
type pins (* Parsed instruction *)
type ins (* Final instruction *)
type reg_arg
type 'ins kpseudo =
| Nop
| Label of string * 'ins kpseudo
| Instruction of 'ins
| Macro of string * reg_arg list
| Symbolic of string
type pseudo = ins kpseudo
type parsedPseudo = pins kpseudo
type 'ins prog = (MiscParser.proc * 'ins kpseudo list) list
end
module type S = sig
include Types
(* Lifting of fold/map *)
val pseudo_map : ('a -> 'b) -> 'a kpseudo -> 'b kpseudo
val pseudo_fold : ('a -> 'b -> 'a) -> 'a -> 'b kpseudo -> 'a
val pseudo_exists : ('a -> bool) -> 'a kpseudo -> bool
val pseudo_dump : ('a -> string) -> 'a kpseudo -> string
val pseudo_iter : ('a -> unit) -> 'a kpseudo -> unit
(* Fold over instructions in code *)
val fold_pseudo_code : ('a -> 'b -> 'a ) -> 'a -> 'b kpseudo list -> 'a
val exists_pseudo_code : ('ins -> bool) -> 'ins kpseudo list -> bool
(* Fold/Map over labels *)
val fold_labels : ('a -> Label.t -> 'a) -> 'a -> pseudo -> 'a
val map_labels_base : (BranchTarget.t -> BranchTarget.t) -> ins -> ins
val map_labels : (Label.t -> Label.t) -> pseudo -> pseudo
val fold_label_addr :
(Label.t -> int -> 'a -> 'a) -> 'a -> int -> pseudo list -> 'a
(* For printing the program, code per processor *)
type nice_prog = (MiscParser.proc * pseudo list) list
(* Counting (static) memory accesses *)
val get_naccesses : pseudo list -> int
(* Translate from parsed instructions *)
val pseudo_parsed_tr : parsedPseudo -> pseudo
(* Lift to pseudo code *)
val lift_code : 'a list -> 'a kpseudo list
(* Does exist some instruction s.t. predicate yields true *)
val code_exists : (ins -> bool) -> pseudo list -> bool
(* Group code and handler *)
val code_by_proc : ins prog -> (Proc.t * (pseudo list * pseudo list)) list
(* Get instructions pointed to by a set of labels *)
val from_labels :
Label.Full.Set.t -> ins prog -> (Label.Full.full * ins) list
(* Get all labels in the code *)
val all_labels : ins prog -> Label.Full.full list
(* Load code, the herd way *)
val size_of_ins : ins -> int
end
(* Input signature *)
module type I = sig
type ins
type pins
type reg_arg
(* translate from parsed *)
val parsed_tr : pins -> ins
(* Number of memory access per instruction *)
val get_naccesses : ins -> int
(* Instruction size, for loading and branch offset computation,
need not be correct? (herd and printing) *)
val size_of_ins : ins -> int
(* fold/map over labels in instructions,
used for label normalisation *)
val fold_labels : 'a -> ('a -> Label.t -> 'a) -> ins -> 'a
val map_labels : (BranchTarget.t -> BranchTarget.t) -> ins -> ins
end
(* Common to all arch, memevents and litmus *)
module Make
(I : I) : S
with type ins = I.ins and type pins = I.pins and type reg_arg = I.reg_arg
=
struct
type ins = I.ins
type pins = I.pins
type reg_arg = I.reg_arg
(* Parsed instructions, ie instructions enriched with labels *)
type 'ins kpseudo =
| Nop
| Label of Label.t * 'ins kpseudo
| Instruction of 'ins
| Macro of string * reg_arg list
| Symbolic of string
type pseudo = ins kpseudo
type parsedPseudo = pins kpseudo
type 'ins prog = (MiscParser.proc * 'ins kpseudo list) list
(* Fold/Map lifting *)
let rec pseudo_map f ins = match ins with
| Nop -> Nop
| Instruction ins -> Instruction (f ins)
| Label (lbl,ins) -> Label (lbl, pseudo_map f ins)
| Symbolic s -> Symbolic s
| Macro (_,_) -> assert false
let rec pseudo_fold f k ins = match ins with
| Nop -> k
| Instruction ins -> f k ins
| Label (_,ins) -> pseudo_fold f k ins
| Symbolic _ -> k
| Macro (_,_) -> assert false
let pseudo_exists p = pseudo_fold (fun b i -> b || p i) false
let pseudo_dump dump = pseudo_fold (fun _ i -> dump i) ""
let pseudo_iter f ins = pseudo_fold (fun () ins -> f ins) () ins
let fold_pseudo_code f = List.fold_left (pseudo_fold f)
let exists_pseudo_code p = List.exists (pseudo_exists p)
(* Fold/Map over labels *)
let rec fold_labels f k ins = match ins with
| Nop -> k
| Instruction ins -> I.fold_labels k f ins
| Label (lbl,ins) -> fold_labels f (f k lbl) ins
| Symbolic _ -> k
| Macro _ -> assert false
let map_labels_base = I.map_labels
let map_label_ins f =
let f =
let open BranchTarget in
function
| Lbl lbl -> Lbl (f lbl)
| Offset _ as o -> o in
I.map_labels f
let rec map_labels f ins = match ins with
| Nop -> Nop
| Instruction ins -> Instruction (map_label_ins f ins)
| Label (lbl,ins) -> Label (f lbl, map_labels f ins)
| Symbolic s -> Symbolic s
| Macro _ -> assert false
(* For printing the program, code per processor *)
type nice_prog = (MiscParser.proc * pseudo list) list
(* Counting memory accesses *)
let get_naccesses code =
List.fold_left
(pseudo_fold
(fun k ins -> k + I.get_naccesses ins))
0 code
(* Translate *)
let pseudo_parsed_tr p = pseudo_map I.parsed_tr p
(* Useful *)
let lift_code xs = List.map (fun i -> Instruction i) xs
let code_exists p =
let rec exists = function
| [] -> false
| ins::code -> pseudo_exists p ins || exists code in
exists
(* Group code by proc *)
let code_by_proc prog =
let m =
let open MiscParser in
List.fold_left
(fun m (p,code) ->
let np = proc_num p in
let (c,f) =
IntMap.safe_find ([],[]) np m in
let v =
match proc_func p with
| Main -> code,f
| FaultHandler -> c,code in
IntMap.add np v m)
IntMap.empty
prog in
let code = IntMap.fold (fun p v k -> (p,v)::k) m [] in
(* Keep threads in increasing id order, although it should not matter. *)
List.rev code
(* Extract instructions pointed by label set *)
let rec add_next_instr m addr lbl code k =
match code with
| [] -> k
| (Nop|Label (_,Nop))::code -> add_next_instr m addr lbl code k
| (Label (_,Instruction i)|Instruction i)::_ ->
let f lbl =
let open BranchTarget in
match lbl with
| Offset _ -> lbl
| Lbl s ->
try
let tgt_addr = Label.Map.find s m in
Offset (tgt_addr-addr)
with Not_found -> lbl in
(lbl,I.map_labels f i)::k
| Label (_,i)::code -> add_next_instr m addr lbl (i::code) k
| (Symbolic _|Macro _)::_ -> assert false
let fold_label_addr f =
let rec fold_ins m addr i code =
match i with
| Label (lbl,ins) ->
fold_ins (f lbl addr m) addr ins code
| Instruction ins ->
fold_rec m (addr+I.size_of_ins ins) code
| Nop ->
fold_rec m addr code
| Macro _|Symbolic _ -> assert false
and fold_rec m addr = function
| [] -> m
| i::rem -> fold_ins m addr i rem in
fold_rec
let mk_label_map m addr code = fold_label_addr Label.Map.add m addr code
let from_labels_code lbls p c f k =
let m = mk_label_map Label.Map.empty 0 c in
let m = mk_label_map m func_size f in
let rec do_rec addr code k =
match code with
| [] -> k
| Label (lbl,pseudoi)::rem ->
let full_lbl = (p,lbl) in
let k =
if Label.Full.Set.mem full_lbl lbls then
add_next_instr m addr full_lbl code k
else k in
do_rec addr (pseudoi::rem) k
| Instruction ins::rem ->
do_rec (addr+I.size_of_ins ins) rem k
| Nop::rem -> do_rec addr rem k
| (Macro _|Symbolic _)::_ -> assert false in
do_rec 0 c k |> do_rec func_size f
let from_labels lbls prog =
if Label.Full.Set.is_empty lbls then []
else
let prog = code_by_proc prog in
List.fold_left
(fun k (p,(c,f)) ->
from_labels_code lbls p c f k)
[] prog
let all_labels prog =
let rec fold_labels f k ins = match ins with
| Label (lbl,ins) -> fold_labels f (f k lbl) ins
| _ -> k
in
let flbls =
List.fold_left
(fun flbls (p,code) ->
List.fold_left
(fun flbls ins ->
fold_labels
(fun flbls lbl -> (MiscParser.proc_num p,lbl)::flbls) flbls ins)
flbls code)
[] prog in
List.rev flbls
let size_of_ins = I.size_of_ins
end
|