@@ -6,7 +6,10 @@ use svd_parser::expand::{
6
6
derive_cluster, derive_peripheral, derive_register, BlockPath , Index , RegisterPath ,
7
7
} ;
8
8
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
+ } ;
10
13
use log:: { debug, trace, warn} ;
11
14
use proc_macro2:: { Ident , Punct , Spacing , Span , TokenStream } ;
12
15
use quote:: { quote, ToTokens } ;
@@ -736,18 +739,26 @@ fn check_erc_derive_infos(
736
739
& mut RegisterCluster :: Register ( register) => {
737
740
let info_name = register. fullname ( config. ignore_groups ) . to_string ( ) ;
738
741
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
+ }
740
746
None => None ,
741
747
} ;
742
748
match register {
743
749
Register :: Single ( _) => {
744
750
let ty_name = info_name. to_string ( ) ;
745
751
* derive_info = match explicit_rpath {
746
752
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) => {
749
761
// make sure the matched register isn't already deriving from this register
750
- let root = find_root ( & prev_name, path, index) ?;
751
762
if ty_name == root. name {
752
763
DeriveInfo :: Root
753
764
} else {
@@ -774,63 +785,22 @@ fn check_erc_derive_infos(
774
785
let ty_name = info_name. to_string ( ) ; // keep suffix for regex matching
775
786
* derive_info = match explicit_rpath {
776
787
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
+ ) ?,
834
804
}
835
805
}
836
806
Some ( rpath) => DeriveInfo :: Explicit ( rpath) ,
@@ -848,7 +818,11 @@ fn check_erc_derive_infos(
848
818
Ok ( derive_infos)
849
819
}
850
820
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 ) > {
852
826
let ( dblock, dname) = RegisterPath :: parse_str ( dpath) ;
853
827
let rdpath;
854
828
let reg_path;
@@ -864,29 +838,98 @@ fn find_root(dpath: &str, path: &BlockPath, index: &Index) -> Result<RegisterPat
864
838
. ok_or_else ( || anyhow ! ( "register {} not found" , dpath) ) ?;
865
839
match d. derived_from . as_ref ( ) {
866
840
Some ( dp) => find_root ( dp, & rdpath, index) ,
867
- None => Ok ( reg_path) ,
841
+ None => Ok ( ( ( * d ) . clone ( ) , reg_path) ) ,
868
842
}
869
843
}
870
844
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 > ,
872
848
ty_name : & str ,
849
+ path : & BlockPath ,
850
+ index : & Index ,
873
851
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 > > {
877
853
for prev in ercs_type_info {
878
854
let ( prev_name, prev_regex, prev_erc, _prev_derive_info) = prev;
879
855
if let RegisterCluster :: Register ( _) = prev_erc {
880
856
if let Some ( prev_re) = prev_regex {
881
- // if matched adopt the previous type name
882
857
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
+ }
885
862
}
886
863
}
887
864
}
888
865
}
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 )
890
933
}
891
934
892
935
/// Calculate the size of a Cluster. If it is an array, then the dimensions
0 commit comments