Skip to content

Commit

Permalink
check bitmask on _add
Browse files Browse the repository at this point in the history
  • Loading branch information
burrbull committed Feb 8, 2025
1 parent c605222 commit f574025
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 41 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
3 changes: 3 additions & 0 deletions CHANGELOG-rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ This changelog tracks the Rust `svdtools` project. See

## [Unreleased]

* Update `svd-rs` to 0.4.10

## [v0.4.4] 2025-02-08

* Add `prefix` and `suffix` as opposite to `strip` and `strip_end`
Expand All @@ -30,6 +32,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

Expand Down
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ rust-version = "1.70"
clap = { version = "4.5", features = ["derive", "cargo", "color"] }
serde = { version = "1.0", features = ["derive"] }
quick-xml = { version = "0.36", features = ["serialize"] }
svd-rs = { version = "0.14.9", features = ["serde", "derive-from"] }
svd-parser = { version = "0.14.7", features = ["expand"] }
svd-encoder = "0.14.5"
svd-rs = { version = "0.14.10", features = ["serde", "derive-from"] }
svd-parser = { version = "0.14.8", features = ["expand"] }
svd-encoder = "0.14.6"
# serde_yaml 0.9.x looks broken
serde_yaml = "0.8.26"
serde_json = { version = "1.0", features = ["preserve_order"] }
Expand Down
3 changes: 1 addition & 2 deletions src/html/html_cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
9 changes: 9 additions & 0 deletions src/patch/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
}
Expand Down
36 changes: 22 additions & 14 deletions src/patch/peripheral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
check_offsets, common_description, make_dim_element, matchname, matchsubspec,
Expand Down Expand Up @@ -172,8 +172,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)),
);
Expand Down Expand Up @@ -1043,7 +1057,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")? {
Expand Down Expand Up @@ -1344,6 +1358,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 {
Expand All @@ -1362,7 +1378,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")? {
Expand All @@ -1386,8 +1402,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()?;
Expand Down Expand Up @@ -1643,10 +1657,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::<Vec<_>>();
let bitmasks = registers.iter().map(|r| r.bitmask()).collect::<Vec<_>>();
if !bitmasks.iter().all(|&m| m == bitmasks[0]) {
return Err(anyhow!(
"{path}: registers cannot be collected into {rspec} array. Different bit masks"
Expand Down Expand Up @@ -1769,10 +1780,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::<Vec<_>>();
let bitmasks = registers.iter().map(|r| r.bitmask()).collect::<Vec<_>>();
let new_dim_index = registers
.iter()
.map(|r| {
Expand Down
36 changes: 15 additions & 21 deletions src/patch/register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand All @@ -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] = &[
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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}`"))?;
}

Expand Down Expand Up @@ -380,12 +363,23 @@ 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() {
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(())
Expand Down

0 comments on commit f574025

Please sign in to comment.