Skip to content

Alternate concept for VirtualMux #187

@clint-lawrence

Description

@clint-lawrence

This came about while thinking of other ways to create a VirtualMux that will be type hint and IDE friendly. Originally a comment on #184 but I think it is better to have an issue separate from that so it doesn't get lost.

Each signal would be a method on the resulting VirtualMux subclass. This would be a big change for existing scripts. But once the jig refactor PR lands, we could introduce something like this and scripts could choose which style to use. For new scripts, the IDE autocomplete benefits of this approach would be nice to have. (There might be a way to type-hint the current VirtualMux, but I haven't figured it out)

# existing
class Mux(VirtualMux):
    pin_list = ("x0", "x1", "x2")
    map_list = (
        ("sig1", "x0"),
        ("sig2", "x1"),
        ("sig3", "x2", "x0"),
    )

#new
@dataclass
class MuxNew(VirtualMux):
    sig1: Sig = signal("x0")
    sig2: Sig = signal("x1")
    sig3: Sig = signal("x2", "x0")

dm.jig.mux.Mux("sig2")
# becomes
dm.jig.mux.NewMux.sig2()

# For tree defined multiplexers
#                                   __________
# a0-------------------------------|          |
#                       ________   |          |
# a1_b0----------------|        |--|          |
# a1_b1----------------| Mux B  |  |          |
#              (None)--|  4:1   |  |          |
# a1_b3----------------| x3  x2 |  |          |
#                      |________|  |          |
#                                  |  Mux A   |
# a2-------------------------------|   4:1    |
#                       ________   |          |
# a3_c0----------------|        |--|          |
# a3_c1----------------| Mux C  |  |          |
# a3_c2----------------|  4:1   |  |          |
#              (None)--| x5  x4 |  |          |
#                      |________|  |          |
#                                  |__x1__x0__|
muxA = MuxTree("x0", "x1")
muxB = MuxTree("x2", "x3", nest=muxA)
muxC = MuxTree("x4", "x5", nest=muxA)

@dataclass
class Mux(VirtualMux):
    a0: Sig = muxA()
    a1_b0: Sig = muxB()
    a1_b1: Sig = muxB()
    muxB()  # "throw away" one entry
    a1_b3: Sig = muxB()
    a2: Sig = muxA()
    a3_c0: Sig = muxC()
    a3_c1: Sig = muxC()
    a3_c2: Sig = muxC()

Implementation - Maybe? very not tested... Most likely bugs, but I think the concept is O.K. I think we would end up with signal returning a class instead of a function, but this maps out the general idea.

Sig = Callable[[VirtualMux, bool], None]

def signal(*pins) -> Sig:
    def _func(self: VirtualMux, trigger_update: bool=False):
        self._do_switch(pins, trigger_update)
    _func.pins = pins
    return _func


class MuxTree:
    def __init__(self, *pins: tuple[Pin], nest: MuxTree) -> None:
        self._pins = set(pins)
        self._pin_gen = generate_bit_sets(pins)
        if nest is not None:
            self._fixed_pins = nest().pins
        else:
            self._fixed_pins = set()

    def __call__(self) -> Sig:
        pins = self._fixed_pins  | next(self._pin_gen)
        return signal(*pins)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions