Skip to main content

vpi/
value.rs

1use std::fmt::Display;
2
3use num_derive::{FromPrimitive, ToPrimitive};
4use num_traits::FromPrimitive;
5use vpi_sys::{PLI_INT32, PLI_UINT32};
6
7use crate::{Handle, Property, Time};
8
9/// High-level value representation returned from or written to VPI objects.
10#[derive(Debug)]
11pub enum Value {
12    /// Binary string value.
13    BinStr(String),
14    /// Octal string value.
15    OctStr(String),
16    /// Hexadecimal string value.
17    HexStr(String),
18    /// Decimal string value.
19    DecStr(String),
20    /// 4-state scalar value.
21    Scalar(ScalarValue),
22    /// 32-bit signed integer value.
23    Int(i32),
24    /// 64-bit floating-point value.
25    Real(f64),
26    /// Plain string value.
27    String(String),
28    /// Vector of scalar bits.
29    Vector(Vec<ScalarValue>),
30    /// Value with drive-strength information.
31    Strength(StrengthValue),
32    /// Time value.
33    Time(Time),
34    /// Raw object type value.
35    ///
36    /// This variant is used when the simulator returns `vpiObjTypeVal`
37    /// directly. When [`ValueType::ObjType`] is requested via
38    /// [`Handle::get_value`], the simulator may instead report a more specific
39    /// value format, in which case `get_value` returns the corresponding
40    /// concrete [`Value`] variant.
41    ObjType(i32),
42    /// Suppress value transfer.
43    Suppress,
44    /// 16-bit signed integer value.
45    ShortInt(i16),
46    /// 64-bit signed integer value.
47    LongInt(i64),
48    /// 32-bit floating-point value.
49    ShortReal(f32),
50    /// Raw 2-state packed bits.
51    RawTwoState(Vec<bool>), // Each bit is either 0 or 1
52    /// Raw 4-state packed bits.
53    RawFourState(Vec<ScalarValue>), // Each bit can be 0, 1, X, or Z
54}
55
56impl Display for Value {
57    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
58        match self {
59            Value::BinStr(s) | Value::OctStr(s) | Value::HexStr(s) | Value::DecStr(s) => {
60                write!(f, "{s}")
61            }
62            Value::Scalar(scalar) => write!(f, "{scalar}"),
63            Value::Int(i) => write!(f, "{i}"),
64            Value::Real(r) => write!(f, "{r}"),
65            Value::String(s) => write!(f, "\"{s}\""),
66            Value::Vector(vec) => {
67                write!(
68                    f,
69                    "{}",
70                    vec.iter().map(|s| format!("{s}")).collect::<String>()
71                )
72            }
73            Value::Strength(strength) => write!(f, "{strength}"),
74            Value::Time(time) => write!(f, "{time}"),
75            Value::ObjType(obj_type) => write!(f, "ObjType({obj_type})"), // Placeholder
76            Value::Suppress => write!(f, "Suppress"),
77            Value::ShortInt(i) => write!(f, "{i}"),
78            Value::LongInt(i) => write!(f, "{i}"),
79            Value::ShortReal(r) => write!(f, "{r}"),
80            Value::RawTwoState(vec) => {
81                write!(
82                    f,
83                    "{}",
84                    vec.iter()
85                        .map(|b| if *b { '1' } else { '0' })
86                        .collect::<String>()
87                )
88            }
89            Value::RawFourState(vec) => {
90                write!(
91                    f,
92                    "{}",
93                    vec.iter().map(|s| format!("{s}")).collect::<String>()
94                )
95            }
96        }
97    }
98}
99
100#[repr(u32)]
101#[derive(FromPrimitive, ToPrimitive, Debug, Copy, Clone)]
102/// VPI value format tags used with `vpi_get_value` and related APIs.
103pub enum ValueType {
104    /// Binary string format.
105    BinStr = vpi_sys::vpiBinStrVal,
106    /// Octal string format.
107    OctStr = vpi_sys::vpiOctStrVal,
108    /// Hexadecimal string format.
109    HexStr = vpi_sys::vpiHexStrVal,
110    /// Decimal string format.
111    DecStr = vpi_sys::vpiDecStrVal,
112    /// 4-state scalar format.
113    Scalar = vpi_sys::vpiScalarVal,
114    /// 32-bit signed integer format.
115    Int = vpi_sys::vpiIntVal,
116    /// 64-bit floating-point format.
117    Real = vpi_sys::vpiRealVal,
118    /// String format.
119    String = vpi_sys::vpiStringVal,
120    /// Vector-of-bits format.
121    Vector = vpi_sys::vpiVectorVal,
122    /// Scalar-plus-strength format.
123    Strength = vpi_sys::vpiStrengthVal,
124    /// Time format.
125    Time = vpi_sys::vpiTimeVal,
126    /// Request that the simulator choose the object's native value format.
127    ///
128    /// When used with [`Handle::get_value`], the simulator can replace this
129    /// request with the actual value format for the object, so the returned
130    /// [`Value`] is typically the corresponding concrete variant rather than
131    /// [`Value::ObjType`].
132    ObjType = vpi_sys::vpiObjTypeVal,
133    /// Suppress value transfer.
134    Suppress = vpi_sys::vpiSuppressVal,
135    /// 16-bit signed integer format.
136    ShortInt = vpi_sys::vpiShortIntVal,
137    /// 64-bit signed integer format.
138    LongInt = vpi_sys::vpiLongIntVal,
139    /// 32-bit floating-point format.
140    ShortReal = vpi_sys::vpiShortRealVal,
141    /// Raw packed 2-state vector format.
142    RawTwoState = vpi_sys::vpiRawTwoStateVal,
143    /// Raw packed 4-state vector format.
144    RawFourState = vpi_sys::vpiRawFourStateVal,
145}
146
147impl std::fmt::Display for ValueType {
148    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
149        let type_name = match self {
150            ValueType::BinStr => "Binary String",
151            ValueType::OctStr => "Octal String",
152            ValueType::HexStr => "Hexadecimal String",
153            ValueType::DecStr => "Decimal String",
154            ValueType::Scalar => "Scalar",
155            ValueType::Int => "Integer",
156            ValueType::Real => "Real",
157            ValueType::String => "String",
158            ValueType::Vector => "Vector",
159            ValueType::Strength => "Strength",
160            ValueType::Time => "Time",
161            ValueType::ObjType => "Object Type",
162            ValueType::Suppress => "Suppress",
163            ValueType::ShortInt => "Short Integer",
164            ValueType::LongInt => "Long Integer",
165            ValueType::ShortReal => "Short Real",
166            ValueType::RawTwoState => "Raw Two-State Vector",
167            ValueType::RawFourState => "Raw Four-State Vector",
168        };
169        write!(f, "{type_name}")
170    }
171}
172
173#[repr(u32)]
174#[derive(FromPrimitive, ToPrimitive, Copy, Clone, Debug, PartialEq)]
175/// 4-state scalar encodings used by VPI.
176pub enum ScalarValue {
177    /// Logic `0`.
178    Zero = vpi_sys::vpi0,
179    /// Logic `1`.
180    One = vpi_sys::vpi1,
181    /// High-impedance state.
182    Z = vpi_sys::vpiZ,
183    /// Unknown logic state.
184    X = vpi_sys::vpiX,
185    /// Weak high state.
186    H = vpi_sys::vpiH,
187    /// Weak low state.
188    L = vpi_sys::vpiL,
189    /// Don't-care state.
190    DontCare = vpi_sys::vpiDontCare,
191    /// Leave the current value unchanged.
192    NoChange = vpi_sys::vpiNoChange,
193}
194
195impl Display for ScalarValue {
196    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
197        write!(f, "{}", char::from(*self))
198    }
199}
200
201impl From<ScalarValue> for char {
202    fn from(value: ScalarValue) -> Self {
203        match value {
204            ScalarValue::Zero => '0',
205            ScalarValue::One => '1',
206            ScalarValue::X => 'X',
207            ScalarValue::Z => 'Z',
208            ScalarValue::H => 'H',
209            ScalarValue::L => 'L',
210            ScalarValue::DontCare => '-',
211            ScalarValue::NoChange => 'N',
212        }
213    }
214}
215
216#[derive(Debug)]
217/// Scalar logic value plus drive strengths.
218pub struct StrengthValue {
219    /// Scalar logic state carried by the value.
220    logic: ScalarValue,
221    /// Drive strength applied when the logic resolves to `0`.
222    strength0: StrengthEncoding,
223    /// Drive strength applied when the logic resolves to `1`.
224    strength1: StrengthEncoding,
225}
226
227impl Display for StrengthValue {
228    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
229        write!(f, "{} ({}, {})", self.logic, self.strength0, self.strength1)
230    }
231}
232
233impl From<vpi_sys::t_vpi_strengthval> for StrengthValue {
234    fn from(strength: vpi_sys::t_vpi_strengthval) -> Self {
235        let logic = ScalarValue::from_u32(strength.logic as u32).unwrap_or(ScalarValue::DontCare);
236        let strength0 = StrengthEncoding::from_bits_truncate(strength.s0 as u32);
237        let strength1 = StrengthEncoding::from_bits_truncate(strength.s1 as u32);
238        Self {
239            logic,
240            strength0,
241            strength1,
242        }
243    }
244}
245
246bitflags::bitflags! {
247    #[derive(Debug)]
248    /// Drive-strength and charge encoding flags.
249    pub struct StrengthEncoding: u32 {
250        /// Supply-strength drive.
251        const SupplyDrive = vpi_sys::vpiSupplyDrive;
252        /// Strong drive strength.
253        const StrongDrive = vpi_sys::vpiStrongDrive;
254        /// Pull drive strength.
255        const PullDrive = vpi_sys::vpiPullDrive;
256        /// Large charge strength.
257        const LargeCharge = vpi_sys::vpiLargeCharge;
258        /// Weak drive strength.
259        const WeakDrive = vpi_sys::vpiWeakDrive;
260        /// Medium charge strength.
261        const MediumCharge = vpi_sys::vpiMediumCharge;
262        /// Small charge strength.
263        const SmallCharge = vpi_sys::vpiSmallCharge;
264        /// High-impedance strength.
265        const HiZ = vpi_sys::vpiHiZ;
266    }
267}
268
269impl Display for StrengthEncoding {
270    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
271        let mut strengths = Vec::new();
272        if self.contains(StrengthEncoding::SupplyDrive) {
273            strengths.push("SupplyDrive");
274        }
275        if self.contains(StrengthEncoding::StrongDrive) {
276            strengths.push("StrongDrive");
277        }
278        if self.contains(StrengthEncoding::PullDrive) {
279            strengths.push("PullDrive");
280        }
281        if self.contains(StrengthEncoding::LargeCharge) {
282            strengths.push("LargeCharge");
283        }
284        if self.contains(StrengthEncoding::WeakDrive) {
285            strengths.push("WeakDrive");
286        }
287        if self.contains(StrengthEncoding::MediumCharge) {
288            strengths.push("MediumCharge");
289        }
290        if self.contains(StrengthEncoding::SmallCharge) {
291            strengths.push("SmallCharge");
292        }
293        if self.contains(StrengthEncoding::HiZ) {
294            strengths.push("HiZ");
295        }
296        write!(f, "{}", strengths.join(" | "))
297    }
298}
299
300bitflags::bitflags! {
301    /// Flags controlling behavior of `vpi_put_value`.
302    pub struct PutValueFlags: u32 {
303        /// Return an event handle for the scheduled value update.
304        const ReturnEvent = vpi_sys::vpiReturnEvent;
305        /// Indicates that associated storage is managed by user code.
306        const UserAllocFlag = vpi_sys::vpiUserAllocFlag;
307        /// Restrict the update to a single value.
308        const OneValue = vpi_sys::vpiOneValue;
309        /// Disable propagation for the value update.
310        const PropagateOff = vpi_sys::vpiPropagateOff;
311    }
312}
313
314/// Convert VPI vector values to a vector of scalar values
315///
316/// The VPI vecval structure encodes each bit as a pair (aval, bval):
317/// - ab: 00 = 0 (Zero)
318/// - ab: 10 = 1 (One)
319/// - ab: 11 = X (X)
320/// - ab: 01 = Z (Z)
321///
322/// # Arguments
323/// * `vec` - Array of `vpi_vecval` structures containing the encoded bits
324/// * `size` - Number of bits to extract
325#[must_use]
326pub fn vector_value_to_scalar_vector(
327    vec: &[vpi_sys::t_vpi_vecval],
328    size: usize,
329) -> Vec<ScalarValue> {
330    let mut result = Vec::with_capacity(size);
331
332    for bit_index in 0..size {
333        // Which word in the vecval array contains this bit?
334        let word_index = bit_index / 32;
335        // Which bit position within that word?
336        let bit_position = bit_index % 32;
337
338        if word_index >= vec.len() {
339            // If we've run out of vecval words, treat as 0
340            result.push(ScalarValue::Zero);
341            continue;
342        }
343
344        let vecval = &vec[word_index];
345
346        // Extract the a and b bits
347        let a_bit = (vecval.aval >> bit_position) & 1;
348        let b_bit = (vecval.bval >> bit_position) & 1;
349
350        // Combine into the encoding: (a << 1) | b
351        // 00=0, 10=1, 11=X, 01=Z
352        let encoded = (a_bit << 1) | b_bit;
353
354        let scalar = match encoded {
355            0 => ScalarValue::Zero,
356            1 => ScalarValue::Z,
357            2 => ScalarValue::One,
358            3 => ScalarValue::X,
359            _ => ScalarValue::DontCare, // Should never happen
360        };
361
362        result.push(scalar);
363    }
364
365    result.reverse(); // Reverse to match Verilog bit ordering (MSB at index 0)
366    result
367}
368
369/// Decode a raw `t_vpi_value` into a high-level [`Value`].
370///
371/// `obj` is used for value formats that require object context (for example,
372/// vector width when decoding `vpiVectorVal`).
373#[must_use]
374pub(crate) fn decode_vpi_value(
375    raw_value: vpi_sys::t_vpi_value,
376    obj: vpi_sys::vpiHandle,
377) -> Option<Value> {
378    match raw_value.format as u32 {
379        vpi_sys::vpiBinStrVal => {
380            let c_str = unsafe { std::ffi::CStr::from_ptr(raw_value.value.str_) };
381            Some(Value::BinStr(c_str.to_str().unwrap_or("").to_string()))
382        }
383        vpi_sys::vpiOctStrVal => {
384            let c_str = unsafe { std::ffi::CStr::from_ptr(raw_value.value.str_) };
385            Some(Value::OctStr(c_str.to_str().unwrap_or("").to_string()))
386        }
387        vpi_sys::vpiHexStrVal => {
388            let c_str = unsafe { std::ffi::CStr::from_ptr(raw_value.value.str_) };
389            Some(Value::HexStr(c_str.to_str().unwrap_or("").to_string()))
390        }
391        vpi_sys::vpiDecStrVal => {
392            let c_str = unsafe { std::ffi::CStr::from_ptr(raw_value.value.str_) };
393            Some(Value::DecStr(c_str.to_str().unwrap_or("").to_string()))
394        }
395        vpi_sys::vpiScalarVal => Some(Value::Scalar(
396            ScalarValue::from_u32(unsafe { raw_value.value.integer } as u32)
397                .unwrap_or(ScalarValue::DontCare),
398        )),
399        vpi_sys::vpiIntVal => Some(Value::Int(unsafe { raw_value.value.integer })),
400        vpi_sys::vpiRealVal => Some(Value::Real(unsafe { raw_value.value.real })),
401        vpi_sys::vpiStringVal => {
402            let c_str = unsafe { std::ffi::CStr::from_ptr(raw_value.value.str_) };
403            Some(Value::String(c_str.to_str().unwrap_or("").to_string()))
404        }
405        vpi_sys::vpiObjTypeVal => Some(Value::ObjType(unsafe { raw_value.value.integer })),
406        vpi_sys::vpiVectorVal => {
407            let vec_ptr = unsafe { raw_value.value.vector };
408            if vec_ptr.is_null() {
409                Some(Value::Vector(vec![]))
410            } else {
411                let size = if obj.is_null() {
412                    0usize
413                } else {
414                    unsafe { vpi_sys::vpi_get(vpi_sys::vpiSize as i32, obj) as usize }
415                };
416                let num_words = size.div_ceil(32);
417                let vec = unsafe { std::slice::from_raw_parts(vec_ptr, num_words) };
418                Some(Value::Vector(vector_value_to_scalar_vector(vec, size)))
419            }
420        }
421        vpi_sys::vpiStrengthVal => {
422            let strength: vpi_sys::t_vpi_strengthval = unsafe { *raw_value.value.strength };
423            Some(Value::Strength(StrengthValue::from(strength)))
424        }
425        vpi_sys::vpiTimeVal => {
426            let vpi_time: vpi_sys::t_vpi_time = unsafe { *raw_value.value.time };
427            Some(Value::Time(Time::from(vpi_time)))
428        }
429        vpi_sys::vpiShortIntVal => Some(Value::ShortInt(unsafe { raw_value.value.integer } as i16)),
430        _ => None,
431    }
432}
433
434/// Convert a binary-encoded [`ScalarValue`] slice (MSB at index 0) to a [`num_bigint::BigUint`].
435///
436/// Returns `None` if any element is not a definite binary value
437/// ([`ScalarValue::Zero`] or [`ScalarValue::One`]).
438/// Any `X`, `Z`, `H`, `L`, `DontCare`, or `NoChange` bit causes `None` to be returned.
439#[cfg(feature = "bigint")]
440#[must_use]
441pub fn scalar_vector_to_biguint(bits: &[ScalarValue]) -> Option<num_bigint::BigUint> {
442    let mut result = num_bigint::BigUint::ZERO;
443    for bit in bits {
444        result <<= 1u32;
445        match bit {
446            ScalarValue::Zero => {}
447            ScalarValue::One => result |= num_bigint::BigUint::from(1u32),
448            _ => return None,
449        }
450    }
451    Some(result)
452}
453
454/// Convert a `u64` to a binary-encoded [`Vec<ScalarValue>`] (MSB at index 0).
455///
456/// The returned vector always contains exactly `bits` elements. If `value`
457/// requires more than `bits` bits to represent, the most-significant bits are
458/// silently truncated.
459#[must_use]
460pub fn uint64_to_scalar_vector(value: u64, bits: usize) -> Vec<ScalarValue> {
461    (0..bits)
462        .rev()
463        .map(|i| {
464            if (value >> i) & 1 == 1 {
465                ScalarValue::One
466            } else {
467                ScalarValue::Zero
468            }
469        })
470        .collect()
471}
472
473/// Convert a binary-encoded [`ScalarValue`] slice (MSB at index 0) to a `u64`.
474///
475/// Returns `None` if the slice contains more than 64 bits or if any element is
476/// not a definite binary value ([`ScalarValue::Zero`] or [`ScalarValue::One`]).
477/// Any `X`, `Z`, `H`, `L`, `DontCare`, or `NoChange` bit causes `None` to be
478/// returned.
479#[must_use]
480pub fn scalar_vector_to_uint64(bits: &[ScalarValue]) -> Option<u64> {
481    if bits.len() > 64 {
482        return None;
483    }
484    let mut result: u64 = 0;
485    for bit in bits {
486        result <<= 1;
487        match bit {
488            ScalarValue::Zero => {}
489            ScalarValue::One => result |= 1,
490            _ => return None,
491        }
492    }
493    Some(result)
494}
495
496/// Convert a [`num_bigint::BigUint`] to a binary-encoded [`Vec<ScalarValue>`] (MSB at index 0).
497///
498/// The returned vector always contains exactly `bits` elements. If `value`
499/// requires more than `bits` bits to represent, the most-significant bits are
500/// silently truncated.
501#[cfg(feature = "bigint")]
502#[must_use]
503pub fn biguint_to_scalar_vector(value: &num_bigint::BigUint, bits: usize) -> Vec<ScalarValue> {
504    (0..bits)
505        .rev()
506        .map(|i| {
507            if value.bit(i as u64) {
508                ScalarValue::One
509            } else {
510                ScalarValue::Zero
511            }
512        })
513        .collect()
514}
515
516/// Convert an `i64` to a two's-complement-encoded [`Vec<ScalarValue>`] (MSB at index 0).
517///
518/// The returned vector always contains exactly `bits` elements. If `bits` is
519/// smaller than needed to represent the value, the most-significant bits are
520/// silently truncated.
521#[must_use]
522pub fn int64_to_scalar_vector(value: i64, bits: usize) -> Vec<ScalarValue> {
523    uint64_to_scalar_vector(value as u64, bits)
524}
525
526/// Convert a two's-complement-encoded [`ScalarValue`] slice (MSB at index 0) to an `i64`.
527///
528/// Returns `None` if the slice is empty, contains more than 64 bits, or if any
529/// element is not a definite binary value ([`ScalarValue::Zero`] or
530/// [`ScalarValue::One`]). Any `X`, `Z`, `H`, `L`, `DontCare`, or `NoChange`
531/// bit causes `None` to be returned.
532#[must_use]
533pub fn scalar_vector_to_int64(bits: &[ScalarValue]) -> Option<i64> {
534    if bits.is_empty() || bits.len() > 64 {
535        return None;
536    }
537    let unsigned = scalar_vector_to_uint64(bits)?;
538    // Sign-extend: if the MSB is 1, fill the upper bits.
539    let shift = 64 - bits.len();
540    Some((unsigned << shift) as i64 >> shift)
541}
542
543/// Convert a [`num_bigint::BigInt`] to a two's-complement-encoded [`Vec<ScalarValue>`]
544/// (MSB at index 0).
545///
546/// The returned vector always contains exactly `bits` elements. If `bits` is
547/// smaller than needed to represent the value, the most-significant bits are
548/// silently truncated.
549#[cfg(feature = "bigint")]
550#[must_use]
551pub fn bigint_to_scalar_vector(value: &num_bigint::BigInt, bits: usize) -> Vec<ScalarValue> {
552    use num_bigint::Sign;
553    // Two's complement: for negative numbers, add 2^bits to get the unsigned representation.
554    let unsigned: num_bigint::BigUint = if value.sign() == Sign::Minus {
555        let modulus = num_bigint::BigUint::from(1u32) << bits;
556        let mag = value.magnitude();
557        modulus - mag
558    } else {
559        value.magnitude().clone()
560    };
561    biguint_to_scalar_vector(&unsigned, bits)
562}
563
564/// Convert a two's-complement-encoded [`ScalarValue`] slice (MSB at index 0) to a
565/// [`num_bigint::BigInt`].
566///
567/// Returns `None` if the slice is empty or if any element is not a definite
568/// binary value ([`ScalarValue::Zero`] or [`ScalarValue::One`]). Any `X`, `Z`,
569/// `H`, `L`, `DontCare`, or `NoChange` bit causes `None` to be returned.
570#[cfg(feature = "bigint")]
571#[must_use]
572pub fn scalar_vector_to_bigint(bits: &[ScalarValue]) -> Option<num_bigint::BigInt> {
573    if bits.is_empty() {
574        return None;
575    }
576    let unsigned = scalar_vector_to_biguint(bits)?;
577    // If MSB is One the value is negative: subtract 2^n.
578    if bits[0] == ScalarValue::One {
579        let modulus = num_bigint::BigUint::from(1u32) << bits.len();
580        Some(num_bigint::BigInt::from(unsigned) - num_bigint::BigInt::from(modulus))
581    } else {
582        Some(num_bigint::BigInt::from(unsigned))
583    }
584}
585
586impl Handle {
587    /// Reads a value from this handle in the requested format.
588    ///
589    /// If `format` is [`ValueType::ObjType`], the simulator may override the
590    /// requested format with the object's native value format. In that case,
591    /// this method returns the matching concrete [`Value`] variant rather than
592    /// always returning [`Value::ObjType`].
593    ///
594    /// Returns `None` for null handles or unsupported formats.
595    #[must_use]
596    pub fn get_value(&self, format: ValueType) -> Option<Value> {
597        if self.is_null() {
598            return None;
599        }
600        let mut value = vpi_sys::t_vpi_value {
601            format: format as i32,
602            value: vpi_sys::t_vpi_value__bindgen_ty_1 { integer: 0 },
603        };
604        unsafe { vpi_sys::vpi_get_value(self.as_raw(), &raw mut value) };
605        decode_vpi_value(value, self.as_raw())
606    }
607
608    /// Retrieve an array of values from a Verilog object (e.g., memory array, packet array).
609    ///
610    /// This function calls `vpi_get_value_array` to fetch multiple values at once.
611    /// It handles various value formats and automatically allocates the necessary memory.
612    ///
613    /// # Arguments
614    /// * `format` - The format of values to retrieve (Int, Real, Time, etc.)
615    ///
616    /// # Returns
617    /// * `Some(Vec<Value>)` - A vector of retrieved values
618    /// * `None` - If the handle is null or the operation fails
619    ///
620    /// # Example
621    /// ```ignore
622    /// let mem = root.scan(vpi_sys::vpiMem)?;
623    /// if let Some(values) = mem.get_value_array(ValueType::Int) {
624    ///     for (i, val) in values.iter().enumerate() {
625    ///         println!("Memory[{}] = {}", i, val);
626    ///     }
627    /// }
628    /// ```
629    #[must_use]
630    pub fn get_value_array(&self, format: ValueType) -> Option<Vec<Value>> {
631        if self.is_null() {
632            return None;
633        }
634
635        let size =
636            unsafe { vpi_sys::vpi_get(vpi_sys::vpiSize as PLI_INT32, self.as_raw()) } as usize;
637
638        if size == 0 {
639            return Some(Vec::new());
640        }
641
642        match format {
643            ValueType::Int => {
644                let mut integers: Vec<i32> = vec![0; size];
645                let mut arrayvalue = vpi_sys::t_vpi_arrayvalue {
646                    format: vpi_sys::vpiIntVal,
647                    flags: 0,
648                    value: vpi_sys::t_vpi_arrayvalue__bindgen_ty_1 {
649                        integers: integers.as_mut_ptr(),
650                    },
651                };
652                let mut index = 0;
653
654                unsafe {
655                    vpi_sys::vpi_get_value_array(
656                        self.as_raw(),
657                        &raw mut arrayvalue,
658                        &raw mut index,
659                        size as PLI_UINT32,
660                    );
661                }
662
663                Some(integers.into_iter().map(Value::Int).collect::<Vec<Value>>())
664            }
665            ValueType::Real => {
666                let mut reals: Vec<f64> = vec![0.0; size];
667                let mut arrayvalue = vpi_sys::t_vpi_arrayvalue {
668                    format: vpi_sys::vpiRealVal,
669                    flags: 0,
670                    value: vpi_sys::t_vpi_arrayvalue__bindgen_ty_1 {
671                        reals: reals.as_mut_ptr(),
672                    },
673                };
674                let mut index = 0;
675
676                unsafe {
677                    vpi_sys::vpi_get_value_array(
678                        self.as_raw(),
679                        &raw mut arrayvalue,
680                        &raw mut index,
681                        size as PLI_UINT32,
682                    );
683                }
684
685                Some(reals.into_iter().map(Value::Real).collect::<Vec<Value>>())
686            }
687            ValueType::Time => {
688                let mut times: Vec<vpi_sys::t_vpi_time> = vec![
689                    vpi_sys::t_vpi_time {
690                        type_: 0,
691                        high: 0,
692                        low: 0,
693                        real: 0.0,
694                    };
695                    size
696                ];
697                let mut arrayvalue = vpi_sys::t_vpi_arrayvalue {
698                    format: vpi_sys::vpiTimeVal,
699                    flags: 0,
700                    value: vpi_sys::t_vpi_arrayvalue__bindgen_ty_1 {
701                        times: times.as_mut_ptr(),
702                    },
703                };
704                let mut index = 0;
705
706                unsafe {
707                    vpi_sys::vpi_get_value_array(
708                        self.as_raw(),
709                        &raw mut arrayvalue,
710                        &raw mut index,
711                        size as PLI_UINT32,
712                    );
713                }
714
715                Some(
716                    times
717                        .into_iter()
718                        .map(|t| {
719                            let vpi_time = vpi_sys::s_vpi_time {
720                                type_: t.type_,
721                                high: t.high,
722                                low: t.low,
723                                real: t.real,
724                            };
725                            Value::Time(Time::from(vpi_time))
726                        })
727                        .collect::<Vec<Value>>(),
728                )
729            }
730            ValueType::ShortInt => {
731                let mut shortints: Vec<i16> = vec![0; size];
732                let mut arrayvalue = vpi_sys::t_vpi_arrayvalue {
733                    format: vpi_sys::vpiShortIntVal,
734                    flags: 0,
735                    value: vpi_sys::t_vpi_arrayvalue__bindgen_ty_1 {
736                        shortints: shortints.as_mut_ptr(),
737                    },
738                };
739                let mut index = 0;
740
741                unsafe {
742                    vpi_sys::vpi_get_value_array(
743                        self.as_raw(),
744                        &raw mut arrayvalue,
745                        &raw mut index,
746                        size as PLI_UINT32,
747                    );
748                }
749
750                Some(
751                    shortints
752                        .into_iter()
753                        .map(Value::ShortInt)
754                        .collect::<Vec<Value>>(),
755                )
756            }
757            ValueType::LongInt => {
758                let mut longints: Vec<i64> = vec![0; size];
759                let mut arrayvalue = vpi_sys::t_vpi_arrayvalue {
760                    format: vpi_sys::vpiLongIntVal,
761                    flags: 0,
762                    value: vpi_sys::t_vpi_arrayvalue__bindgen_ty_1 {
763                        longints: longints.as_mut_ptr(),
764                    },
765                };
766                let mut index = 0;
767
768                unsafe {
769                    vpi_sys::vpi_get_value_array(
770                        self.as_raw(),
771                        &raw mut arrayvalue,
772                        &raw mut index,
773                        size as PLI_UINT32,
774                    );
775                }
776
777                Some(
778                    longints
779                        .into_iter()
780                        .map(Value::LongInt)
781                        .collect::<Vec<Value>>(),
782                )
783            }
784            ValueType::ShortReal => {
785                let mut shortreals: Vec<f32> = vec![0.0; size];
786                let mut arrayvalue = vpi_sys::t_vpi_arrayvalue {
787                    format: vpi_sys::vpiShortRealVal,
788                    flags: 0,
789                    value: vpi_sys::t_vpi_arrayvalue__bindgen_ty_1 {
790                        shortreals: shortreals.as_mut_ptr(),
791                    },
792                };
793                let mut index = 0;
794
795                unsafe {
796                    vpi_sys::vpi_get_value_array(
797                        self.as_raw(),
798                        &raw mut arrayvalue,
799                        &raw mut index,
800                        size as PLI_UINT32,
801                    );
802                }
803
804                Some(
805                    shortreals
806                        .into_iter()
807                        .map(Value::ShortReal)
808                        .collect::<Vec<Value>>(),
809                )
810            }
811            ValueType::Vector => {
812                // For vector arrays, each element needs to be read individually
813                // as the size calculation is different (bits per element vs. total bits)
814                let mut values = Vec::with_capacity(size);
815                for _ in 0..size {
816                    if let Some(val) = self.get_value(ValueType::Vector) {
817                        values.push(val);
818                    }
819                }
820                Some(values)
821            }
822            ValueType::Scalar => {
823                // For scalar arrays
824                let mut rawvals: Vec<vpi_sys::PLI_BYTE8> = vec![0; size];
825                let mut arrayvalue = vpi_sys::t_vpi_arrayvalue {
826                    format: vpi_sys::vpiScalarVal,
827                    flags: 0,
828                    value: vpi_sys::t_vpi_arrayvalue__bindgen_ty_1 {
829                        rawvals: rawvals.as_mut_ptr(),
830                    },
831                };
832                let mut index = 0;
833
834                unsafe {
835                    vpi_sys::vpi_get_value_array(
836                        self.as_raw(),
837                        &raw mut arrayvalue,
838                        &raw mut index,
839                        size as PLI_UINT32,
840                    );
841                }
842
843                Some(
844                    rawvals
845                        .into_iter()
846                        .filter_map(|v| ScalarValue::from_u32(v as u32).map(Value::Scalar))
847                        .collect::<Vec<Value>>(),
848                )
849            }
850            _ => {
851                // For unsupported types, return empty vector
852                Some(Vec::new())
853            }
854        }
855    }
856
857    /// Returns whether this handle represents an array object.
858    #[must_use]
859    pub fn is_array(&self) -> bool {
860        if self.is_null() {
861            return false;
862        }
863        self.get_bool(Property::Array) == Some(true)
864    }
865}
866
867#[cfg(test)]
868mod tests {
869    use super::{
870        int64_to_scalar_vector, scalar_vector_to_int64, scalar_vector_to_uint64,
871        uint64_to_scalar_vector, vector_value_to_scalar_vector, ScalarValue, StrengthEncoding,
872        Value, ValueType,
873    };
874
875    fn scalar_vec_to_string(values: Vec<ScalarValue>) -> String {
876        values.into_iter().map(|value| value.to_string()).collect()
877    }
878
879    #[test]
880    fn vector_value_decodes_ab_encoding_and_reverses_bit_order() {
881        let vec = [vpi_sys::t_vpi_vecval {
882            aval: 0b1010,
883            bval: 0b1100,
884        }];
885        let decoded = vector_value_to_scalar_vector(&vec, 4);
886
887        assert_eq!(scalar_vec_to_string(decoded), "XZ10");
888    }
889
890    #[test]
891    fn vector_value_uses_zero_when_words_are_missing() {
892        let decoded = vector_value_to_scalar_vector(&[], 3);
893
894        assert_eq!(scalar_vec_to_string(decoded), "000");
895    }
896
897    #[test]
898    fn raw_two_state_display_renders_binary_string() {
899        let value = Value::RawTwoState(vec![true, false, true, true, false]);
900
901        assert_eq!(value.to_string(), "10110");
902    }
903
904    #[test]
905    fn raw_four_state_display_renders_scalar_symbols() {
906        let value = Value::RawFourState(vec![
907            ScalarValue::Zero,
908            ScalarValue::One,
909            ScalarValue::X,
910            ScalarValue::Z,
911            ScalarValue::DontCare,
912            ScalarValue::NoChange,
913        ]);
914
915        assert_eq!(value.to_string(), "01XZ-N");
916    }
917
918    #[test]
919    fn strength_encoding_display_joins_active_flags_in_order() {
920        let strength = StrengthEncoding::StrongDrive | StrengthEncoding::HiZ;
921
922        assert_eq!(strength.to_string(), "StrongDrive | HiZ");
923    }
924
925    #[test]
926    fn value_type_display_has_human_readable_labels() {
927        assert_eq!(ValueType::RawFourState.to_string(), "Raw Four-State Vector");
928        assert_eq!(ValueType::ShortInt.to_string(), "Short Integer");
929    }
930
931    #[test]
932    fn scalar_vector_to_uint64_converts_binary_bits() {
933        let bits = vec![
934            ScalarValue::One,
935            ScalarValue::Zero,
936            ScalarValue::One,
937            ScalarValue::One,
938        ];
939        assert_eq!(scalar_vector_to_uint64(&bits), Some(0b1011));
940    }
941
942    #[test]
943    fn scalar_vector_to_uint64_all_zeros() {
944        let bits = vec![ScalarValue::Zero; 8];
945        assert_eq!(scalar_vector_to_uint64(&bits), Some(0));
946    }
947
948    #[test]
949    fn scalar_vector_to_uint64_returns_none_for_x_bit() {
950        let bits = vec![ScalarValue::One, ScalarValue::X, ScalarValue::Zero];
951        assert_eq!(scalar_vector_to_uint64(&bits), None);
952    }
953
954    #[test]
955    fn scalar_vector_to_uint64_returns_none_for_z_bit() {
956        let bits = vec![ScalarValue::Zero, ScalarValue::Z];
957        assert_eq!(scalar_vector_to_uint64(&bits), None);
958    }
959
960    #[test]
961    fn scalar_vector_to_uint64_returns_none_for_over_64_bits() {
962        let bits = vec![ScalarValue::Zero; 65];
963        assert_eq!(scalar_vector_to_uint64(&bits), None);
964    }
965
966    #[test]
967    fn scalar_vector_to_uint64_accepts_exactly_64_bits() {
968        let mut bits = vec![ScalarValue::Zero; 63];
969        bits.push(ScalarValue::One);
970        assert_eq!(scalar_vector_to_uint64(&bits), Some(1));
971    }
972
973    #[test]
974    fn uint64_to_scalar_vector_converts_value() {
975        assert_eq!(
976            uint64_to_scalar_vector(0b1011, 4),
977            vec![
978                ScalarValue::One,
979                ScalarValue::Zero,
980                ScalarValue::One,
981                ScalarValue::One
982            ]
983        );
984    }
985
986    #[test]
987    fn uint64_to_scalar_vector_pads_with_zeros() {
988        assert_eq!(
989            uint64_to_scalar_vector(0b101, 6),
990            vec![
991                ScalarValue::Zero,
992                ScalarValue::Zero,
993                ScalarValue::Zero,
994                ScalarValue::One,
995                ScalarValue::Zero,
996                ScalarValue::One,
997            ]
998        );
999    }
1000
1001    #[test]
1002    fn uint64_to_scalar_vector_truncates_high_bits() {
1003        // Only the lowest 4 bits of 0b11011 should appear
1004        assert_eq!(
1005            uint64_to_scalar_vector(0b11011, 4),
1006            vec![
1007                ScalarValue::One,
1008                ScalarValue::Zero,
1009                ScalarValue::One,
1010                ScalarValue::One
1011            ]
1012        );
1013    }
1014
1015    #[test]
1016    fn uint64_to_scalar_vector_zero_bits_returns_empty() {
1017        assert_eq!(uint64_to_scalar_vector(42, 0), vec![]);
1018    }
1019
1020    #[test]
1021    fn int64_to_scalar_vector_positive_value() {
1022        assert_eq!(
1023            int64_to_scalar_vector(5, 4),
1024            vec![
1025                ScalarValue::Zero,
1026                ScalarValue::One,
1027                ScalarValue::Zero,
1028                ScalarValue::One
1029            ]
1030        );
1031    }
1032
1033    #[test]
1034    fn int64_to_scalar_vector_negative_value() {
1035        // -1 in 4-bit two's complement is 1111
1036        assert_eq!(
1037            int64_to_scalar_vector(-1, 4),
1038            vec![
1039                ScalarValue::One,
1040                ScalarValue::One,
1041                ScalarValue::One,
1042                ScalarValue::One
1043            ]
1044        );
1045    }
1046
1047    #[test]
1048    fn int64_to_scalar_vector_min_negative() {
1049        // -8 in 4-bit two's complement is 1000
1050        assert_eq!(
1051            int64_to_scalar_vector(-8, 4),
1052            vec![
1053                ScalarValue::One,
1054                ScalarValue::Zero,
1055                ScalarValue::Zero,
1056                ScalarValue::Zero
1057            ]
1058        );
1059    }
1060
1061    #[test]
1062    fn scalar_vector_to_int64_positive() {
1063        let bits = vec![
1064            ScalarValue::Zero,
1065            ScalarValue::One,
1066            ScalarValue::Zero,
1067            ScalarValue::One,
1068        ];
1069        assert_eq!(scalar_vector_to_int64(&bits), Some(5));
1070    }
1071
1072    #[test]
1073    fn scalar_vector_to_int64_negative() {
1074        // 1111 in two's complement is -1
1075        let bits = vec![
1076            ScalarValue::One,
1077            ScalarValue::One,
1078            ScalarValue::One,
1079            ScalarValue::One,
1080        ];
1081        assert_eq!(scalar_vector_to_int64(&bits), Some(-1));
1082    }
1083
1084    #[test]
1085    fn scalar_vector_to_int64_min_negative() {
1086        // 1000 in 4-bit two's complement is -8
1087        let bits = vec![
1088            ScalarValue::One,
1089            ScalarValue::Zero,
1090            ScalarValue::Zero,
1091            ScalarValue::Zero,
1092        ];
1093        assert_eq!(scalar_vector_to_int64(&bits), Some(-8));
1094    }
1095
1096    #[test]
1097    fn scalar_vector_to_int64_returns_none_for_empty() {
1098        assert_eq!(scalar_vector_to_int64(&[]), None);
1099    }
1100
1101    #[test]
1102    fn scalar_vector_to_int64_returns_none_for_over_64_bits() {
1103        let bits = vec![ScalarValue::Zero; 65];
1104        assert_eq!(scalar_vector_to_int64(&bits), None);
1105    }
1106
1107    #[test]
1108    fn scalar_vector_to_int64_returns_none_for_x_bit() {
1109        let bits = vec![ScalarValue::One, ScalarValue::X];
1110        assert_eq!(scalar_vector_to_int64(&bits), None);
1111    }
1112
1113    #[cfg(feature = "bigint")]
1114    mod bigint_tests {
1115        use num_bigint::{BigInt, BigUint};
1116
1117        use super::super::{
1118            bigint_to_scalar_vector, biguint_to_scalar_vector, scalar_vector_to_bigint,
1119            scalar_vector_to_biguint, ScalarValue,
1120        };
1121
1122        #[test]
1123        fn scalar_vector_to_biguint_converts_binary_bits() {
1124            let bits = vec![
1125                ScalarValue::One,
1126                ScalarValue::Zero,
1127                ScalarValue::One,
1128                ScalarValue::One,
1129            ];
1130            assert_eq!(
1131                scalar_vector_to_biguint(&bits),
1132                Some(BigUint::from(0b1011u32))
1133            );
1134        }
1135
1136        #[test]
1137        fn scalar_vector_to_biguint_all_zeros() {
1138            let bits = vec![ScalarValue::Zero; 8];
1139            assert_eq!(scalar_vector_to_biguint(&bits), Some(BigUint::ZERO));
1140        }
1141
1142        #[test]
1143        fn scalar_vector_to_biguint_empty_slice() {
1144            assert_eq!(scalar_vector_to_biguint(&[]), Some(BigUint::ZERO));
1145        }
1146
1147        #[test]
1148        fn scalar_vector_to_biguint_returns_none_for_x_bit() {
1149            let bits = vec![ScalarValue::One, ScalarValue::X, ScalarValue::Zero];
1150            assert_eq!(scalar_vector_to_biguint(&bits), None);
1151        }
1152
1153        #[test]
1154        fn scalar_vector_to_biguint_returns_none_for_z_bit() {
1155            let bits = vec![ScalarValue::Zero, ScalarValue::Z];
1156            assert_eq!(scalar_vector_to_biguint(&bits), None);
1157        }
1158
1159        #[test]
1160        fn scalar_vector_to_biguint_exceeds_64_bits() {
1161            let mut bits = vec![ScalarValue::Zero; 64];
1162            bits.push(ScalarValue::One);
1163            // 65-bit value: should still work (no 64-bit limit)
1164            assert_eq!(scalar_vector_to_biguint(&bits), Some(BigUint::from(1u32)));
1165        }
1166
1167        #[test]
1168        fn biguint_to_scalar_vector_converts_value() {
1169            assert_eq!(
1170                biguint_to_scalar_vector(&BigUint::from(0b1011u32), 4),
1171                vec![
1172                    ScalarValue::One,
1173                    ScalarValue::Zero,
1174                    ScalarValue::One,
1175                    ScalarValue::One
1176                ]
1177            );
1178        }
1179
1180        #[test]
1181        fn biguint_to_scalar_vector_pads_with_zeros() {
1182            assert_eq!(
1183                biguint_to_scalar_vector(&BigUint::from(0b101u32), 6),
1184                vec![
1185                    ScalarValue::Zero,
1186                    ScalarValue::Zero,
1187                    ScalarValue::Zero,
1188                    ScalarValue::One,
1189                    ScalarValue::Zero,
1190                    ScalarValue::One,
1191                ]
1192            );
1193        }
1194
1195        #[test]
1196        fn biguint_to_scalar_vector_truncates_high_bits() {
1197            // Only the lowest 4 bits of 0b11011 should appear
1198            assert_eq!(
1199                biguint_to_scalar_vector(&BigUint::from(0b11011u32), 4),
1200                vec![
1201                    ScalarValue::One,
1202                    ScalarValue::Zero,
1203                    ScalarValue::One,
1204                    ScalarValue::One
1205                ]
1206            );
1207        }
1208
1209        #[test]
1210        fn biguint_to_scalar_vector_zero_bits_returns_empty() {
1211            assert_eq!(biguint_to_scalar_vector(&BigUint::from(42u32), 0), vec![]);
1212        }
1213
1214        #[test]
1215        fn biguint_to_scalar_vector_exceeds_64_bits() {
1216            let value = BigUint::from(1u32) << 64u32;
1217            let mut expected = vec![ScalarValue::One];
1218            expected.extend(vec![ScalarValue::Zero; 64]);
1219            assert_eq!(biguint_to_scalar_vector(&value, 65), expected);
1220        }
1221
1222        #[test]
1223        fn bigint_to_scalar_vector_positive_value() {
1224            assert_eq!(
1225                bigint_to_scalar_vector(&BigInt::from(5), 4),
1226                vec![
1227                    ScalarValue::Zero,
1228                    ScalarValue::One,
1229                    ScalarValue::Zero,
1230                    ScalarValue::One
1231                ]
1232            );
1233        }
1234
1235        #[test]
1236        fn bigint_to_scalar_vector_negative_one() {
1237            // -1 in 4-bit two's complement is 1111
1238            assert_eq!(
1239                bigint_to_scalar_vector(&BigInt::from(-1), 4),
1240                vec![
1241                    ScalarValue::One,
1242                    ScalarValue::One,
1243                    ScalarValue::One,
1244                    ScalarValue::One
1245                ]
1246            );
1247        }
1248
1249        #[test]
1250        fn bigint_to_scalar_vector_large_negative() {
1251            // -1 in 65-bit two's complement: all ones
1252            let expected = vec![ScalarValue::One; 65];
1253            assert_eq!(bigint_to_scalar_vector(&BigInt::from(-1), 65), expected);
1254        }
1255
1256        #[test]
1257        fn scalar_vector_to_bigint_positive() {
1258            let bits = vec![
1259                ScalarValue::Zero,
1260                ScalarValue::One,
1261                ScalarValue::Zero,
1262                ScalarValue::One,
1263            ];
1264            assert_eq!(scalar_vector_to_bigint(&bits), Some(BigInt::from(5)));
1265        }
1266
1267        #[test]
1268        fn scalar_vector_to_bigint_negative_one() {
1269            // 1111 in 4-bit two's complement is -1
1270            let bits = vec![
1271                ScalarValue::One,
1272                ScalarValue::One,
1273                ScalarValue::One,
1274                ScalarValue::One,
1275            ];
1276            assert_eq!(scalar_vector_to_bigint(&bits), Some(BigInt::from(-1)));
1277        }
1278
1279        #[test]
1280        fn scalar_vector_to_bigint_large_negative() {
1281            // 65 ones = -1 in 65-bit two's complement
1282            let bits = vec![ScalarValue::One; 65];
1283            assert_eq!(scalar_vector_to_bigint(&bits), Some(BigInt::from(-1)));
1284        }
1285
1286        #[test]
1287        fn scalar_vector_to_bigint_returns_none_for_empty() {
1288            assert_eq!(scalar_vector_to_bigint(&[]), None);
1289        }
1290
1291        #[test]
1292        fn scalar_vector_to_bigint_returns_none_for_x_bit() {
1293            let bits = vec![ScalarValue::One, ScalarValue::X];
1294            assert_eq!(scalar_vector_to_bigint(&bits), None);
1295        }
1296    }
1297}