Skip to content

[IO] Unintuitive behavior with IO objects #1349

@leonardt

Description

@leonardt

Here's an example of some code that doesn't work because of the immutable nature of IO objects.

class RegisterFile(m.Generator):
    def __init__(self, n: int, T: m.Type, has_read_enable: bool = False):
        addr_len = m.bitutils.clog2(n)
        self.io = m.IO(
            raddr=m.In(m.Bits[addr_len]),
            rdata=m.Out(T),
            wen=m.In(m.Enable),
            waddr=m.In(m.Bits[addr_len]),
            wdata=m.In(T)
        )
        rdata = self.io.rdata
        if has_read_enable:
            self.io += m.IO(ren=m.In(m.Enable))
            rdata_reg = m.Register(T)()
            rdata @= rdata_reg.O

The problem here is that the rdata reference is invalidated when the new IO object is created to add the port.

We should at least raise a useful error here (e.g. "Attempting to wire to an invalidated IO object"), although I think we might consider whether we should make IO object mutable to make this seemingly natural code work.

Is there a strong argument for immutability of IO objects? i.e. is there a class of errors we'd like to avoid that immutability guarantees us against? As it currently stands, immutability actually introduces a new class of possible errors, so we'd want a strong argument for why these errors are useful for users (i.e. how they can avoid users introducing more difficult to fix errors).

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions