Skip to content

Commit

Permalink
feat: Remove largest duplicate substr of reg name
Browse files Browse the repository at this point in the history
Problem: Sometimes register names contain duplicate strings that
unnecessarily lengthen them.

Solution: Remove the largest duplicated substring, with a specified
delimiter to avoid removing mere duplicated characters.

Testing: Unit-level test of helper function, integration level test with
SVD file in and expected out.
  • Loading branch information
shaydon-eero committed Jan 10, 2025
1 parent 666ee0d commit 603e2fb
Show file tree
Hide file tree
Showing 4 changed files with 315 additions and 0 deletions.
97 changes: 97 additions & 0 deletions res/remove_duplicate/expected.svd
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<device schemaVersion="1.1"
xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
xs:noNamespaceSchemaLocation="CMSIS-SVD_Schema_1_1.xsd">
<name>STM32L4x2</name>
<peripherals>
<peripheral>
<name>DAC1</name>
<description>Digital-to-analog converter</description>
<groupName>DAC</groupName>
<baseAddress>0x40007400</baseAddress>
<addressBlock>
<offset>0x0</offset>
<size>0x400</size>
<usage>registers</usage>
</addressBlock>
<registers>
<register>
<name>CR</name>
<displayName>CR</displayName>
<addressOffset>0x0</addressOffset>
<size>0x20</size>
<access>read-write</access>
<resetValue>0x00000000</resetValue>
<fields>
<field>
<name>EN1</name>
<description>DAC channel1 enable</description>
<bitOffset>0</bitOffset>
<bitWidth>1</bitWidth>
</field>
</fields>
</register>
</registers>
</peripheral>
<peripheral>
<name>DAC2</name>
<description>Digital-to-analog converter</description>
<groupName>DAC</groupName>
<baseAddress>0x40007400</baseAddress>
<addressBlock>
<offset>0x0</offset>
<size>0x400</size>
<usage>registers</usage>
</addressBlock>
<registers>
<register>
<name>CR</name>
<displayName>CR</displayName>
<description>control register</description>
<addressOffset>0x0</addressOffset>
<size>0x20</size>
<access>read-write</access>
<resetValue>0x00000000</resetValue>
<fields>
<field>
<name>EN1</name>
<description>DAC channel1 enable</description>
<bitOffset>0</bitOffset>
<bitWidth>1</bitWidth>
</field>
</fields>
</register>
</registers>
</peripheral>
<peripheral>
<name>DAC3</name>
<description>Digital-to-analog converter</description>
<groupName>DAC</groupName>
<baseAddress>0x40007400</baseAddress>
<addressBlock>
<offset>0x0</offset>
<size>0x400</size>
<usage>registers</usage>
</addressBlock>
<registers>
<register>
<name>CR</name>
<displayName>CR</displayName>
<description>control register</description>
<addressOffset>0x0</addressOffset>
<size>0x20</size>
<access>read-write</access>
<resetValue>0x00000000</resetValue>
<fields>
<field>
<name>EN1</name>
<description>DAC channel1 enable</description>
<bitOffset>0</bitOffset>
<bitWidth>1</bitWidth>
</field>
</fields>
</register>
</registers>
</peripheral>
</peripherals>
</device>
9 changes: 9 additions & 0 deletions res/remove_duplicate/patch.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
_svd: stm32l4x2.svd

"*":
_remove_duplicate:
- "_"
# "*":
# _remove_duplicate:
# - "_"

97 changes: 97 additions & 0 deletions res/remove_duplicate/stm32l4x2.svd
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<device schemaVersion="1.1"
xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
xs:noNamespaceSchemaLocation="CMSIS-SVD_Schema_1_1.xsd">
<name>STM32L4x2_STM32L4x2</name>
<peripherals>
<peripheral>
<name>DAC1_DAC1</name>
<description>Digital-to-analog converter</description>
<groupName>DAC_DAC</groupName>
<baseAddress>0x40007400</baseAddress>
<addressBlock>
<offset>0x0</offset>
<size>0x400</size>
<usage>registers</usage>
</addressBlock>
<registers>
<register>
<name>CR_CR</name>
<displayName>CR_CR</displayName>
<addressOffset>0x0</addressOffset>
<size>0x20</size>
<access>read-write</access>
<resetValue>0x00000000</resetValue>
<fields>
<field>
<name>EN1_EN1</name>
<description>DAC channel1 enable</description>
<bitOffset>0</bitOffset>
<bitWidth>1</bitWidth>
</field>
</fields>
</register>
</registers>
</peripheral>
<peripheral>
<name>DAC2</name>
<description>Digital-to-analog converter</description>
<groupName>DAC</groupName>
<baseAddress>0x40007400</baseAddress>
<addressBlock>
<offset>0x0</offset>
<size>0x400</size>
<usage>registers</usage>
</addressBlock>
<registers>
<register>
<name>CR</name>
<displayName>CR</displayName>
<description>control register</description>
<addressOffset>0x0</addressOffset>
<size>0x20</size>
<access>read-write</access>
<resetValue>0x00000000</resetValue>
<fields>
<field>
<name>EN1</name>
<description>DAC channel1 enable</description>
<bitOffset>0</bitOffset>
<bitWidth>1</bitWidth>
</field>
</fields>
</register>
</registers>
</peripheral>
<peripheral>
<name>DAC3</name>
<description>Digital-to-analog converter</description>
<groupName>DAC</groupName>
<baseAddress>0x40007400</baseAddress>
<addressBlock>
<offset>0x0</offset>
<size>0x400</size>
<usage>registers</usage>
</addressBlock>
<registers>
<register>
<name>CR</name>
<displayName>CR</displayName>
<description>control register</description>
<addressOffset>0x0</addressOffset>
<size>0x20</size>
<access>read-write</access>
<resetValue>0x00000000</resetValue>
<fields>
<field>
<name>EN1</name>
<description>DAC channel1 enable</description>
<bitOffset>0</bitOffset>
<bitWidth>1</bitWidth>
</field>
</fields>
</register>
</registers>
</peripheral>
</peripherals>
</device>
112 changes: 112 additions & 0 deletions src/patch/peripheral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ pub(crate) trait PeripheralExt: InterruptExt + RegisterBlockExt {
"_cluster",
"_clusters",
"_interrupts",
"_remove_duplicate",
];

/// Work through a peripheral, handling all registers
Expand All @@ -66,6 +67,7 @@ pub(crate) trait ClusterExt: RegisterBlockExt {
"_array",
"_cluster",
"_clusters",
"_remove_duplicate",
];

/// Work through a cluster, handling all registers
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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()?;
Expand Down Expand Up @@ -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()?;
Expand Down Expand Up @@ -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"))
Expand All @@ -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("sar_DWC_mipi_i3c_APB_Slave_DWC_mipi_i3c_block_DEVICE_CTRL_I2C_SLAVE_PRESENT_I2C_SLAVE_PRESENT", '_'), "sar_DWC_mipi_i3c_APB_Slave_DWC_mipi_i3c_block_DEVICE_CTRL_I2C_SLAVE_PRESENT");
assert_eq!(remove_duplicate_sections("DAC1_DAC1", '_'), "DAC1");

Ok(())
}
}

0 comments on commit 603e2fb

Please sign in to comment.