sv4state/
lib.rs

1#![doc = include_str!("../README.md")]
2
3use num_traits::{FromPrimitive, PrimInt, WrappingShr};
4use std::fmt::{Debug, LowerHex};
5
6/// Type for SystemVerilog 4-state value
7#[derive(Copy, Clone, Debug)]
8pub struct Sv4State<T: Copy + Debug> {
9    /// value
10    pub v: T,
11    /// bit flag of hi-z
12    pub z: T,
13    /// bit flag of x
14    pub x: T,
15}
16
17/// Type for packed logic array defined by IEEE 1800-2017 Annex I
18#[repr(C)]
19pub struct svLogicVecVal {
20    pub aval: u32,
21    pub bval: u32,
22}
23
24impl<T: Copy + Debug + PrimInt + WrappingShr> std::fmt::Binary for Sv4State<T> {
25    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26        let payload_width = T::zero().count_zeros();
27        let mut buf = if f.alternate() {
28            String::from("0b")
29        } else {
30            String::from("")
31        };
32
33        for i in 0..payload_width {
34            let v = (self.v.wrapping_shr(payload_width - i - 1)) & T::one();
35            let z = (self.z.wrapping_shr(payload_width - i - 1)) & T::one();
36            let x = (self.x.wrapping_shr(payload_width - i - 1)) & T::one();
37
38            if z == T::one() {
39                buf.push('z')
40            } else if x == T::one() {
41                buf.push('x')
42            } else if v == T::one() {
43                buf.push('1')
44            } else {
45                buf.push('0')
46            }
47        }
48        write!(f, "{}", buf)
49    }
50}
51
52impl<T: Copy + Debug + PrimInt + WrappingShr + FromPrimitive + LowerHex> LowerHex for Sv4State<T> {
53    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54        let payload_width = T::zero().count_zeros();
55        let mut buf = if f.alternate() {
56            String::from("0x")
57        } else {
58            String::from("")
59        };
60
61        let all_hi = T::from_u32(15).unwrap();
62
63        for i in 0..payload_width / 4 {
64            let v = (self.v.wrapping_shr(payload_width - (i + 1) * 4)) & all_hi;
65            let z = (self.z.wrapping_shr(payload_width - (i + 1) * 4)) & all_hi;
66            let x = (self.x.wrapping_shr(payload_width - (i + 1) * 4)) & all_hi;
67
68            if z == all_hi {
69                buf.push('z')
70            } else if z != T::zero() {
71                buf.push('Z')
72            } else if x == all_hi {
73                buf.push('x')
74            } else if x != T::zero() {
75                buf.push('X')
76            } else {
77                buf.push_str(&format!("{:x}", v))
78            }
79        }
80        write!(f, "{}", buf)
81    }
82}
83
84impl<T: Copy + Debug + PrimInt + FromPrimitive> Sv4State<T> {
85    pub fn from_dpi(data: &[svLogicVecVal]) -> Vec<Self> {
86        let payload_width = T::zero().count_zeros() as usize;
87        let bit_width = 32 * data.len();
88        let len = if bit_width % payload_width == 0 {
89            bit_width / payload_width
90        } else {
91            bit_width / payload_width + 1
92        };
93
94        let mut ret = Vec::new();
95        for i in 0..len {
96            let mut v = T::zero();
97            let mut z = T::zero();
98            let mut x = T::zero();
99
100            for j in 0..(payload_width / 8) {
101                // byte index
102                let index = i * payload_width / 8 + j;
103
104                if index / 4 >= data.len() {
105                    break;
106                }
107
108                let aval = data[index / 4].aval >> ((index % 4) * 8) & 0xff;
109                let bval = data[index / 4].bval >> ((index % 4) * 8) & 0xff;
110                let aval = T::from_u32(aval).unwrap();
111                let bval = T::from_u32(bval).unwrap();
112                let aval = aval << (j * 8);
113                let bval = bval << (j * 8);
114
115                v = v | (aval & !bval);
116                z = z | (bval & !aval);
117                x = x | (bval & aval);
118            }
119
120            ret.push(Sv4State { v, z, x });
121        }
122        ret
123    }
124}
125
126#[cfg(test)]
127mod tests {
128    use super::*;
129
130    #[test]
131    fn from_dpi_u8() {
132        let buf = [
133            svLogicVecVal {
134                aval: 0x01234567,
135                bval: 0x00000000,
136            },
137            svLogicVecVal {
138                aval: 0x89abcdef,
139                bval: 0xffffffff,
140            },
141        ];
142        let sv_u8 = Sv4State::<u8>::from_dpi(&buf);
143
144        assert_eq!(sv_u8[0].v, 0x67);
145        assert_eq!(sv_u8[0].z, 0x00);
146        assert_eq!(sv_u8[0].x, 0x00);
147        assert_eq!(sv_u8[1].v, 0x45);
148        assert_eq!(sv_u8[1].z, 0x00);
149        assert_eq!(sv_u8[1].x, 0x00);
150        assert_eq!(sv_u8[2].v, 0x23);
151        assert_eq!(sv_u8[2].z, 0x00);
152        assert_eq!(sv_u8[2].x, 0x00);
153        assert_eq!(sv_u8[3].v, 0x01);
154        assert_eq!(sv_u8[3].z, 0x00);
155        assert_eq!(sv_u8[3].x, 0x00);
156        assert_eq!(sv_u8[4].v, 0x00);
157        assert_eq!(sv_u8[4].z, 0x10);
158        assert_eq!(sv_u8[4].x, 0xef);
159        assert_eq!(sv_u8[5].v, 0x00);
160        assert_eq!(sv_u8[5].z, 0x32);
161        assert_eq!(sv_u8[5].x, 0xcd);
162        assert_eq!(sv_u8[6].v, 0x00);
163        assert_eq!(sv_u8[6].z, 0x54);
164        assert_eq!(sv_u8[6].x, 0xab);
165        assert_eq!(sv_u8[7].v, 0x00);
166        assert_eq!(sv_u8[7].z, 0x76);
167        assert_eq!(sv_u8[7].x, 0x89);
168    }
169
170    #[test]
171    fn from_dpi_u16() {
172        let buf = [
173            svLogicVecVal {
174                aval: 0x01234567,
175                bval: 0x00000000,
176            },
177            svLogicVecVal {
178                aval: 0x89abcdef,
179                bval: 0xffffffff,
180            },
181        ];
182        let sv_u16 = Sv4State::<u16>::from_dpi(&buf);
183
184        assert_eq!(sv_u16[0].v, 0x4567);
185        assert_eq!(sv_u16[0].z, 0x0000);
186        assert_eq!(sv_u16[0].x, 0x0000);
187        assert_eq!(sv_u16[1].v, 0x0123);
188        assert_eq!(sv_u16[1].z, 0x0000);
189        assert_eq!(sv_u16[1].x, 0x0000);
190        assert_eq!(sv_u16[2].v, 0x0000);
191        assert_eq!(sv_u16[2].z, 0x3210);
192        assert_eq!(sv_u16[2].x, 0xcdef);
193        assert_eq!(sv_u16[3].v, 0x0000);
194        assert_eq!(sv_u16[3].z, 0x7654);
195        assert_eq!(sv_u16[3].x, 0x89ab);
196    }
197
198    #[test]
199    fn from_dpi_u32() {
200        let buf = [
201            svLogicVecVal {
202                aval: 0x01234567,
203                bval: 0x00000000,
204            },
205            svLogicVecVal {
206                aval: 0x89abcdef,
207                bval: 0xffffffff,
208            },
209        ];
210        let sv_u32 = Sv4State::<u32>::from_dpi(&buf);
211
212        assert_eq!(sv_u32[0].v, 0x01234567);
213        assert_eq!(sv_u32[0].z, 0x00000000);
214        assert_eq!(sv_u32[0].x, 0x00000000);
215        assert_eq!(sv_u32[1].v, 0x00000000);
216        assert_eq!(sv_u32[1].z, 0x76543210);
217        assert_eq!(sv_u32[1].x, 0x89abcdef);
218    }
219
220    #[test]
221    fn from_dpi_u64() {
222        let buf = [
223            svLogicVecVal {
224                aval: 0x01234567,
225                bval: 0x00000000,
226            },
227            svLogicVecVal {
228                aval: 0x89abcdef,
229                bval: 0xffffffff,
230            },
231        ];
232        let sv_u64 = Sv4State::<u64>::from_dpi(&buf);
233
234        assert_eq!(sv_u64[0].v, 0x0000000001234567);
235        assert_eq!(sv_u64[0].z, 0x7654321000000000);
236        assert_eq!(sv_u64[0].x, 0x89abcdef00000000);
237    }
238
239    #[test]
240    fn from_dpi_u128() {
241        let buf = [
242            svLogicVecVal {
243                aval: 0x01234567,
244                bval: 0x00000000,
245            },
246            svLogicVecVal {
247                aval: 0x89abcdef,
248                bval: 0xffffffff,
249            },
250        ];
251        let sv_u128 = Sv4State::<u128>::from_dpi(&buf);
252
253        assert_eq!(sv_u128[0].v, 0x0000000001234567);
254        assert_eq!(sv_u128[0].z, 0x7654321000000000);
255        assert_eq!(sv_u128[0].x, 0x89abcdef00000000);
256    }
257
258    #[test]
259    fn format_binary() {
260        let buf = [
261            svLogicVecVal {
262                aval: 0x01234567,
263                bval: 0x00000000,
264            },
265            svLogicVecVal {
266                aval: 0x89abcdef,
267                bval: 0xffffffff,
268            },
269        ];
270        let sv_u16 = Sv4State::<u16>::from_dpi(&buf);
271
272        assert_eq!(format!("{:b}", sv_u16[0]), "0100010101100111");
273        assert_eq!(format!("{:#b}", sv_u16[0]), "0b0100010101100111");
274        assert_eq!(format!("{:b}", sv_u16[1]), "0000000100100011");
275        assert_eq!(format!("{:#b}", sv_u16[1]), "0b0000000100100011");
276        assert_eq!(format!("{:b}", sv_u16[2]), "xxzzxxzxxxxzxxxx");
277        assert_eq!(format!("{:#b}", sv_u16[2]), "0bxxzzxxzxxxxzxxxx");
278        assert_eq!(format!("{:b}", sv_u16[3]), "xzzzxzzxxzxzxzxx");
279        assert_eq!(format!("{:#b}", sv_u16[3]), "0bxzzzxzzxxzxzxzxx");
280    }
281
282    #[test]
283    fn format_lower_hex() {
284        let buf = [
285            svLogicVecVal {
286                aval: 0x01234567,
287                bval: 0x00000000,
288            },
289            svLogicVecVal {
290                aval: 0x89abcdef,
291                bval: 0xffffffff,
292            },
293        ];
294        let sv_u32 = Sv4State::<u32>::from_dpi(&buf);
295
296        assert_eq!(format!("{:x}", sv_u32[0]), "01234567");
297        assert_eq!(format!("{:#x}", sv_u32[0]), "0x01234567");
298        assert_eq!(format!("{:x}", sv_u32[1]), "ZZZZZZZx");
299        assert_eq!(format!("{:#x}", sv_u32[1]), "0xZZZZZZZx");
300    }
301}