amaranth-lang / amaranth-soc

System on Chip toolkit for Amaranth HDL
BSD 2-Clause "Simplified" License
83 stars 31 forks source link

MemoryMap should allow adding windows with a larger granularity than the parent #97

Open zyp opened 3 months ago

zyp commented 3 months ago

The data_width attribute of a MemoryMap reflects not the actual data width, but the granularity of the associated bus. A 32-bit bus with byte lanes hence has a memory map with data_width = 8.

MemoryMap.add_window() performs the following check:

        if window.data_width > self.data_width:
            raise ValueError(f"Window has data width {window.data_width}, and cannot be added to a "
                             f"memory map with data width {self.data_width}")

This restriction makes it impossible to add a window without byte lanes (e.g. with granularity 32) to a parent memory map with granularity 8, even if both of the associated buses have an actual data width of 32.

I would like to have a 32-bit wide CSR bus connected to a 32-bit CPU with byte lanes. While the byte lanes are trivial to shim, MemoryMap doesn't support this arrangement, so instead of adding the target memory map as a window, I have to work around it by copying and transforming each individual resource entry to a new memory map.

Example implementation of a simple granularity converter that silently ignores writes smaller than the target granularity: https://paste.jvnv.net/view/g35PB

jfng commented 3 months ago

I think we should add a granularity parameter to csr.Signature instead, which becomes the data_width of the MemoryMap. The data_width of csr.Signature would be restricted to multiples of granularity.

zyp commented 3 months ago

The issue is not strictly limited to CSR buses. You'll run into the same issue any time you would like to attach a target without byte lanes to an initiator with byte lanes. E.g. third party IP cores with memory mapped IO.