Skip to content

Commit cb134d2

Browse files
committed
expand derived registers
This is a very basic first cut at expanding registers with derivedFrom. This commit requires rust-embedded/svd#50
1 parent 5e193ae commit cb134d2

File tree

1 file changed

+79
-3
lines changed

1 file changed

+79
-3
lines changed

src/generate/peripheral.rs

Lines changed: 79 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
use std::borrow::Cow;
22
use std::cmp::Ordering;
3+
use std::collections::HashMap;
34

45
use either::Either;
56
use quote::{ToTokens, Tokens};
6-
use svd::{Cluster, ClusterInfo, Defaults, Peripheral, Register};
7+
use svd::{Cluster, ClusterInfo, Defaults, Peripheral, Register, RegisterInfo};
78
use syn::{self, Ident};
89

910
use errors::*;
@@ -23,7 +24,7 @@ pub fn render(
2324
all_peripherals.iter().find(|x| x.name == *s)
2425
});
2526

26-
let p_merged = p_derivedfrom.map(|x| p_original.derive_from(x));
27+
let p_merged = p_derivedfrom.map(|ancestor| p_original.derive_from(ancestor));
2728
let p = p_merged.as_ref().unwrap_or(p_original);
2829

2930
if p_original.derived_from.is_some() && p_derivedfrom.is_none() {
@@ -75,9 +76,84 @@ pub fn render(
7576

7677
// erc: *E*ither *R*egister or *C*luster
7778
let ercs = p.registers.as_ref().map(|x| x.as_ref()).unwrap_or(&[][..]);
78-
7979
let registers: &[&Register] = &util::only_registers(&ercs)[..];
80+
81+
// make a pass to expand derived registers. Ideally, for the most minimal
82+
// code size, we'd do some analysis to figure out if we can 100% reuse the
83+
// code that we're deriving from. For the sake of proving the concept, we're
84+
// just going to emit a second copy of the accessor code. It'll probably
85+
// get inlined by the compiler anyway, right? :-)
86+
87+
// Build a map so that we can look up registers within this peripheral
88+
let mut reg_map = HashMap::new();
89+
for r in registers {
90+
reg_map.insert(&r.name, r.clone());
91+
}
92+
93+
// Compute the effective, derived version of a register given the definition
94+
// with the derived_from property on it (`info`) and its `ancestor`
95+
fn derive_reg_info(info: &RegisterInfo, ancestor: &RegisterInfo) -> RegisterInfo {
96+
let mut derived = info.clone();
97+
98+
if derived.size.is_none() {
99+
derived.size = ancestor.size.clone();
100+
}
101+
if derived.access.is_none() {
102+
derived.access = ancestor.access.clone();
103+
}
104+
if derived.reset_value.is_none() {
105+
derived.reset_value = ancestor.reset_value.clone();
106+
}
107+
if derived.reset_mask.is_none() {
108+
derived.reset_mask = ancestor.reset_mask.clone();
109+
}
110+
if derived.fields.is_none() {
111+
derived.fields = ancestor.fields.clone();
112+
}
113+
if derived.write_constraint.is_none() {
114+
derived.write_constraint = ancestor.write_constraint.clone();
115+
}
116+
117+
derived
118+
}
119+
120+
// Build up an alternate erc list by expanding any derived registers
121+
let mut alt_erc :Vec<Either<Register,Cluster>> = registers.iter().filter_map(|r| {
122+
match r.derived_from {
123+
Some(ref derived) => {
124+
let ancestor = match reg_map.get(derived) {
125+
Some(r) => r,
126+
None => {
127+
eprintln!("register {} derivedFrom missing register {}", r.name, derived);
128+
return None
129+
}
130+
};
131+
132+
let d = match **ancestor {
133+
Register::Array(ref info, ref array_info) => {
134+
Some(Either::Left(Register::Array(derive_reg_info(*r, info), array_info.clone())))
135+
}
136+
Register::Single(ref info) => {
137+
Some(Either::Left(Register::Single(derive_reg_info(*r, info))))
138+
}
139+
};
140+
141+
d
142+
}
143+
None => Some(Either::Left((*r).clone())),
144+
}
145+
}).collect();
146+
147+
// Now add the clusters to our alternate erc list
148+
let clusters = util::only_clusters(ercs);
149+
for cluster in &clusters {
150+
alt_erc.push(Either::Right((*cluster).clone()));
151+
}
152+
153+
// And revise registers, clusters and ercs to refer to our expanded versions
154+
let registers: &[&Register] = &util::only_registers(&alt_erc)[..];
80155
let clusters = util::only_clusters(ercs);
156+
let ercs = &alt_erc;
81157

82158
// No `struct RegisterBlock` can be generated
83159
if registers.is_empty() && clusters.is_empty() {

0 commit comments

Comments
 (0)