Skip to content

Commit ff56f52

Browse files
committed
field array support
1 parent 39934be commit ff56f52

File tree

3 files changed

+189
-46
lines changed

3 files changed

+189
-46
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- Support of field arrays
13+
1014
### Fixed
1115

1216
- Properly use of default RegisterProperties.

src/generate/register.rs

Lines changed: 177 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -221,8 +221,9 @@ pub fn fields(
221221
width,
222222
range_type: _,
223223
} = f.bit_range;
224-
let sc = f.name.to_sanitized_snake_case();
225-
let pc = f.name.to_sanitized_upper_case();
224+
let name = util::replace_suffix(&f.name, "");
225+
let sc = name.to_sanitized_snake_case();
226+
let pc = name.to_sanitized_upper_case();
226227
let span = Span::call_site();
227228
let pc_r = Ident::new(&format!("{}_A", pc), span);
228229
let _pc_r = Ident::new(&format!("{}_R", pc), span);
@@ -234,26 +235,43 @@ pub fn fields(
234235
} else {
235236
"bits"
236237
}, Span::call_site());
237-
let mut description_with_bits = if width == 1 {
238-
format!("Bit {}", offset)
239-
} else {
240-
format!("Bits {}:{}", offset, offset + width - 1)
241-
};
242-
if let Some(d) = &f.description {
243-
description_with_bits.push_str(" - ");
244-
description_with_bits.push_str(&util::respace(&util::escape_brackets(d)));
245-
}
246238
let description = if let Some(d) = &f.description {
247239
util::respace(&util::escape_brackets(d))
248240
} else {
249241
"".to_owned()
250242
};
251243

244+
let dim = match f {
245+
Field::Array(_, de) => {
246+
let (first, index) = if let Some(dim_index) = &de.dim_index {
247+
if let Ok(first) = dim_index[0].parse::<u32>() {
248+
let sequential_indexes = dim_index
249+
.iter()
250+
.map(|element| element.parse::<u32>())
251+
.eq((first..de.dim+first).map(Ok));
252+
if !sequential_indexes {
253+
return Err(format!("unsupported array indexes in {}", f.name))?;
254+
}
255+
(first, None)
256+
} else {
257+
(0, de.dim_index.clone())
258+
}
259+
} else {
260+
(0, None)
261+
};
262+
let suffixes: Vec<_> = match index {
263+
Some(ix) => ix,
264+
None => (0..de.dim).map(|i| (first + i).to_string()).collect(),
265+
};
266+
Some((first, de.dim, de.dim_increment, suffixes))
267+
},
268+
Field::Single(_) => None
269+
};
270+
252271
Ok(F {
253272
_pc_w,
254273
_sc,
255274
description,
256-
description_with_bits,
257275
pc_r,
258276
_pc_r,
259277
pc_w,
@@ -267,6 +285,7 @@ pub fn fields(
267285
offset: u64::from(offset),
268286
ty: width.to_ty()?,
269287
write_constraint: f.write_constraint.as_ref(),
288+
dim,
270289
})
271290
}
272291
}
@@ -306,10 +325,10 @@ pub fn fields(
306325
let _pc_r = &f._pc_r;
307326
let _pc_w = &f._pc_w;
308327
let description = &f.description;
309-
let description_with_bits = &f.description_with_bits;
328+
let width = f.width;
310329

311330
if can_read {
312-
let cast = if f.width == 1 {
331+
let cast = if width == 1 {
313332
quote! { != 0 }
314333
} else {
315334
quote! { as #fty }
@@ -325,21 +344,72 @@ pub fn fields(
325344
}
326345
};
327346

328-
if let Some((evs, base)) = lookup_filter(&lookup_results, Usage::Read) {
329-
evs_r = Some(evs.clone());
330-
331-
let sc = &f.sc;
347+
let sc = &f.sc;
348+
if let Some((first, dim, increment, suffixes)) = f.dim.clone() {
349+
let mut offset_calc = if first != 0 {
350+
let first = util::unsuffixed(first as u64);
351+
quote! { (n - #first) }
352+
} else {
353+
quote! { n }
354+
};
355+
if increment != 1 {
356+
let increment = util::unsuffixed(increment as u64);
357+
offset_calc = quote! { #offset_calc * #increment };
358+
}
359+
offset_calc = if offset !=0 {
360+
let offset = &util::unsuffixed(offset);
361+
quote! { let o = #offset_calc + #offset; }
362+
} else {
363+
quote! { let o = #offset_calc; }
364+
};
365+
let value = quote! { ((self.bits >> o) & #mask) #cast };
366+
let doc = &f.description;
332367
r_impl_items.push(quote! {
333-
#[doc = #description_with_bits]
368+
#[doc = #doc]
369+
#[inline(always)]
370+
pub unsafe fn #sc(&self, n: u32) -> #_pc_r {
371+
#offset_calc
372+
#_pc_r::new( #value )
373+
}
374+
});
375+
for (i, suffix) in (0..dim).zip(suffixes.iter()) {
376+
let offset = offset + (i as u64)*(increment as u64);
377+
let value = if offset != 0 {
378+
let offset = &util::unsuffixed(offset);
379+
quote! {
380+
((self.bits >> #offset) & #mask) #cast
381+
}
382+
} else {
383+
quote! {
384+
(self.bits & #mask) #cast
385+
}
386+
};
387+
let sc_n = Ident::new(&util::replace_suffix(&f.name.to_sanitized_snake_case(), &suffix), Span::call_site());
388+
let doc = util::replace_suffix(&description_with_bits(&f.description, offset, width), &suffix);
389+
r_impl_items.push(quote! {
390+
#[doc = #doc]
391+
#[inline(always)]
392+
pub fn #sc_n(&self) -> #_pc_r {
393+
#_pc_r::new( #value )
394+
}
395+
});
396+
}
397+
} else {
398+
let doc = description_with_bits(&f.description, f.offset, width);
399+
r_impl_items.push(quote! {
400+
#[doc = #doc]
334401
#[inline(always)]
335402
pub fn #sc(&self) -> #_pc_r {
336403
#_pc_r::new( #value )
337404
}
338405
});
406+
}
407+
408+
if let Some((evs, base)) = lookup_filter(&lookup_results, Usage::Read) {
409+
evs_r = Some(evs.clone());
339410

340411
base_pc_w = base.as_ref().map(|base| {
341-
let pc = base.field.to_sanitized_upper_case();
342-
let base_pc_r = Ident::new(&format!("{}_A", pc), Span::call_site());
412+
let base_pc_r = Ident::new(&format!("{}_A", util::replace_suffix(base.field, "").to_sanitized_upper_case()), Span::call_site());
343413
let base_pc_r = derive_from_base(mod_items, &base, &pc_r, &base_pc_r, description);
344414

345415
let doc = format!("Reader of field `{}`", f.name);
@@ -352,7 +422,7 @@ pub fn fields(
352422
});
353423

354424
if base.is_none() {
355-
let has_reserved_variant = evs.values.len() != (1 << f.width);
425+
let has_reserved_variant = evs.values.len() != (1 << width);
356426
let variants = Variant::from_enumerated_values(evs)?;
357427

358428
add_from_variants(mod_items, &variants, pc_r, &f, description, rv);
@@ -362,7 +432,7 @@ pub fn fields(
362432
let mut arms = variants
363433
.iter()
364434
.map(|v| {
365-
let i = util::unsuffixed_or_bool(v.value, f.width);
435+
let i = util::unsuffixed_or_bool(v.value, width);
366436
let pc = &v.pc;
367437

368438
if has_reserved_variant {
@@ -377,7 +447,7 @@ pub fn fields(
377447
arms.push(quote! {
378448
i => Res(i)
379449
});
380-
} else if 1 << f.width.to_ty_width()? != variants.len() {
450+
} else if 1 << width.to_ty_width()? != variants.len() {
381451
arms.push(quote! {
382452
_ => unreachable!()
383453
});
@@ -437,15 +507,6 @@ pub fn fields(
437507
}
438508

439509
} else {
440-
let sc = &f.sc;
441-
r_impl_items.push(quote! {
442-
#[doc = #description_with_bits]
443-
#[inline(always)]
444-
pub fn #sc(&self) -> #_pc_r {
445-
#_pc_r::new ( #value )
446-
}
447-
});
448-
449510
let doc = format!("Reader of field `{}`", f.name);
450511
mod_items.push(quote! {
451512
#[doc = #doc]
@@ -458,22 +519,20 @@ pub fn fields(
458519
if can_write {
459520
let mut proxy_items = vec![];
460521

461-
let mut unsafety = unsafety(f.write_constraint, f.width);
462-
let width = f.width;
522+
let mut unsafety = unsafety(f.write_constraint, width);
463523

464524
if let Some((evs, base)) = lookup_filter(&lookup_results, Usage::Write) {
465525
let variants = Variant::from_enumerated_values(evs)?;
466526

467-
if variants.len() == 1 << f.width {
527+
if variants.len() == 1 << width {
468528
unsafety = None;
469529
}
470530

471531
if Some(evs) != evs_r.as_ref() {
472532
pc_w = &f.pc_w;
473533

474534
base_pc_w = base.as_ref().map(|base| {
475-
let pc = base.field.to_sanitized_upper_case();
476-
let base_pc_w = Ident::new(&format!("{}_AW", pc), Span::call_site());
535+
let base_pc_w = Ident::new(&format!("{}_AW", util::replace_suffix(base.field, "").to_sanitized_upper_case()), Span::call_site());
477536
derive_from_base(mod_items, &base, &pc_w, &base_pc_w, description)
478537
});
479538

@@ -533,7 +592,33 @@ pub fn fields(
533592
});
534593
}
535594

536-
proxy_items.push(if offset != 0 {
595+
proxy_items.push(if let Some((first, _, increment, _)) = f.dim {
596+
let mut offset_calc = if first != 0 {
597+
let first = util::unsuffixed(first as u64);
598+
quote! { (self.n - #first) }
599+
} else {
600+
quote! { self.n }
601+
};
602+
if increment != 1 {
603+
let increment = util::unsuffixed(increment as u64);
604+
offset_calc = quote! { #offset_calc * #increment };
605+
}
606+
offset_calc = if offset !=0 {
607+
let offset = &util::unsuffixed(offset);
608+
quote! { let o = #offset_calc + #offset; }
609+
} else {
610+
quote! { let o = #offset_calc; }
611+
};
612+
quote! {
613+
///Writes raw bits to the field
614+
#[inline(always)]
615+
pub #unsafety fn #bits(self, value: #fty) -> &'a mut W {
616+
#offset_calc
617+
self.w.bits = (self.w.bits & !(#mask << o)) | (((value as #rty) & #mask) << o);
618+
self.w
619+
}
620+
}
621+
} else if offset != 0 {
537622
let offset = &util::unsuffixed(offset);
538623
quote! {
539624
///Writes raw bits to the field
@@ -554,11 +639,18 @@ pub fn fields(
554639
}
555640
});
556641

642+
let n_entry = if f.dim.is_some() {
643+
quote! {n: u32,}
644+
} else {
645+
quote! {}
646+
};
647+
557648
let doc = format!("Write proxy for field `{}`", f.name);
558649
mod_items.push(quote! {
559650
#[doc = #doc]
560651
pub struct #_pc_w<'a> {
561652
w: &'a mut W,
653+
#n_entry
562654
}
563655

564656
impl<'a> #_pc_w<'a> {
@@ -567,13 +659,39 @@ pub fn fields(
567659
});
568660

569661
let sc = &f.sc;
570-
w_impl_items.push(quote! {
571-
#[doc = #description_with_bits]
572-
#[inline(always)]
573-
pub fn #sc(&mut self) -> #_pc_w {
574-
#_pc_w { w: self }
662+
if let Some((first, dim, increment, suffixes)) = f.dim.clone() {
663+
let doc = &f.description;
664+
w_impl_items.push(quote! {
665+
#[doc = #doc]
666+
#[inline(always)]
667+
pub unsafe fn #sc(&mut self, n: u32) -> #_pc_w {
668+
#_pc_w { w: self, n }
669+
}
670+
});
671+
for (i, suffix) in (0..dim).zip(suffixes.iter()) {
672+
let n = first + i;
673+
let n = util::unsuffixed(n as u64);
674+
let offset = offset + (i as u64)*(increment as u64);
675+
let sc_n = Ident::new(&util::replace_suffix(&f.name.to_sanitized_snake_case(), &suffix), Span::call_site());
676+
let doc = util::replace_suffix(&description_with_bits(&f.description, offset, width), &suffix);
677+
w_impl_items.push(quote! {
678+
#[doc = #doc]
679+
#[inline(always)]
680+
pub fn #sc_n(&mut self) -> #_pc_w {
681+
#_pc_w { w: self, n: #n }
682+
}
683+
});
575684
}
576-
})
685+
} else {
686+
let doc = description_with_bits(&f.description, f.offset, width);
687+
w_impl_items.push(quote! {
688+
#[doc = #doc]
689+
#[inline(always)]
690+
pub fn #sc(&mut self) -> #_pc_w {
691+
#_pc_w { w: self }
692+
}
693+
});
694+
}
577695
}
578696
}
579697

@@ -719,12 +837,24 @@ fn derive_from_base(mod_items: &mut Vec<TokenStream>, base: &Base, pc: &Ident, b
719837
}
720838
}
721839

840+
fn description_with_bits(description: &str, offset: u64, width: u32) -> String {
841+
let mut res = if width == 1 {
842+
format!("Bit {}", offset)
843+
} else {
844+
format!("Bits {}:{}", offset, offset + width as u64 - 1)
845+
};
846+
if description.len() > 0 {
847+
res.push_str(" - ");
848+
res.push_str(&util::respace(&util::escape_brackets(description)));
849+
}
850+
res
851+
}
852+
722853
struct F<'a> {
723854
_pc_w: Ident,
724855
_sc: Ident,
725856
access: Option<Access>,
726857
description: String,
727-
description_with_bits: String,
728858
evs: &'a [EnumeratedValues],
729859
mask: u64,
730860
name: &'a str,
@@ -737,6 +867,7 @@ struct F<'a> {
737867
ty: Ident,
738868
width: u32,
739869
write_constraint: Option<&'a WriteConstraint>,
870+
dim: Option<(u32, u32, u32, Vec<String>)>,
740871
}
741872

742873
#[derive(Clone, Debug)]

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)