Exemple #1
0
    class _ConfigRegister(magma.Circuit):
        name = f"ConfigRegister_{width}_{addr_width}_{data_width}_{addr}"
        ports = {
            "clk": magma.In(magma.Clock),
            "reset": magma.In(magma.AsyncReset),
            "O": magma.Out(T),
            "config_addr": magma.In(magma.Bits[addr_width]),
            "config_data": magma.In(magma.Bits[data_width]),
        }
        if use_config_en:
            ports["config_en"] = magma.In(magma.Bit)
        io = magma.IO(**ports)

        reg = magma.Register(magma.Bits[width],
                             has_enable=True,
                             reset_type=magma.AsyncReset)()
        magma.wire(io.clk, reg.CLK)
        ce = (io.config_addr == magma.bits(addr, addr_width))
        magma.wire(io.reset, reg.ASYNCRESET)
        if use_config_en:
            ce = ce & io.config_en
        magma.wire(io.config_data[0:width], reg.I)
        magma.wire(magma.enable(ce), reg.CE)
        magma.wire(reg.O, io.O)
Exemple #2
0
    def __init__(self, length: int, fanout: int = 0):
        self.io = m.IO(I=m.In(m.Bit), O=m.Out(m.Bit))
        self.io += m.IO(
            **{f"fanout_{i}": m.Out(m.Bit)
               for i in range(length * fanout)})

        index = 0
        curr = self.io.I
        for _ in range(length):
            curr = ~curr
            for _ in range(fanout):
                out = getattr(self.io, f"fanout_{index}")
                out @= curr
                index += 1
        self.io.O @= curr
Exemple #3
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.Bits[self.in_width]),
            O=magma.Out(magma.Bits[self.out_width]),
        )
Exemple #4
0
class SimpleALU(m.Circuit):
    name = "SimpleALU"
    IO = [
        "a",
        m.In(m.UInt(4)), "b",
        m.In(m.UInt(4)), "opcode",
        m.In(m.UInt(2)), "out",
        m.Out(m.UInt(4))
    ]

    @classmethod
    def definition(io):
        is_op0 = io.opcode == m.uint(0, n=2)
        is_op1 = io.opcode == m.uint(1, n=2)
        is_op2 = io.opcode == m.uint(2, n=2)
        is_op3 = io.opcode == m.uint(3, n=2)
        op0_out = io.a + io.b
        op1_out = io.a - io.b
        op2_out = io.a
        op3_out = io.b
        m.wire(
            io.out,
            one_hot_mux([is_op0, is_op1, is_op2, is_op3],
                        [op0_out, op1_out, op2_out, op3_out]))
Exemple #5
0
def test_ram():
    main = m.DefineCircuit("main", "rdata", m.Out(m.Bit), "CLKIN",
                           m.In(m.Clock))

    ram = mantle.RAM(4, 1)

    waddr = mantle.Counter(4)
    wdata = mantle.Counter(1)
    we = 1
    raddr = mantle.FF()(mantle.Counter(4))

    ram(raddr, waddr, wdata, we, CLK=main.CLKIN)

    m.wire(ram.RDATA, main.rdata)
    m.EndDefine()
    m.compile("build/test_common_ram", main)
Exemple #6
0
    def __init__(self, width):
        super().__init__()

        self.width = width
        self.impl = FromVerilog("experimental/simple_cgra/tiny_mem_core.v")

        T = magma.Bits(self.width)
        self.add_ports(
            I=magma.In(T),
            O=magma.Out(T),
        )
        self.add_configs(wr_en=1, )

        self.wire(self.I, self.impl.in_)
        self.wire(self.wr_en, self.impl.wr_en)
        self.wire(self.impl.out, self.O)
Exemple #7
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)
class TestNestedClockTuple(m.Circuit):
    IO = [
        "I",
        m.In(m.Tuple(clk1=m.Clock, clk2=m.Clock, i=m.Bit)), "O",
        m.Out(m.Bits(2))
    ]

    @classmethod
    def definition(io):
        ff0 = mantle.FF()
        ff1 = mantle.FF()
        m.wire(io.I.clk1, ff0.CLK)
        m.wire(io.I.clk2, ff1.CLK)
        m.wire(io.I.i, ff0.I)
        m.wire(io.I.i, ff1.I)
        m.wire(m.bits([ff0.O, ff1.O]), io.O)
Exemple #9
0
def clk_physical(interconnect: Interconnect):
    for (x, y) in interconnect.tile_circuits:
        tile = interconnect.tile_circuits[(x, y)]
        tile_core = tile.core
        # We only want to do this on PE and memory tiles
        if tile_core is None or isinstance(tile_core, IOCoreBase):
            continue
        elif isinstance(tile_core, MemCore):
            if (x, y + 1) in interconnect.tile_circuits:
                tile_below = interconnect.tile_circuits[(x, y + 1)]
                if "clk" in tile_below.ports:
                    interconnect.remove_wire(tile.ports.clk_out,
                                             tile_below.ports.clk)
            # Get the PE tile to the left of this mem tile
            tile_left = interconnect.tile_circuits[(x - 1, y)]
            # Connect the clk input of this mem tile to the right clk
            # output of the neighboring PE tile
            interconnect.wire(tile_left.ports.clk_pass_through_out_right,
                              tile.ports.clk)
        else:
            orig_in_port = tile.ports.clk
            orig_out_port = tile.ports.clk_out
            # Remove the pass through connection that already exists
            tile.remove_wire(orig_in_port, orig_out_port)
            # Create a new pass through clock input
            tile.add_port("clk_pass_through", magma.In(magma.Clock))
            pass_through_input = tile.ports.clk_pass_through
            # Create 2 new clk pass through outputs (bottom and right)
            tile.add_port("clk_pass_through_out_bot", magma.Out(magma.Clock))
            tile.add_port("clk_pass_through_out_right", magma.Out(magma.Clock))
            tile.wire(tile.ports.clk_pass_through,
                      tile.ports.clk_pass_through_out_bot)
            tile.wire(tile.ports.clk_pass_through,
                      tile.ports.clk_pass_through_out_right)

            # Connect new clk pass through input to old pass through output
            tile.wire(pass_through_input, orig_out_port)
            # For top row tiles, connect new clk input to global clock
            if y < 2:
                interconnect.wire(interconnect.ports.clk, pass_through_input)
            # For other tiles, connect new clk input to
            # pass through output of tile above.
            else:
                tile_above = interconnect.tile_circuits[(x, y - 1)]
                interconnect.wire(tile_above.ports.clk_pass_through_out_bot,
                                  pass_through_input)
    def __init__(self, wordWidth: int, metricWidth: int, idx: int):
        self.io = io = m.IO(
            inputFeatureOne=m.In(m.UInt[wordWidth]),
            inputFeatureTwo=m.In(m.UInt[wordWidth]),
            inputMetric=m.In(m.UInt[metricWidth]),
            inputValid=m.In(m.Bit),
            shiftMode=m.In(
                m.Bit
            ),  # one cycle pause required between last inputValid and start of shiftMode
            doShift=m.In(m.Bit),
            neighborOutputIn=m.In(m.UInt[64]),
            out=m.Out(m.UInt[64])) + m.ClockIO(has_reset=True)

        ram_size = 1 << (2 * wordWidth)
        bram = PairMem(ram_size)()

        lastFeatureOne = reg_next(io.inputFeatureOne)
        lastFeatureTwo = reg_next(io.inputFeatureTwo)
        lastMetric = reg_next(io.inputMetric)
        lastInputValid = reg_next_init(io.inputValid, False)
        if idx >= 800 and idx < 2479:  # BRAM
            lastWrite = reg_next(bram.WDATA)
            collision = reg_next((bram.RADDR == bram.WADDR) & bram.WEN)
            readData = m.mux([bram.RDATA, lastWrite], collision)
        else:
            readData = bram.RDATA

        outputCounter = reg_init(m.UInt[2 * wordWidth], 0)
        io.out @= bram.RDATA

        @m.inline_combinational()
        def logic():
            if io.doShift:
                outputCounter.I @= outputCounter.O + 1  # wraps around
            else:
                outputCounter.I @= outputCounter.O  # default required
            if io.shiftMode:
                bram.RADDR @= outputCounter.O + 1 if io.doShift else outputCounter.O
                bram.WDATA @= io.neighborOutputIn
                bram.WADDR @= outputCounter.O
                bram.WE @= io.doShift
            else:
                bram.RADDR @= io.inputFeatureTwo.concat(io.inputFeatureOne)
                bram.WDATA @= (
                    readData[:32] +
                    m.zext_to(lastMetric, 32)).concat(readData[32:] + 1)
                bram.WADDR @= lastFeatureTwo.concat(lastFeatureOne)
                bram.WE @= lastInputValid
Exemple #11
0
def test_tester_verilog_wrapped(target, simulator):
    SimpleALU = m.DefineFromVerilogFile("tests/simple_alu.v",
                                        type_map={"CLK": m.In(m.Clock)},
                                        target_modules=["SimpleALU"])[0]

    circ = m.DefineCircuit("top", "a", m.In(m.Bits(16)), "b", m.In(m.Bits(16)),
                           "c", m.Out(m.Bits(16)), "config_data",
                           m.In(m.Bits(2)), "config_en", m.In(m.Bit), "CLK",
                           m.In(m.Clock))
    simple_alu = SimpleALU()
    m.wire(simple_alu.a, circ.a)
    m.wire(simple_alu.b, circ.b)
    m.wire(simple_alu.c, circ.c)
    m.wire(simple_alu.config_data, circ.config_data)
    m.wire(simple_alu.config_en, circ.config_en)
    m.wire(simple_alu.CLK, circ.CLK)
    m.EndDefine()

    tester = fault.Tester(circ, circ.CLK)
    tester.verilator_include("SimpleALU")
    tester.verilator_include("ConfigReg")
    for i in range(0, 4):
        tester.poke(
            fault.WrappedVerilogInternalPort("SimpleALU_inst0.config_reg.Q",
                                             m.Bits(2)), i)
        tester.step(2)
        tester.expect(
            fault.WrappedVerilogInternalPort("SimpleALU_inst0.opcode",
                                             m.Bits(2)), i)
        signal = tester.peek(
            fault.WrappedVerilogInternalPort("SimpleALU_inst0.opcode",
                                             m.Bits(2)))
        tester.expect(
            fault.WrappedVerilogInternalPort("SimpleALU_inst0.opcode",
                                             m.Bits(2)), signal)
        tester.expect(
            fault.WrappedVerilogInternalPort("SimpleALU_inst0.config_reg.Q",
                                             m.Bits(2)), i)
        signal = tester.peek(
            fault.WrappedVerilogInternalPort("SimpleALU_inst0.config_reg.Q",
                                             m.Bits(2)))
        tester.expect(
            fault.WrappedVerilogInternalPort("SimpleALU_inst0.config_reg.Q",
                                             m.Bits(2)), signal)
    with tempfile.TemporaryDirectory() as _dir:
        if target == "verilator":
            tester.compile_and_run(target,
                                   directory=_dir,
                                   flags=["-Wno-fatal"])
        else:
            tester.compile_and_run(target, directory=_dir, simulator=simulator)
Exemple #12
0
        class Register(m.Circuit):
            name = f"Register__has_ce_{has_ce}__has_reset_{has_reset}__" \
                   f"has_async_reset__{has_async_reset}__" \
                   f"type_{_type.__name__}__n_{n}"
            IO = ["I", m.In(T), "O", m.Out(T)]
            IO += m.ClockInterface(has_ce=has_ce,
                                   has_reset=has_reset,
                                   has_async_reset=has_async_reset)

            @classmethod
            def definition(io):
                reg = DefineCoreirReg(n, init, has_async_reset, _type)()
                I = io.I
                if has_reset:
                    I = mantle.mux([io.I, m.bits(init, n)], io.RESET)
                if has_ce:
                    I = mantle.mux([reg.O, I], io.CE)
                m.wire(I, reg.I)
                m.wire(io.O, reg.O)
Exemple #13
0
    def __init__(self, peak_generator):
        super().__init__(8, 32)

        self.wrapper = _PeakWrapper(peak_generator)

        # Generate core RTL (as magma).
        self.peak_circuit = FromMagma(self.wrapper.rtl())

        # Add input/output ports and wire them.
        inputs = self.wrapper.inputs()
        outputs = self.wrapper.outputs()
        for ports, dir_ in (
            (inputs, magma.In),
            (outputs, magma.Out),
        ):
            for i, (name, typ) in enumerate(ports.items()):
                magma_type = _convert_type(typ)
                self.add_port(name, dir_(magma_type))
                my_port = self.ports[name]
                if magma_type is magma.Bits[1]:
                    my_port = my_port[0]
                magma_name = name if dir_ is magma.In else f"O{i}"
                self.wire(my_port, self.peak_circuit.ports[magma_name])

        self.add_ports(config=magma.In(ConfigurationType(8, 32)), )

        # TODO(rsetaluri): Figure out stall signals.

        # Set up configuration for PE instruction. Currently, we perform a naive
        # partitioning of the large instruction into 32-bit config registers.
        config_width = self.wrapper.instruction_width()
        num_config = math.ceil(config_width / 32)
        instr_name = self.wrapper.instruction_name()
        for i in range(num_config):
            name = f"{instr_name}_{i}"
            self.add_config(name, 32)
            lb = i * 32
            ub = min(i * 32 + 32, config_width)
            len_ = ub - lb
            self.wire(self.registers[name].ports.O[:len_],
                      self.peak_circuit.ports[instr_name][lb:ub])

        self._setup_config()
Exemple #14
0
def test_spice_bus(target, simulator, vsup=1.5):
    # declare circuit
    dut = m.DeclareCircuit('mybus', 'a', m.In(m.Bits[2]), 'b',
                           m.Out(m.Bits[3]), 'vdd', m.BitIn, 'vss', m.BitIn)

    # define the test
    tester = fault.Tester(dut)
    tester.poke(dut.vdd, 1)
    tester.poke(dut.vss, 0)

    # step through all possible inputs
    tester.poke(dut.a, 0b000)
    tester.expect(dut.b, 0b101)
    tester.poke(dut.a, 0b001)
    tester.expect(dut.b, 0b100)
    tester.poke(dut.a, 0b010)
    tester.expect(dut.b, 0b111)
    tester.poke(dut.a, 0b011)
    tester.expect(dut.b, 0b110)

    # test one bit of the bus at a time
    tester.poke(dut.a[0], 0)
    tester.expect(dut.b[0], 1)
    tester.poke(dut.a[0], 1)
    tester.expect(dut.b[0], 0)
    tester.expect(dut.b[2], 1)

    tester.poke(dut.a[1], 0)
    tester.expect(dut.b[1], 0)
    tester.poke(dut.a[1], 1)
    tester.expect(dut.b[1], 1)
    tester.expect(dut.b[2], 1)

    # set options
    kwargs = dict(target=target,
                  simulator=simulator,
                  model_paths=[Path('tests/spice/mybus.sp').resolve()],
                  vsup=vsup,
                  tmp_dir=True)

    # run the simulation
    tester.compile_and_run(**kwargs)
Exemple #15
0
def DefineCounter(n,
                  cin=False,
                  cout=True,
                  incr=1,
                  has_ce=False,
                  has_reset=False):
    """
    Create an n-bit counter with a given increment.

    O : m.Out(m.UInt(n)), COUT : m.Out(m.Bit)
    """
    name_ = counter_name(f'Counter{n}', incr, has_ce, has_reset, cin, cout)
    args = {}
    if cin:
        args["CIN"] = m.In(m.Bit)
    args["O"] = m.Out(m.UInt[n])
    if cout:
        args["COUT"] = m.Out(m.Bit)

    class _Counter(m.Circuit):
        name = name_
        io = m.IO(**args)
        io += m.ClockIO(has_ce, has_reset)

        add = DefineAdd(n, cin=cin, cout=cout)()
        reg = Register(n, has_ce=has_ce, has_reset=has_reset)

        m.wire(reg.O, add.I0)
        m.wire(m.array(incr, n), add.I1)
        reg(add.O)

        next = False
        if next:
            m.wire(add.O, io.O)
        else:
            m.wire(reg.O, io.O)
        if cin:
            m.wire(io.CIN, add.CIN)
        if cout:
            m.wire(add.COUT, io.COUT)

    return _Counter
Exemple #16
0
def test_ram():
    main = m.DefineCircuit("main", "rdata", m.Out(m.Bit), "CLKIN",
                           m.In(m.Clock))

    ram = mantle.RAM(4, 1)

    waddr = mantle.Counter(4, cout=False)
    wdata = mantle.Counter(1, cout=False)
    we = 1
    raddr = mantle.Counter(4, cout=False)

    ram(raddr, waddr, wdata, we, CLK=main.CLKIN)

    m.wire(ram.RDATA[0], main.rdata)
    m.EndDefine()
    if m.mantle_target == "coreir":
        output = "coreir"
    else:
        output = "verilog"
    m.compile("build/test_common_ram", main, output)
Exemple #17
0
    class TestCircuit(m.Circuit):
        name = _name
        IO = ["I", m.In(in_T), "O0", out_T, "O1", out_T]

        @classmethod
        def definition(io):
            # Test using the method directly
            res = getattr(mantle, op.name)(io.I)
            assert isinstance(res, expected_res_type), type(res)
            m.wire(res, io.O0)
            # Test using the operator if it exists, otherwise wire 0 to O1
            if op.operator is None or (op.name in ["sub", "add"] + comparisons
                                       and T == m.Bits):
                if op.name in comparisons:
                    m.wire(0, io.O1)
                else:
                    m.wire(m.bits(0, N), io.O1)
            else:
                res_operator = eval(f"{op.operator} io.I")
                m.wire(res_operator, io.O1)
Exemple #18
0
def test_ext_vlog(target, simulator):
    # declare circuit
    mybuf_inc_test = m.DeclareCircuit(
        'mybuf_inc_test',
        'in_', m.In(m.Bit),
        'out', m.Out(m.Bit)
    )

    # define the test
    tester = fault.BufTester(mybuf_inc_test)

    # run the test
    tester.compile_and_run(
        target=target,
        simulator=simulator,
        ext_libs=[Path('tests/verilog/mybuf_inc_test.v').resolve()],
        inc_dirs=[Path('tests/verilog').resolve()],
        ext_model_file=True,
        tmp_dir=True
    )
Exemple #19
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 #20
0
    def __init__(self,
                 node: PortNode,
                 config_addr_width: int,
                 config_data_width: int,
                 double_buffer: bool = False):
        if not isinstance(node, PortNode):
            raise ValueError(node, PortNode.__name__)
        self.node: PortNode = node

        super().__init__(config_addr_width,
                         config_data_width,
                         double_buffer=double_buffer)

        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)), )
            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)
        else:
            # remove clk and reset ports from the base class since it's going
            # to be a pass through wire anyway
            self.ports.pop("clk")
            self.ports.pop("reset")
            self.ports.pop("read_config_data")
            if self.double_buffer:
                self.ports.pop("use_db")
                self.ports.pop("config_db")

        self._setup_config()

        self.instance_name = self.name()
Exemple #21
0
def wrap_with_disassembler(PE, disassembler, width, layout, inst_type):
    WrappedIO = []
    for key, value in PE.interface.ports.items():
        WrappedIO.append(key)
        if type(value) == m.Out(inst_type):
            WrappedIO.append(m.In(m.Bits[width]))
        else:
            WrappedIO.append(m.Flip(type(value)))

    def wire_inst_fields(wrapper_inst, pe_inst, layout):
        if isinstance(wrapper_inst, m.Product):
            for key, value in layout.items():
                begin = value[0]
                end = value[1]
                wire_inst_fields(wrapper_inst[begin:end], getattr(pe_inst,
                                                                  key),
                                 value[2])
        else:
            for key, value in layout.items():
                begin = value[0]
                end = value[1]
                region = wrapper_inst[begin:end]
                field = getattr(pe_inst, key)
                if isinstance(type(field), m._BitKind):
                    region = m.bit(region)
                m.wire(region, field)

    class WrappedPE(m.Circuit):
        IO = WrappedIO
        @classmethod
        def definition(io):
            pe = PE()
            for key, value in PE.interface.ports.items():
                if type(value) == m.Out(inst_type):
                    wire_inst_fields(getattr(io, key), getattr(pe, key),
                                     layout)
                elif value.isoutput():
                    getattr(pe, key) <= getattr(io, key)
                else:
                    getattr(io, key) <= getattr(pe, key)
    return WrappedPE
Exemple #22
0
    def __init__(self, width, num_tracks):
        super().__init__()

        self.width = width
        self.num_tracks = num_tracks
        is_power_of_two = lambda x: x != 0 and ((x & (x - 1)) == 0)
        assert is_power_of_two(self.num_tracks)
        self.mux = MuxWrapper(self.num_tracks, self.width)

        T = magma.Bits(self.width)
        sel_bits = magma.bitutils.clog2(self.num_tracks)

        self.add_ports(
            I=magma.In(magma.Array(self.num_tracks, T)),
            O=magma.Out(T),
        )
        self.add_configs(sel=sel_bits, )

        self.wire(self.I, self.mux.I)
        self.wire(self.sel, self.mux.S)
        self.wire(self.mux.O, self.O)
Exemple #23
0
    def __init__(self, width, num_tracks):
        super().__init__()

        self.width = width
        self.num_tracks = num_tracks
        is_power_of_two = lambda x: x != 0 and ((x & (x - 1)) == 0)
        assert is_power_of_two(self.num_tracks)
        self.mux = FromMagma(mantle.DefineMux(self.num_tracks, self.width))
        T = magma.Bits(self.width)
        sel_bits = math.ceil(math.log(self.num_tracks, 2))

        self.add_ports(
            I=magma.In(magma.Array(self.num_tracks, T)),
            O=magma.Out(T),
        )
        self.add_configs(sel=sel_bits, )

        for i in range(self.num_tracks):
            self.wire(self.I[i], getattr(self.mux, f"I{i}"))
        self.wire(self.sel, self.mux.S)
        self.wire(self.mux.O, self.O)
Exemple #24
0
def test_vams_wrap():
    # declare the circuit
    class myblk(m.Circuit):
        io = m.IO(a=RealIn,
                  b=RealOut,
                  c=m.In(m.Bit),
                  d=m.Out(m.Bits[2]),
                  e=ElectIn,
                  f=ElectOut)

    wrap_circ = VAMSWrap(myblk)

    # check magma representation of wrapped circuit
    assert wrap_circ.IO.ports['a'] is RealIn
    assert wrap_circ.IO.ports['b'] is RealOut
    assert wrap_circ.IO.ports['c'] is m.In(m.Bit)
    assert wrap_circ.IO.ports['d'] is m.Out(m.Bits[2])
    assert wrap_circ.IO.ports['e'] is ElectIn
    assert wrap_circ.IO.ports['f'] is ElectOut

    # check Verilog-AMS code itself
    assert wrap_circ.vams_code == '''\
Exemple #25
0
def wrap_with_disassembler(PE, disassembler, width, layout, inst_type):
    WrappedIO = OrderedDict()
    for key, value in PE.interface.ports.items():
        if isinstance(value, m.Out(inst_type)):
            vtype = m.In(m.Bits[width])
        else:
            vtype = m.Flip(type(value))
        WrappedIO[key] = vtype

    def wire_inst_fields(wrapper_inst, pe_inst, layout):
        if isinstance(wrapper_inst, m.Product):
            for key, value in layout.items():
                begin = value[0]
                end = value[1]
                wire_inst_fields(wrapper_inst[begin:end],
                                 getattr(pe_inst, key), value[2])
        else:
            for key, value in layout.items():
                begin = value[0]
                end = value[1]
                region = wrapper_inst[begin:end]
                field = getattr(pe_inst, key)
                if issubclass(type(field), m.Digital):
                    region = m.bit(region)
                m.wire(region, field)

    class WrappedPE(m.Circuit):
        io = m.IO(**WrappedIO)
        pe = PE()
        for key, value in PE.interface.ports.items():
            if type(value) == m.Out(inst_type):
                wire_inst_fields(getattr(io, key), getattr(pe, key), layout)
            elif value.is_output():
                m.wire(getattr(pe, key), getattr(io, key))
            else:
                m.wire(getattr(io, key), getattr(pe, key))

    return WrappedPE
Exemple #26
0
 class dut(m.Circuit):
     name = 'test_analog_slice'
     io = m.IO(
         chunk=m.In(m.Bits[CFG['chunk_width']]),
         chunk_idx=m.In(m.Bits[int(ceil(log2(CFG['num_chunks'])))]),
         pi_ctl=m.In(m.Bits[CFG['pi_ctl_width']]),
         slice_offset=m.In(m.Bits[int(ceil(log2(CFG['slices_per_bank'])))]),
         sample_ctl=m.BitIn,
         incr_sum=m.BitIn,
         write_output=m.BitIn,
         out_sgn=m.BitOut,
         out_mag=m.Out(m.Bits[CFG['n_adc']]),
         clk=m.BitIn,
         rst=m.BitIn,
         jitter_rms=fault.RealIn,
         noise_rms=fault.RealIn,
         wdata0=m.In(m.Bits[func_widths[0]]),
         wdata1=m.In(m.Bits[func_widths[1]]),
         waddr=m.In(m.Bits[9]),
         we=m.BitIn
     )
Exemple #27
0
def test_val():
    """
    Test instances of Bits[4] work correctly
    """
    bits_4_in = m.In(m.Bits[4])
    bits_4_out = m.Out(m.Bits[4])

    assert m.Flip(bits_4_in) == bits_4_out
    assert m.Flip(bits_4_out) == bits_4_in

    a_0 = bits_4_out(name='a0')
    print(a_0)

    a_1 = bits_4_in(name='a1')
    print(a_1)

    a_1.wire(a_0)

    b_0 = a_1[0]
    assert b_0 is a_1[0], "getitem failed"

    a_3 = a_1[0:2]
    assert a_3 == a_1[0:2], "getitem of slice failed"
Exemple #28
0
def AXI4SlaveType(addr_width, data_width):
    """
    This function returns a axi4-slave class (parameterized by @addr_width and
    @data_width) which can be used as the magma ports with these inputs
    and outputs
    Below is AXI4-Lite interface ports in verilog

    input  logic [`$cfg_addr_width-1`:0]    AWADDR,
    input  logic                            AWVALID,
    output logic                            AWREADY,
    input  logic [`$cfg_bus_width-1`:0]     WDATA,
    input  logic                            WVALID,
    output logic                            WREADY,
    input  logic [`$cfg_bus_width-1`:0]     ARADDR,
    input  logic                            ARVALID,
    output logic                            ARREADY,
    output logic [`$cfg_bus_width-1`:0]     RDATA,
    output logic [1:0]                      RRESP,
    output logic                            RVALID,
    input  logic                            RREADY,
    output logic                            interrupt,

    """

    _AXI4SlaveType = magma.Tuple(awaddr=magma.In(magma.Bits[addr_width]),
                                 awvalid=magma.In(magma.Bit),
                                 awready=magma.Out(magma.Bit),
                                 wdata=magma.In(magma.Bits[data_width]),
                                 wvalid=magma.In(magma.Bit),
                                 wready=magma.Out(magma.Bit),
                                 araddr=magma.In(magma.Bits[addr_width]),
                                 arvalid=magma.In(magma.Bit),
                                 arready=magma.Out(magma.Bit),
                                 rdata=magma.Out(magma.Bits[data_width]),
                                 rresp=magma.Out(magma.Bits[2]),
                                 rvalid=magma.Out(magma.Bit),
                                 rready=magma.In(magma.Bit),
                                 interrupt=magma.Out(magma.Bit))

    return _AXI4SlaveType
Exemple #29
0
class RAM(m.Circuit):
    io = m.IO(
        RADDR=m.In(m.Bits[addr_width]),
        RDATA=m.Out(m.Bits[data_width]),
        WADDR=m.In(m.Bits[addr_width]),
        WDATA=m.In(m.Bits[data_width]),
        WE=m.In(m.Bit),
        CLK=m.In(m.Clock),
        RESET=m.In(m.Reset)
    )

    regs = [mantle.Register(data_width, init=int(init[i]), has_ce=True,
                            has_reset=True)
            for i in range(1 << addr_width)]
    for i, reg in enumerate(regs):
        reg.I <= io.WDATA
        reg.CE <= (io.WADDR == m.bits(i, addr_width)) & io.WE
    io.RDATA <= mantle.mux([reg.O for reg in regs], io.RADDR)
Exemple #30
0
def apply_global_parallel_meso_wiring(interconnect: Interconnect,
                                      io_sides: IOSide, num_cfg: int = 1):

    interconnect_read_data_or = apply_global_meso_wiring(interconnect,
                                                         io_sides)
    # interconnect must have config port
    assert "config" in interconnect.ports
    # there must be at least one configuration path
    assert num_cfg >= 1

    interconnect.remove_port("config")
    # this is not a typo. Total number of bits in configuration address
    # is same as config_data
    config_data_width = interconnect.config_data_width
    interconnect.add_port(
        "config",
        magma.In(magma.Array[num_cfg,
                             ConfigurationType(config_data_width,
                                               config_data_width)]))

    cgra_width = interconnect.x_max - interconnect.x_min + 1
    # number of CGRA columns one configuration controller is in charge of
    col_per_config = math.ceil(cgra_width / num_cfg)

    # looping through on a per-column bases
    for x_coor in range(interconnect.x_min, interconnect.x_max + 1):
        column = interconnect.get_column(x_coor)
        # skip tiles with no config
        column = [entry for entry in column if "config" in entry.ports]
        # select which configuration controller is connected to that column
        config_sel = int(x_coor/col_per_config)
        # wire configuration ports to first tile in column
        interconnect.wire(interconnect.ports.config[config_sel],
                          column[0].ports.config)

    return interconnect_read_data_or