new: implement converter (Successfully read current CSR XML)

This commit is contained in:
Wataru Otsubo 2025-01-31 00:36:19 +09:00
parent 51a074d2c0
commit 53c8cbd90f
5 changed files with 398 additions and 30 deletions

View file

@ -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<Self, DomConversionError> {
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::<Result<_, _>>()?;
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<Self, DomConversionError> {
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::<Result<_, _>>()?;
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<Self, DomConversionError> {
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()?
{

View file

@ -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(())
}

View file

@ -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 {