diff --git a/Cargo.lock b/Cargo.lock index 713961d..dfaf1ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,14 +2,141 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "anstyle-parse" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" +dependencies = [ + "anstyle", + "once_cell", + "windows-sys", +] + +[[package]] +name = "anyhow" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" + +[[package]] +name = "colorchoice" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" + [[package]] name = "endcap-sl-software-ri-generator" version = "0.1.0" dependencies = [ + "anyhow", + "env_logger", + "log", "roxmltree", "thiserror", ] +[[package]] +name = "env_filter" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "humantime", + "log", +] + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "log" +version = "0.4.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + [[package]] name = "proc-macro2" version = "1.0.93" @@ -28,6 +155,35 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + [[package]] name = "roxmltree" version = "0.20.0" @@ -70,3 +226,82 @@ name = "unicode-ident" version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/Cargo.toml b/Cargo.toml index dc47faa..8a02725 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,5 +12,8 @@ name = "endcap_sl_software_ri_generator" path = "src/lib.rs" [dependencies] +anyhow = "1.0.95" +env_logger = "0.11.6" +log = "0.4" roxmltree = "0.20" thiserror = "2.0" diff --git a/src/converter.rs b/src/converter.rs index 96fb98c..c9fcabe 100644 --- a/src/converter.rs +++ b/src/converter.rs @@ -5,10 +5,10 @@ use std::{num, str}; use roxmltree::{Node, TextPos}; use thiserror::Error; -use crate::parser::{ParseEnumError, ParsePrefixedU32, ParsePrefixedU32Error}; +use crate::parser::{ParseCustomBool, ParseEnumError, ParsePrefixedU32, ParsePrefixedU32Error}; use crate::types::{ - BitString, Block, DataType, Field, Fifo, Memory, Module, ModuleBlockElements, MultipleParams, - Register, Value, + BitString, Block, Field, Fifo, Memory, Module, ModuleBlockElements, MultipleParams, Register, + Value, }; #[derive(Debug, Error, PartialEq)] @@ -44,6 +44,11 @@ pub enum DomConversionError { pos: (TextPos, TextPos), found: String, }, + #[error("failed to complete/infer parameter {param}: {start} - {end}", start = pos.0, end = pos.1)] + ParameterCompletion { + param: &'static str, + pos: (TextPos, TextPos), + }, #[error("other dom conversion error: {0}")] OtherError(String), } @@ -88,6 +93,15 @@ impl DomConversionError { } } + fn parameter_completion_error(param: &'static str, node: Node) -> Self { + let range = node.range(); + let doc = node.document(); + Self::ParameterCompletion { + param, + pos: (doc.text_pos_at(range.start), doc.text_pos_at(range.end)), + } + } + fn invalid_node(found: String, node: Node) -> Self { let range = node.range(); let doc = node.document(); @@ -240,10 +254,7 @@ impl Block { Some(addr) => addr .parse_prefixed_u32() .map_err(|e| DomConversionError::parse_prefixed_u32_error(e, "addr", node))?, - None => { - // derive from parent - todo!("need to confirm") - } + None => 0, }; let r#type = match util::get_type(node).transpose()? { Some(x) => Some(x), @@ -305,7 +316,58 @@ impl Block { impl Register { pub(crate) fn from_xml_dom(node: Node) -> Result { - todo!("do here next") + let name = util::get_name(node)?; + let addr = match node.attribute("addr") { + Some(addr) => addr + .parse_prefixed_u32() + .map_err(|e| DomConversionError::parse_prefixed_u32_error(e, "addr", node))?, + None => 0, + }; + let mask = node + .attribute("mask") + .map(|addr| { + addr.parse_prefixed_u32() + .map_err(|e| DomConversionError::parse_prefixed_u32_error(e, "mask", node)) + }) + .transpose()?; + let modf = util::get_modf(node) + .transpose()? + .map_or_else( + || { + node.ancestors() + .filter_map(util::get_modf) + .next() + .transpose() + }, + |x| Ok(Some(x)), + )? + .ok_or_else(|| DomConversionError::parameter_completion_error("modf", node))?; + let multiple = MultipleParams::from_xml_dom(node)?; + let default = node + .attribute("default") + .map(|x| { + x.parse_prefixed_u32() + .map_err(|e| DomConversionError::parse_prefixed_u32_error(e, "default", node)) + }) + .transpose()?; + let desc = node.attribute("desc").map(str::to_string); + + let children = node + .children() + .filter(|node| node.is_element() && node.tag_name().name().eq("field")) + .map(Field::from_xml_dom) + .collect::>()?; + + Ok(Register { + name, + addr, + mask, + modf, + multiple, + default, + desc, + elements: children, + }) } } @@ -323,13 +385,82 @@ impl Fifo { impl Field { pub(crate) fn from_xml_dom(node: Node) -> Result { - todo!() + let name = util::get_name(node)?; + let mask = node + .attribute("mask") + .map(|addr| { + addr.parse_prefixed_u32() + .map_err(|e| DomConversionError::parse_prefixed_u32_error(e, "mask", node)) + }) + .transpose()? + .ok_or_else(|| DomConversionError::attr_not_found("mask", node))?; + let interface = node + .attribute("interface") + .map(|s| { + s.parse() + .map_err(|e| DomConversionError::parse_enum_error(e, "interface", node)) + }) + .transpose()?; + let multiple = MultipleParams::from_xml_dom(node)?; + let default = node + .attribute("default") + .map(|x| { + x.parse_prefixed_u32() + .map_err(|e| DomConversionError::parse_prefixed_u32_error(e, "default", node)) + }) + .transpose()?; + let sclr = node + .attribute("sclr") + .map(|s| { + s.parse_custom_bool() + .map_err(|e| DomConversionError::parse_enum_error(e, "sclr", node)) + }) + .transpose()?; + let desc = node.attribute("desc").map(str::to_string); + + let children = node + .children() + .filter(|node| node.is_element()) + .map(Value::from_xml_dom) + .collect::>()?; + + if let Some(default) = default { + if default & !(mask) != 0 { + log::warn!( + "default value {} doesn't fit mask {}: {} - {}", + default, + mask, + node.document().text_pos_at(node.range().start), + node.document().text_pos_at(node.range().end) + ) + } + } + + Ok(Field { + name, + mask, + interface, + multiple, + default, + sclr, + desc, + elements: children, + }) } } impl Value { pub(crate) fn from_xml_dom(node: Node) -> Result { - todo!() + let name = util::get_name(node)?; + let data = match node.attribute("data") { + Some(data) => data + .parse_prefixed_u32() + .map_err(|e| DomConversionError::parse_prefixed_u32_error(e, "data", node))?, + None => return Err(DomConversionError::attr_not_found("data", node)), + }; + let desc = node.attribute("desc").map(str::to_string); + + Ok(Value { name, data, desc }) } } @@ -338,8 +469,8 @@ impl MultipleParams { let multiple = match node .attribute("multiple") .map(|x| { - x.parse_prefixed_u32() - .map_err(|e| DomConversionError::parse_prefixed_u32_error(e, "multiple", node)) + x.parse() + .map_err(|e| DomConversionError::parse_int_error(e, "multiple", node)) }) .transpose()? { @@ -350,8 +481,8 @@ impl MultipleParams { let offset = match node .attribute("offset") .map(|x| { - x.parse_prefixed_u32() - .map_err(|e| DomConversionError::parse_prefixed_u32_error(e, "offset", node)) + x.parse() + .map_err(|e| DomConversionError::parse_int_error(e, "offset", node)) }) .transpose()? { diff --git a/src/main.rs b/src/main.rs index 11ce1eb..b042c79 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,26 +1,25 @@ use std::fs; +use anyhow::Result; use endcap_sl_software_ri_generator::types; -fn main() { +fn main() -> Result<()> { + env_logger::init(); + println!("Hello, world!"); - let xmlfile = fs::read_to_string("./csr.xml").unwrap(); + let xmlfile = fs::read_to_string("./csr.xml")?; let doc = roxmltree::Document::parse_with_options( &xmlfile, roxmltree::ParsingOptions { allow_dtd: true, nodes_limit: u32::MAX, }, - ) - .unwrap(); - println!("Parsed: {:#?}", doc); - println!("Root: {:?}", doc.root_element()); - { - let root = doc.root_element(); - println!("tag: {:?}", root.tag_name()); - let root_childs = root.children().filter(|node| node.is_element()); - println!("children: {:?}", root_childs); - } + )?; + // println!("Parsed: {:#?}", doc); + // println!("Root: {:?}", doc.root_element()); - let register_map = types::Module::from_xml_dom(doc.root_element()).unwrap(); + let register_map = types::Module::from_xml_dom(doc.root_element())?; + println!("read: {:#?}", register_map); + + Ok(()) } diff --git a/src/parser.rs b/src/parser.rs index 1afa7c7..41882ef 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -2,9 +2,9 @@ use std::any; +pub(crate) use parse_custom_bool::ParseCustomBool; pub(crate) use parse_prefixed_u32::ParsePrefixedU32; pub use parse_prefixed_u32::ParsePrefixedU32Error; -pub(crate) use parse_custom_bool::ParseCustomBool; use thiserror::Error; #[derive(Debug, Error, PartialEq)] @@ -29,7 +29,7 @@ mod parse_prefixed_u32 { #[derive(Debug, Error, PartialEq)] pub enum ParsePrefixedU32Error { - #[error("invalid prefix: found {found}")] + #[error("invalid prefix: found '{found}'")] InvalidPrefix { found: char }, #[error("parse int error")] ParseIntError(#[from] num::ParseIntError), @@ -45,7 +45,7 @@ mod parse_prefixed_u32 { Some('x') => 16, Some(c) if c.is_numeric() => 10, Some(c) => return Err(ParsePrefixedU32Error::InvalidPrefix { found: c }), - None => return Err(ParsePrefixedU32Error::InvalidPrefix { found: ' ' }), + None => 10, }; match radix {