reda_lib/io/read/
semantic_cell.rs1use crate::error::{LibErrorContext, LibError};
2use crate::model::{LibCell, LibFF, LibGroup, LibLeakagePower, LibPgPin, LibPin};
3use super::FromLibGroup;
4
5impl FromLibGroup for LibCell {
6 type Error = LibError;
7 fn from_group(group: LibGroup) -> Result<Self, LibError> {
8 let mut group = group;
9 let name = group.expect_name().context(|| "cell name")?;
10 let err_context = |msg: &str| {
11 format!("{} in {} cell", msg, &name)
12 };
13
14 let area = group.attr_float_opt("area", || err_context("semantic `area` attr"))?;
15 let drive_strength = group.attr_float_opt("drive_strength", || err_context("semantic `drive_strength` attr"))?.map(|f| f as usize);
16 let cell_leakage_power = group.attr_float_opt("cell_leakage_power", || err_context("semantic `cell_leakage_power` attr"))?;
17
18 let mut pins = vec![];
19 let mut pg_pins = vec![];
20 let mut leakage_powers = vec![];
21 let mut groups = vec![];
22 let mut ff = None;
23
24 for group in group.groups {
25 match group.kind.as_str() {
26 "pin" => pins.push(LibPin::from_group(group).context(|| err_context("semantic pin"))?),
27 "pg_pin" => pg_pins.push(LibPgPin::from_group(group).context(|| err_context("semantic pg_pin"))?),
28 "leakage_power" => leakage_powers.push(LibLeakagePower::from_group(group).context(|| err_context("semantic leakage_power"))?),
29 "ff" => if ff.is_some() {
30 Err(LibError::NotOnlyFF).context(|| err_context("semantic ff"))?;
31 } else {
32 ff = Some(LibFF::from_group(group).context(|| err_context("semantic ff"))?)
33 },
34 _ => groups.push(group),
35 }
36 }
37
38 Ok(Self {
39 name,
40 area,
41 drive_strength,
42 cell_leakage_power,
43 pins,
44 pg_pins,
45 leakage_powers,
46 attrs: group.attrs,
47 groups,
48 ff,
49 })
50 }
51}
52
53impl FromLibGroup for LibPgPin {
54 type Error = LibError;
55
56 fn from_group(group: LibGroup) -> Result<Self, Self::Error> {
57 let mut group = group;
58 let name = group.expect_name().context(|| "cell name")?;
59 let err_context = |msg: &str| format!("{} in `{}` pg_pin", msg, &name);
60
61 Ok(Self {
62 name: name.clone(),
63 voltage_name: group.attr_lliteral("voltage_name", || err_context("semantic `voltage_name` attr"))?.to_string(),
64 pg_type: group.attr_parse("pg_type", &|| err_context("semantic `pg_type` attr"))?,
65 user_pg_type: group.attr_string_opt("user_pg_type", || err_context("semantic `user_pg_type` attr"))?.map(String::from),
66 physical_connection: group.attr_parse_opt("physical_connection", &|| err_context("semantic `physical_connection` attr"))?,
67
68 attrs: group.attrs,
69 groups: group.groups,
70 })
71 }
72}
73
74impl FromLibGroup for LibLeakagePower {
75 type Error = LibError;
76
77 fn from_group(group: LibGroup) -> Result<Self, Self::Error> {
78 let err_context = |msg: &str| format!("{} in leakage_power", msg);
79
80 Ok(Self {
81 when: group.attr_expr("when", &|| err_context("semantic `when` attr"))?,
82 value: group.attr_float("value", &|| err_context("semantic `value` attr"))?,
83 attrs: group.attrs,
84 groups: group.groups,
85 })
86 }
87}
88
89impl FromLibGroup for LibFF {
90 type Error = LibError;
91
92 fn from_group(group: LibGroup) -> Result<Self, Self::Error> {
93 let err_context = |msg: &str| format!("{} in ff", msg);
94 let next_state = group.attr_expr_opt("next_state", &|| err_context("semantic `next_state` attr"))?;
95 let clear = group.attr_expr_opt("clear", &|| err_context("semantic `clear` attr"))?;
96 let clocked_on = group.attr_expr_opt("clocked_on", &|| err_context("semantic `clocked_on` attr"))?;
97 let clocked_on_also = group.attr_expr_opt("clocked_on_also", &|| err_context("semantic `clocked_on_also` attr"))?;
98 let preset = group.attr_expr_opt("preset", &|| err_context("semantic `preset` attr"))?;
99 let clear_preset_var1 = group.attr_parse_opt("clear_preset_var1", &|| err_context("semantic `clear_preset_var1` attr"))?;
100 let clear_preset_var2 = group.attr_parse_opt("clear_preset_var2", &|| err_context("semantic `clear_preset_var2` attr"))?;
101
102 Ok(Self {
103 names: group.params,
104 next_state,
105 clocked_on,
106 clear,
107 clocked_on_also,
108 preset,
109 clear_preset_var1,
110 clear_preset_var2,
111
112 attrs: group.attrs,
113 groups: group.groups,
114 })
115 }
116}
117
118#[cfg(test)]
119mod test {
120 use super::*;
121
122 #[test]
123 fn test_pin_into_group() {
124 let mut pin = LibPin::new("my_pin");
125 pin.groups.push(LibGroup::new("gtype", vec!["gname".to_string()]));
126 }
131
132 #[test]
133 fn test_pin_from_group() {
134 let mut group = LibGroup::new("pin", vec!["a".to_string()]);
135 group.groups.push(LibGroup::new("gtype", vec!["gname".to_string()]));
136 let pin = LibPin::from_group(group).unwrap();
137 assert_eq!(pin.name, "a");
138 assert_eq!(pin.groups.len(), 1);
139 }
140
141 #[test]
142 fn test_cell_into_group() {
143 let mut cell = LibCell::new("my_cell");
144 cell.groups.push(LibGroup::new("gtype", vec!["gname".to_string()]));
145 cell.pins.push(LibPin::new("a"));
146 cell.pins.push(LibPin::new("b"));
147 }
152
153}