reda_lib/model/
semantic.rs1use 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 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 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 }
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 }
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 }
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}