[enhancement] More control over the state of channel queues
- Dominant language
- C++
- Stars
- 1.9k
- Forks
- 283
- Avg merge
- 2d 12h
- Merged PRs (30d)
- 130
Description
### What's hard to do? (limit 100 words)
We'd like to be able to clear contents of the channel queue. This stems from a need to reset a hierarchy of procs sometimes, e.g. after encountering an error. Resetting such hierarchy was already proposed in [#1680 [enhancement] Resetting a hierarchy of subprocs](https://github.com/google/xls/issues/1680), but to guarantee correct execution of resetted procs all channel queues inside this hierarchy must be cleared as well. Otherwise any messages left in queues after the reset that were sent before the reset can cause incorrect results to be produced at best, or incorrect behavior or proc lockup at worst. Resetting proc's state can be currently expressed via non-blocking receive on a dedicated channel, so this enhancement proposal would be useful even without a mechanism for resetting procs baked into the language.
To illustrate these points, consider this example proc that sends a request for 4096 data packets and receives them over 4096 consecutive `next()` evaluations. with the possibility that external reset request clears the `to_receive` counter:
```rust
init { u32:0 }
next(to_receive: u32) {
const REQUEST_N = u32:4096;
let tok = join();
let (_, (), reset_valid) = recv_non_blocking(tok, reset_req_r, ());
send_if(tok, read_req_s, to_receive == u32:0, REQUEST_N);
let (tok, data) = recv(tok, read_resp_r);
let processed_data = data + u32:1;
send(tok, data_out_s, processed_data);
if (reset_valid) {
u32:0
} else if (to_receive == u32:0) {
REQUEST_N - u32:1
} else {
to_receive - u32:1
}
}
```
When a reset request is received on `reset_req_r` state is set to 0, but there may be some lingering packets left in the `read_resp` channel queue that we would like to clear as well.
### Current best alternative workaround (limit 100 words)
One can write a proc in such a way that it will track the amount of messages it needs to receive in case a reset request comes in. Once it does, it needs to perform that amount of receives and discard the received data to empty the queue. This is:
- inefficient in cases where the amount of data requested is very large - we don't want to spend time receiving a gigabyte of data that needs to be discarded anyway because there was some error during processing it halfway through.
- cumbersome for large trees of procs - every proc would need to implement this behavior of receiving non-blocking reset request on dedicated channel and counting how many data it needs to receive to empty all queues during the reset
### Your view of the "best case XLS enhancement" (limit 100 words)
Ability to reset channel queues from within DSLX. This could be as simple as sending a request on a dedicated 0-depth reset channel that is tied to a specific channel.
```rust
let (data_s, data_r, data_rst) = rchan("data");
```
Contributor guide
Research direction
Start by reading the linked #1680 proposal and the DSLX proc example, especially the rchan declaration and recv/send operations. Determine how channel queue reset behavior should relate to proc state reset, and consider the stated requirement that lingering messages be removed without receiving and discarding them individually. Done means the enhancement has a settled design for resetting a specific channel queue from DSLX.
Written by the indexing model from the issue text.
Assessment
- Domain
- compilers
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100