Skip to content

Commit 180c1d4

Browse files
vk2sebzyp
authored andcommitted
fixed.Shape: modify signature to accept underlying storage and f_bits
1 parent 9df1ab8 commit 180c1d4

File tree

1 file changed

+19
-14
lines changed

1 file changed

+19
-14
lines changed

text/0041-fixed-point.md

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,35 +27,38 @@ TODO
2727

2828
This RFC proposes a library addition `amaranth.lib.fixed` with the following contents:
2929

30+
### `fixed.Shape`
31+
3032
`fixed.Shape` is a `ShapeCastable` subclass.
3133
The following operations are defined on it:
3234

33-
- `fixed.Shape(f_width, /, *, signed)`: Create a `fixed.Shape` with zero integer bits and `f_width` fractional bits.
34-
- `fixed.Shape(i_width, f_width, /, *, signed)`: Create a `fixed.Shape` with `i_width` integer bits and `f_width` fractional bits.
35-
- The sign bit is not included in `i_width` or `f_width`, so a `fixed.Shape(7, 8, signed=True)` will be 16 bits wide.
36-
- `fixed.Shape.cast(shape, f_width=0)`: Cast `shape` to a `fixed.Shape` instance.
37-
- `.i_width`, `.f_width`, `.signed`: Width and signedness properties.
35+
- `fixed.Shape(shape, f_bits)`: Create a `fixed.Shape` with underlying storage `shape` and `f_bits` fractional bits.
36+
- The signedness is inherited from `shape`, so a `fixed.Shape(signed(16), 12)` would be a signed fixed-point number, 16 bits wide with 12 fractional bits.
37+
- A `fixed.Shape` may be constructed using the following aliases:
38+
- `SQ(i_bits, f_bits)` is an alias for `fixed.Shape(signed(i_bits + f_bits), f_bits)`.
39+
- `UQ(i_bits, f_bits)` is an alias for `fixed.Shape(unsigned(i_bits + f_bits), f_bits)`.
40+
- `fixed.Shape.cast(shape, f_bits=0)`: Cast `shape` to a `fixed.Shape` instance.
41+
- `.i_bits`, `.f_bits`, `.signed`: Width and signedness properties of the `fixed.Shape`.
42+
- `.i_bits` includes the sign bit. That is, for `fixed.Shape(signed(16), 12)`, `.i_bits == 4`.
3843
- `.const(value)`: Create a `fixed.Const` from `value`.
3944
- `.as_shape()`: Return the underlying `Shape`.
4045
- `.__call__(target)`: Create a `fixed.Value` over `target`.
4146

42-
`SQ(*args)` is an alias for `fixed.Shape(*args, signed=True)`.
43-
44-
`UQ(*args)` is an alias for `fixed.Shape(*args, signed=False)`.
47+
### `fixed.Value`
4548

4649
`fixed.Value` is a `ValueCastable` subclass.
4750
The following operations are defined on it:
4851

4952
- `fixed.Value(shape, target)`: Create a `fixed.Value` with `shape` over `target`.
50-
- `fixed.Value.cast(value, f_width=0)`: Cast `value` to a `fixed.Value`.
51-
- `.i_width`, `.f_width`, `.signed`: Width and signedness properties.
53+
- `fixed.Value.cast(value, f_bits=0)`: Cast `value` to a `fixed.Value`.
54+
- `.i_bits`, `.f_bits`, `.signed`: Width and signedness properties.
5255
- `.shape()`: Return the `fixed.Shape` this was created from.
5356
- `.as_value()`: Return the underlying value.
5457
- `.eq(value)`: Assign `value`.
5558
- If `value` is a `Value`, it'll be assigned directly to the underlying `Value`.
5659
- If `value` is an `int` or `float`, it'll be cast to a `fixed.Const` first.
5760
- If `value` is a `fixed.Value`, the precision will be extended or rounded as required.
58-
- `.round(f_width=0)`: Return a new `fixed.Value` with precision changed to `f_width`, rounding as required.
61+
- `.round(f_bits=0)`: Return a new `fixed.Value` with precision changed to `f_bits`, rounding as required.
5962
- `.__add__(other)`, `.__radd__(other)`, `.__sub__(other)`, `.__rsub__(other)`, `.__mul__(other)`, `.__rmul__(other)`: Binary arithmetic operators.
6063
- If `other` is a `Value`, it'll be cast to a `fixed.Value` first.
6164
- If `other` is an `int`, it'll be cast to a `fixed.Const` first.
@@ -65,6 +68,8 @@ The following operations are defined on it:
6568
- `.__neg__()`, `.__pos__()`, `.__abs__()`: Unary arithmetic operators.
6669
- `.__lt__(other)`, `.__le__(other)`, `.__eq__(other)`, `.__ne__(other)`, `.__gt__(other)`, `.__ge__(other)`: Comparison operators.
6770

71+
### `fixed.Const`
72+
6873
`fixed.Const` is a `fixed.Value` subclass.
6974
The following additional operations are defined on it:
7075

@@ -93,9 +98,9 @@ TBD
9398
Multiplying an integer with a fixedpoint constant and rounding the result back to an integer is a reasonable and likely common thing to want to do.
9499

95100
- There's two slightly different [Q notation](https://en.wikipedia.org/wiki/Q_(number_format)) definitions, namely whether the bit counts includes the sign bit or not.
96-
Not having the sign bit included seems more common, and has the advantage that a number has the same fractional precision whether `i_width` is 0 or not.
97-
98-
- While Q notation names the signed type `Q`, it's more consistent for Amaranth to use `SQ` since other Amaranth types defaults to unsigned.
101+
- Not having the sign bit included seems more common, and has the advantage that a number has the same fractional precision whether `i_bits` is 0 or not.
102+
- Having the sign bit included is the dominant notation in the audio ASIC world (citation needed, comment from samimia-swks@). As of now, this RFC uses this notation as it is also a little simpler to reason about the size of underlying storage on constructing an `SQ`.
103+
- While Q notation names the signed type `Q`, it's more consistent for Amaranth to use `SQ` since other Amaranth types defaults to unsigned.
99104

100105
## Prior art
101106
[prior-art]: #prior-art

0 commit comments

Comments
 (0)