summaryrefslogtreecommitdiff
path: root/src/gen_lib/sail2_state_monad.lem
diff options
context:
space:
mode:
authorJon French2019-02-13 12:27:48 +0000
committerJon French2019-02-13 12:27:48 +0000
commitea39b3c674570ce5eea34067c36d5196ca201f83 (patch)
tree516e7491bc32797a4d0ac397ea47387f2b16cf1b /src/gen_lib/sail2_state_monad.lem
parentab3f3671d4dd682b2aee922d5a05e9455afd5849 (diff)
parent24fc989891ad266eae642815646294279e2485ca (diff)
Merge branch 'sail2' into rmem_interpreter
Diffstat (limited to 'src/gen_lib/sail2_state_monad.lem')
-rw-r--r--src/gen_lib/sail2_state_monad.lem138
1 files changed, 72 insertions, 66 deletions
diff --git a/src/gen_lib/sail2_state_monad.lem b/src/gen_lib/sail2_state_monad.lem
index 30b296cc..3042700c 100644
--- a/src/gen_lib/sail2_state_monad.lem
+++ b/src/gen_lib/sail2_state_monad.lem
@@ -4,24 +4,20 @@ open import Sail2_values
(* 'a is result type *)
-type memstate = map integer memory_byte
-type tagstate = map integer bitU
+type memstate = map nat memory_byte
+type tagstate = map nat bitU
(* type regstate = map string (vector bitU) *)
type sequential_state 'regs =
<| regstate : 'regs;
memstate : memstate;
- tagstate : tagstate;
- write_ea : maybe (write_kind * integer * integer);
- last_exclusive_operation_was_load : bool |>
+ tagstate : tagstate |>
val init_state : forall 'regs. 'regs -> sequential_state 'regs
let init_state regs =
<| regstate = regs;
memstate = Map.empty;
- tagstate = Map.empty;
- write_ea = Nothing;
- last_exclusive_operation_was_load = false |>
+ tagstate = Map.empty |>
type ex 'e =
| Failure of string
@@ -51,8 +47,8 @@ let seqS m n = bindS m (fun (_ : unit) -> n)
let inline (>>$=) = bindS
let inline (>>$) = seqS
-val chooseS : forall 'regs 'a 'e. SetType 'a => set 'a -> monadS 'regs 'a 'e
-let chooseS xs s = Set.map (fun x -> (Value x, s)) xs
+val chooseS : forall 'regs 'a 'e. SetType 'a => list 'a -> monadS 'regs 'a 'e
+let chooseS xs s = Set.fromList (List.map (fun x -> (Value x, s)) xs)
val readS : forall 'regs 'a 'e. (sequential_state 'regs -> 'a) -> monadS 'regs 'a 'e
let readS f = (fun s -> returnS (f s) s)
@@ -63,8 +59,9 @@ let updateS f = (fun s -> returnS () (f s))
val failS : forall 'regs 'a 'e. string -> monadS 'regs 'a 'e
let failS msg s = {(Ex (Failure msg), s)}
-val undefined_boolS : forall 'regval 'regs 'a 'e. unit -> monadS 'regs bool 'e
-let undefined_boolS () = chooseS {false; true}
+val choose_boolS : forall 'regval 'regs 'a 'e. unit -> monadS 'regs bool 'e
+let choose_boolS () = chooseS [false; true]
+let undefined_boolS = choose_boolS
val exitS : forall 'regs 'e 'a. unit -> monadS 'regs 'a 'e
let exitS () = failS "exit"
@@ -120,69 +117,78 @@ end
val read_tagS : forall 'regs 'a 'e. Bitvector 'a => 'a -> monadS 'regs bitU 'e
let read_tagS addr =
- maybe_failS "unsigned" (unsigned addr) >>$= (fun addr ->
+ maybe_failS "nat_of_bv" (nat_of_bv addr) >>$= (fun addr ->
readS (fun s -> fromMaybe B0 (Map.lookup addr s.tagstate)))
(* Read bytes from memory and return in little endian order *)
-val read_mem_bytesS : forall 'regs 'e 'a. Bitvector 'a => read_kind -> 'a -> nat -> monadS 'regs (list memory_byte) 'e
-let read_mem_bytesS read_kind addr sz =
- maybe_failS "unsigned" (unsigned addr) >>$= (fun addr ->
- let sz = integerFromNat sz in
- let addrs = index_list addr (addr+sz-1) 1 in
+val get_mem_bytes : forall 'regs. nat -> nat -> sequential_state 'regs -> maybe (list memory_byte * bitU)
+let get_mem_bytes addr sz s =
+ let addrs = genlist (fun n -> addr + n) sz in
let read_byte s addr = Map.lookup addr s.memstate in
- readS (fun s -> just_list (List.map (read_byte s) addrs)) >>$= (function
- | Just mem_val ->
- updateS (fun s ->
- if read_is_exclusive read_kind
- then <| s with last_exclusive_operation_was_load = true |>
- else s) >>$
- returnS mem_val
- | Nothing -> failS "read_memS"
- end))
+ let read_tag s addr = Map.findWithDefault addr B0 s.tagstate in
+ Maybe.map
+ (fun mem_val -> (mem_val, List.foldl and_bit B1 (List.map (read_tag s) addrs)))
+ (just_list (List.map (read_byte s) addrs))
+
+val read_memt_bytesS : forall 'regs 'e. read_kind -> nat -> nat -> monadS 'regs (list memory_byte * bitU) 'e
+let read_memt_bytesS _ addr sz =
+ readS (get_mem_bytes addr sz) >>$=
+ maybe_failS "read_memS"
+
+val read_mem_bytesS : forall 'regs 'e. read_kind -> nat -> nat -> monadS 'regs (list memory_byte) 'e
+let read_mem_bytesS rk addr sz =
+ read_memt_bytesS rk addr sz >>$= (fun (bytes, _) ->
+ returnS bytes)
+
+val read_memtS : forall 'regs 'e 'a 'b. Bitvector 'a, Bitvector 'b => read_kind -> 'a -> integer -> monadS 'regs ('b * bitU) 'e
+let read_memtS rk a sz =
+ maybe_failS "nat_of_bv" (nat_of_bv a) >>$= (fun a ->
+ read_memt_bytesS rk a (nat_of_int sz) >>$= (fun (bytes, tag) ->
+ maybe_failS "bits_of_mem_bytes" (of_bits (bits_of_mem_bytes bytes)) >>$= (fun mem_val ->
+ returnS (mem_val, tag))))
val read_memS : forall 'regs 'e 'a 'b. Bitvector 'a, Bitvector 'b => read_kind -> 'a -> integer -> monadS 'regs 'b 'e
let read_memS rk a sz =
- read_mem_bytesS rk a (nat_of_int sz) >>$= (fun bytes ->
- maybe_failS "bits_of_mem_bytes" (of_bits (bits_of_mem_bytes bytes)))
+ read_memtS rk a sz >>$= (fun (bytes, _) ->
+ returnS bytes)
val excl_resultS : forall 'regs 'e. unit -> monadS 'regs bool 'e
-let excl_resultS () =
- readS (fun s -> s.last_exclusive_operation_was_load) >>$= (fun excl_load ->
- updateS (fun s -> <| s with last_exclusive_operation_was_load = false |>) >>$
- chooseS (if excl_load then {false; true} else {false}))
-
-val write_mem_eaS : forall 'regs 'e 'a. Bitvector 'a => write_kind -> 'a -> nat -> monadS 'regs unit 'e
-let write_mem_eaS write_kind addr sz =
- maybe_failS "unsigned" (unsigned addr) >>$= (fun addr ->
- let sz = integerFromNat sz in
- updateS (fun s -> <| s with write_ea = Just (write_kind, addr, sz) |>))
-
-(* Write little-endian list of bytes to previously announced address *)
-val write_mem_bytesS : forall 'regs 'e. list memory_byte -> monadS 'regs bool 'e
-let write_mem_bytesS v =
- readS (fun s -> s.write_ea) >>$= (function
- | Nothing -> failS "write ea has not been announced yet"
- | Just (_, addr, sz) ->
- let addrs = index_list addr (addr+sz-1) 1 in
- (*let v = external_mem_value (bits_of v) in*)
- let a_v = List.zip addrs v in
- let write_byte mem (addr, v) = Map.insert addr v mem in
- updateS (fun s ->
- <| s with memstate = List.foldl write_byte s.memstate a_v |>) >>$
- returnS true
- end)
-
-val write_mem_valS : forall 'regs 'e 'a. Bitvector 'a => 'a -> monadS 'regs bool 'e
-let write_mem_valS v = match mem_bytes_of_bits v with
- | Just v -> write_mem_bytesS v
- | Nothing -> failS "write_mem_val"
-end
-
-val write_tagS : forall 'regs 'a 'e. Bitvector 'a => 'a -> bitU -> monadS 'regs bool 'e
-let write_tagS addr t =
- maybe_failS "unsigned" (unsigned addr) >>$= (fun addr ->
- updateS (fun s -> <| s with tagstate = Map.insert addr t s.tagstate |>) >>$
- returnS true)
+let excl_resultS =
+ (* TODO: This used to be more deterministic, checking a flag in the state
+ whether an exclusive load has occurred before. However, this does not
+ seem very precise; it might be safer to overapproximate the possible
+ behaviours by always making a nondeterministic choice. *)
+ undefined_boolS
+
+(* Write little-endian list of bytes to given address *)
+val put_mem_bytes : forall 'regs. nat -> nat -> list memory_byte -> bitU -> sequential_state 'regs -> sequential_state 'regs
+let put_mem_bytes addr sz v tag s =
+ let addrs = genlist (fun n -> addr + n) sz in
+ let a_v = List.zip addrs v in
+ let write_byte mem (addr, v) = Map.insert addr v mem in
+ let write_tag mem addr = Map.insert addr tag mem in
+ <| s with memstate = List.foldl write_byte s.memstate a_v;
+ tagstate = List.foldl write_tag s.tagstate addrs |>
+
+val write_memt_bytesS : forall 'regs 'e. write_kind -> nat -> nat -> list memory_byte -> bitU -> monadS 'regs bool 'e
+let write_memt_bytesS _ addr sz v t =
+ updateS (put_mem_bytes addr sz v t) >>$
+ returnS true
+
+val write_mem_bytesS : forall 'regs 'e. write_kind -> nat -> nat -> list memory_byte -> monadS 'regs bool 'e
+let write_mem_bytesS wk addr sz v = write_memt_bytesS wk addr sz v B0
+
+val write_memtS : forall 'regs 'e 'a 'b. Bitvector 'a, Bitvector 'b =>
+ write_kind -> 'a -> integer -> 'b -> bitU -> monadS 'regs bool 'e
+let write_memtS wk addr sz v t =
+ match (nat_of_bv addr, mem_bytes_of_bits v) with
+ | (Just addr, Just v) -> write_memt_bytesS wk addr (nat_of_int sz) v t
+ | _ -> failS "write_mem"
+ end
+
+val write_memS : forall 'regs 'e 'a 'b. Bitvector 'a, Bitvector 'b =>
+ write_kind -> 'a -> integer -> 'b -> monadS 'regs bool 'e
+let write_memS wk addr sz v = write_memtS wk addr sz v B0
val read_regS : forall 'regs 'rv 'a 'e. register_ref 'regs 'rv 'a -> monadS 'regs 'a 'e
let read_regS reg = readS (fun s -> reg.read_from s.regstate)