spefparse 0.2.0

SPEF parasitics parser
Documentation
//! Standard parasitics exchange format (SPEF) parser.
//!
//! ## How to use
//! See [`SPEF::parse_str`].
//!
//! We also support transforming a SPEF object to a SPEF source
//! code, by using [`std::fmt::Display`].
//!
//! ## Misc
//! This parser obeys the IEEE 1481-1998 standard, with some
//! notable exceptions (to be addressed in future work):
//!
//! 1. prefix bus delimiter `:`, `.` unsupported (because they interfere with hchar.), and empty suffix bus delimiter is unsupported yet.
//! 2. sensitivity is unsupported in cap and res defs. and slew threshold is unsupported in conn attr.
//! 3. Pi model is unsupported.

use compact_str::CompactString;
use std::sync::Arc;

/// SPEF main struct.
/// It contains headers, top ports, and nets.
///
/// SPEF can be constructed by parsing a source `&str` using
/// [`SPEF::parse_str`].
/// SPEF can be dumpped to a source file string using
/// [`std::fmt::Display`].
#[derive(Debug)]
pub struct SPEF {
    pub header: SPEFHeader,
    pub top_ports: Vec<SPEFPort>,
    pub nets: Vec<SPEFNet>,
}

/// SPEF header (from `*SPEF` to `*L_UNIT`).
#[derive(Debug)]
pub struct SPEFHeader {
    pub edition: CompactString,  // "IEEE 1481-1998"
    pub design: CompactString,
    pub date: CompactString,
    pub vendor: CompactString,
    pub program: CompactString,
    pub version: CompactString,
    pub design_flow: Vec<CompactString>,
    pub divider: char,
    pub delimiter: char,
    pub bus_delimiter_left: char,
    pub bus_delimiter_right: char,
    pub time_unit: f32,
    pub cap_unit: f32,
    pub res_unit: f32,
    pub induct_unit: f32
}

/// Direction in SPEF.
///
/// (I don't know why there is yet another direction definition
/// on par with what's inside netlistdb, sverilogparse, and
/// libertyparse.)
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum Direction {
    /// Input
    I,
    /// Output
    O,
    /// Bidirectional
    B
}

/// It seems this means min, nominal, and max.
#[derive(Debug, PartialEq, Copy, Clone)]  // no Eq.
pub enum ParValue {
    Single(f32),
    Three(f32, f32, f32)
}

mod hier_name;
pub use hier_name::HierName;

/// Port or pin reference.
/// 
/// The tuple contains hier name,
/// (optional, port => None, pin => Some) macro pin name,
/// and (optional) bit index.
///
/// Please note that this reference cannot be directly used as
/// key to netlistdb cells/pins/nets. You may create
/// your own wrapper type on top of this. (We should do this
/// in the current crate in the future.)
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct SPEFHierPortPinRef(pub Arc<HierName>, pub Option<CompactString>, pub Option<isize>);

/// A piece of connectivity information in SPEF.
///
/// In the sense of `*C ... *L ... *S ... *D ...`.
#[derive(Debug)]
pub struct SPEFConnAttr {
    pub coords: Option<(f32, f32)>,
    pub cap_load: Option<ParValue>,
    pub slew: Option<(ParValue, ParValue)>,
    pub driving_cell: Option<CompactString>
}

/// A port in SPEF.
#[derive(Debug)]
pub struct SPEFPort {
    /// The `name.1` (macro pin name) is guaranteed to be None,
    /// because this is a port.
    pub name: SPEFHierPortPinRef,
    pub direction: Direction,
    pub conn_attr: SPEFConnAttr
}

/// A net in SPEF.
#[derive(Debug)]
pub struct SPEFNet {
    pub name: SPEFHierPortPinRef,
    pub total_cap: f32,
    pub conns: Vec<SPEFNetConn>,
    pub caps: Vec<SPEFNetCap>,
    pub ress: Vec<SPEFNetRes>
}

/// A connection entry of a net.
#[derive(Debug)]
pub struct SPEFNetConn {
    pub name: SPEFHierPortPinRef,
    pub direction: Direction,
    pub conn_attr: SPEFConnAttr
}

/// A capacitance entry of a net.
#[derive(Debug)]
pub struct SPEFNetCap {
    pub a: SPEFHierPortPinRef,
    /// Optional secondary pin with which the cap is set up.
    /// If not provided, the cap is a grounded capacitance.
    /// If provided, it becomes a coupling capacitance.
    pub b: Option<SPEFHierPortPinRef>,
    pub val: ParValue
}

/// A resistance entry of a net.
#[derive(Debug)]
pub struct SPEFNetRes {
    pub a: SPEFHierPortPinRef,
    pub b: SPEFHierPortPinRef,
    pub val: ParValue
}

/// SPEF parser in PEG (Pest).
mod spefpest;

/// SPEF writer.
mod fmt;

impl SPEF {
    /// Parse a SPEF source string to the SPEF object.
    /// This is the main entry.
    ///
    /// On error, it returns a pretty string message indicating where
    /// it is not working.
    #[inline]
    pub fn parse_str(s: &str) -> Result<SPEF, String> {
        spefpest::parse_spef(s)
    }
}