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 1 commit
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
57 changes: 57 additions & 0 deletions templates/rust/common.tera
Original file line number Diff line number Diff line change
Expand Up @@ -900,3 +900,60 @@ where
START_OFFSET + (self.index * DIM_INCREMENT) as usize
}
}

/// A cluster of identical register blocks.
pub struct Cluster<T: Sized, const DIM: usize, const DIM_INCREMENT: usize> {
jnkr-ifx marked this conversation as resolved.
Show resolved Hide resolved
_t: ::core::marker::PhantomData<T>,
}

impl<T: Sized, const DIM: usize, const DIM_INCREMENT: usize> Cluster<T, DIM, DIM_INCREMENT> {
jnkr-ifx marked this conversation as resolved.
Show resolved Hide resolved
/// Returns the number of register blocks in the cluster.
pub fn len() -> usize {
DIM
}

/// Returns whether the cluster is empty (DIM == 0).
pub fn is_empty() -> bool {
DIM == 0
}

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

/// Returns the cluster element with the specified index.
///
/// Panics if the index is out of bounds.
pub 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`.
pub unsafe fn get_unchecked(&self, index: usize) -> &T {
&*(self.as_ptr().add(index * DIM_INCREMENT) as *const _)
}

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

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 Cluster<T, DIM, DIM_INCREMENT>
{
type Output = T;

fn index(&self, index: usize) -> &T {
self.get(index)
}
}
38 changes: 24 additions & 14 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.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.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)} }
unsafe { {{underscored_cluster_struct_path}}::from_ptr(self.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::Cluster<{{underscored_cluster_struct_path}}, {{cluster.dim}}, {{cluster.dim_increment | to_hex}}> {
unsafe { crate::common::Cluster::from_ptr(self.as_ptr().add({{cluster.offset | to_hex}}usize)) }
}
{%- endif -%}
{%- endmacro -%}
Expand All @@ -145,11 +142,24 @@ 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)]
pub(crate) unsafe fn from_ptr(ptr: *mut u8) -> &'static Self {
jnkr-ifx marked this conversation as resolved.
Show resolved Hide resolved
&*(ptr as *mut _)
}

#[allow(unused)]
pub(crate) const fn 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
5 changes: 5 additions & 0 deletions templates/rust/peri_mod.tera
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ 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)]
pub(crate) const fn as_ptr(&self) -> *mut u8 {
jnkr-ifx marked this conversation as resolved.
Show resolved Hide resolved
self.ptr
}

{%- for register_name,reg in peri.registers %}
{{macros::register_func(types_mod="self",reg=reg)}}
{% endfor -%}
Expand Down