1use crate::error::{LibErrorContext, LibError};
2use crate::model::{LibAst, LibCapacitiveLoadUnit, LibCell, LibGroup, LibLibrary, LibOperatingConditions, LibValue, Model};
3
4use super::FromLibGroup;
5
6impl LibLibrary {
7 pub fn from_ast(ast: LibAst) -> Result<Self, LibError> {
8 let group = LibGroup::from_ast(ast).context(|| "semantic root ast to group")?;
9 Self::from_group(group)
10 }
11}
12
13impl FromLibGroup for LibLibrary {
14 type Error = LibError;
15 fn from_group(group: LibGroup) -> Result<Self, LibError> {
16 let mut group = group;
17 let name = group.expect_name().context(|| "group name")?;
18 let err_context = |msg: &str| format!("{} in `{}` library", msg, &name);
19
20 let get_float_opt =
22 |key: &str| group.attr_float_opt(key, || err_context(&format!("semantic `{}` attr", key)));
23 let get_float =
24 |key: &str| group.attr_float(key, || err_context(&format!("semantic `{}` attr", key)));
25 let get_string_opt =
26 |key: &str| group.attr_string_opt(key, || err_context(&format!("semantic `{}` attr", key))).map(|v| v.map(String::from));
27 let get_string =
28 |key: &str| group.attr_string(key, || err_context(&format!("semantic `{}` attr", key))).map(String::from);
29 let get_ident_opt =
30 |key: &str| group.attr_ident_opt(key, || err_context(&format!("semantic `{}` attr", key))).map(|v| v.map(String::from));
31
32 let date = get_string("date")?;
33 let revision = get_string_opt("revision")?;
34 let comment = get_string_opt("comment")?;
35
36 let delay_model = group.attr_parse("delay_model", &|| err_context("semantic `delay_model` attr"))?;
37
38 let nom_process = get_float_opt("nom_process")?;
39 let nom_temperature = get_float_opt("nom_temperature")?;
40 let nom_voltage = get_float_opt("nom_voltage")?;
41
42 let default_operating_conditions = get_ident_opt("default_operating_conditions")?;
43
44 let slew_lower_threshold_pct_fall = get_float("slew_lower_threshold_pct_fall")?;
45 let slew_lower_threshold_pct_rise = get_float("slew_lower_threshold_pct_rise")?;
46 let slew_upper_threshold_pct_fall = get_float("slew_upper_threshold_pct_fall")?;
47 let slew_upper_threshold_pct_rise = get_float("slew_upper_threshold_pct_rise")?;
48 let slew_derate_from_library = get_float("slew_derate_from_library")?;
49 let input_threshold_pct_fall = get_float("input_threshold_pct_fall")?;
50 let input_threshold_pct_rise = get_float("input_threshold_pct_rise")?;
51 let output_threshold_pct_fall = get_float("output_threshold_pct_fall")?;
52 let output_threshold_pct_rise = get_float("output_threshold_pct_rise")?;
53 let default_leakage_power_density = get_float("default_leakage_power_density")?;
54 let default_cell_leakage_power = get_float("default_cell_leakage_power")?;
55
56 let time_unit = group.attr_parse_string("time_unit", &|| err_context("semantic `time_unit` attr"))?;
57 let voltage_unit = group.attr_parse_string("voltage_unit", &|| err_context("semantic `voltage_unit` attr"))?;
58 let current_unit = group.attr_parse_string_opt("current_unit", &|| err_context("semantic `current_unit` attr"))?;
59 let pulling_resistance_unit = group.attr_parse_string_opt("pulling_resistance_unit", &|| err_context("semantic `pulling_resistance_unit` attr"))?;
60 let leakage_power_unit = group.attr_parse_string_opt("leakage_power_unit", &|| err_context("semantic `leakage_power_unit` attr"))?;
61
62 let capacitive_load_unit = match group.attr("capacitive_load_unit") {
63 Some(value) => {
64 if let LibValue::Vec(vec) = value {
65 if vec.len() != 2 {
66 Err(LibError::Parse("capacitive_load_unit attr should be a (float, ident)".into()))?
67 }
68 let f = vec[0].float().context(|| err_context("semantic `capacitive_load_unit` attr"))?;
69 let i = vec[1].ident().context(|| err_context("semantic `capacitive_load_unit` attr"))?;
70 match i {
71 "ff" => Some(LibCapacitiveLoadUnit::FF(f)),
72 "pf" => Some(LibCapacitiveLoadUnit::PF(f)),
73 _ => Err(LibError::UnsupportEnumValue("capacitive_load_unit", i.into()))?
74 }
75
76 } else {
77 Err(LibError::Parse("capacitive_load_unit attr should be a (float, ident)".into()))?
78 }
79 }
80 None => None,
81 };
82
83 let default_inout_pin_cap = get_float_opt("default_inout_pin_cap")?;
84 let default_input_pin_cap = get_float_opt("default_input_pin_cap")?;
85 let default_output_pin_cap = get_float_opt("default_output_pin_cap")?;
86 let default_fanout_load = get_float_opt("default_fanout_load")?;
87 let default_max_transition = get_float_opt("default_max_transition")?;
88
89 let mut cells = vec![];
90 let mut operating_conditions = vec![];
91 let mut groups = vec![];
92
93 for group in group.groups {
94 match group.kind.as_str() {
95 "cell" => cells.push(LibCell::from_group(group).context(|| err_context("semantic cell"))?),
96 "operating_conditions" => operating_conditions.push(LibOperatingConditions::from_group(group).context(|| err_context("semantic operating_conditions"))?),
97 _ => groups.push(group),
98 }
99 }
100
101 Ok(Self {
102 name,
103
104 date,
105 revision,
106 comment,
107
108 delay_model,
109
110 time_unit,
111 voltage_unit,
112 capacitive_load_unit,
113 current_unit,
114 pulling_resistance_unit,
115 leakage_power_unit,
116
117 nom_process,
118 nom_temperature,
119 nom_voltage,
120
121 slew_lower_threshold_pct_fall,
122 slew_lower_threshold_pct_rise,
123 slew_upper_threshold_pct_fall,
124 slew_upper_threshold_pct_rise,
125 slew_derate_from_library,
126 input_threshold_pct_fall,
127 input_threshold_pct_rise,
128 output_threshold_pct_fall,
129 output_threshold_pct_rise,
130 default_leakage_power_density,
131 default_cell_leakage_power,
132
133 default_operating_conditions,
134
135 default_inout_pin_cap,
136 default_input_pin_cap,
137 default_output_pin_cap,
138 default_fanout_load,
139 default_max_transition,
140
141 attrs: group.attrs,
142 groups,
143 cells,
144 operating_conditions,
145 })
146 }
147}
148
149impl FromLibGroup for LibOperatingConditions {
150 type Error = LibError;
151
152 fn from_group(group: LibGroup) -> Result<Self, Self::Error> {
153 let mut group = group;
154 let name = group.expect_name().context(|| "group name")?;
155 let err_context = |msg: &str| format!("{} in `{}` operating_conditions", msg, &name);
156
157 let get_float_opt =
159 |key: &str| group.attr_float_opt(key, || err_context(&format!("semantic `{}` attr", key)));
160 let get_float =
161 |key: &str| group.attr_float(key, || err_context(&format!("semantic `{}` attr", key)));
162 let get_string_opt =
163 |key: &str| group.attr_string_opt(key, || err_context(&format!("semantic `{}` attr", key))).map(|v| v.map(String::from));
164
165 let process = get_float("process")?;
166 let voltage = get_float("voltage")?;
167 let temperature = get_float("temperature")?;
168 let calc_mode = get_string_opt("calc_mode")?;
169 let parameteri = get_float_opt("parameteri")?;
170 let process_label = get_string_opt("process_label")?;
171 let tree_type = group.attr_parse_opt("tree_type", &|| err_context("semantic `tree_type` attr"))?;
172
173 Ok(Self {
174 name,
175 process,
176 voltage,
177 temperature,
178 calc_mode,
179 parameteri,
180 process_label,
181 tree_type,
182
183 attrs: group.attrs,
184 groups: group.groups,
185 })
186
187 }
188}
189
190#[cfg(test)]
191mod test {
192 use super::*;
193
194 #[test]
195 fn test_cell_from_group() {
196 let mut group = LibGroup::new("cell", vec!["AND2".to_string()]);
197 group.groups.push(LibGroup::new("gtype", vec!["gname".to_string()]));
198 group.groups.push(LibGroup::new("pin", vec!["a".to_string()]));
199 group.groups.push(LibGroup::new("pin", vec!["b".to_string()]));
200 let cell = LibCell::from_group(group).unwrap();
201 assert_eq!(cell.name, "AND2");
202 assert_eq!(cell.groups.len(), 1);
203 assert_eq!(cell.pins.len(), 2);
204 }
205
206 #[test]
207 fn test_library_into_group() {
208 let mut lib = LibLibrary::new("my_lib");
209 lib.groups.push(LibGroup::new("gtype", vec!["gname".to_string()]));
210 lib.cells.push(LibCell::new("AND2"));
211 lib.cells.push(LibCell::new("NAND2"));
212 }
217
218 #[test]
219 fn test_lib_from_group() {
220 let mut group = LibGroup::new("library", vec!["mylib".to_string()]);
221 group.groups.push(LibGroup::new("gtype", vec!["gname".to_string()]));
222 let mut cell = LibGroup::new("cell", vec!["AND2".to_string()]);
223 cell.groups.push(LibGroup::new("pin", vec!["a".to_string()]));
224 cell.groups.push(LibGroup::new("pin", vec!["b".to_string()]));
225 group.groups.push(cell);
226 let lib = LibLibrary::from_group(group).unwrap();
227 assert_eq!(lib.name, "mylib");
228 assert_eq!(lib.groups.len(), 1);
229 assert_eq!(lib.cells.len(), 1);
230 let converted_cell = lib.cell("AND2").unwrap();
231 assert_eq!(converted_cell.name, "AND2");
232 assert_eq!(converted_cell.groups.len(), 0);
233 assert_eq!(converted_cell.pins.len(), 2);
234 }
235}