Skip to main content

reda_lib/io/read/
semantic_pin.rs

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