Skip to content

Commit f8e7692

Browse files
committed
field reader
1 parent c79b4cd commit f8e7692

File tree

6 files changed

+130
-133
lines changed

6 files changed

+130
-133
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1717
- Joined field write proxy into a single line to help dev builds
1818
- Elimated useless 0 shifts to reduce generated code size and fix a clippy lint
1919

20+
- Replace field readers with generic `FR` type
21+
2022
### Fixed
2123

2224
- Correct handling of cluster size tag

src/generate/device.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::errors::*;
66
use crate::util::{self, ToSanitizedUpperCase};
77
use crate::Target;
88

9-
use crate::generate::{interrupt, peripheral};
9+
use crate::generate::{interrupt, peripheral, generic};
1010

1111
/// Whole device generation
1212
pub fn render(
@@ -136,6 +136,8 @@ pub fn render(
136136
}
137137
}
138138

139+
out.extend(generic::render()?);
140+
139141
for p in &d.peripherals {
140142
if target == Target::CortexM && core_peripherals.contains(&&*p.name.to_uppercase()) {
141143
// Core peripherals are handled above

src/generate/generic.rs

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
use quote::Tokens;
2+
3+
use crate::errors::*;
4+
5+
/// Generates generic bit munging code
6+
pub fn render() -> Result<Vec<Tokens>> {
7+
let mut code = vec![];
8+
let mut generic_items = vec![];
9+
10+
generic_items.push(quote! {
11+
use core::marker;
12+
13+
///Converting enumerated values to bits
14+
pub trait ToBits<N> {
15+
///Conversion method
16+
fn _bits(&self) -> N;
17+
}
18+
});
19+
20+
generic_items.push(quote! {
21+
///Value read from the register
22+
pub struct FR<U, T> {
23+
bits: U,
24+
_reg: marker::PhantomData<T>,
25+
}
26+
27+
impl<U, T, FI> PartialEq<FI> for FR<U, T>
28+
where
29+
U: PartialEq,
30+
FI: ToBits<U>
31+
{
32+
fn eq(&self, other: &FI) -> bool {
33+
self.bits.eq(&other._bits())
34+
}
35+
}
36+
37+
impl<U, T> FR<U, T>
38+
where
39+
U: Copy
40+
{
41+
///Create new instance of reader
42+
#[inline(always)]
43+
pub(crate) fn new(bits: U) -> Self {
44+
Self {
45+
bits,
46+
_reg: marker::PhantomData,
47+
}
48+
}
49+
///Read raw bits from field
50+
#[inline(always)]
51+
pub fn bits(&self) -> U {
52+
self.bits
53+
}
54+
}
55+
});
56+
57+
generic_items.push(quote! {
58+
impl<FI> FR<bool, FI> {
59+
///Value of the field as raw bits
60+
#[inline(always)]
61+
pub fn bit(&self) -> bool {
62+
self.bits
63+
}
64+
///Returns `true` if the bit is clear (0)
65+
#[inline(always)]
66+
pub fn bit_is_clear(&self) -> bool {
67+
!self.bit()
68+
}
69+
///Returns `true` if the bit is set (1)
70+
#[inline(always)]
71+
pub fn bit_is_set(&self) -> bool {
72+
self.bit()
73+
}
74+
}
75+
});
76+
77+
code.push(quote! {
78+
#[allow(unused_imports)]
79+
use generic::*;
80+
/// Common register and bit access and modify traits
81+
pub mod generic {
82+
#(#generic_items)*
83+
}
84+
});
85+
86+
Ok(code)
87+
}

src/generate/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pub mod device;
2+
pub mod generic;
23
pub mod interrupt;
34
pub mod peripheral;
45
pub mod register;

src/generate/register.rs

+37-122
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ pub fn fields(
255255
name: &'a str,
256256
offset: Tokens,
257257
pc_r: Ident,
258+
_pc_r: Ident,
258259
pc_w: Ident,
259260
sc: Ident,
260261
bits: Ident,
@@ -274,6 +275,7 @@ pub fn fields(
274275
let sc = f.name.to_sanitized_snake_case();
275276
let pc = f.name.to_sanitized_upper_case();
276277
let pc_r = Ident::from(&*format!("{}R", pc));
278+
let _pc_r = Ident::from(&*format!("{}_R", pc));
277279
let pc_w = Ident::from(&*format!("{}W", pc));
278280
let _pc_w = Ident::from(&*format!("_{}W", pc));
279281
let _sc = Ident::from(&*format!("_{}", sc));
@@ -296,6 +298,7 @@ pub fn fields(
296298
_sc,
297299
description,
298300
pc_r,
301+
_pc_r,
299302
pc_w,
300303
bits,
301304
width,
@@ -344,22 +347,23 @@ pub fn fields(
344347
let value = if offset != 0 {
345348
let offset = &f.offset;
346349
quote! {
347-
((self.bits >> #offset) & #mask) #cast
350+
((self.bits() >> #offset) & #mask) #cast
348351
}
349352
} else {
350353
quote! {
351-
(self.bits & #mask) #cast
354+
(self.bits() & #mask) #cast
352355
}
353356
};
354357

358+
let pc_r = &f.pc_r;
359+
let _pc_r = &f._pc_r;
360+
355361
if let Some((evs, base)) = lookup_filter(&lookup_results, Usage::Read) {
356-
let has_reserved_variant = evs.values.len() != (1 << f.width);
357362
let variants = Variant::from_enumerated_values(evs)?;
358363

359-
let pc_r = &f.pc_r;
360364
if let Some(base) = &base {
361365
let pc = base.field.to_sanitized_upper_case();
362-
let base_pc_r = Ident::from(&*format!("{}R", pc));
366+
let base_pc_r = Ident::from(&*format!("{}_R", pc));
363367
let desc = format!("Possible values of the field `{}`", f.name,);
364368

365369
if let (Some(peripheral), Some(register)) = (&base.peripheral, &base.register) {
@@ -370,20 +374,20 @@ pub fn fields(
370374

371375
mod_items.push(quote! {
372376
#[doc = #desc]
373-
pub type #pc_r = crate::#pmod_::#rmod_::#base_pc_r;
377+
pub type #_pc_r = crate::#pmod_::#rmod_::#base_pc_r;
374378
});
375379
} else if let Some(register) = &base.register {
376380
let mod_ = register.to_sanitized_snake_case();
377381
let mod_ = Ident::from(&*mod_);
378382

379383
mod_items.push(quote! {
380384
#[doc = #desc]
381-
pub type #pc_r = super::#mod_::#base_pc_r;
385+
pub type #_pc_r = super::#mod_::#base_pc_r;
382386
});
383387
} else {
384388
mod_items.push(quote! {
385389
#[doc = #desc]
386-
pub type #pc_r = #base_pc_r;
390+
pub type #_pc_r = #base_pc_r;
387391
});
388392
}
389393
}
@@ -393,15 +397,15 @@ pub fn fields(
393397
r_impl_items.push(quote! {
394398
#[doc = #description]
395399
#[inline(always)]
396-
pub fn #sc(&self) -> #pc_r {
397-
#pc_r::_from( #value )
400+
pub fn #sc(&self) -> #_pc_r {
401+
#_pc_r::new( #value )
398402
}
399403
});
400404

401405
if base.is_none() {
402406
let desc = format!("Possible values of the field `{}`", f.name,);
403407

404-
let mut vars = variants
408+
let vars = variants
405409
.iter()
406410
.map(|v| {
407411
let desc = util::escape_brackets(&v.doc);
@@ -412,12 +416,7 @@ pub fn fields(
412416
}
413417
})
414418
.collect::<Vec<_>>();
415-
if has_reserved_variant {
416-
vars.push(quote! {
417-
///Reserved
418-
_Reserved(#fty)
419-
});
420-
}
419+
421420
mod_items.push(quote! {
422421
#[doc = #desc]
423422
#[derive(Clone, Copy, Debug, PartialEq)]
@@ -428,78 +427,22 @@ pub fn fields(
428427

429428
let mut enum_items = vec![];
430429

431-
let mut arms = variants
432-
.iter()
433-
.map(|v| {
434-
let value = util::hex_or_bool(v.value as u64, f.width);
435-
let pc = &v.pc;
436-
437-
quote! {
438-
#pc_r::#pc => #value
439-
}
440-
})
441-
.collect::<Vec<_>>();
442-
if has_reserved_variant {
443-
arms.push(quote! {
444-
#pc_r::_Reserved(bits) => bits
445-
});
446-
}
447-
448-
if f.width == 1 {
449-
enum_items.push(quote! {
450-
///Returns `true` if the bit is clear (0)
451-
#[inline(always)]
452-
pub fn bit_is_clear(&self) -> bool {
453-
!self.#bits()
454-
}
455-
456-
///Returns `true` if the bit is set (1)
457-
#[inline(always)]
458-
pub fn bit_is_set(&self) -> bool {
459-
self.#bits()
460-
}
461-
});
462-
}
430+
let arms = variants.iter().map(|v| {
431+
let pc = &v.pc;
432+
let value = util::unsuffixed_or_bool(v.value, f.width);
463433

464-
enum_items.push(quote! {
465-
///Value of the field as raw bits
466-
#[inline(always)]
467-
pub fn #bits(&self) -> #fty {
468-
match *self {
469-
#(#arms),*
470-
}
434+
quote! {
435+
#pc_r::#pc => #value
471436
}
472437
});
473438

474-
let mut arms = variants
475-
.iter()
476-
.map(|v| {
477-
let i = util::unsuffixed_or_bool(v.value, f.width);
478-
let pc = &v.pc;
479-
480-
quote! {
481-
#i => #pc_r::#pc
482-
}
483-
})
484-
.collect::<Vec<_>>();
485-
486-
if has_reserved_variant {
487-
arms.push(quote! {
488-
i => #pc_r::_Reserved(i)
489-
});
490-
} else if 1 << f.width.to_ty_width()? != variants.len() {
491-
arms.push(quote! {
492-
_ => unreachable!()
493-
});
494-
}
495-
496-
enum_items.push(quote! {
497-
#[allow(missing_docs)]
498-
#[doc(hidden)]
499-
#[inline(always)]
500-
pub fn _from(value: #fty) -> #pc_r {
501-
match value {
502-
#(#arms),*,
439+
mod_items.push(quote! {
440+
impl crate::ToBits<#fty> for #pc_r {
441+
#[inline(always)]
442+
fn _bits(&self) -> #fty {
443+
match *self {
444+
#(#arms),*
445+
}
503446
}
504447
}
505448
});
@@ -525,58 +468,30 @@ pub fn fields(
525468
}
526469

527470
mod_items.push(quote! {
528-
impl #pc_r {
471+
///Reader of the field
472+
pub type #_pc_r = crate::FR<#fty, #pc_r>;
473+
impl #_pc_r {
529474
#(#enum_items)*
530475
}
531476
});
532477
}
478+
533479
} else {
534480
let description = &util::escape_brackets(&f.description);
535-
let pc_r = &f.pc_r;
536481
let sc = &f.sc;
537482
r_impl_items.push(quote! {
538483
#[doc = #description]
539484
#[inline(always)]
540-
pub fn #sc(&self) -> #pc_r {
541-
let bits = #value;
542-
#pc_r { bits }
485+
pub fn #sc(&self) -> #_pc_r {
486+
#_pc_r::new ( #value )
543487
}
544488
});
545489

546-
let mut pc_r_impl_items = vec![quote! {
547-
///Value of the field as raw bits
548-
#[inline(always)]
549-
pub fn #bits(&self) -> #fty {
550-
self.bits
551-
}
552-
}];
553-
554-
if f.width == 1 {
555-
pc_r_impl_items.push(quote! {
556-
///Returns `true` if the bit is clear (0)
557-
#[inline(always)]
558-
pub fn bit_is_clear(&self) -> bool {
559-
!self.#bits()
560-
}
561-
562-
///Returns `true` if the bit is set (1)
563-
#[inline(always)]
564-
pub fn bit_is_set(&self) -> bool {
565-
self.#bits()
566-
}
567-
});
568-
}
569-
570490
mod_items.push(quote! {
571-
///Value of the field
572-
pub struct #pc_r {
573-
bits: #fty,
574-
}
491+
///Reader of the field
492+
pub type #_pc_r = crate::FR<#fty, #fty>;
493+
})
575494

576-
impl #pc_r {
577-
#(#pc_r_impl_items)*
578-
}
579-
});
580495
}
581496
}
582497

0 commit comments

Comments
 (0)