From fd3bcdef7466eef880c0515eba890746e7b46d46 Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Wed, 14 Apr 2021 10:07:46 +0300 Subject: [PATCH 1/2] const generic field array writer under "const-generic" feature --- CHANGELOG.md | 4 ++ Cargo.toml | 1 + src/generate/register.rs | 128 ++++++++++++++++++++++++++++----------- 3 files changed, 98 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5848c670..9e37f876 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/Cargo.toml b/Cargo.toml index c1b91bb5..bf482ce6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,3 +52,4 @@ features = ["full","extra-traits"] [features] strict = ["svd-parser/strict"] +const-generic = [] diff --git a/src/generate/register.rs b/src/generate/register.rs index 25357bb2..c12f5d46 100644 --- a/src/generate/register.rs +++ b/src/generate/register.rs @@ -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); @@ -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); @@ -716,6 +765,7 @@ 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 @@ -723,6 +773,14 @@ pub fn fields( #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); From 54a44fff1f0f341d750e5cd7367bba81bfe2936e Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Sat, 17 Apr 2021 14:18:48 +0300 Subject: [PATCH 2/2] test features --- .github/workflows/ci.yml | 11 ++++++++++- ci/script.sh | 6 +++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f80f69c2..27d5bf04 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,6 +23,8 @@ jobs: # Temporary hack as long as we use the current CI script TRAVIS_OS_NAME: [linux] + FEATURES: [""] + include: # Test MSRV - rust: 1.40.0 @@ -30,6 +32,13 @@ jobs: 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 @@ -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 diff --git a/ci/script.sh b/ci/script.sh index c587eae5..3591169d 100755 --- a/ci/script.sh +++ b/ci/script.sh @@ -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)