Skip to content

Commit 17092f3

Browse files
committed
refactor field generation logic
1 parent 7af7013 commit 17092f3

File tree

1 file changed

+145
-126
lines changed

1 file changed

+145
-126
lines changed

src/generate/register.rs

Lines changed: 145 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -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\nThe field is **cleared** (set to zero) following a read operation.",
778-
ReadAction::Set => "\n\nThe field is **set** (set to ones) following a read operation.",
779-
ReadAction::Modify => "\n\nThe field is **modified** in some way after a read operation.",
780-
ReadAction::ModifyExternal => "\n\nOne 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\nThe field is **cleared** (set to zero) following a read operation.",
934+
ReadAction::Set => "\n\nThe field is **set** (set to ones) following a read operation.",
935+
ReadAction::Modify => "\n\nThe field is **modified** in some way after a read operation.",
936+
ReadAction::ModifyExternal => "\n\nOne 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

Comments
 (0)