Skip to content

Commit 1f09b9e

Browse files
committed
ignore if not exists
1 parent 1b908c1 commit 1f09b9e

File tree

8 files changed

+115
-19
lines changed

8 files changed

+115
-19
lines changed

CHANGELOG-python.md

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ This changelog tracks the Python `svdtools` project. See
66
## [Unreleased]
77

88
* `-1` for default enum value
9+
* Ignore rule if starts with "?@" and no matched instances
910

1011
## [v0.1.26] 2023-03-28
1112

CHANGELOG-rust.md

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

66
## [Unreleased]
77

8+
* Ignore rule if starts with "?@" and no matched instances
89
* Move field with derived enums before other
910
* `-1` for default enum value
1011
* mmaps: peripheral arrays, bump `svd` crates

README.md

+12-1
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,18 @@ _rebase:
351351
_strip_end:
352352
- "_POSTFIX_"
353353

354-
354+
# You can list glob-like rules separated by commas to cover more periperals or registers at time.
355+
# If rule is optional (peripheral may be missing in some devices) add `?@` in the header.
356+
# Don't abuse it. First test not optional rule.
357+
"?@TIM[18],TIM20":
358+
CR2:
359+
# Fields also support collecting in arrays
360+
_array:
361+
OIS?:
362+
description: Output Idle state %s (OC%s output)
363+
# Optional rules are supported here too
364+
"?@OIS?N":
365+
description: Output Idle state %s (OC%sN output)
355366
```
356367
357368
### Name Matching

src/patch/device.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::{fs::File, io::Read, path::Path};
99
use super::iterators::{MatchIter, Matched};
1010
use super::peripheral::{PeripheralExt, RegisterBlockExt};
1111
use super::yaml_ext::{AsType, GetVal};
12-
use super::{abspath, matchname, PatchResult, VAL_LVL};
12+
use super::{abspath, matchname, PatchResult, Spec, VAL_LVL};
1313
use super::{make_address_block, make_address_blocks, make_cpu, make_interrupt, make_peripheral};
1414
use super::{make_dim_element, modify_dim_element, modify_register_properties};
1515

@@ -418,12 +418,13 @@ impl DeviceExt for Device {
418418
) -> PatchResult {
419419
// Find all peripherals that match the spec
420420
let mut pcount = 0;
421+
let (pspec, ignore) = pspec.spec();
421422
for ptag in self.iter_peripherals(pspec) {
422423
pcount += 1;
423424
ptag.process(peripheral, update_fields)
424425
.with_context(|| format!("Processing peripheral `{}`", ptag.name))?;
425426
}
426-
if pcount == 0 {
427+
if !ignore && pcount == 0 {
427428
Err(anyhow!(
428429
"Could not find `{pspec}. Present peripherals: {}.`",
429430
self.peripherals.iter().map(|p| p.name.as_str()).join(", ")

src/patch/mod.rs

+15
Original file line numberDiff line numberDiff line change
@@ -637,3 +637,18 @@ fn check_offsets(offsets: &[u32], dim_increment: u32) -> bool {
637637
}
638638
true
639639
}
640+
641+
pub trait Spec {
642+
/// Return specification and `ignore_if_not_exists` flag
643+
fn spec(&self) -> (&str, bool);
644+
}
645+
646+
impl Spec for str {
647+
fn spec(&self) -> (&str, bool) {
648+
if let Some(s) = self.strip_prefix("?@") {
649+
(s, true)
650+
} else {
651+
(self, false)
652+
}
653+
}
654+
}

src/patch/peripheral.rs

+25-6
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use super::register::{RegisterExt, RegisterInfoExt};
1111
use super::yaml_ext::{AsType, GetVal, ToYaml};
1212
use super::{
1313
check_offsets, make_dim_element, matchname, matchsubspec, modify_dim_element, spec_ind,
14-
PatchResult, VAL_LVL,
14+
PatchResult, Spec, VAL_LVL,
1515
};
1616
use super::{make_cluster, make_interrupt, make_register};
1717

@@ -412,6 +412,7 @@ impl RegisterBlockExt for Peripheral {
412412
}
413413

414414
fn modify_register(&mut self, rspec: &str, rmod: &Hash) -> PatchResult {
415+
// TODO: empty error
415416
let rtags = self.iter_registers(rspec).collect::<Vec<_>>();
416417
if !rtags.is_empty() {
417418
let register_builder = make_register(rmod)?;
@@ -562,6 +563,7 @@ impl RegisterBlockExt for Peripheral {
562563
}
563564

564565
fn modify_cluster(&mut self, cspec: &str, cmod: &Hash) -> PatchResult {
566+
// TODO: empty error
565567
let ctags = self.iter_clusters(cspec).collect::<Vec<_>>();
566568
if !ctags.is_empty() {
567569
let cluster_builder = make_cluster(cmod)?;
@@ -640,12 +642,13 @@ impl RegisterBlockExt for Peripheral {
640642
// Find all registers that match the spec
641643
let mut rcount = 0;
642644
let pname = self.name.clone();
645+
let (rspec, ignore) = rspec.spec();
643646
for rtag in self.iter_registers(rspec) {
644647
rcount += 1;
645648
rtag.process(rmod, &pname, update_fields)
646649
.with_context(|| format!("Processing register `{}`", rtag.name))?;
647650
}
648-
if rcount == 0 {
651+
if !ignore && rcount == 0 {
649652
Err(anyhow!(
650653
"Could not find `{pname}:{rspec}. Present registers: {}.`",
651654
self.registers().map(|r| r.name.as_str()).join(", ")
@@ -659,12 +662,13 @@ impl RegisterBlockExt for Peripheral {
659662
// Find all clusters that match the spec
660663
let mut ccount = 0;
661664
let pname = self.name.clone();
665+
let (cspec, ignore) = cspec.spec();
662666
for ctag in self.iter_clusters(cspec) {
663667
ccount += 1;
664668
ctag.process(cmod, &pname, update_fields)
665669
.with_context(|| format!("Processing cluster `{}`", ctag.name))?;
666670
}
667-
if ccount == 0 {
671+
if !ignore && ccount == 0 {
668672
Err(anyhow!(
669673
"Could not find `{pname}:{cspec}. Present clusters: {}.`",
670674
self.clusters().map(|c| c.name.as_str()).join(", ")
@@ -1095,12 +1099,13 @@ impl RegisterBlockExt for Cluster {
10951099
// Find all registers that match the spec
10961100
let mut rcount = 0;
10971101
let pname = self.name.clone();
1102+
let (rspec, ignore) = rspec.spec();
10981103
for rtag in self.iter_registers(rspec) {
10991104
rcount += 1;
11001105
rtag.process(rmod, &pname, update_fields)
11011106
.with_context(|| format!("Processing register `{}`", rtag.name))?;
11021107
}
1103-
if rcount == 0 {
1108+
if !ignore && rcount == 0 {
11041109
Err(anyhow!(
11051110
"Could not find `{pname}:{}:{rspec}. Present registers: {}.`",
11061111
self.name,
@@ -1115,12 +1120,13 @@ impl RegisterBlockExt for Cluster {
11151120
// Find all clusters that match the spec
11161121
let mut ccount = 0;
11171122
let pname = self.name.clone();
1123+
let (cspec, ignore) = cspec.spec();
11181124
for ctag in self.iter_clusters(cspec) {
11191125
ccount += 1;
11201126
ctag.process(cmod, &pname, update_fields)
11211127
.with_context(|| format!("Processing cluster `{}`", ctag.name))?;
11221128
}
1123-
if ccount == 0 {
1129+
if !ignore && ccount == 0 {
11241130
Err(anyhow!(
11251131
"Could not find `{pname}:{}:{cspec}. Present clusters: {}.`",
11261132
self.name,
@@ -1141,6 +1147,7 @@ fn collect_in_array(
11411147
let mut registers = Vec::new();
11421148
let mut place = usize::MAX;
11431149
let mut i = 0;
1150+
let (rspec, ignore) = rspec.spec();
11441151
while i < regs.len() {
11451152
match &regs[i] {
11461153
RegisterCluster::Register(Register::Single(r)) if matchname(&r.name, rspec) => {
@@ -1153,6 +1160,9 @@ fn collect_in_array(
11531160
}
11541161
}
11551162
if registers.is_empty() {
1163+
if ignore {
1164+
return Ok(());
1165+
}
11561166
return Err(anyhow!(
11571167
"{path}: registers {rspec} not found. Present registers: {}.`",
11581168
regs.iter()
@@ -1256,9 +1266,9 @@ fn collect_in_cluster(
12561266
if rspec == "description" {
12571267
continue;
12581268
}
1259-
rspecs.push(rspec.to_string());
12601269
let mut registers = Vec::new();
12611270
let mut i = 0;
1271+
let (rspec, ignore) = rspec.spec();
12621272
while i < regs.len() {
12631273
match &regs[i] {
12641274
RegisterCluster::Register(Register::Single(r)) if matchname(&r.name, rspec) => {
@@ -1271,6 +1281,9 @@ fn collect_in_cluster(
12711281
}
12721282
}
12731283
if registers.is_empty() {
1284+
if ignore {
1285+
continue;
1286+
}
12741287
return Err(anyhow!(
12751288
"{path}: registers {rspec} not found. Present registers: {}.`",
12761289
regs.iter()
@@ -1281,6 +1294,7 @@ fn collect_in_cluster(
12811294
.join(", ")
12821295
));
12831296
}
1297+
rspecs.push(rspec.to_string());
12841298
if single {
12851299
if registers.len() > 1 {
12861300
return Err(anyhow!("{path}: more than one registers {rspec} found"));
@@ -1341,6 +1355,11 @@ fn collect_in_cluster(
13411355
}
13421356
rdict.insert(rspec.to_string(), registers);
13431357
}
1358+
if rdict.is_empty() {
1359+
return Err(anyhow!(
1360+
"{path}: registers cannot be collected into {cname} cluster. No matches found"
1361+
));
1362+
}
13441363
let address_offset = rdict
13451364
.values()
13461365
.min_by_key(|rs| rs[0].address_offset)

src/patch/register.rs

+16-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ use yaml_rust::{yaml::Hash, Yaml};
99
use super::iterators::{MatchIter, Matched};
1010
use super::yaml_ext::{AsType, GetVal, ToYaml};
1111
use super::{
12-
check_offsets, make_dim_element, matchname, modify_dim_element, spec_ind, PatchResult, VAL_LVL,
12+
check_offsets, make_dim_element, matchname, modify_dim_element, spec_ind, PatchResult, Spec,
13+
VAL_LVL,
1314
};
1415
use super::{make_derived_enumerated_values, make_ev_array, make_ev_name, make_field};
1516

@@ -360,6 +361,7 @@ impl RegisterExt for Register {
360361
let mut fields = Vec::new();
361362
let mut place = usize::MAX;
362363
let mut i = 0;
364+
let (fspec, ignore) = fspec.spec();
363365
while i < fs.len() {
364366
match &fs[i] {
365367
Field::Single(f) if matchname(&f.name, fspec) => {
@@ -372,6 +374,9 @@ impl RegisterExt for Register {
372374
}
373375
}
374376
if fields.is_empty() {
377+
if ignore {
378+
return Ok(());
379+
}
375380
return Err(anyhow!(
376381
"{}: fields {fspec} not found. Present fields: {}.`",
377382
self.name,
@@ -432,9 +437,13 @@ impl RegisterExt for Register {
432437
Ok(())
433438
}
434439
fn split_fields(&mut self, fspec: &str, fsplit: &Hash) -> PatchResult {
440+
let (fspec, ignore) = fspec.spec();
435441
let mut it = self.iter_fields(fspec);
436442
let (new_fields, name) = match (it.next(), it.next()) {
437443
(None, _) => {
444+
if ignore {
445+
return Ok(());
446+
}
438447
return Err(anyhow!(
439448
"Could not find any fields to split {}:{fspec}. Present fields: {}.`",
440449
self.name,
@@ -686,13 +695,17 @@ impl RegisterExt for Register {
686695
set_enum(ftag, evs.clone(), orig_usage, true, access)?;
687696
}
688697
} else {
698+
let (fspec, ignore) = fspec.spec();
689699
let mut offsets: Vec<_> = Vec::new();
690700
for (i, f) in self.fields().enumerate() {
691701
if matchname(&f.name, fspec) {
692702
offsets.push((f.bit_range.offset, f.name.to_string(), i));
693703
}
694704
}
695705
if offsets.is_empty() {
706+
if ignore {
707+
return Ok(());
708+
}
696709
return Err(anyhow!(
697710
"Could not find field {pname}:{}:{fspec}. Present fields: {}.`",
698711
self.name,
@@ -738,14 +751,15 @@ impl RegisterExt for Register {
738751

739752
fn process_field_range(&mut self, pname: &str, fspec: &str, fmod: &[Yaml]) -> PatchResult {
740753
let mut set_any = false;
754+
let (fspec, ignore) = fspec.spec();
741755
for ftag in self.iter_fields(fspec) {
742756
ftag.write_constraint = Some(WriteConstraint::Range(WriteConstraintRange {
743757
min: fmod[0].i64()? as u64,
744758
max: fmod[1].i64()? as u64,
745759
}));
746760
set_any = true;
747761
}
748-
if !set_any {
762+
if !ignore && !set_any {
749763
return Err(anyhow!(
750764
"Could not find field {pname}:{}:{fspec}. Present fields: {}.`",
751765
self.name,

0 commit comments

Comments
 (0)