Skip to content

Commit

Permalink
fix bug in slice implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
ekiwi committed Nov 28, 2023
1 parent 93318c0 commit 4e5e95d
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 11 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ num-bigint = "0.4.4"
num-traits = "0.2.17"
easy-smt = "0.2.1"
num-integer = "0.1.45"
rand = { version = "0.8.5", default-features = false }
rand_xoshiro = "0.6.0"

[dev-dependencies]
clap = { version = "4.4.8", features = ["derive"] }
Expand Down
43 changes: 32 additions & 11 deletions src/sim/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,18 @@ pub(crate) fn mask(bits: WidthInt) -> Word {
pub(crate) fn slice_to_word(source: &[Word], hi: WidthInt, lo: WidthInt) -> Word {
let lo_word = lo / Word::BITS;
let lo_offset = lo - (lo_word * Word::BITS);
let lo_index = source.len() - 1 - (lo_word as usize); // big endian
let hi_word = hi / Word::BITS;
let hi_offset = hi - (hi_word * Word::BITS);
let hi_index = source.len() - 1 - (hi_word as usize); // big endian

let lsb = source[lo_word as usize] >> lo_offset;
let lsb = source[lo_index] >> lo_offset;
if hi_word == lo_word {
let m = mask(hi - lo + 1);
lsb & m
} else {
let lo_width = Word::BITS - lo_offset;
let msb = source[hi_word as usize] & mask(hi_offset + 1);
let msb = source[hi_index] & mask(hi_offset + 1);
lsb | (msb << lo_width)
}
}
Expand Down Expand Up @@ -193,6 +195,8 @@ pub(crate) fn split_borrow_2(
#[cfg(test)]
mod tests {
use super::*;
use rand::Rng;
use rand_xoshiro::rand_core::SeedableRng;

fn from_bit_str(bits: &str) -> (Vec<Word>, WidthInt) {
let width = bits.len() as WidthInt;
Expand Down Expand Up @@ -286,6 +290,15 @@ mod tests {
assert_eq!(to_bit_str(&c_vec, c_width), c);
}

fn random_bit_str(width: WidthInt, rnd: &mut impl Rng) -> String {
let mut out = String::with_capacity(width as usize);
for _ in 0..width {
let cc = if rnd.gen_bool(0.5) { '1' } else { '0' };
out.push(cc);
}
out
}

fn do_test_concat(a: &str, b: &str) {
let (a_vec, a_width) = from_bit_str(a);
let (b_vec, b_width) = from_bit_str(b);
Expand All @@ -298,11 +311,9 @@ mod tests {

#[test]
fn test_concat() {
do_test_concat(
"10101010100000001010101010101000101010",
"10100001101000100000001010101010101000101010",
);
do_test_concat("10101010100000001010101010101000101010", "00101010");
let mut rng = rand_xoshiro::Xoshiro256PlusPlus::seed_from_u64(1);
do_test_concat(&random_bit_str(38, &mut rng), &random_bit_str(44, &mut rng));
do_test_concat(&random_bit_str(38, &mut rng), &random_bit_str(8, &mut rng));
}

fn do_test_slice(src: &str, hi: WidthInt, lo: WidthInt) {
Expand All @@ -322,9 +333,19 @@ mod tests {

#[test]
fn test_slice() {
do_test_slice("100010101010001", 0, 0);
do_test_slice("100010101010001", 1, 1);
do_test_slice("100010101010001", 6, 0);
do_test_slice("100010101010001", 6, 4);
let mut rng = rand_xoshiro::Xoshiro256PlusPlus::seed_from_u64(1);
let in0 = random_bit_str(15, &mut rng);
do_test_slice(&in0, 0, 0);
do_test_slice(&in0, 1, 1);
do_test_slice(&in0, 6, 0);
do_test_slice(&in0, 6, 4);

// test larger slices
let in1 = random_bit_str(1354, &mut rng);
do_test_slice(&in1, 400, 400); // 400 = 6 * 64 + 16
do_test_slice(&in1, 400, 400 - 20);
do_test_slice(&in1, 400 + 13, 400 - 20);
// result is larger than one word
// do_test_slice(&in1, 875, 875 - (Word::BITS * 2) - 15);
}
}

0 comments on commit 4e5e95d

Please sign in to comment.