Skip to content

Commit 163fc34

Browse files
committed
Support loading names with placeholders
1 parent 7019219 commit 163fc34

1 file changed

Lines changed: 195 additions & 76 deletions

File tree

src/svd2ir.rs

Lines changed: 195 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,107 @@ pub enum NamespaceMode {
3838
BlockWithRegsVals,
3939
}
4040

41+
fn remove_placeholder(str: &str) -> String {
42+
str.replace("[%s]", "").replace("%s", "")
43+
}
44+
45+
fn names<T, F>(array: &MaybeArray<T>, f: F) -> ExpandedMaybeArray
46+
where
47+
F: Fn(&T) -> &str,
48+
{
49+
fn is_numeric(str: &String) -> bool {
50+
str.chars().all(|v| v.is_numeric())
51+
}
52+
53+
fn replace_placeholder(str: &str, replacement: &str) -> String {
54+
str.replace("%s", replacement)
55+
}
56+
57+
fn as_array_name<'a>(
58+
r: &str,
59+
mut dim_element: impl Iterator<Item = &'a String>,
60+
) -> Option<&str> {
61+
if let Some(array) = r.strip_suffix("[%s]") {
62+
Some(array)
63+
} else if let Some(missed_array) = r.strip_suffix("%s") {
64+
// If all dimensions are numeric, the element is an IR
65+
// array because accessing with a number offset makes
66+
// sense.
67+
if dim_element.all(is_numeric) {
68+
Some(missed_array)
69+
} else {
70+
None
71+
}
72+
} else {
73+
None
74+
}
75+
}
76+
77+
match array {
78+
MaybeArray::Single(r) => ExpandedMaybeArray::Single(f(r).to_string()),
79+
MaybeArray::Array(r, dim_element) => {
80+
if let Some(array_name) = as_array_name(f(r), dim_element.dim_index.iter().flatten()) {
81+
ExpandedMaybeArray::Array {
82+
name: array_name.to_string(),
83+
array: Array::Regular(RegularArray {
84+
len: dim_element.dim,
85+
stride: dim_element.dim_increment,
86+
}),
87+
}
88+
} else {
89+
let offsets = (0..).step_by(dim_element.dim_increment as _);
90+
91+
let values = offsets
92+
.zip(
93+
dim_element
94+
.dim_index
95+
.iter()
96+
.flat_map(|v| v.iter())
97+
.map(|dim| replace_placeholder(f(r), dim)),
98+
)
99+
.collect();
100+
101+
ExpandedMaybeArray::Many(values)
102+
}
103+
}
104+
}
105+
}
106+
107+
#[derive(Clone)]
108+
enum ExpandedMaybeArray {
109+
Single(String),
110+
Array { name: String, array: Array },
111+
Many(Vec<(u32, String)>),
112+
}
113+
114+
impl ExpandedMaybeArray {
115+
pub fn array(&self) -> Option<Array> {
116+
match self {
117+
ExpandedMaybeArray::Array { array, .. } => Some(array.clone()),
118+
_ => None,
119+
}
120+
}
121+
}
122+
123+
impl IntoIterator for ExpandedMaybeArray {
124+
type Item = (u32, String);
125+
126+
type IntoIter = std::vec::IntoIter<(u32, String)>;
127+
128+
fn into_iter(self) -> Self::IntoIter {
129+
match self {
130+
ExpandedMaybeArray::Single(s) => vec![(0, s)].into_iter(),
131+
ExpandedMaybeArray::Array { name, .. } => vec![(0, name)].into_iter(),
132+
ExpandedMaybeArray::Many(items) => items.into_iter(),
133+
}
134+
}
135+
}
136+
137+
fn fieldset_name(mut block_name: Vec<String>, reg_name: String) -> Vec<String> {
138+
block_name.push(reg_name);
139+
block_name
140+
}
141+
41142
pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<()> {
42143
let mut blocks = Vec::new();
43144
let pname = p.header_struct_name.clone().unwrap_or(p.name.clone());
@@ -49,7 +150,11 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<()
49150
);
50151

51152
let enum_from_name = enum_map(&blocks);
153+
52154
let mut fieldsets: Vec<ProtoFieldset> = Vec::new();
155+
let mut inner_block_to_fieldset = BTreeMap::new();
156+
let mut used_fieldset_names = BTreeSet::new();
157+
53158
let mut enums: Vec<ProtoEnum> = Vec::new();
54159

55160
let usable_register_clusters = blocks
@@ -68,14 +173,35 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<()
68173
return None;
69174
};
70175

71-
Some((b, r.deref().clone(), fields))
176+
let without_placeholder = remove_placeholder(&r.name);
177+
let mut fs_name = fieldset_name(b.clone(), without_placeholder.clone());
178+
179+
let mut counter = 0;
180+
loop {
181+
if counter != 0 {
182+
let last = fs_name.last_mut().unwrap();
183+
*last = format!("{}_{}", without_placeholder, counter);
184+
}
185+
186+
counter += 1;
187+
188+
if !used_fieldset_names.contains(&fs_name) {
189+
break;
190+
}
191+
}
192+
193+
used_fieldset_names.insert(fs_name.clone());
194+
195+
for (_, full_name) in names(r, |r| &r.name) {
196+
let full_name: Vec<_> = fieldset_name(b.clone(), full_name);
197+
inner_block_to_fieldset.insert(full_name, fs_name.clone());
198+
}
199+
200+
Some((fs_name, r.deref(), fields))
72201
});
73202

74-
for (block_name, r, fields) in usable_register_clusters {
75-
let mut fieldset_name = block_name.clone();
203+
for (fieldset_name, r, fields) in usable_register_clusters {
76204
let mut field_name_counts: BTreeMap<String, usize> = BTreeMap::new();
77-
fieldset_name.push(remove_placeholder(&r.name));
78-
79205
let mut out_fields = Vec::with_capacity(fields.len());
80206

81207
for f in fields {
@@ -88,7 +214,6 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<()
88214
let mut enum_readwrite = None;
89215

90216
let mut field_name = remove_placeholder(&f.name);
91-
92217
let field_name_count = field_name_counts.entry(field_name.clone()).or_insert(0);
93218
*field_name_count += 1;
94219
if *field_name_count > 1 {
@@ -219,37 +344,44 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<()
219344
continue;
220345
}
221346

222-
let block_item = create_block_item(proto, &fieldset_names, r);
223-
block.items.push(block_item)
347+
let names = crate::svd2ir::names(&r, |r| &r.name);
348+
let array = names.array();
349+
350+
for (offset, name) in names {
351+
let block_item = create_block_item(
352+
name,
353+
offset,
354+
proto,
355+
&inner_block_to_fieldset,
356+
&fieldset_names,
357+
array.as_ref(),
358+
r,
359+
);
360+
block.items.push(block_item)
361+
}
224362
}
225363
svd::RegisterCluster::Cluster(c) => {
226364
if c.derived_from.is_some() {
227365
warn!("unsupported derived_from in clusters");
228366
continue;
229367
}
230368

231-
let cname = remove_placeholder(&c.name);
232-
233-
let array = if let svd::Cluster::Array(_, dim) = c {
234-
Some(Array::Regular(RegularArray {
235-
len: dim.dim,
236-
stride: dim.dim_increment,
237-
}))
238-
} else {
239-
None
240-
};
241-
242-
let mut block_name = proto.name.clone();
243-
block_name.push(remove_placeholder(&c.name));
244-
let block_name = block_names.get(&block_name).unwrap().clone();
245-
246-
block.items.push(BlockItem {
247-
name: cname.clone(),
248-
description: c.description.clone(),
249-
array,
250-
byte_offset: c.address_offset,
251-
inner: BlockItemInner::Block(BlockItemBlock { block: block_name }),
252-
});
369+
let names = names(c, |c| &c.name);
370+
let array = names.array();
371+
372+
for (offset, cname) in names {
373+
let mut block_name = proto.name.clone();
374+
block_name.push(cname.clone());
375+
let block_name = block_names.get(&block_name).unwrap().clone();
376+
377+
block.items.push(BlockItem {
378+
name: cname.clone(),
379+
description: c.description.clone(),
380+
array: array.clone(),
381+
byte_offset: c.address_offset + offset,
382+
inner: BlockItemInner::Block(BlockItemBlock { block: block_name }),
383+
});
384+
}
253385
}
254386
}
255387
}
@@ -272,32 +404,26 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<()
272404
warn!("unsupported derived_from in fieldset");
273405
}
274406

275-
let array = if let svd::Field::Array(_, dim) = f {
276-
Some(Array::Regular(RegularArray {
277-
len: dim.dim,
278-
stride: dim.dim_increment,
279-
}))
280-
} else {
281-
None
282-
};
407+
let names = names(f, |f| &f.name);
408+
let array = names.array();
283409

284-
let field_name = remove_placeholder(&f.name);
285-
286-
let field = Field {
287-
name: field_name.clone(),
288-
description: f.description.clone(),
289-
bit_offset: BitOffset::Regular(f.bit_range.offset),
290-
bit_size: f.bit_range.width,
291-
array,
292-
enumm: enumm.as_ref().map(|v| {
293-
enum_names
294-
.get(v)
295-
.cloned()
296-
.expect("All enums have a unique-name mapping")
297-
}),
298-
};
410+
for (offset, field_name) in names {
411+
let field = Field {
412+
name: field_name.clone(),
413+
description: f.description.clone(),
414+
bit_offset: BitOffset::Regular(f.bit_range.offset + offset),
415+
bit_size: f.bit_range.width,
416+
array: array.clone(),
417+
enumm: enumm.as_ref().map(|v| {
418+
enum_names
419+
.get(v)
420+
.cloned()
421+
.expect("All enums have a unique-name mapping")
422+
}),
423+
};
299424

300-
fieldset.fields.push(field)
425+
fieldset.fields.push(field)
426+
}
301427
}
302428

303429
let fieldset_name = fieldset_names.get(&proto.name).unwrap().clone();
@@ -336,23 +462,18 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<()
336462
}
337463

338464
fn create_block_item(
465+
name: String,
466+
offset: u32,
339467
proto: &ProtoBlock,
468+
inner_block_to_fieldset: &BTreeMap<Vec<String>, Vec<String>>,
340469
fieldset_names: &BTreeMap<Vec<String>, String>,
470+
array: Option<&Array>,
341471
r: &MaybeArray<RegisterInfo>,
342472
) -> BlockItem {
343473
let fieldset_name = if r.fields.is_some() {
344-
let mut fieldset_name = proto.name.clone();
345-
fieldset_name.push(remove_placeholder(&r.name));
346-
Some(fieldset_names.get(&fieldset_name).unwrap().clone())
347-
} else {
348-
None
349-
};
350-
351-
let array = if let svd::Register::Array(_, dim) = r {
352-
Some(Array::Regular(RegularArray {
353-
len: dim.dim,
354-
stride: dim.dim_increment,
355-
}))
474+
let fieldset_full_name = fieldset_name(proto.name.clone(), name.clone());
475+
let fieldset_name = inner_block_to_fieldset.get(&fieldset_full_name).unwrap();
476+
Some(fieldset_names.get(fieldset_name).unwrap().clone())
356477
} else {
357478
None
358479
};
@@ -367,10 +488,10 @@ fn create_block_item(
367488
};
368489

369490
BlockItem {
370-
name: remove_placeholder(&r.name),
491+
name: name,
371492
description: r.description.clone(),
372-
array,
373-
byte_offset: r.address_offset,
493+
array: array.cloned(),
494+
byte_offset: r.address_offset + offset,
374495
inner: BlockItemInner::Register(Register {
375496
access, // todo
376497
bit_size: r.properties.size.unwrap_or(32),
@@ -504,9 +625,11 @@ fn collect_blocks(
504625
continue;
505626
}
506627

507-
let mut block_name = block_name.clone();
508-
block_name.push(remove_placeholder(&c.name));
509-
collect_blocks(out, block_name, c.description.clone(), &c.children);
628+
for (_, block) in names(c, |c| &c.name) {
629+
let mut block_name = block_name.clone();
630+
block_name.push(block);
631+
collect_blocks(out, block_name, c.description.clone(), &c.children);
632+
}
510633
}
511634
}
512635
}
@@ -600,7 +723,3 @@ pub fn namespace_names(peripheral: &PeripheralInfo, ir: &mut IR, namespace: Name
600723
}
601724
});
602725
}
603-
604-
pub fn remove_placeholder(name: &str) -> String {
605-
name.replace("[%s]", "").replace("%s", "")
606-
}

0 commit comments

Comments
 (0)