reda_lib/model/
mod.rs

1mod semantic;
2use std::{collections::HashMap, path::Path};
3use reda_lib_macro::model;
4pub use semantic::{FromGroup, IntoGroup};
5use crate::{ast::{self, Value}, error::LibError};
6
7pub trait Model {
8    fn attrs(&self) -> &HashMap<String, Value>;
9    fn groups(&self) -> &[Group];
10    fn attr(&self, name: &str) -> Option<&Value> {
11        self.attrs().get(name)
12    }
13    fn kind_groups(&self, kind: &str) -> impl IntoIterator<Item = &Group> {
14        self.groups().into_iter().filter(move |g| g.kind == kind)
15    }
16}
17
18#[model]
19#[derive(Debug, PartialEq, Clone, Default)]
20pub struct Library {
21    pub name: String,
22    pub cells: Vec<Cell>,
23}
24
25impl Library {
26    pub fn new<S: Into<String>>(name: S) -> Self {
27        Self { 
28            name: name.into(),
29            ..Default::default()
30        }
31    }
32
33    pub fn load_file<P: AsRef<Path>>(path: P) -> Result<Self, LibError> {
34        let context = std::fs::read_to_string(path)?;
35        let ast = ast::parse_liberty(&context)?;
36        Self::from_ast(ast)
37    }
38
39    pub fn cell(&self, name: &str) -> Option<&Cell> {
40        self.cells.iter().find(|c| c.name == name)
41    }
42}
43
44#[model]
45#[derive(Debug, PartialEq, Clone, Default)]
46pub struct Cell {
47    pub name: String,
48    pub pins: Vec<Pin>,
49}
50
51impl Cell {
52    pub fn new<S: Into<String>>(name: S) -> Self {
53        Self { 
54            name: name.into(),
55            ..Default::default()
56        }
57    }
58
59    pub fn pin(&self, name: &str) -> Option<&Pin> {
60        self.pins.iter().find(|p| p.name == name)
61    }
62}
63
64#[model]
65#[derive(Debug, PartialEq, Clone, Default)]
66pub struct Pin {
67    pub name: String,
68    pub direction: PinDirection,
69    pub function: Option<String>,
70}
71
72#[derive(Debug, PartialEq, Clone, Default)]
73pub enum PinDirection {
74    #[default]
75    Input,
76    Output,
77    Inout,
78    Internal,
79}
80
81impl Pin {
82    pub fn new<S: Into<String>>(name: S) -> Self {
83        Self { 
84            name: name.into(),
85            ..Default::default()
86        }
87    }
88}
89
90#[derive(Debug, PartialEq, Clone, Default)]
91pub struct Group {
92    pub kind: String,
93    pub params: Vec<String>,
94
95    pub attrs: HashMap<String, Value>,
96    pub groups: Vec<Group>,
97}
98
99impl Group {
100    pub fn new<S: Into<String>, P: Into<Vec<String>>>(kind: S, params: P) -> Self {
101        Self {
102            kind: kind.into(),
103            params: params.into(),
104            ..Default::default()
105        }
106    }
107}
108
109impl Model for Group {
110    fn attrs(&self) -> &HashMap<String, Value> {
111        &self.attrs
112    }
113
114    fn groups(&self) -> &[Group] {
115        &self.groups
116    }
117}
118
119impl Group {
120    pub fn expect_name(&mut self) -> Result<String, LibError> {
121        if self.params.len() != 1 {
122            Err(LibError::LibraryParamLenUnmatch)?
123        }
124        Ok(self.params[0].clone())
125    }
126
127    pub fn expect_ident_attr(&mut self, attr_name: &str) -> Result<String, LibError> {
128        if let Some(value) = self.attrs.remove(attr_name) {
129            let s = value.into_ident()?;
130            Ok(s)
131        } else {
132            Err(LibError::MissAttr(attr_name.to_string()))
133        }
134    }
135
136    pub fn expect_ident_attr_opt(&mut self, attr_name: &str) -> Result<Option<String>, LibError> {
137        if let Some(value) = self.attrs.remove(attr_name) {
138            let s = value.into_ident()?;
139            Ok(Some(s))
140        } else {
141            Ok(None)
142        }
143    }
144
145    pub fn expect_string_attr_opt(&mut self, attr_name: &str) -> Result<Option<String>, LibError> {
146        if let Some(value) = self.attrs.remove(attr_name) {
147            let s = value.into_string()?;
148            Ok(Some(s))
149        } else {
150            Ok(None)
151        }
152    }
153}
154
155#[cfg(test)]
156mod test {
157    use super::*;
158
159    #[test]
160    fn test_cells() {
161        let lib = Library::load_file("./data/cells.lib").unwrap();
162        let and2 = lib.cell("AND2").unwrap();
163        let pin = and2.pin("o").unwrap();
164        println!("{:#?}", pin.function);
165    }
166}