Open HarryMakes opened 3 years ago
It would become difficult to determine which module a CSR belong to, and this seems prone to errors IMO.
I suggest doing things explicitly:
for i in range(2):
dummy = DummyAutoCSR()
setattr(self.submodules, "dummy_{}".format(i), dummy)
And instead of using AutoCSR
, it is also possible to implement get_csrs
manually, e.g.
def get_csrs(self):
return self.submodule1.get_csrs() + self.submodule2.get_csrs()
Yes, anyone who use MiSoC should be careful with their CSRs and understand how each helper method is currently implemented. Either by adding each AutoCSR
object as a named submodule, or overriding get_csrs()
should suffice to avoid this kind of CSR name conflicts.
That said, what I'm proposing is assuming that the user doesn't know deeply how our SoC builder works with CSR structures, and hence defining objects in an unexpected way while still passing the Python compile-time requirements. If my assumption is valid, then there should be a way to either stop the user from doing so, or adopt this kind of CSR instantiation as a new feature to bring CSRs from deeper levels to the current module level without setting attributes to self.submodules
.
If my assumption doesn't really hold, then perhaps my proposal isn't helpful, and I'd better work on the documentations instead. :thinking:
This PR is an attempt to tackle an issue where multiple CSRs with the same name are instantiated within different submodules, and then collected only at some ancestor at higher levels indirectly.
Background
Normally, a CSR should be made collectible by some CSR bank implementations (e.g.
misoc.interconnect.csr_bus.CSRBankArray
) by instantiating it as a member in anAutoCSR
object that, itself, is added as a member of the CSR bank object. The implication is that a CSR should be instantiated within a named submodule of the source module of the bank. For example, inSoCCore
implementations, the hierarchy of CSRs is normally like this:Possible Scenario
The user of MiSoC might want to add a CSR several levels below a module representing its device, while still being able to allocate memory for the CSR. While the gatherer functions like
get_csrs()
andget_memories()
can recursively collect CSRs, these functions require that the submodule at each sub-level must be named (i.e. usingself.submodules.xyz = ...
). If the user does not intend to name the submodule, these gatherers would fail. Consider the following scenario:This code would force the gatherer functions to collect the underlying CSR in
dummies[0]
. However, the current implementation of the gatherers would only add a unique prefix to the CSR name (e.g. for the bank on the top level) if its owner is a named submodule. Thus, while the CSR referred bydummy.dummy_csr
would be renamed asdummy_dummy_csr
, the CSR referred byspecial_csr
would simply be calleddummy_csr
by the gatherer. Consider adding the following line toDummyDevice
:Instead of
another_special_csr
, the gatherer would call itdummy_csr
without prefixing. Now, there will be twodummy_csr
in the list of the CSR collection, which would result in name duplication error whenmisoc.integration.builder
is generating thecsr.h
orcsr.rs
for theSoCCore
.Solution
While I am unsure whether or not the user should be prohibited from adding CSRs to the collection in this manner, there should be a way to have the gatherer functions uniquely naming the CSRs. My proposal is to make these gatherers scan through all the submodules to check if the CSR is owned by one (or some submodule at an even lower level). If so, the original attribute name assigned as a reference to the CSR at the current module level will be used as a unique identifier. This means for the above code, the
get_csrs()
gatherer called on theDummyDevice
object would return the following list of CSR names:["dummy_dummy_csr", "special_csr", "another_special_csr"]
. An example of the generatedcsr.rs
would now contain the following: