Skip to content

implement both owning and const generic field array writers #503

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,22 @@ jobs:
# Temporary hack as long as we use the current CI script
TRAVIS_OS_NAME: [linux]

FEATURES: [""]

include:
# Test MSRV
- rust: 1.40.0
VENDOR: Nordic
TARGET: x86_64-unknown-linux-gnu
TRAVIS_OS_NAME: linux

# Test features
- rust: 1.51.0
VENDOR: RISC-V
TARGET: x86_64-unknown-linux-gnu
TRAVIS_OS_NAME: linux
FEATURES: "strict,const-generic"

# Use nightly for architectures which don't support stable
- rust: nightly
experimental: true
Expand Down Expand Up @@ -64,4 +73,4 @@ jobs:
override: true
components: rustfmt
- name: Run CI script for ${{ matrix.VENDOR }} under ${{ matrix.rust }}
run: TARGET=${{ matrix.TARGET }} VENDOR=${{ matrix.VENDOR }} TRAVIS_OS_NAME=${{ matrix.TRAVIS_OS_NAME }} bash ci/script.sh
run: TARGET=${{ matrix.TARGET }} VENDOR=${{ matrix.VENDOR }} TRAVIS_OS_NAME=${{ matrix.TRAVIS_OS_NAME }} FEATURES=${{ matrix.FEATURES }} bash ci/script.sh
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

### Changed

- with feature "const-generic" generate const generic variant of
"field array" structure in addition to structure
that contain offset (requires rust 1.51)

- move interrupt generation after generic file

- [breaking-change] make `write_with_zero` method `unsafe` because the way it is
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,4 @@ features = ["full","extra-traits"]

[features]
strict = ["svd-parser/strict"]
const-generic = []
6 changes: 5 additions & 1 deletion ci/script.sh
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,11 @@ main() {
return
fi

cargo build --target $TARGET --release
if [ -z ${FEATURES-} ]; then
cargo build --target $TARGET --release
else
cargo build --target $TARGET --release --features $FEATURES
fi

case $TRAVIS_OS_NAME in
linux)
Expand Down
128 changes: 93 additions & 35 deletions src/generate/register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,8 @@ pub fn fields(
if can_write {
let new_pc_aw = Ident::new(&(name_pc.clone() + "_AW"), span);
let name_pc_w = Ident::new(&(name_pc.clone() + "_W"), span);
#[cfg(feature = "const-generic")]
let name_pc_cgw = Ident::new(&(name_pc.clone() + "_CGW"), span);

let mut proxy_items = TokenStream::new();
let mut unsafety = unsafety(f.write_constraint.as_ref(), width);
Expand Down Expand Up @@ -639,61 +641,108 @@ pub fn fields(
});
}

proxy_items.extend(if field_dim.is_some() {
quote! {
let mut proxy_items_fa = TokenStream::new();
#[cfg(feature = "const-generic")]
let mut proxy_items_cg = TokenStream::new();
if field_dim.is_some() {
proxy_items_fa.extend(quote! {
///Writes raw bits to the field
#inline
pub #unsafety fn #bits(self, value: #fty) -> &'a mut W {
self.w.bits = (self.w.bits & !(#hexmask << self.offset)) | ((value as #rty & #hexmask) << self.offset);
self.w
}
}
} else if offset != 0 {
let offset = &util::unsuffixed(offset);
quote! {
});
#[cfg(feature="const-generic")]
proxy_items_cg.extend(quote! {
///Writes raw bits to the field
#inline
pub #unsafety fn #bits(self, value: #fty) -> &'a mut W {
self.w.bits = (self.w.bits & !(#hexmask << #offset)) | ((value as #rty & #hexmask) << #offset);
self.w.bits = (self.w.bits & !(#hexmask << O)) | ((value as #rty & #hexmask) << O);
self.w
}
}
});
} else {
quote! {
///Writes raw bits to the field
#inline
pub #unsafety fn #bits(self, value: #fty) -> &'a mut W {
self.w.bits = (self.w.bits & !#hexmask) | (value as #rty & #hexmask);
self.w
proxy_items.extend(if offset != 0 {
let offset = &util::unsuffixed(offset);
quote! {
///Writes raw bits to the field
#inline
pub #unsafety fn #bits(self, value: #fty) -> &'a mut W {
self.w.bits = (self.w.bits & !(#hexmask << #offset)) | ((value as #rty & #hexmask) << #offset);
self.w
}
}
}
});
} else {
quote! {
///Writes raw bits to the field
#inline
pub #unsafety fn #bits(self, value: #fty) -> &'a mut W {
self.w.bits = (self.w.bits & !#hexmask) | (value as #rty & #hexmask);
self.w
}
}
});
}

let doc;
let offset_entry;
if let Some((_, _, _, _, suffixes_str)) = &field_dim {
doc = format!(
#[cfg(feature = "const-generic")]
let mut cgdoc = String::new();
let doc = if let Some((_, _, _, _, suffixes_str)) = &field_dim {
#[cfg(feature = "const-generic")]
{
cgdoc = format!(
"Fields `{}` const generic writer - {}",
util::replace_suffix(&f.name, suffixes_str),
description
);
}
format!(
"Fields `{}` writer - {}",
util::replace_suffix(&f.name, suffixes_str),
description
);
offset_entry = quote! {offset: usize,};
)
} else {
doc = format!("Field `{}` writer - {}", f.name, description);
offset_entry = quote! {};
}
format!("Field `{}` writer - {}", f.name, description)
};

mod_items.extend(quote! {
#[doc = #doc]
pub struct #name_pc_w<'a> {
w: &'a mut W,
#offset_entry
}
if field_dim.is_some() {
mod_items.extend(quote! {
#[doc = #doc]
pub struct #name_pc_w<'a> {
w: &'a mut W,
offset: usize,
}

impl<'a> #name_pc_w<'a> {
#proxy_items
}
});
impl<'a> #name_pc_w<'a> {
#proxy_items
#proxy_items_fa
}
});

#[cfg(feature = "const-generic")]
mod_items.extend(quote! {
#[doc = #cgdoc]
pub struct #name_pc_cgw<'a, const O: usize> {
w: &'a mut W,
}

impl<'a, const O: usize> #name_pc_cgw<'a, O> {
#proxy_items
#proxy_items_cg
}
});
} else {
mod_items.extend(quote! {
#[doc = #doc]
pub struct #name_pc_w<'a> {
w: &'a mut W,
}

impl<'a> #name_pc_w<'a> {
#proxy_items
}
});
}

if let Some((first, dim, increment, suffixes, suffixes_str)) = &field_dim {
let offset_calc = calculate_offset(*first, *increment, offset);
Expand All @@ -716,13 +765,22 @@ pub fn fields(
&suffix,
);
let sub_offset = util::unsuffixed(sub_offset as u64);
#[cfg(not(feature = "const-generic"))]
w_impl_items.extend(quote! {
#[doc = #doc]
#inline
pub fn #name_sc_n(&mut self) -> #name_pc_w {
#name_pc_w { w: self, offset: #sub_offset }
}
});
#[cfg(feature = "const-generic")]
w_impl_items.extend(quote! {
#[doc = #doc]
#inline
pub fn #name_sc_n(&mut self) -> #name_pc_cgw<#sub_offset> {
#name_pc_cgw { w: self }
}
});
}
} else {
let doc = description_with_bits(&description, offset, width);
Expand Down