reda_lib/model/
semantic.rs

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