mod ast;
mod library;
mod cell;
mod pin;
pub use ast::*;
pub use library::*;
pub use cell::*;
pub use pin::*;
use std::collections::HashMap;
use crate::error::LibError;
pub trait Model {
fn attrs(&self) -> &HashMap<String, LibValue>;
fn groups(&self) -> &[LibGroup];
fn attr(&self, name: &str) -> Option<&LibValue> {
self.attrs().get(name)
}
fn kind_groups(&self, kind: &str) -> impl IntoIterator<Item = &LibGroup> {
self.groups().into_iter().filter(move |g| g.kind == kind)
}
}
#[derive(Debug, PartialEq, Clone, Default)]
pub struct LibGroup {
pub kind: String,
pub params: Vec<String>,
pub attrs: HashMap<String, LibValue>,
pub groups: Vec<LibGroup>,
}
impl LibGroup {
pub fn new<S: Into<String>, P: Into<Vec<String>>>(kind: S, params: P) -> Self {
Self {
kind: kind.into(),
params: params.into(),
..Default::default()
}
}
}
impl Model for LibGroup {
fn attrs(&self) -> &HashMap<String, LibValue> {
&self.attrs
}
fn groups(&self) -> &[LibGroup] {
&self.groups
}
}
impl LibGroup {
pub fn expect_name(&mut self) -> Result<String, LibError> {
if self.params.len() != 1 {
Err(LibError::LibraryParamLenUnmatch)?
}
Ok(self.params[0].clone())
}
pub fn expect_ident_attr(&mut self, attr_name: &str) -> Result<String, LibError> {
if let Some(value) = self.attrs.remove(attr_name) {
let s = value.into_ident()?;
Ok(s)
} else {
Err(LibError::MissAttr(attr_name.to_string()))
}
}
pub fn expect_ident_attr_opt(&mut self, attr_name: &str) -> Result<Option<String>, LibError> {
if let Some(value) = self.attrs.remove(attr_name) {
let s = value.into_ident()?;
Ok(Some(s))
} else {
Ok(None)
}
}
pub fn expect_string_attr_opt(&mut self, attr_name: &str) -> Result<Option<String>, LibError> {
if let Some(value) = self.attrs.remove(attr_name) {
let s = value.into_string()?;
Ok(Some(s))
} else {
Ok(None)
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_cells() {
let lib = LibLibrary::load_file("./data/cells.lib").unwrap();
let and2 = lib.cell("AND2").unwrap();
let pin = and2.pin("o").unwrap();
println!("{:#?}", pin.function);
}
}