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

Use a custom type to represent clusters instead of an array #48

Merged
merged 3 commits into from
Jan 17, 2025
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
106 changes: 106 additions & 0 deletions templates/rust/common.tera
Original file line number Diff line number Diff line change
Expand Up @@ -900,3 +900,109 @@ where
START_OFFSET + (self.index * DIM_INCREMENT) as usize
}
}

/// An array of identical register clusters.
pub struct ClusterArray<T: Sized, const DIM: usize, const DIM_INCREMENT: usize> {
_t: ::core::marker::PhantomData<T>,
}

impl<T: Sized, const DIM: usize, const DIM_INCREMENT: usize> ClusterArray<T, DIM, DIM_INCREMENT> {
/// Returns the number of register blocks in the cluster.
#[inline(always)]
pub const fn len(&self) -> usize {
DIM
}

/// Returns whether the cluster is empty (DIM == 0).
#[inline(always)]
pub const fn is_empty(&self) -> bool {
DIM == 0
}

/// Returns an iterator over the elements of this cluster.
#[inline(always)]
pub fn iter(&self) -> impl ::core::iter::ExactSizeIterator<Item = &T> {
jnkr-ifx marked this conversation as resolved.
Show resolved Hide resolved
self.into_iter()
}

/// Returns the cluster element with the specified index.
///
/// Panics if the index is out of bounds.
#[inline]
pub const fn get(&self, index: usize) -> &T {
assert!(index < DIM);
unsafe { self.get_unchecked(index) }
}

/// Returns the cluster element with the specified index.
///
/// # Safety
///
/// `index` must be less than `DIM`.
#[inline(always)]
pub const unsafe fn get_unchecked(&self, index: usize) -> &T {
&*(self.as_ptr().add(index * DIM_INCREMENT) as *const _)
}

#[inline(always)]
pub(crate) const unsafe fn from_ptr(ptr: *mut u8) -> &'static Self {
&*(ptr as *const Self)
}

#[inline(always)]
const fn as_ptr(&self) -> *mut u8 {
self as *const _ as *mut _
}
}

impl<T: Sized, const DIM: usize, const DIM_INCREMENT: usize> ::core::ops::Index<usize>
for ClusterArray<T, DIM, DIM_INCREMENT>
{
type Output = T;

#[inline(always)]
fn index(&self, index: usize) -> &T {
self.get(index)
}
}


impl<'a, T: Sized, const DIM: usize, const DIM_INCREMENT: usize> IntoIterator for &'a ClusterArray<T, DIM, DIM_INCREMENT> {
type Item = &'a T;
type IntoIter = ClusterArrayIterator<'a, T, DIM, DIM_INCREMENT>;

#[inline(always)]
fn into_iter(self) -> Self::IntoIter {
ClusterArrayIterator {
array: self,
index: 0
}
}
}

pub struct ClusterArrayIterator<'a, T: Sized, const DIM: usize, const DIM_INCREMENT: usize> {
array: &'a ClusterArray<T, DIM, DIM_INCREMENT>,
index: usize
}

impl<'a, T: Sized, const DIM: usize, const DIM_INCREMENT: usize> Iterator for ClusterArrayIterator<'a, T, DIM, DIM_INCREMENT> {
type Item = &'a T;
#[inline(always)]
fn next(&mut self) -> Option<&'a T> {
if self.index < self.array.len() {
let result = &self.array[self.index];
self.index += 1;
Some(result)
} else {
None
}
}

#[inline(always)]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.array.len() - self.index;
(len, Some(len))
}
}

impl<T: Sized, const DIM: usize, const DIM_INCREMENT: usize> ExactSizeIterator for ClusterArrayIterator<'_, T, DIM, DIM_INCREMENT> {}
42 changes: 27 additions & 15 deletions templates/rust/macros.tera
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ Unsupported register size
#[inline(always)]
{% if reg.dim == 1 -%}
pub const fn {{reg.name | to_func_id }}(&self) -> crate::common::Reg<{{reg_struct_name}}_SPEC, crate::common::{{reg.access}}> {
unsafe { crate::common::Reg::from_ptr(self.ptr.add({{reg.offset}}usize)) }
unsafe { crate::common::Reg::from_ptr(self._svd2pac_as_ptr().add({{reg.offset}}usize)) }
}
{%- else -%}
pub const fn {{reg.name | to_func_id }}(&self) -> [crate::common::Reg<{{reg_struct_name}}_SPEC, crate::common::{{reg.access}}>;{{reg.dim}}] {
unsafe { [
{%- for index in range(end=reg.dim) -%}
crate::common::Reg::from_ptr(self.ptr.add({{reg.offset | to_hex }}usize + {{index * reg.dim_increment | to_hex }}usize )),
crate::common::Reg::from_ptr(self._svd2pac_as_ptr().add({{reg.offset | to_hex }}usize + {{index * reg.dim_increment | to_hex }}usize )),
{% endfor -%}
] }
}
Expand Down Expand Up @@ -120,20 +120,17 @@ pub mod {{reg_mod_name}} {
{%- set mod_struct_path = cluster.struct_module_path | join(sep="::") -%}
{%- set cluster_struct_id = cluster.struct_id | to_struct_id -%}
{%- set cluster_struct_path = "crate" ~ "::" ~ mod_struct_path ~ "::" ~ cluster_struct_id -%}
{%- set underscored_cluster_struct_path = "crate" ~ "::" ~ mod_struct_path ~ "::_" ~ cluster_struct_id -%}
{%- set cluster_func = cluster.name | to_func_id -%}
#[doc = "{{cluster.description | svd_description_to_doc}}"]
#[inline(always)]
{%- if cluster.dim == 1 %}
pub fn {{cluster_func}}(self) -> {{cluster_struct_path}}{
unsafe { {{cluster_struct_path}}{ptr:self.ptr.add({{cluster.offset}}usize)} }
pub const fn {{cluster_func}}(self) -> {{cluster_struct_path}}{
unsafe { {{underscored_cluster_struct_path}}::_svd2pac_from_ptr(self._svd2pac_as_ptr().add({{cluster.offset}}usize)) }
}
{%- else %}
pub fn {{cluster_func}}(self) -> [{{cluster_struct_path}};{{cluster.dim}}] {
unsafe { [
{%- for index in range(end=cluster.dim) -%}
{{cluster_struct_path}}{ptr:self.ptr.add({{cluster.offset | to_hex}}usize + {{index*cluster.dim_increment | to_hex }}usize)},
{% endfor -%}
] }
pub fn {{cluster_func}}(self) -> &'static crate::common::ClusterArray<{{underscored_cluster_struct_path}}, {{cluster.dim}}, {{cluster.dim_increment | to_hex}}> {
unsafe { crate::common::ClusterArray::from_ptr(self._svd2pac_as_ptr().add({{cluster.offset | to_hex}}usize)) }
}
{%- endif -%}
{%- endmacro -%}
Expand All @@ -145,11 +142,26 @@ pub fn {{cluster_func}}(self) -> [{{cluster_struct_path}};{{cluster.dim}}] {
{%- set cluster_struct = cluster.struct_id | to_struct_id -%}
{%- set cluster_mod = cluster.module_id -%}
#[doc = "{{cluster.description | svd_description_to_doc}}"]
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct {{ cluster_struct }}{pub(crate) ptr: *mut u8}
unsafe impl ::core::marker::Send for {{ cluster_struct}} {}
unsafe impl ::core::marker::Sync for {{ cluster_struct }} {}
impl {{cluster_struct}} {
#[non_exhaustive]
pub struct _{{ cluster_struct }};

#[doc = "{{cluster.description | svd_description_to_doc}}"]
pub type {{ cluster_struct }} = &'static _{{ cluster_struct }};

unsafe impl ::core::marker::Sync for _{{ cluster_struct }} {}
impl _{{cluster_struct}} {
#[allow(unused)]
#[inline(always)]
pub(crate) const unsafe fn _svd2pac_from_ptr(ptr: *mut u8) -> &'static Self {
&*(ptr as *mut _)
}

#[allow(unused)]
#[inline(always)]
pub(crate) const fn _svd2pac_as_ptr(&self) -> *mut u8 {
self as *const Self as *mut u8
}

{% for register_name,reg in cluster.registers -%}
{{self::register_func(types_mod=cluster_mod,reg=reg)}}
{% endfor -%}
Expand Down
6 changes: 6 additions & 0 deletions templates/rust/peri_mod.tera
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ use crate::common::sealed;
unsafe impl ::core::marker::Send for super::{{ peri_struct }} {}
unsafe impl ::core::marker::Sync for super::{{ peri_struct }} {}
impl super::{{ peri_struct }} {
#[allow(unused)]
#[inline(always)]
pub(crate) const fn _svd2pac_as_ptr(&self) -> *mut u8 {
self.ptr
}

{%- for register_name,reg in peri.registers %}
{{macros::register_func(types_mod="self",reg=reg)}}
{% endfor -%}
Expand Down
4 changes: 2 additions & 2 deletions test_svd/simple.xml
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@
<resetValue>0x1000</resetValue>
<fields>
<field>
<name>filed1</name>
<name>field1</name>
<lsb>0</lsb>
<msb>2</msb>
<access>read-write</access>
Expand Down Expand Up @@ -8338,4 +8338,4 @@
</peripheral>
</aurixCSFR>
</vendorExtensions>
</device>
</device>
6 changes: 6 additions & 0 deletions tests/resources/project_files_generic/src/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@ fn main() -> ! {

// Test 64Bit register
TIMER.register64bit().modify(|r| r.boolean().set(crate::timer::register64bit::Boolean::FALSE));

// Test cluster array
TIMER.clusterdim()[0].cr().modify(|r| r.field1().set(0));
for elem in TIMER.clusterdim() {
TIMER.clusterdim()[0].cr().modify(|r| r.field1().set(1));
}
}
loop {}
}
Loading