| (* |
| * Copyright 2016, NICTA |
| * |
| * 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(NICTA_GPL) |
| *) |
| |
| theory FunBucket |
| imports |
| TypBucket |
| L4vBucket |
| begin |
| |
| definition count :: "'a list \<Rightarrow> ('b::len) word" |
| where |
| "count xs \<equiv> of_nat (length xs) :: 'b word" |
| |
| definition is_pow_of_2 :: "U32 \<Rightarrow> bool" |
| where |
| "is_pow_of_2 x \<equiv> \<exists>k. x = 1 << k \<and> k < 32" |
| |
| declare fun_app_def [iff] |
| |
| text {* slice: Return a slice of a list, frm and to are offset from the |
| beginning of the list *} |
| definition |
| slice :: "nat \<Rightarrow> nat \<Rightarrow> 'a list \<Rightarrow> 'a list" |
| where |
| "slice frm to xs \<equiv> drop frm $ take to xs" |
| |
| lemma length_slice: |
| "length (slice f t xs) = min (length xs) t - f" |
| by (simp add: slice_def) |
| |
| lemma slice_n_n: |
| "slice n n xs = []" |
| by (simp add: slice_def) |
| |
| lemma slice_append: "slice f t (xs @ ys) = slice f t xs @ slice (f - min (length xs) t) (t - length xs) ys" |
| by (simp add: slice_def) |
| |
| lemmas slice_simps = length_slice slice_n_n slice_append slice_def |
| |
| lemma sub_mod_mask: |
| "\<lbrakk>k < 32 \<rbrakk> \<Longrightarrow> (x::32 word) - x mod 2^k = x && ~~ mask k" |
| apply (simp add: word_mod_2p_is_mask p2_gt_0 mask_out_sub_mask) |
| done |
| |
| lemma alignUp_not_aligned_eq2: |
| " \<not> is_aligned a n \<Longrightarrow> Word_Lib.alignUp a n = ((a >> n) + 1) << n" |
| apply (cases "n < size a") |
| apply (subst alignUp_not_aligned_eq, assumption) |
| apply (simp add: word_size) |
| apply (simp add: shiftr_div_2n_w shiftl_t2n) |
| apply (simp add: Word_Lib.alignUp_def power_overflow |
| word_size complement_def shiftl_zero_size) |
| done |
| |
| lemma alignUp_not_aligned_eq3: |
| "\<not> is_aligned a n \<Longrightarrow> Word_Lib.alignUp a n = (a && ~~ mask n) + (1 << n)" |
| by (simp add: alignUp_not_aligned_eq2 word_shiftl_add_distrib and_not_mask) |
| |
| lemma alignUp_def2: |
| "alignUp a sz = a + 2 ^ sz - 1 && ~~ mask sz" |
| unfolding alignUp_def[unfolded complement_def] |
| by (simp add: mask_def[symmetric,unfolded shiftl_t2n,simplified]) |
| |
| lemma align32_alignUp: |
| "\<lbrakk>y = 1 << k; k < 32\<rbrakk> \<Longrightarrow> align32(x,y) = alignUp x k" |
| apply (clarsimp simp: align32_def) |
| apply (fold mask_def[simplified]) |
| apply (subst mask_def, simp) |
| apply (subst add_diff_eq) |
| apply (subst alignUp_def2[symmetric]) |
| by simp |
| |
| lemma align32_eq: |
| "\<lbrakk>y=1<<k; k < 32\<rbrakk> \<Longrightarrow> align32(x,y) = (if y udvd x then x else x + y - (x mod y))" |
| apply (simp add: align32_alignUp) |
| apply safe |
| apply (simp add: udvd_iff_dvd) |
| apply (simp add: and_mask_dvd_nat) |
| apply (simp only: is_aligned_mask[symmetric]) |
| apply (simp add: alignUp_idem) |
| apply (subst diff_add_eq[symmetric]) |
| apply (subst sub_mod_mask, assumption) |
| apply (subst alignUp_not_aligned_eq3) |
| apply (clarsimp simp: is_aligned_def udvd_iff_dvd) |
| apply clarsimp |
| done |
| |
| lemma align32_unchanged: |
| "\<lbrakk>is_pow_of_2 a; a udvd x\<rbrakk> \<Longrightarrow> align32 (x,a) = x" |
| by (clarsimp simp: is_pow_of_2_def align32_eq) |
| |
| lemma alignUp_not_aligned_eq': "\<not> is_aligned x k |
| \<Longrightarrow> alignUp x k = x + (2 ^ k - (x && mask k))" |
| apply (subst alignUp_not_aligned_eq3, assumption) |
| apply (subst mask_out_sub_mask) |
| apply simp |
| done |
| |
| lemma al_dvd_align32: |
| "\<lbrakk>is_pow_of_2 al; v < v + al\<rbrakk> \<Longrightarrow> al udvd align32 (v, al)" |
| by (clarsimp simp: is_pow_of_2_def align32_alignUp |
| udvd_iff_dvd is_aligned_def[symmetric]) |
| |
| lemma align32_le: |
| "\<lbrakk>is_pow_of_2 al; v < v + al\<rbrakk> \<Longrightarrow> v \<le> align32 (v, al)" |
| apply (case_tac "v=0", clarsimp simp: align32_alignUp) |
| apply (clarsimp simp: align32_alignUp is_pow_of_2_def) |
| apply (case_tac "is_aligned v k") |
| apply (rule alignUp_ge, simp) |
| apply (rule_tac x=v in alignUp_is_aligned_nz) |
| apply simp |
| apply simp |
| apply simp |
| apply simp |
| apply (simp add: alignUp_not_aligned_eq') |
| apply (drule word_less_sub_1) |
| apply (rule word_plus_mono_right2) |
| apply (subst(asm) field_simps[symmetric], assumption) |
| apply (rule word_le_minus_mono_right) |
| apply (clarsimp simp: lt1_neq0 is_aligned_mask) |
| apply (rule order_trans, rule word_and_le1) |
| apply (rule order_less_imp_le) |
| apply (simp add: mask_lt_2pn) |
| apply (simp add: word_1_le_power) |
| done |
| |
| lemma align32_ge: |
| "\<lbrakk>is_pow_of_2 al; v < v + al\<rbrakk> \<Longrightarrow> align32 (v, al) \<ge> v" |
| by (auto simp:align32_le) |
| |
| lemma alignUp_greater: |
| "\<lbrakk>(v::32 word) < 2^n; v \<noteq> 0\<rbrakk> \<Longrightarrow> alignUp v n = 2^n" |
| apply (subst alignUp_not_aligned_eq') |
| apply (clarsimp simp: aligned_small_is_0) |
| apply (simp add: less_mask_eq) |
| done |
| |
| lemma mask_out_add_aligned: |
| assumes al: "is_aligned p n" |
| shows "p + (q && ~~ mask n) = (p + q) && ~~ mask n" |
| using mask_add_aligned [OF al] |
| by (simp add: mask_out_sub_mask) |
| |
| lemma is_aligned_triv2: |
| "is_aligned (2^a) a" |
| apply (case_tac "word_bits\<le> a") |
| apply (simp add:is_aligned_triv)+ |
| done |
| |
| lemma alignUp_def3: |
| "alignUp a sz = 2^ sz + (a - 1 && ~~ mask sz)" (is "?lhs = ?rhs") |
| apply (simp add:alignUp_def2) |
| apply (subgoal_tac "2 ^ sz + a - 1 && ~~ mask sz = ?rhs") |
| apply (clarsimp simp:field_simps) |
| apply (subst mask_out_add_aligned) |
| apply (rule is_aligned_triv2) |
| apply (simp add:field_simps) |
| done |
| |
| lemma mask_lower_twice: |
| "n \<le> m \<Longrightarrow> (x && ~~ mask n) && ~~ mask m = x && ~~ mask m" |
| apply (rule word_eqI) |
| apply (simp add: word_size word_ops_nth_size) |
| apply safe |
| apply simp |
| done |
| |
| lemma alignUp_distance: |
| "(alignUp (q :: 'a :: len word) sz) - q \<le> mask sz" |
| apply (case_tac "len_of TYPE('a) \<le> sz") |
| apply (simp add:alignUp_def2 mask_def power_overflow) |
| apply (case_tac "is_aligned q sz") |
| apply (clarsimp simp:alignUp_def2 p_assoc_help) |
| apply (subst mask_out_add_aligned[symmetric],simp)+ |
| apply (simp add:mask_lower_twice word_and_le2) |
| apply (simp add:and_not_mask) |
| apply (subst le_mask_iff[THEN iffD1]) |
| apply (simp add:mask_def) |
| apply simp |
| apply (clarsimp simp:alignUp_def3) |
| apply (subgoal_tac "2 ^ sz - (q - (q - 1 && ~~ mask sz)) \<le> 2 ^ sz - 1") |
| apply (simp add:field_simps mask_def) |
| apply (rule word_sub_mono) |
| apply simp |
| apply (rule ccontr) |
| apply (clarsimp simp:not_le) |
| apply (drule eq_refl) |
| apply (drule order_trans[OF _ word_and_le2]) |
| apply (subgoal_tac "q \<noteq> 0") |
| apply (drule minus_one_helper[rotated]) |
| apply simp |
| apply simp |
| apply (fastforce) |
| apply (simp add: word_sub_le_iff) |
| apply (subgoal_tac "q - 1 && ~~ mask sz = (q - 1) - (q - 1 && mask sz)") |
| apply simp |
| apply (rule order_trans) |
| apply (rule word_add_le_mono2) |
| apply (rule word_and_le1) |
| apply (subst unat_plus_simple[THEN iffD1,symmetric]) |
| apply (simp add:not_le mask_def) |
| apply (rule word_sub_1_le) |
| apply simp |
| apply (rule unat_lt2p) |
| apply (simp add:mask_def) |
| apply (simp add:mask_out_sub_mask) |
| apply (rule word_sub_1_le) |
| apply simp |
| done |
| |
| lemma alignUp_nz: |
| "\<lbrakk>(v :: 32 word) \<noteq> 0; v < v + 2^k; k < 32\<rbrakk> \<Longrightarrow> alignUp v k \<noteq> 0" |
| apply (cut_tac v=v and al="2^k" in align32_le, simp add: is_pow_of_2_def) |
| apply (rule_tac x=k in exI, simp+) |
| apply (subst (asm) align32_alignUp[simplified], simp+) |
| apply auto |
| done |
| |
| lemma aligned_neq_into_ineq: |
| fixes x :: "'a::len word" |
| assumes neq: "x \<noteq> y" |
| and alx: "is_aligned x sz" |
| and aly: "is_aligned y sz" |
| shows "x + 2 ^ sz - 1 < y \<or> y + 2 ^ sz - 1 < x" |
| proof - |
| note no_ov = aligned_neq_into_no_overlap [OF neq alx aly] |
| note x = eqset_imp_iff[OF no_ov, where x=x] |
| note y = eqset_imp_iff[OF no_ov, where x=y] |
| from x y show ?thesis |
| apply (simp add: is_aligned_no_overflow' alx aly) |
| apply (auto simp: field_simps) |
| done |
| qed |
| |
| lemma align32_upper_bound: |
| "\<lbrakk>v \<le> bound; is_pow_of_2 al; al udvd bound; v < v + al\<rbrakk> \<Longrightarrow> |
| align32 (v, al) \<le> bound" |
| apply (case_tac "v=0") |
| apply (clarsimp simp: align32_alignUp is_pow_of_2_def alignUp_def2 mask_def) |
| apply (clarsimp simp: is_pow_of_2_def) |
| apply (subst (asm) udvd_iff_dvd) |
| apply simp |
| apply (fold is_aligned_def) |
| apply (subst align32_alignUp, simp+) |
| apply (case_tac "is_aligned v k") |
| apply (simp add: alignUp_idem) |
| apply (case_tac "al > v") |
| apply (subst alignUp_greater, simp+) |
| apply (drule_tac a=bound in is_aligned_less_sz) |
| apply clarsimp |
| apply (simp add: le_def[symmetric]) |
| apply (simp add: le_def[symmetric]) |
| apply (cut_tac p=v and n=k in is_aligned_alignUp) |
| apply (cut_tac q=v and sz=k in alignUp_distance) |
| apply (drule word_diff_ls'(3)) |
| apply (drule word_less_sub_1) |
| apply (simp add: mask_def word_less_sub_1) |
| apply (subst diff_add_eq) |
| apply (simp add: add.commute) |
| apply (case_tac "v + 2^k \<le> bound") |
| apply (simp add: mask_def) |
| apply (cut_tac v=v and k=k in alignUp_nz, simp+) |
| apply (metis (erased, hide_lams) add.commute add_diff_eq |
| not_less order_trans word_le_less_eq word_less_1 word_sub_le) |
| apply (subst (asm) word_not_le) |
| apply (case_tac "bound = alignUp v k") |
| apply simp |
| apply (frule_tac x=bound and y="alignUp v k" and sz=k |
| in aligned_neq_into_ineq, assumption+) |
| apply (simp add: mask_def) |
| apply safe |
| apply (simp add: L4vBucket.alignUp_le_greater_al) |
| apply (simp add: L4vBucket.alignUp_le_greater_al) |
| done |
| |
| lemma align32_idempotence: |
| "is_pow_of_2 y \<Longrightarrow> x < x + y \<Longrightarrow> |
| align32 (align32 (x, y), y) = align32 (x, y)" |
| apply (frule (1) al_dvd_align32) |
| apply (erule (1) align32_unchanged) |
| done |
| |
| |
| end |