1use crate::error::{LibErrorContext, LibError};
2use crate::model::{LibAst, LibCapacitiveLoadUnit, LibCell, LibGroup, LibLibrary, LibLuTableTemplate, 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 lu_table_templates = vec![];
92 let mut groups = vec![];
93
94 for group in group.groups {
95 match group.kind.as_str() {
96 "cell" => cells.push(LibCell::from_group(group).context(|| err_context("semantic cell"))?),
97 "operating_conditions" => operating_conditions.push(LibOperatingConditions::from_group(group).context(|| err_context("semantic operating_conditions"))?),
98 "lu_table_template" => lu_table_templates.push(LibLuTableTemplate::from_group(group).context(|| err_context("semantic lu_table_templates"))?),
99 _ => groups.push(group),
100 }
101 }
102
103 Ok(Self {
104 name,
105
106 date,
107 revision,
108 comment,
109
110 delay_model,
111
112 time_unit,
113 voltage_unit,
114 capacitive_load_unit,
115 current_unit,
116 pulling_resistance_unit,
117 leakage_power_unit,
118
119 nom_process,
120 nom_temperature,
121 nom_voltage,
122
123 slew_lower_threshold_pct_fall,
124 slew_lower_threshold_pct_rise,
125 slew_upper_threshold_pct_fall,
126 slew_upper_threshold_pct_rise,
127 slew_derate_from_library,
128 input_threshold_pct_fall,
129 input_threshold_pct_rise,
130 output_threshold_pct_fall,
131 output_threshold_pct_rise,
132 default_leakage_power_density,
133 default_cell_leakage_power,
134
135 default_operating_conditions,
136
137 default_inout_pin_cap,
138 default_input_pin_cap,
139 default_output_pin_cap,
140 default_fanout_load,
141 default_max_transition,
142
143 attrs: group.attrs,
144 groups,
145 cells,
146 lu_table_templates,
147 operating_conditions,
148 })
149 }
150}
151
152impl FromLibGroup for LibOperatingConditions {
153 type Error = LibError;
154
155 fn from_group(group: LibGroup) -> Result<Self, Self::Error> {
156 let mut group = group;
157 let name = group.expect_name().context(|| "group name")?;
158 let err_context = |msg: &str| format!("{} in `{}` operating_conditions", msg, &name);
159
160 let get_float_opt =
162 |key: &str| group.attr_float_opt(key, || err_context(&format!("semantic `{}` attr", key)));
163 let get_float =
164 |key: &str| group.attr_float(key, || err_context(&format!("semantic `{}` attr", key)));
165 let get_string_opt =
166 |key: &str| group.attr_string_opt(key, || err_context(&format!("semantic `{}` attr", key))).map(|v| v.map(String::from));
167
168 let process = get_float("process")?;
169 let voltage = get_float("voltage")?;
170 let temperature = get_float("temperature")?;
171 let calc_mode = get_string_opt("calc_mode")?;
172 let parameteri = get_float_opt("parameteri")?;
173 let process_label = get_string_opt("process_label")?;
174 let tree_type = group.attr_parse_opt("tree_type", &|| err_context("semantic `tree_type` attr"))?;
175
176 Ok(Self {
177 name,
178 process,
179 voltage,
180 temperature,
181 calc_mode,
182 parameteri,
183 process_label,
184 tree_type,
185
186 attrs: group.attrs,
187 groups: group.groups,
188 })
189
190 }
191}
192
193
194impl FromLibGroup for LibLuTableTemplate {
195 type Error = LibError;
196
197 fn from_group(group: LibGroup) -> Result<Self, Self::Error> {
198 let mut group = group;
199 let name = group.expect_name().context(|| "group name")?;
200 let err_context = |msg: &str| format!("{} in `{}` lu_table_template", msg, &name);
201
202 let variable_1 = group.attr_parse_opt("variable_1", &|| err_context("semantic `variable_1` attr"))?;
203 let variable_2 = group.attr_parse_opt("variable_2", &|| err_context("semantic `variable_2` attr"))?;
204 let variable_3 = group.attr_parse_opt("variable_3", &|| err_context("semantic `variable_3` attr"))?;
205
206 let index_1 = group.attr_floats_opt("index_1", &|| err_context("semantic `index_1` attr"))?;
207 let index_2 = group.attr_floats_opt("index_2", &|| err_context("semantic `index_2` attr"))?;
208 let index_3 = group.attr_floats_opt("index_3", &|| err_context("semantic `index_3` attr"))?;
209
210 Ok(Self {
211 name,
212 variable_1,
213 variable_2,
214 variable_3,
215 index_1,
216 index_2,
217 index_3,
218
219 attrs: group.attrs,
220 groups: group.groups,
221 })
222 }
223}
224
225#[cfg(test)]
226mod test {
227 use super::*;
228
229 #[test]
230 fn test_cell_from_group() {
231 let mut group = LibGroup::new("cell", vec!["AND2".to_string()]);
232 group.groups.push(LibGroup::new("gtype", vec!["gname".to_string()]));
233 group.groups.push(LibGroup::new("pin", vec!["a".to_string()]));
234 group.groups.push(LibGroup::new("pin", vec!["b".to_string()]));
235 let cell = LibCell::from_group(group).unwrap();
236 assert_eq!(cell.name, "AND2");
237 assert_eq!(cell.groups.len(), 1);
238 assert_eq!(cell.pins.len(), 2);
239 }
240
241 #[test]
242 fn test_library_into_group() {
243 let mut lib = LibLibrary::new("my_lib");
244 lib.groups.push(LibGroup::new("gtype", vec!["gname".to_string()]));
245 lib.cells.push(LibCell::new("AND2"));
246 lib.cells.push(LibCell::new("NAND2"));
247 }
252
253 }