Skip to content

Commit f8e5628

Browse files
committed
support of alternateGroup registers
1 parent cbb1ade commit f8e5628

File tree

3 files changed

+71
-50
lines changed

3 files changed

+71
-50
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
99

1010
### Added
1111

12+
- Support for registers with alternateGroup
13+
1214
- New `-m` switch generates a `mod.rs` file instead of `lib.rs`, which can
1315
be used as a module inside a crate without further modification.
1416

src/generate/peripheral.rs

+52-47
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use quote::{quote, ToTokens};
1010
use svd_parser::derive_from::DeriveFrom;
1111
use syn::{parse_str, Token};
1212

13-
use crate::util::{self, ToSanitizedSnakeCase, ToSanitizedUpperCase, BITS_PER_BYTE};
13+
use crate::util::{self, FullName, ToSanitizedSnakeCase, ToSanitizedUpperCase, BITS_PER_BYTE};
1414
use anyhow::{anyhow, bail, Context, Result};
1515

1616
use crate::generate::register;
@@ -223,17 +223,17 @@ struct RegisterBlockField {
223223

224224
#[derive(Clone, Debug)]
225225
struct Region {
226-
fields: Vec<RegisterBlockField>,
226+
rbfs: Vec<RegisterBlockField>,
227227
offset: u32,
228228
end: u32,
229-
/// This is only used for regions with `fields.len() > 1`
229+
/// This is only used for regions with `rbfs.len() > 1`
230230
pub ident: Option<String>,
231231
}
232232

233233
impl Region {
234234
fn shortest_ident(&self) -> Option<String> {
235235
let mut idents: Vec<_> = self
236-
.fields
236+
.rbfs
237237
.iter()
238238
.filter_map(|f| match &f.field.ident {
239239
None => None,
@@ -274,7 +274,7 @@ impl Region {
274274
}
275275

276276
let idents: Vec<_> = self
277-
.fields
277+
.rbfs
278278
.iter()
279279
.filter_map(|f| match &f.field.ident {
280280
None => None,
@@ -304,10 +304,13 @@ impl Region {
304304
}
305305
if index <= 1 {
306306
None
307-
} else if first.get(index).is_some() && first[index].chars().all(|c| c.is_numeric()) {
308-
Some(first.iter().take(index).cloned().collect())
309307
} else {
310-
Some(first.iter().take(index - 1).cloned().collect())
308+
Some(match first.get(index) {
309+
Some(elem) if elem.chars().all(|c| c.is_numeric()) => {
310+
first.iter().take(index).cloned().collect()
311+
}
312+
_ => first.iter().take(index - 1).cloned().collect(),
313+
})
311314
}
312315
}
313316

@@ -320,12 +323,12 @@ impl Region {
320323
}
321324

322325
fn is_union(&self) -> bool {
323-
self.fields.len() > 1
326+
self.rbfs.len() > 1
324327
}
325328
}
326329

327330
/// FieldRegions keeps track of overlapping field regions,
328-
/// merging fields into appropriate regions as we process them.
331+
/// merging rbfs into appropriate regions as we process them.
329332
/// This allows us to reason about when to create a union
330333
/// rather than a struct.
331334
#[derive(Default, Debug)]
@@ -338,19 +341,19 @@ struct FieldRegions {
338341
impl FieldRegions {
339342
/// Track a field. If the field overlaps with 1 or more existing
340343
/// entries, they will be merged together.
341-
fn add(&mut self, field: &RegisterBlockField) -> Result<()> {
344+
fn add(&mut self, rbf: &RegisterBlockField) -> Result<()> {
342345
// When merging, this holds the indices in self.regions
343-
// that the input `field` will be merging with.
346+
// that the input `rbf` will be merging with.
344347
let mut indices = Vec::new();
345348

346-
let field_start = field.offset;
347-
let field_end = field_start + (field.size + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
349+
let rbf_start = rbf.offset;
350+
let rbf_end = rbf_start + (rbf.size + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
348351

349352
// The region that we're going to insert
350353
let mut new_region = Region {
351-
fields: vec![field.clone()],
352-
offset: field.offset,
353-
end: field_end,
354+
rbfs: vec![rbf.clone()],
355+
offset: rbf.offset,
356+
end: rbf_end,
354357
ident: None,
355358
};
356359

@@ -363,8 +366,8 @@ impl FieldRegions {
363366
let f_end = f.end;
364367

365368
// Compute intersection range
366-
let begin = f_start.max(field_start);
367-
let end = f_end.min(field_end);
369+
let begin = f_start.max(rbf_start);
370+
let end = f_end.min(rbf_end);
368371

369372
if end > begin {
370373
// We're going to remove this element and fold it
@@ -375,8 +378,8 @@ impl FieldRegions {
375378
new_region.offset = new_region.offset.min(f_start);
376379
new_region.end = new_region.end.max(f_end);
377380

378-
// And merge in the fields
379-
new_region.fields.append(&mut f.fields);
381+
// And merge in the rbfs
382+
new_region.rbfs.append(&mut f.rbfs);
380383
}
381384
}
382385

@@ -387,7 +390,7 @@ impl FieldRegions {
387390
self.regions.remove(*idx);
388391
}
389392

390-
new_region.fields.sort_by_key(|f| f.offset);
393+
new_region.rbfs.sort_by_key(|f| f.offset);
391394

392395
// maintain the regions ordered by starting offset
393396
let idx = self
@@ -413,7 +416,7 @@ impl FieldRegions {
413416
let idents: Vec<_> = {
414417
self.regions
415418
.iter_mut()
416-
.filter(|r| r.fields.len() > 1)
419+
.filter(|r| r.rbfs.len() > 1)
417420
.map(|r| {
418421
r.ident = r.compute_ident();
419422
r.ident.clone()
@@ -424,15 +427,15 @@ impl FieldRegions {
424427
.iter_mut()
425428
.filter(|r| r.ident.is_some())
426429
.filter(|r| {
427-
r.fields.len() > 1 && (idents.iter().filter(|ident| **ident == r.ident).count() > 1)
430+
r.rbfs.len() > 1 && (idents.iter().filter(|&ident| ident == &r.ident).count() > 1)
428431
})
429432
.for_each(|r| {
433+
let new_ident = r.shortest_ident();
430434
warn!(
431435
"Found type name conflict with region {:?}, renamed to {:?}",
432-
r.ident,
433-
r.shortest_ident()
436+
r.ident, new_ident
434437
);
435-
r.ident = r.shortest_ident();
438+
r.ident = new_ident;
436439
});
437440
Ok(())
438441
}
@@ -444,7 +447,7 @@ fn register_or_cluster_block(
444447
name: Option<&str>,
445448
_nightly: bool,
446449
) -> Result<TokenStream> {
447-
let mut fields = TokenStream::new();
450+
let mut rbfs = TokenStream::new();
448451
let mut accessors = TokenStream::new();
449452
let mut have_accessors = false;
450453

@@ -459,7 +462,7 @@ fn register_or_cluster_block(
459462

460463
// We need to compute the idents of each register/union block first to make sure no conflicts exists.
461464
regions.resolve_idents()?;
462-
// The end of the region for which we previously emitted a field into `fields`
465+
// The end of the region for which we previously emitted a rbf into `rbfs`
463466
let mut last_end = 0;
464467

465468
let span = Span::call_site();
@@ -469,15 +472,15 @@ fn register_or_cluster_block(
469472
if pad != 0 {
470473
let name = Ident::new(&format!("_reserved{}", i), span);
471474
let pad = pad as usize;
472-
fields.extend(quote! {
475+
rbfs.extend(quote! {
473476
#name : [u8; #pad],
474477
});
475478
}
476479

477-
let mut region_fields = TokenStream::new();
480+
let mut region_rbfs = TokenStream::new();
478481
let is_region_a_union = region.is_union();
479482

480-
for reg_block_field in &region.fields {
483+
for reg_block_field in &region.rbfs {
481484
let comment = &format!(
482485
"0x{:02x} - {}",
483486
reg_block_field.offset,
@@ -499,20 +502,20 @@ fn register_or_cluster_block(
499502
}
500503
});
501504
} else {
502-
region_fields.extend(quote! {
505+
region_rbfs.extend(quote! {
503506
#[doc = #comment]
504507
});
505508

506-
reg_block_field.field.to_tokens(&mut region_fields);
507-
Punct::new(',', Spacing::Alone).to_tokens(&mut region_fields);
509+
reg_block_field.field.to_tokens(&mut region_rbfs);
510+
Punct::new(',', Spacing::Alone).to_tokens(&mut region_rbfs);
508511
}
509512
}
510513

511514
if !is_region_a_union {
512-
fields.extend(region_fields);
515+
rbfs.extend(region_rbfs);
513516
} else {
514517
// Emit padding for the items that we're not emitting
515-
// as fields so that subsequent fields have the correct
518+
// as rbfs so that subsequent rbfs have the correct
516519
// alignment in the struct. We could omit this and just
517520
// not updated `last_end`, so that the padding check in
518521
// the outer loop kicks in, but it is nice to be able to
@@ -534,7 +537,7 @@ fn register_or_cluster_block(
534537
span,
535538
);
536539
let pad = (region.end - region.offset) as usize;
537-
fields.extend(quote! {
540+
rbfs.extend(quote! {
538541
#name: [u8; #pad],
539542
})
540543
}
@@ -563,7 +566,7 @@ fn register_or_cluster_block(
563566
///Register block
564567
#[repr(C)]
565568
pub struct #name {
566-
#fields
569+
#rbfs
567570
}
568571

569572
#accessors
@@ -809,10 +812,10 @@ fn expand_svd_register(
809812
)
810813
});
811814

812-
let ty_name = util::replace_suffix(&info.name, "");
815+
let ty_name = util::replace_suffix(&info.fullname(), "");
813816

814817
for (idx, _i) in indices.iter().zip(0..) {
815-
let nb_name = util::replace_suffix(&info.name, idx);
818+
let nb_name = util::replace_suffix(&info.fullname(), idx);
816819

817820
let ty = name_to_wrapped_ty(&ty_name, name)?;
818821

@@ -826,13 +829,15 @@ fn expand_svd_register(
826829
/// Convert a parsed `Register` into its `Field` equivalent
827830
fn convert_svd_register(register: &Register, name: Option<&str>) -> Result<syn::Field, syn::Error> {
828831
Ok(match register {
829-
Register::Single(info) => new_syn_field(
830-
&info.name.to_sanitized_snake_case(),
831-
name_to_wrapped_ty(&info.name, name)?,
832-
),
832+
Register::Single(info) => {
833+
let info_name = info.fullname();
834+
new_syn_field(
835+
&info_name.to_sanitized_snake_case(),
836+
name_to_wrapped_ty(&info_name, name)?,
837+
)
838+
}
833839
Register::Array(info, array_info) => {
834-
let nb_name = util::replace_suffix(&info.name, "");
835-
840+
let nb_name = util::replace_suffix(&info.fullname(), "");
836841
let ty = syn::Type::Array(parse_str::<syn::TypeArray>(&format!(
837842
"[{};{}]",
838843
name_to_wrapped_ty_str(&nb_name, name),

src/util.rs

+17-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::borrow::Cow;
22

3-
use crate::svd::{Access, Cluster, Register, RegisterCluster};
3+
use crate::svd::{Access, Cluster, Register, RegisterCluster, RegisterInfo};
44
use inflections::Inflect;
55
use proc_macro2::{Ident, Literal, Span, TokenStream};
66
use quote::{quote, ToTokens};
@@ -146,8 +146,8 @@ pub fn escape_brackets(s: &str) -> String {
146146

147147
pub fn name_of(register: &Register) -> Cow<str> {
148148
match register {
149-
Register::Single(info) => Cow::from(&info.name),
150-
Register::Array(info, _) => replace_suffix(&info.name, "").into(),
149+
Register::Single(info) => info.fullname(),
150+
Register::Array(info, _) => replace_suffix(&info.fullname(), "").into(),
151151
}
152152
}
153153

@@ -331,3 +331,17 @@ pub fn build_rs() -> TokenStream {
331331
}
332332
}
333333
}
334+
335+
pub trait FullName {
336+
fn fullname(&self) -> Cow<str>;
337+
}
338+
339+
impl FullName for RegisterInfo {
340+
fn fullname(&self) -> Cow<str> {
341+
if let Some(group) = &self.alternate_group {
342+
format!("{}_{}", group, self.name).into()
343+
} else {
344+
self.name.as_str().into()
345+
}
346+
}
347+
}

0 commit comments

Comments
 (0)