liberty_parse/
liberty.rs

1//! Defines a slightly enhanced data structure than the base AST
2//!
3//! Specifically:
4//! * attributes are separated into `simple_attributes` and `complex_attributes`
5//!   struct fields as [HashMap](std::collections::HashMap)s.
6//! * `cell` and `pin` groups are brought out into [HashMap](std::collections::HashMap)s so they're
7//!   easier to work with
8
9use std::collections::HashMap;
10
11use crate::ast::{GroupItem, LibertyAst, Value};
12
13/// Top-level data structure of a Liberty file
14#[derive(Debug, PartialEq, Clone)]
15pub struct Liberty(pub Vec<Library>);
16
17impl Liberty {
18    pub fn to_ast(self) -> LibertyAst {
19        LibertyAst(
20            self.0
21                .into_iter()
22                .map(|g| g.into_group().into_group_item())
23                .collect(),
24        )
25    }
26    pub fn from_ast(ast: LibertyAst) -> Self {
27        Liberty(
28            ast.0
29                .into_iter()
30                .map(|g| Library::from_group(Group::from_group_item(g)))
31                .collect(),
32        )
33    }
34}
35
36impl IntoIterator for Liberty {
37    type Item = Library;
38    type IntoIter = ::std::vec::IntoIter<Self::Item>;
39
40    fn into_iter(self) -> Self::IntoIter {
41        self.0.into_iter()
42    }
43}
44
45/// Top-level `library` group
46///
47/// Every liberty file defines a `library` at the top-most level. Libraries contain
48/// attributes, groups, and [Cell](Cell)s.
49#[derive(Debug, PartialEq, Clone)]
50pub struct Library {
51    pub name: String,
52    pub simple_attributes: HashMap<String, Value>,
53    pub complex_attributes: HashMap<String, Vec<Value>>,
54    pub groups: Vec<Group>,
55    pub cells: HashMap<String, Cell>,
56}
57
58impl Library {
59    pub fn new(name: &str) -> Self {
60        Self {
61            name: name.to_string(),
62            simple_attributes: HashMap::new(),
63            complex_attributes: HashMap::new(),
64            groups: vec![],
65            cells: HashMap::new(),
66        }
67    }
68}
69
70/// General group struct
71///
72/// Groups contain simple attributes, complex attributes, and other groups
73#[derive(Debug, PartialEq, Clone)]
74pub struct Group {
75    pub type_: String,
76    pub name: String,
77    pub simple_attributes: HashMap<String, Value>,
78    pub complex_attributes: HashMap<String, Vec<Value>>,
79    pub groups: Vec<Group>,
80}
81
82impl Group {
83    /// Create a group with empty attributes and sub-groups
84    pub fn new(type_: &str, name: &str) -> Self {
85        Self {
86            type_: type_.to_string(),
87            name: name.to_string(),
88            simple_attributes: HashMap::new(),
89            complex_attributes: HashMap::new(),
90            groups: vec![],
91        }
92    }
93
94    /// Convert an AST [GroupItem::Group] variant into a [Group] struct
95    pub fn from_group_item(group_item: GroupItem) -> Self {
96        let (type_, name, items) = group_item.group();
97        let mut simple_attributes: HashMap<String, Value> = HashMap::new();
98        let mut complex_attributes: HashMap<String, Vec<Value>> = HashMap::new();
99        let mut groups: Vec<Self> = vec![];
100        for item in items {
101            match item {
102                GroupItem::SimpleAttr(name, value) => {
103                    simple_attributes.insert(name, value);
104                }
105                GroupItem::ComplexAttr(name, value) => {
106                    complex_attributes.insert(name, value);
107                }
108                GroupItem::Group(type_, name, items) => {
109                    groups.push(Group::from_group_item(GroupItem::Group(type_, name, items)));
110                }
111                _ => {}
112            }
113        }
114        Self {
115            name: name,
116            type_: type_,
117            simple_attributes: simple_attributes,
118            complex_attributes: complex_attributes,
119            groups: groups,
120        }
121    }
122
123    /// Convert a [Liberty] struct into a [GroupItem::Group] variant
124    pub fn into_group_item(self) -> GroupItem {
125        let mut items: Vec<GroupItem> = Vec::with_capacity(
126            self.simple_attributes.len() + self.complex_attributes.len() + self.groups.len(),
127        );
128        items.extend(
129            self.simple_attributes
130                .into_iter()
131                .map(|(name, value)| GroupItem::SimpleAttr(name, value)),
132        );
133        items.extend(
134            self.complex_attributes
135                .into_iter()
136                .map(|(name, value)| GroupItem::ComplexAttr(name, value)),
137        );
138        items.extend(self.groups.into_iter().map(|g| g.into_group_item()));
139        GroupItem::Group(self.type_, self.name, items)
140    }
141}
142
143/// `cell` group of a [Library](Library)
144#[derive(Debug, PartialEq, Clone)]
145pub struct Cell {
146    pub name: String,
147    pub simple_attributes: HashMap<String, Value>,
148    pub complex_attributes: HashMap<String, Vec<Value>>,
149    pub groups: Vec<Group>,
150    pub pins: HashMap<String, Pin>,
151}
152
153impl Cell {
154    /// Create a cell with empty attributes and sub-groups
155    pub fn new(name: &str) -> Self {
156        Self {
157            name: name.to_string(),
158            simple_attributes: HashMap::new(),
159            complex_attributes: HashMap::new(),
160            groups: vec![],
161            pins: HashMap::new(),
162        }
163    }
164}
165
166/// `pin` group of a [Cell](Cell)
167#[derive(Debug, PartialEq, Clone)]
168pub struct Pin {
169    pub name: String,
170    pub simple_attributes: HashMap<String, Value>,
171    pub complex_attributes: HashMap<String, Vec<Value>>,
172    pub groups: Vec<Group>,
173}
174
175impl Pin {
176    /// Create a pin with empty attributes and sub-groups
177    pub fn new(name: &str) -> Self {
178        Self {
179            name: name.to_string(),
180            simple_attributes: HashMap::new(),
181            complex_attributes: HashMap::new(),
182            groups: vec![],
183        }
184    }
185}
186
187/// Convert a general Group into a more specific type
188///
189/// Implemented by Pin, Cell, or Library
190pub trait FromGroup {
191    type Item;
192
193    fn from_group(group: Group) -> Self::Item;
194}
195
196pub trait ToGroup {
197    type Item;
198
199    fn into_group(self) -> Group;
200}
201
202impl FromGroup for Library {
203    type Item = Library;
204    fn from_group(group: Group) -> Self::Item {
205        let (cells, groups) = group.groups.into_iter().partition(|g| g.type_ == "cell");
206        Self {
207            name: group.name,
208            simple_attributes: group.simple_attributes,
209            complex_attributes: group.complex_attributes,
210            groups: groups,
211            cells: cells.into_iter().fold(HashMap::new(), |mut acc, cell| {
212                acc.insert(cell.name.clone(), Cell::from_group(cell));
213                acc
214            }),
215        }
216    }
217}
218
219impl ToGroup for Library {
220    type Item = Library;
221    fn into_group(self) -> Group {
222        let mut groups: Vec<Group> = Vec::with_capacity(self.groups.len() + self.cells.len());
223        groups.extend(self.cells.into_iter().map(|(_, cell)| cell.into_group()));
224        groups.extend(self.groups);
225        Group {
226            name: self.name,
227            type_: String::from("library"),
228            simple_attributes: self.simple_attributes,
229            complex_attributes: self.complex_attributes,
230            groups: groups,
231        }
232    }
233}
234
235impl FromGroup for Cell {
236    type Item = Cell;
237    fn from_group(group: Group) -> Self::Item {
238        let (pins, groups) = group.groups.into_iter().partition(|g| g.type_ == "pin");
239        Self {
240            name: group.name,
241            simple_attributes: group.simple_attributes,
242            complex_attributes: group.complex_attributes,
243            groups: groups,
244            pins: pins.into_iter().fold(HashMap::new(), |mut acc, pin| {
245                acc.insert(pin.name.clone(), Pin::from_group(pin));
246                acc
247            }),
248        }
249    }
250}
251
252impl ToGroup for Cell {
253    type Item = Cell;
254
255    fn into_group(self) -> Group {
256        let mut groups: Vec<Group> = Vec::with_capacity(self.groups.len() + self.pins.len());
257        groups.extend(self.pins.into_iter().map(|(_, pin)| pin.into_group()));
258        groups.extend(self.groups);
259        Group {
260            name: self.name,
261            type_: String::from("cell"),
262            simple_attributes: self.simple_attributes,
263            complex_attributes: self.complex_attributes,
264            groups: groups,
265        }
266    }
267}
268
269impl FromGroup for Pin {
270    type Item = Pin;
271    fn from_group(group: Group) -> Self::Item {
272        Self {
273            name: group.name,
274            simple_attributes: group.simple_attributes,
275            complex_attributes: group.complex_attributes,
276            groups: group.groups,
277        }
278    }
279}
280
281impl ToGroup for Pin {
282    type Item = Pin;
283    fn into_group(self) -> Group {
284        Group {
285            name: self.name,
286            type_: String::from("pin"),
287            simple_attributes: self.simple_attributes,
288            complex_attributes: self.complex_attributes,
289            groups: self.groups,
290        }
291    }
292}
293
294#[cfg(test)]
295mod test {
296    use super::*;
297
298    #[test]
299    fn test_iter() {
300        let lib = Liberty(vec![Library::new("mylib")]);
301        let mut iter = lib.into_iter();
302        assert_eq!(iter.next(), Some(Library::new("mylib")));
303        assert_eq!(iter.next(), None);
304    }
305
306    #[test]
307    fn test_pin_into_group() {
308        let mut pin = Pin::new("my_pin");
309        pin.groups.push(Group::new("gtype", "gname"));
310        let group = pin.into_group();
311        assert_eq!(group.type_, "pin");
312        assert_eq!(group.name, "my_pin");
313        assert_eq!(group.groups.len(), 1);
314    }
315
316    #[test]
317    fn test_pin_from_group() {
318        let mut group = Group::new("pin", "a");
319        group.groups.push(Group::new("gtype", "gname"));
320        let pin = Pin::from_group(group);
321        assert_eq!(pin.name, "a");
322        assert_eq!(pin.groups.len(), 1);
323    }
324
325    #[test]
326    fn test_cell_into_group() {
327        let mut cell = Cell::new("my_cell");
328        cell.groups.push(Group::new("gtype", "gname"));
329        cell.pins.insert("a".to_string(), Pin::new("a"));
330        cell.pins.insert("b".to_string(), Pin::new("b"));
331        let group = cell.into_group();
332        assert_eq!(group.type_, "cell");
333        assert_eq!(group.name, "my_cell");
334        assert_eq!(group.groups.len(), 3);
335    }
336
337    #[test]
338    fn test_cell_from_group() {
339        let mut group = Group::new("cell", "AND2");
340        group.groups.push(Group::new("gtype", "gname"));
341        group.groups.push(Group::new("pin", "a"));
342        group.groups.push(Group::new("pin", "b"));
343        let cell = Cell::from_group(group);
344        assert_eq!(cell.name, "AND2");
345        assert_eq!(cell.groups.len(), 1);
346        assert_eq!(cell.pins.len(), 2);
347    }
348
349    #[test]
350    fn test_library_into_group() {
351        let mut lib = Library::new("my_lib");
352        lib.groups.push(Group::new("gtype", "gname"));
353        lib.cells.insert("AND2".to_string(), Cell::new("AND2"));
354        lib.cells.insert("NAND2".to_string(), Cell::new("NAND2"));
355        let group = lib.into_group();
356        assert_eq!(group.type_, "library");
357        assert_eq!(group.name, "my_lib");
358        assert_eq!(group.groups.len(), 3);
359    }
360
361    #[test]
362    fn test_lib_from_group() {
363        let mut group = Group::new("library", "mylib");
364        group.groups.push(Group::new("gtype", "gname"));
365        let mut cell = Group::new("cell", "AND2");
366        cell.groups.push(Group::new("pin", "a"));
367        cell.groups.push(Group::new("pin", "b"));
368        group.groups.push(cell);
369        let lib = Library::from_group(group);
370        assert_eq!(lib.name, "mylib");
371        assert_eq!(lib.groups.len(), 1);
372        assert_eq!(lib.cells.len(), 1);
373        let converted_cell = lib.cells.get("AND2").unwrap();
374        assert_eq!(converted_cell.name, "AND2");
375        assert_eq!(converted_cell.groups.len(), 0);
376        assert_eq!(converted_cell.pins.len(), 2);
377    }
378}