-
Notifications
You must be signed in to change notification settings - Fork 156
Register array in RegisterBlock #121
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
Conversation
Also have a look at line 399 at generate.rs I guess that is only valid as long as there are 4 byte (32 bit) registers. However I'm not sure how it can be generalized over register lengths? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR, @kjetilkjeka.
It seems reasonable to only translate register arrays to a Rust array in the case of compact (no hole) arrays.
I left several comments about the implementation.
I guess that is only valid as long as there are 4 byte (32 bit) registers. However I'm not sure how it can be generalized over register lengths?
I did not understand this constraint. Why are 4 byte registers special here? Shouldn't the check be register.size == dim_increment
? That would check if each array element has reserved space apart from the rergister.
src/generate.rs
Outdated
let mut previous = 0; | ||
|
||
let get_number_option = |element_option: Option<&String>| -> Option<usize> {element_option | ||
.and_then(|element| match element.parse::<usize>() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this match element.parse()
is equivalent to element.parse().ok()
src/generate.rs
Outdated
}) | ||
}; | ||
|
||
let mut index_convertible_temp = match get_number_option(index_iter.next()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this match is equivalent to LHS == Some(0)
src/generate.rs
Outdated
for element in index_iter { | ||
if !index_convertible_temp { break; } | ||
|
||
index_convertible_temp = match get_number_option(Some(element)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this get_number_option(Some(element))
would be simpler as element.parse().ok()
src/generate.rs
Outdated
for element in index_iter { | ||
if !index_convertible_temp { break; } | ||
|
||
index_convertible_temp = match get_number_option(Some(element)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the match
can probably be replaced by LHS == Some(previous + 1)
src/generate.rs
Outdated
match *register { | ||
Register::Single(ref _into) => registers_expanded.push(register.clone()), | ||
Register::Array(ref _into, ref array_info) => { | ||
let index_convertible = if let Some(ref indexes) = array_info.dim_index { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a comment about what this does? It wasn't entirely clear from reading the contents. Is it checking that indexes == 0..info.dim
? In that case this may be simpler to write this as indexes.iter().eq(0..info.dim)
.
src/util.rs
Outdated
out | ||
} | ||
|
||
|
||
pub fn sort_by_offset(mut registers: Vec<Register>) -> Vec<Register> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this routine is complex enough that should be a function.
src/util.rs
Outdated
/// the register arrays have been expanded. | ||
pub fn expand(registers: &[Register]) -> Vec<ExpandedRegister> { | ||
/// and turn in into alist of registers where the register arrays have been expanded. | ||
pub fn expand(register: &Register) -> Vec<Register> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that this will now only be used with Register::Array
it may be better not to pass &Register
but rather the contens of the Register::Array
variant
src/util.rs
Outdated
info.name.replace("[%s]", "") | ||
for (idx, i) in indices.iter().zip(0..) { | ||
let name = if has_brackets { | ||
info.name.replace("[%s]", format!("%s({})", idx).as_str()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we want to keep the "%s" in this stage? Is it going to be used afterwards? Why not just directly replace it with the formatted idx
at this point?
src/util.rs
Outdated
} else { | ||
info.name.replace("%s", "") | ||
info.name.replace("%s", format!("%s({})", idx).as_str()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same question as above
src/generate.rs
Outdated
|| { | ||
format!("Register {} has no `size` field", register.name) | ||
}, | ||
)? * array_info.dim / 8, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I know that it's unrelated to this PR but could you replace the 8
by a BITS_PER_BYTE
constant?
I agree that %s(N) is hacky. But the ExpandedRegister didn't work either as there was no support for array. I made a new struct extending syn::Field (by composition) adding size, offset and description. This makes perfect sense in my head as we're converting from svd::Register to rust fields (which syn::Field represents). Another bonus is the ability to use to_tokens instead of formating manually. Hope you agree with this reasoning? This made some refactoring necessary inside util but I think it makes more sense as it is now.
You're not suppose to understand that, was just me beeing stupid. Should be fixed now. Most of your comments were considering the conditions for expanding. I've cleaned them up a whole lot. I think it's readable to the point making more comment than the one outside the function unnecessary. But since I wrote the code 2 hours ago I'm quite biased, say if you still want me to add a comment there. I think I've addressed all the issues you mentioned except "Given that this will now only be used with Register::Array it may be better not to pass &Register but rather the contens of the Register::Array variant". I was a bit reluctant to change this out because:
|
☔ The latest upstream changes (presumably c7aed0a) made this pull request unmergeable. Please resolve the merge conflicts. |
Rebase onto japaric/master to resolve merge conflicts and include bare_metal features |
☔ The latest upstream changes (presumably 82ebef2) made this pull request unmergeable. Please resolve the merge conflicts. |
…ndedRegister extension
…llable on single registers instead of the whole slice
…ly contains numeric indexes and it starts on 0 and contains every element in the range. Then it is convertable to a rust array
…verted to a rust array
… of spliting on [ had a bug when the index was in the middle of the name.
…ork on the new struct RegisterBlockField. Instead of creating a brand new type representing a rust field it's an extension (by composition) of the syn::Field to also give information about offset, size and description. This means that the util extend function now extend to a vector of syn::Field.
…ould have been in the first place)
… array is that it's packed in memory, not that fields are 32 bits
Rebased onto 0.11.1 to make mergeable |
@japaric What's the status on svd2rust at them moment? Now that the bare metal changes are adopted will this PR be next in line or should I expect others merged before it? |
@japaric I guess you didn't have the time to look at this PR last time we talked about it. Do you have an updated estimate of when you will be able to review this PR? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for taking so long to come back to this.
I've requested two changes: one is required to have svd2rust not regress in terms of documentation rendering. Please fix them and I'll merge this.
Do you know if any of the devices in the test suite is exercising this change? If none is could you add your SVD file to the test suite?
src/generate.rs
Outdated
@@ -461,69 +460,135 @@ pub fn peripheral( | |||
Ok(()) | |||
} | |||
|
|||
struct RegisterBlockField { | |||
field: syn::Field, | |||
description: Ident, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not a identifier; it should be a String
.
src/generate.rs
Outdated
i += 1; | ||
} | ||
|
||
let comment = &format!( | ||
"0x{:02x} - {}", | ||
register.offset, | ||
util::respace(®ister.info.description) | ||
register.description, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please revert this change or the documentation will have random newlines in it. As in: keep the util::respace
.
Thank you for the review @japaric
This should be fixed now.
MK02F12810.svd should exercise this change (amongst other) for this register.
The diff for this register (between kjetilkjeka/svd2rust/master and kjetilkjeka/svd2rust/field_array) looks like the following:
This means that the doc string is the same as it used to be for tagvdw0s0. "#[doc = 0x100 - Cache Tag Storage]" I've also manually inspected the other registers in this file where the new code path is exercised and they are equivalent to the previous example. The previous example is also equivalent to the .svd file I tested during devlopment S32K144.svd I can, of course, manually inspect more files? But I've also tested it with the different (allowed) uses of dimIncrement and dimIndex manually. So I believe the next step should be to confirm that all the .svd files in the test suite will be compiled without error. |
Thanks, @kjetilkjeka. @homunkulus r+ |
📌 Commit 52cf267 has been approved by |
Register array in RegisterBlock I guess this pull request is dropping a bit out of the sky, but I realized I needed the feature sooner rather than later so decided to just go for it. When it's merged it should fix #114 Some refactoring was done to allow for integration register arrays, the most significant are - expand function only takes 1 register instead of slice. This means that the function has to be called for every register that should be expanded. This was done so a register can be conditionaly expanded depending on if it's possible to convert to a Rust array or not. - register_to_rust method was factored out from register_block. Mainly so register block wouldn't grow very large with lots of nested control flow. - ExpandedRegister was removed, the functions only use Register struct now. This was because if not it would require conversion functions when registers was not expanded. The struct would also need changing as it would only have to support arrays. - Since the ExpandedRegisters was dropped the expand function now writes ```%s(i)``` (where i is the index) to the names of the expanded registers. This is used later on to resolve name and type. - regex is a dependecy, this is used to replace ```%s(i)``` with the index. Adding this dependecy might not be desired? and if not I can reimplement it with some logic that iterates over the string. I've tested with [S32K144.svd](https://github.com/kjetilkjeka/s32k144.rs/blob/master/src/S32K144.svd) and it seems to work perfectly with that file. As mentioned in #114 i do hope that the method of using svd array information instead of unrolling arrays after is acceptable.
☀️ Test successful - status-appveyor, status-travis |
I guess this pull request is dropping a bit out of the sky, but I realized I needed the feature sooner rather than later so decided to just go for it. When it's merged it should fix #114
Some refactoring was done to allow for integration register arrays, the most significant are
%s(i)
(where i is the index) to the names of the expanded registers. This is used later on to resolve name and type.%s(i)
with the index. Adding this dependecy might not be desired? and if not I can reimplement it with some logic that iterates over the string.I've tested with S32K144.svd and it seems to work perfectly with that file.
As mentioned in #114 i do hope that the method of using svd array information instead of unrolling arrays after is acceptable.