mirror of
https://gitlab.cern.ch/wotsubo/endcap-sl-software-ri-generator.git
synced 2025-04-21 04:06:03 +09:00
Compare commits
No commits in common. "9971774a0142bdb807b79b1d18684d890b3ecce5" and "605228e2b53da59ffe5867c8db7f7fa18648f231" have entirely different histories.
9971774a01
...
605228e2b5
9 changed files with 6 additions and 428 deletions
|
@ -7,10 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
## [unreleased]
|
## [unreleased]
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Added register map validator and flattened map generator.
|
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Changed block, register type definitions to support multiple backends. See [the merge request at mpsoc software](https://gitlab.cern.ch/wotsubo/mpsoc-software/-/merge_requests/9) for more information.
|
- Changed block, register type definitions to support multiple backends. See [the merge request at mpsoc software](https://gitlab.cern.ch/wotsubo/mpsoc-software/-/merge_requests/9) for more information.
|
||||||
|
|
22
Cargo.lock
generated
22
Cargo.lock
generated
|
@ -260,27 +260,6 @@ dependencies = [
|
||||||
"typenum",
|
"typenum",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "csv"
|
|
||||||
version = "1.3.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf"
|
|
||||||
dependencies = [
|
|
||||||
"csv-core",
|
|
||||||
"itoa",
|
|
||||||
"ryu",
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "csv-core"
|
|
||||||
version = "0.1.12"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7d02f3b0da4c6504f86e9cd789d8dbafab48c2321be74e9987593de5a894d93d"
|
|
||||||
dependencies = [
|
|
||||||
"memchr",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "darling"
|
name = "darling"
|
||||||
version = "0.20.10"
|
version = "0.20.10"
|
||||||
|
@ -379,7 +358,6 @@ dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
"csv",
|
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"heck",
|
"heck",
|
||||||
"hex",
|
"hex",
|
||||||
|
|
|
@ -20,7 +20,6 @@ path = "src/lib.rs"
|
||||||
anyhow = { version = "1.0", optional = true }
|
anyhow = { version = "1.0", optional = true }
|
||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
clap = { version = "4.5", features = ["derive"] }
|
clap = { version = "4.5", features = ["derive"] }
|
||||||
csv = { version = "1.3.1", optional = true }
|
|
||||||
env_logger = { version = "0.11", optional = true }
|
env_logger = { version = "0.11", optional = true }
|
||||||
heck = "0.5"
|
heck = "0.5"
|
||||||
hex = "0.4"
|
hex = "0.4"
|
||||||
|
@ -39,4 +38,3 @@ vergen-gitcl = { version = "1.0", features = ["build", "cargo", "rustc", "si"] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
bin = ["anyhow", "env_logger"]
|
bin = ["anyhow", "env_logger"]
|
||||||
flatmap = ["csv"]
|
|
||||||
|
|
|
@ -219,8 +219,6 @@ impl CodeGen for Module {
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
let out = quote! {
|
let out = quote! {
|
||||||
#(#child_mods)*
|
#(#child_mods)*
|
||||||
|
|
||||||
pub use super::RegisterInterface;
|
|
||||||
};
|
};
|
||||||
files.insert(PathBuf::from("./register_interface.rs"), out);
|
files.insert(PathBuf::from("./register_interface.rs"), out);
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
use std::path;
|
use std::path;
|
||||||
|
|
||||||
use itertools::Itertools;
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
converter, generator,
|
converter, generator,
|
||||||
io::{get_xml_gitinfo, XmlGitInfoError},
|
io::{get_xml_gitinfo, XmlGitInfoError},
|
||||||
types, validator,
|
types,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
|
@ -19,13 +18,8 @@ pub enum Error {
|
||||||
XmlParseError(#[from] roxmltree::Error),
|
XmlParseError(#[from] roxmltree::Error),
|
||||||
#[error("dom conversion error: {0}")]
|
#[error("dom conversion error: {0}")]
|
||||||
DomConversionError(#[from] converter::DomConversionError),
|
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}")]
|
#[error("code generation error: {0}")]
|
||||||
CodeGenError(#[from] generator::CodeGenError),
|
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`.
|
/// Generate register interface code from xml in `xml` and write them under directory `out`.
|
||||||
|
@ -48,31 +42,6 @@ pub fn generate(xml: &path::Path, out: &path::Path) -> Result<(), Error> {
|
||||||
let register_map = types::Module::from_xml_dom(doc.root_element(), xml_git_info)?;
|
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() {
|
|
||||||
return Err(Error::RegmapValidationError(errors));
|
|
||||||
}
|
|
||||||
// TODO: this is a temporarily implementation
|
|
||||||
println!("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());
|
|
||||||
println!(
|
|
||||||
"0x{:04x},{},{},{},{},{},",
|
|
||||||
addr,
|
|
||||||
path,
|
|
||||||
reg.1.name,
|
|
||||||
multiple_id,
|
|
||||||
reg.1.modf,
|
|
||||||
reg.1.desc.as_ref().map_or_else(|| "", |s| s),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
None => println!("0x{:04x},,,,", addr),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let files = register_map.generate_code()?;
|
let files = register_map.generate_code()?;
|
||||||
if log::log_enabled!(log::Level::Debug) {
|
if log::log_enabled!(log::Level::Debug) {
|
||||||
for (path, code) in &files {
|
for (path, code) in &files {
|
||||||
|
@ -87,76 +56,3 @@ pub fn generate(xml: &path::Path, out: &path::Path) -> Result<(), Error> {
|
||||||
|
|
||||||
Ok(())
|
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(())
|
|
||||||
}
|
|
||||||
|
|
|
@ -31,7 +31,6 @@ pub mod meta;
|
||||||
mod parser;
|
mod parser;
|
||||||
mod type_traits;
|
mod type_traits;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
pub mod validator;
|
|
||||||
|
|
||||||
pub use integrated::generate;
|
pub use integrated::generate;
|
||||||
pub use io::write_to_files;
|
pub use io::write_to_files;
|
||||||
|
|
31
src/main.rs
31
src/main.rs
|
@ -1,7 +1,7 @@
|
||||||
use std::path;
|
use std::path;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::{Parser, Subcommand};
|
use clap::Parser;
|
||||||
|
|
||||||
/// Generate register interface from register map xml.
|
/// Generate register interface from register map xml.
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
|
@ -9,21 +9,8 @@ use clap::{Parser, Subcommand};
|
||||||
struct Args {
|
struct Args {
|
||||||
/// Input XML register map.
|
/// Input XML register map.
|
||||||
xml: path::PathBuf,
|
xml: path::PathBuf,
|
||||||
#[command(subcommand)]
|
/// Output directory.
|
||||||
command: Commands,
|
out: path::PathBuf,
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Subcommand)]
|
|
||||||
enum Commands {
|
|
||||||
Generate {
|
|
||||||
/// Output directory.
|
|
||||||
out: path::PathBuf,
|
|
||||||
},
|
|
||||||
#[cfg(feature = "flatmap")]
|
|
||||||
Flatmap {
|
|
||||||
/// Flattened csv out path.
|
|
||||||
flatmap: Option<path::PathBuf>,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
|
@ -32,17 +19,7 @@ fn main() -> Result<()> {
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
log::debug!("args: {:?}", args);
|
log::debug!("args: {:?}", args);
|
||||||
|
|
||||||
match args.command {
|
endcap_sl_software_ri_generator::generate(&args.xml, &args.out)?;
|
||||||
Commands::Generate { out } => endcap_sl_software_ri_generator::generate(&args.xml, &out)?,
|
|
||||||
#[cfg(feature = "flatmap")]
|
|
||||||
Commands::Flatmap { flatmap } => {
|
|
||||||
let outpath: Option<&path::Path> = match flatmap {
|
|
||||||
Some(ref p) => Some(p.as_path()),
|
|
||||||
None => None,
|
|
||||||
};
|
|
||||||
endcap_sl_software_ri_generator::integrated::generate_flatmap(&args.xml, outpath)?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
//! Util traits to get info from types in [`crate::types`].
|
//! Util traits to get info from types in [`crate::types`].
|
||||||
|
|
||||||
use std::fmt::Display;
|
use crate::types::{Block, ModuleBlockElements, Register};
|
||||||
|
|
||||||
use crate::types::{Block, ModuleBlockElements, Register, RwSpecifier};
|
|
||||||
|
|
||||||
pub(crate) trait GetName {
|
pub(crate) trait GetName {
|
||||||
fn get_name(&self) -> String;
|
fn get_name(&self) -> String;
|
||||||
|
@ -30,14 +28,3 @@ impl GetName for Register {
|
||||||
self.name.clone()
|
self.name.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for RwSpecifier {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
let s = match self {
|
|
||||||
RwSpecifier::R => "r",
|
|
||||||
RwSpecifier::W => "w",
|
|
||||||
RwSpecifier::RW => "rw",
|
|
||||||
};
|
|
||||||
write!(f, "{}", s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
251
src/validator.rs
251
src/validator.rs
|
@ -1,251 +0,0 @@
|
||||||
//! Validate the address assignment and generate a flattened register map.
|
|
||||||
|
|
||||||
use thiserror::Error;
|
|
||||||
|
|
||||||
use crate::types::{Block, Module, ModuleBlockElements, Register};
|
|
||||||
|
|
||||||
type FlattenedRegisterMap<'a> = Vec<Option<(Vec<&'a str>, &'a Register, Option<u32>)>>;
|
|
||||||
|
|
||||||
impl Module {
|
|
||||||
/// Validate the address assignment, generating a flatten register map.
|
|
||||||
pub fn validate(&self) -> (FlattenedRegisterMap, Vec<ValidationError>) {
|
|
||||||
let mut mapping = Vec::new();
|
|
||||||
mapping.resize(self.size.try_into().unwrap(), None);
|
|
||||||
let errors = Vec::new();
|
|
||||||
self.fill(mapping, errors, (0x0, Vec::new()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
|
||||||
pub enum ValidationError {
|
|
||||||
#[error("address duplicated at 0x{address:08x}: \"{existing_name}\", \"{new_name}\"")]
|
|
||||||
AddressDuplicated {
|
|
||||||
address: u32,
|
|
||||||
existing_name: String,
|
|
||||||
new_name: String,
|
|
||||||
},
|
|
||||||
#[error("unsupported structure: {msg}")]
|
|
||||||
UnsupportedStructure { msg: &'static str },
|
|
||||||
}
|
|
||||||
|
|
||||||
trait Validate {
|
|
||||||
fn fill<'a>(
|
|
||||||
&'a self,
|
|
||||||
mapping: FlattenedRegisterMap<'a>,
|
|
||||||
errors: Vec<ValidationError>,
|
|
||||||
base: (u32, Vec<&'a str>),
|
|
||||||
) -> (FlattenedRegisterMap<'a>, Vec<ValidationError>);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Validate for Module {
|
|
||||||
fn fill<'a>(
|
|
||||||
&'a self,
|
|
||||||
mut mapping: FlattenedRegisterMap<'a>,
|
|
||||||
mut errors: Vec<ValidationError>,
|
|
||||||
base: (u32, Vec<&'a str>),
|
|
||||||
) -> (FlattenedRegisterMap<'a>, Vec<ValidationError>) {
|
|
||||||
for child in &self.elements_other {
|
|
||||||
(mapping, errors) = child.fill(mapping, errors, base.clone());
|
|
||||||
}
|
|
||||||
(mapping, errors)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Validate for ModuleBlockElements {
|
|
||||||
fn fill<'a>(
|
|
||||||
&'a self,
|
|
||||||
mapping: FlattenedRegisterMap<'a>,
|
|
||||||
errors: Vec<ValidationError>,
|
|
||||||
base: (u32, Vec<&'a str>),
|
|
||||||
) -> (FlattenedRegisterMap<'a>, Vec<ValidationError>) {
|
|
||||||
match self {
|
|
||||||
ModuleBlockElements::Block(block) => block.fill(mapping, errors, base),
|
|
||||||
ModuleBlockElements::Register(register) => register.fill(mapping, errors, base),
|
|
||||||
ModuleBlockElements::Memory(_memory) => todo!(),
|
|
||||||
ModuleBlockElements::Fifo(_fifo) => todo!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Validate for Block {
|
|
||||||
fn fill<'a>(
|
|
||||||
&'a self,
|
|
||||||
mut mapping: FlattenedRegisterMap<'a>,
|
|
||||||
mut errors: Vec<ValidationError>,
|
|
||||||
base: (u32, Vec<&'a str>),
|
|
||||||
) -> (FlattenedRegisterMap<'a>, Vec<ValidationError>) {
|
|
||||||
if self.multiple.is_some() {
|
|
||||||
errors.push(ValidationError::UnsupportedStructure {
|
|
||||||
msg: "multiple in block",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let addr = base.0 + self.addr;
|
|
||||||
let mut path = base.1;
|
|
||||||
path.push(&self.name);
|
|
||||||
for child in &self.elements {
|
|
||||||
(mapping, errors) = child.fill(mapping, errors, (addr, path.clone()));
|
|
||||||
}
|
|
||||||
(mapping, errors)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Validate for Register {
|
|
||||||
fn fill<'a>(
|
|
||||||
&'a self,
|
|
||||||
mut mapping: FlattenedRegisterMap<'a>,
|
|
||||||
mut errors: Vec<ValidationError>,
|
|
||||||
base: (u32, Vec<&'a str>),
|
|
||||||
) -> (FlattenedRegisterMap<'a>, Vec<ValidationError>) {
|
|
||||||
let addr = base.0 + self.addr;
|
|
||||||
let path = base.1;
|
|
||||||
let (len, offset) = match &self.multiple {
|
|
||||||
Some(multiple) => (multiple.multiple, multiple.offset),
|
|
||||||
None => (1, 1),
|
|
||||||
};
|
|
||||||
for id in 0..len {
|
|
||||||
let addr = addr + id * offset;
|
|
||||||
let regmap: &mut Option<_> = mapping
|
|
||||||
.get_mut::<usize>(addr.try_into().unwrap())
|
|
||||||
.expect("index of mapping out of range");
|
|
||||||
if let Some(old) = regmap {
|
|
||||||
let existing_name = {
|
|
||||||
let mut path = old.0.clone();
|
|
||||||
path.push(&old.1.name);
|
|
||||||
path.join("/")
|
|
||||||
};
|
|
||||||
let new_name = {
|
|
||||||
let mut path = path.clone();
|
|
||||||
path.push(&self.name);
|
|
||||||
path.join("/")
|
|
||||||
};
|
|
||||||
errors.push(ValidationError::AddressDuplicated {
|
|
||||||
address: addr,
|
|
||||||
existing_name,
|
|
||||||
new_name,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
let multiple_id = if len == 1 { None } else { Some(id) };
|
|
||||||
*regmap = Some((path.clone(), self, multiple_id))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(mapping, errors)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use itertools::Itertools;
|
|
||||||
|
|
||||||
use crate::types::{
|
|
||||||
Module, ModuleBlockElements, MultipleParams, Register, RwSpecifier, XmlGitInfo,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn duplicate() {
|
|
||||||
let reg1 = Register {
|
|
||||||
name: "test1".to_string(),
|
|
||||||
addr: 0,
|
|
||||||
r#type: crate::types::DataType::D32,
|
|
||||||
mask: None,
|
|
||||||
modf: RwSpecifier::R,
|
|
||||||
multiple: None,
|
|
||||||
default: None,
|
|
||||||
desc: None,
|
|
||||||
elements: vec![],
|
|
||||||
};
|
|
||||||
let reg2 = Register {
|
|
||||||
name: "test1".to_string(),
|
|
||||||
addr: 0,
|
|
||||||
r#type: crate::types::DataType::D32,
|
|
||||||
mask: None,
|
|
||||||
modf: RwSpecifier::R,
|
|
||||||
multiple: None,
|
|
||||||
default: None,
|
|
||||||
desc: None,
|
|
||||||
elements: vec![],
|
|
||||||
};
|
|
||||||
let module = Module {
|
|
||||||
name: "module".to_string(),
|
|
||||||
addr: 0,
|
|
||||||
size: 0x10,
|
|
||||||
amod: None,
|
|
||||||
r#type: None,
|
|
||||||
desc: None,
|
|
||||||
elements_bitstring: vec![],
|
|
||||||
elements_other: vec![
|
|
||||||
ModuleBlockElements::Register(reg1),
|
|
||||||
ModuleBlockElements::Register(reg2),
|
|
||||||
],
|
|
||||||
xmlhash: [0; 32],
|
|
||||||
git_info: XmlGitInfo {
|
|
||||||
describe: "".to_string(),
|
|
||||||
commit_timestamp: "".to_string(),
|
|
||||||
sha: "".to_string(),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let (maps, errors) = module.validate();
|
|
||||||
eprintln!("{:#?}", maps);
|
|
||||||
eprintln!(
|
|
||||||
"{:#?}",
|
|
||||||
maps.iter().filter(|e| e.is_some()).collect_vec().len()
|
|
||||||
);
|
|
||||||
assert_eq!(maps.len(), 0x10);
|
|
||||||
assert!(!errors.is_empty());
|
|
||||||
assert_eq!(maps.iter().filter(|e| e.is_some()).collect_vec().len(), 0x1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn duplicate_with_multiple() {
|
|
||||||
let reg1 = Register {
|
|
||||||
name: "test1".to_string(),
|
|
||||||
addr: 0,
|
|
||||||
r#type: crate::types::DataType::D32,
|
|
||||||
mask: None,
|
|
||||||
modf: RwSpecifier::R,
|
|
||||||
multiple: Some(MultipleParams {
|
|
||||||
multiple: 16,
|
|
||||||
offset: 1,
|
|
||||||
}),
|
|
||||||
default: None,
|
|
||||||
desc: None,
|
|
||||||
elements: vec![],
|
|
||||||
};
|
|
||||||
let reg2 = Register {
|
|
||||||
name: "test1".to_string(),
|
|
||||||
addr: 15,
|
|
||||||
r#type: crate::types::DataType::D32,
|
|
||||||
mask: None,
|
|
||||||
modf: RwSpecifier::R,
|
|
||||||
multiple: None,
|
|
||||||
default: None,
|
|
||||||
desc: None,
|
|
||||||
elements: vec![],
|
|
||||||
};
|
|
||||||
let module = Module {
|
|
||||||
name: "module".to_string(),
|
|
||||||
addr: 0,
|
|
||||||
size: 0x1000,
|
|
||||||
amod: None,
|
|
||||||
r#type: None,
|
|
||||||
desc: None,
|
|
||||||
elements_bitstring: vec![],
|
|
||||||
elements_other: vec![
|
|
||||||
ModuleBlockElements::Register(reg1),
|
|
||||||
ModuleBlockElements::Register(reg2),
|
|
||||||
],
|
|
||||||
xmlhash: [0; 32],
|
|
||||||
git_info: XmlGitInfo {
|
|
||||||
describe: "".to_string(),
|
|
||||||
commit_timestamp: "".to_string(),
|
|
||||||
sha: "".to_string(),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let (maps, errors) = module.validate();
|
|
||||||
assert_eq!(maps.len(), 0x1000);
|
|
||||||
assert_eq!(errors.len(), 1);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue