lowRISC / lowRISC/ibex

Ease of adapting Ibex memory protocol to tilelink for non 32-bit access

Open
#757 10 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Component:RTL Type:Task
Dominant language
SystemVerilog
Stars
2.1k
Forks
810
Avg merge
5d 23h
Merged PRs (30d)
9

Description

Tilelink has a `size` field it its message payload, that the native Ibex protocol does not have.

When accessing 'standard' memory this is not a big problem. An Ibex -> Tilelink adapater could just always use 32-bit sizes and set all byte-enables for read (`Get` in Tilelink terms) and for writes take the byte-enables from the `data_be_o` from Ibex.

However this could give some difficulties around reads to devices where a read could trigger some action. Specifically if a device triggers some action on particular byte reads and the simple adapter described above is used a single `lb` instruction will turn into a 4-byte `Get` in Tilelink. The device might then trigger an action because certain bytes have been read but from a programmer's perspective these bytes haven't been touched.

In Tilelink for a `Get` message you cannot partially set the byte mask, so you must use the `size` field to communicate what bytes you actually intend to read where this matters. Ibex (from a quick look at the RTL anyway) does generate `data_be_o` that indicates the precise bytes you want so it would be possible to build some logic that can work out an appropriate `size` from the `data_be_o`.

You may also find that your TileLink devices only respond to `PutFullData` so in order to do a byte-write to such a device you'd need to generate `PutFullData` with a byte size. Again the logic mentioned above could be employed to ensure the correct `size` field is generated along with some logic to understand if it's a `PullFullData` or not.

This logic would be a little fiddly, add extra area and increase the depth of logic. In some sense it's simply undoing what `ibex_load_store_unit` has done internally (taking the size and address and generating a be). We could introduce a `data_size_o` to the Ibex top-level interface allowing simpler adaption to Tilelink and other similar protocols.

We probably also want a requirement that `data_be_o` matches tilelink requires for its `mask` field but I think this is already the case, but worth documenting.

Another potential addition would a `data_full_o` that indicates `data_be_o` is set for every byte that's covered by `data_size_o`. This would allows a simple way to choose `PutPartialData` vs `PutFullData` on the tilelink interface. However it may be the adapter would always emit `PutPartialData` anyway. I will open an OpenTitan issue to discuss this point.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing ibex_load_store_unit and the Ibex top-level interface, focusing on how data_be_o represents accessed bytes. Define whether data_size_o and data_full_o are needed for TileLink adaptation, and document the required relationship between data_be_o and TileLink's mask and size fields.

Written by the indexing model from the issue text.

Assessment

Domain
embedded-iot
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.