Skip to content

Commit d2fb516

Browse files
bors[bot]burrbull
andauthored
Merge #400
400: field array support r=Disasm a=burrbull Co-authored-by: Andrey Zgarbul <[email protected]>
2 parents 7d3cdf6 + abbe720 commit d2fb516

File tree

1 file changed

+206
-39
lines changed

1 file changed

+206
-39
lines changed

src/generate/register.rs

+206-39
Original file line numberDiff line numberDiff line change
@@ -213,26 +213,19 @@ pub fn fields(
213213
let can_write = access != Access::ReadOnly;
214214

215215
// TODO enumeratedValues
216+
let inline = quote! { #[inline(always)] };
216217
for f in fields.iter() {
217218
// TODO(AJM) - do we need to do anything with this range type?
218219
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();
220+
let name = util::replace_suffix(&f.name, "");
221+
let sc = Ident::new(&name.to_sanitized_snake_case(), span);
222+
let pc = name.to_sanitized_upper_case();
221223
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-
};
227224
let description = if let Some(d) = &f.description {
228225
util::respace(&util::escape_brackets(d))
229226
} else {
230227
"".to_owned()
231228
};
232-
if !description.is_empty() {
233-
description_with_bits.push_str(" - ");
234-
description_with_bits.push_str(&description);
235-
}
236229

237230
let can_read = can_read
238231
&& (f.access != Some(Access::WriteOnly))
@@ -245,8 +238,6 @@ pub fn fields(
245238
let rv = reset_value.map(|rv| (rv >> offset) & mask);
246239
let fty = width.to_ty()?;
247240
let evs = &f.enumerated_values;
248-
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,50 @@ 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(_) => {
284+
if f.name.contains("%s") {
285+
return Err(format!("incorrect field {}", f.name))?;
286+
}
287+
None
288+
}
289+
};
290+
267291
if can_read {
292+
let readerdoc = if let Some((_, _, _, _, suffixes_str)) = &field_dim {
293+
format!(
294+
"Reader of fields `{}`",
295+
util::replace_suffix(&f.name, suffixes_str)
296+
)
297+
} else {
298+
let quotedfield = String::from("`") + &f.name + "`";
299+
String::from("Reader of field ") + &quotedfield
300+
};
301+
268302
let _pc_r = Ident::new(&(pc.clone() + "_R"), span);
269303

270304
let cast = if width == 1 {
@@ -283,20 +317,63 @@ pub fn fields(
283317
}
284318
};
285319

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 )
320+
if let Some((first, dim, increment, suffixes, suffixes_str)) = &field_dim {
321+
let offset_calc = calculate_offset(*first, *increment, offset);
322+
let value = quote! { ((self.bits >> #offset_calc) & #hexmask) #cast };
323+
let doc = &util::replace_suffix(&description, suffixes_str);
324+
r_impl_items.extend(quote! {
325+
#[doc = #doc]
326+
#inline
327+
pub unsafe fn #sc(&self, n: usize) -> #_pc_r {
328+
#_pc_r::new ( #value )
329+
}
330+
});
331+
for (i, suffix) in (0..*dim).zip(suffixes.iter()) {
332+
let sub_offset = offset + (i as u64) * (*increment as u64);
333+
let value = if sub_offset != 0 {
334+
let sub_offset = &util::unsuffixed(sub_offset);
335+
quote! {
336+
((self.bits >> #sub_offset) & #hexmask) #cast
337+
}
338+
} else {
339+
quote! {
340+
(self.bits & #hexmask) #cast
341+
}
342+
};
343+
let sc_n = Ident::new(
344+
&util::replace_suffix(&f.name.to_sanitized_snake_case(), &suffix),
345+
Span::call_site(),
346+
);
347+
let doc = util::replace_suffix(
348+
&description_with_bits(&description, sub_offset, width),
349+
&suffix,
350+
);
351+
r_impl_items.extend(quote! {
352+
#[doc = #doc]
353+
#inline
354+
pub fn #sc_n(&self) -> #_pc_r {
355+
#_pc_r::new ( #value )
356+
}
357+
});
291358
}
292-
});
359+
} else {
360+
let doc = description_with_bits(&description, offset, width);
361+
r_impl_items.extend(quote! {
362+
#[doc = #doc]
363+
#inline
364+
pub fn #sc(&self) -> #_pc_r {
365+
#_pc_r::new ( #value )
366+
}
367+
});
368+
}
293369

294370
if let Some((evs, base)) = lookup_filter(&lookup_results, Usage::Read) {
295371
evs_r = Some(evs.clone());
296372

297373
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);
374+
let pc = util::replace_suffix(base.field, "");
375+
let pc = pc.to_sanitized_upper_case();
376+
let base_pc_r = Ident::new(&(pc + "_A"), span);
300377
derive_from_base(mod_items, &base, &pc_r, &base_pc_r, &description);
301378

302379
mod_items.extend(quote! {
@@ -338,7 +415,7 @@ pub fn fields(
338415
if has_reserved_variant {
339416
enum_items.extend(quote! {
340417
///Get enumerated values variant
341-
#[inline(always)]
418+
#inline
342419
pub fn variant(&self) -> crate::Variant<#fty, #pc_r> {
343420
use crate::Variant::*;
344421
match self.bits {
@@ -349,7 +426,7 @@ pub fn fields(
349426
} else {
350427
enum_items.extend(quote! {
351428
///Get enumerated values variant
352-
#[inline(always)]
429+
#inline
353430
pub fn variant(&self) -> #pc_r {
354431
match self.bits {
355432
#arms
@@ -374,7 +451,7 @@ pub fn fields(
374451
let doc = format!("Checks if the value of the field is `{}`", pc);
375452
enum_items.extend(quote! {
376453
#[doc = #doc]
377-
#[inline(always)]
454+
#inline
378455
pub fn #is_variant(&self) -> bool {
379456
*self == #pc_r::#pc
380457
}
@@ -414,7 +491,8 @@ pub fn fields(
414491
if Some(evs) != evs_r.as_ref() {
415492
pc_w = &new_pc_w;
416493
if let Some(base) = base {
417-
let pc = base.field.to_sanitized_upper_case();
494+
let pc = util::replace_suffix(base.field, "");
495+
let pc = pc.to_sanitized_upper_case();
418496
let base_pc_w = Ident::new(&(pc + "_AW"), span);
419497
derive_from_base(mod_items, &base, &pc_w, &base_pc_w, &description)
420498
} else {
@@ -424,7 +502,7 @@ pub fn fields(
424502

425503
proxy_items.extend(quote! {
426504
///Writes `variant` to the field
427-
#[inline(always)]
505+
#inline
428506
pub fn variant(self, variant: #pc_w) -> &'a mut W {
429507
#unsafety {
430508
self.#bits(variant.into())
@@ -439,7 +517,7 @@ pub fn fields(
439517
let doc = util::escape_brackets(util::respace(&v.doc).as_ref());
440518
proxy_items.extend(quote! {
441519
#[doc = #doc]
442-
#[inline(always)]
520+
#inline
443521
pub fn #sc(self) -> &'a mut W {
444522
self.variant(#pc_w::#pc)
445523
}
@@ -450,24 +528,33 @@ pub fn fields(
450528
if width == 1 {
451529
proxy_items.extend(quote! {
452530
///Sets the field bit
453-
#[inline(always)]
531+
#inline
454532
pub #unsafety fn set_bit(self) -> &'a mut W {
455533
self.bit(true)
456534
}
457535

458536
///Clears the field bit
459-
#[inline(always)]
537+
#inline
460538
pub #unsafety fn clear_bit(self) -> &'a mut W {
461539
self.bit(false)
462540
}
463541
});
464542
}
465543

466-
proxy_items.extend(if offset != 0 {
544+
proxy_items.extend(if field_dim.is_some() {
545+
quote! {
546+
///Writes raw bits to the field
547+
#inline
548+
pub #unsafety fn #bits(self, value: #fty) -> &'a mut W {
549+
self.w.bits = (self.w.bits & !(#hexmask << self.offset)) | (((value as #rty) & #hexmask) << self.offset);
550+
self.w
551+
}
552+
}
553+
} else if offset != 0 {
467554
let offset = &util::unsuffixed(offset);
468555
quote! {
469556
///Writes raw bits to the field
470-
#[inline(always)]
557+
#inline
471558
pub #unsafety fn #bits(self, value: #fty) -> &'a mut W {
472559
self.w.bits = (self.w.bits & !(#hexmask << #offset)) | (((value as #rty) & #hexmask) << #offset);
473560
self.w
@@ -476,33 +563,78 @@ pub fn fields(
476563
} else {
477564
quote! {
478565
///Writes raw bits to the field
479-
#[inline(always)]
566+
#inline
480567
pub #unsafety fn #bits(self, value: #fty) -> &'a mut W {
481568
self.w.bits = (self.w.bits & !#hexmask) | ((value as #rty) & #hexmask);
482569
self.w
483570
}
484571
}
485572
});
486573

487-
let doc = format!("Write proxy for field `{}`", f.name);
574+
let doc;
575+
let offset_entry;
576+
if let Some((_, _, _, _, suffixes_str)) = &field_dim {
577+
doc = format!(
578+
"Write proxy for fields `{}`",
579+
util::replace_suffix(&f.name, suffixes_str)
580+
);
581+
offset_entry = quote! {offset: usize,};
582+
} else {
583+
doc = format!("Write proxy for field `{}`", f.name);
584+
offset_entry = quote! {};
585+
}
586+
488587
mod_items.extend(quote! {
489588
#[doc = #doc]
490589
pub struct #_pc_w<'a> {
491590
w: &'a mut W,
591+
#offset_entry
492592
}
493593

494594
impl<'a> #_pc_w<'a> {
495595
#proxy_items
496596
}
497597
});
498598

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

@@ -612,6 +744,41 @@ fn add_from_variants(
612744
});
613745
}
614746

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

0 commit comments

Comments
 (0)