Skip to content

Commit 7f0d1c3

Browse files
committed
check bitmask on _add
1 parent c605222 commit 7f0d1c3

File tree

7 files changed

+95
-61
lines changed

7 files changed

+95
-61
lines changed

.github/workflows/ci.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,4 @@ jobs:
6363
python -m pip install --upgrade pip
6464
pip install .
6565
- name: Check
66-
run: bash tools/check_${{ matrix.target }}.sh
66+
run: RUST_LOG=warn bash tools/check_${{ matrix.target }}.sh

CHANGELOG-rust.md

+3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ This changelog tracks the Rust `svdtools` project. See
55

66
## [Unreleased]
77

8+
* Update `svd-rs` to 0.4.10
9+
810
## [v0.4.4] 2025-02-08
911

1012
* Add `prefix` and `suffix` as opposite to `strip` and `strip_end`
@@ -30,6 +32,7 @@ This changelog tracks the Rust `svdtools` project. See
3032
## [v0.3.21] 2024-12-31
3133

3234
* `_derive` field
35+
* WARN when add field intersecting with other fields
3336

3437
## [v0.3.20] 2024-11-14
3538

Cargo.toml

+3-3
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ rust-version = "1.70"
2929
clap = { version = "4.5", features = ["derive", "cargo", "color"] }
3030
serde = { version = "1.0", features = ["derive"] }
3131
quick-xml = { version = "0.36", features = ["serialize"] }
32-
svd-rs = { version = "0.14.9", features = ["serde", "derive-from"] }
33-
svd-parser = { version = "0.14.7", features = ["expand"] }
34-
svd-encoder = "0.14.5"
32+
svd-rs = { version = "0.14.10", features = ["serde", "derive-from"] }
33+
svd-parser = { version = "0.14.8", features = ["expand"] }
34+
svd-encoder = "0.14.6"
3535
# serde_yaml 0.9.x looks broken
3636
serde_yaml = "0.8.26"
3737
serde_json = { version = "1.0", features = ["preserve_order"] }

src/html/html_cli.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -283,8 +283,7 @@ fn parse_register(
283283

284284
let foffset = ftag.bit_offset();
285285
let fwidth = ftag.bit_width();
286-
let bit_mask = (u64::MAX >> (u64::BITS - fwidth)) << foffset;
287-
filling |= bit_mask;
286+
filling |= ftag.bitmask();
288287

289288
let faccs = ftag.access.map(Access::as_str).unwrap_or(raccs);
290289
let enums = ftag.enumerated_values.first();

src/patch/device.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,15 @@ impl DeviceExt for Device {
183183
}
184184

185185
fn delete_peripheral(&mut self, pspec: &str) -> PatchResult {
186-
self.peripherals.retain(|p| !(matchname(&p.name, pspec)));
186+
let mut done = false;
187+
self.peripherals.retain(|p| {
188+
let del = matchname(&p.name, pspec);
189+
done |= del;
190+
!del
191+
});
192+
if !done {
193+
log::info!("Trying to delete absent `{}` peripheral", pspec);
194+
}
187195
Ok(())
188196
}
189197

src/patch/peripheral.rs

+57-32
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use svd_parser::svd::{
99
use yaml_rust::{yaml::Hash, Yaml};
1010

1111
use super::iterators::{MatchIter, Matched};
12-
use super::register::{RegisterExt, RegisterInfoExt};
12+
use super::register::RegisterExt;
1313
use super::yaml_ext::{AsType, GetVal, ToYaml};
1414
use super::{
1515
check_offsets, common_description, make_dim_element, matchname, matchsubspec,
@@ -162,21 +162,43 @@ pub(crate) trait RegisterBlockExt: Name {
162162
fn add_child(&mut self, child: RegisterCluster);
163163

164164
/// Delete registers and clusters matched by rspec inside ptag
165-
fn delete_child(&mut self, rcspec: &str) -> PatchResult {
165+
fn delete_child(&mut self, rcspec: &str, bpath: &BlockPath) -> PatchResult {
166166
if let Some(children) = self.children_mut() {
167-
children.retain(|rc| !matchname(rc.name(), rcspec));
167+
let mut done = false;
168+
children.retain(|rc| {
169+
let del = matchname(rc.name(), rcspec);
170+
done |= del;
171+
!del
172+
});
173+
if !done {
174+
log::info!(
175+
"Trying to delete absent `{}` register/cluster from {}",
176+
rcspec,
177+
bpath
178+
);
179+
}
168180
Ok(())
169181
} else {
170182
Err(anyhow!("No registers or clusters"))
171183
}
172184
}
173185

174186
/// Delete registers matched by rspec inside ptag
175-
fn delete_register(&mut self, rspec: &str) -> PatchResult {
187+
fn delete_register(&mut self, rspec: &str, bpath: &BlockPath) -> PatchResult {
176188
if let Some(children) = self.children_mut() {
177-
children.retain(
178-
|rc| !matches!(rc, RegisterCluster::Register(r) if matchname(&r.name, rspec)),
179-
);
189+
let mut done = false;
190+
children.retain(|rc| {
191+
let del = matches!(rc, RegisterCluster::Register(r) if matchname(&r.name, rspec));
192+
done |= del;
193+
!del
194+
});
195+
if !done {
196+
log::info!(
197+
"Trying to delete absent `{}` register from {}",
198+
rspec,
199+
bpath
200+
);
201+
}
180202
Ok(())
181203
} else {
182204
Err(anyhow!("No registers or clusters"))
@@ -187,16 +209,13 @@ pub(crate) trait RegisterBlockExt: Name {
187209
let (cspec, ignore) = cspec.spec();
188210

189211
if let Some(children) = self.children_mut() {
190-
let mut deleted = false;
212+
let mut done = false;
191213
children.retain(|rc| {
192-
let retain =
193-
!matches!(rc, RegisterCluster::Cluster(c) if matchname(&c.name, cspec));
194-
if !retain {
195-
deleted = true;
196-
}
197-
retain
214+
let del = matches!(rc, RegisterCluster::Cluster(c) if matchname(&c.name, cspec));
215+
done |= del;
216+
!del
198217
});
199-
if !deleted && !ignore {
218+
if !done && !ignore {
200219
Err(anyhow!("No matching clusters found"))
201220
} else {
202221
Ok(())
@@ -1029,21 +1048,21 @@ impl PeripheralExt for Peripheral {
10291048
if let Some(deletions) = pmod.get_yaml("_delete") {
10301049
match deletions {
10311050
Yaml::String(rcspec) => {
1032-
self.delete_child(rcspec).with_context(|| {
1051+
self.delete_child(rcspec, &ppath).with_context(|| {
10331052
format!("Deleting registers and clusters matched to `{rcspec}`")
10341053
})?;
10351054
}
10361055
Yaml::Array(deletions) => {
10371056
for rcspec in deletions {
10381057
let rcspec = rcspec.str()?;
1039-
self.delete_child(rcspec).with_context(|| {
1058+
self.delete_child(rcspec, &ppath).with_context(|| {
10401059
format!("Deleting registers and clusters matched to `{rcspec}`")
10411060
})?;
10421061
}
10431062
}
10441063
Yaml::Hash(deletions) => {
10451064
for rspec in deletions.str_vec_iter("_registers")? {
1046-
self.delete_register(rspec)
1065+
self.delete_register(rspec, &ppath)
10471066
.with_context(|| format!("Deleting registers matched to `{rspec}`"))?;
10481067
}
10491068
for cspec in deletions.str_vec_iter("_clusters")? {
@@ -1337,32 +1356,46 @@ impl InterruptExt for Peripheral {
13371356
}
13381357

13391358
fn delete_interrupt(&mut self, ispec: &str) -> PatchResult {
1340-
self.interrupt.retain(|i| !(matchname(&i.name, ispec)));
1359+
let mut done = false;
1360+
self.interrupt.retain(|i| {
1361+
let del = matchname(&i.name, ispec);
1362+
done |= del;
1363+
!del
1364+
});
1365+
if !done {
1366+
log::info!(
1367+
"Trying to delete absent `{}` interrupt from {}",
1368+
ispec,
1369+
self.name
1370+
);
1371+
}
13411372
Ok(())
13421373
}
13431374
}
13441375

13451376
impl ClusterExt for Cluster {
13461377
fn pre_process(&mut self, cmod: &Hash, parent: &BlockPath, _config: &Config) -> PatchResult {
1378+
let cpath = parent.new_cluster(&self.name);
1379+
13471380
// Handle deletions
13481381
if let Some(deletions) = cmod.get_yaml("_delete") {
13491382
match deletions {
13501383
Yaml::String(rcspec) => {
1351-
self.delete_child(rcspec).with_context(|| {
1384+
self.delete_child(rcspec, &cpath).with_context(|| {
13521385
format!("Deleting registers and clusters matched to `{rcspec}`")
13531386
})?;
13541387
}
13551388
Yaml::Array(deletions) => {
13561389
for rcspec in deletions {
13571390
let rcspec = rcspec.str()?;
1358-
self.delete_child(rcspec).with_context(|| {
1391+
self.delete_child(rcspec, &cpath).with_context(|| {
13591392
format!("Deleting registers and clusters matched to `{rcspec}`")
13601393
})?;
13611394
}
13621395
}
13631396
Yaml::Hash(deletions) => {
13641397
for rspec in deletions.str_vec_iter("_registers")? {
1365-
self.delete_register(rspec)
1398+
self.delete_register(rspec, &cpath)
13661399
.with_context(|| format!("Deleting registers matched to `{rspec}`"))?;
13671400
}
13681401
for cspec in deletions.str_vec_iter("_clusters")? {
@@ -1386,8 +1419,6 @@ impl ClusterExt for Cluster {
13861419
}
13871420
}
13881421

1389-
let cpath = parent.new_cluster(&self.name);
1390-
13911422
// Handle any copied peripherals
13921423
for (rname, rcopy) in cmod.hash_iter("_copy") {
13931424
let rname = rname.str()?;
@@ -1643,10 +1674,7 @@ fn collect_in_array(
16431674
if !check_offsets(&offsets, dim_increment) {
16441675
return Err(anyhow!("{path}: registers cannot be collected into {rspec} array. Different addressOffset increments"));
16451676
}
1646-
let bitmasks = registers
1647-
.iter()
1648-
.map(RegisterInfo::get_bitmask)
1649-
.collect::<Vec<_>>();
1677+
let bitmasks = registers.iter().map(|r| r.bitmask()).collect::<Vec<_>>();
16501678
if !bitmasks.iter().all(|&m| m == bitmasks[0]) {
16511679
return Err(anyhow!(
16521680
"{path}: registers cannot be collected into {rspec} array. Different bit masks"
@@ -1769,10 +1797,7 @@ fn collect_in_cluster(
17691797
"Some of `{rspec}` registers are arrays and some are not"
17701798
));
17711799
}
1772-
let bitmasks = registers
1773-
.iter()
1774-
.map(|r| RegisterInfo::get_bitmask(r))
1775-
.collect::<Vec<_>>();
1800+
let bitmasks = registers.iter().map(|r| r.bitmask()).collect::<Vec<_>>();
17761801
let new_dim_index = registers
17771802
.iter()
17781803
.map(|r| {

src/patch/register.rs

+21-22
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use itertools::Itertools;
55
use svd_parser::expand::{BlockPath, RegisterPath};
66
use svd_parser::svd::{
77
Access, BitRange, DimElement, EnumeratedValues, Field, FieldInfo, ModifiedWriteValues,
8-
ReadAction, Register, RegisterInfo, Usage, WriteConstraint, WriteConstraintRange,
8+
ReadAction, Register, Usage, WriteConstraint, WriteConstraintRange,
99
};
1010
use yaml_rust::{yaml::Hash, Yaml};
1111

@@ -21,23 +21,6 @@ use super::{make_derived_enumerated_values, make_ev_array, make_ev_name, make_fi
2121

2222
pub type FieldMatchIterMut<'a, 'b> = MatchIter<'b, std::slice::IterMut<'a, Field>>;
2323

24-
pub(crate) trait RegisterInfoExt {
25-
/// Calculate filling of register
26-
fn get_bitmask(&self) -> u64;
27-
}
28-
29-
impl RegisterInfoExt for RegisterInfo {
30-
fn get_bitmask(&self) -> u64 {
31-
let mut mask = 0x0;
32-
if let Some(fields) = self.fields.as_ref() {
33-
for ftag in fields {
34-
mask |= (!0 >> (64 - ftag.bit_range.width)) << ftag.bit_range.offset;
35-
}
36-
}
37-
mask
38-
}
39-
}
40-
4124
/// Collecting methods for processing register contents
4225
pub trait RegisterExt {
4326
const KEYWORDS: &'static [&'static str] = &[
@@ -70,7 +53,7 @@ pub trait RegisterExt {
7053
fn add_field(&mut self, fname: &str, fadd: &Hash, rpath: &RegisterPath) -> PatchResult;
7154

7255
/// Delete fields matched by fspec inside rtag
73-
fn delete_field(&mut self, fspec: &str) -> PatchResult;
56+
fn delete_field(&mut self, fspec: &str, rpath: &RegisterPath) -> PatchResult;
7457

7558
/// Clear field from rname and mark it as derivedFrom rderive.
7659
fn derive_field(&mut self, fname: &str, fderive: &Yaml, rpath: &RegisterPath) -> PatchResult;
@@ -166,7 +149,7 @@ impl RegisterExt for Register {
166149

167150
// Handle deletions
168151
for fspec in rmod.str_vec_iter("_delete")? {
169-
self.delete_field(fspec)
152+
self.delete_field(fspec, &rpath)
170153
.with_context(|| format!("Deleting fields matched to `{fspec}`"))?;
171154
}
172155

@@ -380,13 +363,29 @@ impl RegisterExt for Register {
380363
} else {
381364
fnew.single()
382365
};
366+
let exist_bits = self.bitmask();
367+
if exist_bits & fnew.bitmask() != 0 {
368+
log::warn!("field {fname} conflicts with other fields in register {rpath}");
369+
}
383370
self.fields.get_or_insert_with(Default::default).push(fnew);
384371
Ok(())
385372
}
386373

387-
fn delete_field(&mut self, fspec: &str) -> PatchResult {
374+
fn delete_field(&mut self, fspec: &str, rpath: &RegisterPath) -> PatchResult {
388375
if let Some(fields) = self.fields.as_mut() {
389-
fields.retain(|f| !(matchname(&f.name, fspec)));
376+
let mut done = false;
377+
fields.retain(|f| {
378+
let del = matchname(&f.name, fspec);
379+
done |= del;
380+
!del
381+
});
382+
if !done {
383+
log::info!(
384+
"Trying to delete absent `{}` field from register {}",
385+
fspec,
386+
rpath
387+
);
388+
}
390389
}
391390
Ok(())
392391
}

0 commit comments

Comments
 (0)