Skip to content

[WIP] Implement RFC 41: lib.fixed #1578

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

vk2seb
Copy link
Contributor

@vk2seb vk2seb commented Apr 21, 2025

Overview

  • This is a staging ground for experimenting with the ergonomics of lib.fixed while the associated RFC is being worked on. It started as a fork of @zyp's early implementation of the RFC here, however a few things have changed since then.
    • Most importantly, this PR adds some tests, which makes it more obvious what the consequences of different design decisions will be.
    • Also, all operators required for real-world use are now implemented
  • As of now, this PR adheres to the latest version of the RFC, with some minor changes (these will be discussed further in the RFC issue):
    • New methods on fixed.Value - .saturate() and .clamp() - these are commonly needed in my DSP codebase, but it may make sense to punt these new methods to a future RFC.
    • .truncate() is added as an alias for .reshape(), the only difference being that it verifies there was a reduction of f_bits requested.
    • The numerator() method is dropped, as I found a way to combine it with as_value() reliably.
  • I have already integrated this implementation of lib.fixed in this Tiliqua PR and tested it underneath my library of DSP cores, and will continue to use the learnings there in order to guide the RFC.
  • It should be obvious that this PR needs a cleanup pass, improved diagnostics, and a lot of documentation work after the RFC is complete. However, it is already usable in real projects as all essential operations are implemented.

Simple example

Consider the implementation of a simple Low-pass filter, where we wish to compute the difference equation y = y[n-1] * beta + x * (1 - beta) using fixed point representation:

class OnePole(wiring.Component):

    def __init__(self, beta=0.9, sq=fixed.SQ(1, 15)):
        self.beta = beta
        self.sq = sq
        super().__init__({
            "x": In(sq),
            "y": Out(sq),
        })

    def elaborate():
        m = Module()
        a = fixed.Const(self.beta, shape=self.sq)
        b = fixed.Const(1-self.beta, shape=self.sq)
        # Quantization from wider to smaller fixed.Value occurs on the `.eq()`
        m.d.sync += self.y.eq(self.y*a + self.x*b)
        return m

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

1 participant