chore: introduce BitVec.setWidth to unify zeroExtend and truncate
incomplete deprecations chore: complete deprecations
This commit is contained in:
parent
4641ed8c96
commit
d38dc72a54
9 changed files with 341 additions and 203 deletions
|
|
@ -453,13 +453,15 @@ SMT-Lib name: `extract`.
|
|||
def extractLsb (hi lo : Nat) (x : BitVec n) : BitVec (hi - lo + 1) := extractLsb' lo _ x
|
||||
|
||||
/--
|
||||
A version of `zeroExtend` that requires a proof, but is a noop.
|
||||
A version of `setWidth` that requires a proof, but is a noop.
|
||||
-/
|
||||
def zeroExtend' {n w : Nat} (le : n ≤ w) (x : BitVec n) : BitVec w :=
|
||||
def setWidth' {n w : Nat} (le : n ≤ w) (x : BitVec n) : BitVec w :=
|
||||
x.toNat#'(by
|
||||
apply Nat.lt_of_lt_of_le x.isLt
|
||||
exact Nat.pow_le_pow_of_le_right (by trivial) le)
|
||||
|
||||
@[deprecated setWidth' (since := "2024-09-18"), inherit_doc setWidth'] abbrev zeroExtend' := @setWidth'
|
||||
|
||||
/--
|
||||
`shiftLeftZeroExtend x n` returns `zeroExtend (w+n) x <<< n` without
|
||||
needing to compute `x % 2^(2+n)`.
|
||||
|
|
@ -472,22 +474,35 @@ def shiftLeftZeroExtend (msbs : BitVec w) (m : Nat) : BitVec (w + m) :=
|
|||
(msbs.toNat <<< m)#'(shiftLeftLt msbs.isLt m)
|
||||
|
||||
/--
|
||||
Zero extend vector `x` of length `w` by adding zeros in the high bits until it has length `v`.
|
||||
If `v < w` then it truncates the high bits instead.
|
||||
Transform `x` of length `w` into a bitvector of length `v`, by either:
|
||||
- zero extending, that is, adding zeros in the high bits until it has length `v`, if `v > w`, or
|
||||
- truncating the high bits, if `v < w`.
|
||||
|
||||
SMT-Lib name: `zero_extend`.
|
||||
-/
|
||||
def zeroExtend (v : Nat) (x : BitVec w) : BitVec v :=
|
||||
def setWidth (v : Nat) (x : BitVec w) : BitVec v :=
|
||||
if h : w ≤ v then
|
||||
zeroExtend' h x
|
||||
setWidth' h x
|
||||
else
|
||||
.ofNat v x.toNat
|
||||
|
||||
/--
|
||||
Truncate the high bits of bitvector `x` of length `w`, resulting in a vector of length `v`.
|
||||
If `v > w` then it zero-extends the vector instead.
|
||||
Transform `x` of length `w` into a bitvector of length `v`, by either:
|
||||
- zero extending, that is, adding zeros in the high bits until it has length `v`, if `v > w`, or
|
||||
- truncating the high bits, if `v < w`.
|
||||
|
||||
SMT-Lib name: `zero_extend`.
|
||||
-/
|
||||
abbrev truncate := @zeroExtend
|
||||
abbrev zeroExtend := @setWidth
|
||||
|
||||
/--
|
||||
Transform `x` of length `w` into a bitvector of length `v`, by either:
|
||||
- zero extending, that is, adding zeros in the high bits until it has length `v`, if `v > w`, or
|
||||
- truncating the high bits, if `v < w`.
|
||||
|
||||
SMT-Lib name: `zero_extend`.
|
||||
-/
|
||||
abbrev truncate := @setWidth
|
||||
|
||||
/--
|
||||
Sign extend a vector of length `w`, extending with `i` additional copies of the most significant
|
||||
|
|
@ -638,7 +653,7 @@ input is on the left, so `0xAB#8 ++ 0xCD#8 = 0xABCD#16`.
|
|||
SMT-Lib name: `concat`.
|
||||
-/
|
||||
def append (msbs : BitVec n) (lsbs : BitVec m) : BitVec (n+m) :=
|
||||
shiftLeftZeroExtend msbs m ||| zeroExtend' (Nat.le_add_left m n) lsbs
|
||||
shiftLeftZeroExtend msbs m ||| setWidth' (Nat.le_add_left m n) lsbs
|
||||
|
||||
instance : HAppend (BitVec w) (BitVec v) (BitVec (w + v)) := ⟨.append⟩
|
||||
|
||||
|
|
|
|||
|
|
@ -139,11 +139,11 @@ def adc (x y : BitVec w) : Bool → Bool × BitVec w :=
|
|||
iunfoldr fun (i : Fin w) c => adcb (x.getLsbD i) (y.getLsbD i) c
|
||||
|
||||
theorem getLsbD_add_add_bool {i : Nat} (i_lt : i < w) (x y : BitVec w) (c : Bool) :
|
||||
getLsbD (x + y + zeroExtend w (ofBool c)) i =
|
||||
getLsbD (x + y + setWidth w (ofBool c)) i =
|
||||
Bool.xor (getLsbD x i) (Bool.xor (getLsbD y i) (carry i x y c)) := by
|
||||
let ⟨x, x_lt⟩ := x
|
||||
let ⟨y, y_lt⟩ := y
|
||||
simp only [getLsbD, toNat_add, toNat_zeroExtend, i_lt, toNat_ofFin, toNat_ofBool,
|
||||
simp only [getLsbD, toNat_add, toNat_setWidth, i_lt, toNat_ofFin, toNat_ofBool,
|
||||
Nat.mod_add_mod, Nat.add_mod_mod]
|
||||
apply Eq.trans
|
||||
rw [← Nat.div_add_mod x (2^i), ← Nat.div_add_mod y (2^i)]
|
||||
|
|
@ -165,11 +165,11 @@ theorem getLsbD_add {i : Nat} (i_lt : i < w) (x y : BitVec w) :
|
|||
simpa using getLsbD_add_add_bool i_lt x y false
|
||||
|
||||
theorem adc_spec (x y : BitVec w) (c : Bool) :
|
||||
adc x y c = (carry w x y c, x + y + zeroExtend w (ofBool c)) := by
|
||||
adc x y c = (carry w x y c, x + y + setWidth w (ofBool c)) := by
|
||||
simp only [adc]
|
||||
apply iunfoldr_replace
|
||||
(fun i => carry i x y c)
|
||||
(x + y + zeroExtend w (ofBool c))
|
||||
(x + y + setWidth w (ofBool c))
|
||||
c
|
||||
case init =>
|
||||
simp [carry, Nat.mod_one]
|
||||
|
|
@ -306,12 +306,12 @@ theorem mulRec_succ_eq (x y : BitVec w) (s : Nat) :
|
|||
Recurrence lemma: truncating to `i+1` bits and then zero extending to `w`
|
||||
equals truncating upto `i` bits `[0..i-1]`, and then adding the `i`th bit of `x`.
|
||||
-/
|
||||
theorem zeroExtend_truncate_succ_eq_zeroExtend_truncate_add_twoPow (x : BitVec w) (i : Nat) :
|
||||
zeroExtend w (x.truncate (i + 1)) =
|
||||
zeroExtend w (x.truncate i) + (x &&& twoPow w i) := by
|
||||
theorem setWidth_setWidth_succ_eq_setWidth_setWidth_add_twoPow (x : BitVec w) (i : Nat) :
|
||||
setWidth w (x.setWidth (i + 1)) =
|
||||
setWidth w (x.setWidth i) + (x &&& twoPow w i) := by
|
||||
rw [add_eq_or_of_and_eq_zero]
|
||||
· ext k
|
||||
simp only [getLsbD_zeroExtend, Fin.is_lt, decide_True, Bool.true_and, getLsbD_or, getLsbD_and]
|
||||
simp only [getLsbD_setWidth, Fin.is_lt, decide_True, Bool.true_and, getLsbD_or, getLsbD_and]
|
||||
by_cases hik : i = k
|
||||
· subst hik
|
||||
simp
|
||||
|
|
@ -322,27 +322,32 @@ theorem zeroExtend_truncate_succ_eq_zeroExtend_truncate_add_twoPow (x : BitVec w
|
|||
· have hik'' : ¬ (k < i) := by omega
|
||||
simp [hik', hik'']
|
||||
· ext k
|
||||
simp only [and_twoPow, getLsbD_and, getLsbD_zeroExtend, Fin.is_lt, decide_True, Bool.true_and,
|
||||
simp only [and_twoPow, getLsbD_and, getLsbD_setWidth, Fin.is_lt, decide_True, Bool.true_and,
|
||||
getLsbD_zero, and_eq_false_imp, and_eq_true, decide_eq_true_eq, and_imp]
|
||||
by_cases hi : x.getLsbD i <;> simp [hi] <;> omega
|
||||
|
||||
@[deprecated setWidth_setWidth_succ_eq_setWidth_setWidth_add_twoPow (since := "2024-09-18"),
|
||||
inherit_doc setWidth_setWidth_succ_eq_setWidth_setWidth_add_twoPow]
|
||||
abbrev zeroExtend_truncate_succ_eq_zeroExtend_truncate_add_twoPow :=
|
||||
@setWidth_setWidth_succ_eq_setWidth_setWidth_add_twoPow
|
||||
|
||||
/--
|
||||
Recurrence lemma: multiplying `x` with the first `s` bits of `y` is the
|
||||
same as truncating `y` to `s` bits, then zero extending to the original length,
|
||||
and performing the multplication. -/
|
||||
theorem mulRec_eq_mul_signExtend_truncate (x y : BitVec w) (s : Nat) :
|
||||
mulRec x y s = x * ((y.truncate (s + 1)).zeroExtend w) := by
|
||||
theorem mulRec_eq_mul_signExtend_setWidth (x y : BitVec w) (s : Nat) :
|
||||
mulRec x y s = x * ((y.setWidth (s + 1)).setWidth w) := by
|
||||
induction s
|
||||
case zero =>
|
||||
simp only [mulRec_zero_eq, ofNat_eq_ofNat, Nat.reduceAdd]
|
||||
by_cases y.getLsbD 0
|
||||
case pos hy =>
|
||||
simp only [hy, ↓reduceIte, truncate, zeroExtend_one_eq_ofBool_getLsb_zero,
|
||||
simp only [hy, ↓reduceIte, setWidth_one_eq_ofBool_getLsb_zero,
|
||||
ofBool_true, ofNat_eq_ofNat]
|
||||
rw [zeroExtend_ofNat_one_eq_ofNat_one_of_lt (by omega)]
|
||||
rw [setWidth_ofNat_one_eq_ofNat_one_of_lt (by omega)]
|
||||
simp
|
||||
case neg hy =>
|
||||
simp [hy, zeroExtend_one_eq_ofBool_getLsb_zero]
|
||||
simp [hy, setWidth_one_eq_ofBool_getLsb_zero]
|
||||
case succ s' hs =>
|
||||
rw [mulRec_succ_eq, hs]
|
||||
have heq :
|
||||
|
|
@ -350,13 +355,16 @@ theorem mulRec_eq_mul_signExtend_truncate (x y : BitVec w) (s : Nat) :
|
|||
(x * (y &&& (BitVec.twoPow w (s' + 1)))) := by
|
||||
simp only [ofNat_eq_ofNat, and_twoPow]
|
||||
by_cases hy : y.getLsbD (s' + 1) <;> simp [hy]
|
||||
rw [heq, ← BitVec.mul_add, ← zeroExtend_truncate_succ_eq_zeroExtend_truncate_add_twoPow]
|
||||
rw [heq, ← BitVec.mul_add, ← setWidth_setWidth_succ_eq_setWidth_setWidth_add_twoPow]
|
||||
|
||||
@[deprecated mulRec_eq_mul_signExtend_setWidth (since := "2024-09-18"),
|
||||
inherit_doc mulRec_eq_mul_signExtend_setWidth]
|
||||
abbrev mulRec_eq_mul_signExtend_truncate := @mulRec_eq_mul_signExtend_setWidth
|
||||
|
||||
theorem getLsbD_mul (x y : BitVec w) (i : Nat) :
|
||||
(x * y).getLsbD i = (mulRec x y w).getLsbD i := by
|
||||
simp only [mulRec_eq_mul_signExtend_truncate]
|
||||
rw [truncate, ← truncate_eq_zeroExtend, ← truncate_eq_zeroExtend,
|
||||
truncate_truncate_of_le]
|
||||
simp only [mulRec_eq_mul_signExtend_setWidth]
|
||||
rw [setWidth_setWidth_of_le]
|
||||
· simp
|
||||
· omega
|
||||
|
||||
|
|
@ -402,22 +410,22 @@ theorem shiftLeft_or_of_and_eq_zero {x : BitVec w₁} {y z : BitVec w₂}
|
|||
`shiftLeftRec x y n` shifts `x` to the left by the first `n` bits of `y`.
|
||||
-/
|
||||
theorem shiftLeftRec_eq {x : BitVec w₁} {y : BitVec w₂} {n : Nat} :
|
||||
shiftLeftRec x y n = x <<< (y.truncate (n + 1)).zeroExtend w₂ := by
|
||||
shiftLeftRec x y n = x <<< (y.setWidth (n + 1)).setWidth w₂ := by
|
||||
induction n generalizing x y
|
||||
case zero =>
|
||||
ext i
|
||||
simp only [shiftLeftRec_zero, twoPow_zero, Nat.reduceAdd, truncate_one,
|
||||
and_one_eq_zeroExtend_ofBool_getLsbD]
|
||||
simp only [shiftLeftRec_zero, twoPow_zero, Nat.reduceAdd, setWidth_one,
|
||||
and_one_eq_setWidth_ofBool_getLsbD]
|
||||
case succ n ih =>
|
||||
simp only [shiftLeftRec_succ, and_twoPow]
|
||||
rw [ih]
|
||||
by_cases h : y.getLsbD (n + 1)
|
||||
· simp only [h, ↓reduceIte]
|
||||
rw [zeroExtend_truncate_succ_eq_zeroExtend_truncate_or_twoPow_of_getLsbD_true h,
|
||||
rw [setWidth_setWidth_succ_eq_setWidth_setWidth_or_twoPow_of_getLsbD_true h,
|
||||
shiftLeft_or_of_and_eq_zero]
|
||||
simp [and_twoPow]
|
||||
· simp only [h, false_eq_true, ↓reduceIte, shiftLeft_zero']
|
||||
rw [zeroExtend_truncate_succ_eq_zeroExtend_truncate_of_getLsbD_false (i := n + 1)]
|
||||
rw [setWidth_setWidth_succ_eq_setWidth_setWidth_of_getLsbD_false (i := n + 1)]
|
||||
simp [h]
|
||||
|
||||
/--
|
||||
|
|
@ -466,18 +474,18 @@ theorem sshiftRight'_or_of_and_eq_zero {x : BitVec w₁} {y z : BitVec w₂}
|
|||
toNat_add_of_and_eq_zero h, sshiftRight_add]
|
||||
|
||||
theorem sshiftRightRec_eq (x : BitVec w₁) (y : BitVec w₂) (n : Nat) :
|
||||
sshiftRightRec x y n = x.sshiftRight' ((y.truncate (n + 1)).zeroExtend w₂) := by
|
||||
sshiftRightRec x y n = x.sshiftRight' ((y.setWidth (n + 1)).setWidth w₂) := by
|
||||
induction n generalizing x y
|
||||
case zero =>
|
||||
ext i
|
||||
simp [twoPow_zero, Nat.reduceAdd, and_one_eq_zeroExtend_ofBool_getLsbD, truncate_one]
|
||||
simp [twoPow_zero, Nat.reduceAdd, and_one_eq_setWidth_ofBool_getLsbD, setWidth_one]
|
||||
case succ n ih =>
|
||||
simp only [sshiftRightRec_succ_eq, and_twoPow, ih]
|
||||
by_cases h : y.getLsbD (n + 1)
|
||||
· rw [zeroExtend_truncate_succ_eq_zeroExtend_truncate_or_twoPow_of_getLsbD_true h,
|
||||
· rw [setWidth_setWidth_succ_eq_setWidth_setWidth_or_twoPow_of_getLsbD_true h,
|
||||
sshiftRight'_or_of_and_eq_zero (by simp [and_twoPow]), h]
|
||||
simp
|
||||
· rw [zeroExtend_truncate_succ_eq_zeroExtend_truncate_of_getLsbD_false (i := n + 1)
|
||||
· rw [setWidth_setWidth_succ_eq_setWidth_setWidth_of_getLsbD_false (i := n + 1)
|
||||
(by simp [h])]
|
||||
simp [h]
|
||||
|
||||
|
|
@ -529,20 +537,20 @@ theorem ushiftRight'_or_of_and_eq_zero {x : BitVec w₁} {y z : BitVec w₂}
|
|||
simp [← add_eq_or_of_and_eq_zero _ _ h, toNat_add_of_and_eq_zero h, shiftRight_add]
|
||||
|
||||
theorem ushiftRightRec_eq (x : BitVec w₁) (y : BitVec w₂) (n : Nat) :
|
||||
ushiftRightRec x y n = x >>> (y.truncate (n + 1)).zeroExtend w₂ := by
|
||||
ushiftRightRec x y n = x >>> (y.setWidth (n + 1)).setWidth w₂ := by
|
||||
induction n generalizing x y
|
||||
case zero =>
|
||||
ext i
|
||||
simp only [ushiftRightRec_zero, twoPow_zero, Nat.reduceAdd,
|
||||
and_one_eq_zeroExtend_ofBool_getLsbD, truncate_one]
|
||||
and_one_eq_setWidth_ofBool_getLsbD, setWidth_one]
|
||||
case succ n ih =>
|
||||
simp only [ushiftRightRec_succ, and_twoPow]
|
||||
rw [ih]
|
||||
by_cases h : y.getLsbD (n + 1) <;> simp only [h, ↓reduceIte]
|
||||
· rw [zeroExtend_truncate_succ_eq_zeroExtend_truncate_or_twoPow_of_getLsbD_true h,
|
||||
· rw [setWidth_setWidth_succ_eq_setWidth_setWidth_or_twoPow_of_getLsbD_true h,
|
||||
ushiftRight'_or_of_and_eq_zero]
|
||||
simp [and_twoPow]
|
||||
· simp [zeroExtend_truncate_succ_eq_zeroExtend_truncate_of_getLsbD_false, h]
|
||||
· simp [setWidth_setWidth_succ_eq_setWidth_setWidth_of_getLsbD_false, h]
|
||||
|
||||
/--
|
||||
Show that `x >>> y` can be written in terms of `ushiftRightRec`.
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ private theorem iunfoldr.eq_test
|
|||
simp only [init, eq_nil]
|
||||
case step =>
|
||||
intro i
|
||||
simp_all [truncate_succ]
|
||||
simp_all [setWidth_succ]
|
||||
|
||||
theorem iunfoldr_getLsbD' {f : Fin w → α → α × Bool} (state : Nat → α)
|
||||
(ind : ∀(i : Fin w), (f i (state i.val)).fst = state (i.val+1)) :
|
||||
|
|
|
|||
|
|
@ -438,46 +438,46 @@ theorem toInt_pos_iff {w : Nat} {x : BitVec w} :
|
|||
0 ≤ BitVec.toInt x ↔ 2 * x.toNat < 2 ^ w := by
|
||||
simp [toInt_eq_toNat_cond]; omega
|
||||
|
||||
/-! ### zeroExtend and truncate -/
|
||||
/-! ### setWidth, zeroExtend and truncate -/
|
||||
|
||||
theorem truncate_eq_zeroExtend {v : Nat} {x : BitVec w} :
|
||||
truncate v x = zeroExtend v x := rfl
|
||||
@[simp]
|
||||
theorem truncate_eq_setWidth {v : Nat} {x : BitVec w} :
|
||||
truncate v x = setWidth v x := rfl
|
||||
|
||||
@[simp, bv_toNat] theorem toNat_zeroExtend' {m n : Nat} (p : m ≤ n) (x : BitVec m) :
|
||||
(zeroExtend' p x).toNat = x.toNat := by
|
||||
simp [zeroExtend']
|
||||
@[simp]
|
||||
theorem zeroExtend_eq_setWidth {v : Nat} {x : BitVec w} :
|
||||
zeroExtend v x = setWidth v x := rfl
|
||||
|
||||
@[bv_toNat] theorem toNat_zeroExtend (i : Nat) (x : BitVec n) :
|
||||
BitVec.toNat (zeroExtend i x) = x.toNat % 2^i := by
|
||||
@[simp, bv_toNat] theorem toNat_setWidth' {m n : Nat} (p : m ≤ n) (x : BitVec m) :
|
||||
(setWidth' p x).toNat = x.toNat := by
|
||||
simp [setWidth']
|
||||
|
||||
@[simp, bv_toNat] theorem toNat_setWidth (i : Nat) (x : BitVec n) :
|
||||
BitVec.toNat (setWidth i x) = x.toNat % 2^i := by
|
||||
let ⟨x, lt_n⟩ := x
|
||||
simp only [zeroExtend]
|
||||
simp only [setWidth]
|
||||
if n_le_i : n ≤ i then
|
||||
have x_lt_two_i : x < 2 ^ i := lt_two_pow_of_le lt_n n_le_i
|
||||
simp [n_le_i, Nat.mod_eq_of_lt, x_lt_two_i]
|
||||
else
|
||||
simp [n_le_i, toNat_ofNat]
|
||||
|
||||
theorem zeroExtend'_eq {x : BitVec w} (h : w ≤ v) : x.zeroExtend' h = x.zeroExtend v := by
|
||||
theorem setWidth'_eq {x : BitVec w} (h : w ≤ v) : x.setWidth' h = x.setWidth v := by
|
||||
apply eq_of_toNat_eq
|
||||
rw [toNat_zeroExtend, toNat_zeroExtend']
|
||||
rw [toNat_setWidth, toNat_setWidth']
|
||||
rw [Nat.mod_eq_of_lt]
|
||||
exact Nat.lt_of_lt_of_le x.isLt (Nat.pow_le_pow_right (Nat.zero_lt_two) h)
|
||||
|
||||
@[simp, bv_toNat] theorem toNat_truncate (x : BitVec n) : (truncate i x).toNat = x.toNat % 2^i :=
|
||||
toNat_zeroExtend i x
|
||||
|
||||
@[simp] theorem zeroExtend_eq (x : BitVec n) : zeroExtend n x = x := by
|
||||
@[simp] theorem setWidth_eq (x : BitVec n) : setWidth n x = x := by
|
||||
apply eq_of_toNat_eq
|
||||
let ⟨x, lt_n⟩ := x
|
||||
simp [truncate, zeroExtend]
|
||||
simp [setWidth]
|
||||
|
||||
@[simp] theorem zeroExtend_zero (m n : Nat) : zeroExtend m 0#n = 0#m := by
|
||||
@[simp] theorem setWidth_zero (m n : Nat) : setWidth m 0#n = 0#m := by
|
||||
apply eq_of_toNat_eq
|
||||
simp [toNat_zeroExtend]
|
||||
simp [toNat_setWidth]
|
||||
|
||||
theorem truncate_eq (x : BitVec n) : truncate n x = x := zeroExtend_eq x
|
||||
|
||||
@[simp] theorem ofNat_toNat (m : Nat) (x : BitVec n) : BitVec.ofNat m x.toNat = truncate m x := by
|
||||
@[simp] theorem ofNat_toNat (m : Nat) (x : BitVec n) : BitVec.ofNat m x.toNat = setWidth m x := by
|
||||
apply eq_of_toNat_eq
|
||||
simp
|
||||
|
||||
|
|
@ -496,33 +496,33 @@ theorem nat_eq_toNat {x : BitVec w} {y : Nat}
|
|||
rw [@eq_comm _ _ x.toNat]
|
||||
apply toNat_eq_nat
|
||||
|
||||
theorem getElem_zeroExtend' (x : BitVec w) (i : Nat) (h : w ≤ v) (hi : i < v) :
|
||||
(zeroExtend' h x)[i] = x.getLsbD i := by
|
||||
rw [getElem_eq_testBit_toNat, toNat_zeroExtend', getLsbD]
|
||||
theorem getElem_setWidth' (x : BitVec w) (i : Nat) (h : w ≤ v) (hi : i < v) :
|
||||
(setWidth' h x)[i] = x.getLsbD i := by
|
||||
rw [getElem_eq_testBit_toNat, toNat_setWidth', getLsbD]
|
||||
|
||||
theorem getElem_zeroExtend (m : Nat) (x : BitVec n) (i : Nat) (h : i < m) :
|
||||
(zeroExtend m x)[i] = x.getLsbD i := by
|
||||
rw [zeroExtend]
|
||||
theorem getElem_setWidth (m : Nat) (x : BitVec n) (i : Nat) (h : i < m) :
|
||||
(setWidth m x)[i] = x.getLsbD i := by
|
||||
rw [setWidth]
|
||||
split
|
||||
· rw [getElem_zeroExtend']
|
||||
· rw [getElem_setWidth']
|
||||
· simp [getElem_eq_testBit_toNat, getLsbD]
|
||||
omega
|
||||
|
||||
theorem getElem?_zeroExtend' (x : BitVec w) (i : Nat) (h : w ≤ v) :
|
||||
(zeroExtend' h x)[i]? = if i < v then some (x.getLsbD i) else none := by
|
||||
simp [getElem?_eq, getElem_zeroExtend']
|
||||
theorem getElem?_setWidth' (x : BitVec w) (i : Nat) (h : w ≤ v) :
|
||||
(setWidth' h x)[i]? = if i < v then some (x.getLsbD i) else none := by
|
||||
simp [getElem?_eq, getElem_setWidth']
|
||||
|
||||
theorem getElem?_zeroExtend (m : Nat) (x : BitVec n) (i : Nat) :
|
||||
(x.zeroExtend m)[i]? = if i < m then some (x.getLsbD i) else none := by
|
||||
simp [getElem?_eq, getElem_zeroExtend]
|
||||
theorem getElem?_setWidth (m : Nat) (x : BitVec n) (i : Nat) :
|
||||
(x.setWidth m)[i]? = if i < m then some (x.getLsbD i) else none := by
|
||||
simp [getElem?_eq, getElem_setWidth]
|
||||
|
||||
@[simp] theorem getLsbD_zeroExtend' (ge : m ≥ n) (x : BitVec n) (i : Nat) :
|
||||
getLsbD (zeroExtend' ge x) i = getLsbD x i := by
|
||||
simp [getLsbD, toNat_zeroExtend']
|
||||
@[simp] theorem getLsbD_setWidth' (ge : m ≥ n) (x : BitVec n) (i : Nat) :
|
||||
getLsbD (setWidth' ge x) i = getLsbD x i := by
|
||||
simp [getLsbD, toNat_setWidth']
|
||||
|
||||
@[simp] theorem getMsbD_zeroExtend' (ge : m ≥ n) (x : BitVec n) (i : Nat) :
|
||||
getMsbD (zeroExtend' ge x) i = (decide (i ≥ m - n) && getMsbD x (i - (m - n))) := by
|
||||
simp only [getMsbD, getLsbD_zeroExtend', gt_iff_lt]
|
||||
@[simp] theorem getMsbD_setWidth' (ge : m ≥ n) (x : BitVec n) (i : Nat) :
|
||||
getMsbD (setWidth' ge x) i = (decide (i ≥ m - n) && getMsbD x (i - (m - n))) := by
|
||||
simp only [getMsbD, getLsbD_setWidth', gt_iff_lt]
|
||||
by_cases h₁ : decide (i < m) <;> by_cases h₂ : decide (i ≥ m - n) <;> by_cases h₃ : decide (i - (m - n) < n) <;>
|
||||
by_cases h₄ : n - 1 - (i - (m - n)) = m - 1 - i
|
||||
all_goals
|
||||
|
|
@ -533,15 +533,15 @@ theorem getElem?_zeroExtend (m : Nat) (x : BitVec n) (i : Nat) :
|
|||
(try apply (getLsbD_ge _ _ _).symm) <;>
|
||||
omega
|
||||
|
||||
@[simp] theorem getLsbD_zeroExtend (m : Nat) (x : BitVec n) (i : Nat) :
|
||||
getLsbD (zeroExtend m x) i = (decide (i < m) && getLsbD x i) := by
|
||||
simp [getLsbD, toNat_zeroExtend, Nat.testBit_mod_two_pow]
|
||||
@[simp] theorem getLsbD_setWidth (m : Nat) (x : BitVec n) (i : Nat) :
|
||||
getLsbD (setWidth m x) i = (decide (i < m) && getLsbD x i) := by
|
||||
simp [getLsbD, toNat_setWidth, Nat.testBit_mod_two_pow]
|
||||
|
||||
@[simp] theorem getMsbD_zeroExtend_add {x : BitVec w} (h : k ≤ i) :
|
||||
(x.zeroExtend (w + k)).getMsbD i = x.getMsbD (i - k) := by
|
||||
@[simp] theorem getMsbD_setWidth_add {x : BitVec w} (h : k ≤ i) :
|
||||
(x.setWidth (w + k)).getMsbD i = x.getMsbD (i - k) := by
|
||||
by_cases h : w = 0
|
||||
· subst h; simp [of_length_zero]
|
||||
simp only [getMsbD, getLsbD_zeroExtend]
|
||||
simp only [getMsbD, getLsbD_setWidth]
|
||||
by_cases h₁ : i < w + k <;> by_cases h₂ : i - k < w <;> by_cases h₃ : w + k - 1 - i < w + k
|
||||
<;> simp [h₁, h₂, h₃]
|
||||
· congr 1
|
||||
|
|
@ -549,87 +549,60 @@ theorem getElem?_zeroExtend (m : Nat) (x : BitVec n) (i : Nat) :
|
|||
all_goals (first | apply getLsbD_ge | apply Eq.symm; apply getLsbD_ge)
|
||||
<;> omega
|
||||
|
||||
@[simp]
|
||||
theorem getElem_truncate (m : Nat) (x : BitVec n) (i : Nat) (hi : i < m) :
|
||||
(truncate m x)[i] = x.getLsbD i := by
|
||||
simp only [getElem_zeroExtend]
|
||||
|
||||
theorem getElem?_truncate (m : Nat) (x : BitVec n) (i : Nat) :
|
||||
(truncate m x)[i]? = if i < m then some (x.getLsbD i) else none :=
|
||||
getElem?_zeroExtend m x i
|
||||
|
||||
theorem getLsbD_truncate (m : Nat) (x : BitVec n) (i : Nat) :
|
||||
getLsbD (truncate m x) i = (decide (i < m) && getLsbD x i) :=
|
||||
getLsbD_zeroExtend m x i
|
||||
|
||||
theorem msb_truncate (x : BitVec w) : (x.truncate (k + 1)).msb = x.getLsbD k := by
|
||||
simp [BitVec.msb, getMsbD]
|
||||
|
||||
@[simp] theorem cast_zeroExtend (h : v = v') (x : BitVec w) :
|
||||
cast h (zeroExtend v x) = zeroExtend v' x := by
|
||||
@[simp] theorem cast_setWidth (h : v = v') (x : BitVec w) :
|
||||
cast h (setWidth v x) = setWidth v' x := by
|
||||
subst h
|
||||
ext
|
||||
simp
|
||||
|
||||
@[simp] theorem cast_truncate (h : v = v') (x : BitVec w) :
|
||||
cast h (truncate v x) = truncate v' x := by
|
||||
subst h
|
||||
ext
|
||||
simp
|
||||
|
||||
@[simp] theorem zeroExtend_zeroExtend_of_le (x : BitVec w) (h : k ≤ l) :
|
||||
(x.zeroExtend l).zeroExtend k = x.zeroExtend k := by
|
||||
@[simp] theorem setWidth_setWidth_of_le (x : BitVec w) (h : k ≤ l) :
|
||||
(x.setWidth l).setWidth k = x.setWidth k := by
|
||||
ext i
|
||||
simp only [getLsbD_zeroExtend, Fin.is_lt, decide_True, Bool.true_and]
|
||||
simp only [getLsbD_setWidth, Fin.is_lt, decide_True, Bool.true_and]
|
||||
have p := lt_of_getLsbD (x := x) (i := i)
|
||||
revert p
|
||||
cases getLsbD x i <;> simp; omega
|
||||
|
||||
@[simp] theorem truncate_truncate_of_le (x : BitVec w) (h : k ≤ l) :
|
||||
(x.truncate l).truncate k = x.truncate k :=
|
||||
zeroExtend_zeroExtend_of_le x h
|
||||
|
||||
/-- Truncating by the bitwidth has no effect. -/
|
||||
-- This doesn't need to be a `@[simp]` lemma, as `zeroExtend_eq` applies.
|
||||
theorem truncate_eq_self {x : BitVec w} : x.truncate w = x := zeroExtend_eq _
|
||||
|
||||
@[simp] theorem truncate_cast {h : w = v} : (cast h x).truncate k = x.truncate k := by
|
||||
@[simp] theorem setWidth_cast {h : w = v} : (cast h x).setWidth k = x.setWidth k := by
|
||||
apply eq_of_getLsbD_eq
|
||||
simp
|
||||
|
||||
theorem msb_zeroExtend (x : BitVec w) : (x.zeroExtend v).msb = (decide (0 < v) && x.getLsbD (v - 1)) := by
|
||||
theorem msb_setWidth (x : BitVec w) : (x.setWidth v).msb = (decide (0 < v) && x.getLsbD (v - 1)) := by
|
||||
rw [msb_eq_getLsbD_last]
|
||||
simp only [getLsbD_zeroExtend]
|
||||
simp only [getLsbD_setWidth]
|
||||
cases getLsbD x (v - 1) <;> simp; omega
|
||||
|
||||
theorem msb_zeroExtend' (x : BitVec w) (h : w ≤ v) : (x.zeroExtend' h).msb = (decide (0 < v) && x.getLsbD (v - 1)) := by
|
||||
rw [zeroExtend'_eq, msb_zeroExtend]
|
||||
theorem msb_setWidth' (x : BitVec w) (h : w ≤ v) : (x.setWidth' h).msb = (decide (0 < v) && x.getLsbD (v - 1)) := by
|
||||
rw [setWidth'_eq, msb_setWidth]
|
||||
|
||||
theorem msb_setWidth'' (x : BitVec w) : (x.setWidth (k + 1)).msb = x.getLsbD k := by
|
||||
simp [BitVec.msb, getMsbD]
|
||||
|
||||
/-- zero extending a bitvector to width 1 equals the boolean of the lsb. -/
|
||||
theorem zeroExtend_one_eq_ofBool_getLsb_zero (x : BitVec w) :
|
||||
x.zeroExtend 1 = BitVec.ofBool (x.getLsbD 0) := by
|
||||
theorem setWidth_one_eq_ofBool_getLsb_zero (x : BitVec w) :
|
||||
x.setWidth 1 = BitVec.ofBool (x.getLsbD 0) := by
|
||||
ext i
|
||||
simp [getLsbD_zeroExtend, Fin.fin_one_eq_zero i]
|
||||
simp [getLsbD_setWidth, Fin.fin_one_eq_zero i]
|
||||
|
||||
/-- Zero extending `1#v` to `1#w` equals `1#w` when `v > 0`. -/
|
||||
theorem zeroExtend_ofNat_one_eq_ofNat_one_of_lt {v w : Nat} (hv : 0 < v) :
|
||||
(BitVec.ofNat v 1).zeroExtend w = BitVec.ofNat w 1 := by
|
||||
theorem setWidth_ofNat_one_eq_ofNat_one_of_lt {v w : Nat} (hv : 0 < v) :
|
||||
(BitVec.ofNat v 1).setWidth w = BitVec.ofNat w 1 := by
|
||||
ext ⟨i, hilt⟩
|
||||
simp only [getLsbD_zeroExtend, hilt, decide_True, getLsbD_ofNat, Bool.true_and,
|
||||
simp only [getLsbD_setWidth, hilt, decide_True, getLsbD_ofNat, Bool.true_and,
|
||||
Bool.and_iff_right_iff_imp, decide_eq_true_eq]
|
||||
intros hi₁
|
||||
have hv := Nat.testBit_one_eq_true_iff_self_eq_zero.mp hi₁
|
||||
omega
|
||||
|
||||
/-- Truncating to width 1 produces a bitvector equal to the least significant bit. -/
|
||||
theorem truncate_one {x : BitVec w} :
|
||||
x.truncate 1 = ofBool (x.getLsbD 0) := by
|
||||
theorem setWidth_one {x : BitVec w} :
|
||||
x.setWidth 1 = ofBool (x.getLsbD 0) := by
|
||||
ext i
|
||||
simp [show i = 0 by omega]
|
||||
|
||||
@[simp] theorem truncate_ofNat_of_le (h : v ≤ w) (x : Nat) : truncate v (BitVec.ofNat w x) = BitVec.ofNat v x := by
|
||||
@[simp] theorem setWidth_ofNat_of_le (h : v ≤ w) (x : Nat) : setWidth v (BitVec.ofNat w x) = BitVec.ofNat v x := by
|
||||
apply BitVec.eq_of_toNat_eq
|
||||
simp only [toNat_truncate, toNat_ofNat]
|
||||
simp only [toNat_setWidth, toNat_ofNat]
|
||||
rw [Nat.mod_mod_of_dvd]
|
||||
exact Nat.pow_dvd_pow_iff_le_right'.mpr h
|
||||
|
||||
|
|
@ -710,8 +683,8 @@ theorem extractLsb'_eq_extractLsb {w : Nat} (x : BitVec w) (start len : Nat) (h
|
|||
@[simp] theorem msb_or {x y : BitVec w} : (x ||| y).msb = (x.msb || y.msb) := by
|
||||
simp [BitVec.msb]
|
||||
|
||||
@[simp] theorem truncate_or {x y : BitVec w} :
|
||||
(x ||| y).truncate k = x.truncate k ||| y.truncate k := by
|
||||
@[simp] theorem setWidth_or {x y : BitVec w} :
|
||||
(x ||| y).setWidth k = x.setWidth k ||| y.setWidth k := by
|
||||
ext
|
||||
simp
|
||||
|
||||
|
|
@ -751,8 +724,8 @@ instance : Std.Commutative (fun (x y : BitVec w) => x ||| y) := ⟨BitVec.or_com
|
|||
@[simp] theorem msb_and {x y : BitVec w} : (x &&& y).msb = (x.msb && y.msb) := by
|
||||
simp [BitVec.msb]
|
||||
|
||||
@[simp] theorem truncate_and {x y : BitVec w} :
|
||||
(x &&& y).truncate k = x.truncate k &&& y.truncate k := by
|
||||
@[simp] theorem setWidth_and {x y : BitVec w} :
|
||||
(x &&& y).setWidth k = x.setWidth k &&& y.setWidth k := by
|
||||
ext
|
||||
simp
|
||||
|
||||
|
|
@ -795,8 +768,8 @@ instance : Std.Commutative (fun (x y : BitVec w) => x &&& y) := ⟨BitVec.and_co
|
|||
(x ^^^ y).msb = (xor x.msb y.msb) := by
|
||||
simp [BitVec.msb]
|
||||
|
||||
@[simp] theorem truncate_xor {x y : BitVec w} :
|
||||
(x ^^^ y).truncate k = x.truncate k ^^^ y.truncate k := by
|
||||
@[simp] theorem setWidth_xor {x y : BitVec w} :
|
||||
(x ^^^ y).setWidth k = x.setWidth k ^^^ y.setWidth k := by
|
||||
ext
|
||||
simp
|
||||
|
||||
|
|
@ -850,8 +823,8 @@ theorem not_def {x : BitVec v} : ~~~x = allOnes v ^^^ x := rfl
|
|||
rw [Nat.testBit_two_pow_sub_succ x.isLt]
|
||||
simp [h]
|
||||
|
||||
@[simp] theorem truncate_not {x : BitVec w} (h : k ≤ w) :
|
||||
(~~~x).truncate k = ~~~(x.truncate k) := by
|
||||
@[simp] theorem setWidth_not {x : BitVec w} (h : k ≤ w) :
|
||||
(~~~x).setWidth k = ~~~(x.setWidth k) := by
|
||||
ext
|
||||
simp [h]
|
||||
omega
|
||||
|
|
@ -939,9 +912,9 @@ theorem shiftLeft_or_distrib (x y : BitVec w) (n : Nat) :
|
|||
<;> omega
|
||||
|
||||
theorem shiftLeftZeroExtend_eq {x : BitVec w} :
|
||||
shiftLeftZeroExtend x n = zeroExtend (w+n) x <<< n := by
|
||||
shiftLeftZeroExtend x n = setWidth (w+n) x <<< n := by
|
||||
apply eq_of_toNat_eq
|
||||
rw [shiftLeftZeroExtend, zeroExtend]
|
||||
rw [shiftLeftZeroExtend, setWidth]
|
||||
split
|
||||
· simp
|
||||
rw [Nat.mod_eq_of_lt]
|
||||
|
|
@ -952,7 +925,7 @@ theorem shiftLeftZeroExtend_eq {x : BitVec w} :
|
|||
@[simp] theorem getLsbD_shiftLeftZeroExtend (x : BitVec m) (n : Nat) :
|
||||
getLsbD (shiftLeftZeroExtend x n) i = ((! decide (i < n)) && getLsbD x (i - n)) := by
|
||||
rw [shiftLeftZeroExtend_eq]
|
||||
simp only [getLsbD_shiftLeft, getLsbD_zeroExtend]
|
||||
simp only [getLsbD_shiftLeft, getLsbD_setWidth]
|
||||
cases h₁ : decide (i < n) <;> cases h₂ : decide (i - n < m + n) <;> cases h₃ : decide (i < m + n)
|
||||
<;> simp_all
|
||||
<;> (rw [getLsbD_ge]; omega)
|
||||
|
|
@ -1195,15 +1168,15 @@ private theorem Int.negSucc_emod (m : Nat) (n : Int) :
|
|||
-(m + 1) % n = Int.subNatNat (Int.natAbs n) ((m % Int.natAbs n) + 1) := rfl
|
||||
|
||||
/-- The sign extension is the same as zero extending when `msb = false`. -/
|
||||
theorem signExtend_eq_not_zeroExtend_not_of_msb_false {x : BitVec w} {v : Nat} (hmsb : x.msb = false) :
|
||||
x.signExtend v = x.zeroExtend v := by
|
||||
theorem signExtend_eq_not_setWidth_not_of_msb_false {x : BitVec w} {v : Nat} (hmsb : x.msb = false) :
|
||||
x.signExtend v = x.setWidth v := by
|
||||
ext i
|
||||
by_cases hv : i < v
|
||||
· simp only [signExtend, getLsbD, getLsbD_zeroExtend, hv, decide_True, Bool.true_and, toNat_ofInt,
|
||||
· simp only [signExtend, getLsbD, getLsbD_setWidth, hv, decide_True, Bool.true_and, toNat_ofInt,
|
||||
BitVec.toInt_eq_msb_cond, hmsb, ↓reduceIte, reduceCtorEq]
|
||||
rw [Int.ofNat_mod_ofNat, Int.toNat_ofNat, Nat.testBit_mod_two_pow]
|
||||
simp [BitVec.testBit_toNat]
|
||||
· simp only [getLsbD_zeroExtend, hv, decide_False, Bool.false_and]
|
||||
· simp only [getLsbD_setWidth, hv, decide_False, Bool.false_and]
|
||||
apply getLsbD_ge
|
||||
omega
|
||||
|
||||
|
|
@ -1211,11 +1184,11 @@ theorem signExtend_eq_not_zeroExtend_not_of_msb_false {x : BitVec w} {v : Nat} (
|
|||
The sign extension is a bitwise not, followed by a zero extend, followed by another bitwise not
|
||||
when `msb = true`. The double bitwise not ensures that the high bits are '1',
|
||||
and the lower bits are preserved. -/
|
||||
theorem signExtend_eq_not_zeroExtend_not_of_msb_true {x : BitVec w} {v : Nat} (hmsb : x.msb = true) :
|
||||
x.signExtend v = ~~~((~~~x).zeroExtend v) := by
|
||||
theorem signExtend_eq_not_setWidth_not_of_msb_true {x : BitVec w} {v : Nat} (hmsb : x.msb = true) :
|
||||
x.signExtend v = ~~~((~~~x).setWidth v) := by
|
||||
apply BitVec.eq_of_toNat_eq
|
||||
simp only [signExtend, BitVec.toInt_eq_msb_cond, toNat_ofInt, toNat_not,
|
||||
toNat_truncate, hmsb, ↓reduceIte]
|
||||
toNat_setWidth, hmsb, ↓reduceIte]
|
||||
norm_cast
|
||||
rw [Int.ofNat_sub_ofNat_of_lt, Int.negSucc_emod]
|
||||
simp only [Int.natAbs_ofNat, Nat.succ_eq_add_one]
|
||||
|
|
@ -1231,27 +1204,27 @@ theorem signExtend_eq_not_zeroExtend_not_of_msb_true {x : BitVec w} {v : Nat} (h
|
|||
@[simp] theorem getLsbD_signExtend (x : BitVec w) {v i : Nat} :
|
||||
(x.signExtend v).getLsbD i = (decide (i < v) && if i < w then x.getLsbD i else x.msb) := by
|
||||
rcases hmsb : x.msb with rfl | rfl
|
||||
· rw [signExtend_eq_not_zeroExtend_not_of_msb_false hmsb]
|
||||
· rw [signExtend_eq_not_setWidth_not_of_msb_false hmsb]
|
||||
by_cases (i < v) <;> by_cases (i < w) <;> simp_all <;> omega
|
||||
· rw [signExtend_eq_not_zeroExtend_not_of_msb_true hmsb]
|
||||
· rw [signExtend_eq_not_setWidth_not_of_msb_true hmsb]
|
||||
by_cases (i < v) <;> by_cases (i < w) <;> simp_all <;> omega
|
||||
|
||||
/-- Sign extending to a width smaller than the starting width is a truncation. -/
|
||||
theorem signExtend_eq_truncate_of_lt (x : BitVec w) {v : Nat} (hv : v ≤ w):
|
||||
x.signExtend v = x.truncate v := by
|
||||
theorem signExtend_eq_setWidth_of_lt (x : BitVec w) {v : Nat} (hv : v ≤ w):
|
||||
x.signExtend v = x.setWidth v := by
|
||||
ext i
|
||||
simp only [getLsbD_signExtend, Fin.is_lt, decide_True, Bool.true_and, getLsbD_zeroExtend,
|
||||
simp only [getLsbD_signExtend, Fin.is_lt, decide_True, Bool.true_and, getLsbD_setWidth,
|
||||
ite_eq_left_iff, Nat.not_lt]
|
||||
omega
|
||||
|
||||
/-- Sign extending to the same bitwidth is a no op. -/
|
||||
theorem signExtend_eq (x : BitVec w) : x.signExtend w = x := by
|
||||
rw [signExtend_eq_truncate_of_lt _ (Nat.le_refl _), truncate_eq]
|
||||
rw [signExtend_eq_setWidth_of_lt _ (Nat.le_refl _), setWidth_eq]
|
||||
|
||||
/-! ### append -/
|
||||
|
||||
theorem append_def (x : BitVec v) (y : BitVec w) :
|
||||
x ++ y = (shiftLeftZeroExtend x w ||| zeroExtend' (Nat.le_add_left w v) y) := rfl
|
||||
x ++ y = (shiftLeftZeroExtend x w ||| setWidth' (Nat.le_add_left w v) y) := rfl
|
||||
|
||||
@[simp] theorem toNat_append (x : BitVec m) (y : BitVec n) :
|
||||
(x ++ y).toNat = x.toNat <<< n ||| y.toNat :=
|
||||
|
|
@ -1259,7 +1232,7 @@ theorem append_def (x : BitVec v) (y : BitVec w) :
|
|||
|
||||
@[simp] theorem getLsbD_append {x : BitVec n} {y : BitVec m} :
|
||||
getLsbD (x ++ y) i = bif i < m then getLsbD y i else getLsbD x (i - m) := by
|
||||
simp only [append_def, getLsbD_or, getLsbD_shiftLeftZeroExtend, getLsbD_zeroExtend']
|
||||
simp only [append_def, getLsbD_or, getLsbD_shiftLeftZeroExtend, getLsbD_setWidth']
|
||||
by_cases h : i < m
|
||||
· simp [h]
|
||||
· simp [h]; simp_all
|
||||
|
|
@ -1274,7 +1247,7 @@ theorem append_def (x : BitVec v) (y : BitVec w) :
|
|||
theorem msb_append {x : BitVec w} {y : BitVec v} :
|
||||
(x ++ y).msb = bif (w == 0) then (y.msb) else (x.msb) := by
|
||||
rw [← append_eq, append]
|
||||
simp [msb_zeroExtend']
|
||||
simp [msb_setWidth']
|
||||
by_cases h : w = 0
|
||||
· subst h
|
||||
simp [BitVec.msb, getMsbD]
|
||||
|
|
@ -1309,11 +1282,11 @@ theorem msb_append {x : BitVec w} {y : BitVec v} :
|
|||
ext
|
||||
simp
|
||||
|
||||
theorem truncate_append {x : BitVec w} {y : BitVec v} :
|
||||
(x ++ y).truncate k = if h : k ≤ v then y.truncate k else (x.truncate (k - v) ++ y).cast (by omega) := by
|
||||
theorem setWidth_append {x : BitVec w} {y : BitVec v} :
|
||||
(x ++ y).setWidth k = if h : k ≤ v then y.setWidth k else (x.setWidth (k - v) ++ y).cast (by omega) := by
|
||||
apply eq_of_getLsbD_eq
|
||||
intro i
|
||||
simp only [getLsbD_zeroExtend, Fin.is_lt, decide_True, getLsbD_append, Bool.true_and]
|
||||
simp only [getLsbD_setWidth, Fin.is_lt, decide_True, getLsbD_append, Bool.true_and]
|
||||
split
|
||||
· have t : i < v := by omega
|
||||
simp [t]
|
||||
|
|
@ -1322,11 +1295,11 @@ theorem truncate_append {x : BitVec w} {y : BitVec v} :
|
|||
· have t' : i - v < k - v := by omega
|
||||
simp [t, t']
|
||||
|
||||
@[simp] theorem truncate_append_of_eq {x : BitVec v} {y : BitVec w} (h : w' = w) : truncate (v' + w') (x ++ y) = truncate v' x ++ truncate w' y := by
|
||||
@[simp] theorem setWidth_append_of_eq {x : BitVec v} {y : BitVec w} (h : w' = w) : setWidth (v' + w') (x ++ y) = setWidth v' x ++ setWidth w' y := by
|
||||
subst h
|
||||
ext i
|
||||
simp only [getLsbD_zeroExtend, Fin.is_lt, decide_True, getLsbD_append, cond_eq_if,
|
||||
decide_eq_true_eq, Bool.true_and, zeroExtend_eq]
|
||||
simp only [getLsbD_setWidth, Fin.is_lt, decide_True, getLsbD_append, cond_eq_if,
|
||||
decide_eq_true_eq, Bool.true_and, setWidth_eq]
|
||||
split
|
||||
· simp_all
|
||||
· simp_all only [Bool.iff_and_self, decide_eq_true_eq]
|
||||
|
|
@ -1334,8 +1307,8 @@ theorem truncate_append {x : BitVec w} {y : BitVec v} :
|
|||
have := BitVec.lt_of_getLsbD h
|
||||
omega
|
||||
|
||||
@[simp] theorem truncate_cons {x : BitVec w} : (cons a x).truncate w = x := by
|
||||
simp [cons, truncate_append]
|
||||
@[simp] theorem setWidth_cons {x : BitVec w} : (cons a x).setWidth w = x := by
|
||||
simp [cons, setWidth_append]
|
||||
|
||||
@[simp] theorem not_append {x : BitVec w} {y : BitVec v} : ~~~ (x ++ y) = (~~~ x) ++ (~~~ y) := by
|
||||
ext i
|
||||
|
|
@ -1422,18 +1395,18 @@ theorem toNat_cons' {x : BitVec w} :
|
|||
@[simp] theorem getMsbD_cons_succ : (cons a x).getMsbD (i + 1) = x.getMsbD i := by
|
||||
simp [cons, Nat.le_add_left 1 i]
|
||||
|
||||
theorem truncate_succ (x : BitVec w) :
|
||||
truncate (i+1) x = cons (getLsbD x i) (truncate i x) := by
|
||||
theorem setWidth_succ (x : BitVec w) :
|
||||
setWidth (i+1) x = cons (getLsbD x i) (setWidth i x) := by
|
||||
apply eq_of_getLsbD_eq
|
||||
intro j
|
||||
simp only [getLsbD_truncate, getLsbD_cons, j.isLt, decide_True, Bool.true_and]
|
||||
simp only [getLsbD_setWidth, getLsbD_cons, j.isLt, decide_True, Bool.true_and]
|
||||
if j_eq : j.val = i then
|
||||
simp [j_eq]
|
||||
else
|
||||
have j_lt : j.val < i := Nat.lt_of_le_of_ne (Nat.le_of_succ_le_succ j.isLt) j_eq
|
||||
simp [j_eq, j_lt]
|
||||
|
||||
theorem eq_msb_cons_truncate (x : BitVec (w+1)) : x = (cons x.msb (x.truncate w)) := by
|
||||
theorem eq_msb_cons_setWidth (x : BitVec (w+1)) : x = (cons x.msb (x.setWidth w)) := by
|
||||
ext i
|
||||
simp
|
||||
split <;> rename_i h
|
||||
|
|
@ -1532,8 +1505,8 @@ instance : Std.LawfulIdentity (α := BitVec n) (· + ·) 0#n where
|
|||
left_id := BitVec.zero_add
|
||||
right_id := BitVec.add_zero
|
||||
|
||||
theorem truncate_add (x y : BitVec w) (h : i ≤ w) :
|
||||
(x + y).truncate i = x.truncate i + y.truncate i := by
|
||||
theorem setWidth_add (x y : BitVec w) (h : i ≤ w) :
|
||||
(x + y).setWidth i = x.setWidth i + y.setWidth i := by
|
||||
have dvd : 2^i ∣ 2^w := Nat.pow_dvd_pow _ h
|
||||
simp [bv_toNat, h, Nat.mod_mod_of_dvd _ dvd]
|
||||
|
||||
|
|
@ -1991,18 +1964,18 @@ theorem twoPow_zero {w : Nat} : twoPow w 0 = 1#w := by
|
|||
theorem getLsbD_one {w i : Nat} : (1#w).getLsbD i = (decide (0 < w) && decide (0 = i)) := by
|
||||
rw [← twoPow_zero, getLsbD_twoPow]
|
||||
|
||||
/- ### zeroExtend, truncate, and bitwise operations -/
|
||||
/- ### setWidth, setWidth, and bitwise operations -/
|
||||
|
||||
/--
|
||||
When the `(i+1)`th bit of `x` is false,
|
||||
keeping the lower `(i + 1)` bits of `x` equals keeping the lower `i` bits.
|
||||
-/
|
||||
theorem zeroExtend_truncate_succ_eq_zeroExtend_truncate_of_getLsbD_false
|
||||
theorem setWidth_setWidth_succ_eq_setWidth_setWidth_of_getLsbD_false
|
||||
{x : BitVec w} {i : Nat} (hx : x.getLsbD i = false) :
|
||||
zeroExtend w (x.truncate (i + 1)) =
|
||||
zeroExtend w (x.truncate i) := by
|
||||
setWidth w (x.setWidth (i + 1)) =
|
||||
setWidth w (x.setWidth i) := by
|
||||
ext k
|
||||
simp only [getLsbD_zeroExtend, Fin.is_lt, decide_True, Bool.true_and, getLsbD_or, getLsbD_and]
|
||||
simp only [getLsbD_setWidth, Fin.is_lt, decide_True, Bool.true_and, getLsbD_or, getLsbD_and]
|
||||
by_cases hik : i = k
|
||||
· subst hik
|
||||
simp [hx]
|
||||
|
|
@ -2013,22 +1986,22 @@ When the `(i+1)`th bit of `x` is true,
|
|||
keeping the lower `(i + 1)` bits of `x` equalsk eeping the lower `i` bits
|
||||
and then performing bitwise-or with `twoPow i = (1 << i)`,
|
||||
-/
|
||||
theorem zeroExtend_truncate_succ_eq_zeroExtend_truncate_or_twoPow_of_getLsbD_true
|
||||
theorem setWidth_setWidth_succ_eq_setWidth_setWidth_or_twoPow_of_getLsbD_true
|
||||
{x : BitVec w} {i : Nat} (hx : x.getLsbD i = true) :
|
||||
zeroExtend w (x.truncate (i + 1)) =
|
||||
zeroExtend w (x.truncate i) ||| (twoPow w i) := by
|
||||
setWidth w (x.setWidth (i + 1)) =
|
||||
setWidth w (x.setWidth i) ||| (twoPow w i) := by
|
||||
ext k
|
||||
simp only [getLsbD_zeroExtend, Fin.is_lt, decide_True, Bool.true_and, getLsbD_or, getLsbD_and]
|
||||
simp only [getLsbD_setWidth, Fin.is_lt, decide_True, Bool.true_and, getLsbD_or, getLsbD_and]
|
||||
by_cases hik : i = k
|
||||
· subst hik
|
||||
simp [hx]
|
||||
· by_cases hik' : k < i + 1 <;> simp [hik, hik'] <;> omega
|
||||
|
||||
/-- Bitwise and of `(x : BitVec w)` with `1#w` equals zero extending `x.lsb` to `w`. -/
|
||||
theorem and_one_eq_zeroExtend_ofBool_getLsbD {x : BitVec w} :
|
||||
(x &&& 1#w) = zeroExtend w (ofBool (x.getLsbD 0)) := by
|
||||
theorem and_one_eq_setWidth_ofBool_getLsbD {x : BitVec w} :
|
||||
(x &&& 1#w) = setWidth w (ofBool (x.getLsbD 0)) := by
|
||||
ext i
|
||||
simp only [getLsbD_and, getLsbD_one, getLsbD_zeroExtend, Fin.is_lt, decide_True, getLsbD_ofBool,
|
||||
simp only [getLsbD_and, getLsbD_one, getLsbD_setWidth, Fin.is_lt, decide_True, getLsbD_ofBool,
|
||||
Bool.true_and]
|
||||
by_cases h : (0 = (i : Nat)) <;> simp [h] <;> omega
|
||||
|
||||
|
|
@ -2140,4 +2113,143 @@ theorem toNat_sub_of_le {x y : BitVec n} (h : y ≤ x) :
|
|||
· have : 2 ^ n - y.toNat + x.toNat = 2 ^ n + (x.toNat - y.toNat) := by omega
|
||||
rw [this, Nat.add_mod_left, Nat.mod_eq_of_lt (by omega)]
|
||||
|
||||
/-! ### Deprecations -/
|
||||
|
||||
set_option linter.missingDocs false
|
||||
|
||||
@[deprecated truncate_eq_setWidth (since := "2024-09-18")]
|
||||
abbrev truncate_eq_zeroExtend := @truncate_eq_setWidth
|
||||
|
||||
@[deprecated toNat_setWidth' (since := "2024-09-18")]
|
||||
abbrev toNat_zeroExtend' := @toNat_setWidth'
|
||||
|
||||
@[deprecated toNat_setWidth (since := "2024-09-18")]
|
||||
abbrev toNat_zeroExtend := @toNat_setWidth
|
||||
|
||||
@[deprecated toNat_setWidth (since := "2024-09-18")]
|
||||
abbrev toNat_truncate := @toNat_setWidth
|
||||
|
||||
@[deprecated setWidth_eq (since := "2024-09-18")]
|
||||
abbrev zeroExtend_eq := @setWidth_eq
|
||||
|
||||
@[deprecated setWidth_eq (since := "2024-09-18")]
|
||||
abbrev truncate_eq := @setWidth_eq
|
||||
|
||||
@[deprecated setWidth_zero (since := "2024-09-18")]
|
||||
abbrev zeroExtend_zero := @setWidth_zero
|
||||
|
||||
@[deprecated getElem_setWidth (since := "2024-09-18")]
|
||||
abbrev getElem_zeroExtend := @getElem_setWidth
|
||||
|
||||
@[deprecated getElem_setWidth' (since := "2024-09-18")]
|
||||
abbrev getElem_zeroExtend' := @getElem_setWidth'
|
||||
|
||||
@[deprecated getElem?_setWidth (since := "2024-09-18")]
|
||||
abbrev getElem?_zeroExtend := @getElem?_setWidth
|
||||
|
||||
@[deprecated getElem?_setWidth' (since := "2024-09-18")]
|
||||
abbrev getElem?_zeroExtend' := @getElem?_setWidth'
|
||||
|
||||
@[deprecated getLsbD_setWidth (since := "2024-09-18")]
|
||||
abbrev getLsbD_zeroExtend := @getLsbD_setWidth
|
||||
|
||||
@[deprecated getLsbD_setWidth' (since := "2024-09-18")]
|
||||
abbrev getLsbD_zeroExtend' := @getLsbD_setWidth'
|
||||
|
||||
@[deprecated getMsbD_setWidth_add (since := "2024-09-18")]
|
||||
abbrev getMsbD_zeroExtend_add := @getMsbD_setWidth_add
|
||||
|
||||
@[deprecated getMsbD_setWidth' (since := "2024-09-18")]
|
||||
abbrev getMsbD_zeroExtend' := @getMsbD_setWidth'
|
||||
|
||||
@[deprecated getElem_setWidth (since := "2024-09-18")]
|
||||
abbrev getElem_truncate := @getElem_setWidth
|
||||
|
||||
@[deprecated getElem?_setWidth (since := "2024-09-18")]
|
||||
abbrev getElem?_truncate := @getElem?_setWidth
|
||||
|
||||
@[deprecated getLsbD_setWidth (since := "2024-09-18")]
|
||||
abbrev getLsbD_truncate := @getLsbD_setWidth
|
||||
|
||||
@[deprecated msb_setWidth (since := "2024-09-18")]
|
||||
abbrev msb_truncate := @msb_setWidth
|
||||
|
||||
@[deprecated cast_setWidth (since := "2024-09-18")]
|
||||
abbrev cast_zeroExtend := @cast_setWidth
|
||||
|
||||
@[deprecated cast_setWidth (since := "2024-09-18")]
|
||||
abbrev cast_truncate := @cast_setWidth
|
||||
|
||||
@[deprecated setWidth_setWidth_of_le (since := "2024-09-18")]
|
||||
abbrev zeroExtend_zeroExtend_of_le := @setWidth_setWidth_of_le
|
||||
|
||||
@[deprecated setWidth_eq (since := "2024-09-18")]
|
||||
abbrev truncate_eq_self := @setWidth_eq
|
||||
|
||||
@[deprecated setWidth_cast (since := "2024-09-18")]
|
||||
abbrev truncate_cast := @setWidth_cast
|
||||
|
||||
@[deprecated msb_setWidth (since := "2024-09-18")]
|
||||
abbrev mbs_zeroExtend := @msb_setWidth
|
||||
|
||||
@[deprecated msb_setWidth' (since := "2024-09-18")]
|
||||
abbrev mbs_zeroExtend' := @msb_setWidth'
|
||||
|
||||
@[deprecated setWidth_one_eq_ofBool_getLsb_zero (since := "2024-09-18")]
|
||||
abbrev zeroExtend_one_eq_ofBool_getLsb_zero := @setWidth_one_eq_ofBool_getLsb_zero
|
||||
|
||||
@[deprecated setWidth_ofNat_one_eq_ofNat_one_of_lt (since := "2024-09-18")]
|
||||
abbrev zeroExtend_ofNat_one_eq_ofNat_one_of_lt := @setWidth_ofNat_one_eq_ofNat_one_of_lt
|
||||
|
||||
@[deprecated setWidth_one (since := "2024-09-18")]
|
||||
abbrev truncate_one := @setWidth_one
|
||||
|
||||
@[deprecated setWidth_ofNat_of_le (since := "2024-09-18")]
|
||||
abbrev truncate_ofNat_of_le := @setWidth_ofNat_of_le
|
||||
|
||||
@[deprecated setWidth_or (since := "2024-09-18")]
|
||||
abbrev truncate_or := @setWidth_or
|
||||
|
||||
@[deprecated setWidth_and (since := "2024-09-18")]
|
||||
abbrev truncate_and := @setWidth_and
|
||||
|
||||
@[deprecated setWidth_xor (since := "2024-09-18")]
|
||||
abbrev truncate_xor := @setWidth_xor
|
||||
|
||||
@[deprecated setWidth_not (since := "2024-09-18")]
|
||||
abbrev truncate_not := @setWidth_not
|
||||
|
||||
@[deprecated signExtend_eq_not_setWidth_not_of_msb_false (since := "2024-09-18")]
|
||||
abbrev signExtend_eq_not_zeroExtend_not_of_msb_false := @signExtend_eq_not_setWidth_not_of_msb_false
|
||||
|
||||
@[deprecated signExtend_eq_not_setWidth_not_of_msb_true (since := "2024-09-18")]
|
||||
abbrev signExtend_eq_not_zeroExtend_not_of_msb_true := @signExtend_eq_not_setWidth_not_of_msb_true
|
||||
|
||||
@[deprecated signExtend_eq_setWidth_of_lt (since := "2024-09-18")]
|
||||
abbrev signExtend_eq_truncate_of_lt := @signExtend_eq_setWidth_of_lt
|
||||
|
||||
@[deprecated truncate_append (since := "2024-09-18")]
|
||||
abbrev truncate_append := @setWidth_append
|
||||
|
||||
@[deprecated truncate_append_of_eq (since := "2024-09-18")]
|
||||
abbrev truncate_append_of_eq := @setWidth_append_of_eq
|
||||
|
||||
@[deprecated truncate_cons (since := "2024-09-18")]
|
||||
abbrev truncate_cons := @setWidth_cons
|
||||
|
||||
@[deprecated truncate_succ (since := "2024-09-18")]
|
||||
abbrev truncate_succ := @setWidth_succ
|
||||
|
||||
@[deprecated truncate_add (since := "2024-09-18")]
|
||||
abbrev truncate_add := @setWidth_add
|
||||
|
||||
@[deprecated setWidth_setWidth_succ_eq_setWidth_setWidth_of_getLsbD_false (since := "2024-09-18")]
|
||||
abbrev zeroExtend_truncate_succ_eq_zeroExtend_truncate_of_getLsbD_false := @setWidth_setWidth_succ_eq_setWidth_setWidth_of_getLsbD_false
|
||||
|
||||
@[deprecated setWidth_setWidth_succ_eq_setWidth_setWidth_or_twoPow_of_getLsbD_true (since := "2024-09-18")]
|
||||
abbrev zeroExtend_truncate_succ_eq_zeroExtend_truncate_or_twoPow_of_getLsbD_true := @setWidth_setWidth_succ_eq_setWidth_setWidth_or_twoPow_of_getLsbD_true
|
||||
|
||||
@[deprecated and_one_eq_setWidth_ofBool_getLsbD (since := "2024-09-18")]
|
||||
abbrev and_one_eq_zeroExtend_ofBool_getLsbD := @and_one_eq_setWidth_ofBool_getLsbD
|
||||
|
||||
end BitVec
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ Helper function for reducing homogenous binary bitvector operators.
|
|||
else
|
||||
return .continue
|
||||
|
||||
/-- Simplification procedure for `zeroExtend` and `signExtend` on `BitVec`s. -/
|
||||
/-- Simplification procedure for `setWidth`, `zeroExtend` and `signExtend` on `BitVec`s. -/
|
||||
@[inline] def reduceExtend (declName : Name)
|
||||
(op : {n : Nat} → (m : Nat) → BitVec n → BitVec m) (e : Expr) : SimpM DStep := do
|
||||
unless e.isAppOfArity declName 3 do return .continue
|
||||
|
|
@ -253,13 +253,13 @@ builtin_dsimproc [simp, seval] reduceSLT (BitVec.slt _ _) :=
|
|||
builtin_dsimproc [simp, seval] reduceSLE (BitVec.sle _ _) :=
|
||||
reduceBoolPred ``BitVec.sle 3 BitVec.sle
|
||||
|
||||
/-- Simplification procedure for `zeroExtend'` on `BitVec`s. -/
|
||||
builtin_dsimproc [simp, seval] reduceZeroExtend' (zeroExtend' _ _) := fun e => do
|
||||
let_expr zeroExtend' _ w _ v ← e | return .continue
|
||||
/-- Simplification procedure for `setWidth'` on `BitVec`s. -/
|
||||
builtin_dsimproc [simp, seval] reduceSetWidth' (setWidth' _ _) := fun e => do
|
||||
let_expr setWidth' _ w _ v ← e | return .continue
|
||||
let some v ← fromExpr? v | return .continue
|
||||
let some w ← Nat.fromExpr? w | return .continue
|
||||
if h : v.n ≤ w then
|
||||
return .done <| toExpr (v.value.zeroExtend' h)
|
||||
return .done <| toExpr (v.value.setWidth' h)
|
||||
else
|
||||
return .continue
|
||||
|
||||
|
|
@ -285,6 +285,9 @@ builtin_dsimproc [simp, seval] reduceReplicate (replicate _ _) := fun e => do
|
|||
let some i ← Nat.fromExpr? i | return .continue
|
||||
return .done <| toExpr (v.value.replicate i)
|
||||
|
||||
/-- Simplification procedure for `setWidth` on `BitVec`s. -/
|
||||
builtin_dsimproc [simp, seval] reduceSetWidth (setWidth _ _) := reduceExtend ``setWidth setWidth
|
||||
|
||||
/-- Simplification procedure for `zeroExtend` on `BitVec`s. -/
|
||||
builtin_dsimproc [simp, seval] reduceZeroExtend (zeroExtend _ _) := reduceExtend ``zeroExtend zeroExtend
|
||||
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ theorem go_denote_eq (aig : AIG BVBit) (expr : BVExpr w) (assign : Assignment) :
|
|||
simp [go, hidx, denote_blastVar]
|
||||
| zeroExtend v inner ih =>
|
||||
simp only [go, denote_blastZeroExtend, ih, dite_eq_ite, Bool.if_false_right,
|
||||
eval_zeroExtend, BitVec.getLsbD_zeroExtend, hidx, decide_True, Bool.true_and,
|
||||
eval_zeroExtend, BitVec.getLsbD_setWidth, hidx, decide_True, Bool.true_and,
|
||||
Bool.and_iff_right_iff_imp, decide_eq_true_eq]
|
||||
apply BitVec.lt_of_getLsbD
|
||||
| append lhs rhs lih rih =>
|
||||
|
|
@ -93,9 +93,9 @@ theorem go_denote_eq (aig : AIG BVBit) (expr : BVExpr w) (assign : Assignment) :
|
|||
rw [blastSignExtend_empty_eq_zeroExtend] at hgo
|
||||
· rw [← hgo]
|
||||
simp only [eval_signExtend]
|
||||
rw [BitVec.signExtend_eq_not_zeroExtend_not_of_msb_false]
|
||||
rw [BitVec.signExtend_eq_not_setWidth_not_of_msb_false]
|
||||
· simp only [denote_blastZeroExtend, ih, dite_eq_ite, Bool.if_false_right,
|
||||
BitVec.getLsbD_zeroExtend, hidx, decide_True, Bool.true_and, Bool.and_iff_right_iff_imp,
|
||||
BitVec.getLsbD_setWidth, hidx, decide_True, Bool.true_and, Bool.and_iff_right_iff_imp,
|
||||
decide_eq_true_eq]
|
||||
apply BitVec.lt_of_getLsbD
|
||||
· subst heq
|
||||
|
|
|
|||
|
|
@ -56,8 +56,8 @@ attribute [bv_normalize] BitVec.zero_add
|
|||
attribute [bv_normalize] BitVec.neg_zero
|
||||
attribute [bv_normalize] BitVec.sub_self
|
||||
attribute [bv_normalize] BitVec.sub_zero
|
||||
attribute [bv_normalize] BitVec.zeroExtend_eq
|
||||
attribute [bv_normalize] BitVec.zeroExtend_zero
|
||||
attribute [bv_normalize] BitVec.setWidth_eq
|
||||
attribute [bv_normalize] BitVec.setWidth_zero
|
||||
attribute [bv_normalize] BitVec.getLsbD_zero
|
||||
attribute [bv_normalize] BitVec.getLsbD_zero_length
|
||||
attribute [bv_normalize] BitVec.getLsbD_concat_zero
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ example (h : x) : x = (3#3 ≥ 1#3) := by
|
|||
simp; guard_target =ₛ x; assumption
|
||||
example (h : ¬x) : x = (3#3 ≥ 4#3) := by
|
||||
simp; guard_target =ₛ ¬x; assumption
|
||||
example (h : x = (5 : BitVec 7)) : x = (5#3).zeroExtend' (by decide) := by
|
||||
example (h : x = (5 : BitVec 7)) : x = (5#3).setWidth' (by decide) := by
|
||||
simp; guard_target =ₛ x = 5#7; assumption
|
||||
example (h : x = (80 : BitVec 7)) : x = (5#3).shiftLeftZeroExtend 4 := by
|
||||
simp; guard_target =ₛ x = 80#7; assumption
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ theorem write_simplify_test_0 (a x y : BitVec 64)
|
|||
write (2 * ((8 * 8) / 8)) a (BitVec.cast h (zeroExtend (8 * 8) x ++ (zeroExtend (8 * 8) y))) s
|
||||
=
|
||||
write 16 a (x ++ y) s := by
|
||||
simp only [zeroExtend_eq, BitVec.cast_eq]
|
||||
simp only [setWidth_eq, BitVec.cast_eq]
|
||||
|
||||
/--
|
||||
warning: declaration uses 'sorry'
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue