google / google/xls

[enhancement] Allow non-constexpr indexing for arrays of channels

Open
#2,028 0 comments 0 reactions 0 assignees View on GitHub
enhancement
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.