Skip to content

ignore if not exists #176

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG-python.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ This changelog tracks the Python `svdtools` project. See
* Support `_include` in peripherals in `device.yaml`
* `-1` for default enum value
* Strip `alternateRegister` too
* Ignore rule if starts with "?~" and no matched instances

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

Expand Down
1 change: 1 addition & 0 deletions CHANGELOG-rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ This changelog tracks the Rust `svdtools` project. See
* Add `--enum_derive` flag
* Strip `alternateRegister` too
* Add `modifiedWriteValues` and `readAction` field patch (#156)
* Ignore rule if starts with "?~" and no matched instances
* Fix #144
* Flag to check for errors after patching

Expand Down
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,18 @@ _rebase:
_strip_end:
- "_POSTFIX_"


# You can list glob-like rules separated by commas to cover more periperals or registers at time.
# If rule is optional (peripheral may be missing in some devices) add `?~` in the header.
# Don't abuse it. First test not optional rule.
"?~TIM[18],TIM20":
CR2:
# Fields also support collecting in arrays
_array:
OIS?:
description: Output Idle state (OC%s output)
# Optional rules are supported here too
"?~OIS?N":
description: Output Idle state (OC%sN output)
```

### Name Matching
Expand Down
5 changes: 3 additions & 2 deletions src/patch/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::{fs::File, io::Read, path::Path};
use super::iterators::{MatchIter, Matched};
use super::peripheral::{PeripheralExt, RegisterBlockExt};
use super::yaml_ext::{AsType, GetVal};
use super::{abspath, matchname, Config, PatchResult, VAL_LVL};
use super::{abspath, matchname, Config, PatchResult, Spec, VAL_LVL};
use super::{make_address_block, make_address_blocks, make_cpu, make_interrupt, make_peripheral};
use super::{make_dim_element, modify_dim_element, modify_register_properties};

Expand Down Expand Up @@ -418,12 +418,13 @@ impl DeviceExt for Device {
) -> PatchResult {
// Find all peripherals that match the spec
let mut pcount = 0;
let (pspec, ignore) = pspec.spec();
for ptag in self.iter_peripherals(pspec) {
pcount += 1;
ptag.process(peripheral, config)
.with_context(|| format!("Processing peripheral `{}`", ptag.name))?;
}
if pcount == 0 {
if !ignore && pcount == 0 {
Err(anyhow!(
"Could not find `{pspec}. Present peripherals: {}.`",
self.peripherals.iter().map(|p| p.name.as_str()).join(", ")
Expand Down
15 changes: 15 additions & 0 deletions src/patch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -736,3 +736,18 @@ fn common_description(descs: &[Option<&str>], dim_index: &[String]) -> Option<Op
}
same.then(|| desc0.map(Into::into))
}

pub trait Spec {
/// Return specification and `ignore_if_not_exists` flag
fn spec(&self) -> (&str, bool);
}

impl Spec for str {
fn spec(&self) -> (&str, bool) {
if let Some(s) = self.strip_prefix("?~") {
(s, true)
} else {
(self, false)
}
}
}
31 changes: 25 additions & 6 deletions src/patch/peripheral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use super::register::{RegisterExt, RegisterInfoExt};
use super::yaml_ext::{AsType, GetVal, ToYaml};
use super::{
check_offsets, common_description, make_dim_element, matchname, matchsubspec,
modify_dim_element, spec_ind, Config, PatchResult, VAL_LVL,
modify_dim_element, spec_ind, Config, PatchResult, Spec, VAL_LVL,
};
use super::{make_cluster, make_interrupt, make_register};

Expand Down Expand Up @@ -407,6 +407,7 @@ impl RegisterBlockExt for Peripheral {
}

fn modify_register(&mut self, rspec: &str, rmod: &Hash) -> PatchResult {
// TODO: empty error
let rtags = self.iter_registers(rspec).collect::<Vec<_>>();
if !rtags.is_empty() {
let register_builder = make_register(rmod)?;
Expand Down Expand Up @@ -557,6 +558,7 @@ impl RegisterBlockExt for Peripheral {
}

fn modify_cluster(&mut self, cspec: &str, cmod: &Hash) -> PatchResult {
// TODO: empty error
let ctags = self.iter_clusters(cspec).collect::<Vec<_>>();
if !ctags.is_empty() {
let cluster_builder = make_cluster(cmod)?;
Expand Down Expand Up @@ -646,12 +648,13 @@ impl RegisterBlockExt for Peripheral {
// Find all registers that match the spec
let mut rcount = 0;
let pname = self.name.clone();
let (rspec, ignore) = rspec.spec();
for rtag in self.iter_registers(rspec) {
rcount += 1;
rtag.process(rmod, &pname, config)
.with_context(|| format!("Processing register `{}`", rtag.name))?;
}
if rcount == 0 {
if !ignore && rcount == 0 {
Err(anyhow!(
"Could not find `{pname}:{rspec}. Present registers: {}.`",
self.registers().map(|r| r.name.as_str()).join(", ")
Expand All @@ -665,12 +668,13 @@ impl RegisterBlockExt for Peripheral {
// Find all clusters that match the spec
let mut ccount = 0;
let pname = self.name.clone();
let (cspec, ignore) = cspec.spec();
for ctag in self.iter_clusters(cspec) {
ccount += 1;
ctag.process(cmod, &pname, config)
.with_context(|| format!("Processing cluster `{}`", ctag.name))?;
}
if ccount == 0 {
if !ignore && ccount == 0 {
Err(anyhow!(
"Could not find `{pname}:{cspec}. Present clusters: {}.`",
self.clusters().map(|c| c.name.as_str()).join(", ")
Expand Down Expand Up @@ -1112,12 +1116,13 @@ impl RegisterBlockExt for Cluster {
// Find all registers that match the spec
let mut rcount = 0;
let pname = self.name.clone();
let (rspec, ignore) = rspec.spec();
for rtag in self.iter_registers(rspec) {
rcount += 1;
rtag.process(rmod, &pname, config)
.with_context(|| format!("Processing register `{}`", rtag.name))?;
}
if rcount == 0 {
if !ignore && rcount == 0 {
Err(anyhow!(
"Could not find `{pname}:{}:{rspec}. Present registers: {}.`",
self.name,
Expand All @@ -1132,12 +1137,13 @@ impl RegisterBlockExt for Cluster {
// Find all clusters that match the spec
let mut ccount = 0;
let pname = self.name.clone();
let (cspec, ignore) = cspec.spec();
for ctag in self.iter_clusters(cspec) {
ccount += 1;
ctag.process(cmod, &pname, config)
.with_context(|| format!("Processing cluster `{}`", ctag.name))?;
}
if ccount == 0 {
if !ignore && ccount == 0 {
Err(anyhow!(
"Could not find `{pname}:{}:{cspec}. Present clusters: {}.`",
self.name,
Expand All @@ -1159,6 +1165,7 @@ fn collect_in_array(
let mut registers = Vec::new();
let mut place = usize::MAX;
let mut i = 0;
let (rspec, ignore) = rspec.spec();
while i < regs.len() {
match &regs[i] {
RegisterCluster::Register(Register::Single(r)) if matchname(&r.name, rspec) => {
Expand All @@ -1171,6 +1178,9 @@ fn collect_in_array(
}
}
if registers.is_empty() {
if ignore {
return Ok(());
}
return Err(anyhow!(
"{path}: registers {rspec} not found. Present registers: {}.`",
regs.iter()
Expand Down Expand Up @@ -1299,9 +1309,9 @@ fn collect_in_cluster(
if rspec == "description" {
continue;
}
rspecs.push(rspec.to_string());
let mut registers = Vec::new();
let mut i = 0;
let (rspec, ignore) = rspec.spec();
while i < regs.len() {
match &regs[i] {
RegisterCluster::Register(Register::Single(r)) if matchname(&r.name, rspec) => {
Expand All @@ -1314,6 +1324,9 @@ fn collect_in_cluster(
}
}
if registers.is_empty() {
if ignore {
continue;
}
return Err(anyhow!(
"{path}: registers {rspec} not found. Present registers: {}.`",
regs.iter()
Expand All @@ -1324,6 +1337,7 @@ fn collect_in_cluster(
.join(", ")
));
}
rspecs.push(rspec.to_string());
if single {
if registers.len() > 1 {
return Err(anyhow!("{path}: more than one registers {rspec} found"));
Expand Down Expand Up @@ -1384,6 +1398,11 @@ fn collect_in_cluster(
}
rdict.insert(rspec.to_string(), registers);
}
if rdict.is_empty() {
return Err(anyhow!(
"{path}: registers cannot be collected into {cname} cluster. No matches found"
));
}
let address_offset = rdict
.values()
.min_by_key(|rs| rs[0].address_offset)
Expand Down
17 changes: 15 additions & 2 deletions src/patch/register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use super::iterators::{MatchIter, Matched};
use super::yaml_ext::{AsType, GetVal, ToYaml};
use super::{
check_offsets, common_description, make_dim_element, matchname, modify_dim_element, spec_ind,
Config, PatchResult, VAL_LVL,
Config, PatchResult, Spec, VAL_LVL,
};
use super::{make_derived_enumerated_values, make_ev_array, make_ev_name, make_field};

Expand Down Expand Up @@ -370,6 +370,7 @@ impl RegisterExt for Register {
let mut fields = Vec::new();
let mut place = usize::MAX;
let mut i = 0;
let (fspec, ignore) = fspec.spec();
while i < fs.len() {
match &fs[i] {
Field::Single(f) if matchname(&f.name, fspec) => {
Expand All @@ -382,6 +383,9 @@ impl RegisterExt for Register {
}
}
if fields.is_empty() {
if ignore {
return Ok(());
}
return Err(anyhow!(
"{}: fields {fspec} not found. Present fields: {}.`",
self.name,
Expand Down Expand Up @@ -448,9 +452,13 @@ impl RegisterExt for Register {
Ok(())
}
fn split_fields(&mut self, fspec: &str, fsplit: &Hash) -> PatchResult {
let (fspec, ignore) = fspec.spec();
let mut it = self.iter_fields(fspec);
let (new_fields, name) = match (it.next(), it.next()) {
(None, _) => {
if ignore {
return Ok(());
}
return Err(anyhow!(
"Could not find any fields to split {}:{fspec}. Present fields: {}.`",
self.name,
Expand Down Expand Up @@ -721,13 +729,17 @@ impl RegisterExt for Register {
set_enum(ftag, evs.clone(), orig_usage, true, access)?;
}
} else {
let (fspec, ignore) = fspec.spec();
let mut offsets: Vec<_> = Vec::new();
for (i, f) in self.fields().enumerate() {
if matchname(&f.name, fspec) {
offsets.push((f.bit_range.offset, f.name.to_string(), i));
}
}
if offsets.is_empty() {
if ignore {
return Ok(());
}
return Err(anyhow!(
"Could not find field {pname}:{}:{fspec}. Present fields: {}.`",
self.name,
Expand Down Expand Up @@ -779,14 +791,15 @@ impl RegisterExt for Register {

fn process_field_range(&mut self, pname: &str, fspec: &str, fmod: &[Yaml]) -> PatchResult {
let mut set_any = false;
let (fspec, ignore) = fspec.spec();
for ftag in self.iter_fields(fspec) {
ftag.write_constraint = Some(WriteConstraint::Range(WriteConstraintRange {
min: fmod[0].i64()? as u64,
max: fmod[1].i64()? as u64,
}));
set_any = true;
}
if !set_any {
if !ignore && !set_any {
return Err(anyhow!(
"Could not find field {pname}:{}:{fspec}. Present fields: {}.`",
self.name,
Expand Down
Loading