mirror of
https://gitlab.cern.ch/wotsubo/endcap-sl-software-ri-generator.git
synced 2025-04-20 11:46:04 +09:00
Allow mask definition in register with fields, iff they match
This commit is contained in:
parent
205b08400b
commit
fa777f43fb
3 changed files with 165 additions and 10 deletions
|
@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added register map validator and flattened map generator.
|
- Added register map validator and flattened map generator.
|
||||||
|
- Allow register with mask and fields iff the masks are matched.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|
|
@ -396,12 +396,6 @@ impl Register {
|
||||||
.collect::<Result<_, _>>()?;
|
.collect::<Result<_, _>>()?;
|
||||||
|
|
||||||
// Validation
|
// Validation
|
||||||
if mask.is_some() && !children.is_empty() {
|
|
||||||
return Err(DomConversionError::other_error(
|
|
||||||
"both mask and field are used in the same register",
|
|
||||||
node,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
if default.is_some() && !children.is_empty() {
|
if default.is_some() && !children.is_empty() {
|
||||||
return Err(DomConversionError::other_error(
|
return Err(DomConversionError::other_error(
|
||||||
"both default and field are used in the same register",
|
"both default and field are used in the same register",
|
||||||
|
|
168
src/validator.rs
168
src/validator.rs
|
@ -28,7 +28,7 @@ impl Module {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error, PartialEq)]
|
||||||
pub enum ValidationError {
|
pub enum ValidationError {
|
||||||
#[error("address duplicated at 0x{address:08x}: \"{existing_name}\", \"{new_name}\"")]
|
#[error("address duplicated at 0x{address:08x}: \"{existing_name}\", \"{new_name}\"")]
|
||||||
RegisterAddressDuplicated {
|
RegisterAddressDuplicated {
|
||||||
|
@ -44,6 +44,13 @@ pub enum ValidationError {
|
||||||
reg_name: String,
|
reg_name: String,
|
||||||
duplicated_mask: u32,
|
duplicated_mask: u32,
|
||||||
},
|
},
|
||||||
|
#[error("register \"{name}\" at 0x{address:08x} has mask 0x{reg_mask:08x} that doesn't match sum of field masks: 0x{fields_mask:08x}")]
|
||||||
|
RegisterAndFieldMaskMismatch {
|
||||||
|
address: u32,
|
||||||
|
name: String,
|
||||||
|
reg_mask: u32,
|
||||||
|
fields_mask: u32,
|
||||||
|
},
|
||||||
#[error("unsupported structure: {msg}")]
|
#[error("unsupported structure: {msg}")]
|
||||||
UnsupportedStructure { msg: &'static str },
|
UnsupportedStructure { msg: &'static str },
|
||||||
}
|
}
|
||||||
|
@ -131,7 +138,13 @@ impl Validate for Register {
|
||||||
.elements
|
.elements
|
||||||
.iter()
|
.iter()
|
||||||
.fold((0, 0), |(sum, _duplicate_bits), field| {
|
.fold((0, 0), |(sum, _duplicate_bits), field| {
|
||||||
(sum + field.mask, sum & field.mask)
|
let field_mask = match &field.multiple {
|
||||||
|
Some(multiple) => (0..multiple.multiple)
|
||||||
|
.map(|multiple_id| field.mask << (multiple.offset * multiple_id))
|
||||||
|
.sum(),
|
||||||
|
None => field.mask,
|
||||||
|
};
|
||||||
|
(sum + field_mask, sum & field_mask)
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
if duplicate_bits != 0 {
|
if duplicate_bits != 0 {
|
||||||
|
@ -142,6 +155,18 @@ impl Validate for Register {
|
||||||
});
|
});
|
||||||
return (mapping, errors);
|
return (mapping, errors);
|
||||||
}
|
}
|
||||||
|
if let Some(mask) = self.mask {
|
||||||
|
let has_fields = !self.elements.is_empty();
|
||||||
|
if has_fields && mask != reg_mask {
|
||||||
|
errors.push(ValidationError::RegisterAndFieldMaskMismatch {
|
||||||
|
address: addr,
|
||||||
|
name: new_name.clone(),
|
||||||
|
reg_mask: mask,
|
||||||
|
fields_mask: reg_mask,
|
||||||
|
});
|
||||||
|
return (mapping, errors);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let (len, offset) = match &self.multiple {
|
let (len, offset) = match &self.multiple {
|
||||||
Some(multiple) => (multiple.multiple, multiple.offset),
|
Some(multiple) => (multiple.multiple, multiple.offset),
|
||||||
|
@ -213,8 +238,11 @@ impl Validate for Register {
|
||||||
mod test {
|
mod test {
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
use crate::types::{
|
use crate::{
|
||||||
Field, Module, ModuleBlockElements, MultipleParams, Register, RwSpecifier, XmlGitInfo,
|
types::{
|
||||||
|
Field, Module, ModuleBlockElements, MultipleParams, Register, RwSpecifier, XmlGitInfo,
|
||||||
|
},
|
||||||
|
validator::ValidationError,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -422,4 +450,136 @@ mod test {
|
||||||
assert!(errors.is_empty());
|
assert!(errors.is_empty());
|
||||||
assert_eq!(maps.iter().filter(|e| e.is_some()).collect_vec().len(), 0x1);
|
assert_eq!(maps.iter().filter(|e| e.is_some()).collect_vec().len(), 0x1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn register_with_mask_and_field() {
|
||||||
|
let reg1 = Register {
|
||||||
|
name: "test1".to_string(),
|
||||||
|
addr: 0,
|
||||||
|
r#type: crate::types::DataType::D32,
|
||||||
|
mask: Some(0x000f_00ff),
|
||||||
|
modf: RwSpecifier::R,
|
||||||
|
multiple: None,
|
||||||
|
default: None,
|
||||||
|
desc: None,
|
||||||
|
elements: vec![
|
||||||
|
Field {
|
||||||
|
name: "field_1".to_string(),
|
||||||
|
mask: 0x0000_0001,
|
||||||
|
interface: None,
|
||||||
|
multiple: Some(MultipleParams {
|
||||||
|
multiple: 8,
|
||||||
|
offset: 1,
|
||||||
|
}),
|
||||||
|
default: None,
|
||||||
|
sclr: None,
|
||||||
|
desc: Some("field 1 description".to_string()),
|
||||||
|
elements: vec![],
|
||||||
|
},
|
||||||
|
Field {
|
||||||
|
name: "field_2".to_string(),
|
||||||
|
mask: 0x0003_0000,
|
||||||
|
interface: None,
|
||||||
|
multiple: Some(MultipleParams {
|
||||||
|
multiple: 2,
|
||||||
|
offset: 2,
|
||||||
|
}),
|
||||||
|
default: None,
|
||||||
|
sclr: None,
|
||||||
|
desc: Some("field 1 description".to_string()),
|
||||||
|
elements: vec![],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
let module = Module {
|
||||||
|
name: "module".to_string(),
|
||||||
|
addr: 0,
|
||||||
|
size: 0x1,
|
||||||
|
amod: None,
|
||||||
|
r#type: None,
|
||||||
|
desc: None,
|
||||||
|
elements_bitstring: vec![],
|
||||||
|
elements_other: vec![ModuleBlockElements::Register(reg1)],
|
||||||
|
xmlhash: [0; 32],
|
||||||
|
git_info: XmlGitInfo {
|
||||||
|
describe: "".to_string(),
|
||||||
|
commit_timestamp: "".to_string(),
|
||||||
|
sha: "".to_string(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let (maps, errors) = module.validate();
|
||||||
|
eprintln!("{:#?}", maps);
|
||||||
|
eprintln!("{:#?}", errors);
|
||||||
|
eprintln!(
|
||||||
|
"{:#?}",
|
||||||
|
maps.iter().filter(|e| e.is_some()).collect_vec().len()
|
||||||
|
);
|
||||||
|
assert_eq!(maps.len(), 0x1);
|
||||||
|
assert!(errors.is_empty());
|
||||||
|
assert_eq!(maps.iter().filter(|e| e.is_some()).collect_vec().len(), 0x1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn register_with_invalid_mask_and_field() {
|
||||||
|
let reg1 = Register {
|
||||||
|
name: "test1".to_string(),
|
||||||
|
addr: 0,
|
||||||
|
r#type: crate::types::DataType::D32,
|
||||||
|
mask: Some(0x0000_000f),
|
||||||
|
modf: RwSpecifier::R,
|
||||||
|
multiple: None,
|
||||||
|
default: None,
|
||||||
|
desc: None,
|
||||||
|
elements: vec![Field {
|
||||||
|
name: "field_1".to_string(),
|
||||||
|
mask: 0x0000_0001,
|
||||||
|
interface: None,
|
||||||
|
multiple: Some(MultipleParams {
|
||||||
|
multiple: 8,
|
||||||
|
offset: 1,
|
||||||
|
}),
|
||||||
|
default: None,
|
||||||
|
sclr: None,
|
||||||
|
desc: Some("field 1 description".to_string()),
|
||||||
|
elements: vec![],
|
||||||
|
}],
|
||||||
|
};
|
||||||
|
let module = Module {
|
||||||
|
name: "module".to_string(),
|
||||||
|
addr: 0,
|
||||||
|
size: 0x1,
|
||||||
|
amod: None,
|
||||||
|
r#type: None,
|
||||||
|
desc: None,
|
||||||
|
elements_bitstring: vec![],
|
||||||
|
elements_other: vec![ModuleBlockElements::Register(reg1)],
|
||||||
|
xmlhash: [0; 32],
|
||||||
|
git_info: XmlGitInfo {
|
||||||
|
describe: "".to_string(),
|
||||||
|
commit_timestamp: "".to_string(),
|
||||||
|
sha: "".to_string(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let (maps, errors) = module.validate();
|
||||||
|
eprintln!("{:#?}", maps);
|
||||||
|
eprintln!("{:#?}", errors);
|
||||||
|
eprintln!(
|
||||||
|
"{:#?}",
|
||||||
|
maps.iter().filter(|e| e.is_some()).collect_vec().len()
|
||||||
|
);
|
||||||
|
assert_eq!(maps.len(), 0x1);
|
||||||
|
assert_eq!(errors.len(), 1);
|
||||||
|
assert_eq!(maps.iter().filter(|e| e.is_some()).collect_vec().len(), 0x0);
|
||||||
|
assert_eq!(
|
||||||
|
errors.first().unwrap(),
|
||||||
|
&ValidationError::RegisterAndFieldMaskMismatch {
|
||||||
|
address: 0x0,
|
||||||
|
name: "test1".to_string(),
|
||||||
|
reg_mask: 0x0000_000f,
|
||||||
|
fields_mask: 0x0000_00ff
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue