summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/coq/Makefile2
-rw-r--r--lib/coq/Sail2_operators_mwords.v5
-rw-r--r--lib/coq/Sail2_prompt.v21
-rw-r--r--lib/coq/Sail2_values.v364
-rw-r--r--lib/coq/_CoqProject2
-rw-r--r--lib/flow.sail4
-rw-r--r--lib/hol/Holmakefile9
-rw-r--r--lib/hol/Makefile31
-rw-r--r--lib/hol/prompt.lem18
-rw-r--r--lib/hol/sail2_prompt.lem19
-rw-r--r--lib/hol/sail2_prompt_monad.lem (renamed from lib/hol/prompt_monad.lem)6
-rw-r--r--lib/hol/sail2_stateAuxiliaryScript.sml (renamed from lib/hol/stateAuxiliaryScript.sml)4
-rw-r--r--lib/hol/sail2_valuesAuxiliaryScript.sml (renamed from lib/hol/sail_valuesAuxiliaryScript.sml)4
-rw-r--r--lib/isabelle/.gitignore26
-rw-r--r--lib/isabelle/Hoare.thy155
-rw-r--r--lib/isabelle/Sail2_operators_mwords_lemmas.thy95
-rw-r--r--lib/isabelle/Sail2_prompt_monad_lemmas.thy45
-rw-r--r--lib/isabelle/Sail2_state_lemmas.thy115
-rw-r--r--lib/isabelle/Sail2_state_monad_lemmas.thy6
-rw-r--r--lib/isabelle/Sail2_values_lemmas.thy140
-rw-r--r--lib/isabelle/manual/Manual.thy7
-rw-r--r--lib/main.ml1
-rw-r--r--lib/mono_rewrites.sail18
-rw-r--r--lib/regfp.sail4
-rw-r--r--lib/rts.c8
-rw-r--r--lib/rts.h2
-rw-r--r--lib/sail.c64
-rw-r--r--lib/sail.h17
-rw-r--r--lib/vector_dec.sail6
29 files changed, 1030 insertions, 168 deletions
diff --git a/lib/coq/Makefile b/lib/coq/Makefile
index 816a6c3d..97869e3c 100644
--- a/lib/coq/Makefile
+++ b/lib/coq/Makefile
@@ -1,4 +1,4 @@
-BBV_DIR=../../../bbv
+BBV_DIR=../../../bbv/theories
SRC=Sail2_prompt_monad.v Sail2_prompt.v Sail2_impl_base.v Sail2_instr_kinds.v Sail2_operators_bitlists.v Sail2_operators_mwords.v Sail2_operators.v Sail2_values.v Sail2_state_monad.v Sail2_state.v
diff --git a/lib/coq/Sail2_operators_mwords.v b/lib/coq/Sail2_operators_mwords.v
index ee98c94e..bb4bf053 100644
--- a/lib/coq/Sail2_operators_mwords.v
+++ b/lib/coq/Sail2_operators_mwords.v
@@ -3,6 +3,7 @@ Require Import Sail2_operators.
Require Import Sail2_prompt_monad.
Require Import Sail2_prompt.
Require Import bbv.Word.
+Require bbv.BinNotation.
Require Import Arith.
Require Import ZArith.
Require Import Omega.
@@ -267,8 +268,8 @@ Definition msb := most_significant
val int_of_vec : forall 'a. Size 'a => bool -> mword 'a -> integer
Definition int_of_vec := int_of_bv
-val string_of_vec : forall 'a. Size 'a => mword 'a -> string
-Definition string_of_vec := string_of_bv*)
+val string_of_vec : forall 'a. Size 'a => mword 'a -> string*)
+Definition string_of_bits {n} (w : mword n) : string := string_of_bv w.
Definition with_word' {n} (P : Type -> Type) : (forall n, Word.word n -> P (Word.word n)) -> mword n -> P (mword n) := fun f w => @with_word n _ (f (Z.to_nat n)) w.
Definition word_binop {n} (f : forall n, Word.word n -> Word.word n -> Word.word n) : mword n -> mword n -> mword n := with_word' (fun x => x -> x) f.
Definition word_unop {n} (f : forall n, Word.word n -> Word.word n) : mword n -> mword n := with_word' (fun x => x) f.
diff --git a/lib/coq/Sail2_prompt.v b/lib/coq/Sail2_prompt.v
index 336ca8de..c98e2926 100644
--- a/lib/coq/Sail2_prompt.v
+++ b/lib/coq/Sail2_prompt.v
@@ -30,6 +30,27 @@ match l with
foreachM xs vars body
end.
+Fixpoint foreach_ZM_up' {rv e Vars} from to step off n `{ArithFact (0 < step)} `{ArithFact (0 <= off)} (vars : Vars) (body : forall (z : Z) `(ArithFact (from <= z <= to)), Vars -> monad rv Vars e) {struct n} : monad rv Vars e :=
+ if sumbool_of_bool (from + off <=? to) then
+ match n with
+ | O => returnm vars
+ | S n => body (from + off) _ vars >>= fun vars => foreach_ZM_up' from to step (off + step) n vars body
+ end
+ else returnm vars.
+
+Fixpoint foreach_ZM_down' {rv e Vars} from to step off n `{ArithFact (0 < step)} `{ArithFact (off <= 0)} (vars : Vars) (body : forall (z : Z) `(ArithFact (to <= z <= from)), Vars -> monad rv Vars e) {struct n} : monad rv Vars e :=
+ if sumbool_of_bool (to <=? from + off) then
+ match n with
+ | O => returnm vars
+ | S n => body (from + off) _ vars >>= fun vars => foreach_ZM_down' from to step (off - step) n vars body
+ end
+ else returnm vars.
+
+Definition foreach_ZM_up {rv e Vars} from to step vars body `{ArithFact (0 < step)} :=
+ foreach_ZM_up' (rv := rv) (e := e) (Vars := Vars) from to step 0 (S (Z.abs_nat (from - to))) vars body.
+Definition foreach_ZM_down {rv e Vars} from to step vars body `{ArithFact (0 < step)} :=
+ foreach_ZM_down' (rv := rv) (e := e) (Vars := Vars) from to step 0 (S (Z.abs_nat (from - to))) vars body.
+
(*declare {isabelle} termination_argument foreachM = automatic*)
(*val and_boolM : forall 'rv 'e. monad 'rv bool 'e -> monad 'rv bool 'e -> monad 'rv bool 'e*)
diff --git a/lib/coq/Sail2_values.v b/lib/coq/Sail2_values.v
index 137be85c..0ce6134f 100644
--- a/lib/coq/Sail2_values.v
+++ b/lib/coq/Sail2_values.v
@@ -2,6 +2,7 @@
(*Require Import Sail_impl_base*)
Require Export ZArith.
+Require Import Ascii.
Require Export String.
Require Import bbv.Word.
Require Export List.
@@ -72,7 +73,13 @@ Definition nn := nat.
(*val pow : Z -> Z -> Z*)
Definition pow m n := m ^ n.
-Definition pow2 n := pow 2 n.
+Program Definition pow2 n : {z : Z & ArithFact (2 ^ n <= z <= 2 ^ n)} := existT _ (pow 2 n) _.
+Next Obligation.
+constructor.
+unfold pow.
+auto using Z.le_refl.
+Qed.
+
(*
Definition inline lt := (<)
Definition inline gt := (>)
@@ -105,7 +112,15 @@ Definition negate_real r := realNegate r
Definition abs_real r := realAbs r
Definition power_real b e := realPowInteger b e*)
+Definition print_endline (_ : string) : unit := tt.
+Definition prerr_endline (_ : string) : unit := tt.
+Definition prerr (_ : string) : unit := tt.
Definition print_int (_ : string) (_ : Z) : unit := tt.
+Definition prerr_int (_ : string) (_ : Z) : unit := tt.
+Definition putchar (_ : Z) : unit := tt.
+
+Definition shl_int := Z.shiftl.
+Definition shr_int := Z.shiftr.
(*
Definition or_bool l r := (l || r)
@@ -123,9 +138,29 @@ Fixpoint repeat' {a} (xs : list a) n :=
| O => []
| S n => xs ++ repeat' xs n
end.
+Lemma repeat'_length {a} {xs : list a} {n : nat} : List.length (repeat' xs n) = (n * List.length xs)%nat.
+induction n.
+* reflexivity.
+* simpl.
+ rewrite app_length.
+ auto with arith.
+Qed.
Definition repeat {a} (xs : list a) (n : Z) :=
if n <=? 0 then []
else repeat' xs (Z.to_nat n).
+Lemma repeat_length {a} {xs : list a} {n : Z} (H : n >= 0) : length_list (repeat xs n) = n * length_list xs.
+unfold length_list, repeat.
+destruct n.
++ reflexivity.
++ simpl (List.length _).
+ rewrite repeat'_length.
+ rewrite Nat2Z.inj_mul.
+ rewrite positive_nat_Z.
+ reflexivity.
++ exfalso.
+ auto with zarith.
+Qed.
+
(*declare {isabelle} termination_argument repeat = automatic
Definition duplicate_to_list bit length := repeat [bit] length
@@ -186,6 +221,48 @@ lemma just_list_spec:
((forall xs. (just_list xs = None) <-> List.elem None xs) &&
(forall xs es. (just_list xs = Some es) <-> (xs = List.map Some es)))*)
+Lemma just_list_length {A} : forall (l : list (option A)) (l' : list A),
+ Some l' = just_list l -> List.length l = List.length l'.
+induction l.
+* intros.
+ simpl in H.
+ inversion H.
+ reflexivity.
+* intros.
+ destruct a; simplify_eq H.
+ simpl in *.
+ destruct (just_list l); simplify_eq H.
+ intros.
+ subst.
+ simpl.
+ f_equal.
+ apply IHl.
+ reflexivity.
+Qed.
+
+Lemma just_list_length_Z {A} : forall (l : list (option A)) l', Some l' = just_list l -> length_list l = length_list l'.
+unfold length_list.
+intros.
+f_equal.
+auto using just_list_length.
+Qed.
+
+Fixpoint member_Z_list (x : Z) (l : list Z) : bool :=
+match l with
+| [] => false
+| h::t => if x =? h then true else member_Z_list x t
+end.
+
+Lemma member_Z_list_In {x l} : member_Z_list x l = true <-> In x l.
+induction l.
+* simpl. split. congruence. tauto.
+* simpl. destruct (x =? a) eqn:H.
+ + rewrite Z.eqb_eq in H. subst. tauto.
+ + rewrite Z.eqb_neq in H. split.
+ - intro Heq. right. apply IHl. assumption.
+ - intros [bad | good]. congruence. apply IHl. assumption.
+Qed.
+
(*** Bits *)
Inductive bitU := B0 | B1 | BU.
@@ -196,6 +273,13 @@ match b with
| BU => "U"
end%string.
+Definition bitU_char b :=
+match b with
+| B0 => "0"
+| B1 => "1"
+| BU => "?"
+end%char.
+
(*instance (Show bitU)
let show := showBitU
end*)
@@ -463,47 +547,52 @@ Definition arith_op_bits (op : Z -> Z -> Z) (sign : bool) l r :=
end.
-(*
-Definition char_of_nibble := function
- | (B0, B0, B0, B0) => Some #'0'
- | (B0, B0, B0, B1) => Some #'1'
- | (B0, B0, B1, B0) => Some #'2'
- | (B0, B0, B1, B1) => Some #'3'
- | (B0, B1, B0, B0) => Some #'4'
- | (B0, B1, B0, B1) => Some #'5'
- | (B0, B1, B1, B0) => Some #'6'
- | (B0, B1, B1, B1) => Some #'7'
- | (B1, B0, B0, B0) => Some #'8'
- | (B1, B0, B0, B1) => Some #'9'
- | (B1, B0, B1, B0) => Some #'A'
- | (B1, B0, B1, B1) => Some #'B'
- | (B1, B1, B0, B0) => Some #'C'
- | (B1, B1, B0, B1) => Some #'D'
- | (B1, B1, B1, B0) => Some #'E'
- | (B1, B1, B1, B1) => Some #'F'
+Definition char_of_nibble x :=
+ match x with
+ | (B0, B0, B0, B0) => Some "0"%char
+ | (B0, B0, B0, B1) => Some "1"%char
+ | (B0, B0, B1, B0) => Some "2"%char
+ | (B0, B0, B1, B1) => Some "3"%char
+ | (B0, B1, B0, B0) => Some "4"%char
+ | (B0, B1, B0, B1) => Some "5"%char
+ | (B0, B1, B1, B0) => Some "6"%char
+ | (B0, B1, B1, B1) => Some "7"%char
+ | (B1, B0, B0, B0) => Some "8"%char
+ | (B1, B0, B0, B1) => Some "9"%char
+ | (B1, B0, B1, B0) => Some "A"%char
+ | (B1, B0, B1, B1) => Some "B"%char
+ | (B1, B1, B0, B0) => Some "C"%char
+ | (B1, B1, B0, B1) => Some "D"%char
+ | (B1, B1, B1, B0) => Some "E"%char
+ | (B1, B1, B1, B1) => Some "F"%char
| _ => None
- end
+ end.
Fixpoint hexstring_of_bits bs := match bs with
| b1 :: b2 :: b3 :: b4 :: bs =>
let n := char_of_nibble (b1, b2, b3, b4) in
let s := hexstring_of_bits bs in
match (n, s) with
- | (Some n, Some s) => Some (n :: s)
+ | (Some n, Some s) => Some (String n s)
| _ => None
end
+ | [] => Some EmptyString
| _ => None
- end
-declare {isabelle} termination_argument hexstring_of_bits = automatic
+ end%string.
+
+Fixpoint binstring_of_bits bs := match bs with
+ | b :: bs => String (bitU_char b) (binstring_of_bits bs)
+ | [] => EmptyString
+ end.
Definition show_bitlist bs :=
match hexstring_of_bits bs with
- | Some s => toString (#'0' :: #x' :: s)
- | None => show bs
- end
+ | Some s => String "0" (String "x" s)
+ | None => String "0" (String "b" (binstring_of_bits bs))
+ end.
(*** List operations *)
-
+(*
Definition inline (^^) := append_list
val subrange_list_inc : forall a. list a -> Z -> Z -> list a*)
@@ -628,10 +717,10 @@ Definition update_list {A} (is_inc : bool) (xs : list A) n x :=
| [] => failwith "extract_only_element called for empty list"
| [e] => e
| _ => failwith "extract_only_element called for list with more elements"
-end
+end*)
(*** Machine words *)
-*)
+
Definition mword (n : Z) :=
match n with
| Zneg _ => False
@@ -832,8 +921,20 @@ Class ReasonableSize (a : Z) : Prop := {
isPositive : a >= 0
}.
-Hint Resolve -> Z.gtb_lt Z.geb_le Z.ltb_lt Z.leb_le : zbool.
-Hint Resolve <- Z.ge_le_iff Z.gt_lt_iff : zbool.
+(* Omega doesn't know about In, but can handle disjunctions. *)
+Ltac unfold_In :=
+repeat match goal with
+| H:context [member_Z_list _ _ = true] |- _ => rewrite member_Z_list_In in H
+| H:context [In ?x (?y :: ?t)] |- _ => change (In x (y :: t)) with (y = x \/ In x t) in H
+| H:context [In ?x []] |- _ => change (In x []) with False in H
+end.
+
+(* Definitions in the context that involve proof for other constraints can
+ break some of the constraint solving tactics, so prune definition bodies
+ down to integer types. *)
+Ltac not_Z ty := match ty with Z => fail 1 | _ => idtac end.
+Ltac clear_non_Z_defns :=
+ repeat match goal with H := _ : ?X |- _ => not_Z X; clearbody H end.
Lemma ArithFact_mword (a : Z) (w : mword a) : ArithFact (a >= 0).
constructor.
@@ -843,7 +944,7 @@ auto using Z.le_ge, Zle_0_pos.
destruct w.
Qed.
Ltac unwrap_ArithFacts :=
- repeat match goal with H:(ArithFact _) |- _ => apply use_ArithFact in H end.
+ repeat match goal with H:(ArithFact _) |- _ => let H' := fresh H in case H as [H'] end.
Ltac unbool_comparisons :=
repeat match goal with
| H:context [Z.geb _ _] |- _ => rewrite Z.geb_leb in H
@@ -855,16 +956,29 @@ Ltac unbool_comparisons :=
| H:context [Z.ltb _ _ = false] |- _ => rewrite Z.ltb_ge in H
| H:context [Z.eqb _ _ = false] |- _ => rewrite Z.eqb_neq in H
| H:context [orb _ _ = true] |- _ => rewrite Bool.orb_true_iff in H
+ | H:context [orb _ _ = false] |- _ => rewrite Bool.orb_false_iff in H
+ | H:context [andb _ _ = true] |- _ => rewrite Bool.andb_true_iff in H
+ | H:context [andb _ _ = false] |- _ => rewrite Bool.andb_false_iff in H
+ | H:context [negb _ = true] |- _ => rewrite Bool.negb_true_iff in H
+ | H:context [negb _ = false] |- _ => rewrite Bool.negb_false_iff in H
| H:context [generic_eq _ _ = true] |- _ => apply generic_eq_true in H
| H:context [generic_eq _ _ = false] |- _ => apply generic_eq_false in H
| H:context [generic_neq _ _ = true] |- _ => apply generic_neq_true in H
| H:context [generic_neq _ _ = false] |- _ => apply generic_neq_false in H
end.
+
(* Split up dependent pairs to get at proofs of properties *)
-(* TODO: simpl is probably too strong here *)
Ltac extract_properties :=
- repeat match goal with H := (projT1 ?X) |- _ => destruct X in *; simpl in H; unfold H in * end;
- repeat match goal with |- context [projT1 ?X] => destruct X in *; simpl end.
+ repeat match goal with H := (projT1 ?X) |- _ =>
+ let x := fresh "x" in
+ let Hx := fresh "Hx" in
+ destruct X as [x Hx] in *;
+ change (projT1 (existT _ x Hx)) with x in *; unfold H in * end;
+ repeat match goal with |- context [projT1 ?X] =>
+ let x := fresh "x" in
+ let Hx := fresh "Hx" in
+ destruct X as [x Hx] in *;
+ change (projT1 (existT _ x Hx)) with x in * end.
(* TODO: hyps, too? *)
Ltac reduce_list_lengths :=
repeat match goal with |- context [length_list ?X] =>
@@ -881,22 +995,37 @@ Ltac reduce_pow :=
let r := (eval cbn in (Z.pow X Y)) in
change (Z.pow X Y) with r
end.
-Ltac solve_arithfact :=
+Ltac dump_context :=
+ repeat match goal with
+ | H:=?X |- _ => idtac H ":=" X; fail
+ | H:?X |- _ => idtac H ":" X; fail end;
+ match goal with |- ?X => idtac "Goal:" X end.
+Ltac prepare_for_solver :=
+(*dump_context;*)
+ clear_non_Z_defns;
extract_properties;
repeat match goal with w:mword ?n |- _ => apply ArithFact_mword in w end;
unwrap_ArithFacts;
+ unfold_In;
autounfold with sail in * |- *; (* You can add Hint Unfold ... : sail to let omega see through fns *)
unbool_comparisons;
reduce_list_lengths;
- reduce_pow;
+ reduce_pow.
+Ltac solve_arithfact :=
+prepare_for_solver;
+(*dump_context;*)
solve [apply ArithFact_mword; assumption
| constructor; omega with Z
(* The datatypes hints give us some list handling, esp In *)
- | constructor; auto with datatypes zbool zarith sail].
+ | constructor; eauto with datatypes zarith sail
+ | constructor; idtac "Unable to solve constraint"; dump_context; fail].
Hint Extern 0 (ArithFact _) => solve_arithfact : typeclass_instances.
Hint Unfold length_mword : sail.
+Definition neq_atom (x : Z) (y : Z) : bool := negb (Z.eqb x y).
+Hint Unfold neq_atom : sail.
+
Lemma ReasonableSize_witness (a : Z) (w : mword a) : ReasonableSize a.
constructor.
destruct a.
@@ -946,9 +1075,9 @@ Definition extz_bv n (v : a) : option b := of_bits (extz_bits n (bits_of v)).
(*val exts_bv : forall a b. Bitvector a, Bitvector b => Z -> a -> b*)
Definition exts_bv n (v : a) : option b := of_bits (exts_bits n (bits_of v)).
-(*val string_of_bv : forall a. Bitvector a => a -> string
-Definition string_of_bv v := show_bitlist (bits_of v)
-*)
+(*val string_of_bv : forall a. Bitvector a => a -> string *)
+Definition string_of_bv v := show_bitlist (bits_of v).
+
End Bitvector_defs.
(*** Bytes and addresses *)
@@ -1216,17 +1345,51 @@ end.
(*declare {isabelle} termination_argument foreach = automatic
val index_list : Z -> Z -> Z -> list Z*)
-Fixpoint index_list' from step n :=
- match n with
- | O => []
- | S n => from :: index_list' (from + step) step n
- end.
+Fixpoint index_list' from to step n :=
+ if orb (andb (step >? 0) (from <=? to)) (andb (step <? 0) (to <=? from)) then
+ match n with
+ | O => []
+ | S n => from :: index_list' (from + step) to step n
+ end
+ else [].
Definition index_list from to step :=
if orb (andb (step >? 0) (from <=? to)) (andb (step <? 0) (to <=? from)) then
- index_list' from step (S (Z.abs_nat (from - to)))
+ index_list' from to step (S (Z.abs_nat (from - to)))
else [].
+Fixpoint foreach_Z' {Vars} from to step n (vars : Vars) (body : Z -> Vars -> Vars) : Vars :=
+ if orb (andb (step >? 0) (from <=? to)) (andb (step <? 0) (to <=? from)) then
+ match n with
+ | O => vars
+ | S n => let vars := body from vars in foreach_Z' (from + step) to step n vars body
+ end
+ else vars.
+
+Definition foreach_Z {Vars} from to step vars body :=
+ foreach_Z' (Vars := Vars) from to step (S (Z.abs_nat (from - to))) vars body.
+
+Fixpoint foreach_Z_up' {Vars} from to step off n `{ArithFact (0 < step)} `{ArithFact (0 <= off)} (vars : Vars) (body : forall (z : Z) `(ArithFact (from <= z <= to)), Vars -> Vars) {struct n} : Vars :=
+ if sumbool_of_bool (from + off <=? to) then
+ match n with
+ | O => vars
+ | S n => let vars := body (from + off) _ vars in foreach_Z_up' from to step (off + step) n vars body
+ end
+ else vars.
+
+Fixpoint foreach_Z_down' {Vars} from to step off n `{ArithFact (0 < step)} `{ArithFact (off <= 0)} (vars : Vars) (body : forall (z : Z) `(ArithFact (to <= z <= from)), Vars -> Vars) {struct n} : Vars :=
+ if sumbool_of_bool (to <=? from + off) then
+ match n with
+ | O => vars
+ | S n => let vars := body (from + off) _ vars in foreach_Z_down' from to step (off - step) n vars body
+ end
+ else vars.
+
+Definition foreach_Z_up {Vars} from to step vars body `{ArithFact (0 < step)} :=
+ foreach_Z_up' (Vars := Vars) from to step 0 (S (Z.abs_nat (from - to))) vars body.
+Definition foreach_Z_down {Vars} from to step vars body `{ArithFact (0 < step)} :=
+ foreach_Z_down' (Vars := Vars) from to step 0 (S (Z.abs_nat (from - to))) vars body.
+
(*val while : forall vars. vars -> (vars -> bool) -> (vars -> vars) -> vars
Fixpoint while vars cond body :=
if cond vars then while (body vars) cond body else vars
@@ -1323,6 +1486,8 @@ Definition abs_with_eq n : {o : Z & ArithFact (o = Z.abs n)} := build_ex (Z.ab
(* Similarly, for ranges (currently in MIPS) *)
+Definition eq_range {n m o p} (l : {l & ArithFact (n <= l <= m)}) (r : {r & ArithFact (o <= r <= p)}) : bool :=
+ (projT1 l) =? (projT1 r).
Definition add_range {n m o p} (l : {l & ArithFact (n <= l <= m)}) (r : {r & ArithFact (o <= r <= p)})
: {x & ArithFact (n+o <= x <= m+p)} :=
build_ex ((projT1 l) + (projT1 r)).
@@ -1338,3 +1503,108 @@ Definition min_atom (a : Z) (b : Z) : {c : Z & ArithFact (c = a \/ c = b /\ c <=
Definition max_atom (a : Z) (b : Z) : {c : Z & ArithFact (c = a \/ c = b /\ c >= a /\ c >= b)} :=
build_ex (Z.max a b).
+
+(*** Generic vectors *)
+
+Definition vec (T:Type) (n:Z) := { l : list T & length_list l = n }.
+Definition vec_length {T n} (v : vec T n) := n.
+Definition vec_access_dec {T n} (v : vec T n) m `{ArithFact (0 <= m < n)} : T :=
+ access_list_dec (projT1 v) m.
+Definition vec_access_inc {T n} (v : vec T n) m `{ArithFact (0 <= m < n)} : T :=
+ access_list_inc (projT1 v) m.
+
+Program Definition vec_init {T} (t : T) (n : Z) `{ArithFact (n >= 0)} : vec T n :=
+ existT _ (repeat [t] n) _.
+Next Obligation.
+rewrite repeat_length; auto using fact.
+unfold length_list.
+simpl.
+auto with zarith.
+Qed.
+
+Lemma skipn_length {A n} {l: list A} : (n <= List.length l -> List.length (skipn n l) = List.length l - n)%nat.
+revert l.
+induction n.
+* simpl. auto with arith.
+* intros l H.
+ destruct l.
+ + inversion H.
+ + simpl in H.
+ simpl.
+ rewrite IHn; auto with arith.
+Qed.
+Lemma update_list_inc_length {T} {l:list T} {m x} : 0 <= m < length_list l -> length_list (update_list_inc l m x) = length_list l.
+unfold update_list_inc, list_update, length_list.
+intro H.
+f_equal.
+assert ((0 <= Z.to_nat m < Datatypes.length l)%nat).
+{ destruct H as [H1 H2].
+ split.
+ + change 0%nat with (Z.to_nat 0).
+ apply Z2Nat.inj_le; auto with zarith.
+ + rewrite <- Nat2Z.id.
+ apply Z2Nat.inj_lt; auto with zarith.
+}
+rewrite app_length.
+rewrite firstn_length_le; only 2:omega.
+cbn -[skipn].
+rewrite skipn_length;
+omega.
+Qed.
+
+Program Definition vec_update_dec {T n} (v : vec T n) m t `{ArithFact (0 <= m < n)} : vec T n := existT _ (update_list_dec (projT1 v) m t) _.
+Next Obligation.
+unfold update_list_dec.
+rewrite update_list_inc_length.
++ destruct v. apply e.
++ destruct H.
+ destruct v. simpl (projT1 _). rewrite e.
+ omega.
+Qed.
+
+Program Definition vec_update_inc {T n} (v : vec T n) m t `{ArithFact (0 <= m < n)} : vec T n := existT _ (update_list_inc (projT1 v) m t) _.
+Next Obligation.
+rewrite update_list_inc_length.
++ destruct v. apply e.
++ destruct H.
+ destruct v. simpl (projT1 _). rewrite e.
+ omega.
+Qed.
+
+Program Definition vec_map {S T} (f : S -> T) {n} (v : vec S n) : vec T n := existT _ (List.map f (projT1 v)) _.
+Next Obligation.
+destruct v as [l H].
+cbn.
+unfold length_list.
+rewrite map_length.
+apply H.
+Qed.
+
+Program Definition just_vec {A n} (v : vec (option A) n) : option (vec A n) :=
+ match just_list (projT1 v) with
+ | None => None
+ | Some v' => Some (existT _ v' _)
+ end.
+Next Obligation.
+rewrite <- (just_list_length_Z _ _ Heq_anonymous).
+destruct v.
+assumption.
+Qed.
+
+Definition list_of_vec {A n} (v : vec A n) : list A := projT1 v.
+
+Program Definition vec_of_list {A} n (l : list A) : option (vec A n) :=
+ if sumbool_of_bool (n =? length_list l) then Some (existT _ l _) else None.
+Next Obligation.
+symmetry.
+apply Z.eqb_eq.
+assumption.
+Qed.
+
+Definition vec_of_list_len {A} (l : list A) : vec A (length_list l) := existT _ l (eq_refl _).
+
+Definition map_bind {A B} (f : A -> option B) (a : option A) : option B :=
+match a with
+| Some a' => f a'
+| None => None
+end. \ No newline at end of file
diff --git a/lib/coq/_CoqProject b/lib/coq/_CoqProject
new file mode 100644
index 00000000..9f5d26b8
--- /dev/null
+++ b/lib/coq/_CoqProject
@@ -0,0 +1,2 @@
+-R . Sail
+-R ../../../bbv/theories bbv
diff --git a/lib/flow.sail b/lib/flow.sail
index c4ffd75a..b4440eaa 100644
--- a/lib/flow.sail
+++ b/lib/flow.sail
@@ -9,7 +9,7 @@ val or_bool = {coq: "orb", _: "or_bool"} : (bool, bool) -> bool
val eq_atom = {ocaml: "eq_int", lem: "eq", c: "eq_int", coq: "Z.eqb"} : forall 'n 'm. (atom('n), atom('m)) -> bool
-val neq_atom = {lem: "neq"} : forall 'n 'm. (atom('n), atom('m)) -> bool
+val neq_atom = {lem: "neq", coq: "neq_atom"} : forall 'n 'm. (atom('n), atom('m)) -> bool
function neq_atom (x, y) = not_bool(eq_atom(x, y))
@@ -27,7 +27,7 @@ val lteq_atom_range = {coq: "leb_range_r", _: "lteq"} : forall 'n 'm 'o. (atom('
val gt_atom_range = {coq: "gtb_range_r", _: "gt"} : forall 'n 'm 'o. (atom('n), range('m, 'o)) -> bool
val gteq_atom_range = {coq: "geb_range_r", _: "gteq"} : forall 'n 'm 'o. (atom('n), range('m, 'o)) -> bool
-val eq_range = {ocaml: "eq_int", lem: "eq", c: "eq_int", coq: "Z.eqb"} : forall 'n 'm 'o 'p. (range('n, 'm), range('o, 'p)) -> bool
+val eq_range = {ocaml: "eq_int", lem: "eq", c: "eq_int", coq: "eq_range"} : forall 'n 'm 'o 'p. (range('n, 'm), range('o, 'p)) -> bool
val eq_int = {ocaml: "eq_int", lem: "eq", c: "eq_int", coq: "Z.eqb"} : (int, int) -> bool
val eq_bool = {ocaml: "eq_bool", lem: "eq", c: "eq_bool", coq: "Bool.eqb"} : (bool, bool) -> bool
diff --git a/lib/hol/Holmakefile b/lib/hol/Holmakefile
index eac4fec8..8e8403f3 100644
--- a/lib/hol/Holmakefile
+++ b/lib/hol/Holmakefile
@@ -1,11 +1,12 @@
-LEM_SCRIPTS = sail_instr_kindsScript.sml sail_valuesScript.sml sail_operatorsScript.sml \
- sail_operators_mwordsScript.sml sail_operators_bitlistsScript.sml \
- state_monadScript.sml stateScript.sml promptScript.sml prompt_monadScript.sml
+LEM_SCRIPTS = sail2_instr_kindsScript.sml sail2_valuesScript.sml sail2_operatorsScript.sml \
+ sail2_operators_mwordsScript.sml sail2_operators_bitlistsScript.sml \
+ sail2_state_monadScript.sml sail2_stateScript.sml sail2_promptScript.sml sail2_prompt_monadScript.sml \
+ sail2_stringScript.sml
LEM_CLEANS = $(LEM_SCRIPTS)
SCRIPTS = $(LEM_SCRIPTS) \
- sail_valuesAuxiliaryScript.sml stateAuxiliaryScript.sml
+ sail2_valuesAuxiliaryScript.sml sail2_stateAuxiliaryScript.sml
THYS = $(patsubst %Script.sml,%Theory.uo,$(SCRIPTS))
diff --git a/lib/hol/Makefile b/lib/hol/Makefile
index 065f887a..783ef23d 100644
--- a/lib/hol/Makefile
+++ b/lib/hol/Makefile
@@ -1,22 +1,25 @@
LEMSRC = \
- ../../src/lem_interp/sail_instr_kinds.lem \
- ../../src/gen_lib/sail_values.lem \
- ../../src/gen_lib/sail_operators.lem \
- ../../src/gen_lib/sail_operators_mwords.lem \
- ../../src/gen_lib/sail_operators_bitlists.lem \
- ../../src/gen_lib/state_monad.lem \
- ../../src/gen_lib/state.lem \
- prompt_monad.lem \
- prompt.lem
+ ../../src/lem_interp/sail2_instr_kinds.lem \
+ ../../src/gen_lib/sail2_values.lem \
+ ../../src/gen_lib/sail2_operators.lem \
+ ../../src/gen_lib/sail2_operators_mwords.lem \
+ ../../src/gen_lib/sail2_operators_bitlists.lem \
+ ../../src/gen_lib/sail2_state_monad.lem \
+ ../../src/gen_lib/sail2_state.lem \
+ ../../src/gen_lib/sail2_string.lem \
+ sail2_prompt_monad.lem \
+ sail2_prompt.lem
-SCRIPTS = sail_instr_kindsScript.sml sail_valuesScript.sml sail_operatorsScript.sml \
- sail_operators_mwordsScript.sml sail_operators_bitlistsScript.sml \
- state_monadScript.sml stateScript.sml \
- prompt_monadScript.sml promptScript.sml
+SCRIPTS = sail2_instr_kindsScript.sml sail2_valuesScript.sml sail2_operatorsScript.sml \
+ sail2_operators_mwordsScript.sml sail2_operators_bitlistsScript.sml \
+ sail2_state_monadScript.sml sail2_stateScript.sml \
+ sail2_prompt_monadScript.sml sail2_promptScript.sml \
+ sail2_stringScript.sml
THYS = $(patsubst %Script.sml,%Theory.uo,$(SCRIPTS))
all: sail-heap $(THYS)
+all-scripts: $(SCRIPTS)
$(SCRIPTS): $(LEMSRC)
lem -hol -outdir . -auxiliary_level none -lib ../../src/lem_interp -lib ../../src/gen_lib $(LEMSRC)
@@ -28,4 +31,4 @@ $(THYS) sail-heap: $(SCRIPTS)
clean:
Holmake cleanAll
-.PHONY: all clean
+.PHONY: all all-scripts clean
diff --git a/lib/hol/prompt.lem b/lib/hol/prompt.lem
deleted file mode 100644
index edbd3752..00000000
--- a/lib/hol/prompt.lem
+++ /dev/null
@@ -1,18 +0,0 @@
-open import Prompt_monad
-open import State_monad
-open import State
-
-let inline undefined_bool = undefined_boolS
-let inline bool_of_bitU_oracle = bool_of_bitU_oracleS
-let inline bool_of_bitU_fail = bool_of_bitU_fail
-let inline bools_of_bits_oracle = bools_of_bits_oracleS
-let inline of_bits_oracle = of_bits_oracleS
-let inline of_bits_fail = of_bits_failS
-let inline mword_oracle = mword_oracleS
-let inline reg_deref = read_regS
-
-let inline foreachM = foreachS
-let inline whileM = whileS
-let inline untilM = untilS
-let inline and_boolM = and_boolS
-let inline or_boolM = or_boolS
diff --git a/lib/hol/sail2_prompt.lem b/lib/hol/sail2_prompt.lem
new file mode 100644
index 00000000..674d4e34
--- /dev/null
+++ b/lib/hol/sail2_prompt.lem
@@ -0,0 +1,19 @@
+open import Sail2_prompt_monad
+open import Sail2_state_monad
+open import Sail2_state
+
+let inline undefined_bool = undefined_boolS
+let inline bool_of_bitU_nondet = bool_of_bitU_nondetS
+let inline bool_of_bitU_fail = bool_of_bitU_fail
+let inline bools_of_bits_nondet = bools_of_bits_nondetS
+let inline of_bits_nondet = of_bits_nondetS
+let inline of_bits_fail = of_bits_failS
+let inline mword_nondet = mword_nondetS
+let inline reg_deref = read_regS
+let inline internal_pick = internal_pickS
+
+let inline foreachM = foreachS
+let inline whileM = whileS
+let inline untilM = untilS
+let inline and_boolM = and_boolS
+let inline or_boolM = or_boolS
diff --git a/lib/hol/prompt_monad.lem b/lib/hol/sail2_prompt_monad.lem
index 8fcd645a..3af931a5 100644
--- a/lib/hol/prompt_monad.lem
+++ b/lib/hol/sail2_prompt_monad.lem
@@ -1,7 +1,7 @@
open import Pervasives_extra
-open import Sail_instr_kinds
-open import Sail_values
-open import State_monad
+open import Sail2_instr_kinds
+open import Sail2_values
+open import Sail2_state_monad
(* Fake interface of the prompt monad by redirecting to the state monad, since
the former is not currently supported by HOL4 *)
diff --git a/lib/hol/stateAuxiliaryScript.sml b/lib/hol/sail2_stateAuxiliaryScript.sml
index c8269750..4d70b033 100644
--- a/lib/hol/stateAuxiliaryScript.sml
+++ b/lib/hol/sail2_stateAuxiliaryScript.sml
@@ -1,6 +1,6 @@
(*Generated by Lem from ../../src/gen_lib/state.lem.*)
open HolKernel Parse boolLib bossLib;
-open lem_pervasives_extraTheory sail_valuesTheory state_monadTheory stateTheory;
+open lem_pervasives_extraTheory sail2_valuesTheory sail2_state_monadTheory sail2_stateTheory;
val _ = numLib.prefer_num();
@@ -8,7 +8,7 @@ val _ = numLib.prefer_num();
open lemLib;
(* val _ = lemLib.run_interactive := true; *)
-val _ = new_theory "stateAuxiliary"
+val _ = new_theory "sail2_stateAuxiliary"
(****************************************************)
diff --git a/lib/hol/sail_valuesAuxiliaryScript.sml b/lib/hol/sail2_valuesAuxiliaryScript.sml
index aa169979..b475c5ea 100644
--- a/lib/hol/sail_valuesAuxiliaryScript.sml
+++ b/lib/hol/sail2_valuesAuxiliaryScript.sml
@@ -1,6 +1,6 @@
(*Generated by Lem from ../../src/gen_lib/sail_values.lem.*)
open HolKernel Parse boolLib bossLib;
-open lem_pervasives_extraTheory lem_machine_wordTheory sail_valuesTheory;
+open lem_pervasives_extraTheory lem_machine_wordTheory sail2_valuesTheory;
open intLib;
val _ = numLib.prefer_num();
@@ -9,7 +9,7 @@ val _ = numLib.prefer_num();
open lemLib;
(* val _ = lemLib.run_interactive := true; *)
-val _ = new_theory "sail_valuesAuxiliary"
+val _ = new_theory "sail2_valuesAuxiliary"
(****************************************************)
diff --git a/lib/isabelle/.gitignore b/lib/isabelle/.gitignore
index 0d595f3c..ed83cdc1 100644
--- a/lib/isabelle/.gitignore
+++ b/lib/isabelle/.gitignore
@@ -1,13 +1,13 @@
-PromptAuxiliary.thy
-Prompt_monadAuxiliary.thy
-Prompt_monad.thy
-Prompt.thy
-Sail_instr_kinds.thy
-Sail_operators_bitlists.thy
-Sail_operators_mwords.thy
-Sail_operators.thy
-Sail_valuesAuxiliary.thy
-Sail_values.thy
-StateAuxiliary.thy
-State_monad.thy
-State.thy
+Sail2_promptAuxiliary.thy
+Sail2_prompt_monadAuxiliary.thy
+Sail2_prompt_monad.thy
+Sail2_prompt.thy
+Sail2_instr_kinds.thy
+Sail2_operators_bitlists.thy
+Sail2_operators_mwords.thy
+Sail2_operators.thy
+Sail2_valuesAuxiliary.thy
+Sail2_values.thy
+Sail2_stateAuxiliary.thy
+Sail2_state_monad.thy
+Sail2_state.thy
diff --git a/lib/isabelle/Hoare.thy b/lib/isabelle/Hoare.thy
index 5c77c5e7..76750117 100644
--- a/lib/isabelle/Hoare.thy
+++ b/lib/isabelle/Hoare.thy
@@ -13,7 +13,7 @@ subsection \<open>Hoare triples\<close>
type_synonym 'regs predS = "'regs sequential_state \<Rightarrow> bool"
-definition PrePost :: "'regs predS \<Rightarrow> ('regs, 'a, 'e) monadS \<Rightarrow> (('a, 'e) result \<Rightarrow> 'regs predS) \<Rightarrow> bool"
+definition PrePost :: "'regs predS \<Rightarrow> ('regs, 'a, 'e) monadS \<Rightarrow> (('a, 'e) result \<Rightarrow> 'regs predS) \<Rightarrow> bool" ("\<lbrace>_\<rbrace> _ \<lbrace>_\<rbrace>")
where "PrePost P f Q \<equiv> (\<forall>s. P s \<longrightarrow> (\<forall>(r, s') \<in> f s. Q r s'))"
lemma PrePostI:
@@ -211,7 +211,7 @@ there is an exception.
[1] D. Cock, G. Klein, and T. Sewell, ‘Secure Microkernels, State Monads and Scalable Refinement’,
in Theorem Proving in Higher Order Logics, 2008, pp. 167–182.\<close>
-definition PrePostE :: "'regs predS \<Rightarrow> ('regs, 'a, 'e) monadS \<Rightarrow> ('a \<Rightarrow> 'regs predS) \<Rightarrow> ('e ex \<Rightarrow> 'regs predS) \<Rightarrow> bool"
+definition PrePostE :: "'regs predS \<Rightarrow> ('regs, 'a, 'e) monadS \<Rightarrow> ('a \<Rightarrow> 'regs predS) \<Rightarrow> ('e ex \<Rightarrow> 'regs predS) \<Rightarrow> bool" ("\<lbrace>_\<rbrace> _ \<lbrace>_ \<bar> _\<rbrace>")
where "PrePostE P f Q E \<equiv> PrePost P f (\<lambda>v. case v of Value a \<Rightarrow> Q a | Ex e \<Rightarrow> E e)"
lemmas PrePost_defs = PrePost_def PrePostE_def
@@ -253,6 +253,27 @@ lemma PrePostE_weaken_post:
named_theorems PrePostE_compositeI
named_theorems PrePostE_atomI
+lemma PrePostE_conj_conds:
+ assumes "PrePostE P1 m Q1 E1"
+ and "PrePostE P2 m Q2 E2"
+ shows "PrePostE (\<lambda>s. P1 s \<and> P2 s) m (\<lambda>r s. Q1 r s \<and> Q2 r s) (\<lambda>e s. E1 e s \<and> E2 e s)"
+ using assms by (auto intro: PrePostE_I elim: PrePostE_elim)
+
+lemmas PrePostE_conj_conds_consequence = PrePostE_conj_conds[THEN PrePostE_consequence]
+
+lemma PrePostE_post_mp:
+ assumes "PrePostE P m Q' E"
+ and "PrePostE P m (\<lambda>r s. Q' r s \<longrightarrow> Q r s) E"
+ shows "PrePostE P m Q E"
+ using PrePostE_conj_conds[OF assms] by (auto intro: PrePostE_weaken_post)
+
+lemma PrePostE_cong:
+ assumes "\<And>s. P1 s \<longleftrightarrow> P2 s" and "\<And>s. P1 s \<Longrightarrow> m1 s = m2 s" and "\<And>r s. Q1 r s \<longleftrightarrow> Q2 r s"
+ and "\<And>e s. E1 e s \<longleftrightarrow> E2 e s"
+ shows "PrePostE P1 m1 Q1 E1 \<longleftrightarrow> PrePostE P2 m2 Q2 E2"
+ using assms unfolding PrePostE_def PrePost_def
+ by (auto split: result.splits)
+
lemma PrePostE_True_post[PrePostE_atomI, intro, simp]:
"PrePostE P m (\<lambda>_ _. True) (\<lambda>_ _. True)"
unfolding PrePost_defs by (auto split: result.splits)
@@ -320,6 +341,11 @@ lemma PrePostE_option_cases[PrePostE_compositeI]:
shows "PrePostE (case x of Some a \<Rightarrow> PS a | None \<Rightarrow> PN) (case x of Some a \<Rightarrow> s a | None \<Rightarrow> n) Q E"
using assms by (auto split: option.splits)
+lemma PrePostE_sum_cases[PrePostE_compositeI]:
+ assumes "\<And>a. PrePostE (Pl a) (l a) Q E" and "\<And>b. PrePostE (Pr b) (r b) Q E"
+ shows "PrePostE (case x of Inl a \<Rightarrow> Pl a | Inr b \<Rightarrow> Pr b) (case x of Inl a \<Rightarrow> l a | Inr b \<Rightarrow> r b) Q E"
+ using assms by (auto split: sum.splits)
+
lemma PrePostE_let[PrePostE_compositeI]:
assumes "PrePostE P (m y) Q E"
shows "PrePostE P (let x = y in m x) Q E"
@@ -347,10 +373,51 @@ lemma PrePostE_failS[PrePostE_atomI, intro]:
"PrePostE (E (Failure msg)) (failS msg) Q E"
unfolding PrePostE_def by (auto intro: PrePost_strengthen_pre)
+lemma PrePostE_maybe_failS[PrePostE_atomI]:
+ "PrePostE (\<lambda>s. case v of Some v \<Rightarrow> Q v s | None \<Rightarrow> E (Failure msg) s) (maybe_failS msg v) Q E"
+ by (auto simp: maybe_failS_def split: option.splits)
+
+lemma PrePostE_exitS[PrePostE_atomI, intro]: "PrePostE (E (Failure ''exit'')) (exitS msg) Q E"
+ unfolding exitS_def PrePostE_def PrePost_def failS_def by auto
+
lemma PrePostE_chooseS[intro, PrePostE_atomI]:
"PrePostE (\<lambda>s. \<forall>x \<in> xs. Q x s) (chooseS xs) Q E"
unfolding PrePostE_def by (auto intro: PrePost_strengthen_pre)
+lemma PrePostE_throwS[PrePostE_atomI]: "PrePostE (E (Throw e)) (throwS e) Q E"
+ by (intro PrePostE_I) (auto simp: throwS_def)
+
+lemma PrePostE_try_catchS[PrePostE_compositeI]:
+ assumes Ph: "\<And>s e s'. (Ex (Throw e), s') \<in> m s \<Longrightarrow> PrePostE (Ph e) (h e) Q E"
+ and m: "PrePostE P m Q (\<lambda>ex. case ex of Throw e \<Rightarrow> Ph e | Failure msg \<Rightarrow> E (Failure msg))"
+ shows "PrePostE P (try_catchS m h) Q E"
+ unfolding PrePostE_def
+proof (intro PrePostI)
+ fix s r s'
+ assume "(r, s') \<in> try_catchS m h s" and P: "P s"
+ then show "(case r of Value a \<Rightarrow> Q a | result.Ex e \<Rightarrow> E e) s'" using m
+ proof (cases rule: try_catchS_cases)
+ case (h e s'')
+ then have "Ph e s''" using P m by (auto elim!: PrePostE_elim)
+ then show ?thesis using Ph[OF h(1)] h(2) by (auto elim!: PrePostE_elim)
+ qed (auto elim!: PrePostE_elim)
+qed
+
+lemma PrePostE_catch_early_returnS[PrePostE_compositeI]:
+ assumes "PrePostE P m Q (\<lambda>ex. case ex of Throw (Inl a) \<Rightarrow> Q a | Throw (Inr e) \<Rightarrow> E (Throw e) | Failure msg \<Rightarrow> E (Failure msg))"
+ shows "PrePostE P (catch_early_returnS m) Q E"
+ unfolding catch_early_returnS_def
+ by (rule PrePostE_try_catchS, rule PrePostE_sum_cases[OF PrePostE_returnS PrePostE_throwS])
+ (auto intro: assms)
+
+lemma PrePostE_early_returnS[PrePostE_atomI]: "PrePostE (E (Throw (Inl r))) (early_returnS r) Q E"
+ by (auto simp: early_returnS_def intro: PrePostE_throwS)
+
+lemma PrePostE_liftRS[PrePostE_compositeI]:
+ assumes "PrePostE P m Q (\<lambda>ex. case ex of Throw e \<Rightarrow> E (Throw (Inr e)) | Failure msg \<Rightarrow> E (Failure msg))"
+ shows "PrePostE P (liftRS m) Q E"
+ using assms unfolding liftRS_def by (intro PrePostE_try_catchS[OF PrePostE_throwS])
+
lemma PrePostE_foreachS_Cons:
assumes "\<And>s vars' s'. (Value vars', s') \<in> body x vars s \<Longrightarrow> PrePostE (Q vars') (foreachS xs vars' body) Q E"
and "PrePostE (Q vars) (body x vars) Q E"
@@ -363,4 +430,88 @@ lemma PrePostE_foreachS_invariant:
using assms unfolding PrePostE_def
by (intro PrePost_foreachS_invariant[THEN PrePost_strengthen_pre]) auto
+lemma PrePostE_untilS:
+ assumes dom: "\<And>s. Inv Q vars s \<Longrightarrow> untilS_dom (vars, cond, body, s)"
+ and cond: "\<And>vars. PrePostE (Inv' Q vars) (cond vars) (\<lambda>c s'. Inv Q vars s' \<and> (c \<longrightarrow> Q vars s')) E"
+ and body: "\<And>vars. PrePostE (Inv Q vars) (body vars) (Inv' Q) E"
+ shows "PrePostE (Inv Q vars) (untilS vars cond body) Q E"
+proof (unfold PrePostE_def, rule PrePostI)
+ fix s r s'
+ assume Inv_s: "Inv Q vars s" and r: "(r, s') \<in> untilS vars cond body s"
+ with dom[OF Inv_s] cond body
+ show "(case r of Value a \<Rightarrow> Q a | result.Ex e \<Rightarrow> E e) s'"
+ proof (induction vars cond body s rule: untilS.pinduct[case_names Step])
+ case (Step vars cond body s)
+ consider
+ (Value) vars' c sb sc where "(Value vars', sb) \<in> body vars s" and "(Value c, sc) \<in> cond vars' sb"
+ and "if c then r = Value vars' \<and> s' = sc else (r, s') \<in> untilS vars' cond body sc"
+ | (Ex) e where "(Ex e, s') \<in> bindS (body vars) cond s" and "r = Ex e"
+ using Step(1,6)
+ by (auto simp: untilS.psimps returnS_def Ex_bindS_iff elim!: bindS_cases split: if_splits; fastforce)
+ then show ?case
+ proof cases
+ case Value
+ then show ?thesis using Step.IH[OF Value(1,2) _ Step(3,4)] Step(3,4,5)
+ by (auto split: if_splits elim: PrePostE_elim)
+ next
+ case Ex
+ then show ?thesis using Step(3,4,5) by (auto elim!: bindS_cases PrePostE_elim)
+ qed
+ qed
+qed
+
+lemma PrePostE_untilS_pure_cond:
+ assumes dom: "\<And>s. Inv Q vars s \<Longrightarrow> untilS_dom (vars, returnS \<circ> cond, body, s)"
+ and body: "\<And>vars. PrePostE (Inv Q vars) (body vars) (\<lambda>vars' s'. Inv Q vars' s' \<and> (cond vars' \<longrightarrow> Q vars' s')) E"
+ shows "PrePostE (Inv Q vars) (untilS vars (returnS \<circ> cond) body) Q E"
+ using assms by (intro PrePostE_untilS) (auto simp: comp_def)
+
+lemma PrePostE_liftState_untilM:
+ assumes dom: "\<And>s. Inv Q vars s \<Longrightarrow> untilM_dom (vars, cond, body)"
+ and cond: "\<And>vars. PrePostE (Inv' Q vars) (liftState r (cond vars)) (\<lambda>c s'. Inv Q vars s' \<and> (c \<longrightarrow> Q vars s')) E"
+ and body: "\<And>vars. PrePostE (Inv Q vars) (liftState r (body vars)) (Inv' Q) E"
+ shows "PrePostE (Inv Q vars) (liftState r (untilM vars cond body)) Q E"
+proof -
+ have domS: "untilS_dom (vars, liftState r \<circ> cond, liftState r \<circ> body, s)" if "Inv Q vars s" for s
+ using dom that by (intro untilM_dom_untilS_dom)
+ then have "PrePostE (Inv Q vars) (untilS vars (liftState r \<circ> cond) (liftState r \<circ> body)) Q E"
+ using cond body by (auto intro: PrePostE_untilS simp: comp_def)
+ moreover have "liftState r (untilM vars cond body) s = untilS vars (liftState r \<circ> cond) (liftState r \<circ> body) s"
+ if "Inv Q vars s" for s
+ unfolding liftState_untilM[OF domS[OF that] dom[OF that]] ..
+ ultimately show ?thesis by (auto cong: PrePostE_cong)
+qed
+
+lemma PrePostE_liftState_untilM_pure_cond:
+ assumes dom: "\<And>s. Inv Q vars s \<Longrightarrow> untilM_dom (vars, return \<circ> cond, body)"
+ and body: "\<And>vars. PrePostE (Inv Q vars) (liftState r (body vars)) (\<lambda>vars' s'. Inv Q vars' s' \<and> (cond vars' \<longrightarrow> Q vars' s')) E"
+ shows "PrePostE (Inv Q vars) (liftState r (untilM vars (return \<circ> cond) body)) Q E"
+ using assms by (intro PrePostE_liftState_untilM) (auto simp: comp_def liftState_simp)
+
+lemma PrePostE_undefined_boolS[PrePostE_atomI]:
+ "PrePostE (\<lambda>s. \<forall>b. Q b s)
+ (undefined_boolS unit) Q E"
+ unfolding undefined_boolS_def seqS_def
+ by (auto intro: PrePostE_strengthen_pre PrePostE_chooseS)
+
+lemma PrePostE_bool_of_bitU_nondetS_any:
+ "PrePostE (\<lambda>s. \<forall>b. Q b s) (bool_of_bitU_nondetS b) Q E"
+ unfolding bool_of_bitU_nondetS_def undefined_boolS_def
+ by (cases b; simp; rule PrePostE_strengthen_pre, rule PrePostE_atomI) auto
+
+lemma PrePostE_bools_of_bits_nondetS_any:
+ "PrePostE (\<lambda>s. \<forall>bs. Q bs s) (bools_of_bits_nondetS bs) Q E"
+ unfolding bools_of_bits_nondetS_def
+ by (rule PrePostE_weaken_post[where B = "\<lambda>_ s. \<forall>bs. Q bs s"], rule PrePostE_strengthen_pre,
+ (rule PrePostE_foreachS_invariant[OF PrePostE_strengthen_pre] PrePostE_bindS PrePostE_returnS
+ PrePostE_bool_of_bitU_nondetS_any)+)
+ auto
+
+lemma PrePostE_internal_pick:
+ "xs \<noteq> [] \<Longrightarrow> PrePostE (\<lambda>s. \<forall>x \<in> set xs. Q x s) (internal_pickS xs) Q E"
+ unfolding internal_pickS_def Let_def
+ by (rule PrePostE_strengthen_pre,
+ (rule PrePostE_compositeI PrePostE_atomI PrePostE_bools_of_bits_nondetS_any)+)
+ (auto split: option.splits)
+
end
diff --git a/lib/isabelle/Sail2_operators_mwords_lemmas.thy b/lib/isabelle/Sail2_operators_mwords_lemmas.thy
index ae8802f2..fd54c93a 100644
--- a/lib/isabelle/Sail2_operators_mwords_lemmas.thy
+++ b/lib/isabelle/Sail2_operators_mwords_lemmas.thy
@@ -2,14 +2,14 @@ theory Sail2_operators_mwords_lemmas
imports Sail2_operators_mwords
begin
-lemmas uint_simps[simp] = uint_maybe_def uint_fail_def uint_oracle_def
-lemmas sint_simps[simp] = sint_maybe_def sint_fail_def sint_oracle_def
+lemmas uint_simps[simp] = uint_maybe_def uint_fail_def uint_nondet_def
+lemmas sint_simps[simp] = sint_maybe_def sint_fail_def sint_nondet_def
-lemma bools_of_bits_oracle_just_list[simp]:
+lemma bools_of_bits_nondet_just_list[simp]:
assumes "just_list (map bool_of_bitU bus) = Some bs"
- shows "bools_of_bits_oracle bus = return bs"
+ shows "bools_of_bits_nondet bus = return bs"
proof -
- have f: "foreachM bus bools (\<lambda>b bools. bool_of_bitU_oracle b \<bind> (\<lambda>b. return (bools @ [b]))) = return (bools @ bs)"
+ have f: "foreachM bus bools (\<lambda>b bools. bool_of_bitU_nondet b \<bind> (\<lambda>b. return (bools @ [b]))) = return (bools @ bs)"
if "just_list (map bool_of_bitU bus) = Some bs" for bus bs bools
proof (use that in \<open>induction bus arbitrary: bs bools\<close>)
case (Cons bu bus bs)
@@ -17,26 +17,26 @@ proof -
using Cons.prems by (cases bu) (auto split: option.splits)
then show ?case
using Cons.prems Cons.IH[where bs = bs' and bools = "bools @ [b]"]
- by (cases bu) (auto simp: bool_of_bitU_oracle_def split: option.splits)
+ by (cases bu) (auto simp: bool_of_bitU_nondet_def split: option.splits)
qed auto
- then show ?thesis using f[OF assms, of "[]"] unfolding bools_of_bits_oracle_def
+ then show ?thesis using f[OF assms, of "[]"] unfolding bools_of_bits_nondet_def
by auto
qed
lemma of_bits_mword_return_of_bl[simp]:
assumes "just_list (map bool_of_bitU bus) = Some bs"
- shows "of_bits_oracle BC_mword bus = return (of_bl bs)"
+ shows "of_bits_nondet BC_mword bus = return (of_bl bs)"
and "of_bits_fail BC_mword bus = return (of_bl bs)"
- by (auto simp: of_bits_oracle_def of_bits_fail_def maybe_fail_def assms BC_mword_defs)
+ by (auto simp: of_bits_nondet_def of_bits_fail_def maybe_fail_def assms BC_mword_defs)
lemma vec_of_bits_of_bl[simp]:
assumes "just_list (map bool_of_bitU bus) = Some bs"
shows "vec_of_bits_maybe bus = Some (of_bl bs)"
and "vec_of_bits_fail bus = return (of_bl bs)"
- and "vec_of_bits_oracle bus = return (of_bl bs)"
+ and "vec_of_bits_nondet bus = return (of_bl bs)"
and "vec_of_bits_failwith bus = of_bl bs"
and "vec_of_bits bus = of_bl bs"
- unfolding vec_of_bits_maybe_def vec_of_bits_fail_def vec_of_bits_oracle_def
+ unfolding vec_of_bits_maybe_def vec_of_bits_fail_def vec_of_bits_nondet_def
vec_of_bits_failwith_def vec_of_bits_def
by (auto simp: assms)
@@ -53,10 +53,10 @@ lemma bool_of_bitU_monadic_simps[simp]:
"bool_of_bitU_fail B0 = return False"
"bool_of_bitU_fail B1 = return True"
"bool_of_bitU_fail BU = Fail ''bool_of_bitU''"
- "bool_of_bitU_oracle B0 = return False"
- "bool_of_bitU_oracle B1 = return True"
- "bool_of_bitU_oracle BU = undefined_bool ()"
- unfolding bool_of_bitU_fail_def bool_of_bitU_oracle_def
+ "bool_of_bitU_nondet B0 = return False"
+ "bool_of_bitU_nondet B1 = return True"
+ "bool_of_bitU_nondet BU = undefined_bool ()"
+ unfolding bool_of_bitU_fail_def bool_of_bitU_nondet_def
by auto
lemma update_vec_dec_simps[simp]:
@@ -66,18 +66,69 @@ lemma update_vec_dec_simps[simp]:
"update_vec_dec_fail w i B0 = return (set_bit w (nat i) False)"
"update_vec_dec_fail w i B1 = return (set_bit w (nat i) True)"
"update_vec_dec_fail w i BU = Fail ''bool_of_bitU''"
- "update_vec_dec_oracle w i B0 = return (set_bit w (nat i) False)"
- "update_vec_dec_oracle w i B1 = return (set_bit w (nat i) True)"
- "update_vec_dec_oracle w i BU = undefined_bool () \<bind> (\<lambda>b. return (set_bit w (nat i) b))"
+ "update_vec_dec_nondet w i B0 = return (set_bit w (nat i) False)"
+ "update_vec_dec_nondet w i B1 = return (set_bit w (nat i) True)"
+ "update_vec_dec_nondet w i BU = undefined_bool () \<bind> (\<lambda>b. return (set_bit w (nat i) b))"
"update_vec_dec w i B0 = set_bit w (nat i) False"
"update_vec_dec w i B1 = set_bit w (nat i) True"
- unfolding update_vec_dec_maybe_def update_vec_dec_fail_def update_vec_dec_oracle_def update_vec_dec_def
+ unfolding update_vec_dec_maybe_def update_vec_dec_fail_def update_vec_dec_nondet_def update_vec_dec_def
by (auto simp: update_mword_dec_def update_mword_bool_dec_def maybe_failwith_def)
lemma len_of_minus_One_minus_nonneg_lt_len_of[simp]:
"n \<ge> 0 \<Longrightarrow> nat (int LENGTH('a::len) - 1 - n) < LENGTH('a)"
by (metis diff_mono diff_zero len_gt_0 nat_eq_iff2 nat_less_iff order_refl zle_diff1_eq)
+declare subrange_vec_dec_def[simp]
+
+lemma update_subrange_vec_dec_update_subrange_list_dec:
+ assumes "0 \<le> j" and "j \<le> i" and "i < int LENGTH('a)"
+ shows "update_subrange_vec_dec (w :: 'a::len word) i j w' =
+ of_bl (update_subrange_list_dec (to_bl w) i j (to_bl w'))"
+ using assms
+ unfolding update_subrange_vec_dec_def update_subrange_list_dec_def update_subrange_list_inc_def
+ by (auto simp: word_update_def split_at_def Let_def nat_diff_distrib min_def)
+
+lemma subrange_vec_dec_subrange_list_dec:
+ assumes "0 \<le> j" and "j \<le> i" and "i < int LENGTH('a)" and "int LENGTH('b) = i - j + 1"
+ shows "subrange_vec_dec (w :: 'a::len word) i j = (of_bl (subrange_list_dec (to_bl w) i j) :: 'b::len word)"
+ using assms unfolding subrange_vec_dec_def
+ by (auto simp: subrange_list_dec_drop_take slice_take of_bl_drop')
+
+lemma slice_simp[simp]: "slice w lo len = Word.slice (nat lo) w"
+ by (auto simp: slice_def)
+
+declare slice_id[simp]
+
+lemma of_bools_of_bl[simp]: "of_bools_method BC_mword = of_bl"
+ by (auto simp: BC_mword_defs)
+
+lemma of_bl_bin_word_of_int:
+ "len = LENGTH('a) \<Longrightarrow> of_bl (bin_to_bl_aux len n []) = (word_of_int n :: ('a::len) word)"
+ by (auto simp: of_bl_def bin_bl_bin')
+
+lemma get_slice_int_0_bin_to_bl[simp]:
+ "len > 0 \<Longrightarrow> get_slice_int len n 0 = of_bl (bin_to_bl (nat len) n)"
+ unfolding get_slice_int_def get_slice_int_bv_def subrange_list_def
+ by (auto simp: subrange_list_dec_drop_take len_bin_to_bl_aux)
+
+lemma to_bl_of_bl[simp]:
+ fixes bl :: "bool list"
+ defines w: "w \<equiv> of_bl bl :: 'a::len word"
+ assumes len: "length bl = LENGTH('a)"
+ shows "to_bl w = bl"
+ using len unfolding w by (intro word_bl.Abs_inverse) auto
+
+lemma reverse_endianness_byte[simp]:
+ "LENGTH('a) = 8 \<Longrightarrow> reverse_endianness (w :: 'a::len word) = w"
+ unfolding reverse_endianness_def by (auto simp: reverse_endianness_list_simps)
+
+lemma reverse_reverse_endianness[simp]:
+ "8 dvd LENGTH('a) \<Longrightarrow> reverse_endianness (reverse_endianness w) = (w :: 'a::len word)"
+ unfolding reverse_endianness_def by (simp)
+
+lemma replicate_bits_zero[simp]: "replicate_bits 0 n = 0"
+ by (intro word_eqI) (auto simp: replicate_bits_def test_bit_of_bl rev_nth nth_repeat simp del: repeat.simps)
+
declare extz_vec_def[simp]
declare exts_vec_def[simp]
declare concat_vec_def[simp]
@@ -109,4 +160,10 @@ lemma arith_vec_int_simps[simp]:
unfolding add_vec_int_def sub_vec_int_def mult_vec_int_def
by (auto simp: arith_op_bv_int_def BC_mword_defs word_add_def word_sub_wi word_mult_def)
+lemma shiftl_simp[simp]: "shiftl w l = w << (nat l)"
+ by (auto simp: shiftl_def shiftl_mword_def)
+
+lemma shiftr_simp[simp]: "shiftr w l = w >> (nat l)"
+ by (auto simp: shiftr_def shiftr_mword_def)
+
end
diff --git a/lib/isabelle/Sail2_prompt_monad_lemmas.thy b/lib/isabelle/Sail2_prompt_monad_lemmas.thy
index 08c9b33c..25eb9f52 100644
--- a/lib/isabelle/Sail2_prompt_monad_lemmas.thy
+++ b/lib/isabelle/Sail2_prompt_monad_lemmas.thy
@@ -64,7 +64,7 @@ inductive_set T :: "(('rv, 'a, 'e) monad \<times> 'rv event \<times> ('rv, 'a, '
| Barrier: "((Barrier bk k), e_barrier bk, k) \<in> T"
| Read_reg: "((Read_reg r k), e_read_reg r v, k v) \<in> T"
| Write_reg: "((Write_reg r v k), e_write_reg r v, k) \<in> T"
-| Undefined : "((Undefined k), e_undefined v, k v) \<in> T"
+| Undefined: "((Undefined k), e_undefined v, k v) \<in> T"
| Print: "((Print msg k), e_print msg, k) \<in> T"
inductive_set Traces :: "(('rv, 'a, 'e) monad \<times> 'rv event list \<times> ('rv, 'a, 'e) monad) set" where
@@ -95,7 +95,7 @@ lemma Traces_cases:
| (Write_ea) wk addr s k t' where "m = Write_ea wk addr s k" and "t = e_write_ea wk addr s # t'" and "(k, t', m') \<in> Traces"
| (Footprint) k t' where "m = Footprint k" and "t = e_footprint # t'" and "(k, t', m') \<in> Traces"
| (Write_reg) reg v k t' where "m = Write_reg reg v k" and "t = e_write_reg reg v # t'" and "(k, t', m') \<in> Traces"
- | (Undefined) v k t' where "m = Undefined k" and "t = e_undefined v # t'" and "(k v, t', m') \<in> Traces"
+ | (Undefined) xs v k t' where "m = Undefined k" and "t = e_undefined v # t'" and "(k v, t', m') \<in> Traces"
| (Print) msg k t' where "m = Print msg k" and "t = e_print msg # t'" and "(k, t', m') \<in> Traces"
proof (use Run in \<open>cases m t m' set: Traces\<close>)
case Nil
@@ -129,6 +129,16 @@ lemma bind_T_cases:
| (Bind) m' where "s' = bind m' f" and "(m, e, m') \<in> T"
using assms by (cases; blast elim: bind.elims)
+lemma Run_bindI:
+ fixes m :: "('r, 'a, 'e) monad"
+ assumes "Run m t1 a1"
+ and "Run (f a1) t2 a2"
+ shows "Run (m \<bind> f) (t1 @ t2) a2"
+proof (use assms in \<open>induction m t1 "Done a1 :: ('r, 'a, 'e) monad" rule: Traces.induct\<close>)
+ case (Step s e s'' t)
+ then show ?case by (elim T.cases) auto
+qed auto
+
lemma Run_bindE:
fixes m :: "('rv, 'b, 'e) monad" and a :: 'a
assumes "Run (bind m f) t a"
@@ -161,6 +171,31 @@ lemma Run_DoneE:
lemma Run_Done_iff_Nil[simp]: "Run (Done a) t a' \<longleftrightarrow> t = [] \<and> a' = a"
by (auto elim: Run_DoneE)
+lemma Run_bindE_ignore_trace:
+ assumes "Run (m \<bind> f) t a"
+ obtains tm tf am where "Run m tm am" and "Run (f am) tf a"
+ using assms by (elim Run_bindE)
+
+lemma Run_letE:
+ assumes "Run (let x = y in f x) t a"
+ obtains "Run (f y) t a"
+ using assms by auto
+
+lemma Run_ifE:
+ assumes "Run (if b then f else g) t a"
+ obtains "b" and "Run f t a" | "\<not>b" and "Run g t a"
+ using assms by (auto split: if_splits)
+
+lemma Run_returnE:
+ assumes "Run (return x) t a"
+ obtains "t = []" and "a = x"
+ using assms by (auto simp: return_def)
+
+lemma Run_early_returnE:
+ assumes "Run (early_return x) t a"
+ shows P
+ using assms by (auto simp: early_return_def throw_def elim: Traces_cases)
+
lemma bind_cong[fundef_cong]:
assumes m: "m1 = m2"
and f: "\<And>t a. Run m2 t a \<Longrightarrow> f1 a = f2 a"
@@ -168,4 +203,10 @@ lemma bind_cong[fundef_cong]:
unfolding m using f
by (induction m2 f1 arbitrary: f2 rule: bind.induct; unfold bind.simps; blast)
+lemma liftR_read_reg[simp]: "liftR (read_reg reg) = read_reg reg" by (auto simp: read_reg_def liftR_def split: option.splits)
+lemma try_catch_return[simp]: "try_catch (return x) h = return x" by (auto simp: return_def)
+lemma liftR_return[simp]: "liftR (return x) = return x" by (auto simp: liftR_def)
+lemma liftR_undefined_bool[simp]: "liftR (undefined_bool ()) = undefined_bool ()" by (auto simp: undefined_bool_def liftR_def)
+lemma assert_exp_True_return[simp]: "assert_exp True msg = return ()" by (auto simp: assert_exp_def return_def)
+
end
diff --git a/lib/isabelle/Sail2_state_lemmas.thy b/lib/isabelle/Sail2_state_lemmas.thy
index 124722ab..ba69d0d8 100644
--- a/lib/isabelle/Sail2_state_lemmas.thy
+++ b/lib/isabelle/Sail2_state_lemmas.thy
@@ -23,6 +23,14 @@ lemma Value_liftState_Run:
lemmas liftState_if_distrib[liftState_simp] = if_distrib[where f = "liftState ra" for ra]
+lemma Value_bindS_iff:
+ "(Value b, s'') \<in> bindS m f s \<longleftrightarrow> (\<exists>a s'. (Value a, s') \<in> m s \<and> (Value b, s'') \<in> f a s')"
+ by (auto elim!: bindS_cases intro: bindS_intros)
+
+lemma Ex_bindS_iff:
+ "(Ex e, s'') \<in> bindS m f s \<longleftrightarrow> (Ex e, s'') \<in> m s \<or> (\<exists>a s'. (Value a, s') \<in> m s \<and> (Ex e, s'') \<in> f a s')"
+ by (auto elim!: bindS_cases intro: bindS_intros)
+
lemma liftState_throw[liftState_simp]: "liftState r (throw e) = throwS e"
by (auto simp: throw_def)
lemma liftState_assert[liftState_simp]: "liftState r (assert_exp c msg) = assert_expS c msg"
@@ -51,7 +59,7 @@ lemma liftState_try_catch[liftState_simp]:
by (induction m h rule: try_catch_induct) (auto simp: try_catchS_bindS_no_throw)
lemma liftState_early_return[liftState_simp]:
- "liftState r (early_return r) = early_returnS r"
+ "liftState r (early_return x) = early_returnS x"
by (auto simp: early_return_def early_returnS_def liftState_simp)
lemma liftState_catch_early_return[liftState_simp]:
@@ -66,6 +74,10 @@ lemma liftState_try_catchR[liftState_simp]:
"liftState r (try_catchR m h) = try_catchRS (liftState r m) (liftState r \<circ> h)"
by (auto simp: try_catchR_def try_catchRS_def sum.case_distrib liftState_simp cong: sum.case_cong)
+lemma liftState_bool_of_bitU_nondet[liftState_simp]:
+ "liftState r (bool_of_bitU_nondet b) = bool_of_bitU_nondetS b"
+ by (cases b; auto simp: bool_of_bitU_nondet_def bool_of_bitU_nondetS_def liftState_simp)
+
lemma liftState_read_mem_BC:
assumes "unsigned_method BC_bitU_list (bits_of_method BCa a) = unsigned_method BCa a"
shows "liftState r (read_mem BCa BCb rk a sz) = read_memS BCa BCb rk a sz"
@@ -87,7 +99,7 @@ lemma liftState_write_mem_ea[liftState_simp]:
"\<And>a. liftState r (write_mem_ea BC_bitU_list rk a sz) = write_mem_eaS BC_bitU_list rk a (nat sz)"
by (auto simp: liftState_write_mem_ea_BC)
-lemma liftState_write_mem_val:
+lemma liftState_write_mem_val[liftState_simp]:
"liftState r (write_mem_val BC v) = write_mem_valS BC v"
by (auto simp: write_mem_val_def write_mem_valS_def liftState_simp split: option.splits)
@@ -126,6 +138,80 @@ lemma liftState_foreachM[liftState_simp]:
by (induction xs vars "\<lambda>x vars. liftState r (body x vars)" rule: foreachS.induct)
(auto simp: liftState_simp cong: bindS_cong)
+lemma liftState_bools_of_bits_nondet[liftState_simp]:
+ "liftState r (bools_of_bits_nondet bs) = bools_of_bits_nondetS bs"
+ unfolding bools_of_bits_nondet_def bools_of_bits_nondetS_def
+ by (auto simp: liftState_simp comp_def)
+
+lemma liftState_internal_pick[liftState_simp]:
+ "liftState r (internal_pick xs) = internal_pickS xs"
+ by (auto simp: internal_pick_def internal_pickS_def liftState_simp comp_def
+ option.case_distrib[where h = "liftState r"]
+ simp del: repeat.simps
+ cong: option.case_cong)
+
+lemma liftRS_returnS[simp]: "liftRS (returnS x) = returnS x"
+ by (auto simp: liftRS_def)
+
+lemma liftRS_bindS:
+ fixes m :: "('regs, 'a, 'e) monadS" and f :: "'a \<Rightarrow> ('regs, 'b, 'e) monadS"
+ shows "(liftRS (bindS m f) :: ('regs, 'b, 'r, 'e) monadRS) = bindS (liftRS m) (liftRS \<circ> f)"
+proof (intro ext set_eqI iffI)
+ fix s and rs' :: "('b, 'r + 'e) result \<times> 'regs sequential_state"
+ assume lhs: "rs' \<in> liftRS (bindS m f) s"
+ then show "rs' \<in> bindS (liftRS m) (liftRS \<circ> f) s"
+ by (cases rs')
+ (fastforce simp: liftRS_def throwS_def elim!: bindS_cases try_catchS_cases
+ intro: bindS_intros try_catchS_intros)
+next
+ fix s and rs' :: "('b, 'r + 'e) result \<times> 'regs sequential_state"
+ assume "rs' \<in> bindS (liftRS m) (liftRS \<circ> f) s"
+ then show "rs' \<in> liftRS (bindS m f) s"
+ by (cases rs')
+ (fastforce simp: liftRS_def throwS_def elim!: bindS_cases try_catchS_cases
+ intro: bindS_intros try_catchS_intros)
+qed
+
+lemma liftRS_assert_expS_True[simp]: "liftRS (assert_expS True msg) = returnS ()"
+ by (auto simp: liftRS_def assert_expS_def)
+
+lemma untilM_domI:
+ fixes V :: "'vars \<Rightarrow> nat"
+ assumes "Inv vars"
+ and "\<And>vars t vars' t'. \<lbrakk>Inv vars; Run (body vars) t vars'; Run (cond vars') t' False\<rbrakk> \<Longrightarrow> V vars' < V vars \<and> Inv vars'"
+ shows "untilM_dom (vars, cond, body)"
+ using assms
+ by (induction vars rule: measure_induct_rule[where f = V])
+ (auto intro: untilM.domintros)
+
+lemma untilM_dom_untilS_dom:
+ assumes "untilM_dom (vars, cond, body)"
+ shows "untilS_dom (vars, liftState r \<circ> cond, liftState r \<circ> body, s)"
+ using assms
+ by (induction vars cond body arbitrary: s rule: untilM.pinduct)
+ (rule untilS.domintros, auto elim!: Value_liftState_Run)
+
+lemma measure2_induct:
+ fixes f :: "'a \<Rightarrow> 'b \<Rightarrow> nat"
+ assumes "\<And>x1 y1. (\<And>x2 y2. f x2 y2 < f x1 y1 \<Longrightarrow> P x2 y2) \<Longrightarrow> P x1 y1"
+ shows "P x y"
+proof -
+ have "P (fst x) (snd x)" for x
+ by (induction x rule: measure_induct_rule[where f = "\<lambda>x. f (fst x) (snd x)"]) (auto intro: assms)
+ then show ?thesis by auto
+qed
+
+lemma untilS_domI:
+ fixes V :: "'vars \<Rightarrow> 'regs sequential_state \<Rightarrow> nat"
+ assumes "Inv vars s"
+ and "\<And>vars s vars' s' s''.
+ \<lbrakk>Inv vars s; (Value vars', s') \<in> body vars s; (Value False, s'') \<in> cond vars' s'\<rbrakk>
+ \<Longrightarrow> V vars' s'' < V vars s \<and> Inv vars' s''"
+ shows "untilS_dom (vars, cond, body, s)"
+ using assms
+ by (induction vars s rule: measure2_induct[where f = V])
+ (auto intro: untilS.domintros)
+
lemma whileS_dom_step:
assumes "whileS_dom (vars, cond, body, s)"
and "(Value True, s') \<in> cond vars s"
@@ -230,6 +316,9 @@ lemma and_boolM_return_if:
"and_boolM (return b) y = (if b then y else return False)"
by (auto simp: and_boolM_def)
+lemma and_boolM_return_return_and[simp]: "and_boolM (return l) (return r) = return (l \<and> r)"
+ by (auto simp: and_boolM_def)
+
lemmas and_boolM_if_distrib[simp] = if_distrib[where f = "\<lambda>x. and_boolM x y" for y]
lemma or_boolM_simps[simp]:
@@ -243,6 +332,9 @@ lemma or_boolM_return_if:
"or_boolM (return b) y = (if b then return True else y)"
by (auto simp: or_boolM_def)
+lemma or_boolM_return_return_or[simp]: "or_boolM (return l) (return r) = return (l \<or> r)"
+ by (auto simp: or_boolM_def)
+
lemmas or_boolM_if_distrib[simp] = if_distrib[where f = "\<lambda>x. or_boolM x y" for y]
lemma if_returnS_returnS[simp]: "(if a then returnS True else returnS False) = returnS a" by auto
@@ -260,8 +352,12 @@ lemma and_boolS_returnS_if:
lemmas and_boolS_if_distrib[simp] = if_distrib[where f = "\<lambda>x. and_boolS x y" for y]
+lemma and_boolS_returnS_True[simp]: "and_boolS (returnS True) c = c"
+ by (auto simp: and_boolS_def)
+
lemma or_boolS_simps[simp]:
"or_boolS (returnS b) (returnS c) = returnS (b \<or> c)"
+ "or_boolS (returnS False) m = m"
"or_boolS x (returnS True) = bindS x (\<lambda>_. returnS True)"
"or_boolS x (returnS False) = x"
"\<And>x y z. or_boolS (bindS x y) z = (bindS x (\<lambda>r. or_boolS (y r) z))"
@@ -273,4 +369,19 @@ lemma or_boolS_returnS_if:
lemmas or_boolS_if_distrib[simp] = if_distrib[where f = "\<lambda>x. or_boolS x y" for y]
+lemma Run_or_boolM_E:
+ assumes "Run (or_boolM l r) t a"
+ obtains "Run l t True" and "a"
+ | tl tr where "Run l tl False" and "Run r tr a" and "t = tl @ tr"
+ using assms by (auto simp: or_boolM_def elim!: Run_bindE Run_ifE Run_returnE)
+
+lemma Run_and_boolM_E:
+ assumes "Run (and_boolM l r) t a"
+ obtains "Run l t False" and "\<not>a"
+ | tl tr where "Run l tl True" and "Run r tr a" and "t = tl @ tr"
+ using assms by (auto simp: and_boolM_def elim!: Run_bindE Run_ifE Run_returnE)
+
+lemma maybe_failS_Some[simp]: "maybe_failS msg (Some v) = returnS v"
+ by (auto simp: maybe_failS_def)
+
end
diff --git a/lib/isabelle/Sail2_state_monad_lemmas.thy b/lib/isabelle/Sail2_state_monad_lemmas.thy
index b705de4c..3a286c10 100644
--- a/lib/isabelle/Sail2_state_monad_lemmas.thy
+++ b/lib/isabelle/Sail2_state_monad_lemmas.thy
@@ -8,6 +8,9 @@ begin
notes returnS_def[simp] and failS_def[simp] and throwS_def[simp] and readS_def[simp] and updateS_def[simp]
begin*)
+notation bindS (infixr "\<bind>\<^sub>S" 54)
+notation seqS (infixr "\<then>\<^sub>S" 54)
+
lemma bindS_ext_cong[fundef_cong]:
assumes m: "m1 s = m2 s"
and f: "\<And>a s'. (Value a, s') \<in> (m2 s) \<Longrightarrow> f1 a s' = f2 a s'"
@@ -35,6 +38,9 @@ lemma bindS_updateS: "bindS (updateS f) m = (\<lambda>s. m () (f s))"
lemma bindS_assertS_True[simp]: "bindS (assert_expS True msg) f = f ()"
by (auto simp: assert_expS_def)
+lemma bindS_chooseS_returnS[simp]: "bindS (chooseS xs) (\<lambda>x. returnS (f x)) = chooseS (f ` xs)"
+ by (intro ext) (auto simp: bindS_def chooseS_def returnS_def)
+
lemma result_cases:
fixes r :: "('a, 'e) result"
diff --git a/lib/isabelle/Sail2_values_lemmas.thy b/lib/isabelle/Sail2_values_lemmas.thy
index b50d8942..576cd8ea 100644
--- a/lib/isabelle/Sail2_values_lemmas.thy
+++ b/lib/isabelle/Sail2_values_lemmas.thy
@@ -2,18 +2,135 @@ theory Sail2_values_lemmas
imports Sail2_values
begin
+lemma while_domI:
+ fixes V :: "'vars \<Rightarrow> nat"
+ assumes "\<And>vars. cond vars \<Longrightarrow> V (body vars) < V vars"
+ shows "while_dom (vars, cond, body)"
+ by (induction vars rule: measure_induct_rule[where f = V])
+ (use assms in \<open>auto intro: while.domintros\<close>)
+
lemma nat_of_int_nat_simps[simp]: "nat_of_int = nat" by (auto simp: nat_of_int_def)
termination reverse_endianness_list by (lexicographic_order simp add: drop_list_def)
+declare reverse_endianness_list.simps[simp del]
+declare take_list_def[simp]
+declare drop_list_def[simp]
+
+function take_chunks :: "nat \<Rightarrow> 'a list \<Rightarrow> 'a list list" where
+ "take_chunks n [] = []"
+| "take_chunks 0 xs = []"
+| "take_chunks n xs = take n xs # take_chunks n (drop n xs)" if "n > 0" and "xs \<noteq> []"
+ by auto blast
+termination by lexicographic_order
+
+lemma take_chunks_length_leq_n: "length xs \<le> n \<Longrightarrow> xs \<noteq> [] \<Longrightarrow> take_chunks n xs = [xs]"
+ by (cases n) auto
+
+lemma take_chunks_append: "n dvd length a \<Longrightarrow> take_chunks n (a @ b) = take_chunks n a @ take_chunks n b"
+ by (induction n a rule: take_chunks.induct) (auto simp: dvd_imp_le)
+
+lemma Suc8_plus8: "Suc (Suc (Suc (Suc (Suc (Suc (Suc (Suc x))))))) = 8 + x"
+ by auto
+
+lemma byte_chunks_take_chunks_8:
+ assumes "8 dvd length xs"
+ shows "byte_chunks xs = Some (take_chunks 8 xs)"
+proof -
+ have Suc8_plus8: "Suc (Suc (Suc (Suc (Suc (Suc (Suc (Suc x))))))) = 8 + x" for x
+ by auto
+ from assms show ?thesis
+ by (induction xs rule: byte_chunks.induct) (auto simp: Suc8_plus8 nat_dvd_not_less)
+qed
+
+lemma reverse_endianness_list_rev_take_chunks:
+ "reverse_endianness_list bits = List.concat (rev (take_chunks 8 bits))"
+ by (induction "8 :: nat" bits rule: take_chunks.induct)
+ (auto simp: reverse_endianness_list.simps)
+
+lemma reverse_endianness_list_simps:
+ "length bits \<le> 8 \<Longrightarrow> reverse_endianness_list bits = bits"
+ "length bits > 8 \<Longrightarrow> reverse_endianness_list bits = reverse_endianness_list (drop 8 bits) @ take 8 bits"
+ by (cases bits; auto simp: reverse_endianness_list_rev_take_chunks)+
+
+lemma reverse_endianness_list_append:
+ assumes "8 dvd length a"
+ shows "reverse_endianness_list (a @ b) = reverse_endianness_list b @ reverse_endianness_list a"
+ using assms by (auto simp: reverse_endianness_list_rev_take_chunks take_chunks_append)
+
+lemma length_reverse_endianness_list[simp]:
+ "length (reverse_endianness_list l) = length l"
+ by (induction l rule: reverse_endianness_list.induct) (auto simp: reverse_endianness_list.simps)
+
+lemma reverse_endianness_list_take_8[simp]:
+ "reverse_endianness_list (take 8 bits) = take 8 bits"
+ by (auto simp: reverse_endianness_list_simps)
+
+lemma reverse_reverse_endianness_list[simp]:
+ assumes "8 dvd length l"
+ shows "reverse_endianness_list (reverse_endianness_list l) = l"
+proof (use assms in \<open>induction l rule: reverse_endianness_list.induct[case_names Step]\<close>)
+ case (Step bits)
+ then show ?case
+ by (auto simp: reverse_endianness_list.simps[of bits] reverse_endianness_list_append)
+qed
+
+declare repeat.simps[simp del]
+
+lemma length_repeat[simp]: "length (repeat xs n) = nat n * length xs"
+proof (induction xs n rule: repeat.induct[case_names Step])
+ case (Step xs n)
+ then show ?case unfolding repeat.simps[of xs n]
+ by (auto simp del: mult_Suc simp: mult_Suc[symmetric])
+qed
+
+lemma nth_repeat:
+ assumes "i < nat n * length xs"
+ shows "repeat xs n ! i = xs ! (i mod length xs)"
+proof (use assms in \<open>induction xs n arbitrary: i rule: repeat.induct[case_names Step]\<close>)
+ case (Step xs n i)
+ show ?case
+ using Step.prems Step.IH[of "i - length xs"]
+ unfolding repeat.simps[of xs n]
+ by (auto simp: nth_append mod_geq[symmetric] nat_diff_distrib diff_mult_distrib)
+qed
termination index_list
by (relation "measure (\<lambda>(i, j, step). nat ((j - i + step) * sgn step))") auto
+lemma index_list_Zero[simp]: "index_list i j 0 = []"
+ by auto
+
+lemma index_list_singleton[simp]: "n \<noteq> 0 \<Longrightarrow> index_list i i n = [i]"
+ by auto
+
+lemma index_list_simps:
+ "0 < step \<Longrightarrow> from \<le> to \<Longrightarrow> index_list from to step = from # index_list (from + step) to step"
+ "0 < step \<Longrightarrow> from > to \<Longrightarrow> index_list from to step = []"
+ "0 > step \<Longrightarrow> from \<ge> to \<Longrightarrow> index_list from to step = from # index_list (from + step) to step"
+ "0 > step \<Longrightarrow> from < to \<Longrightarrow> index_list from to step = []"
+ by auto
+
+lemma index_list_step1_upto[simp]: "index_list i j 1 = [i..j]"
+ by (induction i j "1 :: int" rule: index_list.induct)
+ (auto simp: index_list_simps upto.simps)
+
+lemma length_upto[simp]: "i \<le> j \<Longrightarrow> length [i..j] = nat (j - i + 1)"
+ by (induction i j rule: upto.induct) (auto simp: upto.simps)
+
+lemma nth_upto[simp]: "i + int n \<le> j \<Longrightarrow> [i..j] ! n = i + int n"
+ by (induction i j arbitrary: n rule: upto.induct)
+ (auto simp: upto.simps nth_Cons split: nat.splits)
+
+declare index_list.simps[simp del]
+
lemma just_list_map_Some[simp]: "just_list (map Some v) = Some v" by (induction v) auto
lemma just_list_None_iff[simp]: "just_list xs = None \<longleftrightarrow> None \<in> set xs"
by (induction xs) (auto split: option.splits)
+lemma just_list_None_member_None: "None \<in> set xs \<Longrightarrow> just_list xs = None"
+ by auto
+
lemma just_list_Some_iff[simp]: "just_list xs = Some ys \<longleftrightarrow> xs = map Some ys"
by (induction xs arbitrary: ys) (auto split: option.splits)
@@ -28,10 +145,10 @@ lemma repeat_singleton_replicate[simp]:
proof (induction n)
case (nonneg n)
have "nat (1 + int m) = Suc m" for m by auto
- then show ?case by (induction n) auto
+ then show ?case by (induction n) (auto simp: repeat.simps)
next
case (neg n)
- then show ?case by auto
+ then show ?case by (auto simp: repeat.simps)
qed
lemma bool_of_bitU_simps[simp]:
@@ -102,6 +219,15 @@ lemma unsigned_bits_of_mword[simp]:
"unsigned_method BC_bitU_list (bits_of_method BC_mword a) = Some (uint a)"
by (auto simp: BC_bitU_list_def BC_mword_defs unsigned_of_bits_def unsigned_of_bools_def)
+definition mem_bytes_of_word :: "'a::len word \<Rightarrow> bitU list list" where
+ "mem_bytes_of_word w = rev (take_chunks 8 (map bitU_of_bool (to_bl w)))"
+
+lemma mem_bytes_of_bits_mem_bytes_of_word[simp]:
+ assumes "8 dvd LENGTH('a)"
+ shows "mem_bytes_of_bits BC_mword (w :: 'a::len word) = Some (mem_bytes_of_word w)"
+ using assms
+ by (auto simp: mem_bytes_of_bits_def bytes_of_bits_def BC_mword_defs byte_chunks_take_chunks_8 mem_bytes_of_word_def)
+
lemma bits_of_bitU_list[simp]:
"bits_of_method BC_bitU_list v = v"
"of_bits_method BC_bitU_list v = Some v"
@@ -158,6 +284,14 @@ lemma update_list_dec_update[simp]:
"update_list_dec xs n x = xs[length xs - nat (n + 1) := x]"
by (auto simp: update_list_dec_def add.commute diff_diff_add nat_minus_as_int)
+lemma update_list_dec_update_rev:
+ "0 \<le> n \<Longrightarrow> nat n < length xs \<Longrightarrow> update_list_dec xs n x = rev ((rev xs)[nat n := x])"
+ by (auto simp: update_list_dec_def add.commute diff_diff_add nat_minus_as_int rev_update)
+
+lemma access_list_dec_update_list_dec[simp]:
+ "0 \<le> n \<Longrightarrow> nat n < length xs \<Longrightarrow> access_list_dec (update_list_dec xs n x) n = x"
+ by (auto simp: access_list_dec_rev_nth update_list_dec_update_rev)
+
lemma bools_of_nat_aux_simps[simp]:
"\<And>len. len \<le> 0 \<Longrightarrow> bools_of_nat_aux len x acc = acc"
"\<And>len. bools_of_nat_aux (int (Suc len)) x acc =
@@ -200,7 +334,7 @@ proof (induction len arbitrary: n acc)
qed auto
lemma bools_of_int_bin_to_bl[simp]:
- "bools_of_int (int len) n = bin_to_bl len n"
+ "bools_of_int len n = bin_to_bl (nat len) n"
by (auto simp: bools_of_int_def Let_def map_Not_bin_to_bl rbl_succ[unfolded bin_to_bl_def])
end
diff --git a/lib/isabelle/manual/Manual.thy b/lib/isabelle/manual/Manual.thy
index 6cd90a9a..0d67f6c5 100644
--- a/lib/isabelle/manual/Manual.thy
+++ b/lib/isabelle/manual/Manual.thy
@@ -168,8 +168,8 @@ following variants:
\<^item> @{term quot_vec_maybe} returns an option type, with
@{lemma "quot_vec_maybe w 0 = None" by (auto simp: quot_vec_maybe_def quot_bv_def arith_op_bv_no0_def)}.
\<^item> @{term quot_vec_fail} is monadic and either returns the result or raises an exception.
- \<^item> @{term quot_vec_oracle} is monadic and uses the @{term Undefined} effect in the exception case
- to fill the result with bits drawn from a bitstream oracle.
+ \<^item> @{term quot_vec_nondet} is monadic and uses the @{term Undefined} effect in the exception case
+ to fill the result with bits chosen nondeterministically.
\<^item> @{term quot_vec} is pure and returns an arbitrary (but fixed) value in the exception case,
currently defined as follows: For the bitlist representation of bitvectors,
@{term "quot_vec w 0"} returns a list filled with @{term BU}, while for the machine word
@@ -263,9 +263,6 @@ The @{type sequential_state} record has the following fields:
of the last announced memory write, if any.
\<^item> The @{term last_exclusive_operation_was_load} flag is used to determine whether exclusive
operations can succeed.
- \<^item> The function stored in the @{term next_bool} field together with the seed in the @{term seed}
- field are used as a random bit generator for undefined values. The @{term next_bool}
- function takes the current seed as an argument and returns a @{type bool} and the next seed.
The library defines several combinators and wrappers in addition to the standard monadic bind and
return (called @{term bindS} and @{term returnS} here, where the suffix @{term S} differentiates them
diff --git a/lib/main.ml b/lib/main.ml
index e9dcb4e0..c1b6fcae 100644
--- a/lib/main.ml
+++ b/lib/main.ml
@@ -1,4 +1,3 @@
-
(**************************************************************************)
(* Sail *)
(* *)
diff --git a/lib/mono_rewrites.sail b/lib/mono_rewrites.sail
index c9164b6c..aa8d05cd 100644
--- a/lib/mono_rewrites.sail
+++ b/lib/mono_rewrites.sail
@@ -42,14 +42,14 @@ val is_zero_subrange : forall 'n, 'n >= 0.
(bits('n), int, int) -> bool effect pure
function is_zero_subrange (xs, i, j) = {
- (xs & slice_mask(j, i-j)) == extzv(0b0)
+ (xs & slice_mask(j, i-j+1)) == extzv(0b0)
}
val is_ones_subrange : forall 'n, 'n >= 0.
(bits('n), int, int) -> bool effect pure
function is_ones_subrange (xs, i, j) = {
- let m : bits('n) = slice_mask(j,j-i) in
+ let m : bits('n) = slice_mask(j,j-i+1) in
(xs & m) == m
}
@@ -76,8 +76,8 @@ val subrange_subrange_eq : forall 'n, 'n >= 0.
(bits('n), int, int, bits('n), int, int) -> bool effect pure
function subrange_subrange_eq (xs, i, j, ys, i', j') = {
- let xs = (xs & slice_mask(j,i-j)) >> j in
- let ys = (ys & slice_mask(j',i'-j')) >> j' in
+ let xs = (xs & slice_mask(j,i-j+1)) >> j in
+ let ys = (ys & slice_mask(j',i'-j'+1)) >> j' in
xs == ys
}
@@ -85,16 +85,16 @@ val subrange_subrange_concat : forall 'n 'o 'p 'm 'q 'r 's, 's = 'o - ('p - 1) +
(bits('n), atom('o), atom('p), bits('m), atom('q), atom('r)) -> bits('s) effect pure
function subrange_subrange_concat (xs, i, j, ys, i', j') = {
- let xs = (xs & slice_mask(j,i-j)) >> j in
- let ys = (ys & slice_mask(j',i'-j')) >> j' in
- extzv(xs) << i' - (j' - 1) | extzv(ys)
+ let xs = (xs & slice_mask(j,i-j+1)) >> j in
+ let ys = (ys & slice_mask(j',i'-j'+1)) >> j' in
+ extzv(xs) << (i' - j' + 1) | extzv(ys)
}
val place_subrange : forall 'n 'm, 'n >= 0 & 'm >= 0.
(bits('n), int, int, int) -> bits('m) effect pure
function place_subrange(xs,i,j,shift) = {
- let xs = (xs & slice_mask(j,i-j)) >> j in
+ let xs = (xs & slice_mask(j,i-j+1)) >> j in
extzv(xs) << shift
}
@@ -144,7 +144,7 @@ val unsigned_subrange : forall 'n, 'n >= 0.
(bits('n), int, int) -> int effect pure
function unsigned_subrange(xs,i,j) = {
- let xs = (xs & slice_mask(j,i-j)) >> i in
+ let xs = (xs & slice_mask(j,i-j+1)) >> i in
_builtin_unsigned(xs)
}
diff --git a/lib/regfp.sail b/lib/regfp.sail
index b8cffb98..fcf10850 100644
--- a/lib/regfp.sail
+++ b/lib/regfp.sail
@@ -75,6 +75,10 @@ enum barrier_kind = {
Barrier_RISCV_r_r,
Barrier_RISCV_rw_w,
Barrier_RISCV_w_w,
+ Barrier_RISCV_w_rw,
+ Barrier_RISCV_rw_r,
+ Barrier_RISCV_r_w,
+ Barrier_RISCV_w_r,
Barrier_RISCV_i,
Barrier_x86_MFENCE
}
diff --git a/lib/rts.c b/lib/rts.c
index 23e16921..729e2a8b 100644
--- a/lib/rts.c
+++ b/lib/rts.c
@@ -7,7 +7,7 @@
#include"elf.h"
static uint64_t g_elf_entry;
-static uint64_t g_cycle_count = 0;
+uint64_t g_cycle_count = 0;
static uint64_t g_cycle_limit;
void sail_match_failure(sail_string msg)
@@ -208,7 +208,7 @@ void kill_mem()
// ***** Memory builtins *****
-unit write_ram(const mpz_t addr_size, // Either 32 or 64
+bool write_ram(const mpz_t addr_size, // Either 32 or 64
const mpz_t data_size_mpz, // Number of bytes
const sail_bits hex_ram, // Currently unused
const sail_bits addr_bv,
@@ -231,7 +231,7 @@ unit write_ram(const mpz_t addr_size, // Either 32 or 64
}
mpz_clear(buf);
- return UNIT;
+ return true;
}
void read_ram(sail_bits *data,
@@ -427,7 +427,7 @@ bool cycle_limit_reached(const unit u)
unit cycle_count(const unit u)
{
if (cycle_limit_reached(UNIT)) {
- printf("\n[Sail] cycle limit %" PRId64 " reached\n", g_cycle_limit);
+ printf("\n[Sail] TIMEOUT: exceeded %" PRId64 " cycles\n", g_cycle_limit);
exit(EXIT_SUCCESS);
}
return UNIT;
diff --git a/lib/rts.h b/lib/rts.h
index cedb555e..98bbd078 100644
--- a/lib/rts.h
+++ b/lib/rts.h
@@ -53,7 +53,7 @@ uint64_t read_mem(uint64_t);
// These memory builtins are intended to match the semantics for the
// __ReadRAM and __WriteRAM functions in ASL.
-unit write_ram(const mpz_t addr_size, // Either 32 or 64
+bool write_ram(const mpz_t addr_size, // Either 32 or 64
const mpz_t data_size_mpz, // Number of bytes
const sail_bits hex_ram, // Currently unused
const sail_bits addr_bv,
diff --git a/lib/sail.c b/lib/sail.c
index 4e5694e9..38c8c273 100644
--- a/lib/sail.c
+++ b/lib/sail.c
@@ -1,3 +1,4 @@
+#include<assert.h>
#include<inttypes.h>
#include<stdbool.h>
#include<stdio.h>
@@ -34,7 +35,7 @@ void cleanup_library(void)
mpq_clear(sail_lib_tmp_real);
}
-bool eq_unit(const unit a, const unit b)
+bool EQUAL(unit)(const unit a, const unit b)
{
return true;
}
@@ -62,7 +63,7 @@ bool not(const bool b) {
return !b;
}
-bool eq_bool(const bool a, const bool b) {
+bool EQUAL(bool)(const bool a, const bool b) {
return a == b;
}
@@ -116,6 +117,11 @@ bool eq_string(const sail_string str1, const sail_string str2)
return strcmp(str1, str2) == 0;
}
+bool EQUAL(sail_string)(const sail_string str1, const sail_string str2)
+{
+ return strcmp(str1, str2) == 0;
+}
+
void undefined_string(sail_string *str, const unit u) {}
void concat_str(sail_string *stro, const sail_string str1, const sail_string str2)
@@ -128,6 +134,12 @@ void concat_str(sail_string *stro, const sail_string str1, const sail_string str
/* ***** Sail integers ***** */
+inline
+bool EQUAL(mach_int)(const mach_int op1, const mach_int op2)
+{
+ return op1 == op2;
+}
+
#ifndef USE_INT128
inline
@@ -197,6 +209,12 @@ bool eq_int(const sail_int op1, const sail_int op2)
}
inline
+bool EQUAL(sail_int)(const sail_int op1, const sail_int op2)
+{
+ return !abs(mpz_cmp(op1, op2));
+}
+
+inline
bool lt(const sail_int op1, const sail_int op2)
{
return mpz_cmp(op1, op2) < 0;
@@ -329,6 +347,11 @@ void pow2(sail_int *rop, const sail_int exp) {
/* ***** Sail bitvectors ***** */
+bool EQUAL(mach_bits)(const mach_bits op1, const mach_bits op2)
+{
+ return op1 == op2;
+}
+
void CREATE(sail_bits)(sail_bits *rop)
{
rop->bits = malloc(sizeof(mpz_t));
@@ -419,6 +442,7 @@ void add_bits(sail_bits *rop, const sail_bits op1, const sail_bits op2)
void sub_bits(sail_bits *rop, const sail_bits op1, const sail_bits op2)
{
+ assert(op1.len == op2.len);
rop->len = op1.len;
mpz_sub(*rop->bits, *op1.bits, *op2.bits);
normalize_sail_bits(rop);
@@ -440,18 +464,21 @@ void sub_bits_int(sail_bits *rop, const sail_bits op1, const mpz_t op2)
void and_bits(sail_bits *rop, const sail_bits op1, const sail_bits op2)
{
+ assert(op1.len == op2.len);
rop->len = op1.len;
mpz_and(*rop->bits, *op1.bits, *op2.bits);
}
void or_bits(sail_bits *rop, const sail_bits op1, const sail_bits op2)
{
+ assert(op1.len == op2.len);
rop->len = op1.len;
mpz_ior(*rop->bits, *op1.bits, *op2.bits);
}
void xor_bits(sail_bits *rop, const sail_bits op1, const sail_bits op2)
{
+ assert(op1.len == op2.len);
rop->len = op1.len;
mpz_xor(*rop->bits, *op1.bits, *op2.bits);
}
@@ -495,12 +522,14 @@ void zeros(sail_bits *rop, const sail_int op)
void zero_extend(sail_bits *rop, const sail_bits op, const sail_int len)
{
+ assert(op.len <= mpz_get_ui(len));
rop->len = mpz_get_ui(len);
mpz_set(*rop->bits, *op.bits);
}
void sign_extend(sail_bits *rop, const sail_bits op, const sail_int len)
{
+ assert(op.len <= mpz_get_ui(len));
rop->len = mpz_get_ui(len);
if(mpz_tstbit(*op.bits, op.len - 1)) {
mpz_set(*rop->bits, *op.bits);
@@ -519,14 +548,21 @@ void length_sail_bits(sail_int *rop, const sail_bits op)
bool eq_bits(const sail_bits op1, const sail_bits op2)
{
+ assert(op1.len == op2.len);
for (mp_bitcnt_t i = 0; i < op1.len; i++) {
if (mpz_tstbit(*op1.bits, i) != mpz_tstbit(*op2.bits, i)) return false;
}
return true;
}
+bool EQUAL(sail_bits)(const sail_bits op1, const sail_bits op2)
+{
+ return eq_bits(op1, op2);
+}
+
bool neq_bits(const sail_bits op1, const sail_bits op2)
{
+ assert(op1.len == op2.len);
for (mp_bitcnt_t i = 0; i < op1.len; i++) {
if (mpz_tstbit(*op1.bits, i) != mpz_tstbit(*op2.bits, i)) return true;
}
@@ -548,6 +584,7 @@ void vector_subrange_sail_bits(sail_bits *rop,
void sail_truncate(sail_bits *rop, const sail_bits op, const sail_int len)
{
+ assert(op.len >= mpz_get_ui(len));
rop->len = mpz_get_ui(len);
mpz_set(*rop->bits, *op.bits);
normalize_sail_bits(rop);
@@ -594,8 +631,8 @@ void replicate_bits(sail_bits *rop, const sail_bits op1, const mpz_t op2)
{
uint64_t op2_ui = mpz_get_ui(op2);
rop->len = op1.len * op2_ui;
- mpz_set(*rop->bits, *op1.bits);
- for (int i = 1; i < op2_ui; i++) {
+ mpz_set_ui(*rop->bits, 0);
+ for (int i = 0; i < op2_ui; i++) {
mpz_mul_2exp(*rop->bits, *rop->bits, op1.len);
mpz_ior(*rop->bits, *rop->bits, *op1.bits);
}
@@ -670,6 +707,7 @@ void vector_update_subrange_sail_bits(sail_bits *rop,
uint64_t m = mpz_get_ui(m_mpz);
mpz_set(*rop->bits, *op.bits);
+ rop->len = op.len;
for (uint64_t i = 0; i < n - (m - 1ul); i++) {
if (mpz_tstbit(*slice.bits, i)) {
@@ -682,10 +720,11 @@ void vector_update_subrange_sail_bits(sail_bits *rop,
void slice(sail_bits *rop, const sail_bits op, const sail_int start_mpz, const sail_int len_mpz)
{
+ assert(mpz_get_ui(start_mpz) + mpz_get_ui(len_mpz) <= op.len);
uint64_t start = mpz_get_ui(start_mpz);
uint64_t len = mpz_get_ui(len_mpz);
- mpz_set_ui(*rop->bits, 0ul);
+ mpz_set_ui(*rop->bits, 0);
rop->len = len;
for (uint64_t i = 0; i < len; i++) {
@@ -742,6 +781,19 @@ void shift_bits_right_arith(sail_bits *rop, const sail_bits op1, const sail_bits
}
}
+void shiftl(sail_bits *rop, const sail_bits op1, const sail_int op2)
+{
+ rop->len = op1.len;
+ mpz_mul_2exp(*rop->bits, *op1.bits, mpz_get_ui(op2));
+ normalize_sail_bits(rop);
+}
+
+void shiftr(sail_bits *rop, const sail_bits op1, const sail_int op2)
+{
+ rop->len = op1.len;
+ mpz_tdiv_q_2exp(*rop->bits, *op1.bits, mpz_get_ui(op2));
+}
+
void reverse_endianness(sail_bits *rop, const sail_bits op)
{
rop->len = op.len;
@@ -916,7 +968,7 @@ void to_real(real *rop, const sail_int op)
mpq_canonicalize(*rop);
}
-bool eq_real(const real op1, const real op2)
+bool EQUAL(real)(const real op1, const real op2)
{
return mpq_cmp(op1, op2) == 0;
}
diff --git a/lib/sail.h b/lib/sail.h
index dce4eea0..9ce3ec6b 100644
--- a/lib/sail.h
+++ b/lib/sail.h
@@ -30,6 +30,7 @@ void cleanup_library(void);
#define COPY(type) copy_ ## type
#define KILL(type) kill_ ## type
#define UNDEFINED(type) undefined_ ## type
+#define EQUAL(type) eq_ ## type
#define SAIL_BUILTIN_TYPE(type)\
void create_ ## type(type *);\
@@ -44,7 +45,7 @@ typedef int unit;
#define UNIT 0
unit UNDEFINED(unit)(const unit);
-bool eq_unit(const unit, const unit);
+bool EQUAL(unit)(const unit, const unit);
unit skip(const unit);
@@ -55,7 +56,7 @@ unit skip(const unit);
* short-circuiting evaluation.
*/
bool not(const bool);
-bool eq_bool(const bool, const bool);
+bool EQUAL(bool)(const bool, const bool);
bool UNDEFINED(bool)(const unit);
/* ***** Sail strings ***** */
@@ -73,6 +74,7 @@ void hex_str(sail_string *str, const mpz_t n);
void undefined_string(sail_string *str, const unit u);
bool eq_string(const sail_string, const sail_string);
+bool EQUAL(sail_string)(const sail_string, const sail_string);
void concat_str(sail_string *stro, const sail_string str1, const sail_string str2);
@@ -80,6 +82,8 @@ void concat_str(sail_string *stro, const sail_string str1, const sail_string str
typedef int64_t mach_int;
+bool EQUAL(mach_int)(const mach_int, const mach_int);
+
/*
* Integers can be either stack-allocated as 128-bit integers if
* __int128 is available, or use GMP arbitrary precision
@@ -114,6 +118,7 @@ typedef __int128 sail_int;
* Comparison operators for integers
*/
bool eq_int(const sail_int, const sail_int);
+bool EQUAL(sail_int)(const sail_int, const sail_int);
bool lt(const sail_int, const sail_int);
bool gt(const sail_int, const sail_int);
@@ -162,6 +167,8 @@ typedef uint64_t mach_bits;
bool eq_bit(const mach_bits a, const mach_bits b);
+bool EQUAL(mach_bits)(const mach_bits, const mach_bits);
+
typedef struct {
mp_bitcnt_t len;
mpz_t *bits;
@@ -218,6 +225,7 @@ void sign_extend(sail_bits *rop, const sail_bits op, const sail_int len);
void length_sail_bits(sail_int *rop, const sail_bits op);
bool eq_bits(const sail_bits op1, const sail_bits op2);
+bool EQUAL(sail_bits)(const sail_bits op1, const sail_bits op2);
bool neq_bits(const sail_bits op1, const sail_bits op2);
void vector_subrange_sail_bits(sail_bits *rop,
@@ -265,6 +273,9 @@ void shift_bits_left(sail_bits *rop, const sail_bits op1, const sail_bits op2);
void shift_bits_right(sail_bits *rop, const sail_bits op1, const sail_bits op2);
void shift_bits_right_arith(sail_bits *rop, const sail_bits op1, const sail_bits op2);
+void shiftl(sail_bits *rop, const sail_bits op1, const sail_int op2);
+void shiftr(sail_bits *rop, const sail_bits op1, const sail_int op2);
+
void reverse_endianness(sail_bits*, sail_bits);
/* ***** Sail reals ***** */
@@ -292,7 +303,7 @@ void round_down(sail_int *rop, const real op);
void to_real(real *rop, const sail_int op);
-bool eq_real(const real op1, const real op2);
+bool EQUAL(real)(const real op1, const real op2);
bool lt_real(const real op1, const real op2);
bool gt_real(const real op1, const real op2);
diff --git a/lib/vector_dec.sail b/lib/vector_dec.sail
index 86bbe601..8abcd218 100644
--- a/lib/vector_dec.sail
+++ b/lib/vector_dec.sail
@@ -22,7 +22,7 @@ val vector_length = {
ocaml: "length",
lem: "length_list",
c: "length",
- coq: "length_list"
+ coq: "vec_length"
} : forall 'n ('a : Type). vector('n, dec, 'a) -> atom('n)
overload length = {bitvector_length, vector_length}
@@ -68,7 +68,7 @@ val bitvector_access = {
val plain_vector_access = {
ocaml: "access",
lem: "access_list_dec",
- coq: "access_list_dec",
+ coq: "vec_access_dec",
c: "vector_access"
} : forall ('n : Int) ('m : Int) ('a : Type), 0 <= 'm < 'n. (vector('n, dec, 'a), atom('m)) -> 'a
@@ -84,7 +84,7 @@ val bitvector_update = {
val plain_vector_update = {
ocaml: "update",
lem: "update_list_dec",
- coq: "update_list_dec",
+ coq: "vec_update_dec",
c: "vector_update"
} : forall 'n ('a : Type). (vector('n, dec, 'a), int, 'a) -> vector('n, dec, 'a)