reda_lib/io/read/
semantic.rs

1use std::fmt::Display;
2use std::{collections::HashMap, str::FromStr};
3use crate::error::{LibErrorContext, LibError};
4use crate::model::{LibAst, LibCell, LibGroup, LibLibrary, LibPin, LibPinDirection};
5
6pub trait FromLibGroup: Sized {
7    type Error: Sized;
8    fn from_group(group: LibGroup) -> Result<Self, Self::Error>;
9}
10
11impl LibLibrary {
12    pub fn from_ast(ast: LibAst) -> Result<Self, LibError> {
13        let group = LibGroup::from_ast(ast).context(|| "semantic root ast to group")?;
14        Self::from_group(group)
15    }
16}
17
18impl FromLibGroup for LibLibrary {
19    type Error = LibError;
20    fn  from_group(group: LibGroup) -> Result<Self, LibError> {
21        let mut group = group;
22        let name = group.expect_name().context(|| "group name")?;
23        let (cell_groups, groups) = group.groups.into_iter().partition(|g| g.kind == "cell");
24        
25        // collect cells
26        let mut cells = Vec::new();
27        for cell_group in cell_groups {
28            cells.push(LibCell::from_group(cell_group).context(|| "semantic cell")?);
29        }
30
31        Ok(Self {
32            name,
33            attrs: group.attrs,
34            groups,
35            cells,
36        })
37    }
38}
39
40impl FromLibGroup for LibCell {
41    type Error = LibError;
42    fn from_group(group: LibGroup) -> Result<Self, LibError> {
43        let mut group = group;
44        let name = group.expect_name().context(|| "cell name")?;
45        let err_context = |msg: &str| {
46            format!("{} in {} cell", msg, &name)
47        };
48
49        let (pin_groups, groups) = group.groups.into_iter().partition(|g| g.kind == "pin");
50
51        // collect cells
52        let mut pins = Vec::new();
53        for cell_group in pin_groups {
54            pins.push(LibPin::from_group(cell_group).context(|| err_context("semantic pin"))?);
55        }
56
57        Ok(Self {
58            name,
59            pins,
60            attrs: group.attrs,
61            groups,
62        })
63    }
64}
65
66impl FromLibGroup for LibPin {
67    type Error = LibError;
68    fn from_group(group: LibGroup) -> Result<Self, LibError> {
69        let mut group = group;
70        let name = group.expect_name().context(|| "pin name")?;
71        let err_context = |msg: &str| {
72            format!("{} in `{}` pin", msg, &name)
73        };
74
75        let direction = match group.expect_ident_attr_opt("direction")
76            .context(|| err_context("semantic `direction` attr"))? 
77        {
78            Some(s) => LibPinDirection::from_str(&s)?,
79            None => LibPinDirection::default(),
80        };
81        let function = group.expect_string_attr_opt("function")
82            .context(|| err_context("semantic `function` attr"))?;
83    
84        Ok(Self {
85            name,
86            direction,
87            function,
88            attrs: group.attrs,
89            groups: group.groups,
90        })
91    }
92}
93
94impl FromStr for LibPinDirection {
95    type Err = LibError;
96    fn from_str(s: &str) -> Result<Self, Self::Err> {
97        match s {
98            "input" => Ok(Self::Input),
99            "output" => Ok(Self::Output),
100            "inout" => Ok(Self::Inout),
101            "internal" => Ok(Self::Internal),
102            s => Err(LibError::UnsupportDirection(s.to_string()))
103        }   
104    }
105}
106
107impl Display for LibPinDirection {
108    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
109        match self {
110            Self::Input => write!(f, "input"),
111            Self::Output => write!(f, "output"),
112            Self::Inout => write!(f, "inout"),
113            Self::Internal => write!(f, "internal"),
114        }
115    }
116}
117
118impl LibGroup {
119    pub fn from_ast(ast: LibAst) -> Result<Self, LibError> {
120        match ast {
121            LibAst::LibGroup { kind, params, items } => {
122                let mut attrs = HashMap::new();
123                let mut groups = Vec::new();
124                
125                for item_ast in items {
126                    if let LibAst::Attr { key, value } = item_ast {
127                        attrs.insert(key, value);
128                    } else {
129                        groups.push(LibGroup::from_ast(item_ast)?);
130                    }
131                }
132
133                Ok(Self {
134                    kind, 
135                    params,
136                    attrs,
137                    groups
138                })
139            }
140            LibAst::Attr { key:_, value:_ } => Err(LibError::ExceptLibGroup),
141        }
142    }
143}
144
145#[cfg(test)]
146mod test {
147    use super::*;
148
149    #[test]
150    fn test_pin_into_group() {
151        let mut pin = LibPin::new("my_pin");
152        pin.groups.push(LibGroup::new("gtype", vec!["gname".to_string()]));
153        // let group = pin.into_group();
154        // assert_eq!(group.type_, "pin");
155        // assert_eq!(group.name, "my_pin");
156        // assert_eq!(group.groups.len(), 1);
157    }
158
159    #[test]
160    fn test_pin_from_group() {
161        let mut group = LibGroup::new("pin", vec!["a".to_string()]);
162        group.groups.push(LibGroup::new("gtype", vec!["gname".to_string()]));
163        let pin = LibPin::from_group(group).unwrap();
164        assert_eq!(pin.name, "a");
165        assert_eq!(pin.groups.len(), 1);
166    }
167
168    #[test]
169    fn test_cell_into_group() {
170        let mut cell = LibCell::new("my_cell");
171        cell.groups.push(LibGroup::new("gtype", vec!["gname".to_string()]));
172        cell.pins.push(LibPin::new("a"));
173        cell.pins.push(LibPin::new("b"));
174        // let group = cell.into_group();
175        // assert_eq!(group.type_, "cell");
176        // assert_eq!(group.name, "my_cell");
177        // assert_eq!(group.groups.len(), 3);
178    }
179
180    #[test]
181    fn test_cell_from_group() {
182        let mut group = LibGroup::new("cell", vec!["AND2".to_string()]);
183        group.groups.push(LibGroup::new("gtype", vec!["gname".to_string()]));
184        group.groups.push(LibGroup::new("pin", vec!["a".to_string()]));
185        group.groups.push(LibGroup::new("pin", vec!["b".to_string()]));
186        let cell = LibCell::from_group(group).unwrap();
187        assert_eq!(cell.name, "AND2");
188        assert_eq!(cell.groups.len(), 1);
189        assert_eq!(cell.pins.len(), 2);
190    }
191
192    #[test]
193    fn test_library_into_group() {
194        let mut lib = LibLibrary::new("my_lib");
195        lib.groups.push(LibGroup::new("gtype", vec!["gname".to_string()]));
196        lib.cells.push(LibCell::new("AND2"));
197        lib.cells.push(LibCell::new("NAND2"));
198        // let group = lib.into_group();
199        // assert_eq!(group.type_, "library");
200        // assert_eq!(group.name, "my_lib");
201        // assert_eq!(group.groups.len(), 3);
202    }
203
204    #[test]
205    fn test_lib_from_group() {
206        let mut group = LibGroup::new("library", vec!["mylib".to_string()]);
207        group.groups.push(LibGroup::new("gtype", vec!["gname".to_string()]));
208        let mut cell = LibGroup::new("cell", vec!["AND2".to_string()]);
209        cell.groups.push(LibGroup::new("pin", vec!["a".to_string()]));
210        cell.groups.push(LibGroup::new("pin", vec!["b".to_string()]));
211        group.groups.push(cell);
212        let lib = LibLibrary::from_group(group).unwrap();
213        assert_eq!(lib.name, "mylib");
214        assert_eq!(lib.groups.len(), 1);
215        assert_eq!(lib.cells.len(), 1);
216        let converted_cell = lib.cell("AND2").unwrap();
217        assert_eq!(converted_cell.name, "AND2");
218        assert_eq!(converted_cell.groups.len(), 0);
219        assert_eq!(converted_cell.pins.len(), 2);
220    }
221}