reda_lib/io/read/
semantic_library.rs

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        // 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 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        // helpers that attach context when calling LibValue accessors
158        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        // let group = lib.into_group();
213        // assert_eq!(group.type_, "library");
214        // assert_eq!(group.name, "my_lib");
215        // assert_eq!(group.groups.len(), 3);
216    }
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}