Skip to content

Commit 48a446a

Browse files
authored
Try #400:
2 parents 39934be + 8a3533b commit 48a446a

File tree

3 files changed

+181
-43
lines changed

3 files changed

+181
-43
lines changed

src/generate/generic.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,13 @@ impl<U, REG> W<U, REG> {
219219
}
220220
}
221221

222+
///Calculate exact field offset in field array
223+
#[allow(dead_code)]
224+
#[inline(always)]
225+
pub const fn field_offset(n: u32, base: u32, first: u32, width: u32) -> u32 {
226+
base + (n - first)*width
227+
}
228+
222229
///Used if enumerated values cover not the whole range
223230
#[derive(Clone,Copy,PartialEq)]
224231
pub enum Variant<U, T> {

src/generate/register.rs

Lines changed: 151 additions & 42 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::name_of_field(&f);
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,46 @@ 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+
if de.dim_increment != 1 {
247+
return Err(format!("Unsupported field array {}, increment = {}", f.name, de.dim_increment))?;
248+
}
249+
let (first, index) = if let Some(dim_index) = &de.dim_index {
250+
if let Ok(first) = dim_index[0].parse::<u32>() {
251+
(first, None)
252+
} else {
253+
(0, de.dim_index.clone())
254+
}
255+
} else {
256+
(0, None)
257+
};
258+
let names_with_index: Vec<_> = match index {
259+
Some(ix) => ix.iter().map(|i| util::replace_suffix(&f.name.to_sanitized_snake_case(), &i)).collect(),
260+
None => (0..de.dim).map(|i| util::replace_suffix(&f.name.to_sanitized_snake_case(), &(first + i).to_string())).collect(),
261+
};
262+
let last = util::unsuffixed((first + de.dim + 1) as u64);
263+
let first_unsuf = util::unsuffixed(first as u64);
264+
let check = if first == 0 {
265+
quote! { debug_assert!(n <= #last); }
266+
} else {
267+
quote! { debug_assert!(n >= #first_unsuf && n <= #last); }
268+
};
269+
Some((first, de.dim, check, names_with_index))
270+
},
271+
Field::Single(_) => None
272+
};
273+
252274
Ok(F {
253275
_pc_w,
254276
_sc,
255277
description,
256-
description_with_bits,
257278
pc_r,
258279
_pc_r,
259280
pc_w,
@@ -267,6 +288,7 @@ pub fn fields(
267288
offset: u64::from(offset),
268289
ty: width.to_ty()?,
269290
write_constraint: f.write_constraint.as_ref(),
291+
dim,
270292
})
271293
}
272294
}
@@ -306,10 +328,10 @@ pub fn fields(
306328
let _pc_r = &f._pc_r;
307329
let _pc_w = &f._pc_w;
308330
let description = &f.description;
309-
let description_with_bits = &f.description_with_bits;
331+
let width = f.width;
310332

311333
if can_read {
312-
let cast = if f.width == 1 {
334+
let cast = if width == 1 {
313335
quote! { != 0 }
314336
} else {
315337
quote! { as #fty }
@@ -325,17 +347,56 @@ pub fn fields(
325347
}
326348
};
327349

328-
if let Some((evs, base)) = lookup_filter(&lookup_results, Usage::Read) {
329-
evs_r = Some(evs.clone());
330-
331-
let sc = &f.sc;
350+
let sc = &f.sc;
351+
if let Some((first, dim, check, names)) = f.dim.clone() {
352+
let first_unsuf = util::unsuffixed(first as u64);
353+
let offset_unsuf = &util::unsuffixed(offset);
354+
let width_unsuf = &util::unsuffixed(width as u64);
355+
let offset_calc = quote! {crate::field_offset(n, #offset_unsuf, #first_unsuf, #width_unsuf)};
356+
let value = quote! { ((self.bits >> #offset_calc) & #mask) #cast };
357+
let doc = &f.description;
332358
r_impl_items.push(quote! {
333-
#[doc = #description_with_bits]
359+
#[doc = #doc]
360+
#[inline(always)]
361+
pub fn #sc(&self, n: u32) -> #_pc_r {
362+
#check
363+
#_pc_r::new( #value )
364+
}
365+
});
366+
for (i, sc_n) in (0..dim).zip(names.iter()) {
367+
let offset = offset + (i as u64)*(width as u64);
368+
let value = if offset != 0 {
369+
let offset = &util::unsuffixed(offset);
370+
quote! {
371+
((self.bits >> #offset) & #mask) #cast
372+
}
373+
} else {
374+
quote! {
375+
(self.bits & #mask) #cast
376+
}
377+
};
378+
let doc = description_with_bits(&f.description, offset, width);
379+
r_impl_items.push(quote! {
380+
#[doc = #doc]
381+
#[inline(always)]
382+
pub fn #sc_n(&self) -> #_pc_r {
383+
#_pc_r::new( #value )
384+
}
385+
});
386+
}
387+
} else {
388+
let doc = description_with_bits(&f.description, f.offset, width);
389+
r_impl_items.push(quote! {
390+
#[doc = #doc]
334391
#[inline(always)]
335392
pub fn #sc(&self) -> #_pc_r {
336393
#_pc_r::new( #value )
337394
}
338395
});
396+
}
397+
398+
if let Some((evs, base)) = lookup_filter(&lookup_results, Usage::Read) {
399+
evs_r = Some(evs.clone());
339400

340401
base_pc_w = base.as_ref().map(|base| {
341402
let pc = base.field.to_sanitized_upper_case();
@@ -352,7 +413,7 @@ pub fn fields(
352413
});
353414

354415
if base.is_none() {
355-
let has_reserved_variant = evs.values.len() != (1 << f.width);
416+
let has_reserved_variant = evs.values.len() != (1 << width);
356417
let variants = Variant::from_enumerated_values(evs)?;
357418

358419
add_from_variants(mod_items, &variants, pc_r, &f, description, rv);
@@ -362,7 +423,7 @@ pub fn fields(
362423
let mut arms = variants
363424
.iter()
364425
.map(|v| {
365-
let i = util::unsuffixed_or_bool(v.value, f.width);
426+
let i = util::unsuffixed_or_bool(v.value, width);
366427
let pc = &v.pc;
367428

368429
if has_reserved_variant {
@@ -377,7 +438,7 @@ pub fn fields(
377438
arms.push(quote! {
378439
i => Res(i)
379440
});
380-
} else if 1 << f.width.to_ty_width()? != variants.len() {
441+
} else if 1 << width.to_ty_width()? != variants.len() {
381442
arms.push(quote! {
382443
_ => unreachable!()
383444
});
@@ -437,15 +498,6 @@ pub fn fields(
437498
}
438499

439500
} 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-
449501
let doc = format!("Reader of field `{}`", f.name);
450502
mod_items.push(quote! {
451503
#[doc = #doc]
@@ -458,13 +510,12 @@ pub fn fields(
458510
if can_write {
459511
let mut proxy_items = vec![];
460512

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

464515
if let Some((evs, base)) = lookup_filter(&lookup_results, Usage::Write) {
465516
let variants = Variant::from_enumerated_values(evs)?;
466517

467-
if variants.len() == 1 << f.width {
518+
if variants.len() == 1 << width {
468519
unsafety = None;
469520
}
470521

@@ -533,7 +584,19 @@ pub fn fields(
533584
});
534585
}
535586

536-
proxy_items.push(if offset != 0 {
587+
proxy_items.push(if let Some((first, _, _, _)) = f.dim {
588+
let offset = &util::unsuffixed(offset);
589+
let first = util::unsuffixed(first as u64);
590+
let offset_calc = quote! {crate::field_offset(self.n, #offset, #first, #width)};
591+
quote! {
592+
///Writes raw bits to the field
593+
#[inline(always)]
594+
pub #unsafety fn #bits(self, value: #fty) -> &'a mut W {
595+
self.w.bits = (self.w.bits & !(#mask << #offset_calc)) | (((value as #rty) & #mask) << #offset_calc);
596+
self.w
597+
}
598+
}
599+
} else if offset != 0 {
537600
let offset = &util::unsuffixed(offset);
538601
quote! {
539602
///Writes raw bits to the field
@@ -554,11 +617,18 @@ pub fn fields(
554617
}
555618
});
556619

620+
let n_entry = if f.dim.is_some() {
621+
quote! {n: u32,}
622+
} else {
623+
quote! {}
624+
};
625+
557626
let doc = format!("Write proxy for field `{}`", f.name);
558627
mod_items.push(quote! {
559628
#[doc = #doc]
560629
pub struct #_pc_w<'a> {
561630
w: &'a mut W,
631+
#n_entry
562632
}
563633

564634
impl<'a> #_pc_w<'a> {
@@ -567,13 +637,39 @@ pub fn fields(
567637
});
568638

569639
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 }
640+
if let Some((first, dim, check, names)) = f.dim.clone() {
641+
let doc = &f.description;
642+
w_impl_items.push(quote! {
643+
#[doc = #doc]
644+
#[inline(always)]
645+
pub fn #sc(&mut self, n: u32) -> #_pc_w {
646+
#check
647+
#_pc_w { w: self, n }
648+
}
649+
});
650+
for (i, sc_n) in (0..dim).zip(names.iter()) {
651+
let n = first + i;
652+
let n = util::unsuffixed(n as u64);
653+
let offset = offset + (i as u64)*(width as u64);
654+
let doc = description_with_bits(&f.description, offset, width);
655+
w_impl_items.push(quote! {
656+
#[doc = #doc]
657+
#[inline(always)]
658+
pub fn #sc_n(&mut self) -> #_pc_w {
659+
#_pc_w { w: self, n: #n }
660+
}
661+
});
575662
}
576-
})
663+
} else {
664+
let doc = description_with_bits(&f.description, f.offset, width);
665+
w_impl_items.push(quote! {
666+
#[doc = #doc]
667+
#[inline(always)]
668+
pub fn #sc(&mut self) -> #_pc_w {
669+
#_pc_w { w: self }
670+
}
671+
});
672+
}
577673
}
578674
}
579675

@@ -719,12 +815,24 @@ fn derive_from_base(mod_items: &mut Vec<TokenStream>, base: &Base, pc: &Ident, b
719815
}
720816
}
721817

818+
fn description_with_bits(description: &str, offset: u64, width: u32) -> String {
819+
let mut res = if width == 1 {
820+
format!("Bit {}", offset)
821+
} else {
822+
format!("Bits {}:{}", offset, offset + width as u64 - 1)
823+
};
824+
if description.len() > 0 {
825+
res.push_str(" - ");
826+
res.push_str(&util::respace(&util::escape_brackets(description)));
827+
}
828+
res
829+
}
830+
722831
struct F<'a> {
723832
_pc_w: Ident,
724833
_sc: Ident,
725834
access: Option<Access>,
726835
description: String,
727-
description_with_bits: String,
728836
evs: &'a [EnumeratedValues],
729837
mask: u64,
730838
name: &'a str,
@@ -737,6 +845,7 @@ struct F<'a> {
737845
ty: Ident,
738846
width: u32,
739847
write_constraint: Option<&'a WriteConstraint>,
848+
dim: Option<(u32, u32, TokenStream, Vec<Ident>)>,
740849
}
741850

742851
#[derive(Clone, Debug)]

src/util.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::borrow::Cow;
22

33
use inflections::Inflect;
4-
use crate::svd::{Access, Cluster, Register, RegisterCluster};
4+
use crate::svd::{Access, Cluster, Field, Register, RegisterCluster};
55
use proc_macro2::{TokenStream, Ident, Span, Literal};
66
use crate::quote::{TokenStreamExt, ToTokens};
77

@@ -195,6 +195,28 @@ pub fn name_of(register: &Register) -> Cow<str> {
195195
}
196196
}
197197

198+
pub fn name_of_field(register: &Field) -> Cow<str> {
199+
match register {
200+
Field::Single(info) => Cow::from(&info.name),
201+
Field::Array(info, _) => {
202+
if info.name.contains("[%s]") {
203+
info.name.replace("[%s]", "").into()
204+
} else {
205+
info.name.replace("%s", "").into()
206+
}
207+
}
208+
}
209+
}
210+
211+
pub fn replace_suffix(name: &str, suffix: &str) -> Ident {
212+
let span = Span::call_site();
213+
Ident::new(&(if name.contains("[%s]") {
214+
name.replace("[%s]", suffix)
215+
} else {
216+
name.replace("%s", suffix)
217+
}), span)
218+
}
219+
198220
pub fn access_of(register: &Register) -> Access {
199221
register.access.unwrap_or_else(|| {
200222
if let Some(fields) = &register.fields {

0 commit comments

Comments
 (0)