Skip to content

Commit 852da47

Browse files
committed
field array support
1 parent ab03e5e commit 852da47

File tree

2 files changed

+192
-36
lines changed

2 files changed

+192
-36
lines changed

src/generate/register.rs

Lines changed: 184 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -228,23 +228,15 @@ pub fn fields(
228228
// TODO(AJM) - do we need to do anything with this range type?
229229
let BitRange { offset, width, .. } = f.bit_range;
230230
let span = Span::call_site();
231-
let sc = Ident::new(&f.name.to_sanitized_snake_case(), span);
232-
let pc = f.name.to_sanitized_upper_case();
231+
let name = util::replace_suffix(&f.name, "");
232+
let sc = Ident::new(&name.to_sanitized_snake_case(), span);
233+
let pc = name.to_sanitized_upper_case();
233234
let bits = Ident::new(if width == 1 { "bit" } else { "bits" }, span);
234-
let mut description_with_bits = if width == 1 {
235-
format!("Bit {}", offset)
236-
} else {
237-
format!("Bits {}:{}", offset, offset + width - 1)
238-
};
239235
let description = if let Some(d) = &f.description {
240236
util::respace(&util::escape_brackets(d))
241237
} else {
242238
"".to_owned()
243239
};
244-
if !description.is_empty() {
245-
description_with_bits.push_str(" - ");
246-
description_with_bits.push_str(&description);
247-
}
248240

249241
let can_read = [Access::ReadOnly, Access::ReadWriteOnce, Access::ReadWrite]
250242
.contains(&access)
@@ -275,6 +267,34 @@ pub fn fields(
275267

276268
let mut evs_r = None;
277269

270+
let field_dim = match f {
271+
Field::Array(_, de) => {
272+
let (first, index) = if let Some(dim_index) = &de.dim_index {
273+
if let Ok(first) = dim_index[0].parse::<u32>() {
274+
let sequential_indexes = dim_index
275+
.iter()
276+
.map(|element| element.parse::<u32>())
277+
.eq((first..de.dim + first).map(Ok));
278+
if !sequential_indexes {
279+
return Err(format!("unsupported array indexes in {}", f.name))?;
280+
}
281+
(first, None)
282+
} else {
283+
(0, de.dim_index.clone())
284+
}
285+
} else {
286+
(0, None)
287+
};
288+
let suffixes: Vec<_> = match index {
289+
Some(ix) => ix,
290+
None => (0..de.dim).map(|i| (first + i).to_string()).collect(),
291+
};
292+
let suffixes_str = format!("{}-{}", first, first + de.dim - 1);
293+
Some((first, de.dim, de.dim_increment, suffixes, suffixes_str))
294+
}
295+
Field::Single(_) => None,
296+
};
297+
278298
if can_read {
279299
let _pc_r = Ident::new(&(pc.clone() + "_R"), span);
280300

@@ -294,23 +314,71 @@ pub fn fields(
294314
}
295315
};
296316

297-
if let Some((evs, base)) = lookup_filter(&lookup_results, Usage::Read) {
298-
evs_r = Some(evs.clone());
299-
317+
if let Some((first, dim, increment, suffixes, _)) = &field_dim {
318+
let offset_calc = calculate_offset(*first, *increment, offset);
319+
let value = quote! { ((self.bits >> #offset_calc) & #hexmask) #cast };
320+
let doc = &description;
300321
r_impl_items.push(quote! {
301-
#[doc = #description_with_bits]
322+
#[doc = #doc]
323+
#[inline(always)]
324+
pub unsafe fn #sc(&self, n: usize) -> #_pc_r {
325+
#_pc_r::new( #value )
326+
}
327+
});
328+
for (i, suffix) in (0..*dim).zip(suffixes.iter()) {
329+
let sub_offset = offset + (i as u64) * (*increment as u64);
330+
let value = if sub_offset != 0 {
331+
let sub_offset = &util::unsuffixed(sub_offset);
332+
quote! {
333+
((self.bits >> #sub_offset) & #hexmask) #cast
334+
}
335+
} else {
336+
quote! {
337+
(self.bits & #hexmask) #cast
338+
}
339+
};
340+
let sc_n = Ident::new(
341+
&util::replace_suffix(&f.name.to_sanitized_snake_case(), &suffix),
342+
Span::call_site(),
343+
);
344+
let doc = util::replace_suffix(
345+
&description_with_bits(&description, sub_offset, width),
346+
&suffix,
347+
);
348+
r_impl_items.push(quote! {
349+
#[doc = #doc]
350+
#[inline(always)]
351+
pub fn #sc_n(&self) -> #_pc_r {
352+
#_pc_r::new( #value )
353+
}
354+
});
355+
}
356+
} else {
357+
let doc = description_with_bits(&description, offset, width);
358+
r_impl_items.push(quote! {
359+
#[doc = #doc]
302360
#[inline(always)]
303361
pub fn #sc(&self) -> #_pc_r {
304362
#_pc_r::new( #value )
305363
}
306364
});
365+
}
366+
367+
if let Some((evs, base)) = lookup_filter(&lookup_results, Usage::Read) {
368+
evs_r = Some(evs.clone());
307369

308370
if let Some(base) = base {
309-
let pc = base.field.to_sanitized_upper_case();
310-
let base_pc_r = Ident::new(&(pc.clone() + "_A"), span);
371+
let base_pc_r = Ident::new(
372+
&(util::replace_suffix(base.field, "").to_sanitized_upper_case() + "_A"),
373+
span,
374+
);
311375
derive_from_base(mod_items, &base, &pc_r, &base_pc_r, &description);
312376

313-
let doc = format!("Reader of field `{}`", f.name);
377+
let doc = if let Some((_, _, _, _, suffixes_str)) = &field_dim {
378+
format!("Reader of fields `{}({})`", &name, &suffixes_str)
379+
} else {
380+
format!("Reader of field `{}`", f.name)
381+
};
314382
mod_items.push(quote! {
315383
#[doc = #doc]
316384
pub type #_pc_r = crate::R<#fty, #pc_r>;
@@ -403,14 +471,6 @@ pub fn fields(
403471
});
404472
}
405473
} else {
406-
r_impl_items.push(quote! {
407-
#[doc = #description_with_bits]
408-
#[inline(always)]
409-
pub fn #sc(&self) -> #_pc_r {
410-
#_pc_r::new ( #value )
411-
}
412-
});
413-
414474
let doc = format!("Reader of field `{}`", f.name);
415475
mod_items.push(quote! {
416476
#[doc = #doc]
@@ -436,8 +496,11 @@ pub fn fields(
436496
if Some(evs) != evs_r.as_ref() {
437497
pc_w = &new_pc_w;
438498
if let Some(base) = base {
439-
let pc = base.field.to_sanitized_upper_case();
440-
let base_pc_w = Ident::new(&(pc + "_AW"), span);
499+
let base_pc_w = Ident::new(
500+
&(util::replace_suffix(base.field, "").to_sanitized_upper_case()
501+
+ "_AW"),
502+
span,
503+
);
441504
derive_from_base(mod_items, &base, &pc_w, &base_pc_w, &description)
442505
} else {
443506
add_from_variants(mod_items, &variants, pc_w, &fty, &description, rv);
@@ -485,7 +548,16 @@ pub fn fields(
485548
});
486549
}
487550

488-
proxy_items.push(if offset != 0 {
551+
proxy_items.push(if field_dim.is_some() {
552+
quote! {
553+
///Writes raw bits to the field
554+
#[inline(always)]
555+
pub #unsafety fn #bits(self, value: #fty) -> &'a mut W {
556+
self.w.bits = (self.w.bits & !(#hexmask << self.offset)) | (((value as #rty) & #hexmask) << self.offset);
557+
self.w
558+
}
559+
}
560+
} else if offset != 0 {
489561
let offset = &util::unsuffixed(offset);
490562
quote! {
491563
///Writes raw bits to the field
@@ -506,25 +578,66 @@ pub fn fields(
506578
}
507579
});
508580

509-
let doc = format!("Write proxy for field `{}`", f.name);
581+
let (doc, offset_entry) = if let Some((_, _, _, _, suffixes_str)) = &field_dim {
582+
(
583+
format!("Write proxy for fields `{}({})`", &name, &suffixes_str),
584+
quote! {offset: usize,},
585+
)
586+
} else {
587+
(format!("Write proxy for field `{}`", f.name), quote! {})
588+
};
589+
510590
mod_items.push(quote! {
511591
#[doc = #doc]
512592
pub struct #_pc_w<'a> {
513593
w: &'a mut W,
594+
#offset_entry
514595
}
515596

516597
impl<'a> #_pc_w<'a> {
517598
#(#proxy_items)*
518599
}
519600
});
520601

521-
w_impl_items.push(quote! {
522-
#[doc = #description_with_bits]
523-
#[inline(always)]
524-
pub fn #sc(&mut self) -> #_pc_w {
525-
#_pc_w { w: self }
602+
if let Some((first, dim, increment, suffixes, _)) = &field_dim {
603+
let offset_calc = calculate_offset(*first, *increment, offset);
604+
let doc = &description;
605+
w_impl_items.push(quote! {
606+
#[doc = #doc]
607+
#[inline(always)]
608+
pub unsafe fn #sc(&mut self, n: usize) -> #_pc_w {
609+
#_pc_w { w: self, offset: #offset_calc }
610+
}
611+
});
612+
for (i, suffix) in (0..*dim).zip(suffixes.iter()) {
613+
let sub_offset = offset + (i as u64) * (*increment as u64);
614+
let sc_n = Ident::new(
615+
&util::replace_suffix(&f.name.to_sanitized_snake_case(), &suffix),
616+
Span::call_site(),
617+
);
618+
let doc = util::replace_suffix(
619+
&description_with_bits(&description, sub_offset, width),
620+
&suffix,
621+
);
622+
let sub_offset = util::unsuffixed(sub_offset as u64);
623+
w_impl_items.push(quote! {
624+
#[doc = #doc]
625+
#[inline(always)]
626+
pub fn #sc_n(&mut self) -> #_pc_w {
627+
#_pc_w { w: self, offset: #sub_offset }
628+
}
629+
});
526630
}
527-
})
631+
} else {
632+
let doc = description_with_bits(&description, offset, width);
633+
w_impl_items.push(quote! {
634+
#[doc = #doc]
635+
#[inline(always)]
636+
pub fn #sc(&mut self) -> #_pc_w {
637+
#_pc_w { w: self }
638+
}
639+
});
640+
}
528641
}
529642
}
530643

@@ -634,6 +747,41 @@ fn add_from_variants(
634747
});
635748
}
636749

750+
fn calculate_offset(first: u32, increment: u32, offset: u64) -> TokenStream {
751+
let mut res = if first != 0 {
752+
let first = util::unsuffixed(first as u64);
753+
quote! { n - #first }
754+
} else {
755+
quote! { n }
756+
};
757+
if increment != 1 {
758+
let increment = util::unsuffixed(increment as u64);
759+
res = if first != 0 {
760+
quote! { (#res) * #increment }
761+
} else {
762+
quote! { #res * #increment }
763+
};
764+
}
765+
if offset != 0 {
766+
let offset = &util::unsuffixed(offset);
767+
res = quote! { #res + #offset };
768+
}
769+
res
770+
}
771+
772+
fn description_with_bits(description: &str, offset: u64, width: u32) -> String {
773+
let mut res = if width == 1 {
774+
format!("Bit {}", offset)
775+
} else {
776+
format!("Bits {}:{}", offset, offset + width as u64 - 1)
777+
};
778+
if description.len() > 0 {
779+
res.push_str(" - ");
780+
res.push_str(&util::respace(&util::escape_brackets(description)));
781+
}
782+
res
783+
}
784+
637785
fn derive_from_base(
638786
mod_items: &mut Vec<TokenStream>,
639787
base: &Base,

src/util.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,14 @@ pub fn name_of(register: &Register) -> Cow<str> {
195195
}
196196
}
197197

198+
pub fn replace_suffix(name: &str, suffix: &str) -> String {
199+
if name.contains("[%s]") {
200+
name.replace("[%s]", suffix)
201+
} else {
202+
name.replace("%s", suffix)
203+
}
204+
}
205+
198206
pub fn access_of(register: &Register) -> Access {
199207
register.access.unwrap_or_else(|| {
200208
if let Some(fields) = &register.fields {

0 commit comments

Comments
 (0)