softcore_prelude/
lib.rs

1#![allow(incomplete_features, non_camel_case_types)]
2
3use core::ops;
4use std::cmp::min;
5
6// NOTE: Ideally we would use unbounded integers for natural numbers. Yet in practice this would
7// mess up with things such as the SMT solver during symbolic execution.
8// After manual inspection, u128 are big enough for all the RISC-V use cases, so we keep that until
9// a better solution is needed.
10pub type nat = u128;
11
12pub fn sail_branch_announce(_value: i128, _pc: BitVector<64>) {}
13
14pub fn lteq_int(e1: i128, e2: i128) -> bool {
15    e1 <= e2
16}
17
18pub fn gt_int(e1: i128, e2: i128) -> bool {
19    e1 > e2
20}
21
22pub fn bitvector_length<const N: i128>(_e: BitVector<N>) -> i128 {
23    N
24}
25
26pub fn parse_hex_bits<const N: i128>(_n: i128, _hex_str: &str) -> BitVector<N> {
27    todo!("'parse_hex_bits' is not yet implemented");
28}
29
30pub fn bitvector_concat<const N: i128, const M: i128, const NM: i128>(
31    e1: BitVector<N>,
32    e2: BitVector<M>,
33) -> BitVector<{ NM }> {
34    bv::<{ NM }>((e1.bits() << M) | e2.bits())
35}
36
37pub const fn get_slice_int<const L: i128>(l: i128, n: i128, start: i128) -> BitVector<L> {
38    let val = (n >> start) & (mask128(l as usize) as i128);
39    bv(val as u64)
40}
41
42pub const fn slice<const N: i128, const M: i128>(
43    bits: BitVector<M>,
44    start: i128,
45    len: i128,
46) -> BitVector<N> {
47    let mask = mask(len as usize);
48    bv((bits.bits() >> start) & mask)
49}
50
51pub fn get_16_random_bits(_unit: ()) -> BitVector<16> {
52    bv::<16>(0)
53}
54
55pub fn not_implemented<T>(_any: T) -> ! {
56    panic!("Feature not implemented yet");
57}
58
59pub fn internal_error(_file: String, _line: i128, _s: String) -> ! {
60    panic!("Softcore: internal error")
61}
62
63pub fn print_output<const N: i128>(text: String, _csr: BitVector<N>) {
64    println!("{}", text)
65}
66
67pub fn print_platform(text: String) {
68    println!("{}", text)
69}
70
71pub fn bits_str<const N: i128>(val: BitVector<N>) -> String {
72    format!("{:b}", val.bits())
73}
74
75pub fn bitvector_access<const N: i128>(vec: BitVector<N>, idx: i128) -> bool {
76    (vec.bits() & (1 << idx)) > 0
77}
78
79// Todo: implement truncate for other sizes if required
80pub fn truncate(v: BitVector<64>, size: i128) -> BitVector<64> {
81    assert!(size == 64);
82    v
83}
84
85pub fn sail_sign_extend<const M: i128, const N: i128>(
86    input: BitVector<M>,
87    n: i128,
88) -> BitVector<N> {
89    assert!(n == N, "Mismatch `sail_sign_extend` size");
90    assert!(N >= M, "Cannot sign extend to smaller size");
91    assert!(N <= 64, "Maximum supported size is 64 for now");
92
93    // Special case: when extending from same size to same size, it's a no-op
94    if M == N {
95        return bv::<N>(input.bits());
96    }
97
98    // Check if the sign bit (MSB) is set
99    let sign_bit = (input.bits() >> (M - 1)) & 1;
100
101    if sign_bit == 0 {
102        // Positive number - just zero extend
103        bv::<N>(input.bits())
104    } else {
105        // Negative number - fill upper bits with 1s
106        // Handle the case where M=64 to avoid shift overflow
107        let mask = if M == 64 { 0u64 } else { (1u64 << M) - 1 };
108        let extension_bits = !mask & if N == 64 { u64::MAX } else { (1u64 << N) - 1 };
109        bv::<N>(input.bits() | extension_bits)
110    }
111}
112
113pub const fn sail_ones<const N: i128>(n: i128) -> BitVector<N> {
114    assert!(n <= 64);
115    bv::<N>(mask(n as usize))
116}
117
118pub const fn sail_zeros<const N: i128>(_n: i128) -> BitVector<N> {
119    bv::<N>(0)
120}
121
122pub const fn sail_shiftright<const N: i128>(bits: BitVector<N>, shift: i128) -> BitVector<N> {
123    bv(bits.bits() >> (shift as u64))
124}
125
126pub const fn sail_shiftleft<const N: i128>(bits: BitVector<N>, shift: i128) -> BitVector<N> {
127    bv(bits.bits() << (shift as u64))
128}
129
130pub fn min_int(v1: i128, v2: i128) -> i128 {
131    min(v1, v2)
132}
133
134pub fn cancel_reservation(_unit: ()) {
135    // In the future, extend this function
136}
137
138fn hex_bits<const N: i128>(bits: &str) -> BitVector<N> {
139    let parsed = bits.parse::<u64>().expect("Could not parse hex bits");
140    bv(parsed)
141}
142
143pub fn hex_bits_12_forwards(_reg: BitVector<12>) -> ! {
144    todo!("Implement this function")
145}
146
147pub fn hex_bits_12_backwards(bits: &str) -> BitVector<12> {
148    hex_bits(bits)
149}
150
151pub fn hex_bits_12_backwards_matches(bits: &str) -> bool {
152    match bits.parse::<u64>() {
153        Ok(n) => n < (1 << 12),
154        Err(_) => false,
155    }
156}
157
158pub fn subrange_bits<const IN: i128, const OUT: i128>(
159    vec: BitVector<IN>,
160    end: i128,
161    start: i128,
162) -> BitVector<OUT> {
163    assert_eq!((end - start + 1), OUT);
164    assert!(OUT <= IN);
165
166    bv((vec.bits >> start) & mask(OUT as usize))
167}
168
169pub fn update_subrange_bits<const N: i128, const M: i128>(
170    bits: BitVector<N>,
171    to: u64,
172    from: u64,
173    value: BitVector<M>,
174) -> BitVector<N> {
175    assert!(to - from + 1 == M as u64, "size don't match");
176
177    // Generate the 111111 mask
178    let mut mask = (1 << M) - 1;
179    // Shit and invert it
180    mask = !(mask << from);
181
182    // Now we can update and return the updated value
183    bv((bits.bits & mask) | (value.bits() << from))
184}
185
186pub fn bitvector_update<const N: i128>(v: BitVector<N>, pos: i128, value: bool) -> BitVector<N> {
187    let mask = 1 << pos;
188    bv((v.bits() & !mask) | (value as u64) << pos)
189}
190
191#[derive(Eq, PartialEq, Clone, Copy, Debug, Default)]
192pub struct BitVector<const N: i128> {
193    bits: u64,
194}
195
196#[derive(Eq, PartialEq, Clone, Copy, Debug, Default)]
197pub struct BitField<const T: i128> {
198    pub bits: BitVector<T>,
199}
200
201impl<const N: i128> BitField<N> {
202    pub const fn new(value: u64) -> Self {
203        BitField { bits: bv(value) }
204    }
205
206    pub const fn subrange<const A: i128, const B: i128, const C: i128>(self) -> BitVector<C> {
207        assert!(B - A == C, "Invalid subrange parameters");
208        assert!(B <= N, "Invalid subrange");
209
210        self.bits.subrange::<A, B, C>()
211    }
212
213    pub const fn set_subrange<const A: i128, const B: i128, const C: i128>(
214        self,
215        bitvector: BitVector<C>,
216    ) -> Self {
217        assert!(B - A == C, "Invalid subrange parameters");
218        assert!(A <= B && B <= N, "Invalid subrange");
219
220        BitField::<N> {
221            bits: self.bits.set_subrange::<A, B, C>(bitvector),
222        }
223    }
224}
225
226impl<const N: i128> PartialOrd for BitVector<N> {
227    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
228        self.bits.partial_cmp(&other.bits)
229    }
230}
231
232/// Create a fresh [BitVector].
233///
234/// This is equivalent to [BitVector::new], with a shorted syntax.
235pub const fn bv<const N: i128>(val: u64) -> BitVector<N> {
236    BitVector::new(val)
237}
238
239impl<const N: i128> BitVector<N> {
240    pub const fn new(val: u64) -> Self {
241        if N < 64 {
242            Self {
243                bits: val & ((1 << N) - 1),
244            }
245        } else {
246            Self { bits: val }
247        }
248    }
249
250    pub const fn new_empty() -> Self {
251        Self { bits: 0 }
252    }
253
254    pub const fn bits(self) -> u64 {
255        self.bits
256    }
257
258    /// Get the bits as an integer.
259    ///
260    /// The bitvector is interpreted as unsigned.
261    pub const fn unsigned(self) -> i128 {
262        // Note that bits is unsigned, so converting to a bigger i128 guarantees the result is
263        // still positive.
264        self.bits as i128
265    }
266
267    /// Get the bits as an integer.
268    ///
269    /// The bitvector is interpreted as signed
270    pub const fn signed(self) -> i128 {
271        let value = self.bits as u128;
272        let sign_bit_mask = 1 << (N - 1);
273        if value & sign_bit_mask == 0 {
274            // The number is positive, nothing to do
275            value as i128
276        } else {
277            // The number is negative, need to fill upper bits with 1s
278            let fill_mask = !((1 << N) - 1);
279            (value | fill_mask) as i128
280        }
281    }
282
283    pub const fn as_usize(self) -> usize {
284        self.bits as usize
285    }
286
287    pub const fn as_i128(self) -> i128 {
288        self.bits as i128
289    }
290
291    pub const fn zero_extend<const M: i128>(self) -> BitVector<M> {
292        assert!(M >= N, "Can not zero-extend to a smaller size!");
293        assert!(M <= 64, "Maximum zero-extend supported size if 64");
294
295        // Here we have nothing to do, we already use 64 bits with zeroes for MSBs
296        BitVector { bits: self.bits }
297    }
298
299    pub fn set_bit(self, idx: i128, value: bool) -> Self {
300        assert!(idx < N, "Out of bounds array check");
301        let new_value = if value {
302            self.bits | 1u64 << idx
303        } else {
304            self.bits & !(1u64 << idx)
305        };
306        BitVector { bits: new_value }
307    }
308
309    pub const fn subrange<const A: i128, const B: i128, const C: i128>(self) -> BitVector<C> {
310        assert!(B - A == C, "Invalid subrange parameters");
311        assert!(B <= N, "Invalid subrange");
312
313        let mut val = self.bits; // The current value
314        val &= BitVector::<B>::bit_mask(); // Remove top bits
315        val >>= A; // Shift all the bits
316        bv(val)
317    }
318
319    pub const fn set_subrange<const A: i128, const B: i128, const C: i128>(
320        self,
321        bits: BitVector<C>,
322    ) -> Self {
323        assert!(B - A == C, "Invalid set_subrange parameters");
324        assert!(B <= N, "Invalid subrange");
325
326        let mask = !(BitVector::<C>::bit_mask() << A);
327        let new_bits = bits.bits() << A;
328        bv((self.bits & mask) | new_bits)
329    }
330
331    pub const fn wrapped_add(self, other: BitVector<N>) -> BitVector<N> {
332        bv::<N>(self.bits.wrapping_add(other.bits))
333    }
334
335    /// Returns a bit mask with 1 for the first [N] bits.
336    const fn bit_mask() -> u64 {
337        assert!(N <= 64);
338
339        if N == 64 { u64::MAX } else { (1 << N) - 1 }
340    }
341}
342
343impl<const N: i128> ops::BitAnd for BitVector<N> {
344    type Output = Self;
345
346    fn bitand(self, rhs: Self) -> Self::Output {
347        Self {
348            bits: self.bits & rhs.bits,
349        }
350    }
351}
352
353impl<const N: i128> ops::BitOr for BitVector<N> {
354    type Output = Self;
355
356    fn bitor(self, rhs: Self) -> Self::Output {
357        Self {
358            bits: self.bits | rhs.bits,
359        }
360    }
361}
362
363impl<const N: i128> ops::BitXor for BitVector<N> {
364    type Output = Self;
365
366    fn bitxor(self, rhs: Self) -> Self::Output {
367        Self {
368            bits: self.bits ^ rhs.bits,
369        }
370    }
371}
372
373impl<const N: i128> ops::Shl<usize> for BitVector<N> {
374    type Output = Self;
375
376    fn shl(self, rhs: usize) -> Self::Output {
377        Self {
378            bits: self.bits << rhs,
379        }
380    }
381}
382
383impl<const N: i128> ops::Shl<i128> for BitVector<N> {
384    type Output = Self;
385
386    fn shl(self, rhs: i128) -> Self::Output {
387        Self {
388            bits: self.bits << rhs,
389        }
390    }
391}
392
393impl<const N: i128> ops::Shl<i32> for BitVector<N> {
394    type Output = Self;
395
396    fn shl(self, rhs: i32) -> Self::Output {
397        Self {
398            bits: self.bits << rhs,
399        }
400    }
401}
402
403impl<const N: i128> ops::Shr<usize> for BitVector<N> {
404    type Output = Self;
405
406    fn shr(self, rhs: usize) -> Self::Output {
407        Self {
408            bits: self.bits >> rhs,
409        }
410    }
411}
412
413impl<const N: i128> ops::Shr<i128> for BitVector<N> {
414    type Output = Self;
415
416    fn shr(self, rhs: i128) -> Self::Output {
417        Self {
418            bits: self.bits >> rhs,
419        }
420    }
421}
422
423impl<const N: i128> ops::Shr<i32> for BitVector<N> {
424    type Output = Self;
425
426    fn shr(self, rhs: i32) -> Self::Output {
427        Self {
428            bits: self.bits >> rhs,
429        }
430    }
431}
432
433impl<const N: i128> ops::Not for BitVector<N> {
434    type Output = Self;
435
436    fn not(self) -> Self::Output {
437        bv((!self.bits) & Self::bit_mask())
438    }
439}
440
441impl<const N: i128> std::ops::Add<i64> for BitVector<N> {
442    type Output = Self;
443
444    fn add(self, rhs: i64) -> BitVector<N> {
445        let result = self.bits as i64 + rhs;
446        // If the result is out of bounds, we may want to handle overflow
447        bv::<N>(result as u64) // Returning the result as BitVector
448    }
449}
450
451// ———————————————————————————————— Helpers ————————————————————————————————— //
452
453const fn mask(nb_ones: usize) -> u64 {
454    assert!(nb_ones <= 64, "Unsupported mask size");
455    if nb_ones == 64 {
456        u64::MAX
457    } else {
458        (1 << nb_ones) - 1
459    }
460}
461
462const fn mask128(nb_ones: usize) -> u128 {
463    assert!(nb_ones <= 128, "Unsupported mask size");
464    if nb_ones == 128 {
465        u128::MAX
466    } else {
467        (1 << nb_ones) - 1
468    }
469}
470
471// ————————————————————————————————— Tests —————————————————————————————————— //
472
473#[cfg(test)]
474mod tests {
475    use super::*;
476
477    #[test]
478    fn bitvec_masks() {
479        assert_eq!(BitVector::<0>::bit_mask(), 0b0);
480        assert_eq!(BitVector::<1>::bit_mask(), 0b1);
481        assert_eq!(BitVector::<2>::bit_mask(), 0b11);
482        assert_eq!(BitVector::<8>::bit_mask(), 0b11111111);
483        assert_eq!(BitVector::<64>::bit_mask(), 0xffffffffffffffff);
484    }
485
486    #[test]
487    fn bitvec_not() {
488        assert_eq!((!bv::<1>(0b1)).bits(), 0b0);
489        assert_eq!((!bv::<1>(0b0)).bits(), 0b1);
490        assert_eq!((!bv::<2>(0b01)).bits(), 0b10);
491        assert_eq!((!bv::<2>(0b11)).bits(), 0b00);
492    }
493
494    #[test]
495    fn subrange_bitvector() {
496        let v = bv::<32>(0b10110111);
497
498        assert_eq!(v.subrange::<0, 1, 1>().bits(), 0b1);
499        assert_eq!(v.subrange::<0, 2, 2>().bits(), 0b11);
500        assert_eq!(v.subrange::<0, 3, 3>().bits(), 0b111);
501        assert_eq!(v.subrange::<0, 4, 4>().bits(), 0b0111);
502        assert_eq!(v.subrange::<0, 5, 5>().bits(), 0b10111);
503
504        assert_eq!(v.subrange::<2, 3, 1>().bits(), 0b1);
505        assert_eq!(v.subrange::<2, 4, 2>().bits(), 0b01);
506        assert_eq!(v.subrange::<2, 5, 3>().bits(), 0b101);
507        assert_eq!(v.subrange::<2, 6, 4>().bits(), 0b1101);
508        assert_eq!(v.subrange::<2, 7, 5>().bits(), 0b01101);
509
510        assert_eq!(bv::<32>(0xffffffff).subrange::<7, 23, 16>().bits(), 0xffff);
511        assert_eq!(v.subrange::<2, 7, 5>().bits(), 0b01101);
512
513        let v = bv::<32>(0b10110111);
514        assert_eq!(v.set_subrange::<0, 1, 1>(bv(0b0)).bits(), 0b10110110);
515        assert_eq!(v.set_subrange::<0, 1, 1>(bv(0b1)).bits(), 0b10110111);
516        assert_eq!(v.set_subrange::<0, 2, 2>(bv(0b00)).bits(), 0b10110100);
517        assert_eq!(v.set_subrange::<2, 5, 3>(bv(0b010)).bits(), 0b10101011);
518
519        assert_eq!(
520            bv::<64>(0x0000000000000000).subrange::<60, 64, 4>().bits(),
521            0x0
522        );
523        assert_eq!(
524            bv::<64>(0xa000000000000000).subrange::<60, 64, 4>().bits(),
525            0xa
526        );
527        assert_eq!(
528            bv::<64>(0xb000000000000000).subrange::<60, 64, 4>().bits(),
529            0xb
530        );
531        assert_eq!(
532            bv::<64>(0xc000000000000000).subrange::<60, 64, 4>().bits(),
533            0xc
534        );
535        assert_eq!(
536            bv::<64>(0xd000000000000000).subrange::<60, 64, 4>().bits(),
537            0xd
538        );
539        assert_eq!(
540            bv::<64>(0xe000000000000000).subrange::<60, 64, 4>().bits(),
541            0xe
542        );
543        assert_eq!(
544            bv::<64>(0xf000000000000000).subrange::<60, 64, 4>().bits(),
545            0xf
546        );
547    }
548
549    // TODO: In the future squash with the previous function
550    #[test]
551    fn subrange_bitfield() {
552        let bitfield = BitField::<32>::new(0b10110111);
553
554        assert_eq!(bitfield.subrange::<0, 1, 1>().bits(), 0b1);
555        assert_eq!(bitfield.subrange::<0, 2, 2>().bits(), 0b11);
556        assert_eq!(bitfield.subrange::<0, 3, 3>().bits(), 0b111);
557        assert_eq!(bitfield.subrange::<0, 4, 4>().bits(), 0b0111);
558        assert_eq!(bitfield.subrange::<0, 5, 5>().bits(), 0b10111);
559
560        assert_eq!(bitfield.subrange::<2, 3, 1>().bits(), 0b1);
561        assert_eq!(bitfield.subrange::<2, 4, 2>().bits(), 0b01);
562        assert_eq!(bitfield.subrange::<2, 5, 3>().bits(), 0b101);
563        assert_eq!(bitfield.subrange::<2, 6, 4>().bits(), 0b1101);
564        assert_eq!(bitfield.subrange::<2, 7, 5>().bits(), 0b01101);
565
566        let v = bv::<32>(0b10110111);
567        assert_eq!(v.set_subrange::<0, 1, 1>(bv(0b0)).bits(), 0b10110110);
568        assert_eq!(v.set_subrange::<0, 1, 1>(bv(0b1)).bits(), 0b10110111);
569        assert_eq!(v.set_subrange::<0, 2, 2>(bv(0b00)).bits(), 0b10110100);
570        assert_eq!(v.set_subrange::<2, 5, 3>(bv(0b010)).bits(), 0b10101011);
571    }
572
573    #[test]
574    fn test_update_subrange_bits() {
575        assert_eq!(
576            update_subrange_bits(bv::<8>(0b11111100), 1, 0, bv::<2>(0b11)).bits,
577            0b11111111
578        );
579        assert_eq!(
580            update_subrange_bits(bv::<8>(0b00000000), 0, 0, bv::<1>(0b1)).bits,
581            0b00000001
582        );
583        assert_eq!(
584            update_subrange_bits(bv::<8>(0b00000000), 1, 1, bv::<1>(0b1)).bits,
585            0b00000010
586        );
587        assert_eq!(
588            update_subrange_bits(bv::<8>(0b00000000), 2, 2, bv::<1>(0b1)).bits,
589            0b00000100
590        );
591        assert_eq!(
592            update_subrange_bits(bv::<8>(0b00000000), 3, 3, bv::<1>(0b1)).bits,
593            0b00001000
594        );
595        assert_eq!(
596            update_subrange_bits(bv::<8>(0b00000000), 4, 4, bv::<1>(0b1)).bits,
597            0b00010000
598        );
599        assert_eq!(
600            update_subrange_bits(bv::<8>(0b00000000), 5, 5, bv::<1>(0b1)).bits,
601            0b00100000
602        );
603        assert_eq!(
604            update_subrange_bits(bv::<8>(0b00000000), 6, 6, bv::<1>(0b1)).bits,
605            0b01000000
606        );
607        assert_eq!(
608            update_subrange_bits(bv::<8>(0b00000000), 7, 7, bv::<1>(0b1)).bits,
609            0b10000000
610        );
611    }
612
613    #[test]
614    fn bitwise_operators() {
615        let v = bv::<32>(0b1);
616
617        assert_eq!(v, v | v);
618        assert_eq!(v, v & v);
619        assert_eq!(v, v ^ v ^ v);
620        assert_eq!(v, !!v);
621
622        for i in 0..30 {
623            assert_eq!(v, (v << (i as usize)) >> (i as usize));
624        }
625
626        // Test i32 shift operators
627        for i in 0i32..30i32 {
628            assert_eq!(v, (v << i) >> i);
629        }
630    }
631
632    #[test]
633    fn test_zero_extend() {
634        let v = bv::<8>(0b1010);
635
636        assert_eq!(v.bits, v.zero_extend::<16>().bits);
637        assert_eq!(v.bits, v.zero_extend::<63>().bits);
638        assert_eq!(v.bits, v.zero_extend::<64>().bits);
639    }
640
641    #[test]
642    fn test_bitvector_concat() {
643        const SIZE: i128 = 20;
644        const NEW_SIZE: i128 = 40;
645
646        for i in 0..(1 << (SIZE as usize)) {
647            let v = bv::<SIZE>(i);
648            assert_eq!(
649                bitvector_concat::<SIZE, SIZE, NEW_SIZE>(v, v).bits,
650                i + (i << (SIZE as usize))
651            );
652        }
653    }
654
655    #[test]
656    fn test_bitvector_access() {
657        const SIZE: i128 = 10;
658
659        for i in 0..(1 << (SIZE as usize)) {
660            let v = bv::<SIZE>(i);
661            for idx in 0..(SIZE as usize) {
662                assert_eq!((i & (1 << idx)) > 0, bitvector_access(v, idx as i128))
663            }
664        }
665    }
666
667    #[test]
668    fn test_set_bit() {
669        const SIZE: i128 = 60;
670
671        let mut v = bv::<SIZE>(0);
672        let mut val: u64 = 0;
673        for idx in 0..(SIZE as usize) {
674            val |= 1u64 << idx;
675            v = v.set_bit(idx as i128, true);
676
677            assert_eq!(v.bits, val);
678        }
679
680        for i in 0..(SIZE as usize) {
681            v = v.set_bit(i as i128, false);
682        }
683
684        assert_eq!(v.bits, 0);
685    }
686
687    #[test]
688    fn test_signed_interpretation() {
689        // Test 1-bit signed values
690        assert_eq!(bv::<1>(0b0).signed(), 0);
691        assert_eq!(bv::<1>(0b1).signed(), -1);
692
693        // Test 2-bit signed values
694        assert_eq!(bv::<2>(0b00).signed(), 0);
695        assert_eq!(bv::<2>(0b01).signed(), 1);
696        assert_eq!(bv::<2>(0b10).signed(), -2);
697        assert_eq!(bv::<2>(0b11).signed(), -1);
698
699        // Test 3-bit signed values
700        assert_eq!(bv::<3>(0b000).signed(), 0);
701        assert_eq!(bv::<3>(0b001).signed(), 1);
702        assert_eq!(bv::<3>(0b010).signed(), 2);
703        assert_eq!(bv::<3>(0b011).signed(), 3);
704        assert_eq!(bv::<3>(0b100).signed(), -4);
705        assert_eq!(bv::<3>(0b101).signed(), -3);
706        assert_eq!(bv::<3>(0b110).signed(), -2);
707        assert_eq!(bv::<3>(0b111).signed(), -1);
708
709        // Test 4-bit signed values
710        assert_eq!(bv::<4>(0b0000).signed(), 0);
711        assert_eq!(bv::<4>(0b0001).signed(), 1);
712        assert_eq!(bv::<4>(0b0111).signed(), 7);
713        assert_eq!(bv::<4>(0b1000).signed(), -8);
714        assert_eq!(bv::<4>(0b1001).signed(), -7);
715        assert_eq!(bv::<4>(0b1111).signed(), -1);
716
717        // Test 8-bit signed values
718        assert_eq!(bv::<8>(0x00).signed(), 0);
719        assert_eq!(bv::<8>(0x01).signed(), 1);
720        assert_eq!(bv::<8>(0x7F).signed(), 127);
721        assert_eq!(bv::<8>(0x80).signed(), -128);
722        assert_eq!(bv::<8>(0xFF).signed(), -1);
723
724        // Test 16-bit signed values
725        assert_eq!(bv::<16>(0x0000).signed(), 0);
726        assert_eq!(bv::<16>(0x0001).signed(), 1);
727        assert_eq!(bv::<16>(0x7FFF).signed(), 32767);
728        assert_eq!(bv::<16>(0x8000).signed(), -32768);
729        assert_eq!(bv::<16>(0xFFFF).signed(), -1);
730
731        // Test 32-bit signed values
732        assert_eq!(bv::<32>(0x00000000).signed(), 0);
733        assert_eq!(bv::<32>(0x00000001).signed(), 1);
734        assert_eq!(bv::<32>(0x7FFFFFFF).signed(), 2147483647);
735        assert_eq!(bv::<32>(0x80000000).signed(), -2147483648);
736        assert_eq!(bv::<32>(0xFFFFFFFF).signed(), -1);
737
738        // Test 64-bit signed values
739        assert_eq!(bv::<64>(0x0000000000000000).signed(), 0);
740        assert_eq!(bv::<64>(0x0000000000000001).signed(), 1);
741        assert_eq!(bv::<64>(0x7FFFFFFFFFFFFFFF).signed(), 9223372036854775807);
742        assert_eq!(bv::<64>(0x8000000000000000).signed(), -9223372036854775808);
743        assert_eq!(bv::<64>(0xFFFFFFFFFFFFFFFF).signed(), -1);
744    }
745
746    #[test]
747    fn test_signed_vs_unsigned() {
748        // Test that unsigned and signed give different results for negative values
749        let v = bv::<8>(0xFF);
750        assert_eq!(v.unsigned(), 255);
751        assert_eq!(v.signed(), -1);
752
753        let v = bv::<8>(0x80);
754        assert_eq!(v.unsigned(), 128);
755        assert_eq!(v.signed(), -128);
756
757        let v = bv::<16>(0x8000);
758        assert_eq!(v.unsigned(), 32768);
759        assert_eq!(v.signed(), -32768);
760
761        // Test that unsigned and signed give same results for positive values
762        let v = bv::<8>(0x7F);
763        assert_eq!(v.unsigned(), 127);
764        assert_eq!(v.signed(), 127);
765
766        let v = bv::<8>(0x00);
767        assert_eq!(v.unsigned(), 0);
768        assert_eq!(v.signed(), 0);
769    }
770
771    #[test]
772    fn test_sign_extend() {
773        // Test sign extending positive values from 4 to 8 bits
774        let input = bv::<4>(0b0111); // 7 in 4 bits
775        let result = sail_sign_extend::<4, 8>(input, 8);
776        assert_eq!(result.bits(), 0b00000111); // Should remain 7 in 8 bits
777
778        // Test sign extending negative values from 4 to 8 bits
779        let input = bv::<4>(0b1000); // -8 in 4 bits (two's complement)
780        let result = sail_sign_extend::<4, 8>(input, 8);
781        assert_eq!(result.bits(), 0b11111000); // Should become -8 in 8 bits
782
783        let input = bv::<4>(0b1111); // -1 in 4 bits
784        let result = sail_sign_extend::<4, 8>(input, 8);
785        assert_eq!(result.bits(), 0b11111111); // Should become -1 in 8 bits
786
787        // Test sign extending from 8 to 16 bits
788        let input = bv::<8>(0x7F); // 127 in 8 bits (positive)
789        let result = sail_sign_extend::<8, 16>(input, 16);
790        assert_eq!(result.bits(), 0x007F); // Should remain 127 in 16 bits
791
792        let input = bv::<8>(0x80); // -128 in 8 bits (negative)
793        let result = sail_sign_extend::<8, 16>(input, 16);
794        assert_eq!(result.bits(), 0xFF80); // Should become -128 in 16 bits
795
796        let input = bv::<8>(0xFF); // -1 in 8 bits
797        let result = sail_sign_extend::<8, 16>(input, 16);
798        assert_eq!(result.bits(), 0xFFFF); // Should become -1 in 16 bits
799
800        // Test sign extending from 16 to 32 bits
801        let input = bv::<16>(0x7FFF); // 32767 in 16 bits (positive)
802        let result = sail_sign_extend::<16, 32>(input, 32);
803        assert_eq!(result.bits(), 0x00007FFF); // Should remain 32767 in 32 bits
804
805        let input = bv::<16>(0x8000); // -32768 in 16 bits (negative)
806        let result = sail_sign_extend::<16, 32>(input, 32);
807        assert_eq!(result.bits(), 0xFFFF8000); // Should become -32768 in 32 bits
808
809        // Test sign extending from 32 to 64 bits
810        let input = bv::<32>(0x7FFFFFFF); // Positive value
811        let result = sail_sign_extend::<32, 64>(input, 64);
812        assert_eq!(result.bits(), 0x000000007FFFFFFF);
813
814        let input = bv::<32>(0x80000000); // Negative value
815        let result = sail_sign_extend::<32, 64>(input, 64);
816        assert_eq!(result.bits(), 0xFFFFFFFF80000000);
817
818        // Test edge cases - extending by 1 bit
819        let input = bv::<1>(0b0); // 0 in 1 bit
820        let result = sail_sign_extend::<1, 2>(input, 2);
821        assert_eq!(result.bits(), 0b00); // Should remain 0
822
823        let input = bv::<1>(0b1); // -1 in 1 bit
824        let result = sail_sign_extend::<1, 2>(input, 2);
825        assert_eq!(result.bits(), 0b11); // Should become -1 in 2 bits
826
827        // Test extending smaller values
828        let input = bv::<3>(0b101); // -3 in 3 bits
829        let result = sail_sign_extend::<3, 8>(input, 8);
830        assert_eq!(result.bits(), 0b11111101); // Should become -3 in 8 bits
831
832        let input = bv::<3>(0b011); // 3 in 3 bits
833        let result = sail_sign_extend::<3, 8>(input, 8);
834        assert_eq!(result.bits(), 0b00000011); // Should remain 3 in 8 bits
835
836        // Test extending from 64 to 64 bits (no-op, but widely used)
837        let input = bv::<64>(0x7FFFFFFFFFFFFFFF); // Maximum positive 64-bit value
838        let result = sail_sign_extend::<64, 64>(input, 64);
839        assert_eq!(result.bits(), 0x7FFFFFFFFFFFFFFF); // Should remain unchanged
840
841        let input = bv::<64>(0x8000000000000000); // Minimum negative 64-bit value
842        let result = sail_sign_extend::<64, 64>(input, 64);
843        assert_eq!(result.bits(), 0x8000000000000000); // Should remain unchanged
844
845        let input = bv::<64>(0xFFFFFFFFFFFFFFFF); // -1 in 64 bits
846        let result = sail_sign_extend::<64, 64>(input, 64);
847        assert_eq!(result.bits(), 0xFFFFFFFFFFFFFFFF); // Should remain unchanged
848
849        let input = bv::<64>(0x0000000000000000); // 0 in 64 bits
850        let result = sail_sign_extend::<64, 64>(input, 64);
851        assert_eq!(result.bits(), 0x0000000000000000); // Should remain unchanged
852    }
853}