mirror of
https://gitlab.cern.ch/wotsubo/endcap-sl-software-ri-generator.git
synced 2025-04-19 03:06:13 +09:00
142 lines
4.3 KiB
Rust
142 lines
4.3 KiB
Rust
use std::path;
|
|
|
|
use itertools::Itertools;
|
|
use thiserror::Error;
|
|
|
|
use crate::{
|
|
converter, generator,
|
|
io::{get_xml_gitinfo, XmlGitInfoError},
|
|
types, validator,
|
|
};
|
|
|
|
#[derive(Debug, Error)]
|
|
pub enum Error {
|
|
#[error("error in getting xml git info: {0}")]
|
|
XmlGitInfoError(#[from] XmlGitInfoError),
|
|
#[error("io error: {0}")]
|
|
IOError(#[from] std::io::Error),
|
|
#[error("xml parse error: {0}")]
|
|
XmlParseError(#[from] roxmltree::Error),
|
|
#[error("dom conversion error: {0}")]
|
|
DomConversionError(#[from] converter::DomConversionError),
|
|
#[error("invalid register map:\n{}", ._0.iter().map(|e| e.to_string()).join("\n"))]
|
|
RegmapValidationError(Vec<validator::ValidationError>),
|
|
#[error("code generation error: {0}")]
|
|
CodeGenError(#[from] generator::CodeGenError),
|
|
#[cfg(feature = "flatmap")]
|
|
#[error("csv write error: {0}")]
|
|
CsvWriteError(#[from] csv::Error),
|
|
}
|
|
|
|
/// Generate register interface code from xml in `xml` and write them under directory `out`.
|
|
pub fn generate(xml: &path::Path, out: &path::Path) -> Result<(), Error> {
|
|
log::debug!("generate called: xml:{:?}, out: {:?}", xml, out);
|
|
|
|
let xml_git_info = get_xml_gitinfo(xml)?;
|
|
log::debug!("xml git info {xml_git_info:?}");
|
|
|
|
let xmlfile = std::fs::read_to_string(xml)?;
|
|
let doc = roxmltree::Document::parse_with_options(
|
|
&xmlfile,
|
|
roxmltree::ParsingOptions {
|
|
allow_dtd: true,
|
|
nodes_limit: u32::MAX,
|
|
},
|
|
)?;
|
|
log::debug!("xml parsed {doc:?}");
|
|
|
|
let register_map = types::Module::from_xml_dom(doc.root_element(), xml_git_info)?;
|
|
log::debug!("converted {register_map:?}");
|
|
|
|
let (_maps, errors) = register_map.validate();
|
|
if !errors.is_empty() {
|
|
return Err(Error::RegmapValidationError(errors));
|
|
}
|
|
|
|
let files = register_map.generate_code()?;
|
|
if log::log_enabled!(log::Level::Debug) {
|
|
for (path, code) in &files {
|
|
log::debug!("path: {:?}", path);
|
|
log::debug!("{}", prettyplease::unparse(code));
|
|
log::trace!("{}", prettyplease::unparse(code));
|
|
}
|
|
}
|
|
|
|
crate::write_to_files(files, out)?;
|
|
log::debug!("wrote to files");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[cfg(feature = "flatmap")]
|
|
pub fn generate_flatmap(xml: &path::Path, out: Option<&path::Path>) -> Result<(), Error> {
|
|
use std::{
|
|
fs::File,
|
|
io::{self, BufWriter, Write},
|
|
};
|
|
|
|
log::debug!("generate called: xml:{:?}, out: {:?}", xml, out);
|
|
|
|
let xml_git_info = get_xml_gitinfo(xml)?;
|
|
log::debug!("xml git info {xml_git_info:?}");
|
|
|
|
let xmlfile = std::fs::read_to_string(xml)?;
|
|
let doc = roxmltree::Document::parse_with_options(
|
|
&xmlfile,
|
|
roxmltree::ParsingOptions {
|
|
allow_dtd: true,
|
|
nodes_limit: u32::MAX,
|
|
},
|
|
)?;
|
|
log::debug!("xml parsed {doc:?}");
|
|
|
|
let register_map = types::Module::from_xml_dom(doc.root_element(), xml_git_info)?;
|
|
log::debug!("converted {register_map:?}");
|
|
|
|
let (maps, errors) = register_map.validate();
|
|
if !errors.is_empty() {
|
|
return Err(Error::RegmapValidationError(errors));
|
|
}
|
|
let f: Box<dyn Write> = match out {
|
|
Some(f) => {
|
|
let file = File::options().write(true).truncate(true).open(f)?;
|
|
Box::new(BufWriter::new(file))
|
|
}
|
|
None => Box::new(io::stdout()),
|
|
};
|
|
let mut wtr = csv::Writer::from_writer(f);
|
|
|
|
wtr.write_record([
|
|
"address",
|
|
"path",
|
|
"name",
|
|
"multiple_id",
|
|
"modf",
|
|
"description",
|
|
])?;
|
|
for (addr, reg) in maps.iter().enumerate() {
|
|
match reg {
|
|
Some(reg) => {
|
|
let path = reg.0.join("/");
|
|
let multiple_id = reg.2.map_or("".to_string(), |x| x.to_string());
|
|
wtr.write_record([
|
|
format!("0x{:04x}", addr),
|
|
path,
|
|
reg.1.name.clone(),
|
|
multiple_id,
|
|
reg.1.modf.to_string(),
|
|
reg.1.desc.as_ref().unwrap_or(&"".to_string()).to_string(),
|
|
])?;
|
|
}
|
|
None => wtr.write_record([
|
|
format!("0x{:04x}", addr),
|
|
"".to_string(),
|
|
"".to_string(),
|
|
"".to_string(),
|
|
"".to_string(),
|
|
"".to_string(),
|
|
])?,
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|