コード例 #1
0
def packets_read(dut, axis_reader, pkts_ref, check_timing):
    """Check DuT output for correctness."""
    p = None
    for i, (pkt_ref, inter_packet_cycles_ref) in enumerate(pkts_ref):
        # read AXI4-Stream data
        (tdata, tkeep, _) = yield axis_reader.read()

        # convert AXI4-Stream data to scapy packet
        pkt = axis_data_to_packet(tdata, tkeep, AXIS_BIT_WIDTH)

        # make sure packets match
        if str(pkt) != str(pkt_ref):
            raise cocotb.result.TestFailure("Packet #%d: wrong data" % i)

        # get cycles since between transmissions
        cycles_transmission = cntr_cycles_between_axis_transmission

        if check_timing and i > 0 \
                and cntr_cycles_between_axis_transmission != p:
            raise cocotb.result.TestFailure(
                ("Packet #%d: wrong timing, " + "Cycles IS: %d " +
                 "Cycles Expected %d ") % (i, cycles_transmission, p))

        p = inter_packet_cycles_ref

        # print progress
        print_progress(i, N_PACKETS)
コード例 #2
0
def packets_read(dut, axis_reader, pkts_ref, timestamps):
    """Evaluate data at DuT output and validate correct behavior."""
    # read as many packets as we originally generated
    for i, pkt_ref in enumerate(pkts_ref):
        # read axi stream data
        (tdata, tkeep, _) = yield axis_reader.read()

        # convert axi stream data to scapy packet
        pkt = axis_data_to_packet(tdata, tkeep, AXIS_BIT_WIDTH)

        # check if sent and received packets match and if (possibly) inserted
        # timestamps match
        if int(dut.mode_i) == MODE_DISABLED:
            # timestamping is disabled, received and sent packets must be
            # identical
            valid = str(pkt) == str(pkt_ref)
        elif int(dut.mode_i) == MODE_HEADER:
            # timestamp is located in packet header
            valid = validate_packet_timestamp_header(pkt_ref, pkt,
                                                     timestamps[i])
        elif int(dut.mode_i) == MODE_FIXED_POS:
            # timestamp is loacted at fixed byte position
            valid = validate_packet_timestamp_fixed(dut, pkt_ref, pkt,
                                                    timestamps[i])
        else:
            # this should never happen
            assert False

        if not valid:
            raise cocotb.result.TestFailure(
                ("Packet #%d: received invalid " + "packet data or timestamp")
                % i)

        # print progress
        print_progress(i, N_PACKETS)
コード例 #3
0
def packets_read(dut, axis_reader, pkts_ref):
    """Evaluate correct packet data at DuT output."""
    # we must read as many packets as we appyed at the input
    for i, pkt_ref in enumerate(pkts_ref):
        # read AXI4-Stream data
        (tdata, tkeep, tuser) = yield axis_reader.read()

        # convert AXI4-Stream data to scapy packet
        pkt = axis_data_to_packet(tdata, tkeep, AXIS_BIT_WIDTH)

        # make sure read packet matches the one we expected
        if str(pkt) != str(pkt_ref):
            raise cocotb.result.TestFailure(("Packet #%d: read invalid " +
                                             "packet data") % i)

        # make sure that all TUSER values except the last one are set to zero
        if any(v != 0 for v in tuser[1:len(tuser)-1]):
            raise cocotb.result.TestFailure(("Packet #%d: invalid TUSER " +
                                             "value (!= 0)") % i)

        # the 25 LSB of the last TUSER value must match the value we applied on
        # the input
        if tuser[-1] & 0x1FFFFFF != TUSER_LSB:
            raise cocotb.result.TestFailure(("Packet #%d: invalid TUSER " +
                                             "value (!= input)") % i)

        # print progress
        print_progress(i, N_PACKETS)

        # inter-packet time is a relative number. start evaluation with second
        # packet
        if i == 0:
            continue

        # extract inter-packet time from TUSER
        inter_packet_cycles = tuser[len(tuser)-1] >> 25

        # get the expected inter-packet time from FIFO
        inter_packet_cycles_ref = inter_packet_cycles_monitor.pop(0)

        # make sure the extracted inter-packet time matches the one monitored
        # on the DuT output
        if inter_packet_cycles != inter_packet_cycles_ref:
            raise cocotb.result.TestFailure(("Packet #%d: invalid " +
                                             "inter-packet time " +
                                             "(Expected: %d, Is: %d)") %
                                            (i, inter_packet_cycles_ref,
                                             inter_packet_cycles))
コード例 #4
0
def frames_read(dut, axis_reader, frames_ref):
    """Evaluate data at DuT output and validates correct behavior."""
    # iterate over the list of frames that we are expecting to read
    for i, frame_ref in enumerate(frames_ref):
        # read AXI4-Stream data
        (tdata, tkeep, _) = yield axis_reader.read()

        # convert AXI4-Stream data to scapy frame
        frame = axis_data_to_packet(tdata, tkeep, AXIS_BIT_WIDTH)

        # check if written and read frames are equal
        if str(frame) != str(frame_ref):
            raise cocotb.result.TestFailure("Frame #%d: invalid data" % i)

        # print progress
        print_progress(i, N_FRAMES)
コード例 #5
0
def check_output(dut, trace, axis_reader):
    """Check whether the DUT output is the one that is expected.

    Based on a given trace replay file, the coroutine constructs the expected
    output behavior of the DUT and compares it to the actual values.
    """
    # get trace size
    trace_size = trace.size()

    # initialize address used to index memory-mapped trace file
    addr = 0

    while addr < trace_size:
        # read 8 byte from trace file. contains packet meta data
        meta = trace.read_reverse_byte_order(addr, 8)
        addr += 8

        if meta == 2**64 - 1:
            # the overall trace data has to be 512 bit aligned. If the actual
            # trace size is smaller, we can add padding at the end of the
            # trace (in multiples of 64 bit words). all bits of the padding
            # data have to be set to 1
            continue

        # extract meta data
        meta_delta_t = meta & 2**32 - 1
        meta_len_snap = (meta >> 32) & 2**11 - 1
        meta_len_wire = (meta >> 48) & 2**11 - 1

        # read packet data from trace file
        data = trace.read(addr, meta_len_snap)

        # increase address. packet data is aligned to 8 byte aligned
        if meta_len_snap % 8 == 0:
            addr += meta_len_snap
        else:
            addr += 8 * (meta_len_snap / 8 + 1)

        # if number of bytes on the wire is larger than the number of snap
        # bytes, add zero bytes as padding
        for _ in range(meta_len_wire - meta_len_snap):
            data <<= 8

        # create reference ethernet frame from the read data
        data = "%x" % data
        data = data.zfill(meta_len_wire)
        frame_ref = Ether(binascii.unhexlify(data))

        # read arriving frame from AXI4-Stream
        (tdata, tkeep, tuser) = yield axis_reader.read()

        # convert AXI4-Stream data to ethernet frame
        frame_recv = axis_data_to_packet(tdata, tkeep, AXIS_BIT_WIDTH)

        # make sure frames match
        if str(frame_ref) != str(frame_recv):
            raise cocotb.result.TestFailure("received wrong data")

        # inter-packet time is located in first tuser word
        meta_delta_t_recv = tuser[0] & 2**32 - 1

        # make sure the inter-packet time matches the expected one
        if meta_delta_t != meta_delta_t_recv:
            raise cocotb.result.TestFailure("wrong timing information")

        # all other tuser fields must be set to zero
        if any(v != 0 for v in tuser[2:]):
            raise cocotb.result.TestFailure("invalid tuser data")

    # wait some more cycles after last packet. there should not be any data on
    # the axi stream anymore
    for _ in range(1000):
        yield RisingEdge(dut.clk)
        check_value("m_axis_tvalid", dut.m_axis_tvalid, 0)
コード例 #6
0
def packets_read(dut, axis_reader, pkts_ref, timestamps_ref):
    """Evaluate data at DuT output and validate correct behavior."""
    # read as many packets as we originally generated
    for i, pkt_ref in enumerate(pkts_ref):
        # read AXI4-Stream data
        (tdata, tkeep, tuser) = yield axis_reader.read()

        # print progress
        print_progress(i, N_PACKETS)

        # convert AXI4-Stream data to scapy packet
        pkt = axis_data_to_packet(tdata, tkeep, AXIS_BIT_WIDTH)

        # make sure received packet matches expected packet
        if str(pkt) != str(pkt_ref):
            raise cocotb.result.TestFailure(
                ("Packet #%d: received invalid " + "packet data") % i)

        # make sure that all tuser values except the last one are set to zero
        if any(v != 0 for v in tuser[1:-1]):
            raise cocotb.result.TestFailure("Packet #%d: invalid TUSER value" %
                                            i)

        if int(dut.mode_i) == MODE_HEADER:
            # latency timestamp is saved in IP packet header. latency values
            # must be extracted for all IP packets
            if pkt_ref.type == 0x800 or pkt_ref.type == 0x86dd:
                # latency value provided at output?
                latency_valid = tuser[-1] >> 24
                if latency_valid == 0:
                    raise cocotb.result.TestFailure(
                        ("Packet #%d: no " + "latency value in " + "output") %
                        i)

                # get latency value
                latency = tuser[-1] & 0xFFFFFF

                # calculate reference latency
                timestamp_cur = int(dut.timestamp_i) & 0xFFFF
                if timestamp_cur > timestamps_ref[i]:
                    latency_ref = timestamp_cur - timestamps_ref[i]
                else:
                    latency_ref = 0xFFFF - timestamps_ref[i] + \
                        timestamp_cur + 1

                # make sure latency values match
                if latency != latency_ref:
                    raise cocotb.result.TestFailure(
                        ("Packet #%d: wrong " + "latency value") % i)

            else:
                # non latency value must be provided on output for non-IP
                # packets
                if tuser[-1] != 0:
                    raise cocotb.result.TestFailure(
                        ("Packet #%d: latency " + "value on output") % i)
        elif int(dut.mode_i) == MODE_FIXED_POS:
            # latency timestamp is located at a fixed byte position in the
            # packet

            # is packet long enough to contain a timestamp?
            if int(dut.width_i) == 0:
                # timestamp is 16 bit wide
                if len(pkt_ref) < int(dut.pos_i) + 2:
                    # not long enough, make sure that no latency value is
                    # provided
                    if tuser[-1] != 0:
                        raise cocotb.result.TestFailure(
                            ("Packet #%d: " + "latency value on " + "output") %
                            i)

                    # ensure that we did not generate a timestamp for this
                    # packet
                    assert timestamps_ref[i] is None

                    # nothing more to do for this packet
                    continue
            else:
                # timestamp is 24 bit wide
                if len(pkt_ref) < int(dut.pos_i) + 3:
                    # not long enough, make sure that no latency value is
                    # provided
                    if tuser[-1] != 0:
                        raise cocotb.result.TestFailure(
                            ("Packet #%d: " + "latency value on " + "output") %
                            i)
                    # ensure that we did not generate a timestamp for this
                    # packet
                    assert timestamps_ref[i] is None

                    # nothing more to do for this packet
                    continue

            # make sure latency value is provided at output
            latency_valid = tuser[-1] >> 24
            if latency_valid == 0:
                raise cocotb.result.TestFailure(
                    ("Packet #%d: no " + "latency value in " + "output") % i)

            # get latency value
            latency = tuser[-1] & 0xFFFFFF

            # calculate reference latency
            if int(dut.width_i) == 0:
                # 16 bit timestamp
                timestamp_cur = int(dut.timestamp_i) & 0xFFFF
                if timestamp_cur > timestamps_ref[i]:
                    latency_ref = timestamp_cur - timestamps_ref[i]
                else:
                    latency_ref = 0xFFFF - timestamps_ref[i] + \
                        timestamp_cur + 1
            else:
                # 24 bit timestamp
                timestamp_cur = int(dut.timestamp_i)
                if timestamp_cur > timestamps_ref[i]:
                    latency_ref = timestamp_cur - timestamps_ref[i]
                else:
                    latency_ref = 0xFFFFFF - timestamps_ref[i] + \
                        timestamp_cur + 1

            # make sure latency values match
            if latency != latency_ref:
                raise cocotb.result.TestFailure(
                    ("Packet #%d: wrong " + "latency value") % i)

        elif int(dut.mode_i) == MODE_DISABLED:
            # timestamping is disabled

            # all bits of the last tuser value must be set to zero
            if tuser[-1] != 0:
                raise cocotb.result.TestFailure(("Packet #%d: latency value "
                                                 "in output") % i)
        else:
            # this should never happen
            assert False
コード例 #7
0
def check_data(pkts_ref, latencies_ref, inter_packet_times_ref, data,
               max_len_capture):
    """Check the received data for correctness.

    The function ensures that the data read from the ring buffer (a list of
    512 bit data words) matches the expected meta data (timestamps, wire +
    capture length) and packet data.
    """
    # data word index
    i_data = 0

    # iterate over all packets
    for i_pkt, pkt_ref in enumerate(pkts_ref):
        # determinal actual capture length
        len_capture = min(len(pkt_ref), max_len_capture)

        # data is captured at the granularity of 8 byte words. how many 8 byte
        # words do we have?
        if len_capture % 8 == 0:
            len_capture_words = len_capture / 8
        else:
            len_capture_words = len_capture / 8 + 1

        # initialize empty packet data list
        packet_data = []

        # iterate over captured data words (8 byte each)
        for i in range(len_capture_words + 1):
            # get data word and increment data word index
            d = data[i_data]
            i_data += 1

            # swap byte order
            d = swp_byte_order(d, AXIS_BIT_WIDTH / 8)

            if i == 0:
                # this is meta data
                meta_latency = d & 0xFFFFFF
                meta_latency_valid = (d >> 24) & 0x1
                meta_interpackettime = (d >> 25) & 0xFFFFFFF
                meta_len_wire = (d >> 53) & 0x7FF

                # make sure the latency is marked valid
                if meta_latency_valid != 0x1:
                    raise cocotb.result.TestFailure(
                        ("Packet #%d: " + "Latency value not " + "valid") % i)

                # make sure latency matches reference value
                if latencies_ref[i_pkt] != meta_latency:
                    raise cocotb.result.TestFailure(
                        ("Packet #%d: " + "incorrect latency") % i_pkt)

                # make sure inter-packet time matches reference value
                if inter_packet_times_ref[i_pkt] != meta_interpackettime:
                    raise cocotb.result.TestFailure(
                        ("Packet #%d: " + "incorrect inter-" + "packet time") %
                        i_pkt)
                # make sure wire length matches packet length
                if len(pkt_ref) != meta_len_wire:
                    raise cocotb.result.TestFailure(
                        ("Packet #%d: " + "invalid wire " + "length") % i_pkt)

            else:
                # this is packet data
                packet_data.append(d)

        # create packet from captured data
        if len_capture % 8 == 0:
            pkt = axis_data_to_packet(packet_data, 2**8 - 1, 64)
        else:
            pkt = axis_data_to_packet(packet_data, 2**(len_capture % 8) - 1,
                                      64)

        # make sure packet data matches the exepcted packet data
        if str(pkt)[0:len_capture] != \
                str(pkt_ref)[0:len_capture]:
            raise cocotb.result.TestFailure(
                ("Packet #%d: " + "invalid data") % i_pkt)
コード例 #8
0
def check_output(dut, pkts_ref, latencies_ref, inter_packet_times_ref):
    """Check DuT output for correctness."""
    # check whether capturing is enabled
    enabled = int(dut.active_i) == 1

    if not enabled:
        # packet data capturing is disabled. make sure that the module does not
        # output any data
        pkt_cnt = 0
        while pkt_cnt < len(pkts_ref):
            # the module should not write any data to the FIFOs at all
            yield RisingEdge(dut.clk)
            assert int(dut.fifo_meta_wr_en_o) == 0
            assert int(dut.fifo_data_wr_en_o) == 0
            assert int(dut.pkt_cnt_o) == 0

            if int(dut.s_axis_tvalid) and int(dut.s_axis_tready) and \
                    int(dut.s_axis_tlast):
                # one full packet has been applied at DuT input -> print
                # progress and increment packet counter
                print_progress(pkt_cnt, N_PACKETS)
                pkt_cnt += 1

        # make sure packet counter is still at zero
        check_value("pkt_cnt_o", dut.pkt_cnt_o, 0x0)
    else:
        # packet capture is enabled

        # get the configured maximum capture length
        max_len_capture = int(dut.max_len_capture_i)

        data = []

        # iterate over all reference packets
        for i, pkt_ref in enumerate(pkts_ref):

            # calculate the expected capture length
            meta_len_capture_ref = min(len(pkt_ref), max_len_capture)

            # each data FIFO word is 8 bytes wide, calculate number of data
            # words that shall be written for the captured data
            if meta_len_capture_ref % 8 == 0:
                n_words_ref = meta_len_capture_ref / 8
            else:
                n_words_ref = (meta_len_capture_ref / 8) + 1

            while True:
                yield RisingEdge(dut.clk)

                if int(dut.fifo_meta_wr_en_o):
                    # meta data is written to FIFO in this cycle

                    # get meta data
                    meta_data = int(dut.fifo_meta_din_o)

                    # make sure that the correct number of data words have been
                    # written to the FIFO
                    assert len(data) == n_words_ref

                    # extract meta data
                    meta_latency = meta_data & 0xFFFFFF
                    meta_latency_valid = (meta_data >> 24) & 0x1
                    meta_interpackettime = (meta_data >> 25) & 0xFFFFFFF
                    meta_len_wire = (meta_data >> 53) & 0x7FF
                    meta_len_capture = (meta_data >> 64) & 0x7FF

                    # make sure the latency is marked valid
                    if meta_latency_valid != 0x1:
                        raise cocotb.result.TestFailure(("Packet #%d: " +
                                                         "Latency value not " +
                                                         "valid") % i)

                    # make sure latency matches reference value
                    if latencies_ref[i] != meta_latency:
                        raise cocotb.result.TestFailure(("Packet #%d: " +
                                                         "incorrect latency") %
                                                        i)

                    # make sure inter-packet time matches reference value
                    if inter_packet_times_ref[i] != meta_interpackettime:
                        raise cocotb.result.TestFailure(("Packet #%d: " +
                                                         "incorrect inter-" +
                                                         "packet time") % i)
                    # make sure wire length matches packet length
                    if len(pkt_ref) != meta_len_wire:
                        raise cocotb.result.TestFailure(("Packet #%d: " +
                                                         "invalid wire " +
                                                         "length") % i)

                    # make sure capture length matches expected value
                    if meta_len_capture != meta_len_capture_ref:
                        raise cocotb.result.TestFailure(("Packet #%d: " +
                                                         "invalid capture" +
                                                         "length") % i)

                    # create packet from captured data
                    if meta_len_capture % (DATAPATH_BIT_WIDTH/8) == 0:
                        pkt = axis_data_to_packet(data,
                                                  2**(DATAPATH_BIT_WIDTH/8)-1,
                                                  DATAPATH_BIT_WIDTH)
                    else:
                        pkt = axis_data_to_packet(data,
                                                  2**(meta_len_capture % 8)-1,
                                                  DATAPATH_BIT_WIDTH)

                    # make sure packet data matches the exepcted packet data
                    if str(pkt)[0:meta_len_capture] != \
                            str(pkt_ref)[0:meta_len_capture]:
                        raise cocotb.result.TestFailure(("Packet #%d: " +
                                                         "invalid data") % i)

                    # delete captured data
                    data = []

                if int(dut.fifo_data_wr_en_o):
                    # data is being written to the data FIFO
                    data.append(int(dut.fifo_data_din_o))

                if int(dut.fifo_meta_wr_en_o):
                    # meta data has been written and checked -> we are done for
                    # this packet.
                    print_progress(i, N_PACKETS)
                    break

        # make sure packet counter value is correct
        check_value("pkt_cnt_o", dut.pkt_cnt_o, len(pkts_ref))

    # make sure no errors are flagged by the DuT
    check_value("err_data_fifo_full_o", dut.err_data_fifo_full_o, 0x0)
    check_value("err_meta_fifo_full_o", dut.err_meta_fifo_full_o, 0x0)
コード例 #9
0
def check_output(dut, pkts_ref, latencies_ref, inter_packet_times_ref):
    """Check DuT output for correctness."""
    # check whether capturing is enabled
    enabled = int(dut.active_i) == 1

    if not enabled:
        # packet data capturing is disabled. make sure that the module does not
        # output any data
        pkt_cnt = 0
        while pkt_cnt < len(pkts_ref):
            # the module should not write any data to the output FIFO at all
            yield RisingEdge(dut.clk)
            assert int(dut.fifo_wr_en_o) == 0
            assert int(dut.pkt_cnt_o) == 0

            if int(dut.s_axis_tvalid) and int(dut.s_axis_tready) and \
                    int(dut.s_axis_tlast):
                # one full packet has been applied at DuT input -> print
                # progress and increment packet counter
                print_progress(pkt_cnt, N_PACKETS)
                pkt_cnt += 1

            if pkt_cnt == len(pkts_ref):
                # all packets have been applied -> done!
                break

        # make sure packet counter is still at zero
        check_value("pkt_cnt_o", dut.pkt_cnt_o, 0x0)

    else:
        # packet capture is enabled

        # get the configured maximum capture length
        max_len_capture = int(dut.max_len_capture_i)

        # iterate over all reference packets
        for i, pkt_ref in enumerate(pkts_ref):

            # get the packet's capture length
            len_capture = min(len(pkt_ref), max_len_capture)

            # wait for fifo write output signal to become high
            while True:
                yield RisingEdge(dut.clk)
                if int(dut.fifo_wr_en_o):
                    break

            # get meta data
            meta_data = int(dut.fifo_din_o)

            # extract meta data
            meta_latency = meta_data & 0xFFFFFF
            meta_latency_valid = (meta_data >> 24) & 0x1
            meta_interpackettime = (meta_data >> 25) & 0xFFFFFFF
            meta_len_wire = (meta_data >> 53) & 0x7FF

            # make sure the latency is marked valid
            if meta_latency_valid != 0x1:
                raise cocotb.result.TestFailure(
                    ("Packet #%d: " + "Latency value not " + "valid") % i)

            if latencies_ref[i] != meta_latency:
                raise cocotb.result.TestFailure(
                    ("Packet #%d: " + "incorrect latency") % i)

            # make sure inter-packet time matches reference value
            if inter_packet_times_ref[i] != meta_interpackettime:
                raise cocotb.result.TestFailure(
                    ("Packet #%d: " + "incorrect inter-" + "packet time") % i)
            # make sure wire length matches packet length
            if len(pkt_ref) != meta_len_wire:
                raise cocotb.result.TestFailure(
                    ("Packet #%d: " + "invalid wire " + "length") % i)

            # calculate number of 8 byte packet data words
            if len_capture % 8 == 0:
                len_capture_words = len_capture / 8
            else:
                len_capture_words = len_capture / 8 + 1

            # read as many data words as specified by capture length
            data = []
            for _ in range(len_capture_words):
                # wait for FIFO write output signal to become high
                while True:
                    yield RisingEdge(dut.clk)
                    if int(dut.fifo_wr_en_o):
                        break

                # read data word
                data.append(int(dut.fifo_din_o))

            # create packet from captured data
            if len_capture % (DATAPATH_BIT_WIDTH / 8) == 0:
                pkt = axis_data_to_packet(data,
                                          2**(DATAPATH_BIT_WIDTH / 8) - 1,
                                          DATAPATH_BIT_WIDTH)
            else:
                pkt = axis_data_to_packet(data, 2**(len_capture % 8) - 1,
                                          DATAPATH_BIT_WIDTH)

            # make sure packet data matches the exepcted packet data
            if str(pkt)[0:len_capture] != \
                    str(pkt_ref)[0:len_capture]:
                raise cocotb.result.TestFailure(
                    ("Packet #%d:" + "invalid data") % i)

            # print progress
            print_progress(i, N_PACKETS)

        # make sure packet counter value is correct
        check_value("pkt_cnt_o", dut.pkt_cnt_o, len(pkts_ref))

    # make sure no errors are flagged by the DuT
    check_value("err_data_fifo_full_o", dut.err_data_fifo_full_o, 0x0)
    check_value("err_meta_fifo_full_o", dut.err_meta_fifo_full_o, 0x0)