Skip to content

Commit 1ca7988

Browse files
committed
field array support
1 parent ab03e5e commit 1ca7988

File tree

2 files changed

+183
-34
lines changed

2 files changed

+183
-34
lines changed

src/generate/register.rs

Lines changed: 175 additions & 34 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,33 @@ 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+
Some((first, de.dim, de.dim_increment, suffixes))
293+
}
294+
Field::Single(_) => None,
295+
};
296+
278297
if can_read {
279298
let _pc_r = Ident::new(&(pc.clone() + "_R"), span);
280299

@@ -294,20 +313,64 @@ pub fn fields(
294313
}
295314
};
296315

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

308369
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);
370+
let base_pc_r = Ident::new(
371+
&(util::replace_suffix(base.field, "").to_sanitized_upper_case() + "_A"),
372+
span,
373+
);
311374
derive_from_base(mod_items, &base, &pc_r, &base_pc_r, &description);
312375

313376
let doc = format!("Reader of field `{}`", f.name);
@@ -403,14 +466,6 @@ pub fn fields(
403466
});
404467
}
405468
} 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-
414469
let doc = format!("Reader of field `{}`", f.name);
415470
mod_items.push(quote! {
416471
#[doc = #doc]
@@ -436,8 +491,11 @@ pub fn fields(
436491
if Some(evs) != evs_r.as_ref() {
437492
pc_w = &new_pc_w;
438493
if let Some(base) = base {
439-
let pc = base.field.to_sanitized_upper_case();
440-
let base_pc_w = Ident::new(&(pc + "_AW"), span);
494+
let base_pc_w = Ident::new(
495+
&(util::replace_suffix(base.field, "").to_sanitized_upper_case()
496+
+ "_AW"),
497+
span,
498+
);
441499
derive_from_base(mod_items, &base, &pc_w, &base_pc_w, &description)
442500
} else {
443501
add_from_variants(mod_items, &variants, pc_w, &fty, &description, rv);
@@ -485,7 +543,16 @@ pub fn fields(
485543
});
486544
}
487545

488-
proxy_items.push(if offset != 0 {
546+
proxy_items.push(if field_dim.is_some() {
547+
quote! {
548+
///Writes raw bits to the field
549+
#[inline(always)]
550+
pub #unsafety fn #bits(self, value: #fty) -> &'a mut W {
551+
self.w.bits = (self.w.bits & !(#hexmask << self.offset)) | (((value as #rty) & #hexmask) << self.offset);
552+
self.w
553+
}
554+
}
555+
} else if offset != 0 {
489556
let offset = &util::unsuffixed(offset);
490557
quote! {
491558
///Writes raw bits to the field
@@ -506,25 +573,64 @@ pub fn fields(
506573
}
507574
});
508575

576+
let offset_entry = if field_dim.is_some() {
577+
quote! {offset: usize,}
578+
} else {
579+
quote! {}
580+
};
581+
509582
let doc = format!("Write proxy for field `{}`", f.name);
510583
mod_items.push(quote! {
511584
#[doc = #doc]
512585
pub struct #_pc_w<'a> {
513586
w: &'a mut W,
587+
#offset_entry
514588
}
515589

516590
impl<'a> #_pc_w<'a> {
517591
#(#proxy_items)*
518592
}
519593
});
520594

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 }
595+
if let Some((first, dim, increment, suffixes)) = field_dim.clone() {
596+
let offset_calc = calculate_offset(first, increment, offset);
597+
let doc = &f.description;
598+
w_impl_items.push(quote! {
599+
#[doc = #doc]
600+
#[inline(always)]
601+
pub unsafe fn #sc(&mut self, n: usize) -> #_pc_w {
602+
#_pc_w { w: self, offset: #offset_calc }
603+
}
604+
});
605+
for (i, suffix) in (0..dim).zip(suffixes.iter()) {
606+
let sub_offset = offset + (i as u64) * (increment as u64);
607+
let sc_n = Ident::new(
608+
&util::replace_suffix(&f.name.to_sanitized_snake_case(), &suffix),
609+
Span::call_site(),
610+
);
611+
let doc = util::replace_suffix(
612+
&description_with_bits(&description, sub_offset, width),
613+
&suffix,
614+
);
615+
let sub_offset = util::unsuffixed(sub_offset as u64);
616+
w_impl_items.push(quote! {
617+
#[doc = #doc]
618+
#[inline(always)]
619+
pub fn #sc_n(&mut self) -> #_pc_w {
620+
#_pc_w { w: self, offset: #sub_offset }
621+
}
622+
});
526623
}
527-
})
624+
} else {
625+
let doc = description_with_bits(&description, offset, width);
626+
w_impl_items.push(quote! {
627+
#[doc = #doc]
628+
#[inline(always)]
629+
pub fn #sc(&mut self) -> #_pc_w {
630+
#_pc_w { w: self }
631+
}
632+
});
633+
}
528634
}
529635
}
530636

@@ -634,6 +740,41 @@ fn add_from_variants(
634740
});
635741
}
636742

743+
fn calculate_offset(first: u32, increment: u32, offset: u64) -> TokenStream {
744+
let mut res = if first != 0 {
745+
let first = util::unsuffixed(first as u64);
746+
quote! { n - #first }
747+
} else {
748+
quote! { n }
749+
};
750+
if increment != 1 {
751+
let increment = util::unsuffixed(increment as u64);
752+
res = if first != 0 {
753+
quote! { (#res) * #increment }
754+
} else {
755+
quote! { #res * #increment }
756+
};
757+
}
758+
if offset != 0 {
759+
let offset = &util::unsuffixed(offset);
760+
res = quote! { #res + #offset };
761+
}
762+
res
763+
}
764+
765+
fn description_with_bits(description: &str, offset: u64, width: u32) -> String {
766+
let mut res = if width == 1 {
767+
format!("Bit {}", offset)
768+
} else {
769+
format!("Bits {}:{}", offset, offset + width as u64 - 1)
770+
};
771+
if description.len() > 0 {
772+
res.push_str(" - ");
773+
res.push_str(&util::respace(&util::escape_brackets(description)));
774+
}
775+
res
776+
}
777+
637778
fn derive_from_base(
638779
mod_items: &mut Vec<TokenStream>,
639780
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)