Skip to content

Commit 25d4b15

Browse files
bors[bot]n8tlarsen
andauthored
Merge #698
698: Compare contents before deriving r=burrbull,emilgardis a=n8tlarsen Closes #660. Compares register properties and fields of regex-matched register names to decide if implicitly deriving is possible. I could use some help with the CI integration for vendor Renesas. See [ra-rs/ra](https://github.com/ra-rs/ra) for SVDs. Co-authored-by: n8tlarsen <[email protected]>
2 parents e80b309 + cdc3a9d commit 25d4b15

File tree

2 files changed

+116
-73
lines changed

2 files changed

+116
-73
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
1414
- Test patched STM32
1515
- simplify ci strategy
1616
- Fix generated code for MSP430 atomics
17-
- Add handling for disjoint arrays
17+
- Add handling for disjoint register arrays and validation of derives
1818

1919
## [v0.27.1] - 2022-10-25
2020

src/generate/peripheral.rs

Lines changed: 115 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ use svd_parser::expand::{
66
derive_cluster, derive_peripheral, derive_register, BlockPath, Index, RegisterPath,
77
};
88

9-
use crate::svd::{array::names, Cluster, ClusterInfo, Peripheral, Register, RegisterCluster};
9+
use crate::svd::{
10+
array::names, Cluster, ClusterInfo, MaybeArray, Peripheral, Register, RegisterCluster,
11+
RegisterInfo,
12+
};
1013
use log::{debug, trace, warn};
1114
use proc_macro2::{Ident, Punct, Spacing, Span, TokenStream};
1215
use quote::{quote, ToTokens};
@@ -736,18 +739,26 @@ fn check_erc_derive_infos(
736739
&mut RegisterCluster::Register(register) => {
737740
let info_name = register.fullname(config.ignore_groups).to_string();
738741
let explicit_rpath = match &mut register.derived_from.clone() {
739-
Some(dpath) => Some(find_root(&dpath, path, index)?),
742+
Some(dpath) => {
743+
let (_, root) = find_root(&dpath, path, index)?;
744+
Some(root)
745+
}
740746
None => None,
741747
};
742748
match register {
743749
Register::Single(_) => {
744750
let ty_name = info_name.to_string();
745751
*derive_info = match explicit_rpath {
746752
None => {
747-
match regex_against_prev(&ty_name, &ercs_type_info) {
748-
Some(prev_name) => {
753+
match compare_this_against_prev(
754+
&register,
755+
&ty_name,
756+
path,
757+
index,
758+
&ercs_type_info,
759+
)? {
760+
Some(root) => {
749761
// make sure the matched register isn't already deriving from this register
750-
let root = find_root(&prev_name, path, index)?;
751762
if ty_name == root.name {
752763
DeriveInfo::Root
753764
} else {
@@ -774,63 +785,22 @@ fn check_erc_derive_infos(
774785
let ty_name = info_name.to_string(); // keep suffix for regex matching
775786
*derive_info = match explicit_rpath {
776787
None => {
777-
match regex_against_prev(&ty_name, &ercs_type_info) {
778-
Some(prev_name) => {
779-
let root = find_root(&prev_name, path, index)?;
780-
DeriveInfo::Implicit(root)
781-
}
782-
None => {
783-
let mut my_derive_info = DeriveInfo::Root;
784-
// Check this type regex against previous names
785-
for prev in &mut ercs_type_info {
786-
let (
787-
prev_name,
788-
_prev_regex,
789-
prev_erc,
790-
prev_derive_info,
791-
) = prev;
792-
if let RegisterCluster::Register(prev_reg) = prev_erc {
793-
if let Register::Array(..) = prev_reg {
794-
// Arrays had a chance to match above
795-
continue;
796-
}
797-
if re.is_match(&prev_name) {
798-
let loop_derive_info = match prev_derive_info {
799-
DeriveInfo::Root => {
800-
let implicit_rpath =
801-
find_root(&ty_name, path, index)?;
802-
**prev_derive_info =
803-
DeriveInfo::Implicit(implicit_rpath);
804-
DeriveInfo::Root
805-
}
806-
DeriveInfo::Explicit(rpath) => {
807-
let implicit_rpath = find_root(
808-
&rpath.name,
809-
path,
810-
index,
811-
)?;
812-
DeriveInfo::Implicit(implicit_rpath)
813-
}
814-
DeriveInfo::Implicit(rpath) => {
815-
DeriveInfo::Implicit(rpath.clone())
816-
}
817-
DeriveInfo::Cluster => {
818-
return Err(anyhow!(
819-
"register {} derive_infoesented as cluster",
820-
register.name
821-
))
822-
}
823-
};
824-
if let DeriveInfo::Root = my_derive_info {
825-
if my_derive_info != loop_derive_info {
826-
my_derive_info = loop_derive_info;
827-
}
828-
}
829-
}
830-
}
831-
}
832-
my_derive_info
833-
}
788+
match compare_this_against_prev(
789+
&register,
790+
&ty_name,
791+
path,
792+
index,
793+
&ercs_type_info,
794+
)? {
795+
Some(root) => DeriveInfo::Implicit(root),
796+
None => compare_prev_against_this(
797+
&register,
798+
&ty_name,
799+
&re,
800+
path,
801+
index,
802+
&mut ercs_type_info,
803+
)?,
834804
}
835805
}
836806
Some(rpath) => DeriveInfo::Explicit(rpath),
@@ -848,7 +818,11 @@ fn check_erc_derive_infos(
848818
Ok(derive_infos)
849819
}
850820

851-
fn find_root(dpath: &str, path: &BlockPath, index: &Index) -> Result<RegisterPath> {
821+
fn find_root(
822+
dpath: &str,
823+
path: &BlockPath,
824+
index: &Index,
825+
) -> Result<(MaybeArray<RegisterInfo>, RegisterPath)> {
852826
let (dblock, dname) = RegisterPath::parse_str(dpath);
853827
let rdpath;
854828
let reg_path;
@@ -864,29 +838,98 @@ fn find_root(dpath: &str, path: &BlockPath, index: &Index) -> Result<RegisterPat
864838
.ok_or_else(|| anyhow!("register {} not found", dpath))?;
865839
match d.derived_from.as_ref() {
866840
Some(dp) => find_root(dp, &rdpath, index),
867-
None => Ok(reg_path),
841+
None => Ok(((*d).clone(), reg_path)),
868842
}
869843
}
870844

871-
fn regex_against_prev(
845+
/// Compare the given type name against previous regexs, then inspect fields
846+
fn compare_this_against_prev(
847+
reg: &MaybeArray<RegisterInfo>,
872848
ty_name: &str,
849+
path: &BlockPath,
850+
index: &Index,
873851
ercs_type_info: &Vec<(String, Option<Regex>, &RegisterCluster, &mut DeriveInfo)>,
874-
) -> Option<String> {
875-
let mut prev_match = None;
876-
// Check this type name against previous regexs
852+
) -> Result<Option<RegisterPath>> {
877853
for prev in ercs_type_info {
878854
let (prev_name, prev_regex, prev_erc, _prev_derive_info) = prev;
879855
if let RegisterCluster::Register(_) = prev_erc {
880856
if let Some(prev_re) = prev_regex {
881-
// if matched adopt the previous type name
882857
if prev_re.is_match(&ty_name) {
883-
prev_match = Some(prev_name.to_string());
884-
break;
858+
let (source_reg, rpath) = find_root(&prev_name, path, index)?;
859+
if is_derivable(&source_reg, &reg) {
860+
return Ok(Some(rpath));
861+
}
885862
}
886863
}
887864
}
888865
}
889-
prev_match
866+
Ok(None)
867+
}
868+
869+
/// Compare the given type name against previous regexs, then inspect fields
870+
fn compare_prev_against_this(
871+
reg: &MaybeArray<RegisterInfo>,
872+
ty_name: &String,
873+
re: &regex::Regex,
874+
path: &BlockPath,
875+
index: &Index,
876+
ercs_type_info: &mut Vec<(String, Option<Regex>, &RegisterCluster, &mut DeriveInfo)>,
877+
) -> Result<DeriveInfo> {
878+
let mut my_derive_info = DeriveInfo::Root;
879+
// Check this type regex against previous names
880+
for prev in ercs_type_info {
881+
let (prev_name, _prev_regex, prev_erc, prev_derive_info) = prev;
882+
if let RegisterCluster::Register(prev_reg) = prev_erc {
883+
if let Register::Array(..) = prev_reg {
884+
// Arrays are covered with compare_this_against_prev
885+
continue;
886+
}
887+
if re.is_match(&prev_name) {
888+
let loop_derive_info = match prev_derive_info {
889+
DeriveInfo::Root => {
890+
// Get the RegisterPath for reg
891+
let (_, implicit_rpath) = find_root(&ty_name, path, index)?;
892+
if is_derivable(&prev_reg, &reg) {
893+
**prev_derive_info = DeriveInfo::Implicit(implicit_rpath);
894+
}
895+
DeriveInfo::Root
896+
}
897+
DeriveInfo::Explicit(rpath) => {
898+
let (source_reg, implicit_rpath) = find_root(&rpath.name, path, index)?;
899+
if is_derivable(&source_reg, reg) {
900+
DeriveInfo::Implicit(implicit_rpath)
901+
} else {
902+
DeriveInfo::Root
903+
}
904+
}
905+
DeriveInfo::Implicit(rpath) => {
906+
let (source_reg, _) = find_root(&rpath.name, path, index)?;
907+
if is_derivable(&source_reg, reg) {
908+
DeriveInfo::Implicit(rpath.clone())
909+
} else {
910+
DeriveInfo::Root
911+
}
912+
}
913+
DeriveInfo::Cluster => {
914+
return Err(anyhow!("register {} represented as cluster", prev_reg.name))
915+
}
916+
};
917+
if let DeriveInfo::Root = my_derive_info {
918+
if my_derive_info != loop_derive_info {
919+
my_derive_info = loop_derive_info;
920+
}
921+
}
922+
}
923+
}
924+
}
925+
Ok(my_derive_info)
926+
}
927+
928+
fn is_derivable(
929+
source_reg: &MaybeArray<RegisterInfo>,
930+
target_reg: &MaybeArray<RegisterInfo>,
931+
) -> bool {
932+
(source_reg.properties == target_reg.properties) && (source_reg.fields == target_reg.fields)
890933
}
891934

892935
/// Calculate the size of a Cluster. If it is an array, then the dimensions

0 commit comments

Comments
 (0)