Skip to content

Commit 960b03c

Browse files
Merge #412
412: Simplify register generation code r=burrbull a=therealprof Co-authored-by: Daniel Egger <daniel@eggers-club.de>
2 parents d35250c + 004a68f commit 960b03c

File tree

1 file changed

+57
-113
lines changed

1 file changed

+57
-113
lines changed

src/generate/register.rs

Lines changed: 57 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -223,113 +223,81 @@ pub fn fields(
223223
r_impl_items: &mut Vec<TokenStream>,
224224
w_impl_items: &mut Vec<TokenStream>,
225225
) -> Result<()> {
226-
impl<'a> F<'a> {
227-
fn from(f: &'a Field) -> Result<Self> {
228-
// TODO(AJM) - do we need to do anything with this range type?
229-
let BitRange { offset, width, .. } = f.bit_range;
230-
let sc = f.name.to_sanitized_snake_case();
231-
let pc = f.name.to_sanitized_upper_case();
232-
let span = Span::call_site();
233-
let pc_r = Ident::new(&format!("{}_A", pc), span);
234-
let _pc_r = Ident::new(&format!("{}_R", pc), span);
235-
let pc_w = Ident::new(&format!("{}_AW", pc), span);
236-
let _pc_w = Ident::new(&format!("{}_W", pc), span);
237-
let _sc = Ident::new(&format!("_{}", sc), span);
238-
let bits = Ident::new(if width == 1 { "bit" } else { "bits" }, Span::call_site());
239-
let mut description_with_bits = if width == 1 {
240-
format!("Bit {}", offset)
241-
} else {
242-
format!("Bits {}:{}", offset, offset + width - 1)
243-
};
244-
if let Some(d) = &f.description {
245-
description_with_bits.push_str(" - ");
246-
description_with_bits.push_str(&util::respace(&util::escape_brackets(d)));
247-
}
248-
let description = if let Some(d) = &f.description {
249-
util::respace(&util::escape_brackets(d))
250-
} else {
251-
"".to_owned()
252-
};
253-
254-
Ok(F {
255-
_pc_w,
256-
_sc,
257-
description,
258-
description_with_bits,
259-
pc_r,
260-
_pc_r,
261-
pc_w,
262-
bits,
263-
width,
264-
access: f.access,
265-
evs: &f.enumerated_values,
266-
sc: Ident::new(&sc, Span::call_site()),
267-
mask: 1u64.wrapping_neg() >> (64 - width),
268-
name: &f.name,
269-
offset: u64::from(offset),
270-
ty: width.to_ty()?,
271-
write_constraint: f.write_constraint.as_ref(),
272-
})
226+
// TODO enumeratedValues
227+
for f in fields.into_iter() {
228+
// TODO(AJM) - do we need to do anything with this range type?
229+
let BitRange { offset, width, .. } = f.bit_range;
230+
let span = Span::call_site();
231+
let sc = Ident::new(&f.name.to_sanitized_snake_case(), span);
232+
let pc = f.name.to_sanitized_upper_case();
233+
let bits = Ident::new(if width == 1 { "bit" } else { "bits" }, span);
234+
let mut description_with_bits = if width == 1 {
235+
format!("Bit {}", offset)
236+
} else {
237+
format!("Bits {}:{}", offset, offset + width - 1)
238+
};
239+
let description = if let Some(d) = &f.description {
240+
util::respace(&util::escape_brackets(d))
241+
} else {
242+
"".to_owned()
243+
};
244+
if !description.is_empty() {
245+
description_with_bits.push_str(" - ");
246+
description_with_bits.push_str(&description);
273247
}
274-
}
275248

276-
let fs = fields.iter().map(F::from).collect::<Result<Vec<_>>>()?;
277-
278-
// TODO enumeratedValues
279-
for f in &fs {
280249
let can_read = [Access::ReadOnly, Access::ReadWriteOnce, Access::ReadWrite]
281250
.contains(&access)
282251
&& (f.access != Some(Access::WriteOnly))
283252
&& (f.access != Some(Access::WriteOnce));
284253
let can_write = (access != Access::ReadOnly) && (f.access != Some(Access::ReadOnly));
285254

286-
let bits = &f.bits;
287-
let mask = &util::hex(f.mask);
288-
let offset = f.offset;
289-
let rv = reset_value.map(|rv| (rv >> offset) & f.mask);
290-
let fty = &f.ty;
255+
let mask = 1u64.wrapping_neg() >> (64 - width);
256+
let hexmask = &util::hex(mask);
257+
let offset = u64::from(offset);
258+
let rv = reset_value.map(|rv| (rv >> offset) & mask);
259+
let fty = width.to_ty()?;
260+
let evs = &f.enumerated_values;
291261

292262
let lookup_results = lookup(
293-
&f.evs,
263+
evs,
294264
fields,
295265
parent,
296266
all_registers,
297267
peripheral,
298268
all_peripherals,
299269
)?;
300270

301-
let pc_r = &f.pc_r;
302-
let mut pc_w = &f.pc_r;
271+
// Reader and writer use one common `Enum_A` unless a fields have two `enumeratedValues`,
272+
// then we have one for read-only `Enum_A` and another for write-only `Enum_AW`
273+
let pc_r = Ident::new(&(pc.clone() + "_A"), span);
274+
let mut pc_w = &pc_r;
303275

304276
let mut base_pc_w = None;
305277
let mut evs_r = None;
306278

307-
let _pc_r = &f._pc_r;
308-
let _pc_w = &f._pc_w;
309-
let description = &f.description;
310-
let description_with_bits = &f.description_with_bits;
311-
312279
if can_read {
313-
let cast = if f.width == 1 {
280+
let _pc_r = Ident::new(&(pc.clone() + "_R"), span);
281+
282+
let cast = if width == 1 {
314283
quote! { != 0 }
315284
} else {
316285
quote! { as #fty }
317286
};
318287
let value = if offset != 0 {
319288
let offset = &util::unsuffixed(offset);
320289
quote! {
321-
((self.bits >> #offset) & #mask) #cast
290+
((self.bits >> #offset) & #hexmask) #cast
322291
}
323292
} else {
324293
quote! {
325-
(self.bits & #mask) #cast
294+
(self.bits & #hexmask) #cast
326295
}
327296
};
328297

329298
if let Some((evs, base)) = lookup_filter(&lookup_results, Usage::Read) {
330299
evs_r = Some(evs.clone());
331300

332-
let sc = &f.sc;
333301
r_impl_items.push(quote! {
334302
#[doc = #description_with_bits]
335303
#[inline(always)]
@@ -340,9 +308,9 @@ pub fn fields(
340308

341309
base_pc_w = base.as_ref().map(|base| {
342310
let pc = base.field.to_sanitized_upper_case();
343-
let base_pc_r = Ident::new(&format!("{}_A", pc), Span::call_site());
311+
let base_pc_r = Ident::new(&(pc.clone() + "_A"), span);
344312
let base_pc_r =
345-
derive_from_base(mod_items, &base, &pc_r, &base_pc_r, description);
313+
derive_from_base(mod_items, &base, &pc_r, &base_pc_r, &description);
346314

347315
let doc = format!("Reader of field `{}`", f.name);
348316
mod_items.push(quote! {
@@ -354,17 +322,17 @@ pub fn fields(
354322
});
355323

356324
if base.is_none() {
357-
let has_reserved_variant = evs.values.len() != (1 << f.width);
325+
let has_reserved_variant = evs.values.len() != (1 << width);
358326
let variants = Variant::from_enumerated_values(evs)?;
359327

360-
add_from_variants(mod_items, &variants, pc_r, &f, description, rv);
328+
add_from_variants(mod_items, &variants, &pc_r, &fty, &description, rv);
361329

362330
let mut enum_items = vec![];
363331

364332
let mut arms = variants
365333
.iter()
366334
.map(|v| {
367-
let i = util::unsuffixed_or_bool(v.value, f.width);
335+
let i = util::unsuffixed_or_bool(v.value, width);
368336
let pc = &v.pc;
369337

370338
if has_reserved_variant {
@@ -379,7 +347,7 @@ pub fn fields(
379347
arms.push(quote! {
380348
i => Res(i)
381349
});
382-
} else if 1 << f.width.to_ty_width()? != variants.len() {
350+
} else if 1 << width.to_ty_width()? != variants.len() {
383351
arms.push(quote! {
384352
_ => unreachable!()
385353
});
@@ -418,7 +386,7 @@ pub fn fields(
418386
} else {
419387
format!("is_{}", sc)
420388
},
421-
Span::call_site(),
389+
span,
422390
);
423391

424392
let doc = format!("Checks if the value of the field is `{}`", pc);
@@ -441,7 +409,6 @@ pub fn fields(
441409
});
442410
}
443411
} else {
444-
let sc = &f.sc;
445412
r_impl_items.push(quote! {
446413
#[doc = #description_with_bits]
447414
#[inline(always)]
@@ -459,29 +426,29 @@ pub fn fields(
459426
}
460427

461428
if can_write {
462-
let mut proxy_items = vec![];
429+
let new_pc_w = Ident::new(&(pc.clone() + "_AW"), span);
430+
let _pc_w = Ident::new(&(pc.clone() + "_W"), span);
463431

464-
let mut unsafety = unsafety(f.write_constraint, f.width);
465-
let width = f.width;
432+
let mut proxy_items = vec![];
433+
let mut unsafety = unsafety(f.write_constraint.as_ref(), width);
466434

467435
if let Some((evs, base)) = lookup_filter(&lookup_results, Usage::Write) {
468436
let variants = Variant::from_enumerated_values(evs)?;
469437

470-
if variants.len() == 1 << f.width {
438+
if variants.len() == 1 << width {
471439
unsafety = None;
472440
}
473441

474442
if Some(evs) != evs_r.as_ref() {
475-
pc_w = &f.pc_w;
476-
443+
pc_w = &new_pc_w;
477444
base_pc_w = base.as_ref().map(|base| {
478445
let pc = base.field.to_sanitized_upper_case();
479-
let base_pc_w = Ident::new(&format!("{}_AW", pc), Span::call_site());
480-
derive_from_base(mod_items, &base, &pc_w, &base_pc_w, description)
446+
let base_pc_w = Ident::new(&(pc + "_AW"), span);
447+
derive_from_base(mod_items, &base, &pc_w, &base_pc_w, &description)
481448
});
482449

483450
if base.is_none() {
484-
add_from_variants(mod_items, &variants, pc_w, &f, description, rv);
451+
add_from_variants(mod_items, &variants, &pc_w, &fty, &description, rv);
485452
}
486453
}
487454

@@ -542,7 +509,7 @@ pub fn fields(
542509
///Writes raw bits to the field
543510
#[inline(always)]
544511
pub #unsafety fn #bits(self, value: #fty) -> &'a mut W {
545-
self.w.bits = (self.w.bits & !(#mask << #offset)) | (((value as #rty) & #mask) << #offset);
512+
self.w.bits = (self.w.bits & !(#hexmask << #offset)) | (((value as #rty) & #hexmask) << #offset);
546513
self.w
547514
}
548515
}
@@ -551,7 +518,7 @@ pub fn fields(
551518
///Writes raw bits to the field
552519
#[inline(always)]
553520
pub #unsafety fn #bits(self, value: #fty) -> &'a mut W {
554-
self.w.bits = (self.w.bits & !#mask) | ((value as #rty) & #mask);
521+
self.w.bits = (self.w.bits & !#hexmask) | ((value as #rty) & #hexmask);
555522
self.w
556523
}
557524
}
@@ -569,7 +536,6 @@ pub fn fields(
569536
}
570537
});
571538

572-
let sc = &f.sc;
573539
w_impl_items.push(quote! {
574540
#[doc = #description_with_bits]
575541
#[inline(always)]
@@ -641,13 +607,11 @@ fn add_from_variants(
641607
mod_items: &mut Vec<TokenStream>,
642608
variants: &[Variant],
643609
pc: &Ident,
644-
f: &F,
610+
fty: &Ident,
645611
desc: &str,
646612
reset_value: Option<u64>,
647613
) {
648-
let fty = &f.ty;
649-
650-
let (repr, cast) = if f.ty == "bool" {
614+
let (repr, cast) = if fty == "bool" {
651615
(quote! {}, quote! { variant as u8 != 0 })
652616
} else {
653617
(quote! { #[repr(#fty)] }, quote! { variant as _ })
@@ -736,26 +700,6 @@ fn derive_from_base(
736700
}
737701
}
738702

739-
struct F<'a> {
740-
_pc_w: Ident,
741-
_sc: Ident,
742-
access: Option<Access>,
743-
description: String,
744-
description_with_bits: String,
745-
evs: &'a [EnumeratedValues],
746-
mask: u64,
747-
name: &'a str,
748-
offset: u64,
749-
pc_r: Ident,
750-
_pc_r: Ident,
751-
pc_w: Ident,
752-
sc: Ident,
753-
bits: Ident,
754-
ty: Ident,
755-
width: u32,
756-
write_constraint: Option<&'a WriteConstraint>,
757-
}
758-
759703
#[derive(Clone, Debug)]
760704
pub struct Base<'a> {
761705
pub peripheral: Option<&'a str>,

0 commit comments

Comments
 (0)