LEF/DEF input and output module for LibrEDA.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

327 lines
8.1 KiB

/*
* Copyright (c) 2021-2021 Thomas Kramer.
*
* This file is part of LibrEDA
* (see https://codeberg.org/libreda/libreda-lefdef).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//! Data types and parser functions used for both LEF and DEF.
use std::str::FromStr;
use std::fmt;
use crate::stream_parser::{Tokenized, LefDefError};
use itertools::PeekingNext;
/// 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>) -> Result<(T, T), LefDefError>
where I: Iterator<Item=char> + PeekingNext {
// Points should be declared in parenthesis. This is not always the case though.
let uses_parentheses = tokens.test("(")?;
let x: T = tokens.take_and_parse()?;
tokens.test(",")?;
let y: T = tokens.take_and_parse()?;
if uses_parentheses {
tokens.expect(")")?;
}
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>) -> Result<Vec<(T, T)>, LefDefError>
where I: Iterator<Item=char> + PeekingNext {
// Read points until ';'.
let mut points = Vec::new();
loop {
if tokens.test(";")? {
break;
} else {
points.push(read_point(tokens)?);
}
}
Ok(points)
}
/// Read a rectangle.
pub fn read_rect<T: FromStr, I>(tokens: &mut Tokenized<I>) -> Result<((T, T), (T, T)), LefDefError>
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.
///
/// 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)
}
}
}
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(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")
}
}
}