1#![doc = include_str!("../README.md")]
2
3use num_traits::{FromPrimitive, PrimInt, WrappingShr};
4use std::fmt::{Debug, LowerHex};
5
6#[derive(Copy, Clone, Debug)]
8pub struct Sv4State<T: Copy + Debug> {
9 pub v: T,
11 pub z: T,
13 pub x: T,
15}
16
17#[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 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}