enjoy-digital / litex

Build your hardware, easily!
Other
3k stars 569 forks source link

RFC: Etherbone address detection #2085

Open m-byte opened 1 month ago

m-byte commented 1 month ago

I was recently thinking about how it would be nice of we were able to automatically detect the addresses of some standard ip cores connected to etherbone (haven't really looked into that, but this proposal probably also applies to uartbone and other host bridges). Here's the approach that seems most sensible to me:

Introduce a new message type on the same port as etherbone, but change the magic numbers slightly (e.g. 0x4E9F). The header should be similar to etherbone and include at least the following: Magic number, version, message type, actual number of records, maximum number of records, flags for support of optional features, a more data available flag After the header comes data with the length defined in the header.

As for message types, I envision the following: A) DETECT_REQ: a detection request, if the protocol extension is supported, the other side will respond with DETECT_ACK. No response after a certain time period means the extension is not supported and csr files are definitely required. Number of entries is the maximum number of records that should be replied with. B) DETECT_ACK: see above, number of entries is the actual number of entries sent back C) DETECT_CONTINUE (optional): similar to DETECT_REQ, but starting after the last entry returned (only to be used if the more flag was set) D) ADDR_REQ (optional): a way to request individual records by their well known id (see below) E) ADDR_RESP (optional): response to ADDR_REQ with up to the maximum requested number of entries. The available number of entries per type should usually be identical to the number of published instances of that module.

The records: All records consist of the following data within a fixed length): Well known id Base address Version Space for some optional flags that would have to be defined per module (module authors would be expected to change the version when making incompatible changes to these optional flags)

Well known ids: To simplify the detection of standard cores (e.g. bitbang i2c, litei2c, litespi, litescope, ...), a range of ids should be set aside to uniquely identify these. This range should be managed either in a repo or wiki to prevent collisions. For custom modules, another range should be set aside.

This should integrate into the host bridge, so that the address width determined using e.g. etherbone probe can be assumed to also apply to the address detection scheme. Since the requesting side is usually a computer, this would move potential overhead to that side.

Purpose: For external tools like sigrok, litescope_cli or custom tools, there is currently no way around either compiling the base addresses (which might change from system to system) into the binary or accepting a csr.csv/.json. This can be quite annoying for users, as this file might change between versions and has to be kept track of accordingly. With this scheme, it would be possible to publish specific modules, or all modules in a soc in a way that would be easy for external tools. For less powerful FPGAs, only the basic DETECT part would have to be implemented. For more powerful FPGAs, which are more likely to have a lot of modules inside, the optional ADDR feature would simplify the detection of specific modules. So, depending on users needs it would be possible to e.g. only publish the deviceid address, multiple I2C ports or even all the modules available in the soc.

Of course, there is still one caveat: tools like litescope_cli would need more data than realistically could be placed into the optional data section, so some additional feature to also exchange this would be very convenient.

Alternatives I considered:

  1. Define a well known address in wishbone -> almost impossible to make backward compatible
  2. Have a second wishbone with CSRs that is only accessible to host bridges, store the data described above in those CSRs and then use the magic numbers to switch between the two -> seems wasteful

Any thoughts on this?

enjoy-digital commented 1 month ago

Hi @m-byte,

Thanks for the suggestion. One possible alternative could be using a dedicated ROM to store this information, potentially in a compiled .dtb format. This way, the host can simply read from the ROM and get all the required details about the SoC. It would avoid the need for a specific protocol and the pricinple would be the same for all bridges.

m-byte commented 1 month ago

@enjoy-digital that would fall under 1. above. You'd have to specify a well known address for this to ROM. Otherwise, you'd still have to tell all tools about the address of the ROM. However, a well known address might interfere with addresses a user has pinned. Potential issues here mean that it would be difficult to enable this by default. However, without being enabled by default, especially new users won't know about it and it is unlikely to be adopted by tools. Thinking about this a bit more, though, it should actually be possible to turn it on by default, as long as possible address collisions are detected and the ROM is not generated in those cases.

Btw: I feel like this ROM should by default only contain the most important addresses (i.e. litescope and crossover uart, maybe i2c/spi) as those are most likely to be used by external tools and there are a lot of lower end FPGAs that wouldn't have as much memory to spare. With potential resource constraints in mind, I'm also doubtful whether dtb would be our best option. It would only be beneficial when booting Linux on the SoC. Any other OS (especially the ones meant for MCU-like systems) won't use it on-device. Of ourse, it has the advantage that it is well defined and that there are a lot of tools around it. And as I wrote before, it would make sense to store some extra data (e.g. for litescope to communicate the signals being measured, buffer size, etc)