opentitan
opentitan copied to clipboard
[topgen] Improve support for multiple address spaces
I'm working towards adding support for multiple CPUs within the OpenTitan complex. With this change, topgen
supports MMIO regions in multiple address spaces. It requires associating each memory with an address space, which is now required to be defined in the top-level HJSON definition.
Further, topgen
generates defines for the peripheral interface for all address spaces. For Darjeeling, that means the SOC-facing interfaces, e.g., the SOC port of the mailbox, get their base address definitions and the size of the address window.
It further fixes a bug to correctly compute TOP_DARJEELING_MMIO_SIZE_BYTES
for the rust definitions, which are the same now as the C definitions. In general, the code here is duplicated. I suggest factoring that out and follow a DRY principle.
It might help if I could understand the desired feature set and where topgen currently falls short. For this case of "multiple CPUs within the OpenTitan complex," what sort of topology are we talking about for the interconnect? Do each of these CPUs actually have different maps?
How should the C and Rust output look when there are multiple address spaces of interest? Do we have 1 file per address space or a single file that puts all address spaces together? If it's the former, do we need the name of the address space to be part of the identifier?
For a CPU inside the OpenTitan complex, I'd think each CPU would only need the one address space (i.e. the one attached to its host node in the xbar definition). Are there cases where a CPU would bridge into other address spaces?
It might help if I could understand the desired feature set and where topgen currently falls short. For this case of "multiple CPUs within the OpenTitan complex," what sort of topology are we talking about for the interconnect? Do each of these CPUs actually have different maps?
Right now, I envision multiple CPUs that have their own maps but share common infrastructure from the RoT CPU. For example, the RoT Ibex has one alert manager connected and is in charge of configuring it. IPs from other maps are attached to this one alert manager. There might be a shared bus, connecting the current egress ports of Darjeeling and a second CPU, as well as some shared IPs.
How should the C and Rust output look when there are multiple address spaces of interest? Do we have 1 file per address space or a single file that puts all address spaces together? If it's the former, do we need the name of the address space to be part of the identifier?
Currently, I used a single TopgGenC call to generate a common C/Rust output for all address spaces. This is the main shortcoming of topgen right now. However, the more I think about it, it may make more sense to perform multiple TopGenC calls for every address space, generating individual C and Rust outputs for every address space. It would leave the outputs not polluted with outputs from other address spaces. But I think FW teams should maybe chime in here?
For a CPU inside the OpenTitan complex, I'd think each CPU would only need the one address space (i.e. the one attached to its host node in the xbar definition). Are there cases where a CPU would bridge into other address spaces?
Currently, we think the same. The CPU needs only one address space, which is orthogonal to other CPUs.
Right now, I envision multiple CPUs that have their own maps but share common infrastructure from the RoT CPU. For example, the RoT Ibex has one alert manager connected and is in charge of configuring it. IPs from other maps are attached to this one alert manager. There might be a shared bus, connecting the current egress ports of Darjeeling and a second CPU, as well as some shared IPs.
So in this case, the shared infrastructure may be at different addresses vs. the RoT CPU, I suppose. That's fine, but that might mean we'll want them to have generated output that is tailored to their specific maps. And that leads us to the next bit... :)
Currently, I used a single TopgGenC call to generate a common C/Rust output for all address spaces. This is the main shortcoming of topgen right now. However, the more I think about it, it may make more sense to perform multiple TopGenC calls for every address space, generating individual C and Rust outputs for every address space. It would leave the outputs not polluted with outputs from other address spaces. But I think FW teams should maybe chime in here?
Hehe, I'm also part of the FW team, but agreed on all points. I figure it would be best to generate a different file for each address space. For a given CPU, it should only use the file that is for its own address space. Ultimately, if a CPU has a different map, then it can't be treated as the exact same compilation target--We can hide the differences behind a library interface and avoid duplicating an entire build graph, though!
If possible, it'd be nice to not need the address space name to be part of the C macro name, to need to disambiguate between address spaces. As long as there is no bridging across spaces, I think that should work fine, assuming I'm not missing something.
Rust's namespaces are nicer to work with than C's one, big, global namespace, so it might matter less there.
Currently, we think the same. The CPU needs only one address space, which is orthogonal to other CPUs.
Thanks for clarifying!
Closing as superseded by #23122