diff --git a/res/remove_duplicate/expected.svd b/res/remove_duplicate/expected.svd
new file mode 100644
index 00000000..3ff0ff36
--- /dev/null
+++ b/res/remove_duplicate/expected.svd
@@ -0,0 +1,97 @@
+
+
+ STM32L4x2
+
+
+ DAC1
+ Digital-to-analog converter
+ DAC
+ 0x40007400
+
+ 0x0
+ 0x400
+ registers
+
+
+
+ CR
+ CR
+ 0x0
+ 0x20
+ read-write
+ 0x00000000
+
+
+ EN1
+ DAC channel1 enable
+ 0
+ 1
+
+
+
+
+
+
+ DAC2
+ Digital-to-analog converter
+ DAC
+ 0x40007400
+
+ 0x0
+ 0x400
+ registers
+
+
+
+ CR
+ CR
+ control register
+ 0x0
+ 0x20
+ read-write
+ 0x00000000
+
+
+ EN1
+ DAC channel1 enable
+ 0
+ 1
+
+
+
+
+
+
+ DAC3
+ Digital-to-analog converter
+ DAC
+ 0x40007400
+
+ 0x0
+ 0x400
+ registers
+
+
+
+ CR
+ CR
+ control register
+ 0x0
+ 0x20
+ read-write
+ 0x00000000
+
+
+ EN1
+ DAC channel1 enable
+ 0
+ 1
+
+
+
+
+
+
+
diff --git a/res/remove_duplicate/patch.yaml b/res/remove_duplicate/patch.yaml
new file mode 100644
index 00000000..004e8f45
--- /dev/null
+++ b/res/remove_duplicate/patch.yaml
@@ -0,0 +1,9 @@
+_svd: stm32l4x2.svd
+
+"*":
+ _remove_duplicate:
+ - "_"
+ # "*":
+ # _remove_duplicate:
+ # - "_"
+
diff --git a/res/remove_duplicate/stm32l4x2.svd b/res/remove_duplicate/stm32l4x2.svd
new file mode 100644
index 00000000..3ff78800
--- /dev/null
+++ b/res/remove_duplicate/stm32l4x2.svd
@@ -0,0 +1,97 @@
+
+
+ STM32L4x2_STM32L4x2
+
+
+ DAC1_DAC1
+ Digital-to-analog converter
+ DAC_DAC
+ 0x40007400
+
+ 0x0
+ 0x400
+ registers
+
+
+
+ CR_CR
+ CR_CR
+ 0x0
+ 0x20
+ read-write
+ 0x00000000
+
+
+ EN1_EN1
+ DAC channel1 enable
+ 0
+ 1
+
+
+
+
+
+
+ DAC2
+ Digital-to-analog converter
+ DAC
+ 0x40007400
+
+ 0x0
+ 0x400
+ registers
+
+
+
+ CR
+ CR
+ control register
+ 0x0
+ 0x20
+ read-write
+ 0x00000000
+
+
+ EN1
+ DAC channel1 enable
+ 0
+ 1
+
+
+
+
+
+
+ DAC3
+ Digital-to-analog converter
+ DAC
+ 0x40007400
+
+ 0x0
+ 0x400
+ registers
+
+
+
+ CR
+ CR
+ control register
+ 0x0
+ 0x20
+ read-write
+ 0x00000000
+
+
+ EN1
+ DAC channel1 enable
+ 0
+ 1
+
+
+
+
+
+
+
diff --git a/src/patch/peripheral.rs b/src/patch/peripheral.rs
index 8a168203..5cab4c19 100644
--- a/src/patch/peripheral.rs
+++ b/src/patch/peripheral.rs
@@ -42,6 +42,7 @@ pub(crate) trait PeripheralExt: InterruptExt + RegisterBlockExt {
"_cluster",
"_clusters",
"_interrupts",
+ "_remove_duplicate",
];
/// Work through a peripheral, handling all registers
@@ -66,6 +67,7 @@ pub(crate) trait ClusterExt: RegisterBlockExt {
"_array",
"_cluster",
"_clusters",
+ "_remove_duplicate",
];
/// Work through a cluster, handling all registers
@@ -474,6 +476,35 @@ pub(crate) trait RegisterBlockExt: Name {
Ok(())
}
+ /// Delete substring from within register names if there is any repeated data inside ptag
+ fn remove_duplicate(&mut self, delimiter: char) -> PatchResult {
+ // Define a regex to match duplicated groups of underscore-separated words
+ // As it turns out, this is not viable since backreferences are not supported by Regex in Rust
+ // let re = Regex::new(r"(?i)(\b(?:\w+_)+\w+)_\1").unwrap();
+
+ for rtag in self.regs_mut() {
+ // Remove the offending repreated string from register name
+ rtag.name = remove_duplicate_sections(&rtag.name, delimiter);
+
+ if let Some(dname) = rtag.display_name.as_mut() {
+ *dname = remove_duplicate_sections(dname, delimiter);
+ }
+ if let Some(name) = rtag.alternate_register.as_mut() {
+ *name = remove_duplicate_sections(name, delimiter);
+ }
+ }
+ for ctag in self.clstrs_mut() {
+ ctag.name = remove_duplicate_sections(&ctag.name, delimiter);
+ if let Some(dname) = ctag.header_struct_name.as_mut() {
+ *dname = remove_duplicate_sections(dname, delimiter);
+ }
+ if let Some(name) = ctag.alternate_cluster.as_mut() {
+ *name = remove_duplicate_sections(name, delimiter);
+ }
+ }
+ Ok(())
+ }
+
/// Delete substring from the beginning of register names inside ptag
fn strip_start(&mut self, prefix: &str) -> PatchResult {
let len = prefix.len();
@@ -1066,6 +1097,23 @@ impl PeripheralExt for Peripheral {
.with_context(|| format!("Stripping suffix `{suffix}` from register names"))?;
}
+ // Handle duplicate removal
+ for delimiter in pmod.str_vec_iter("_remove_duplicate")? {
+ println!("I'M AT LEAST TRYING SOMETHING!!!");
+ if let Some(delimiter) = delimiter.chars().nth(0) {
+ self.remove_duplicate(delimiter).with_context(|| {
+ format!(
+ "Removing largest duplicate substring conjoined by delimiter {}",
+ delimiter
+ )
+ })?;
+ } else {
+ return Err(anyhow!(
+ "`_remove_duplicate` requires a delimiter of length 1 to break name up by"
+ ));
+ }
+ }
+
// Handle modifications
for (rspec, rmod) in pmod.hash_iter("_modify") {
let rmod = rmod.hash()?;
@@ -1374,6 +1422,23 @@ impl ClusterExt for Cluster {
.with_context(|| format!("Stripping suffix `{suffix}` from register names"))?;
}
+ // Handle duplicate removal
+ for delimiter in cmod.str_vec_iter("_remove_duplicate")? {
+ println!("I'M AT LEAST TRYING SOMETHING!!!");
+ if let Some(delimiter) = delimiter.chars().nth(0) {
+ self.remove_duplicate(delimiter).with_context(|| {
+ format!(
+ "Removing largest duplicate substring conjoined by delimiter {}",
+ delimiter
+ )
+ })?;
+ } else {
+ return Err(anyhow!(
+ "`_remove_duplicate` requires a delimiter of length 1 to break name up by"
+ ));
+ }
+ }
+
// Handle modifications
for (rspec, rmod) in cmod.hash_iter("_modify") {
let rmod = rmod.hash()?;
@@ -1838,12 +1903,46 @@ fn collect_in_cluster(
Ok(())
}
+/// Remove largest adjacent section of the string that is duplicated
+fn remove_duplicate_sections(input: &str, delimiter: char) -> String {
+ let parts: Vec<&str> = input.split(delimiter).collect(); // Split the input by underscores
+ let mut result = Vec::new(); // Store the final result
+ let mut window_size = parts.len() / 2;
+
+ while window_size > 0 {
+ // Sliding window size
+ let mut i = 0;
+
+ while i + (2 * window_size) <= parts.len() {
+ if parts[i..i + window_size] == parts[i + window_size..i + (2 * window_size)] {
+ result.extend_from_slice(&parts[0..i]);
+ result.extend_from_slice(&parts[i + window_size..]);
+ println!(
+ "Found dupe! {} will be shortened to {} over delimiter {}...",
+ input,
+ result.join(&delimiter.to_string()),
+ delimiter
+ );
+ return result.join(&delimiter.to_string());
+ }
+ i += 1;
+ }
+
+ window_size -= 1;
+ }
+
+ // Rejoin the original input if no changes are required
+ parts.join(&delimiter.to_string())
+}
+
#[cfg(test)]
mod tests {
use crate::test_utils;
use anyhow::Result;
use std::path::Path;
+ use super::remove_duplicate_sections;
+
#[test]
fn cluster() -> Result<()> {
test_utils::test_expected(Path::new("cluster"))
@@ -1853,4 +1952,17 @@ mod tests {
fn cross_cluster_derive() -> Result<()> {
test_utils::test_expected(Path::new("cross_cluster_derive"))
}
+
+ #[test]
+ fn remove_duplicate() -> Result<()> {
+ test_utils::test_expected(Path::new("remove_duplicate"))
+ }
+
+ #[test]
+ fn test_remove_duplicate_sections() -> Result<()> {
+ assert_eq!(remove_duplicate_sections("some_random_long_name_that_serves_as_a_representative_prefix_DEVICE_CTRL_COMMS_IP_PERIPH_PRESENT_COMMS_IP_PERIPH_PRESENT", '_'), "some_random_long_name_that_serves_as_a_representative_prefix_DEVICE_CTRL_COMMS_IP_PERIPH_PRESENT");
+ assert_eq!(remove_duplicate_sections("DAC1_DAC1", '_'), "DAC1");
+
+ Ok(())
+ }
}