reda_lib/io/read/
semantic.rs

1use std::collections::HashMap;
2use crate::error::{LibErrorContext, LibError};
3use crate::model::{LibAst, LibCell, LibGroup, LibLibrary, LibPin, LibPinDirection};
4
5pub trait FromLibGroup: Sized {
6    type Error: Sized;
7    fn from_group(group: LibGroup) -> Result<Self, Self::Error>;
8}
9
10impl LibLibrary {
11    pub fn from_ast(ast: LibAst) -> Result<Self, LibError> {
12        let group = LibGroup::from_ast(ast).context(|| "semantic root ast to group")?;
13        Self::from_group(group)
14    }
15}
16
17impl FromLibGroup for LibLibrary {
18    type Error = LibError;
19    fn  from_group(group: LibGroup) -> Result<Self, LibError> {
20        let mut group = group;
21        let name = group.expect_name().context(|| "group name")?;
22        let (cell_groups, groups) = group.groups.into_iter().partition(|g| g.kind == "cell");
23        
24        // collect cells
25        let mut cells = Vec::new();
26        for cell_group in cell_groups {
27            cells.push(LibCell::from_group(cell_group).context(|| "semantic cell")?);
28        }
29
30        Ok(Self {
31            name,
32            attrs: group.attrs,
33            groups,
34            cells,
35        })
36    }
37}
38
39impl FromLibGroup for LibCell {
40    type Error = LibError;
41    fn from_group(group: LibGroup) -> Result<Self, LibError> {
42        let mut group = group;
43        let name = group.expect_name().context(|| "cell name")?;
44        let err_context = |msg: &str| {
45            format!("{} in {} cell", msg, &name)
46        };
47
48        let (pin_groups, groups) = group.groups.into_iter().partition(|g| g.kind == "pin");
49
50        // collect cells
51        let mut pins = Vec::new();
52        for cell_group in pin_groups {
53            pins.push(LibPin::from_group(cell_group).context(|| err_context("semantic pin"))?);
54        }
55
56        Ok(Self {
57            name,
58            pins,
59            attrs: group.attrs,
60            groups,
61        })
62    }
63}
64
65impl FromLibGroup for LibPin {
66    type Error = LibError;
67
68    fn from_group(group: LibGroup) -> Result<Self, LibError> {
69        let mut group = group;
70        let name = group.expect_name().context(|| "pin name")?;
71        let err_context = |msg: &str| format!("{} in `{}` pin", msg, &name);
72
73        // helpers that attach context when calling LibValue accessors
74        let get_bool_opt = 
75            |key: &str| group.attr_bool_opt(key, || err_context(&format!("semantic `{}` attr", key)));
76        let get_float_opt = 
77            |key: &str| group.attr_float_opt(key, || err_context(&format!("semantic `{}` attr", key)));
78        let get_string_opt = 
79            |key: &str| group.attr_string_opt(key, || err_context(&format!("semantic `{}` attr", key))).map(|v| v.map(String::from));
80        let get_ident_opt = 
81            |key: &str| group.attr_ident_opt(key, || err_context(&format!("semantic `{}` attr", key))).map(|v| v.map(String::from));
82        let get_expr_opt = 
83            |key: &str| group.attr_expr_opt(key, &|| err_context(&format!("semantic `{}` attr", key)));
84
85
86        let alive_during_power_up = get_bool_opt("alive_during_power_up")?;
87        let always_on = get_bool_opt("always_on")?;
88
89        let antenna_diode_type = group.attr_parse_opt("antenna_diode_type", &|| err_context("semantic `antenna_diode_type` attr"))?;
90        let nextstate_type = group.attr_parse_opt("nextstate_type", &|| err_context("semantic `nextstate_type` attr"))?;
91
92        let antenna_diode_related_ground_pins = get_string_opt("antenna_diode_related_ground_pins")?;
93        let antenna_diode_related_power_pins = get_string_opt("antenna_diode_related_power_pins")?;
94        let bit_width = get_float_opt("bit_width")?.map(|v| v as usize);
95
96        let capacitance = get_float_opt("capacitance")?;
97        let fall_capacitance = get_float_opt("fall_capacitance")?;
98        let fanout_load = get_float_opt("fanout_load")?;
99        let drive_current = get_float_opt("drive_current")?;
100        let fall_current_slope_after_threshold = get_float_opt("fall_current_slope_after_threshold")?;
101        let fall_current_slope_before_threshold = get_float_opt("fall_current_slope_before_threshold")?;
102        let fall_time_after_threshold = get_float_opt("fall_time_after_threshold")?;
103        let fall_time_before_threshold = get_float_opt("fall_time_before_threshold")?;
104
105        let max_capacitance = get_float_opt("max_capacitance")?;
106        let min_capacitance = get_float_opt("min_capacitance")?;
107        let max_fanout = get_float_opt("max_fanout")?;
108        let min_fanout = get_float_opt("min_fanout")?;
109        let max_transition = get_float_opt("max_transition")?;
110        let min_transition = get_float_opt("min_transition")?;
111        let min_period = get_float_opt("min_period")?;
112        let min_pulse_width_high = get_float_opt("min_pulse_width_high")?;
113        let min_pulse_width_low = get_float_opt("min_pulse_width_low")?;
114        let max_input_delta_overdrive_high = get_float_opt("max_input_delta_overdrive_high")?;
115        let max_input_delta_underdrive_high = get_float_opt("max_input_delta_underdrive_high")?;
116
117        let clamp_0_function = get_string_opt("clamp_0_function")?;
118        let clamp_1_function = get_string_opt("clamp_1_function")?;
119        let clamp_latch_function = get_string_opt("clamp_latch_function")?;
120        let clamp_z_function = get_string_opt("clamp_z_function")?;
121        let illegal_clamp_condition = get_string_opt("illegal_clamp_condition")?;
122        let complementary_pin = get_string_opt("complementary_pin")?;
123
124        let clock = get_bool_opt("clock")?;
125        let clock_gate_clock_pin = get_bool_opt("clock_gate_clock_pin")?;
126        let clock_gate_enable_pin = get_bool_opt("clock_gate_enable_pin")?;
127        let clock_gate_test_pin = get_bool_opt("clock_gate_test_pin")?;
128        let clock_gate_obs_pin = get_bool_opt("clock_gate_obs_pin")?;
129        let clock_gate_out_pin = get_bool_opt("clock_gate_out_pin")?;
130        let clock_isolation_cell_clock_pin = get_bool_opt("clock_isolation_cell_clock_pin")?;
131
132        let direction = group.attr_parse_opt("direction", &|| err_context("semantic `direction` attr"))?.unwrap_or(LibPinDirection::Input);
133
134        let driver_type = group.attr_parse_opt("driver_type", &|| err_context("semantic `driver_type` attr"))?;
135
136        let output_signal_level = get_string_opt("output_signal_level")?;
137        let output_signal_level_high = get_float_opt("output_signal_level_high")?;
138        let output_signal_level_low = get_float_opt("output_signal_level_low")?;
139        let output_voltage = get_string_opt("output_voltage")?;
140        let input_signal_level = get_string_opt("input_signal_level")?;
141        let input_voltage = get_string_opt("input_voltage")?;
142
143        let has_builtin_pad = get_bool_opt("has_builtin_pad")?;
144        let hysteresis = get_bool_opt("hysteresis")?;
145        let is_pad = get_bool_opt("is_pad")?;
146        let is_unconnected = get_bool_opt("is_unconnected")?;
147        let multicell_pad_pin = get_bool_opt("multicell_pad_pin")?;
148        let inverted_output = get_bool_opt("inverted_output")?;
149
150        let connection_class = get_string_opt("connection_class")?;
151        let fault_model = get_string_opt("fault_model")?;
152        let dont_fault = group.attr_parse_opt("dont_fault", &|| err_context("semantic `dont_fault` attr"))?;
153        let internal_node = get_ident_opt("internal_node")?;
154        let input_map = get_string_opt("input_map")?;
155
156        let function = get_expr_opt("function")?;
157
158        // enums via attr_parse_opt (uses FromStr impls above)
159        let pin_func_type = group.attr_parse_opt("pin_func_type", &|| err_context("semantic `pin_func_type` attr"))?;
160        let primary_output = get_bool_opt("primary_output")?;
161        let pulling_current = get_float_opt("pulling_current")?;
162        let pulling_resistance = get_float_opt("pulling_resistance")?;
163        let restore_action = group.attr_parse_opt("restore_action", &|| err_context("semantic `restore_action` attr"))?;
164        let restore_edge_type = group.attr_parse_opt("restore_edge_type", &|| err_context("semantic `restore_edge_type` attr"))?;
165
166        // rise* (floats)
167        let rise_capacitance = get_float_opt("rise_capacitance")?;
168        let rise_current_slope_after_threshold = get_float_opt("rise_current_slope_after_threshold")?;
169        let rise_current_slope_before_threshold = get_float_opt("rise_current_slope_before_threshold")?;
170        let rise_time_after_threshold = get_float_opt("rise_time_after_threshold")?;
171        let rise_time_before_threshold = get_float_opt("rise_time_before_threshold")?;
172
173        let save_action = group.attr_parse_opt("save_action", &|| err_context("semantic `save_action` attr"))?;
174        let signal_type = group.attr_parse_opt("signal_type", &|| err_context("semantic `signal_type` attr"))?;
175        let slew_control = group.attr_parse_opt("slew_control", &|| err_context("semantic `slew_control` attr"))?;
176
177        // boolean / expr fields
178        let state_function = get_expr_opt("state_function")?;
179        let test_output_only = get_bool_opt("test_output_only")?;
180        let three_state = get_expr_opt("three_state")?;
181        let x_function = get_expr_opt("x_function")?;
182
183        let fall_capacitance_range = group.attr_floats_opt("fall_capacitance_range", &|| err_context("semantic `fall_capacitance_range` attr"))?;
184        let rise_capacitance_range = group.attr_floats_opt("rise_capacitance_range", &|| err_context("semantic `rise_capacitance_range` attr"))?;
185
186        Ok(Self {
187            name,
188
189            alive_during_power_up,
190            always_on,
191
192            antenna_diode_type,
193            antenna_diode_related_ground_pins,
194            antenna_diode_related_power_pins,
195
196            bit_width,
197
198            capacitance,
199            fall_capacitance,
200            fanout_load,
201            drive_current,
202            fall_current_slope_after_threshold,
203            fall_current_slope_before_threshold,
204            fall_time_after_threshold,
205            fall_time_before_threshold,
206
207            max_capacitance,
208            min_capacitance,
209            max_fanout,
210            min_fanout,
211            max_transition,
212            min_transition,
213            min_period,
214            min_pulse_width_high,
215            min_pulse_width_low,
216            max_input_delta_overdrive_high,
217            max_input_delta_underdrive_high,
218
219            clamp_0_function,
220            clamp_1_function,
221            clamp_latch_function,
222            clamp_z_function,
223            illegal_clamp_condition,
224            complementary_pin,
225            nextstate_type,
226
227            clock,
228            clock_gate_clock_pin,
229            clock_gate_enable_pin,
230            clock_gate_test_pin,
231            clock_gate_obs_pin,
232            clock_gate_out_pin,
233            clock_isolation_cell_clock_pin,
234
235            direction,
236            driver_type,
237            output_signal_level,
238            output_signal_level_high,
239            output_signal_level_low,
240            output_voltage,
241            input_signal_level,
242            input_voltage,
243
244            has_builtin_pad,
245            hysteresis,
246            is_pad,
247            is_unconnected,
248            multicell_pad_pin,
249            inverted_output,
250
251            connection_class,
252            fault_model,
253            dont_fault,
254            internal_node,
255            input_map,
256
257            function,
258
259            pin_func_type,
260            primary_output,
261            pulling_current,
262            pulling_resistance,
263            restore_action,
264            restore_edge_type,
265            rise_capacitance,
266            rise_current_slope_after_threshold,
267            rise_current_slope_before_threshold,
268            rise_time_after_threshold,
269            rise_time_before_threshold,
270            save_action,
271            signal_type,
272            slew_control,
273            state_function,
274            test_output_only,
275            three_state,
276            x_function,
277
278            fall_capacitance_range,
279            rise_capacitance_range,
280
281            attrs: group.attrs,
282            groups: group.groups,
283        })
284    }
285}
286
287impl LibGroup {
288    pub fn from_ast(ast: LibAst) -> Result<Self, LibError> {
289        match ast {
290            LibAst::LibGroup { kind, params, items } => {
291                let mut attrs = HashMap::new();
292                let mut groups = Vec::new();
293                
294                for item_ast in items {
295                    if let LibAst::Attr { key, value } = item_ast {
296                        attrs.insert(key, value);
297                    } else {
298                        groups.push(LibGroup::from_ast(item_ast)?);
299                    }
300                }
301
302                Ok(Self {
303                    kind, 
304                    params,
305                    attrs,
306                    groups
307                })
308            }
309            LibAst::Attr { key:_, value:_ } => Err(LibError::ExceptLibGroup),
310        }
311    }
312}
313
314#[cfg(test)]
315mod test {
316    use super::*;
317
318    #[test]
319    fn test_pin_into_group() {
320        let mut pin = LibPin::new("my_pin");
321        pin.groups.push(LibGroup::new("gtype", vec!["gname".to_string()]));
322        // let group = pin.into_group();
323        // assert_eq!(group.type_, "pin");
324        // assert_eq!(group.name, "my_pin");
325        // assert_eq!(group.groups.len(), 1);
326    }
327
328    #[test]
329    fn test_pin_from_group() {
330        let mut group = LibGroup::new("pin", vec!["a".to_string()]);
331        group.groups.push(LibGroup::new("gtype", vec!["gname".to_string()]));
332        let pin = LibPin::from_group(group).unwrap();
333        assert_eq!(pin.name, "a");
334        assert_eq!(pin.groups.len(), 1);
335    }
336
337    #[test]
338    fn test_cell_into_group() {
339        let mut cell = LibCell::new("my_cell");
340        cell.groups.push(LibGroup::new("gtype", vec!["gname".to_string()]));
341        cell.pins.push(LibPin::new("a"));
342        cell.pins.push(LibPin::new("b"));
343        // let group = cell.into_group();
344        // assert_eq!(group.type_, "cell");
345        // assert_eq!(group.name, "my_cell");
346        // assert_eq!(group.groups.len(), 3);
347    }
348
349    #[test]
350    fn test_cell_from_group() {
351        let mut group = LibGroup::new("cell", vec!["AND2".to_string()]);
352        group.groups.push(LibGroup::new("gtype", vec!["gname".to_string()]));
353        group.groups.push(LibGroup::new("pin", vec!["a".to_string()]));
354        group.groups.push(LibGroup::new("pin", vec!["b".to_string()]));
355        let cell = LibCell::from_group(group).unwrap();
356        assert_eq!(cell.name, "AND2");
357        assert_eq!(cell.groups.len(), 1);
358        assert_eq!(cell.pins.len(), 2);
359    }
360
361    #[test]
362    fn test_library_into_group() {
363        let mut lib = LibLibrary::new("my_lib");
364        lib.groups.push(LibGroup::new("gtype", vec!["gname".to_string()]));
365        lib.cells.push(LibCell::new("AND2"));
366        lib.cells.push(LibCell::new("NAND2"));
367        // let group = lib.into_group();
368        // assert_eq!(group.type_, "library");
369        // assert_eq!(group.name, "my_lib");
370        // assert_eq!(group.groups.len(), 3);
371    }
372
373    #[test]
374    fn test_lib_from_group() {
375        let mut group = LibGroup::new("library", vec!["mylib".to_string()]);
376        group.groups.push(LibGroup::new("gtype", vec!["gname".to_string()]));
377        let mut cell = LibGroup::new("cell", vec!["AND2".to_string()]);
378        cell.groups.push(LibGroup::new("pin", vec!["a".to_string()]));
379        cell.groups.push(LibGroup::new("pin", vec!["b".to_string()]));
380        group.groups.push(cell);
381        let lib = LibLibrary::from_group(group).unwrap();
382        assert_eq!(lib.name, "mylib");
383        assert_eq!(lib.groups.len(), 1);
384        assert_eq!(lib.cells.len(), 1);
385        let converted_cell = lib.cell("AND2").unwrap();
386        assert_eq!(converted_cell.name, "AND2");
387        assert_eq!(converted_cell.groups.len(), 0);
388        assert_eq!(converted_cell.pins.len(), 2);
389    }
390}