Skip to content

Commit e420dc8

Browse files
committed
multi-level derive register inside peripheral
1 parent e63aaa7 commit e420dc8

File tree

2 files changed

+51
-52
lines changed

2 files changed

+51
-52
lines changed

src/generate/peripheral.rs

Lines changed: 47 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ pub fn render(
3535
let p = p_merged.as_ref().unwrap_or(p_original);
3636

3737
if let (Some(df), None) = (p_original.derived_from.as_ref(), &p_derivedfrom) {
38-
eprintln!(
38+
return Err(anyhow!(
3939
"Couldn't find derivedFrom original: {} for {}, skipping",
40-
df, p_original.name
41-
);
42-
return Ok(out);
40+
df,
41+
p_original.name
42+
));
4343
}
4444

4545
let name = util::name_of(p, config.ignore_groups);
@@ -149,7 +149,7 @@ pub fn render(
149149
}
150150

151151
// erc: *E*ither *R*egister or *C*luster
152-
let ercs = p.registers.as_ref().map(|x| x.as_ref()).unwrap_or(&[][..]);
152+
let ercs_in = p.registers.as_ref().map(|x| x.as_ref()).unwrap_or(&[][..]);
153153

154154
// make a pass to expand derived registers and clusters. Ideally, for the most minimal
155155
// code size, we'd do some analysis to figure out if we can 100% reuse the
@@ -159,48 +159,15 @@ pub fn render(
159159

160160
// Build a map so that we can look up registers within this peripheral
161161
let mut erc_map = HashMap::new();
162-
for erc in ercs {
163-
erc_map.insert(util::erc_name(erc), erc.clone());
162+
for erc in ercs_in {
163+
erc_map.insert(util::erc_name(erc), erc);
164164
}
165165

166166
// Build up an alternate erc list by expanding any derived registers/clusters
167-
let ercs: Vec<RegisterCluster> = ercs
168-
.iter()
169-
.filter_map(|erc| match util::erc_derived_from(erc) {
170-
Some(ref derived) => {
171-
let ancestor = match erc_map.get(derived) {
172-
Some(erc) => erc,
173-
None => {
174-
eprintln!(
175-
"register/cluster {} derivedFrom missing register/cluster {}",
176-
util::erc_name(erc),
177-
derived
178-
);
179-
return None;
180-
}
181-
};
182-
183-
match (erc, ancestor) {
184-
(RegisterCluster::Register(reg), RegisterCluster::Register(other_reg)) => {
185-
Some(RegisterCluster::Register(reg.derive_from(other_reg)))
186-
}
187-
(
188-
RegisterCluster::Cluster(cluster),
189-
RegisterCluster::Cluster(other_cluster),
190-
) => Some(RegisterCluster::Cluster(cluster.derive_from(other_cluster))),
191-
_ => {
192-
eprintln!(
193-
"{} can't derive from {}",
194-
util::erc_name(erc),
195-
util::erc_name(ancestor)
196-
);
197-
None
198-
}
199-
}
200-
}
201-
None => Some(erc.clone()),
202-
})
203-
.collect();
167+
let mut ercs = Vec::with_capacity(ercs_in.len());
168+
for erc in ercs_in {
169+
ercs.push(derive_register_cluster(erc, &erc_map)?.into_owned());
170+
}
204171

205172
// And revise registers, clusters and ercs to refer to our expanded versions
206173
let registers: &[&Register] = &util::only_registers(&ercs)[..];
@@ -259,6 +226,42 @@ pub fn render(
259226
Ok(out)
260227
}
261228

229+
fn derive_register_cluster<'a>(
230+
erc: &'a RegisterCluster,
231+
erc_map: &'a HashMap<&'a String, &'a RegisterCluster>,
232+
) -> Result<Cow<'a, RegisterCluster>> {
233+
Ok(if let Some(derived) = util::erc_derived_from(erc) {
234+
let ancestor = erc_map.get(derived).ok_or_else(|| {
235+
anyhow!(
236+
"register/cluster {} derivedFrom missing register/cluster {}",
237+
util::erc_name(erc),
238+
derived
239+
)
240+
})?;
241+
242+
let ancestor = derive_register_cluster(ancestor, erc_map)?;
243+
244+
use RegisterCluster::*;
245+
match (erc, ancestor.as_ref()) {
246+
(Register(reg), Register(other_reg)) => {
247+
Cow::Owned(Register(reg.derive_from(other_reg)))
248+
}
249+
(Cluster(cluster), Cluster(other_cluster)) => {
250+
Cow::Owned(Cluster(cluster.derive_from(other_cluster)))
251+
}
252+
_ => {
253+
return Err(anyhow!(
254+
"{} can't derive from {}",
255+
util::erc_name(erc),
256+
util::erc_name(&ancestor)
257+
));
258+
}
259+
}
260+
} else {
261+
Cow::Borrowed(erc)
262+
})
263+
}
264+
262265
#[derive(Clone, Debug)]
263266
struct RegisterBlockField {
264267
field: syn::Field,

src/util.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -389,26 +389,22 @@ pub fn erc_derived_from(erc: &RegisterCluster) -> &Option<String> {
389389

390390
/// Return only the clusters from the slice of either register or clusters.
391391
pub fn only_clusters(ercs: &[RegisterCluster]) -> Vec<&Cluster> {
392-
let clusters: Vec<&Cluster> = ercs
393-
.iter()
392+
ercs.iter()
394393
.filter_map(|x| match x {
395394
RegisterCluster::Cluster(x) => Some(x),
396395
_ => None,
397396
})
398-
.collect();
399-
clusters
397+
.collect()
400398
}
401399

402400
/// Return only the registers the given slice of either register or clusters.
403401
pub fn only_registers(ercs: &[RegisterCluster]) -> Vec<&Register> {
404-
let registers: Vec<&Register> = ercs
405-
.iter()
402+
ercs.iter()
406403
.filter_map(|x| match x {
407404
RegisterCluster::Register(x) => Some(x),
408405
_ => None,
409406
})
410-
.collect();
411-
registers
407+
.collect()
412408
}
413409

414410
pub fn build_rs() -> TokenStream {

0 commit comments

Comments
 (0)