You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: text/0041-fixed-point.md
+14-14Lines changed: 14 additions & 14 deletions
Original file line number
Diff line number
Diff line change
@@ -15,7 +15,7 @@ Add fixed point types to Amaranth.
15
15
Fractional values in hardware are usually represented as some form of fixed point value.
16
16
Without a first class fixed point type, the user has to manually manage how the value needs to be shifted to be represented as an integer and keep track of how that interacts with arithmetic operations.
17
17
18
-
A fixed point type would encode and keep track of the precision through arithmetic operations, as well as provide standard operations for converting values to and from fixed point representations with correct rounding.
18
+
A fixed point type would encode and keep track of the precision through arithmetic operations, as well as provide standard operations for converting values to and from fixed point representations.
- Comparisons between `fixed.Value` of matching size, or between `fixed.Value` and `int` are permitted.
76
-
- Comparisons between `fixed.Value` of different widths are not permitted.
77
-
- Users are guided by an exception to explicitly `truncate()` or `round()` as needed.
75
+
- Comparisons between `fixed.Value` of different `f_bits` are not permitted.
76
+
- Users are guided by an exception to explicitly `reshape()` as needed.
78
77
- Comparisons between `fixed.Value` and `float` are not permitted.
79
78
- Users are guided by an exception to explicitly convert using `fixed.Const` as needed.
80
79
@@ -86,7 +85,7 @@ The following additional operations are defined on it:
86
85
-`fixed.Const(value, shape=None, clamp=False)`: Create a `fixed.Const` from `value`. `shape` must be a `fixed.Shape` if specified.
87
86
- If `value` is an `int` and `shape` is not specified, the smallest shape that will fit `value` will be selected.
88
87
- If `value` is a `float` and `shape` is not specified, the smallest shape that gives a perfect representation will be selected.
89
-
If `shape` is specified, `value` will be rounded to the closest representable value first.
88
+
If `shape` is specified, `value` will be truncated to the closest representable value first.
90
89
- If `shape` is specified and `value` is too large to be represented by that shape, an exception is thrown.
91
90
- The exception invites the user to try `clamp=True` to squash this exception, instead clamping the constant to the maximum / minimum value representable by the provided `shape`.
92
91
-`.as_integer_ratio()`: Return the value represented as an integer ratio `tuple`.
@@ -124,7 +123,7 @@ TBD
124
123
125
124
- What should we do if a `float` is passed as `other` to an arithmetic operation?
126
125
- We could use `float.as_integer_ratio()` to derive a perfect fixed point representation.
127
-
However, since a Python `float` is double precision, this means it's easy to make a >50 bit number by accident by doing something like `value * (1 / 3)`, and even if the result is rounded or truncated afterwards, the lower bits can affect rounding and thus won't be optimized out in synthesis.
126
+
However, since a Python `float` is double precision, this means it's easy to make a >50 bit number by accident by doing something like `value * (1 / 3)`, and even if the result is truncated afterwards, the lower bits can affect rounding and thus won't be optimized out in synthesis.
128
127
- We could use the same width for `other` as for `self`, adjusted to the appropriate exponent for the value.
129
128
- We could outright reject it, requiring the user to explicitly specify precision like e.g. `value * Q(15).const(1 / 3)`.
130
129
- vk2seb@: I would lean toward outright rejecting this, with an explicit cast necessary (now reflected above).
@@ -135,7 +134,10 @@ TBD
135
134
- IEEE 754 defaults to round to nearest, ties to even, which is more expensive to implement.
136
135
- Should we make it user selectable?
137
136
- We still need a default mode used when a higher precision number is passed to `.eq()`.
138
-
- vk2seb@: Both truncation and simple rounding (round to nearest) are commonly used in DSP algorithms. For now, we provide only `truncate()` and `round()` strategies (now reflected above). Additional rounding strategies may be added in a future RFC, however we will always need a default rounding strategy.
137
+
- samimia-swks@: In most DSP applications, simple truncating is done (bit picking, which is equivalent to a floor()) because it's free. I would vote for that being the default behavior at least.
138
+
- ld-cd@: (...) Truncate is still a reasonable default for most applications.
139
+
- ld-cd@: (...) I think a better approach would be to leave rounding and several other common operations that require platform dependent lowering to a subsequent RFC (...).
140
+
- vk2seb@: Both truncation and simple rounding (round to nearest) are commonly used in DSP algorithms. For now, we provide only `reshape()` (truncation, now reflected above). Additional rounding strategies may be added in a future RFC, however we will always need a default rounding strategy, and truncation seems like a sane default.
139
141
140
142
- Are there any other operations that would be good to have?
141
143
- From ld-cd@: `min()`, `max()` on `fixed.Shape` (vk2seb@: agree, heavily use this)
@@ -163,9 +165,7 @@ TBD
163
165
- vk2seb@: The existing modifications address this:
164
166
- Library name: `lib.fixed`
165
167
- Type names and shapes: signature has now been updated to use `i_bits`, `f_bits` and the explicit underlying storage in the constructor for `fixed.Shape`.
166
-
- We now have both `.round()` and `.truncate()`. I don't think using the same name for increasing and decreasing precision is so bad. But if you feel strongly about this we may consider:
167
-
- Renaming them.
168
-
- Disallowing increasing precision with these methods, and add a new method for precision extension .
168
+
- We now have `.reshape()`, which better represents increasing and decreasing precision. However, I'm open to new names.
0 commit comments