google / google/xls

Improve `for` loop syntax

Open
#1,671 2 comments 0 reactions 1 assignee Claimed by @erinzmoore View on GitHub
dslx dslx:syntax 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)

for loops are quite cumbersome compared to other languages like C++ or SystemVerilog.

This largely stems from the lack of `mut`, probably, but it is still a pain every time I need to write a for loop.

Consider an egregious case of building 2 related 2D arrays. In other languages, this would otherwise be a trivial nested for loop with adjacent inner loops. Let's take SystemVerilog as an example, since the focus is on representing synthesizable hardware:

```
baz_t [J-1:0][I-1:0] foo;
baz_t [K-1:0][I-1:0] bar;

always_comb begin
for (int i = 0; i < I; i++) begin
for (int j = 0; j < J; j++) begin
foo[j][i] = baz_t'(...);
end

for (int k = 0; k < K; k++) begin
bar[k][i] = baz_t'(...);
end
end
end
```

This takes significantly more thought to write in DSLX (see below).

### Current best alternative workaround (limit 100 words)

Two approaches come to mind (just sketched out, may have errors). Neither seems as easy to get right without thinking as the code above.

1. Do all the updates in the inner loop and keep track of multiple layers of the full array accumulator. Something like:
```
let (foo, bar) = for(i, (foo, bar)): (u32, (baz_t[I][J], baz_t[I][K])) in range(u32:0, I) {
let foo_new = for(j, foo): (u32, baz_t[I][J]) in range(u32:0, J) {
let foo_j = update(foo[j], i, ...);
update(foo, j, foo_j)
}(foo);

let bar_new = for(k, bar): (u32, baz_t[I][K]) in range(u32:0, K) {
let bar_k = update(bar[k], i, ...);
update(bar, k, bar_k)
}(bar);

(foo_new, bar_new)
}((zero!(), zero!()));
```

1. Split this into two outer loops, so you can do the array updates in the same direction as the nested looping:
```
let foo = for(j, foo): (u32, baz_t[I][J]) in range(u32:0, J) {
let foo_j_new = for (i, foo_j): (u32, baz_t[I]) in range(u32:0, I) {
update(foo_j, i, ...)
}(foo[j]);
update(foo, j, foo_j_new)
}(zero!());

let bar = for(k, bar): (u32, baz_t[I][K]) in range(u32:0, K) {
let bar_k_new = for (i, bar_k): (u32, baz_t[I]) in range(u32:0, I) {
update(bar_k, i, ...)
}(bar[k]);
update(bar, k, bar_k_new)
}(zero!());
```

### Your view of the "best case XLS enhancement" (limit 100 words)

Make it easier to write for loops.

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.