google / xls

XLS: Accelerated HW Synthesis
http://google.github.io/xls/
Apache License 2.0
1.19k stars 174 forks source link

Assigning bit-slices to tuple with pattern matching ? #1180

Open hzeller opened 10 months ago

hzeller commented 10 months ago

Sometimes, the bit-splicing operations can get a bit hard to read, in particular when extracting multiple ranges.

What would be good is to have an option to write assigning to a tuple in a pattern-matching style. Since the right-hand side is of known width, we can assign bits to the left-hand side to a tuple that sums up to the exact same number of bits (and even determine one unknown bit-width).

In the IR, this would just be regular bit-slices.

 let x = u32:42;
 let (foo:u1, bar:u2, baz:u29) = x;     // bit-splice with all widths defined
 let (sign:u1, exp, mantissa:u23) = x;  // bit-splice, auto-determine width of exp
 let (sign, exp, mantissa:u23) = x;     // ERROR: two fields without width
 let (sign:u1, _, rounding:u1) = x;     // can also be used for "don't care"

Possible relevant issue for discussion: bit-endianness needs to be intuitive ( Similar issue with with other bit-slice operations). Most intuitive would be if it behaves opposite to ++:

let (sign:u1, exp, mantissa:u23) = x; 
let y = sign ++ exp ++ mantissa;
assert_eq(x, y);
allight commented 10 months ago

Just putting my thoughts from xls-dev in here.

Imo this is something we probably want to have a more explicit std magic function for.

The rest of dslx is really against any sort of automatic conversion (even let x: u8 = ...; let y : u16 = x needs a cast) so I don't see this as any different.

I'd advocate for something like BitSlice!<(u1, u2, u3)>!(x) in the standard library implemented as a builtin.

This does prevent you from doing any sort of "don't care about the middle bits" style thing without making it even more magical.

proppy commented 3 weeks ago

maybe an explicit cast from scalar to tuple would be more consistent with existing dslx semantics?

let (foo, bar, baz) = u32:41 as (u1, u2, u29);

it could even leverage @dplassgit rest of tuple operator.

let (foo, .., baz) = u32:41 as (u1, u2, u5, u24);
allight commented 3 weeks ago

I still kind of prefer the magic-macro version just for pushing the user to think about what they're doing but @proppy's suggestion seems fine to me.