@@ -567,7 +567,31 @@ impl<'a> RWEnum<'a> {
567567 _ => None ,
568568 }
569569 }
570- pub fn gen_write_enum ( & self ) -> bool {
570+ pub fn generate_reader ( & self ) -> bool {
571+ matches ! (
572+ self ,
573+ Self :: ReadAndWriteEnum ( ( _, None ) )
574+ | Self :: ReadEnumWriteEnum ( ( _, None ) , _)
575+ | Self :: ReadEnumWriteRaw ( ( _, None ) )
576+ | Self :: ReadRawWriteEnum ( _)
577+ | Self :: ReadEnum ( ( _, None ) )
578+ | Self :: ReadRaw
579+ | Self :: ReadRawWriteRaw
580+ )
581+ }
582+ pub fn generate_writer ( & self ) -> bool {
583+ matches ! (
584+ self ,
585+ Self :: ReadAndWriteEnum ( ( _, None ) )
586+ | Self :: ReadEnumWriteEnum ( _, ( _, None ) )
587+ | Self :: ReadRawWriteEnum ( ( _, None ) )
588+ | Self :: ReadEnumWriteRaw ( _)
589+ | Self :: WriteEnum ( ( _, None ) )
590+ | Self :: WriteRaw
591+ | Self :: ReadRawWriteRaw
592+ )
593+ }
594+ pub fn generate_write_enum ( & self ) -> bool {
571595 matches ! (
572596 self ,
573597 Self :: ReadEnumWriteEnum ( _, _) | Self :: ReadRawWriteEnum ( _) | Self :: WriteEnum ( _)
@@ -691,7 +715,7 @@ pub fn fields(
691715 ( true , None , false , _) => RWEnum :: ReadRaw ,
692716 ( false , _, true , Some ( e) ) => RWEnum :: WriteEnum ( e) ,
693717 ( false , _, true , None ) => RWEnum :: WriteRaw ,
694- ( true , _ , true , _ ) => RWEnum :: ReadRawWriteRaw ,
718+ ( true , None , true , None ) => RWEnum :: ReadRawWriteRaw ,
695719 ( false , _, false , _) => {
696720 return Err ( anyhow ! ( "Field {fpath} is not writtable or readable" ) )
697721 }
@@ -710,29 +734,6 @@ pub fn fields(
710734
711735 // If this field can be read, generate read proxy structure and value structure.
712736 if can_read {
713- let cast = if width == 1 {
714- quote ! { != 0 }
715- } else {
716- quote ! { as #fty }
717- } ;
718- let value = if offset != 0 {
719- let offset = & unsuffixed ( offset) ;
720- quote ! { ( self . bits >> #offset) }
721- } else {
722- quote ! { self . bits }
723- } ;
724- let value = if use_mask && use_cast {
725- quote ! { ( #value & #hexmask) #cast }
726- } else if use_mask {
727- quote ! { #value & #hexmask }
728- } else {
729- value
730- } ;
731-
732- // get a brief description for this field
733- // the suffix string from field name is removed in brief description.
734- let field_reader_brief = format ! ( "Field `{name}{brief_suffix}` reader - {description}" ) ;
735-
736737 // get the type of value structure. It can be generated from either name field
737738 // in enumeratedValues if it's an enumeration, or from field name directly if it's not.
738739 let value_read_ty = if let Some ( ( evs, _) ) = rwenum. read_enum ( ) {
@@ -747,45 +748,6 @@ pub fn fields(
747748 fty. clone ( )
748749 } ;
749750
750- // name of read proxy type
751- let reader_ty = ident ( & name, config, "field_reader" , span) ;
752-
753- // if it's enumeratedValues and it's derived from base, don't derive the read proxy
754- // as the base has already dealt with this;
755- // if it's enumeratedValues but not derived from base, derive the reader from
756- // information in enumeratedValues;
757- // if it's not enumeratedValues, always derive the read proxy as we do not need to re-export
758- // it again from BitReader or FieldReader.
759- let should_derive_reader = matches ! ( rwenum. read_enum( ) , Some ( ( _, None ) ) | None ) ;
760-
761- // derive the read proxy structure if necessary.
762- if should_derive_reader {
763- let reader = if width == 1 {
764- if value_read_ty == "bool" {
765- quote ! { crate :: BitReader }
766- } else {
767- quote ! { crate :: BitReader <#value_read_ty> }
768- }
769- } else if value_read_ty == "u8" {
770- quote ! { crate :: FieldReader }
771- } else {
772- quote ! { crate :: FieldReader <#value_read_ty> }
773- } ;
774- let mut readerdoc = field_reader_brief. clone ( ) ;
775- if let Some ( action) = f. read_action {
776- readerdoc += match action {
777- ReadAction :: Clear => "\n \n The field is **cleared** (set to zero) following a read operation." ,
778- ReadAction :: Set => "\n \n The field is **set** (set to ones) following a read operation." ,
779- ReadAction :: Modify => "\n \n The field is **modified** in some way after a read operation." ,
780- ReadAction :: ModifyExternal => "\n \n One or more dependent resources other than the current field are immediately affected by a read operation." ,
781- } ;
782- }
783- mod_items. extend ( quote ! {
784- #[ doc = #readerdoc]
785- pub type #reader_ty = #reader;
786- } ) ;
787- }
788-
789751 // collect information on items in enumeration to generate it later.
790752 let mut enum_items = TokenStream :: new ( ) ;
791753
@@ -927,11 +889,61 @@ pub fn fields(
927889 } ) ;
928890 }
929891 }
892+ } else if let Some ( ( _, Some ( base) ) ) = rwenum. read_enum ( ) {
893+ // only pub use enum when derived from another register.
894+ // If field is in the same register it emits
895+ // pub use enum from same module which is not expected
896+ if base. register ( ) != fpath. register ( ) {
897+ // use the same enum structure name
898+ if !enum_derives. contains ( & value_read_ty) {
899+ let base_path = base_syn_path ( base, & fpath, & value_read_ty, config) ?;
900+ mod_items. extend ( quote ! {
901+ #[ doc = #description]
902+ pub use #base_path as #value_read_ty;
903+ } ) ;
904+ enum_derives. insert ( value_read_ty. clone ( ) ) ;
905+ }
906+ }
930907 }
931908
932- // if this value is derived from a base, generate `pub use` code for each read proxy and value
933- // if necessary.
934- if let Some ( ( _, Some ( base) ) ) = rwenum. read_enum ( ) {
909+ // get a brief description for this field
910+ // the suffix string from field name is removed in brief description.
911+ let field_reader_brief = format ! ( "Field `{name}{brief_suffix}` reader - {description}" ) ;
912+
913+ // name of read proxy type
914+ let reader_ty = ident ( & name, config, "field_reader" , span) ;
915+
916+ if rwenum. generate_reader ( ) {
917+ // Generate the read proxy structure if necessary.
918+
919+ let reader = if width == 1 {
920+ if value_read_ty == "bool" {
921+ quote ! { crate :: BitReader }
922+ } else {
923+ quote ! { crate :: BitReader <#value_read_ty> }
924+ }
925+ } else if value_read_ty == "u8" {
926+ quote ! { crate :: FieldReader }
927+ } else {
928+ quote ! { crate :: FieldReader <#value_read_ty> }
929+ } ;
930+ let mut readerdoc = field_reader_brief. clone ( ) ;
931+ if let Some ( action) = f. read_action {
932+ readerdoc += match action {
933+ ReadAction :: Clear => "\n \n The field is **cleared** (set to zero) following a read operation." ,
934+ ReadAction :: Set => "\n \n The field is **set** (set to ones) following a read operation." ,
935+ ReadAction :: Modify => "\n \n The field is **modified** in some way after a read operation." ,
936+ ReadAction :: ModifyExternal => "\n \n One or more dependent resources other than the current field are immediately affected by a read operation." ,
937+ } ;
938+ }
939+ mod_items. extend ( quote ! {
940+ #[ doc = #readerdoc]
941+ pub type #reader_ty = #reader;
942+ } ) ;
943+ } else if let Some ( ( _, Some ( base) ) ) = rwenum. read_enum ( ) {
944+ // if this value is derived from a base, generate `pub use` code for each read proxy
945+ // and value if necessary.
946+
935947 // generate pub use field_1 reader as field_2 reader
936948 let base_field = util:: replace_suffix ( & base. field . name , "" ) ;
937949 let base_r = ident ( & base_field, config, "field_reader" , span) ;
@@ -943,21 +955,15 @@ pub fn fields(
943955 } ) ;
944956 reader_derives. insert ( reader_ty. clone ( ) ) ;
945957 }
946- // only pub use enum when base.register != None. if base.register == None, it emits
947- // pub use enum from same module which is not expected
948- if base. register ( ) != fpath. register ( ) {
949- // use the same enum structure name
950- if !enum_derives. contains ( & value_read_ty) {
951- let base_path = base_syn_path ( base, & fpath, & value_read_ty, config) ?;
952- mod_items. extend ( quote ! {
953- #[ doc = #description]
954- pub use #base_path as #value_read_ty;
955- } ) ;
956- enum_derives. insert ( value_read_ty. clone ( ) ) ;
957- }
958- }
959958 }
960959
960+ // Generate field reader accessors
961+ let cast = if width == 1 {
962+ quote ! { != 0 }
963+ } else {
964+ quote ! { as #fty }
965+ } ;
966+
961967 if let Field :: Array ( f, de) = & f {
962968 let increment = de. dim_increment ;
963969 let doc = util:: replace_suffix ( & description, & brief_suffix) ;
@@ -1015,6 +1021,20 @@ pub fn fields(
10151021 } ) ;
10161022 }
10171023 } else {
1024+ let value = if offset != 0 {
1025+ let offset = & unsuffixed ( offset) ;
1026+ quote ! { ( self . bits >> #offset) }
1027+ } else {
1028+ quote ! { self . bits }
1029+ } ;
1030+ let value = if use_mask && use_cast {
1031+ quote ! { ( #value & #hexmask) #cast }
1032+ } else if use_mask {
1033+ quote ! { #value & #hexmask }
1034+ } else {
1035+ value
1036+ } ;
1037+
10181038 let doc = description_with_bits ( description_raw, offset, width) ;
10191039 r_impl_items. extend ( quote ! {
10201040 #[ doc = #doc]
@@ -1038,10 +1058,6 @@ pub fn fields(
10381058 // If this field can be written, generate write proxy. Generate write value if it differs from
10391059 // the read value, or else we reuse read value.
10401060 if can_write {
1041- let mwv = f. modified_write_values . or ( rmwv) . unwrap_or_default ( ) ;
1042- // gets a brief of write proxy
1043- let field_writer_brief = format ! ( "Field `{name}{brief_suffix}` writer - {description}" ) ;
1044-
10451061 let value_write_ty = if let Some ( ( evs, _) ) = rwenum. write_enum ( ) {
10461062 let fmt = if rwenum. different_enums ( ) {
10471063 "enum_write_name"
@@ -1054,9 +1070,6 @@ pub fn fields(
10541070 fty. clone ( )
10551071 } ;
10561072
1057- // name of write proxy type
1058- let writer_ty = ident ( & name, config, "field_writer" , span) ;
1059-
10601073 let mut proxy_items = TokenStream :: new ( ) ;
10611074 let mut unsafety = unsafety ( f. write_constraint . as_ref ( ) , width) ;
10621075
@@ -1083,7 +1096,7 @@ pub fn fields(
10831096 }
10841097
10851098 // generate write value structure and From conversation if we can't reuse read value structure.
1086- if rwenum. gen_write_enum ( ) {
1099+ if rwenum. generate_write_enum ( ) {
10871100 if variants. is_empty ( ) {
10881101 add_with_no_variants (
10891102 mod_items,
@@ -1119,14 +1132,33 @@ pub fn fields(
11191132 }
11201133 } ) ;
11211134 }
1135+ } else if let Some ( ( _, Some ( base) ) ) = rwenum. write_enum ( ) {
1136+ // If field is in the same register it emits pub use structure from same module.
1137+ if base. register ( ) != fpath. register ( ) {
1138+ if rwenum. generate_write_enum ( ) {
1139+ // use the same enum structure name
1140+ if !writer_enum_derives. contains ( & value_write_ty) {
1141+ let base_path = base_syn_path ( base, & fpath, & value_write_ty, config) ?;
1142+ mod_items. extend ( quote ! {
1143+ #[ doc = #description]
1144+ pub use #base_path as #value_write_ty;
1145+ } ) ;
1146+ writer_enum_derives. insert ( value_write_ty. clone ( ) ) ;
1147+ }
1148+ }
1149+ }
11221150 }
11231151
1124- // derive writer. We derive writer if the write proxy is in current register module,
1125- // or writer in different register have different _SPEC structures
1126- let should_derive_writer = matches ! ( rwenum. write_enum( ) , Some ( ( _, None ) ) | None ) ;
1152+ let mwv = f. modified_write_values . or ( rmwv) . unwrap_or_default ( ) ;
1153+
1154+ // gets a brief of write proxy
1155+ let field_writer_brief = format ! ( "Field `{name}{brief_suffix}` writer - {description}" ) ;
1156+
1157+ // name of write proxy type
1158+ let writer_ty = ident ( & name, config, "field_writer" , span) ;
11271159
1128- // derive writer structure by type alias to generic write proxy structure.
1129- if should_derive_writer {
1160+ // Generate writer structure by type alias to generic write proxy structure.
1161+ if rwenum . generate_writer ( ) {
11301162 let proxy = if width == 1 {
11311163 use ModifiedWriteValues :: * ;
11321164 let wproxy = Ident :: new (
@@ -1166,6 +1198,23 @@ pub fn fields(
11661198 #[ doc = #field_writer_brief]
11671199 pub type #writer_ty<' a, REG > = #proxy;
11681200 } ) ;
1201+ } else if let Some ( ( _, Some ( base) ) ) = rwenum. write_enum ( ) {
1202+ // if base.register == None, derive write from the same module. This is allowed because both
1203+ // the generated and source write proxy are in the same module.
1204+ // we never reuse writer for writer in different module does not have the same _SPEC strcuture,
1205+ // thus we cannot write to current register using re-exported write proxy.
1206+
1207+ // generate pub use field_1 writer as field_2 writer
1208+ let base_field = util:: replace_suffix ( & base. field . name , "" ) ;
1209+ let base_w = ident ( & base_field, config, "field_writer" , span) ;
1210+ if !writer_derives. contains ( & writer_ty) {
1211+ let base_path = base_syn_path ( base, & fpath, & base_w, config) ?;
1212+ mod_items. extend ( quote ! {
1213+ #[ doc = #field_writer_brief]
1214+ pub use #base_path as #writer_ty;
1215+ } ) ;
1216+ writer_derives. insert ( writer_ty. clone ( ) ) ;
1217+ }
11691218 }
11701219
11711220 // generate proxy items from collected information
@@ -1192,39 +1241,7 @@ pub fn fields(
11921241 } ) ;
11931242 }
11941243
1195- if let Some ( ( _, Some ( base) ) ) = rwenum. write_enum ( ) {
1196- // if base.register == None, derive write from the same module. This is allowed because both
1197- // the generated and source write proxy are in the same module.
1198- // we never reuse writer for writer in different module does not have the same _SPEC strcuture,
1199- // thus we cannot write to current register using re-exported write proxy.
1200-
1201- // generate pub use field_1 writer as field_2 writer
1202- let base_field = util:: replace_suffix ( & base. field . name , "" ) ;
1203- let base_w = ident ( & base_field, config, "field_writer" , span) ;
1204- if !writer_derives. contains ( & writer_ty) {
1205- let base_path = base_syn_path ( base, & fpath, & base_w, config) ?;
1206- mod_items. extend ( quote ! {
1207- #[ doc = #field_writer_brief]
1208- pub use #base_path as #writer_ty;
1209- } ) ;
1210- writer_derives. insert ( writer_ty. clone ( ) ) ;
1211- }
1212- // if base.register == None, it emits pub use structure from same module.
1213- if base. register ( ) != fpath. register ( ) {
1214- if rwenum. gen_write_enum ( ) {
1215- // use the same enum structure name
1216- if !writer_enum_derives. contains ( & value_write_ty) {
1217- let base_path = base_syn_path ( base, & fpath, & value_write_ty, config) ?;
1218- mod_items. extend ( quote ! {
1219- #[ doc = #description]
1220- pub use #base_path as #value_write_ty;
1221- } ) ;
1222- writer_enum_derives. insert ( value_write_ty. clone ( ) ) ;
1223- }
1224- }
1225- }
1226- }
1227-
1244+ // Generate field writer accessors
12281245 if let Field :: Array ( f, de) = & f {
12291246 let increment = de. dim_increment ;
12301247 let offset_calc = calculate_offset ( increment, offset, false ) ;
@@ -1276,6 +1293,8 @@ pub fn fields(
12761293 }
12771294 } ) ;
12781295 }
1296+
1297+ // Update register modify bit masks
12791298 let bitmask = ( u64:: MAX >> ( 64 - width) ) << offset;
12801299 use ModifiedWriteValues :: * ;
12811300 match mwv {
0 commit comments