|
| 1 | +''' |
| 2 | +Created on Nov 8, 2024 |
| 3 | +
|
| 4 | +Test for ValueInt.from_bits functionality |
| 5 | +''' |
| 6 | +import sys |
| 7 | +import os |
| 8 | +# Add src to path to allow importing vsc modules |
| 9 | +sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', 'src')) |
| 10 | + |
| 11 | +from unittest import TestCase |
| 12 | + |
| 13 | +# Import ValueInt directly to avoid full vsc package dependencies |
| 14 | +try: |
| 15 | + from vsc.types import ValueInt |
| 16 | +except ImportError: |
| 17 | + # Fallback to direct import if vsc package can't be fully loaded |
| 18 | + from vsc.model.value_scalar import ValueInt |
| 19 | + |
| 20 | + |
| 21 | +class TestValueInt(TestCase): |
| 22 | + |
| 23 | + def test_from_bits_unsigned_8bit(self): |
| 24 | + """Test unsigned 8-bit value conversion""" |
| 25 | + # Test maximum unsigned value |
| 26 | + result = ValueInt.from_bits(0xFF, 8, signed=False) |
| 27 | + self.assertEqual(result, 255) |
| 28 | + |
| 29 | + # Test zero |
| 30 | + result = ValueInt.from_bits(0x00, 8, signed=False) |
| 31 | + self.assertEqual(result, 0) |
| 32 | + |
| 33 | + # Test mid-range value |
| 34 | + result = ValueInt.from_bits(0x7F, 8, signed=False) |
| 35 | + self.assertEqual(result, 127) |
| 36 | + |
| 37 | + def test_from_bits_signed_8bit(self): |
| 38 | + """Test signed 8-bit value conversion""" |
| 39 | + # Test -1 (0xFF in 8-bit two's complement) |
| 40 | + result = ValueInt.from_bits(0xFF, 8, signed=True) |
| 41 | + self.assertEqual(result, -1) |
| 42 | + |
| 43 | + # Test -128 (0x80 in 8-bit two's complement) |
| 44 | + result = ValueInt.from_bits(0x80, 8, signed=True) |
| 45 | + self.assertEqual(result, -128) |
| 46 | + |
| 47 | + # Test positive value (MSB = 0) |
| 48 | + result = ValueInt.from_bits(0x7F, 8, signed=True) |
| 49 | + self.assertEqual(result, 127) |
| 50 | + |
| 51 | + # Test zero |
| 52 | + result = ValueInt.from_bits(0x00, 8, signed=True) |
| 53 | + self.assertEqual(result, 0) |
| 54 | + |
| 55 | + def test_from_bits_unsigned_32bit(self): |
| 56 | + """Test unsigned 32-bit value conversion""" |
| 57 | + # Test maximum unsigned 32-bit value |
| 58 | + result = ValueInt.from_bits(0xFFFFFFFF, 32, signed=False) |
| 59 | + self.assertEqual(result, 4294967295) |
| 60 | + |
| 61 | + # Test mid-range value |
| 62 | + result = ValueInt.from_bits(0x80000000, 32, signed=False) |
| 63 | + self.assertEqual(result, 2147483648) |
| 64 | + |
| 65 | + def test_from_bits_signed_32bit(self): |
| 66 | + """Test signed 32-bit value conversion""" |
| 67 | + # Test -1 (0xFFFFFFFF in 32-bit two's complement) |
| 68 | + result = ValueInt.from_bits(0xFFFFFFFF, 32, signed=True) |
| 69 | + self.assertEqual(result, -1) |
| 70 | + |
| 71 | + # Test minimum signed 32-bit value |
| 72 | + result = ValueInt.from_bits(0x80000000, 32, signed=True) |
| 73 | + self.assertEqual(result, -2147483648) |
| 74 | + |
| 75 | + # Test positive value |
| 76 | + result = ValueInt.from_bits(0x7FFFFFFF, 32, signed=True) |
| 77 | + self.assertEqual(result, 2147483647) |
| 78 | + |
| 79 | + def test_from_bits_masking(self): |
| 80 | + """Test that values are properly masked to specified width""" |
| 81 | + # Value larger than 8 bits should be masked |
| 82 | + result = ValueInt.from_bits(0x1FF, 8, signed=False) |
| 83 | + self.assertEqual(result, 0xFF) |
| 84 | + |
| 85 | + # Value larger than 4 bits should be masked |
| 86 | + result = ValueInt.from_bits(0xFF, 4, signed=False) |
| 87 | + self.assertEqual(result, 0x0F) |
| 88 | + |
| 89 | + # Signed masking |
| 90 | + result = ValueInt.from_bits(0xFF, 4, signed=True) |
| 91 | + self.assertEqual(result, -1) |
| 92 | + |
| 93 | + def test_from_bits_sign_detection(self): |
| 94 | + """Test sign bit detection at various widths""" |
| 95 | + # 4-bit: 0x8 should be -8 when signed |
| 96 | + result = ValueInt.from_bits(0x8, 4, signed=True) |
| 97 | + self.assertEqual(result, -8) |
| 98 | + |
| 99 | + # 4-bit: 0x7 should be 7 when signed (positive) |
| 100 | + result = ValueInt.from_bits(0x7, 4, signed=True) |
| 101 | + self.assertEqual(result, 7) |
| 102 | + |
| 103 | + # 16-bit: 0x8000 should be -32768 when signed |
| 104 | + result = ValueInt.from_bits(0x8000, 16, signed=True) |
| 105 | + self.assertEqual(result, -32768) |
| 106 | + |
| 107 | + # 16-bit: 0x7FFF should be 32767 when signed (positive) |
| 108 | + result = ValueInt.from_bits(0x7FFF, 16, signed=True) |
| 109 | + self.assertEqual(result, 32767) |
| 110 | + |
| 111 | + def test_from_bits_edge_cases(self): |
| 112 | + """Test edge cases""" |
| 113 | + # 1-bit unsigned |
| 114 | + result = ValueInt.from_bits(1, 1, signed=False) |
| 115 | + self.assertEqual(result, 1) |
| 116 | + |
| 117 | + result = ValueInt.from_bits(0, 1, signed=False) |
| 118 | + self.assertEqual(result, 0) |
| 119 | + |
| 120 | + # 1-bit signed: can only represent -1 and 0 |
| 121 | + result = ValueInt.from_bits(1, 1, signed=True) |
| 122 | + self.assertEqual(result, -1) |
| 123 | + |
| 124 | + result = ValueInt.from_bits(0, 1, signed=True) |
| 125 | + self.assertEqual(result, 0) |
| 126 | + |
| 127 | + def test_from_bits_practical_dut_example(self): |
| 128 | + """Test practical example from DUT interface""" |
| 129 | + # Simulating a DUT returning 0xFFFFFFF0 from a 32-bit signed register |
| 130 | + dut_val = 0xFFFFFFF0 |
| 131 | + vsc_val = ValueInt.from_bits(dut_val, width=32, signed=True) |
| 132 | + self.assertEqual(vsc_val, -16) |
| 133 | + |
| 134 | + # Simulating a DUT returning 0xFF from an 8-bit signed register |
| 135 | + dut_val = 0xFF |
| 136 | + vsc_val = ValueInt.from_bits(dut_val, width=8, signed=True) |
| 137 | + self.assertEqual(vsc_val, -1) |
| 138 | + |
| 139 | + # Simulating a DUT returning 0xFF from an 8-bit unsigned register |
| 140 | + dut_val = 0xFF |
| 141 | + vsc_val = ValueInt.from_bits(dut_val, width=8, signed=False) |
| 142 | + self.assertEqual(vsc_val, 255) |
0 commit comments