Skip to content

Commit c192581

Browse files
committed
field array support
1 parent 7d3cdf6 commit c192581

File tree

2 files changed

+195
-30
lines changed

2 files changed

+195
-30
lines changed

src/generate/register.rs

Lines changed: 187 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -216,23 +216,15 @@ pub fn fields(
216216
for f in fields.iter() {
217217
// TODO(AJM) - do we need to do anything with this range type?
218218
let BitRange { offset, width, .. } = f.bit_range;
219-
let sc = Ident::new(&f.name.to_sanitized_snake_case(), span);
220-
let pc = f.name.to_sanitized_upper_case();
219+
let name = util::replace_suffix(&f.name, "");
220+
let sc = Ident::new(&name.to_sanitized_snake_case(), span);
221+
let pc = name.to_sanitized_upper_case();
221222
let bits = Ident::new(if width == 1 { "bit" } else { "bits" }, span);
222-
let mut description_with_bits = if width == 1 {
223-
format!("Bit {}", offset)
224-
} else {
225-
format!("Bits {}:{}", offset, offset + width - 1)
226-
};
227223
let description = if let Some(d) = &f.description {
228224
util::respace(&util::escape_brackets(d))
229225
} else {
230226
"".to_owned()
231227
};
232-
if !description.is_empty() {
233-
description_with_bits.push_str(" - ");
234-
description_with_bits.push_str(&description);
235-
}
236228

237229
let can_read = can_read
238230
&& (f.access != Some(Access::WriteOnly))
@@ -246,7 +238,6 @@ pub fn fields(
246238
let fty = width.to_ty()?;
247239
let evs = &f.enumerated_values;
248240
let quotedfield = String::from("`") + &f.name + "`";
249-
let readerdoc = String::from("Reader of field ") + &quotedfield;
250241

251242
let lookup_results = lookup(
252243
evs,
@@ -264,7 +255,41 @@ pub fn fields(
264255

265256
let mut evs_r = None;
266257

258+
let field_dim = match f {
259+
Field::Array(_, de) => {
260+
let (first, index) = if let Some(dim_index) = &de.dim_index {
261+
if let Ok(first) = dim_index[0].parse::<u32>() {
262+
let sequential_indexes = dim_index
263+
.iter()
264+
.map(|element| element.parse::<u32>())
265+
.eq((first..de.dim + first).map(Ok));
266+
if !sequential_indexes {
267+
return Err(format!("unsupported array indexes in {}", f.name))?;
268+
}
269+
(first, None)
270+
} else {
271+
(0, de.dim_index.clone())
272+
}
273+
} else {
274+
(0, None)
275+
};
276+
let suffixes: Vec<_> = match index {
277+
Some(ix) => ix,
278+
None => (0..de.dim).map(|i| (first + i).to_string()).collect(),
279+
};
280+
let suffixes_str = format!("({}-{})", first, first + de.dim - 1);
281+
Some((first, de.dim, de.dim_increment, suffixes, suffixes_str))
282+
}
283+
Field::Single(_) => None,
284+
};
285+
267286
if can_read {
287+
let readerdoc = if let Some((_, _, _, _, suffixes_str)) = &field_dim {
288+
format!("Reader of fields `{}{}`", &name, &suffixes_str)
289+
} else {
290+
String::from("Reader of field ") + &quotedfield
291+
};
292+
268293
let _pc_r = Ident::new(&(pc.clone() + "_R"), span);
269294

270295
let cast = if width == 1 {
@@ -283,20 +308,64 @@ pub fn fields(
283308
}
284309
};
285310

286-
r_impl_items.extend(quote! {
287-
#[doc = #description_with_bits]
288-
#[inline(always)]
289-
pub fn #sc(&self) -> #_pc_r {
290-
#_pc_r::new ( #value )
311+
if let Some((first, dim, increment, suffixes, suffixes_str)) = &field_dim {
312+
let offset_calc = calculate_offset(*first, *increment, offset);
313+
let value = quote! { ((self.bits >> #offset_calc) & #hexmask) #cast };
314+
let doc = &util::replace_suffix(&description, suffixes_str);
315+
r_impl_items.extend(quote! {
316+
#[doc = #doc]
317+
#[inline(always)]
318+
pub unsafe fn #sc(&self, n: usize) -> #_pc_r {
319+
#_pc_r::new ( #value )
320+
}
321+
});
322+
for (i, suffix) in (0..*dim).zip(suffixes.iter()) {
323+
let sub_offset = offset + (i as u64) * (*increment as u64);
324+
let value = if sub_offset != 0 {
325+
let sub_offset = &util::unsuffixed(sub_offset);
326+
quote! {
327+
((self.bits >> #sub_offset) & #hexmask) #cast
328+
}
329+
} else {
330+
quote! {
331+
(self.bits & #hexmask) #cast
332+
}
333+
};
334+
let sc_n = Ident::new(
335+
&util::replace_suffix(&f.name.to_sanitized_snake_case(), &suffix),
336+
Span::call_site(),
337+
);
338+
let doc = util::replace_suffix(
339+
&description_with_bits(&description, sub_offset, width),
340+
&suffix,
341+
);
342+
r_impl_items.extend(quote! {
343+
#[doc = #doc]
344+
#[inline(always)]
345+
pub fn #sc_n(&self) -> #_pc_r {
346+
#_pc_r::new ( #value )
347+
}
348+
});
291349
}
292-
});
350+
} else {
351+
let doc = description_with_bits(&description, offset, width);
352+
r_impl_items.extend(quote! {
353+
#[doc = #doc]
354+
#[inline(always)]
355+
pub fn #sc(&self) -> #_pc_r {
356+
#_pc_r::new ( #value )
357+
}
358+
});
359+
}
293360

294361
if let Some((evs, base)) = lookup_filter(&lookup_results, Usage::Read) {
295362
evs_r = Some(evs.clone());
296363

297364
if let Some(base) = base {
298-
let pc = base.field.to_sanitized_upper_case();
299-
let base_pc_r = Ident::new(&(pc.clone() + "_A"), span);
365+
let base_pc_r = Ident::new(
366+
&(util::replace_suffix(base.field, "").to_sanitized_upper_case() + "_A"),
367+
span,
368+
);
300369
derive_from_base(mod_items, &base, &pc_r, &base_pc_r, &description);
301370

302371
mod_items.extend(quote! {
@@ -414,8 +483,11 @@ pub fn fields(
414483
if Some(evs) != evs_r.as_ref() {
415484
pc_w = &new_pc_w;
416485
if let Some(base) = base {
417-
let pc = base.field.to_sanitized_upper_case();
418-
let base_pc_w = Ident::new(&(pc + "_AW"), span);
486+
let base_pc_w = Ident::new(
487+
&(util::replace_suffix(base.field, "").to_sanitized_upper_case()
488+
+ "_AW"),
489+
span,
490+
);
419491
derive_from_base(mod_items, &base, &pc_w, &base_pc_w, &description)
420492
} else {
421493
add_from_variants(mod_items, &variants, pc_w, &fty, &description, rv);
@@ -463,7 +535,16 @@ pub fn fields(
463535
});
464536
}
465537

466-
proxy_items.extend(if offset != 0 {
538+
proxy_items.extend(if field_dim.is_some() {
539+
quote! {
540+
///Writes raw bits to the field
541+
#[inline(always)]
542+
pub #unsafety fn #bits(self, value: #fty) -> &'a mut W {
543+
self.w.bits = (self.w.bits & !(#hexmask << self.offset)) | (((value as #rty) & #hexmask) << self.offset);
544+
self.w
545+
}
546+
}
547+
} else if offset != 0 {
467548
let offset = &util::unsuffixed(offset);
468549
quote! {
469550
///Writes raw bits to the field
@@ -484,25 +565,66 @@ pub fn fields(
484565
}
485566
});
486567

487-
let doc = format!("Write proxy for field `{}`", f.name);
568+
let (doc, offset_entry) = if let Some((_, _, _, _, suffixes_str)) = &field_dim {
569+
(
570+
format!("Write proxy for fields `{}{}`", &name, &suffixes_str),
571+
quote! {offset: usize,},
572+
)
573+
} else {
574+
(format!("Write proxy for field `{}`", f.name), quote! {})
575+
};
576+
488577
mod_items.extend(quote! {
489578
#[doc = #doc]
490579
pub struct #_pc_w<'a> {
491580
w: &'a mut W,
581+
#offset_entry
492582
}
493583

494584
impl<'a> #_pc_w<'a> {
495585
#proxy_items
496586
}
497587
});
498588

499-
w_impl_items.extend(quote! {
500-
#[doc = #description_with_bits]
501-
#[inline(always)]
502-
pub fn #sc(&mut self) -> #_pc_w {
503-
#_pc_w { w: self }
589+
if let Some((first, dim, increment, suffixes, suffixes_str)) = &field_dim {
590+
let offset_calc = calculate_offset(*first, *increment, offset);
591+
let doc = &util::replace_suffix(&description, suffixes_str);
592+
w_impl_items.extend(quote! {
593+
#[doc = #doc]
594+
#[inline(always)]
595+
pub unsafe fn #sc(&mut self, n: usize) -> #_pc_w {
596+
#_pc_w { w: self, offset: #offset_calc }
597+
}
598+
});
599+
for (i, suffix) in (0..*dim).zip(suffixes.iter()) {
600+
let sub_offset = offset + (i as u64) * (*increment as u64);
601+
let sc_n = Ident::new(
602+
&util::replace_suffix(&f.name.to_sanitized_snake_case(), &suffix),
603+
Span::call_site(),
604+
);
605+
let doc = util::replace_suffix(
606+
&description_with_bits(&description, sub_offset, width),
607+
&suffix,
608+
);
609+
let sub_offset = util::unsuffixed(sub_offset as u64);
610+
w_impl_items.extend(quote! {
611+
#[doc = #doc]
612+
#[inline(always)]
613+
pub fn #sc_n(&mut self) -> #_pc_w {
614+
#_pc_w { w: self, offset: #sub_offset }
615+
}
616+
});
504617
}
505-
})
618+
} else {
619+
let doc = description_with_bits(&description, offset, width);
620+
w_impl_items.extend(quote! {
621+
#[doc = #doc]
622+
#[inline(always)]
623+
pub fn #sc(&mut self) -> #_pc_w {
624+
#_pc_w { w: self }
625+
}
626+
});
627+
}
506628
}
507629
}
508630

@@ -612,6 +734,41 @@ fn add_from_variants(
612734
});
613735
}
614736

737+
fn calculate_offset(first: u32, increment: u32, offset: u64) -> TokenStream {
738+
let mut res = if first != 0 {
739+
let first = util::unsuffixed(first as u64);
740+
quote! { n - #first }
741+
} else {
742+
quote! { n }
743+
};
744+
if increment != 1 {
745+
let increment = util::unsuffixed(increment as u64);
746+
res = if first != 0 {
747+
quote! { (#res) * #increment }
748+
} else {
749+
quote! { #res * #increment }
750+
};
751+
}
752+
if offset != 0 {
753+
let offset = &util::unsuffixed(offset);
754+
res = quote! { #res + #offset };
755+
}
756+
res
757+
}
758+
759+
fn description_with_bits(description: &str, offset: u64, width: u32) -> String {
760+
let mut res = if width == 1 {
761+
format!("Bit {}", offset)
762+
} else {
763+
format!("Bits {}:{}", offset, offset + width as u64 - 1)
764+
};
765+
if description.len() > 0 {
766+
res.push_str(" - ");
767+
res.push_str(&util::respace(&util::escape_brackets(description)));
768+
}
769+
res
770+
}
771+
615772
fn derive_from_base(
616773
mod_items: &mut TokenStream,
617774
base: &Base,

src/util.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,14 @@ pub fn replace_suffix(name: &str, suffix: &str) -> String {
197197
}
198198
}
199199

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

0 commit comments

Comments
 (0)