svd2rust icon indicating copy to clipboard operation
svd2rust copied to clipboard

Indirect register access

Open daym opened this issue 4 years ago • 3 comments

It would be nice to be able to use svd2rust for SVDs that describe indirect accesses via a data port register (for example the infamous pci index and pci data register, MSRs, etc).

I'll try to extend svd2rust to do that, but I wanted to ask first

(1) Whether there will be unforseen hurdles

(2) Whether there is interest in that

For these kind of indirect accesses, svd2rust would not be able to use RegisterBlocks that are represented as real C structs directly accessed via MMIO. Reason is because the indirect access only allows you to read/write one word at a time.

daym avatar Mar 10 '21 18:03 daym

What sort of thing did you have in mind? I don't think the SVD specification has any support for indicating data port registers, so I don't know how you'd plan to tell svd2rust to generate whatever special output you needed.

It seems like this sort of thing would usually be handled by a higher level (a HAL) which would know how to access the data port and could present a more convenient API to the user.

adamgreig avatar Mar 10 '21 20:03 adamgreig

For the most important indirect access for us (SMN), it would be accessing a specific PCI device and two specific registers (always the same ones) in configuration space as the index and data register.

In https://github.com/daym/amd-register-interface-extractor we currently emit one svd file for each access method--including one for direct (MMIO) access, but the others all indirect.

So we'd know that we need an indirect access by virtue of this svd2rust invocation being with a svd file with all indirect accesses of this kind only (because that would be the only kind of thing that that specific svd file contains).

The implementation of the indirect access would need to be provided by the user.

For an overview, we have 24802 mmio-direct-accessed register instances (those work fine with svd2rust), 16140 SMN-indirect-accessed register instances, 2032 Data-Fabric-indirect-accessed register instances, 331 MSR-indirect-accessed register instances, 15 IO-indirect-accessed register instances, 6 IO-accessed register instances.

For the indirect accesses, we wrote the svd generator in a way that baseAddress + addressOffset now contains the final value that is supposed to go to the (implied) index register (including any flags already etc). So the only thing missing is a tool that processes the svds as before and generates accessors--but those accessors always would use an externally-provided way to load the index register with the respective addressOffset and then read/write the data register, instead of directly accessing memory. (See https://github.com/daym/amd-register-interface-extractor/blob/master/DESIGN.md at the bottom)

For our use case, it's really more or less random that they are behind such an indirect access. And we'd especially like to use the facility of svd2rust to make all those bitfields in each word nicely accessible, and for the namespacing.

(If you are curious about SMN, see https://www.youtube.com/watch?v=bKH5nGLgi08 starting at 20:00)

daym avatar Mar 10 '21 20:03 daym

That's a cool use case and I can see why you'd want to use svd2rust!

It sounds like the ideal situation would be if the sort of "user facing API generator" was separate so you could use it without the MMIO assumption. My feeling is that the svd2rust binary (at least the one we provide here) shouldn't include this sort of thing because it's completely out of scope - SVD files are explicitly only about MMIO, the format doesn't have anything to indicate an alternative indirect access, and indirect access to config/status registers tends to be a very rare feature in embedded microcontrollers.

There is interest in re-designing parts of the generated code so that instead of memory-mapped structs, we use only raw pointers and ptr::read_volatile/ptr::write_volatile, because of a long-standing issue where rustc can insert reads wherever it wants to references, which we need to avoid for MMIO. I could imagine that with such a change it might be possible to also have an alternative codegen that uses indirect access, but again we probably wouldn't want to include it in svd2rust-the-binary because it's so out of scope. Maybe it would be possible for you to build a binary that depends on svd2rust for almost all the generation, but then emits a custom indirect access method? I'm not sure exactly what this would look like, and perhaps once you've been able to prototype something on your side it would be clearer where it might tie in.

adamgreig avatar Mar 13 '21 20:03 adamgreig