Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

16 add support of derived from for peripherals #19

Merged
merged 6 commits into from
May 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ This tool has a very different approach compared to `svd2rust` and it is inspire

## Limitations

* Inheritance via `derivedFrom` attribute is supported only in `cluster` and register declaration and requires.
in case that parent is an element of an array only the first element is supported.
* Inheritance via `derivedFrom` attribute is presently not supported for bitfields declaration.
Moreover in case that parent is an element of an array only the first element is supported.
* `resetMask` tag is ignored
* `protection` tag is ignored
* `writeConstraint` tag is ignored
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@
//!
//! # Limitations
//!
//! * Inheritance via `derivedFrom` attribute is supported only in `cluster` and register declaration and requires.
//! in case that parent is an element of an array only the first element is supported.
//! * Inheritance via `derivedFrom` attribute is presently not supported for bitfields declaration.
//! Moreover in case that parent is an element of an array only the first element is supported.
//! * `resetMask` tag is ignored
//! * `protection` tag is ignored
//! * `writeConstraint` tag is ignored
Expand Down
10 changes: 8 additions & 2 deletions src/rust_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,15 +429,21 @@ fn generate_peripheral_module(
destination_folder: &Path,
) -> anyhow::Result<()> {
// Generate one module for each peripheral
for (peri_name, peri) in &ir.device.peripheral_mod {
for (_, peri) in &ir.device.peripheral_mod {
// No need to generate a module if the peripheral is derived
let borrowed_peri = peri.borrow();
if borrowed_peri.is_derived_from {
continue;
}
let module_name = borrowed_peri.module_id.clone();
let mut context = tera::Context::new();
context.insert("peri", peri);
context.insert("ir", &ir);
execute_template(
tera,
template_name,
&context,
&destination_folder.join(format!("src/{}.rs", peri_name.to_lowercase())),
&destination_folder.join(format!("src/{}.rs", module_name)),
)
.context("Failed generation of code")?;
}
Expand Down
9 changes: 5 additions & 4 deletions src/rust_gen/ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,11 @@ pub struct PeripheralMod {
pub registers: LinkedHashMap<String, Rc<RefCell<Register>>>,
pub base_addr: Vec<u64>,
pub interrupts: Vec<Interrupt>,
// pub is_derived_from: bool,
// /// Struct identifier of the peripheral.
// /// It can be different from cluster name in case derivedFrom and/or headerStructName are used
// pub struct_id: String,
pub is_derived_from: bool,
// Struct identifier of the peripheral.
pub struct_id: String,
// It could be different from name lower case if derived_from is used.
pub module_id: String,
}

/// Represents a part of a fully qualified path name for registers.
Expand Down
99 changes: 67 additions & 32 deletions src/rust_gen/xml2ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use linked_hash_map::LinkedHashMap;
use log::{debug, error, warn};
use svd2temp::*;
use svd_parser::svd;
use svd_parser::svd::Name;

trait RegisterHelper {
/// Get name of register considering the presence of alternate group
Expand Down Expand Up @@ -97,44 +96,76 @@ impl Visitor {
self.device.name.clone_from(&device.name);
self.device.description.clone_from(&device.description);

for peripheral in device.peripherals.iter() {
let name = peripheral.name().to_internal_ident();
let mut peripheral_mod = PeripheralMod {
name: name.clone(),
..Default::default()
};
self.push_current_item_svd_path(peripheral);
self.visit_peripheral(peripheral, &mut peripheral_mod);
let peripheral_mod = Rc::new(RefCell::new(peripheral_mod));
for svd_peripheral in device.peripherals.iter() {
let derived_peripheral: Option<PeripheralMod> =
if let Some(derived_ref) = &svd_peripheral.derived_from {
if let Some(ref_item) = self.svd_ref_to_ir_item.get(derived_ref) {
if let DeviceItem::Peripheral(ref_peripheral) = ref_item {
Some(ref_peripheral.borrow().clone())
} else {
panic!(
"reference {:} in {:} doesn't point to a peripheral",
derived_ref, svd_peripheral.name
)
}
} else {
panic!(
"Missing reference {:} in {:}",
derived_ref, svd_peripheral.name
);
}
} else {
None
};

// Push the peripheral svd and ir path in corresponding FIFO stack
self.push_current_item_svd_path(svd_peripheral);
// If derivedFrom point to some peripheral get a clone of this peripheral
// other wise create a new one
let mut peripheral = derived_peripheral
.as_ref()
.map_or_else(PeripheralMod::default, |x| x.clone());
// Update the peripheral_mod with data from svd::peripheral
self.visit_peripheral(svd_peripheral, &mut peripheral);

let name = peripheral.name.clone();

peripheral.is_derived_from = derived_peripheral
.is_some_and(|derived_peri| peripheral.has_same_type(&derived_peri));
let peripheral_mod = Rc::new(RefCell::new(peripheral));
self.device
.peripheral_mod
.insert(name, peripheral_mod.clone());

self.svd_ref_to_ir_item.insert(
peripheral.name().to_string(),
DeviceItem::Peripheral(peripheral_mod.clone()),
);
// Pop out the paths and the just updated peripheral in svd to it index
self.pop_current_item_svd_path(DeviceItem::Peripheral(peripheral_mod));
}
}
fn visit_peripheral(
&mut self,
peripheral: &svd::Peripheral,
target_peripheral: &mut PeripheralMod,
svd_peripheral: &svd::Peripheral,
peripheral: &mut PeripheralMod,
) {
/*I don't generate any type if the peripheral has derivedFrom attribute.
Overriding of peripheral content is not supported*/
assert!(
peripheral.derived_from.is_none(),
"derived_from is not supported in peripherals"
);
debug!("Parsing peripheral: {}", &target_peripheral.name);

let (dim, dim_increment) = get_dim_dim_increment(peripheral);
target_peripheral.base_addr = (0..dim)
.map(|index| peripheral.base_address + (index * dim_increment) as u64)
debug!("Parsing peripheral: {}", &svd_peripheral.name);
peripheral.name = svd_peripheral.name.to_internal_ident();
peripheral.description = svd_peripheral.description.clone().unwrap_or_default();

if let Some(header_struct) = &svd_peripheral.header_struct_name {
// defined headerStructName has priority for struct ide definition.
peripheral.struct_id = header_struct.to_sanitized_struct_ident()
} else if peripheral.struct_id.is_empty() {
// If the peripheral has no parent create Rust struct id
peripheral.struct_id = svd_peripheral.name.to_sanitized_struct_ident();
}

if peripheral.module_id.is_empty() {
peripheral.module_id = svd_peripheral.name.to_sanitized_mod_ident();
}

let (dim, dim_increment) = get_dim_dim_increment(svd_peripheral);
peripheral.base_addr = (0..dim)
.map(|index| svd_peripheral.base_address + (index * dim_increment) as u64)
.collect();
target_peripheral.interrupts = peripheral
peripheral.interrupts = svd_peripheral
.interrupt
.iter()
.map(|x| Interrupt {
Expand All @@ -146,17 +177,21 @@ impl Visitor {
.map_or_else(String::new, |x| x.clone()),
})
.collect();
target_peripheral.description = peripheral.description.clone().unwrap_or_default();

for cluster_register in peripheral.registers.as_ref().unwrap_or(&Vec::new()) {
for cluster_register in svd_peripheral.registers.as_ref().unwrap_or(&Vec::new()) {
self.visit_cluster_register(
cluster_register,
PeripheralClusterE::Peripheral(target_peripheral),
PeripheralClusterE::Peripheral(peripheral),
);
}
}

fn visit_register(&mut self, reg: &svd::Register, register: &mut Register) {
//TODO Review this call. If alternate_group is used
// inheritance resolver will not work
//TODO It is not clear what is happen with inheritance.
// In derivedFrom, shall I refer to a register in alterante group with name prefixed ?
// need reverse engineering of svd_conv.
register.name = reg.get_name_id_internal();
register.description = reg.description.clone().unwrap_or_default();
register.offset = reg.address_offset;
Expand Down
2 changes: 1 addition & 1 deletion templates/rust/Cargo_toml.tera
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ cortex-m = "0.7.6"

[features]
{%- for peri_mod_name, peri in ir.device.peripheral_mod %}
{{peri.name | to_mod_id}} = []
{{peri.name | to_mod_id}} = [{%if peri.is_derived_from %}"{{ peri.module_id }}"{% endif %}]
{%- endfor %}
{% if ir_csfr %}
{%- for peri_mod_name, peri in ir_csfr.device.peripheral_mod %}
Expand Down
1 change: 1 addition & 0 deletions templates/rust/lib.tera
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub mod reg_name;
pub mod tracing;
{% endif %} {# tracing #}
{% for peri_mod_name, peri in ir.device.peripheral_mod -%}
{%- if peri.is_derived_from %} {% continue %} {% endif %} {# module that are derived doesn't have a module #}
{%- set module_name = peri.name | to_mod_id -%}
#[cfg(feature = "{{module_name}}")]
pub mod {{module_name}};
Expand Down
5 changes: 5 additions & 0 deletions test_svd/simple.xml
Original file line number Diff line number Diff line change
Expand Up @@ -951,6 +951,11 @@
</cluster>
</registers>
</peripheral>
<peripheral derivedFrom="P33">
<name>DerivedPeripheral</name>
<description>DerivedPeripheral</description>
<baseAddress>0x70200000</baseAddress>
</peripheral>
</peripherals>
<vendorExtensions>
<aurixCSFR>
Expand Down
2 changes: 1 addition & 1 deletion tests/resources/project_files_aurix/rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[toolchain]
channel = "tricore-htc-none-v0.2.0"
channel = "tricore-htc-none-v1.0.0"

Loading