Skip to content

Commit 8a52649

Browse files
committed
Instead of working on Register structs inside register_block we now work on the new struct RegisterBlockField. Instead of creating a brand new type representing a rust field it's an extension (by composition) of the syn::Field to also give information about offset, size and description. This means that the util extend function now extend to a vector of syn::Field.
1 parent a24a245 commit 8a52649

File tree

2 files changed

+112
-94
lines changed

2 files changed

+112
-94
lines changed

src/generate.rs

Lines changed: 79 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ use std::collections::HashMap;
22
use std::io::{self, Write};
33

44
use cast::u64;
5-
use quote::Tokens;
5+
use quote::{Tokens, ToTokens};
66
use svd::{Access, BitRange, Defaults, Device, EnumeratedValues, Field,
77
Peripheral, Register, Usage, WriteConstraint};
8+
use syn;
89
use syn::{Ident, Lit};
910

1011
use errors::*;
@@ -460,8 +461,15 @@ pub fn peripheral(
460461
Ok(())
461462
}
462463

464+
struct RegisterBlockField {
465+
field: syn::Field,
466+
description: Ident,
467+
offset: u32,
468+
size: u32,
469+
}
470+
463471
fn register_block(registers: &[Register], defs: &Defaults) -> Result<Tokens> {
464-
let mut fields = vec![];
472+
let mut fields = Tokens::new();
465473
// enumeration of reserved fields
466474
let mut i = 0;
467475
// offset from the base address, in bytes
@@ -470,8 +478,19 @@ fn register_block(registers: &[Register], defs: &Defaults) -> Result<Tokens> {
470478

471479
for register in registers {
472480
match *register {
473-
Register::Single(ref _into) => registers_expanded.push(register.clone()),
474-
Register::Array(ref _into, ref array_info) => {
481+
Register::Single(ref info) => registers_expanded.push(
482+
RegisterBlockField{
483+
field: util::convert_svd_register(register),
484+
description: Ident::from(info.description.clone()),
485+
offset: info.address_offset,
486+
size: info.size.or(defs.size)
487+
.ok_or_else(
488+
|| {
489+
format!("Register {} has no `size` field", register.name)
490+
},)?,
491+
}
492+
),
493+
Register::Array(ref info, ref array_info) => {
475494
let index_convertible = if let Some(ref indexes) = array_info.dim_index {
476495
let mut index_iter = indexes.iter();
477496
let mut previous = 0;
@@ -512,69 +531,90 @@ fn register_block(registers: &[Register], defs: &Defaults) -> Result<Tokens> {
512531
let array_convertible = index_convertible && packed_registers;
513532

514533
if array_convertible {
515-
registers_expanded.push(register.clone());
534+
registers_expanded.push(
535+
RegisterBlockField{
536+
field: util::convert_svd_register(&register),
537+
description: Ident::from(info.description.clone()),
538+
offset: info.address_offset,
539+
size: info.size.or(defs.size)
540+
.ok_or_else(
541+
|| {
542+
format!("Register {} has no `size` field", register.name)
543+
},)?
544+
* array_info.dim,
545+
});
516546
} else {
517-
registers_expanded.append(&mut util::expand(register));
547+
let mut field_num = 0;
548+
for field in util::expand_svd_register(register).iter() {
549+
registers_expanded.push(
550+
RegisterBlockField{
551+
field: field.clone(),
552+
description: Ident::from(info.description.clone()),
553+
offset: info.address_offset + field_num * array_info.dim_increment,
554+
size: info.size.or(defs.size)
555+
.ok_or_else(
556+
|| {
557+
format!("Register {} has no `size` field", register.name)
558+
},)?
559+
});
560+
field_num += 1;
561+
}
518562
}
519563
},
520564
}
521565
}
522566

523-
524-
for register in util::sort_by_offset(registers_expanded) {
525-
let pad = if let Some(pad) = register.address_offset.checked_sub(offset) {
567+
registers_expanded.sort_by_key(|x| x.offset);
568+
569+
for register in registers_expanded {
570+
let pad = if let Some(pad) = register.offset.checked_sub(offset) {
526571
pad
527572
} else {
528573
writeln!(
529574
io::stderr(),
530575
"WARNING {} overlaps with another register at offset {}. \
531576
Ignoring.",
532-
register.name,
533-
register.address_offset
534-
).ok();
577+
register.field.ident.unwrap(),
578+
register.offset
579+
)
580+
.ok();
535581
continue;
536582
};
537583

538584
if pad != 0 {
539585
let name = Ident::new(format!("_reserved{}", i));
540586
let pad = pad as usize;
541-
fields.push(quote! {
542-
#name : [u8; #pad],
543-
});
587+
fields.append(
588+
quote! {
589+
#name : [u8; #pad],
590+
});
544591
i += 1;
545592
}
593+
594+
let comment = &format!(
595+
"0x{:02x} - {}",
596+
register.offset,
597+
register.description,
598+
)
599+
[..];
546600

547-
fields.push( util::register_to_rust(&register) );
601+
fields.append(
602+
quote! {
603+
#[doc = #comment]
604+
}
605+
);
548606

549-
offset = match register {
550-
Register::Single(ref _into) => register.address_offset
551-
+
552-
register
553-
.size
554-
.or(defs.size)
555-
.ok_or_else(
556-
|| {
557-
format!("Register {} has no `size` field", register.name)
558-
},
559-
)? / 8,
560-
Register::Array(ref _into, ref array_info) => register.address_offset
561-
+
562-
register
563-
.size
564-
.or(defs.size)
565-
.ok_or_else(
566-
|| {
567-
format!("Register {} has no `size` field", register.name)
568-
},
569-
)? * array_info.dim / 8,
570-
};
607+
register.field.to_tokens(&mut fields);
608+
Ident::new(",").to_tokens(&mut fields);
609+
610+
offset = register.offset + register.size/8;
571611
}
572612

573613
Ok(quote! {
574614
/// Register block
575615
#[repr(C)]
576616
pub struct RegisterBlock {
577-
#(#fields)*
617+
#fields
578618
}
579619
})
580620
}

src/util.rs

Lines changed: 33 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use svd::{Access, EnumeratedValues, Field, Peripheral, Register,
77
Usage};
88
use syn;
99
use syn::{Ident, IntTy, Lit};
10-
use quote::{Tokens, ToTokens};
1110

1211
use errors::*;
1312

@@ -138,44 +137,23 @@ pub fn respace(s: &str) -> String {
138137
s.split_whitespace().collect::<Vec<_>>().join(" ")
139138
}
140139

141-
pub fn register_to_rust(register: &Register) -> Tokens {
142-
match *register {
143-
Register::Single(ref _info) => {
144-
let comment = &format!(
145-
"0x{:02x} - {}",
146-
register.address_offset,
147-
respace(&register.description)
148-
)
149-
[..];
150-
151-
let array_index_match = Regex::new(r"%s\((?P<i>[ a-zA-Z0-9]*)\)").unwrap();
152-
//println!("{}", register.name.as_str());
153-
let rty = Ident::new(array_index_match.replace_all(register.name.as_str(), "").to_sanitized_upper_case());
154-
let reg_name = Ident::new(array_index_match.replace_all(register.name.as_str(), "$i").to_sanitized_snake_case());
155-
156-
quote! {
157-
#[doc = #comment]
158-
pub #reg_name : #rty,
159-
}
160-
},
161-
Register::Array(ref info, ref array_info) => {
162-
let field = convert_svd_register(register);
163-
let mut tokens = Tokens::new();
164-
field.to_tokens(&mut tokens);
165-
Ident::new(",").to_tokens(&mut tokens);
166-
tokens
167-
},
168-
}
169-
}
170-
140+
/// Takes a svd::Register which may be a register array, and turn in into
141+
/// a list of syn::Field where the register arrays have been expanded.
142+
pub fn expand_svd_register(register: &Register) -> Vec<syn::Field> {
143+
let name_to_ty = |name: &String| -> syn::Ty {
144+
syn::Ty::Path(None, syn::Path{
145+
global: false,
146+
segments: vec![syn::PathSegment{
147+
ident: Ident::new(name.to_sanitized_upper_case()),
148+
parameters: syn::PathParameters::none(),
149+
}],
150+
})
151+
};
171152

172-
/// Takes a list of "registers", some of which may actually be register arrays,
173-
/// and turn in into alist of registers where the register arrays have been expanded.
174-
pub fn expand(register: &Register) -> Vec<Register> {
175153
let mut out = vec![];
176154

177155
match *register {
178-
Register::Single(ref _info) => out.push( register.clone() ),
156+
Register::Single(ref _info) => out.push( convert_svd_register(register) ),
179157
Register::Array(ref info, ref array_info) => {
180158
let has_brackets = info.name.contains("[%s]");
181159

@@ -192,28 +170,34 @@ pub fn expand(register: &Register) -> Vec<Register> {
192170
)
193171
},
194172
);
195-
196-
for (idx, i) in indices.iter().zip(0..) {
173+
174+
for (idx, _i) in indices.iter().zip(0..) {
197175
let name = if has_brackets {
198-
info.name.replace("[%s]", format!("%s({})", idx).as_str())
176+
info.name.replace("[%s]", format!("{}", idx).as_str())
199177
} else {
200-
info.name.replace("%s", format!("%s({})", idx).as_str())
178+
info.name.replace("%s", format!("{}", idx).as_str())
201179
};
202-
203-
let offset = info.address_offset +
204-
i * array_info.dim_increment;
205-
206-
let mut expanded_info = info.clone();
207-
expanded_info.name = name;
208-
expanded_info.address_offset = offset;
209180

181+
let ty_name = if has_brackets {
182+
info.name.replace("[%s]", "")
183+
} else {
184+
info.name.replace("%s", "")
185+
};
186+
187+
let ident = Ident::new(name.to_sanitized_snake_case());
188+
let ty = name_to_ty(&ty_name);
189+
210190
out.push(
211-
Register::Single(expanded_info)
191+
syn::Field{
192+
ident: Some(ident),
193+
vis: syn::Visibility::Public,
194+
attrs: vec![],
195+
ty: ty,
196+
}
212197
);
213198
}
214-
}
199+
},
215200
}
216-
217201
out
218202
}
219203

@@ -263,12 +247,6 @@ pub fn convert_svd_register(register: &svd::Register) -> syn::Field {
263247
}
264248
}
265249

266-
267-
pub fn sort_by_offset(mut registers: Vec<Register>) -> Vec<Register> {
268-
registers.sort_by_key(|x| x.address_offset);
269-
return registers;
270-
}
271-
272250
pub fn name_of(register: &Register) -> Cow<str> {
273251
match *register {
274252
Register::Single(ref info) => Cow::from(&*info.name),

0 commit comments

Comments
 (0)