1use xlsynth_sys::{CIrBits, CIrValue};
4
5use crate::{
6 lib_support::{
7 xls_bits_make_sbits, xls_bits_make_ubits, xls_bits_to_debug_str, xls_bits_to_string,
8 xls_format_preference_from_string, xls_value_eq, xls_value_free, xls_value_get_bits,
9 xls_value_get_element, xls_value_get_element_count, xls_value_make_array,
10 xls_value_make_sbits, xls_value_make_tuple, xls_value_make_ubits, xls_value_to_string,
11 xls_value_to_string_format_preference,
12 },
13 xls_parse_typed_value,
14 xlsynth_error::XlsynthError,
15};
16
17pub struct IrBits {
18 #[allow(dead_code)]
19 pub(crate) ptr: *mut CIrBits,
20}
21
22impl IrBits {
23 pub fn make_ubits(bit_count: usize, value: u64) -> Result<Self, XlsynthError> {
24 xls_bits_make_ubits(bit_count, value)
25 }
26
27 pub fn make_sbits(bit_count: usize, value: i64) -> Result<Self, XlsynthError> {
28 xls_bits_make_sbits(bit_count, value)
29 }
30
31 pub fn get_bit_count(&self) -> usize {
32 let bit_count = unsafe { xlsynth_sys::xls_bits_get_bit_count(self.ptr) };
33 assert!(bit_count >= 0);
34 bit_count as usize
35 }
36
37 pub fn to_debug_str(&self) -> String {
38 xls_bits_to_debug_str(self.ptr)
39 }
40
41 pub fn get_bit(&self, index: usize) -> Result<bool, XlsynthError> {
42 if self.get_bit_count() <= index {
43 return Err(XlsynthError(format!(
44 "Index {} out of bounds for bits[{}]:{}",
45 index,
46 self.get_bit_count(),
47 self.to_debug_str()
48 )));
49 }
50 let bit = unsafe { xlsynth_sys::xls_bits_get_bit(self.ptr, index as i64) };
51 Ok(bit)
52 }
53
54 pub fn to_string_fmt(&self, format: IrFormatPreference, include_bit_count: bool) -> String {
55 let fmt_pref: xlsynth_sys::XlsFormatPreference =
56 xls_format_preference_from_string(format.to_string()).unwrap();
57 xls_bits_to_string(self.ptr, fmt_pref, include_bit_count).unwrap()
58 }
59
60 #[allow(dead_code)]
61 fn to_hex_string(&self) -> String {
62 let value = self.to_string_fmt(IrFormatPreference::Hex, false);
63 format!("bits[{}]:{}", self.get_bit_count(), value)
64 }
65
66 pub fn umul(&self, rhs: &IrBits) -> IrBits {
67 let result = unsafe { xlsynth_sys::xls_bits_umul(self.ptr, rhs.ptr) };
68 IrBits { ptr: result }
69 }
70
71 pub fn smul(&self, rhs: &IrBits) -> IrBits {
72 let result = unsafe { xlsynth_sys::xls_bits_smul(self.ptr, rhs.ptr) };
73 IrBits { ptr: result }
74 }
75
76 pub fn negate(&self) -> IrBits {
77 let result = unsafe { xlsynth_sys::xls_bits_negate(self.ptr) };
78 IrBits { ptr: result }
79 }
80
81 pub fn abs(&self) -> IrBits {
82 let result = unsafe { xlsynth_sys::xls_bits_abs(self.ptr) };
83 IrBits { ptr: result }
84 }
85
86 pub fn msb(&self) -> bool {
87 self.get_bit(self.get_bit_count() - 1).unwrap()
88 }
89
90 pub fn shll(&self, shift_amount: i64) -> IrBits {
91 let result = unsafe { xlsynth_sys::xls_bits_shift_left_logical(self.ptr, shift_amount) };
92 IrBits { ptr: result }
93 }
94
95 pub fn shrl(&self, shift_amount: i64) -> IrBits {
96 let result = unsafe { xlsynth_sys::xls_bits_shift_right_logical(self.ptr, shift_amount) };
97 IrBits { ptr: result }
98 }
99
100 pub fn shra(&self, shift_amount: i64) -> IrBits {
101 let result =
102 unsafe { xlsynth_sys::xls_bits_shift_right_arithmetic(self.ptr, shift_amount) };
103 IrBits { ptr: result }
104 }
105
106 pub fn width_slice(&self, start: i64, width: i64) -> IrBits {
107 let result = unsafe { xlsynth_sys::xls_bits_width_slice(self.ptr, start, width) };
108 IrBits { ptr: result }
109 }
110
111 pub fn not(&self) -> IrBits {
112 let result = unsafe { xlsynth_sys::xls_bits_not(self.ptr) };
113 IrBits { ptr: result }
114 }
115
116 pub fn and(&self, rhs: &IrBits) -> IrBits {
117 let result = unsafe { xlsynth_sys::xls_bits_and(self.ptr, rhs.ptr) };
118 IrBits { ptr: result }
119 }
120
121 pub fn or(&self, rhs: &IrBits) -> IrBits {
122 let result = unsafe { xlsynth_sys::xls_bits_or(self.ptr, rhs.ptr) };
123 IrBits { ptr: result }
124 }
125
126 pub fn xor(&self, rhs: &IrBits) -> IrBits {
127 let result = unsafe { xlsynth_sys::xls_bits_xor(self.ptr, rhs.ptr) };
128 IrBits { ptr: result }
129 }
130}
131
132impl Drop for IrBits {
133 fn drop(&mut self) {
134 unsafe { xlsynth_sys::xls_bits_free(self.ptr) }
135 }
136}
137
138impl std::cmp::PartialEq for IrBits {
139 fn eq(&self, other: &Self) -> bool {
140 unsafe { xlsynth_sys::xls_bits_eq(self.ptr, other.ptr) }
141 }
142}
143
144impl std::fmt::Debug for IrBits {
145 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
146 write!(f, "{}", self.to_debug_str())
147 }
148}
149
150impl From<&IrBits> for IrValue {
151 fn from(bits: &IrBits) -> Self {
152 IrValue::from_bits(bits)
153 }
154}
155
156impl std::fmt::Display for IrBits {
157 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
158 write!(
159 f,
160 "bits[{}]:{}",
161 self.get_bit_count(),
162 self.to_string_fmt(IrFormatPreference::Default, false)
163 )
164 }
165}
166
167impl std::ops::Add for IrBits {
168 type Output = Self;
169
170 fn add(self, rhs: Self) -> Self::Output {
171 let result = unsafe { xlsynth_sys::xls_bits_add(self.ptr, rhs.ptr) };
172 Self { ptr: result }
173 }
174}
175
176impl std::ops::BitAnd for IrBits {
177 type Output = Self;
178
179 fn bitand(self, rhs: Self) -> Self::Output {
180 let result = unsafe { xlsynth_sys::xls_bits_and(self.ptr, rhs.ptr) };
181 Self { ptr: result }
182 }
183}
184
185impl std::ops::BitOr for IrBits {
186 type Output = Self;
187
188 fn bitor(self, rhs: Self) -> Self::Output {
189 IrBits::or(&self, &rhs)
190 }
191}
192
193impl std::ops::BitXor for IrBits {
194 type Output = Self;
195
196 fn bitxor(self, rhs: Self) -> Self::Output {
197 IrBits::xor(&self, &rhs)
198 }
199}
200
201impl std::ops::Not for IrBits {
202 type Output = Self;
203
204 fn not(self) -> Self::Output {
205 IrBits::not(&self)
206 }
207}
208
209pub enum IrFormatPreference {
212 Default,
213 Binary,
214 SignedDecimal,
215 UnsignedDecimal,
216 Hex,
217 PlainBinary,
218 ZeroPaddedBinary,
219 PlainHex,
220 ZeroPaddedHex,
221}
222
223impl IrFormatPreference {
224 pub fn to_string(&self) -> &'static str {
225 match self {
226 IrFormatPreference::Default => "default",
227 IrFormatPreference::Binary => "binary",
228 IrFormatPreference::SignedDecimal => "signed_decimal",
229 IrFormatPreference::UnsignedDecimal => "unsigned_decimal",
230 IrFormatPreference::Hex => "hex",
231 IrFormatPreference::PlainBinary => "plain_binary",
232 IrFormatPreference::ZeroPaddedBinary => "zero_padded_binary",
233 IrFormatPreference::PlainHex => "plain_hex",
234 IrFormatPreference::ZeroPaddedHex => "zero_padded_hex",
235 }
236 }
237}
238
239pub struct IrValue {
240 pub(crate) ptr: *mut CIrValue,
241}
242
243impl IrValue {
244 pub fn make_tuple(elements: &[IrValue]) -> Self {
245 xls_value_make_tuple(elements)
246 }
247
248 pub fn make_array(elements: &[IrValue]) -> Result<Self, XlsynthError> {
250 xls_value_make_array(elements)
251 }
252
253 pub fn from_bits(bits: &IrBits) -> Self {
254 let ptr = unsafe { xlsynth_sys::xls_value_from_bits(bits.ptr) };
255 Self { ptr }
256 }
257
258 pub fn parse_typed(s: &str) -> Result<Self, XlsynthError> {
259 xls_parse_typed_value(s)
260 }
261
262 pub fn bool(value: bool) -> Self {
263 xls_value_make_ubits(value as u64, 1).unwrap()
264 }
265
266 pub fn u32(value: u32) -> Self {
267 xls_value_make_ubits(value as u64, 32).unwrap()
269 }
270
271 pub fn u64(value: u64) -> Self {
272 xls_value_make_ubits(value as u64, 64).unwrap()
274 }
275
276 pub fn make_ubits(bit_count: usize, value: u64) -> Result<Self, XlsynthError> {
277 xls_value_make_ubits(value as u64, bit_count)
278 }
279
280 pub fn make_sbits(bit_count: usize, value: i64) -> Result<Self, XlsynthError> {
281 xls_value_make_sbits(value, bit_count)
282 }
283
284 pub fn bit_count(&self) -> Result<usize, XlsynthError> {
285 let bits = self.to_bits()?;
287 Ok(bits.get_bit_count())
288 }
289
290 pub fn to_string_fmt(&self, format: IrFormatPreference) -> Result<String, XlsynthError> {
291 let fmt_pref: xlsynth_sys::XlsFormatPreference =
292 xls_format_preference_from_string(format.to_string())?;
293 xls_value_to_string_format_preference(self.ptr, fmt_pref)
294 }
295
296 pub fn to_string_fmt_no_prefix(
297 &self,
298 format: IrFormatPreference,
299 ) -> Result<String, XlsynthError> {
300 let s = self.to_string_fmt(format)?;
301 if s.starts_with("bits[") {
302 let parts: Vec<&str> = s.split(':').collect();
303 Ok(parts[1].to_string())
304 } else {
305 Ok(s)
306 }
307 }
308
309 pub fn to_bool(&self) -> Result<bool, XlsynthError> {
310 let bits = self.to_bits()?;
311 if bits.get_bit_count() != 1 {
312 return Err(XlsynthError(format!(
313 "IrValue {} is not single-bit; must be bits[1] to convert to bool",
314 self.to_string()
315 )));
316 }
317 bits.get_bit(0)
318 }
319
320 pub fn to_i64(&self) -> Result<i64, XlsynthError> {
321 let string = self.to_string_fmt(IrFormatPreference::SignedDecimal)?;
322 let number = string.split(':').nth(1).expect("split success");
323 match number.parse::<i64>() {
324 Ok(i) => Ok(i),
325 Err(e) => Err(XlsynthError(format!(
326 "IrValue::to_i64() failed to parse i64 from string: {}",
327 e
328 ))),
329 }
330 }
331
332 pub fn to_u64(&self) -> Result<u64, XlsynthError> {
333 let string = self.to_string_fmt(IrFormatPreference::UnsignedDecimal)?;
334 let number = string.split(':').nth(1).expect("split success");
335 match number.parse::<u64>() {
336 Ok(i) => Ok(i),
337 Err(e) => Err(XlsynthError(format!(
338 "IrValue::to_u64() failed to parse u64 from string: {}",
339 e
340 ))),
341 }
342 }
343
344 pub fn to_u32(&self) -> Result<u32, XlsynthError> {
345 let string = self.to_string_fmt(IrFormatPreference::UnsignedDecimal)?;
346 let number = string.split(':').nth(1).expect("split success");
347 match number.parse::<u32>() {
348 Ok(i) => Ok(i),
349 Err(e) => Err(XlsynthError(format!(
350 "IrValue::to_u32() failed to parse u32 from string: {}",
351 e
352 ))),
353 }
354 }
355
356 pub fn to_bits(&self) -> Result<IrBits, XlsynthError> {
360 xls_value_get_bits(self.ptr)
361 }
362
363 pub fn get_element(&self, index: usize) -> Result<IrValue, XlsynthError> {
364 xls_value_get_element(self.ptr, index)
365 }
366
367 pub fn get_element_count(&self) -> Result<usize, XlsynthError> {
368 xls_value_get_element_count(self.ptr)
369 }
370
371 pub fn get_elements(&self) -> Result<Vec<IrValue>, XlsynthError> {
372 let count = self.get_element_count()?;
373 let mut elements = Vec::with_capacity(count);
374 for i in 0..count {
375 let element = self.get_element(i)?;
376 elements.push(element);
377 }
378 Ok(elements)
379 }
380}
381
382unsafe impl Send for IrValue {}
383unsafe impl Sync for IrValue {}
384
385impl Into<IrValue> for bool {
386 fn into(self) -> IrValue {
387 IrValue::bool(self)
388 }
389}
390
391impl Into<IrValue> for u32 {
392 fn into(self) -> IrValue {
393 IrValue::u32(self)
394 }
395}
396
397impl Into<IrValue> for u64 {
398 fn into(self) -> IrValue {
399 IrValue::u64(self)
400 }
401}
402
403impl std::cmp::PartialEq for IrValue {
404 fn eq(&self, other: &Self) -> bool {
405 xls_value_eq(self.ptr, other.ptr).expect("eq success")
406 }
407}
408
409impl std::fmt::Display for IrValue {
410 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
411 write!(
412 f,
413 "{}",
414 xls_value_to_string(self.ptr).expect("stringify success")
415 )
416 }
417}
418
419impl std::fmt::Debug for IrValue {
420 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
421 write!(
422 f,
423 "{}",
424 xls_value_to_string(self.ptr).expect("stringify success")
425 )
426 }
427}
428
429impl Drop for IrValue {
430 fn drop(&mut self) {
431 xls_value_free(self.ptr)
432 }
433}
434
435impl Clone for IrValue {
436 fn clone(&self) -> Self {
437 let ptr = unsafe { xlsynth_sys::xls_value_clone(self.ptr) };
438 Self { ptr }
439 }
440}
441
442pub struct IrUBits<const BIT_COUNT: usize> {
446 #[allow(dead_code)]
447 wrapped: IrBits,
448}
449
450impl<const BIT_COUNT: usize> IrUBits<BIT_COUNT> {
451 pub const SIGNEDNESS: bool = false;
452
453 pub fn new(wrapped: IrBits) -> Result<Self, XlsynthError> {
454 if wrapped.get_bit_count() != BIT_COUNT {
455 return Err(XlsynthError(format!(
456 "Expected {} bits, got {}",
457 BIT_COUNT,
458 wrapped.get_bit_count()
459 )));
460 }
461 Ok(Self { wrapped })
462 }
463}
464
465pub struct IrSBits<const BIT_COUNT: usize> {
469 #[allow(dead_code)]
470 wrapped: IrBits,
471}
472
473impl<const BIT_COUNT: usize> IrSBits<BIT_COUNT> {
474 pub const SIGNEDNESS: bool = true;
475
476 pub fn new(wrapped: IrBits) -> Result<Self, XlsynthError> {
477 if wrapped.get_bit_count() != BIT_COUNT {
478 return Err(XlsynthError(format!(
479 "Expected {} bits, got {}",
480 BIT_COUNT,
481 wrapped.get_bit_count()
482 )));
483 }
484 Ok(Self { wrapped })
485 }
486}
487
488#[cfg(test)]
489mod tests {
490 use super::*;
491
492 #[test]
493 fn test_ir_value_eq() {
494 let v1 = IrValue::parse_typed("bits[32]:42").expect("parse success");
495 let v2 = IrValue::parse_typed("bits[32]:42").expect("parse success");
496 assert_eq!(v1, v2);
497 }
498
499 #[test]
500 fn test_ir_value_eq_fail() {
501 let v1 = IrValue::parse_typed("bits[32]:42").expect("parse success");
502 let v2 = IrValue::parse_typed("bits[32]:43").expect("parse success");
503 assert_ne!(v1, v2);
504 }
505
506 #[test]
507 fn test_ir_value_display() {
508 let v = IrValue::parse_typed("bits[32]:42").expect("parse success");
509 assert_eq!(format!("{}", v), "bits[32]:42");
510 }
511
512 #[test]
513 fn test_ir_value_debug() {
514 let v = IrValue::parse_typed("bits[32]:42").expect("parse success");
515 assert_eq!(format!("{:?}", v), "bits[32]:42");
516 }
517
518 #[test]
519 fn test_ir_value_drop() {
520 let v = IrValue::parse_typed("bits[32]:42").expect("parse success");
521 drop(v);
522 }
523
524 #[test]
525 fn test_ir_value_fmt_pref() {
526 let v = IrValue::parse_typed("bits[32]:42").expect("parse success");
527 assert_eq!(
528 v.to_string_fmt(IrFormatPreference::Default)
529 .expect("fmt success"),
530 "bits[32]:42"
531 );
532 assert_eq!(
533 v.to_string_fmt(IrFormatPreference::Binary)
534 .expect("fmt success"),
535 "bits[32]:0b10_1010"
536 );
537 assert_eq!(
538 v.to_string_fmt(IrFormatPreference::SignedDecimal)
539 .expect("fmt success"),
540 "bits[32]:42"
541 );
542 assert_eq!(
543 v.to_string_fmt(IrFormatPreference::UnsignedDecimal)
544 .expect("fmt success"),
545 "bits[32]:42"
546 );
547 assert_eq!(
548 v.to_string_fmt(IrFormatPreference::Hex)
549 .expect("fmt success"),
550 "bits[32]:0x2a"
551 );
552 assert_eq!(
553 v.to_string_fmt(IrFormatPreference::PlainBinary)
554 .expect("fmt success"),
555 "bits[32]:101010"
556 );
557 assert_eq!(
558 v.to_string_fmt(IrFormatPreference::PlainHex)
559 .expect("fmt success"),
560 "bits[32]:2a"
561 );
562 }
563
564 #[test]
565 fn test_ir_value_from_rust() {
566 let v = IrValue::u64(42);
567
568 assert_eq!(
570 v.to_string_fmt(IrFormatPreference::Default)
571 .expect("fmt success"),
572 "bits[64]:42"
573 );
574 assert_eq!(v.bit_count().unwrap(), 64);
576
577 v.to_bool()
579 .expect_err("bool conversion should error for u64");
580
581 let v_i64 = v.to_i64().expect("i64 conversion success");
582 assert_eq!(v_i64, 42);
583
584 let f = IrValue::parse_typed("bits[1]:0").expect("parse success");
585 assert_eq!(f.to_bool().unwrap(), false);
586
587 let t = IrValue::parse_typed("bits[1]:1").expect("parse success");
588 assert_eq!(t.to_bool().unwrap(), true);
589 }
590
591 #[test]
592 fn test_ir_value_get_bits() {
593 let v = IrValue::parse_typed("bits[32]:42").expect("parse success");
594 let bits = v.to_bits().expect("to_bits success");
595
596 let v2 = IrValue::make_ubits(32, 42).expect("make_ubits success");
598 assert_eq!(v, v2);
599
600 assert_eq!(bits.get_bit(0).unwrap(), false);
602 assert_eq!(bits.get_bit(1).unwrap(), true);
603 assert_eq!(bits.get_bit(2).unwrap(), false);
604 assert_eq!(bits.get_bit(3).unwrap(), true);
605 assert_eq!(bits.get_bit(4).unwrap(), false);
606 assert_eq!(bits.get_bit(5).unwrap(), true);
607 assert_eq!(bits.get_bit(6).unwrap(), false);
608 for i in 7..32 {
609 assert_eq!(bits.get_bit(i).unwrap(), false);
610 }
611 assert!(
612 bits.get_bit(32).is_err(),
613 "Expected an error for out of bounds index"
614 );
615 assert!(bits
616 .get_bit(32)
617 .unwrap_err()
618 .to_string()
619 .contains("Index 32 out of bounds for bits[32]:0b00000000000000000000000000101010"));
620
621 let debug_fmt = format!("{:?}", bits);
622 assert_eq!(debug_fmt, "0b00000000000000000000000000101010");
623 }
624
625 #[test]
626 fn test_ir_value_make_bits() {
627 let zero_u2 = IrValue::make_ubits(2, 0).expect("make_ubits success");
628 assert_eq!(
629 zero_u2
630 .to_string_fmt(IrFormatPreference::Default)
631 .expect("fmt success"),
632 "bits[2]:0"
633 );
634
635 let three_u2 = IrValue::make_ubits(2, 3).expect("make_ubits success");
636 assert_eq!(
637 three_u2
638 .to_string_fmt(IrFormatPreference::Default)
639 .expect("fmt success"),
640 "bits[2]:3"
641 );
642 }
643
644 #[test]
645 fn test_ir_value_parse_array_value() {
646 let text = "[bits[32]:1, bits[32]:2]";
647 let v = IrValue::parse_typed(text).expect("parse success");
648 assert_eq!(v.to_string(), text);
649 }
650
651 #[test]
652 fn test_ir_value_parse_2d_array_value() {
653 let text = "[[bits[32]:1, bits[32]:2], [bits[32]:3, bits[32]:4], [bits[32]:5, bits[32]:6]]";
654 let v = IrValue::parse_typed(text).expect("parse success");
655 assert_eq!(v.to_string(), text);
656 }
657
658 #[test]
659 fn test_ir_bits_add_two_plus_three() {
660 let two = IrBits::make_ubits(32, 2).expect("make_ubits success");
661 let three = IrBits::make_ubits(32, 3).expect("make_ubits success");
662 let sum = two + three;
663 assert_eq!(sum.to_string(), "bits[32]:5");
664 }
665
666 #[test]
667 fn test_ir_bits_umul_two_times_three() {
668 let two = IrBits::make_ubits(32, 2).expect("make_ubits success");
669 let three = IrBits::make_ubits(32, 3).expect("make_ubits success");
670 let product = two.umul(&three);
671 assert_eq!(product.to_string(), "bits[64]:6");
672 }
673
674 #[test]
675 fn test_ir_bits_smul_two_times_neg_three() {
676 let two = IrBits::make_ubits(32, 2).expect("make_ubits success");
677 let neg_three = IrBits::make_ubits(32, 3)
678 .expect("make_ubits success")
679 .negate();
680 let product = two.smul(&neg_three);
681 assert_eq!(product.msb(), true);
682 assert_eq!(product.abs().to_string(), "bits[64]:6");
683 }
684
685 #[test]
686 fn test_ir_bits_width_slice() {
687 let bits = IrBits::make_ubits(32, 0x12345678).expect("make_ubits success");
688 let slice = bits.width_slice(8, 16);
689 assert_eq!(slice.to_hex_string(), "bits[16]:0x3456");
690 }
691
692 #[test]
693 fn test_ir_bits_shll() {
694 let bits = IrBits::make_ubits(32, 0x12345678).expect("make_ubits success");
695 let shifted = bits.shll(8);
696 assert_eq!(shifted.to_hex_string(), "bits[32]:0x3456_7800");
697 }
698
699 #[test]
700 fn test_ir_bits_shrl() {
701 let bits = IrBits::make_ubits(32, 0x12345678).expect("make_ubits success");
702 let shifted = bits.shrl(8);
703 assert_eq!(shifted.to_hex_string(), "bits[32]:0x12_3456");
704 }
705
706 #[test]
707 fn test_ir_bits_shra() {
708 let bits = IrBits::make_ubits(32, 0x92345678).expect("make_ubits success");
709 let shifted = bits.shra(8);
710 assert_eq!(shifted.to_hex_string(), "bits[32]:0xff92_3456");
711 }
712
713 #[test]
714 fn test_ir_bits_and() {
715 let lhs = IrBits::make_ubits(32, 0x5a5a5a5a).expect("make_ubits success");
716 let rhs = IrBits::make_ubits(32, 0xa5a5a5a5).expect("make_ubits success");
717 assert_eq!(lhs.and(&rhs).to_hex_string(), "bits[32]:0x0");
718 assert_eq!(lhs.and(&rhs.not()).to_hex_string(), "bits[32]:0x5a5a_5a5a");
719 }
720
721 #[test]
722 fn test_ir_bits_or() {
723 let lhs = IrBits::make_ubits(32, 0x5a5a5a5a).expect("make_ubits success");
724 let rhs = IrBits::make_ubits(32, 0xa5a5a5a5).expect("make_ubits success");
725 assert_eq!(lhs.or(&rhs).to_hex_string(), "bits[32]:0xffff_ffff");
726 assert_eq!(lhs.or(&rhs.not()).to_hex_string(), "bits[32]:0x5a5a_5a5a");
727 }
728
729 #[test]
730 fn test_ir_bits_xor() {
731 let lhs = IrBits::make_ubits(32, 0x5a5a5a5a).expect("make_ubits success");
732 let rhs = IrBits::make_ubits(32, 0xa5a5a5a5).expect("make_ubits success");
733 assert_eq!(lhs.xor(&rhs).to_hex_string(), "bits[32]:0xffff_ffff");
734 assert_eq!(lhs.xor(&rhs.not()).to_hex_string(), "bits[32]:0x0");
735 }
736
737 #[test]
738 fn test_make_tuple_and_get_elements() {
739 let _ = env_logger::builder().is_test(true).try_init();
740 let b1_v0 = IrValue::make_ubits(1, 0).expect("make_ubits success");
741 let b2_v1 = IrValue::make_ubits(2, 1).expect("make_ubits success");
742 let b3_v2 = IrValue::make_ubits(3, 2).expect("make_ubits success");
743 let tuple = IrValue::make_tuple(&[b1_v0.clone(), b2_v1.clone(), b3_v2.clone()]);
744 let elements = tuple.get_elements().expect("get_elements success");
745 assert_eq!(elements.len(), 3);
746 assert_eq!(elements[0].to_string(), "bits[1]:0");
747 assert_eq!(elements[0], b1_v0);
748 assert_eq!(elements[1].to_string(), "bits[2]:1");
749 assert_eq!(elements[1], b2_v1);
750 assert_eq!(elements[2].to_string(), "bits[3]:2");
751 assert_eq!(elements[2], b3_v2);
752 }
753
754 #[test]
755 fn test_make_ir_value_bits_that_does_not_fit() {
756 let result = IrValue::make_ubits(1, 2);
757 assert!(result.is_err());
758 let error = result.unwrap_err();
759 assert!(error.to_string().contains("0x2 requires 2 bits to fit in an unsigned datatype, but attempting to fit in 1 bit"), "got: {}", error);
760
761 let result = IrValue::make_sbits(1, -2);
762 assert!(result.is_err());
763 let error = result.unwrap_err();
764 assert!(error.to_string().contains("0xfffffffffffffffe requires 2 bits to fit in an signed datatype, but attempting to fit in 1 bit"), "got: {}", error);
765 }
766
767 #[test]
768 fn test_make_ir_value_array() {
769 let b2_v0 = IrValue::make_ubits(2, 0).expect("make_ubits success");
770 let b2_v1 = IrValue::make_ubits(2, 1).expect("make_ubits success");
771 let b2_v2 = IrValue::make_ubits(2, 2).expect("make_ubits success");
772 let b2_v3 = IrValue::make_ubits(2, 3).expect("make_ubits success");
773 let array = IrValue::make_array(&[b2_v0, b2_v1, b2_v2, b2_v3]).expect("make_array success");
774 assert_eq!(
775 array.to_string(),
776 "[bits[2]:0, bits[2]:1, bits[2]:2, bits[2]:3]"
777 );
778 }
779
780 #[test]
781 fn test_make_ir_value_empty_array() {
782 IrValue::make_array(&[]).expect_err("make_array should fail for empty array");
783 }
784
785 #[test]
786 fn test_make_ir_value_array_with_mixed_types() {
787 let b2_v0 = IrValue::make_ubits(2, 0).expect("make_ubits success");
788 let b3_v1 = IrValue::make_ubits(3, 1).expect("make_ubits success");
789 let result = IrValue::make_array(&[b2_v0, b3_v1]);
790 assert!(result.is_err());
791 let error = result.unwrap_err();
792 assert!(error.to_string().contains("SameTypeAs"));
793 }
794}