@@ -12,8 +12,8 @@ use quote::{quote, ToTokens};
12
12
use syn:: { parse_str, Token } ;
13
13
14
14
use crate :: util:: {
15
- self , handle_cluster_error, handle_reg_error, Config , FullName , ToSanitizedSnakeCase ,
16
- ToSanitizedUpperCase , BITS_PER_BYTE ,
15
+ self , handle_cluster_error, handle_reg_error, unsuffixed , Config , FullName ,
16
+ ToSanitizedSnakeCase , ToSanitizedUpperCase , BITS_PER_BYTE ,
17
17
} ;
18
18
use anyhow:: { anyhow, bail, Context , Result } ;
19
19
@@ -219,6 +219,7 @@ struct RegisterBlockField {
219
219
description : String ,
220
220
offset : u32 ,
221
221
size : u32 ,
222
+ accessors : Option < TokenStream > ,
222
223
}
223
224
224
225
#[ derive( Clone , Debug ) ]
@@ -435,6 +436,23 @@ impl FieldRegions {
435
436
}
436
437
}
437
438
439
+ fn make_comment ( size : u32 , offset : u32 , description : & str ) -> String {
440
+ if size > 32 {
441
+ format ! (
442
+ "0x{:02x}..0x{:02x} - {}" ,
443
+ offset,
444
+ offset + size / 8 ,
445
+ util:: escape_brackets( & util:: respace( description) ) ,
446
+ )
447
+ } else {
448
+ format ! (
449
+ "0x{:02x} - {}" ,
450
+ offset,
451
+ util:: escape_brackets( & util:: respace( description) ) ,
452
+ )
453
+ }
454
+ }
455
+
438
456
fn register_or_cluster_block (
439
457
ercs : & [ RegisterCluster ] ,
440
458
defs : & RegisterProperties ,
@@ -443,7 +461,6 @@ fn register_or_cluster_block(
443
461
) -> Result < TokenStream > {
444
462
let mut rbfs = TokenStream :: new ( ) ;
445
463
let mut accessors = TokenStream :: new ( ) ;
446
- let mut have_accessors = false ;
447
464
448
465
let ercs_expanded = expand ( ercs, defs, name, config)
449
466
. with_context ( || "Could not expand register or cluster block" ) ?;
@@ -453,6 +470,9 @@ fn register_or_cluster_block(
453
470
454
471
for reg_block_field in & ercs_expanded {
455
472
regions. add ( reg_block_field) ?;
473
+ if let Some ( ts) = & reg_block_field. accessors {
474
+ accessors. extend ( ts. clone ( ) ) ;
475
+ }
456
476
}
457
477
458
478
// We need to compute the idents of each register/union block first to make sure no conflicts exists.
@@ -476,26 +496,16 @@ fn register_or_cluster_block(
476
496
let is_region_a_union = region. is_union ( ) ;
477
497
478
498
for reg_block_field in & region. rbfs {
479
- let comment = if reg_block_field. size > 32 {
480
- format ! (
481
- "0x{:02x}..0x{:02x} - {}" ,
482
- reg_block_field. offset,
483
- reg_block_field. offset + reg_block_field. size / 8 ,
484
- util:: escape_brackets( util:: respace( & reg_block_field. description) . as_ref( ) ) ,
485
- )
486
- } else {
487
- format ! (
488
- "0x{:02x} - {}" ,
489
- reg_block_field. offset,
490
- util:: escape_brackets( util:: respace( & reg_block_field. description) . as_ref( ) ) ,
491
- )
492
- } ;
499
+ let comment = make_comment (
500
+ reg_block_field. size ,
501
+ reg_block_field. offset ,
502
+ & reg_block_field. description ,
503
+ ) ;
493
504
494
505
if is_region_a_union {
495
506
let name = & reg_block_field. field . ident ;
496
507
let ty = & reg_block_field. field . ty ;
497
508
let offset = reg_block_field. offset as usize ;
498
- have_accessors = true ;
499
509
accessors. extend ( quote ! {
500
510
#[ doc = #comment]
501
511
#[ inline( always) ]
@@ -556,7 +566,7 @@ fn register_or_cluster_block(
556
566
span,
557
567
) ;
558
568
559
- let accessors = if have_accessors {
569
+ let accessors = if !accessors . is_empty ( ) {
560
570
quote ! {
561
571
impl #name {
562
572
#accessors
@@ -700,6 +710,7 @@ fn expand_cluster(
700
710
description : info. description . as_ref ( ) . unwrap_or ( & info. name ) . into ( ) ,
701
711
offset : info. address_offset ,
702
712
size : cluster_size,
713
+ accessors : None ,
703
714
} ) ,
704
715
Cluster :: Array ( info, array_info) => {
705
716
let sequential_addresses = cluster_size == array_info. dim_increment * BITS_PER_BYTE ;
@@ -720,15 +731,51 @@ fn expand_cluster(
720
731
false => true ,
721
732
} ;
722
733
723
- let array_convertible = sequential_indexes && sequential_addresses && convert_list;
734
+ let array_convertible = sequential_addresses && convert_list;
724
735
725
736
if array_convertible {
726
- cluster_expanded. push ( RegisterBlockField {
727
- field : convert_svd_cluster ( cluster, name) ?,
728
- description : info. description . as_ref ( ) . unwrap_or ( & info. name ) . into ( ) ,
729
- offset : info. address_offset ,
730
- size : cluster_size * array_info. dim ,
731
- } ) ;
737
+ if sequential_indexes {
738
+ cluster_expanded. push ( RegisterBlockField {
739
+ field : convert_svd_cluster ( cluster, name) ?,
740
+ description : info. description . as_ref ( ) . unwrap_or ( & info. name ) . into ( ) ,
741
+ offset : info. address_offset ,
742
+ size : cluster_size * array_info. dim ,
743
+ accessors : None ,
744
+ } ) ;
745
+ } else {
746
+ let mut accessors = TokenStream :: new ( ) ;
747
+ let nb_name = util:: replace_suffix ( & info. name , "" ) ;
748
+ let ty = name_to_wrapped_ty ( & nb_name, name) ?;
749
+ let nb_name_cs =
750
+ Ident :: new ( & nb_name. to_sanitized_snake_case ( ) , Span :: call_site ( ) ) ;
751
+ let description = info. description . as_ref ( ) . unwrap_or ( & info. name ) ;
752
+ for ( i, idx) in array_info. indexes ( ) . enumerate ( ) {
753
+ let idx_name = Ident :: new (
754
+ & util:: replace_suffix ( & info. name , & idx) . to_sanitized_snake_case ( ) ,
755
+ Span :: call_site ( ) ,
756
+ ) ;
757
+ let comment = make_comment (
758
+ cluster_size,
759
+ info. address_offset + ( i as u32 ) * cluster_size / 8 ,
760
+ description,
761
+ ) ;
762
+ let i = unsuffixed ( i as _ ) ;
763
+ accessors. extend ( quote ! {
764
+ #[ doc = #comment]
765
+ #[ inline( always) ]
766
+ pub fn #idx_name( & self ) -> & #ty {
767
+ & self . #nb_name_cs[ #i]
768
+ }
769
+ } ) ;
770
+ }
771
+ cluster_expanded. push ( RegisterBlockField {
772
+ field : convert_svd_cluster ( cluster, name) ?,
773
+ description : description. into ( ) ,
774
+ offset : info. address_offset ,
775
+ size : cluster_size * array_info. dim ,
776
+ accessors : Some ( accessors) ,
777
+ } ) ;
778
+ }
732
779
} else if sequential_indexes && config. const_generic {
733
780
// Include a ZST ArrayProxy giving indexed access to the
734
781
// elements.
@@ -740,6 +787,7 @@ fn expand_cluster(
740
787
description : info. description . as_ref ( ) . unwrap_or ( & info. name ) . into ( ) ,
741
788
offset : info. address_offset + field_num as u32 * array_info. dim_increment ,
742
789
size : cluster_size,
790
+ accessors : None ,
743
791
} ) ;
744
792
}
745
793
}
@@ -772,6 +820,7 @@ fn expand_register(
772
820
description : info. description . clone ( ) . unwrap_or_default ( ) ,
773
821
offset : info. address_offset ,
774
822
size : register_size,
823
+ accessors : None ,
775
824
} ) ,
776
825
Register :: Array ( info, array_info) => {
777
826
let sequential_addresses = register_size == array_info. dim_increment * BITS_PER_BYTE ;
@@ -792,15 +841,52 @@ fn expand_register(
792
841
false => true ,
793
842
} ;
794
843
795
- let array_convertible = sequential_indexes && sequential_addresses && convert_list;
844
+ let array_convertible = sequential_addresses && convert_list;
796
845
797
846
if array_convertible {
798
- register_expanded. push ( RegisterBlockField {
799
- field : convert_svd_register ( register, name, config. ignore_groups ) ?,
800
- description : info. description . clone ( ) . unwrap_or_default ( ) ,
801
- offset : info. address_offset ,
802
- size : register_size * array_info. dim ,
803
- } ) ;
847
+ if sequential_indexes {
848
+ register_expanded. push ( RegisterBlockField {
849
+ field : convert_svd_register ( register, name, config. ignore_groups ) ?,
850
+ description : info. description . clone ( ) . unwrap_or_default ( ) ,
851
+ offset : info. address_offset ,
852
+ size : register_size * array_info. dim ,
853
+ accessors : None ,
854
+ } ) ;
855
+ } else {
856
+ let mut accessors = TokenStream :: new ( ) ;
857
+ let nb_name = util:: replace_suffix ( & info. fullname ( config. ignore_groups ) , "" ) ;
858
+ let ty = name_to_wrapped_ty ( & nb_name, name) ?;
859
+ let nb_name_cs =
860
+ Ident :: new ( & nb_name. to_sanitized_snake_case ( ) , Span :: call_site ( ) ) ;
861
+ let description = info. description . clone ( ) . unwrap_or_default ( ) ;
862
+ for ( i, idx) in array_info. indexes ( ) . enumerate ( ) {
863
+ let idx_name = Ident :: new (
864
+ & util:: replace_suffix ( & info. fullname ( config. ignore_groups ) , & idx)
865
+ . to_sanitized_snake_case ( ) ,
866
+ Span :: call_site ( ) ,
867
+ ) ;
868
+ let comment = make_comment (
869
+ register_size,
870
+ info. address_offset + ( i as u32 ) * register_size / 8 ,
871
+ & description,
872
+ ) ;
873
+ let i = unsuffixed ( i as _ ) ;
874
+ accessors. extend ( quote ! {
875
+ #[ doc = #comment]
876
+ #[ inline( always) ]
877
+ pub fn #idx_name( & self ) -> & #ty {
878
+ & self . #nb_name_cs[ #i]
879
+ }
880
+ } ) ;
881
+ }
882
+ register_expanded. push ( RegisterBlockField {
883
+ field : convert_svd_register ( register, name, config. ignore_groups ) ?,
884
+ description,
885
+ offset : info. address_offset ,
886
+ size : register_size * array_info. dim ,
887
+ accessors : Some ( accessors) ,
888
+ } ) ;
889
+ }
804
890
} else {
805
891
for ( field_num, field) in expand_svd_register ( register, name, config. ignore_groups ) ?
806
892
. iter ( )
@@ -811,6 +897,7 @@ fn expand_register(
811
897
description : info. description . clone ( ) . unwrap_or_default ( ) ,
812
898
offset : info. address_offset + field_num as u32 * array_info. dim_increment ,
813
899
size : register_size,
900
+ accessors : None ,
814
901
} ) ;
815
902
}
816
903
}
@@ -893,22 +980,10 @@ fn expand_svd_register(
893
980
match register {
894
981
Register :: Single ( _info) => out. push ( convert_svd_register ( register, name, ignore_group) ?) ,
895
982
Register :: Array ( info, array_info) => {
896
- let indices = array_info
897
- . dim_index
898
- . as_ref ( )
899
- . map ( |v| Cow :: from ( & * * v) )
900
- . unwrap_or_else ( || {
901
- Cow :: from (
902
- ( 0 ..array_info. dim )
903
- . map ( |i| i. to_string ( ) )
904
- . collect :: < Vec < _ > > ( ) ,
905
- )
906
- } ) ;
907
-
908
983
let ty_name = util:: replace_suffix ( & info. fullname ( ignore_group) , "" ) ;
909
984
910
- for ( idx, _i ) in indices . iter ( ) . zip ( 0 .. ) {
911
- let nb_name = util:: replace_suffix ( & info. fullname ( ignore_group) , idx) ;
985
+ for idx in array_info . indexes ( ) {
986
+ let nb_name = util:: replace_suffix ( & info. fullname ( ignore_group) , & idx) ;
912
987
913
988
let ty = name_to_wrapped_ty ( & ty_name, name) ?;
914
989
@@ -968,6 +1043,7 @@ fn array_proxy(
968
1043
description : info. description . as_ref ( ) . unwrap_or ( & info. name ) . into ( ) ,
969
1044
offset : info. address_offset ,
970
1045
size : 0 ,
1046
+ accessors : None ,
971
1047
} )
972
1048
}
973
1049
@@ -982,22 +1058,10 @@ fn expand_svd_cluster(
982
1058
match & cluster {
983
1059
Cluster :: Single ( _info) => out. push ( convert_svd_cluster ( cluster, name) ?) ,
984
1060
Cluster :: Array ( info, array_info) => {
985
- let indices = array_info
986
- . dim_index
987
- . as_ref ( )
988
- . map ( |v| Cow :: from ( & * * v) )
989
- . unwrap_or_else ( || {
990
- Cow :: from (
991
- ( 0 ..array_info. dim )
992
- . map ( |i| i. to_string ( ) )
993
- . collect :: < Vec < _ > > ( ) ,
994
- )
995
- } ) ;
996
-
997
1061
let ty_name = util:: replace_suffix ( & info. name , "" ) ;
998
1062
999
- for ( idx, _i ) in indices . iter ( ) . zip ( 0 .. ) {
1000
- let nb_name = util:: replace_suffix ( & info. name , idx) ;
1063
+ for idx in array_info . indexes ( ) {
1064
+ let nb_name = util:: replace_suffix ( & info. name , & idx) ;
1001
1065
1002
1066
let ty = name_to_ty ( & ty_name, name) ?;
1003
1067
0 commit comments