Skip to content

Commit 98e66d9

Browse files
committed
process cluster rule simplify
1 parent dbc339b commit 98e66d9

File tree

2 files changed

+135
-55
lines changed

2 files changed

+135
-55
lines changed

CHANGELOG-rust.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ This changelog tracks the Rust `svdtools` project. See
99
* Add addressOffset check in `collect_in_cluster`
1010
* Refactor `RegisterBlockExt`, use `BlockPath` for better errors
1111
* Allow specs started with `_`
12+
* Allow process, `_delete` and `_modify` cluster without `_clusters` specifier
1213

1314
## [v0.3.11] 2024-03-06
1415

src/patch/peripheral.rs

Lines changed: 134 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,9 @@ pub(crate) trait RegisterBlockExt: Name {
131131
/// Get mutable register by name
132132
fn get_mut_reg(&mut self, name: &str) -> Option<&mut Register>;
133133

134+
/// Register/cluster block
135+
fn children(&self) -> Option<&Vec<RegisterCluster>>;
136+
134137
/// Register/cluster block
135138
fn children_mut(&mut self) -> Option<&mut Vec<RegisterCluster>>;
136139

@@ -156,6 +159,16 @@ pub(crate) trait RegisterBlockExt: Name {
156159

157160
fn add_child(&mut self, child: RegisterCluster);
158161

162+
/// Delete registers and clusters matched by rspec inside ptag
163+
fn delete_child(&mut self, rcspec: &str) -> PatchResult {
164+
if let Some(children) = self.children_mut() {
165+
children.retain(|rc| !matchname(rc.name(), rcspec));
166+
Ok(())
167+
} else {
168+
Err(anyhow!("No registers or clusters"))
169+
}
170+
}
171+
159172
/// Delete registers matched by rspec inside ptag
160173
fn delete_register(&mut self, rspec: &str) -> PatchResult {
161174
if let Some(children) = self.children_mut() {
@@ -301,31 +314,38 @@ pub(crate) trait RegisterBlockExt: Name {
301314
todo!()
302315
}
303316

317+
fn modify_child(&mut self, rcspec: &str, rcmod: &Hash, bpath: &BlockPath) -> PatchResult {
318+
let (rcspec, ignore) = rcspec.spec();
319+
let rtags = self.iter_registers(rcspec).collect::<Vec<_>>();
320+
if rtags.is_empty() && !ignore {
321+
let ctags = self.iter_clusters(rcspec).collect::<Vec<_>>();
322+
if ctags.is_empty() {
323+
let present = self.present_registers();
324+
Err(anyhow!(
325+
"Could not find `{bpath}:{rcspec}. Present registers: {present}.`"
326+
))
327+
} else {
328+
modify_cluster(ctags, rcmod)
329+
}
330+
} else {
331+
modify_register(rtags, rcmod)
332+
}
333+
}
334+
304335
/// Modify rspec inside ptag according to rmod
305-
fn modify_register(&mut self, rspec: &str, rmod: &Hash, _bpath: &BlockPath) -> PatchResult {
306-
let (rspec, _ignore) = rspec.spec();
336+
fn modify_register(&mut self, rspec: &str, rmod: &Hash, bpath: &BlockPath) -> PatchResult {
337+
let (rspec, ignore) = rspec.spec();
307338
let rtags = self.iter_registers(rspec).collect::<Vec<_>>();
308-
// TODO: enable this check
309-
/*if rtags.is_empty() && !ignore {
339+
if rtags.is_empty() && !ignore {
310340
let present = self.present_registers();
311341
return Err(anyhow!(
312342
"Could not find `{bpath}:{rspec}. Present registers: {present}.`"
313343
));
314-
}*/
315-
let register_builder = make_register(rmod)?;
316-
let dim = make_dim_element(rmod)?;
317-
for rtag in rtags {
318-
modify_dim_element(rtag, &dim)?;
319-
rtag.modify_from(register_builder.clone(), VAL_LVL)?;
320-
if let Some("") = rmod.get_str("access")? {
321-
rtag.properties.access = None;
322-
}
323344
}
324-
Ok(())
345+
modify_register(rtags, rmod)
325346
}
326347

327348
/// Modify cspec inside ptag according to cmod
328-
329349
fn modify_cluster(&mut self, cspec: &str, cmod: &Hash, bpath: &BlockPath) -> PatchResult {
330350
let (cspec, ignore) = cspec.spec();
331351
let ctags = self.iter_clusters(cspec).collect::<Vec<_>>();
@@ -335,13 +355,39 @@ pub(crate) trait RegisterBlockExt: Name {
335355
"Could not find cluster `{bpath}:{cspec}. Present clusters: {present}.`"
336356
));
337357
}
338-
let cluster_builder = make_cluster(cmod)?;
339-
let dim = make_dim_element(cmod)?;
340-
for ctag in ctags {
341-
modify_dim_element(ctag, &dim)?;
342-
ctag.modify_from(cluster_builder.clone(), VAL_LVL)?;
358+
modify_cluster(ctags, cmod)
359+
}
360+
/// Work through a register or cluster
361+
fn process_child(
362+
&mut self,
363+
rcspec: &str,
364+
rcmod: &Hash,
365+
bpath: &BlockPath,
366+
config: &Config,
367+
) -> PatchResult {
368+
let (rspec, ignore) = rcspec.spec();
369+
let rtags = self.iter_registers(rspec).collect::<Vec<_>>();
370+
if rtags.is_empty() && !ignore {
371+
let ctags = self.iter_clusters(rspec).collect::<Vec<_>>();
372+
if ctags.is_empty() {
373+
let present = self.present_registers();
374+
Err(anyhow!(
375+
"Could not find `{bpath}:{rspec}. Present registers: {present}.`"
376+
))
377+
} else {
378+
for ctag in ctags {
379+
ctag.process(rcmod, bpath, config)
380+
.with_context(|| format!("Processing cluster `{}`", ctag.name))?;
381+
}
382+
Ok(())
383+
}
384+
} else {
385+
for rtag in rtags {
386+
rtag.process(rcmod, bpath, config)
387+
.with_context(|| format!("Processing register `{}`", rtag.name))?;
388+
}
389+
Ok(())
343390
}
344-
Ok(())
345391
}
346392
/// Work through a register, handling all fields
347393
fn process_register(
@@ -507,6 +553,29 @@ pub(crate) trait RegisterBlockExt: Name {
507553
}
508554
}
509555

556+
fn modify_register(rtags: Vec<&mut Register>, rmod: &Hash) -> PatchResult {
557+
let register_builder = make_register(rmod)?;
558+
let dim = make_dim_element(rmod)?;
559+
for rtag in rtags {
560+
modify_dim_element(rtag, &dim)?;
561+
rtag.modify_from(register_builder.clone(), VAL_LVL)?;
562+
if let Some("") = rmod.get_str("access")? {
563+
rtag.properties.access = None;
564+
}
565+
}
566+
Ok(())
567+
}
568+
569+
fn modify_cluster(ctags: Vec<&mut Cluster>, cmod: &Hash) -> PatchResult {
570+
let cluster_builder = make_cluster(cmod)?;
571+
let dim = make_dim_element(cmod)?;
572+
for ctag in ctags {
573+
modify_dim_element(ctag, &dim)?;
574+
ctag.modify_from(cluster_builder.clone(), VAL_LVL)?;
575+
}
576+
Ok(())
577+
}
578+
510579
impl RegisterBlockExt for Peripheral {
511580
const RB_TYPE: &'static str = "peripheral";
512581

@@ -531,6 +600,9 @@ impl RegisterBlockExt for Peripheral {
531600
fn get_mut_reg(&mut self, name: &str) -> Option<&mut Register> {
532601
self.get_mut_register(name)
533602
}
603+
fn children(&self) -> Option<&Vec<RegisterCluster>> {
604+
self.registers.as_ref()
605+
}
534606
fn children_mut(&mut self) -> Option<&mut Vec<RegisterCluster>> {
535607
self.registers.as_mut()
536608
}
@@ -566,6 +638,9 @@ impl RegisterBlockExt for Cluster {
566638
fn get_mut_reg(&mut self, name: &str) -> Option<&mut Register> {
567639
self.get_mut_register(name)
568640
}
641+
fn children(&self) -> Option<&Vec<RegisterCluster>> {
642+
Some(&self.children)
643+
}
569644
fn children_mut(&mut self) -> Option<&mut Vec<RegisterCluster>> {
570645
Some(&mut self.children)
571646
}
@@ -617,15 +692,17 @@ impl PeripheralExt for Peripheral {
617692
// Handle deletions
618693
if let Some(deletions) = pmod.get_yaml("_delete") {
619694
match deletions {
620-
Yaml::String(rspec) => {
621-
self.delete_register(rspec)
622-
.with_context(|| format!("Deleting registers matched to `{rspec}`"))?;
695+
Yaml::String(rcspec) => {
696+
self.delete_child(rcspec).with_context(|| {
697+
format!("Deleting registers and clusters matched to `{rcspec}`")
698+
})?;
623699
}
624700
Yaml::Array(deletions) => {
625-
for rspec in deletions {
626-
let rspec = rspec.str()?;
627-
self.delete_register(rspec)
628-
.with_context(|| format!("Deleting registers matched to `{rspec}`"))?;
701+
for rcspec in deletions {
702+
let rcspec = rcspec.str()?;
703+
self.delete_child(rcspec).with_context(|| {
704+
format!("Deleting registers and clusters matched to `{rcspec}`")
705+
})?;
629706
}
630707
}
631708
Yaml::Hash(deletions) => {
@@ -716,16 +793,16 @@ impl PeripheralExt for Peripheral {
716793
})?;
717794
}
718795
}
719-
"_cluster" => {
796+
"_clusters" => {
720797
for (cspec, val) in rmod {
721798
let cspec = cspec.str()?;
722799
self.modify_cluster(cspec, val.hash()?, &ppath)
723800
.with_context(|| format!("Modifying clusters matched to `{cspec}`"))?;
724801
}
725802
}
726-
rspec => self
727-
.modify_register(rspec, rmod, &ppath)
728-
.with_context(|| format!("Modifying registers matched to `{rspec}`"))?,
803+
rcspec => self.modify_child(rcspec, rmod, &ppath).with_context(|| {
804+
format!("Modifying registers or clusters matched to `{rcspec}`")
805+
})?,
729806
}
730807
}
731808

@@ -795,14 +872,14 @@ impl PeripheralExt for Peripheral {
795872
}
796873
}
797874

798-
// Handle registers
799-
for (rspec, register) in pmod {
800-
let rspec = rspec.str()?;
801-
if Self::KEYWORDS.contains(&rspec) {
875+
// Handle registers or clusters
876+
for (rcspec, rcmod) in pmod {
877+
let rcspec = rcspec.str()?;
878+
if Self::KEYWORDS.contains(&rcspec) {
802879
continue;
803880
}
804-
self.process_register(rspec, register.hash()?, &ppath, config)
805-
.with_context(|| format!("According to `{rspec}`"))?;
881+
self.process_child(rcspec, rcmod.hash()?, &ppath, config)
882+
.with_context(|| format!("According to `{rcspec}`"))?;
806883
}
807884

808885
// Expand register arrays
@@ -874,15 +951,17 @@ impl ClusterExt for Cluster {
874951
// Handle deletions
875952
if let Some(deletions) = cmod.get_yaml("_delete") {
876953
match deletions {
877-
Yaml::String(rspec) => {
878-
self.delete_register(rspec)
879-
.with_context(|| format!("Deleting registers matched to `{rspec}`"))?;
954+
Yaml::String(rcspec) => {
955+
self.delete_child(rcspec).with_context(|| {
956+
format!("Deleting registers and clusters matched to `{rcspec}`")
957+
})?;
880958
}
881959
Yaml::Array(deletions) => {
882-
for rspec in deletions {
883-
let rspec = rspec.str()?;
884-
self.delete_register(rspec)
885-
.with_context(|| format!("Deleting registers matched to `{rspec}`"))?;
960+
for rcspec in deletions {
961+
let rcspec = rcspec.str()?;
962+
self.delete_child(rcspec).with_context(|| {
963+
format!("Deleting registers and clusters matched to `{rcspec}`")
964+
})?;
886965
}
887966
}
888967
Yaml::Hash(deletions) => {
@@ -963,16 +1042,16 @@ impl ClusterExt for Cluster {
9631042
.with_context(|| format!("Modifying registers matched to `{rspec}`"))?;
9641043
}
9651044
}
966-
"_cluster" => {
1045+
"_clusters" => {
9671046
for (cspec, val) in rmod {
9681047
let cspec = cspec.str()?;
9691048
self.modify_cluster(cspec, val.hash()?, &cpath)
9701049
.with_context(|| format!("Modifying clusters matched to `{cspec}`"))?;
9711050
}
9721051
}
973-
rspec => self
974-
.modify_register(rspec, rmod, &cpath)
975-
.with_context(|| format!("Modifying registers matched to `{rspec}`"))?,
1052+
rcspec => self.modify_child(rcspec, rmod, &cpath).with_context(|| {
1053+
format!("Modifying registers or clusters matched to `{rcspec}`")
1054+
})?,
9761055
}
9771056
}
9781057

@@ -1050,14 +1129,14 @@ impl ClusterExt for Cluster {
10501129
.with_context(|| format!("According to `{cspec}`"))?;
10511130
}
10521131

1053-
// Handle registers
1054-
for (rspec, register) in cmod {
1055-
let rspec = rspec.str()?;
1056-
if Self::KEYWORDS.contains(&rspec) {
1132+
// Handle registers or clusters
1133+
for (rcspec, rcmod) in cmod {
1134+
let rcspec = rcspec.str()?;
1135+
if Self::KEYWORDS.contains(&rcspec) {
10571136
continue;
10581137
}
1059-
self.process_register(rspec, register.hash()?, &cpath, config)
1060-
.with_context(|| format!("According to `{rspec}`"))?;
1138+
self.process_child(rcspec, rcmod.hash()?, &cpath, config)
1139+
.with_context(|| format!("According to `{rcspec}`"))?;
10611140
}
10621141

10631142
self.post_process(cmod, parent, config)

0 commit comments

Comments
 (0)