# [Libre-soc-dev] clamping/saturation semantics

Luke Kenneth Casson Leighton lkcl at lkcl.net
Sun Dec 13 03:36:41 GMT 2020

```On 12/13/20, Jacob Lifshay <programmerjake at gmail.com> wrote:

> I think the best way to do it is to do the ops at as wide as necessary to
> avoid overflowing intermediates, then do the saturation to dest size at the
> end.

there's one school of thought that advocates increasing the
intermediate width, another that the width should have been increased
at the src by the programmer already, and another is that the FU
probably has the intermediary result at the width already.

in the case of FP we already add at least 4 bits to the mantissa in
order to have guard, sticky, round and m0 duplicate, such that
rounding is guaranteed to be computed correctly.

> In particular, for i8 * i8 -> i8 multiplication, the intermediate needs to
> be i16, since otherwise you'd get the wrong answer:
> with 8-bit intermediates: 0x40 * 0x40 -> 0x00; saturates to -> 0x00 (wrong)
> with 16-bit intermediates: 0x40 * 0x40 -> 0x1000; saturates to -> 0x7F
> (correct)

in this case, it turns out that mul has an intermediate that is double
the bitwidth, anyway.

so testing the saturation limits on the intermediate is the sensible /
correct thing, i feel, but there is no need to expand either src or
dest width.

> Similarly for u8 - u8 -> u8 subtraction, the intermediate needs to be i9 to
> avoid getting the wrong answer:
> with 8-bit unsigned intermediates: 0x01 - 0xFF -> 0x02; saturates to ->
> 0x02 (wrong)
> with 9-bit signed intermediates: 0x01 - 0xFF -> -0xFE; saturates to -> 0x00
> (correct)

interestingly the same logic applies, and here it is the carry-out
that gives the 9th bit.

the one that is particularly odd is avg.  that one: how the heck do we
SIMD-i-fy and saturate that one??

> Same kind of thing for addition and left-shift.

it would be good to make sure each of these is documented.  we have to
go through them all when it comes to implementation so having some
notes will help.

l.

```