From e41895b3dddd4942e68a5aa5e1780d7e6fb13a35 Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Mon, 23 Dec 2024 18:43:08 +0300 Subject: [PATCH 1/2] check bitmask on _add --- .github/workflows/ci.yaml | 2 +- CHANGELOG-rust.md | 1 + src/patch/mod.rs | 17 ++++++++++++++++- src/patch/register.rs | 12 +++++------- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 78f3701..641474c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -63,4 +63,4 @@ jobs: python -m pip install --upgrade pip pip install . - name: Check - run: bash tools/check_${{ matrix.target }}.sh + run: RUST_LOG=warn bash tools/check_${{ matrix.target }}.sh diff --git a/CHANGELOG-rust.md b/CHANGELOG-rust.md index 2aa6252..4c26304 100644 --- a/CHANGELOG-rust.md +++ b/CHANGELOG-rust.md @@ -13,6 +13,7 @@ This changelog tracks the Rust `svdtools` project. See ## [v0.3.21] 2024-12-31 * `_derive` field +* WARN when add field intersecting with other fields ## [v0.3.20] 2024-11-14 diff --git a/src/patch/mod.rs b/src/patch/mod.rs index 2a3a0ed..9bddb46 100644 --- a/src/patch/mod.rs +++ b/src/patch/mod.rs @@ -16,7 +16,7 @@ use svd_parser::svd::{ WriteConstraintRange, }; use svd_parser::SVDError::DimIndexParse; -use svd_rs::{BitRange, DimArrayIndex, DimElement, DimElementBuilder, MaybeArray}; +use svd_rs::{BitRange, DimArrayIndex, DimElement, DimElementBuilder, Field, MaybeArray}; use yaml_rust::{yaml::Hash, Yaml, YamlLoader}; use hashlink::linked_hash_map; @@ -888,6 +888,21 @@ impl Interpolate for FieldPath { } } +fn bitmask(f: &Field) -> u64 { + let BitRange { offset, width, .. } = f.bit_range; + let mask = (!0u64 >> (64 - width)) << offset; + match f { + Field::Single(_) => mask, + Field::Array(_, d) => { + let mut bits = 0; + for i in 0..d.dim { + bits |= mask << (i * d.dim_increment); + } + bits + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/patch/register.rs b/src/patch/register.rs index 9b62b26..a108026 100644 --- a/src/patch/register.rs +++ b/src/patch/register.rs @@ -28,13 +28,7 @@ pub(crate) trait RegisterInfoExt { impl RegisterInfoExt for RegisterInfo { fn get_bitmask(&self) -> u64 { - let mut mask = 0x0; - if let Some(fields) = self.fields.as_ref() { - for ftag in fields { - mask |= (!0 >> (64 - ftag.bit_range.width)) << ftag.bit_range.offset; - } - } - mask + self.fields().fold(0, |mask, f| mask | super::bitmask(f)) } } @@ -347,6 +341,10 @@ impl RegisterExt for Register { } else { fnew.single() }; + let exist_bits = self.get_bitmask(); + if exist_bits & super::bitmask(&fnew) != 0 { + log::warn!("field {fname} conflicts with other fields in register {rpath}"); + } self.fields.get_or_insert_with(Default::default).push(fnew); Ok(()) } From 55b8b0256d5d119f3eb1f296269fb09319feea14 Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Wed, 8 Jan 2025 20:51:20 +0300 Subject: [PATCH 2/2] delete --- src/patch/device.rs | 9 +++++++++ src/patch/peripheral.rs | 24 +++++++++++++++++++----- src/patch/register.rs | 13 ++++++++++--- 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/src/patch/device.rs b/src/patch/device.rs index 2ed3ed8..b739608 100644 --- a/src/patch/device.rs +++ b/src/patch/device.rs @@ -183,6 +183,15 @@ impl DeviceExt for Device { } fn delete_peripheral(&mut self, pspec: &str) -> PatchResult { + if self + .peripherals + .iter() + .filter(|p| matchname(&p.name, pspec)) + .count() + == 0 + { + log::info!("Trying to delete absent `{}` peripheral", pspec); + } self.peripherals.retain(|p| !(matchname(&p.name, pspec))); Ok(()) } diff --git a/src/patch/peripheral.rs b/src/patch/peripheral.rs index 8a16820..083f68f 100644 --- a/src/patch/peripheral.rs +++ b/src/patch/peripheral.rs @@ -168,8 +168,22 @@ pub(crate) trait RegisterBlockExt: Name { } /// Delete registers matched by rspec inside ptag - fn delete_register(&mut self, rspec: &str) -> PatchResult { + fn delete_register(&mut self, rspec: &str, bpath: &BlockPath) -> PatchResult { if let Some(children) = self.children_mut() { + if children + .iter() + .filter( + |rc| matches!(rc, RegisterCluster::Register(r) if matchname(&r.name, rspec)), + ) + .count() + == 0 + { + log::info!( + "Trying to delete absent `{}` register from {}", + rspec, + bpath + ); + } children.retain( |rc| !matches!(rc, RegisterCluster::Register(r) if matchname(&r.name, rspec)), ); @@ -999,7 +1013,7 @@ impl PeripheralExt for Peripheral { } Yaml::Hash(deletions) => { for rspec in deletions.str_vec_iter("_registers")? { - self.delete_register(rspec) + self.delete_register(rspec, &ppath) .with_context(|| format!("Deleting registers matched to `{rspec}`"))?; } for cspec in deletions.str_vec_iter("_clusters")? { @@ -1291,6 +1305,8 @@ impl InterruptExt for Peripheral { impl ClusterExt for Cluster { fn pre_process(&mut self, cmod: &Hash, parent: &BlockPath, _config: &Config) -> PatchResult { + let cpath = parent.new_cluster(&self.name); + // Handle deletions if let Some(deletions) = cmod.get_yaml("_delete") { match deletions { @@ -1309,7 +1325,7 @@ impl ClusterExt for Cluster { } Yaml::Hash(deletions) => { for rspec in deletions.str_vec_iter("_registers")? { - self.delete_register(rspec) + self.delete_register(rspec, &cpath) .with_context(|| format!("Deleting registers matched to `{rspec}`"))?; } for cspec in deletions.str_vec_iter("_clusters")? { @@ -1333,8 +1349,6 @@ impl ClusterExt for Cluster { } } - let cpath = parent.new_cluster(&self.name); - // Handle any copied peripherals for (rname, rcopy) in cmod.hash_iter("_copy") { let rname = rname.str()?; diff --git a/src/patch/register.rs b/src/patch/register.rs index a108026..0407e4b 100644 --- a/src/patch/register.rs +++ b/src/patch/register.rs @@ -62,7 +62,7 @@ pub trait RegisterExt { fn add_field(&mut self, fname: &str, fadd: &Hash, rpath: &RegisterPath) -> PatchResult; /// Delete fields matched by fspec inside rtag - fn delete_field(&mut self, fspec: &str) -> PatchResult; + fn delete_field(&mut self, fspec: &str, rpath: &RegisterPath) -> PatchResult; /// Clear field from rname and mark it as derivedFrom rderive. fn derive_field(&mut self, fname: &str, fderive: &Yaml, rpath: &RegisterPath) -> PatchResult; @@ -152,7 +152,7 @@ impl RegisterExt for Register { // Handle deletions for fspec in rmod.str_vec_iter("_delete")? { - self.delete_field(fspec) + self.delete_field(fspec, &rpath) .with_context(|| format!("Deleting fields matched to `{fspec}`"))?; } @@ -349,8 +349,15 @@ impl RegisterExt for Register { Ok(()) } - fn delete_field(&mut self, fspec: &str) -> PatchResult { + fn delete_field(&mut self, fspec: &str, rpath: &RegisterPath) -> PatchResult { if let Some(fields) = self.fields.as_mut() { + if fields.iter().filter(|f| matchname(&f.name, fspec)).count() == 0 { + log::info!( + "Trying to delete absent `{}` field from register {}", + fspec, + rpath + ); + } fields.retain(|f| !(matchname(&f.name, fspec))); } Ok(())