feat: proposed change to BitVec API (#5200)

This renames `BitVec.getLsb` to `getLsbD` (`D` for "default" value, i.e.
false), and introduces `getLsb?` and `getLsb'` (which we can rename to
`getLsb` after a deprecation cycle).

(Similarly for `getMsb`.)

Also adds a `GetElem` class so we can use `x[i]` and `x[i]?` notation. 

Later, we will turn
```
theorem getLsbD_eq_getElem?_getD (x : BitVec w) (i : Nat) (h : i < w) :
    x.getLsbD i = x[i]?.getD false
```
on as a `@[simp]` lemma.

This PR doesn't attempt to demonstrate the benefits, but I think both
arguments are going to get easier, and this will bring the BitVec API
closer in line to List/Array, etc.

---------

Co-authored-by: Markus Himmel <markus@lean-fro.org>
This commit is contained in:
Kim Morrison 2024-08-30 12:00:57 +10:00 committed by GitHub
parent f30ff6ae79
commit 6b62fed82e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
35 changed files with 638 additions and 501 deletions

View file

@ -116,17 +116,62 @@ end zero_allOnes
section getXsb
/--
Return the `i`-th least significant bit.
This will be renamed `getLsb` after the existing deprecated alias is removed.
-/
@[inline] def getLsb' (x : BitVec w) (i : Fin w) : Bool := x.toNat.testBit i
/-- Return the `i`-th least significant bit or `none` if `i ≥ w`. -/
@[inline] def getLsb? (x : BitVec w) (i : Nat) : Option Bool :=
if h : i < w then some (getLsb' x ⟨i, h⟩) else none
/--
Return the `i`-th most significant bit.
This will be renamed `getMsb` after the existing deprecated alias is removed.
-/
@[inline] def getMsb' (x : BitVec w) (i : Fin w) : Bool := x.getLsb' ⟨w-1-i, by omega⟩
/-- Return the `i`-th most significant bit or `none` if `i ≥ w`. -/
@[inline] def getMsb? (x : BitVec w) (i : Nat) : Option Bool :=
if h : i < w then some (getMsb' x ⟨i, h⟩) else none
/-- Return the `i`-th least significant bit or `false` if `i ≥ w`. -/
@[inline] def getLsb (x : BitVec w) (i : Nat) : Bool := x.toNat.testBit i
@[inline] def getLsbD (x : BitVec w) (i : Nat) : Bool :=
x.toNat.testBit i
@[deprecated getLsbD (since := "2024-08-29"), inherit_doc getLsbD]
def getLsb (x : BitVec w) (i : Nat) : Bool := x.getLsbD i
/-- Return the `i`-th most significant bit or `false` if `i ≥ w`. -/
@[inline] def getMsb (x : BitVec w) (i : Nat) : Bool := i < w && getLsb x (w-1-i)
@[inline] def getMsbD (x : BitVec w) (i : Nat) : Bool :=
i < w && x.getLsbD (w-1-i)
@[deprecated getMsbD (since := "2024-08-29"), inherit_doc getMsbD]
def getMsb (x : BitVec w) (i : Nat) : Bool := x.getMsbD i
/-- Return most-significant bit in bitvector. -/
@[inline] protected def msb (x : BitVec n) : Bool := getMsb x 0
@[inline] protected def msb (x : BitVec n) : Bool := getMsbD x 0
end getXsb
section getElem
instance : GetElem (BitVec w) Nat Bool fun _ i => i < w where
getElem xs i h := xs.getLsb' ⟨i, h⟩
/-- We prefer `x[i]` as the simp normal form for `getLsb'` -/
@[simp] theorem getLsb'_eq_getElem (x : BitVec w) (i : Fin w) :
x.getLsb' i = x[i] := rfl
/-- We prefer `x[i]?` as the simp normal form for `getLsb?` -/
@[simp] theorem getLsb?_eq_getElem? (x : BitVec w) (i : Nat) :
x.getLsb? i = x[i]? := rfl
end getElem
section Int
/-- Interpret the bitvector as an integer stored in two's complement form. -/

View file

@ -92,8 +92,8 @@ def carry (i : Nat) (x y : BitVec w) (c : Bool) : Bool :=
cases c <;> simp [carry, mod_one]
theorem carry_succ (i : Nat) (x y : BitVec w) (c : Bool) :
carry (i+1) x y c = atLeastTwo (x.getLsb i) (y.getLsb i) (carry i x y c) := by
simp only [carry, mod_two_pow_succ, atLeastTwo, getLsb]
carry (i+1) x y c = atLeastTwo (x.getLsbD i) (y.getLsbD i) (carry i x y c) := by
simp only [carry, mod_two_pow_succ, atLeastTwo, getLsbD]
simp only [Nat.pow_succ']
have sum_bnd : x.toNat%2^i + (y.toNat%2^i + c.toNat) < 2*2^i := by
simp only [← Nat.pow_succ']
@ -110,7 +110,7 @@ theorem carry_of_and_eq_zero {x y : BitVec w} (h : x &&& y = 0#w) : carry i x y
induction i with
| zero => simp
| succ i ih =>
replace h := congrArg (·.getLsb i) h
replace h := congrArg (·.getLsbD i) h
simp_all [carry_succ]
/-- The final carry bit when computing `x + y + c` is `true` iff `x.toNat + y.toNat + c.toNat ≥ 2^w`. -/
@ -136,14 +136,14 @@ def adcb (x y c : Bool) : Bool × Bool := (atLeastTwo x y c, Bool.xor x (Bool.xo
/-- Bitwise addition implemented via a ripple carry adder. -/
def adc (x y : BitVec w) : Bool → Bool × BitVec w :=
iunfoldr fun (i : Fin w) c => adcb (x.getLsb i) (y.getLsb i) c
iunfoldr fun (i : Fin w) c => adcb (x.getLsbD i) (y.getLsbD i) c
theorem getLsb_add_add_bool {i : Nat} (i_lt : i < w) (x y : BitVec w) (c : Bool) :
getLsb (x + y + zeroExtend w (ofBool c)) i =
Bool.xor (getLsb x i) (Bool.xor (getLsb y i) (carry i x y c)) := by
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 =
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 [getLsb, toNat_add, toNat_zeroExtend, i_lt, toNat_ofFin, toNat_ofBool,
simp only [getLsbD, toNat_add, toNat_zeroExtend, 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)]
@ -159,10 +159,10 @@ theorem getLsb_add_add_bool {i : Nat} (i_lt : i < w) (x y : BitVec w) (c : Bool)
]
simp [testBit_to_div_mod, carry, Nat.add_assoc]
theorem getLsb_add {i : Nat} (i_lt : i < w) (x y : BitVec w) :
getLsb (x + y) i =
Bool.xor (getLsb x i) (Bool.xor (getLsb y i) (carry i x y false)) := by
simpa using getLsb_add_add_bool i_lt x y false
theorem getLsbD_add {i : Nat} (i_lt : i < w) (x y : BitVec w) :
getLsbD (x + y) i =
Bool.xor (getLsbD x i) (Bool.xor (getLsbD y i) (carry i x y false)) := by
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
@ -175,7 +175,7 @@ theorem adc_spec (x y : BitVec w) (c : Bool) :
simp [carry, Nat.mod_one]
cases c <;> rfl
case step =>
simp [adcb, Prod.mk.injEq, carry_succ, getLsb_add_add_bool]
simp [adcb, Prod.mk.injEq, carry_succ, getLsbD_add_add_bool]
theorem add_eq_adc (w : Nat) (x y : BitVec w) : x + y = (adc x y false).snd := by
simp [adc_spec]
@ -197,37 +197,37 @@ theorem add_eq_or_of_and_eq_zero {w : Nat} (x y : BitVec w)
(h : x &&& y = 0#w) : x + y = x ||| y := by
rw [add_eq_adc, adc, iunfoldr_replace (fun _ => false) (x ||| y)]
· rfl
· simp only [adcb, atLeastTwo, Bool.and_false, Bool.or_false, bne_false, getLsb_or,
· simp only [adcb, atLeastTwo, Bool.and_false, Bool.or_false, bne_false, getLsbD_or,
Prod.mk.injEq, and_eq_false_imp]
intros i
replace h : (x &&& y).getLsb i = (0#w).getLsb i := by rw [h]
simp only [getLsb_and, getLsb_zero, and_eq_false_imp] at h
replace h : (x &&& y).getLsbD i = (0#w).getLsbD i := by rw [h]
simp only [getLsbD_and, getLsbD_zero, and_eq_false_imp] at h
constructor
· intros hx
simp_all [hx]
· by_cases hx : x.getLsb i <;> simp_all [hx]
· by_cases hx : x.getLsbD i <;> simp_all [hx]
/-! ### Negation -/
theorem bit_not_testBit (x : BitVec w) (i : Fin w) :
getLsb (((iunfoldr (fun (i : Fin w) c => (c, !(x.getLsb i)))) ()).snd) i.val = !(getLsb x i.val) := by
apply iunfoldr_getLsb (fun _ => ()) i (by simp)
getLsbD (((iunfoldr (fun (i : Fin w) c => (c, !(x.getLsbD i)))) ()).snd) i.val = !(getLsbD x i.val) := by
apply iunfoldr_getLsbD (fun _ => ()) i (by simp)
theorem bit_not_add_self (x : BitVec w) :
((iunfoldr (fun (i : Fin w) c => (c, !(x.getLsb i)))) ()).snd + x = -1 := by
((iunfoldr (fun (i : Fin w) c => (c, !(x.getLsbD i)))) ()).snd + x = -1 := by
simp only [add_eq_adc]
apply iunfoldr_replace_snd (fun _ => false) (-1) false rfl
intro i; simp only [ BitVec.not, adcb, testBit_toNat]
rw [iunfoldr_replace_snd (fun _ => ()) (((iunfoldr (fun i c => (c, !(x.getLsb i)))) ()).snd)]
<;> simp [bit_not_testBit, negOne_eq_allOnes, getLsb_allOnes]
rw [iunfoldr_replace_snd (fun _ => ()) (((iunfoldr (fun i c => (c, !(x.getLsbD i)))) ()).snd)]
<;> simp [bit_not_testBit, negOne_eq_allOnes, getLsbD_allOnes]
theorem bit_not_eq_not (x : BitVec w) :
((iunfoldr (fun i c => (c, !(x.getLsb i)))) ()).snd = ~~~ x := by
((iunfoldr (fun i c => (c, !(x.getLsbD i)))) ()).snd = ~~~ x := by
simp [←allOnes_sub_eq_not, BitVec.eq_sub_iff_add_eq.mpr (bit_not_add_self x), ←negOne_eq_allOnes]
theorem bit_neg_eq_neg (x : BitVec w) : -x = (adc (((iunfoldr (fun (i : Fin w) c => (c, !(x.getLsb i)))) ()).snd) (BitVec.ofNat w 1) false).snd:= by
theorem bit_neg_eq_neg (x : BitVec w) : -x = (adc (((iunfoldr (fun (i : Fin w) c => (c, !(x.getLsbD i)))) ()).snd) (BitVec.ofNat w 1) false).snd:= by
simp only [← add_eq_adc]
rw [iunfoldr_replace_snd ((fun _ => ())) (((iunfoldr (fun (i : Fin w) c => (c, !(x.getLsb i)))) ()).snd) _ rfl]
rw [iunfoldr_replace_snd ((fun _ => ())) (((iunfoldr (fun (i : Fin w) c => (c, !(x.getLsbD i)))) ()).snd) _ rfl]
· rw [BitVec.eq_sub_iff_add_eq.mpr (bit_not_add_self x), sub_toAdd, BitVec.add_comm _ (-x)]
simp [← sub_toAdd, BitVec.sub_add_cancel]
· simp [bit_not_testBit x _]
@ -290,17 +290,17 @@ A recurrence that describes multiplication as repeated addition.
Is useful for bitblasting multiplication.
-/
def mulRec (x y : BitVec w) (s : Nat) : BitVec w :=
let cur := if y.getLsb s then (x <<< s) else 0
let cur := if y.getLsbD s then (x <<< s) else 0
match s with
| 0 => cur
| s + 1 => mulRec x y s + cur
theorem mulRec_zero_eq (x y : BitVec w) :
mulRec x y 0 = if y.getLsb 0 then x else 0 := by
mulRec x y 0 = if y.getLsbD 0 then x else 0 := by
simp [mulRec]
theorem mulRec_succ_eq (x y : BitVec w) (s : Nat) :
mulRec x y (s + 1) = mulRec x y s + if y.getLsb (s + 1) then (x <<< (s + 1)) else 0 := rfl
mulRec x y (s + 1) = mulRec x y s + if y.getLsbD (s + 1) then (x <<< (s + 1)) else 0 := rfl
/--
Recurrence lemma: truncating to `i+1` bits and then zero extending to `w`
@ -311,11 +311,11 @@ theorem zeroExtend_truncate_succ_eq_zeroExtend_truncate_add_twoPow (x : BitVec w
zeroExtend w (x.truncate i) + (x &&& twoPow w i) := by
rw [add_eq_or_of_and_eq_zero]
· ext k
simp only [getLsb_zeroExtend, Fin.is_lt, decide_True, Bool.true_and, getLsb_or, getLsb_and]
simp only [getLsbD_zeroExtend, Fin.is_lt, decide_True, Bool.true_and, getLsbD_or, getLsbD_and]
by_cases hik : i = k
· subst hik
simp
· simp only [getLsb_twoPow, hik, decide_False, Bool.and_false, Bool.or_false]
· simp only [getLsbD_twoPow, hik, decide_False, Bool.and_false, Bool.or_false]
by_cases hik' : k < (i + 1)
· have hik'' : k < i := by omega
simp [hik', hik'']
@ -323,7 +323,7 @@ theorem zeroExtend_truncate_succ_eq_zeroExtend_truncate_add_twoPow (x : BitVec w
simp [hik', hik'']
· ext k
simp
by_cases hi : x.getLsb i <;> simp [hi] <;> omega
by_cases hi : x.getLsbD i <;> simp [hi] <;> omega
/--
Recurrence lemma: multiplying `x` with the first `s` bits of `y` is the
@ -334,7 +334,7 @@ theorem mulRec_eq_mul_signExtend_truncate (x y : BitVec w) (s : Nat) :
induction s
case zero =>
simp only [mulRec_zero_eq, ofNat_eq_ofNat, Nat.reduceAdd]
by_cases y.getLsb 0
by_cases y.getLsbD 0
case pos hy =>
simp only [hy, ↓reduceIte, truncate, zeroExtend_one_eq_ofBool_getLsb_zero,
ofBool_true, ofNat_eq_ofNat]
@ -345,14 +345,14 @@ theorem mulRec_eq_mul_signExtend_truncate (x y : BitVec w) (s : Nat) :
case succ s' hs =>
rw [mulRec_succ_eq, hs]
have heq :
(if y.getLsb (s' + 1) = true then x <<< (s' + 1) else 0) =
(if y.getLsbD (s' + 1) = true then x <<< (s' + 1) else 0) =
(x * (y &&& (BitVec.twoPow w (s' + 1)))) := by
simp only [ofNat_eq_ofNat, and_twoPow]
by_cases hy : y.getLsb (s' + 1) <;> simp [hy]
by_cases hy : y.getLsbD (s' + 1) <;> simp [hy]
rw [heq, ← BitVec.mul_add, ← zeroExtend_truncate_succ_eq_zeroExtend_truncate_add_twoPow]
theorem getLsb_mul (x y : BitVec w) (i : Nat) :
(x * y).getLsb i = (mulRec x y w).getLsb i := by
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]
@ -406,17 +406,17 @@ theorem shiftLeftRec_eq {x : BitVec w₁} {y : BitVec w₂} {n : Nat} :
case zero =>
ext i
simp only [shiftLeftRec_zero, twoPow_zero, Nat.reduceAdd, truncate_one,
and_one_eq_zeroExtend_ofBool_getLsb]
and_one_eq_zeroExtend_ofBool_getLsbD]
case succ n ih =>
simp only [shiftLeftRec_succ, and_twoPow]
rw [ih]
by_cases h : y.getLsb (n + 1)
by_cases h : y.getLsbD (n + 1)
· simp only [h, ↓reduceIte]
rw [zeroExtend_truncate_succ_eq_zeroExtend_truncate_or_twoPow_of_getLsb_true h,
rw [zeroExtend_truncate_succ_eq_zeroExtend_truncate_or_twoPow_of_getLsbD_true h,
shiftLeft_or_of_and_eq_zero]
simp
· simp only [h, false_eq_true, ↓reduceIte, shiftLeft_zero']
rw [zeroExtend_truncate_succ_eq_zeroExtend_truncate_of_getLsb_false (i := n + 1)]
rw [zeroExtend_truncate_succ_eq_zeroExtend_truncate_of_getLsbD_false (i := n + 1)]
simp [h]
/--
@ -469,14 +469,14 @@ theorem sshiftRightRec_eq (x : BitVec w₁) (y : BitVec w₂) (n : Nat) :
induction n generalizing x y
case zero =>
ext i
simp [twoPow_zero, Nat.reduceAdd, and_one_eq_zeroExtend_ofBool_getLsb, truncate_one]
simp [twoPow_zero, Nat.reduceAdd, and_one_eq_zeroExtend_ofBool_getLsbD, truncate_one]
case succ n ih =>
simp only [sshiftRightRec_succ_eq, and_twoPow, ih]
by_cases h : y.getLsb (n + 1)
· rw [zeroExtend_truncate_succ_eq_zeroExtend_truncate_or_twoPow_of_getLsb_true h,
by_cases h : y.getLsbD (n + 1)
· rw [zeroExtend_truncate_succ_eq_zeroExtend_truncate_or_twoPow_of_getLsbD_true h,
sshiftRight'_or_of_and_eq_zero (by simp), h]
simp
· rw [zeroExtend_truncate_succ_eq_zeroExtend_truncate_of_getLsb_false (i := n + 1)
· rw [zeroExtend_truncate_succ_eq_zeroExtend_truncate_of_getLsbD_false (i := n + 1)
(by simp [h])]
simp [h]
@ -485,7 +485,7 @@ Show that `x.sshiftRight y` can be written in terms of `sshiftRightRec`.
This can be unfolded in terms of `sshiftRightRec_zero_eq`, `sshiftRightRec_succ_eq` for bitblasting.
-/
theorem sshiftRight_eq_sshiftRightRec (x : BitVec w₁) (y : BitVec w₂) :
(x.sshiftRight' y).getLsb i = (sshiftRightRec x y (w₂ - 1)).getLsb i := by
(x.sshiftRight' y).getLsbD i = (sshiftRightRec x y (w₂ - 1)).getLsbD i := by
rcases w₂ with rfl | w₂
· simp [of_length_zero]
· simp [sshiftRightRec_eq]
@ -533,15 +533,15 @@ theorem ushiftRightRec_eq (x : BitVec w₁) (y : BitVec w₂) (n : Nat) :
case zero =>
ext i
simp only [ushiftRightRec_zero, twoPow_zero, Nat.reduceAdd,
and_one_eq_zeroExtend_ofBool_getLsb, truncate_one]
and_one_eq_zeroExtend_ofBool_getLsbD, truncate_one]
case succ n ih =>
simp only [ushiftRightRec_succ, and_twoPow]
rw [ih]
by_cases h : y.getLsb (n + 1) <;> simp only [h, ↓reduceIte]
· rw [zeroExtend_truncate_succ_eq_zeroExtend_truncate_or_twoPow_of_getLsb_true h,
by_cases h : y.getLsbD (n + 1) <;> simp only [h, ↓reduceIte]
· rw [zeroExtend_truncate_succ_eq_zeroExtend_truncate_or_twoPow_of_getLsbD_true h,
ushiftRight'_or_of_and_eq_zero]
simp
· simp [zeroExtend_truncate_succ_eq_zeroExtend_truncate_of_getLsb_false, h]
· simp [zeroExtend_truncate_succ_eq_zeroExtend_truncate_of_getLsbD_false, h]
/--
Show that `x >>> y` can be written in terms of `ushiftRightRec`.

View file

@ -41,7 +41,7 @@ theorem iunfoldr.fst_eq
private theorem iunfoldr.eq_test
{f : Fin w → αα × Bool} (state : Nat → α) (value : BitVec w) (a : α)
(init : state 0 = a)
(step : ∀(i : Fin w), f i (state i.val) = (state (i.val+1), value.getLsb i.val)) :
(step : ∀(i : Fin w), f i (state i.val) = (state (i.val+1), value.getLsbD i.val)) :
iunfoldr f a = (state w, BitVec.truncate w value) := by
apply Fin.hIterate_eq (fun i => ((state i, BitVec.truncate i value) : α × BitVec i))
case init =>
@ -50,15 +50,15 @@ private theorem iunfoldr.eq_test
intro i
simp_all [truncate_succ]
theorem iunfoldr_getLsb' {f : Fin w → αα × Bool} (state : Nat → α)
theorem iunfoldr_getLsbD' {f : Fin w → αα × Bool} (state : Nat → α)
(ind : ∀(i : Fin w), (f i (state i.val)).fst = state (i.val+1)) :
(∀ i : Fin w, getLsb (iunfoldr f (state 0)).snd i.val = (f i (state i.val)).snd)
(∀ i : Fin w, getLsbD (iunfoldr f (state 0)).snd i.val = (f i (state i.val)).snd)
∧ (iunfoldr f (state 0)).fst = state w := by
unfold iunfoldr
simp
apply Fin.hIterate_elim
(fun j (p : α × BitVec j) => (hj : j ≤ w) →
(∀ i : Fin j, getLsb p.snd i.val = (f ⟨i.val, Nat.lt_of_lt_of_le i.isLt hj⟩ (state i.val)).snd)
(∀ i : Fin j, getLsbD p.snd i.val = (f ⟨i.val, Nat.lt_of_lt_of_le i.isLt hj⟩ (state i.val)).snd)
∧ p.fst = state j)
case hj => simp
case init =>
@ -73,7 +73,7 @@ theorem iunfoldr_getLsb' {f : Fin w → αα × Bool} (state : Nat → α)
apply And.intro
case left =>
intro i
simp only [getLsb_cons]
simp only [getLsbD_cons]
have hj2 : j.val ≤ w := by simp
cases (Nat.lt_or_eq_of_le (Nat.lt_succ.mp i.isLt)) with
| inl h3 => simp [if_neg, (Nat.ne_of_lt h3)]
@ -90,10 +90,10 @@ theorem iunfoldr_getLsb' {f : Fin w → αα × Bool} (state : Nat → α)
rw [← ind j, ← (ih hj2).2]
theorem iunfoldr_getLsb {f : Fin w → αα × Bool} (state : Nat → α) (i : Fin w)
theorem iunfoldr_getLsbD {f : Fin w → αα × Bool} (state : Nat → α) (i : Fin w)
(ind : ∀(i : Fin w), (f i (state i.val)).fst = state (i.val+1)) :
getLsb (iunfoldr f (state 0)).snd i.val = (f i (state i.val)).snd := by
exact (iunfoldr_getLsb' state ind).1 i
getLsbD (iunfoldr f (state 0)).snd i.val = (f i (state i.val)).snd := by
exact (iunfoldr_getLsbD' state ind).1 i
/--
Correctness theorem for `iunfoldr`.
@ -101,14 +101,14 @@ Correctness theorem for `iunfoldr`.
theorem iunfoldr_replace
{f : Fin w → αα × Bool} (state : Nat → α) (value : BitVec w) (a : α)
(init : state 0 = a)
(step : ∀(i : Fin w), f i (state i.val) = (state (i.val+1), value.getLsb i.val)) :
(step : ∀(i : Fin w), f i (state i.val) = (state (i.val+1), value.getLsbD i.val)) :
iunfoldr f a = (state w, value) := by
simp [iunfoldr.eq_test state value a init step]
theorem iunfoldr_replace_snd
{f : Fin w → αα × Bool} (state : Nat → α) (value : BitVec w) (a : α)
(init : state 0 = a)
(step : ∀(i : Fin w), f i (state i.val) = (state (i.val+1), value.getLsb i.val)) :
(step : ∀(i : Fin w), f i (state i.val) = (state (i.val+1), value.getLsbD i.val)) :
(iunfoldr f a).snd = value := by
simp [iunfoldr.eq_test state value a init step]

File diff suppressed because it is too large Load diff

View file

@ -255,7 +255,7 @@ theorem get!_len_le [Inhabited α] : ∀ {l : List α} {n}, length l ≤ n → l
/-! ### getElem? and getElem -/
@[simp] theorem getElem?_eq_getElem {l : List α} {n} (h : n < l.length) : l[n]? = some l[n] := by
simp only [← get?_eq_getElem?, get?_eq_get, h, get_eq_getElem]
simp only [getElem?_def, h, ↓reduceDIte]
theorem getElem?_eq_some {l : List α} : l[n]? = some a ↔ ∃ h : n < l.length, l[n] = a := by
simp only [← get?_eq_getElem?, get?_eq_some, get_eq_getElem]

View file

@ -88,8 +88,8 @@ where
go : BVPred → Expr
| .bin (w := w) lhs op rhs =>
mkApp4 (mkConst ``BVPred.bin) (toExpr w) (toExpr lhs) (toExpr op) (toExpr rhs)
| .getLsb (w := w) expr idx =>
mkApp3 (mkConst ``BVPred.getLsb) (toExpr w) (toExpr expr) (toExpr idx)
| .getLsbD (w := w) expr idx =>
mkApp3 (mkConst ``BVPred.getLsbD) (toExpr w) (toExpr expr) (toExpr idx)
instance [ToExpr α] : ToExpr (BoolExpr α) where

View file

@ -46,16 +46,16 @@ def of (t : Expr) : M (Option ReifiedBVPred) := do
binaryReflection lhsExpr rhsExpr .eq ``Std.Tactic.BVDecide.Reflect.BitVec.beq_congr
| BitVec.ult _ lhsExpr rhsExpr =>
binaryReflection lhsExpr rhsExpr .ult ``Std.Tactic.BVDecide.Reflect.BitVec.ult_congr
| BitVec.getLsb _ subExpr idxExpr =>
| BitVec.getLsbD _ subExpr idxExpr =>
let some sub ← ReifiedBVExpr.of subExpr | return none
let some idx ← getNatValue? idxExpr | return none
let bvExpr : BVPred := .getLsb sub.bvExpr idx
let expr := mkApp3 (mkConst ``BVPred.getLsb) (toExpr sub.width) sub.expr idxExpr
let bvExpr : BVPred := .getLsbD sub.bvExpr idx
let expr := mkApp3 (mkConst ``BVPred.getLsbD) (toExpr sub.width) sub.expr idxExpr
let proof := do
let subEval ← ReifiedBVExpr.mkEvalExpr sub.width sub.expr
let subProof ← sub.evalsAtAtoms
return mkApp5
(mkConst ``Std.Tactic.BVDecide.Reflect.BitVec.getLsb_congr)
(mkConst ``Std.Tactic.BVDecide.Reflect.BitVec.getLsbD_congr)
idxExpr
(toExpr sub.width)
subExpr
@ -73,8 +73,8 @@ def of (t : Expr) : M (Option ReifiedBVPred) := do
let ty ← inferType t
let_expr Bool := ty | return none
let atom ← ReifiedBVExpr.mkAtom (mkApp (mkConst ``BitVec.ofBool) t) 1
let bvExpr : BVPred := .getLsb atom.bvExpr 0
let expr := mkApp3 (mkConst ``BVPred.getLsb) (toExpr 1) atom.expr (toExpr 0)
let bvExpr : BVPred := .getLsbD atom.bvExpr 0
let expr := mkApp3 (mkConst ``BVPred.getLsbD) (toExpr 1) atom.expr (toExpr 0)
let proof := do
let atomEval ← ReifiedBVExpr.mkEvalExpr atom.width atom.expr
let atomProof ← atom.evalsAtAtoms

View file

@ -154,9 +154,9 @@ builtin_dsimproc [simp, seval] reduceSDiv ((sdiv _ _ : BitVec _)) := reduceBin `
/-- Simplification procedure for signed division of `BitVec`s using the SMT-Lib conventions. -/
builtin_dsimproc [simp, seval] reduceSMTSDiv ((smtSDiv _ _ : BitVec _)) := reduceBin ``smtSDiv 3 smtSDiv
/-- Simplification procedure for `getLsb` (lowest significant bit) on `BitVec`. -/
builtin_dsimproc [simp, seval] reduceGetLsb (getLsb _ _) := reduceGetBit ``getLsb getLsb
builtin_dsimproc [simp, seval] reduceGetLsb (getLsbD _ _) := reduceGetBit ``getLsbD getLsbD
/-- Simplification procedure for `getMsb` (most significant bit) on `BitVec`. -/
builtin_dsimproc [simp, seval] reduceGetMsb (getMsb _ _) := reduceGetBit ``getMsb getMsb
builtin_dsimproc [simp, seval] reduceGetMsb (getMsbD _ _) := reduceGetBit ``getMsbD getMsbD
/-- Simplification procedure for shift left on `BitVec`. -/
builtin_dsimproc [simp, seval] reduceShiftLeft (BitVec.shiftLeft _ _) :=

View file

@ -375,7 +375,7 @@ inductive BVPred where
/--
Getting a constant LSB from a `BitVec`.
-/
| getLsb (expr : BVExpr w) (idx : Nat)
| getLsbD (expr : BVExpr w) (idx : Nat)
namespace BVPred
@ -389,7 +389,7 @@ structure ExprPair where
def toString : BVPred → String
| bin lhs op rhs => s!"({lhs.toString} {op.toString} {rhs.toString})"
| getLsb expr idx => s!"{expr.toString}[{idx}]"
| getLsbD expr idx => s!"{expr.toString}[{idx}]"
instance : ToString BVPred := ⟨toString⟩
@ -398,14 +398,14 @@ The semantics for `BVPred`.
-/
def eval (assign : BVExpr.Assignment) : BVPred → Bool
| bin lhs op rhs => op.eval (lhs.eval assign) (rhs.eval assign)
| getLsb expr idx => (expr.eval assign).getLsb idx
| getLsbD expr idx => (expr.eval assign).getLsbD idx
@[simp]
theorem eval_bin : eval assign (.bin lhs op rhs) = op.eval (lhs.eval assign) (rhs.eval assign) := by
rfl
@[simp]
theorem eval_getLsb : eval assign (.getLsb expr idx) = (expr.eval assign).getLsb idx := by
theorem eval_getLsbD : eval assign (.getLsbD expr idx) = (expr.eval assign).getLsbD idx := by
rfl
end BVPred

View file

@ -27,7 +27,7 @@ where
go (aig : AIG α) (val : BitVec w) (curr : Nat) (s : AIG.RefVec aig curr) (hcurr : curr ≤ w) :
AIG.RefVecEntry α w :=
if hcurr : curr < w then
let res := aig.mkConstCached (val.getLsb curr)
let res := aig.mkConstCached (val.getLsbD curr)
let aig := res.aig
let bitRef := res.ref
let s := s.cast <| AIG.LawfulOperator.le_size (f := AIG.mkConstCached) ..

View file

@ -8,7 +8,7 @@ import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Impl.Operations.Add
import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Impl.Operations.Append
import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Impl.Operations.Eq
import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Impl.Operations.Extract
import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Impl.Operations.GetLsb
import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Impl.Operations.GetLsbD
import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Impl.Operations.Mul
import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Impl.Operations.Not
import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Impl.Operations.Replicate

View file

@ -8,7 +8,7 @@ import Std.Sat.AIG.CachedGatesLemmas
import Std.Sat.AIG.RefVec
/-!
This module contains the implementation of a bitblaster for `BitVec.getLsb`.
This module contains the implementation of a bitblaster for `BitVec.getLsbD`.
-/
namespace Std.Tactic.BVDecide
@ -19,27 +19,27 @@ namespace BVPred
variable [Hashable α] [DecidableEq α]
structure GetLsbTarget (aig : AIG α) where
structure GetLsbDTarget (aig : AIG α) where
{w : Nat}
vec : AIG.RefVec aig w
idx : Nat
def blastGetLsb (aig : AIG α) (target : GetLsbTarget aig) : AIG.Entrypoint α :=
def blastGetLsbD (aig : AIG α) (target : GetLsbDTarget aig) : AIG.Entrypoint α :=
if h : target.idx < target.w then
⟨aig, target.vec.get target.idx h⟩
else
AIG.mkConstCached aig false
instance : AIG.LawfulOperator α GetLsbTarget blastGetLsb where
instance : AIG.LawfulOperator α GetLsbDTarget blastGetLsbD where
le_size := by
intros
unfold blastGetLsb
unfold blastGetLsbD
split
· simp
· apply AIG.LawfulOperator.le_size (f := AIG.mkConstCached)
decl_eq := by
intros
unfold blastGetLsb
unfold blastGetLsbD
split
· simp
· rw [AIG.LawfulOperator.decl_eq (f := AIG.mkConstCached)]

View file

@ -6,7 +6,7 @@ Authors: Henrik Böving
prelude
import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Impl.Operations.Eq
import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Impl.Operations.Ult
import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Impl.Operations.GetLsb
import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Impl.Operations.GetLsbD
import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Impl.Expr
/-!
@ -33,7 +33,7 @@ def bitblast (aig : AIG BVBit) (pred : BVPred) : AIG.Entrypoint BVBit :=
match op with
| .eq => mkEq aig ⟨lhsRefs, rhsRefs⟩
| .ult => mkUlt aig ⟨lhsRefs, rhsRefs⟩
| .getLsb expr idx =>
| .getLsbD expr idx =>
/-
Note: This blasts the entire expression up to `w` despite only needing it up to `idx`.
However the vast majority of operations are interested in all bits so the API is currently
@ -42,7 +42,7 @@ def bitblast (aig : AIG BVBit) (pred : BVPred) : AIG.Entrypoint BVBit :=
let res := expr.bitblast aig
let aig := res.aig
let refs := res.vec
blastGetLsb aig ⟨refs, idx⟩
blastGetLsbD aig ⟨refs, idx⟩
instance : AIG.LawfulOperator BVBit (fun _ => BVPred) bitblast where
le_size := by
@ -59,8 +59,8 @@ instance : AIG.LawfulOperator BVBit (fun _ => BVPred) bitblast where
apply AIG.LawfulOperator.le_size_of_le_aig_size (f := mkUlt)
apply AIG.LawfulVecOperator.le_size_of_le_aig_size (f := BVExpr.bitblast)
apply AIG.LawfulVecOperator.le_size (f := BVExpr.bitblast)
| getLsb expr idx =>
apply AIG.LawfulOperator.le_size_of_le_aig_size (f := blastGetLsb)
| getLsbD expr idx =>
apply AIG.LawfulOperator.le_size_of_le_aig_size (f := blastGetLsbD)
apply AIG.LawfulVecOperator.le_size (f := BVExpr.bitblast)
decl_eq := by
intro aig pred idx h1 h2
@ -87,9 +87,9 @@ instance : AIG.LawfulOperator BVBit (fun _ => BVPred) bitblast where
· apply AIG.LawfulVecOperator.lt_size_of_lt_aig_size (f := BVExpr.bitblast)
apply AIG.LawfulVecOperator.le_size_of_le_aig_size (f := BVExpr.bitblast)
assumption
| getLsb expr idx =>
| getLsbD expr idx =>
simp only [bitblast]
rw [AIG.LawfulOperator.decl_eq (f := blastGetLsb)]
rw [AIG.LawfulOperator.decl_eq (f := blastGetLsbD)]
rw [AIG.LawfulVecOperator.decl_eq (f := BVExpr.bitblast)]
apply AIG.LawfulVecOperator.lt_size_of_lt_aig_size (f := BVExpr.bitblast)
assumption

View file

@ -18,11 +18,11 @@ namespace Std.Tactic.BVDecide
namespace BVExpr
def Assignment.toAIGAssignment (assign : Assignment) : BVBit → Bool :=
fun bit => (assign.getD bit.var).bv.getLsb bit.idx
fun bit => (assign.getD bit.var).bv.getLsbD bit.idx
@[simp]
theorem Assignment.toAIGAssignment_apply (assign : Assignment) (bit : BVBit) :
assign.toAIGAssignment bit = (assign.getD bit.var).bv.getLsb bit.idx := by
assign.toAIGAssignment bit = (assign.getD bit.var).bv.getLsbD bit.idx := by
rfl
end BVExpr

View file

@ -26,8 +26,8 @@ namespace mkOverflowBit
theorem go_eq_carry (aig : AIG α) (curr : Nat) (hcurr : curr ≤ w) (cin : Ref aig) (origCin : Ref aig)
(lhs rhs : RefVec aig w) (lhsExpr rhsExpr : BitVec w) (assign : α → Bool)
(hleft : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, lhs.get idx hidx, assign⟧ = lhsExpr.getLsb idx)
(hright : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, rhs.get idx hidx, assign⟧ = rhsExpr.getLsb idx)
(hleft : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, lhs.get idx hidx, assign⟧ = lhsExpr.getLsbD idx)
(hright : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, rhs.get idx hidx, assign⟧ = rhsExpr.getLsbD idx)
(hcin : ⟦aig, cin, assign⟧ = BitVec.carry curr lhsExpr rhsExpr ⟦aig, origCin, assign⟧) :
⟦go aig lhs rhs curr hcurr cin, assign⟧
=
@ -59,8 +59,8 @@ end mkOverflowBit
theorem mkOverflowBit_eq_carry (aig : AIG α) (input : OverflowInput aig) (lhs rhs : BitVec input.w)
(assign : α → Bool)
(hleft : ∀ (idx : Nat) (hidx : idx < input.w), ⟦aig, input.vec.lhs.get idx hidx, assign⟧ = lhs.getLsb idx)
(hright : ∀ (idx : Nat) (hidx : idx < input.w), ⟦aig, input.vec.rhs.get idx hidx, assign⟧ = rhs.getLsb idx) :
(hleft : ∀ (idx : Nat) (hidx : idx < input.w), ⟦aig, input.vec.lhs.get idx hidx, assign⟧ = lhs.getLsbD idx)
(hright : ∀ (idx : Nat) (hidx : idx < input.w), ⟦aig, input.vec.rhs.get idx hidx, assign⟧ = rhs.getLsbD idx) :
⟦mkOverflowBit aig input, assign⟧
=
BitVec.carry input.w lhs rhs ⟦aig, input.cin, assign⟧ := by

View file

@ -87,7 +87,7 @@ theorem go_denote_eq (aig : AIG α) (c : BitVec w) (assign : α → Bool)
assign
=
c.getLsb idx := by
c.getLsbD idx := by
intro idx hidx1 hidx2
generalize hgo : go aig c curr s hcurr = res
unfold go at hgo
@ -117,7 +117,7 @@ theorem denote_blastConst (aig : AIG α) (c : BitVec w) (assign : α → Bool) :
∀ (idx : Nat) (hidx : idx < w),
⟦(blastConst aig c).aig, (blastConst aig c).vec.get idx hidx, assign⟧
=
c.getLsb idx := by
c.getLsbD idx := by
intros
apply blastConst.go_denote_eq
omega

View file

@ -58,7 +58,7 @@ theorem go_denote_eq (aig : AIG BVBit) (expr : BVExpr w) (assign : Assignment) :
∀ (idx : Nat) (hidx : idx < w),
⟦(go aig expr).val.aig, (go aig expr).val.vec.get idx hidx, assign.toAIGAssignment⟧
=
(expr.eval assign).getLsb idx := by
(expr.eval assign).getLsbD idx := by
intro idx hidx
induction expr generalizing aig idx with
| const =>
@ -67,13 +67,13 @@ 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.getLsb_zeroExtend, hidx, decide_True, Bool.true_and,
eval_zeroExtend, BitVec.getLsbD_zeroExtend, hidx, decide_True, Bool.true_and,
Bool.and_iff_right_iff_imp, decide_eq_true_eq]
apply BitVec.lt_of_getLsb
apply BitVec.lt_of_getLsbD
| append lhs rhs lih rih =>
rename_i lw rw
simp only [go, denote_blastAppend, RefVec.get_cast, Ref.cast_eq, eval_append,
BitVec.getLsb_append]
BitVec.getLsbD_append]
split
· next hsplit =>
simp only [hsplit, decide_True, cond_true]
@ -95,9 +95,9 @@ theorem go_denote_eq (aig : AIG BVBit) (expr : BVExpr w) (assign : Assignment) :
simp only [eval_signExtend]
rw [BitVec.signExtend_eq_not_zeroExtend_not_of_msb_false]
· simp only [denote_blastZeroExtend, ih, dite_eq_ite, Bool.if_false_right,
BitVec.getLsb_zeroExtend, hidx, decide_True, Bool.true_and, Bool.and_iff_right_iff_imp,
BitVec.getLsbD_zeroExtend, hidx, decide_True, Bool.true_and, Bool.and_iff_right_iff_imp,
decide_eq_true_eq]
apply BitVec.lt_of_getLsb
apply BitVec.lt_of_getLsbD
· subst heq
rw [BitVec.msb_zero_length]
· simp [heq]
@ -105,23 +105,23 @@ theorem go_denote_eq (aig : AIG BVBit) (expr : BVExpr w) (assign : Assignment) :
rw [← hgo]
rw [denote_blastSignExtend]
simp only [eval_signExtend]
rw [BitVec.getLsb_signExtend]
rw [BitVec.getLsbD_signExtend]
· simp only [hidx, decide_True, Bool.true_and]
split
· rw [ih]
· rw [BitVec.msb_eq_getLsb_last]
· rw [BitVec.msb_eq_getLsbD_last]
rw [ih]
· dsimp only; omega
| extract hi lo inner ih =>
simp only [go, denote_blastExtract, Bool.if_false_right, eval_extract,
BitVec.getLsb_extract]
BitVec.getLsbD_extract]
have : idx ≤ hi - lo := by omega
simp only [this, decide_True, Bool.true_and]
split
· next hsplit =>
rw [ih]
· apply Eq.symm
apply BitVec.getLsb_ge
apply BitVec.getLsbD_ge
omega
| shiftLeft lhs rhs lih rih =>
simp only [go, eval_shiftLeft]
@ -151,21 +151,21 @@ theorem go_denote_eq (aig : AIG BVBit) (expr : BVExpr w) (assign : Assignment) :
cases op with
| and =>
simp only [go, RefVec.denote_zip, denote_mkAndCached, rih, eval_bin, BVBinOp.eval_and,
BitVec.getLsb_and]
BitVec.getLsbD_and]
simp only [go_val_eq_bitblast, RefVec.get_cast]
rw [AIG.LawfulVecOperator.denote_input_vec (f := bitblast)]
rw [← go_val_eq_bitblast]
rw [lih]
| or =>
simp only [go, RefVec.denote_zip, denote_mkOrCached, rih, eval_bin, BVBinOp.eval_or,
BitVec.getLsb_or]
BitVec.getLsbD_or]
simp only [go_val_eq_bitblast, RefVec.get_cast]
rw [AIG.LawfulVecOperator.denote_input_vec (f := bitblast)]
rw [← go_val_eq_bitblast]
rw [lih]
| xor =>
simp only [go, RefVec.denote_zip, denote_mkXorCached, rih, eval_bin, BVBinOp.eval_xor,
BitVec.getLsb_xor]
BitVec.getLsbD_xor]
simp only [go_val_eq_bitblast, RefVec.get_cast]
rw [AIG.LawfulVecOperator.denote_input_vec (f := bitblast)]
rw [← go_val_eq_bitblast]
@ -200,17 +200,17 @@ theorem go_denote_eq (aig : AIG BVBit) (expr : BVExpr w) (assign : Assignment) :
| shiftLeftConst => simp [go, ih, hidx]
| shiftRightConst =>
simp only [go, denote_blastShiftRightConst, ih, dite_eq_ite, Bool.if_false_right, eval_un,
BVUnOp.eval_shiftRightConst, BitVec.getLsb_ushiftRight, Bool.and_iff_right_iff_imp,
BVUnOp.eval_shiftRightConst, BitVec.getLsbD_ushiftRight, Bool.and_iff_right_iff_imp,
decide_eq_true_eq]
intro h
apply BitVec.lt_of_getLsb
apply BitVec.lt_of_getLsbD
assumption
| rotateLeft => simp [go, ih, hidx]
| rotateRight => simp [go, ih, hidx]
| arithShiftRightConst n =>
rename_i w
have : ¬(w ≤ idx) := by omega
simp [go, ih, this, BitVec.getLsb_sshiftRight, BitVec.msb_eq_getLsb_last ]
simp [go, ih, this, BitVec.getLsbD_sshiftRight, BitVec.msb_eq_getLsbD_last ]
end bitblast
@ -219,7 +219,7 @@ theorem denote_bitblast (aig : AIG BVBit) (expr : BVExpr w) (assign : Assignment
∀ (idx : Nat) (hidx : idx < w),
⟦(bitblast aig expr).aig, (bitblast aig expr).vec.get idx hidx, assign.toAIGAssignment⟧
=
(expr.eval assign).getLsb idx
(expr.eval assign).getLsbD idx
:= by
intros
rw [← bitblast.go_val_eq_bitblast]

View file

@ -8,7 +8,7 @@ import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Lemmas.Operations.Add
import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Lemmas.Operations.Append
import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Lemmas.Operations.Eq
import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Lemmas.Operations.Extract
import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Lemmas.Operations.GetLsb
import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Lemmas.Operations.GetLsbD
import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Lemmas.Operations.Mul
import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Lemmas.Operations.Not
import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Lemmas.Operations.Replicate

View file

@ -144,8 +144,8 @@ theorem atLeastTwo_eq_halfAdder (lhsBit rhsBit carry : Bool) :
theorem go_denote_eq (aig : AIG α) (curr : Nat) (hcurr : curr ≤ w) (cin : Ref aig)
(s : AIG.RefVec aig curr) (lhs rhs : AIG.RefVec aig w) (assign : α → Bool)
(lhsExpr rhsExpr : BitVec w)
(hleft : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, lhs.get idx hidx, assign⟧ = lhsExpr.getLsb idx)
(hright : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, rhs.get idx hidx, assign⟧ = rhsExpr.getLsb idx)
(hleft : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, lhs.get idx hidx, assign⟧ = lhsExpr.getLsbD idx)
(hright : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, rhs.get idx hidx, assign⟧ = rhsExpr.getLsbD idx)
(hcin : ⟦aig, cin, assign⟧ = BitVec.carry curr lhsExpr rhsExpr false) :
∀ (idx : Nat) (hidx1 : idx < w),
curr ≤ idx
@ -211,14 +211,14 @@ end blastAdd
theorem denote_blastAdd (aig : AIG α) (lhs rhs : BitVec w) (assign : α → Bool)
(input : BinaryRefVec aig w)
(hleft : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, input.lhs.get idx hidx, assign⟧ = lhs.getLsb idx)
(hright : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, input.rhs.get idx hidx, assign⟧ = rhs.getLsb idx) :
(hleft : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, input.lhs.get idx hidx, assign⟧ = lhs.getLsbD idx)
(hright : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, input.rhs.get idx hidx, assign⟧ = rhs.getLsbD idx) :
∀ (idx : Nat) (hidx : idx < w),
⟦(blastAdd aig input).aig, (blastAdd aig input).vec.get idx hidx, assign⟧
=
(lhs + rhs).getLsb idx := by
(lhs + rhs).getLsbD idx := by
intro idx hidx
rw [BitVec.getLsb_add]
rw [BitVec.getLsbD_add]
· rw [← hleft idx hidx]
rw [← hright idx hidx]
unfold blastAdd

View file

@ -22,8 +22,8 @@ variable [Hashable α] [DecidableEq α]
theorem mkEq_denote_eq (aig : AIG α) (pair : AIG.BinaryRefVec aig w) (assign : α → Bool)
(lhs rhs : BitVec w)
(hleft : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, pair.lhs.get idx hidx, assign⟧ = lhs.getLsb idx)
(hright : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, pair.rhs.get idx hidx, assign⟧ = rhs.getLsb idx) :
(hleft : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, pair.lhs.get idx hidx, assign⟧ = lhs.getLsbD idx)
(hright : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, pair.rhs.get idx hidx, assign⟧ = rhs.getLsbD idx) :
⟦mkEq aig pair, assign⟧ = (lhs == rhs) := by
unfold mkEq
rw [Bool.eq_iff_iff]

View file

@ -5,7 +5,7 @@ Authors: Henrik Böving
-/
prelude
import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Lemmas.Basic
import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Impl.Operations.GetLsb
import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Impl.Operations.GetLsbD
/-!
This module contains the verification of the `BitVec.getLsb` bitblaster from `Impl.Operations.Extract`.
@ -21,16 +21,16 @@ namespace BVPred
variable [Hashable α] [DecidableEq α]
@[simp]
theorem denote_blastGetLsb (aig : AIG α) (target : GetLsbTarget aig)
theorem denote_blastGetLsbD (aig : AIG α) (target : GetLsbDTarget aig)
(assign : α → Bool) :
⟦blastGetLsb aig target, assign⟧
⟦blastGetLsbD aig target, assign⟧
=
if h : target.idx < target.w then
⟦aig, target.vec.get target.idx h, assign⟧
else
false := by
rcases target with ⟨expr, idx⟩
unfold blastGetLsb
unfold blastGetLsbD
dsimp only
split <;> simp

View file

@ -27,12 +27,12 @@ namespace blastMul
theorem go_denote_eq {w : Nat} (aig : AIG BVBit) (curr : Nat) (hcurr : curr + 1 ≤ w)
(acc : AIG.RefVec aig w) (lhs rhs : AIG.RefVec aig w) (lexpr rexpr : BitVec w) (assign : Assignment)
(hleft : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, lhs.get idx hidx, assign.toAIGAssignment⟧ = lexpr.getLsb idx)
(hright : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, rhs.get idx hidx, assign.toAIGAssignment⟧ = rexpr.getLsb idx)
(hleft : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, lhs.get idx hidx, assign.toAIGAssignment⟧ = lexpr.getLsbD idx)
(hright : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, rhs.get idx hidx, assign.toAIGAssignment⟧ = rexpr.getLsbD idx)
(hacc : ∀ (idx : Nat) (hidx : idx < w),
⟦aig, acc.get idx hidx, assign.toAIGAssignment⟧
=
(BitVec.mulRec lexpr rexpr curr).getLsb idx) :
(BitVec.mulRec lexpr rexpr curr).getLsbD idx) :
∀ (idx : Nat) (hidx : idx < w),
(go aig lhs rhs (curr + 1) hcurr acc).aig,
@ -40,7 +40,7 @@ theorem go_denote_eq {w : Nat} (aig : AIG BVBit) (curr : Nat) (hcurr : curr + 1
assign.toAIGAssignment
=
(BitVec.mulRec lexpr rexpr w).getLsb idx := by
(BitVec.mulRec lexpr rexpr w).getLsbD idx := by
intro idx hidx
generalize hgo: go aig lhs rhs (curr + 1) hcurr acc = res
unfold go at hgo
@ -65,7 +65,7 @@ theorem go_denote_eq {w : Nat} (aig : AIG BVBit) (curr : Nat) (hcurr : curr + 1
simp only [RefVec.denote_ite, RefVec.get_cast, Ref.cast_eq, BitVec.ofNat_eq_ofNat]
split
· next hdiscr =>
have : rexpr.getLsb (curr + 1) = true := by
have : rexpr.getLsbD (curr + 1) = true := by
rw [AIG.LawfulVecOperator.denote_mem_prefix (f := blastAdd)] at hdiscr
rw [AIG.LawfulVecOperator.denote_mem_prefix (f := blastShiftLeftConst)] at hdiscr
rw [hright] at hdiscr
@ -77,14 +77,14 @@ theorem go_denote_eq {w : Nat} (aig : AIG BVBit) (curr : Nat) (hcurr : curr + 1
rw [AIG.LawfulVecOperator.denote_mem_prefix (f := blastShiftLeftConst)]
rw [hacc]
· intros
simp only [denote_blastShiftLeftConst, BitVec.getLsb_shiftLeft]
simp only [denote_blastShiftLeftConst, BitVec.getLsbD_shiftLeft]
split
· next hdiscr => simp [hdiscr]
· next hidx hdiscr =>
rw [hleft]
simp [hdiscr, hidx]
· next hdiscr =>
have : rexpr.getLsb (curr + 1) = false := by
have : rexpr.getLsbD (curr + 1) = false := by
rw [AIG.LawfulVecOperator.denote_mem_prefix (f := blastAdd)] at hdiscr
rw [AIG.LawfulVecOperator.denote_mem_prefix (f := blastShiftLeftConst)] at hdiscr
rw [hright] at hdiscr
@ -98,8 +98,8 @@ theorem go_denote_eq {w : Nat} (aig : AIG BVBit) (curr : Nat) (hcurr : curr + 1
rw [← hgo]
rw [hacc]
rw [BitVec.mulRec_succ_eq]
have : rexpr.getLsb (curr + 1) = false := by
apply BitVec.getLsb_ge
have : rexpr.getLsbD (curr + 1) = false := by
apply BitVec.getLsbD_ge
omega
simp [this]
termination_by w - curr
@ -112,14 +112,14 @@ end blastMul
theorem denote_blastMul (aig : AIG BVBit) (lhs rhs : BitVec w) (assign : Assignment)
(input : BinaryRefVec aig w)
(hleft : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, input.lhs.get idx hidx, assign.toAIGAssignment⟧ = lhs.getLsb idx)
(hright : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, input.rhs.get idx hidx, assign.toAIGAssignment⟧ = rhs.getLsb idx) :
(hleft : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, input.lhs.get idx hidx, assign.toAIGAssignment⟧ = lhs.getLsbD idx)
(hright : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, input.rhs.get idx hidx, assign.toAIGAssignment⟧ = rhs.getLsbD idx) :
∀ (idx : Nat) (hidx : idx < w),
⟦(blastMul aig input).aig, (blastMul aig input).vec.get idx hidx, assign.toAIGAssignment⟧
=
(lhs * rhs).getLsb idx := by
(lhs * rhs).getLsbD idx := by
intro idx hidx
rw [BitVec.getLsb_mul]
rw [BitVec.getLsbD_mul]
generalize hb : blastMul aig input = res
unfold blastMul at hb
dsimp only at hb
@ -145,7 +145,7 @@ theorem denote_blastMul (aig : AIG BVBit) (lhs rhs : BitVec w) (assign : Assignm
rw [BitVec.mulRec_zero_eq]
simp only [Nat.succ_eq_add_one, RefVec.denote_ite, BinaryRefVec.rhs_get_cast,
Ref.gate_cast, BinaryRefVec.lhs_get_cast, denote_blastConst,
BitVec.ofNat_eq_ofNat, eval_const, BitVec.getLsb_zero, Bool.if_false_right,
BitVec.ofNat_eq_ofNat, eval_const, BitVec.getLsbD_zero, Bool.if_false_right,
Bool.decide_eq_true]
split
· next heq =>

View file

@ -173,8 +173,8 @@ namespace blastShiftLeft
theorem twoPowShift_eq (aig : AIG α) (target : TwoPowShiftTarget aig w) (lhs : BitVec w)
(rhs : BitVec target.n) (assign : α → Bool)
(hleft : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, target.lhs.get idx hidx, assign⟧ = lhs.getLsb idx)
(hright : ∀ (idx : Nat) (hidx : idx < target.n), ⟦aig, target.rhs.get idx hidx, assign⟧ = rhs.getLsb idx) :
(hleft : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, target.lhs.get idx hidx, assign⟧ = lhs.getLsbD idx)
(hright : ∀ (idx : Nat) (hidx : idx < target.n), ⟦aig, target.rhs.get idx hidx, assign⟧ = rhs.getLsbD idx) :
∀ (idx : Nat) (hidx : idx < w),
(twoPowShift aig target).aig,
@ -182,7 +182,7 @@ theorem twoPowShift_eq (aig : AIG α) (target : TwoPowShiftTarget aig w) (lhs :
assign
=
(lhs <<< (rhs &&& BitVec.twoPow target.n target.pow)).getLsb idx := by
(lhs <<< (rhs &&& BitVec.twoPow target.n target.pow)).getLsbD idx := by
intro idx hidx
generalize hg : twoPowShift aig target = res
rcases target with ⟨n, lvec, rvec, pow⟩
@ -202,14 +202,14 @@ theorem twoPowShift_eq (aig : AIG α) (target : TwoPowShiftTarget aig w) (lhs :
apply Nat.mod_eq_of_lt
apply Nat.pow_lt_pow_of_lt <;> omega
split
· simp only [BitVec.shiftLeft_eq', BitVec.toNat_twoPow, BitVec.getLsb_shiftLeft,
· simp only [BitVec.shiftLeft_eq', BitVec.toNat_twoPow, BitVec.getLsbD_shiftLeft,
Bool.false_eq, Bool.and_eq_false_imp, Bool.and_eq_true, decide_eq_true_eq,
Bool.not_eq_true', decide_eq_false_iff_not, Nat.not_lt, and_imp]
intros
apply BitVec.getLsb_ge
apply BitVec.getLsbD_ge
omega
· rw [hleft]
simp only [BitVec.shiftLeft_eq', BitVec.toNat_twoPow, hmod, BitVec.getLsb_shiftLeft, hidx,
simp only [BitVec.shiftLeft_eq', BitVec.toNat_twoPow, hmod, BitVec.getLsbD_shiftLeft, hidx,
decide_True, Bool.true_and, Bool.iff_and_self, Bool.not_eq_true', decide_eq_false_iff_not,
Nat.not_lt]
omega
@ -224,8 +224,8 @@ theorem twoPowShift_eq (aig : AIG α) (target : TwoPowShiftTarget aig w) (lhs :
rw [AIG.LawfulVecOperator.denote_mem_prefix (f := blastShiftLeftConst)]
rw [hleft]
simp
· have : rhs.getLsb pow = false := by
apply BitVec.getLsb_ge
· have : rhs.getLsbD pow = false := by
apply BitVec.getLsbD_ge
dsimp only
omega
simp only [this, Bool.false_eq_true, ↓reduceIte]
@ -236,8 +236,8 @@ theorem twoPowShift_eq (aig : AIG α) (target : TwoPowShiftTarget aig w) (lhs :
theorem go_denote_eq (aig : AIG α) (distance : AIG.RefVec aig n) (curr : Nat)
(hcurr : curr ≤ n - 1) (acc : AIG.RefVec aig w)
(lhs : BitVec w) (rhs : BitVec n) (assign : α → Bool)
(hacc : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, acc.get idx hidx, assign⟧ = (BitVec.shiftLeftRec lhs rhs curr).getLsb idx)
(hright : ∀ (idx : Nat) (hidx : idx < n), ⟦aig, distance.get idx hidx, assign⟧ = rhs.getLsb idx) :
(hacc : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, acc.get idx hidx, assign⟧ = (BitVec.shiftLeftRec lhs rhs curr).getLsbD idx)
(hright : ∀ (idx : Nat) (hidx : idx < n), ⟦aig, distance.get idx hidx, assign⟧ = rhs.getLsbD idx) :
∀ (idx : Nat) (hidx : idx < w),
(go aig distance curr hcurr acc).aig,
@ -245,7 +245,7 @@ theorem go_denote_eq (aig : AIG α) (distance : AIG.RefVec aig n) (curr : Nat)
assign
=
(BitVec.shiftLeftRec lhs rhs (n - 1)).getLsb idx := by
(BitVec.shiftLeftRec lhs rhs (n - 1)).getLsbD idx := by
intro idx hidx
generalize hgo : go aig distance curr hcurr acc = res
unfold go at hgo
@ -271,8 +271,8 @@ end blastShiftLeft
theorem denote_blastShiftLeft (aig : AIG α) (target : ArbitraryShiftTarget aig w0)
(lhs : BitVec w0) (rhs : BitVec target.n) (assign : α → Bool)
(hleft : ∀ (idx : Nat) (hidx : idx < w0), ⟦aig, target.target.get idx hidx, assign⟧ = lhs.getLsb idx)
(hright : ∀ (idx : Nat) (hidx : idx < target.n), ⟦aig, target.distance.get idx hidx, assign⟧ = rhs.getLsb idx) :
(hleft : ∀ (idx : Nat) (hidx : idx < w0), ⟦aig, target.target.get idx hidx, assign⟧ = lhs.getLsbD idx)
(hright : ∀ (idx : Nat) (hidx : idx < target.n), ⟦aig, target.distance.get idx hidx, assign⟧ = rhs.getLsbD idx) :
∀ (idx : Nat) (hidx : idx < w0),
(blastShiftLeft aig target).aig,
@ -280,7 +280,7 @@ theorem denote_blastShiftLeft (aig : AIG α) (target : ArbitraryShiftTarget aig
assign
=
(lhs <<< rhs).getLsb idx := by
(lhs <<< rhs).getLsbD idx := by
intro idx hidx
rw [BitVec.shiftLeft_eq_shiftLeftRec]
generalize hg : blastShiftLeft aig target = res
@ -293,10 +293,10 @@ theorem denote_blastShiftLeft (aig : AIG α) (target : ArbitraryShiftTarget aig
subst hzero
rw [← hg]
simp only [hleft, Nat.zero_sub, BitVec.shiftLeftRec_zero, BitVec.and_twoPow, Nat.le_refl,
BitVec.getLsb_ge, Bool.false_eq_true, ↓reduceIte, BitVec.reduceHShiftLeft',
BitVec.getLsb_shiftLeft, Nat.sub_zero, Bool.iff_and_self, Bool.and_eq_true, decide_eq_true_eq,
BitVec.getLsbD_ge, Bool.false_eq_true, ↓reduceIte, BitVec.reduceHShiftLeft',
BitVec.getLsbD_shiftLeft, Nat.sub_zero, Bool.iff_and_self, Bool.and_eq_true, decide_eq_true_eq,
Bool.not_eq_true', decide_eq_false_iff_not, Nat.not_lt, Nat.zero_le, and_true]
apply BitVec.lt_of_getLsb
apply BitVec.lt_of_getLsbD
· rw [← hg]
rw [blastShiftLeft.go_denote_eq]
· intro idx hidx

View file

@ -262,8 +262,8 @@ namespace blastShiftRight
theorem twoPowShift_eq (aig : AIG α) (target : TwoPowShiftTarget aig w) (lhs : BitVec w)
(rhs : BitVec target.n) (assign : α → Bool)
(hleft : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, target.lhs.get idx hidx, assign⟧ = lhs.getLsb idx)
(hright : ∀ (idx : Nat) (hidx : idx < target.n), ⟦aig, target.rhs.get idx hidx, assign⟧ = rhs.getLsb idx) :
(hleft : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, target.lhs.get idx hidx, assign⟧ = lhs.getLsbD idx)
(hright : ∀ (idx : Nat) (hidx : idx < target.n), ⟦aig, target.rhs.get idx hidx, assign⟧ = rhs.getLsbD idx) :
∀ (idx : Nat) (hidx : idx < w),
(twoPowShift aig target).aig,
@ -271,7 +271,7 @@ theorem twoPowShift_eq (aig : AIG α) (target : TwoPowShiftTarget aig w) (lhs :
assign
=
(lhs >>> (rhs &&& BitVec.twoPow target.n target.pow)).getLsb idx := by
(lhs >>> (rhs &&& BitVec.twoPow target.n target.pow)).getLsbD idx := by
intro idx hidx
generalize hg : twoPowShift aig target = res
rcases target with ⟨n, lvec, rvec, pow⟩
@ -293,9 +293,9 @@ theorem twoPowShift_eq (aig : AIG α) (target : TwoPowShiftTarget aig w) (lhs :
split
· rw [hleft]
simp [hmod]
· simp only [BitVec.ushiftRight_eq', BitVec.toNat_twoPow, BitVec.getLsb_ushiftRight,
· simp only [BitVec.ushiftRight_eq', BitVec.toNat_twoPow, BitVec.getLsbD_ushiftRight,
Bool.false_eq]
apply BitVec.getLsb_ge
apply BitVec.getLsbD_ge
omega
· next hif1 =>
simp only [Bool.not_eq_true] at hif1
@ -308,8 +308,8 @@ theorem twoPowShift_eq (aig : AIG α) (target : TwoPowShiftTarget aig w) (lhs :
rw [AIG.LawfulVecOperator.denote_mem_prefix (f := blastShiftRightConst)]
rw [hleft]
simp
· have : rhs.getLsb pow = false := by
apply BitVec.getLsb_ge
· have : rhs.getLsbD pow = false := by
apply BitVec.getLsbD_ge
dsimp only
omega
simp only [this, Bool.false_eq_true, ↓reduceIte]
@ -320,8 +320,8 @@ theorem twoPowShift_eq (aig : AIG α) (target : TwoPowShiftTarget aig w) (lhs :
theorem go_denote_eq (aig : AIG α) (distance : AIG.RefVec aig n) (curr : Nat)
(hcurr : curr ≤ n - 1) (acc : AIG.RefVec aig w)
(lhs : BitVec w) (rhs : BitVec n) (assign : α → Bool)
(hacc : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, acc.get idx hidx, assign⟧ = (BitVec.ushiftRightRec lhs rhs curr).getLsb idx)
(hright : ∀ (idx : Nat) (hidx : idx < n), ⟦aig, distance.get idx hidx, assign⟧ = rhs.getLsb idx) :
(hacc : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, acc.get idx hidx, assign⟧ = (BitVec.ushiftRightRec lhs rhs curr).getLsbD idx)
(hright : ∀ (idx : Nat) (hidx : idx < n), ⟦aig, distance.get idx hidx, assign⟧ = rhs.getLsbD idx) :
∀ (idx : Nat) (hidx : idx < w),
(go aig distance curr hcurr acc).aig,
@ -329,7 +329,7 @@ theorem go_denote_eq (aig : AIG α) (distance : AIG.RefVec aig n) (curr : Nat)
assign
=
(BitVec.ushiftRightRec lhs rhs (n - 1)).getLsb idx := by
(BitVec.ushiftRightRec lhs rhs (n - 1)).getLsbD idx := by
intro idx hidx
generalize hgo : go aig distance curr hcurr acc = res
unfold go at hgo
@ -355,8 +355,8 @@ end blastShiftRight
theorem denote_blastShiftRight (aig : AIG α) (target : ArbitraryShiftTarget aig w0)
(lhs : BitVec w0) (rhs : BitVec target.n) (assign : α → Bool)
(hleft : ∀ (idx : Nat) (hidx : idx < w0), ⟦aig, target.target.get idx hidx, assign⟧ = lhs.getLsb idx)
(hright : ∀ (idx : Nat) (hidx : idx < target.n), ⟦aig, target.distance.get idx hidx, assign⟧ = rhs.getLsb idx) :
(hleft : ∀ (idx : Nat) (hidx : idx < w0), ⟦aig, target.target.get idx hidx, assign⟧ = lhs.getLsbD idx)
(hright : ∀ (idx : Nat) (hidx : idx < target.n), ⟦aig, target.distance.get idx hidx, assign⟧ = rhs.getLsbD idx) :
∀ (idx : Nat) (hidx : idx < w0),
(blastShiftRight aig target).aig,
@ -364,7 +364,7 @@ theorem denote_blastShiftRight (aig : AIG α) (target : ArbitraryShiftTarget aig
assign
=
(lhs >>> rhs).getLsb idx := by
(lhs >>> rhs).getLsbD idx := by
intro idx hidx
rw [BitVec.shiftRight_eq_ushiftRightRec]
generalize hres : blastShiftRight aig target = res

View file

@ -24,8 +24,8 @@ variable [Hashable α] [DecidableEq α]
theorem mkUlt_denote_eq (aig : AIG α) (lhs rhs : BitVec w) (input : BinaryRefVec aig w)
(assign : α → Bool)
(hleft : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, input.lhs.get idx hidx, assign⟧ = lhs.getLsb idx)
(hright : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, input.rhs.get idx hidx, assign⟧ = rhs.getLsb idx) :
(hleft : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, input.lhs.get idx hidx, assign⟧ = lhs.getLsbD idx)
(hright : ∀ (idx : Nat) (hidx : idx < w), ⟦aig, input.rhs.get idx hidx, assign⟧ = rhs.getLsbD idx) :
⟦(mkUlt aig input).aig, (mkUlt aig input).ref, assign⟧ = BitVec.ult lhs rhs := by
rw [BitVec.ult_eq_not_carry]
unfold mkUlt
@ -42,7 +42,7 @@ theorem mkUlt_denote_eq (aig : AIG α) (lhs rhs : BitVec w) (input : BinaryRefVe
· dsimp only
intro idx hidx
rw [AIG.LawfulOperator.denote_mem_prefix (f := AIG.mkConstCached)]
· simp only [RefVec.get_cast, Ref.gate_cast, BitVec.getLsb_not, hidx, decide_True,
· simp only [RefVec.get_cast, Ref.gate_cast, BitVec.getLsbD_not, hidx, decide_True,
Bool.true_and]
rw [BVExpr.bitblast.denote_blastNot]
congr 1

View file

@ -6,7 +6,7 @@ Authors: Henrik Böving
prelude
import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Lemmas.Operations.Eq
import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Lemmas.Operations.Ult
import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Lemmas.Operations.GetLsb
import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Lemmas.Operations.GetLsbD
import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Lemmas.Expr
import Std.Tactic.BVDecide.Bitblast.BVExpr.Circuit.Impl.Pred
@ -48,10 +48,10 @@ theorem denote_bitblast (aig : AIG BVBit) (pred : BVPred) (assign : BVExpr.Assig
· simp [Ref.hgate]
· intros
simp
| getLsb expr idx =>
simp only [bitblast, denote_blastGetLsb, BVExpr.denote_bitblast, dite_eq_ite,
Bool.if_false_right, eval_getLsb, Bool.and_iff_right_iff_imp, decide_eq_true_eq]
apply BitVec.lt_of_getLsb
| getLsbD expr idx =>
simp only [bitblast, denote_blastGetLsbD, BVExpr.denote_bitblast, dite_eq_ite,
Bool.if_false_right, eval_getLsbD, Bool.and_iff_right_iff_imp, decide_eq_true_eq]
apply BitVec.lt_of_getLsbD
end BVPred

View file

@ -85,7 +85,7 @@ theorem go_denote_eq (aig : AIG BVBit) (a : Nat) (assign : Assignment) (curr : N
assign.toAIGAssignment
=
((BVExpr.var (w := w) a).eval assign).getLsb idx := by
((BVExpr.var (w := w) a).eval assign).getLsbD idx := by
intro idx hidx1 hidx2
generalize hgo : go aig w a curr s hcurr = res
unfold go at hgo
@ -118,7 +118,7 @@ theorem denote_blastVar (aig : AIG BVBit) (var : BVVar w) (assign : Assignment)
∀ (idx : Nat) (hidx : idx < w),
⟦(blastVar aig var).aig, (blastVar aig var).vec.get idx hidx, assign.toAIGAssignment⟧
=
((BVExpr.var (w := w) var.ident).eval assign).getLsb idx := by
((BVExpr.var (w := w) var.ident).eval assign).getLsbD idx := by
intros
apply blastVar.go_denote_eq
omega

View file

@ -34,7 +34,7 @@ attribute [bv_normalize] ge_iff_le
theorem BitVec.truncate_eq_zeroExtend (x : BitVec w) : x.truncate n = x.zeroExtend n := by
rfl
attribute [bv_normalize] BitVec.msb_eq_getLsb_last
attribute [bv_normalize] BitVec.msb_eq_getLsbD_last
attribute [bv_normalize] BitVec.slt_eq_ult
attribute [bv_normalize] BitVec.sle_eq_not_slt
@ -57,9 +57,9 @@ 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.getLsb_zero
attribute [bv_normalize] BitVec.getLsb_zero_length
attribute [bv_normalize] BitVec.getLsb_concat_zero
attribute [bv_normalize] BitVec.getLsbD_zero
attribute [bv_normalize] BitVec.getLsbD_zero_length
attribute [bv_normalize] BitVec.getLsbD_concat_zero
attribute [bv_normalize] BitVec.mul_one
attribute [bv_normalize] BitVec.one_mul
@ -123,12 +123,12 @@ theorem BitVec.neg_add (a : BitVec w) : (-a) + a = 0#w := by
@[bv_normalize]
theorem BitVec.zero_sshiftRight : BitVec.sshiftRight 0#w a = 0#w := by
ext
simp [BitVec.getLsb_sshiftRight]
simp [BitVec.getLsbD_sshiftRight]
@[bv_normalize]
theorem BitVec.sshiftRight_zero : BitVec.sshiftRight a 0 = a := by
ext
simp [BitVec.getLsb_sshiftRight]
simp [BitVec.getLsbD_sshiftRight]
@[bv_normalize]
theorem BitVec.mul_zero (a : BitVec w) : a * 0#w = 0#w := by

View file

@ -75,7 +75,7 @@ theorem Bool.decide_eq_true (a : Bool) : (decide (a = true)) = a := by
theorem Bool.eq_true_eq_true_eq (x y : Bool) : ((x = true) = (y = true)) = (x = y) :=
by simp
attribute [bv_normalize] BitVec.getLsb_cast
attribute [bv_normalize] BitVec.getLsbD_cast
attribute [bv_normalize] BitVec.testBit_toNat
@[bv_normalize]

View file

@ -103,11 +103,11 @@ theorem ult_congr (lhs rhs lhs' rhs' : BitVec w) (h1 : lhs' = lhs) (h2 : rhs' =
(BitVec.ult lhs' rhs') = (BitVec.ult lhs rhs) := by
simp[*]
theorem getLsb_congr (i : Nat) (w : Nat) (e e' : BitVec w) (h : e' = e) :
(e'.getLsb i) = (e.getLsb i) := by
theorem getLsbD_congr (i : Nat) (w : Nat) (e e' : BitVec w) (h : e' = e) :
(e'.getLsbD i) = (e.getLsbD i) := by
simp[*]
theorem ofBool_congr (b : Bool) (e' : BitVec 1) (h : e' = BitVec.ofBool b) : e'.getLsb 0 = b := by
theorem ofBool_congr (b : Bool) (e' : BitVec 1) (h : e' = BitVec.ofBool b) : e'.getLsbD 0 = b := by
cases b <;> simp [h]
end BitVec

View file

@ -30,21 +30,21 @@
"position": {"line": 9, "character": 11}},
"id": {"const": {"declName": "instToBoolBool"}}}},
{"sortText": "2",
"label": "BitVec.getLsb_ofBoolListBE",
"label": "BitVec.getLsbD_ofBoolListBE",
"kind": 3,
"data":
{"params":
{"textDocument": {"uri": "file:///completionPrv.lean"},
"position": {"line": 9, "character": 11}},
"id": {"const": {"declName": "BitVec.getLsb_ofBoolListBE"}}}},
"id": {"const": {"declName": "BitVec.getLsbD_ofBoolListBE"}}}},
{"sortText": "3",
"label": "BitVec.getMsb_ofBoolListBE",
"label": "BitVec.getMsbD_ofBoolListBE",
"kind": 3,
"data":
{"params":
{"textDocument": {"uri": "file:///completionPrv.lean"},
"position": {"line": 9, "character": 11}},
"id": {"const": {"declName": "BitVec.getMsb_ofBoolListBE"}}}},
"id": {"const": {"declName": "BitVec.getMsbD_ofBoolListBE"}}}},
{"sortText": "4",
"label": "BitVec.ofBoolListBE",
"kind": 3,

View file

@ -43,13 +43,13 @@ example (h : x = (1 : BitVec 32)) : x = - smtSDiv 9 0 := by
simp; guard_target =ₛ x = 1#32; assumption
example (h : x = (1 : BitVec 32)) : x = smtSDiv (-9) 0 := by
simp; guard_target =ₛ x = 1#32; assumption
example (h : x = false) : x = (4#3).getLsb 0:= by
example (h : x = false) : x = (4#3).getLsbD 0:= by
simp; guard_target =ₛ x = false; assumption
example (h : x = true) : x = (4#3).getLsb 2:= by
example (h : x = true) : x = (4#3).getLsbD 2:= by
simp; guard_target =ₛ x = true; assumption
example (h : x = true) : x = (4#3).getMsb 0:= by
example (h : x = true) : x = (4#3).getMsbD 0:= by
simp; guard_target =ₛ x = true; assumption
example (h : x = false) : x = (4#3).getMsb 2:= by
example (h : x = false) : x = (4#3).getMsbD 2:= by
simp; guard_target =ₛ x = false; assumption
example (h : x = (24 : BitVec 32)) : x = 6#32 <<< 2 := by
simp; guard_target =ₛ x = 24#32; assumption

View file

@ -14,16 +14,16 @@ theorem bitwise_unit_2 {x : BitVec 64} : x ^^^ x = 0 := by
theorem bitwise_unit_2' {x : BitVec 64} : (BitVec.xor x x) = 0 := by
bv_decide
theorem bitwise_unit_3 {x : BitVec 64} : (x ^^^ x).getLsb 32 = false := by
theorem bitwise_unit_3 {x : BitVec 64} : (x ^^^ x).getLsbD 32 = false := by
bv_decide
theorem bitwise_unit_4 {x : BitVec 64} : (x ^^^ ~~~x).getLsb 32 = true := by
theorem bitwise_unit_4 {x : BitVec 64} : (x ^^^ ~~~x).getLsbD 32 = true := by
bv_decide
theorem bitwise_unit_5 {x : BitVec 64} : (x ^^^ ~~~x).getLsb 128 = false := by
theorem bitwise_unit_5 {x : BitVec 64} : (x ^^^ ~~~x).getLsbD 128 = false := by
bv_decide
theorem bitwise_unit_6 {x : BitVec 64} : (x ^^^ ~~~x).getLsb 63 = (x ^^^ ~~~x).msb := by
theorem bitwise_unit_6 {x : BitVec 64} : (x ^^^ ~~~x).getLsbD 63 = (x ^^^ ~~~x).msb := by
bv_decide
theorem bitwise_unit_7 (x : BitVec 32) : x ^^^ 123#32 = 123#'(by decide) ^^^ x := by

View file

@ -35,5 +35,5 @@ theorem cast_unit_8 (x : BitVec 64) : (x.signExtend 128 = x.zeroExtend 128) ↔
theorem cast_unit_9 (x : BitVec 32) : (x.replicate 20).zeroExtend 32 = x := by
bv_decide
theorem cast_unit_10 (x : BitVec 32) : (x.replicate 20).getLsb 40 = x.getLsb 8 := by
theorem cast_unit_10 (x : BitVec 32) : (x.replicate 20).getLsbD 40 = x.getLsbD 8 := by
bv_decide

View file

@ -78,7 +78,7 @@ bool will_add_overflow_bitwise_3(int32_t a_, int32_t b_) {
-/
def will_add_overflow_bitwise_3 (a b : BitVec 32) : Bool :=
let c := a + b
getLsb (((~~~a &&& ~~~b &&& c) ||| (a &&& b &&& ~~~c)) >>> 31) 0
getLsbD (((~~~a &&& ~~~b &&& c) ||| (a &&& b &&& ~~~c)) >>> 31) 0
example (a b : BitVec 32) : will_add_overflow_bitwise_2 a b = will_add_overflow_bitwise_3 a b := by
dsimp [will_add_overflow_bitwise_2, will_add_overflow_bitwise_3]
@ -93,7 +93,7 @@ bool will_add_overflow_optimized_a(int32_t a_, int32_t b_) {
-/
def will_add_overflow_optimized_a (a b : BitVec 32) : Bool :=
let c := a + b
getLsb ((~~~(a ^^^ b) &&& (c ^^^ a)) >>> 31) 0
getLsbD ((~~~(a ^^^ b) &&& (c ^^^ a)) >>> 31) 0
example (a b : BitVec 32) :
will_add_overflow_bitwise_3 a b = will_add_overflow_optimized_a a b := by
@ -109,7 +109,7 @@ bool will_add_overflow_optimized_b(int32_t a_, int32_t b_) {
-/
def will_add_overflow_optimized_b (a b : BitVec 32) : Bool :=
let c := a + b
getLsb (((c ^^^ a) &&& (c ^^^ b)) >>> 31) 0
getLsbD (((c ^^^ a) &&& (c ^^^ b)) >>> 31) 0
example (a b : BitVec 32) :
will_add_overflow_optimized_a a b = will_add_overflow_optimized_b a b := by