diff --git a/src/svd2ir.rs b/src/svd2ir.rs index 202fc02..5069357 100644 --- a/src/svd2ir.rs +++ b/src/svd2ir.rs @@ -285,6 +285,7 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<() fields: Vec::new(), }; + let mut field_name_counts: BTreeMap = BTreeMap::new(); for f in &proto.fields { if f.derived_from.is_some() { warn!("unsupported derived_from in fieldset"); @@ -299,7 +300,13 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<() None }; - let field_name = replace_suffix(&f.name, ""); + let mut field_name = replace_suffix(&f.name, ""); + + let field_name_count = field_name_counts.entry(field_name.clone()).or_insert(0); + *field_name_count += 1; + if *field_name_count > 1 { + field_name = format!("{}{}", field_name, field_name_count); + } let mut field = Field { name: field_name.clone(), diff --git a/tests/rename_dups.rs b/tests/rename_dups.rs new file mode 100644 index 0000000..08db86e --- /dev/null +++ b/tests/rename_dups.rs @@ -0,0 +1,92 @@ +use chiptool::{ir::IR, svd2ir::convert_peripheral, transform::sanitize::Sanitize}; +use svd_parser::ValidateLevel; + +#[test] +fn duplicate_svd_fields_should_not_collide() -> Result<(), Box> { + let input_svd = r#" + + duplicate_fields_should_not_collide + + + PERIPHERAL + 0x0 + + + Fieldset + 0x41F + + + Reserved + 1 + 2 + + + Reserved + 3 + 4 + + + + + + + + "#; + + let config = svd_parser::Config::default() + .expand_properties(true) + .validate_level(ValidateLevel::Disabled); + + let device = svd_parser::parse_with_config(input_svd, &config)?; + let mut ir = IR::new(); + convert_peripheral(&mut ir, device.peripherals.iter().next().unwrap())?; + + let (name, fieldset) = ir.fieldsets.iter().next().expect("Fieldset not found"); + + assert_eq!(name, "Fieldset"); + + let field_names = fieldset + .fields + .iter() + .map(|field| &field.name) + .collect::>(); + + assert_eq!(field_names, &["Reserved", "Reserved2"]); + + Ok(()) +} + +#[test] +fn duplicate_ir_fields_should_not_collide() -> Result<(), Box> { + let input_yaml = r#" + block/BLOCK: + items: + - name: register + byte_offset: 0 + bit_size: 32 + fieldset: regs::Fieldset + fieldset/regs::Fieldset: + fields: + - name: reserved + bit_offset: 0 + bit_size: 1 + - name: reserved + bit_offset: 1 + bit_size: 1 + "#; + let ir: IR = serde_yaml::from_slice(input_yaml.as_bytes())?; + + let (name, fieldset) = ir.fieldsets.iter().next().expect("Fieldset not found"); + + assert_eq!(name, "regs::Fieldset"); + + let field_names = fieldset + .fields + .iter() + .map(|field| &field.name) + .collect::>(); + + assert_eq!(field_names, &["reserved", "reserved2"]); + + Ok(()) +}