Skip to content

Commit 91b37c7

Browse files
committed
Rehome some util functions
1 parent 71283da commit 91b37c7

File tree

3 files changed

+334
-332
lines changed

3 files changed

+334
-332
lines changed

src/generate/peripheral.rs

Lines changed: 120 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::io::{self, Write};
2+
use std::borrow::Cow;
23

34
use quote::{ToTokens, Tokens};
45
use svd::{Defaults, Peripheral, Register};
@@ -7,6 +8,7 @@ use syn::{self, Ident};
78
use errors::*;
89
use util::{self, ToSanitizedSnakeCase, ToSanitizedUpperCase, BITS_PER_BYTE};
910

11+
1012
use generate::register;
1113

1214
pub fn render(
@@ -116,7 +118,7 @@ fn register_block(registers: &[Register], defs: &Defaults) -> Result<Tokens> {
116118

117119
match *register {
118120
Register::Single(ref info) => registers_expanded.push(RegisterBlockField {
119-
field: util::convert_svd_register(register),
121+
field: convert_svd_register(register),
120122
description: info.description.clone(),
121123
offset: info.address_offset,
122124
size: register_size,
@@ -136,14 +138,14 @@ fn register_block(registers: &[Register], defs: &Defaults) -> Result<Tokens> {
136138

137139
if array_convertible {
138140
registers_expanded.push(RegisterBlockField {
139-
field: util::convert_svd_register(&register),
141+
field: convert_svd_register(&register),
140142
description: info.description.clone(),
141143
offset: info.address_offset,
142144
size: register_size * array_info.dim,
143145
});
144146
} else {
145147
let mut field_num = 0;
146-
for field in util::expand_svd_register(register).iter() {
148+
for field in expand_svd_register(register).iter() {
147149
registers_expanded.push(RegisterBlockField {
148150
field: field.clone(),
149151
description: info.description.clone(),
@@ -206,3 +208,118 @@ fn register_block(registers: &[Register], defs: &Defaults) -> Result<Tokens> {
206208
}
207209
})
208210
}
211+
212+
213+
/// Takes a svd::Register which may be a register array, and turn in into
214+
/// a list of syn::Field where the register arrays have been expanded.
215+
fn expand_svd_register(register: &Register) -> Vec<syn::Field> {
216+
let name_to_ty = |name: &String| -> syn::Ty {
217+
syn::Ty::Path(
218+
None,
219+
syn::Path {
220+
global: false,
221+
segments: vec![
222+
syn::PathSegment {
223+
ident: Ident::new(name.to_sanitized_upper_case()),
224+
parameters: syn::PathParameters::none(),
225+
},
226+
],
227+
},
228+
)
229+
};
230+
231+
let mut out = vec![];
232+
233+
match *register {
234+
Register::Single(ref _info) => out.push(convert_svd_register(register)),
235+
Register::Array(ref info, ref array_info) => {
236+
let has_brackets = info.name.contains("[%s]");
237+
238+
let indices = array_info
239+
.dim_index
240+
.as_ref()
241+
.map(|v| Cow::from(&**v))
242+
.unwrap_or_else(|| {
243+
Cow::from(
244+
(0..array_info.dim)
245+
.map(|i| i.to_string())
246+
.collect::<Vec<_>>(),
247+
)
248+
});
249+
250+
for (idx, _i) in indices.iter().zip(0..) {
251+
let name = if has_brackets {
252+
info.name.replace("[%s]", format!("{}", idx).as_str())
253+
} else {
254+
info.name.replace("%s", format!("{}", idx).as_str())
255+
};
256+
257+
let ty_name = if has_brackets {
258+
info.name.replace("[%s]", "")
259+
} else {
260+
info.name.replace("%s", "")
261+
};
262+
263+
let ident = Ident::new(name.to_sanitized_snake_case());
264+
let ty = name_to_ty(&ty_name);
265+
266+
out.push(syn::Field {
267+
ident: Some(ident),
268+
vis: syn::Visibility::Public,
269+
attrs: vec![],
270+
ty: ty,
271+
});
272+
}
273+
}
274+
}
275+
out
276+
}
277+
278+
fn convert_svd_register(register: &Register) -> syn::Field {
279+
let name_to_ty = |name: &String| -> syn::Ty {
280+
syn::Ty::Path(
281+
None,
282+
syn::Path {
283+
global: false,
284+
segments: vec![
285+
syn::PathSegment {
286+
ident: Ident::new(name.to_sanitized_upper_case()),
287+
parameters: syn::PathParameters::none(),
288+
},
289+
],
290+
},
291+
)
292+
};
293+
294+
match *register {
295+
Register::Single(ref info) => syn::Field {
296+
ident: Some(Ident::new(info.name.to_sanitized_snake_case())),
297+
vis: syn::Visibility::Public,
298+
attrs: vec![],
299+
ty: name_to_ty(&info.name),
300+
},
301+
Register::Array(ref info, ref array_info) => {
302+
let has_brackets = info.name.contains("[%s]");
303+
304+
let name = if has_brackets {
305+
info.name.replace("[%s]", "")
306+
} else {
307+
info.name.replace("%s", "")
308+
};
309+
310+
let ident = Ident::new(name.to_sanitized_snake_case());
311+
312+
let ty = syn::Ty::Array(
313+
Box::new(name_to_ty(&name)),
314+
syn::ConstExpr::Lit(syn::Lit::Int(array_info.dim as u64, syn::IntTy::Unsuffixed)),
315+
);
316+
317+
syn::Field {
318+
ident: Some(ident),
319+
vis: syn::Visibility::Public,
320+
attrs: vec![],
321+
ty: ty,
322+
}
323+
}
324+
}
325+
}

src/generate/register.rs

Lines changed: 212 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ pub fn fields(
296296
((self.bits >> OFFSET) & MASK as #rty) #cast
297297
};
298298

299-
if let Some((evs, base)) = util::lookup(
299+
if let Some((evs, base)) = lookup(
300300
f.evs,
301301
fields,
302302
parent,
@@ -584,7 +584,7 @@ pub fn fields(
584584
let mask = &f.mask;
585585
let width = f.width;
586586

587-
if let Some((evs, base)) = util::lookup(
587+
if let Some((evs, base)) = lookup(
588588
&f.evs,
589589
fields,
590590
parent,
@@ -803,3 +803,213 @@ pub fn fields(
803803

804804
Ok(())
805805
}
806+
807+
#[derive(Clone, Debug)]
808+
pub struct Base<'a> {
809+
pub peripheral: Option<&'a str>,
810+
pub register: Option<&'a str>,
811+
pub field: &'a str,
812+
}
813+
814+
fn lookup<'a>(
815+
evs: &'a [EnumeratedValues],
816+
fields: &'a [Field],
817+
register: &'a Register,
818+
all_registers: &'a [Register],
819+
peripheral: &'a Peripheral,
820+
all_peripherals: &'a [Peripheral],
821+
usage: Usage,
822+
) -> Result<Option<(&'a EnumeratedValues, Option<Base<'a>>)>> {
823+
let evs = evs.iter()
824+
.map(|evs| if let Some(ref base) = evs.derived_from {
825+
let mut parts = base.split('.');
826+
827+
match (parts.next(), parts.next(), parts.next(), parts.next()) {
828+
(Some(base_peripheral), Some(base_register), Some(base_field), Some(base_evs)) => {
829+
lookup_in_peripherals(
830+
base_peripheral,
831+
base_register,
832+
base_field,
833+
base_evs,
834+
all_peripherals,
835+
)
836+
}
837+
(Some(base_register), Some(base_field), Some(base_evs), None) => {
838+
lookup_in_peripheral(
839+
None,
840+
base_register,
841+
base_field,
842+
base_evs,
843+
all_registers,
844+
peripheral,
845+
)
846+
}
847+
(Some(base_field), Some(base_evs), None, None) => {
848+
lookup_in_fields(base_evs, base_field, fields, register)
849+
}
850+
(Some(base_evs), None, None, None) => lookup_in_register(base_evs, register),
851+
_ => unreachable!(),
852+
}
853+
} else {
854+
Ok((evs, None))
855+
})
856+
.collect::<Result<Vec<_>>>()?;
857+
858+
for &(ref evs, ref base) in evs.iter() {
859+
if evs.usage == Some(usage) {
860+
return Ok(Some((*evs, base.clone())));
861+
}
862+
}
863+
864+
Ok(evs.first().cloned())
865+
}
866+
867+
fn lookup_in_fields<'f>(
868+
base_evs: &str,
869+
base_field: &str,
870+
fields: &'f [Field],
871+
register: &Register,
872+
) -> Result<(&'f EnumeratedValues, Option<Base<'f>>)> {
873+
if let Some(base_field) = fields.iter().find(|f| f.name == base_field) {
874+
return lookup_in_field(base_evs, None, None, base_field);
875+
} else {
876+
Err(format!(
877+
"Field {} not found in register {}",
878+
base_field,
879+
register.name
880+
))?
881+
}
882+
}
883+
884+
fn lookup_in_peripheral<'p>(
885+
base_peripheral: Option<&'p str>,
886+
base_register: &'p str,
887+
base_field: &str,
888+
base_evs: &str,
889+
all_registers: &'p [Register],
890+
peripheral: &'p Peripheral,
891+
) -> Result<(&'p EnumeratedValues, Option<Base<'p>>)> {
892+
if let Some(register) = all_registers.iter().find(|r| r.name == base_register) {
893+
if let Some(field) = register
894+
.fields
895+
.as_ref()
896+
.map(|fs| &**fs)
897+
.unwrap_or(&[])
898+
.iter()
899+
.find(|f| f.name == base_field)
900+
{
901+
lookup_in_field(base_evs, Some(base_register), base_peripheral, field)
902+
} else {
903+
Err(format!(
904+
"No field {} in register {}",
905+
base_field,
906+
register.name
907+
))?
908+
}
909+
} else {
910+
Err(format!(
911+
"No register {} in peripheral {}",
912+
base_register,
913+
peripheral.name
914+
))?
915+
}
916+
}
917+
918+
fn lookup_in_field<'f>(
919+
base_evs: &str,
920+
base_register: Option<&'f str>,
921+
base_peripheral: Option<&'f str>,
922+
field: &'f Field,
923+
) -> Result<(&'f EnumeratedValues, Option<Base<'f>>)> {
924+
for evs in &field.enumerated_values {
925+
if evs.name.as_ref().map(|s| &**s) == Some(base_evs) {
926+
return Ok(
927+
(
928+
evs,
929+
Some(Base {
930+
field: &field.name,
931+
register: base_register,
932+
peripheral: base_peripheral,
933+
}),
934+
),
935+
);
936+
}
937+
}
938+
939+
Err(format!(
940+
"No EnumeratedValues {} in field {}",
941+
base_evs,
942+
field.name
943+
))?
944+
}
945+
946+
fn lookup_in_register<'r>(
947+
base_evs: &str,
948+
register: &'r Register,
949+
) -> Result<(&'r EnumeratedValues, Option<Base<'r>>)> {
950+
let mut matches = vec![];
951+
952+
for f in register.fields.as_ref().map(|v| &**v).unwrap_or(&[]) {
953+
if let Some(evs) = f.enumerated_values
954+
.iter()
955+
.find(|evs| evs.name.as_ref().map(|s| &**s) == Some(base_evs))
956+
{
957+
matches.push((evs, &f.name))
958+
}
959+
}
960+
961+
match matches.first() {
962+
None => Err(format!(
963+
"EnumeratedValues {} not found in register {}",
964+
base_evs,
965+
register.name
966+
))?,
967+
Some(&(evs, field)) => if matches.len() == 1 {
968+
return Ok((
969+
evs,
970+
Some(Base {
971+
field: field,
972+
register: None,
973+
peripheral: None,
974+
}),
975+
));
976+
} else {
977+
let fields = matches
978+
.iter()
979+
.map(|&(ref f, _)| &f.name)
980+
.collect::<Vec<_>>();
981+
Err(format!(
982+
"Fields {:?} have an \
983+
enumeratedValues named {}",
984+
fields,
985+
base_evs
986+
))?
987+
},
988+
}
989+
}
990+
991+
fn lookup_in_peripherals<'p>(
992+
base_peripheral: &'p str,
993+
base_register: &'p str,
994+
base_field: &str,
995+
base_evs: &str,
996+
all_peripherals: &'p [Peripheral],
997+
) -> Result<(&'p EnumeratedValues, Option<Base<'p>>)> {
998+
if let Some(peripheral) = all_peripherals.iter().find(|p| p.name == base_peripheral) {
999+
let all_registers = peripheral
1000+
.registers
1001+
.as_ref()
1002+
.map(|x| x.as_ref())
1003+
.unwrap_or(&[][..]);
1004+
lookup_in_peripheral(
1005+
Some(base_peripheral),
1006+
base_register,
1007+
base_field,
1008+
base_evs,
1009+
all_registers,
1010+
peripheral,
1011+
)
1012+
} else {
1013+
Err(format!("No peripheral {}", base_peripheral))?
1014+
}
1015+
}

0 commit comments

Comments
 (0)