Exemple #1
0
    class _MAC(m.Circuit):
        name = "MAC" + str(n)
        logn = log2(n) + 1
        IO = ['CLK', m.In(m.Clock), 'I0', m.In(m.Bits(n)),
              'I1', m.In(m.Bits(n)), 'P', m.Out(m.Bits(logn)),
              'O', m.Out(m.Bit)]

        @classmethod
        def definition(io):
            # XNOR for binary affine mapped multiplication
            mul = mantle.NXOr(height=2, width=n)
            m.wire(mul.I0, io.I0)
            m.wire(mul.I1, io.I1)

            pop = PopCount(n)

            m.wire(mul.O, pop.I)
            m.wire(pop.O, io.P)

            width = log2(n)+2
            sign = mantle.UGE(width)
            m.wire(m.zext(pop.O, 1), sign.I0)
            m.wire(m.bits(n, width), sign.I1)

            m.wire(sign.O, io.O)
Exemple #2
0
    def __init__(self, height, width):
        super().__init__()

        self.height = height
        self.width = width

        T = magma.Bits(self.width)

        # In the case that @height <= 1, we make this circuit a simple
        # pass-through circuit.
        if self.height <= 1:
            self.add_ports(
                I=magma.In(magma.Array(1, T)),
                O=magma.Out(T),
            )
            self.wire(self.ports.I[0], self.ports.O)
            self.sel_bits = 0
            return

        MuxCls = mantle.DefineMux(self.height, self.width)
        self.mux = FromMagma(MuxCls)

        self.sel_bits = magma.bitutils.clog2(self.height)

        self.add_ports(
            I=magma.In(magma.Array(self.height, T)),
            S=magma.In(magma.Bits(self.sel_bits)),
            O=magma.Out(T),
        )

        for i in range(self.height):
            self.wire(self.ports.I[i], self.mux.ports[f"I{i}"])
        mux_in = self.ports.S if self.sel_bits > 1 else self.ports.S[0]
        self.wire(mux_in, self.mux.ports.S)
        self.wire(self.mux.ports.O, self.ports.O)
Exemple #3
0
    def __init__(self, data_width, data_depth):
        super().__init__()

        self.data_width = data_width
        self.data_depth = data_depth
        TData = magma.Bits(self.data_width)
        TBit = magma.Bits(1)

        self.add_ports(data_in=magma.In(TData),
                       addr_in=magma.In(TData),
                       data_out=magma.Out(TData),
                       clk=magma.In(magma.Clock),
                       config=magma.In(ConfigurationType(8, 32)),
                       read_config_data=magma.Out(magma.Bits(32)),
                       reset=magma.In(magma.AsyncReset),
                       flush=magma.In(TBit),
                       wen_in=magma.In(TBit),
                       ren_in=magma.In(TBit),
                       stall=magma.In(magma.Bits(4)))

        wrapper = memory_core_genesis2.memory_core_wrapper
        param_mapping = memory_core_genesis2.param_mapping
        generator = wrapper.generator(param_mapping, mode="declare")
        circ = generator(data_width=self.data_width,
                         data_depth=self.data_depth)
        self.underlying = FromMagma(circ)

        self.wire(self.ports.data_in, self.underlying.ports.data_in)
        self.wire(self.ports.addr_in, self.underlying.ports.addr_in)
        self.wire(self.ports.data_out, self.underlying.ports.data_out)
        self.wire(self.ports.config.config_addr,
                  self.underlying.ports.config_addr[24:32])
        self.wire(self.ports.config.config_data,
                  self.underlying.ports.config_data)
        self.wire(self.ports.config.write[0], self.underlying.ports.config_en)
        self.wire(self.underlying.ports.read_data, self.ports.read_config_data)
        self.wire(self.ports.reset, self.underlying.ports.reset)
        self.wire(self.ports.flush[0], self.underlying.ports.flush)
        self.wire(self.ports.wen_in[0], self.underlying.ports.wen_in)
        self.wire(self.ports.ren_in[0], self.underlying.ports.ren_in)

        # PE core uses clk_en (essentially active low stall)
        self.stallInverter = FromMagma(mantle.DefineInvert(1))
        self.wire(self.stallInverter.ports.I, self.ports.stall[0:1])
        self.wire(self.stallInverter.ports.O[0], self.underlying.ports.clk_en)

        # TODO(rsetaluri): Actually wire these inputs.
        signals = (
            ("config_en_sram", 4),
            ("config_en_linebuf", 1),
            ("chain_wen_in", 1),
            ("config_read", 1),
            ("config_write", 1),
            ("chain_in", self.data_width),
        )
        for name, width in signals:
            val = magma.bits(0, width) if width > 1 else magma.bit(0)
            self.wire(Const(val), self.underlying.ports[name])
        self.wire(Const(magma.bits(0, 24)),
                  self.underlying.ports.config_addr[0:24])
Exemple #4
0
    class DFF3(m.Circuit):
        name = make_name_dff3(array_size_2, array_size_1, width, pipe_depth,
                              retime_status)

        IO = [
            "data_in",
            m.Array(array_size_2, m.Array(array_size_1, m.In(m.Bits(width)))),
            "clk",
            m.In(m.Clock), "reset",
            m.In(m.Reset), "en",
            m.In(m.Bit), "data_out",
            m.Array(array_size_2, m.Array(array_size_1, m.Out(m.Bits(width))))
        ]

        @classmethod
        def definition(io):
            dffs = m.braid(m.map_(
                DefineDFF2(array_size_1, width, pipe_depth, retime_status),
                array_size_2),
                           joinargs=["data_in", "data_out"],
                           forkargs=["clk", "en", "reset"])
            m.wire(dffs.data_in, io.data_in)
            m.wire(dffs.data_out, io.data_out)
            m.wire(dffs.clk, io.clk)
            m.wire(dffs.en, io.en)
            m.wire(dffs.reset, io.reset)
Exemple #5
0
def test_generator(mode):
    def _foo(*args, **kwargs):
        pass

    generator = WRAPPER.generator(mode=mode)
    assert inspect.isfunction(generator)
    assert inspect.signature(generator) == inspect.signature(_foo)
    # Check that passing non-kwargs fails.
    try:
        generator(0)
        assert False
    except NotImplementedError as e:
        pass
    module = generator(**PARAMS)
    type_ = m.circuit.DefineCircuitKind if mode == "define" \
        else m.circuit.CircuitKind
    assert isinstance(module, type_)
    expected_ports = {
        "clk": m.Out(m.Bit),
        "reset": m.Out(m.Bit),
        "in0": m.Out(m.Bits(16)),
        "in1": m.Out(m.Bits(16)),
        "sel": m.Out(m.Bit),
        "out": m.In(m.Bits(16)),
    }
    for name, type_ in module.IO.ports.items():
        assert type(expected_ports[name]) == type(type_)
def ConfigInterface(config_addr_width, config_data_width):
    return [
        "config_addr", m.In(m.Bits(config_addr_width)),
        "config_data", m.In(m.Bits(config_data_width)),
        "config_en", m.In(m.Enable),
        "read_data", m.Out(m.Bits(config_data_width))
    ]
Exemple #7
0
        def return_ll_ur(I: m.Bits(3), S: m.Bit) -> (m.Bits(bits), m.Bits(bits)
                                                     ):
            if ~I[0]:
                if ~I[1]:
                    if ~I[2]:
                        ll = io.poly_in[2][S]
                        ur = io.poly_in[0][S]
                    else:
                        ll = io.poly_in[2][S]
                        ur = io.poly_in[0][S]
                else:
                    if ~I[2]:
                        ll = io.poly_in[1][S]
                        ur = io.poly_in[0][S]
                    else:
                        ll = io.poly_in[1][S]
                        ur = io.poly_in[2][S]
            else:
                if ~I[1]:
                    if ~I[2]:
                        ll = io.poly_in[2][S]
                        ur = io.poly_in[1][S]
                    else:
                        ll = io.poly_in[0][S]
                        ur = io.poly_in[1][S]
                else:
                    if ~I[2]:
                        ll = io.poly_in[0][S]
                        ur = io.poly_in[2][S]
                    else:
                        ll = io.poly_in[0][S]
                        ur = io.poly_in[2][S]

            return ll, ur
Exemple #8
0
    class SwitchBox(m.Circuit):
        name = 'switch_box'
        IO = [
            "clk",
            m.In(m.Clock), "rst",
            m.In(m.Reset), "config_data",
            m.In(m.Bits(32)), "config_en",
            m.In(m.Bit), "clb_result",
            m.In(m.Bits(WireWidth))
        ]

        for side in range(0, 4):
            for track in range(0, 4):
                IO.append('side_' + str(side) + '_track_' + str(track) + '_in')
                IO.append(m.In(m.Bits(WireWidth)))
                IO.append('side_' + str(side) + '_track_' + str(track) +
                          '_out')
                IO.append(m.Out(m.Bits(WireWidth)))

        @classmethod
        def definition(io):
            # Configuration data
            config_reg = mantle.Register(32,
                                         init=0,
                                         has_ce=True,
                                         has_reset=True)

            m.wire(io.config_data, config_reg.I)
            m.wire(io.clk, config_reg.CLK)
            m.wire(io.config_en, config_reg.CE)

            rst_inv = mantle.Invert(1)
            m.wire(rst_inv.I[0], io.rst)
            m.wire(rst_inv.O[0], config_reg.RESET)

            # switch muxes

            config_offset = 0
            for side in range(0, 4):
                for track in range(0, 4):
                    switch_mux = mantle.Mux(height=4, width=1)
                    m.wire(
                        switch_mux.O,
                        getattr(
                            io, 'side_' + str(side) + '_track_' + str(track) +
                            '_out'))
                    m.wire(switch_mux.S,
                           config_reg.O[config_offset:(config_offset + 2)])
                    config_offset += 2

                    for in_side in range(0, 4):
                        if in_side == side:
                            m.wire(getattr(switch_mux, "I" + str(in_side)),
                                   io.clb_result)
                        else:
                            m.wire(
                                getattr(switch_mux, "I" + str(in_side)),
                                getattr(
                                    io, 'side_' + str(in_side) + '_track_' +
                                    str(track) + '_in'))
Exemple #9
0
def create_io1out_pad():
    cb = m.DefineCircuit("io1out_pad", "clk", m.In(m.Clock), "rst",
                         m.In(m.Reset), "config_data", m.In(m.Bits(32)),
                         "config_addr", m.In(m.Bits(32)), "tile_id",
                         m.In(m.Bits(16)), "pin_0", m.In(m.Bit), "pin_1",
                         m.In(m.Bit), "pin_2", m.In(m.Bit), "pin_3",
                         m.In(m.Bit), "top_pin", m.Out(m.Bits(1)))

    # Configuration data
    config_reg = mantle.Register(32, init=0, has_ce=True, has_reset=True)
    addr_match = mantle.EQ(16)
    m.wire(addr_match.I0, cb.config_addr[0:16])
    m.wire(addr_match.I1, cb.tile_id)
    m.wire(addr_match.O, config_reg.CE)

    m.wire(cb.config_data, config_reg.I)
    m.wire(cb.clk, config_reg.CLK)

    rst_inv = mantle.Invert(1)
    m.wire(rst_inv.I[0], cb.rst)
    m.wire(rst_inv.O[0], config_reg.RESET)

    # Config mux
    config_mux = mantle.Mux(height=4, width=1)
    m.wire(config_mux.O, cb.top_pin)
    m.wire(config_mux.S, config_reg.O[0:2])

    m.wire(cb.pin_0, config_mux.I0[0])
    m.wire(cb.pin_1, config_mux.I1[0])
    m.wire(cb.pin_2, config_mux.I2[0])
    m.wire(cb.pin_3, config_mux.I3[0])

    m.EndDefine()

    return cb
Exemple #10
0
class ConfigReg(m.Circuit):
    IO = ["D", m.In(m.Bits(2)), "Q", m.Out(m.Bits(2))] + \
        m.ClockInterface(has_ce=True)

    @classmethod
    def definition(io):
        reg = mantle.Register(2, has_ce=True, name="conf_reg")
        io.Q <= reg(io.D, CE=io.CE)
Exemple #11
0
    class CLB(m.Circuit):
        name = 'configurable_logic_block'
        IO = [
            "operand0",
            m.In(m.Bits(WireWidth)), "operand1",
            m.In(m.Bits(WireWidth)), "result",
            m.Out(m.Bits(WireWidth)), "clk",
            m.In(m.Clock), "rst",
            m.In(m.Reset), "config_data",
            m.In(m.Bits(32)), "config_en",
            m.In(m.Bit)
        ]

        @classmethod
        def definition(io):

            # Configuration data
            config_reg = mantle.Register(32,
                                         init=0,
                                         has_ce=True,
                                         has_reset=True)

            m.wire(io.config_data, config_reg.I)
            m.wire(io.clk, config_reg.CLK)
            m.wire(io.config_en, config_reg.CE)

            rst_inv = mantle.Invert(1)
            m.wire(rst_inv.I[0], io.rst)
            m.wire(rst_inv.O[0], config_reg.RESET)

            # Operations in CLB
            and_op = mantle.And(2, 1)
            m.wire(io.operand0, and_op.I0)
            m.wire(io.operand1, and_op.I1)

            or_op = mantle.Or(2, 1)
            m.wire(io.operand0, or_op.I0)
            m.wire(io.operand1, or_op.I1)

            xor_op = mantle.XOr(2, 1)
            m.wire(io.operand0, xor_op.I0)
            m.wire(io.operand1, xor_op.I1)

            not_op = mantle.Invert(1)
            m.wire(io.operand0, not_op.I)

            # Config mux
            config_mux = mantle.Mux(height=4, width=1)
            m.wire(config_mux.O, io.result)
            m.wire(config_mux.S, config_reg.O[0:2])

            m.wire(and_op.O, config_mux.I0)
            m.wire(or_op.O, config_mux.I1)
            m.wire(xor_op.O, config_mux.I2)
            m.wire(not_op.O, config_mux.I3)
Exemple #12
0
    def __init__(self, num_tracks, width):
        super().__init__()

        if num_tracks <= 1:
            raise ValueError("num_tracks must be > 1")
        self.num_tracks = num_tracks
        self.width = width
        sel_bits = magma.bitutils.clog2(self.num_tracks)

        self.mux = MuxWrapper(self.num_tracks, self.width)

        T = magma.Bits(self.width)

        self.add_ports(
            I=magma.In(magma.Array(self.num_tracks, T)),
            O=magma.Out(T),
            clk=magma.In(magma.Clock),
            reset=magma.In(magma.AsyncReset),
            config=magma.In(ConfigurationType(8, 32)),
            read_config_data=magma.Out(magma.Bits(32)),
        )
        self.add_configs(S=sel_bits)
        # read_config_data output
        num_config_reg = len(self.registers)
        if (num_config_reg > 1):
            self.read_config_data_mux = MuxWrapper(num_config_reg, 32)
            self.wire(self.ports.config.config_addr,
                      self.read_config_data_mux.ports.S)
            self.wire(self.read_config_data_mux.ports.O,
                      self.ports.read_config_data)
            for idx, reg in enumerate(self.registers.values()):
                self.wire(reg.ports.O, self.read_config_data_mux.ports.I[idx])
                # Wire up config register resets
                self.wire(reg.ports.reset, self.ports.reset)
        # If we only have 1 config register, we don't need a mux
        # Wire sole config register directly to read_config_data_output
        else:
            reg = list(self.registers.values())[0]
            zext = ZextWrapper(reg.width, 32)
            self.wire(reg.ports.O, zext.ports.I)
            zext_out = zext.ports.O
            self.wire(zext_out, self.ports.read_config_data)

        self.wire(self.ports.I, self.mux.ports.I)
        self.wire(self.registers.S.ports.O, self.mux.ports.S)
        self.wire(self.mux.ports.O, self.ports.O)

        for idx, reg in enumerate(self.registers.values()):
            reg.set_addr(idx)
            reg.set_addr_width(8)
            reg.set_data_width(32)
            self.wire(self.ports.config.config_addr, reg.ports.config_addr)
            self.wire(self.ports.config.config_data, reg.ports.config_data)
            # Connect config_en for each config reg
            self.wire(reg.ports.config_en, self.ports.config.write[0])
Exemple #13
0
    def __init__(self, num_inputs, width, sel_bits, default):
        super().__init__()

        self.num_inputs = num_inputs
        self.width = width
        self.sel_bits = sel_bits
        self.default = default

        if 2**self.sel_bits <= self.num_inputs:
            raise ValueError(f"(2 ^ sel_bits) must be > num_inputs "
                             f"(sel_bits={self.sel_bits}, "
                             f"num_inputs={self.num_inputs})")

        self.data_mux = MuxWrapper(self.num_inputs, self.width)
        self.default_mux = MuxWrapper(2, self.width)
        lt = mantle.DefineULT(self.sel_bits)
        and_gate = mantle.DefineAnd(2)
        self.lt = FromMagma(lt)
        self.and_gate = FromMagma(and_gate)

        T = magma.Bits(self.width)
        self.add_ports(
            I=magma.In(magma.Array(self.num_inputs, T)),
            S=magma.In(magma.Bits(self.sel_bits)),
            EN=magma.In(magma.Bits(1)),
            O=magma.Out(T),
        )

        # Wire data inputs to data mux.
        for i in range(self.num_inputs):
            self.wire(self.ports.I[i], self.data_mux.ports.I[i])

        # Wire select input to select input of data_mux. Note that we only wire
        # the first clog2(num_inputs) bits of the select input.
        self.wire(self.ports.S[:self.data_mux.sel_bits], self.data_mux.ports.S)

        # Wire default value to first input of default mux, and output of
        # data_mux to second input of default mux.
        default_mux_inputs = [
            Const(magma.bits(self.default, self.width)),
            self.data_mux.ports.O,
        ]
        for i, mux_in in enumerate(default_mux_inputs):
            self.wire(mux_in, self.default_mux.ports.I[i])

        # Generate select logic for default mux:
        #   sel = (S < num_inputs) & EN
        self.wire(self.ports.S, self.lt.ports.I0)
        self.wire(Const(magma.bits(self.num_inputs, self.sel_bits)),
                  self.lt.ports.I1)
        self.wire(self.lt.ports.O, self.and_gate.ports.I0)
        self.wire(self.ports.EN[0], self.and_gate.ports.I1)
        self.wire(self.and_gate.ports.O, self.default_mux.ports.S[0])
        self.wire(self.default_mux.ports.O, self.ports.O)
Exemple #14
0
    class Configurable(m.Circuit):
        IO = ["config_addr", m.In(m.Bits(32)), "config_data", m.In(m.Bits(32)),
              "config_en", m.In(m.Enable), "O", m.Out(m.Bits(32))
              ] + m.ClockInterface()

        @classmethod
        def definition(io):
            reg = mantle.Register(32, has_ce=True)

            reg(io.config_data,
                CE=(io.config_addr == m.bits(1, 32)) & m.bit(io.config_en))
            m.wire(reg.O, io.O)
Exemple #15
0
    class ConnectBox(m.Circuit):

        name = 'connect_box'

        IO = [
            "clk",
            m.In(m.Clock), "rst",
            m.In(m.Reset), "config_data",
            m.In(m.Bits(32)), "config_en",
            m.In(m.Bit), "track_0_in",
            m.In(m.Bits(WireWidth)), "track_1_in",
            m.In(m.Bits(WireWidth)), "track_2_in",
            m.In(m.Bits(WireWidth)), "track_3_in",
            m.In(m.Bits(WireWidth)), "track_0_out",
            m.In(m.Bits(WireWidth)), "track_1_out",
            m.In(m.Bits(WireWidth)), "track_2_out",
            m.In(m.Bits(WireWidth)), "track_3_out",
            m.In(m.Bits(WireWidth)), "out",
            m.Out(m.Bits(WireWidth))
        ]

        @classmethod
        def definition(io):
            # Configuration data
            config_reg = mantle.Register(32,
                                         init=0,
                                         has_ce=True,
                                         has_reset=True)

            m.wire(io.config_data, config_reg.I)
            m.wire(io.clk, config_reg.CLK)
            m.wire(io.config_en, config_reg.CE)

            rst_inv = mantle.Invert(1)
            m.wire(rst_inv.I[0], io.rst)
            m.wire(rst_inv.O[0], config_reg.RESET)

            # Config mux
            config_mux = mantle.Mux(height=8, width=1)
            m.wire(config_mux.O, io.out)
            m.wire(config_mux.S, config_reg.O[0:3])

            m.wire(io.track_0_in, config_mux.I0)
            m.wire(io.track_1_in, config_mux.I1)
            m.wire(io.track_2_in, config_mux.I2)
            m.wire(io.track_3_in, config_mux.I3)

            m.wire(io.track_0_out, config_mux.I4)
            m.wire(io.track_1_out, config_mux.I5)
            m.wire(io.track_2_out, config_mux.I6)
            m.wire(io.track_3_out, config_mux.I7)
Exemple #16
0
    def __init__(self):
        super().__init__()

        # TODO(rsetaluri): Currently we assume the default parameters into the
        # wrapper. Ideally we should take some arguments into this generator
        # and pass them to the genesis wrapper.
        wrapper = pe_core_genesis2.pe_core_wrapper
        generator = wrapper.generator(mode="declare")
        circ = generator()
        self.underlying = FromMagma(circ)

        TData = magma.Bits(16)
        TBit = magma.Bits(1)
        TFlag = magma.Bits(4)

        self.add_ports(
            data0=magma.In(TData),
            data1=magma.In(TData),
            bit0=magma.In(TBit),
            bit1=magma.In(TBit),
            bit2=magma.In(TBit),
            res=magma.Out(TData),
            res_p=magma.Out(TFlag),
            clk=magma.In(magma.Clock),
            reset=magma.In(magma.AsyncReset),
            config=magma.In(ConfigurationType(8, 32)),
            read_config_data=magma.Out(magma.Bits(32)),
            # TODO: Make number of stall domains paramaterizable
            stall=magma.In(magma.Bits(4))
        )

        self.wire(self.ports.data0, self.underlying.ports.data0)
        self.wire(self.ports.data1, self.underlying.ports.data1)
        self.wire(self.ports.bit0[0], self.underlying.ports.bit0)
        self.wire(self.ports.bit1[0], self.underlying.ports.bit1)
        self.wire(self.ports.bit2[0], self.underlying.ports.bit2)
        self.wire(self.ports.res, self.underlying.ports.res)
        self.wire(self.ports.res_p, self.underlying.ports.res_p)
        self.wire(self.ports.config.config_addr, self.underlying.ports.cfg_a)
        self.wire(self.ports.config.config_data,
                  self.underlying.ports.cfg_d)
        self.wire(self.ports.config.write[0], self.underlying.ports.cfg_en)
        self.wire(self.underlying.ports.read_data, self.ports.read_config_data)

        # TODO: Make PE core use active high reset
        self.wire(self.ports.reset, self.underlying.ports.rst_n)

        # PE core uses clk_en (essentially active low stall)
        self.stallInverter = FromMagma(mantle.DefineInvert(1))
        self.wire(self.stallInverter.ports.I, self.ports.stall[0:1])
        self.wire(self.stallInverter.ports.O[0], self.underlying.ports.clk_en)
Exemple #17
0
def create_connect_box():
    cb = m.DefineCircuit("connect_box",
                          "operand0", m.In(m.Bits(1)),
                          "operand1", m.In(m.Bits(1)),
                          "result", m.Out(m.Bits(1)),
                          "clk", m.In(m.Clock),
                          "rst", m.In(m.Reset),
                          "config_data", m.In(m.Bits(32)),
                          "config_en", m.In(m.Bit))

    # Configuration data
    config_reg = mantle.Register(32, init=0, has_ce=True, has_reset=True)

    m.wire(cb.config_data, config_reg.I)
    m.wire(cb.clk, config_reg.CLK)
    m.wire(cb.config_en, config_reg.CE)

    rst_inv = mantle.Invert(1)
    m.wire(rst_inv.I[0], cb.rst)
    m.wire(rst_inv.O[0], config_reg.RESET)

    # Operations in CB
    and_op = mantle.And(2, 1)
    m.wire(cb.operand0, and_op.I0)
    m.wire(cb.operand1, and_op.I1)

    or_op = mantle.Or(2, 1)
    m.wire(cb.operand0, or_op.I0)
    m.wire(cb.operand1, or_op.I1)

    xor_op = mantle.XOr(2, 1)
    m.wire(cb.operand0, xor_op.I0)
    m.wire(cb.operand1, xor_op.I1)

    not_op = mantle.Invert(1)
    m.wire(cb.operand0, not_op.I)
    
    # Config mux
    config_mux = mantle.Mux(height=4, width=1)
    m.wire(config_mux.O, cb.result)
    m.wire(config_mux.S, config_reg.O[0:2])
    
    m.wire(and_op.O, config_mux.I0)
    m.wire(or_op.O, config_mux.I1)
    m.wire(xor_op.O, config_mux.I2)
    m.wire(not_op.O, config_mux.I3)


    return cb
Exemple #18
0
    def __init__(self, in_width, out_width):
        super().__init__()

        if out_width <= in_width:
            raise ValueError(f"output width must be greater than input width "
                             f"(output width = {out_width}, input width = "
                             f"{in_width})")

        self.in_width = in_width
        self.out_width = out_width

        self.add_ports(
            I=magma.In(magma.In(magma.Bits(self.in_width))),
            O=magma.Out(magma.Out(magma.Bits(self.out_width))),
        )
Exemple #19
0
    def __init__(self, width, num_tracks):
        super().__init__()

        self.width = width
        self.num_tracks = num_tracks
        core = PECoreGenerator(self.width)
        sb = SBGenerator(self.width, self.num_tracks, len(core.outputs()))
        self.add_features(
            core=core,
            sb=sb,
        )
        for i in range(len(self.features.core.inputs())):
            cb = CBGenerator(self.width, self.num_tracks)
            self.add_feature(f"cb{i}", cb)
        T = magma.Array(self.num_tracks, magma.Bits(self.width))

        self.add_ports(
            I=magma.In(T),
            O=magma.Out(T),
        )

        self.wire(self.I, self.features.sb.I)
        for i in range(len(self.features.core.inputs())):
            cb = getattr(self.features, f"cb{i}")
            self.wire(self.I, cb.I)
        for i, core_in in enumerate(self.features.core.inputs()):
            cb = getattr(self.features, f"cb{i}")
            self.wire(cb.O, core_in)
        for i, core_out in enumerate(self.features.core.outputs()):
            self.wire(core_out, self.features.sb.core_in[i])
        self.wire(self.features.sb.O, self.O)
Exemple #20
0
    def __init__(self):
        super().__init__()

        width = 16
        num_tracks = 4
        num_tiles = 10
        T = magma.Array(num_tracks, magma.Bits(width))

        self.tiles = [TileGenerator(width, num_tracks) \
                      for _ in range(num_tiles)]

        self.add_ports(
            I=magma.In(T),
            O=magma.Out(T),
        )

        # for tile in self.tiles:
        #    self.wire(self.config_addr, tile.config_addr)
        #    self.wire(self.config_data, tile.config_data)
        self.wire(self.I, self.tiles[0].I)
        self.wire(self.tiles[-1].O, self.O)
        for i in range(1, len(self.tiles)):
            t0 = self.tiles[i - 1]
            t1 = self.tiles[i]
            self.wire(t0.O, t1.I)
Exemple #21
0
    def __init__(self, width, num_tracks, core_inputs):
        super().__init__()

        self.width = width
        self.num_tracks = num_tracks
        assert core_inputs == 1
        self.core_inputs = core_inputs
        self.muxs = [MuxWrapper(self.num_tracks, self.width) \
                     for _ in range(self.num_tracks)]
        T = magma.Array(self.num_tracks, magma.Bits(self.width))
        bits_per_sel = math.ceil(math.log(self.num_tracks, 2))

        self.add_ports(
            I=magma.In(T),
            core_in=magma.In(magma.Array(self.core_inputs, T.T)),
            O=magma.Out(T),
        )
        for i in range(self.num_tracks):
            self.add_config(f"sel_{i}", bits_per_sel)
        self.selects = [getattr(self, f"sel_{i}") \
                        for i in range(self.num_tracks)]

        for i in range(self.num_tracks):
            mux = self.muxs[i]
            for j in range(self.num_tracks):
                mux_in = self.I[j] if i != j else self.core_in[0]
                self.wire(mux_in, mux.I[j])
            self.wire(self.selects[i], mux.S)
            self.wire(mux.O, self.O[i])
Exemple #22
0
 def top_to_tile(top, tile, tile_idx):
     tile.add_ports(tile_id=magma.In(magma.Bits(16)))
     top.wire(Const(magma.bits(tile_idx, 16)), tile.tile_id)
     tile_eq = FromMagma(mantle.DefineEQ(16))
     tile.wire(tile.tile_id, tile_eq.I0)
     tile.wire(tile.config.config_addr[0:16], tile_eq.I1)
     return tile_eq
Exemple #23
0
    def __init__(self):
        super().__init__()

        width = 16
        num_tracks = 4
        num_tiles = 10
        T = magma.Array(num_tracks, magma.Bits(width))

        self.tiles = []
        for i in range(num_tiles):
            if i % 2 == 0:
                core = PECoreGenerator(width)
            else:
                core = MemCoreGenerator(width)
            self.tiles.append(TileGenerator(width, num_tracks, core))

        self.add_ports(
            I=magma.In(T),
            O=magma.Out(T),
        )

        self.wire(self.I, self.tiles[0].I)
        self.wire(self.tiles[-1].O, self.O)
        for i in range(1, len(self.tiles)):
            t0 = self.tiles[i - 1]
            t1 = self.tiles[i]
            self.wire(t0.O, t1.I)
Exemple #24
0
    def __init__(self, width, num_tracks, core):
        super().__init__()

        self.width = width
        self.num_tracks = num_tracks
        self.core = core
        self.sb = SBGenerator(self.width, self.num_tracks,
                              len(self.core.outputs()))
        self.cbs = [CBGenerator(self.width, self.num_tracks) \
                    for _ in range(len(self.core.inputs()))]
        T = magma.Array(self.num_tracks, magma.Bits(self.width))

        self.add_ports(
            I=magma.In(T),
            O=magma.Out(T),
        )

        self.wire(self.I, self.sb.I)
        for cb in self.cbs:
            self.wire(self.I, cb.I)
        for i, core_in in enumerate(self.core.inputs()):
            self.wire(self.cbs[i].O, core_in)
        for i, core_out in enumerate(self.core.outputs()):
            self.wire(core_out, self.sb.core_in[i])
        self.wire(self.sb.O, self.O)
Exemple #25
0
class LinkerTest(m.Circuit):
    name = "LinkerTest0"
    IO = [
        "I0",
        m.In(m.Bits(width)), "I1",
        m.In(m.Bits(width)), "O",
        m.Out(m.Bits(width))
    ]

    @classmethod
    def definition(self):
        Smax = DefineSmax(width=width)
        smax = Smax()
        m.wire(self.I0, smax.in0)
        m.wire(self.I1, smax.in1)
        m.wire(self.O, smax.out)
Exemple #26
0
def SideType(num_tracks, layers):
    layers_dict = {
        f"layer{l}": magma.Array(num_tracks, magma.Bits(l))
        for l in layers
    }
    T = magma.Tuple(**layers_dict)
    return magma.Tuple(I=magma.In(T), O=magma.Out(T))
Exemple #27
0
    def __init__(self, node: PortNode, config_addr_width: int,
                 config_data_width: int):
        if not isinstance(node, PortNode):
            raise ValueError(node, PortNode.__name__)
        super().__init__(config_addr_width, config_data_width)

        self.node: PortNode = node
        self.mux = create_mux(self.node)

        # lift the port to the top level
        self.add_ports(I=self.mux.ports.I.base_type(),
                       O=self.mux.ports.O.base_type())

        self.wire(self.ports.I, self.mux.ports.I)
        self.wire(self.ports.O, self.mux.ports.O)

        if self.mux.height > 1:
            self.add_ports(
                config=magma.In(
                    ConfigurationType(config_addr_width, config_data_width)),
                read_config_data=magma.Out(magma.Bits(config_data_width)),
            )
            config_name = get_mux_sel_name(self.node)
            self.add_config(config_name, self.mux.sel_bits)
            self.wire(self.registers[config_name].ports.O, self.mux.ports.S)

        self._setup_config()
Exemple #28
0
def counter(context, values, module_def):
    print("Running magma generator")
    width = values['width'].value
    has_en = values['has_en'].value

    IO_ = ["out", m.Out(m.Bits(width)), "clk", m.In(m.Clock)]
    if has_en:
        IO_ += ["en", m.In(m.Bit)]

    class MyCounter(m.Circuit):
        name = f"MyCounter_{width}_{has_en}"
        IO = IO_

        @classmethod
        def definition(cls):
            counter = mantle.Counter(width, has_ce=has_en)
            m.wire(counter.O, cls.out)
            m.wire(counter.CLK, cls.clk)
            if has_en:
                m.wire(counter.CE, cls.en)

    import magma.backend.coreir_ as coreir_backend
    coreir_backend.CoreIRBackend(context).compile_dependencies(MyCounter)
    coreir_backend.CoreIRBackend(
        context).compile_definition_to_module_definition(
            MyCounter, module_def)
def test_shift_register():
    N = 4
    Register4 = DefineRegister(4)
    T = m.Bits(N)

    class ShiftRegister(m.Circuit):
        name = "ShiftRegister"
        IO = ["I", m.In(T), "O", m.Out(T), "CLK", m.In(m.Clock)]

        @classmethod
        def definition(io):
            regs = [Register4() for _ in range(N)]
            m.wire(io.I, regs[0].I)
            m.fold(regs, foldargs={"I": "O"})
            m.wire(regs[-1].O, io.O)

    simulator = PythonSimulator(ShiftRegister, clock=ShiftRegister.CLK)
    expected = [0, 0, 0] + list(range(0, 1 << N, 3))[:-3]
    actual = []
    for i in range(0, 1 << N, 3):
        simulator.set_value(ShiftRegister.I, i)
        simulator.advance(2)
        actual.append(simulator.get_value(ShiftRegister.O))

    assert actual == expected

    m.compile("build/ShiftRegister", ShiftRegister, output="coreir")
    assert m.testing.check_files_equal(__file__, "build/ShiftRegister.json",
                                       "gold/ShiftRegister.json")
Exemple #30
0
    def __init__(self, columns):
        super().__init__()

        assert all([c.height == columns[0].height for c in columns])
        self.width = len(columns)
        self.height = columns[0].height
        self.columns = columns
        self.side_type = SideType(5, (1, 16))

        self.add_ports(
            north=magma.Array(self.width, self.side_type),
            south=magma.Array(self.width, self.side_type),
            west=magma.Array(self.height, self.side_type),
            east=magma.Array(self.height, self.side_type),
            config=magma.In(ConfigurationType(32, 32)),
            clk=magma.In(magma.Clock),
            reset=magma.In(magma.AsyncReset),
            read_config_data=magma.Out(magma.Bits(32)),
            # TODO: make number of stall domains a param
            stall=magma.In(magma.Bits(4)))

        for column in self.columns:
            self.wire(self.ports.config, column.ports.config)
            self.wire(self.ports.reset, column.ports.reset)
            self.wire(self.ports.stall, column.ports.stall)
        self.wire(self.ports.west, self.columns[0].ports.west)
        self.wire(self.ports.east, self.columns[-1].ports.east)
        for i, column in enumerate(self.columns):
            self.wire(self.ports.north[i], column.ports.north)
            self.wire(self.ports.south[i], column.ports.south)
        for i in range(1, self.width):
            c0 = self.columns[i - 1]
            c1 = self.columns[i]
            for j in range(self.height):
                self.wire(c1.ports.west[j].O, c0.ports.east[j].I)
                self.wire(c0.ports.east[j].O, c1.ports.west[j].I)

        # OR together read_data outputs from each column
        # number of inputs = number of columns
        self.read_data_OR = FromMagma(mantle.DefineOr(len(self.columns), 32))
        for i, col in enumerate(columns):
            self.wire(self.read_data_OR.ports[f"I{i}"],
                      col.ports.read_config_data)
            # wire up column number input
            self.wire(col.ports.column_num, Const(magma.bits(i, 8)))
        self.wire(self.read_data_OR.ports.O, self.ports.read_config_data)