Skip to content

Commit

Permalink
add missing bitvector ops
Browse files Browse the repository at this point in the history
  • Loading branch information
ekiwi committed May 30, 2024
1 parent 9c3ed54 commit 4db2152
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 99 deletions.
25 changes: 0 additions & 25 deletions src/arithmetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,22 +41,6 @@ pub(crate) fn assign(dst: &mut [Word], source: &[Word]) {
}
}

#[inline]
pub(crate) fn read_bool(source: &[Word]) -> bool {
word_to_bool(source[0])
}

#[inline]
pub(crate) fn assign_word(dst: &mut [Word], value: Word) {
// assign the lsb
dst[0] = value;

// zero extend
for other in dst.iter_mut().skip(1) {
*other = 0;
}
}

#[inline]
pub(crate) fn zero_extend(dst: &mut [Word], source: &[Word]) {
// copy source to dst
Expand Down Expand Up @@ -396,15 +380,6 @@ pub(crate) fn cmp_greater_equal_signed(a: &[Word], b: &[Word], width: WidthInt)
}
}

#[inline]
pub(crate) fn bool_to_word(value: bool) -> Word {
if value {
1
} else {
0
}
}

#[inline]
pub(crate) fn word_to_bool(value: Word) -> bool {
(value & 1) == 1
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use thiserror::Error;
#[derive(Debug, Error)]
pub enum Error {}

pub use ops::{BitVecMutOps, BitVecOps};
pub use ops::{ArrayMutOps, ArrayOps, BitVecMutOps, BitVecOps, DENSE_ARRAY_MAX_INDEX_WIDTH};
pub use value::borrowed::{BitVecValueMutRef, BitVecValueRef};
pub use value::indexed::{BitVecValueIndex, GetBitVecMutRef, GetBitVecRef};
pub use value::owned::BitVecValue;
pub use value::owned::{ArrayValue, BitVecValue};
179 changes: 109 additions & 70 deletions src/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,30 @@
//
// Traits for operations on bit-vectors.

use crate::value::owned::value_vec;
use crate::{BitVecValue, BitVecValueMutRef, BitVecValueRef, WidthInt, Word};
use smallvec::{smallvec, SmallVec};

/// Declares an arithmetic function which takes in two equal size bitvector and yields a
/// bitvector of the same size.
macro_rules! declare_arith_bin_fn {
($name:ident) => {
fn $name<R: BitVecOps>(&self, rhs: &R) -> BitVecValue {
debug_assert_eq!(self.width(), rhs.width());
debug_assert_eq!(self.words().len(), rhs.words().len());
if self.words().len() == 1 {
// specialized for 1-word case
let mut out = [0; 2];
crate::arithmetic::$name(
&mut out[0..1],
self.words(),
rhs.words(),
self.width(),
);
BitVecValue {
width: self.width(),
words: SmallVec::from_buf(out),
}
} else {
let mut out = smallvec![0; self.words().len()];
crate::arithmetic::$name(
out.as_mut(),
self.words(),
rhs.words(),
self.width(),
);
BitVecValue {
width: self.width(),
words: out,
debug_assert_eq!(self.width(), rhs.width());
debug_assert_eq!(self.words().len(), rhs.words().len());
let mut out = value_vec(self.width());
if self.words().len() == 1 {
// specialized for 1-word case
crate::arithmetic::$name(
&mut out[0..1],
&self.words()[0..1],
&rhs.words()[0..1],
self.width(),
);
} else {
crate::arithmetic::$name(&mut out, self.words(), rhs.words(), self.width());
}
BitVecValue::new(self.width(), out)
}
}
};
}

Expand All @@ -49,33 +36,17 @@ macro_rules! declare_arith_bin_fn {
macro_rules! declare_bit_arith_bin_fn {
($name:ident) => {
fn $name<R: BitVecOps>(&self, rhs: &R) -> BitVecValue {
debug_assert_eq!(self.width(), rhs.width());
debug_assert_eq!(self.words().len(), rhs.words().len());
if self.words().len() == 1 {
// specialized for 1-word case
let mut out = [0; 2];
crate::arithmetic::$name(
&mut out[0..1],
self.words(),
rhs.words(),
);
BitVecValue {
width: self.width(),
words: SmallVec::from_buf(out),
}
} else {
let mut out = smallvec![0; self.words().len()];
crate::arithmetic::$name(
out.as_mut(),
self.words(),
rhs.words(),
);
BitVecValue {
width: self.width(),
words: out,
debug_assert_eq!(self.width(), rhs.width());
debug_assert_eq!(self.words().len(), rhs.words().len());
let mut out = value_vec(self.width());
if self.words().len() == 1 {
// specialized for 1-word case
crate::arithmetic::$name(&mut out[0..1], &self.words()[0..1], &rhs.words()[0..1]);
} else {
crate::arithmetic::$name(&mut out, self.words(), rhs.words());
}
BitVecValue::new(self.width(), out)
}
}
};
}

Expand Down Expand Up @@ -167,6 +138,7 @@ pub trait BitVecOps {
declare_arith_bin_fn!(shift_left);
declare_arith_bin_fn!(shift_right);
declare_arith_bin_fn!(arithmetic_shift_right);
declare_arith_bin_fn!(mul);
declare_bit_arith_bin_fn!(and);
declare_bit_arith_bin_fn!(or);
declare_bit_arith_bin_fn!(xor);
Expand All @@ -191,7 +163,7 @@ pub trait BitVecOps {
debug_assert_eq!(self.words().len(), rhs.words().len());
if self.words().len() == 1 {
// specialized for 1-word case
crate::arithmetic::cmp_greater(self.words(), rhs.words())
crate::arithmetic::cmp_greater(&self.words()[0..1], &rhs.words()[0..1])
} else {
crate::arithmetic::cmp_greater(self.words(), rhs.words())
}
Expand All @@ -202,7 +174,7 @@ pub trait BitVecOps {
debug_assert_eq!(self.words().len(), rhs.words().len());
if self.words().len() == 1 {
// specialized for 1-word case
crate::arithmetic::cmp_greater_equal(self.words(), rhs.words())
crate::arithmetic::cmp_greater_equal(&self.words()[0..1], &rhs.words()[0..1])
} else {
crate::arithmetic::cmp_greater(self.words(), rhs.words())
}
Expand All @@ -223,7 +195,11 @@ pub trait BitVecOps {
debug_assert_eq!(self.words().len(), rhs.words().len());
if self.words().len() == 1 {
// specialized for 1-word case
crate::arithmetic::cmp_greater_signed(self.words(), rhs.words(), self.width())
crate::arithmetic::cmp_greater_signed(
&self.words()[0..1],
&rhs.words()[0..1],
self.width(),
)
} else {
crate::arithmetic::cmp_greater_signed(self.words(), rhs.words(), self.width())
}
Expand All @@ -234,7 +210,11 @@ pub trait BitVecOps {
debug_assert_eq!(self.words().len(), rhs.words().len());
if self.words().len() == 1 {
// specialized for 1-word case
crate::arithmetic::cmp_greater_equal_signed(self.words(), rhs.words(), self.width())
crate::arithmetic::cmp_greater_equal_signed(
&self.words()[0..1],
&rhs.words()[0..1],
self.width(),
)
} else {
crate::arithmetic::cmp_greater_equal_signed(self.words(), rhs.words(), self.width())
}
Expand All @@ -254,23 +234,82 @@ pub trait BitVecOps {
debug_assert!(msb <= self.width());
debug_assert!(msb >= lsb);
let out_width = msb - lsb + 1;
let out_words = out_width.div_ceil(Word::BITS);
if out_words == 1 {
let mut out = value_vec(out_width);
if out_width <= Word::BITS {
// specialized for 1-word case
let mut out = [0; 2];
crate::arithmetic::slice(&mut out[0..1], self.words(), msb, lsb);
BitVecValue {
width: out_width,
words: SmallVec::from_buf(out),
}
} else {
let mut out = smallvec![0; out_words as usize];
crate::arithmetic::slice(out.as_mut(), self.words(), msb, lsb);
BitVecValue {
width: out_width,
words: out,
}
crate::arithmetic::slice(&mut out, self.words(), msb, lsb);
}
BitVecValue::new(out_width, out)
}

fn sign_extend(&self, by: WidthInt) -> BitVecValue {
let out_width = self.width() + by;
let mut out = value_vec(out_width);
if out_width <= Word::BITS {
// specialized for 1-word case
crate::arithmetic::sign_extend(
&mut out[0..1],
&self.words()[0..1],
self.width(),
out_width,
);
} else {
crate::arithmetic::sign_extend(&mut out, self.words(), self.width(), out_width);
}
BitVecValue::new(out_width, out)
}

fn zero_extend(&self, by: WidthInt) -> BitVecValue {
let out_width = self.width() + by;
let mut out = value_vec(out_width);
if out_width <= Word::BITS {
// specialized for 1-word case
crate::arithmetic::zero_extend(&mut out[0..1], &self.words()[0..1]);
} else {
crate::arithmetic::zero_extend(&mut out, self.words());
}
BitVecValue::new(out_width, out)
}

fn not(&self) -> BitVecValue {
let mut out = value_vec(self.width());
if self.words().len() <= 1 {
// specialized for 1-word case
crate::arithmetic::not(&mut out[0..1], &self.words()[0..1], self.width());
} else {
crate::arithmetic::not(&mut out, self.words(), self.width());
}
BitVecValue::new(self.width(), out)
}

fn negate(&self) -> BitVecValue {
let mut out = value_vec(self.width());
if self.words().len() <= 1 {
// specialized for 1-word case
crate::arithmetic::negate(&mut out[0..1], &self.words()[0..1], self.width());
} else {
crate::arithmetic::negate(&mut out, self.words(), self.width());
}
BitVecValue::new(self.width(), out)
}

fn concat<R: BitVecOps + ?Sized>(&self, rhs: &R) -> BitVecValue {
let out_width = self.width() + rhs.width();
let mut out = value_vec(out_width);
if out_width <= Word::BITS {
// specialized for 1-word case
crate::arithmetic::concat(
&mut out[0..1],
&self.words()[0..1],
&rhs.words()[0..1],
rhs.width(),
);
} else {
crate::arithmetic::concat(&mut out, self.words(), rhs.words(), rhs.width());
}
BitVecValue::new(out_width, out)
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/value/indexed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
// Access a slice of `Word` as a bit-vector.

use super::borrowed::{BitVecValueMutRef, BitVecValueRef};
use crate::ops::{ArrayMutOps, ArrayOps};
use crate::{BitVecOps, WidthInt, Word};
use std::collections::HashMap;

Expand Down Expand Up @@ -359,6 +358,7 @@ mod tests {
assert_eq!(BitVecValue::from_big_int(value, width), v0);
}

#[allow(unused)]
fn gen_big_int_and_width() -> impl Strategy<Value = (BigInt, WidthInt)> {
let max_bits = 16 * Word::BITS;
(1..max_bits)
Expand Down
5 changes: 5 additions & 0 deletions src/value/owned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ impl BitVecValue {
crate::io::fraction::from_fixed_point(value, bits, fraction_width, &mut words);
Self { width: bits, words }
}

/// Raw constructor for internal use.
pub(crate) fn new(width: WidthInt, words: ValueVec) -> Self {
Self { width, words }
}
}

/// Owned dense bit-vector array.
Expand Down
2 changes: 1 addition & 1 deletion tests/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
// released under BSD 3-Clause License
// author: Kevin Laeufer <laeufer@berkeley.edu>

use proptest::proptest;
// use proptest::proptest;

// TODO

0 comments on commit 4db2152

Please sign in to comment.