Esempio n. 1
0
def _dem_to_di_rx(dut, num_transfers=500, max_delay=100):

    reader = NocDiReader(dut, dut.clk)
    ex_packet = DiPacket()

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

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

        rx_packet = yield reader.receive_packet(set_ready=True)

        data = _dem_to_di_fifo.pop(0)

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

        if not rx_packet:
            raise TestFailure("receive_packet() timed out")

        if not rx_packet.equal_to(dut, ex_packet, mask=None):
            raise TestFailure("Unexpected content of " + rx_packet.__str__() +
                              "\n Expected " + ex_packet.__str__())

        yield RisingEdge(dut.clk)
Esempio n. 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))
Esempio n. 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.")
Esempio n. 4
0
    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)
Esempio n. 5
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.")
Esempio n. 6
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))
Esempio n. 7
0
def _check_pkgs(dut):
    bypass_reader_signal_aliases = {
        'debug_out': 'out_bypass',
        'debug_out_ready': 'out_bypass_ready'
    }
    bypass_reader = NocDiReader(dut, dut.clk, bypass_reader_signal_aliases)

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

    pkg_rcv_cnt = 0
    while True:
        yield RisingEdge(dut.clk)

        bypass_active = dut.out_bypass.valid.value and dut.out_bypass_ready.value
        reg_active = dut.out_reg.valid.value and dut.out_reg_ready.value

        if not (bypass_active or reg_active):
            continue

        if bypass_active and reg_active:
            raise TestFailure(
                "Both out_*.valid signals are high. Invalid state.")

        if len(_sent_pkgs) == 0:
            raise TestFailure(
                "Got valid signal even though no packet has been sent.")

        sent_pkg = _sent_pkgs.pop(0)

        if bypass_active:
            if sent_pkg.type == DiPacket.TYPE.REG.value:
                raise TestFailure(
                    "out_bypass.valid signal is high even though "
                    "we have sent a REG packet: Sent packet was "
                    "%s" % str(sent_pkg))
            rcv_pkg = yield bypass_reader.receive_packet()

        if reg_active:
            if not sent_pkg.type == DiPacket.TYPE.REG.value:
                raise TestFailure("out_reg.valid signal is high even though "
                                  "we have *not* sent a REG packet. Sent "
                                  "packet was %s" % str(sent_pkg))
            rcv_pkg = yield reg_reader.receive_packet()

        if not rcv_pkg:
            raise TestFailure("Packet lost.")

        if not rcv_pkg.equal_to(dut, sent_pkg):
            raise TestFailure("Data corruption.")

        pkg_rcv_cnt += 1

        if pkg_rcv_cnt == STRESS_TEST_PKG_COUNT:
            return
Esempio n. 8
0
def test_dem_uart_activation(dut):
    """
    Check if DEM_UART is handling the activation bit correctly
    """

    access = RegAccess(dut)

    yield _init_dut(dut)

    dut._log.info("Check contents of MOD_CS")
    yield access.assert_reg_value(MODULE_DI_ADDRESS, SENDER_DI_ADDRESS,
                                  DiPacket.BASE_REG.MOD_CS.value, 16, 0)

    yield _activate_module(dut)

    dut._log.info("Check contents of MOD_CS")
    yield access.assert_reg_value(MODULE_DI_ADDRESS, SENDER_DI_ADDRESS,
                                  DiPacket.BASE_REG.MOD_CS.value, 16, 1)

    _bus_to_di_fifo.clear()

    write_thread = cocotb.fork(_bus_to_di_tx(dut, num_transfers=5))

    read_thread = cocotb.fork(_bus_to_di_rx(dut, num_transfers=5))
    yield read_thread.join()

    yield access.write_register(dest=MODULE_DI_ADDRESS, src=SENDER_DI_ADDRESS,
                                word_width=16,
                                regaddr=DiPacket.BASE_REG.MOD_CS.value,
                                value=0)

    write_thread = cocotb.fork(_bus_to_di_tx(dut, num_transfers=5))

    # Wait one cycle to make sure the reader below doesn't accidentally try to
    # receive parts of the RegAccess response packet
    yield RisingEdge(dut.clk)

    # Don't confuse users of this test when they see a warning message
    dut._log.warning("The following warning 'packet receive timed out' is expected:")
    packet = yield NocDiReader(dut, dut.clk).receive_packet(set_ready=True)
    if packet:
        raise TestFailure("Received packet while module was deactivated")

    yield access.write_register(dest=MODULE_DI_ADDRESS, src=SENDER_DI_ADDRESS,
                                word_width=16,
                                regaddr=DiPacket.BASE_REG.MOD_CS.value,
                                value=1)

    read_thread = cocotb.fork(_bus_to_di_rx(dut, num_transfers=5))
    yield read_thread.join()
Esempio n. 9
0
def _assert_trace_event(dut, trace_id, trace_value):
    """
    Stimuli on the trace port will be generated once to trigger the emission
    of a new debug event packet which will be read and evaluated.
    """

    generator = StmTraceGenerator()
    reader = NocDiReader(dut, dut.clk)

    # Build expected packet
    expected_packet = DiPacket()
    exp_payload = [0, 0, trace_id]
    payload_words = int(dut.VALWIDTH.value.integer / 16)
    for w in range(0, payload_words):
        exp_payload.append(trace_value >> (w * 16) & 0xFFFF)

    expected_packet.set_contents(dest=SENDER_DI_ADDRESS,
                                 src=MODULE_DI_ADDRESS,
                                 type=DiPacket.TYPE.EVENT.value,
                                 type_sub=0,
                                 payload=exp_payload)

    # Build comparison mask for expected packet
    # Ignore flits 0 and 1 with timestamp
    exp_payload_mask = [1] * len(exp_payload)
    exp_payload_mask[0] = 0
    exp_payload_mask[1] = 0

    yield generator.trigger_event(dut, trace_id, trace_value)
    rcv_pkg = yield reader.receive_packet(set_ready=True)

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

    if not rcv_pkg.equal_to(dut, expected_packet, exp_payload_mask):
        raise TestFailure(
            "The STM generated an unexpected debug event packet!")
Esempio n. 10
0
def test_fixedwidth(dut):
    """Test the generation of two packets with a byte padding"""
    yield _init_dut(dut)

    dut.id <= MODULE_DI_ADDRESS
    dut.dest <= SENDER_DI_ADDRESS
    data_str = '\xef\x12\x34\xde\xad\xbe\xef\xef\xab\xab\xcd'
    dut.data.value = BinaryValue(data_str)
    dut.overflow <= 0
    dut.event_available <= 1


    # packet 1
    exp_pkg = DiPacket()
    exp_pkg.set_contents(dest=SENDER_DI_ADDRESS,
                         src=MODULE_DI_ADDRESS,
                         type=DiPacket.TYPE.EVENT,
                         type_sub=1,
                         payload=[0xabcd, 0xefab, 0xbeef, 0x0dead, 0x1234])

    reader = NocDiReader(dut, dut.clk)
    rcv_pkg = yield reader.receive_packet(set_ready=True)

    if not rcv_pkg:
        raise TestFailure("No packet 1 generated!")

    if not rcv_pkg.equal_to(dut, exp_pkg):
        raise TestFailure("Received packet 1 doesn't match expected packet. "
                          "Got %s, expected %s" % (str(rcv_pkg), str(exp_pkg)))

    # packet 2
    yield RisingEdge(dut.clk)
    exp_pkg = DiPacket()
    exp_pkg.set_contents(dest=SENDER_DI_ADDRESS,
                         src=MODULE_DI_ADDRESS,
                         type=DiPacket.TYPE.EVENT,
                         type_sub=0,
                         payload=[0x00ef])

    reader = NocDiReader(dut, dut.clk)
    rcv_pkg = yield reader.receive_packet(set_ready=True)

    if not rcv_pkg:
        raise TestFailure("No packet 2 generated!")

    if not rcv_pkg.equal_to(dut, exp_pkg):
        raise TestFailure("Received packet 2 doesn't match expected packet. "
                          "Got %s, expected %s" % (str(rcv_pkg), str(exp_pkg)))

    # check if the DUT is ready for the next event transfer
    if not dut.event_consumed.value:
        raise TestFailure("DUT does not indicate that the event has been "
                          "consumed.")
Esempio n. 11
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.")
def test_fixedwidth(dut):
    """Test the generation of two packets with a byte padding"""
    yield _init_dut(dut)

    
    dut.id <= MODULE_DI_ADDRESS
    dut.dest <= SENDER_DI_ADDRESS
    
    # create data for two packets: one full packet, and one packet with 
    # only a single payload word
    payload_words_per_pkg = dut.MAX_PKT_LEN.value.integer - 3 # 3 header words
    payload_bytes = (payload_words_per_pkg + 1) * 2
    data_bytes = bytearray(random.getrandbits(8) for _ in range(payload_bytes))
    data_int = int.from_bytes(data_bytes, byteorder='little', signed=False)
    dut.data.value = BinaryValue(data_int)

    dut.overflow <= 0
    dut.event_available <= 1


    # packet 1
    exp_pkg1_payload = [data_bytes[i+1] << 8 | data_bytes[i] for i in range(0, payload_words_per_pkg * 2, 2)]
    exp_pkg = DiPacket()
    exp_pkg.set_contents(dest=SENDER_DI_ADDRESS,
                         src=MODULE_DI_ADDRESS,
                         type=DiPacket.TYPE.EVENT,
                         type_sub=1,
                         payload=exp_pkg1_payload)

    reader = NocDiReader(dut, dut.clk)
    rcv_pkg = yield reader.receive_packet(set_ready=True)

    if not rcv_pkg:
        raise TestFailure("No packet 1 generated!")

    if not rcv_pkg.equal_to(dut, exp_pkg):
        raise TestFailure("Received packet 1 doesn't match expected packet. "
                          "Got %s, expected %s" % (str(rcv_pkg), str(exp_pkg)))

    # packet 2
    yield RisingEdge(dut.clk)
    exp_pkg2_payload = [data_bytes[i+1] << 8 | data_bytes[i] for i in range(payload_words_per_pkg * 2, payload_bytes, 2)]
    exp_pkg = DiPacket()
    exp_pkg.set_contents(dest=SENDER_DI_ADDRESS,
                         src=MODULE_DI_ADDRESS,
                         type=DiPacket.TYPE.EVENT,
                         type_sub=0,
                         payload=exp_pkg2_payload)

    reader = NocDiReader(dut, dut.clk)
    rcv_pkg = yield reader.receive_packet(set_ready=True)

    if not rcv_pkg:
        raise TestFailure("No packet 2 generated!")

    if not rcv_pkg.equal_to(dut, exp_pkg):
        raise TestFailure("Received packet 2 doesn't match expected packet. "
                          "Got %s, expected %s" % (str(rcv_pkg), str(exp_pkg)))

    # check if the DUT is ready for the next event transfer
    if not dut.event_consumed.value:
        raise TestFailure("DUT does not indicate that the event has been "
                          "consumed.")