@@ -131,6 +131,9 @@ pub(crate) trait RegisterBlockExt: Name {
131131 /// Get mutable register by name
132132 fn get_mut_reg ( & mut self , name : & str ) -> Option < & mut Register > ;
133133
134+ /// Register/cluster block
135+ fn children ( & self ) -> Option < & Vec < RegisterCluster > > ;
136+
134137 /// Register/cluster block
135138 fn children_mut ( & mut self ) -> Option < & mut Vec < RegisterCluster > > ;
136139
@@ -156,6 +159,16 @@ pub(crate) trait RegisterBlockExt: Name {
156159
157160 fn add_child ( & mut self , child : RegisterCluster ) ;
158161
162+ /// Delete registers and clusters matched by rspec inside ptag
163+ fn delete_child ( & mut self , rcspec : & str ) -> PatchResult {
164+ if let Some ( children) = self . children_mut ( ) {
165+ children. retain ( |rc| !matchname ( rc. name ( ) , rcspec) ) ;
166+ Ok ( ( ) )
167+ } else {
168+ Err ( anyhow ! ( "No registers or clusters" ) )
169+ }
170+ }
171+
159172 /// Delete registers matched by rspec inside ptag
160173 fn delete_register ( & mut self , rspec : & str ) -> PatchResult {
161174 if let Some ( children) = self . children_mut ( ) {
@@ -301,31 +314,38 @@ pub(crate) trait RegisterBlockExt: Name {
301314 todo ! ( )
302315 }
303316
317+ fn modify_child ( & mut self , rcspec : & str , rcmod : & Hash , bpath : & BlockPath ) -> PatchResult {
318+ let ( rcspec, ignore) = rcspec. spec ( ) ;
319+ let rtags = self . iter_registers ( rcspec) . collect :: < Vec < _ > > ( ) ;
320+ if rtags. is_empty ( ) && !ignore {
321+ let ctags = self . iter_clusters ( rcspec) . collect :: < Vec < _ > > ( ) ;
322+ if ctags. is_empty ( ) {
323+ let present = self . present_registers ( ) ;
324+ Err ( anyhow ! (
325+ "Could not find `{bpath}:{rcspec}. Present registers: {present}.`"
326+ ) )
327+ } else {
328+ modify_cluster ( ctags, rcmod)
329+ }
330+ } else {
331+ modify_register ( rtags, rcmod)
332+ }
333+ }
334+
304335 /// Modify rspec inside ptag according to rmod
305- fn modify_register ( & mut self , rspec : & str , rmod : & Hash , _bpath : & BlockPath ) -> PatchResult {
306- let ( rspec, _ignore ) = rspec. spec ( ) ;
336+ fn modify_register ( & mut self , rspec : & str , rmod : & Hash , bpath : & BlockPath ) -> PatchResult {
337+ let ( rspec, ignore ) = rspec. spec ( ) ;
307338 let rtags = self . iter_registers ( rspec) . collect :: < Vec < _ > > ( ) ;
308- // TODO: enable this check
309- /*if rtags.is_empty() && !ignore {
339+ if rtags. is_empty ( ) && !ignore {
310340 let present = self . present_registers ( ) ;
311341 return Err ( anyhow ! (
312342 "Could not find `{bpath}:{rspec}. Present registers: {present}.`"
313343 ) ) ;
314- }*/
315- let register_builder = make_register ( rmod) ?;
316- let dim = make_dim_element ( rmod) ?;
317- for rtag in rtags {
318- modify_dim_element ( rtag, & dim) ?;
319- rtag. modify_from ( register_builder. clone ( ) , VAL_LVL ) ?;
320- if let Some ( "" ) = rmod. get_str ( "access" ) ? {
321- rtag. properties . access = None ;
322- }
323344 }
324- Ok ( ( ) )
345+ modify_register ( rtags , rmod )
325346 }
326347
327348 /// Modify cspec inside ptag according to cmod
328-
329349 fn modify_cluster ( & mut self , cspec : & str , cmod : & Hash , bpath : & BlockPath ) -> PatchResult {
330350 let ( cspec, ignore) = cspec. spec ( ) ;
331351 let ctags = self . iter_clusters ( cspec) . collect :: < Vec < _ > > ( ) ;
@@ -335,13 +355,39 @@ pub(crate) trait RegisterBlockExt: Name {
335355 "Could not find cluster `{bpath}:{cspec}. Present clusters: {present}.`"
336356 ) ) ;
337357 }
338- let cluster_builder = make_cluster ( cmod) ?;
339- let dim = make_dim_element ( cmod) ?;
340- for ctag in ctags {
341- modify_dim_element ( ctag, & dim) ?;
342- ctag. modify_from ( cluster_builder. clone ( ) , VAL_LVL ) ?;
358+ modify_cluster ( ctags, cmod)
359+ }
360+ /// Work through a register or cluster
361+ fn process_child (
362+ & mut self ,
363+ rcspec : & str ,
364+ rcmod : & Hash ,
365+ bpath : & BlockPath ,
366+ config : & Config ,
367+ ) -> PatchResult {
368+ let ( rspec, ignore) = rcspec. spec ( ) ;
369+ let rtags = self . iter_registers ( rspec) . collect :: < Vec < _ > > ( ) ;
370+ if rtags. is_empty ( ) && !ignore {
371+ let ctags = self . iter_clusters ( rspec) . collect :: < Vec < _ > > ( ) ;
372+ if ctags. is_empty ( ) {
373+ let present = self . present_registers ( ) ;
374+ Err ( anyhow ! (
375+ "Could not find `{bpath}:{rspec}. Present registers: {present}.`"
376+ ) )
377+ } else {
378+ for ctag in ctags {
379+ ctag. process ( rcmod, bpath, config)
380+ . with_context ( || format ! ( "Processing cluster `{}`" , ctag. name) ) ?;
381+ }
382+ Ok ( ( ) )
383+ }
384+ } else {
385+ for rtag in rtags {
386+ rtag. process ( rcmod, bpath, config)
387+ . with_context ( || format ! ( "Processing register `{}`" , rtag. name) ) ?;
388+ }
389+ Ok ( ( ) )
343390 }
344- Ok ( ( ) )
345391 }
346392 /// Work through a register, handling all fields
347393 fn process_register (
@@ -507,6 +553,29 @@ pub(crate) trait RegisterBlockExt: Name {
507553 }
508554}
509555
556+ fn modify_register ( rtags : Vec < & mut Register > , rmod : & Hash ) -> PatchResult {
557+ let register_builder = make_register ( rmod) ?;
558+ let dim = make_dim_element ( rmod) ?;
559+ for rtag in rtags {
560+ modify_dim_element ( rtag, & dim) ?;
561+ rtag. modify_from ( register_builder. clone ( ) , VAL_LVL ) ?;
562+ if let Some ( "" ) = rmod. get_str ( "access" ) ? {
563+ rtag. properties . access = None ;
564+ }
565+ }
566+ Ok ( ( ) )
567+ }
568+
569+ fn modify_cluster ( ctags : Vec < & mut Cluster > , cmod : & Hash ) -> PatchResult {
570+ let cluster_builder = make_cluster ( cmod) ?;
571+ let dim = make_dim_element ( cmod) ?;
572+ for ctag in ctags {
573+ modify_dim_element ( ctag, & dim) ?;
574+ ctag. modify_from ( cluster_builder. clone ( ) , VAL_LVL ) ?;
575+ }
576+ Ok ( ( ) )
577+ }
578+
510579impl RegisterBlockExt for Peripheral {
511580 const RB_TYPE : & ' static str = "peripheral" ;
512581
@@ -531,6 +600,9 @@ impl RegisterBlockExt for Peripheral {
531600 fn get_mut_reg ( & mut self , name : & str ) -> Option < & mut Register > {
532601 self . get_mut_register ( name)
533602 }
603+ fn children ( & self ) -> Option < & Vec < RegisterCluster > > {
604+ self . registers . as_ref ( )
605+ }
534606 fn children_mut ( & mut self ) -> Option < & mut Vec < RegisterCluster > > {
535607 self . registers . as_mut ( )
536608 }
@@ -566,6 +638,9 @@ impl RegisterBlockExt for Cluster {
566638 fn get_mut_reg ( & mut self , name : & str ) -> Option < & mut Register > {
567639 self . get_mut_register ( name)
568640 }
641+ fn children ( & self ) -> Option < & Vec < RegisterCluster > > {
642+ Some ( & self . children )
643+ }
569644 fn children_mut ( & mut self ) -> Option < & mut Vec < RegisterCluster > > {
570645 Some ( & mut self . children )
571646 }
@@ -617,15 +692,17 @@ impl PeripheralExt for Peripheral {
617692 // Handle deletions
618693 if let Some ( deletions) = pmod. get_yaml ( "_delete" ) {
619694 match deletions {
620- Yaml :: String ( rspec) => {
621- self . delete_register ( rspec)
622- . with_context ( || format ! ( "Deleting registers matched to `{rspec}`" ) ) ?;
695+ Yaml :: String ( rcspec) => {
696+ self . delete_child ( rcspec) . with_context ( || {
697+ format ! ( "Deleting registers and clusters matched to `{rcspec}`" )
698+ } ) ?;
623699 }
624700 Yaml :: Array ( deletions) => {
625- for rspec in deletions {
626- let rspec = rspec. str ( ) ?;
627- self . delete_register ( rspec)
628- . with_context ( || format ! ( "Deleting registers matched to `{rspec}`" ) ) ?;
701+ for rcspec in deletions {
702+ let rcspec = rcspec. str ( ) ?;
703+ self . delete_child ( rcspec) . with_context ( || {
704+ format ! ( "Deleting registers and clusters matched to `{rcspec}`" )
705+ } ) ?;
629706 }
630707 }
631708 Yaml :: Hash ( deletions) => {
@@ -716,16 +793,16 @@ impl PeripheralExt for Peripheral {
716793 } ) ?;
717794 }
718795 }
719- "_cluster " => {
796+ "_clusters " => {
720797 for ( cspec, val) in rmod {
721798 let cspec = cspec. str ( ) ?;
722799 self . modify_cluster ( cspec, val. hash ( ) ?, & ppath)
723800 . with_context ( || format ! ( "Modifying clusters matched to `{cspec}`" ) ) ?;
724801 }
725802 }
726- rspec => self
727- . modify_register ( rspec , rmod , & ppath )
728- . with_context ( || format ! ( "Modifying registers matched to `{rspec}`" ) ) ?,
803+ rcspec => self . modify_child ( rcspec , rmod , & ppath ) . with_context ( || {
804+ format ! ( "Modifying registers or clusters matched to `{rcspec}`" )
805+ } ) ?,
729806 }
730807 }
731808
@@ -795,14 +872,14 @@ impl PeripheralExt for Peripheral {
795872 }
796873 }
797874
798- // Handle registers
799- for ( rspec , register ) in pmod {
800- let rspec = rspec . str ( ) ?;
801- if Self :: KEYWORDS . contains ( & rspec ) {
875+ // Handle registers or clusters
876+ for ( rcspec , rcmod ) in pmod {
877+ let rcspec = rcspec . str ( ) ?;
878+ if Self :: KEYWORDS . contains ( & rcspec ) {
802879 continue ;
803880 }
804- self . process_register ( rspec , register . hash ( ) ?, & ppath, config)
805- . with_context ( || format ! ( "According to `{rspec }`" ) ) ?;
881+ self . process_child ( rcspec , rcmod . hash ( ) ?, & ppath, config)
882+ . with_context ( || format ! ( "According to `{rcspec }`" ) ) ?;
806883 }
807884
808885 // Expand register arrays
@@ -874,15 +951,17 @@ impl ClusterExt for Cluster {
874951 // Handle deletions
875952 if let Some ( deletions) = cmod. get_yaml ( "_delete" ) {
876953 match deletions {
877- Yaml :: String ( rspec) => {
878- self . delete_register ( rspec)
879- . with_context ( || format ! ( "Deleting registers matched to `{rspec}`" ) ) ?;
954+ Yaml :: String ( rcspec) => {
955+ self . delete_child ( rcspec) . with_context ( || {
956+ format ! ( "Deleting registers and clusters matched to `{rcspec}`" )
957+ } ) ?;
880958 }
881959 Yaml :: Array ( deletions) => {
882- for rspec in deletions {
883- let rspec = rspec. str ( ) ?;
884- self . delete_register ( rspec)
885- . with_context ( || format ! ( "Deleting registers matched to `{rspec}`" ) ) ?;
960+ for rcspec in deletions {
961+ let rcspec = rcspec. str ( ) ?;
962+ self . delete_child ( rcspec) . with_context ( || {
963+ format ! ( "Deleting registers and clusters matched to `{rcspec}`" )
964+ } ) ?;
886965 }
887966 }
888967 Yaml :: Hash ( deletions) => {
@@ -963,16 +1042,16 @@ impl ClusterExt for Cluster {
9631042 . with_context ( || format ! ( "Modifying registers matched to `{rspec}`" ) ) ?;
9641043 }
9651044 }
966- "_cluster " => {
1045+ "_clusters " => {
9671046 for ( cspec, val) in rmod {
9681047 let cspec = cspec. str ( ) ?;
9691048 self . modify_cluster ( cspec, val. hash ( ) ?, & cpath)
9701049 . with_context ( || format ! ( "Modifying clusters matched to `{cspec}`" ) ) ?;
9711050 }
9721051 }
973- rspec => self
974- . modify_register ( rspec , rmod , & cpath )
975- . with_context ( || format ! ( "Modifying registers matched to `{rspec}`" ) ) ?,
1052+ rcspec => self . modify_child ( rcspec , rmod , & cpath ) . with_context ( || {
1053+ format ! ( "Modifying registers or clusters matched to `{rcspec}`" )
1054+ } ) ?,
9761055 }
9771056 }
9781057
@@ -1050,14 +1129,14 @@ impl ClusterExt for Cluster {
10501129 . with_context ( || format ! ( "According to `{cspec}`" ) ) ?;
10511130 }
10521131
1053- // Handle registers
1054- for ( rspec , register ) in cmod {
1055- let rspec = rspec . str ( ) ?;
1056- if Self :: KEYWORDS . contains ( & rspec ) {
1132+ // Handle registers or clusters
1133+ for ( rcspec , rcmod ) in cmod {
1134+ let rcspec = rcspec . str ( ) ?;
1135+ if Self :: KEYWORDS . contains ( & rcspec ) {
10571136 continue ;
10581137 }
1059- self . process_register ( rspec , register . hash ( ) ?, & cpath, config)
1060- . with_context ( || format ! ( "According to `{rspec }`" ) ) ?;
1138+ self . process_child ( rcspec , rcmod . hash ( ) ?, & cpath, config)
1139+ . with_context ( || format ! ( "According to `{rcspec }`" ) ) ?;
10611140 }
10621141
10631142 self . post_process ( cmod, parent, config)
0 commit comments