From 27f2f75ee2603310898665d059e05d2029dbe5ce Mon Sep 17 00:00:00 2001 From: Wataru Otsubo Date: Thu, 24 Apr 2025 03:04:04 +0900 Subject: [PATCH 1/6] add(converter): support value under register, by inserting field during conversion --- src/converter.rs | 57 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 52 insertions(+), 5 deletions(-) diff --git a/src/converter.rs b/src/converter.rs index 27d78b0..472ef0f 100644 --- a/src/converter.rs +++ b/src/converter.rs @@ -389,11 +389,19 @@ impl Register { .transpose()?; let desc = node.attribute("desc").map(str::to_string); - let children: Vec<_> = node - .children() - .filter(|node| node.is_element() && node.tag_name().name().eq("field")) - .map(Field::from_xml_dom) - .collect::>()?; + let children: Vec<_> = { + let mut child_elements = node.children().filter(|node| node.is_element()); + if child_elements.any(|node| node.tag_name().name().eq("value")) { + // Generate virtual single field under the register, to absorb difference between + // normal format + vec![Field::from_xml_register_dom(node)?] + } else { + child_elements + .filter(|node| node.tag_name().name().eq("field")) + .map(Field::from_xml_dom) + .collect::>()? + } + }; // Validation if default.is_some() && !children.is_empty() { @@ -505,6 +513,45 @@ impl Field { elements: children, }) } + + /// Generate Field from Registers (piracy), guessing a lot of parameters. + pub(crate) fn from_xml_register_dom(node: Node) -> Result { + let name = util::get_name(node)?; + let mask = node + .ancestors() + .filter_map(|node| util::get_type(node)) + .next() + .transpose()? + .map_or_else( + || Err(DomConversionError::parameter_completion_error("type", node)), + |dtype| match dtype { + crate::types::DataType::D32 => Ok(u32::MAX), + }, + )?; + if node.has_attribute("default") { + return Err(DomConversionError::other_error( + "unsupported structure: register with @default without field", + node, + )); + } + let desc = node.attribute("desc").map(str::to_string); + let children = node + .children() + .filter(|node| node.is_element()) + .map(Value::from_xml_dom) + .collect::>()?; + + Ok(Field { + name, + mask, + interface: None, + multiple: None, + default: None, + sclr: None, + desc, + elements: children, + }) + } } impl Value { From 6ee8239682ff140c793952a83a9ba15639ebc04a Mon Sep 17 00:00:00 2001 From: Wataru Otsubo Date: Thu, 24 Apr 2025 03:06:26 +0900 Subject: [PATCH 2/6] update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5212799..9adca3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Packagin with Nix flakes (with nixpkgs buildRustPackage) [!16](https://gitlab.cern.ch/wotsubo/endcap-sl-software-ri-generator/-/merge_requests/16) - Now xml metadata can be overwritten with corresponding environmental variables. [!17](https://gitlab.cern.ch/wotsubo/endcap-sl-software-ri-generator/-/merge_requests/17) +- Support value element just under the register element by inserting single field during conversion. [!3](https://gitlab.cern.ch/wotsubo/endcap-sl-software-ri-generator/-/merge_requests/18) ### Changed From 3379babe12f7d651d804b6c6c2d99558caae216d Mon Sep 17 00:00:00 2001 From: Wataru Otsubo Date: Thu, 24 Apr 2025 03:11:08 +0900 Subject: [PATCH 3/6] fix(converter): use mask of parent register for virtual field if exists --- src/converter.rs | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/converter.rs b/src/converter.rs index 472ef0f..fbdf7f1 100644 --- a/src/converter.rs +++ b/src/converter.rs @@ -517,17 +517,22 @@ impl Field { /// Generate Field from Registers (piracy), guessing a lot of parameters. pub(crate) fn from_xml_register_dom(node: Node) -> Result { let name = util::get_name(node)?; - let mask = node - .ancestors() - .filter_map(|node| util::get_type(node)) - .next() - .transpose()? - .map_or_else( - || Err(DomConversionError::parameter_completion_error("type", node)), - |dtype| match dtype { - crate::types::DataType::D32 => Ok(u32::MAX), - }, - )?; + let mask = match node.attribute("mask") { + Some(mask) => mask + .parse_prefixed_u32() + .map_err(|e| DomConversionError::parse_prefixed_u32_error(e, "mask", node))?, + None => node + .ancestors() + .filter_map(|node| util::get_type(node)) + .next() + .transpose()? + .map_or_else( + || Err(DomConversionError::parameter_completion_error("type", node)), + |dtype| match dtype { + crate::types::DataType::D32 => Ok(u32::MAX), + }, + )?, + }; if node.has_attribute("default") { return Err(DomConversionError::other_error( "unsupported structure: register with @default without field", From e6f09d684a2ed369ed0c4166eefbaee87723e1d8 Mon Sep 17 00:00:00 2001 From: Wataru Otsubo Date: Tue, 20 May 2025 18:09:10 +0900 Subject: [PATCH 4/6] fix(converter): prepend "val_" to avoid name confliction with register obj --- src/converter.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/converter.rs b/src/converter.rs index fbdf7f1..7ab276a 100644 --- a/src/converter.rs +++ b/src/converter.rs @@ -514,9 +514,10 @@ impl Field { }) } - /// Generate Field from Registers (piracy), guessing a lot of parameters. + /// Generate virtual Field from Registers node (piracy), guessing a lot of parameters. pub(crate) fn from_xml_register_dom(node: Node) -> Result { - let name = util::get_name(node)?; + // Prepend "val_" to avoid name confliction with struct for accessing values + let name = "val_".to_string() + &util::get_name(node)?; let mask = match node.attribute("mask") { Some(mask) => mask .parse_prefixed_u32() @@ -539,6 +540,7 @@ impl Field { node, )); } + // Duplicated with parent (register) desc so should be removed, or add some comment? let desc = node.attribute("desc").map(str::to_string); let children = node .children() From 83e0c6cb3d60b5c112e070bdbb525c48c404868d Mon Sep 17 00:00:00 2001 From: Wataru Otsubo Date: Tue, 20 May 2025 18:49:01 +0900 Subject: [PATCH 5/6] fix(converter): wrong iterator usage all iterator was consumed for searching value before collecting field --- src/converter.rs | 10 +++++++--- src/integrated.rs | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/converter.rs b/src/converter.rs index 7ab276a..2b9ecad 100644 --- a/src/converter.rs +++ b/src/converter.rs @@ -390,13 +390,17 @@ impl Register { let desc = node.attribute("desc").map(str::to_string); let children: Vec<_> = { - let mut child_elements = node.children().filter(|node| node.is_element()); - if child_elements.any(|node| node.tag_name().name().eq("value")) { + if node + .children() + .filter(|node| node.is_element()) + .any(|node| node.tag_name().name().eq("value")) + { // Generate virtual single field under the register, to absorb difference between // normal format vec![Field::from_xml_register_dom(node)?] } else { - child_elements + node.children() + .filter(|node| node.is_element()) .filter(|node| node.tag_name().name().eq("field")) .map(Field::from_xml_dom) .collect::>()? diff --git a/src/integrated.rs b/src/integrated.rs index 341c448..0d64ee8 100644 --- a/src/integrated.rs +++ b/src/integrated.rs @@ -46,7 +46,7 @@ pub fn generate(xml: &path::Path, out: &path::Path) -> Result<(), Error> { log::debug!("xml parsed {doc:?}"); let register_map = types::Module::from_xml_dom(doc.root_element(), xml_git_info)?; - log::debug!("converted {register_map:?}"); + log::debug!("converted {register_map:#?}"); let (_maps, errors) = register_map.validate(); if !errors.is_empty() { From eee043cd0f785780d4f7b32edac90244dbf900b8 Mon Sep 17 00:00:00 2001 From: Wataru Otsubo Date: Tue, 20 May 2025 18:55:07 +0900 Subject: [PATCH 6/6] change(converter): name "field" for autogened virtual field instead of val_ prefixed register name --- src/converter.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/converter.rs b/src/converter.rs index 2b9ecad..2fcc4a4 100644 --- a/src/converter.rs +++ b/src/converter.rs @@ -520,8 +520,9 @@ impl Field { /// Generate virtual Field from Registers node (piracy), guessing a lot of parameters. pub(crate) fn from_xml_register_dom(node: Node) -> Result { - // Prepend "val_" to avoid name confliction with struct for accessing values - let name = "val_".to_string() + &util::get_name(node)?; + // // Prepend "val_" to avoid name confliction with struct for accessing values + // let name = "val_".to_string() + &util::get_name(node)?; + let name = "field".to_string(); let mask = match node.attribute("mask") { Some(mask) => mask .parse_prefixed_u32()