Skip to content

Commit

Permalink
Merge pull request #172 from rust-embedded/sort-derived-fields
Browse files Browse the repository at this point in the history
Move field with derived enums before other, use Itertools::join
  • Loading branch information
adamgreig authored Oct 16, 2023
2 parents 9fbd8a0 + 7cbe747 commit 848fe7a
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 87 deletions.
2 changes: 2 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]

* Move field with derived enums before other

## [v0.3.4] 2023-10-14

* Revert #145
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ liquid = "0.26.0"
once_cell = "1.18.0"
rayon = "1.7.0"
regex = "1.9.1"
itertools = "0.11.0"

[dev-dependencies]
tempfile = "3.3"
87 changes: 60 additions & 27 deletions src/patch/device.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use anyhow::{anyhow, Context};
use itertools::Itertools;
use svd_parser::svd::{Device, Peripheral, PeripheralInfo};
use yaml_rust::{yaml::Hash, Yaml};

Expand Down Expand Up @@ -305,32 +306,60 @@ impl DeviceExt for Device {
return Err(anyhow!("derive: incorrect syntax for {pname}"));
};

if !pderive.contains('.') {
self.get_peripheral(pderive)
.ok_or_else(|| anyhow!("peripheral {pderive} not found"))?;
}
let derived_pos = if !pderive.contains('.') {
let Some((i, _)) = self
.peripherals
.iter()
.enumerate()
.find(|(_, f)| f.name == pderive)
else {
return Err(anyhow!("peripheral {pderive} not found"));
};
Some(i)
} else {
None
};

match self.get_mut_peripheral(pname) {
Some(peripheral) => peripheral.modify_from(info, VAL_LVL)?,
let mut min_pos = self.peripherals.len();
match self
.peripherals
.iter_mut()
.enumerate()
.find(|(_, f)| f.name == pname)
{
Some((i, peripheral)) => {
min_pos = i;
peripheral.modify_from(info, VAL_LVL)?;
}
None => {
let peripheral = info.name(pname.into()).build(VAL_LVL)?.single();
self.peripherals.push(peripheral);
}
}

for p in self
.peripherals
.iter_mut()
.filter(|p| p.derived_from.as_deref() == Some(pname))
{
p.derived_from = Some(pderive.into());
for (i, p) in self.peripherals.iter_mut().enumerate() {
if p.derived_from.as_deref() == Some(pname) {
if i < min_pos {
min_pos = i;
}
p.derived_from = Some(pderive.into());
}
}
if let Some(derived_pos) = derived_pos {
if derived_pos > min_pos {
let p = self.peripherals.remove(derived_pos);
self.peripherals.insert(min_pos, p);
}
}
Ok(())
}

fn rebase_peripheral(&mut self, pnew: &str, pold: &str) -> PatchResult {
let old = self
.get_mut_peripheral(pold)
let (mut min_pos, old) = self
.peripherals
.iter_mut()
.enumerate()
.find(|(_, f)| f.name == pold)
.ok_or_else(|| anyhow!("peripheral {pold} not found"))?;
let mut d = std::mem::replace(
old,
Expand All @@ -346,19 +375,27 @@ impl DeviceExt for Device {
.build(VAL_LVL)?
.single(),
);
let new = self
.get_mut_peripheral(pnew)
let (new_pos, new) = self
.peripherals
.iter_mut()
.enumerate()
.find(|(_, f)| f.name == pnew)
.ok_or_else(|| anyhow!("peripheral {pnew} not found"))?;
d.name = new.name.clone();
d.base_address = new.base_address;
d.interrupt = new.interrupt.clone();
*new = d;
for p in self
.peripherals
.iter_mut()
.filter(|p| p.derived_from.as_deref() == Some(pold))
{
p.derived_from = Some(pnew.into());
for (i, p) in self.peripherals.iter_mut().enumerate() {
if p.derived_from.as_deref() == Some(pold) {
if i < min_pos {
min_pos = i;
}
p.derived_from = Some(pnew.into());
}
}
if new_pos > min_pos {
let p = self.peripherals.remove(new_pos);
self.peripherals.insert(min_pos, p);
}
Ok(())
}
Expand Down Expand Up @@ -389,11 +426,7 @@ impl DeviceExt for Device {
if pcount == 0 {
Err(anyhow!(
"Could not find `{pspec}. Present peripherals: {}.`",
self.peripherals
.iter()
.map(|p| p.name.as_str())
.collect::<Vec<_>>()
.join(", ")
self.peripherals.iter().map(|p| p.name.as_str()).join(", ")
))
} else {
Ok(())
Expand Down
41 changes: 10 additions & 31 deletions src/patch/peripheral.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use anyhow::{anyhow, Context};
use itertools::Itertools;
use svd_parser::svd::{
self, Cluster, ClusterInfo, DimElement, Interrupt, Peripheral, Register, RegisterCluster,
RegisterInfo,
Expand Down Expand Up @@ -487,10 +488,7 @@ impl RegisterBlockExt for Peripheral {
self.get_register(rderive).ok_or_else(|| {
anyhow!(
"register {rderive} not found. Present registers: {}.`",
self.registers()
.map(|r| r.name.as_str())
.collect::<Vec<_>>()
.join(", ")
self.registers().map(|r| r.name.as_str()).join(", ")
)
})?;

Expand Down Expand Up @@ -535,10 +533,8 @@ impl RegisterBlockExt for Peripheral {
source.address_offset = ptag.address_offset;
*ptag = source;
} else {
self.registers
.as_mut()
.unwrap()
.push(RegisterCluster::Register(source))
let registers = self.registers.get_or_insert_with(Vec::new);
registers.push(RegisterCluster::Register(source));
}
Ok(())
}
Expand Down Expand Up @@ -652,10 +648,7 @@ impl RegisterBlockExt for Peripheral {
if rcount == 0 {
Err(anyhow!(
"Could not find `{pname}:{rspec}. Present registers: {}.`",
self.registers()
.map(|r| r.name.as_str())
.collect::<Vec<_>>()
.join(", ")
self.registers().map(|r| r.name.as_str()).join(", ")
))
} else {
Ok(())
Expand All @@ -674,10 +667,7 @@ impl RegisterBlockExt for Peripheral {
if ccount == 0 {
Err(anyhow!(
"Could not find `{pname}:{cspec}. Present clusters: {}.`",
self.clusters()
.map(|c| c.name.as_str())
.collect::<Vec<_>>()
.join(", ")
self.clusters().map(|c| c.name.as_str()).join(", ")
))
} else {
Ok(())
Expand Down Expand Up @@ -966,10 +956,7 @@ impl RegisterBlockExt for Cluster {
self.get_register(rderive).ok_or_else(|| {
anyhow!(
"register {rderive} not found. Present registers: {}.`",
self.registers()
.map(|r| r.name.as_str())
.collect::<Vec<_>>()
.join(", ")
self.registers().map(|r| r.name.as_str()).join(", ")
)
})?;

Expand Down Expand Up @@ -1117,10 +1104,7 @@ impl RegisterBlockExt for Cluster {
Err(anyhow!(
"Could not find `{pname}:{}:{rspec}. Present registers: {}.`",
self.name,
self.registers()
.map(|r| r.name.as_str())
.collect::<Vec<_>>()
.join(", ")
self.registers().map(|r| r.name.as_str()).join(", ")
))
} else {
Ok(())
Expand All @@ -1140,10 +1124,7 @@ impl RegisterBlockExt for Cluster {
Err(anyhow!(
"Could not find `{pname}:{}:{cspec}. Present clusters: {}.`",
self.name,
self.clusters()
.map(|c| c.name.as_str())
.collect::<Vec<_>>()
.join(", ")
self.clusters().map(|c| c.name.as_str()).join(", ")
))
} else {
Ok(())
Expand Down Expand Up @@ -1179,7 +1160,6 @@ fn collect_in_array(
RegisterCluster::Register(r) => Some(r.name.as_str()),
_ => None,
})
.collect::<Vec<_>>()
.join(", ")
));
}
Expand Down Expand Up @@ -1298,7 +1278,6 @@ fn collect_in_cluster(
RegisterCluster::Register(r) => Some(r.name.as_str()),
_ => None,
})
.collect::<Vec<_>>()
.join(", ")
));
}
Expand Down Expand Up @@ -1347,7 +1326,7 @@ fn collect_in_cluster(
if dim > 1 {
dim_increment = offsets[1] - offsets[0];
}
first = Some(rspec.clone());
first = Some(rspec);
}
if !check_offsets(&offsets, dim_increment) {
return Err(anyhow!(
Expand Down
52 changes: 23 additions & 29 deletions src/patch/register.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use anyhow::{anyhow, Context};
use itertools::Itertools;
use svd_parser::svd::{
Access, BitRange, DimElement, EnumeratedValues, Field, FieldInfo, ModifiedWriteValues,
ReadAction, Register, RegisterInfo, Usage, WriteConstraint, WriteConstraintRange,
Expand Down Expand Up @@ -323,10 +324,7 @@ impl RegisterExt for Register {
return Err(anyhow!(
"Could not find any fields to merge {}:{key}. Present fields: {}.`",
self.name,
self.fields()
.map(|f| f.name.as_str())
.collect::<Vec<_>>()
.join(", ")
self.fields().map(|f| f.name.as_str()).join(", ")
));
}
let mut bitwidth = 0;
Expand Down Expand Up @@ -377,10 +375,7 @@ impl RegisterExt for Register {
return Err(anyhow!(
"{}: fields {fspec} not found. Present fields: {}.`",
self.name,
self.fields()
.map(|f| f.name.as_str())
.collect::<Vec<_>>()
.join(", ")
self.fields().map(|f| f.name.as_str()).join(", ")
));
}
fields.sort_by_key(|f| f.bit_range.offset);
Expand Down Expand Up @@ -443,10 +438,7 @@ impl RegisterExt for Register {
return Err(anyhow!(
"Could not find any fields to split {}:{fspec}. Present fields: {}.`",
self.name,
self.fields()
.map(|f| f.name.as_str())
.collect::<Vec<_>>()
.join(", ")
self.fields().map(|f| f.name.as_str()).join(", ")
));
}
(Some(_), Some(_)) => {
Expand Down Expand Up @@ -664,10 +656,7 @@ impl RegisterExt for Register {
// This is a derived enumeratedValues => Try to find the
// original definition to extract its <usage>
let mut derived_enums = self
.fields
.as_ref()
.unwrap()
.iter()
.fields()
.flat_map(|f| f.enumerated_values.iter())
.filter(|e| e.name.as_deref() == Some(d));
let orig_usage = match (derived_enums.next(), derived_enums.next()) {
Expand Down Expand Up @@ -697,21 +686,22 @@ impl RegisterExt for Register {
set_enum(ftag, evs.clone(), orig_usage, true, access)?;
}
} else {
let offsets = self
.iter_fields(fspec)
.map(|f| (f.bit_range.offset, f.name.to_string()))
.collect::<Vec<_>>();
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() {
return Err(anyhow!(
"Could not find field {pname}:{}:{fspec}. Present fields: {}.`",
self.name,
self.fields()
.map(|f| f.name.as_str())
.collect::<Vec<_>>()
.join(", ")
self.fields().map(|f| f.name.as_str()).join(", ")
));
}
let (min_offset, fname) = offsets.iter().min_by_key(|on| on.0).unwrap();
let (min_offset, fname, min_offset_pos) =
offsets.iter().min_by_key(|&on| on.0).unwrap();
let min_pos = offsets.iter().map(|on| on.2).min().unwrap();
let name = make_ev_name(&fname.replace("%s", ""), usage)?;
for ftag in self.iter_fields(fspec) {
let access = ftag.access.or(reg_access).unwrap_or_default();
Expand All @@ -735,6 +725,13 @@ impl RegisterExt for Register {
)?;
}
}
// Move field with derived enums before other
if let Some(fields) = self.fields.as_mut() {
if *min_offset_pos != min_pos {
let f = fields.remove(*min_offset_pos);
fields.insert(min_pos, f);
}
}
}
Ok(())
}
Expand All @@ -752,10 +749,7 @@ impl RegisterExt for Register {
return Err(anyhow!(
"Could not find field {pname}:{}:{fspec}. Present fields: {}.`",
self.name,
self.fields()
.map(|f| f.name.as_str())
.collect::<Vec<_>>()
.join(", ")
self.fields().map(|f| f.name.as_str()).join(", ")
));
}
Ok(())
Expand Down

0 comments on commit 848fe7a

Please sign in to comment.