Skip to content
Open
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
36 changes: 27 additions & 9 deletions src/generate/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,33 @@ pub fn render(opts: &super::Options, ir: &IR, b: &Block, path: &str) -> Result<T

let ty = quote!(#common_path::Reg<#reg_ty, #access>);
if let Some(array) = &i.array {
let (len, offs_expr) = super::process_array(array);
items.extend(quote!(
#doc
#[inline(always)]
pub const fn #name(self, n: usize) -> #ty {
assert!(n < #len);
unsafe { #common_path::Reg::from_ptr(self.ptr.wrapping_add(#offset + #offs_expr) as _) }
let (len, offs_expr, indexes) = super::process_array(array);

if let Some(indexes) = indexes {
for (array_offset, index) in indexes.iter() {
// TODO don't erase %s so we can position the index in the name as our overlords intended?
let name = Ident::new(&format!("{}_{}", i.name, index), span);
let doc =
util::doc(&i.description.clone().map(|s| s.replace("%s", index)));

items.extend(quote!(
#doc
#[inline(always)]
pub const fn #name(self) -> #ty {
unsafe { #common_path::Reg::from_ptr(self.ptr.wrapping_add(#offset + #array_offset) as _) }
}
));
}
));
} else {
items.extend(quote!(
#doc
#[inline(always)]
pub const fn #name(self, n: usize) -> #ty {
assert!(n < #len);
unsafe { #common_path::Reg::from_ptr(self.ptr.wrapping_add(#offset + #offs_expr) as _) }
}
));
}
} else {
items.extend(quote!(
#doc
Expand All @@ -67,7 +85,7 @@ pub fn render(opts: &super::Options, ir: &IR, b: &Block, path: &str) -> Result<T
let _b2 = ir.blocks.get(block_path).unwrap();
let ty = util::relative_path(block_path, path);
if let Some(array) = &i.array {
let (len, offs_expr) = super::process_array(array);
let (len, offs_expr, _indexes) = super::process_array(array);

items.extend(quote!(
#doc
Expand Down
4 changes: 2 additions & 2 deletions src/generate/fieldset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ pub fn render(opts: &super::Options, ir: &IR, fs: &FieldSet, path: &str) -> Resu
BitOffset::Regular(off_in_reg) => {
let off_in_reg = off_in_reg as usize;
if let Some(array) = &f.array {
let (len, offs_expr) = super::process_array(array);
let (len, offs_expr, _indexes) = super::process_array(array);
items.extend(quote!(
#doc
#[must_use]
Expand Down Expand Up @@ -144,7 +144,7 @@ pub fn render(opts: &super::Options, ir: &IR, fs: &FieldSet, path: &str) -> Resu
}

if let Some(array) = &f.array {
let (len, offs_expr) = super::process_array(array);
let (len, offs_expr, _indexes) = super::process_array(array);
items.extend(quote!(
#doc
#[must_use]
Expand Down
13 changes: 10 additions & 3 deletions src/generate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,13 +214,20 @@ fn split_path(s: &str) -> (Vec<&str>, &str) {
(v, n)
}

fn process_array(array: &Array) -> (usize, TokenStream) {
fn process_array(array: &Array) -> (usize, TokenStream, Option<Vec<(TokenStream, String)>>) {
match array {
Array::Regular(array) => {
let len = array.len as usize;
let stride = array.stride as usize;
let offs_expr = quote!(n*#stride);
(len, offs_expr)
let indexes = array.indexes.clone().map(|indexes| {
indexes
.into_iter()
.enumerate()
.map(|(i, index_name)| (quote!(#i * #stride), index_name))
.collect()
});
(len, offs_expr, indexes)
}
Array::Cursed(array) => {
let len = array.offsets.len();
Expand All @@ -230,7 +237,7 @@ fn process_array(array: &Array) -> (usize, TokenStream) {
.map(|&x| x as usize)
.collect::<Vec<_>>();
let offs_expr = quote!(([#(#offsets),*][n] as usize));
(len, offs_expr)
(len, offs_expr, None)
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ impl Array {
pub struct RegularArray {
pub len: u32,
pub stride: u32,
pub indexes: Option<Vec<String>>,
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
Expand Down
40 changes: 39 additions & 1 deletion src/svd2ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,29 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<()
let mut enums: Vec<ProtoEnum> = Vec::new();

for block in &blocks {
let mut register_name_counts: BTreeMap<String, usize> = BTreeMap::new();

for r in &block.registers {
if let svd::RegisterCluster::Register(r) = r {
if r.derived_from.is_some() {
continue;
}

let register_name_count = register_name_counts.entry(r.name.clone()).or_insert(0);
let mut register_name = r.name.clone();
*register_name_count += 1;
if *register_name_count > 1 {
if r.is_array() {
register_name = format!("{}{}", register_name, register_name_count);
} else {
// This will blow up in unique_names
error!("Dupe Register: {register_name}");
}
}

if let Some(fields) = &r.fields {
let mut fieldset_name = block.name.clone();
fieldset_name.push(util::replace_suffix(&r.name, ""));
fieldset_name.push(util::replace_suffix(&register_name, ""));
fieldsets.push(ProtoFieldset {
name: fieldset_name.clone(),
description: r.description.clone(),
Expand Down Expand Up @@ -193,9 +207,31 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<()
};

let array = if let svd::Register::Array(_, dim) = r {
let indexes = match &dim.dim_index {
Some(indexes) => {
// If the indexes are a range of integers treat the register as an array
// TODO: Check the stop, start and finesse the accessors thusly
let indexes = indexes
.iter()
.filter_map(|i| match i.parse::<usize>() {
Ok(_) => None,
Err(_) => Some(i.to_lowercase()),
})
.collect::<Vec<String>>();

if !indexes.is_empty() {
Some(indexes.clone())
} else {
None
}
}
None => None,
};

Some(Array::Regular(RegularArray {
len: dim.dim,
stride: dim.dim_increment,
indexes,
}))
} else {
None
Expand Down Expand Up @@ -236,6 +272,7 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<()
Some(Array::Regular(RegularArray {
len: dim.dim,
stride: dim.dim_increment,
indexes: dim.dim_index.clone(),
}))
} else {
None
Expand Down Expand Up @@ -278,6 +315,7 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<()
Some(Array::Regular(RegularArray {
len: dim.dim,
stride: dim.dim_increment,
indexes: dim.dim_index.clone(),
}))
} else {
None
Expand Down
10 changes: 9 additions & 1 deletion src/transform/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ pub(crate) fn calc_array(mut offsets: Vec<u32>, mode: ArrayMode) -> anyhow::Resu
Array::Regular(RegularArray {
len: offsets.len() as _,
stride,
indexes: None,
}),
));
}
Expand All @@ -328,7 +329,14 @@ pub(crate) fn calc_array(mut offsets: Vec<u32>, mode: ArrayMode) -> anyhow::Resu
}
ArrayMode::Holey => {
let len = (offsets.last().unwrap() - offsets.first().unwrap()) / stride + 1;
Ok((start_offset, Array::Regular(RegularArray { len, stride })))
Ok((
start_offset,
Array::Regular(RegularArray {
len,
stride,
indexes: None,
}),
))
}
}
}
Expand Down
28 changes: 27 additions & 1 deletion src/transform/sanitize.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use serde::{Deserialize, Serialize};

use crate::util::StringExt;
use crate::{ir::BlockItemInner, util::StringExt};

use super::{map_names, NameKind, IR};

Expand Down Expand Up @@ -28,6 +28,7 @@ impl Sanitize {
rename_duplicate_variants(enumm);
}

rename_duplicate_fieldsets(ir);
Ok(())
}
}
Expand Down Expand Up @@ -92,3 +93,28 @@ fn rename_duplicate_variants(enumm: &mut crate::ir::Enum) {
}
}
}

fn rename_duplicate_fieldsets(ir: &mut crate::ir::IR) {
use std::collections::BTreeMap;

for (_name, blk) in ir.blocks.iter_mut() {
let mut register_name_counts: BTreeMap<String, usize> = BTreeMap::new();
for block_item in blk.items.iter_mut() {
if let BlockItemInner::Register(r) = &mut block_item.inner {
let name_count = register_name_counts
.entry(block_item.name.clone())
.or_insert(0);

*name_count += 1;

if *name_count > 1 {
block_item.name = format!("{}{}", block_item.name, name_count);
r.fieldset = r
.fieldset
.as_mut()
.map(|path| format!("{}{}", path, name_count));
}
}
}
}
}