Skip to content

Commit 4d523d6

Browse files
authored
Try #400:
2 parents 39934be + bedc69f commit 4d523d6

File tree

3 files changed

+168
-46
lines changed

3 files changed

+168
-46
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, increment: u32) -> u32 {
226+
base + (n - first)*increment
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: 153 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+
(first, None)
249+
} else {
250+
(0, de.dim_index.clone())
251+
}
252+
} else {
253+
(0, None)
254+
};
255+
let suffixes: Vec<_> = match index {
256+
Some(ix) => ix,
257+
None => (0..de.dim).map(|i| (first + i).to_string()).collect(),
258+
};
259+
let last = util::unsuffixed((first + de.dim - 1) as u64);
260+
let first_unsuf = util::unsuffixed(first as u64);
261+
let check = if first == 0 {
262+
quote! { debug_assert!(n <= #last); }
263+
} else {
264+
quote! { debug_assert!(n >= #first_unsuf && n <= #last); }
265+
};
266+
Some((first, de.dim, de.dim_increment, check, 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,60 @@ 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, check, suffixes)) = f.dim.clone() {
349+
let first_unsuf = util::unsuffixed(first as u64);
350+
let offset_unsuf = &util::unsuffixed(offset);
351+
let increment_unsuf = &util::unsuffixed(increment as u64);
352+
let offset_calc = quote! {crate::field_offset(n, #offset_unsuf, #first_unsuf, #increment_unsuf)};
353+
let value = quote! { ((self.bits >> #offset_calc) & #mask) #cast };
354+
let doc = &f.description;
355+
r_impl_items.push(quote! {
356+
#[doc = #doc]
357+
#[inline(always)]
358+
pub fn #sc(&self, n: u32) -> #_pc_r {
359+
#check
360+
#_pc_r::new( #value )
361+
}
362+
});
363+
for (i, suffix) in (0..dim).zip(suffixes.iter()) {
364+
let offset = offset + (i as u64)*(increment as u64);
365+
let value = if offset != 0 {
366+
let offset = &util::unsuffixed(offset);
367+
quote! {
368+
((self.bits >> #offset) & #mask) #cast
369+
}
370+
} else {
371+
quote! {
372+
(self.bits & #mask) #cast
373+
}
374+
};
375+
let sc_n = Ident::new(&util::replace_suffix(&f.name.to_sanitized_snake_case(), &suffix), Span::call_site());
376+
let doc = util::replace_suffix(&description_with_bits(&f.description, offset, width), &suffix);
377+
r_impl_items.push(quote! {
378+
#[doc = #doc]
379+
#[inline(always)]
380+
pub fn #sc_n(&self) -> #_pc_r {
381+
#_pc_r::new( #value )
382+
}
383+
});
384+
}
385+
} else {
386+
let doc = description_with_bits(&f.description, f.offset, width);
332387
r_impl_items.push(quote! {
333-
#[doc = #description_with_bits]
388+
#[doc = #doc]
334389
#[inline(always)]
335390
pub fn #sc(&self) -> #_pc_r {
336391
#_pc_r::new( #value )
337392
}
338393
});
394+
}
395+
396+
if let Some((evs, base)) = lookup_filter(&lookup_results, Usage::Read) {
397+
evs_r = Some(evs.clone());
339398

340399
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());
400+
let base_pc_r = Ident::new(&format!("{}_A", util::replace_suffix(base.field, "").to_sanitized_upper_case()), Span::call_site());
343401
let base_pc_r = derive_from_base(mod_items, &base, &pc_r, &base_pc_r, description);
344402

345403
let doc = format!("Reader of field `{}`", f.name);
@@ -352,7 +410,7 @@ pub fn fields(
352410
});
353411

354412
if base.is_none() {
355-
let has_reserved_variant = evs.values.len() != (1 << f.width);
413+
let has_reserved_variant = evs.values.len() != (1 << width);
356414
let variants = Variant::from_enumerated_values(evs)?;
357415

358416
add_from_variants(mod_items, &variants, pc_r, &f, description, rv);
@@ -362,7 +420,7 @@ pub fn fields(
362420
let mut arms = variants
363421
.iter()
364422
.map(|v| {
365-
let i = util::unsuffixed_or_bool(v.value, f.width);
423+
let i = util::unsuffixed_or_bool(v.value, width);
366424
let pc = &v.pc;
367425

368426
if has_reserved_variant {
@@ -377,7 +435,7 @@ pub fn fields(
377435
arms.push(quote! {
378436
i => Res(i)
379437
});
380-
} else if 1 << f.width.to_ty_width()? != variants.len() {
438+
} else if 1 << width.to_ty_width()? != variants.len() {
381439
arms.push(quote! {
382440
_ => unreachable!()
383441
});
@@ -437,15 +495,6 @@ pub fn fields(
437495
}
438496

439497
} 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-
449498
let doc = format!("Reader of field `{}`", f.name);
450499
mod_items.push(quote! {
451500
#[doc = #doc]
@@ -458,22 +507,20 @@ pub fn fields(
458507
if can_write {
459508
let mut proxy_items = vec![];
460509

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

464512
if let Some((evs, base)) = lookup_filter(&lookup_results, Usage::Write) {
465513
let variants = Variant::from_enumerated_values(evs)?;
466514

467-
if variants.len() == 1 << f.width {
515+
if variants.len() == 1 << width {
468516
unsafety = None;
469517
}
470518

471519
if Some(evs) != evs_r.as_ref() {
472520
pc_w = &f.pc_w;
473521

474522
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());
523+
let base_pc_w = Ident::new(&format!("{}_AW", util::replace_suffix(base.field, "").to_sanitized_upper_case()), Span::call_site());
477524
derive_from_base(mod_items, &base, &pc_w, &base_pc_w, description)
478525
});
479526

@@ -533,7 +580,20 @@ pub fn fields(
533580
});
534581
}
535582

536-
proxy_items.push(if offset != 0 {
583+
proxy_items.push(if let Some((first, _, increment, _, _)) = f.dim {
584+
let offset = &util::unsuffixed(offset);
585+
let first = util::unsuffixed(first as u64);
586+
let increment_unsuf = util::unsuffixed(increment as u64);
587+
let offset_calc = quote! {crate::field_offset(self.n, #offset, #first, #increment_unsuf)};
588+
quote! {
589+
///Writes raw bits to the field
590+
#[inline(always)]
591+
pub #unsafety fn #bits(self, value: #fty) -> &'a mut W {
592+
self.w.bits = (self.w.bits & !(#mask << #offset_calc)) | (((value as #rty) & #mask) << #offset_calc);
593+
self.w
594+
}
595+
}
596+
} else if offset != 0 {
537597
let offset = &util::unsuffixed(offset);
538598
quote! {
539599
///Writes raw bits to the field
@@ -554,11 +614,18 @@ pub fn fields(
554614
}
555615
});
556616

617+
let n_entry = if f.dim.is_some() {
618+
quote! {n: u32,}
619+
} else {
620+
quote! {}
621+
};
622+
557623
let doc = format!("Write proxy for field `{}`", f.name);
558624
mod_items.push(quote! {
559625
#[doc = #doc]
560626
pub struct #_pc_w<'a> {
561627
w: &'a mut W,
628+
#n_entry
562629
}
563630

564631
impl<'a> #_pc_w<'a> {
@@ -567,13 +634,40 @@ pub fn fields(
567634
});
568635

569636
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 }
637+
if let Some((first, dim, increment, check, suffixes)) = f.dim.clone() {
638+
let doc = &f.description;
639+
w_impl_items.push(quote! {
640+
#[doc = #doc]
641+
#[inline(always)]
642+
pub fn #sc(&mut self, n: u32) -> #_pc_w {
643+
#check
644+
#_pc_w { w: self, n }
645+
}
646+
});
647+
for (i, suffix) in (0..dim).zip(suffixes.iter()) {
648+
let n = first + i;
649+
let n = util::unsuffixed(n as u64);
650+
let offset = offset + (i as u64)*(increment as u64);
651+
let sc_n = Ident::new(&util::replace_suffix(&f.name.to_sanitized_snake_case(), &suffix), Span::call_site());
652+
let doc = util::replace_suffix(&description_with_bits(&f.description, offset, width), &suffix);
653+
w_impl_items.push(quote! {
654+
#[doc = #doc]
655+
#[inline(always)]
656+
pub fn #sc_n(&mut self) -> #_pc_w {
657+
#_pc_w { w: self, n: #n }
658+
}
659+
});
575660
}
576-
})
661+
} else {
662+
let doc = description_with_bits(&f.description, f.offset, width);
663+
w_impl_items.push(quote! {
664+
#[doc = #doc]
665+
#[inline(always)]
666+
pub fn #sc(&mut self) -> #_pc_w {
667+
#_pc_w { w: self }
668+
}
669+
});
670+
}
577671
}
578672
}
579673

@@ -719,12 +813,24 @@ fn derive_from_base(mod_items: &mut Vec<TokenStream>, base: &Base, pc: &Ident, b
719813
}
720814
}
721815

816+
fn description_with_bits(description: &str, offset: u64, width: u32) -> String {
817+
let mut res = if width == 1 {
818+
format!("Bit {}", offset)
819+
} else {
820+
format!("Bits {}:{}", offset, offset + width as u64 - 1)
821+
};
822+
if description.len() > 0 {
823+
res.push_str(" - ");
824+
res.push_str(&util::respace(&util::escape_brackets(description)));
825+
}
826+
res
827+
}
828+
722829
struct F<'a> {
723830
_pc_w: Ident,
724831
_sc: Ident,
725832
access: Option<Access>,
726833
description: String,
727-
description_with_bits: String,
728834
evs: &'a [EnumeratedValues],
729835
mask: u64,
730836
name: &'a str,
@@ -737,6 +843,7 @@ struct F<'a> {
737843
ty: Ident,
738844
width: u32,
739845
write_constraint: Option<&'a WriteConstraint>,
846+
dim: Option<(u32, u32, u32, TokenStream, Vec<String>)>,
740847
}
741848

742849
#[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)