Theory Compositionality
section ‹Compositionality Proof for SIFUM-Security Property›
theory Compositionality
imports Security
begin
context sifum_security_init
begin
definition
differing_vars :: "('Var, 'Val) Mem ⇒ (_, _) Mem ⇒ 'Var set"
where
"differing_vars mem⇩1 mem⇩2 ≡ {x. mem⇩1 x ≠ mem⇩2 x}"
definition
differing_vars_lists :: "('Var, 'Val) Mem ⇒ (_, _) Mem ⇒
((_, _) Mem × (_, _) Mem) list ⇒ nat ⇒ 'Var set"
where
"differing_vars_lists mem⇩1 mem⇩2 mems i ≡
(differing_vars mem⇩1 (fst (mems ! i)) ∪ differing_vars mem⇩2 (snd (mems ! i)))"
lemma differing_finite: "finite (differing_vars mem⇩1 mem⇩2)"
by (metis UNIV_def Un_UNIV_left finite_Un finite_memory)
lemma differing_lists_finite: "finite (differing_vars_lists mem⇩1 mem⇩2 mems i)"
by (simp add: differing_finite differing_vars_lists_def)
fun makes_compatible ::
"('Com, 'Var, 'Val) GlobalConf ⇒
('Com, 'Var, 'Val) GlobalConf ⇒
((_, _) Mem × (_, _) Mem) list ⇒
bool"
where
"makes_compatible (cms⇩1, mem⇩1) (cms⇩2, mem⇩2) mems =
(length cms⇩1 = length cms⇩2 ∧ length cms⇩1 = length mems ∧
(∀ i. i < length cms⇩1 ⟶
(∀ σ. dom σ = differing_vars_lists mem⇩1 mem⇩2 mems i ⟶
(cms⇩1 ! i, (fst (mems ! i)) [↦ σ]) ≈ (cms⇩2 ! i, (snd (mems ! i)) [↦ σ])) ∧
(∀ x. (mem⇩1 x = mem⇩2 x ∨ dma mem⇩1 x = High ∨ x ∈ 𝒞) ⟶
x ∉ differing_vars_lists mem⇩1 mem⇩2 mems i)) ∧
((length cms⇩1 = 0 ∧ mem⇩1 =⇧l mem⇩2) ∨ (∀ x. ∃ i. i < length cms⇩1 ∧
x ∉ differing_vars_lists mem⇩1 mem⇩2 mems i)))"
lemma makes_compatible_intro [intro]:
"⟦ length cms⇩1 = length cms⇩2 ∧ length cms⇩1 = length mems;
(⋀ i σ. ⟦ i < length cms⇩1; dom σ = differing_vars_lists mem⇩1 mem⇩2 mems i ⟧ ⟹
(cms⇩1 ! i, (fst (mems ! i)) [↦ σ]) ≈ (cms⇩2 ! i, (snd (mems ! i)) [↦ σ]));
(⋀ i x. ⟦ i < length cms⇩1; mem⇩1 x = mem⇩2 x ∨ dma mem⇩1 x = High ∨ x ∈ 𝒞 ⟧ ⟹
x ∉ differing_vars_lists mem⇩1 mem⇩2 mems i);
(length cms⇩1 = 0 ∧ mem⇩1 =⇧l mem⇩2) ∨
(∀ x. ∃ i. i < length cms⇩1 ∧ x ∉ differing_vars_lists mem⇩1 mem⇩2 mems i) ⟧ ⟹
makes_compatible (cms⇩1, mem⇩1) (cms⇩2, mem⇩2) mems"
by auto
lemma compat_low:
"⟦ makes_compatible (cms⇩1, mem⇩1) (cms⇩2, mem⇩2) mems;
i < length cms⇩1;
x ∈ differing_vars_lists mem⇩1 mem⇩2 mems i ⟧ ⟹ dma mem⇩1 x = Low"
proof -
assume "i < length cms⇩1" and *: "x ∈ differing_vars_lists mem⇩1 mem⇩2 mems i" and
"makes_compatible (cms⇩1, mem⇩1) (cms⇩2, mem⇩2) mems"
then have
"(mem⇩1 x = mem⇩2 x ∨ dma mem⇩1 x = High ∨ x ∈ 𝒞) ⟶ x ∉ differing_vars_lists mem⇩1 mem⇩2 mems i"
by (simp add: Let_def, blast)
with * show "dma mem⇩1 x = Low"
by (cases "dma mem⇩1 x", blast)
qed
lemma compat_different:
"⟦ makes_compatible (cms⇩1, mem⇩1) (cms⇩2, mem⇩2) mems;
i < length cms⇩1;
x ∈ differing_vars_lists mem⇩1 mem⇩2 mems i ⟧ ⟹ mem⇩1 x ≠ mem⇩2 x ∧ dma mem⇩1 x = Low ∧ x ∉ 𝒞"
by (cases "dma mem⇩1 x", auto)
lemma sound_modes_no_read :
"⟦ sound_mode_use (cms, mem); x ∈ (map snd cms ! i) GuarNoReadOrWrite; i < length cms ⟧ ⟹
doesnt_read_or_modify (fst (cms ! i)) x"
proof -
fix cms mem x i
assume sound_modes: "sound_mode_use (cms, mem)" and "i < length cms"
hence "locally_sound_mode_use (cms ! i, mem)"
by (auto simp: sound_mode_use_def list_all_length)
moreover
assume "x ∈ (map snd cms ! i) GuarNoReadOrWrite"
ultimately show "doesnt_read_or_modify (fst (cms !i)) x"
apply (simp add: locally_sound_mode_use_def)
using ‹i < length cms› ‹locally_sound_mode_use (cms ! i, mem)› locally_sound_respects_guarantees respects_own_guarantees_def by auto
qed
lemma differing_vars_neg: "x ∉ differing_vars_lists mem1 mem2 mems i ⟹
(fst (mems ! i) x = mem1 x ∧ snd (mems ! i) x = mem2 x)"
by (simp add: differing_vars_lists_def differing_vars_def)
lemma differing_vars_neg_intro:
"⟦ mem⇩1 x = fst (mems ! i) x;
mem⇩2 x = snd (mems ! i) x ⟧ ⟹ x ∉ differing_vars_lists mem⇩1 mem⇩2 mems i"
by (auto simp: differing_vars_lists_def differing_vars_def)
lemma differing_vars_elim [elim]:
"x ∈ differing_vars_lists mem⇩1 mem⇩2 mems i ⟹
(fst (mems ! i) x ≠ mem⇩1 x) ∨ (snd (mems ! i) x ≠ mem⇩2 x)"
by (auto simp: differing_vars_lists_def differing_vars_def)
lemma makes_compatible_dma_eq:
assumes compat: "makes_compatible (cms⇩1, mem⇩1) (cms⇩2, mem⇩2) mems"
assumes ile: "i < length cms⇩1"
assumes domσ: "dom σ = differing_vars_lists mem⇩1 mem⇩2 mems i"
shows "dma ((fst (mems ! i)) [↦ σ]) = dma mem⇩1"
proof(rule dma_𝒞, clarify)
fix x
assume "x ∈ 𝒞"
with compat ile have notin_diff: "x ∉ differing_vars_lists mem⇩1 mem⇩2 mems i"
by simp
hence "x ∉ dom σ"
by(metis domσ)
hence "(fst (mems ! i) [↦ σ]) x = (fst (mems ! i)) x"
by(metis subst_not_in_dom)
moreover have "(fst (mems ! i)) x = mem⇩1 x"
using notin_diff differing_vars_neg by metis
ultimately show "(fst (mems ! i) [↦ σ]) x = mem⇩1 x" by simp
qed
lemma compat_different_vars:
"⟦ fst (mems ! i) x = snd (mems ! i) x;
x ∉ differing_vars_lists mem⇩1 mem⇩2 mems i ⟧ ⟹
mem⇩1 x = mem⇩2 x"
proof -
assume "x ∉ differing_vars_lists mem⇩1 mem⇩2 mems i"
hence "fst (mems ! i) x = mem⇩1 x ∧ snd (mems ! i) x = mem⇩2 x"
by (simp add: differing_vars_lists_def differing_vars_def)
moreover assume "fst (mems ! i) x = snd (mems ! i) x"
ultimately show "mem⇩1 x = mem⇩2 x" by auto
qed
lemma differing_vars_subst [rule_format]:
assumes domσ: "dom σ ⊇ differing_vars mem⇩1 mem⇩2"
shows "mem⇩1 [↦ σ] = mem⇩2 [↦ σ]"
proof (rule ext)
fix x
from domσ show "mem⇩1 [↦ σ] x = mem⇩2 [↦ σ] x"
unfolding subst_def differing_vars_def
by (cases "σ x", auto)
qed
lemma mm_equiv_low_eq:
"⟦ ⟨ c⇩1, mds, mem⇩1 ⟩ ≈ ⟨ c⇩2, mds, mem⇩2 ⟩ ⟧ ⟹ mem⇩1 =⇘mds⇙⇧l mem⇩2"
unfolding mm_equiv.simps strong_low_bisim_mm_def
by fast
lemma globally_sound_modes_compatible:
"⟦ globally_sound_mode_use (cms, mem) ⟧ ⟹ compatible_modes (map snd cms)"
apply (simp add: globally_sound_mode_use_def reachable_mode_states_def)
using meval_sched.simps(1) by blast
lemma compatible_different_no_read :
assumes sound_modes: "sound_mode_use (cms⇩1, mem⇩1)"
"sound_mode_use (cms⇩2, mem⇩2)"
assumes compat: "makes_compatible (cms⇩1, mem⇩1) (cms⇩2, mem⇩2) mems"
assumes modes_eq: "map snd cms⇩1 = map snd cms⇩2"
assumes ile: "i < length cms⇩1"
assumes x: "x ∈ differing_vars_lists mem⇩1 mem⇩2 mems i"
shows "doesnt_read_or_modify (fst (cms⇩1 ! i)) x ∧ doesnt_read_or_modify (fst (cms⇩2 ! i)) x"
proof -
from compat have len: "length cms⇩1 = length cms⇩2"
by simp
let ?X⇩i = "differing_vars_lists mem⇩1 mem⇩2 mems i"
from compat ile x have a: "dma mem⇩1 x = Low"
by (metis compat_low)
from compat ile x have b: "mem⇩1 x ≠ mem⇩2 x"
by (metis compat_different)
from compat ile x have not_in_𝒞: "x ∉ 𝒞"
by (metis compat_different)
with a and compat ile x obtain j where
jprop: "j < length cms⇩1 ∧ x ∉ differing_vars_lists mem⇩1 mem⇩2 mems j"
by fastforce
let ?X⇩j = "differing_vars_lists mem⇩1 mem⇩2 mems j"
obtain σ :: "'Var ⇀ 'Val" where domσ: "dom σ = ?X⇩j"
proof
let ?σ = "λ x. if (x ∈ ?X⇩j) then Some some_val else None"
show "dom ?σ = ?X⇩j" unfolding dom_def by auto
qed
let ?mdss = "map snd cms⇩1" and
?mems⇩1j = "fst (mems ! j)" and
?mems⇩2j = "snd (mems ! j)"
from jprop domσ have subst_eq:
"?mems⇩1j [↦ σ] x = ?mems⇩1j x ∧ ?mems⇩2j [↦ σ] x = ?mems⇩2j x"
by (metis subst_not_in_dom)
from compat jprop domσ
have "(cms⇩1 ! j, ?mems⇩1j [↦ σ]) ≈ (cms⇩2 ! j, ?mems⇩2j [↦ σ])"
by (auto simp: Let_def)
hence low_eq: "?mems⇩1j [↦ σ] =⇘?mdss ! j⇙⇧l ?mems⇩2j [↦ σ]" using modes_eq
by (metis (no_types) jprop len mm_equiv_low_eq nth_map surjective_pairing)
with jprop and b have "x ∈ (?mdss ! j) AsmNoReadOrWrite"
proof -
{ assume "x ∉ (?mdss ! j) AsmNoReadOrWrite"
then have mems_eq: "?mems⇩1j x = ?mems⇩2j x"
using ‹dma mem⇩1 x = Low› low_eq subst_eq
makes_compatible_dma_eq[OF compat jprop[THEN conjunct1] domσ]
low_mds_eq_def
by (metis (poly_guards_query))
hence "mem⇩1 x = mem⇩2 x"
by (metis compat_different_vars jprop)
hence False by (metis b)
}
thus ?thesis by metis
qed
hence "x ∈ (?mdss ! i) GuarNoReadOrWrite"
using sound_modes jprop
by (metis compatible_modes_def globally_sound_modes_compatible
length_map sound_mode_use.simps x ile)
thus "doesnt_read_or_modify (fst (cms⇩1 ! i)) x ∧ doesnt_read_or_modify (fst (cms⇩2 ! i)) x" using sound_modes ile
by (metis len modes_eq sound_modes_no_read)
qed
definition
vars_and_𝒞 :: "'Var set ⇒ 'Var set"
where
"vars_and_𝒞 X ≡ X ∪ vars_𝒞 X"
fun change_respecting ::
"('Com, 'Var, 'Val) LocalConf ⇒
('Com, 'Var, 'Val) LocalConf ⇒
'Var set ⇒ bool"
where "change_respecting (cms, mem) (cms', mem') X =
((cms, mem) ↝ (cms', mem') ∧
(∀ σ. dom σ = vars_and_𝒞 X ⟶ (cms, mem [↦ σ]) ↝ (cms', mem' [↦ σ])))"
lemma subst_overrides: "dom σ = dom τ ⟹ mem [↦ τ] [↦ σ] = mem [↦ σ]"
unfolding subst_def
by (metis domIff option.exhaust option.simps(4) option.simps(5))
definition to_partial :: "('a ⇒ 'b) ⇒ ('a ⇀ 'b)"
where "to_partial f = (λ x. Some (f x))"
lemma dom_restrict_total: "dom (to_partial f |` X) = X"
unfolding to_partial_def
by (metis Int_UNIV_left dom_const dom_restrict)
lemma change_respecting_doesnt_modify':
assumes eval: "(cms, mem) ↝ (cms', mem')"
assumes cr: "∀ f. dom f = Y ⟶ (cms, mem [↦ f]) ↝ (cms', mem' [↦ f])"
assumes x_in_dom: "x ∈ Y"
shows "mem x = mem' x"
proof -
let ?f' = "to_partial mem |` Y"
have domf': "dom ?f' = Y"
by (metis dom_restrict_total)
from this cr have eval': "(cms, mem [↦ ?f']) ↝ (cms', mem' [↦ ?f'])"
by (metis)
have mem_eq: "mem [↦ ?f'] = mem"
proof
fix x
show "mem [↦ ?f'] x = mem x"
unfolding subst_def
apply (cases "x ∈ Y")
apply (metis option.simps(5) restrict_in to_partial_def)
by (metis domf' subst_def subst_not_in_dom)
qed
then have mem'_eq: "mem' [↦ ?f'] = mem'"
using eval eval' deterministic
by (metis Pair_inject)
moreover
have x_in_dom': "x ∈ dom ?f'"
by (metis x_in_dom dom_restrict_total)
hence "?f' x = Some (mem x)"
by (metis restrict_in to_partial_def x_in_dom)
hence "mem' [↦ ?f'] x = mem x"
using subst_def x_in_dom'
by (metis option.simps(5))
thus "mem x = mem' x"
by (metis mem'_eq)
qed
lemma change_respecting_subset':
assumes step: "(cms, mem) ↝ (cms', mem')"
assumes noread: "(∀ σ. dom σ = X ⟶ (cms, mem [↦ σ]) ↝ (cms', mem' [↦ σ]))"
assumes dom_subset: "dom σ ⊆ X"
shows "(cms, mem [↦ σ]) ↝ (cms', mem' [↦ σ])"
proof -
define σ⇩X where "σ⇩X x = (if x ∈ X then if x ∈ dom σ then σ x else Some (mem x) else None)" for x
have "dom σ⇩X = X" using dom_subset by(auto simp: σ⇩X_def)
have "mem [↦ σ] = mem [↦ σ⇩X]"
apply(rule ext)
using dom_subset apply(auto simp: subst_def σ⇩X_def split: option.splits)
done
moreover have "mem' [↦ σ] = mem' [↦ σ⇩X]"
apply(rule ext)
using dom_subset apply(auto simp: subst_def σ⇩X_def split: option.splits simp: change_respecting_doesnt_modify'[OF step noread])
done
moreover from noread ‹dom σ⇩X = X› have "(cms, mem [↦ σ⇩X]) ↝ (cms', mem' [↦ σ⇩X])" by metis
ultimately show ?thesis by simp
qed
lemma change_respecting_subst:
"change_respecting (cms, mem) (cms', mem') X ⟹
(∀ σ. dom σ = X ⟶ (cms, mem [↦ σ]) ↝ (cms', mem' [↦ σ]))"
unfolding change_respecting.simps vars_and_𝒞_def
using change_respecting_subset' by blast
lemma change_respecting_intro [iff]:
"⟦ ⟨ c, mds, mem ⟩ ↝ ⟨ c', mds', mem' ⟩;
⋀ f. dom f = vars_and_𝒞 X ⟹
(⟨ c, mds, mem [↦ f] ⟩ ↝ ⟨ c', mds', mem' [↦ f] ⟩) ⟧
⟹ change_respecting ⟨c, mds, mem⟩ ⟨c', mds', mem'⟩ X"
unfolding change_respecting.simps
by blast
lemma vars_𝒞_mono:
"X ⊆ Y ⟹ vars_𝒞 X ⊆ vars_𝒞 Y"
by(auto simp: vars_𝒞_def)
lemma vars_𝒞_Un:
"vars_𝒞 (X ∪ Y) = (vars_𝒞 X ∪ vars_𝒞 Y)"
by(simp add: vars_𝒞_def)
lemma vars_𝒞_insert:
"vars_𝒞 (insert x Y) = (vars_𝒞 {x}) ∪ (vars_𝒞 Y)"
apply(subst insert_is_Un)
apply(rule vars_𝒞_Un)
done
lemma vars_𝒞_empty[simp]:
"vars_𝒞 {} = {}"
by(simp add: vars_𝒞_def)
lemma 𝒞_vars_of_𝒞_vars_empty:
"x ∈ 𝒞_vars y ⟹ 𝒞_vars x = {}"
apply(drule subsetD[OF 𝒞_vars_subset_𝒞])
apply(erule 𝒞_vars_𝒞)
done
lemma vars_and_𝒞_mono:
"X ⊆ X' ⟹ vars_and_𝒞 X ⊆ vars_and_𝒞 X'"
apply(unfold vars_and_𝒞_def)
apply(metis Un_mono vars_𝒞_mono)
done
lemma 𝒞_vars_finite[simp]:
"finite (𝒞_vars x)"
apply(rule finite_subset[OF _ finite_memory])
by blast
lemma finite_dom:
"finite (dom (σ::'Var ⇒ 'Val option))"
by(blast intro: finite_subset[OF _ finite_memory])
lemma doesnt_read_or_modify_subst:
assumes noread: "doesnt_read_or_modify c x"
assumes step: "⟨c, mds, mem⟩ ↝ ⟨c', mds', mem'⟩"
assumes subset: "X ⊆ {x} ∪ 𝒞_vars x"
shows "⋀ σ. dom σ = X ⟹ ⟨c, mds, mem[↦ σ]⟩ ↝ ⟨c', mds', mem'[↦ σ]⟩"
proof -
have "finite X"
using subset apply(rule finite_subset)
by simp
show "⋀ σ. dom σ = X ⟹ ⟨c, mds, mem[↦ σ]⟩ ↝ ⟨c', mds', mem'[↦ σ]⟩"
using ‹finite X› subset
proof(induct "X" rule: finite_subset_induct[where A="{x} ∪ 𝒞_vars x"])
case empty
thus "⟨c, mds, subst σ mem⟩ ↝ ⟨c', mds', subst σ mem'⟩"
using step by(simp add: subst_def)
next
case (insert a X)
show "⟨c, mds, subst σ mem⟩ ↝ ⟨c', mds', subst σ mem'⟩"
proof -
let ?σ⇩X = "(σ |` X)"
have IH⇩X: "⟨c, mds, subst ?σ⇩X mem⟩ ↝ ⟨c', mds', subst ?σ⇩X mem'⟩"
apply(rule insert(4))
using insert by (metis dom_restrict inf.absorb2 subset_insertI)
from insert obtain v where σa: "σ a = Some v" by auto
have r: "⋀mem. (subst ?σ⇩X mem)(a := v) = subst σ mem"
apply(rule ext, rename_tac y)
apply(simp, safe)
apply(simp add: subst_def σa)
using ‹a ∉ X› insert apply(auto simp: subst_def split: option.splits simp: restrict_map_def)
done
have "⟨c, mds, (subst ?σ⇩X mem)(a := v)⟩ ↝ ⟨c', mds', (subst ?σ⇩X mem')(a := v)⟩"
using noread ‹a ∈ {x} ∪ 𝒞_vars x› IH⇩X
unfolding doesnt_read_or_modify_def doesnt_read_or_modify_vars_def by metis
thus ?thesis by(simp add: r)
qed
qed
qed
lemma subst_restrict_twice:
"dom σ = A ∪ B ⟹
mem [↦ (σ |` A)] [↦ (σ |` B)] = mem [↦ σ]"
by(fastforce simp: subst_def split: option.splits intro!: ext simp: restrict_map_def)
lemma noread_exists_change_respecting:
assumes fin: "finite (X :: 'Var set)"
assumes eval: "⟨ c, mds, mem ⟩ ↝ ⟨ c', mds', mem' ⟩"
assumes noread: "∀ x ∈ X. doesnt_read_or_modify c x"
shows "change_respecting ⟨c, mds, mem⟩ ⟨c', mds', mem'⟩ X"
proof -
let ?lc = "⟨c, mds, mem⟩" and ?lc' = "⟨c', mds', mem'⟩"
from fin eval noread show "change_respecting ⟨c, mds, mem⟩ ⟨c', mds', mem'⟩ X"
proof (induct "X" arbitrary: mem mem' rule: finite_induct)
case empty
have "mem [↦ Map.empty] = mem" "mem' [↦ Map.empty] = mem'"
unfolding subst_def
by auto
hence "change_respecting ⟨c, mds, mem⟩ ⟨c', mds', mem'⟩ {}"
using empty
unfolding change_respecting.simps subst_def vars_𝒞_def vars_and_𝒞_def
by auto
thus ?case by blast
next
case (insert x X)
then have IH: "change_respecting ⟨c, mds, mem⟩ ⟨c', mds', mem'⟩ X"
by (metis (poly_guards_query) insertCI insert_disjoint(1))
show "change_respecting ⟨c, mds, mem⟩ ⟨c', mds', mem'⟩ (insert x X)"
proof
show "⟨c, mds, mem⟩ ↝ ⟨c', mds', mem'⟩" using insert by auto
next
fix σ :: "'Var ⇀ 'Val"
let ?σ⇩X = "σ |` vars_and_𝒞 X"
let ?σ⇩x = "σ |` ({x} ∪ 𝒞_vars x)"
assume domσ: "dom σ = vars_and_𝒞 (insert x X)"
hence "dom ?σ⇩X = vars_and_𝒞 X"
by (metis dom_restrict inf_absorb2 subset_insertI vars_and_𝒞_mono)
from domσ have domσ⇩x: "dom ?σ⇩x = {x} ∪ 𝒞_vars x"
by(simp add: domσ vars_and_𝒞_def vars_𝒞_def, blast)
have "dom σ = vars_and_𝒞 X ∪ ({x} ∪ 𝒞_vars x)"
by(simp add: domσ vars_and_𝒞_def vars_𝒞_def, blast)
hence substσ: "⋀ mem. mem [↦ ?σ⇩X] [↦ ?σ⇩x] = mem [↦ σ]"
by(rule subst_restrict_twice)
from insert have "doesnt_read_or_modify c x" by auto
moreover from IH have eval⇩X: "⟨c, mds, mem [↦ ?σ⇩X]⟩ ↝ ⟨c', mds', mem' [↦ ?σ⇩X]⟩"
using ‹dom ?σ⇩X = vars_and_𝒞 X›
unfolding change_respecting.simps
by auto
ultimately have "⟨c, mds, mem [↦ ?σ⇩X] [↦ ?σ⇩x]⟩ ↝ ⟨c', mds', mem' [↦ ?σ⇩X] [↦ ?σ⇩x]⟩"
using subset_refl domσ⇩x doesnt_read_or_modify_subst by metis
thus "⟨c, mds, mem [↦ σ]⟩ ↝ ⟨c', mds', mem' [↦ σ]⟩"
using substσ by metis
qed
qed
qed
lemma update_nth_eq:
"⟦ xs = ys; n < length xs ⟧ ⟹ xs = ys [n := xs ! n]"
by (metis list_update_id)
text ‹This property is obvious,
so an unreadable apply-style proof is acceptable here:›
lemma mm_equiv_step:
assumes bisim: "(cms⇩1, mem⇩1) ≈ (cms⇩2, mem⇩2)"
assumes modes_eq: "snd cms⇩1 = snd cms⇩2"
assumes step: "(cms⇩1, mem⇩1) ↝ (cms⇩1', mem⇩1')"
shows "∃ c⇩2' mem⇩2'. (cms⇩2, mem⇩2) ↝ ⟨ c⇩2', snd cms⇩1', mem⇩2' ⟩ ∧
(cms⇩1', mem⇩1') ≈ ⟨ c⇩2', snd cms⇩1', mem⇩2' ⟩"
using assms mm_equiv_strong_low_bisim
unfolding strong_low_bisim_mm_def
apply auto
apply (erule_tac x = "fst cms⇩1" in allE)
apply (erule_tac x = "snd cms⇩1" in allE)
by (metis surjective_pairing)
lemma change_respecting_doesnt_modify:
assumes cr: "change_respecting (cms, mem) (cms', mem') X"
assumes eval: "(cms, mem) ↝ (cms', mem')"
assumes x_in_dom: "x ∈ X ∪ vars_𝒞 X"
shows "mem x = mem' x"
using change_respecting_doesnt_modify'[where Y="X ∪ vars_𝒞 X", OF eval] cr
change_respecting.simps vars_and_𝒞_def x_in_dom
by metis
lemma change_respecting_doesnt_modify_dma:
assumes cr: "change_respecting (cms, mem) (cms', mem') X"
assumes eval: "(cms, mem) ↝ (cms', mem')"
assumes x_in_dom: "x ∈ X"
shows "dma mem x = dma mem' x"
proof -
have "⋀y. y ∈ 𝒞_vars x ⟹ mem y = mem' y"
proof -
fix y
assume "y ∈ 𝒞_vars x"
hence "y ∈ vars_𝒞 X"
using x_in_dom by(auto simp: vars_𝒞_def)
thus "mem y = mem' y"
using cr eval change_respecting_doesnt_modify by blast
qed
thus ?thesis by(metis dma_𝒞_vars)
qed
definition restrict_total :: "('a ⇒ 'b) ⇒ 'a set ⇒ 'a ⇀ 'b"
where "restrict_total f A = to_partial f |` A"
lemma differing_empty_eq:
"⟦ differing_vars mem mem' = {} ⟧ ⟹ mem = mem'"
unfolding differing_vars_def
by auto
lemma adaptation_finite:
"finite (dom (A::('Var,'Val) adaptation))"
apply(rule finite_subset[OF _ finite_memory])
by blast
definition
globally_consistent :: "('Var, 'Val) adaptation ⇒ 'Var Mds ⇒ ('Var,'Val) Mem ⇒ ('Var,'Val) Mem ⇒ bool"
where "globally_consistent A mds mem⇩1 mem⇩2 ≡
(∀x. case A x of Some (v,v') ⇒ (mem⇩1 x ≠ v ∨ mem⇩2 x ≠ v') ⟶ ¬ var_asm_not_written mds x | _ ⇒ True) ∧
(∀x. dma mem⇩1 [∥⇩1 A] x ≠ dma mem⇩1 x ⟶ ¬ var_asm_not_written mds x) ∧
(∀x. dma (mem⇩1 [∥⇩1 A]) x = Low ∧ (x ∉ mds AsmNoReadOrWrite ∨ x ∈ 𝒞) ⟶ (mem⇩1 [∥⇩1 A]) x = (mem⇩2 [∥⇩2 A]) x)"
lemma globally_consistent_adapt_bisim:
assumes bisim: "⟨c⇩1, mds, mem⇩1⟩ ≈ ⟨c⇩2, mds, mem⇩2⟩"
assumes globally_consistent: "globally_consistent A mds mem⇩1 mem⇩2"
shows "⟨c⇩1, mds, mem⇩1 [∥⇩1 A]⟩ ≈ ⟨c⇩2, mds, mem⇩2 [∥⇩2 A]⟩"
apply(rule mm_equiv_glob_consistent[simplified closed_glob_consistent_def, rule_format])
apply(rule bisim)
apply(fold globally_consistent_def)
by(rule globally_consistent)
lemma mm_equiv_𝒞_eq:
"(a,b) ≈ (a',b') ⟹ snd a = snd a' ⟹
∀x∈𝒞. b x = b' x"
apply(case_tac a, case_tac a')
using mm_equiv_strong_low_bisim[simplified strong_low_bisim_mm_def, rule_format]
by(auto simp: low_mds_eq_def 𝒞_Low)
lemma apply_adaptation_not_in_dom:
"x ∉ dom A ⟹ apply_adaptation b blah A x = blah x"
apply(simp add: apply_adaptation_def domIff split: option.splits)
done
lemma makes_compatible_invariant:
assumes sound_modes: "sound_mode_use (cms⇩1, mem⇩1)"
"sound_mode_use (cms⇩2, mem⇩2)"
assumes compat: "makes_compatible (cms⇩1, mem⇩1) (cms⇩2, mem⇩2) mems"
assumes modes_eq: "map snd cms⇩1 = map snd cms⇩2"
assumes eval: "(cms⇩1, mem⇩1) ↝⇘k⇙ (cms⇩1', mem⇩1')"
obtains cms⇩2' mem⇩2' mems' where
"map snd cms⇩1' = map snd cms⇩2' ∧
(cms⇩2, mem⇩2) ↝⇘k⇙ (cms⇩2', mem⇩2') ∧
makes_compatible (cms⇩1', mem⇩1') (cms⇩2', mem⇩2') mems'"
proof -
let ?X = "λ i. differing_vars_lists mem⇩1 mem⇩2 mems i"
from sound_modes compat modes_eq have
a: "∀ i < length cms⇩1. ∀ x ∈ (?X i). doesnt_read_or_modify (fst (cms⇩1 ! i)) x ∧
doesnt_read_or_modify (fst (cms⇩2 ! i)) x"
by (metis compatible_different_no_read)
from eval have
b: "k < length cms⇩1 ∧ (cms⇩1 ! k, mem⇩1) ↝ (cms⇩1' ! k, mem⇩1') ∧
cms⇩1' = cms⇩1 [k := cms⇩1' ! k]"
by (metis meval_elim nth_list_update_eq)
from modes_eq have equal_size: "length cms⇩1 = length cms⇩2"
by (metis length_map)
let ?mds⇩k = "snd (cms⇩1 ! k)" and
?mds⇩k' = "snd (cms⇩1' ! k)" and
?mems⇩1k = "fst (mems ! k)" and
?mems⇩2k = "snd (mems ! k)" and
?n = "length cms⇩1"
have "finite (?X k)"
by (metis differing_lists_finite)
then have
c: "change_respecting (cms⇩1 ! k, mem⇩1) (cms⇩1' ! k, mem⇩1') (?X k)"
using noread_exists_change_respecting b a
by (metis surjective_pairing)
from compat have "⋀ σ. dom σ = ?X k ⟹ ?mems⇩1k [↦ σ] = mem⇩1 [↦ σ]"
using differing_vars_subst differing_vars_lists_def
by (metis Un_upper1 Un_subset_iff)
hence
eval⇩σ: "⋀ σ. dom σ = ?X k ⟹ (cms⇩1 ! k, ?mems⇩1k [↦ σ]) ↝ (cms⇩1' ! k, mem⇩1' [↦ σ])"
by(metis change_respecting_subst[rule_format, where X="?X k"] c)
moreover
with b and compat have
bisim⇩σ: "⋀ σ. dom σ = ?X k ⟹ (cms⇩1 ! k, ?mems⇩1k [↦ σ]) ≈ (cms⇩2 ! k, ?mems⇩2k [↦ σ])"
by auto
moreover have "snd (cms⇩1 ! k) = snd (cms⇩2 ! k)"
by (metis b equal_size modes_eq nth_map)
ultimately have d: "⋀ σ. dom σ = ?X k ⟹ ∃ c⇩f' mem⇩f'.
(cms⇩2 ! k, ?mems⇩2k [↦ σ]) ↝ ⟨ c⇩f', ?mds⇩k', mem⇩f' ⟩ ∧
(cms⇩1' ! k, mem⇩1' [↦ σ]) ≈ ⟨ c⇩f', ?mds⇩k', mem⇩f' ⟩"
by (metis mm_equiv_step)
obtain h :: "'Var ⇀ 'Val" where domh: "dom h = ?X k"
by (metis dom_restrict_total)
then obtain c⇩h mem⇩h where h_prop:
"(cms⇩2 ! k, ?mems⇩2k [↦ h]) ↝ ⟨ c⇩h, ?mds⇩k', mem⇩h ⟩ ∧
(cms⇩1' ! k, mem⇩1' [↦ h]) ≈ ⟨ c⇩h, ?mds⇩k', mem⇩h ⟩"
using d
by metis
then have
"change_respecting (cms⇩2 ! k, ?mems⇩2k [↦ h]) ⟨ c⇩h, ?mds⇩k', mem⇩h ⟩ (?X k)"
using a b noread_exists_change_respecting
by (metis differing_lists_finite surjective_pairing)
with h_prop have
"∀ σ. dom σ = ?X k ⟶
(cms⇩2 ! k, ?mems⇩2k [↦ h] [↦ σ]) ↝ ⟨ c⇩h, ?mds⇩k', mem⇩h [↦ σ] ⟩"
by (metis change_respecting_subst)
with domh have f:
"∀ σ. dom σ = ?X k ⟶
(cms⇩2 ! k, ?mems⇩2k [↦ σ]) ↝ ⟨ c⇩h, ?mds⇩k', mem⇩h [↦ σ] ⟩"
by (auto simp: subst_overrides)
from d and f have g: "⋀ σ. dom σ = ?X k ⟹
(cms⇩2 ! k, ?mems⇩2k [↦ σ]) ↝ ⟨ c⇩h, ?mds⇩k', mem⇩h [↦ σ] ⟩ ∧
(cms⇩1' ! k, mem⇩1' [↦ σ]) ≈ ⟨ c⇩h, ?mds⇩k', mem⇩h [↦ σ] ⟩"
using h_prop
by (metis deterministic)
let ?σ_mem⇩2 = "to_partial mem⇩2 |` ?X k"
define mem⇩2' where "mem⇩2' = mem⇩h [↦ ?σ_mem⇩2]"
define c⇩2' where "c⇩2' = c⇩h"
have domσ_mem⇩2: "dom ?σ_mem⇩2 = ?X k"
by (metis dom_restrict_total)
have "mem⇩2 = ?mems⇩2k [↦ ?σ_mem⇩2]"
proof (rule ext)
fix x
show "mem⇩2 x = ?mems⇩2k [↦ ?σ_mem⇩2] x"
using domσ_mem⇩2
unfolding to_partial_def subst_def
apply (cases "x ∈ ?X k")
apply auto
by (metis differing_vars_neg)
qed
with f domσ_mem⇩2 have i: "(cms⇩2 ! k, mem⇩2) ↝ ⟨ c⇩2', ?mds⇩k', mem⇩2' ⟩"
unfolding mem⇩2'_def c⇩2'_def
by metis
define cms⇩2' where "cms⇩2' = cms⇩2 [k := (c⇩2', ?mds⇩k')]"
with i b equal_size have "(cms⇩2, mem⇩2) ↝⇘k⇙ (cms⇩2', mem⇩2')"
by (metis meval_intro)
moreover
from equal_size have new_length: "length cms⇩1' = length cms⇩2'"
unfolding cms⇩2'_def
by (metis eval length_list_update meval_elim)
with modes_eq have "map snd cms⇩1' = map snd cms⇩2'"
unfolding cms⇩2'_def
by (metis b map_update snd_conv)
moreover
obtain mems' where "makes_compatible (cms⇩1', mem⇩1') (cms⇩2', mem⇩2') mems'"
proof
have x_unchanged: "⋀ x. ⟦ x ∈ ?X k ⟧ ⟹
mem⇩1 x = mem⇩1' x ∧ mem⇩2 x = mem⇩2' x ∧ dma mem⇩1 x = dma mem⇩1' x"
proof(intro conjI)
fix x
assume "x ∈ ?X k"
thus "mem⇩1 x = mem⇩1' x"
using a b c change_respecting_doesnt_modify domh
by (metis (erased, opaque_lifting) Un_upper1 contra_subsetD)
next
fix x
assume "x ∈ ?X k"
hence eq_mem⇩2: "?σ_mem⇩2 x = Some (mem⇩2 x)"
by (metis restrict_in to_partial_def)
hence "?mems⇩2k [↦ h] [↦ ?σ_mem⇩2] x = mem⇩2 x"
by (auto simp: subst_def)
moreover have "mem⇩h [↦ ?σ_mem⇩2] x = mem⇩2 x"
by (auto simp: subst_def ‹x ∈ ?X k› eq_mem⇩2)
ultimately have "?mems⇩2k [↦ h] [↦ ?σ_mem⇩2] x = mem⇩h [↦ ?σ_mem⇩2] x"
by auto
thus "mem⇩2 x = mem⇩2' x"
by (metis ‹mem⇩2 = ?mems⇩2k [↦ ?σ_mem⇩2]› domσ_mem⇩2 domh mem⇩2'_def subst_overrides)
next
fix x
assume "x ∈ ?X k"
thus "dma mem⇩1 x = dma mem⇩1' x"
using a b c change_respecting_doesnt_modify_dma domh
by (metis (erased, opaque_lifting))
qed
define mems'_k where "mems'_k x =
(if x ∉ ?X k
then (mem⇩1' x, mem⇩2' x)
else (?mems⇩1k x, ?mems⇩2k x))" for x
define mems'_i where "mems'_i i x =
(if ((mem⇩1 x ≠ mem⇩1' x ∨ mem⇩2 x ≠ mem⇩2' x) ∧
(mem⇩1' x = mem⇩2' x ∨ dma mem⇩1' x = High))
then (mem⇩1' x, mem⇩2' x)
else if ((mem⇩1 x ≠ mem⇩1' x ∨ mem⇩2 x ≠ mem⇩2' x) ∧
(mem⇩1' x ≠ mem⇩2' x ∧ dma mem⇩1' x = Low))
then (some_val, some_val)
else if dma mem⇩1 x = High ∧ dma mem⇩1' x = Low then (mem⇩1 x, mem⇩1 x)
else if dma mem⇩1' x = dma mem⇩1 x then (fst (mems ! i) x, snd (mems ! i) x)
else (mem⇩1' x, mem⇩2' x))" for i x
define mems'
where "mems' =
map (λ i.
if i = k
then (fst ∘ mems'_k, snd ∘ mems'_k)
else (fst ∘ mems'_i i, snd ∘ mems'_i i))
[0..< length cms⇩1]"
from b have mems'_k_simp: "mems' ! k = (fst ∘ mems'_k, snd ∘ mems'_k)"
unfolding mems'_def
by auto
have mems'_simp2: "⋀i. ⟦ i ≠ k; i < length cms⇩1 ⟧ ⟹
mems' ! i = (fst ∘ mems'_i i, snd ∘ mems'_i i)"
unfolding mems'_def
by auto
have mems'_k_1 [simp]: "⋀ x. ⟦ x ∉ ?X k ⟧ ⟹
fst (mems' ! k) x = mem⇩1' x ∧ snd (mems' ! k) x = mem⇩2' x"
unfolding mems'_k_simp mems'_k_def
by auto
have mems'_k_2 [simp]: "⋀ x. ⟦ x ∈ ?X k ⟧ ⟹
fst (mems' ! k) x = fst (mems ! k) x ∧ snd (mems' ! k) x = snd (mems ! k) x"
unfolding mems'_k_simp mems'_k_def
by auto
have mems'_k_cases:
"⋀ P x.
⟦
⟦ x ∉ ?X k;
fst (mems' ! k) x = mem⇩1' x;
snd (mems' ! k) x = mem⇩2' x ⟧ ⟹ P x;
⟦ x ∈ ?X k;
fst (mems' ! k) x = fst (mems ! k) x;
snd (mems' ! k) x = snd (mems ! k) x ⟧ ⟹ P x ⟧ ⟹ P x"
apply(case_tac "x ∉ ?X k")
apply simp
apply simp
done
have mems'_i_simp:
"⋀ i. ⟦ i < length cms⇩1; i ≠ k ⟧ ⟹ mems' ! i = (fst ∘ mems'_i i, snd ∘ mems'_i i)"
unfolding mems'_def
by auto
have mems'_i_1 [simp]:
"⋀ i x. ⟦ i ≠ k; i < length cms⇩1;
mem⇩1 x ≠ mem⇩1' x ∨ mem⇩2 x ≠ mem⇩2' x;
mem⇩1' x = mem⇩2' x ∨ dma mem⇩1' x = High ⟧ ⟹
fst (mems' ! i) x = mem⇩1' x ∧ snd (mems' ! i) x = mem⇩2' x"
unfolding mems'_i_def mems'_i_simp
by auto
have mems'_i_2 [simp]:
"⋀ i x. ⟦ i ≠ k; i < length cms⇩1;
mem⇩1 x ≠ mem⇩1' x ∨ mem⇩2 x ≠ mem⇩2' x;
mem⇩1' x ≠ mem⇩2' x; dma mem⇩1' x = Low ⟧ ⟹
fst (mems' ! i) x = some_val ∧ snd (mems' ! i) x = some_val"
unfolding mems'_i_def mems'_i_simp
by auto
have mems'_i_3 [simp]:
"⋀ i x. ⟦ i ≠ k; i < length cms⇩1;
mem⇩1 x = mem⇩1' x; mem⇩2 x = mem⇩2' x;
dma mem⇩1 x = High ∧ dma mem⇩1' x = Low ⟧ ⟹
fst (mems' ! i) x = mem⇩1 x ∧ snd (mems' ! i) x = mem⇩1 x"
unfolding mems'_i_def mems'_i_simp
by auto
have mems'_i_4 [simp]:
"⋀ i x. ⟦ i ≠ k; i < length cms⇩1;
mem⇩1 x = mem⇩1' x; mem⇩2 x = mem⇩2' x;
dma mem⇩1 x = Low ∨ dma mem⇩1' x = High;
dma mem⇩1' x = dma mem⇩1 x ⟧ ⟹
fst (mems' ! i) x = fst (mems ! i) x ∧ snd (mems' ! i) x = snd (mems ! i) x"
unfolding mems'_i_def mems'_i_simp
by auto
have mems'_i_5 [simp]:
"⋀ i x. ⟦ i ≠ k; i < length cms⇩1;
mem⇩1 x = mem⇩1' x; mem⇩2 x = mem⇩2' x;
dma mem⇩1 x = Low ∧ dma mem⇩1' x = High;
dma mem⇩1' x ≠ dma mem⇩1 x ⟧ ⟹
fst (mems' ! i) x = mem⇩1' x ∧ snd (mems' ! i) x = mem⇩2' x"
unfolding mems'_i_def mems'_i_simp
by auto
have mems'_i_cases:
"⋀ P i x.
⟦ i ≠ k; i < length cms⇩1;
⟦ mem⇩1 x ≠ mem⇩1' x ∨ mem⇩2 x ≠ mem⇩2' x;
mem⇩1' x = mem⇩2' x ∨ dma mem⇩1' x = High;
fst (mems' ! i) x = mem⇩1' x; snd (mems' ! i) x = mem⇩2' x ⟧ ⟹ P x;
⟦ mem⇩1 x ≠ mem⇩1' x ∨ mem⇩2 x ≠ mem⇩2' x;
mem⇩1' x ≠ mem⇩2' x; dma mem⇩1' x = Low;
fst (mems' ! i) x = some_val; snd (mems' ! i) x = some_val ⟧ ⟹ P x;
⟦ mem⇩1 x = mem⇩1' x; mem⇩2 x = mem⇩2' x; dma mem⇩1 x = High;
dma mem⇩1' x = Low;
fst (mems' ! i) x = mem⇩1 x; snd (mems' ! i) x = mem⇩1 x ⟧ ⟹ P x;
⟦ mem⇩1 x = mem⇩1' x; mem⇩2 x = mem⇩2' x; dma mem⇩1 x = Low ∨ dma mem⇩1' x = High;
dma mem⇩1' x = dma mem⇩1 x;
fst (mems' ! i) x = fst (mems ! i) x; snd (mems' ! i) x = snd (mems ! i) x ⟧ ⟹ P x;
⟦ mem⇩1 x = mem⇩1' x; mem⇩2 x = mem⇩2' x; dma mem⇩1 x = Low; dma mem⇩1' x = High;
fst (mems' ! i) x = mem⇩1' x; snd (mems' ! i) x = mem⇩2' x ⟧ ⟹ P x ⟧
⟹ P x"
using mems'_i_1 mems'_i_2 mems'_i_3 mems'_i_4 mems'_i_5
by (metis (full_types) Sec.exhaust)
let ?X' = "λ i. differing_vars_lists mem⇩1' mem⇩2' mems' i"
have len_unchanged: "length cms⇩1' = length cms⇩1"
by (metis cms⇩2'_def equal_size length_list_update new_length)
have mm_equiv': "(cms⇩1' ! k, subst (?σ_mem⇩2) mem⇩1') ≈ ⟨c⇩h, snd (cms⇩1' ! k), mem⇩2'⟩"
apply(simp add: mem⇩2'_def)
apply(rule g[THEN conjunct2])
apply(rule dom_restrict_total)
done
hence 𝒞_subst_eq: "∀x∈𝒞. (subst (?σ_mem⇩2) mem⇩1') x = mem⇩2' x"
apply(rule mm_equiv_𝒞_eq)
by simp
have low_mds_eq': "(subst (?σ_mem⇩2) mem⇩1') =⇘snd (cms⇩1' ! k)⇙⇧l mem⇩2'"
apply(rule mm_equiv_low_eq[where c⇩1="fst (cms⇩1' ! k)"])
apply(force intro: mm_equiv')
done
have 𝒞_subst_eq_idemp: "⋀x. x ∈ 𝒞 ⟹ (subst (?σ_mem⇩2) mem⇩1') x = mem⇩1' x"
apply(rule subst_not_in_dom)
apply(rule notI)
apply(simp add: dom_restrict_total)
using compat b by force
from 𝒞_subst_eq 𝒞_subst_eq_idemp
have 𝒞_eq: "⋀x. x ∈ 𝒞 ⟹ mem⇩1' x = mem⇩2' x"
by simp
have not_control: "⋀x i. i < length cms⇩1' ⟹ x ∈ ?X' i ⟹ x ∉ 𝒞"
proof(rule ccontr, clarsimp)
fix x i
let ?mems⇩1i = "fst (mems ! i)"
let ?mems⇩2i = "snd (mems ! i)"
let ?mems⇩1'i = "fst (mems' ! i)"
let ?mems⇩2'i = "snd (mems' ! i)"
assume "i < length cms⇩1'"
have "i < length cms⇩1" by (metis len_unchanged ‹i < length cms⇩1'›)
assume "x ∈ ?X' i"
assume "x ∈ 𝒞"
have "x ∉ ?X i"
using compat ‹i < length cms⇩1'› len_unchanged new_length
by (metis ‹x ∈ 𝒞› compat_different)
from ‹x ∈ 𝒞› have "mem⇩1' x = mem⇩2' x" by(rule 𝒞_eq)
from ‹x ∈ 𝒞› have "dma mem⇩1' x = Low" by(simp add: 𝒞_Low)
show "False"
proof(cases "i = k")
assume eq[simp]: "i = k"
show ?thesis
using ‹x ∉ ?X i› ‹x ∈ ?X' i›
by(force simp: differing_vars_lists_def differing_vars_def)
next
assume neq: "i ≠ k"
thus ?thesis
using ‹x ∈ ?X' i› ‹x ∉ ?X i› ‹x ∈ 𝒞› 𝒞_Low ‹mem⇩1' x = mem⇩2' x›
by(force elim: mems'_i_cases[of "i" "x" "λx. False", OF _ ‹i < length cms⇩1›]
simp: differing_vars_lists_def differing_vars_def)
qed
qed
show "makes_compatible (cms⇩1', mem⇩1') (cms⇩2', mem⇩2') mems'"
proof
have "length cms⇩1' = length cms⇩1"
by (metis cms⇩2'_def equal_size length_list_update new_length)
then show "length cms⇩1' = length cms⇩2' ∧ length cms⇩1' = length mems'"
using compat new_length
unfolding mems'_def
by auto
next
fix i
fix σ :: "'Var ⇀ 'Val"
let ?mems⇩1'i = "fst (mems' ! i)"
let ?mems⇩2'i = "snd (mems' ! i)"
assume i_le: "i < length cms⇩1'"
assume domσ: "dom σ = ?X' i"
show "(cms⇩1' ! i, (fst (mems' ! i)) [↦ σ]) ≈ (cms⇩2' ! i, (snd (mems' ! i)) [↦ σ])"
proof (cases "i = k")
assume [simp]: "i = k"
define σ' where "σ' x =
(if x ∈ ?X k
then if x ∈ ?X' k
then σ x
else Some (mem⇩1' x)
else None)" for x
have domσ': "dom σ' = ?X k"
using σ'_def [abs_def]
apply (clarsimp, safe)
by( metis domI domIff, metis ‹i = k› domD domσ )
have diff_vars_impl [simp]: "⋀x. x ∈ ?X' k ⟹ x ∈ ?X k"
proof (rule ccontr)
fix x
assume "x ∉ ?X k"
hence "mem⇩1 x = ?mems⇩1k x ∧ mem⇩2 x = ?mems⇩2k x"
by (metis differing_vars_neg)
from ‹x ∉ ?X k› have "?mems⇩1'i x = mem⇩1' x ∧ ?mems⇩2'i x = mem⇩2' x"
by auto
moreover
assume "x ∈ ?X' k"
hence "mem⇩1' x ≠ ?mems⇩1'i x ∨ mem⇩2' x ≠ ?mems⇩2'i x"
by (metis ‹i = k› differing_vars_elim)
ultimately show False
by auto
qed
have "?mems⇩1'i [↦ σ] = mem⇩1' [↦ σ']"
proof (rule ext)
fix x
show "?mems⇩1'i [↦ σ] x = mem⇩1' [↦ σ'] x"
proof (cases "x ∈ ?X' k")
assume x_in_X'k: "x ∈ ?X' k"
then obtain v where "σ x = Some v"
by (metis domσ domD ‹i = k›)
hence "?mems⇩1'i [↦ σ] x = v"
using ‹x ∈ ?X' k› domσ
by (auto simp: subst_def)
moreover
from domσ' and ‹x ∈ ?X' k› have "x ∈ dom σ'" by simp
hence "mem⇩1' [↦ σ'] x = v"
using domσ'
unfolding subst_def
by (metis σ'_def ‹σ x = Some v› diff_vars_impl option.simps(5) x_in_X'k)
ultimately show "?mems⇩1'i [↦ σ] x = mem⇩1' [↦ σ'] x" ..
next
assume "x ∉ ?X' k"
hence "?mems⇩1'i [↦ σ] x = ?mems⇩1'i x"
using domσ
by (metis ‹i = k› subst_not_in_dom)
show ?thesis
proof(case_tac "x ∈ ?X k")
assume "x ∈ ?X k"
from ‹x ∉ ?X' k› have "mem⇩1' x = ?mems⇩1'i x"
by(metis differing_vars_neg ‹i = k›)
then have "σ' x = Some (?mems⇩1'i x)"
unfolding σ'_def
using domσ' domh
by(simp add: ‹x ∈ ?X k› ‹x ∉ ?X' k›)
hence "mem⇩1' [↦ σ'] x = ?mems⇩1'i x"
unfolding subst_def
by (metis option.simps(5))
thus ?thesis
by (metis ‹?mems⇩1'i [↦σ] x = ?mems⇩1'i x›)
next
assume "x ∉ ?X k"
then have "mem⇩1' [↦ σ'] x = mem⇩1' x"
by (metis domσ' subst_not_in_dom)
moreover
have "?mems⇩1'i x = mem⇩1' x"
by (metis ‹i = k› ‹x ∉ ?X' k› differing_vars_neg)
ultimately show ?thesis
by (metis ‹?mems⇩1'i [↦σ] x = ?mems⇩1'i x›)
qed
qed
qed
moreover have "?mems⇩2'i [↦ σ] = mem⇩h [↦ σ']"
proof (rule ext)
fix x
show "?mems⇩2'i [↦ σ] x = mem⇩h [↦ σ'] x"
proof (cases "x ∈ ?X' k")
assume "x ∈ ?X' k"
then obtain v where "σ x = Some v"
using domσ
by (metis domD ‹i = k›)
hence "?mems⇩2'i [↦ σ] x = v"
using ‹x ∈ ?X' k› domσ
unfolding subst_def
by (metis option.simps(5))
moreover
from ‹x ∈ ?X' k› have "x ∈ ?X k"
by auto
hence "x ∈ dom (σ')"
by (metis domσ' ‹x ∈ ?X' k›)
hence "mem⇩2' [↦ σ'] x = v"
using domσ' c
unfolding subst_def
by (metis σ'_def ‹σ x = Some v› diff_vars_impl option.simps(5) ‹x ∈ ?X' k›)
ultimately show ?thesis
by (metis domσ' dom_restrict_total mem⇩2'_def subst_overrides)
next
assume "x ∉ ?X' k"
hence "?mems⇩2'i [↦ σ] x = ?mems⇩2'i x"
using domσ
by (metis ‹i = k› subst_not_in_dom)
show ?thesis
proof(case_tac "x ∈ ?X k")
assume "x ∈ ?X k"
hence "mem⇩1 x = mem⇩1' x ∧ mem⇩2 x = mem⇩2' x" by (metis x_unchanged)
moreover from ‹x ∉ ?X' k› ‹i = k› have "?mems⇩1'i x = mem⇩1' x ∧ ?mems⇩2'i x = mem⇩2' x"
by(metis differing_vars_neg)
moreover from ‹x ∈ ?X k› have "fst (mems ! i) x ≠ mem⇩1 x ∨ snd (mems ! i) x ≠ mem⇩2 x"
by(metis differing_vars_elim ‹i = k›)
moreover from ‹x ∈ ?X k› have "fst (mems' ! i) x = fst (mems ! i) x ∧
snd (mems' ! i) x = snd (mems ! i) x"
by(metis mems'_k_2 ‹i = k›)
ultimately have "False" by auto
thus ?thesis by blast
next
assume "x ∉ ?X k"
hence "x ∉ dom σ'" by (simp add: domσ')
then have "mem⇩h [↦ σ'] x = mem⇩h x"
by (metis subst_not_in_dom)
moreover
have "?mems⇩2'i x = mem⇩2' x"
by (metis ‹i = k› mems'_k_1 ‹x ∉ ?X k›)
hence "?mems⇩2'i x = mem⇩h x"
unfolding mem⇩2'_def
by (metis domσ_mem⇩2 subst_not_in_dom ‹x ∉ ?X k›)
ultimately show ?thesis
by (metis ‹?mems⇩2'i [↦σ] x = ?mems⇩2'i x›)
qed
qed
qed
ultimately show
"(cms⇩1' ! i, (fst (mems' ! i)) [↦ σ]) ≈ (cms⇩2' ! i, (snd (mems' ! i)) [↦ σ])"
using domσ domσ' g b ‹i = k›
by (metis c⇩2'_def cms⇩2'_def equal_size nth_list_update_eq)
next
assume "i ≠ k"
define σ' where "σ' x =
(if x ∈ ?X i
then if x ∈ ?X' i
then σ x
else Some (mem⇩1' x)
else None)" for x
let ?mems⇩1i = "fst (mems ! i)" and
?mems⇩2i = "snd (mems ! i)"
have "dom σ' = ?X i"
unfolding σ'_def
apply auto
apply (metis option.simps(2))
by (metis domD domσ)
have o: "⋀ x.
((?mems⇩1'i [↦ σ] x ≠ ?mems⇩1i [↦ σ'] x ∨
?mems⇩2'i [↦ σ] x ≠ ?mems⇩2i [↦ σ'] x) ∧
(dma mem⇩1 x = Low ∨ dma mem⇩1' x = High) ∧
(dma mem⇩1' x = dma mem⇩1 x))
⟶ (mem⇩1' x ≠ mem⇩1 x ∨ mem⇩2' x ≠ mem⇩2 x)"
proof -
fix x
{
assume eq_mem: "mem⇩1' x = mem⇩1 x ∧ mem⇩2' x = mem⇩2 x"
and clas: "dma mem⇩1 x = Low ∨ dma mem⇩1' x = High"
and clas_eq: "dma mem⇩1' x = dma mem⇩1 x"
hence mems'_simp: "?mems⇩1'i x = ?mems⇩1i x ∧ ?mems⇩2'i x = ?mems⇩2i x"
using mems'_i_4
by (metis ‹i ≠ k› b i_le length_list_update)
have
"?mems⇩1'i [↦ σ] x = ?mems⇩1i [↦ σ'] x ∧ ?mems⇩2'i [↦ σ] x = ?mems⇩2i [↦ σ'] x"
proof (cases "x ∈ ?X' i")
assume "x ∈ ?X' i"
hence "?mems⇩1'i x ≠ mem⇩1' x ∨ ?mems⇩2'i x ≠ mem⇩2' x"
by (metis differing_vars_neg_intro)
hence "x ∈ ?X i"
using eq_mem mems'_simp
by (metis differing_vars_neg)
hence "σ' x = σ x"
by (metis σ'_def ‹x ∈ ?X' i›)
thus ?thesis
by (clarsimp simp: subst_def mems'_simp split: option.splits)
next
assume "x ∉ ?X' i"
hence "?mems⇩1'i x = mem⇩1' x ∧ ?mems⇩2'i x = mem⇩2' x"
by (metis differing_vars_neg)
hence "x ∉ ?X i"
using eq_mem mems'_simp
by (auto simp: differing_vars_neg_intro)
thus ?thesis
by (metis ‹dom σ' = ?X i› ‹x ∉ ?X' i› domσ mems'_simp subst_not_in_dom)
qed
}
thus "?thesis x" by blast
qed
have o_downgrade: "⋀x. x ∉ ?X' i ∧ (subst σ (fst (mems' ! i)) x ≠ subst σ' (fst (mems ! i)) x ∨
subst σ (snd (mems' ! i)) x ≠ subst σ' (snd (mems ! i)) x) ∧
(dma mem⇩1 x = High ∧ dma mem⇩1' x = Low) ⟶
mem⇩1' x ≠ mem⇩1 x ∨ mem⇩2' x ≠ mem⇩2 x"
proof -
fix x {
assume mem_eq: "mem⇩1' x = mem⇩1 x ∧ mem⇩2' x = mem⇩2 x"
and clas: "(dma mem⇩1 x = High ∧ dma mem⇩1' x = Low)"
and notin: "x ∉ ?X' i"
hence mems'_simp [simp]: "?mems⇩1'i x = mem⇩1 x ∧ ?mems⇩2'i x = mem⇩1 x"
using mems'_i_3
by (metis ‹i ≠ k› b i_le length_list_update)
have
"?mems⇩1'i [↦ σ] x = ?mems⇩1i [↦ σ'] x ∧ ?mems⇩2'i [↦ σ] x = ?mems⇩2i [↦ σ'] x"
proof (cases "x ∈ ?X' i")
assume "x ∈ ?X' i"
thus ?thesis using notin by blast
next
assume "x ∉ ?X' i"
hence "?mems⇩1'i x = mem⇩1' x ∧ ?mems⇩2'i x = mem⇩2' x"
by (metis differing_vars_neg)
moreover have "x ∉ ?X i"
using clas compat i_le len_unchanged
by (force)
ultimately show ?thesis
using domσ ‹dom σ' = ?X i› ‹x ∉ ?X' i› apply(simp add: subst_not_in_dom)
apply(simp add: mem_eq)
apply(force simp: differing_vars_def differing_vars_lists_def)
done
qed
} thus "?thesis x" by blast
qed
have modifies_no_var_asm_not_written:
"⋀x. mem⇩1' x ≠ mem⇩1 x ∨ mem⇩2' x ≠ mem⇩2 x ∨
dma mem⇩1' x ≠ dma mem⇩1 x ∨ dma mem⇩2' x ≠ dma mem⇩2 x ⟹
¬ var_asm_not_written (snd (cms⇩1 ! i)) x"
proof -
fix x
assume "mem⇩1' x ≠ mem⇩1 x ∨ mem⇩2' x ≠ mem⇩2 x ∨ dma mem⇩1' x ≠ dma mem⇩1 x ∨ dma mem⇩2' x ≠ dma mem⇩2 x"
hence modified: " ¬ (doesnt_modify (fst (cms⇩1 ! k)) x) ∨ ¬ (doesnt_modify (fst (cms⇩2 ! k)) x)"
using b i
unfolding doesnt_modify_def
by (metis surjective_pairing)
hence modified_r: " ¬ (doesnt_read_or_modify (fst (cms⇩1 ! k)) x) ∨ ¬ (doesnt_read_or_modify (fst (cms⇩2 ! k)) x)" using doesnt_read_or_modify_doesnt_modify by fastforce
from sound_modes have loc_modes:
"locally_sound_mode_use (cms⇩1 ! k, mem⇩1) ∧
locally_sound_mode_use (cms⇩2 ! k, mem⇩2)"
unfolding sound_mode_use.simps
by (metis b equal_size list_all_length)
moreover
have "snd (cms⇩1 ! k) = snd (cms⇩2 ! k)"
by (metis b equal_size modes_eq nth_map)
have "(cms⇩1 ! k, mem⇩1) ∈ loc_reach (cms⇩1 ! k, mem⇩1)"
using loc_reach.refl by auto
hence guars:
"x ∈ snd (cms⇩1 ! k) GuarNoWrite ⟶ doesnt_modify (fst (cms⇩1 ! k)) x ∧
x ∈ snd (cms⇩2 ! k) GuarNoWrite ⟶ doesnt_modify (fst (cms⇩1 ! k)) x ∧
x ∈ snd (cms⇩1 ! k) GuarNoReadOrWrite ⟶ doesnt_read_or_modify (fst (cms⇩1 ! k)) x ∧
x ∈ snd (cms⇩2 ! k) GuarNoReadOrWrite ⟶ doesnt_read_or_modify (fst (cms⇩1 ! k)) x"
using loc_modes
unfolding locally_sound_mode_use_def ‹snd (cms⇩1 ! k) = snd (cms⇩2 ! k)›
by (metis loc_reach.refl surjective_pairing)
hence "x ∉ snd (cms⇩1 ! k) GuarNoWrite ∧ x ∉ snd (cms⇩1 ! k) GuarNoReadOrWrite"
using modified modified_r loc_modes locally_sound_mode_use_def
by (metis (no_types, lifting) ‹(cms⇩2, mem⇩2) ↝⇘k⇙ (cms⇩2', mem⇩2')› b locally_sound_respects_guarantees modes_eq nth_map meval_elim respects_own_guarantees_def sifum_security_init_axioms)
moreover
from sound_modes have "compatible_modes (map snd cms⇩1)"
by (metis globally_sound_modes_compatible sound_mode_use.simps)
ultimately show "(?thesis x)"
unfolding compatible_modes_def var_asm_not_written_def
using ‹i ≠ k› i_le
by (metis (no_types) b length_list_update length_map nth_map)
qed
from o o_downgrade have
p: "⋀ x. ⟦ ?mems⇩1'i [↦ σ] x ≠ ?mems⇩1i [↦ σ'] x ∨
?mems⇩2'i [↦ σ] x ≠ ?mems⇩2i [↦ σ'] x;
x ∉ ?X' i ∨ ((dma mem⇩1 x = Low ∨ dma mem⇩1' x = High) ∧
(dma mem⇩1' x = dma mem⇩1 x)) ⟧ ⟹
¬ var_asm_not_written (snd (cms⇩1 ! i)) x"
proof -
fix x
assume mems_neq:
"?mems⇩1'i [↦ σ] x ≠ ?mems⇩1i [↦ σ'] x ∨ ?mems⇩2'i [↦ σ] x ≠ ?mems⇩2i [↦ σ'] x"
and nin:
"x ∉ ?X' i ∨ ((dma mem⇩1 x = Low ∨ dma mem⇩1' x = High) ∧
(dma mem⇩1' x = dma mem⇩1 x))"
hence "mem⇩1' x ≠ mem⇩1 x ∨ mem⇩2' x ≠ mem⇩2 x ∨ dma mem⇩1' x ≠ dma mem⇩1 x"
apply -
apply(erule disjE[where P="x ∉ ?X' i"])
apply(case_tac "(dma mem⇩1 x = High ∧ dma mem⇩1' x = Low)")
apply(metis o_downgrade[rule_format])
apply(case_tac "dma mem⇩1' x = dma mem⇩1 x")
apply(metis (poly_guards_query) o Sec.exhaust)
apply fastforce
apply(metis (poly_guards_query) o Sec.exhaust)
done
thus "?thesis x"
by(force simp: modifies_no_var_asm_not_written)
qed
have q':
"⋀ x. ⟦ dma mem⇩1 x = Low; dma mem⇩1' x = Low;
?mems⇩1'i [↦ σ] x ≠ ?mems⇩1i [↦ σ'] x ∨
?mems⇩2'i [↦ σ] x ≠ ?mems⇩2i [↦ σ'] x;
x ∉ ?X' i ⟧ ⟹
mem⇩1' x = mem⇩2' x"
by (metis ‹i ≠ k› b compat_different_vars i_le length_list_update mems'_i_2 o)
have "i < length cms⇩1"
by (metis cms⇩2'_def equal_size i_le length_list_update new_length)
with compat and ‹dom σ' = ?X i› have
bisim: "(cms⇩1 ! i, ?mems⇩1i [↦ σ']) ≈ (cms⇩2 ! i, ?mems⇩2i [↦ σ'])"
by auto
define σ'⇩k where "σ'⇩k x = (if x ∈ ?X k then Some (undefined::'Val) else None)" for x
have "dom σ'⇩k = ?X k" unfolding σ'⇩k_def by (simp add: dom_def)
with compat and ‹dom σ'⇩k = ?X k› and b have
bisim⇩k: "(cms⇩1 ! k, ?mems⇩1k [↦ σ'⇩k]) ≈ (cms⇩2 ! k, ?mems⇩2k [↦ σ'⇩k])"
by auto
have q_downgrade:
"⋀ x. ⟦ dma mem⇩1 x = High; dma mem⇩1' x = Low;
?mems⇩1'i [↦ σ] x ≠ ?mems⇩1i [↦ σ'] x ∨
?mems⇩2'i [↦ σ] x ≠ ?mems⇩2i [↦ σ'] x;
x ∉ ?X' i ⟧ ⟹
mem⇩1' x = mem⇩2' x"
by (metis (erased, opaque_lifting) ‹i ≠ k› compat_different_vars i_le len_unchanged mems'_i_2 o_downgrade)
have q: "⋀ x. ⟦ dma mem⇩1' x = Low;
?mems⇩1'i [↦ σ] x ≠ ?mems⇩1i [↦ σ'] x ∨
?mems⇩2'i [↦ σ] x ≠ ?mems⇩2i [↦ σ'] x;
x ∉ ?X' i ⟧ ⟹
mem⇩1' x = mem⇩2' x"
apply(case_tac "dma mem⇩1 x")
apply(blast intro: q_downgrade)
by(blast intro: q')
let ?Δ = "differing_vars (?mems⇩1i [↦ σ']) (?mems⇩1'i [↦ σ]) ∪
differing_vars (?mems⇩2i [↦ σ']) (?mems⇩2'i [↦ σ])"
have Δ_finite: "finite ?Δ"
by (metis (no_types) differing_finite finite_UnI)
define A where "A x =
(if x ∈ ?Δ
then if dma (?mems⇩1'i [↦ σ]) x = High
then Some (?mems⇩1'i [↦ σ] x, ?mems⇩2'i [↦ σ] x)
else if x ∈ ?X' i
then (case σ x of
Some v ⇒ Some (v, v)
| None ⇒ None)
else Some (mem⇩1' x, mem⇩1' x)
else None)" for x
have domA: "dom A = ?Δ"
proof
show "dom A ⊆ ?Δ"
using A_def
apply (auto simp: domD)
by (metis option.simps(2))
next
show "?Δ ⊆ dom A"
unfolding A_def
apply auto
apply (metis (no_types) domIff domσ option.exhaust option.simps(5))
by (metis (no_types) domIff domσ option.exhaust option.simps(5))
qed
have dma_eq: "dma (?mems⇩1'i [↦ σ]) = dma mem⇩1'"
apply(rule dma_𝒞)
apply(rule ballI)
apply(case_tac "x ∈ ?X' i")
apply(drule not_control[rotated])
apply (metis i_le)
apply blast
apply(subst subst_not_in_dom)
apply(simp add: domσ)
apply(simp add: differing_vars_lists_def differing_vars_def)
done
have dma_eq'': "dma (?mems⇩1i [↦ σ']) = dma mem⇩1"
apply(rule dma_𝒞)
apply(rule ballI)
apply(case_tac "x ∈ ?X i")
using compat compat i_le len_unchanged apply fastforce
apply(subst subst_not_in_dom)
apply(simp add: ‹dom σ' = ?X i›)
apply(simp add: differing_vars_lists_def differing_vars_def)
done
have dma_eq': "dma (subst ((to_partial mem⇩2 |` differing_vars_lists mem⇩1 mem⇩2 mems k)) mem⇩1') = dma mem⇩1'"
using compat b
by(force intro!: dma_𝒞 subst_not_in_dom)
have A_correct:
"⋀ x.
?mems⇩1i [↦ σ'] [∥⇩1 A] x = ?mems⇩1'i [↦ σ] x ∧
?mems⇩2i [↦ σ'] [∥⇩2 A] x = ?mems⇩2'i [↦ σ] x"
proof -
fix x
show "?thesis x"
(is "?Eq⇩1 ∧ ?Eq⇩2")
proof (cases "x ∈ ?Δ")
assume "x ∈ ?Δ"
hence diff:
"?mems⇩1'i [↦ σ] x ≠ ?mems⇩1i [↦ σ'] x ∨ ?mems⇩2'i [↦ σ] x ≠ ?mems⇩2i [↦ σ'] x"
by (auto simp: differing_vars_def)
show ?thesis
proof (cases "dma (?mems⇩1'i [↦ σ]) x")
assume "dma (?mems⇩1'i [↦ σ]) x = High"
from ‹dma (?mems⇩1'i [↦ σ]) x = High› have A_simp [simp]:
"A x = Some (?mems⇩1'i [↦ σ] x, ?mems⇩2'i [↦ σ] x)"
unfolding A_def
by (metis ‹x ∈ ?Δ›)
from A_simp have ?Eq⇩1 ?Eq⇩2
unfolding A_def apply_adaptation_def
by auto
thus ?thesis
by auto
next
assume "dma (?mems⇩1'i [↦ σ]) x = Low"
show ?thesis
proof (cases "x ∈ ?X' i")
assume "x ∈ ?X' i"
then obtain v where "σ x = Some v"
by (metis domD domσ)
hence eq: "?mems⇩1'i [↦ σ] x = v ∧ ?mems⇩2'i [↦ σ] x = v"
unfolding subst_def
by auto
moreover
from ‹x ∈ ?X' i› and ‹dma (?mems⇩1'i [↦ σ]) x = Low› have A_simp [simp]:
"A x = (case σ x of
Some v ⇒ Some (v, v)
| None ⇒ None)"
unfolding A_def
by (metis Sec.simps(1) ‹x ∈ ?Δ›)
ultimately show ?thesis
using domA ‹x ∈ ?Δ› ‹σ x = Some v›
by (auto simp: apply_adaptation_def)
next
assume "x ∉ ?X' i"
hence A_simp [simp]: "A x = Some (mem⇩1' x, mem⇩1' x)"
unfolding A_def
using ‹x ∈ ?Δ› ‹x ∉ ?X' i› ‹dma (?mems⇩1'i [↦ σ]) x = Low›
by auto
from q have "mem⇩1' x = mem⇩2' x"
by (metis ‹dma (?mems⇩1'i [↦ σ]) x = Low› diff ‹x ∉ ?X' i› dma_eq dma_eq'')
from ‹x ∉ ?X' i› have
"?mems⇩1'i [↦ σ] x = ?mems⇩1'i x ∧ ?mems⇩2'i [↦ σ] x = ?mems⇩2'i x"
by (metis domσ subst_not_in_dom)
moreover
from ‹x ∉ ?X' i› have "?mems⇩1'i x = mem⇩1' x ∧ ?mems⇩2'i x = mem⇩2' x"
by (metis differing_vars_neg)
ultimately show ?thesis
using ‹mem⇩1' x = mem⇩2' x›
by (auto simp: apply_adaptation_def)
qed
qed
next
assume "x ∉ ?Δ"
hence "A x = None"
by (metis domA domIff)
from ‹A x = None› have "x ∉ dom A"
by (metis domIff)
from ‹x ∉ ?Δ› have "?mems⇩1i [↦ σ'] [∥⇩1 A] x = ?mems⇩1'i [↦ σ] x ∧
?mems⇩2i [↦ σ'] [∥⇩2 A] x = ?mems⇩2'i [↦ σ] x"
using ‹A x = None›
unfolding differing_vars_def apply_adaptation_def
by auto
thus ?thesis
by auto
qed
qed
hence adapt_eq:
"?mems⇩1i [↦ σ'] [∥⇩1 A] = ?mems⇩1'i [↦ σ] ∧
?mems⇩2i [↦ σ'] [∥⇩2 A] = ?mems⇩2'i [↦ σ]"
by auto
have "cms⇩1' ! i = cms⇩1 ! i"
by (metis ‹i ≠ k› b nth_list_update_neq)
have A_correct': "globally_consistent A (snd (cms⇩1 ! i)) (?mems⇩1i [↦ σ']) (?mems⇩2i [↦ σ'])"
apply(clarsimp simp: globally_consistent_def)
apply(rule conjI)
apply(split option.split)
apply(intro allI conjI)
apply simp
apply(intro allI impI)
apply(split prod.split)
apply(intro allI impI)
apply(simp only:)
proof -
fix x v v'
assume A_updates_x⇩1: "A x = Some (v, v')"
and A_updates_x⇩2:"subst σ' (fst (mems ! i)) x ≠ v ∨ subst σ' (snd (mems ! i)) x ≠ v'"
hence "x ∈ dom A" by(blast)
hence diff:
"?mems⇩1'i [↦ σ] x ≠ ?mems⇩1i [↦ σ'] x ∨ ?mems⇩2'i [↦ σ] x ≠ ?mems⇩2i [↦ σ'] x"
by (auto simp: differing_vars_def domA)
show "¬ var_asm_not_written (snd (cms⇩1 ! i)) x"
proof (cases "x ∉ ?X' i ∨ ((dma mem⇩1 x = Low ∨ dma mem⇩1' x = High) ∧ dma mem⇩1' x = dma mem⇩1 x)")
assume "x ∉ ?X' i ∨ ((dma mem⇩1 x = Low ∨ dma mem⇩1' x = High) ∧ (dma mem⇩1' x = dma mem⇩1 x))"
from this p and diff show writable: "¬ var_asm_not_written (snd (cms⇩1 ! i)) x"
by auto
next
assume "¬ (x ∉ ?X' i ∨ ((dma mem⇩1 x = Low ∨ dma mem⇩1' x = High) ∧ (dma mem⇩1' x = dma mem⇩1 x)))"
hence "x ∈ ?X' i" "((dma mem⇩1 x = High ∧ dma mem⇩1' x = Low) ∨ (dma mem⇩1' x ≠ dma mem⇩1 x))"
by (metis Sec.exhaust)+
thus ?thesis by(fastforce simp add: modifies_no_var_asm_not_written)
qed
next
have reclas: "(∀x. dma ((subst σ' (fst (mems ! i))) [∥⇩1 A]) x ≠ dma (subst σ' (fst (mems ! i))) x ⟶
¬ var_asm_not_written (snd (cms⇩1 ! i)) x)"
apply(simp add: adapt_eq dma_eq dma_eq'')
apply(simp add: modifies_no_var_asm_not_written)
done
have "snd (cms⇩2 ! i) = snd (cms⇩1 ! i)"
by (metis ‹i < length cms⇩1› equal_size modes_eq nth_map)
hence low_mds_eq: "(subst σ' (fst (mems ! i))) =⇘snd (cms⇩1 ! i)⇙⇧l (subst σ' (snd (mems ! i)))"
apply -
apply(rule mm_equiv_low_eq[where c⇩1="fst (cms⇩1 ! i)" and c⇩2="fst (cms⇩2 ! i)"])
using bisim
by (metis prod.collapse)
have "snd (cms⇩2 ! k) = snd (cms⇩1 ! k)"
by (metis b equal_size modes_eq nth_map)
hence low_mds_eq⇩k: "(subst σ'⇩k (fst (mems ! k))) =⇘snd (cms⇩1 ! k)⇙⇧l (subst σ'⇩k (snd (mems ! k)))"
apply -
apply(rule mm_equiv_low_eq[where c⇩1="fst (cms⇩1 ! k)" and c⇩2="fst (cms⇩2 ! k)"])
using bisim⇩k
by (metis prod.collapse)
have eq: "∀x. dma ((subst σ' (fst (mems ! i))) [∥⇩1 A]) x = Low ∧ (x ∈ (snd (cms⇩1 ! i)) AsmNoReadOrWrite ⟶ x ∈ 𝒞) ⟶
(subst σ' (fst (mems ! i))) [∥⇩1 A] x = (subst σ' (snd (mems ! i))) [∥⇩2 A] x"
apply(clarsimp simp: adapt_eq dma_eq)
apply(case_tac "x ∈ dom σ")
apply(force simp: subst_def)
apply(simp add: subst_not_in_dom)
apply(simp add: domσ)
apply(clarsimp simp: differing_vars_lists_def differing_vars_def)
apply(case_tac "i = k")
apply(simp add: ‹i ≠ k›)
apply(erule mems'_i_cases)
apply(rule ‹i < length cms⇩1'›[simplified len_unchanged])
apply force
apply fastforce
apply clarsimp
apply clarsimp
apply(case_tac "x ∈ differing_vars_lists mem⇩1 mem⇩2 mems i")
apply(force simp: differing_vars_lists_def differing_vars_def)
apply(insert low_mds_eq)[1]
apply(simp add: low_mds_eq_def)
apply(drule_tac x=x in spec)
apply(subst (asm) makes_compatible_dma_eq)
apply(rule compat)
apply(rule ‹i < length cms⇩1›)
apply(rule ‹dom σ' = differing_vars_lists mem⇩1 mem⇩2 mems i›)
apply simp
apply(subgoal_tac "x ∉ dom σ'")
apply(simp add: subst_not_in_dom)
apply force
apply(simp add: ‹dom σ' = differing_vars_lists mem⇩1 mem⇩2 mems i›)+
done
from reclas eq
show " (∀x. dma ((subst σ' (fst (mems ! i))) [∥⇩1 A]) x ≠ dma (subst σ' (fst (mems ! i))) x ⟶
¬ var_asm_not_written (snd (cms⇩1 ! i)) x) ∧
(∀x. dma ((subst σ' (fst (mems ! i))) [∥⇩1 A]) x = Low ∧ (x ∈ snd (cms⇩1 ! i) AsmNoReadOrWrite ⟶ x ∈ 𝒞) ⟶
(subst σ' (fst (mems ! i))) [∥⇩1 A] x = (subst σ' (snd (mems ! i))) [∥⇩2 A] x)"
by blast
qed
have "snd (cms⇩1 ! i) = snd (cms⇩2 ! i)"
by (metis ‹i < length cms⇩1› equal_size modes_eq nth_map)
with bisim have "(cms⇩1 ! i, ?mems⇩1i [↦ σ'] [∥⇩1 A]) ≈ (cms⇩2 ! i, ?mems⇩2i [↦ σ'] [∥⇩2 A])"
using A_correct'
apply (subst surjective_pairing[of "cms⇩1 ! i"])
apply (subst surjective_pairing[of "cms⇩2 ! i"])
by (metis surjective_pairing globally_consistent_adapt_bisim)
thus ?thesis using adapt_eq
by (metis ‹i ≠ k› b cms⇩2'_def nth_list_update_neq)
qed
next
fix i x
let ?mems⇩1'i = "fst (mems' ! i)"
let ?mems⇩2'i = "snd (mems' ! i)"
assume i_le: "i < length cms⇩1'"
assume mem_eq': "mem⇩1' x = mem⇩2' x ∨ dma mem⇩1' x = High ∨ x ∈ 𝒞"
show "x ∉ ?X' i"
proof (cases "x ∈ 𝒞")
assume "x ∈ 𝒞"
thus ?thesis by(metis not_control i_le)
next
assume "x ∉ 𝒞"
hence mem_eq: "mem⇩1' x = mem⇩2' x ∨ dma mem⇩1' x = High" by(metis mem_eq')
thus ?thesis
proof (cases "i = k")
assume "i = k"
thus "x ∉ ?X' i"
apply (cases "x ∉ ?X k")
apply (metis differing_vars_neg_intro mems'_k_1 mems'_k_2)
by(metis compat_different[OF compat] b mem_eq Sec.distinct(1) x_unchanged)
next
assume "i ≠ k"
thus "x ∉ ?X' i"
proof (rule mems'_i_cases)
from b i_le show "i < length cms⇩1"
by (metis length_list_update)
next
assume "fst (mems' ! i) x = mem⇩1' x"
"snd (mems' ! i) x = mem⇩2' x"
thus "x ∉ ?X' i"
by (metis differing_vars_neg_intro)
next
assume "mem⇩1 x ≠ mem⇩1' x ∨ mem⇩2 x ≠ mem⇩2' x"
"mem⇩1' x ≠ mem⇩2' x" and "dma mem⇩1' x = Low"
thus "x ∉ ?X' i"
by (metis Sec.simps(2) mem_eq)
next
assume case3: "mem⇩1 x = mem⇩1' x" "mem⇩2 x = mem⇩2' x"
"dma mem⇩1 x = Low ∨ dma mem⇩1' x = High"
"fst (mems' ! i) x = fst (mems ! i) x"
"snd (mems' ! i) x = snd (mems ! i) x"
have "x ∈ ?X' i ⟹ mem⇩1' x ≠ mem⇩2' x ∧ dma mem⇩1' x = Low"
proof -
assume "x ∈ ?X' i"
from case3 and ‹x ∈ ?X' i› have "x ∈ ?X i"
by (metis differing_vars_neg differing_vars_elim)
with case3 have "mem⇩1' x ≠ mem⇩2' x ∧ dma mem⇩1 x = Low"
by (metis b compat compat_different i_le length_list_update)
with mem_eq have clases: "dma mem⇩1 x = Low ∧ dma mem⇩1' x = High" by auto
have "fst (mems' ! i) x = mem⇩1' x ∧ snd (mems' ! i) x = mem⇩2' x"
apply(rule mems'_i_5)
apply(rule ‹i ≠ k›)
using i_le len_unchanged apply(simp)
apply(simp add: case3)+
apply(simp add: clases)+
done
hence "x ∉ ?X' i" by (metis differing_vars_neg_intro)
with ‹x ∈ ?X' i› show ?thesis by blast
qed
with ‹mem⇩1' x = mem⇩2' x ∨ dma mem⇩1' x = High› show "x ∉ ?X' i"
by auto
next
assume case4: "mem⇩1 x = mem⇩1' x" "mem⇩2 x = mem⇩2' x"
"dma mem⇩1 x = High" "dma mem⇩1' x = Low"
"fst (mems' ! i) x = mem⇩1 x" "snd (mems' ! i) x = mem⇩1 x"
with mem_eq have "mem⇩1' x = mem⇩2' x" by auto
with case4 show ?thesis by(auto simp: differing_vars_def differing_vars_lists_def)
next
assume "fst (mems' ! i) x = mem⇩1' x"
"snd (mems' ! i) x = mem⇩2' x" thus ?thesis by(metis differing_vars_neg_intro)
qed
qed
qed
next
{ fix x
have "∃ i < length cms⇩1. x ∉ ?X' i"
proof (cases "mem⇩1 x ≠ mem⇩1' x ∨ mem⇩2 x ≠ mem⇩2' x ∨ dma mem⇩1' x ≠ dma mem⇩1 x")
assume var_changed: "mem⇩1 x ≠ mem⇩1' x ∨ mem⇩2 x ≠ mem⇩2' x ∨ dma mem⇩1' x ≠ dma mem⇩1 x"
have "x ∉ ?X' k"
apply (rule mems'_k_cases)
apply (metis differing_vars_neg_intro)
by (metis var_changed x_unchanged)
thus ?thesis by (metis b)
next
assume "¬ (mem⇩1 x ≠ mem⇩1' x ∨ mem⇩2 x ≠ mem⇩2' x ∨ dma mem⇩1' x ≠ dma mem⇩1 x)"
hence assms: "mem⇩1 x = mem⇩1' x" "mem⇩2 x = mem⇩2' x" "dma mem⇩1' x = dma mem⇩1 x" by auto
have "length cms⇩1 ≠ 0"
using b
by (metis less_zeroE)
then obtain i where i_prop: "i < length cms⇩1 ∧ x ∉ ?X i"
using compat
by (auto, blast)
show ?thesis
proof (cases "i = k")
assume "i = k"
have "x ∉ ?X' k"
apply (rule mems'_k_cases)
apply (metis differing_vars_neg_intro)
by (metis i_prop ‹i = k›)
thus ?thesis
by (metis b)
next
from i_prop have "x ∉ ?X i" by simp
assume "i ≠ k"
hence "x ∉ ?X' i"
apply -
apply(rule mems'_i_cases)
apply assumption
apply(simp add: i_prop)
apply(simp add: assms)+
using ‹x ∉ ?X i› differing_vars_neg
using ‹¬ (mem⇩1 x ≠ mem⇩1' x ∨ mem⇩2 x ≠ mem⇩2' x ∨ dma mem⇩1' x ≠ dma mem⇩1 x)› differing_vars_elim apply auto[1]
by(metis differing_vars_neg_intro)
with i_prop show ?thesis
by auto
qed
qed
}
thus "(length cms⇩1' = 0 ∧ mem⇩1' =⇧l mem⇩2') ∨ (∀ x. ∃ i < length cms⇩1'. x ∉ ?X' i)"
by (metis cms⇩2'_def equal_size length_list_update new_length)
qed
qed
ultimately show ?thesis using that by blast
qed
text ‹The Isar proof language provides a readable
way of specifying assumptions while also giving them names for subsequent
usage.›
lemma compat_low_eq:
assumes compat: "makes_compatible (cms⇩1, mem⇩1) (cms⇩2, mem⇩2) mems"
assumes modes_eq: "map snd cms⇩1 = map snd cms⇩2"
assumes x_low: "dma mem⇩1 x = Low"
assumes x_readable: "x ∈ 𝒞 ∨ (∀ i < length cms⇩1. x ∉ snd (cms⇩1 ! i) AsmNoReadOrWrite)"
shows "mem⇩1 x = mem⇩2 x"
proof -
let ?X = "λ i. differing_vars_lists mem⇩1 mem⇩2 mems i"
from compat have "(length cms⇩1 = 0 ∧ mem⇩1 =⇧l mem⇩2) ∨
(∀ x. ∃ j. j < length cms⇩1 ∧ x ∉ ?X j)"
by auto
thus "mem⇩1 x = mem⇩2 x"
proof
assume "length cms⇩1 = 0 ∧ mem⇩1 =⇧l mem⇩2"
with x_low show ?thesis
by (simp add: low_eq_def)
next
assume "∀ x. ∃ j. j < length cms⇩1 ∧ x ∉ ?X j"
then obtain j where j_prop: "j < length cms⇩1 ∧ x ∉ ?X j"
by auto
let ?mems⇩1j = "fst (mems ! j)" and
?mems⇩2j = "snd (mems ! j)"
obtain σ :: "'Var ⇀ 'Val" where domσ: "dom σ = ?X j"
by (metis dom_restrict_total)
from compat x_low makes_compatible_dma_eq j_prop ‹dom σ = ?X j›
have x_low: "dma (?mems⇩1j [↦ σ]) x = Low"
by metis
from domσ compat and j_prop have "(cms⇩1 ! j, ?mems⇩1j [↦ σ]) ≈ (cms⇩2 ! j, ?mems⇩2j [↦ σ])"
by auto
moreover
have "snd (cms⇩1 ! j) = snd (cms⇩2 ! j)"
using modes_eq
by (metis j_prop length_map nth_map)
ultimately have "?mems⇩1j [↦ σ] =⇘snd (cms⇩1 ! j)⇙⇧l ?mems⇩2j [↦ σ]"
using modes_eq j_prop
by (metis mm_equiv_low_eq prod.collapse)
hence "?mems⇩1j x = ?mems⇩2j x"
using x_low x_readable j_prop ‹dom σ = ?X j›
unfolding low_mds_eq_def
by (metis subst_not_in_dom)
thus ?thesis
using j_prop
by (metis compat_different_vars)
qed
qed
lemma loc_reach_subset:
assumes eval: "⟨c, mds, mem⟩ ↝ ⟨c', mds', mem'⟩"
shows "loc_reach ⟨c', mds', mem'⟩ ⊆ loc_reach ⟨c, mds, mem⟩"
proof (clarify)
fix c'' mds'' mem''
from eval have "⟨c', mds', mem'⟩ ∈ loc_reach ⟨c, mds, mem⟩"
by (metis loc_reach.refl loc_reach.step surjective_pairing)
assume "⟨c'', mds'', mem''⟩ ∈ loc_reach ⟨c', mds', mem'⟩"
thus "⟨c'', mds'', mem''⟩ ∈ loc_reach ⟨c, mds, mem⟩"
apply induct
apply (metis ‹⟨c', mds', mem'⟩ ∈ loc_reach ⟨c, mds, mem⟩› surjective_pairing)
apply (metis loc_reach.step)
by (metis loc_reach.mem_diff)
qed
lemma locally_sound_modes_invariant:
assumes sound_modes: "locally_sound_mode_use ⟨c, mds, mem⟩"
assumes eval: "⟨c, mds, mem⟩ ↝ ⟨c', mds', mem'⟩"
shows "locally_sound_mode_use ⟨c', mds', mem'⟩"
proof -
from eval have "⟨c', mds', mem'⟩ ∈ loc_reach ⟨c, mds, mem⟩"
by (metis fst_conv loc_reach.refl loc_reach.step snd_conv)
thus ?thesis
using sound_modes
unfolding locally_sound_mode_use_def
by (metis (no_types) Collect_empty_eq eval loc_reach_subset subsetD)
qed
lemma meval_sched_one:
"(cms, mem) ↝⇘k⇙ (cms', mem') ⟹
(cms, mem) →⇘[k]⇙ (cms', mem')"
apply(simp)
done
lemma meval_sched_ConsI:
"(cms, mem) ↝⇘k⇙ (cms', mem') ⟹
(cms', mem') →⇘sched⇙ (cms'', mem'') ⟹
(cms, mem) →⇘(k#sched)⇙ (cms'', mem'')"
by fastforce
lemma reachable_modes_subset:
assumes eval: "(cms, mem) ↝⇘k⇙ (cms', mem')"
shows "reachable_mode_states (cms', mem') ⊆ reachable_mode_states (cms, mem)"
proof
fix mdss
assume "mdss ∈ reachable_mode_states (cms', mem')"
thus "mdss ∈ reachable_mode_states (cms, mem)"
using assms
unfolding reachable_mode_states_def
by (blast intro: meval_sched_ConsI)
qed
lemma globally_sound_modes_invariant:
assumes globally_sound: "globally_sound_mode_use (cms, mem)"
assumes eval: "(cms, mem) ↝⇘k⇙ (cms', mem')"
shows "globally_sound_mode_use (cms', mem')"
using assms reachable_modes_subset
unfolding globally_sound_mode_use_def
by (metis (no_types) subsetD)
lemma loc_reach_mem_diff_subset:
assumes mem_diff: "∀ x. var_asm_not_written mds x ⟶ mem⇩1 x = mem⇩2 x ∧ dma mem⇩1 x = dma mem⇩2 x"
shows "⟨c', mds', mem'⟩ ∈ loc_reach ⟨c, mds, mem⇩1⟩ ⟹ ⟨c', mds', mem'⟩ ∈ loc_reach ⟨c, mds, mem⇩2⟩"
proof -
let ?lc = "⟨c', mds', mem'⟩"
assume "?lc ∈ loc_reach ⟨c, mds, mem⇩1⟩"
thus ?thesis
proof (induct)
case refl
thus ?case
by (metis fst_conv loc_reach.mem_diff loc_reach.refl mem_diff snd_conv)
next
case step
thus ?case
by (metis loc_reach.step)
next
case mem_diff
thus ?case
by (metis loc_reach.mem_diff)
qed
qed
lemma loc_reach_mem_diff_eq:
assumes mem_diff: "∀ x. var_asm_not_written mds x ⟶ mem' x = mem x ∧ dma mem' x = dma mem x"
shows "loc_reach ⟨c, mds, mem⟩ = loc_reach ⟨c, mds, mem'⟩"
using assms loc_reach_mem_diff_subset
by (auto, metis)
lemma sound_modes_invariant:
assumes sound_modes: "sound_mode_use (cms, mem)"
assumes eval: "(cms, mem) ↝⇘k⇙ (cms', mem')"
shows "sound_mode_use (cms', mem')"
proof -
from sound_modes and eval have "globally_sound_mode_use (cms', mem')"
by (metis globally_sound_modes_invariant sound_mode_use.simps)
moreover
from sound_modes have loc_sound: "∀ i < length cms. locally_sound_mode_use (cms ! i, mem)"
unfolding sound_mode_use_def
by simp (metis list_all_length)
from eval obtain k cms⇩k' where
ev: "(cms ! k, mem) ↝ (cms⇩k', mem') ∧ k < length cms ∧ cms' = cms [k := cms⇩k']"
by (metis meval_elim)
hence "length cms = length cms'"
by auto
have "⋀ i. i < length cms' ⟹ locally_sound_mode_use (cms' ! i, mem')"
proof -
fix i
assume i_le: "i < length cms'"
thus "?thesis i"
proof (cases "i = k")
assume "i = k"
thus ?thesis
using i_le ev loc_sound
by (metis (opaque_lifting, no_types) locally_sound_modes_invariant nth_list_update surj_pair)
next
assume "i ≠ k"
hence "cms' ! i = cms ! i"
by (metis ev nth_list_update_neq)
from sound_modes have "compatible_modes (map snd cms)"
unfolding sound_mode_use.simps
by (metis globally_sound_modes_compatible)
hence "⋀ x. var_asm_not_written (snd (cms ! i)) x ⟹ x ∈ snd (cms ! k) GuarNoWrite ∨ x ∈ snd (cms ! k) GuarNoReadOrWrite"
unfolding compatible_modes_def
by (metis (no_types) ‹i ≠ k› ‹length cms = length cms'› ev i_le length_map nth_map var_asm_not_written_def)
hence "⋀ x. var_asm_not_written (snd (cms ! i)) x ⟶ doesnt_modify (fst (cms ! k)) x"
using ev loc_sound
unfolding locally_sound_mode_use_def
by (metis loc_reach.refl surjective_pairing doesnt_read_or_modify_doesnt_modify)
with ev have "⋀ x. var_asm_not_written (snd (cms ! i)) x ⟹ mem x = mem' x ∧ dma mem x = dma mem' x"
unfolding doesnt_modify_def by (metis prod.collapse)
with loc_reach_mem_diff_eq have "loc_reach (cms ! i, mem') = loc_reach (cms ! i, mem)"
apply -
by(case_tac "cms ! i", simp)
thus ?thesis
using loc_sound i_le ‹length cms = length cms'›
unfolding locally_sound_mode_use_def
by (metis ‹cms' ! i = cms ! i›)
qed
qed
ultimately show ?thesis
unfolding sound_mode_use.simps
by (metis (no_types) list_all_length)
qed
lemma app_Cons_rewrite:
"ns @ (a # ms) = ((ns @ [a]) @ ms)"
apply simp
done
lemma meval_sched_app_iff:
"(cms⇩1, mem⇩1) →⇘ns@ms⇙ (cms⇩1', mem⇩1') =
(∃cms⇩1'' mem⇩1''. (cms⇩1, mem⇩1) →⇘ns⇙ (cms⇩1'', mem⇩1'') ∧ (cms⇩1'', mem⇩1'') →⇘ms⇙ (cms⇩1', mem⇩1'))"
apply(induct ns arbitrary: ms cms⇩1 mem⇩1)
apply simp
apply force
done
lemmas meval_sched_appD = meval_sched_app_iff[THEN iffD1]
lemmas meval_sched_appI = meval_sched_app_iff[THEN iffD2, OF exI, OF exI]
lemma meval_sched_snocD:
"(cms⇩1, mem⇩1) →⇘ns@[n]⇙ (cms⇩1', mem⇩1') ⟹
∃cms⇩1'' mem⇩1''. (cms⇩1, mem⇩1) →⇘ns⇙ (cms⇩1'', mem⇩1'') ∧ (cms⇩1'', mem⇩1'') ↝⇘n⇙ (cms⇩1', mem⇩1')"
apply(fastforce dest: meval_sched_appD)
done
lemma meval_sched_snocI:
"(cms⇩1, mem⇩1) →⇘ns⇙ (cms⇩1'', mem⇩1'') ∧ (cms⇩1'', mem⇩1'') ↝⇘n⇙ (cms⇩1', mem⇩1') ⟹
(cms⇩1, mem⇩1) →⇘ns@[n]⇙ (cms⇩1', mem⇩1')"
apply(fastforce intro: meval_sched_appI)
done
lemma makes_compatible_eval_sched:
assumes compat: "makes_compatible (cms⇩1, mem⇩1) (cms⇩2, mem⇩2) mems"
assumes modes_eq: "map snd cms⇩1 = map snd cms⇩2"
assumes sound_modes: "sound_mode_use (cms⇩1, mem⇩1)" "sound_mode_use (cms⇩2, mem⇩2)"
assumes eval: "(cms⇩1, mem⇩1) →⇘sched⇙ (cms⇩1', mem⇩1')"
shows "∃ cms⇩2' mem⇩2' mems'. sound_mode_use (cms⇩1', mem⇩1') ∧
sound_mode_use (cms⇩2', mem⇩2') ∧
map snd cms⇩1' = map snd cms⇩2' ∧
(cms⇩2, mem⇩2) →⇘sched⇙ (cms⇩2', mem⇩2') ∧
makes_compatible (cms⇩1', mem⇩1') (cms⇩2', mem⇩2') mems'"
proof -
from eval show ?thesis
proof (induct "sched" arbitrary: cms⇩1' mem⇩1' rule: rev_induct)
case Nil
hence "cms⇩1' = cms⇩1 ∧ mem⇩1' = mem⇩1"
by (simp add: Pair_inject meval_sched.simps(1))
thus ?case
by (metis compat meval_sched.simps(1) modes_eq sound_modes)
next
case (snoc n ns)
then obtain cms⇩1'' mem⇩1'' where eval'':
"(cms⇩1, mem⇩1) →⇘ns⇙ (cms⇩1'', mem⇩1'') ∧ (cms⇩1'', mem⇩1'') ↝⇘n⇙ (cms⇩1', mem⇩1')"
by (metis meval_sched_snocD prod_cases3 snd_conv)
hence "(cms⇩1'', mem⇩1'') ↝⇘n⇙ (cms⇩1', mem⇩1')" ..
moreover
from eval'' obtain cms⇩2'' mem⇩2'' mems'' where IH:
"sound_mode_use (cms⇩1'', mem⇩1'') ∧
sound_mode_use (cms⇩2'', mem⇩2'') ∧
map snd cms⇩1'' = map snd cms⇩2'' ∧
(cms⇩2, mem⇩2) →⇘ns⇙ (cms⇩2'', mem⇩2'') ∧
makes_compatible (cms⇩1'', mem⇩1'') (cms⇩2'', mem⇩2'') mems''"
using snoc
by metis
ultimately obtain cms⇩2' mem⇩2' mems' where
"map snd cms⇩1' = map snd cms⇩2' ∧
(cms⇩2'', mem⇩2'') ↝⇘n⇙ (cms⇩2', mem⇩2') ∧
makes_compatible (cms⇩1', mem⇩1') (cms⇩2', mem⇩2') mems'"
using makes_compatible_invariant
by blast
thus ?case
using IH eval'' meval_sched_snocI sound_modes_invariant
by metis
qed
qed
lemma differing_vars_initially_empty:
"i < n ⟹ x ∉ differing_vars_lists mem⇩1 mem⇩2 (zip (replicate n mem⇩1) (replicate n mem⇩2)) i"
unfolding differing_vars_lists_def differing_vars_def
by auto
lemma compatible_refl:
assumes coms_secure: "list_all com_sifum_secure cmds"
assumes low_eq: "mem⇩1 =⇧l mem⇩2"
shows "makes_compatible (cmds, mem⇩1)
(cmds, mem⇩2)
(replicate (length cmds) (mem⇩1, mem⇩2))"
proof -
let ?n = "length cmds"
let ?mems = "replicate ?n (mem⇩1, mem⇩2)" and
?mdss = "map snd cmds"
let ?X = "differing_vars_lists mem⇩1 mem⇩2 ?mems"
have diff_empty: "∀ i < ?n. ?X i = {}"
by (metis differing_vars_initially_empty ex_in_conv min.idem zip_replicate)
show ?thesis
proof
show "length cmds = length cmds ∧ length cmds = length ?mems"
by auto
next
fix i and σ :: "'Var ⇒ 'Val option"
let ?mems⇩1i = "fst (?mems ! i)" and ?mems⇩2i = "snd (?mems ! i)"
let ?mdss⇩i = "?mdss ! i"
assume i: "i < length cmds"
assume domσ: "dom σ =
differing_vars_lists mem⇩1 mem⇩2
(replicate (length cmds) (mem⇩1, mem⇩2)) i"
from i have "?mems⇩1i = mem⇩1" "?mems⇩2i = mem⇩2"
by auto
with domσ have [simp]: "dom σ = {}" by(auto simp: differing_vars_lists_def differing_vars_def i)
from i coms_secure have "com_sifum_secure (cmds ! i)"
using coms_secure
by (metis length_map length_replicate list_all_length map_snd_zip)
with i have "⋀ mem⇩1 mem⇩2. mem⇩1 =⇘?mdss⇩i⇙⇧l mem⇩2 ⟹
(cmds ! i, mem⇩1) ≈ (cmds ! i, mem⇩2)"
using com_sifum_secure_def low_indistinguishable_def
by auto
moreover
have "⋀x. σ x = None" using ‹dom σ = {}›
by (metis domIff empty_iff)
hence [simp]: "⋀ mem. mem [↦ σ] = mem"
by(simp add: subst_def)
from i have "?mems⇩1i = mem⇩1" "?mems⇩2i = mem⇩2"
by auto
with low_eq have "?mems⇩1i [↦ σ] =⇘?mdss⇩i⇙⇧l ?mems⇩2i [↦ σ]"
by (auto simp: low_mds_eq_def low_eq_def)
ultimately show "(cmds ! i, ?mems⇩1i [↦ σ]) ≈ (cmds ! i, ?mems⇩2i [↦ σ])"
by simp
next
fix i x
assume "i < length cmds"
with diff_empty show "x ∉ ?X i" by auto
next
show "(length cmds = 0 ∧ mem⇩1 =⇧l mem⇩2) ∨ (∀ x. ∃ i < length cmds. x ∉ ?X i)"
using diff_empty
by (metis bot_less bot_nat_def empty_iff length_zip low_eq min_0L)
qed
qed
theorem sifum_compositionality_cont:
assumes com_secure: "list_all com_sifum_secure cmds"
assumes sound_modes: "∀ mem. INIT mem ⟶ sound_mode_use (cmds, mem)"
shows "prog_sifum_secure_cont cmds"
unfolding prog_sifum_secure_cont_def
using assms
proof (clarify)
fix mem⇩1 mem⇩2 :: "'Var ⇒ 'Val"
fix sched cms⇩1' mem⇩1'
let ?n = "length cmds"
let ?mems = "zip (replicate ?n mem⇩1) (replicate ?n mem⇩2)"
assume INIT⇩1: "INIT mem⇩1" and INIT⇩2: "INIT mem⇩2"
assume low_eq: "mem⇩1 =⇧l mem⇩2"
with com_secure have compat:
"makes_compatible (cmds, mem⇩1) (cmds, mem⇩2) ?mems"
by (metis compatible_refl fst_conv length_replicate map_replicate snd_conv zip_eq_conv INIT⇩1 INIT⇩2)
also assume eval: "(cmds, mem⇩1) →⇘sched⇙ (cms⇩1', mem⇩1')"
ultimately obtain cms⇩2' mem⇩2' mems'
where p: "map snd cms⇩1' = map snd cms⇩2' ∧
(cmds, mem⇩2) →⇘sched⇙ (cms⇩2', mem⇩2') ∧
makes_compatible (cms⇩1', mem⇩1') (cms⇩2', mem⇩2') mems'"
using sound_modes makes_compatible_eval_sched INIT⇩1 INIT⇩2
by blast
thus "∃ cms⇩2' mem⇩2'. (cmds, mem⇩2) →⇘sched⇙ (cms⇩2', mem⇩2') ∧
map snd cms⇩1' = map snd cms⇩2' ∧
length cms⇩2' = length cms⇩1' ∧
(∀ x. dma mem⇩1' x = Low ∧ (x ∈ 𝒞 ∨ (∀ i < length cms⇩1'. x ∉ snd (cms⇩1' ! i) AsmNoReadOrWrite))
⟶ mem⇩1' x = mem⇩2' x)"
using p compat_low_eq
by (metis length_map)
qed
end
end