Ejemplo n.º 1
0
def nt_timestamp_test(dut):
    """Main test bench function.

    TODO: no automatic validation of DUT output yet. Look at waveforms.
    """
    # start the clock
    cocotb.fork(clk_gen(dut.clk156, CLK_FREQ_MHZ))

    # reset dut
    yield rstn(dut.clk156, dut.rstn156)

    # create axi lite writer, connect and reset
    axi_writer = AXI_Lite_Writer()
    axi_writer.connect(dut, dut.clk156, AXI_DATA_WIDTH, "ctrl")
    yield axi_writer.rst()

    # run simulation for a while
    yield wait_n_cycles(dut.clk156, 1000)

    # set number of clock cycles which shall pass until counter is incremented
    # to 10
    yield axi_writer.write(CPUREG_OFFSET_CTRL_CYCLES_PER_TICK, 10)

    # run simulation for a while
    yield wait_n_cycles(dut.clk156, 1000)
Ejemplo n.º 2
0
def nt_recv_filter_mac_top_test(dut):
    """Test bench main function."""
    # start the clock
    cocotb.fork(clk_gen(dut.clk, CLK_FREQ_MHZ))

    # no software reset
    dut.rst_sw <= 0

    # reset the dut
    yield rstn(dut.clk, dut.rstn)

    # create, connect and reset AXI4-Lite writer
    axi_lite_writer = AXI_Lite_Writer()
    axi_lite_writer.connect(dut, dut.clk, AXI_CTRL_BIT_WIDTH, "ctrl")
    yield axi_lite_writer.rst()

    # create and reset AXI4-Stream writer
    axis_writer = AXIS_Writer()
    axis_writer.connect(dut, dut.clk, AXIS_BIT_WIDTH)
    yield axis_writer.rst()

    # create and reset AXI4-Stream reader
    axis_reader = AXIS_Reader()
    axis_reader.connect(dut, dut.clk, AXIS_BIT_WIDTH)
    yield axis_reader.rst()

    # start random toggling of axi stream reader tready
    cocotb.fork(toggle_signal(dut.clk, dut.m_axis_tready))

    # perform a set of test. each run will generate its own random mac
    # addresses
    for i in range(N_RUNS):
        print("Test %d/%d" % (i + 1, N_RUNS))
        yield perform_test(dut, axi_lite_writer, axis_writer, axis_reader)
Ejemplo n.º 3
0
def nt_recv_capture_rx_test(dut):
    """Test bench main function."""
    # start the clock
    cocotb.fork(clk_gen(dut.clk, CLK_FREQ_MHZ))

    # do not issue software reset
    dut.rst_sw <= 0

    # reset the dut
    yield rstn(dut.clk, dut.rstn)

    # instantiate an AXI4-Stream writer, connect and reset it
    axis_writer = AXIS_Writer()
    axis_writer.connect(dut, dut.clk, DATAPATH_BIT_WIDTH)
    yield axis_writer.rst()

    # generate a couple of random Ethernet packets. For each packet, generate
    # a 16 bit latency value and a 26 bit inter-packet time value
    pkts = []
    latencies = []
    inter_packet_times = []
    for _ in range(N_PACKETS):
        pkts.append(gen_packet())
        latencies.append(randint(0, 2**24-1))
        inter_packet_times.append(randint(0, 2**28-1))

    # meta and data FIFOs never become full
    dut.fifo_meta_full_i <= 0
    dut.fifo_data_full_i <= 0

    # test 0: capture disabled
    print("Performing test 1/%d" % (N_REPEATS+3))
    yield perform_test(dut, axis_writer, pkts, latencies, inter_packet_times,
                       False, 0)

    # test 1: max capture size: 1514 byte
    print("Performing test 2/%d" % (N_REPEATS+3))
    yield perform_test(dut, axis_writer, pkts, latencies, inter_packet_times,
                       True, 1514)

    # test 2: max capture size: 0 byte
    print("Performing test 3/%d" % (N_REPEATS+3))
    yield perform_test(dut, axis_writer, pkts, latencies, inter_packet_times,
                       True, 0)

    # perform some more tests for random capture sizes
    for i in range(N_REPEATS):
        print("Performing test %d/%d" % (3+i, N_REPEATS+3))
        yield perform_test(dut, axis_writer, pkts, latencies,
                           inter_packet_times, True, randint(64, 1514))
def nt_recv_capture_mem_write_fifo_wrapper_test(dut):
    """Test bench main function."""
    # start the clock
    cocotb.fork(clk_gen(dut.clk, CLK_FREQ_MHZ))

    # do not issue software reset
    dut.rst_sw <= 0

    # initially we do not read or write data to the FIFO
    dut.rd_en_i <= 0
    dut.wr_en_i <= 0

    # initially do not add alignment data
    dut.align_i <= 0

    # reset the dut
    yield rstn(dut.clk, dut.rstn)

    # wait a few cycles
    yield wait_n_cycles(dut.clk, 10)

    for i, n_words in enumerate(N_INPUT_WORDS):
        print("Test %d/%d" % (i + 1, len(N_INPUT_WORDS)))

        # generate 64 bit input data
        data64 = gen_input_data(n_words)

        # convert 64 bit input data to 512 bit output data
        data512 = convert_data_64_to_512(data64)

        # start input coroutine
        coroutine_in = cocotb.fork(apply_input(dut, data64))

        # start ouput coroutine
        coroutine_out = cocotb.fork(check_output(dut, data512))

        # start one coroutine for triggering aligment
        coroutine_align = cocotb.fork(trigger_align(dut, data64))

        # wait for coroutines to complete
        yield coroutine_in.join()
        yield coroutine_out.join()
        yield coroutine_align.join()
def nt_recv_interpackettime_test(dut):
    """Test bench main function."""
    # start the clock
    cocotb.fork(clk_gen(dut.clk156, CLK_FREQ_MHZ))

    # no software reset
    dut.rst_sw156 <= 0

    # reset the DuT
    yield rstn(dut.clk156, dut.rstn156)

    # create an AXI4-Stream reader, connect and reset it
    axis_reader = AXIS_Reader()
    axis_reader.connect(dut, dut.clk156, AXIS_BIT_WIDTH)
    yield axis_reader.rst()

    # create an AXI4-Stream writer, connect and reset it
    axis_writer = AXIS_Writer()
    axis_writer.connect(dut, dut.clk156, AXIS_BIT_WIDTH)
    yield axis_writer.rst()

    # generate some random packets
    pkts = []
    for _ in range(N_PACKETS):
        pkts.append(gen_packet())

    # start random toggling of AXI4-Stream reader TREADY
    cocotb.fork(toggle_signal(dut.clk156, dut.m_axis_tready))

    # start one coroutine to apply packets on DuT input
    cocotb.fork(packets_write(dut, axis_writer, pkts))

    # start one coroutine to read packets on DuT output
    coroutine_read = cocotb.fork(packets_read(dut, axis_reader, pkts))

    # start one coroutine that monitors inter-packet times
    cocotb.fork(monitor_inter_packet_time(dut))

    # wait for coroutines to complete
    yield coroutine_read.join()
def nt_recv_capture_fifo_merge(dut):
    """Test bench main function."""
    # start the clock
    cocotb.fork(clk_gen(dut.clk, CLK_FREQ_MHZ))

    # do not issue software reset
    dut.rst_sw <= 0

    # output fifo is never full
    dut.fifo_full_i <= 0

    # intially not writing to input fifos
    dut.fifo_meta_wr_en_i <= 0
    dut.fifo_data_wr_en_i <= 0

    # reset the dut
    yield rstn(dut.clk, dut.rstn)

    # wait a few cycles
    yield wait_n_cycles(dut.clk, 5)

    for i in range(N_REPEATS):
        # print out some status
        print("Test %d/%d" % (i+1, N_REPEATS))

        # determine random maximum capture length
        max_len_capture = random.randint(0, 1514)

        # generate packet and meta data
        (meta, data) = gen_input_data(max_len_capture)

        # start stimulus coroutine
        cocotb.fork(apply_input(dut, meta, data))

        # start coroutine checking output
        coroutine_chk = cocotb.fork(check_output(dut, meta, data,
                                                 max_len_capture))

        # wat for checking coroutine to complete
        yield coroutine_chk.join()
Ejemplo n.º 7
0
def nt_gen_replay_top_test(dut):
    """Test bench main function."""
    # start the clock
    cocotb.fork(clk_gen(dut.clk, CLK_FREQ_MHZ))

    # no software reset
    dut.rst_sw <= 0

    # reset dut
    yield rstn(dut.clk, dut.rstn)

    # open trace file
    trace = File("files/random.file")

    # get trace file size
    trace_size = trace.size()

    # trace file must be a multiple of the AXI data width
    if trace.size() % (AXI_MEM_BIT_WIDTH / 8) != 0:
        raise cocotb.result.TestFailure("invalid trace size")

    # calculate ring buffer sizes
    ring_buff_sizes = []
    for ring_buff_size in RING_BUFF_SIZES:
        # size of ring buffer is determined by multiplying the size factor by
        # the size of the trace
        ring_buff_size = int(ring_buff_size * trace_size)

        # make sure that the ring buffer size is multiple of AXI data width
        if ring_buff_size % (AXI_MEM_BIT_WIDTH / 8) != 0:
            ring_buff_size += AXI_MEM_BIT_WIDTH/8 - \
                    ring_buff_size % (AXI_MEM_BIT_WIDTH/8)
        ring_buff_sizes.append(ring_buff_size)

    # create a ring buffer memory (initially of size 0) and connect it to the
    # DUT
    ring_buff = Mem(0)
    ring_buff.connect(dut, "ddr3")

    # create axi lite writer, connect and reset
    axi_lite_writer = AXI_Lite_Writer()
    axi_lite_writer.connect(dut, dut.clk, AXI_LITE_BIT_WIDTH, "ctrl")
    yield axi_lite_writer.rst()

    # create axi lite reader, connect and reset
    axi_lite_reader = AXI_Lite_Reader()
    axi_lite_reader.connect(dut, dut.clk, AXI_LITE_BIT_WIDTH, "ctrl")
    yield axi_lite_reader.rst()

    # create axi stream reader, connect and reset
    axis_reader = AXIS_Reader()
    axis_reader.connect(dut, dut.clk, AXIS_BIT_WIDTH)
    yield axis_reader.rst()

    # start the ring buffer memory main routine
    cocotb.fork(ring_buff.main())

    # toggle m_axis_tready
    cocotb.fork(toggle_signal(dut.clk, dut.m_axis_tready))

    # iterate over all ring buffer sizes
    for i, ring_buff_size in enumerate(ring_buff_sizes):

        # set ring buffer size
        ring_buff.set_size(ring_buff_size)

        # iterate over all addresses where ring buffer shall be located in
        # memory
        for j, ring_buff_addr in enumerate(RING_BUFF_ADDRS):

            # print status
            print("Test %d/%d" % (i * len(RING_BUFF_ADDRS) + j + 1,
                                  len(RING_BUFF_ADDRS) * len(RING_BUFF_SIZES)))

            print("Ring Buff Addr: 0x%x, Size: %d" %
                  (ring_buff_addr, ring_buff_size))

            # we have a total of 8 GByte of memory. Make sure the ring buffer
            # fits at the desired address
            if ring_buff_addr + ring_buff_size > 0x1FFFFFFFF:
                raise cocotb.result.TestFailure("ring buffer is too large")

            # to reduce the simulation memory footprint, provide the memory
            # module the first memory address that we acutally care about
            ring_buff.set_offset(ring_buff_addr)

            # configure ring buffer memory location
            yield axi_lite_writer.write(CPUREG_OFFSET_CTRL_MEM_ADDR_HI,
                                        ring_buff_addr >> 32)
            yield axi_lite_writer.write(CPUREG_OFFSET_CTRL_MEM_ADDR_LO,
                                        ring_buff_addr & 0xFFFFFFFF)

            # configure ring buffer address range
            yield axi_lite_writer.write(CPUREG_OFFSET_CTRL_MEM_RANGE,
                                        ring_buff_size - 1)

            # configure trace size
            yield axi_lite_writer.write(CPUREG_OFFSET_CTRL_TRACE_SIZE_HI,
                                        trace_size >> 32)
            yield axi_lite_writer.write(CPUREG_OFFSET_CTRL_TRACE_SIZE_LO,
                                        trace_size & 0xFFFFFFFF)

            # reset write address pointer
            yield axi_lite_writer.write(CPUREG_OFFSET_CTRL_ADDR_WR, 0x0)

            # make sure module initially is inactive
            status = yield axi_lite_reader.read(CPUREG_OFFSET_STATUS)
            if status & 0x3 != 0:
                raise cocotb.reset.TestFailure("module is active")

            # start the module
            yield axi_lite_writer.write(CPUREG_OFFSET_CTRL_START, 0x1)

            # wait a few cycles
            yield wait_n_cycles(dut.clk, 10)

            # start writing the ring buffer
            cocotb.fork(
                ring_buff_write(dut, ring_buff, trace, ring_buff_addr,
                                axi_lite_reader, axi_lite_writer))

            # start coroutine that checks dut output
            coroutine_chk_out = cocotb.fork(
                check_output(dut, trace, axis_reader))

            # wait a few cycles and make sure module is active
            yield wait_n_cycles(dut.clk, 10)
            status = yield axi_lite_reader.read(CPUREG_OFFSET_STATUS)
            if status & 0x1 == 0x0:
                raise cocotb.result.TestFailure("mem read not active")
            if status & 0x2 == 0x0:
                raise cocotb.result.TestFailure("packet assembly not active")

            # wait for output check to complete
            yield coroutine_chk_out.join()

            # wait a few cycles
            yield wait_n_cycles(dut.clk, 10)

            # make sure module is now inactive
            status = yield axi_lite_reader.read(CPUREG_OFFSET_STATUS)
            if status & 0x3 != 0x0:
                raise cocotb.result.TestFailure("module does not become " +
                                                "inactive")

            # clear the ring buffer contents
            ring_buff.clear()

    # close the trace file
    trace.close()
Ejemplo n.º 8
0
def nt_gen_timestamp_insert_test(dut):
    """Test bench main function."""
    # start the clock
    cocotb.fork(clk_gen(dut.clk156, CLK_FREQ_MHZ))

    # no software reset
    dut.rst_sw156 <= 0

    # reset the dut
    yield rstn(dut.clk156, dut.rstn156)

    # create an axi stream writer, connect it and reset if
    axis_writer = AXIS_Writer()
    axis_writer.connect(dut, dut.clk156, AXIS_BIT_WIDTH)
    yield axis_writer.rst()

    # create an axi stream reader, connect it and reset if
    axis_reader = AXIS_Reader()
    axis_reader.connect(dut, dut.clk156, AXIS_BIT_WIDTH)
    yield axis_reader.rst()

    # start the timestamp counter
    cocotb.fork(timestamp_counter(dut))

    # generate some ip packets
    pkts = []
    for _ in range(N_PACKETS):
        pkts.append(gen_packet())

    # initially we insert timestamps in the packet headers
    dut.mode_i <= MODE_HEADER

    print("Test Timestamp Header")
    yield perform_test(dut, axis_writer, axis_reader, pkts)

    # then we perform one test where we do not insert any timestamps at all
    dut.mode_i <= MODE_DISABLED

    print("Test Timestamp Disabled")
    yield perform_test(dut, axis_writer, axis_reader, pkts)

    # next run some random tests with timestamp inserted at fixed byte position
    for i in range(N_REPEATS):
        # generate some ip packets
        pkts = []
        for _ in range(N_PACKETS):
            pkts.append(gen_packet())

        # fixed byte position
        dut.mode_i <= MODE_FIXED_POS

        # randomly choose 16 bit or 24 bit timestamp width
        width = randint(0, 1)

        # find valid timestamp positions
        while True:
            pos = randint(0, 1518)
            if width == 0 and (pos % 8) < 7:
                break
            elif width == 1 and (pos % 8) < 6:
                break

        # set timestamp position and width
        dut.pos_i <= pos
        dut.width_i <= width

        # perform the test
        print("Test Timestamp Fixed Pos %d/%d (Pos: %d, Width: %d)" %
              (i + 1, N_REPEATS, pos, width))
        yield perform_test(dut, axis_writer, axis_reader, pkts)
Ejemplo n.º 9
0
def nt_recv_latency_test(dut):
    """Test bench main function."""
    # start the clock
    cocotb.fork(clk_gen(dut.clk156, CLK_FREQ_MHZ))

    # no software reset
    dut.rst_sw156 <= 0

    # reset the dut
    yield rstn(dut.clk156, dut.rstn156)

    # create an AXI4-Stream reader, connect and reset it
    axis_reader = AXIS_Reader()
    axis_reader.connect(dut, dut.clk156, AXIS_BIT_WIDTH)
    yield axis_reader.rst()

    # create an AXI4-Stream writer, connect and reset it
    axis_writer = AXIS_Writer()
    axis_writer.connect(dut, dut.clk156, AXIS_BIT_WIDTH)
    yield axis_writer.rst()

    # start random toggling of AXI4-Stream reader TREADY
    cocotb.fork(toggle_signal(dut.clk156, dut.m_axis_tready))

    # set current timestamp to be static at 8421376
    dut.timestamp_i <= 8421376
    yield RisingEdge(dut.clk156)

    # generate 70% of N_PACKETS IP packets and insert random timestamp in
    # packet header
    n_packets_ip = int(0.7 * N_PACKETS)
    pkts = []
    timestamps = []
    for _ in range(n_packets_ip):
        pkt = gen_packet()
        packet_insert_random_timestamp_header(pkt, timestamps)
        pkts.append(pkt)

    # then generate 30% of N_PACKETS non-IP packets. no timestamp will be
    # inserted
    for _ in range(N_PACKETS - n_packets_ip):
        pkt = gen_packet(eth_only=True)
        pkts.append(pkt)
        timestamps.append(None)

    # shuffle pkt and timestamp lists (in same order)
    tmp = list(zip(pkts, timestamps))
    shuffle(tmp)
    pkts, timestamps = zip(*tmp)

    # we inserted timestamps in packet header
    dut.mode_i <= MODE_HEADER

    print("Test Timestamp Header")
    yield perform_test(dut, axis_writer, axis_reader, pkts, timestamps)

    # perform another test where timestamping is disabled
    dut.mode_i <= MODE_DISABLED

    print("Test Timestamp Disabled")
    yield perform_test(dut, axis_writer, axis_reader, pkts, timestamps)

    # next run some random tests with timestamp inserted at fixed byte position
    for i in range(N_REPEATS):
        # fixed byte position
        dut.mode_i <= MODE_FIXED_POS

        # randomly choose 16 bit or 24 bit timestamp width
        width = randint(0, 1)

        # find valid timestamp positions
        while True:
            pos = randint(0, 1518)
            if width == 0 and (pos % 8) < 7:
                break
            elif width == 1 and (pos % 8) < 6:
                break

        # set timestamp position and width
        dut.pos_i <= pos
        dut.width_i <= width

        # generate some ip packets and insert random timestamps
        pkts = []
        timestamps = []
        for _ in range(N_PACKETS):
            pkt = gen_packet()
            pkt = packet_insert_random_timestamp_fixed(pkt, timestamps, pos,
                                                       width)
            pkts.append(pkt)

        # perform the test
        print("Test Timestamp Fixed Pos %d/%d (Pos: %d, Width: %d)" %
              (i + 1, N_REPEATS, pos, width))
        yield perform_test(dut, axis_writer, axis_reader, pkts, timestamps)
def nt_gen_rate_ctrl_top_test(dut):
    """Test bench main function."""
    # initially module is inactive
    dut.active_i <= 0

    # no software reset
    dut.rst_sw156 <= 0

    # start the clock
    cocotb.fork(clk_gen(dut.clk156, CLK_FREQ_MHZ))

    # reset the DuT
    yield rstn(dut.clk156, dut.rstn156)

    # create AXI4-Stream writer and reader
    axis_writer = AXIS_Writer()
    axis_writer.connect(dut, dut.clk156, AXIS_BIT_WIDTH)
    yield axis_writer.rst()

    axis_reader = AXIS_Reader()
    axis_reader.connect(dut, dut.clk156, AXIS_BIT_WIDTH)
    yield axis_reader.rst()

    # create AXI4-Lite writer and connect to DuT
    axi_lite_writer = AXI_Lite_Writer()
    axi_lite_writer.connect(dut, dut.clk156, AXI_CTRL_BIT_WIDTH, "ctrl")
    yield axi_lite_writer.rst()

    # create AXI4-Lite reader and connect to DuT
    axi_lite_reader = AXI_Lite_Reader()
    axi_lite_reader.connect(dut, dut.clk156, AXI_CTRL_BIT_WIDTH, "ctrl")
    yield axi_lite_reader.rst()

    # initially we are always ready to receive
    dut.m_axis_tready <= 1

    # start a coroutine that counts the number of cycles between two packets
    # on the output axi stream
    cocotb.fork(count_cycles_between_axis_transmission(dut))

    print("Test 1/4")

    # generate some packets and inter-packet times. we start with a constant
    # inter-packet time of 200 cycles, more than enough to transmit each packet
    pkts = []
    for _ in range(N_PACKETS):
        pkts.append((gen_packet(), 200))

    # write packet data
    cocotb.fork(packets_write(dut, axis_writer, pkts))

    # wait a little
    yield wait_n_cycles(dut.clk156, 500)

    # start the module
    dut.active_i <= 1

    # start coroutine that checks output and wait until it completes
    yield cocotb.fork(packets_read(dut, axis_reader, pkts, True))

    # deactive the module
    dut.active_i <= 0

    # make sure no warning was flagged
    status = yield axi_lite_reader.read(CPUREG_OFFSET_STATUS)
    assert status == 0x0

    print("Test 2/4")

    # now generate packets of fixed size of 800 bytes. Since the datapath is
    # 8 byte wide, it will take exactly 100 cycles to send them. Also select
    # a fixed inter-packet time of 100 cycles. packets should be sent
    # back-to-back
    pkts = []
    for _ in range(N_PACKETS):
        pkt = Ether(src="53:00:00:00:00:01", dst="53:00:00:00:00:02")
        pkt /= ''.join(
            chr(random.randint(0, 255)) for _ in range(800 - len(pkt)))
        pkts.append((pkt, 100))

    # apply packet data
    cocotb.fork(packets_write(dut, axis_writer, pkts))

    # wait a little
    yield wait_n_cycles(dut.clk156, 1000)

    # start the module
    dut.active_i <= 1

    # start coroutine that checks output and wait until it completes
    yield cocotb.fork(packets_read(dut, axis_reader, pkts, True))

    # deactive the module
    dut.active_i <= 0

    # make sure no warning was flagged
    status = yield axi_lite_reader.read(CPUREG_OFFSET_STATUS)
    assert status == 0x0

    print("Test 3/4")

    # repeat the experiment, but decrement inter-packet time to 99 cycles.
    # since inter-packet time is smaller than the packet transmit time, we
    # should get a warning
    pkts = []
    for _ in range(N_PACKETS):
        pkt = Ether(src="53:00:00:00:00:01", dst="53:00:00:00:00:02")
        pkt /= ''.join(
            chr(random.randint(0, 255)) for _ in range(800 - len(pkt)))
        pkts.append((pkt, 99))

    # apply packet data
    cocotb.fork(packets_write(dut, axis_writer, pkts))

    # wait a little
    yield wait_n_cycles(dut.clk156, 500)

    # start the module
    dut.active_i <= 1

    # start coroutine that checks output and wait until it completes
    yield cocotb.fork(packets_read(dut, axis_reader, pkts, False))

    # deactive the module
    dut.active_i <= 0

    # make sure a warning was flagged
    status = yield axi_lite_reader.read(CPUREG_OFFSET_STATUS)
    assert status == 0x1

    # perform software reset to clear warning flag
    yield axi_lite_writer.write(CPUREG_OFFSET_RST, 0x1)

    # now start toggeling tready
    cocotb.fork(toggle_signal(dut.clk156, dut.m_axis_tready))

    print("Test 4/4")

    # repeat the experiment, inter-packet time back at 100 cycles. since the
    # slave is not always ready to receive, this should cause a warning
    pkts = []
    for _ in range(N_PACKETS):
        pkt = Ether(src="53:00:00:00:00:01", dst="53:00:00:00:00:02")
        pkt /= ''.join(
            chr(random.randint(0, 255)) for _ in range(800 - len(pkt)))
        pkts.append((pkt, 100))

    # apply packet data
    cocotb.fork(packets_write(dut, axis_writer, pkts))

    # wait a little
    yield wait_n_cycles(dut.clk156, 500)

    # start the module
    dut.active_i <= 1

    # start coroutine that checks output and wait until it completes
    yield cocotb.fork(packets_read(dut, axis_reader, pkts, False))

    # deactive the module
    dut.active_i <= 0

    # make sure no warning was flagged
    status = yield axi_lite_reader.read(CPUREG_OFFSET_STATUS)
    assert status == 0x1
Ejemplo n.º 11
0
def nt_recv_capture_top_test(dut):
    """Test bench main function."""
    # start the clock
    cocotb.fork(clk_gen(dut.clk, CLK_FREQ_MHZ))

    # no software reset
    dut.rst_sw <= 0

    # reset DuT
    yield rstn(dut.clk, dut.rstn)

    # create AXI4-Lite writer, connect and reset it
    axilite_writer = AXI_Lite_Writer()
    axilite_writer.connect(dut, dut.clk, AXI_CTRL_BIT_WIDTH, "ctrl")
    yield axilite_writer.rst()

    # create AXI4-Lite reader, connect and reset it
    axilite_reader = AXI_Lite_Reader()
    axilite_reader.connect(dut, dut.clk, AXI_CTRL_BIT_WIDTH, "ctrl")
    yield axilite_reader.rst()

    # create AXI4-Stream writer, connect and reset it
    axis_writer = AXIS_Writer()
    axis_writer.connect(dut, dut.clk, AXIS_BIT_WIDTH)
    yield axis_writer.rst()

    # create a ring buffer memory (initially of size 0) and connect it to the
    # DuT
    ring_buff = Mem(0)
    ring_buff.connect(dut, "ddr3")

    # generate a couple of random Ethernet packets. For each packet, generate
    # a 16 bit latency value and a 26 bit inter-packet time value
    pkts = []
    latencies = []
    inter_packet_times = []
    for _ in range(N_PACKETS):
        pkts.append(gen_packet())
        latencies.append(random.randint(0, 2**24 - 1))
        inter_packet_times.append(random.randint(0, 2**28 - 1))

    # start the ring buffer memory main routine
    cocotb.fork(ring_buff.main())

    # wait some more clock cycles
    yield wait_n_cycles(dut.clk, 5)

    # iterate over all ring buffer sizes
    for i, ring_buff_size in enumerate(RING_BUFF_SIZES):

        # set ring buffer size
        ring_buff.set_size(ring_buff_size)

        # iterate over all adderesses where ring buffer shall be located in
        # memory
        for j, ring_buff_addr in enumerate(RING_BUFF_ADDRS):

            # print status
            print("Test %d/%d (this will take a while)" %
                  (i * len(RING_BUFF_ADDRS) + j + 1,
                   len(RING_BUFF_ADDRS) * len(RING_BUFF_SIZES)))

            # we have a total of 8 GByte of memory. Make sure the ring buffer
            # fits at the desired address
            if ring_buff_addr + ring_buff_size > 0x1FFFFFFFF:
                raise cocotb.result.TestFailure("ring buffer is too large")

            # to reduce the simulation memory footprint, provide the memory
            # module the first memory address that we actually care about
            ring_buff.set_offset(ring_buff_addr)

            # write ring buffer memory location and address range
            yield axilite_writer.write(CPUREG_OFFSET_CTRL_MEM_ADDR_HI,
                                       ring_buff_addr >> 32)
            yield axilite_writer.write(CPUREG_OFFSET_CTRL_MEM_ADDR_LO,
                                       ring_buff_addr & 0xFFFFFFFF)
            yield axilite_writer.write(CPUREG_OFFSET_CTRL_MEM_RANGE,
                                       ring_buff_size - 1)

            # itererate over all capture lengths
            for max_len_capture in MAX_CAPTURE_LENS:
                # reset read address pointer
                yield axilite_writer.write(CPUREG_OFFSET_CTRL_ADDR_RD, 0x0)

                # set max capture length
                yield axilite_writer.write(CPUREG_OFFSET_CTRL_MAX_LEN_CAPTURE,
                                           max_len_capture)

                # start couroutine that applies packets at input
                cocotb.fork(
                    packets_write(dut, axis_writer, axilite_writer,
                                  axilite_reader, pkts, latencies,
                                  inter_packet_times))

                # wait a bit
                yield wait_n_cycles(dut.clk, 50)

                # start the ring buffer read coroutine and wait until it
                # completes
                yield ring_buff_read(dut, axilite_writer, axilite_reader,
                                     ring_buff, ring_buff_addr,
                                     max_len_capture, pkts, latencies,
                                     inter_packet_times)

                # make sure no error occured
                errs = yield axilite_reader.read(CPUREG_OFFSET_STATUS_ERRS)
                assert errs == 0x0

                # make sure packet count is correct
                pkt_cnt = \
                    yield axilite_reader.read(CPUREG_OFFSET_STATUS_PKT_CNT)
                assert pkt_cnt == len(pkts)

                # make sure module is deactivated now
                active = yield axilite_reader.read(CPUREG_OFFSET_STATUS_ACTIVE)
                assert active == 0

                # clear the ring buffer contents
                ring_buff.clear()
Ejemplo n.º 12
0
def nt_gen_replay_mem_read_test(dut):
    """Test bench main function."""
    # open trace file
    trace = File("files/random.file")

    # get trace file size
    trace_size = trace.size()

    # trace file size must be a multiple of AXI data width
    if trace.size() % (AXI_BIT_WIDTH / 8) != 0:
        raise cocotb.result.TestFailure("invalid trace size")

    # calculate ring buffer sizes
    ring_buff_sizes = []
    for ring_buff_size in RING_BUFF_SIZES:
        # size of ring buffer is determined by multiplying the size factor by
        # the size of the trace
        ring_buff_size = int(ring_buff_size * trace_size)

        # make sure that the ring buffer size is multiple of AXI data width
        if ring_buff_size % (AXI_BIT_WIDTH / 8) != 0:
            ring_buff_size += AXI_BIT_WIDTH/8 - ring_buff_size % \
                             (AXI_BIT_WIDTH/8)
        ring_buff_sizes.append(ring_buff_size)

    # create a ring buffer memory (initially of size 0) and connect it to the
    # DUT
    ring_buff = Mem(0)
    ring_buff.connect(dut)

    # start the clock
    cocotb.fork(clk_gen(dut.clk, CLK_FREQ_MHZ))

    # deassert sw reset
    dut.rst_sw <= 0

    # initially module start is not triggered
    dut.ctrl_start_i <= 0

    # reset dut
    yield rstn(dut.clk, dut.rstn)

    # start the ring buffer memory main routine
    cocotb.fork(ring_buff.main())

    # wait some more clock cycles
    yield wait_n_cycles(dut.clk, 5)

    # randomly toggle fifo_prog_full input signal
    dut.fifo_prog_full_i <= 0
    cocotb.fork(toggle_signal(dut.clk, dut.fifo_prog_full_i))

    # iterate over all ring buffer sizes
    for i, ring_buff_size in enumerate(ring_buff_sizes):

        # set ring buffer size
        ring_buff.set_size(ring_buff_size)

        # iterate over all adderesses where ring buffer shall be located in
        # memory
        for j, ring_buff_addr in enumerate(RING_BUFF_ADDRS):

            # print status
            print("Test %d/%d" % (i * len(RING_BUFF_ADDRS) + j + 1,
                                  len(RING_BUFF_ADDRS) * len(RING_BUFF_SIZES)))

            # we have a total of 8 GByte of memory. Make sure the ring buffer
            # fits at the desired address
            if ring_buff_addr + ring_buff_size > 0x1FFFFFFFF:
                raise cocotb.result.TestFailure("ring buffer is too large")

            # to reduce the simulation memory footprint, provide the memory
            # module the first memory address that we actually care about
            ring_buff.set_offset(ring_buff_addr)

            # apply ring buffer memory location to dut
            dut.ctrl_mem_addr_hi_i <= ring_buff_addr >> 32
            dut.ctrl_mem_addr_lo_i <= ring_buff_addr & 0xFFFFFFFF

            # apply ring buffer address range to dut
            dut.ctrl_mem_range_i <= ring_buff_size - 1

            # apply trace size to dut
            dut.ctrl_trace_size_hi_i <= trace_size >> 32
            dut.ctrl_trace_size_lo_i <= trace_size & 0xFFFFFFFF

            # reset write address pointer
            dut.ctrl_addr_wr_i <= 0

            # start reading from the ring buffer
            dut.ctrl_start_i <= 1
            yield RisingEdge(dut.clk)
            dut.ctrl_start_i <= 0
            yield RisingEdge(dut.clk)

            # start writing the ring buffer
            cocotb.fork(ring_buff_write(dut, ring_buff, trace))

            # start checking dut output and wait until it completes
            yield cocotb.fork(check_output(dut, trace)).join()

            # clear the ring buffer contents
            ring_buff.clear()

    # close trace file
    trace.close()
Ejemplo n.º 13
0
def nt_recv_capture_rx_fifo_merge_test(dut):
    """Test bench main function."""
    # start the clock
    cocotb.fork(clk_gen(dut.clk, CLK_FREQ_MHZ))

    # do not issue software reset
    dut.rst_sw <= 0

    # reset the dut
    yield rstn(dut.clk, dut.rstn)

    # instantiate an AXI4-Stream writer, connect and reset
    axis_writer = AXIS_Writer()
    axis_writer.connect(dut, dut.clk, DATAPATH_BIT_WIDTH)
    yield axis_writer.rst()

    # generate a couple of random Ethernet packets. For each packet, generate
    # a 16 bit latency value and a 26 bit inter-packet time value
    pkts = []
    latencies = []
    inter_packet_times = []
    for _ in range(N_PACKETS):
        pkts.append(gen_packet())
        latencies.append(randint(0, 2**24 - 1))
        inter_packet_times.append(randint(0, 2**28 - 1))

    # initially output FIFO is not full
    dut.fifo_full_i <= 0

    # test: capture disabled
    print("Performing test 1/%d" % (N_REPEATS + 5))
    yield perform_test(dut, axis_writer, pkts, latencies, inter_packet_times,
                       False, 0)

    # test: max capture size: 1514 byte
    print("Performing test 2/%d" % (N_REPEATS + 5))
    yield perform_test(dut, axis_writer, pkts, latencies, inter_packet_times,
                       True, 1514)

    # test: max capture size: 0 byte
    print("Performing test 3/%d" % (N_REPEATS + 5))
    yield perform_test(dut, axis_writer, pkts, latencies, inter_packet_times,
                       True, 0)

    # perform some more tests for random capture sizes
    for i in range(N_REPEATS):
        print("Performing test %d/%d" % (3 + i, N_REPEATS + 5))
        yield perform_test(dut, axis_writer, pkts, latencies,
                           inter_packet_times, True, randint(64, 1514))

    # now mark the fifo as full
    dut.fifo_full_i <= 1

    # perform another test and check data fifo error output signal
    # should become full
    print("Performing test %d/%d (no status output)" %
          (N_REPEATS + 4, N_REPEATS + 5))
    cocotb.fork(
        perform_test(dut, axis_writer, pkts, latencies, inter_packet_times,
                     True, 1514))

    # wait until all packets have been applied on AXI stream interface
    pkt_cnt = 0
    while pkt_cnt < len(pkts):
        yield RisingEdge(dut.clk)
        if int(dut.s_axis_tvalid) and int(dut.s_axis_tready) and \
                int(dut.s_axis_tlast):
            pkt_cnt += 1

    # make sure the data fifo full error signal is asserted
    assert int(dut.err_data_fifo_full_o)

    # perform reset
    dut.rst_sw <= 1
    yield RisingEdge(dut.clk)
    dut.rst_sw <= 0
    yield RisingEdge(dut.clk)

    # perform one final test to check whether the meta data fifo error signal
    # is asserted when the fifo becomes full
    print("Performing test %d/%d (no status output)" %
          (N_REPEATS + 5, N_REPEATS + 5))
    cocotb.fork(
        perform_test(dut, axis_writer, pkts, latencies, inter_packet_times,
                     True, 0))

    # wait until all packets have been applied on AXI stream interface
    pkt_cnt = 0
    while pkt_cnt < len(pkts):
        yield RisingEdge(dut.clk)
        if int(dut.s_axis_tvalid) and int(dut.s_axis_tready) and \
                int(dut.s_axis_tlast):
            pkt_cnt += 1

    # make sure the meta fifo full error signal is asserted
    assert int(dut.err_meta_fifo_full_o)
Ejemplo n.º 14
0
def nt_recv_capture_mem_write_test(dut):
    """Test bench main function."""
    # open file with random content
    try:
        f = File("files/random.file")
    except IOError:
        raise cocotb.result.TestFailure("Generate input data by calling " +
                                        "'./create_random.py' in 'files' " +
                                        "folder!")

    # file size must be a multiple of AXI data width
    if f.size() % (BIT_WIDTH_MEM_WRITE / 8) != 0:
        raise cocotb.result.TestFailure("invalid input data size")

    # create a ring buffer memory (initially of size 0) and connect it to the
    # DuT
    ring_buff = Mem(0)
    ring_buff.connect(dut)

    # start the clock
    cocotb.fork(clk_gen(dut.clk, CLK_FREQ_MHZ))

    # deassert sw reset
    dut.rst_sw <= 0

    # initially module is disabled
    dut.active_i <= 0

    # initially no FIFO flush
    dut.flush_i <= 0

    # reset DuT
    yield rstn(dut.clk, dut.rstn)

    # start the ring buffer memory main routine
    cocotb.fork(ring_buff.main())

    # wait some more clock cycles
    yield wait_n_cycles(dut.clk, 5)

    # iterate over all ring buffer sizes
    for i, ring_buff_size in enumerate(RING_BUFF_SIZES):

        # set ring buffer size
        ring_buff.set_size(ring_buff_size)

        # iterate over all adderesses where ring buffer shall be located in
        # memory
        for j, ring_buff_addr in enumerate(RING_BUFF_ADDRS):

            # print status
            print("Test %d/%d" % (i * len(RING_BUFF_ADDRS) + j + 1,
                                  len(RING_BUFF_ADDRS) * len(RING_BUFF_SIZES)))

            # we have a total of 8 GByte of memory. Make sure the ring buffer
            # fits at the desired address
            if ring_buff_addr + ring_buff_size > 0x1FFFFFFFF:
                raise cocotb.result.TestFailure("ring buffer is too large")

            # to reduce the simulation memory footprint, provide the memory
            # module the first memory address that we actually care about
            ring_buff.set_offset(ring_buff_addr)

            # apply ring buffer memory location to dut
            dut.mem_addr_hi_i <= ring_buff_addr >> 32
            dut.mem_addr_lo_i <= ring_buff_addr & 0xFFFFFFFF

            # apply ring buffer address range to dut
            dut.mem_range_i <= ring_buff_size - 1

            # reset read address pointer
            dut.addr_rd_i <= 0

            # start a couroutine that applies input data
            cocotb.fork(apply_input(dut, f))

            # wait a few clock cycles
            yield wait_n_cycles(dut.clk, 10)

            # start the ring buffer read coroutine and wait until it completes
            yield ring_buff_read(dut, ring_buff, f)

            # clear the ring buffer contents
            ring_buff.clear()

    # close file
    f.close()