(* * Copyright 2016, General Dynamics C4 Systems * * This software may be distributed and modified according to the terms of * the GNU General Public License version 2. Note that NO WARRANTY is provided. * See "LICENSE_GPLv2.txt" for details. * * @TAG(GD_GPL) *) (* Experimental AutoCorres proofs over CRefine: work in progress *) theory AutoCorresTest imports (* Frameworks and tactics *) AutoCorres_C (* import Refine_C last to minimise change to global context *) Refine_C begin section \Simple test case: handleYield\ autocorres [ skip_heap_abs, skip_word_abs, (* for compatibility *) scope = handleYield, scope_depth = 0, c_locale = kernel_all_substitute, no_c_termination ] "c/kernel_all.c_pp" context kernel_m begin text \Export corres_underlying rules for handleYield's callees.\ thm getCurThread_ccorres lemma getCurThread_wrapper_corres: "corres_underlying {(x, y). cstate_relation x y} True True (\ct ct'. tcb_ptr_to_ctcb_ptr ct = ct') invs' (\_. True) getCurThread (gets ksCurThread_')" by (simp add: getCurThread_def cstate_relation_def Let_def) thm ccorres_pre_getCurThread lemma corres_pre_getCurThread_wrapper: assumes cc: "\rv rv'. rv' = tcb_ptr_to_ctcb_ptr rv \ corres_underlying {(x, y). cstate_relation x y} True True R (P rv) (P' rv) (f rv) (f' rv')" shows "corres_underlying {(x, y). cstate_relation x y} True True R (\s. \rv. ksCurThread s = rv \ P rv s) (\s. \rv. ksCurThread_' s = tcb_ptr_to_ctcb_ptr rv \ P' rv s) (getCurThread >>= f) (gets ksCurThread_' >>= f')" (* ugly but works -- corres_symb_exec_l doesn't *) using cc apply (clarsimp simp: corres_underlying_def getCurThread_def) apply monad_eq apply (clarsimp simp: cstate_relation_def Let_def) done thm tcbSchedDequeue_ccorres lemma tcbSchedDequeue_wrapper_corres: "tcb_ptr_to_ctcb_ptr ct = ct' \ corres_underlying {(x, y). cstate_relation x y} True True (op=) (Invariants_H.valid_queues and valid_queues' and tcb_at' ct and valid_objs') \ (tcbSchedDequeue ct) (tcbSchedDequeue' ct')" apply (rule ccorres_to_corres_no_termination) apply (simp add: tcbSchedDequeue'_def) apply (clarsimp simp: ccorres_rrel_nat_unit tcbSchedDequeue_ccorres[simplified]) done thm tcbSchedAppend_ccorres lemma tcbSchedAppend_wrapper_corres: "tcb_ptr_to_ctcb_ptr ct = ct' \ corres_underlying {(x, y). cstate_relation x y} True True (op=) (Invariants_H.valid_queues and tcb_at' ct and valid_objs') \ (tcbSchedAppend ct) (tcbSchedAppend' ct')" apply (rule ccorres_to_corres_no_termination) apply (simp add: tcbSchedAppend'_def) apply (clarsimp simp: ccorres_rrel_nat_unit tcbSchedAppend_ccorres[simplified]) done thm rescheduleRequired_ccorres lemma rescheduleRequired_wrapper_corres: "corres_underlying {(x, y). cstate_relation x y} True True (op=) (Invariants_H.valid_queues and (\s. weak_sch_act_wf (ksSchedulerAction s) s) and valid_objs') \ rescheduleRequired rescheduleRequired'" apply (rule ccorres_to_corres_no_termination) apply (simp add: rescheduleRequired'_def) apply (clarsimp simp: ccorres_rrel_nat_unit rescheduleRequired_ccorres[simplified]) done text \ Proving handleYield_ccorres via handleYield'. The handleYield spec has one less getCurThread, so we need to use the fact that tcbSchedDequeue does not modify ksCurThread. \ local_setup \AutoCorresModifiesProofs.new_modifies_rules "c/kernel_all.c_pp"\ thm tcbSchedDequeue'_modifies text \Existing ccorres proof, for reference\ lemma (* handleYield_ccorres: *) "ccorres dc xfdc (invs' and ct_active') UNIV [] (handleYield) (Call handleYield_'proc)" apply cinit apply (rule ccorres_pre_getCurThread) apply (ctac add: tcbSchedDequeue_ccorres) apply (ctac add: tcbSchedAppend_ccorres) apply (ctac add: rescheduleRequired_ccorres) apply (wp weak_sch_act_wf_lift_linear tcbSchedAppend_valid_objs') apply (vcg exspec= tcbSchedAppend_modifies) apply (wp weak_sch_act_wf_lift_linear tcbSchedDequeue_valid_queues) apply (vcg exspec= tcbSchedDequeue_modifies) apply (clarsimp simp: tcb_at_invs' invs_valid_objs' valid_objs'_maxPriority valid_objs'_maxDomain) apply (auto simp: obj_at'_def st_tcb_at'_def ct_in_state'_def valid_objs'_maxDomain) done lemma reorder_gets: "(\x. \ \s. x = f s \ g \ \_ s. x = f s \) \ (do x \ gets f; g; h x od) = (do g; x \ gets f; h x od)" by (fastforce simp: bind_def' valid_def gets_def get_def return_def) text \Now the proof.\ lemma (* handleYield_ccorres: *) "ccorres dc xfdc (invs' and ct_active') UNIV [] (handleYield) (Call handleYield_'proc)" apply (rule ac_corres_to_ccorres) apply (rule kernel_all_substitute.handleYield'_ac_corres) apply simp apply (simp add: handleYield_def handleYield'_def) apply (rule corres_guard_imp) (* Show that current thread is unmodified. * FIXME: proper way to do this? *) apply (subst reorder_gets[symmetric, unfolded K_bind_def]) using tcbSchedDequeue'_modifies apply (fastforce simp: valid_def) apply (subst gets_gets) apply (rule corres_pre_getCurThread_wrapper) apply (rule corres_split[OF _ tcbSchedDequeue_wrapper_corres]) apply (rule corres_split[OF _ tcbSchedAppend_wrapper_corres]) apply (rule rescheduleRequired_wrapper_corres) apply (solves simp) apply (solves \wp tcbSchedAppend_valid_objs' weak_sch_act_wf_lift_linear | simp\)+ apply (solves \wp tcbSchedDequeue_invs' tcbSchedDequeue_typ_at' tcbSchedDequeue_valid_queues tcbSchedDequeue_valid_objs' weak_sch_act_wf_lift_linear\) apply (solves wp) apply (clarsimp simp: invs_valid_objs' invs_queues invs_valid_queues' tcb_at_invs' valid_objs'_maxPriority valid_objs'_maxDomain) apply (fastforce simp: obj_at'_def st_tcb_at'_def ct_in_state'_def dest: ct_active_runnable') apply fastforce done end section \Function call testcase: handleFault and handleDoubleFault\ autocorres [ skip_heap_abs, skip_word_abs, (* for compatibility *) scope = handleDoubleFault, scope_depth = 0, c_locale = kernel_all_substitute, no_c_termination ] "c/kernel_all.c_pp" context kernel_m begin local_setup \AutoCorresModifiesProofs.new_modifies_rules "c/kernel_all.c_pp"\ text \Export corres_underlying rules for handleDoubleFault's callees.\ thm setThreadState_ccorres[no_vars] lemma setThreadState_wrapper_corres: "(\cl fl. cthread_state_relation_lifted st (cl\tsType_CL := ts && mask 4\, fl)) \ tptr = tcb_ptr_to_ctcb_ptr thread \ corres_underlying {(x, y). cstate_relation x y} True True (op=) (\s. tcb_at' thread s \ Invariants_H.valid_queues s \ valid_objs' s \ valid_tcb_state' st s \ (ksSchedulerAction s = SwitchToThread thread \ runnable' st) \ (\p. thread \ set (ksReadyQueues s p) \ runnable' st) \ sch_act_wf (ksSchedulerAction s) s) \ (setThreadState st thread) (setThreadState' tptr ts)" apply (rule ccorres_to_corres_no_termination) apply (simp add: setThreadState'_def) apply (clarsimp simp: ccorres_rrel_nat_unit) using setThreadState_ccorres apply (fastforce simp: ccorres_underlying_def Ball_def) done text \Extra corres_underlying rules.\ lemma corres_gen_asm': "\ corres_underlying sr nf nf' r Q P' f g; \s s'. \ (s, s') \ sr; P s; P' s' \ \ Q s\ \ corres_underlying sr nf nf' r P P' f g" by (fastforce simp: corres_underlying_def) lemma corres_add_noop_rhs2: "corres_underlying sr nf nf' r P P' f (do _ \ g; return () od) \ corres_underlying sr nf nf' r P P' f g" by simp (* Use termination (nf=True) to avoid exs_valid *) lemma corres_noop2_no_exs: assumes x: "\s. P s \ \op = s\ f \\r. op = s\ \ empty_fail f" assumes y: "\s. P' s \ \op = s\ g \\r. op = s\" assumes z: "nf' \ no_fail P f" "no_fail P' g" shows "corres_underlying sr True nf' dc P P' f g" apply (clarsimp simp: corres_underlying_def) apply (rule conjI) apply (drule x, drule y) apply (clarsimp simp: valid_def empty_fail_def Ball_def Bex_def) apply fast apply (insert z) apply (clarsimp simp: no_fail_def) done lemma corres_symb_exec_l_no_exs: assumes z: "\rv. corres_underlying sr True nf' r (Q rv) P' (x rv) y" assumes x: "\s. P s \ \op = s\ m \\r. op = s\ \ empty_fail m" assumes y: "\P\ m \Q\" assumes nf: "nf' \ no_fail P m" shows "corres_underlying sr True nf' r P P' (m >>= (\rv. x rv)) y" apply (rule corres_guard_imp) apply (subst gets_bind_ign[symmetric], rule corres_split) apply (rule z) apply (rule corres_noop2_no_exs) apply (erule x) apply (rule gets_wp) apply (erule nf) apply (rule non_fail_gets) apply (rule y) apply (rule gets_wp) apply simp+ done text \Existing ccorres proof, for reference\ lemma (* handleDoubleFault_ccorres: *) "ccorres dc xfdc (invs' and tcb_at' tptr and (\s. weak_sch_act_wf (ksSchedulerAction s) s) and sch_act_not tptr and (\s. \p. tptr \ set (ksReadyQueues s p))) (UNIV \ {s. tptr_' s = tcb_ptr_to_ctcb_ptr tptr}) [] (handleDoubleFault tptr ex1 ex2) (Call handleDoubleFault_'proc)" apply (cinit lift: tptr_') apply (subst ccorres_seq_skip'[symmetric]) apply (ctac (no_vcg)) apply (rule ccorres_symb_exec_l) apply (rule ccorres_return_Skip) apply (wp asUser_inv getRestartPC_inv) apply (rule empty_fail_asUser) apply (simp add: getRestartPC_def) apply wp apply clarsimp apply (simp add: ThreadState_Inactive_def) apply (fastforce simp: valid_tcb_state'_def) done text \New proof of handleDoubleFault\ lemma (* handleDoubleFault_ccorres: *) "ccorres dc xfdc (invs' and tcb_at' tptr and (\s. weak_sch_act_wf (ksSchedulerAction s) s) and sch_act_not tptr and (\s. \p. tptr \ set (ksReadyQueues s p))) (UNIV \ {s. ex1_' s = ex1' \ tptr_' s = tcb_ptr_to_ctcb_ptr tptr}) [] (handleDoubleFault tptr ex1 ex2) (Call handleDoubleFault_'proc)" apply (rule ac_corres_to_ccorres[where R="op="]) apply (rule handleDoubleFault'_ac_corres) apply (simp add: pred_conj_def) apply (unfold handleDoubleFault_def handleDoubleFault'_def) apply (simp only: K_bind_def) -- "normalise" apply (rule corres_add_noop_rhs2) -- "split out extra haskell code" apply (rule corres_split') (* call setThreadState *) apply (rule corres_gen_asm') apply (rule setThreadState_wrapper_corres) apply (simp add: ThreadState_Inactive_def) apply (fastforce simp: valid_tcb_state'_def ThreadState_Inactive_def) (* extra haskell code *) apply simp apply (rule corres_symb_exec_l_no_exs) apply simp apply (rule conjI) apply (wp asUser_inv getRestartPC_inv) apply (wp empty_fail_asUser)[1] apply (rule hoare_TrueI) apply (simp add: getRestartPC_def) apply wp apply simp apply (rule hoare_TrueI) done end autocorres [ skip_heap_abs, skip_word_abs, (* for compatibility *) scope = handleFault, scope_depth = 0, c_locale = kernel_all_substitute, no_c_termination ] "c/kernel_all.c_pp" (* Prove and store modifies rules. *) context kernel_m begin local_setup \AutoCorresModifiesProofs.new_modifies_rules "c/kernel_all.c_pp"\ (* TODO: proof for handleFault' *) thm handleFault'_def thm handleFault_ccorres end section \Experiment: translating clzl\ text \ __builtin_clzl is defined using guarded_spec_body, which is a bit hard to translate generically. This is an experiment to translate clzl manually. \ context kernel_all_substitute begin thm kernel_m.clzl_spec clzl_body_def definition l1_clzl' :: "nat \ (globals myvars, unit + unit) nondet_monad" where "l1_clzl' rec_measure' \ L1_spec ({(s', t). (\s. s' \ \s. \<^bsup>s\<^esup>x \ 0\ \ t \ \\ret__long = of_nat (word_clz \<^bsup>s\<^esup>x)\) \ (\s. s' \ \s. \<^bsup>s\<^esup>x \ 0\)} \ {(s, t). t may_not_modify_globals s})" lemma l1_clzl'_corres: "L1corres ct \ (l1_clzl' rec_measure') (Call clzl_'proc)" apply (unfold l1_clzl'_def) apply (rule L1corres_Call) apply (rule clzl_impl) apply (unfold clzl_body_def) apply (rule L1corres_guarded_spec) done definition l2_clzl' :: "nat \ 32 word \ (globals, unit + 32 signed word) nondet_monad" where "l2_clzl' rec_measure' x \ L2_seq (L2_guard (\_. x \ 0)) (\_. L2_gets (\_. of_nat (word_clz x)) [''ret''])" lemma l2_clzl'_corres: "L2corres globals ret__long_' (\_. ()) (\s. x_' s = x) (l2_clzl' rec_measure' x) (l1_clzl' rec_measure')" apply (unfold l2_clzl'_def l1_clzl'_def) (* TODO: how to automate this? *) apply (monad_eq simp: L1_defs L2_defs L2corres_def corresXF_def meq_def) apply (subst myvars.splits) apply simp done definition clzl' :: "32 word \ (globals, 32 signed word) nondet_monad" where "clzl' x \ do guard (\_. x \ 0); return (of_nat (word_clz x)) od" lemma clzl'_TScorres: "L2_call (l2_clzl' rec_measure' x) = liftE (clzl' x)" apply (unfold l2_clzl'_def clzl'_def) apply (tactic {* simp_tac (@{context} addsimps (#lift_rules (the (Monad_Types.get_monad_type "nondet" (Context.Proof @{context}))) |> Thmtab.dest |> map fst)) 1 *}) done lemma clzl'_ac_corres: "ac_corres globals ct \ ret__long_' (\s. x_' s = x) (liftE (clzl' x)) (Call clzl_'proc)" apply (rule ac_corres_chain[OF _ _ L2Tcorres_id corresTA_trivial, simplified o_def, simplified]) apply (rule l1_clzl'_corres) apply (rule l2_clzl'_corres) apply (rule clzl'_TScorres) done end text \Add our manual translation of clzl into the AutoCorres function info.\ ML \ fun phasetab_merge_with merge (tab1, tab2) = sort_distinct FunctionInfo.phase_ord (FunctionInfo.Phasetab.keys tab1 @ FunctionInfo.Phasetab.keys tab2) |> map (fn k => (k, case (FunctionInfo.Phasetab.lookup tab1 k, FunctionInfo.Phasetab.lookup tab2 k) of (SOME x1, SOME x2) => merge (x1, x2) | (SOME x1, NONE) => x1 | (NONE, SOME x2) => x2 (* (NONE, NONE) impossible *))) |> FunctionInfo.Phasetab.make; \ setup {* fn thy => let val clzl_cp = { name = "clzl", invented_body = false, is_simpl_wrapper = false, callees = Symset.empty, rec_callees = Symset.empty, phase = FunctionInfo.CP, args = [("x", @{typ "32 word"})], return_type = @{typ "32 signed word"}, const = @{term "clzl_'proc"}, raw_const = @{term "clzl_'proc"}, definition = @{thm kernel_all_substitute.clzl_body_def}, mono_thm = NONE, corres_thm = @{thm TrueI} }: FunctionInfo.function_info; val clzl_l1 = clzl_cp |> FunctionInfo.function_info_upd_phase FunctionInfo.L1 |> FunctionInfo.function_info_upd_const @{term "kernel_all_substitute.l1_clzl'"} |> FunctionInfo.function_info_upd_definition @{thm kernel_all_substitute.l1_clzl'_def} |> FunctionInfo.function_info_upd_corres_thm @{thm "kernel_all_substitute.l1_clzl'_corres"}; val clzl_l2 = clzl_l1 |> FunctionInfo.function_info_upd_phase FunctionInfo.L2 |> FunctionInfo.function_info_upd_const @{term "kernel_all_substitute.l2_clzl'"} |> FunctionInfo.function_info_upd_definition @{thm kernel_all_substitute.l2_clzl'_def} |> FunctionInfo.function_info_upd_corres_thm @{thm "kernel_all_substitute.l2_clzl'_corres"}; val clzl_ts = clzl_l2 |> FunctionInfo.function_info_upd_phase FunctionInfo.TS |> FunctionInfo.function_info_upd_const @{term "kernel_all_substitute.clzl'"} |> FunctionInfo.function_info_upd_definition @{thm kernel_all_substitute.clzl'_def} |> FunctionInfo.function_info_upd_corres_thm @{thm "kernel_all_substitute.clzl'_TScorres"}; val clzl_info = FunctionInfo.Phasetab.make (map (fn info => (#phase info, Symtab.make [("clzl", info)])) [clzl_cp, clzl_l1, clzl_l2, clzl_ts]); val file = "c/kernel_all.c_pp"; val fn_info = the (Symtab.lookup (AutoCorresFunctionInfo.get thy) file); val fn_info' = phasetab_merge_with (Symtab.merge (K false)) (fn_info, clzl_info); in thy |> AutoCorresFunctionInfo.map (Symtab.update (file, fn_info')) end *} text \Now AutoCorres will use our specification in calls to clzl.\ autocorres [ skip_heap_abs, skip_word_abs, (* for compatibility *) scope = chooseThread, scope_depth = 0, c_locale = kernel_all_substitute, no_c_termination ] "c/kernel_all.c_pp" context kernel_m begin thm clzl'_def thm chooseThread'_def end subsection \Test recursion + call to previously translated (cap_get_capType)\ autocorres [ skip_heap_abs, skip_word_abs, ts_rules = nondet, (* for compatibility *) scope = cap_get_capType, scope_depth = 0, c_locale = kernel_all_substitute ] "c/kernel_all.c_pp" thm kernel_all_substitute.cap_get_capType'_def kernel_all_substitute.cap_get_capType_body_def autocorres [ skip_heap_abs, skip_word_abs, ts_rules = nondet, (* for compatibility *) scope = cteDelete finaliseSlot reduceZombie, scope_depth = 0, c_locale = kernel_all_substitute ] "c/kernel_all.c_pp" context kernel_m begin thm cteDelete'.simps finaliseSlot'.simps reduceZombie'.simps end text \Test call to recursive function group\ autocorres [ skip_heap_abs, skip_word_abs, ts_rules = nondet, (* for compatibility *) scope = cteRevoke, scope_depth = 0, c_locale = kernel_all_substitute ] "c/kernel_all.c_pp" context kernel_m begin thm cteRevoke'_def end subsection \Experiment with proving bitfield specs\ text \ Here we translate some bitfield functions, then separately prove that the translated functions satisfy the bitfield_gen specs. \ autocorres [ skip_heap_abs, skip_word_abs, ts_rules = nondet, (* for compatibility *) scope = cap_capType_equals cap_cnode_cap_get_capCNodePtr cap_cnode_cap_get_capCNodeGuard cap_cnode_cap_get_capCNodeRadix, scope_depth = 0, c_locale = kernel_all_substitute ] "c/kernel_all.c_pp" lemma of_bl_from_cond: "(if C then 1 else 0) = of_bl [C]" by (simp add: word_1_bl) lemma of_bl_cond: "(if C then of_bl [A] else of_bl [B]) = of_bl [if C then A else B]" by (rule if_f) context kernel_m begin lemma "\\_. cap_get_tag cap = scast cap_cnode_cap\ cap_cnode_cap_get_capCNodePtr' cap \\r _. r = capCNodePtr_CL (cap_cnode_cap_lift cap)\!" apply (unfold cap_cnode_cap_get_capCNodePtr'_def) apply wp apply (simp add: cap_get_tag_def cap_cnode_cap_lift_def cap_lift_def cap_tag_values shiftr_over_and_dist) done lemma "\\_. cap_get_tag cap = scast cap_cnode_cap\ cap_cnode_cap_get_capCNodeGuard' cap \\r _. r = capCNodeGuard_CL (cap_cnode_cap_lift cap)\!" apply (unfold cap_cnode_cap_get_capCNodeGuard'_def) apply wp apply (simp add: cap_get_tag_def cap_cnode_cap_lift_def cap_lift_def cap_tag_values shiftr_over_and_dist) done lemma "\\_. cap_get_tag cap = scast cap_cnode_cap\ cap_cnode_cap_get_capCNodeRadix' cap \\r _. r = capCNodeRadix_CL (cap_cnode_cap_lift cap)\!" apply (unfold cap_cnode_cap_get_capCNodeRadix'_def) apply wp apply (simp add: cap_get_tag_def cap_cnode_cap_lift_def cap_lift_def cap_tag_values shiftr_over_and_dist) done end subsection \Experiment with transferring bitfield specs\ text \ For wrapped bitfield functions, the @{term hoarep} triples for them can be transferred to @{term valid} triples. \ context kernel_m begin thm cap_zombie_cap_get_capZombiePtr_spec lemma cap_zombie_cap_get_capZombiePtr'_spec: "\\s. s = s0 \ cap_get_tag cap = scast cap_zombie_cap \ get_capZombieBits_CL (cap_zombie_cap_lift cap) < 0x1F\ cap_zombie_cap_get_capZombiePtr' cap \\r s. s = s0 \ r = get_capZombiePtr_CL (cap_zombie_cap_lift cap)\" (* setup *) apply (rule hoare_weaken_pre) apply (rule hoare_strengthen_post) (* generic transfer operation *) thm autocorres_transfer_spec_no_modifies[OF cap_zombie_cap_get_capZombiePtr'_def cap_zombie_cap_get_capZombiePtr_spec] apply (rule autocorres_transfer_spec_no_modifies[OF cap_zombie_cap_get_capZombiePtr'_def cap_zombie_cap_get_capZombiePtr_spec _ refl, where cs="undefined\globals := s0, cap_' := cap\"]) (* the standard tactics can't invent a suitable cs automatically *) apply (rule cap_zombie_cap_get_capZombiePtr_modifies) (* prove sanity conditions on local variables and preconds *) apply auto done thm cap_zombie_cap_get_capZombieType_spec lemma cap_zombie_cap_get_capZombieType'_spec: "\\s. s = s0 \ cap_get_tag cap = scast cap_zombie_cap \ cap_zombie_cap_get_capZombieType' cap \\r s. s = s0 \ r = capZombieType_CL (cap_zombie_cap_lift cap)\" apply (rule hoare_weaken_pre) apply (rule hoare_strengthen_post) thm autocorres_transfer_spec_no_modifies[OF cap_zombie_cap_get_capZombieType'_def cap_zombie_cap_get_capZombieType_spec] apply (rule autocorres_transfer_spec_no_modifies[OF cap_zombie_cap_get_capZombieType'_def cap_zombie_cap_get_capZombieType_spec _ refl, where cs="undefined\globals := s0, cap_' := cap\"]) apply (rule cap_zombie_cap_get_capZombieType_modifies) apply auto done text \There are some extra complications when transferring bitfield update specs\ thm cap_zombie_cap_set_capZombieNumber_spec (* extra quantified var; precond talks about initial state *) lemma cap_zombie_cap_set_capZombieNumber'_spec: "\\s. s = s0 \ ccap_relation cap' cap \ isZombie cap' \ capAligned cap' \ unat n \ zombieCTEs (capZombieType cap')\ cap_zombie_cap_set_capZombieNumber' cap n \\r s. s = s0 \ ccap_relation (capZombieNumber_update (\_. unat n) cap') r\" apply (rule hoare_weaken_pre) apply (rule hoare_strengthen_post) (* All_to_all' drops the extra quantifier. (rule_format would remove both) *) thm autocorres_transfer_spec_no_modifies[OF cap_zombie_cap_set_capZombieNumber'_def cap_zombie_cap_set_capZombieNumber_spec[THEN All_to_all']] apply (rule autocorres_transfer_spec_no_modifies[OF cap_zombie_cap_set_capZombieNumber'_def cap_zombie_cap_set_capZombieNumber_spec[THEN All_to_all'], where cs="undefined\globals := s0, cap_' := cap, n_' := n\"]) apply (rule cap_zombie_cap_set_capZombieNumber_modifies) (* swap initial state var to allow unification *) apply (rule collect_unlift) apply auto done thm cap_capType_equals_spec lemma cap_capType_equals'_spec: "\\s. s = s0 \ AC_call_L1 (\s. cap_' s = cap \ cap_type_tag_' s = cap_type_tag) globals ret__int_' (L1_call_simpl check_termination \ cap_capType_equals_'proc) \\r s. s = s0 \ r = of_bl [cap_get_tag cap = cap_type_tag]\" apply (rule hoare_weaken_pre) apply (rule hoare_strengthen_post) thm autocorres_transfer_spec_no_modifies[OF reflexive cap_capType_equals_spec] apply (rule autocorres_transfer_spec_no_modifies[ OF reflexive cap_capType_equals_spec, where cs="undefined\globals := s0, cap_' := cap, cap_type_tag_' := cap_type_tag\"]) apply (rule cap_capType_equals_modifies) apply auto done (* TODO: any other types of bitfield_gen functions? *) end context kernel_m begin text \Termination proofs for use with @{thm ccorres_to_corres_with_termination}. Currently unused.\ lemma cap_get_capType_terminates: "\ \ Call cap_get_capType_'proc \ Normal s" apply (tactic \ALLGOALS (terminates_trivial_tac @{context})\; fail) done lemma thread_state_get_tcbQueued_terminates: "\ \ Call thread_state_get_tcbQueued_'proc \ Normal s" apply (tactic \ALLGOALS (terminates_trivial_tac @{context})\; fail) done lemma thread_state_ptr_set_tcbQueued_terminates: "\ \ Call thread_state_ptr_set_tcbQueued_'proc \ Normal s" apply (tactic \ALLGOALS (terminates_trivial_tac @{context})\; fail) done lemma ready_queues_index_terminates: "\ \ Call ready_queues_index_'proc \ Normal s" apply (tactic \ALLGOALS (terminates_trivial_tac @{context})\; fail) done lemma prio_to_l1index_terminates: "\ \ Call prio_to_l1index_'proc \ Normal s" apply (tactic \ALLGOALS (terminates_trivial_tac @{context})\; fail) done lemma removeFromBitmap_terminates: "\ \ Call removeFromBitmap_'proc \ Normal s" apply (tactic \ALLGOALS (terminates_trivial_tac @{context})\; rule prio_to_l1index_terminates) done lemma addToBitmap_terminates: "\ \ Call addToBitmap_'proc \ Normal s" apply (tactic \ALLGOALS (terminates_trivial_tac @{context})\; rule prio_to_l1index_terminates) done lemma tcbSchedDequeue_terminates: "\ \ Call tcbSchedDequeue_'proc \ Normal s" apply (tactic \ALLGOALS (terminates_trivial_tac @{context})\; rule thread_state_get_tcbQueued_terminates thread_state_ptr_set_tcbQueued_terminates ready_queues_index_terminates removeFromBitmap_terminates) done lemma tcbSchedAppend_terminates: "\ \ Call tcbSchedAppend_'proc \ Normal s" apply (tactic \ALLGOALS (terminates_trivial_tac @{context})\; rule thread_state_get_tcbQueued_terminates thread_state_ptr_set_tcbQueued_terminates ready_queues_index_terminates addToBitmap_terminates) done lemma tcbSchedEnqueue_terminates: "\ \ Call tcbSchedEnqueue_'proc \ Normal s" apply (tactic \ALLGOALS (terminates_trivial_tac @{context})\; rule thread_state_get_tcbQueued_terminates thread_state_ptr_set_tcbQueued_terminates ready_queues_index_terminates addToBitmap_terminates) done lemma rescheduleRequired_terminates: "\ \ Call rescheduleRequired_'proc \ Normal s" apply (tactic \ALLGOALS (terminates_trivial_tac @{context})\; rule tcbSchedEnqueue_terminates) done end end