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 cec3399..0c099f4 100644 --- a/CHANGELOG-rust.md +++ b/CHANGELOG-rust.md @@ -6,6 +6,7 @@ This changelog tracks the Rust `svdtools` project. See ## [Unreleased] * Calculate `_add` position for peripherals and registers +* Update `svd-rs` to 0.4.10 ## [v0.4.4] 2025-02-08 @@ -32,6 +33,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/html/html_cli.rs b/src/html/html_cli.rs index 0978fcf..e4b7caf 100644 --- a/src/html/html_cli.rs +++ b/src/html/html_cli.rs @@ -283,8 +283,7 @@ fn parse_register( let foffset = ftag.bit_offset(); let fwidth = ftag.bit_width(); - let bit_mask = (u64::MAX >> (u64::BITS - fwidth)) << foffset; - filling |= bit_mask; + filling |= ftag.bitmask(); let faccs = ftag.access.map(Access::as_str).unwrap_or(raccs); let enums = ftag.enumerated_values.first(); diff --git a/src/patch/device.rs b/src/patch/device.rs index e7a3cb1..8d5d73c 100644 --- a/src/patch/device.rs +++ b/src/patch/device.rs @@ -183,7 +183,15 @@ impl DeviceExt for Device { } fn delete_peripheral(&mut self, pspec: &str) -> PatchResult { - self.peripherals.retain(|p| !(matchname(&p.name, pspec))); + let mut done = false; + self.peripherals.retain(|p| { + let del = matchname(&p.name, pspec); + done |= del; + !del + }); + if !done { + log::info!("Trying to delete absent `{}` peripheral", pspec); + } Ok(()) } diff --git a/src/patch/peripheral.rs b/src/patch/peripheral.rs index cd690b3..a153bec 100644 --- a/src/patch/peripheral.rs +++ b/src/patch/peripheral.rs @@ -9,7 +9,7 @@ use svd_parser::svd::{ use yaml_rust::{yaml::Hash, Yaml}; use super::iterators::{MatchIter, Matched}; -use super::register::{RegisterExt, RegisterInfoExt}; +use super::register::RegisterExt; use super::yaml_ext::{AsType, GetVal, ToYaml}; use super::{ adding_pos, check_offsets, common_description, make_dim_element, matchname, matchsubspec, @@ -170,9 +170,21 @@ pub(crate) trait RegisterBlockExt: Name { } /// Delete registers and clusters matched by rspec inside ptag - fn delete_child(&mut self, rcspec: &str) -> PatchResult { + fn delete_child(&mut self, rcspec: &str, bpath: &BlockPath) -> PatchResult { if let Some(children) = self.children_mut() { - children.retain(|rc| !matchname(rc.name(), rcspec)); + let mut done = false; + children.retain(|rc| { + let del = matchname(rc.name(), rcspec); + done |= del; + !del + }); + if !done { + log::info!( + "Trying to delete absent `{}` register/cluster from {}", + rcspec, + bpath + ); + } Ok(()) } else { Err(anyhow!("No registers or clusters")) @@ -180,11 +192,21 @@ 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() { - children.retain( - |rc| !matches!(rc, RegisterCluster::Register(r) if matchname(&r.name, rspec)), - ); + let mut done = false; + children.retain(|rc| { + let del = matches!(rc, RegisterCluster::Register(r) if matchname(&r.name, rspec)); + done |= del; + !del + }); + if !done { + log::info!( + "Trying to delete absent `{}` register from {}", + rspec, + bpath + ); + } Ok(()) } else { Err(anyhow!("No registers or clusters")) @@ -195,16 +217,13 @@ pub(crate) trait RegisterBlockExt: Name { let (cspec, ignore) = cspec.spec(); if let Some(children) = self.children_mut() { - let mut deleted = false; + let mut done = false; children.retain(|rc| { - let retain = - !matches!(rc, RegisterCluster::Cluster(c) if matchname(&c.name, cspec)); - if !retain { - deleted = true; - } - retain + let del = matches!(rc, RegisterCluster::Cluster(c) if matchname(&c.name, cspec)); + done |= del; + !del }); - if !deleted && !ignore { + if !done && !ignore { Err(anyhow!("No matching clusters found")) } else { Ok(()) @@ -1061,21 +1080,21 @@ impl PeripheralExt for Peripheral { if let Some(deletions) = pmod.get_yaml("_delete") { match deletions { Yaml::String(rcspec) => { - self.delete_child(rcspec).with_context(|| { + self.delete_child(rcspec, &ppath).with_context(|| { format!("Deleting registers and clusters matched to `{rcspec}`") })?; } Yaml::Array(deletions) => { for rcspec in deletions { let rcspec = rcspec.str()?; - self.delete_child(rcspec).with_context(|| { + self.delete_child(rcspec, &ppath).with_context(|| { format!("Deleting registers and clusters matched to `{rcspec}`") })?; } } 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")? { @@ -1369,32 +1388,46 @@ impl InterruptExt for Peripheral { } fn delete_interrupt(&mut self, ispec: &str) -> PatchResult { - self.interrupt.retain(|i| !(matchname(&i.name, ispec))); + let mut done = false; + self.interrupt.retain(|i| { + let del = matchname(&i.name, ispec); + done |= del; + !del + }); + if !done { + log::info!( + "Trying to delete absent `{}` interrupt from {}", + ispec, + self.name + ); + } Ok(()) } } 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 { Yaml::String(rcspec) => { - self.delete_child(rcspec).with_context(|| { + self.delete_child(rcspec, &cpath).with_context(|| { format!("Deleting registers and clusters matched to `{rcspec}`") })?; } Yaml::Array(deletions) => { for rcspec in deletions { let rcspec = rcspec.str()?; - self.delete_child(rcspec).with_context(|| { + self.delete_child(rcspec, &cpath).with_context(|| { format!("Deleting registers and clusters matched to `{rcspec}`") })?; } } 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")? { @@ -1418,8 +1451,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()?; @@ -1675,10 +1706,7 @@ fn collect_in_array( if !check_offsets(&offsets, dim_increment) { return Err(anyhow!("{path}: registers cannot be collected into {rspec} array. Different addressOffset increments")); } - let bitmasks = registers - .iter() - .map(RegisterInfo::get_bitmask) - .collect::>(); + let bitmasks = registers.iter().map(|r| r.bitmask()).collect::>(); if !bitmasks.iter().all(|&m| m == bitmasks[0]) { return Err(anyhow!( "{path}: registers cannot be collected into {rspec} array. Different bit masks" @@ -1801,10 +1829,7 @@ fn collect_in_cluster( "Some of `{rspec}` registers are arrays and some are not" )); } - let bitmasks = registers - .iter() - .map(|r| RegisterInfo::get_bitmask(r)) - .collect::>(); + let bitmasks = registers.iter().map(|r| r.bitmask()).collect::>(); let new_dim_index = registers .iter() .map(|r| { diff --git a/src/patch/register.rs b/src/patch/register.rs index 170aa86..5608cb9 100644 --- a/src/patch/register.rs +++ b/src/patch/register.rs @@ -5,7 +5,7 @@ use itertools::Itertools; use svd_parser::expand::{BlockPath, RegisterPath}; use svd_parser::svd::{ Access, BitRange, DimElement, EnumeratedValues, Field, FieldInfo, ModifiedWriteValues, - ReadAction, Register, RegisterInfo, Usage, WriteConstraint, WriteConstraintRange, + ReadAction, Register, Usage, WriteConstraint, WriteConstraintRange, }; use yaml_rust::{yaml::Hash, Yaml}; @@ -21,23 +21,6 @@ use super::{make_derived_enumerated_values, make_ev_array, make_ev_name, make_fi pub type FieldMatchIterMut<'a, 'b> = MatchIter<'b, std::slice::IterMut<'a, Field>>; -pub(crate) trait RegisterInfoExt { - /// Calculate filling of register - fn get_bitmask(&self) -> u64; -} - -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 - } -} - /// Collecting methods for processing register contents pub trait RegisterExt { const KEYWORDS: &'static [&'static str] = &[ @@ -70,7 +53,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; @@ -166,7 +149,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}`"))?; } @@ -380,13 +363,29 @@ impl RegisterExt for Register { } else { fnew.single() }; + let exist_bits = self.bitmask(); + if exist_bits & fnew.bitmask() != 0 { + log::warn!("field {fname} conflicts with other fields in register {rpath}"); + } self.fields.get_or_insert_with(Default::default).push(fnew); 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() { - fields.retain(|f| !(matchname(&f.name, fspec))); + let mut done = false; + fields.retain(|f| { + let del = matchname(&f.name, fspec); + done |= del; + !del + }); + if !done { + log::info!( + "Trying to delete absent `{}` field from register {}", + fspec, + rpath + ); + } } Ok(()) }