Skip to content

Commit 95c020b

Browse files
committed
check bitmask on _add
1 parent 858e5c7 commit 95c020b

File tree

6 files changed

+91
-58
lines changed

6 files changed

+91
-58
lines changed

.github/workflows/ci.yaml

Lines changed: 1 addition & 1 deletion
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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ This changelog tracks the Rust `svdtools` project. See
66
## [Unreleased]
77

88
* Calculate `_add` position for peripherals and registers
9+
* Update `svd-rs` to 0.4.10
910

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

@@ -32,6 +33,7 @@ This changelog tracks the Rust `svdtools` project. See
3233
## [v0.3.21] 2024-12-31
3334

3435
* `_derive` field
36+
* WARN when add field intersecting with other fields
3537

3638
## [v0.3.20] 2024-11-14
3739

src/html/html_cli.rs

Lines changed: 1 addition & 2 deletions
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

Lines changed: 9 additions & 1 deletion
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

Lines changed: 57 additions & 32 deletions
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
adding_pos, check_offsets, common_description, make_dim_element, matchname, matchsubspec,
@@ -170,21 +170,43 @@ pub(crate) trait RegisterBlockExt: Name {
170170
}
171171

172172
/// Delete registers and clusters matched by rspec inside ptag
173-
fn delete_child(&mut self, rcspec: &str) -> PatchResult {
173+
fn delete_child(&mut self, rcspec: &str, bpath: &BlockPath) -> PatchResult {
174174
if let Some(children) = self.children_mut() {
175-
children.retain(|rc| !matchname(rc.name(), rcspec));
175+
let mut done = false;
176+
children.retain(|rc| {
177+
let del = matchname(rc.name(), rcspec);
178+
done |= del;
179+
!del
180+
});
181+
if !done {
182+
log::info!(
183+
"Trying to delete absent `{}` register/cluster from {}",
184+
rcspec,
185+
bpath
186+
);
187+
}
176188
Ok(())
177189
} else {
178190
Err(anyhow!("No registers or clusters"))
179191
}
180192
}
181193

182194
/// Delete registers matched by rspec inside ptag
183-
fn delete_register(&mut self, rspec: &str) -> PatchResult {
195+
fn delete_register(&mut self, rspec: &str, bpath: &BlockPath) -> PatchResult {
184196
if let Some(children) = self.children_mut() {
185-
children.retain(
186-
|rc| !matches!(rc, RegisterCluster::Register(r) if matchname(&r.name, rspec)),
187-
);
197+
let mut done = false;
198+
children.retain(|rc| {
199+
let del = matches!(rc, RegisterCluster::Register(r) if matchname(&r.name, rspec));
200+
done |= del;
201+
!del
202+
});
203+
if !done {
204+
log::info!(
205+
"Trying to delete absent `{}` register from {}",
206+
rspec,
207+
bpath
208+
);
209+
}
188210
Ok(())
189211
} else {
190212
Err(anyhow!("No registers or clusters"))
@@ -195,16 +217,13 @@ pub(crate) trait RegisterBlockExt: Name {
195217
let (cspec, ignore) = cspec.spec();
196218

197219
if let Some(children) = self.children_mut() {
198-
let mut deleted = false;
220+
let mut done = false;
199221
children.retain(|rc| {
200-
let retain =
201-
!matches!(rc, RegisterCluster::Cluster(c) if matchname(&c.name, cspec));
202-
if !retain {
203-
deleted = true;
204-
}
205-
retain
222+
let del = matches!(rc, RegisterCluster::Cluster(c) if matchname(&c.name, cspec));
223+
done |= del;
224+
!del
206225
});
207-
if !deleted && !ignore {
226+
if !done && !ignore {
208227
Err(anyhow!("No matching clusters found"))
209228
} else {
210229
Ok(())
@@ -1061,21 +1080,21 @@ impl PeripheralExt for Peripheral {
10611080
if let Some(deletions) = pmod.get_yaml("_delete") {
10621081
match deletions {
10631082
Yaml::String(rcspec) => {
1064-
self.delete_child(rcspec).with_context(|| {
1083+
self.delete_child(rcspec, &ppath).with_context(|| {
10651084
format!("Deleting registers and clusters matched to `{rcspec}`")
10661085
})?;
10671086
}
10681087
Yaml::Array(deletions) => {
10691088
for rcspec in deletions {
10701089
let rcspec = rcspec.str()?;
1071-
self.delete_child(rcspec).with_context(|| {
1090+
self.delete_child(rcspec, &ppath).with_context(|| {
10721091
format!("Deleting registers and clusters matched to `{rcspec}`")
10731092
})?;
10741093
}
10751094
}
10761095
Yaml::Hash(deletions) => {
10771096
for rspec in deletions.str_vec_iter("_registers")? {
1078-
self.delete_register(rspec)
1097+
self.delete_register(rspec, &ppath)
10791098
.with_context(|| format!("Deleting registers matched to `{rspec}`"))?;
10801099
}
10811100
for cspec in deletions.str_vec_iter("_clusters")? {
@@ -1369,32 +1388,46 @@ impl InterruptExt for Peripheral {
13691388
}
13701389

13711390
fn delete_interrupt(&mut self, ispec: &str) -> PatchResult {
1372-
self.interrupt.retain(|i| !(matchname(&i.name, ispec)));
1391+
let mut done = false;
1392+
self.interrupt.retain(|i| {
1393+
let del = matchname(&i.name, ispec);
1394+
done |= del;
1395+
!del
1396+
});
1397+
if !done {
1398+
log::info!(
1399+
"Trying to delete absent `{}` interrupt from {}",
1400+
ispec,
1401+
self.name
1402+
);
1403+
}
13731404
Ok(())
13741405
}
13751406
}
13761407

13771408
impl ClusterExt for Cluster {
13781409
fn pre_process(&mut self, cmod: &Hash, parent: &BlockPath, _config: &Config) -> PatchResult {
1410+
let cpath = parent.new_cluster(&self.name);
1411+
13791412
// Handle deletions
13801413
if let Some(deletions) = cmod.get_yaml("_delete") {
13811414
match deletions {
13821415
Yaml::String(rcspec) => {
1383-
self.delete_child(rcspec).with_context(|| {
1416+
self.delete_child(rcspec, &cpath).with_context(|| {
13841417
format!("Deleting registers and clusters matched to `{rcspec}`")
13851418
})?;
13861419
}
13871420
Yaml::Array(deletions) => {
13881421
for rcspec in deletions {
13891422
let rcspec = rcspec.str()?;
1390-
self.delete_child(rcspec).with_context(|| {
1423+
self.delete_child(rcspec, &cpath).with_context(|| {
13911424
format!("Deleting registers and clusters matched to `{rcspec}`")
13921425
})?;
13931426
}
13941427
}
13951428
Yaml::Hash(deletions) => {
13961429
for rspec in deletions.str_vec_iter("_registers")? {
1397-
self.delete_register(rspec)
1430+
self.delete_register(rspec, &cpath)
13981431
.with_context(|| format!("Deleting registers matched to `{rspec}`"))?;
13991432
}
14001433
for cspec in deletions.str_vec_iter("_clusters")? {
@@ -1418,8 +1451,6 @@ impl ClusterExt for Cluster {
14181451
}
14191452
}
14201453

1421-
let cpath = parent.new_cluster(&self.name);
1422-
14231454
// Handle any copied peripherals
14241455
for (rname, rcopy) in cmod.hash_iter("_copy") {
14251456
let rname = rname.str()?;
@@ -1675,10 +1706,7 @@ fn collect_in_array(
16751706
if !check_offsets(&offsets, dim_increment) {
16761707
return Err(anyhow!("{path}: registers cannot be collected into {rspec} array. Different addressOffset increments"));
16771708
}
1678-
let bitmasks = registers
1679-
.iter()
1680-
.map(RegisterInfo::get_bitmask)
1681-
.collect::<Vec<_>>();
1709+
let bitmasks = registers.iter().map(|r| r.bitmask()).collect::<Vec<_>>();
16821710
if !bitmasks.iter().all(|&m| m == bitmasks[0]) {
16831711
return Err(anyhow!(
16841712
"{path}: registers cannot be collected into {rspec} array. Different bit masks"
@@ -1801,10 +1829,7 @@ fn collect_in_cluster(
18011829
"Some of `{rspec}` registers are arrays and some are not"
18021830
));
18031831
}
1804-
let bitmasks = registers
1805-
.iter()
1806-
.map(|r| RegisterInfo::get_bitmask(r))
1807-
.collect::<Vec<_>>();
1832+
let bitmasks = registers.iter().map(|r| r.bitmask()).collect::<Vec<_>>();
18081833
let new_dim_index = registers
18091834
.iter()
18101835
.map(|r| {

src/patch/register.rs

Lines changed: 21 additions & 22 deletions
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)