@@ -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+ } ;
1013use log:: { debug, trace, warn} ;
1114use proc_macro2:: { Ident , Punct , Spacing , Span , TokenStream } ;
1215use 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