Skip to content

Commit c0df912

Browse files
committed
_derive register (Rust)
1 parent 539f169 commit c0df912

File tree

2 files changed

+96
-20
lines changed

2 files changed

+96
-20
lines changed

src/patch/device.rs

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use anyhow::{anyhow, Context};
22
use svd_parser::svd::{Device, Peripheral, PeripheralInfo};
3-
use yaml_rust::yaml::Hash;
3+
use yaml_rust::{yaml::Hash, Yaml};
44

55
use std::{fs::File, io::Read, path::Path};
66

@@ -54,7 +54,7 @@ pub trait DeviceExt {
5454

5555
/// Remove registers from pname and mark it as derivedFrom pderive.
5656
/// Update all derivedFrom referencing pname
57-
fn derive_peripheral(&mut self, pname: &str, pderive: &str) -> PatchResult;
57+
fn derive_peripheral(&mut self, pname: &str, pderive: &Yaml) -> PatchResult;
5858

5959
/// Move registers from pold to pnew.
6060
/// Update all derivedFrom referencing pold
@@ -163,9 +163,8 @@ impl DeviceExt for Device {
163163
// Handle any derived peripherals
164164
for (pname, pderive) in device.hash_iter("_derive") {
165165
let pname = pname.str()?;
166-
let pderive = pderive.str()?;
167166
self.derive_peripheral(pname, pderive)
168-
.with_context(|| format!("Deriving peripheral `{}` from `{}`", pname, pderive))?;
167+
.with_context(|| format!("Deriving peripheral `{}` from `{:?}`", pname, pderive))?;
169168
}
170169

171170
// Handle any rebased peripherals
@@ -288,15 +287,37 @@ impl DeviceExt for Device {
288287
Ok(())
289288
}
290289

291-
fn derive_peripheral(&mut self, pname: &str, pderive: &str) -> PatchResult {
290+
fn derive_peripheral(&mut self, pname: &str, pderive: &Yaml) -> PatchResult {
291+
let (pderive, info) = if let Some(pderive) = pderive.as_str() {
292+
(
293+
pderive,
294+
PeripheralInfo::builder().derived_from(Some(pderive.into())),
295+
)
296+
} else if let Some(hash) = pderive.as_hash() {
297+
let pderive = hash.get_str("_from")?.ok_or_else(|| {
298+
anyhow!(
299+
"derive: source peripheral not given, please add a _from field to {}",
300+
pname
301+
)
302+
})?;
303+
(
304+
pderive,
305+
make_peripheral(hash, true)?.derived_from(Some(pderive.into())),
306+
)
307+
} else {
308+
return Err(anyhow!("derive: incorrect syntax for {}", pname));
309+
};
292310
self.get_peripheral(pderive)
293311
.ok_or_else(|| anyhow!("peripheral {} not found", pderive))?;
294-
self.get_mut_peripheral(pname)
295-
.ok_or_else(|| anyhow!("peripheral {} not found", pname))?
296-
.modify_from(
297-
PeripheralInfo::builder().derived_from(Some(pderive.into())),
298-
VAL_LVL,
299-
)?;
312+
313+
match self.get_mut_peripheral(pname) {
314+
Some(peripheral) => peripheral.modify_from(info, VAL_LVL)?,
315+
None => {
316+
let peripheral = info.name(pname.into()).build(VAL_LVL)?.single();
317+
self.peripherals.push(peripheral);
318+
}
319+
}
320+
300321
for p in self
301322
.peripherals
302323
.iter_mut()

src/patch/peripheral.rs

Lines changed: 64 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ pub trait PeripheralExt {
4646
/// Add rname given by radd to ptag
4747
fn add_register(&mut self, rname: &str, radd: &Hash) -> PatchResult;
4848

49+
/// Remove fields from rname and mark it as derivedFrom rderive.
50+
/// Update all derivedFrom referencing rname
51+
fn derive_register(&mut self, rname: &str, rderive: &Yaml) -> PatchResult;
52+
4953
/// Add rname given by deriving from rsource to ptag
5054
fn copy_register(&mut self, rname: &str, rderive: &Hash) -> PatchResult;
5155

@@ -158,6 +162,14 @@ impl PeripheralExt for Peripheral {
158162
}
159163
}
160164

165+
// Handle any copied peripherals
166+
for (rname, rderive) in pmod.hash_iter("_copy") {
167+
let rderive = rderive.hash()?;
168+
let rname = rname.str()?;
169+
self.copy_register(rname, rderive)
170+
.with_context(|| format!("Copying register `{}`", rname))?
171+
}
172+
161173
// Handle modifications
162174
for (rspec, rmod) in pmod.hash_iter("_modify") {
163175
let rmod = rmod.hash()?;
@@ -237,25 +249,27 @@ impl PeripheralExt for Peripheral {
237249
}
238250

239251
for (rname, rderive) in pmod.hash_iter("_derive") {
240-
let rderive = rderive.hash()?;
241252
let rname = rname.str()?;
242253
match rname {
243254
"_registers" => {
244-
for (rname, val) in rderive {
255+
for (rname, val) in rderive.hash()? {
245256
let rname = rname.str()?;
246-
self.copy_register(rname, val.hash()?)
247-
.with_context(|| format!("Copying register `{}`", rname))?;
257+
self.derive_register(rname, val).with_context(|| {
258+
format!("Deriving register `{}` from `{:?}`", rname, val)
259+
})?;
248260
}
249261
}
250-
"_interrupts" => {
262+
"_clusters" => {
251263
return Err(anyhow!(
252-
"deriving interrupts not implemented yet: {}",
264+
"deriving clusters is not implemented yet: {}",
253265
rname
254266
))
255267
}
256-
_ => self
257-
.copy_register(rname, rderive)
258-
.with_context(|| format!("Copying register `{}`", rname))?,
268+
_ => {
269+
self.derive_register(rname, rderive).with_context(|| {
270+
format!("Deriving register `{}` from `{:?}`", rname, rderive)
271+
})?;
272+
}
259273
}
260274
}
261275

@@ -343,6 +357,47 @@ impl PeripheralExt for Peripheral {
343357
Ok(())
344358
}
345359

360+
fn derive_register(&mut self, rname: &str, rderive: &Yaml) -> PatchResult {
361+
let (rderive, info) = if let Some(rderive) = rderive.as_str() {
362+
(
363+
rderive,
364+
RegisterInfo::builder().derived_from(Some(rderive.into())),
365+
)
366+
} else if let Some(hash) = rderive.as_hash() {
367+
let rderive = hash.get_str("_from")?.ok_or_else(|| {
368+
anyhow!(
369+
"derive: source register not given, please add a _from field to {}",
370+
rname
371+
)
372+
})?;
373+
(
374+
rderive,
375+
make_register(hash)?.derived_from(Some(rderive.into())),
376+
)
377+
} else {
378+
return Err(anyhow!("derive: incorrect syntax for {}", rname));
379+
};
380+
self.get_register(rderive)
381+
.ok_or_else(|| anyhow!("register {} not found", rderive))?;
382+
383+
match self.get_mut_register(rname) {
384+
Some(register) => register.modify_from(info, VAL_LVL)?,
385+
None => {
386+
let register = info.name(rname.into()).build(VAL_LVL)?.single();
387+
self.registers
388+
.get_or_insert_with(Default::default)
389+
.push(RegisterCluster::Register(register));
390+
}
391+
}
392+
for r in self
393+
.registers_mut()
394+
.filter(|r| r.derived_from.as_deref() == Some(rname))
395+
{
396+
r.derived_from = Some(rderive.into());
397+
}
398+
Ok(())
399+
}
400+
346401
fn copy_register(&mut self, rname: &str, rderive: &Hash) -> PatchResult {
347402
let srcname = rderive.get_str("_from")?.ok_or_else(|| {
348403
anyhow!(

0 commit comments

Comments
 (0)