mirror of
https://gitlab.cern.ch/wotsubo/endcap-sl-software-ri-generator.git
synced 2025-04-11 16:07:55 +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 register map validator and flattened map generator.
|
||||
- Allow register with mask and fields iff the masks are matched.
|
||||
|
||||
### Changed
|
||||
|
||||
|
|
|
@ -396,12 +396,6 @@ impl Register {
|
|||
.collect::<Result<_, _>>()?;
|
||||
|
||||
// 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() {
|
||||
return Err(DomConversionError::other_error(
|
||||
"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 {
|
||||
#[error("address duplicated at 0x{address:08x}: \"{existing_name}\", \"{new_name}\"")]
|
||||
RegisterAddressDuplicated {
|
||||
|
@ -44,6 +44,13 @@ pub enum ValidationError {
|
|||
reg_name: String,
|
||||
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}")]
|
||||
UnsupportedStructure { msg: &'static str },
|
||||
}
|
||||
|
@ -131,7 +138,13 @@ impl Validate for Register {
|
|||
.elements
|
||||
.iter()
|
||||
.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 {
|
||||
|
@ -142,6 +155,18 @@ impl Validate for Register {
|
|||
});
|
||||
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 {
|
||||
Some(multiple) => (multiple.multiple, multiple.offset),
|
||||
|
@ -213,8 +238,11 @@ impl Validate for Register {
|
|||
mod test {
|
||||
use itertools::Itertools;
|
||||
|
||||
use crate::types::{
|
||||
Field, Module, ModuleBlockElements, MultipleParams, Register, RwSpecifier, XmlGitInfo,
|
||||
use crate::{
|
||||
types::{
|
||||
Field, Module, ModuleBlockElements, MultipleParams, Register, RwSpecifier, XmlGitInfo,
|
||||
},
|
||||
validator::ValidationError,
|
||||
};
|
||||
|
||||
#[test]
|
||||
|
@ -422,4 +450,136 @@ mod test {
|
|||
assert!(errors.is_empty());
|
||||
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