libreda-lefdef 0.0.5

LEF/DEF input/output for libreda-db.
Documentation
// Copyright (c) 2021-2021 Thomas Kramer.
// SPDX-FileCopyrightText: 2022 Thomas Kramer <code@tkramer.ch>
//
// SPDX-License-Identifier: AGPL-3.0-or-later

//! Data types and parser functions used for both LEF and DEF.

use crate::stream_parser::{LefDefLexer, LefDefParseError};
use itertools::PeekingNext;
use libreda_stream_parser::{tokenize, Tokenized};
use std::fmt;
use std::str::FromStr;

/// Data type of a property value.
#[derive(Clone, Debug)]
pub enum PropertyType {
    /// Integer number.
    Integer,
    /// Floating point number.
    Real,
    /// String.
    String,
}

impl FromStr for PropertyType {
    type Err = ();

    fn from_str(input: &str) -> Result<Self, Self::Err> {
        match input {
            "INTEGER" => Ok(Self::Integer),
            "REAL" => Ok(Self::Real),
            "STRING" => Ok(Self::String),
            _ => Err(()),
        }
    }
}

impl fmt::Display for PropertyType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::Integer => f.write_str("INTEGER"),
            Self::Real => f.write_str("REAL"),
            Self::String => f.write_str("STRING"),
        }
    }
}

/// Value of a LEF/DEF property.
#[derive(Clone, Debug)]
pub enum PropertyValue {
    /// Integer.
    Int(i32),
    /// Floating point number.
    Real(f64),
    /// Quoted ASCII string.
    String(String),
}

impl fmt::Display for PropertyValue {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            PropertyValue::Int(v) => write!(f, "{}", v),
            PropertyValue::Real(v) => write!(f, "{}", v),
            PropertyValue::String(v) => write!(f, r#""{}""#, v),
        }
    }
}

/// Read a point of the form `( x y )`, `x y` or `( x , y )`.
pub fn read_point<T: FromStr, I>(
    tokens: &mut Tokenized<I, LefDefLexer>,
) -> Result<(T, T), LefDefParseError>
where
    I: Iterator<Item = char> + PeekingNext,
{
    // Points should be declared in parenthesis. This is not always the case though.
    let uses_parentheses = tokens.test_str("(")?;
    let x: T = tokens.take_and_parse()?;
    tokens.test_str(",")?;
    let y: T = tokens.take_and_parse()?;
    if uses_parentheses {
        tokens.expect_str(")")?;
    }

    Ok((x, y))
}

/// Read a polygon. Does not expect 'POLYGON' token at the beginning.
pub fn read_polygon<T: FromStr, I>(
    tokens: &mut Tokenized<I, LefDefLexer>,
) -> Result<Vec<(T, T)>, LefDefParseError>
where
    I: Iterator<Item = char> + PeekingNext,
{
    // Read points until ';'.
    let mut points = Vec::new();
    loop {
        if tokens.test_str(";")? {
            break;
        } else {
            points.push(read_point(tokens)?);
        }
    }

    Ok(points)
}

/// Read a rectangle of the form `( x1 y1 ) ( x2 y2 )`.
pub fn read_rect<T: FromStr, I>(
    tokens: &mut Tokenized<I, LefDefLexer>,
) -> Result<((T, T), (T, T)), LefDefParseError>
where
    I: Iterator<Item = char> + PeekingNext,
{
    let p1 = read_point(tokens)?;
    let p2 = read_point(tokens)?;

    Ok((p1, p2))
}

/// Macro orientations that can be used by the placer.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
pub struct Symmetry {
    /// Mirroring macro at x-axis.
    x: bool,
    /// Mirroring macro at y-axis.
    y: bool,
    /// Rotating by 90 degrees. Intended for pad cells only.
    r90: bool,
}

impl Symmetry {
    /// Create a new symmetry definition.
    pub fn new(x: bool, y: bool, r90: bool) -> Self {
        Self { x, y, r90 }
    }

    /// Mirror symmetry at x-axis.
    pub fn x() -> Self {
        Self::new(true, false, false)
    }
    /// Mirror symmetry at y-axis.
    pub fn y() -> Self {
        Self::new(false, true, false)
    }
    /// Rotation by 90 degrees.
    pub fn r90() -> Self {
        Self::new(false, false, true)
    }

    /// Take the union of the both symmetry definitions.
    pub fn union(self, other: Self) -> Self {
        Self {
            x: self.x | other.x,
            y: self.y | other.y,
            r90: self.r90 | other.r90,
        }
    }
}

impl FromStr for Symmetry {
    type Err = ();

    fn from_str(input: &str) -> Result<Self, Self::Err> {
        match input {
            "X" => Ok(Self::x()),
            "Y" => Ok(Self::y()),
            "R90" => Ok(Self::r90()),
            _ => Err(()),
        }
    }
}

impl fmt::Display for Symmetry {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        if self.x {
            f.write_str("X")?;
        }
        if self.y {
            f.write_str("Y")?;
        }
        if self.r90 {
            f.write_str("R90")?;
        }

        Ok(())
    }
}

/// Antenna rule definitions.
#[derive(Clone, Debug, Default)]
pub struct AntennaRules {
    /// Antenna model.
    model: (),
    area_ratio: (),
    diff_area_ration: (),
    cum_area_ratio: (),
    cum_diff_area_ratio: (),
    // ...
}

/// Orientation, consists of rotation and mirroring.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum Orient {
    /// North.
    N,
    /// South.
    S,
    /// East.
    E,
    /// West.
    W,
    /// Flipped North.
    FN,
    /// Flipped South.
    FS,
    /// FLipped East.
    FE,
    /// Flipped West.
    FW,
}

impl Default for Orient {
    fn default() -> Self {
        Self::N
    }
}

impl Orient {
    /// Decompose into a non-flipped orientation and a flag telling whether the orientation is flipped
    /// or not.
    /// Flipping is applied after rotation. Flips happen about the y-axis (switching left-right).
    ///
    /// Returns `(orientation, is_flipped)`.
    pub fn decomposed(&self) -> (Self, bool) {
        match self {
            Orient::FN => (Orient::N, true),
            Orient::FS => (Orient::S, true),
            Orient::FE => (Orient::E, true),
            Orient::FW => (Orient::W, true),
            other => (*other, false),
        }
    }

    /// Returns the flipped orientation.
    /// For example turns a `N` into a `FN`.
    pub fn flipped(&self) -> Self {
        use Orient::*;
        match self {
            N => FN,
            S => FS,
            E => FE,
            W => FW,
            FN => N,
            FS => S,
            FE => E,
            FW => W,
        }
    }
}

impl FromStr for Orient {
    type Err = ();

    fn from_str(input: &str) -> Result<Self, Self::Err> {
        match input {
            "N" => Ok(Self::N),
            "S" => Ok(Self::S),
            "E" => Ok(Self::E),
            "W" => Ok(Self::W),
            "FN" => Ok(Self::FN),
            "FS" => Ok(Self::FS),
            "FE" => Ok(Self::FE),
            "FW" => Ok(Self::FW),
            _ => Err(()),
        }
    }
}

impl fmt::Display for Orient {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::N => f.write_str("N"),
            Self::S => f.write_str("S"),
            Self::E => f.write_str("E"),
            Self::W => f.write_str("W"),
            Self::FN => f.write_str("FN"),
            Self::FS => f.write_str("FS"),
            Self::FE => f.write_str("FE"),
            Self::FW => f.write_str("FW"),
        }
    }
}

/// Signal direction of a pin.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum PinDirection {
    /// INPUT
    Input,
    /// OUTPUT. Is TRISTATE when the boolean flag is set.
    Output(bool),
    /// INOUT: Both input and output.
    Inout,
    /// FEEDTHRU: Pin crosses the cell. Direct electrical connection.
    Feedthru,
}

impl FromStr for PinDirection {
    type Err = ();

    fn from_str(input: &str) -> Result<Self, Self::Err> {
        match input {
            "INPUT" => Ok(Self::Input),
            "OUTPUT" => Ok(Self::Output(false)),
            "INOUT" => Ok(Self::Inout),
            "FEEDTHRU" => Ok(Self::Feedthru),
            _ => Err(()),
        }
    }
}

impl fmt::Display for PinDirection {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::Input => f.write_str("INPUT"),
            Self::Output(false) => f.write_str("OUTPUT"),
            Self::Output(true) => f.write_str("OUTPUT TRISTATE"),
            Self::Inout => f.write_str("INOUT"),
            Self::Feedthru => f.write_str("FEEDTHRU"),
        }
    }
}