reda_lib/model/
mod.rs

1mod ast;
2mod library;
3mod cell;
4mod pin;
5mod expr;
6pub use ast::*;
7pub use library::*;
8pub use cell::*;
9pub use pin::*;
10pub use expr::*;
11
12use std::{collections::HashMap, error::Error, str::FromStr};
13use crate::error::{LibError, LibErrorContext};
14
15pub trait Model {
16    fn attrs(&self) -> &HashMap<String, LibValue>;
17    fn groups(&self) -> &[LibGroup];
18    fn attr(&self, name: &str) -> Option<&LibValue> {
19        self.attrs().get(name)
20    }
21    fn attr_must(&self, name: &str) -> Result<&LibValue, LibError> {
22        self.attr(name).ok_or_else(|| LibError::MissAttr(name.to_string()))
23    }
24    fn kind_groups(&self, kind: &str) -> impl IntoIterator<Item = &LibGroup> {
25        self.groups().into_iter().filter(move |g| g.kind == kind)
26    }
27}
28
29#[derive(Debug, PartialEq, Clone, Default)]
30pub struct LibGroup {
31    pub kind: String,
32    pub params: Vec<String>,
33
34    pub attrs: HashMap<String, LibValue>,
35    pub groups: Vec<LibGroup>,
36}
37
38impl LibGroup {
39    pub fn new<S: Into<String>, P: Into<Vec<String>>>(kind: S, params: P) -> Self {
40        Self {
41            kind: kind.into(),
42            params: params.into(),
43            ..Default::default()
44        }
45    }
46}
47
48impl Model for LibGroup {
49    fn attrs(&self) -> &HashMap<String, LibValue> {
50        &self.attrs
51    }
52
53    fn groups(&self) -> &[LibGroup] {
54        &self.groups
55    }
56}
57
58impl LibGroup {
59    pub fn expect_name(&mut self) -> Result<String, LibError> {
60        if self.params.len() != 1 {
61            Err(LibError::LibraryParamLenUnmatch)?
62        }
63        Ok(self.params[0].clone())
64    }
65
66    pub fn attr_bool_opt<S: Into<String>>(&self, attr_name: &str, ctx: impl Fn() -> S) -> Result<Option<bool>, LibError> {
67        match self.attr(attr_name) {
68            Some(v) => Ok(Some(v.bool().context(ctx)?)),
69            None => Ok(None),
70        }
71    }
72
73    pub fn attr_float_opt<S: Into<String>>(&self, attr_name: &str, ctx: impl Fn() -> S) -> Result<Option<f64>, LibError> {
74        match self.attr(attr_name) {
75            Some(v) => Ok(Some(v.float().context(ctx)?)),
76            None => Ok(None),
77        }
78    }
79
80    pub fn attr_string_opt<S: Into<String>>(&self, attr_name: &str, ctx: impl Fn() -> S) -> Result<Option<&str>, LibError> {
81        match self.attr(attr_name) {
82            Some(v) => Ok(Some(v.string().context(ctx)?)),
83            None => Ok(None),
84        }
85    }
86
87    pub fn attr_ident_opt<S: Into<String>>(&self, attr_name: &str, ctx: impl Fn() -> S) -> Result<Option<&str>, LibError> {
88        match self.attr(attr_name) {
89            Some(v) => Ok(Some(v.ident().context(ctx)?)),
90            None => Ok(None),
91        }
92    }
93
94    pub fn attr_expr_opt<S: Into<String>>(&self, attr_name: &str, ctx: &impl Fn() -> S) -> Result<Option<LibExpr>, LibError> {
95        match self.attr(attr_name) {
96            Some(v) => {
97                let s = v.string().context(ctx)?;
98                let expr = LibExpr::from_str(s).context(ctx)?;
99                Ok(Some(expr))
100            }
101            None => Ok(None),
102        }
103    }
104
105    pub fn attr_floats_opt<const N: usize, S: Into<String>>(&self, attr_name: &str, ctx: &impl Fn() -> S) -> Result<Option<[f64; N]>, LibError> {
106        match self.attr(attr_name) {
107            Some(v) => {
108                let vs = v.vector().context(ctx)?;
109                if vs.len() != N {
110                    Err(LibError::Parse(format!("expect float len {}, got {}", N, vs.len())))?;
111                }
112                let mut fs = [0.0; N];
113                for i in 0..N {
114                    let v = &vs[i];
115                    let f = v.float().context(ctx)?;
116                    fs[i] = f;
117                }
118                Ok(Some(fs))
119            }
120            None => Ok(None),
121        }
122    }
123
124    pub fn attr_parse_opt<T, S, F>(&self, attr_name: &str, ctx: &F) -> Result<Option<T>, LibError> 
125    where 
126        T: FromStr,
127        T::Err: Error,
128        S: Into<String>,
129        F: Fn() -> S
130    {
131        match self.attr(attr_name) {
132            Some(v) => {
133                let s = v.ident().context(ctx)?;
134                let v = T::from_str(s).map_err(|e| LibError::Parse(e.to_string())).context(ctx)?;
135                Ok(Some(v))
136            }
137            None => Ok(None),
138        }
139    }
140
141    pub fn attr_bool<S: Into<String>>(&self, attr_name: &str, ctx: impl Fn() -> S) -> Result<bool, LibError> {
142        let v = self.attr_bool_opt(attr_name, ctx)?;
143        v.ok_or_else(|| LibError::MissAttr(attr_name.into()))
144    }
145
146    pub fn attr_float<S: Into<String>>(&self, attr_name: &str, ctx: impl Fn() -> S) -> Result<f64, LibError> {
147        let v = self.attr_float_opt(attr_name, ctx)?;
148        v.ok_or_else(|| LibError::MissAttr(attr_name.into()))
149    }
150
151    pub fn attr_string<S: Into<String>>(&self, attr_name: &str, ctx: impl Fn() -> S) -> Result<&str, LibError> {
152        let v = self.attr_string_opt(attr_name, ctx)?;
153        v.ok_or_else(|| LibError::MissAttr(attr_name.into()))
154    }
155
156    pub fn attr_ident<S: Into<String>>(&self, attr_name: &str, ctx: impl Fn() -> S) -> Result<&str, LibError> {
157        let v = self.attr_ident_opt(attr_name, ctx)?;
158        v.ok_or_else(|| LibError::MissAttr(attr_name.into()))
159    }
160
161    pub fn attr_expr<S: Into<String>>(&self, attr_name: &str, ctx: &impl Fn() -> S) -> Result<LibExpr, LibError> {
162        let v = self.attr_expr_opt(attr_name, ctx)?;
163        v.ok_or_else(|| LibError::MissAttr(attr_name.into()))
164    }
165
166    pub fn attr_parse<T, S, F>(&self, attr_name: &str, ctx: &F) -> Result<T, LibError> 
167    where 
168        T: FromStr,
169        T::Err: Error,
170        S: Into<String>,
171        F: Fn() -> S
172    {
173        let v = self.attr_parse_opt(attr_name, ctx)?;
174        v.ok_or_else(|| LibError::MissAttr(attr_name.into()))
175    }
176}
177
178#[cfg(test)]
179mod test {
180    use super::*;
181
182    #[test]
183    fn test_cells() {
184        let lib = LibLibrary::load_file("./data/cells.lib").unwrap();
185        let and2 = lib.cell("AND2").unwrap();
186        let pin = and2.pin("o").unwrap();
187        println!("{:#?}", pin.function);
188    }
189}