Skip to content

Commit 3804bed

Browse files
authored
Merge pull request #930 from rust-embedded/arrays
fix known issues in derive register arrays
2 parents 939f38b + 2ca591c commit 3804bed

File tree

6 files changed

+69
-32
lines changed

6 files changed

+69
-32
lines changed

.github/workflows/ci.yml

+7-3
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,10 @@ jobs:
8383
- { vendor: Spansion, options: "-- --atomics" }
8484
- { vendor: STMicro }
8585
- { vendor: STMicro, options: "-- --atomics" }
86-
- { vendor: STMicro, options: "-- --strict -f enum_value::p: --max-cluster-size --atomics --atomics-feature atomics --impl-debug --impl-defmt defmt" }
86+
- {
87+
vendor: STMicro,
88+
options: "-- --strict -f enum_value::p: --max-cluster-size --atomics --atomics-feature atomics --impl-debug --impl-defmt defmt",
89+
}
8790
- { vendor: Toshiba }
8891
- { vendor: Toshiba, options: "-- --strict --atomics" }
8992
- { vendor: TexasInstruments }
@@ -92,6 +95,7 @@ jobs:
9295
- { vendor: Espressif, options: "-- --atomics" }
9396
- { vendor: Vorago }
9497
- { vendor: Vorago, options: "-- --strict --atomics" }
98+
- { vendor: Renesas }
9599
- { vendor: RaspberryPi }
96100
- { vendor: RaspberryPi, options: "-- --atomics" }
97101

@@ -176,11 +180,11 @@ jobs:
176180
- name: Cache
177181
uses: Swatinem/rust-cache@v2
178182
with:
179-
key: svdtools-0.3.19
183+
key: svdtools-0.4.6
180184

181185
- name: Install svdtools
182186
run: |
183-
cargo install svdtools --version 0.3.19 --target-dir target
187+
cargo install svdtools --version 0.4.6 --target-dir target
184188
185189
- name: Run CI script
186190
run: |

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
88
## [Unreleased]
99

1010
- Update `irx-config`
11+
- Fix register array derive regression
1112

1213
## [v0.36.0] - 2025-03-09
1314

src/generate/peripheral.rs

+36-22
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,15 @@ pub fn render(p_original: &Peripheral, index: &Index, config: &Config) -> Result
188188
"Pushing {} register or cluster blocks into output",
189189
ercs.len()
190190
);
191-
let reg_block =
192-
register_or_cluster_block(&ercs, &derive_infos, None, "Register block", None, config)?;
191+
let reg_block = register_or_cluster_block(
192+
&ercs,
193+
&BlockPath::new(&p.name),
194+
&derive_infos,
195+
None,
196+
"Register block",
197+
None,
198+
config,
199+
)?;
193200

194201
out.extend(quote! {
195202
#[doc = #doc]
@@ -469,6 +476,7 @@ fn make_comment(size: u32, offset: u32, description: &str) -> String {
469476

470477
fn register_or_cluster_block(
471478
ercs: &[RegisterCluster],
479+
path: &BlockPath,
472480
derive_infos: &[DeriveInfo],
473481
name: Option<&str>,
474482
doc: &str,
@@ -478,7 +486,7 @@ fn register_or_cluster_block(
478486
let mut rbfs = TokenStream::new();
479487
let mut accessors = TokenStream::new();
480488

481-
let ercs_expanded = expand(ercs, derive_infos, config)
489+
let ercs_expanded = expand(ercs, path, derive_infos, config)
482490
.with_context(|| "Could not expand register or cluster block")?;
483491

484492
// Locate conflicting regions; we'll need to use unions to represent them.
@@ -612,6 +620,7 @@ fn register_or_cluster_block(
612620
/// `RegisterBlockField`s containing `Field`s.
613621
fn expand(
614622
ercs: &[RegisterCluster],
623+
path: &BlockPath,
615624
derive_infos: &[DeriveInfo],
616625
config: &Config,
617626
) -> Result<Vec<RegisterBlockField>> {
@@ -623,14 +632,14 @@ fn expand(
623632
match &erc {
624633
RegisterCluster::Register(register) => {
625634
let reg_name = &register.name;
626-
let expanded_reg = expand_register(register, derive_info, config)
635+
let expanded_reg = expand_register(register, path, derive_info, config)
627636
.with_context(|| format!("can't expand register '{reg_name}'"))?;
628637
trace!("Register: {reg_name}");
629638
ercs_expanded.extend(expanded_reg);
630639
}
631640
RegisterCluster::Cluster(cluster) => {
632641
let cluster_name = &cluster.name;
633-
let expanded_cluster = expand_cluster(cluster, config)
642+
let expanded_cluster = expand_cluster(cluster, path, config)
634643
.with_context(|| format!("can't expand cluster '{cluster_name}'"))?;
635644
trace!("Cluster: {cluster_name}");
636645
ercs_expanded.extend(expanded_cluster);
@@ -873,9 +882,9 @@ fn is_derivable(
873882
/// Calculate the size of a Cluster. If it is an array, then the dimensions
874883
/// tell us the size of the array. Otherwise, inspect the contents using
875884
/// [cluster_info_size_in_bits].
876-
fn cluster_size_in_bits(cluster: &Cluster, config: &Config) -> Result<u32> {
885+
fn cluster_size_in_bits(cluster: &Cluster, path: &BlockPath, config: &Config) -> Result<u32> {
877886
match cluster {
878-
Cluster::Single(info) => cluster_info_size_in_bits(info, config),
887+
Cluster::Single(info) => cluster_info_size_in_bits(info, path, config),
879888
// If the contained array cluster has a mismatch between the
880889
// dimIncrement and the size of the array items, then the array
881890
// will get expanded in expand_cluster below. The overall size
@@ -885,29 +894,29 @@ fn cluster_size_in_bits(cluster: &Cluster, config: &Config) -> Result<u32> {
885894
return Ok(0); // Special case!
886895
}
887896
let last_offset = (dim.dim - 1) * dim.dim_increment * BITS_PER_BYTE;
888-
let last_size = cluster_info_size_in_bits(info, config);
897+
let last_size = cluster_info_size_in_bits(info, path, config);
889898
Ok(last_offset + last_size?)
890899
}
891900
}
892901
}
893902

894903
/// Recursively calculate the size of a ClusterInfo. A cluster's size is the
895904
/// maximum end position of its recursive children.
896-
fn cluster_info_size_in_bits(info: &ClusterInfo, config: &Config) -> Result<u32> {
905+
fn cluster_info_size_in_bits(info: &ClusterInfo, path: &BlockPath, config: &Config) -> Result<u32> {
897906
let mut size = 0;
898907

899908
for c in &info.children {
900909
let end = match c {
901910
RegisterCluster::Register(reg) => {
902-
let reg_size: u32 = expand_register(reg, &DeriveInfo::Root, config)?
911+
let reg_size: u32 = expand_register(reg, path, &DeriveInfo::Root, config)?
903912
.iter()
904913
.map(|rbf| rbf.size)
905914
.sum();
906915

907916
(reg.address_offset * BITS_PER_BYTE) + reg_size
908917
}
909918
RegisterCluster::Cluster(clust) => {
910-
(clust.address_offset * BITS_PER_BYTE) + cluster_size_in_bits(clust, config)?
919+
(clust.address_offset * BITS_PER_BYTE) + cluster_size_in_bits(clust, path, config)?
911920
}
912921
};
913922

@@ -917,10 +926,14 @@ fn cluster_info_size_in_bits(info: &ClusterInfo, config: &Config) -> Result<u32>
917926
}
918927

919928
/// Render a given cluster (and any children) into `RegisterBlockField`s
920-
fn expand_cluster(cluster: &Cluster, config: &Config) -> Result<Vec<RegisterBlockField>> {
929+
fn expand_cluster(
930+
cluster: &Cluster,
931+
path: &BlockPath,
932+
config: &Config,
933+
) -> Result<Vec<RegisterBlockField>> {
921934
let mut cluster_expanded = vec![];
922935

923-
let cluster_size = cluster_info_size_in_bits(cluster, config)
936+
let cluster_size = cluster_info_size_in_bits(cluster, path, config)
924937
.with_context(|| format!("Can't calculate cluster {} size", cluster.name))?;
925938
let description = cluster
926939
.description
@@ -1087,6 +1100,7 @@ fn expand_cluster(cluster: &Cluster, config: &Config) -> Result<Vec<RegisterBloc
10871100
/// A `DeriveInfo::Implicit(_)` will also cause an array to be expanded.
10881101
fn expand_register(
10891102
register: &Register,
1103+
path: &BlockPath,
10901104
derive_info: &DeriveInfo,
10911105
config: &Config,
10921106
) -> Result<Vec<RegisterBlockField>> {
@@ -1104,7 +1118,7 @@ fn expand_register(
11041118
} else {
11051119
info_name.remove_dim()
11061120
};
1107-
let ty_str = ty_name.clone();
1121+
let mut ty_str = ty_name.clone();
11081122

11091123
match register {
11101124
Register::Single(info) => {
@@ -1135,7 +1149,7 @@ fn expand_register(
11351149
|| (register_size <= array_info.dim_increment * BITS_PER_BYTE);
11361150

11371151
let convert_list = match config.keep_list {
1138-
true => info.name.contains("[%s]"),
1152+
true => info_name.contains("[%s]"),
11391153
false => true,
11401154
};
11411155

@@ -1154,13 +1168,12 @@ fn expand_register(
11541168
"".into()
11551169
};
11561170
let ac = match derive_info {
1157-
DeriveInfo::Implicit(_) => {
1158-
ty_name = info_name.expand_dim(&index);
1159-
convert_list && sequential_indexes_from0
1160-
}
1161-
DeriveInfo::Explicit(_) => {
1171+
DeriveInfo::Implicit(di) | DeriveInfo::Explicit(di)
1172+
if path == &di.block && !info_name.contains("[%s]") =>
1173+
{
11621174
ty_name = info_name.expand_dim(&index);
1163-
convert_list && sequential_indexes_from0
1175+
ty_str = ty_name.clone();
1176+
false
11641177
}
11651178
_ => convert_list,
11661179
};
@@ -1207,7 +1220,7 @@ fn expand_register(
12071220
let idx_name = ident(
12081221
&util::fullname(&ri.name, &info.alternate_group, config.ignore_groups),
12091222
config,
1210-
"cluster_accessor",
1223+
"register_accessor",
12111224
span,
12121225
);
12131226
let doc = make_comment(
@@ -1374,6 +1387,7 @@ fn cluster_block(
13741387
};
13751388
let reg_block = register_or_cluster_block(
13761389
&c.children,
1390+
&path.new_cluster(&c.name),
13771391
&mod_derive_infos,
13781392
Some(&mod_name),
13791393
&doc,

src/generate/register.rs

+17-7
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,16 @@ pub fn render(
5050
) -> Result<TokenStream> {
5151
let mut name = util::name_of(register, config.ignore_groups);
5252
// Rename if this is a derived array
53-
if dpath.is_some() {
53+
if let Some(dpath) = dpath.as_ref() {
5454
if let MaybeArray::Array(info, array_info) = register {
5555
if let Some(dim_index) = &array_info.dim_index {
56-
let index: Cow<str> = dim_index.first().unwrap().into();
57-
name = info
58-
.fullname(config.ignore_groups)
59-
.expand_dim(&index)
60-
.into()
56+
if path == &dpath.block {
57+
let index: Cow<str> = dim_index.first().unwrap().into();
58+
name = info
59+
.fullname(config.ignore_groups)
60+
.expand_dim(&index)
61+
.into()
62+
}
6163
}
6264
}
6365
}
@@ -1452,7 +1454,15 @@ impl Variant {
14521454
span,
14531455
);
14541456
let sc = case.sanitize(&ev.name);
1455-
const INTERNALS: [&str; 6] = ["bit", "bits", "clear_bit", "set", "set_bit", "variant"];
1457+
const INTERNALS: [&str; 7] = [
1458+
"bit",
1459+
"bits",
1460+
"clear_bit",
1461+
"set",
1462+
"set_bit",
1463+
"variant",
1464+
"offset",
1465+
];
14561466
let sc = Ident::new(
14571467
&(if INTERNALS.contains(&sc.as_ref()) {
14581468
sc + "_"

svd2rust-regress/src/tests.rs

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pub enum Manufacturer {
2525
Vorago,
2626
Espressif,
2727
RaspberryPi,
28+
Renesas,
2829
Unknown,
2930
}
3031

@@ -47,6 +48,7 @@ impl Manufacturer {
4748
Toshiba,
4849
SiFive,
4950
RaspberryPi,
51+
Renesas,
5052
TexasInstruments,
5153
Espressif,
5254
]

svd2rust-regress/tests.yml

+6
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,12 @@
696696
chip: va108xx
697697
svd_url: https://raw.githubusercontent.com/us-irs/va108xx-rs/refs/heads/main/va108xx/svd/va108xx.svd.patched
698698

699+
# Renesas
700+
- arch: cortex-m
701+
mfgr: Renesas
702+
chip: r7fa4m1ab
703+
svd_url: https://raw.githubusercontent.com/ra-rs/ra/refs/heads/main/svd/vendor/R7FA4M1AB.svd
704+
699705
# Raspberry Pi
700706
- arch: cortex-m
701707
mfgr: RaspberryPi

0 commit comments

Comments
 (0)