Пример #1
0
def _create_pkgs(dut):
    writer_signal_aliases = {'debug_in': 'in', 'debug_in_ready': 'in_ready'}
    writer = NocDiWriter(dut, dut.clk, writer_signal_aliases)

    for i in range(STRESS_TEST_PKG_COUNT):
        is_reg_pkg = random.randint(0, 1)
        pkg = DiPacket()
        if is_reg_pkg:
            pkg.set_contents(dest=1,
                             src=0,
                             type=DiPacket.TYPE.REG.value,
                             type_sub=DiPacket.TYPE_SUB.REQ_WRITE_REG_16.value,
                             payload=[0xdead])
        else:
            payload_len = random.randint(0, 5)
            payload = []
            for _ in range(payload_len):
                payload.append(random.randint(0, 2**16 - 1))

            pkg.set_contents(dest=1,
                             src=0,
                             type=DiPacket.TYPE.EVENT.value,
                             type_sub=0x3,
                             payload=payload)

        # wait a random number of cycles before sending the packet
        for s in range(random.randint(0, 100)):
            yield RisingEdge(dut.clk)

        _sent_pkgs.append(pkg)
        yield writer.send_packet(pkg)
Пример #2
0
def _trigger_reg_wr_req_err(dut, dest, src, word_width, regaddr, value):
    """
    Sends a register write request to the module and checks if an error response
    gets returned.
    """

    tx_packet = DiPacket()
    rx_packet = DiPacket()
    writer = NocDiWriter(dut, dut.clk)
    reader = NocDiReader(dut, dut.clk)

    if word_width == 16:
        type_sub = DiPacket.TYPE_SUB.REQ_WRITE_REG_16.value
        words = 1
    elif word_width == 32:
        type_sub = DiPacket.TYPE_SUB.REQ_WRITE_REG_32.value
        words = 2
    elif word_width == 64:
        type_sub = DiPacket.TYPE_SUB.REQ_WRITE_REG_64.value
        words = 4
    elif word_width == 128:
        type_sub = DiPacket.TYPE_SUB.REQ_WRITE_REG_128.value
        words = 8
    else:
        raise TestFailure("An invalid register width parameter was chosen! (%d)" %\
                           word_width)

    # Assemble payload of REG debug packet
    payload = [regaddr]
    for w in range(0, words):
        payload.append((value >> ((words - 1 - w) * 16)) & 0xFFFF)

    tx_packet.set_contents(dest=dest,
                           src=src,
                           type=DiPacket.TYPE.REG.value,
                           type_sub=type_sub,
                           payload=payload)

    yield writer.send_packet(tx_packet)

    rx_packet = yield reader.receive_packet(set_ready=True)

    if not rx_packet:
        raise TestFailure("No response packet received!")

    if rx_packet.type_sub != DiPacket.TYPE_SUB.RESP_WRITE_REG_ERROR.value:
        raise TestFailure(
            "Register write did not return RESP_WRITE_REG_ERROR "
            "when writing 0x%x to register 0x%x of module 0x%x." %
            (value, regaddr, dest))
Пример #3
0
def test_only_regaccess_ready(dut):
    """
    Check if a register access packet passes through, even though the bypass
    ready signal is tied to 0.
    """

    yield _init_dut(dut)

    dut.out_reg_ready <= 1
    dut.out_bypass_ready <= 0

    reg_reader_signal_aliases = {
        'debug_out': 'out_reg',
        'debug_out_ready': 'out_reg_ready'
    }
    reg_reader = NocDiReader(dut, dut.clk, reg_reader_signal_aliases)

    writer_signal_aliases = {'debug_in': 'in', 'debug_in_ready': 'in_ready'}
    writer = NocDiWriter(dut, dut.clk, writer_signal_aliases)

    reg_pkg = DiPacket()
    reg_pkg.set_contents(dest=1,
                         src=0,
                         type=DiPacket.TYPE.REG.value,
                         type_sub=DiPacket.TYPE_SUB.REQ_WRITE_REG_16.value,
                         payload=[0xdead])

    # send a register write packet to the DUT
    write_thread = cocotb.fork(writer.send_packet(reg_pkg))

    # ensure that the bypass valid signal isn't asserted
    checker_thread = cocotb.fork(
        _assert_signal_stays_low(dut.clk, dut.out_bypass.valid))

    # get packet on reg output
    rcv_pkg = yield reg_reader.receive_packet()

    yield write_thread.join()
    checker_thread.kill()

    if not rcv_pkg:
        raise TestFailure("Register access packet not routed to output.")

    if not rcv_pkg.equal_to(dut, reg_pkg):
        raise TestFailure("Data corruption.")
Пример #4
0
def test_event_pkg(dut):
    """
    Check if a register access packet passes through
    """

    yield _init_dut(dut)

    dut.out_reg_ready <= 1
    dut.out_bypass_ready <= 1

    bypass_reader_signal_aliases = {
        'debug_out': 'out_bypass',
        'debug_out_ready': 'out_bypass_ready'
    }
    bypass_reader = NocDiReader(dut, dut.clk, bypass_reader_signal_aliases)

    writer_signal_aliases = {'debug_in': 'in', 'debug_in_ready': 'in_ready'}
    writer = NocDiWriter(dut, dut.clk, writer_signal_aliases)

    event_pkg = DiPacket()
    event_pkg.set_contents(dest=1,
                           src=0,
                           type=DiPacket.TYPE.EVENT.value,
                           type_sub=0,
                           payload=[0xdead])

    # send an event packet to the DUT
    write_thread = cocotb.fork(writer.send_packet(event_pkg))

    # ensure that the register output valid signal isn't asserted
    checker_thread = cocotb.fork(
        _assert_signal_stays_low(dut.clk, dut.out_reg.valid))

    # get packet on bypass output
    rcv_pkg = yield bypass_reader.receive_packet()

    yield write_thread.join()
    checker_thread.kill()

    if not rcv_pkg:
        raise TestFailure("Event access packet not routed to output.")

    if not rcv_pkg.equal_to(dut, event_pkg):
        raise TestFailure("Data corruption.")
Пример #5
0
def _trigger_reg_rd_req_err(dut, dest, src, word_width, regaddr):
    """
    Sends a register read request to the module and checks if an error response
    gets returned.
    """

    tx_packet = DiPacket()
    rx_packet = DiPacket()
    writer = NocDiWriter(dut, dut.clk)
    reader = NocDiReader(dut, dut.clk)

    if word_width == 16:
        type_sub = DiPacket.TYPE_SUB.REQ_READ_REG_16.value
    elif word_width == 32:
        type_sub = DiPacket.TYPE_SUB.REQ_READ_REG_32.value
    elif word_width == 64:
        type_sub = DiPacket.TYPE_SUB.REQ_READ_REG_64.value
    elif word_width == 128:
        type_sub = DiPacket.TYPE_SUB.REQ_READ_REG_128.value
    else:
        raise TestFailure("An invalid register width parameter was chosen! (%d)" %\
                           word_width)

    tx_packet.set_contents(dest=dest,
                           src=src,
                           type=DiPacket.TYPE.REG.value,
                           type_sub=type_sub,
                           payload=[regaddr])

    yield writer.send_packet(tx_packet)

    rx_packet = yield reader.receive_packet(set_ready=True)

    if not rx_packet:
        raise TestFailure("No response packet received!")

    if rx_packet.type_sub != DiPacket.TYPE_SUB.RESP_READ_REG_ERROR.value:
        raise TestFailure("Register read did not return RESP_READ_REG_ERROR "
                          "when reading from register 0x%x of module 0x%x." %
                          (regaddr, dest))
Пример #6
0
def _di_to_bus_tx(dut, num_transfers=500, max_delay=100, random_data=False):

    writer = NocDiWriter(dut, dut.clk);
    tx_packet = DiPacket();

    for i in range(num_transfers):
        delay = random.randint(0, max_delay)

        for _ in range(delay):
            yield RisingEdge(dut.clk)

        data = random.randint(0, 255) if random_data else 0x42

        tx_packet.set_contents(dest=MODULE_DI_ADDRESS, src=SENDER_DI_ADDRESS,
                               type=DiPacket.TYPE.EVENT.value, type_sub=0,
                               payload=[data])

        yield writer.send_packet(tx_packet)

        yield RisingEdge(dut.clk)

        _di_to_bus_fifo.append(data)
Пример #7
0
class MamDiDriver:
    """
    MAM memory transfer driver on the Debug Interconnect
    """

    def __init__(self, entity, clock, di_writer=None, di_reader=None,
                 MAX_PKT_LEN=12, MODULE_DI_ADDRESS=1, SENDER_DI_ADDRESS=0):
        self.entity = entity
        self.clock = clock
        self.log = entity._log
        self.MAX_PKT_LEN = MAX_PKT_LEN
        self.MODULE_DI_ADDRESS = MODULE_DI_ADDRESS
        self.SENDER_DI_ADDRESS = SENDER_DI_ADDRESS

        if di_writer:
            self.di_writer = di_writer
        else:
            self.di_writer = NocDiWriter(entity, clock)

        if di_reader:
            self.di_reader = di_reader
        else:
            self.di_reader = NocDiReader(entity, clock)

    def _create_mam_transfer(self, mem_transfer):
        """
        Get MAM transfer bytearray representing the memory transfer 
        """
        mam_transfer = bytearray()

        we = (mem_transfer.operation == 'write')

        selsize = 0
        if mem_transfer.burst:
            selsize = int(len(mem_transfer.data) / (mem_transfer.DW / 8))
        else:
            selsize = mem_transfer.byteselect
        if selsize > 0xFF:
            raise TestFailure("selsize overflow detected")

        hdr0 = 0
        hdr0 |= (we & 0x1) << 7
        hdr0 |= (mem_transfer.burst & 0x1) << 6
        hdr0 |= (mem_transfer.sync & 0x1) << 5

        hdr1 = selsize

        mam_transfer.append(hdr0)
        mam_transfer.append(hdr1)
        mam_transfer.extend(mem_transfer.addr.to_bytes(int(mem_transfer.AW / 8),
                                                       byteorder='big'))

        if mem_transfer.operation == 'write' and mem_transfer.data:
            mam_transfer.extend(mem_transfer.data)

        return mam_transfer

    def _create_di_pkgs(self, mam_transfer):
        """
        Get DI packages representing the memory transfer
        """
        pkgs = []

        max_payload_bytes = (self.MAX_PKT_LEN - 3) * 2
        number_of_pkgs = ceil(len(mam_transfer) / max_payload_bytes)

        b = 0
        for _ in range(number_of_pkgs):
            pkg = DiPacket()
            pkg.dest = self.MODULE_DI_ADDRESS
            pkg.src = self.SENDER_DI_ADDRESS
            pkg.type = DiPacket.TYPE.EVENT.value
            pkg.type_sub = 0

            for i in range(int(max_payload_bytes / 2)):
                payload_word = mam_transfer[b] << 8 | mam_transfer[b + 1]
                pkg.payload.append(payload_word)

                b += 2
                if b >= len(mam_transfer):
                    break

            pkgs.append(pkg)

        return pkgs

    @cocotb.coroutine
    def drive(self, mem_transfer):
        """
        Drive the Debug Interconnect with a memory transfer and check the
        results
        """

        # request
        mam_transfer_request = self._create_mam_transfer(mem_transfer)
        req_pkgs = self._create_di_pkgs(mam_transfer_request)
        for pkg in req_pkgs:
            yield self.di_writer.send_packet(pkg)

        # response
        if mem_transfer.operation == 'read':
            rcv_data = bytearray()

            while len(rcv_data) < len(mem_transfer.data):
                yield RisingEdge(self.clock)
                pkg = yield self.di_reader.receive_packet(set_ready=True)

                self.log.debug("Received memory read response " + str(pkg))
                for payload_word in pkg.payload:
                    rcv_data.extend(payload_word.to_bytes(2, byteorder='big'))

            # check received data
            if rcv_data != mem_transfer.data:
                raise TestFailure("Got invalid data.\nExpected: %s\nReceived: %s" %
                                  (mem_transfer.data.hex(), rcv_data.hex()))

        # for synchronous writes: check if we received a acknowledgement packet
        if mem_transfer.operation == 'write' and mem_transfer.sync:
            pkg = yield self.di_reader.receive_packet(set_ready=True)
            exp_sync_pkg = DiPacket()
            exp_sync_pkg.set_contents(self.SENDER_DI_ADDRESS,
                                      self.MODULE_DI_ADDRESS,
                                      DiPacket.TYPE.EVENT.value, 0, [])
            if not pkg.equal_to(self.entity, exp_sync_pkg):
                raise TestFailure(
                    "Acknowledgement packet for sync write invalid.")