phanrahan / magma

magma circuits
Other
253 stars 24 forks source link

Creating intermediate values using `Wire` gives `TypeError` #1327

Closed rkshthrmsh closed 1 year ago

rkshthrmsh commented 1 year ago

How to create a (verilog) wire to store an intermediate value? The following attempt gives a TypeError: unsupported operand type(s) for @=: 'Wire' and 'SInt[(2, Out(Bit))]'.

class Test1(m.Circuit):
    io = m.IO(
        A=m.In(m.SInt[2]),
        En=m.In(m.Bit),
        O=m.Out(m.SInt[2]),
    )
    temp = m.Wire(m.SInt[2])
    with m.when(io.En):
        temp @= io.A
    with m.otherwise():
        temp @= 0    

    io.O @= temp + 1

The equivalent verilog would be

assign temp = En? A : 0;
assign O = temp + 1;

How can this be done?

rkshthrmsh commented 1 year ago

Figured out there is no need to declare a Wire. Instead, calling the data type SInt serves the same purpose.

    temp = m.SInt[2]()
    with m.when(io.En):
        temp @= io.A
    with m.otherwise():
        temp @= 0
rsetaluri commented 1 year ago

Yes @rkshthrmsh good observation. To follow up on that you should use temp = T() as you do (with T = m.Sint[2] in your case, for example). You can use the m.Wire() primitive, but it is a circuit like any other circuit, so you would have to do:

temp_wire = m.Wire(m.SInt[2])()  # note the extra pair of paren's
with m.when(...):
    temp_wire.I @= ...  # note we do .I to get the input of this primitive
with m.otherwise():
    temp_wire.I @= ...
io.O @= temp_wire.O + 1

That being said, there really is no reason to use m.Wire() primitive. Doing temp = m.Sint[2]() is definitely preferred.