Skip to main content

reda_lib/io/read/
semantic_library.rs

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        // helpers that attach context when calling LibValue accessors
21        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        // helpers that attach context when calling LibValue accessors
161        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        // let group = lib.into_group();
248        // assert_eq!(group.type_, "library");
249        // assert_eq!(group.name, "my_lib");
250        // assert_eq!(group.groups.len(), 3);
251    }
252
253    // #[test]
254    // fn test_lib_from_group() {
255    //     let mut group = LibGroup::new("library", vec!["mylib".to_string()]);
256    //     group.groups.push(LibGroup::new("gtype", vec!["gname".to_string()]));
257    //     let mut cell = LibGroup::new("cell", vec!["AND2".to_string()]);
258    //     cell.groups.push(LibGroup::new("pin", vec!["a".to_string()]));
259    //     cell.groups.push(LibGroup::new("pin", vec!["b".to_string()]));
260    //     group.groups.push(cell);
261    //     let lib = LibLibrary::from_group(group).unwrap();
262    //     assert_eq!(lib.name, "mylib");
263    //     assert_eq!(lib.groups.len(), 1);
264    //     assert_eq!(lib.cells.len(), 1);
265    //     let converted_cell = lib.cell("AND2").unwrap();
266    //     assert_eq!(converted_cell.name, "AND2");
267    //     assert_eq!(converted_cell.groups.len(), 0);
268    //     assert_eq!(converted_cell.pins.len(), 2);
269    // }
270}