Skip to content

Commit da24535

Browse files
committed
Remove enum_read, enum_write.
Chiptool's codegen doesn't support it and never will. Having it in the IR schema complicates things for no benefit. svd2ir now merges read-only enum and write-only enums if both are present.
1 parent ac6e00b commit da24535

8 files changed

+93
-85
lines changed

src/generate/fieldset.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pub fn render(_opts: &super::Options, ir: &IR, fs: &FieldSet, path: &str) -> Res
3131
let to_bits: TokenStream;
3232
let from_bits: TokenStream;
3333

34-
if let Some(e_path) = &f.enum_readwrite {
34+
if let Some(e_path) = &f.enumm {
3535
let Some(e) = ir.enums.get(e_path) else {
3636
panic!("missing enum {}", e_path);
3737
};

src/ir.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -157,12 +157,8 @@ pub struct Field {
157157
pub bit_size: u32,
158158
#[serde(default, skip_serializing_if = "Option::is_none")]
159159
pub array: Option<Array>,
160-
#[serde(default, skip_serializing_if = "Option::is_none")]
161-
pub enum_read: Option<String>,
162-
#[serde(default, skip_serializing_if = "Option::is_none")]
163-
pub enum_write: Option<String>,
164160
#[serde(default, skip_serializing_if = "Option::is_none", rename = "enum")]
165-
pub enum_readwrite: Option<String>,
161+
pub enumm: Option<String>,
166162
}
167163

168164
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]

src/svd2ir.rs

+83-48
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ struct ProtoFieldset {
2323
#[derive(Debug)]
2424
struct ProtoEnum {
2525
name: Vec<String>,
26-
usage: Option<svd::Usage>,
2726
bit_size: u32,
2827
variants: Vec<svd::EnumeratedValue>,
2928
}
@@ -58,26 +57,97 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<()
5857
});
5958

6059
for f in fields {
60+
info!("field {}.{}", r.name, f.name);
61+
6162
if f.derived_from.is_some() {
6263
continue;
6364
}
6465

65-
let field_name = f.name.clone();
66+
let mut enum_read = None;
67+
let mut enum_write = None;
68+
let mut enum_readwrite = None;
6669

6770
for e in &f.enumerated_values {
6871
if e.derived_from.is_some() {
72+
// TODO
73+
warn!("ignoring enum with derivedFrom");
74+
continue;
75+
}
76+
77+
let usage = e.usage.unwrap_or(svd::Usage::ReadWrite);
78+
let target = match usage {
79+
svd::Usage::Read => &mut enum_read,
80+
svd::Usage::Write => &mut enum_write,
81+
svd::Usage::ReadWrite => &mut enum_readwrite,
82+
};
83+
84+
if target.is_some() {
85+
warn!("ignoring enum with dup usage {:?}", usage);
6986
continue;
7087
}
7188

72-
let mut enum_name = fieldset_name.clone();
73-
enum_name.push(make_enum_name(e, &f.enumerated_values, &field_name));
74-
info!("adding enum {:?}", enum_name);
89+
*target = Some(e)
90+
}
91+
92+
enum EnumSet<'a> {
93+
Single(&'a svd::EnumeratedValues),
94+
ReadWrite(&'a svd::EnumeratedValues, &'a svd::EnumeratedValues),
95+
}
7596

97+
let set = match (enum_read, enum_write, enum_readwrite) {
98+
(None, None, None) => None,
99+
(Some(e), None, None) => Some(EnumSet::Single(e)),
100+
(None, Some(e), None) => Some(EnumSet::Single(e)),
101+
(None, None, Some(e)) => Some(EnumSet::Single(e)),
102+
(Some(r), Some(w), None) => Some(EnumSet::ReadWrite(r, w)),
103+
(Some(r), None, Some(w)) => Some(EnumSet::ReadWrite(r, w)),
104+
(None, Some(w), Some(r)) => Some(EnumSet::ReadWrite(r, w)),
105+
(Some(_), Some(_), Some(_)) => panic!(
106+
"cannot have enumeratedvalues for read, write and readwrite!"
107+
),
108+
};
109+
110+
if let Some(set) = set {
111+
let variants = match set {
112+
EnumSet::Single(e) => e.values.clone(),
113+
EnumSet::ReadWrite(r, w) => {
114+
let r_values = r.values.iter().map(|v| v.value.unwrap());
115+
let w_values = w.values.iter().map(|v| v.value.unwrap());
116+
let values: HashSet<_> = r_values.chain(w_values).collect();
117+
let mut values: Vec<_> = values.iter().collect();
118+
values.sort();
119+
120+
let r_values: HashMap<_, _> =
121+
r.values.iter().map(|v| (v.value.unwrap(), v)).collect();
122+
let w_values: HashMap<_, _> =
123+
w.values.iter().map(|v| (v.value.unwrap(), v)).collect();
124+
125+
values
126+
.into_iter()
127+
.map(|&v| match (r_values.get(&v), w_values.get(&v)) {
128+
(None, None) => unreachable!(),
129+
(Some(&r), None) => r.clone(),
130+
(None, Some(&w)) => w.clone(),
131+
(Some(&r), Some(&w)) => {
132+
let mut m = r.clone();
133+
if r.name != w.name {
134+
m.name = format!("R_{}_W_{}", r.name, w.name);
135+
}
136+
m
137+
}
138+
})
139+
.collect()
140+
}
141+
};
142+
143+
info!("adding enum {:?}", fieldset_name);
144+
145+
let mut name = fieldset_name.clone();
146+
name.push(f.name.clone());
76147
enums.push(ProtoEnum {
77-
name: enum_name,
78-
usage: e.usage,
148+
name,
79149
bit_size: f.bit_range.width,
80-
variants: e.values.clone(),
150+
variants,
81151
});
82152
}
83153
}
@@ -203,30 +273,17 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<()
203273
bit_offset: f.bit_range.offset,
204274
bit_size: f.bit_range.width,
205275
array: None,
206-
enum_read: None,
207-
enum_write: None,
208-
enum_readwrite: None,
276+
enumm: None,
209277
};
210278

211-
for e in &f.enumerated_values {
279+
if !f.enumerated_values.is_empty() {
212280
let mut enum_name = proto.name.clone();
213-
enum_name.push(
214-
e.derived_from
215-
.clone()
216-
.unwrap_or_else(|| make_enum_name(e, &f.enumerated_values, &f.name)),
217-
);
281+
enum_name.push(f.name.clone());
282+
218283
info!("finding enum {:?}", enum_name);
219-
let enumm = enums.iter().find(|e| e.name == enum_name).unwrap();
220284
let enum_name = enum_names.get(&enum_name).unwrap().clone();
221285
info!("found {:?}", enum_name);
222-
223-
let usage = enumm.usage.unwrap_or(svd::Usage::ReadWrite);
224-
225-
match usage {
226-
svd::Usage::Read => field.enum_read = Some(enum_name.clone()),
227-
svd::Usage::Write => field.enum_write = Some(enum_name.clone()),
228-
svd::Usage::ReadWrite => field.enum_readwrite = Some(enum_name.clone()),
229-
}
286+
field.enumm = Some(enum_name.clone())
230287
}
231288

232289
fieldset.fields.push(field)
@@ -367,28 +424,6 @@ fn collect_blocks(
367424
}
368425
}
369426

370-
fn make_enum_name(
371-
e: &svd::EnumeratedValues,
372-
evs: &[svd::EnumeratedValues],
373-
field_name: &str,
374-
) -> String {
375-
if let Some(name) = &e.name {
376-
return name.clone();
377-
}
378-
379-
let mut res = field_name.to_string();
380-
if evs.len() > 1 {
381-
let suffix = match e.usage {
382-
None => "",
383-
Some(svd::Usage::Read) => "_R",
384-
Some(svd::Usage::Write) => "_W",
385-
Some(svd::Usage::ReadWrite) => "_RW",
386-
};
387-
res.push_str(suffix);
388-
}
389-
res
390-
}
391-
392427
fn unique_names(names: Vec<Vec<String>>) -> HashMap<Vec<String>, String> {
393428
let mut res = HashMap::new();
394429
let mut seen = HashSet::new();

src/transform/common.rs

+2-7
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,7 @@ pub(crate) fn mergeable_fields(a: &Field, b: &Field, level: CheckLevel) -> bool
103103
if level >= CheckLevel::Layout {
104104
res &= a.bit_size == b.bit_size
105105
&& a.bit_offset == b.bit_offset
106-
&& a.enum_read == b.enum_read
107-
&& a.enum_write == b.enum_write
108-
&& a.enum_readwrite == b.enum_readwrite
106+
&& a.enumm == b.enumm
109107
&& a.array == b.array;
110108
}
111109
if level >= CheckLevel::Names {
@@ -192,10 +190,7 @@ pub(crate) fn match_expand(s: &str, regex: &regex::Regex, res: &str) -> Option<S
192190
pub(crate) fn replace_enum_ids(ir: &mut IR, from: &HashSet<String>, to: String) {
193191
for (_, fs) in ir.fieldsets.iter_mut() {
194192
for f in fs.fields.iter_mut() {
195-
for id in [&mut f.enum_read, &mut f.enum_write, &mut f.enum_readwrite]
196-
.into_iter()
197-
.flatten()
198-
{
193+
if let Some(id) = &mut f.enumm {
199194
if from.contains(id) {
200195
*id = to.clone()
201196
}

src/transform/delete_enums.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,9 @@ impl DeleteEnums {
4141
pub(crate) fn remove_enum_ids(ir: &mut IR, from: &HashSet<String>) {
4242
for (_, fs) in ir.fieldsets.iter_mut() {
4343
for f in fs.fields.iter_mut() {
44-
for e in [&mut f.enum_read, &mut f.enum_write, &mut f.enum_readwrite].into_iter() {
45-
if let Some(id) = e {
46-
if from.contains(id) {
47-
*e = None
48-
}
44+
if let Some(id) = &mut f.enumm {
45+
if from.contains(id) {
46+
f.enumm = None
4947
}
5048
}
5149
}

src/transform/delete_enums_used_in.rs

+1-9
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,7 @@ impl DeleteEnumsUsedIn {
2222
if re.is_match(id) {
2323
info!("matched fieldset {}", id);
2424
for f in &fs.fields {
25-
if let Some(id) = &f.enum_read {
26-
info!("deleting enum {}", id);
27-
ids.insert(id.clone());
28-
}
29-
if let Some(id) = &f.enum_write {
30-
info!("deleting enum {}", id);
31-
ids.insert(id.clone());
32-
}
33-
if let Some(id) = &f.enum_readwrite {
25+
if let Some(id) = &f.enumm {
3426
info!("deleting enum {}", id);
3527
ids.insert(id.clone());
3628
}

src/transform/delete_fieldsets.rs

+1-7
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,7 @@ impl DeleteFieldsets {
4141
fn is_useless(fs: &FieldSet) -> bool {
4242
match &fs.fields[..] {
4343
[] => true,
44-
[f] => {
45-
fs.bit_size == f.bit_size
46-
&& f.bit_offset == 0
47-
&& f.enum_read.is_none()
48-
&& f.enum_write.is_none()
49-
&& f.enum_readwrite.is_none()
50-
}
44+
[f] => fs.bit_size == f.bit_size && f.bit_offset == 0 && f.enumm.is_none(),
5145
_ => false,
5246
}
5347
}

src/transform/mod.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,7 @@ pub fn map_enum_names(ir: &mut IR, f: impl Fn(&mut String)) {
7979

8080
for (_, fs) in ir.fieldsets.iter_mut() {
8181
for ff in fs.fields.iter_mut() {
82-
rename_opt(&mut ff.enum_read, &f);
83-
rename_opt(&mut ff.enum_write, &f);
84-
rename_opt(&mut ff.enum_readwrite, &f);
82+
rename_opt(&mut ff.enumm, &f);
8583
}
8684
}
8785
}

0 commit comments

Comments
 (0)