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}