Skip to content

Put padding for cluster-arrays inside each individual array element, #531

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

Closed
wants to merge 1 commit into from

Conversation

rcls
Copy link
Contributor

@rcls rcls commented Jun 17, 2021

Currently, some SVD arrays get emitted as a sequence of numbered fields, instead of as a single rust array, due to padding between elements.

This change moves the padding into the array elements, allowing the SVD array to be emitted as a rust array. This makes the generated API more consistent and easier to use. (The downside is that the API changes are not backward compatible.)

Cypress PSOC and Traveo processors appear to be particularly effected with this, it looks like many others get no change. I made a git repo show the changes for three processors at rcls/svd2rust-example@08798fc

@rcls rcls requested a review from a team as a code owner June 17, 2021 09:38
@rust-highfive
Copy link

r? @burrbull

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-tools labels Jun 17, 2021
instead of breaking the array up into a list of items and adding
padding between the items.
@rcls rcls force-pushed the internal_cluster_padding branch from d6f4dc6 to 655e0a1 Compare June 17, 2021 09:44
@burrbull
Copy link
Member

This is excellent change in theory.
But do you check than those reserved spaces don't cross with other registers?
if dim_increment != addressOffset it is not guaranteed that spaces are empty.

@rcls
Copy link
Contributor Author

rcls commented Jun 17, 2021

I hadn't thought of the case where some random other register was placed within the padding (Does SVD allow that? - I'm not particularly familiar with the specification).
Yes, now you point that out, I'm pretty certain I could concoct a SVD that would break with this change. I have no idea whether or not it is a real-life problem. (Also I suspect you could produce similar nastiness that would break svd2rust as it is today.)

@burrbull
Copy link
Member

burrbull commented Jun 17, 2021

Does SVD allow

I'm afraid, the answer YES.
I saw many such files.

@rcls
Copy link
Contributor Author

rcls commented Jun 17, 2021

I saw many such files.

I'll attempt to address this & only apply my change in cases where it is safe. Do you have a SVD you can point me at? (Or I can probably make one up).

@rcls rcls marked this pull request as draft June 18, 2021 18:22
@rcls
Copy link
Contributor Author

rcls commented Jun 18, 2021

To get this right, seems to need a bit of re-arranging of the existing code, as currently we decide whether or not to split an array before sorting, making it harder to know whether or not another register falls into the padding.
And potentially the array could be nested inside another cluster, with a potentially conflicting register outside of that containing cluster. Apart from needing to find that register, we also need to deal with the fact items in different clusters have different base addresses, so the offsets can't be directly compared...
So I'm thinking:

  • Expand to Vec<RegisterBlockField> optimistically assuming that SVD arrays can be kept as arrays.
  • Then have a separate pass on the Vec<RegisterBlockField> expanding arrays when necessary.
  • We also need to consider arrays with names in dimIndex, if we defer expanding those then we need to push the dimIndex into the RegisterBlockField, which seems a bit ugly. Instead, I think factor out the array-expansion code so it can be called separately to cover this case also.

@burrbull does that sound like a sensible plan to you? Or am I still missing some complexity.

@burrbull
Copy link
Member

I'm thinking about 2-pass expanding of peripheral children.
On first pass we need to get memory map of peripheral.
It might look like Vec<u8> where u8 is number of different registers mapped on corresponding byte of peripheral.
Size of vector is number of bytes in peripheral.
On second pass we can see if register/cluster intersects with any other just by looking on memory map.
This is just an idea.

@rcls
Copy link
Contributor Author

rcls commented Jun 21, 2021

A much less elegant solution, but easier to implement, would be to add methods to do the array indexing on the containing cluster: get_foo(self,idx:usize)->&FOO
That can just do address arithmetic internally.
One advantage of this, is that it can co-exist with cluster arrays with named elements.

@burrbull
Copy link
Member

A much less elegant solution, but easier to implement, would be to add methods to do the array indexing on the containing cluster: get_foo(self,idx:usize)->&FOO
That can just do address arithmetic internally.
One advantage of this, is that it can co-exist with cluster arrays with named elements.

This is a good temporary solution in the sense that we can deprecate it some time after we find better way and implement it.

@rcls
Copy link
Contributor Author

rcls commented Jun 23, 2021

A slight variant on the get_foo() idea: create a zero-sized-type implementing the Index trait to do the address calculations. As long as safe code cannot create objects of that type, it is just more convenient syntax for the same thing.
It seems pretty straightforward to code...

@rcls
Copy link
Contributor Author

rcls commented Jul 19, 2021

Closing this pull-request. #534 has a different approach which doesn't fall foul of the problems discussed above.

@rcls rcls closed this Jul 19, 2021
bors bot added a commit that referenced this pull request Jul 21, 2021
534: Emit more Cluster arrays as arrays instead of lists of elements. r=burrbull a=rcls

(This obsoletes #531)
Some Cluster arrays cannot be emitted as Rust (built-in) arrays due to padding between elements.
Add a helper zero-sized type `ArrayProxy` that overloads `[]` to do pointer-arithmetic internally.

I believe, although I'm not 100% confident, that I'm not breaking Rust safety, as follows: There is no way for (safe) code to create an `ArrayProxy`. Code that produces a (reference to) an `ArrayProxy` has to use `unsafe` somewhere.

See rcls/svd2rust-example@b8645fe for any example of the difference this makes (or does not make):
- STM32L051 and LPC408x get no change.
- Cypress PSOC gets a significant difference.

This uses const generics, so the new functionality requires the `--const_generic` command line optoin.

Co-authored-by: Ralph Loader <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-tools
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants