Skip to content

Commit ebbb697

Browse files
committed
Try #256:
2 parents 51d76e6 + b6d2c9a commit ebbb697

File tree

5 files changed

+127
-37
lines changed

5 files changed

+127
-37
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,5 @@ either = "1.0.3"
3333
error-chain = "0.11.0"
3434
inflections = "1.1.0"
3535
quote = "0.3.15"
36-
svd-parser = "0.6"
36+
svd-parser = { git = "https://github.com/japaric/svd", rev = "6aa4fdc138b91d7b9d2f0bd42fd1c85cb4fb5df9" }
3737
syn = "0.11.11"

src/generate/peripheral.rs

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

4-
use either::Either;
55
use quote::{ToTokens, Tokens};
6-
use svd::{Cluster, ClusterInfo, Defaults, Peripheral, Register};
6+
use svd::{Cluster, ClusterInfo, Defaults, Peripheral, Register, RegisterCluster, RegisterInfo};
77
use syn::{self, Ident};
88

99
use errors::*;
@@ -12,25 +12,36 @@ use util::{self, ToSanitizedSnakeCase, ToSanitizedUpperCase, BITS_PER_BYTE};
1212
use generate::register;
1313

1414
pub fn render(
15-
p: &Peripheral,
15+
p_original: &Peripheral,
1616
all_peripherals: &[Peripheral],
1717
defaults: &Defaults,
1818
nightly: bool,
1919
) -> Result<Vec<Tokens>> {
2020
let mut out = vec![];
2121

22+
let p_derivedfrom = p_original.derived_from.as_ref().and_then(|s| {
23+
all_peripherals.iter().find(|x| x.name == *s)
24+
});
25+
26+
let p_merged = p_derivedfrom.map(|ancestor| p_original.derive_from(ancestor));
27+
let p = p_merged.as_ref().unwrap_or(p_original);
28+
29+
if p_original.derived_from.is_some() && p_derivedfrom.is_none() {
30+
eprintln!("Couldn't find derivedFrom original: {} for {}, skipping",
31+
p_original.derived_from.as_ref().unwrap(), p_original.name);
32+
return Ok(out);
33+
}
34+
2235
let name_pc = Ident::new(&*p.name.to_sanitized_upper_case());
2336
let address = util::hex(p.base_address);
2437
let description = util::escape_brackets(util::respace(p.description.as_ref().unwrap_or(&p.name)).as_ref());
38+
let derive_regs = p_derivedfrom.is_some() && p_original.registers.is_none();
2539

2640
let name_sc = Ident::new(&*p.name.to_sanitized_snake_case());
27-
let (base, derived) = if let Some(base) = p.derived_from.as_ref() {
28-
// TODO Verify that base exists
29-
// TODO We don't handle inheritance style `derivedFrom`, we should raise
30-
// an error in that case
31-
(Ident::new(&*base.to_sanitized_snake_case()), true)
41+
let base = if derive_regs {
42+
Ident::new(&*p_derivedfrom.unwrap().name.to_sanitized_snake_case())
3243
} else {
33-
(name_sc.clone(), false)
44+
name_sc.clone()
3445
};
3546

3647
// Insert the peripheral structure
@@ -56,17 +67,92 @@ pub fn render(
5667
}
5768
});
5869

59-
// Derived peripherals do not require re-implementation, and will instead
60-
// use a single definition of the non-derived version
61-
if derived {
70+
// Derived peripherals may not require re-implementation, and will instead
71+
// use a single definition of the non-derived version.
72+
if derive_regs {
6273
return Ok(out);
6374
}
6475

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

71157
// No `struct RegisterBlock` can be generated
72158
if registers.is_empty() && clusters.is_empty() {
@@ -77,7 +163,7 @@ pub fn render(
77163

78164
// Push any register or cluster blocks into the output
79165
let mut mod_items = vec![];
80-
mod_items.push(register_or_cluster_block(ercs, defaults, None, nightly)?);
166+
mod_items.push(register_or_cluster_block(ercs.as_slice(), defaults, None, nightly)?);
81167

82168
// Push all cluster related information into the peripheral module
83169
for c in &clusters {
@@ -346,7 +432,7 @@ impl FieldRegions {
346432
}
347433

348434
fn register_or_cluster_block(
349-
ercs: &[Either<Register, Cluster>],
435+
ercs: &[RegisterCluster],
350436
defs: &Defaults,
351437
name: Option<&str>,
352438
nightly: bool,
@@ -359,7 +445,7 @@ fn register_or_cluster_block(
359445
}
360446

361447
fn register_or_cluster_block_stable(
362-
ercs: &[Either<Register, Cluster>],
448+
ercs: &[RegisterCluster],
363449
defs: &Defaults,
364450
name: Option<&str>,
365451
) -> Result<Tokens> {
@@ -424,7 +510,7 @@ fn register_or_cluster_block_stable(
424510
}
425511

426512
fn register_or_cluster_block_nightly(
427-
ercs: &[Either<Register, Cluster>],
513+
ercs: &[RegisterCluster],
428514
defs: &Defaults,
429515
name: Option<&str>,
430516
) -> Result<Tokens> {
@@ -544,16 +630,16 @@ fn register_or_cluster_block_nightly(
544630
/// Expand a list of parsed `Register`s or `Cluster`s, and render them to
545631
/// `RegisterBlockField`s containing `Field`s.
546632
fn expand(
547-
ercs: &[Either<Register, Cluster>],
633+
ercs: &[RegisterCluster],
548634
defs: &Defaults,
549635
name: Option<&str>,
550636
) -> Result<Vec<RegisterBlockField>> {
551637
let mut ercs_expanded = vec![];
552638

553639
for erc in ercs {
554640
ercs_expanded.extend(match erc {
555-
Either::Left(ref register) => expand_register(register, defs, name)?,
556-
Either::Right(ref cluster) => expand_cluster(cluster, defs)?,
641+
RegisterCluster::Register(ref register) => expand_register(register, defs, name)?,
642+
RegisterCluster::Cluster(ref cluster) => expand_cluster(cluster, defs)?,
557643
});
558644
}
559645

@@ -569,15 +655,15 @@ fn cluster_size_in_bits(info: &ClusterInfo, defs: &Defaults) -> Result<u32> {
569655

570656
for c in &info.children {
571657
let end = match *c {
572-
Either::Left(ref reg) => {
658+
RegisterCluster::Register(ref reg) => {
573659
let reg_size: u32 = expand_register(reg, defs, None)?
574660
.iter()
575661
.map(|rbf| rbf.size)
576662
.sum();
577663

578664
(reg.address_offset * BITS_PER_BYTE) + reg_size
579665
}
580-
Either::Right(ref clust) => {
666+
RegisterCluster::Cluster(ref clust) => {
581667
(clust.address_offset * BITS_PER_BYTE) + cluster_size_in_bits(clust, defs)?
582668
}
583669
};

src/generate/register.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
use cast::u64;
2-
use either::Either;
32
use quote::Tokens;
4-
use svd::{Access, BitRange, Cluster, Defaults, EnumeratedValues, Field, Peripheral, Register,
5-
Usage, WriteConstraint};
3+
use svd::{Access, BitRange, Defaults, EnumeratedValues, Field, Peripheral, Register,
4+
RegisterCluster, Usage, WriteConstraint};
65
use syn::Ident;
76

87
use errors::*;
@@ -230,7 +229,8 @@ pub fn fields(
230229

231230
impl<'a> F<'a> {
232231
fn from(f: &'a Field) -> Result<Self> {
233-
let BitRange { offset, width } = f.bit_range;
232+
// TODO(AJM) - do we need to do anything with this range type?
233+
let BitRange { offset, width, range_type: _ } = f.bit_range;
234234
let sc = f.name.to_sanitized_snake_case();
235235
let pc = f.name.to_sanitized_upper_case();
236236
let pc_r = Ident::new(&*format!("{}R", pc));
@@ -1027,7 +1027,7 @@ fn lookup_in_peripherals<'p>(
10271027

10281028
fn periph_all_registers<'a>(p: &'a Peripheral) -> Vec<&'a Register> {
10291029
let mut par: Vec<&Register> = Vec::new();
1030-
let mut rem: Vec<&Either<Register, Cluster>> = Vec::new();
1030+
let mut rem: Vec<&RegisterCluster> = Vec::new();
10311031
if p.registers.is_none() {
10321032
return par;
10331033
}
@@ -1046,10 +1046,10 @@ fn periph_all_registers<'a>(p: &'a Peripheral) -> Vec<&'a Register> {
10461046

10471047
let b = b.unwrap();
10481048
match *b {
1049-
Either::Left(ref reg) => {
1049+
RegisterCluster::Register(ref reg) => {
10501050
par.push(reg);
10511051
}
1052-
Either::Right(ref cluster) => for c in cluster.children.iter() {
1052+
RegisterCluster::Cluster(ref cluster) => for c in cluster.children.iter() {
10531053
rem.push(c);
10541054
},
10551055
}

src/main.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,12 @@ fn run() -> Result<()> {
101101
let nightly = matches.is_present("nightly_features");
102102

103103
let mut device_x = String::new();
104-
let items = generate::device::render(&device, &target, nightly, &mut device_x)?;
104+
let items = generate::device::render(
105+
&device.expect("//TODO(AJM)"),
106+
&target,
107+
nightly,
108+
&mut device_x
109+
)?;
105110

106111
if target == Target::CortexM {
107112
writeln!(File::create("lib.rs").unwrap(), "{}", quote!(#(#items)*)).unwrap();

src/util.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
use std::borrow::Cow;
22

33
use inflections::Inflect;
4-
use svd::{Access, Cluster, Register};
4+
use svd::{Access, Cluster, Register, RegisterCluster};
55
use syn::Ident;
66
use quote::Tokens;
7-
use either::Either;
87

98
use errors::*;
109

@@ -271,21 +270,21 @@ impl U32Ext for u32 {
271270
}
272271

273272
/// Return only the clusters from the slice of either register or clusters.
274-
pub fn only_clusters(ercs: &[Either<Register, Cluster>]) -> Vec<&Cluster> {
273+
pub fn only_clusters(ercs: &[RegisterCluster]) -> Vec<&Cluster> {
275274
let clusters: Vec<&Cluster> = ercs.iter()
276275
.filter_map(|x| match *x {
277-
Either::Right(ref x) => Some(x),
276+
RegisterCluster::Cluster(ref x) => Some(x),
278277
_ => None,
279278
})
280279
.collect();
281280
clusters
282281
}
283282

284283
/// Return only the registers the given slice of either register or clusters.
285-
pub fn only_registers(ercs: &[Either<Register, Cluster>]) -> Vec<&Register> {
284+
pub fn only_registers(ercs: &[RegisterCluster]) -> Vec<&Register> {
286285
let registers: Vec<&Register> = ercs.iter()
287286
.filter_map(|x| match *x {
288-
Either::Left(ref x) => Some(x),
287+
RegisterCluster::Register(ref x) => Some(x),
289288
_ => None,
290289
})
291290
.collect();

0 commit comments

Comments
 (0)