Skip to content
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

Registering product types #1215

Open
rkshthrmsh opened this issue Dec 22, 2022 · 4 comments
Open

Registering product types #1215

rkshthrmsh opened this issue Dec 22, 2022 · 4 comments

Comments

@rkshthrmsh
Copy link
Contributor

How can one 'register' all members of a product type in a single expression? Here, I am showing a product type with uniformly sized fields, but the same question could apply for non-uniform fields.

class SetParams(m.Product):
    a = m.In(m.UInt[2])
    b = m.In(m.UInt[2])
    c = m.In(m.UInt[2])


class Test(m.Circuit):
    io = m.IO(
        CLK=m.In(m.Clock),
        RESETN=m.In(m.ResetN),
        in_params=SetParams,
        load=m.In(m.Bit),
        out_params=m.Flip(SetParams)
    )
    set_reg = m.Register(SetParams,                                # Can SetParams be used this way, 
                         reset_type=m.ResetN)()(I=io.in_params)    # or should it be something else?

    io.out_params @= set_reg.O

Also tried this with Array (will not be applicable for a general product type)

    set_reg = m.Register(m.Array[3, m.UInt[2]], 
                         reset_type=m.ResetN)()(I=io.in_params) 

but the output of compile was this:

AttributeError: 'Array[(3, Out(UInt[2]))]' object has no attribute 'O'

A use case I had in mind was for registering all inputs and / or outputs of a circuit.

@leonardt
Copy link
Collaborator

We should add an error for this, but m.Register expects an undirected type, so here's a version that slightly changes it by having SetParams be undirected and qualifying it both ways in the IO.

import magma as m


class SetParams(m.Product):
    a = m.UInt[2]
    b = m.UInt[2]
    c = m.UInt[2]


class Test(m.Circuit):
    io = m.IO(
        CLK=m.In(m.Clock),
        RESETN=m.In(m.ResetN),
        in_params=m.In(SetParams),
        load=m.In(m.Bit),
        out_params=m.Out(SetParams)
    )
    set_reg_O = m.Register(SetParams,                                # Can SetParams be used this way,
                         reset_type=m.ResetN)()(I=io.in_params)    # or should it be something else?

    io.out_params @= set_reg_O

the second problem is you were using set_reg.O, but using the function call syntax to wire up the register instance returns the output, so you should either assign the result to a variable for the output (e.g. set_reg_O in my example) or remove the .O reference or separate the instance/wiring statements so set_reg refers to the instance rather than the output that's returned.

@rkshthrmsh
Copy link
Contributor Author

rkshthrmsh commented Dec 23, 2022

How would you recommend handling registering in compound product types. For example, consider an axi stream interface with two outputs and an input. Having them defined as directed makes it conveneint to group and provide flipped versions (or at least, that's the way I was using it). Sometimes, it may be necessary to register inputs, outputs, or both. Is there a way to do this?

class axisMaster(m.Product):
    tdata = m.Out(m.UInt[32])
    tvalid = m.Out(m.Bit)
    tready = m.In(m.Bit)


class ThreshStim(m.Circuit):
    io = m.IO(
        out=axisMaster,
        in=m.Flip(axisMaster)
    )
# Register all inputs, outputs, or both

I could think of breaking up the interface to input and output product types, and it seems that it would work. Though, I was wondering if there is a more concise way of doing this?

class Data(m.Product):
    tdata = m.UInt[32]
    tvalid = m.Bit


class Ready(m.Product):
    tready = m.In(m.Bit)


class AxisM(m.Product):
    out = m.Out(Data)
    in = m.In(Ready)


class ThreshStim(m.Circuit):
    io = m.IO(
        out=axisM,
        in=m.Flip(axisM)
    )
# Registers for 'data', 'ready', or both product types

@leonardt
Copy link
Collaborator

leonardt commented Jan 5, 2023

Breaking it up would work but is quite tedious. I'll have to think of a good way to do this.

One option would be have a helper that returns an anonymous handle to the register values (basically walks the type, for each input, register and return reg.I, for each output, register and return reg.O). @rsetaluri any ideas on this pattern?

@rkshthrmsh
Copy link
Contributor Author

rkshthrmsh commented Aug 19, 2023

Breaking it up would work but is quite tedious. I'll have to think of a good way to do this.

One option would be have a helper that returns an anonymous handle to the register values (basically walks the type, for each input, register and return reg.I, for each output, register and return reg.O). @rsetaluri any ideas on this pattern?

Hi @leonardt, following up on this discussion. Is it possible to register just the inputs, outputs, or both of product types with directions?

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

No branches or pull requests

2 participants