[enhancement] Allow non-constexpr indexing for arrays of channels
- Dominant language
- C++
- Stars
- 1.9k
- Forks
- 283
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 135
Description
### What's hard to do? (limit 100 words)
As noted in https://github.com/google/xls/issues/1726#issuecomment-2483175535, it's currently impossible to use an array of channels with non-`constexpr` indices. Currently this kind of operations are allowed in DSLX, but cannot be translated to IR. Supporting this syntax could be useful for implementing custom channel muxing/arbitration logic.
Here is an example of the syntax that can be used in DSLX, but will cause errors when translating to IR:
```rust
config(
sel_r: chan in,
chan_array: chan[10] in,
...
) { ... }
next(state: ()) {
let (tok, sel) = recv(join(), sel_r);
let (tok, result) = recv(tok, chan_array[sel]);
}
```
### Current best alternative workaround (limit 100 words)
A possible workaround is manually unrolling the array of channels:
```rust
config(
sel_r: chan in,
chan_array: chan[10] in,
...
) { ... }
next(state: ()) {
let (tok, sel) = recv(join(), sel_r);
let (tok, result) = unroll_for!(i, (tok, result)): (u32, (token, u32)) in range(u32:0, u32:10) {
recv_if(tok, n_req_r[i], sel == i, result)
}((tok, u32:0));
}
```
### Your view of the "best case XLS enhancement" (limit 100 words)
Supporting dynamic access to an array of channels would be useful, but several challenges need to be addressed:
1. `recv()` on a channel array is functionally equivalent to calling `recv_if()` on each channel individually. If the same `recv()` syntax is used, the actual cost of this operation may be hidden.
2. Similarly to handling arrays, there should be a reasonable default for handling out-of-bonds accesses
3. Arrays of channels can possibly become multidimensional
4. Access to channels individually should also remain possible.
To address challenges 1 and 2, dedicated keywords could be introduced to support this kind of operations:
```rust
let (tok, result) = array_recv(token, array_of_channels, index, default_value);
let tok = array_send(token, array_of_channels, index, value);
```
together with more specialized variants:
```rust
let (tok, result) = array_recv_if(token, array_of_channels, index, conditional, default_value);
let (tok, result, result_valid) = array_recv_non_blocking(token, array_of_channels, index, default_value);
let (tok, result, result_valid) = array_recv_if_non_blocking(token, array_of_channels, index, conditional, default_value);
```
In order to satisfy point 3, the `index` can use the same syntax as in the [update() built-in](https://google.github.io/xls/dslx_std/#update) and allow for passing a tuple.
To satisfy point 4, the exclusivity check should track all the indices individually.
Contributor guide
Assessment
This issue has not been assessed yet.