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 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 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 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 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 }
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}