Beispiel #1
0
def bench():

    # Parameters
    AXIS_PCIE_DATA_WIDTH = 256
    AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH / 32)
    AXIS_PCIE_RC_USER_WIDTH = 75
    AXIS_PCIE_RQ_USER_WIDTH = 60
    RQ_SEQ_NUM_WIDTH = 4 if AXIS_PCIE_RQ_USER_WIDTH == 60 else 6
    RQ_SEQ_NUM_ENABLE = 1
    SEG_COUNT = max(2, int(AXIS_PCIE_DATA_WIDTH * 2 / 128))
    SEG_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH * 2 / SEG_COUNT
    SEG_ADDR_WIDTH = 12
    SEG_BE_WIDTH = int(SEG_DATA_WIDTH / 8)
    RAM_SEL_WIDTH = 2
    RAM_ADDR_WIDTH = SEG_ADDR_WIDTH + (SEG_COUNT - 1).bit_length() + (
        SEG_BE_WIDTH - 1).bit_length()
    PCIE_ADDR_WIDTH = 64
    PCIE_TAG_COUNT = 64 if AXIS_PCIE_RQ_USER_WIDTH == 60 else 256
    PCIE_TAG_WIDTH = (PCIE_TAG_COUNT - 1).bit_length()
    PCIE_EXT_TAG_ENABLE = (PCIE_TAG_COUNT > 32)
    LEN_WIDTH = 16
    TAG_WIDTH = 8
    READ_OP_TABLE_SIZE = PCIE_TAG_COUNT
    READ_TX_LIMIT = 2**(RQ_SEQ_NUM_WIDTH - 1)
    WRITE_OP_TABLE_SIZE = 2**(RQ_SEQ_NUM_WIDTH - 1)
    WRITE_TX_LIMIT = 2**(RQ_SEQ_NUM_WIDTH - 1)

    # Inputs
    clk = Signal(bool(0))
    rst = Signal(bool(0))
    current_test = Signal(intbv(0)[8:])

    s_axis_rc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
    s_axis_rc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
    s_axis_rc_tvalid = Signal(bool(0))
    s_axis_rc_tlast = Signal(bool(0))
    s_axis_rc_tuser = Signal(intbv(0)[AXIS_PCIE_RC_USER_WIDTH:])
    m_axis_rq_tready = Signal(bool(0))
    s_axis_rq_seq_num_0 = Signal(intbv(0)[RQ_SEQ_NUM_WIDTH:])
    s_axis_rq_seq_num_valid_0 = Signal(bool(0))
    s_axis_rq_seq_num_1 = Signal(intbv(0)[RQ_SEQ_NUM_WIDTH:])
    s_axis_rq_seq_num_valid_1 = Signal(bool(0))
    s_axis_read_desc_pcie_addr = Signal(intbv(0)[PCIE_ADDR_WIDTH:])
    s_axis_read_desc_ram_sel = Signal(intbv(0)[RAM_SEL_WIDTH:])
    s_axis_read_desc_ram_addr = Signal(intbv(0)[RAM_ADDR_WIDTH:])
    s_axis_read_desc_len = Signal(intbv(0)[LEN_WIDTH:])
    s_axis_read_desc_tag = Signal(intbv(0)[TAG_WIDTH:])
    s_axis_read_desc_valid = Signal(bool(0))
    s_axis_write_desc_pcie_addr = Signal(intbv(0)[PCIE_ADDR_WIDTH:])
    s_axis_write_desc_ram_sel = Signal(intbv(0)[RAM_SEL_WIDTH:])
    s_axis_write_desc_ram_addr = Signal(intbv(0)[RAM_ADDR_WIDTH:])
    s_axis_write_desc_len = Signal(intbv(0)[LEN_WIDTH:])
    s_axis_write_desc_tag = Signal(intbv(0)[TAG_WIDTH:])
    s_axis_write_desc_valid = Signal(bool(0))
    ram_wr_cmd_ready = Signal(intbv(0)[SEG_COUNT:])
    ram_rd_cmd_ready = Signal(intbv(0)[SEG_COUNT:])
    ram_rd_resp_data = Signal(intbv(0)[SEG_COUNT * SEG_DATA_WIDTH:])
    ram_rd_resp_valid = Signal(intbv(0)[SEG_COUNT:])
    read_enable = Signal(bool(0))
    write_enable = Signal(bool(0))
    ext_tag_enable = Signal(bool(0))
    requester_id = Signal(intbv(0)[16:])
    requester_id_enable = Signal(bool(0))
    max_read_request_size = Signal(intbv(0)[3:])
    max_payload_size = Signal(intbv(0)[3:])

    # Outputs
    s_axis_rc_tready = Signal(bool(0))
    m_axis_rq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
    m_axis_rq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
    m_axis_rq_tvalid = Signal(bool(0))
    m_axis_rq_tlast = Signal(bool(0))
    m_axis_rq_tuser = Signal(intbv(0)[AXIS_PCIE_RQ_USER_WIDTH:])
    s_axis_read_desc_ready = Signal(bool(0))
    m_axis_read_desc_status_tag = Signal(intbv(0)[TAG_WIDTH:])
    m_axis_read_desc_status_valid = Signal(bool(0))
    s_axis_write_desc_ready = Signal(bool(0))
    m_axis_write_desc_status_tag = Signal(intbv(0)[TAG_WIDTH:])
    m_axis_write_desc_status_valid = Signal(bool(0))
    ram_wr_cmd_sel = Signal(intbv(0)[SEG_COUNT * RAM_SEL_WIDTH:])
    ram_wr_cmd_be = Signal(intbv(0)[SEG_COUNT * SEG_BE_WIDTH:])
    ram_wr_cmd_addr = Signal(intbv(0)[SEG_COUNT * SEG_ADDR_WIDTH:])
    ram_wr_cmd_data = Signal(intbv(0)[SEG_COUNT * SEG_DATA_WIDTH:])
    ram_wr_cmd_valid = Signal(intbv(0)[SEG_COUNT:])
    ram_rd_cmd_sel = Signal(intbv(0)[SEG_COUNT * RAM_SEL_WIDTH:])
    ram_rd_cmd_addr = Signal(intbv(0)[SEG_COUNT * SEG_ADDR_WIDTH:])
    ram_rd_cmd_valid = Signal(intbv(0)[SEG_COUNT:])
    ram_rd_resp_ready = Signal(intbv(0)[SEG_COUNT:])
    status_error_cor = Signal(bool(0))
    status_error_uncor = Signal(bool(0))

    # Clock and Reset Interface
    user_clk = Signal(bool(0))
    user_reset = Signal(bool(0))
    sys_clk = Signal(bool(0))
    sys_reset = Signal(bool(0))

    # PCIe DMA RAM
    dma_ram_inst = dma_ram.PSDPRam(2**16)
    dma_ram_pause = Signal(bool(0))

    dma_ram_port0_wr = dma_ram_inst.create_write_ports(
        user_clk,
        ram_wr_cmd_be=ram_wr_cmd_be,
        ram_wr_cmd_addr=ram_wr_cmd_addr,
        ram_wr_cmd_data=ram_wr_cmd_data,
        ram_wr_cmd_valid=ram_wr_cmd_valid,
        ram_wr_cmd_ready=ram_wr_cmd_ready,
        pause=dma_ram_pause,
        name='port0_wr')

    dma_ram_port0_rd = dma_ram_inst.create_read_ports(
        user_clk,
        ram_rd_cmd_addr=ram_rd_cmd_addr,
        ram_rd_cmd_valid=ram_rd_cmd_valid,
        ram_rd_cmd_ready=ram_rd_cmd_ready,
        ram_rd_resp_data=ram_rd_resp_data,
        ram_rd_resp_valid=ram_rd_resp_valid,
        ram_rd_resp_ready=ram_rd_resp_ready,
        pause=dma_ram_pause,
        name='port0_rd')

    # sources and sinks
    read_desc_source = axis_ep.AXIStreamSource()

    read_desc_source_logic = read_desc_source.create_logic(
        user_clk,
        user_reset,
        tdata=(s_axis_read_desc_pcie_addr, s_axis_read_desc_ram_sel,
               s_axis_read_desc_ram_addr, s_axis_read_desc_len,
               s_axis_read_desc_tag),
        tvalid=s_axis_read_desc_valid,
        tready=s_axis_read_desc_ready,
        name='read_desc_source')

    read_desc_status_sink = axis_ep.AXIStreamSink()

    read_desc_status_sink_logic = read_desc_status_sink.create_logic(
        user_clk,
        user_reset,
        tdata=(m_axis_read_desc_status_tag, ),
        tvalid=m_axis_read_desc_status_valid,
        name='read_desc_status_sink')

    write_desc_source = axis_ep.AXIStreamSource()

    write_desc_source_logic = write_desc_source.create_logic(
        user_clk,
        user_reset,
        tdata=(s_axis_write_desc_pcie_addr, s_axis_write_desc_ram_sel,
               s_axis_write_desc_ram_addr, s_axis_write_desc_len,
               s_axis_write_desc_tag),
        tvalid=s_axis_write_desc_valid,
        tready=s_axis_write_desc_ready,
        name='write_desc_source')

    write_desc_status_sink = axis_ep.AXIStreamSink()

    write_desc_status_sink_logic = write_desc_status_sink.create_logic(
        user_clk,
        user_reset,
        tdata=(m_axis_write_desc_status_tag, ),
        tvalid=m_axis_write_desc_status_valid,
        name='write_desc_status_sink')

    # PCIe devices
    rc = pcie.RootComplex()

    mem_base, mem_data = rc.alloc_region(16 * 1024 * 1024)

    dev = pcie_us.UltrascalePCIe()

    dev.pcie_generation = 3
    dev.pcie_link_width = 8
    dev.user_clock_frequency = 256e6

    rc.make_port().connect(dev)

    cq_pause = Signal(bool(0))
    cc_pause = Signal(bool(0))
    rq_pause = Signal(bool(0))
    rc_pause = Signal(bool(0))

    pcie_logic = dev.create_logic(
        # Completer reQuest Interface
        m_axis_cq_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
        m_axis_cq_tuser=Signal(intbv(0)[85:]),
        m_axis_cq_tlast=Signal(bool(0)),
        m_axis_cq_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
        m_axis_cq_tvalid=Signal(bool(0)),
        m_axis_cq_tready=Signal(bool(1)),
        pcie_cq_np_req=Signal(bool(1)),
        pcie_cq_np_req_count=Signal(intbv(0)[6:]),

        # Completer Completion Interface
        s_axis_cc_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
        s_axis_cc_tuser=Signal(intbv(0)[33:]),
        s_axis_cc_tlast=Signal(bool(0)),
        s_axis_cc_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
        s_axis_cc_tvalid=Signal(bool(0)),
        s_axis_cc_tready=Signal(bool(0)),

        # Requester reQuest Interface
        s_axis_rq_tdata=m_axis_rq_tdata,
        s_axis_rq_tuser=m_axis_rq_tuser,
        s_axis_rq_tlast=m_axis_rq_tlast,
        s_axis_rq_tkeep=m_axis_rq_tkeep,
        s_axis_rq_tvalid=m_axis_rq_tvalid,
        s_axis_rq_tready=m_axis_rq_tready,
        pcie_rq_seq_num=s_axis_rq_seq_num_0,
        pcie_rq_seq_num_vld=s_axis_rq_seq_num_valid_0,
        # pcie_rq_tag=pcie_rq_tag,
        # pcie_rq_tag_av=pcie_rq_tag_av,
        # pcie_rq_tag_vld=pcie_rq_tag_vld,

        # Requester Completion Interface
        m_axis_rc_tdata=s_axis_rc_tdata,
        m_axis_rc_tuser=s_axis_rc_tuser,
        m_axis_rc_tlast=s_axis_rc_tlast,
        m_axis_rc_tkeep=s_axis_rc_tkeep,
        m_axis_rc_tvalid=s_axis_rc_tvalid,
        m_axis_rc_tready=s_axis_rc_tready,

        # Transmit Flow Control Interface
        # pcie_tfc_nph_av=pcie_tfc_nph_av,
        # pcie_tfc_npd_av=pcie_tfc_npd_av,

        # Configuration Control Interface
        # cfg_hot_reset_in=cfg_hot_reset_in,
        # cfg_hot_reset_out=cfg_hot_reset_out,
        # cfg_config_space_enable=cfg_config_space_enable,
        # cfg_per_function_update_done=cfg_per_function_update_done,
        # cfg_per_function_number=cfg_per_function_number,
        # cfg_per_function_output_request=cfg_per_function_output_request,
        # cfg_dsn=cfg_dsn,
        # cfg_ds_bus_number=cfg_ds_bus_number,
        # cfg_ds_device_number=cfg_ds_device_number,
        # cfg_ds_function_number=cfg_ds_function_number,
        # cfg_power_state_change_ack=cfg_power_state_change_ack,
        # cfg_power_state_change_interrupt=cfg_power_state_change_interrupt,
        # cfg_err_cor_in=cfg_err_cor_in,
        # cfg_err_uncor_in=cfg_err_uncor_in,
        # cfg_flr_done=cfg_flr_done,
        # cfg_vf_flr_done=cfg_vf_flr_done,
        # cfg_flr_in_process=cfg_flr_in_process,
        # cfg_vf_flr_in_process=cfg_vf_flr_in_process,
        # cfg_req_pm_transition_l23_ready=cfg_req_pm_transition_l23_ready,
        # cfg_link_training_enable=cfg_link_training_enable,

        # Clock and Reset Interface
        user_clk=user_clk,
        user_reset=user_reset,
        #user_lnk_up=user_lnk_up,
        sys_clk=sys_clk,
        sys_clk_gt=sys_clk,
        sys_reset=sys_reset,
        cq_pause=cq_pause,
        cc_pause=cc_pause,
        rq_pause=rq_pause,
        rc_pause=rc_pause)

    # DUT
    if os.system(build_cmd):
        raise Exception("Error running build command")

    dut = Cosimulation(
        "vvp -m myhdl %s.vvp -lxt2" % testbench,
        clk=user_clk,
        rst=user_reset,
        current_test=current_test,
        s_axis_rc_tdata=s_axis_rc_tdata,
        s_axis_rc_tkeep=s_axis_rc_tkeep,
        s_axis_rc_tvalid=s_axis_rc_tvalid,
        s_axis_rc_tready=s_axis_rc_tready,
        s_axis_rc_tlast=s_axis_rc_tlast,
        s_axis_rc_tuser=s_axis_rc_tuser,
        m_axis_rq_tdata=m_axis_rq_tdata,
        m_axis_rq_tkeep=m_axis_rq_tkeep,
        m_axis_rq_tvalid=m_axis_rq_tvalid,
        m_axis_rq_tready=m_axis_rq_tready,
        m_axis_rq_tlast=m_axis_rq_tlast,
        m_axis_rq_tuser=m_axis_rq_tuser,
        s_axis_rq_seq_num_0=s_axis_rq_seq_num_0,
        s_axis_rq_seq_num_valid_0=s_axis_rq_seq_num_valid_0,
        s_axis_rq_seq_num_1=s_axis_rq_seq_num_1,
        s_axis_rq_seq_num_valid_1=s_axis_rq_seq_num_valid_1,
        s_axis_read_desc_pcie_addr=s_axis_read_desc_pcie_addr,
        s_axis_read_desc_ram_sel=s_axis_read_desc_ram_sel,
        s_axis_read_desc_ram_addr=s_axis_read_desc_ram_addr,
        s_axis_read_desc_len=s_axis_read_desc_len,
        s_axis_read_desc_tag=s_axis_read_desc_tag,
        s_axis_read_desc_valid=s_axis_read_desc_valid,
        s_axis_read_desc_ready=s_axis_read_desc_ready,
        m_axis_read_desc_status_tag=m_axis_read_desc_status_tag,
        m_axis_read_desc_status_valid=m_axis_read_desc_status_valid,
        s_axis_write_desc_pcie_addr=s_axis_write_desc_pcie_addr,
        s_axis_write_desc_ram_sel=s_axis_write_desc_ram_sel,
        s_axis_write_desc_ram_addr=s_axis_write_desc_ram_addr,
        s_axis_write_desc_len=s_axis_write_desc_len,
        s_axis_write_desc_tag=s_axis_write_desc_tag,
        s_axis_write_desc_valid=s_axis_write_desc_valid,
        s_axis_write_desc_ready=s_axis_write_desc_ready,
        m_axis_write_desc_status_tag=m_axis_write_desc_status_tag,
        m_axis_write_desc_status_valid=m_axis_write_desc_status_valid,
        ram_wr_cmd_sel=ram_wr_cmd_sel,
        ram_wr_cmd_be=ram_wr_cmd_be,
        ram_wr_cmd_addr=ram_wr_cmd_addr,
        ram_wr_cmd_data=ram_wr_cmd_data,
        ram_wr_cmd_valid=ram_wr_cmd_valid,
        ram_wr_cmd_ready=ram_wr_cmd_ready,
        ram_rd_cmd_sel=ram_rd_cmd_sel,
        ram_rd_cmd_addr=ram_rd_cmd_addr,
        ram_rd_cmd_valid=ram_rd_cmd_valid,
        ram_rd_cmd_ready=ram_rd_cmd_ready,
        ram_rd_resp_data=ram_rd_resp_data,
        ram_rd_resp_valid=ram_rd_resp_valid,
        ram_rd_resp_ready=ram_rd_resp_ready,
        read_enable=read_enable,
        write_enable=write_enable,
        ext_tag_enable=ext_tag_enable,
        requester_id=requester_id,
        requester_id_enable=requester_id_enable,
        max_read_request_size=max_read_request_size,
        max_payload_size=max_payload_size,
        status_error_cor=status_error_cor,
        status_error_uncor=status_error_uncor)

    @always(delay(4))
    def clkgen():
        clk.next = not clk

    @always_comb
    def clk_logic():
        sys_clk.next = clk
        sys_reset.next = not rst

    @instance
    def check():
        yield delay(100)
        yield clk.posedge
        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge
        yield delay(100)
        yield clk.posedge

        # testbench stimulus

        cur_tag = 1

        max_payload_size.next = 0
        max_read_request_size.next = 2

        read_enable.next = 1
        write_enable.next = 1

        yield user_clk.posedge
        print("test 1: enumeration")
        current_test.next = 1

        yield rc.enumerate(enable_bus_mastering=True)

        yield delay(100)

        yield user_clk.posedge
        print("test 2: PCIe write")
        current_test.next = 2

        pcie_addr = 0x00000000
        ram_addr = 0x00000000
        test_data = b'\x11\x22\x33\x44'

        dma_ram_inst.write_mem(ram_addr, test_data)
        mem_data[pcie_addr:pcie_addr +
                 len(test_data)] = b'\x00' * len(test_data)

        data = dma_ram_inst.read_mem(ram_addr, 32)
        for i in range(0, len(data), 16):
            print(" ".join(
                ("{:02x}".format(c) for c in bytearray(data[i:i + 16]))))

        write_desc_source.send([(mem_base + pcie_addr, 0, ram_addr,
                                 len(test_data), cur_tag)])

        yield write_desc_status_sink.wait(1000)
        yield delay(50)

        status = write_desc_status_sink.recv()

        print(status)

        assert status.data[0][0] == cur_tag

        data = mem_data[pcie_addr:pcie_addr + 32]
        for i in range(0, len(data), 16):
            print(" ".join(
                ("{:02x}".format(c) for c in bytearray(data[i:i + 16]))))

        assert mem_data[pcie_addr:pcie_addr + len(test_data)] == test_data

        cur_tag = (cur_tag + 1) % 256

        yield delay(100)

        yield user_clk.posedge
        print("test 3: PCIe read")
        current_test.next = 3

        pcie_addr = 0x00000000
        ram_addr = 0x00000000
        test_data = b'\x11\x22\x33\x44'

        dma_ram_inst.write_mem(ram_addr, b'\x00' * len(test_data))
        mem_data[pcie_addr:pcie_addr + len(test_data)] = test_data

        data = mem_data[pcie_addr:pcie_addr + 32]
        for i in range(0, len(data), 16):
            print(" ".join(
                ("{:02x}".format(c) for c in bytearray(data[i:i + 16]))))

        read_desc_source.send([(pcie_addr, 0, ram_addr, len(test_data),
                                cur_tag)])

        yield read_desc_status_sink.wait(2000)

        status = read_desc_status_sink.recv()

        print(status)

        assert status.data[0][0] == cur_tag

        data = dma_ram_inst.read_mem(ram_addr, 32)
        for i in range(0, len(data), 16):
            print(" ".join(
                ("{:02x}".format(c) for c in bytearray(data[i:i + 16]))))

        assert dma_ram_inst.read_mem(ram_addr, len(test_data)) == test_data

        cur_tag = (cur_tag + 1) % 256

        yield delay(100)

        raise StopSimulation

    return instances()
Beispiel #2
0
def bench():

    # Parameters
    AXIS_PCIE_DATA_WIDTH = 256
    AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH / 32)
    AXIS_PCIE_RC_USER_WIDTH = 75
    AXIS_PCIE_RQ_USER_WIDTH = 60
    AXIS_PCIE_CQ_USER_WIDTH = 85
    AXIS_PCIE_CC_USER_WIDTH = 33
    RQ_SEQ_NUM_WIDTH = 4
    BAR0_APERTURE = 24

    # Inputs
    clk = Signal(bool(0))
    rst = Signal(bool(0))
    current_test = Signal(intbv(0)[8:])

    clk_156mhz = Signal(bool(0))
    rst_156mhz = Signal(bool(0))
    clk_250mhz = Signal(bool(0))
    rst_250mhz = Signal(bool(0))
    btnu = Signal(bool(0))
    btnl = Signal(bool(0))
    btnd = Signal(bool(0))
    btnr = Signal(bool(0))
    btnc = Signal(bool(0))
    sw = Signal(intbv(0)[4:])
    i2c_scl_i = Signal(bool(1))
    i2c_sda_i = Signal(bool(1))
    m_axis_rq_tready = Signal(bool(0))
    s_axis_rc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
    s_axis_rc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
    s_axis_rc_tlast = Signal(bool(0))
    s_axis_rc_tuser = Signal(intbv(0)[AXIS_PCIE_RC_USER_WIDTH:])
    s_axis_rc_tvalid = Signal(bool(0))
    s_axis_cq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
    s_axis_cq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
    s_axis_cq_tlast = Signal(bool(0))
    s_axis_cq_tuser = Signal(intbv(0)[AXIS_PCIE_CQ_USER_WIDTH:])
    s_axis_cq_tvalid = Signal(bool(0))
    m_axis_cc_tready = Signal(bool(0))
    s_axis_rq_seq_num = Signal(intbv(0)[RQ_SEQ_NUM_WIDTH:])
    s_axis_rq_seq_num_valid = Signal(bool(0))
    pcie_tfc_nph_av = Signal(intbv(0)[2:])
    pcie_tfc_npd_av = Signal(intbv(0)[2:])
    cfg_max_payload = Signal(intbv(0)[3:])
    cfg_max_read_req = Signal(intbv(0)[3:])
    cfg_mgmt_read_data = Signal(intbv(0)[32:])
    cfg_mgmt_read_write_done = Signal(bool(0))
    cfg_fc_ph = Signal(intbv(0)[8:])
    cfg_fc_pd = Signal(intbv(0)[12:])
    cfg_fc_nph = Signal(intbv(0)[8:])
    cfg_fc_npd = Signal(intbv(0)[12:])
    cfg_fc_cplh = Signal(intbv(0)[8:])
    cfg_fc_cpld = Signal(intbv(0)[12:])
    cfg_interrupt_msi_enable = Signal(intbv(0)[4:])
    cfg_interrupt_msi_vf_enable = Signal(intbv(0)[8:])
    cfg_interrupt_msi_mmenable = Signal(intbv(0)[12:])
    cfg_interrupt_msi_mask_update = Signal(bool(0))
    cfg_interrupt_msi_data = Signal(intbv(0)[32:])
    cfg_interrupt_msi_sent = Signal(bool(0))
    cfg_interrupt_msi_fail = Signal(bool(0))
    qsfp_tx_clk_1 = Signal(bool(0))
    qsfp_tx_rst_1 = Signal(bool(0))
    qsfp_rx_clk_1 = Signal(bool(0))
    qsfp_rx_rst_1 = Signal(bool(0))
    qsfp_rxd_1 = Signal(intbv(0)[64:])
    qsfp_rxc_1 = Signal(intbv(0)[8:])
    qsfp_tx_clk_2 = Signal(bool(0))
    qsfp_tx_rst_2 = Signal(bool(0))
    qsfp_rx_clk_2 = Signal(bool(0))
    qsfp_rx_rst_2 = Signal(bool(0))
    qsfp_rxd_2 = Signal(intbv(0)[64:])
    qsfp_rxc_2 = Signal(intbv(0)[8:])
    qsfp_tx_clk_3 = Signal(bool(0))
    qsfp_tx_rst_3 = Signal(bool(0))
    qsfp_rx_clk_3 = Signal(bool(0))
    qsfp_rx_rst_3 = Signal(bool(0))
    qsfp_rxd_3 = Signal(intbv(0)[64:])
    qsfp_rxc_3 = Signal(intbv(0)[8:])
    qsfp_tx_clk_4 = Signal(bool(0))
    qsfp_tx_rst_4 = Signal(bool(0))
    qsfp_rx_clk_4 = Signal(bool(0))
    qsfp_rx_rst_4 = Signal(bool(0))
    qsfp_rxd_4 = Signal(intbv(0)[64:])
    qsfp_rxc_4 = Signal(intbv(0)[8:])
    qsfp_modprsl = Signal(bool(1))
    qsfp_intl = Signal(bool(1))
    flash_dq_i = Signal(intbv(0)[16:])

    # Outputs
    led = Signal(intbv(0)[8:])
    i2c_scl_o = Signal(bool(1))
    i2c_scl_t = Signal(bool(1))
    i2c_sda_o = Signal(bool(1))
    i2c_sda_t = Signal(bool(1))
    m_axis_rq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
    m_axis_rq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
    m_axis_rq_tlast = Signal(bool(0))
    m_axis_rq_tuser = Signal(intbv(0)[AXIS_PCIE_RQ_USER_WIDTH:])
    m_axis_rq_tvalid = Signal(bool(0))
    s_axis_rc_tready = Signal(bool(0))
    s_axis_cq_tready = Signal(bool(0))
    m_axis_cc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
    m_axis_cc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
    m_axis_cc_tlast = Signal(bool(0))
    m_axis_cc_tuser = Signal(intbv(0)[AXIS_PCIE_CC_USER_WIDTH:])
    m_axis_cc_tvalid = Signal(bool(0))
    status_error_cor = Signal(bool(0))
    status_error_uncor = Signal(bool(0))
    cfg_mgmt_addr = Signal(intbv(0)[19:])
    cfg_mgmt_write = Signal(bool(0))
    cfg_mgmt_write_data = Signal(intbv(0)[32:])
    cfg_mgmt_byte_enable = Signal(intbv(0)[4:])
    cfg_mgmt_read = Signal(bool(0))
    cfg_fc_sel = Signal(intbv(4)[3:])
    cfg_interrupt_msi_int = Signal(intbv(0)[32:])
    cfg_interrupt_msi_pending_status = Signal(intbv(0)[32:])
    cfg_interrupt_msi_select = Signal(intbv(0)[4:])
    cfg_interrupt_msi_pending_status_function_num = Signal(intbv(0)[4:])
    cfg_interrupt_msi_pending_status_data_enable = Signal(bool(0))
    cfg_interrupt_msi_attr = Signal(intbv(0)[3:])
    cfg_interrupt_msi_tph_present = Signal(bool(0))
    cfg_interrupt_msi_tph_type = Signal(intbv(0)[2:])
    cfg_interrupt_msi_tph_st_tag = Signal(intbv(0)[9:])
    cfg_interrupt_msi_function_number = Signal(intbv(0)[4:])
    qsfp_txd_1 = Signal(intbv(0)[64:])
    qsfp_txc_1 = Signal(intbv(0)[8:])
    qsfp_txd_2 = Signal(intbv(0)[64:])
    qsfp_txc_2 = Signal(intbv(0)[8:])
    qsfp_txd_3 = Signal(intbv(0)[64:])
    qsfp_txc_3 = Signal(intbv(0)[8:])
    qsfp_txd_4 = Signal(intbv(0)[64:])
    qsfp_txc_4 = Signal(intbv(0)[8:])
    qsfp_modsell = Signal(bool(0))
    qsfp_resetl = Signal(bool(1))
    qsfp_lpmode = Signal(bool(0))
    flash_dq_o = Signal(intbv(0)[16:])
    flash_dq_oe = Signal(bool(0))
    flash_addr = Signal(intbv(0)[23:])
    flash_region = Signal(bool(0))
    flash_region_oe = Signal(bool(0))
    flash_ce_n = Signal(bool(1))
    flash_oe_n = Signal(bool(1))
    flash_we_n = Signal(bool(1))
    flash_adv_n = Signal(bool(1))

    # sources and sinks
    qsfp_1_source = xgmii_ep.XGMIISource()
    qsfp_1_source_logic = qsfp_1_source.create_logic(qsfp_rx_clk_1,
                                                     qsfp_rx_rst_1,
                                                     txd=qsfp_rxd_1,
                                                     txc=qsfp_rxc_1,
                                                     name='qsfp_1_source')

    qsfp_1_sink = xgmii_ep.XGMIISink()
    qsfp_1_sink_logic = qsfp_1_sink.create_logic(qsfp_tx_clk_1,
                                                 qsfp_tx_rst_1,
                                                 rxd=qsfp_txd_1,
                                                 rxc=qsfp_txc_1,
                                                 name='qsfp_1_sink')

    qsfp_2_source = xgmii_ep.XGMIISource()
    qsfp_2_source_logic = qsfp_2_source.create_logic(qsfp_rx_clk_2,
                                                     qsfp_rx_rst_2,
                                                     txd=qsfp_rxd_2,
                                                     txc=qsfp_rxc_2,
                                                     name='qsfp_2_source')

    qsfp_2_sink = xgmii_ep.XGMIISink()
    qsfp_2_sink_logic = qsfp_2_sink.create_logic(qsfp_tx_clk_2,
                                                 qsfp_tx_rst_2,
                                                 rxd=qsfp_txd_2,
                                                 rxc=qsfp_txc_2,
                                                 name='qsfp_2_sink')

    qsfp_3_source = xgmii_ep.XGMIISource()
    qsfp_3_source_logic = qsfp_3_source.create_logic(qsfp_rx_clk_3,
                                                     qsfp_rx_rst_3,
                                                     txd=qsfp_rxd_3,
                                                     txc=qsfp_rxc_3,
                                                     name='qsfp_3_source')

    qsfp_3_sink = xgmii_ep.XGMIISink()
    qsfp_3_sink_logic = qsfp_3_sink.create_logic(qsfp_tx_clk_3,
                                                 qsfp_tx_rst_3,
                                                 rxd=qsfp_txd_3,
                                                 rxc=qsfp_txc_3,
                                                 name='qsfp_3_sink')

    qsfp_4_source = xgmii_ep.XGMIISource()
    qsfp_4_source_logic = qsfp_4_source.create_logic(qsfp_rx_clk_4,
                                                     qsfp_rx_rst_4,
                                                     txd=qsfp_rxd_4,
                                                     txc=qsfp_rxc_4,
                                                     name='qsfp_4_source')

    qsfp_4_sink = xgmii_ep.XGMIISink()
    qsfp_4_sink_logic = qsfp_4_sink.create_logic(qsfp_tx_clk_4,
                                                 qsfp_tx_rst_4,
                                                 rxd=qsfp_txd_4,
                                                 rxc=qsfp_txc_4,
                                                 name='qsfp_4_sink')

    # Clock and Reset Interface
    user_clk = Signal(bool(0))
    user_reset = Signal(bool(0))
    sys_clk = Signal(bool(0))
    sys_reset = Signal(bool(0))

    # PCIe devices
    rc = pcie.RootComplex()

    rc.max_payload_size = 0x1  # 256 bytes
    rc.max_read_request_size = 0x5  # 4096 bytes

    driver = mqnic.Driver(rc)

    dev = pcie_us.UltrascalePCIe()

    dev.pcie_generation = 3
    dev.pcie_link_width = 8
    dev.user_clock_frequency = 256e6

    dev.functions[0].msi_multiple_message_capable = 5

    dev.functions[0].configure_bar(0,
                                   2**BAR0_APERTURE,
                                   ext=True,
                                   prefetch=True)

    rc.make_port().connect(dev)

    pcie_logic = dev.create_logic(
        # Completer reQuest Interface
        m_axis_cq_tdata=s_axis_cq_tdata,
        m_axis_cq_tuser=s_axis_cq_tuser,
        m_axis_cq_tlast=s_axis_cq_tlast,
        m_axis_cq_tkeep=s_axis_cq_tkeep,
        m_axis_cq_tvalid=s_axis_cq_tvalid,
        m_axis_cq_tready=s_axis_cq_tready,
        #pcie_cq_np_req=pcie_cq_np_req,
        pcie_cq_np_req=Signal(bool(1)),
        #pcie_cq_np_req_count=pcie_cq_np_req_count,

        # Completer Completion Interface
        s_axis_cc_tdata=m_axis_cc_tdata,
        s_axis_cc_tuser=m_axis_cc_tuser,
        s_axis_cc_tlast=m_axis_cc_tlast,
        s_axis_cc_tkeep=m_axis_cc_tkeep,
        s_axis_cc_tvalid=m_axis_cc_tvalid,
        s_axis_cc_tready=m_axis_cc_tready,

        # Requester reQuest Interface
        s_axis_rq_tdata=m_axis_rq_tdata,
        s_axis_rq_tuser=m_axis_rq_tuser,
        s_axis_rq_tlast=m_axis_rq_tlast,
        s_axis_rq_tkeep=m_axis_rq_tkeep,
        s_axis_rq_tvalid=m_axis_rq_tvalid,
        s_axis_rq_tready=m_axis_rq_tready,
        pcie_rq_seq_num=s_axis_rq_seq_num,
        pcie_rq_seq_num_vld=s_axis_rq_seq_num_valid,
        #pcie_rq_tag=pcie_rq_tag,
        #pcie_rq_tag_vld=pcie_rq_tag_vld,

        # Requester Completion Interface
        m_axis_rc_tdata=s_axis_rc_tdata,
        m_axis_rc_tuser=s_axis_rc_tuser,
        m_axis_rc_tlast=s_axis_rc_tlast,
        m_axis_rc_tkeep=s_axis_rc_tkeep,
        m_axis_rc_tvalid=s_axis_rc_tvalid,
        m_axis_rc_tready=s_axis_rc_tready,

        # Transmit Flow Control Interface
        pcie_tfc_nph_av=pcie_tfc_nph_av,
        pcie_tfc_npd_av=pcie_tfc_npd_av,

        # Configuration Management Interface
        cfg_mgmt_addr=cfg_mgmt_addr,
        cfg_mgmt_write=cfg_mgmt_write,
        cfg_mgmt_write_data=cfg_mgmt_write_data,
        cfg_mgmt_byte_enable=cfg_mgmt_byte_enable,
        cfg_mgmt_read=cfg_mgmt_read,
        cfg_mgmt_read_data=cfg_mgmt_read_data,
        cfg_mgmt_read_write_done=cfg_mgmt_read_write_done,
        #cfg_mgmt_type1_cfg_reg_access=cfg_mgmt_type1_cfg_reg_access,

        # Configuration Status Interface
        #cfg_phy_link_down=cfg_phy_link_down,
        #cfg_phy_link_status=cfg_phy_link_status,
        #cfg_negotiated_width=cfg_negotiated_width,
        #cfg_current_speed=cfg_current_speed,
        cfg_max_payload=cfg_max_payload,
        cfg_max_read_req=cfg_max_read_req,
        #cfg_function_status=cfg_function_status,
        #cfg_vf_status=cfg_vf_status,
        #cfg_function_power_state=cfg_function_power_state,
        #cfg_vf_power_state=cfg_vf_power_state,
        #cfg_link_power_state=cfg_link_power_state,
        #cfg_err_cor_out=cfg_err_cor_out,
        #cfg_err_nonfatal_out=cfg_err_nonfatal_out,
        #cfg_err_fatal_out=cfg_err_fatal_out,
        #cfg_ltr_enable=cfg_ltr_enable,
        #cfg_ltssm_state=cfg_ltssm_state,
        #cfg_rcb_status=cfg_rcb_status,
        #cfg_dpa_substate_change=cfg_dpa_substate_change,
        #cfg_obff_enable=cfg_obff_enable,
        #cfg_pl_status_change=cfg_pl_status_change,
        #cfg_tph_requester_enable=cfg_tph_requester_enable,
        #cfg_tph_st_mode=cfg_tph_st_mode,
        #cfg_vf_tph_requester_enable=cfg_vf_tph_requester_enable,
        #cfg_vf_tph_st_mode=cfg_vf_tph_st_mode,

        # Configuration Received Message Interface
        #cfg_msg_received=cfg_msg_received,
        #cfg_msg_received_data=cfg_msg_received_data,
        #cfg_msg_received_type=cfg_msg_received_type,

        # Configuration Transmit Message Interface
        #cfg_msg_transmit=cfg_msg_transmit,
        #cfg_msg_transmit_type=cfg_msg_transmit_type,
        #cfg_msg_transmit_data=cfg_msg_transmit_data,
        #cfg_msg_transmit_done=cfg_msg_transmit_done,

        # Configuration Flow Control Interface
        cfg_fc_ph=cfg_fc_ph,
        cfg_fc_pd=cfg_fc_pd,
        cfg_fc_nph=cfg_fc_nph,
        cfg_fc_npd=cfg_fc_npd,
        cfg_fc_cplh=cfg_fc_cplh,
        cfg_fc_cpld=cfg_fc_cpld,
        cfg_fc_sel=cfg_fc_sel,

        # Per-Function Status Interface
        #cfg_per_func_status_control=cfg_per_func_status_control,
        #cfg_per_func_status_data=cfg_per_func_status_data,

        # Configuration Control Interface
        #cfg_hot_reset_in=cfg_hot_reset_in,
        #cfg_hot_reset_out=cfg_hot_reset_out,
        #cfg_config_space_enable=cfg_config_space_enable,
        #cfg_per_function_update_done=cfg_per_function_update_done,
        #cfg_per_function_number=cfg_per_function_number,
        #cfg_per_function_output_request=cfg_per_function_output_request,
        #cfg_dsn=cfg_dsn,
        #cfg_ds_bus_number=cfg_ds_bus_number,
        #cfg_ds_device_number=cfg_ds_device_number,
        #cfg_ds_function_number=cfg_ds_function_number,
        #cfg_power_state_change_ack=cfg_power_state_change_ack,
        #cfg_power_state_change_interrupt=cfg_power_state_change_interrupt,
        cfg_err_cor_in=status_error_cor,
        cfg_err_uncor_in=status_error_uncor,
        #cfg_flr_done=cfg_flr_done,
        #cfg_vf_flr_done=cfg_vf_flr_done,
        #cfg_flr_in_process=cfg_flr_in_process,
        #cfg_vf_flr_in_process=cfg_vf_flr_in_process,
        #cfg_req_pm_transition_l23_ready=cfg_req_pm_transition_l23_ready,
        #cfg_link_training_enable=cfg_link_training_enable,

        # Configuration Interrupt Controller Interface
        #cfg_interrupt_int=cfg_interrupt_int,
        #cfg_interrupt_sent=cfg_interrupt_sent,
        #cfg_interrupt_pending=cfg_interrupt_pending,
        cfg_interrupt_msi_enable=cfg_interrupt_msi_enable,
        cfg_interrupt_msi_vf_enable=cfg_interrupt_msi_vf_enable,
        cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
        cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
        cfg_interrupt_msi_data=cfg_interrupt_msi_data,
        cfg_interrupt_msi_select=cfg_interrupt_msi_select,
        cfg_interrupt_msi_int=cfg_interrupt_msi_int,
        cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
        cfg_interrupt_msi_pending_status_data_enable=
        cfg_interrupt_msi_pending_status_data_enable,
        cfg_interrupt_msi_pending_status_function_num=
        cfg_interrupt_msi_pending_status_function_num,
        cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
        cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
        #cfg_interrupt_msix_enable=cfg_interrupt_msix_enable,
        #cfg_interrupt_msix_mask=cfg_interrupt_msix_mask,
        #cfg_interrupt_msix_vf_enable=cfg_interrupt_msix_vf_enable,
        #cfg_interrupt_msix_vf_mask=cfg_interrupt_msix_vf_mask,
        #cfg_interrupt_msix_address=cfg_interrupt_msix_address,
        #cfg_interrupt_msix_data=cfg_interrupt_msix_data,
        #cfg_interrupt_msix_int=cfg_interrupt_msix_int,
        #cfg_interrupt_msix_sent=cfg_interrupt_msix_sent,
        #cfg_interrupt_msix_fail=cfg_interrupt_msix_fail,
        cfg_interrupt_msi_attr=cfg_interrupt_msi_attr,
        cfg_interrupt_msi_tph_present=cfg_interrupt_msi_tph_present,
        cfg_interrupt_msi_tph_type=cfg_interrupt_msi_tph_type,
        cfg_interrupt_msi_tph_st_tag=cfg_interrupt_msi_tph_st_tag,
        cfg_interrupt_msi_function_number=cfg_interrupt_msi_function_number,

        # Configuration Extend Interface
        #cfg_ext_read_received=cfg_ext_read_received,
        #cfg_ext_write_received=cfg_ext_write_received,
        #cfg_ext_register_number=cfg_ext_register_number,
        #cfg_ext_function_number=cfg_ext_function_number,
        #cfg_ext_write_data=cfg_ext_write_data,
        #cfg_ext_write_byte_enable=cfg_ext_write_byte_enable,
        #cfg_ext_read_data=cfg_ext_read_data,
        #cfg_ext_read_data_valid=cfg_ext_read_data_valid,

        # Clock and Reset Interface
        user_clk=user_clk,
        user_reset=user_reset,
        sys_clk=sys_clk,
        sys_clk_gt=sys_clk,
        sys_reset=sys_reset,
        #pcie_perstn0_out=pcie_perstn0_out,
        #pcie_perstn1_in=pcie_perstn1_in,
        #pcie_perstn1_out=pcie_perstn1_out
    )

    # DUT
    if os.system(build_cmd):
        raise Exception("Error running build command")

    dut = Cosimulation(
        "vvp -m myhdl %s.vvp -lxt2" % testbench,
        clk=clk,
        rst=rst,
        current_test=current_test,
        clk_156mhz=clk_156mhz,
        rst_156mhz=rst_156mhz,
        clk_250mhz=user_clk,
        rst_250mhz=user_reset,
        btnu=btnu,
        btnl=btnl,
        btnd=btnd,
        btnr=btnr,
        btnc=btnc,
        sw=sw,
        led=led,
        i2c_scl_i=i2c_scl_i,
        i2c_scl_o=i2c_scl_o,
        i2c_scl_t=i2c_scl_t,
        i2c_sda_i=i2c_sda_i,
        i2c_sda_o=i2c_sda_o,
        i2c_sda_t=i2c_sda_t,
        m_axis_rq_tdata=m_axis_rq_tdata,
        m_axis_rq_tkeep=m_axis_rq_tkeep,
        m_axis_rq_tlast=m_axis_rq_tlast,
        m_axis_rq_tready=m_axis_rq_tready,
        m_axis_rq_tuser=m_axis_rq_tuser,
        m_axis_rq_tvalid=m_axis_rq_tvalid,
        s_axis_rc_tdata=s_axis_rc_tdata,
        s_axis_rc_tkeep=s_axis_rc_tkeep,
        s_axis_rc_tlast=s_axis_rc_tlast,
        s_axis_rc_tready=s_axis_rc_tready,
        s_axis_rc_tuser=s_axis_rc_tuser,
        s_axis_rc_tvalid=s_axis_rc_tvalid,
        s_axis_cq_tdata=s_axis_cq_tdata,
        s_axis_cq_tkeep=s_axis_cq_tkeep,
        s_axis_cq_tlast=s_axis_cq_tlast,
        s_axis_cq_tready=s_axis_cq_tready,
        s_axis_cq_tuser=s_axis_cq_tuser,
        s_axis_cq_tvalid=s_axis_cq_tvalid,
        m_axis_cc_tdata=m_axis_cc_tdata,
        m_axis_cc_tkeep=m_axis_cc_tkeep,
        m_axis_cc_tlast=m_axis_cc_tlast,
        m_axis_cc_tready=m_axis_cc_tready,
        m_axis_cc_tuser=m_axis_cc_tuser,
        m_axis_cc_tvalid=m_axis_cc_tvalid,
        s_axis_rq_seq_num=s_axis_rq_seq_num,
        s_axis_rq_seq_num_valid=s_axis_rq_seq_num_valid,
        pcie_tfc_nph_av=pcie_tfc_nph_av,
        pcie_tfc_npd_av=pcie_tfc_npd_av,
        cfg_max_payload=cfg_max_payload,
        cfg_max_read_req=cfg_max_read_req,
        cfg_mgmt_addr=cfg_mgmt_addr,
        cfg_mgmt_write=cfg_mgmt_write,
        cfg_mgmt_write_data=cfg_mgmt_write_data,
        cfg_mgmt_byte_enable=cfg_mgmt_byte_enable,
        cfg_mgmt_read=cfg_mgmt_read,
        cfg_mgmt_read_data=cfg_mgmt_read_data,
        cfg_mgmt_read_write_done=cfg_mgmt_read_write_done,
        cfg_fc_ph=cfg_fc_ph,
        cfg_fc_pd=cfg_fc_pd,
        cfg_fc_nph=cfg_fc_nph,
        cfg_fc_npd=cfg_fc_npd,
        cfg_fc_cplh=cfg_fc_cplh,
        cfg_fc_cpld=cfg_fc_cpld,
        cfg_fc_sel=cfg_fc_sel,
        cfg_interrupt_msi_enable=cfg_interrupt_msi_enable,
        cfg_interrupt_msi_vf_enable=cfg_interrupt_msi_vf_enable,
        cfg_interrupt_msi_int=cfg_interrupt_msi_int,
        cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
        cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
        cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
        cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
        cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
        cfg_interrupt_msi_select=cfg_interrupt_msi_select,
        cfg_interrupt_msi_data=cfg_interrupt_msi_data,
        cfg_interrupt_msi_pending_status_function_num=
        cfg_interrupt_msi_pending_status_function_num,
        cfg_interrupt_msi_pending_status_data_enable=
        cfg_interrupt_msi_pending_status_data_enable,
        cfg_interrupt_msi_attr=cfg_interrupt_msi_attr,
        cfg_interrupt_msi_tph_present=cfg_interrupt_msi_tph_present,
        cfg_interrupt_msi_tph_type=cfg_interrupt_msi_tph_type,
        cfg_interrupt_msi_tph_st_tag=cfg_interrupt_msi_tph_st_tag,
        cfg_interrupt_msi_function_number=cfg_interrupt_msi_function_number,
        status_error_cor=status_error_cor,
        status_error_uncor=status_error_uncor,
        qsfp_tx_clk_1=qsfp_tx_clk_1,
        qsfp_tx_rst_1=qsfp_tx_rst_1,
        qsfp_txd_1=qsfp_txd_1,
        qsfp_txc_1=qsfp_txc_1,
        qsfp_rx_clk_1=qsfp_rx_clk_1,
        qsfp_rx_rst_1=qsfp_rx_rst_1,
        qsfp_rxd_1=qsfp_rxd_1,
        qsfp_rxc_1=qsfp_rxc_1,
        qsfp_tx_clk_2=qsfp_tx_clk_2,
        qsfp_tx_rst_2=qsfp_tx_rst_2,
        qsfp_txd_2=qsfp_txd_2,
        qsfp_txc_2=qsfp_txc_2,
        qsfp_rx_clk_2=qsfp_rx_clk_2,
        qsfp_rx_rst_2=qsfp_rx_rst_2,
        qsfp_rxd_2=qsfp_rxd_2,
        qsfp_rxc_2=qsfp_rxc_2,
        qsfp_tx_clk_3=qsfp_tx_clk_3,
        qsfp_tx_rst_3=qsfp_tx_rst_3,
        qsfp_txd_3=qsfp_txd_3,
        qsfp_txc_3=qsfp_txc_3,
        qsfp_rx_clk_3=qsfp_rx_clk_3,
        qsfp_rx_rst_3=qsfp_rx_rst_3,
        qsfp_rxd_3=qsfp_rxd_3,
        qsfp_rxc_3=qsfp_rxc_3,
        qsfp_tx_clk_4=qsfp_tx_clk_4,
        qsfp_tx_rst_4=qsfp_tx_rst_4,
        qsfp_txd_4=qsfp_txd_4,
        qsfp_txc_4=qsfp_txc_4,
        qsfp_rx_clk_4=qsfp_rx_clk_4,
        qsfp_rx_rst_4=qsfp_rx_rst_4,
        qsfp_rxd_4=qsfp_rxd_4,
        qsfp_rxc_4=qsfp_rxc_4,
        qsfp_modsell=qsfp_modsell,
        qsfp_resetl=qsfp_resetl,
        qsfp_modprsl=qsfp_modprsl,
        qsfp_intl=qsfp_intl,
        qsfp_lpmode=qsfp_lpmode,
        flash_dq_i=flash_dq_i,
        flash_dq_o=flash_dq_o,
        flash_dq_oe=flash_dq_oe,
        flash_addr=flash_addr,
        flash_region=flash_region,
        flash_region_oe=flash_region_oe,
        flash_ce_n=flash_ce_n,
        flash_oe_n=flash_oe_n,
        flash_we_n=flash_we_n,
        flash_adv_n=flash_adv_n)

    @always(delay(5))
    def clkgen():
        clk.next = not clk

    @always(delay(3))
    def clkgen2():
        qsfp_tx_clk_1.next = not qsfp_tx_clk_1
        qsfp_rx_clk_1.next = not qsfp_rx_clk_1
        qsfp_tx_clk_2.next = not qsfp_tx_clk_2
        qsfp_rx_clk_2.next = not qsfp_rx_clk_2
        qsfp_tx_clk_3.next = not qsfp_tx_clk_3
        qsfp_rx_clk_3.next = not qsfp_rx_clk_3
        qsfp_tx_clk_4.next = not qsfp_tx_clk_4
        qsfp_rx_clk_4.next = not qsfp_rx_clk_4

    @always_comb
    def clk_logic():
        sys_clk.next = clk
        sys_reset.next = not rst

    loopback_enable = Signal(bool(0))

    @instance
    def loopback():
        while True:

            yield clk.posedge

            if loopback_enable:
                if not qsfp_1_sink.empty():
                    pkt = qsfp_1_sink.recv()
                    qsfp_1_source.send(pkt)
                if not qsfp_2_sink.empty():
                    pkt = qsfp_2_sink.recv()
                    qsfp_2_source.send(pkt)
                if not qsfp_3_sink.empty():
                    pkt = qsfp_3_sink.recv()
                    qsfp_3_source.send(pkt)
                if not qsfp_4_sink.empty():
                    pkt = qsfp_4_sink.recv()
                    qsfp_4_source.send(pkt)

    @instance
    def check():
        yield delay(100)
        yield clk.posedge
        rst.next = 1
        qsfp_tx_rst_1.next = 1
        qsfp_rx_rst_1.next = 1
        qsfp_tx_rst_2.next = 1
        qsfp_rx_rst_2.next = 1
        qsfp_tx_rst_3.next = 1
        qsfp_rx_rst_3.next = 1
        qsfp_tx_rst_4.next = 1
        qsfp_rx_rst_4.next = 1
        yield clk.posedge
        rst.next = 0
        qsfp_tx_rst_1.next = 0
        qsfp_rx_rst_1.next = 0
        qsfp_tx_rst_2.next = 0
        qsfp_rx_rst_2.next = 0
        qsfp_tx_rst_3.next = 0
        qsfp_rx_rst_3.next = 0
        qsfp_tx_rst_4.next = 0
        qsfp_rx_rst_4.next = 0
        yield clk.posedge
        yield delay(100)
        yield clk.posedge

        # testbench stimulus

        current_tag = 1

        yield clk.posedge
        print("test 1: enumeration")
        current_test.next = 1

        yield rc.enumerate(enable_bus_mastering=True, configure_msi=True)

        yield delay(100)

        yield clk.posedge
        print("test 2: init NIC")
        current_test.next = 2

        yield from driver.init_dev(dev.functions[0].get_id())
        yield from driver.interfaces[0].open()

        # enable queues
        yield from rc.mem_write_dword(
            driver.interfaces[0].ports[0].hw_addr +
            mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001)
        for k in range(driver.interfaces[0].tx_queue_count):
            yield from rc.mem_write_dword(
                driver.interfaces[0].ports[0].schedulers[0].hw_addr + 4 * k,
                0x00000003)

        yield from rc.mem_read(driver.hw_addr,
                               4)  # wait for all writes to complete

        yield delay(100)

        yield clk.posedge
        print("test 3: send and receive a packet")
        current_test.next = 3

        data = bytearray([x % 256 for x in range(1024)])

        yield from driver.interfaces[0].start_xmit(data, 0)

        yield qsfp_1_sink.wait()

        pkt = qsfp_1_sink.recv()
        print(pkt)

        qsfp_1_source.send(pkt)

        yield driver.interfaces[0].wait()

        pkt = driver.interfaces[0].recv()

        print(pkt)

        yield delay(100)

        yield clk.posedge
        print("test 4: checksum tests")
        current_test.next = 4

        test_frame = udp_ep.UDPFrame()
        test_frame.eth_dest_mac = 0xDAD1D2D3D4D5
        test_frame.eth_src_mac = 0x5A5152535455
        test_frame.eth_type = 0x0800
        test_frame.ip_version = 4
        test_frame.ip_ihl = 5
        test_frame.ip_length = None
        test_frame.ip_identification = 0
        test_frame.ip_flags = 2
        test_frame.ip_fragment_offset = 0
        test_frame.ip_ttl = 64
        test_frame.ip_protocol = 0x11
        test_frame.ip_header_checksum = None
        test_frame.ip_source_ip = 0xc0a80164
        test_frame.ip_dest_ip = 0xc0a80165
        test_frame.udp_source_port = 1
        test_frame.udp_dest_port = 2
        test_frame.udp_length = None
        test_frame.udp_checksum = None
        test_frame.payload = bytearray((x % 256 for x in range(256)))

        test_frame.set_udp_pseudo_header_checksum()

        axis_frame = test_frame.build_axis()

        yield from driver.interfaces[0].start_xmit(axis_frame.data, 0, 34, 6)

        yield qsfp_1_sink.wait()

        pkt = qsfp_1_sink.recv()
        print(pkt)

        qsfp_1_source.send(pkt)

        yield driver.interfaces[0].wait()

        pkt = driver.interfaces[0].recv()

        print(pkt)

        assert pkt.rx_checksum == frame_checksum(pkt.data)

        check_frame = udp_ep.UDPFrame()
        check_frame.parse_axis(pkt.data)

        assert check_frame.verify_checksums()

        yield delay(100)

        yield clk.posedge
        print("test 5: multiple small packets")
        current_test.next = 5

        count = 64

        pkts = [
            bytearray([(x + k) % 256 for x in range(64)]) for k in range(count)
        ]

        loopback_enable.next = True

        for p in pkts:
            yield from driver.interfaces[0].start_xmit(p, 0)

        for k in range(count):
            pkt = driver.interfaces[0].recv()

            if not pkt:
                yield driver.interfaces[0].wait()
                pkt = driver.interfaces[0].recv()

            print(pkt)
            assert pkt.data == pkts[k]
            assert frame_checksum(pkt.data) == pkt.rx_checksum

        loopback_enable.next = False

        yield delay(100)

        yield clk.posedge
        print("test 6: multiple large packets")
        current_test.next = 6

        count = 64

        pkts = [
            bytearray([(x + k) % 256 for x in range(1514)])
            for k in range(count)
        ]

        loopback_enable.next = True

        for p in pkts:
            yield from driver.interfaces[0].start_xmit(p, 0)

        for k in range(count):
            pkt = driver.interfaces[0].recv()

            if not pkt:
                yield driver.interfaces[0].wait()
                pkt = driver.interfaces[0].recv()

            print(pkt)
            assert pkt.data == pkts[k]
            assert frame_checksum(pkt.data) == pkt.rx_checksum

        loopback_enable.next = False

        yield delay(100)

        raise StopSimulation

    return instances()
def bench():

    # Parameters
    AXIS_PCIE_DATA_WIDTH = 256
    AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH / 32)
    AXIS_PCIE_RC_USER_WIDTH = 75
    AXIS_PCIE_RQ_USER_WIDTH = 60
    AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH
    AXI_ADDR_WIDTH = 64
    AXI_STRB_WIDTH = (AXI_DATA_WIDTH / 8)
    AXI_ID_WIDTH = 8
    AXI_MAX_BURST_LEN = 256
    PCIE_ADDR_WIDTH = 64
    PCIE_CLIENT_TAG = 1
    PCIE_TAG_WIDTH = 8
    PCIE_TAG_COUNT = 256
    PCIE_EXT_TAG_ENABLE = 1
    LEN_WIDTH = 20
    TAG_WIDTH = 8

    # Inputs
    clk = Signal(bool(0))
    rst = Signal(bool(0))
    current_test = Signal(intbv(0)[8:])

    s_axis_rc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
    s_axis_rc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
    s_axis_rc_tvalid = Signal(bool(0))
    s_axis_rc_tlast = Signal(bool(0))
    s_axis_rc_tuser = Signal(intbv(0)[AXIS_PCIE_RC_USER_WIDTH:])
    m_axis_rq_tready = Signal(bool(0))
    s_axis_pcie_rq_tag = Signal(intbv(0)[PCIE_TAG_WIDTH:])
    s_axis_pcie_rq_tag_valid = Signal(bool(0))
    s_axis_read_desc_pcie_addr = Signal(intbv(0)[PCIE_ADDR_WIDTH:])
    s_axis_read_desc_axi_addr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
    s_axis_read_desc_len = Signal(intbv(0)[LEN_WIDTH:])
    s_axis_read_desc_tag = Signal(intbv(0)[TAG_WIDTH:])
    s_axis_read_desc_valid = Signal(bool(0))
    m_axi_awready = Signal(bool(0))
    m_axi_wready = Signal(bool(0))
    m_axi_bid = Signal(intbv(0)[AXI_ID_WIDTH:])
    m_axi_bresp = Signal(intbv(0)[2:])
    m_axi_bvalid = Signal(bool(0))
    enable = Signal(bool(0))
    ext_tag_enable = Signal(bool(0))
    requester_id = Signal(intbv(0)[16:])
    requester_id_enable = Signal(bool(0))
    max_read_request_size = Signal(intbv(0)[3:])

    # Outputs
    s_axis_rc_tready = Signal(bool(0))
    m_axis_rq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
    m_axis_rq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
    m_axis_rq_tvalid = Signal(bool(0))
    m_axis_rq_tlast = Signal(bool(0))
    m_axis_rq_tuser = Signal(intbv(0)[AXIS_PCIE_RQ_USER_WIDTH:])
    s_axis_read_desc_ready = Signal(bool(0))
    m_axis_read_desc_status_tag = Signal(intbv(0)[TAG_WIDTH:])
    m_axis_read_desc_status_valid = Signal(bool(0))
    m_axi_awid = Signal(intbv(0)[AXI_ID_WIDTH:])
    m_axi_awaddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
    m_axi_awlen = Signal(intbv(0)[8:])
    m_axi_awsize = Signal(intbv(5)[3:])
    m_axi_awburst = Signal(intbv(1)[2:])
    m_axi_awlock = Signal(bool(0))
    m_axi_awcache = Signal(intbv(3)[4:])
    m_axi_awprot = Signal(intbv(2)[3:])
    m_axi_awvalid = Signal(bool(0))
    m_axi_wdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
    m_axi_wstrb = Signal(intbv(0)[AXI_STRB_WIDTH:])
    m_axi_wlast = Signal(bool(0))
    m_axi_wvalid = Signal(bool(0))
    m_axi_bready = Signal(bool(0))
    status_error_cor = Signal(bool(0))
    status_error_uncor = Signal(bool(0))

    # Clock and Reset Interface
    user_clk = Signal(bool(0))
    user_reset = Signal(bool(0))
    sys_clk = Signal(bool(0))
    sys_reset = Signal(bool(0))

    # AXI4 RAM model
    axi_ram_inst = axi.AXIRam(2**16)

    axi_ram_port0 = axi_ram_inst.create_port(user_clk,
                                             s_axi_awid=m_axi_awid,
                                             s_axi_awaddr=m_axi_awaddr,
                                             s_axi_awlen=m_axi_awlen,
                                             s_axi_awsize=m_axi_awsize,
                                             s_axi_awburst=m_axi_awburst,
                                             s_axi_awlock=m_axi_awlock,
                                             s_axi_awcache=m_axi_awcache,
                                             s_axi_awprot=m_axi_awprot,
                                             s_axi_awvalid=m_axi_awvalid,
                                             s_axi_awready=m_axi_awready,
                                             s_axi_wdata=m_axi_wdata,
                                             s_axi_wstrb=m_axi_wstrb,
                                             s_axi_wlast=m_axi_wlast,
                                             s_axi_wvalid=m_axi_wvalid,
                                             s_axi_wready=m_axi_wready,
                                             s_axi_bid=m_axi_bid,
                                             s_axi_bresp=m_axi_bresp,
                                             s_axi_bvalid=m_axi_bvalid,
                                             s_axi_bready=m_axi_bready,
                                             name='port0')

    # sources and sinks
    read_desc_source = axis_ep.AXIStreamSource()

    read_desc_source_logic = read_desc_source.create_logic(
        user_clk,
        user_reset,
        tdata=(s_axis_read_desc_pcie_addr, s_axis_read_desc_axi_addr,
               s_axis_read_desc_len, s_axis_read_desc_tag),
        tvalid=s_axis_read_desc_valid,
        tready=s_axis_read_desc_ready,
        name='read_desc_source')

    read_desc_status_sink = axis_ep.AXIStreamSink()

    read_desc_status_sink_logic = read_desc_status_sink.create_logic(
        user_clk,
        user_reset,
        tdata=(m_axis_read_desc_status_tag, ),
        tvalid=m_axis_read_desc_status_valid,
        name='read_desc_status_sink')

    # PCIe devices
    rc = pcie.RootComplex()

    mem_base, mem_data = rc.alloc_region(16 * 1024 * 1024)

    dev = pcie_us.UltrascalePCIe()

    dev.pcie_generation = 3
    dev.pcie_link_width = 8
    dev.user_clock_frequency = 256e6

    rc.make_port().connect(dev)

    cq_pause = Signal(bool(0))
    cc_pause = Signal(bool(0))
    rq_pause = Signal(bool(0))
    rc_pause = Signal(bool(0))

    pcie_logic = dev.create_logic(
        # Completer reQuest Interface
        m_axis_cq_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
        m_axis_cq_tuser=Signal(intbv(0)[85:]),
        m_axis_cq_tlast=Signal(bool(0)),
        m_axis_cq_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
        m_axis_cq_tvalid=Signal(bool(0)),
        m_axis_cq_tready=Signal(bool(1)),
        pcie_cq_np_req=Signal(bool(1)),
        pcie_cq_np_req_count=Signal(intbv(0)[6:]),

        # Completer Completion Interface
        s_axis_cc_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
        s_axis_cc_tuser=Signal(intbv(0)[33:]),
        s_axis_cc_tlast=Signal(bool(0)),
        s_axis_cc_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
        s_axis_cc_tvalid=Signal(bool(0)),
        s_axis_cc_tready=Signal(bool(0)),

        # Requester reQuest Interface
        s_axis_rq_tdata=m_axis_rq_tdata,
        s_axis_rq_tuser=m_axis_rq_tuser,
        s_axis_rq_tlast=m_axis_rq_tlast,
        s_axis_rq_tkeep=m_axis_rq_tkeep,
        s_axis_rq_tvalid=m_axis_rq_tvalid,
        s_axis_rq_tready=m_axis_rq_tready,
        # pcie_rq_seq_num=pcie_rq_seq_num,
        # pcie_rq_seq_num_vld=pcie_rq_seq_num_vld,
        # pcie_rq_tag=pcie_rq_tag,
        # pcie_rq_tag_av=pcie_rq_tag_av,
        # pcie_rq_tag_vld=pcie_rq_tag_vld,

        # Requester Completion Interface
        m_axis_rc_tdata=s_axis_rc_tdata,
        m_axis_rc_tuser=s_axis_rc_tuser,
        m_axis_rc_tlast=s_axis_rc_tlast,
        m_axis_rc_tkeep=s_axis_rc_tkeep,
        m_axis_rc_tvalid=s_axis_rc_tvalid,
        m_axis_rc_tready=s_axis_rc_tready,

        # Transmit Flow Control Interface
        # pcie_tfc_nph_av=pcie_tfc_nph_av,
        # pcie_tfc_npd_av=pcie_tfc_npd_av,

        # Configuration Control Interface
        # cfg_hot_reset_in=cfg_hot_reset_in,
        # cfg_hot_reset_out=cfg_hot_reset_out,
        # cfg_config_space_enable=cfg_config_space_enable,
        # cfg_per_function_update_done=cfg_per_function_update_done,
        # cfg_per_function_number=cfg_per_function_number,
        # cfg_per_function_output_request=cfg_per_function_output_request,
        # cfg_dsn=cfg_dsn,
        # cfg_ds_bus_number=cfg_ds_bus_number,
        # cfg_ds_device_number=cfg_ds_device_number,
        # cfg_ds_function_number=cfg_ds_function_number,
        # cfg_power_state_change_ack=cfg_power_state_change_ack,
        # cfg_power_state_change_interrupt=cfg_power_state_change_interrupt,
        # cfg_err_cor_in=cfg_err_cor_in,
        # cfg_err_uncor_in=cfg_err_uncor_in,
        # cfg_flr_done=cfg_flr_done,
        # cfg_vf_flr_done=cfg_vf_flr_done,
        # cfg_flr_in_process=cfg_flr_in_process,
        # cfg_vf_flr_in_process=cfg_vf_flr_in_process,
        # cfg_req_pm_transition_l23_ready=cfg_req_pm_transition_l23_ready,
        # cfg_link_training_enable=cfg_link_training_enable,

        # Clock and Reset Interface
        user_clk=user_clk,
        user_reset=user_reset,
        #user_lnk_up=user_lnk_up,
        sys_clk=sys_clk,
        sys_clk_gt=sys_clk,
        sys_reset=sys_reset,
        cq_pause=cq_pause,
        cc_pause=cc_pause,
        rq_pause=rq_pause,
        rc_pause=rc_pause)

    # DUT
    if os.system(build_cmd):
        raise Exception("Error running build command")

    dut = Cosimulation(
        "vvp -m myhdl %s.vvp -lxt2" % testbench,
        clk=user_clk,
        rst=user_reset,
        current_test=current_test,
        s_axis_rc_tdata=s_axis_rc_tdata,
        s_axis_rc_tkeep=s_axis_rc_tkeep,
        s_axis_rc_tvalid=s_axis_rc_tvalid,
        s_axis_rc_tready=s_axis_rc_tready,
        s_axis_rc_tlast=s_axis_rc_tlast,
        s_axis_rc_tuser=s_axis_rc_tuser,
        m_axis_rq_tdata=m_axis_rq_tdata,
        m_axis_rq_tkeep=m_axis_rq_tkeep,
        m_axis_rq_tvalid=m_axis_rq_tvalid,
        m_axis_rq_tready=m_axis_rq_tready,
        m_axis_rq_tlast=m_axis_rq_tlast,
        m_axis_rq_tuser=m_axis_rq_tuser,
        s_axis_pcie_rq_tag=s_axis_pcie_rq_tag,
        s_axis_pcie_rq_tag_valid=s_axis_pcie_rq_tag_valid,
        s_axis_read_desc_pcie_addr=s_axis_read_desc_pcie_addr,
        s_axis_read_desc_axi_addr=s_axis_read_desc_axi_addr,
        s_axis_read_desc_len=s_axis_read_desc_len,
        s_axis_read_desc_tag=s_axis_read_desc_tag,
        s_axis_read_desc_valid=s_axis_read_desc_valid,
        s_axis_read_desc_ready=s_axis_read_desc_ready,
        m_axis_read_desc_status_tag=m_axis_read_desc_status_tag,
        m_axis_read_desc_status_valid=m_axis_read_desc_status_valid,
        m_axi_awid=m_axi_awid,
        m_axi_awaddr=m_axi_awaddr,
        m_axi_awlen=m_axi_awlen,
        m_axi_awsize=m_axi_awsize,
        m_axi_awburst=m_axi_awburst,
        m_axi_awlock=m_axi_awlock,
        m_axi_awcache=m_axi_awcache,
        m_axi_awprot=m_axi_awprot,
        m_axi_awvalid=m_axi_awvalid,
        m_axi_awready=m_axi_awready,
        m_axi_wdata=m_axi_wdata,
        m_axi_wstrb=m_axi_wstrb,
        m_axi_wlast=m_axi_wlast,
        m_axi_wvalid=m_axi_wvalid,
        m_axi_wready=m_axi_wready,
        m_axi_bid=m_axi_bid,
        m_axi_bresp=m_axi_bresp,
        m_axi_bvalid=m_axi_bvalid,
        m_axi_bready=m_axi_bready,
        enable=enable,
        ext_tag_enable=ext_tag_enable,
        requester_id=requester_id,
        requester_id_enable=requester_id_enable,
        max_read_request_size=max_read_request_size,
        status_error_cor=status_error_cor,
        status_error_uncor=status_error_uncor)

    @always(delay(4))
    def clkgen():
        clk.next = not clk

    @always_comb
    def clk_logic():
        sys_clk.next = clk
        sys_reset.next = not rst

    status_error_cor_asserted = Signal(bool(0))
    status_error_uncor_asserted = Signal(bool(0))

    @always(clk.posedge)
    def monitor():
        if (status_error_cor):
            status_error_cor_asserted.next = 1
        if (status_error_uncor):
            status_error_uncor_asserted.next = 1

    cq_pause_toggle = Signal(bool(0))
    cc_pause_toggle = Signal(bool(0))
    rq_pause_toggle = Signal(bool(0))
    rc_pause_toggle = Signal(bool(0))

    @instance
    def pause_toggle():
        while True:
            if (cq_pause_toggle or cc_pause_toggle or rq_pause_toggle
                    or rc_pause_toggle):
                cq_pause.next = cq_pause_toggle
                cc_pause.next = cc_pause_toggle
                rq_pause.next = rq_pause_toggle
                rc_pause.next = rc_pause_toggle

                yield user_clk.posedge
                yield user_clk.posedge
                yield user_clk.posedge

                cq_pause.next = 0
                cc_pause.next = 0
                rq_pause.next = 0
                rc_pause.next = 0

            yield user_clk.posedge

    @instance
    def check():
        yield delay(100)
        yield clk.posedge
        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge
        yield delay(100)
        yield clk.posedge

        # testbench stimulus

        cur_tag = 1

        max_read_request_size.next = 2

        enable.next = 1

        yield user_clk.posedge
        print("test 1: enumeration")
        current_test.next = 1

        yield rc.enumerate(enable_bus_mastering=True)

        yield delay(100)

        yield user_clk.posedge
        print("test 2: PCIe read")
        current_test.next = 2

        pcie_addr = 0x00000000
        axi_addr = 0x00000000
        test_data = b'\x11\x22\x33\x44'

        mem_data[pcie_addr:pcie_addr + len(test_data)] = test_data

        data = mem_data[pcie_addr:pcie_addr + 32]
        for i in range(0, len(data), 16):
            print(" ".join(
                ("{:02x}".format(c) for c in bytearray(data[i:i + 16]))))

        read_desc_source.send([(pcie_addr, axi_addr, len(test_data), cur_tag)])

        yield read_desc_status_sink.wait(2000)

        yield delay(50)

        status = read_desc_status_sink.recv()

        print(status)

        data = axi_ram_inst.read_mem(axi_addr, 32)
        for i in range(0, len(data), 16):
            print(" ".join(
                ("{:02x}".format(c) for c in bytearray(data[i:i + 16]))))

        assert axi_ram_inst.read_mem(axi_addr, len(test_data)) == test_data

        cur_tag = (cur_tag + 1) % 256

        yield delay(100)

        yield user_clk.posedge
        print("test 3: various reads")
        current_test.next = 3

        for length in list(range(1, 35)) + list(range(128 - 4,
                                                      128 + 4)) + [1024]:
            for pcie_offset in list(range(8, 13)) + list(
                    range(4096 - 4, 4096 + 4)):
                for axi_offset in list(range(8, 41)) + list(
                        range(4096 - 32, 4096)):
                    for pause in [False, True]:
                        print("length %d, pcie_offset %d, axi_offset %d" %
                              (length, pcie_offset, axi_offset))
                        #pcie_addr = length * 0x100000000 + pcie_offset * 0x10000 + offset
                        pcie_addr = pcie_offset
                        axi_addr = axi_offset
                        test_data = bytearray([x % 256 for x in range(length)])

                        mem_data[pcie_addr:pcie_addr +
                                 len(test_data)] = test_data

                        data = mem_data[pcie_addr
                                        & 0xffff80:(pcie_addr & 0xffff80) + 64]
                        for i in range(0, len(data), 16):
                            print(" ".join(
                                ("{:02x}".format(c)
                                 for c in bytearray(data[i:i + 16]))))

                        axi_ram_inst.write_mem(
                            axi_addr & 0xffff80,
                            b'\xaa' * (len(test_data) + 256))

                        rq_pause_toggle.next = pause
                        rc_pause_toggle.next = pause

                        read_desc_source.send([(pcie_addr, axi_addr,
                                                len(test_data), cur_tag)])

                        yield read_desc_status_sink.wait(2000)

                        rq_pause_toggle.next = 0
                        rc_pause_toggle.next = 0

                        status = read_desc_status_sink.recv()

                        print(status)

                        assert status.data[0][0] == cur_tag

                        data = axi_ram_inst.read_mem(axi_addr & 0xfffff0, 64)
                        for i in range(0, len(data), 16):
                            print(" ".join(
                                ("{:02x}".format(c)
                                 for c in bytearray(data[i:i + 16]))))

                        assert axi_ram_inst.read_mem(
                            axi_addr - 8,
                            len(test_data) +
                            16) == b'\xaa' * 8 + test_data + b'\xaa' * 8

                        cur_tag = (cur_tag + 1) % 256

                        yield delay(50)

        raise StopSimulation

    return instances()
Beispiel #4
0
def bench():

    # Parameters
    dw = 128

    # Inputs
    clk = Signal(bool(0))
    rst = Signal(bool(0))
    current_test = Signal(intbv(0)[8:])

    # Outputs

    # Completer reQuest Interface
    m_axis_cq_tdata = Signal(intbv(0)[dw:])
    m_axis_cq_tuser = Signal(intbv(0)[85:])
    m_axis_cq_tlast = Signal(bool(0))
    m_axis_cq_tkeep = Signal(intbv(0)[int(dw / 32):])
    m_axis_cq_tvalid = Signal(bool(0))
    m_axis_cq_tready = Signal(bool(0))
    pcie_cq_np_req = Signal(bool(1))
    pcie_cq_np_req_count = Signal(intbv(0)[6:])

    # Completer Completion Interface
    s_axis_cc_tdata = Signal(intbv(0)[dw:])
    s_axis_cc_tuser = Signal(intbv(0)[33:])
    s_axis_cc_tlast = Signal(bool(0))
    s_axis_cc_tkeep = Signal(intbv(0)[int(dw / 32):])
    s_axis_cc_tvalid = Signal(bool(0))
    s_axis_cc_tready = Signal(bool(0))

    # Requester reQuest Interface
    s_axis_rq_tdata = Signal(intbv(0)[dw:])
    s_axis_rq_tuser = Signal(intbv(0)[60:])
    s_axis_rq_tlast = Signal(bool(0))
    s_axis_rq_tkeep = Signal(intbv(0)[int(dw / 32):])
    s_axis_rq_tvalid = Signal(bool(0))
    s_axis_rq_tready = Signal(bool(0))
    pcie_rq_seq_num = Signal(intbv(0)[4:])
    pcie_rq_seq_num_vld = Signal(bool(0))
    pcie_rq_tag = Signal(intbv(0)[6:])
    pcie_rq_tag_av = Signal(intbv(0)[2:])
    pcie_rq_tag_vld = Signal(bool(0))

    # Requester Completion Interface
    m_axis_rc_tdata = Signal(intbv(0)[dw:])
    m_axis_rc_tuser = Signal(intbv(0)[75:])
    m_axis_rc_tlast = Signal(bool(0))
    m_axis_rc_tkeep = Signal(intbv(0)[int(dw / 32):])
    m_axis_rc_tvalid = Signal(bool(0))
    m_axis_rc_tready = Signal(bool(0))

    # Transmit Flow Control Interface
    pcie_tfc_nph_av = Signal(intbv(0)[2:])
    pcie_tfc_npd_av = Signal(intbv(0)[2:])

    # Configuration Management Interface
    cfg_mgmt_addr = Signal(intbv(0)[19:])
    cfg_mgmt_write = Signal(bool(0))
    cfg_mgmt_write_data = Signal(intbv(0)[32:])
    cfg_mgmt_byte_enable = Signal(intbv(0)[4:])
    cfg_mgmt_read = Signal(bool(0))
    cfg_mgmt_read_data = Signal(intbv(0)[32:])
    cfg_mgmt_read_write_done = Signal(bool(0))
    cfg_mgmt_type1_cfg_reg_access = Signal(bool(0))

    # Configuration Status Interface
    cfg_phy_link_down = Signal(bool(0))
    cfg_phy_link_status = Signal(intbv(0)[2:])
    cfg_negotiated_width = Signal(intbv(0)[4:])
    cfg_current_speed = Signal(intbv(0)[3:])
    cfg_max_payload = Signal(intbv(0)[3:])
    cfg_max_read_req = Signal(intbv(0)[3:])
    cfg_function_status = Signal(intbv(0)[8:])
    cfg_vf_status = Signal(intbv(0)[12:])
    cfg_function_power_state = Signal(intbv(0)[6:])
    cfg_vf_power_state = Signal(intbv(0)[18:])
    cfg_link_power_state = Signal(intbv(0)[2:])
    cfg_err_cor_out = Signal(bool(0))
    cfg_err_nonfatal_out = Signal(bool(0))
    cfg_err_fatal_out = Signal(bool(0))
    cfg_ltr_enable = Signal(bool(0))
    cfg_ltssm_state = Signal(intbv(0)[6:])
    cfg_rcb_status = Signal(intbv(0)[2:])
    cfg_dpa_substate_change = Signal(intbv(0)[2:])
    cfg_obff_enable = Signal(intbv(0)[2:])
    cfg_pl_status_change = Signal(bool(0))
    cfg_tph_requester_enable = Signal(intbv(0)[2:])
    cfg_tph_st_mode = Signal(intbv(0)[6:])
    cfg_vf_tph_requester_enable = Signal(intbv(0)[6:])
    cfg_vf_tph_st_mode = Signal(intbv(0)[18:])

    # Configuration Received Message Interface
    cfg_msg_received = Signal(bool(0))
    cfg_msg_received_data = Signal(intbv(0)[8:])
    cfg_msg_received_type = Signal(intbv(0)[5:])

    # Configuration Transmit Message Interface
    cfg_msg_transmit = Signal(bool(0))
    cfg_msg_transmit_type = Signal(intbv(0)[3:])
    cfg_msg_transmit_data = Signal(intbv(0)[32:])
    cfg_msg_transmit_done = Signal(bool(0))

    # Configuration Flow Control Interface
    cfg_fc_ph = Signal(intbv(0)[8:])
    cfg_fc_pd = Signal(intbv(0)[12:])
    cfg_fc_nph = Signal(intbv(0)[8:])
    cfg_fc_npd = Signal(intbv(0)[12:])
    cfg_fc_cplh = Signal(intbv(0)[8:])
    cfg_fc_cpld = Signal(intbv(0)[12:])
    cfg_fc_sel = Signal(intbv(0)[3:])

    # Per-Function Status Interface
    cfg_per_func_status_control = Signal(intbv(0)[3:])
    cfg_per_func_status_data = Signal(intbv(0)[16:])

    # Configuration Control Interface
    cfg_hot_reset_in = Signal(bool(0))
    cfg_hot_reset_out = Signal(bool(0))
    cfg_config_space_enable = Signal(bool(1))
    cfg_per_function_update_done = Signal(bool(0))
    cfg_per_function_number = Signal(intbv(0)[3:])
    cfg_per_function_output_request = Signal(bool(0))
    cfg_dsn = Signal(intbv(0)[64:])
    cfg_ds_bus_number = Signal(intbv(0)[8:])
    cfg_ds_device_number = Signal(intbv(0)[5:])
    cfg_ds_function_number = Signal(intbv(0)[3:])
    cfg_power_state_change_ack = Signal(bool(0))
    cfg_power_state_change_interrupt = Signal(bool(0))
    cfg_err_cor_in = Signal(bool(0))
    cfg_err_uncor_in = Signal(bool(0))
    cfg_flr_done = Signal(intbv(0)[2:])
    cfg_vf_flr_done = Signal(intbv(0)[6:])
    cfg_flr_in_process = Signal(intbv(0)[2:])
    cfg_vf_flr_in_process = Signal(intbv(0)[6:])
    cfg_req_pm_transition_l23_ready = Signal(bool(0))
    cfg_link_training_enable = Signal(bool(1))

    # Configuration Interrupt Controller Interface
    cfg_interrupt_int = Signal(intbv(0)[4:])
    cfg_interrupt_sent = Signal(bool(0))
    cfg_interrupt_pending = Signal(intbv(0)[2:])
    cfg_interrupt_msi_enable = Signal(intbv(0)[4:])
    cfg_interrupt_msi_vf_enable = Signal(intbv(0)[8:])
    cfg_interrupt_msi_mmenable = Signal(intbv(0)[12:])
    cfg_interrupt_msi_mask_update = Signal(bool(0))
    cfg_interrupt_msi_data = Signal(intbv(0)[32:])
    cfg_interrupt_msi_select = Signal(intbv(0)[4:])
    cfg_interrupt_msi_int = Signal(intbv(0)[32:])
    cfg_interrupt_msi_pending_status = Signal(intbv(0)[32:])
    cfg_interrupt_msi_pending_status_data_enable = Signal(bool(0))
    cfg_interrupt_msi_pending_status_function_num = Signal(intbv(0)[4:])
    cfg_interrupt_msi_sent = Signal(bool(0))
    cfg_interrupt_msi_fail = Signal(bool(0))
    cfg_interrupt_msix_enable = Signal(intbv(0)[4:])
    cfg_interrupt_msix_mask = Signal(intbv(0)[4:])
    cfg_interrupt_msix_vf_enable = Signal(intbv(0)[8:])
    cfg_interrupt_msix_vf_mask = Signal(intbv(0)[8:])
    cfg_interrupt_msix_address = Signal(intbv(0)[64:])
    cfg_interrupt_msix_data = Signal(intbv(0)[32:])
    cfg_interrupt_msix_int = Signal(bool(0))
    cfg_interrupt_msix_sent = Signal(bool(0))
    cfg_interrupt_msix_fail = Signal(bool(0))
    cfg_interrupt_msi_attr = Signal(intbv(0)[3:])
    cfg_interrupt_msi_tph_present = Signal(bool(0))
    cfg_interrupt_msi_tph_type = Signal(intbv(0)[2:])
    cfg_interrupt_msi_tph_st_tag = Signal(intbv(0)[9:])
    cfg_interrupt_msi_function_number = Signal(intbv(0)[4:])

    # Configuration Extend Interface
    cfg_ext_read_received = Signal(bool(0))
    cfg_ext_write_received = Signal(bool(0))
    cfg_ext_register_number = Signal(intbv(0)[10:])
    cfg_ext_function_number = Signal(intbv(0)[8:])
    cfg_ext_write_data = Signal(intbv(0)[32:])
    cfg_ext_write_byte_enable = Signal(intbv(0)[4:])
    cfg_ext_read_data = Signal(intbv(0)[32:])
    cfg_ext_read_data_valid = Signal(bool(0))

    # Clock and Reset Interface
    user_clk = Signal(bool(0))
    user_reset = Signal(bool(0))
    user_lnk_up = Signal(bool(0))
    sys_clk = Signal(bool(0))
    sys_reset = Signal(bool(0))
    pcie_perstn0_out = Signal(bool(0))
    pcie_perstn1_in = Signal(bool(0))
    pcie_perstn1_out = Signal(bool(0))

    # sources and sinks
    cq_sink = axis_ep.AXIStreamSink()

    cq_sink_logic = cq_sink.create_logic(user_clk,
                                         user_reset,
                                         tdata=m_axis_cq_tdata,
                                         tuser=m_axis_cq_tuser,
                                         tlast=m_axis_cq_tlast,
                                         tkeep=m_axis_cq_tkeep,
                                         tvalid=m_axis_cq_tvalid,
                                         tready=m_axis_cq_tready,
                                         name='cq_sink')

    cc_source = axis_ep.AXIStreamSource()

    cc_source_logic = cc_source.create_logic(user_clk,
                                             user_reset,
                                             tdata=s_axis_cc_tdata,
                                             tuser=s_axis_cc_tuser,
                                             tlast=s_axis_cc_tlast,
                                             tkeep=s_axis_cc_tkeep,
                                             tvalid=s_axis_cc_tvalid,
                                             tready=s_axis_cc_tready,
                                             name='cc_source')

    rq_source = axis_ep.AXIStreamSource()

    rq_source_logic = rq_source.create_logic(user_clk,
                                             user_reset,
                                             tdata=s_axis_rq_tdata,
                                             tuser=s_axis_rq_tuser,
                                             tlast=s_axis_rq_tlast,
                                             tkeep=s_axis_rq_tkeep,
                                             tvalid=s_axis_rq_tvalid,
                                             tready=s_axis_rq_tready,
                                             name='rq_source')

    rc_sink = axis_ep.AXIStreamSink()

    rc_sink_logic = rc_sink.create_logic(user_clk,
                                         user_reset,
                                         tdata=m_axis_rc_tdata,
                                         tuser=m_axis_rc_tuser,
                                         tlast=m_axis_rc_tlast,
                                         tkeep=m_axis_rc_tkeep,
                                         tvalid=m_axis_rc_tvalid,
                                         tready=m_axis_rc_tready,
                                         name='rc_sink')

    # PCIe devices
    rc = pcie.RootComplex()

    mem_base, mem_data = rc.alloc_region(1024 * 1024)
    io_base, io_data = rc.alloc_io_region(1024)

    dev = pcie_us.UltrascalePCIe()

    dev.pcie_generation = 3
    dev.pcie_link_width = 4
    dev.user_clock_frequency = 256e6

    regions = [None] * 6
    regions[0] = bytearray(1024)
    regions[1] = bytearray(1024 * 1024)
    regions[3] = bytearray(1024)

    dev.functions[0].msi_multiple_message_capable = 5

    dev.functions[0].configure_bar(0, len(regions[0]))
    dev.functions[0].configure_bar(1, len(regions[1]), True, True)
    dev.functions[0].configure_bar(3, len(regions[3]), False, False, True)

    rc.make_port().connect(dev)

    pcie_logic = dev.create_logic(
        # Completer reQuest Interface
        m_axis_cq_tdata=m_axis_cq_tdata,
        m_axis_cq_tuser=m_axis_cq_tuser,
        m_axis_cq_tlast=m_axis_cq_tlast,
        m_axis_cq_tkeep=m_axis_cq_tkeep,
        m_axis_cq_tvalid=m_axis_cq_tvalid,
        m_axis_cq_tready=m_axis_cq_tready,
        pcie_cq_np_req=pcie_cq_np_req,
        pcie_cq_np_req_count=pcie_cq_np_req_count,

        # Completer Completion Interface
        s_axis_cc_tdata=s_axis_cc_tdata,
        s_axis_cc_tuser=s_axis_cc_tuser,
        s_axis_cc_tlast=s_axis_cc_tlast,
        s_axis_cc_tkeep=s_axis_cc_tkeep,
        s_axis_cc_tvalid=s_axis_cc_tvalid,
        s_axis_cc_tready=s_axis_cc_tready,

        # Requester reQuest Interface
        s_axis_rq_tdata=s_axis_rq_tdata,
        s_axis_rq_tuser=s_axis_rq_tuser,
        s_axis_rq_tlast=s_axis_rq_tlast,
        s_axis_rq_tkeep=s_axis_rq_tkeep,
        s_axis_rq_tvalid=s_axis_rq_tvalid,
        s_axis_rq_tready=s_axis_rq_tready,
        pcie_rq_seq_num=pcie_rq_seq_num,
        pcie_rq_seq_num_vld=pcie_rq_seq_num_vld,
        pcie_rq_tag=pcie_rq_tag,
        pcie_rq_tag_av=pcie_rq_tag_av,
        pcie_rq_tag_vld=pcie_rq_tag_vld,

        # Requester Completion Interface
        m_axis_rc_tdata=m_axis_rc_tdata,
        m_axis_rc_tuser=m_axis_rc_tuser,
        m_axis_rc_tlast=m_axis_rc_tlast,
        m_axis_rc_tkeep=m_axis_rc_tkeep,
        m_axis_rc_tvalid=m_axis_rc_tvalid,
        m_axis_rc_tready=m_axis_rc_tready,

        # Transmit Flow Control Interface
        pcie_tfc_nph_av=pcie_tfc_nph_av,
        pcie_tfc_npd_av=pcie_tfc_npd_av,

        # Configuration Management Interface
        cfg_mgmt_addr=cfg_mgmt_addr,
        cfg_mgmt_write=cfg_mgmt_write,
        cfg_mgmt_write_data=cfg_mgmt_write_data,
        cfg_mgmt_byte_enable=cfg_mgmt_byte_enable,
        cfg_mgmt_read=cfg_mgmt_read,
        cfg_mgmt_read_data=cfg_mgmt_read_data,
        cfg_mgmt_read_write_done=cfg_mgmt_read_write_done,
        cfg_mgmt_type1_cfg_reg_access=cfg_mgmt_type1_cfg_reg_access,

        # Configuration Status Interface
        cfg_phy_link_down=cfg_phy_link_down,
        cfg_phy_link_status=cfg_phy_link_status,
        cfg_negotiated_width=cfg_negotiated_width,
        cfg_current_speed=cfg_current_speed,
        cfg_max_payload=cfg_max_payload,
        cfg_max_read_req=cfg_max_read_req,
        cfg_function_status=cfg_function_status,
        cfg_vf_status=cfg_vf_status,
        cfg_function_power_state=cfg_function_power_state,
        cfg_vf_power_state=cfg_vf_power_state,
        cfg_link_power_state=cfg_link_power_state,
        cfg_err_cor_out=cfg_err_cor_out,
        cfg_err_nonfatal_out=cfg_err_nonfatal_out,
        cfg_err_fatal_out=cfg_err_fatal_out,
        cfg_ltr_enable=cfg_ltr_enable,
        cfg_ltssm_state=cfg_ltssm_state,
        cfg_rcb_status=cfg_rcb_status,
        cfg_dpa_substate_change=cfg_dpa_substate_change,
        cfg_obff_enable=cfg_obff_enable,
        cfg_pl_status_change=cfg_pl_status_change,
        cfg_tph_requester_enable=cfg_tph_requester_enable,
        cfg_tph_st_mode=cfg_tph_st_mode,
        cfg_vf_tph_requester_enable=cfg_vf_tph_requester_enable,
        cfg_vf_tph_st_mode=cfg_vf_tph_st_mode,

        # Configuration Received Message Interface
        cfg_msg_received=cfg_msg_received,
        cfg_msg_received_data=cfg_msg_received_data,
        cfg_msg_received_type=cfg_msg_received_type,

        # Configuration Transmit Message Interface
        cfg_msg_transmit=cfg_msg_transmit,
        cfg_msg_transmit_type=cfg_msg_transmit_type,
        cfg_msg_transmit_data=cfg_msg_transmit_data,
        cfg_msg_transmit_done=cfg_msg_transmit_done,

        # Configuration Flow Control Interface
        cfg_fc_ph=cfg_fc_ph,
        cfg_fc_pd=cfg_fc_pd,
        cfg_fc_nph=cfg_fc_nph,
        cfg_fc_npd=cfg_fc_npd,
        cfg_fc_cplh=cfg_fc_cplh,
        cfg_fc_cpld=cfg_fc_cpld,
        cfg_fc_sel=cfg_fc_sel,

        # Per-Function Status Interface
        cfg_per_func_status_control=cfg_per_func_status_control,
        cfg_per_func_status_data=cfg_per_func_status_data,

        # Configuration Control Interface
        cfg_hot_reset_in=cfg_hot_reset_in,
        cfg_hot_reset_out=cfg_hot_reset_out,
        cfg_config_space_enable=cfg_config_space_enable,
        cfg_per_function_update_done=cfg_per_function_update_done,
        cfg_per_function_number=cfg_per_function_number,
        cfg_per_function_output_request=cfg_per_function_output_request,
        cfg_dsn=cfg_dsn,
        cfg_ds_bus_number=cfg_ds_bus_number,
        cfg_ds_device_number=cfg_ds_device_number,
        cfg_ds_function_number=cfg_ds_function_number,
        cfg_power_state_change_ack=cfg_power_state_change_ack,
        cfg_power_state_change_interrupt=cfg_power_state_change_interrupt,
        cfg_err_cor_in=cfg_err_cor_in,
        cfg_err_uncor_in=cfg_err_uncor_in,
        cfg_flr_done=cfg_flr_done,
        cfg_vf_flr_done=cfg_vf_flr_done,
        cfg_flr_in_process=cfg_flr_in_process,
        cfg_vf_flr_in_process=cfg_vf_flr_in_process,
        cfg_req_pm_transition_l23_ready=cfg_req_pm_transition_l23_ready,
        cfg_link_training_enable=cfg_link_training_enable,

        # Configuration Interrupt Controller Interface
        cfg_interrupt_int=cfg_interrupt_int,
        cfg_interrupt_sent=cfg_interrupt_sent,
        cfg_interrupt_pending=cfg_interrupt_pending,
        cfg_interrupt_msi_enable=cfg_interrupt_msi_enable,
        cfg_interrupt_msi_vf_enable=cfg_interrupt_msi_vf_enable,
        cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
        cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
        cfg_interrupt_msi_data=cfg_interrupt_msi_data,
        cfg_interrupt_msi_select=cfg_interrupt_msi_select,
        cfg_interrupt_msi_int=cfg_interrupt_msi_int,
        cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
        cfg_interrupt_msi_pending_status_data_enable=
        cfg_interrupt_msi_pending_status_data_enable,
        cfg_interrupt_msi_pending_status_function_num=
        cfg_interrupt_msi_pending_status_function_num,
        cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
        cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
        cfg_interrupt_msix_enable=cfg_interrupt_msix_enable,
        cfg_interrupt_msix_mask=cfg_interrupt_msix_mask,
        cfg_interrupt_msix_vf_enable=cfg_interrupt_msix_vf_enable,
        cfg_interrupt_msix_vf_mask=cfg_interrupt_msix_vf_mask,
        cfg_interrupt_msix_address=cfg_interrupt_msix_address,
        cfg_interrupt_msix_data=cfg_interrupt_msix_data,
        cfg_interrupt_msix_int=cfg_interrupt_msix_int,
        cfg_interrupt_msix_sent=cfg_interrupt_msix_sent,
        cfg_interrupt_msix_fail=cfg_interrupt_msix_fail,
        cfg_interrupt_msi_attr=cfg_interrupt_msi_attr,
        cfg_interrupt_msi_tph_present=cfg_interrupt_msi_tph_present,
        cfg_interrupt_msi_tph_type=cfg_interrupt_msi_tph_type,
        cfg_interrupt_msi_tph_st_tag=cfg_interrupt_msi_tph_st_tag,
        cfg_interrupt_msi_function_number=cfg_interrupt_msi_function_number,

        # Configuration Extend Interface
        cfg_ext_read_received=cfg_ext_read_received,
        cfg_ext_write_received=cfg_ext_write_received,
        cfg_ext_register_number=cfg_ext_register_number,
        cfg_ext_function_number=cfg_ext_function_number,
        cfg_ext_write_data=cfg_ext_write_data,
        cfg_ext_write_byte_enable=cfg_ext_write_byte_enable,
        cfg_ext_read_data=cfg_ext_read_data,
        cfg_ext_read_data_valid=cfg_ext_read_data_valid,

        # Clock and Reset Interface
        user_clk=user_clk,
        user_reset=user_reset,
        user_lnk_up=user_lnk_up,
        sys_clk=sys_clk,
        sys_clk_gt=sys_clk,
        sys_reset=sys_reset,
        pcie_perstn0_out=pcie_perstn0_out,
        pcie_perstn1_in=pcie_perstn1_in,
        pcie_perstn1_out=pcie_perstn1_out)

    @always(delay(5))
    def clkgen():
        clk.next = not clk

    @always_comb
    def clk_logic():
        sys_clk.next = clk
        sys_reset.next = not rst

    @instance
    def user_logic():
        while True:
            yield clk.posedge

            # handle completer request
            if not cq_sink.empty():
                pkt = cq_sink.recv()

                tlp = pcie_us.TLP_us().unpack_us_cq(pkt, dw)

                print(tlp)

                if (tlp.fmt_type == pcie.TLP_IO_READ):
                    print("IO read")

                    cpl = pcie_us.TLP_us()
                    cpl.set_completion(tlp, pcie_us.PcieId(0, 0, 0))
                    cpl.fmt_type = pcie.TLP_CPL_DATA

                    region = tlp.bar_id
                    addr = tlp.address & 0xffff  # TODO
                    offset = 0
                    start_offset = None
                    mask = tlp.first_be

                    # perform operation
                    data = bytearray(4)

                    for k in range(4):
                        if mask & (1 << k):
                            if start_offset is None:
                                start_offset = offset
                        else:
                            if start_offset is not None and offset != start_offset:
                                data[start_offset:offset] = regions[region][
                                    addr + start_offset:addr + offset]
                            start_offset = None

                        offset += 1

                    if start_offset is not None and offset != start_offset:
                        data[start_offset:offset] = regions[region][
                            addr + start_offset:addr + offset]

                    cpl.set_data(data)
                    cpl.byte_count = 4
                    cpl.length = 1

                    cc_source.send(cpl.pack_us_cc(dw))
                elif (tlp.fmt_type == pcie.TLP_IO_WRITE):
                    print("IO write")

                    cpl = pcie_us.TLP_us()
                    cpl.set_completion(tlp, pcie_us.PcieId(0, 0, 0))

                    region = tlp.bar_id
                    addr = tlp.address & 0xffff  # TODO
                    offset = 0
                    start_offset = None
                    mask = tlp.first_be

                    # perform operation
                    data = tlp.get_data()

                    for k in range(4):
                        if mask & (1 << k):
                            if start_offset is None:
                                start_offset = offset
                        else:
                            if start_offset is not None and offset != start_offset:
                                regions[region][addr + start_offset:addr +
                                                offset] = data[
                                                    start_offset:offset]
                            start_offset = None

                        offset += 1

                    if start_offset is not None and offset != start_offset:
                        regions[region][addr + start_offset:addr +
                                        offset] = data[start_offset:offset]

                    cc_source.send(cpl.pack_us_cc(dw))
                if (tlp.fmt_type == pcie.TLP_MEM_READ
                        or tlp.fmt_type == pcie.TLP_MEM_READ_64):
                    print("Memory read")

                    # perform operation
                    region = tlp.bar_id
                    addr = tlp.address & 0xffff  # TODO
                    offset = 0
                    length = tlp.length

                    # perform read
                    data = regions[region][addr:addr + length * 4]

                    # prepare completion TLP(s)
                    n = 0
                    offset = 0
                    addr = tlp.address + offset
                    length = tlp.length * 4

                    while n < length:
                        cpl = pcie_us.TLP_us()
                        cpl.set_completion(tlp, pcie_us.PcieId(0, 0, 0))

                        byte_length = length - n
                        cpl.byte_count = byte_length
                        byte_length = min(
                            byte_length,
                            128 << dev.functions[0].max_payload_size
                        )  # max payload size
                        if byte_length > 128:
                            byte_length -= (addr +
                                            byte_length) % 128  # RCB align
                        byte_length = min(byte_length,
                                          0x1000 - (addr & 0xfff))  # 4k align

                        cpl.lower_address = addr & 0x7f

                        cpl.set_data(data[offset + n:offset + n + byte_length])

                        print("Completion: %s" % (repr(cpl)))
                        cc_source.send(cpl.pack_us_cc(dw))

                        n += byte_length
                        addr += byte_length
                if (tlp.fmt_type == pcie.TLP_MEM_WRITE
                        or tlp.fmt_type == pcie.TLP_MEM_WRITE_64):
                    print("Memory write")

                    # perform operation
                    region = tlp.bar_id
                    addr = tlp.address & 0xffff  # TODO
                    offset = 0
                    start_offset = None
                    mask = tlp.first_be
                    length = tlp.length

                    # perform write
                    data = tlp.get_data()

                    # first dword
                    for k in range(4):
                        if mask & (1 << k):
                            if start_offset is None:
                                start_offset = offset
                        else:
                            if start_offset is not None and offset != start_offset:
                                regions[region][addr + start_offset:addr +
                                                offset] = data[
                                                    start_offset:offset]
                            start_offset = None

                        offset += 1

                    if length > 1:
                        # middle dwords
                        if start_offset is None:
                            start_offset = offset
                        offset += length * 4

                        # last dword
                        mask = tlp.last_be

                        for k in range(4):
                            if mask & (1 << k):
                                if start_offset is None:
                                    start_offset = offset
                            else:
                                if start_offset is not None and offset != start_offset:
                                    regions[region][addr + start_offset:addr +
                                                    offset] = data[
                                                        start_offset:offset]
                                start_offset = None

                            offset += 1

                    if start_offset is not None and offset != start_offset:
                        regions[region][addr + start_offset:addr +
                                        offset] = data[start_offset:offset]

            # haldle requester completion
            #if not rc_sink.empty():
            #    pkt = rc_sink.recv()

    @instance
    def check():
        yield delay(100)
        yield clk.posedge
        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge
        yield delay(100)
        yield clk.posedge

        current_tag = 1

        yield clk.posedge
        print("test 1: enumeration")
        current_test.next = 1

        yield rc.enumerate(enable_bus_mastering=True, configure_msi=True)

        yield delay(100)

        yield clk.posedge
        print("test 2: IO and memory read/write")
        current_test.next = 2

        yield from rc.io_write(0x80000000, bytearray(range(16)), 100)
        assert regions[3][0:16] == bytearray(range(16))

        val = yield from rc.io_read(0x80000000, 16, 100)
        assert val == bytearray(range(16))

        yield from rc.mem_write(0x80000000, bytearray(range(16)), 100)
        yield delay(100)
        assert regions[0][0:16] == bytearray(range(16))

        val = yield from rc.mem_read(0x80000000, 16, 100)
        assert val == bytearray(range(16))

        yield from rc.mem_write(0x8000000000000000, bytearray(range(16)), 100)
        yield delay(100)
        assert regions[1][0:16] == bytearray(range(16))

        val = yield from rc.mem_read(0x8000000000000000, 16, 100)
        assert val == bytearray(range(16))

        yield delay(100)

        # yield clk.posedge
        # print("test 3: Large read/write")
        # current_test.next = 3

        # yield from rc.mem_write(0x8000000000000000, bytearray(range(256))*32, 100)
        # yield delay(100)
        # assert ep.read_region(1, 0, 256*32) == bytearray(range(256))*32

        # val = yield from rc.mem_read(0x8000000000000000, 256*32, 100)
        # assert val == bytearray(range(256))*32

        # yield delay(100)

        yield clk.posedge
        print("test 4: DMA")
        current_test.next = 4

        #yield ep.io_write(io_base, bytearray(range(16)), 100)

        data = bytearray(range(16))
        addr = io_base
        n = 0

        while n < len(data):
            tlp = pcie_us.TLP_us()
            tlp.fmt_type = pcie.TLP_IO_WRITE
            tlp.requester_id = pcie_us.PcieId(dev.bus_num, dev.device_num, 0)
            tlp.tag = current_tag

            first_pad = addr % 4
            byte_length = min(len(data) - n, 4 - first_pad)
            tlp.set_be_data(addr, data[n:n + byte_length])

            tlp.address = addr & ~3

            current_tag = (current_tag % 31) + 1

            rq_source.send(tlp.pack_us_rq(dw))
            yield rc_sink.wait(100)
            pkt = rc_sink.recv()

            if not pkt:
                raise Exception("Timeout")

            cpl = pcie_us.TLP_us().unpack_us_rc(pkt, dw)

            if cpl.status != pcie.CPL_STATUS_SC:
                raise Exception("Unsuccessful completion")

            n += byte_length
            addr += byte_length

        assert io_data[0:16] == bytearray(range(16))

        #val = yield from ep.io_read(io_base, 16, 100)

        length = 16
        data = b''
        addr = io_base
        n = 0

        while n < length:
            tlp = pcie_us.TLP_us()
            tlp.fmt_type = pcie.TLP_IO_READ
            tlp.requester_id = pcie_us.PcieId(dev.bus_num, dev.device_num, 0)
            tlp.tag = current_tag

            first_pad = addr % 4
            byte_length = min(length - n, 4 - first_pad)
            tlp.set_be(addr, byte_length)

            tlp.address = addr & ~3

            current_tag = (current_tag % 31) + 1

            rq_source.send(tlp.pack_us_rq(dw))
            yield rc_sink.wait(100)
            pkt = rc_sink.recv()

            if not pkt:
                raise Exception("Timeout")

            cpl = pcie_us.TLP_us().unpack_us_rc(pkt, dw)

            if cpl.status != pcie.CPL_STATUS_SC:
                raise Exception("Unsuccessful completion")
            else:
                d = struct.pack('<L', cpl.data[0])

            data += d[first_pad:]

            n += byte_length
            addr += byte_length

        data = data[:length]

        assert val == bytearray(range(16))

        #yield ep.mem_write(mem_base, bytearray(range(16)), 100)

        data = bytearray(range(16))
        addr = io_base
        n = 0

        while n < len(data):
            tlp = pcie_us.TLP_us()
            if addr > 0xffffffff:
                tlp.fmt_type = pcie.TLP_MEM_WRITE_64
            else:
                tlp.fmt_type = pcie.TLP_MEM_WRITE
            tlp.requester_id = pcie_us.PcieId(dev.bus_num, dev.device_num, 0)
            tlp.tag = current_tag

            first_pad = addr % 4
            byte_length = len(data) - n
            byte_length = min(byte_length,
                              (128 << dev.functions[0].max_payload_size) -
                              first_pad)  # max payload size
            byte_length = min(byte_length, 0x1000 - (addr & 0xfff))  # 4k align
            tlp.set_be_data(addr, data[n:n + byte_length])

            tlp.address = addr & ~3

            current_tag = (current_tag % 31) + 1

            rq_source.send(tlp.pack_us_rq(dw))

            n += byte_length
            addr += byte_length

        yield delay(100)
        assert mem_data[0:16] == bytearray(range(16))

        #val = yield from ep.mem_read(mem_base, 16, 100)

        length = 16
        data = b''
        addr = mem_base
        n = 0

        while n < length:
            tlp = pcie_us.TLP_us()
            if addr > 0xffffffff:
                tlp.fmt_type = pcie.TLP_MEM_READ_64
            else:
                tlp.fmt_type = pcie.TLP_MEM_READ
            tlp.requester_id = pcie_us.PcieId(dev.bus_num, dev.device_num, 0)
            tlp.tag = current_tag

            first_pad = addr % 4
            byte_length = length - n
            byte_length = min(byte_length,
                              (128 << dev.functions[0].max_read_request_size) -
                              first_pad)  # max read request size
            byte_length = min(byte_length, 0x1000 - (addr & 0xfff))  # 4k align
            tlp.set_be(addr, byte_length)

            tlp.address = addr & ~3

            current_tag = (current_tag % 31) + 1

            rq_source.send(tlp.pack_us_rq(dw))

            m = 0

            while m < byte_length:
                yield rc_sink.wait(100)
                pkt = rc_sink.recv()

                if not pkt:
                    raise Exception("Timeout")

                cpl = pcie_us.TLP_us().unpack_us_rc(pkt, dw)

                if cpl.status != pcie.CPL_STATUS_SC:
                    raise Exception("Unsuccessful completion")
                else:
                    dw_len = cpl.length
                    if dw_len == 0:
                        dw_len = 1024
                    d = bytearray()

                    for k in range(dw_len):
                        d.extend(struct.pack('<L', cpl.data[k]))

                    offset = cpl.lower_address & 3
                    data += d[offset:offset + cpl.byte_count]

                m += len(d) - offset

            n += byte_length
            addr += byte_length

        assert val == bytearray(range(16))

        yield delay(100)

        yield clk.posedge
        print("test 5: MSI")
        current_test.next = 5

        yield user_clk.posedge
        cfg_interrupt_msi_int.next = 1 << 4
        yield user_clk.posedge
        cfg_interrupt_msi_int.next = 0

        yield rc.msi_get_signal(dev.functions[0].get_id(), 4)

        yield delay(100)

        raise StopSimulation

    return instances()
def bench():

    # Parameters
    AXIS_PCIE_DATA_WIDTH = 256
    AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
    AXIS_PCIE_CQ_USER_WIDTH = 85
    AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH
    AXI_ADDR_WIDTH = 64
    AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8)
    AXI_ID_WIDTH = 8
    AXI_MAX_BURST_LEN = 256

    # Inputs
    clk = Signal(bool(0))
    rst = Signal(bool(0))
    current_test = Signal(intbv(0)[8:])

    s_axis_cq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
    s_axis_cq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
    s_axis_cq_tvalid = Signal(bool(0))
    s_axis_cq_tlast = Signal(bool(0))
    s_axis_cq_tuser = Signal(intbv(0)[AXIS_PCIE_CQ_USER_WIDTH:])
    m_axi_awready = Signal(bool(0))
    m_axi_wready = Signal(bool(0))
    m_axi_bid = Signal(intbv(0)[AXI_ID_WIDTH:])
    m_axi_bresp = Signal(intbv(0)[2:])
    m_axi_bvalid = Signal(bool(0))

    # Outputs
    s_axis_cq_tready = Signal(bool(0))
    m_axi_awid = Signal(intbv(0)[AXI_ID_WIDTH:])
    m_axi_awaddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
    m_axi_awlen = Signal(intbv(0)[8:])
    m_axi_awsize = Signal(intbv(5)[3:])
    m_axi_awburst = Signal(intbv(1)[2:])
    m_axi_awlock = Signal(bool(0))
    m_axi_awcache = Signal(intbv(3)[4:])
    m_axi_awprot = Signal(intbv(2)[3:])
    m_axi_awvalid = Signal(bool(0))
    m_axi_wdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
    m_axi_wstrb = Signal(intbv(0)[AXI_STRB_WIDTH:])
    m_axi_wlast = Signal(bool(0))
    m_axi_wvalid = Signal(bool(0))
    m_axi_bready = Signal(bool(1))
    status_error_uncor = Signal(bool(0))

    # Clock and Reset Interface
    user_clk=Signal(bool(0))
    user_reset=Signal(bool(0))
    sys_clk=Signal(bool(0))
    sys_reset=Signal(bool(0))

    # AXI4 RAM model
    axi_ram_inst = axi.AXIRam(2**16)

    axi_ram_port0 = axi_ram_inst.create_port(
        user_clk,
        s_axi_awid=m_axi_awid,
        s_axi_awaddr=m_axi_awaddr,
        s_axi_awlen=m_axi_awlen,
        s_axi_awsize=m_axi_awsize,
        s_axi_awburst=m_axi_awburst,
        s_axi_awlock=m_axi_awlock,
        s_axi_awcache=m_axi_awcache,
        s_axi_awprot=m_axi_awprot,
        s_axi_awvalid=m_axi_awvalid,
        s_axi_awready=m_axi_awready,
        s_axi_wdata=m_axi_wdata,
        s_axi_wstrb=m_axi_wstrb,
        s_axi_wlast=m_axi_wlast,
        s_axi_wvalid=m_axi_wvalid,
        s_axi_wready=m_axi_wready,
        s_axi_bid=m_axi_bid,
        s_axi_bresp=m_axi_bresp,
        s_axi_bvalid=m_axi_bvalid,
        s_axi_bready=m_axi_bready,
        name='port0'
    )

    # PCIe devices
    rc = pcie.RootComplex()

    dev = pcie_us.UltrascalePCIe()

    dev.pcie_generation = 3
    dev.pcie_link_width = 8
    dev.user_clock_frequency = 250e6

    dev.functions[0].configure_bar(0, 16*1024*1024)

    rc.make_port().connect(dev)

    cq_pause = Signal(bool(0))
    cc_pause = Signal(bool(0))
    rq_pause = Signal(bool(0))
    rc_pause = Signal(bool(0))

    pcie_logic = dev.create_logic(
        # Completer reQuest Interface
        m_axis_cq_tdata=s_axis_cq_tdata,
        m_axis_cq_tuser=s_axis_cq_tuser,
        m_axis_cq_tlast=s_axis_cq_tlast,
        m_axis_cq_tkeep=s_axis_cq_tkeep,
        m_axis_cq_tvalid=s_axis_cq_tvalid,
        m_axis_cq_tready=s_axis_cq_tready,
        #pcie_cq_np_req=pcie_cq_np_req,
        #pcie_cq_np_req_count=pcie_cq_np_req_count,

        # Completer Completion Interface
        s_axis_cc_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
        s_axis_cc_tuser=Signal(intbv(0)[33:]),
        s_axis_cc_tlast=Signal(bool(0)),
        s_axis_cc_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
        s_axis_cc_tvalid=Signal(bool(0)),
        s_axis_cc_tready=Signal(bool(0)),

        # Requester reQuest Interface
        s_axis_rq_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
        s_axis_rq_tuser=Signal(intbv(0)[60:]),
        s_axis_rq_tlast=Signal(bool(0)),
        s_axis_rq_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
        s_axis_rq_tvalid=Signal(bool(0)),
        s_axis_rq_tready=Signal(bool(1)),
        # pcie_rq_seq_num=pcie_rq_seq_num,
        # pcie_rq_seq_num_vld=pcie_rq_seq_num_vld,
        # pcie_rq_tag=pcie_rq_tag,
        # pcie_rq_tag_av=pcie_rq_tag_av,
        # pcie_rq_tag_vld=pcie_rq_tag_vld,

        # Requester Completion Interface
        m_axis_rc_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
        m_axis_rc_tuser=Signal(intbv(0)[75:]),
        m_axis_rc_tlast=Signal(bool(0)),
        m_axis_rc_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
        m_axis_rc_tvalid=Signal(bool(0)),
        m_axis_rc_tready=Signal(bool(0)),

        # Transmit Flow Control Interface
        # pcie_tfc_nph_av=pcie_tfc_nph_av,
        # pcie_tfc_npd_av=pcie_tfc_npd_av,

        # Configuration Control Interface
        # cfg_hot_reset_in=cfg_hot_reset_in,
        # cfg_hot_reset_out=cfg_hot_reset_out,
        # cfg_config_space_enable=cfg_config_space_enable,
        # cfg_per_function_update_done=cfg_per_function_update_done,
        # cfg_per_function_number=cfg_per_function_number,
        # cfg_per_function_output_request=cfg_per_function_output_request,
        # cfg_dsn=cfg_dsn,
        # cfg_ds_bus_number=cfg_ds_bus_number,
        # cfg_ds_device_number=cfg_ds_device_number,
        # cfg_ds_function_number=cfg_ds_function_number,
        # cfg_power_state_change_ack=cfg_power_state_change_ack,
        # cfg_power_state_change_interrupt=cfg_power_state_change_interrupt,
        # cfg_err_cor_in=cfg_err_cor_in,
        # cfg_err_uncor_in=cfg_err_uncor_in,
        # cfg_flr_done=cfg_flr_done,
        # cfg_vf_flr_done=cfg_vf_flr_done,
        # cfg_flr_in_process=cfg_flr_in_process,
        # cfg_vf_flr_in_process=cfg_vf_flr_in_process,
        # cfg_req_pm_transition_l23_ready=cfg_req_pm_transition_l23_ready,
        # cfg_link_training_enable=cfg_link_training_enable,

        # Clock and Reset Interface
        user_clk=user_clk,
        user_reset=user_reset,
        #user_lnk_up=user_lnk_up,
        sys_clk=sys_clk,
        sys_clk_gt=sys_clk,
        sys_reset=sys_reset,

        cq_pause=cq_pause,
        cc_pause=cc_pause,
        rq_pause=rq_pause,
        rc_pause=rc_pause
    )

    # DUT
    if os.system(build_cmd):
        raise Exception("Error running build command")

    dut = Cosimulation(
        "vvp -m myhdl %s.vvp -lxt2" % testbench,
        clk=user_clk,
        rst=user_reset,
        current_test=current_test,
        s_axis_cq_tdata=s_axis_cq_tdata,
        s_axis_cq_tkeep=s_axis_cq_tkeep,
        s_axis_cq_tvalid=s_axis_cq_tvalid,
        s_axis_cq_tready=s_axis_cq_tready,
        s_axis_cq_tlast=s_axis_cq_tlast,
        s_axis_cq_tuser=s_axis_cq_tuser,
        m_axi_awid=m_axi_awid,
        m_axi_awaddr=m_axi_awaddr,
        m_axi_awlen=m_axi_awlen,
        m_axi_awsize=m_axi_awsize,
        m_axi_awburst=m_axi_awburst,
        m_axi_awlock=m_axi_awlock,
        m_axi_awcache=m_axi_awcache,
        m_axi_awprot=m_axi_awprot,
        m_axi_awvalid=m_axi_awvalid,
        m_axi_awready=m_axi_awready,
        m_axi_wdata=m_axi_wdata,
        m_axi_wstrb=m_axi_wstrb,
        m_axi_wlast=m_axi_wlast,
        m_axi_wvalid=m_axi_wvalid,
        m_axi_wready=m_axi_wready,
        m_axi_bid=m_axi_bid,
        m_axi_bresp=m_axi_bresp,
        m_axi_bvalid=m_axi_bvalid,
        m_axi_bready=m_axi_bready,
        status_error_uncor=status_error_uncor
    )

    @always(delay(4))
    def clkgen():
        clk.next = not clk

    @always_comb
    def clk_logic():
        sys_clk.next = clk
        sys_reset.next = not rst

    status_error_uncor_asserted = Signal(bool(0))

    @always(user_clk.posedge)
    def monitor():
        if (status_error_uncor):
            status_error_uncor_asserted.next = 1

    cq_pause_toggle = Signal(bool(0))
    cc_pause_toggle = Signal(bool(0))
    rq_pause_toggle = Signal(bool(0))
    rc_pause_toggle = Signal(bool(0))

    @instance
    def pause_toggle():
        while True:
            if (cq_pause_toggle or cc_pause_toggle or rq_pause_toggle or rc_pause_toggle):
                cq_pause.next = cq_pause_toggle
                cc_pause.next = cc_pause_toggle
                rq_pause.next = rq_pause_toggle
                rc_pause.next = rc_pause_toggle

                yield user_clk.posedge
                yield user_clk.posedge
                yield user_clk.posedge

                cq_pause.next = 0
                cc_pause.next = 0
                rq_pause.next = 0
                rc_pause.next = 0

            yield user_clk.posedge

    @instance
    def check():
        yield delay(100)
        yield clk.posedge
        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge
        yield delay(100)
        yield clk.posedge

        # testbench stimulus

        yield user_clk.posedge
        print("test 1: enumeration")
        current_test.next = 1

        yield rc.enumerate()

        dev_bar0 = rc.tree[0][0].bar[0]

        yield delay(100)

        yield clk.posedge
        print("test 2: memory write")
        current_test.next = 2

        pcie_addr = 0x00000000
        test_data = b'\x11\x22\x33\x44'

        yield rc.mem_write(dev_bar0+pcie_addr, test_data)

        yield delay(300)

        data = axi_ram_inst.read_mem(pcie_addr, 32)
        for i in range(0, len(data), 16):
            print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))

        assert axi_ram_inst.read_mem(pcie_addr, len(test_data)) == test_data

        assert not status_error_uncor_asserted

        yield delay(100)

        yield user_clk.posedge
        print("test 3: various writes")
        current_test.next = 3

        for length in list(range(1,34))+[1024]:
            for pcie_offset in list(range(8,41))+list(range(4096-32,4096)):
                for pause in [False, True]:
                    print("length %d, pcie_offset %d"% (length, pcie_offset))
                    #pcie_addr = length * 0x100000000 + pcie_offset * 0x10000 + offset
                    pcie_addr = pcie_offset
                    test_data = bytearray([x%256 for x in range(length)])

                    axi_ram_inst.write_mem(pcie_addr & 0xffff80, b'\x55'*(len(test_data)+256))

                    cq_pause_toggle.next = pause

                    yield from rc.mem_write(dev_bar0+pcie_addr, test_data)

                    yield delay(int(length*4+60))

                    cq_pause_toggle.next = 0

                    data = axi_ram_inst.read_mem(pcie_addr&0xfffff0, 64)
                    for i in range(0, len(data), 16):
                        print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))

                    assert axi_ram_inst.read_mem(pcie_addr-1, len(test_data)+2) == b'\x55'+test_data+b'\x55'

                    assert not status_error_uncor_asserted

                    yield delay(100)

        yield clk.posedge
        print("test 4: bad request")
        current_test.next = 4

        try:
            yield from rc.mem_read(dev_bar0, 4, 100)
        except:
            print("Caught timeout exception")
            pass
        else:
            assert False

        assert status_error_uncor_asserted

        status_error_uncor_asserted.next = False

        yield delay(100)

        raise StopSimulation

    return instances()
Beispiel #6
0
def bench():

    # Parameters
    AXIS_PCIE_DATA_WIDTH = 256
    AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH / 32)
    AXIS_PCIE_RC_USER_WIDTH = 75
    AXIS_PCIE_RQ_USER_WIDTH = 60
    AXIS_PCIE_CQ_USER_WIDTH = 85
    AXIS_PCIE_CC_USER_WIDTH = 33

    # Inputs
    clk = Signal(bool(0))
    rst = Signal(bool(0))
    current_test = Signal(intbv(0)[8:])

    clk_156mhz = Signal(bool(0))
    rst_156mhz = Signal(bool(0))
    clk_250mhz = Signal(bool(0))
    rst_250mhz = Signal(bool(0))
    m_axis_rq_tready = Signal(bool(0))
    s_axis_rc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
    s_axis_rc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
    s_axis_rc_tlast = Signal(bool(0))
    s_axis_rc_tuser = Signal(intbv(0)[AXIS_PCIE_RC_USER_WIDTH:])
    s_axis_rc_tvalid = Signal(bool(0))
    s_axis_cq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
    s_axis_cq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
    s_axis_cq_tlast = Signal(bool(0))
    s_axis_cq_tuser = Signal(intbv(0)[AXIS_PCIE_CQ_USER_WIDTH:])
    s_axis_cq_tvalid = Signal(bool(0))
    m_axis_cc_tready = Signal(bool(0))
    pcie_tfc_nph_av = Signal(intbv(0)[2:])
    pcie_tfc_npd_av = Signal(intbv(0)[2:])
    cfg_max_payload = Signal(intbv(0)[3:])
    cfg_max_read_req = Signal(intbv(0)[3:])
    cfg_mgmt_read_data = Signal(intbv(0)[32:])
    cfg_mgmt_read_write_done = Signal(bool(0))
    cfg_interrupt_msi_enable = Signal(intbv(0)[4:])
    cfg_interrupt_msi_vf_enable = Signal(intbv(0)[8:])
    cfg_interrupt_msi_mmenable = Signal(intbv(0)[12:])
    cfg_interrupt_msi_mask_update = Signal(bool(0))
    cfg_interrupt_msi_data = Signal(intbv(0)[32:])
    cfg_interrupt_msi_sent = Signal(bool(0))
    cfg_interrupt_msi_fail = Signal(bool(0))
    sfp_1_tx_clk = Signal(bool(0))
    sfp_1_tx_rst = Signal(bool(0))
    sfp_1_rx_clk = Signal(bool(0))
    sfp_1_rx_rst = Signal(bool(0))
    sfp_1_rxd = Signal(intbv(0)[64:])
    sfp_1_rxc = Signal(intbv(0)[8:])
    sfp_2_tx_clk = Signal(bool(0))
    sfp_2_tx_rst = Signal(bool(0))
    sfp_2_rx_clk = Signal(bool(0))
    sfp_2_rx_rst = Signal(bool(0))
    sfp_2_rxd = Signal(intbv(0)[64:])
    sfp_2_rxc = Signal(intbv(0)[8:])
    sfp_i2c_scl_i = Signal(bool(1))
    sfp_1_i2c_sda_i = Signal(bool(1))
    sfp_2_i2c_sda_i = Signal(bool(1))
    eeprom_i2c_scl_i = Signal(bool(1))
    eeprom_i2c_sda_i = Signal(bool(1))
    flash_dq_i = Signal(intbv(0)[16:])

    # Outputs
    sfp_1_led = Signal(intbv(0)[2:])
    sfp_2_led = Signal(intbv(0)[2:])
    sma_led = Signal(intbv(0)[2:])
    m_axis_rq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
    m_axis_rq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
    m_axis_rq_tlast = Signal(bool(0))
    m_axis_rq_tuser = Signal(intbv(0)[AXIS_PCIE_RQ_USER_WIDTH:])
    m_axis_rq_tvalid = Signal(bool(0))
    s_axis_rc_tready = Signal(bool(0))
    s_axis_cq_tready = Signal(bool(0))
    m_axis_cc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
    m_axis_cc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
    m_axis_cc_tlast = Signal(bool(0))
    m_axis_cc_tuser = Signal(intbv(0)[AXIS_PCIE_CC_USER_WIDTH:])
    m_axis_cc_tvalid = Signal(bool(0))
    status_error_cor = Signal(bool(0))
    status_error_uncor = Signal(bool(0))
    cfg_mgmt_addr = Signal(intbv(0)[19:])
    cfg_mgmt_write = Signal(bool(0))
    cfg_mgmt_write_data = Signal(intbv(0)[32:])
    cfg_mgmt_byte_enable = Signal(intbv(0)[4:])
    cfg_mgmt_read = Signal(bool(0))
    cfg_interrupt_msi_int = Signal(intbv(0)[32:])
    cfg_interrupt_msi_pending_status = Signal(intbv(0)[32:])
    cfg_interrupt_msi_select = Signal(intbv(0)[4:])
    cfg_interrupt_msi_pending_status_function_num = Signal(intbv(0)[4:])
    cfg_interrupt_msi_pending_status_data_enable = Signal(bool(0))
    cfg_interrupt_msi_attr = Signal(intbv(0)[3:])
    cfg_interrupt_msi_tph_present = Signal(bool(0))
    cfg_interrupt_msi_tph_type = Signal(intbv(0)[2:])
    cfg_interrupt_msi_tph_st_tag = Signal(intbv(0)[9:])
    cfg_interrupt_msi_function_number = Signal(intbv(0)[4:])
    sfp_1_txd = Signal(intbv(0)[64:])
    sfp_1_txc = Signal(intbv(0)[8:])
    sfp_2_txd = Signal(intbv(0)[64:])
    sfp_2_txc = Signal(intbv(0)[8:])
    sfp_i2c_scl_o = Signal(bool(1))
    sfp_i2c_scl_t = Signal(bool(1))
    sfp_1_i2c_sda_o = Signal(bool(1))
    sfp_1_i2c_sda_t = Signal(bool(1))
    sfp_2_i2c_sda_o = Signal(bool(1))
    sfp_2_i2c_sda_t = Signal(bool(1))
    eeprom_i2c_scl_o = Signal(bool(1))
    eeprom_i2c_scl_t = Signal(bool(1))
    eeprom_i2c_sda_o = Signal(bool(1))
    eeprom_i2c_sda_t = Signal(bool(1))
    flash_dq_o = Signal(intbv(0)[16:])
    flash_dq_oe = Signal(bool(0))
    flash_addr = Signal(intbv(0)[23:])
    flash_region = Signal(bool(0))
    flash_region_oe = Signal(bool(0))
    flash_ce_n = Signal(bool(1))
    flash_oe_n = Signal(bool(1))
    flash_we_n = Signal(bool(1))
    flash_adv_n = Signal(bool(1))

    # sources and sinks
    sfp_1_source = xgmii_ep.XGMIISource()
    sfp_1_source_logic = sfp_1_source.create_logic(sfp_1_rx_clk,
                                                   sfp_1_rx_rst,
                                                   txd=sfp_1_rxd,
                                                   txc=sfp_1_rxc,
                                                   name='sfp_1_source')

    sfp_1_sink = xgmii_ep.XGMIISink()
    sfp_1_sink_logic = sfp_1_sink.create_logic(sfp_1_tx_clk,
                                               sfp_1_tx_rst,
                                               rxd=sfp_1_txd,
                                               rxc=sfp_1_txc,
                                               name='sfp_1_sink')

    sfp_2_source = xgmii_ep.XGMIISource()
    sfp_2_source_logic = sfp_2_source.create_logic(sfp_2_rx_clk,
                                                   sfp_2_rx_rst,
                                                   txd=sfp_2_rxd,
                                                   txc=sfp_2_rxc,
                                                   name='sfp_2_source')

    sfp_2_sink = xgmii_ep.XGMIISink()
    sfp_2_sink_logic = sfp_2_sink.create_logic(sfp_2_tx_clk,
                                               sfp_2_tx_rst,
                                               rxd=sfp_2_txd,
                                               rxc=sfp_2_txc,
                                               name='sfp_2_sink')

    # Clock and Reset Interface
    user_clk = Signal(bool(0))
    user_reset = Signal(bool(0))
    sys_clk = Signal(bool(0))
    sys_reset = Signal(bool(0))

    # PCIe devices
    rc = pcie.RootComplex()

    rc.max_payload_size = 0x1  # 256 bytes
    rc.max_read_request_size = 0x5  # 4096 bytes

    driver = mqnic.Driver(rc)

    dev = pcie_us.UltrascalePCIe()

    dev.pcie_generation = 3
    dev.pcie_link_width = 8
    dev.user_clock_frequency = 256e6

    dev.functions[0].msi_multiple_message_capable = 5

    dev.functions[0].configure_bar(0, 16 * 1024 * 1024)
    dev.functions[0].configure_bar(1, 16 * 1024 * 1024)

    rc.make_port().connect(dev)

    pcie_logic = dev.create_logic(
        # Completer reQuest Interface
        m_axis_cq_tdata=s_axis_cq_tdata,
        m_axis_cq_tuser=s_axis_cq_tuser,
        m_axis_cq_tlast=s_axis_cq_tlast,
        m_axis_cq_tkeep=s_axis_cq_tkeep,
        m_axis_cq_tvalid=s_axis_cq_tvalid,
        m_axis_cq_tready=s_axis_cq_tready,
        #pcie_cq_np_req=pcie_cq_np_req,
        pcie_cq_np_req=Signal(bool(1)),
        #pcie_cq_np_req_count=pcie_cq_np_req_count,

        # Completer Completion Interface
        s_axis_cc_tdata=m_axis_cc_tdata,
        s_axis_cc_tuser=m_axis_cc_tuser,
        s_axis_cc_tlast=m_axis_cc_tlast,
        s_axis_cc_tkeep=m_axis_cc_tkeep,
        s_axis_cc_tvalid=m_axis_cc_tvalid,
        s_axis_cc_tready=m_axis_cc_tready,

        # Requester reQuest Interface
        s_axis_rq_tdata=m_axis_rq_tdata,
        s_axis_rq_tuser=m_axis_rq_tuser,
        s_axis_rq_tlast=m_axis_rq_tlast,
        s_axis_rq_tkeep=m_axis_rq_tkeep,
        s_axis_rq_tvalid=m_axis_rq_tvalid,
        s_axis_rq_tready=m_axis_rq_tready,
        #pcie_rq_seq_num=pcie_rq_seq_num,
        #pcie_rq_seq_num_vld=pcie_rq_seq_num_vld,
        #pcie_rq_tag=pcie_rq_tag,
        #pcie_rq_tag_vld=pcie_rq_tag_vld,

        # Requester Completion Interface
        m_axis_rc_tdata=s_axis_rc_tdata,
        m_axis_rc_tuser=s_axis_rc_tuser,
        m_axis_rc_tlast=s_axis_rc_tlast,
        m_axis_rc_tkeep=s_axis_rc_tkeep,
        m_axis_rc_tvalid=s_axis_rc_tvalid,
        m_axis_rc_tready=s_axis_rc_tready,

        # Transmit Flow Control Interface
        pcie_tfc_nph_av=pcie_tfc_nph_av,
        pcie_tfc_npd_av=pcie_tfc_npd_av,

        # Configuration Management Interface
        cfg_mgmt_addr=cfg_mgmt_addr,
        cfg_mgmt_write=cfg_mgmt_write,
        cfg_mgmt_write_data=cfg_mgmt_write_data,
        cfg_mgmt_byte_enable=cfg_mgmt_byte_enable,
        cfg_mgmt_read=cfg_mgmt_read,
        cfg_mgmt_read_data=cfg_mgmt_read_data,
        cfg_mgmt_read_write_done=cfg_mgmt_read_write_done,
        #cfg_mgmt_type1_cfg_reg_access=cfg_mgmt_type1_cfg_reg_access,

        # Configuration Status Interface
        #cfg_phy_link_down=cfg_phy_link_down,
        #cfg_phy_link_status=cfg_phy_link_status,
        #cfg_negotiated_width=cfg_negotiated_width,
        #cfg_current_speed=cfg_current_speed,
        cfg_max_payload=cfg_max_payload,
        cfg_max_read_req=cfg_max_read_req,
        #cfg_function_status=cfg_function_status,
        #cfg_vf_status=cfg_vf_status,
        #cfg_function_power_state=cfg_function_power_state,
        #cfg_vf_power_state=cfg_vf_power_state,
        #cfg_link_power_state=cfg_link_power_state,
        #cfg_err_cor_out=cfg_err_cor_out,
        #cfg_err_nonfatal_out=cfg_err_nonfatal_out,
        #cfg_err_fatal_out=cfg_err_fatal_out,
        #cfg_ltr_enable=cfg_ltr_enable,
        #cfg_ltssm_state=cfg_ltssm_state,
        #cfg_rcb_status=cfg_rcb_status,
        #cfg_dpa_substate_change=cfg_dpa_substate_change,
        #cfg_obff_enable=cfg_obff_enable,
        #cfg_pl_status_change=cfg_pl_status_change,
        #cfg_tph_requester_enable=cfg_tph_requester_enable,
        #cfg_tph_st_mode=cfg_tph_st_mode,
        #cfg_vf_tph_requester_enable=cfg_vf_tph_requester_enable,
        #cfg_vf_tph_st_mode=cfg_vf_tph_st_mode,

        # Configuration Received Message Interface
        #cfg_msg_received=cfg_msg_received,
        #cfg_msg_received_data=cfg_msg_received_data,
        #cfg_msg_received_type=cfg_msg_received_type,

        # Configuration Transmit Message Interface
        #cfg_msg_transmit=cfg_msg_transmit,
        #cfg_msg_transmit_type=cfg_msg_transmit_type,
        #cfg_msg_transmit_data=cfg_msg_transmit_data,
        #cfg_msg_transmit_done=cfg_msg_transmit_done,

        # Configuration Flow Control Interface
        #cfg_fc_ph=cfg_fc_ph,
        #cfg_fc_pd=cfg_fc_pd,
        #cfg_fc_nph=cfg_fc_nph,
        #cfg_fc_npd=cfg_fc_npd,
        #cfg_fc_cplh=cfg_fc_cplh,
        #cfg_fc_cpld=cfg_fc_cpld,
        #cfg_fc_sel=cfg_fc_sel,

        # Per-Function Status Interface
        #cfg_per_func_status_control=cfg_per_func_status_control,
        #cfg_per_func_status_data=cfg_per_func_status_data,

        # Configuration Control Interface
        #cfg_hot_reset_in=cfg_hot_reset_in,
        #cfg_hot_reset_out=cfg_hot_reset_out,
        #cfg_config_space_enable=cfg_config_space_enable,
        #cfg_per_function_update_done=cfg_per_function_update_done,
        #cfg_per_function_number=cfg_per_function_number,
        #cfg_per_function_output_request=cfg_per_function_output_request,
        #cfg_dsn=cfg_dsn,
        #cfg_ds_bus_number=cfg_ds_bus_number,
        #cfg_ds_device_number=cfg_ds_device_number,
        #cfg_ds_function_number=cfg_ds_function_number,
        #cfg_power_state_change_ack=cfg_power_state_change_ack,
        #cfg_power_state_change_interrupt=cfg_power_state_change_interrupt,
        cfg_err_cor_in=status_error_cor,
        cfg_err_uncor_in=status_error_uncor,
        #cfg_flr_done=cfg_flr_done,
        #cfg_vf_flr_done=cfg_vf_flr_done,
        #cfg_flr_in_process=cfg_flr_in_process,
        #cfg_vf_flr_in_process=cfg_vf_flr_in_process,
        #cfg_req_pm_transition_l23_ready=cfg_req_pm_transition_l23_ready,
        #cfg_link_training_enable=cfg_link_training_enable,

        # Configuration Interrupt Controller Interface
        #cfg_interrupt_int=cfg_interrupt_int,
        #cfg_interrupt_sent=cfg_interrupt_sent,
        #cfg_interrupt_pending=cfg_interrupt_pending,
        cfg_interrupt_msi_enable=cfg_interrupt_msi_enable,
        cfg_interrupt_msi_vf_enable=cfg_interrupt_msi_vf_enable,
        cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
        cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
        cfg_interrupt_msi_data=cfg_interrupt_msi_data,
        cfg_interrupt_msi_select=cfg_interrupt_msi_select,
        cfg_interrupt_msi_int=cfg_interrupt_msi_int,
        cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
        cfg_interrupt_msi_pending_status_data_enable=
        cfg_interrupt_msi_pending_status_data_enable,
        cfg_interrupt_msi_pending_status_function_num=
        cfg_interrupt_msi_pending_status_function_num,
        cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
        cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
        #cfg_interrupt_msix_enable=cfg_interrupt_msix_enable,
        #cfg_interrupt_msix_mask=cfg_interrupt_msix_mask,
        #cfg_interrupt_msix_vf_enable=cfg_interrupt_msix_vf_enable,
        #cfg_interrupt_msix_vf_mask=cfg_interrupt_msix_vf_mask,
        #cfg_interrupt_msix_address=cfg_interrupt_msix_address,
        #cfg_interrupt_msix_data=cfg_interrupt_msix_data,
        #cfg_interrupt_msix_int=cfg_interrupt_msix_int,
        #cfg_interrupt_msix_sent=cfg_interrupt_msix_sent,
        #cfg_interrupt_msix_fail=cfg_interrupt_msix_fail,
        cfg_interrupt_msi_attr=cfg_interrupt_msi_attr,
        cfg_interrupt_msi_tph_present=cfg_interrupt_msi_tph_present,
        cfg_interrupt_msi_tph_type=cfg_interrupt_msi_tph_type,
        cfg_interrupt_msi_tph_st_tag=cfg_interrupt_msi_tph_st_tag,
        cfg_interrupt_msi_function_number=cfg_interrupt_msi_function_number,

        # Configuration Extend Interface
        #cfg_ext_read_received=cfg_ext_read_received,
        #cfg_ext_write_received=cfg_ext_write_received,
        #cfg_ext_register_number=cfg_ext_register_number,
        #cfg_ext_function_number=cfg_ext_function_number,
        #cfg_ext_write_data=cfg_ext_write_data,
        #cfg_ext_write_byte_enable=cfg_ext_write_byte_enable,
        #cfg_ext_read_data=cfg_ext_read_data,
        #cfg_ext_read_data_valid=cfg_ext_read_data_valid,

        # Clock and Reset Interface
        user_clk=user_clk,
        user_reset=user_reset,
        sys_clk=sys_clk,
        sys_clk_gt=sys_clk,
        sys_reset=sys_reset,
        #pcie_perstn0_out=pcie_perstn0_out,
        #pcie_perstn1_in=pcie_perstn1_in,
        #pcie_perstn1_out=pcie_perstn1_out
    )

    # DUT
    if os.system(build_cmd):
        raise Exception("Error running build command")

    dut = Cosimulation(
        "vvp -m myhdl %s.vvp -lxt2" % testbench,
        clk=clk,
        rst=rst,
        current_test=current_test,
        clk_156mhz=clk_156mhz,
        rst_156mhz=rst_156mhz,
        clk_250mhz=user_clk,
        rst_250mhz=user_reset,
        sfp_1_led=sfp_1_led,
        sfp_2_led=sfp_2_led,
        sma_led=sma_led,
        m_axis_rq_tdata=m_axis_rq_tdata,
        m_axis_rq_tkeep=m_axis_rq_tkeep,
        m_axis_rq_tlast=m_axis_rq_tlast,
        m_axis_rq_tready=m_axis_rq_tready,
        m_axis_rq_tuser=m_axis_rq_tuser,
        m_axis_rq_tvalid=m_axis_rq_tvalid,
        s_axis_rc_tdata=s_axis_rc_tdata,
        s_axis_rc_tkeep=s_axis_rc_tkeep,
        s_axis_rc_tlast=s_axis_rc_tlast,
        s_axis_rc_tready=s_axis_rc_tready,
        s_axis_rc_tuser=s_axis_rc_tuser,
        s_axis_rc_tvalid=s_axis_rc_tvalid,
        s_axis_cq_tdata=s_axis_cq_tdata,
        s_axis_cq_tkeep=s_axis_cq_tkeep,
        s_axis_cq_tlast=s_axis_cq_tlast,
        s_axis_cq_tready=s_axis_cq_tready,
        s_axis_cq_tuser=s_axis_cq_tuser,
        s_axis_cq_tvalid=s_axis_cq_tvalid,
        m_axis_cc_tdata=m_axis_cc_tdata,
        m_axis_cc_tkeep=m_axis_cc_tkeep,
        m_axis_cc_tlast=m_axis_cc_tlast,
        m_axis_cc_tready=m_axis_cc_tready,
        m_axis_cc_tuser=m_axis_cc_tuser,
        m_axis_cc_tvalid=m_axis_cc_tvalid,
        pcie_tfc_nph_av=pcie_tfc_nph_av,
        pcie_tfc_npd_av=pcie_tfc_npd_av,
        cfg_max_payload=cfg_max_payload,
        cfg_max_read_req=cfg_max_read_req,
        cfg_mgmt_addr=cfg_mgmt_addr,
        cfg_mgmt_write=cfg_mgmt_write,
        cfg_mgmt_write_data=cfg_mgmt_write_data,
        cfg_mgmt_byte_enable=cfg_mgmt_byte_enable,
        cfg_mgmt_read=cfg_mgmt_read,
        cfg_mgmt_read_data=cfg_mgmt_read_data,
        cfg_mgmt_read_write_done=cfg_mgmt_read_write_done,
        cfg_interrupt_msi_enable=cfg_interrupt_msi_enable,
        cfg_interrupt_msi_vf_enable=cfg_interrupt_msi_vf_enable,
        cfg_interrupt_msi_int=cfg_interrupt_msi_int,
        cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
        cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
        cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
        cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
        cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
        cfg_interrupt_msi_select=cfg_interrupt_msi_select,
        cfg_interrupt_msi_data=cfg_interrupt_msi_data,
        cfg_interrupt_msi_pending_status_function_num=
        cfg_interrupt_msi_pending_status_function_num,
        cfg_interrupt_msi_pending_status_data_enable=
        cfg_interrupt_msi_pending_status_data_enable,
        cfg_interrupt_msi_attr=cfg_interrupt_msi_attr,
        cfg_interrupt_msi_tph_present=cfg_interrupt_msi_tph_present,
        cfg_interrupt_msi_tph_type=cfg_interrupt_msi_tph_type,
        cfg_interrupt_msi_tph_st_tag=cfg_interrupt_msi_tph_st_tag,
        cfg_interrupt_msi_function_number=cfg_interrupt_msi_function_number,
        status_error_cor=status_error_cor,
        status_error_uncor=status_error_uncor,
        sfp_1_tx_clk=sfp_1_tx_clk,
        sfp_1_tx_rst=sfp_1_tx_rst,
        sfp_1_txd=sfp_1_txd,
        sfp_1_txc=sfp_1_txc,
        sfp_1_rx_clk=sfp_1_rx_clk,
        sfp_1_rx_rst=sfp_1_rx_rst,
        sfp_1_rxd=sfp_1_rxd,
        sfp_1_rxc=sfp_1_rxc,
        sfp_2_tx_clk=sfp_2_tx_clk,
        sfp_2_tx_rst=sfp_2_tx_rst,
        sfp_2_txd=sfp_2_txd,
        sfp_2_txc=sfp_2_txc,
        sfp_2_rx_clk=sfp_2_rx_clk,
        sfp_2_rx_rst=sfp_2_rx_rst,
        sfp_2_rxd=sfp_2_rxd,
        sfp_2_rxc=sfp_2_rxc,
        sfp_i2c_scl_i=sfp_i2c_scl_i,
        sfp_i2c_scl_o=sfp_i2c_scl_o,
        sfp_i2c_scl_t=sfp_i2c_scl_t,
        sfp_1_i2c_sda_i=sfp_1_i2c_sda_i,
        sfp_1_i2c_sda_o=sfp_1_i2c_sda_o,
        sfp_1_i2c_sda_t=sfp_1_i2c_sda_t,
        sfp_2_i2c_sda_i=sfp_2_i2c_sda_i,
        sfp_2_i2c_sda_o=sfp_2_i2c_sda_o,
        sfp_2_i2c_sda_t=sfp_2_i2c_sda_t,
        eeprom_i2c_scl_i=eeprom_i2c_scl_i,
        eeprom_i2c_scl_o=eeprom_i2c_scl_o,
        eeprom_i2c_scl_t=eeprom_i2c_scl_t,
        eeprom_i2c_sda_i=eeprom_i2c_sda_i,
        eeprom_i2c_sda_o=eeprom_i2c_sda_o,
        eeprom_i2c_sda_t=eeprom_i2c_sda_t,
        flash_dq_i=flash_dq_i,
        flash_dq_o=flash_dq_o,
        flash_dq_oe=flash_dq_oe,
        flash_addr=flash_addr,
        flash_region=flash_region,
        flash_region_oe=flash_region_oe,
        flash_ce_n=flash_ce_n,
        flash_oe_n=flash_oe_n,
        flash_we_n=flash_we_n,
        flash_adv_n=flash_adv_n)

    @always(delay(5))
    def clkgen():
        clk.next = not clk

    @always_comb
    def clk_logic():
        sys_clk.next = clk
        sys_reset.next = not rst

        sfp_1_tx_clk.next = clk
        sfp_1_tx_rst.next = rst
        sfp_1_rx_clk.next = clk
        sfp_1_rx_rst.next = rst
        sfp_2_tx_clk.next = clk
        sfp_2_tx_rst.next = rst
        sfp_2_rx_clk.next = clk
        sfp_2_rx_rst.next = rst

    loopback_enable = Signal(bool(0))

    @instance
    def loopback():
        while True:

            yield clk.posedge

            if loopback_enable:
                if not sfp_1_sink.empty():
                    pkt = sfp_1_sink.recv()
                    sfp_1_source.send(pkt)
                if not sfp_2_sink.empty():
                    pkt = sfp_2_sink.recv()
                    sfp_2_source.send(pkt)

    @instance
    def check():
        yield delay(100)
        yield clk.posedge
        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge
        yield delay(100)
        yield clk.posedge

        # testbench stimulus

        current_tag = 1

        yield clk.posedge
        print("test 1: enumeration")
        current_test.next = 1

        yield rc.enumerate(enable_bus_mastering=True, configure_msi=True)

        dev_pf0_bar0 = dev.functions[0].bar[0] & 0xfffffffc
        dev_pf0_bar1 = dev.functions[0].bar[1] & 0xfffffffc

        yield from rc.mem_write_dword(dev_pf0_bar0 + 0x270, 0)
        yield from rc.mem_write_dword(dev_pf0_bar0 + 0x274, 0)
        yield from rc.mem_write_dword(dev_pf0_bar0 + 0x278, 0)
        yield from rc.mem_write_dword(dev_pf0_bar0 + 0x27C, 0)

        yield from rc.mem_write_dword(dev_pf0_bar0 + 0x290, 0)
        yield from rc.mem_write_dword(dev_pf0_bar0 + 0x294, 1000)
        yield from rc.mem_write_dword(dev_pf0_bar0 + 0x298, 0)
        yield from rc.mem_write_dword(dev_pf0_bar0 + 0x29C, 0)

        yield from rc.mem_write_dword(dev_pf0_bar0 + 0x280, 0)
        yield from rc.mem_write_dword(dev_pf0_bar0 + 0x284, 2000)
        yield from rc.mem_write_dword(dev_pf0_bar0 + 0x288, 0)
        yield from rc.mem_write_dword(dev_pf0_bar0 + 0x28C, 0)

        yield delay(100)

        yield clk.posedge
        print("test 2: init NIC")
        current_test.next = 2

        yield from driver.init_dev(dev.functions[0].get_id())
        yield from driver.interfaces[0].open()

        # enable queues
        yield from rc.mem_write_dword(
            driver.interfaces[0].ports[0].schedulers[0].hw_addr + 0x0200,
            0xffffffff)
        yield from rc.mem_write_dword(
            driver.interfaces[0].ports[0].schedulers[0].hw_addr + 0x0300,
            0xffffffff)

        yield from rc.mem_read(driver.hw_addr,
                               4)  # wait for all writes to complete

        yield delay(100)

        yield clk.posedge
        print("test 3: send and receive a packet")
        current_test.next = 3

        data = bytearray([x % 256 for x in range(1024)])

        yield from driver.interfaces[0].start_xmit(data, 0)

        yield sfp_1_sink.wait()

        pkt = sfp_1_sink.recv()
        print(pkt)

        sfp_1_source.send(pkt)

        yield driver.interfaces[0].wait()

        pkt = driver.interfaces[0].recv()

        print(pkt)

        yield delay(100)

        yield clk.posedge
        print("test 4: checksum tests")
        current_test.next = 4

        test_frame = udp_ep.UDPFrame()
        test_frame.eth_dest_mac = 0xDAD1D2D3D4D5
        test_frame.eth_src_mac = 0x5A5152535455
        test_frame.eth_type = 0x0800
        test_frame.ip_version = 4
        test_frame.ip_ihl = 5
        test_frame.ip_length = None
        test_frame.ip_identification = 0
        test_frame.ip_flags = 2
        test_frame.ip_fragment_offset = 0
        test_frame.ip_ttl = 64
        test_frame.ip_protocol = 0x11
        test_frame.ip_header_checksum = None
        test_frame.ip_source_ip = 0xc0a80164
        test_frame.ip_dest_ip = 0xc0a80165
        test_frame.udp_source_port = 1
        test_frame.udp_dest_port = 2
        test_frame.udp_length = None
        test_frame.udp_checksum = None
        test_frame.payload = bytearray((x % 256 for x in range(256)))

        test_frame.set_udp_pseudo_header_checksum()

        axis_frame = test_frame.build_axis()

        yield from driver.interfaces[0].start_xmit(axis_frame.data, 0, 34, 6)

        yield sfp_1_sink.wait()

        pkt = sfp_1_sink.recv()
        print(pkt)

        sfp_1_source.send(pkt)

        yield driver.interfaces[0].wait()

        pkt = driver.interfaces[0].recv()

        print(pkt)

        assert pkt.rx_checksum == frame_checksum(pkt.data)

        check_frame = udp_ep.UDPFrame()
        check_frame.parse_axis(pkt.data)

        assert check_frame.verify_checksums()

        yield delay(100)

        yield clk.posedge
        print("test 5: multiple small packets")
        current_test.next = 5

        count = 64

        pkts = [
            bytearray([(x + k) % 256 for x in range(64)]) for k in range(count)
        ]

        loopback_enable.next = True

        for p in pkts:
            yield from driver.interfaces[0].start_xmit(p, 0)

        for k in range(count):
            pkt = driver.interfaces[0].recv()

            if not pkt:
                yield driver.interfaces[0].wait()
                pkt = driver.interfaces[0].recv()

            print(pkt)
            assert pkt.data == pkts[k]
            assert frame_checksum(pkt.data) == pkt.rx_checksum

        loopback_enable.next = False

        yield delay(100)

        yield clk.posedge
        print("test 6: multiple large packets")
        current_test.next = 6

        count = 64

        pkts = [
            bytearray([(x + k) % 256 for x in range(1514)])
            for k in range(count)
        ]

        loopback_enable.next = True

        for p in pkts:
            yield from driver.interfaces[0].start_xmit(p, 0)

        for k in range(count):
            pkt = driver.interfaces[0].recv()

            if not pkt:
                yield driver.interfaces[0].wait()
                pkt = driver.interfaces[0].recv()

            print(pkt)
            assert pkt.data == pkts[k]
            assert frame_checksum(pkt.data) == pkt.rx_checksum

        loopback_enable.next = False

        yield delay(1000)

        yield clk.posedge
        print("test 7: TDMA")
        current_test.next = 7

        count = 16

        pkts = [
            bytearray([(x + k) % 256 for x in range(1514)])
            for k in range(count)
        ]

        loopback_enable.next = True

        # configure TDMA

        # configure TDMA scheduler
        yield from rc.mem_write_dword(
            driver.interfaces[0].ports[0].schedulers[0].hw_addr + 0x00120,
            0)  # schedule period fns
        yield from rc.mem_write_dword(
            driver.interfaces[0].ports[0].schedulers[0].hw_addr + 0x00124,
            40000)  # schedule period ns
        yield from rc.mem_write_dword(
            driver.interfaces[0].ports[0].schedulers[0].hw_addr + 0x00128,
            0)  # schedule period sec (low)
        yield from rc.mem_write_dword(
            driver.interfaces[0].ports[0].schedulers[0].hw_addr + 0x0012c,
            0)  # schedule period sec (high)
        yield from rc.mem_write_dword(
            driver.interfaces[0].ports[0].schedulers[0].hw_addr + 0x00130,
            0)  # timeslot period fns
        yield from rc.mem_write_dword(
            driver.interfaces[0].ports[0].schedulers[0].hw_addr + 0x00134,
            10000)  # timeslot period ns
        yield from rc.mem_write_dword(
            driver.interfaces[0].ports[0].schedulers[0].hw_addr + 0x00138,
            0)  # timeslot period sec (low)
        yield from rc.mem_write_dword(
            driver.interfaces[0].ports[0].schedulers[0].hw_addr + 0x0013c,
            0)  # timeslot period sec (high)
        yield from rc.mem_write_dword(
            driver.interfaces[0].ports[0].schedulers[0].hw_addr + 0x00140,
            0)  # active period fns
        yield from rc.mem_write_dword(
            driver.interfaces[0].ports[0].schedulers[0].hw_addr + 0x00144,
            5000)  # active period ns
        yield from rc.mem_write_dword(
            driver.interfaces[0].ports[0].schedulers[0].hw_addr + 0x00148,
            0)  # active period sec (low)
        yield from rc.mem_write_dword(
            driver.interfaces[0].ports[0].schedulers[0].hw_addr + 0x0014c,
            0)  # active period sec (high)
        yield from rc.mem_write_dword(
            driver.interfaces[0].ports[0].schedulers[0].hw_addr + 0x00110,
            0)  # schedule start fns
        yield from rc.mem_write_dword(
            driver.interfaces[0].ports[0].schedulers[0].hw_addr + 0x00114,
            200000)  # schedule start ns
        yield from rc.mem_write_dword(
            driver.interfaces[0].ports[0].schedulers[0].hw_addr + 0x00118,
            0)  # schedule start sec (low)
        yield from rc.mem_write_dword(
            driver.interfaces[0].ports[0].schedulers[0].hw_addr + 0x0011c,
            0)  # schedule start sec (high)
        yield from rc.mem_write_dword(
            driver.interfaces[0].ports[0].schedulers[0].hw_addr + 0x00100,
            0x00000001)

        # enable queues
        yield from rc.mem_write_dword(
            driver.interfaces[0].ports[0].schedulers[0].hw_addr + 0x00200,
            0xffffffff)
        # disable global enable
        yield from rc.mem_write_dword(
            driver.interfaces[0].ports[0].schedulers[0].hw_addr + 0x00300,
            0x00000000)

        # configure slots
        yield from rc.mem_write_dword(
            driver.interfaces[0].ports[0].schedulers[0].hw_addr + 0x10000,
            0x00000001)
        yield from rc.mem_write_dword(
            driver.interfaces[0].ports[0].schedulers[0].hw_addr + 0x10100,
            0x00000002)
        yield from rc.mem_write_dword(
            driver.interfaces[0].ports[0].schedulers[0].hw_addr + 0x10200,
            0x00000004)
        yield from rc.mem_write_dword(
            driver.interfaces[0].ports[0].schedulers[0].hw_addr + 0x10300,
            0x00000008)

        yield from rc.mem_read(driver.hw_addr,
                               4)  # wait for all writes to complete

        # send packets
        for k in range(count):
            yield from driver.interfaces[0].start_xmit(pkts[k], k % 4)

        for k in range(count):
            pkt = driver.interfaces[0].recv()

            if not pkt:
                yield driver.interfaces[0].wait()
                pkt = driver.interfaces[0].recv()

            print(pkt)
            #assert pkt.data == pkts[k]
            #assert frame_checksum(pkt.data) == pkt.rx_checksum

        loopback_enable.next = False

        yield delay(100)

        raise StopSimulation

    return instances()
Beispiel #7
0
def bench():

    # Parameters
    AXIS_PCIE_DATA_WIDTH = 256
    AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
    AXIS_PCIE_CQ_USER_WIDTH = 85
    AXIS_PCIE_CC_USER_WIDTH = 33
    AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH
    AXI_ADDR_WIDTH = 64
    AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8)
    AXI_ID_WIDTH = 8
    AXI_MAX_BURST_LEN = 256

    # Inputs
    clk = Signal(bool(0))
    rst = Signal(bool(0))
    current_test = Signal(intbv(0)[8:])

    s_axis_cq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
    s_axis_cq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
    s_axis_cq_tvalid = Signal(bool(0))
    s_axis_cq_tlast = Signal(bool(0))
    s_axis_cq_tuser = Signal(intbv(0)[AXIS_PCIE_CQ_USER_WIDTH:])
    m_axis_cc_tready = Signal(bool(0))
    m_axi_awready = Signal(bool(0))
    m_axi_wready = Signal(bool(0))
    m_axi_bid = Signal(intbv(0)[AXI_ID_WIDTH:])
    m_axi_bresp = Signal(intbv(0)[2:])
    m_axi_bvalid = Signal(bool(0))
    m_axi_arready = Signal(bool(0))
    m_axi_rid = Signal(intbv(0)[AXI_ID_WIDTH:])
    m_axi_rdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
    m_axi_rresp = Signal(intbv(0)[2:])
    m_axi_rlast = Signal(bool(0))
    m_axi_rvalid = Signal(bool(0))
    completer_id = Signal(intbv(0)[16:])
    completer_id_enable = Signal(bool(0))
    max_payload_size = Signal(intbv(0)[3:])

    # Outputs
    s_axis_cq_tready = Signal(bool(0))
    m_axis_cc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
    m_axis_cc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
    m_axis_cc_tvalid = Signal(bool(0))
    m_axis_cc_tlast = Signal(bool(0))
    m_axis_cc_tuser = Signal(intbv(0)[AXIS_PCIE_CC_USER_WIDTH:])
    m_axi_awid = Signal(intbv(0)[AXI_ID_WIDTH:])
    m_axi_awaddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
    m_axi_awlen = Signal(intbv(0)[8:])
    m_axi_awsize = Signal(intbv(5)[3:])
    m_axi_awburst = Signal(intbv(1)[2:])
    m_axi_awlock = Signal(bool(0))
    m_axi_awcache = Signal(intbv(3)[4:])
    m_axi_awprot = Signal(intbv(2)[3:])
    m_axi_awvalid = Signal(bool(0))
    m_axi_wdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
    m_axi_wstrb = Signal(intbv(0)[AXI_STRB_WIDTH:])
    m_axi_wlast = Signal(bool(0))
    m_axi_wvalid = Signal(bool(0))
    m_axi_bready = Signal(bool(0))
    m_axi_arid = Signal(intbv(0)[AXI_ID_WIDTH:])
    m_axi_araddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
    m_axi_arlen = Signal(intbv(0)[8:])
    m_axi_arsize = Signal(intbv(5)[3:])
    m_axi_arburst = Signal(intbv(1)[2:])
    m_axi_arlock = Signal(bool(0))
    m_axi_arcache = Signal(intbv(3)[4:])
    m_axi_arprot = Signal(intbv(2)[3:])
    m_axi_arvalid = Signal(bool(0))
    m_axi_rready = Signal(bool(0))
    status_error_cor = Signal(bool(0))
    status_error_uncor = Signal(bool(0))

    # Clock and Reset Interface
    user_clk=Signal(bool(0))
    user_reset=Signal(bool(0))
    sys_clk=Signal(bool(0))
    sys_reset=Signal(bool(0))

    # AXI4 RAM model
    axi_ram_inst = axi.AXIRam(2**16)

    axi_ram_port0 = axi_ram_inst.create_port(
        user_clk,
        s_axi_awid=m_axi_awid,
        s_axi_awaddr=m_axi_awaddr,
        s_axi_awlen=m_axi_awlen,
        s_axi_awsize=m_axi_awsize,
        s_axi_awburst=m_axi_awburst,
        s_axi_awlock=m_axi_awlock,
        s_axi_awcache=m_axi_awcache,
        s_axi_awprot=m_axi_awprot,
        s_axi_awvalid=m_axi_awvalid,
        s_axi_awready=m_axi_awready,
        s_axi_wdata=m_axi_wdata,
        s_axi_wstrb=m_axi_wstrb,
        s_axi_wlast=m_axi_wlast,
        s_axi_wvalid=m_axi_wvalid,
        s_axi_wready=m_axi_wready,
        s_axi_bid=m_axi_bid,
        s_axi_bresp=m_axi_bresp,
        s_axi_bvalid=m_axi_bvalid,
        s_axi_bready=m_axi_bready,
        s_axi_arid=m_axi_arid,
        s_axi_araddr=m_axi_araddr,
        s_axi_arlen=m_axi_arlen,
        s_axi_arsize=m_axi_arsize,
        s_axi_arburst=m_axi_arburst,
        s_axi_arlock=m_axi_arlock,
        s_axi_arcache=m_axi_arcache,
        s_axi_arprot=m_axi_arprot,
        s_axi_arvalid=m_axi_arvalid,
        s_axi_arready=m_axi_arready,
        s_axi_rid=m_axi_rid,
        s_axi_rdata=m_axi_rdata,
        s_axi_rresp=m_axi_rresp,
        s_axi_rlast=m_axi_rlast,
        s_axi_rvalid=m_axi_rvalid,
        s_axi_rready=m_axi_rready,
        name='port0'
    )

    # PCIe devices
    rc = pcie.RootComplex()

    dev = pcie_us.UltrascalePCIe()

    dev.pcie_generation = 3
    dev.pcie_link_width = 8
    dev.user_clock_frequency = 250e6

    dev.functions[0].configure_bar(0, 16*1024*1024)

    rc.make_port().connect(dev)

    pcie_logic = dev.create_logic(
        # Completer reQuest Interface
        m_axis_cq_tdata=s_axis_cq_tdata,
        m_axis_cq_tuser=s_axis_cq_tuser,
        m_axis_cq_tlast=s_axis_cq_tlast,
        m_axis_cq_tkeep=s_axis_cq_tkeep,
        m_axis_cq_tvalid=s_axis_cq_tvalid,
        m_axis_cq_tready=s_axis_cq_tready,
        #pcie_cq_np_req=pcie_cq_np_req,
        #pcie_cq_np_req_count=pcie_cq_np_req_count,

        # Completer Completion Interface
        s_axis_cc_tdata=m_axis_cc_tdata,
        s_axis_cc_tuser=m_axis_cc_tuser,
        s_axis_cc_tlast=m_axis_cc_tlast,
        s_axis_cc_tkeep=m_axis_cc_tkeep,
        s_axis_cc_tvalid=m_axis_cc_tvalid,
        s_axis_cc_tready=m_axis_cc_tready,

        # Requester reQuest Interface
        s_axis_rq_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
        s_axis_rq_tuser=Signal(intbv(0)[60:]),
        s_axis_rq_tlast=Signal(bool(0)),
        s_axis_rq_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
        s_axis_rq_tvalid=Signal(bool(0)),
        s_axis_rq_tready=Signal(bool(1)),
        # pcie_rq_seq_num=pcie_rq_seq_num,
        # pcie_rq_seq_num_vld=pcie_rq_seq_num_vld,
        # pcie_rq_tag=pcie_rq_tag,
        # pcie_rq_tag_av=pcie_rq_tag_av,
        # pcie_rq_tag_vld=pcie_rq_tag_vld,

        # Requester Completion Interface
        m_axis_rc_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
        m_axis_rc_tuser=Signal(intbv(0)[75:]),
        m_axis_rc_tlast=Signal(bool(0)),
        m_axis_rc_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
        m_axis_rc_tvalid=Signal(bool(0)),
        m_axis_rc_tready=Signal(bool(0)),

        # Transmit Flow Control Interface
        # pcie_tfc_nph_av=pcie_tfc_nph_av,
        # pcie_tfc_npd_av=pcie_tfc_npd_av,

        # Configuration Control Interface
        # cfg_hot_reset_in=cfg_hot_reset_in,
        # cfg_hot_reset_out=cfg_hot_reset_out,
        # cfg_config_space_enable=cfg_config_space_enable,
        # cfg_per_function_update_done=cfg_per_function_update_done,
        # cfg_per_function_number=cfg_per_function_number,
        # cfg_per_function_output_request=cfg_per_function_output_request,
        # cfg_dsn=cfg_dsn,
        # cfg_ds_bus_number=cfg_ds_bus_number,
        # cfg_ds_device_number=cfg_ds_device_number,
        # cfg_ds_function_number=cfg_ds_function_number,
        # cfg_power_state_change_ack=cfg_power_state_change_ack,
        # cfg_power_state_change_interrupt=cfg_power_state_change_interrupt,
        # cfg_err_cor_in=cfg_err_cor_in,
        # cfg_err_uncor_in=cfg_err_uncor_in,
        # cfg_flr_done=cfg_flr_done,
        # cfg_vf_flr_done=cfg_vf_flr_done,
        # cfg_flr_in_process=cfg_flr_in_process,
        # cfg_vf_flr_in_process=cfg_vf_flr_in_process,
        # cfg_req_pm_transition_l23_ready=cfg_req_pm_transition_l23_ready,
        # cfg_link_training_enable=cfg_link_training_enable,

        # Clock and Reset Interface
        user_clk=user_clk,
        user_reset=user_reset,
        #user_lnk_up=user_lnk_up,
        sys_clk=sys_clk,
        sys_clk_gt=sys_clk,
        sys_reset=sys_reset
    )

    # DUT
    if os.system(build_cmd):
        raise Exception("Error running build command")

    dut = Cosimulation(
        "vvp -m myhdl %s.vvp -lxt2" % testbench,
        clk=user_clk,
        rst=user_reset,
        current_test=current_test,
        s_axis_cq_tdata=s_axis_cq_tdata,
        s_axis_cq_tkeep=s_axis_cq_tkeep,
        s_axis_cq_tvalid=s_axis_cq_tvalid,
        s_axis_cq_tready=s_axis_cq_tready,
        s_axis_cq_tlast=s_axis_cq_tlast,
        s_axis_cq_tuser=s_axis_cq_tuser,
        m_axis_cc_tdata=m_axis_cc_tdata,
        m_axis_cc_tkeep=m_axis_cc_tkeep,
        m_axis_cc_tvalid=m_axis_cc_tvalid,
        m_axis_cc_tready=m_axis_cc_tready,
        m_axis_cc_tlast=m_axis_cc_tlast,
        m_axis_cc_tuser=m_axis_cc_tuser,
        m_axi_awid=m_axi_awid,
        m_axi_awaddr=m_axi_awaddr,
        m_axi_awlen=m_axi_awlen,
        m_axi_awsize=m_axi_awsize,
        m_axi_awburst=m_axi_awburst,
        m_axi_awlock=m_axi_awlock,
        m_axi_awcache=m_axi_awcache,
        m_axi_awprot=m_axi_awprot,
        m_axi_awvalid=m_axi_awvalid,
        m_axi_awready=m_axi_awready,
        m_axi_wdata=m_axi_wdata,
        m_axi_wstrb=m_axi_wstrb,
        m_axi_wlast=m_axi_wlast,
        m_axi_wvalid=m_axi_wvalid,
        m_axi_wready=m_axi_wready,
        m_axi_bid=m_axi_bid,
        m_axi_bresp=m_axi_bresp,
        m_axi_bvalid=m_axi_bvalid,
        m_axi_bready=m_axi_bready,
        m_axi_arid=m_axi_arid,
        m_axi_araddr=m_axi_araddr,
        m_axi_arlen=m_axi_arlen,
        m_axi_arsize=m_axi_arsize,
        m_axi_arburst=m_axi_arburst,
        m_axi_arlock=m_axi_arlock,
        m_axi_arcache=m_axi_arcache,
        m_axi_arprot=m_axi_arprot,
        m_axi_arvalid=m_axi_arvalid,
        m_axi_arready=m_axi_arready,
        m_axi_rid=m_axi_rid,
        m_axi_rdata=m_axi_rdata,
        m_axi_rresp=m_axi_rresp,
        m_axi_rlast=m_axi_rlast,
        m_axi_rvalid=m_axi_rvalid,
        m_axi_rready=m_axi_rready,
        completer_id=completer_id,
        completer_id_enable=completer_id_enable,
        max_payload_size=max_payload_size,
        status_error_cor=status_error_cor,
        status_error_uncor=status_error_uncor
    )

    @always(delay(4))
    def clkgen():
        clk.next = not clk

    @always_comb
    def clk_logic():
        sys_clk.next = clk
        sys_reset.next = not rst

    status_error_cor_asserted = Signal(bool(0))
    status_error_uncor_asserted = Signal(bool(0))

    @always(user_clk.posedge)
    def monitor():
        if (status_error_cor):
            status_error_cor_asserted.next = 1
        if (status_error_uncor):
            status_error_uncor_asserted.next = 1

    @instance
    def check():
        yield delay(100)
        yield clk.posedge
        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge
        yield delay(100)
        yield clk.posedge

        # testbench stimulus

        max_payload_size.next = 0

        yield user_clk.posedge
        print("test 1: enumeration")
        current_test.next = 1

        yield rc.enumerate()

        dev_bar0 = rc.tree[0][0].bar[0]

        yield delay(100)

        yield clk.posedge
        print("test 2: memory write")
        current_test.next = 2

        pcie_addr = 0x00000000
        test_data = b'\x11\x22\x33\x44'

        yield rc.mem_write(dev_bar0+pcie_addr, test_data)

        yield delay(300)

        data = axi_ram_inst.read_mem(pcie_addr, 32)
        for i in range(0, len(data), 16):
            print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))

        assert axi_ram_inst.read_mem(pcie_addr, len(test_data)) == test_data

        assert not status_error_cor_asserted
        assert not status_error_uncor_asserted

        yield delay(100)

        yield clk.posedge
        print("test 3: memory read")
        current_test.next = 3

        pcie_addr = 0x00000000
        test_data = b'\x11\x22\x33\x44'

        axi_ram_inst.write_mem(pcie_addr, test_data)

        data = axi_ram_inst.read_mem(0, 32)
        for i in range(0, len(data), 16):
            print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))

        val = yield from rc.mem_read(dev_bar0+pcie_addr, len(test_data), 1000)

        print(val)

        assert val == test_data

        assert not status_error_cor_asserted
        assert not status_error_uncor_asserted

        yield delay(100)

        raise StopSimulation

    return instances()
def bench():

    # Parameters
    AXIS_PCIE_DATA_WIDTH = 256
    AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH / 32)
    AXIS_PCIE_RC_USER_WIDTH = 75
    AXIS_PCIE_RQ_USER_WIDTH = 60
    RQ_SEQ_NUM_WIDTH = 4 if AXIS_PCIE_RQ_USER_WIDTH == 60 else 6
    RQ_SEQ_NUM_ENABLE = 1
    SEG_COUNT = max(2, int(AXIS_PCIE_DATA_WIDTH * 2 / 128))
    SEG_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH * 2 / SEG_COUNT
    SEG_ADDR_WIDTH = 12
    SEG_BE_WIDTH = int(SEG_DATA_WIDTH / 8)
    SEG_SEL_WIDTH = 2
    RAM_ADDR_WIDTH = SEG_ADDR_WIDTH + (SEG_COUNT - 1).bit_length() + (
        SEG_BE_WIDTH - 1).bit_length()
    PCIE_ADDR_WIDTH = 64
    PCIE_TAG_COUNT = 64 if AXIS_PCIE_RQ_USER_WIDTH == 60 else 256
    PCIE_TAG_WIDTH = (PCIE_TAG_COUNT - 1).bit_length()
    PCIE_EXT_TAG_ENABLE = (PCIE_TAG_COUNT > 32)
    LEN_WIDTH = 16
    TAG_WIDTH = 8
    OP_TABLE_SIZE = PCIE_TAG_COUNT
    TX_LIMIT = 2**(RQ_SEQ_NUM_WIDTH - 1)
    TX_FC_ENABLE = 1

    # Inputs
    clk = Signal(bool(0))
    rst = Signal(bool(0))
    current_test = Signal(intbv(0)[8:])

    s_axis_rc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
    s_axis_rc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
    s_axis_rc_tvalid = Signal(bool(0))
    s_axis_rc_tlast = Signal(bool(0))
    s_axis_rc_tuser = Signal(intbv(0)[AXIS_PCIE_RC_USER_WIDTH:])
    m_axis_rq_tready = Signal(bool(0))
    s_axis_rq_seq_num_0 = Signal(intbv(0)[RQ_SEQ_NUM_WIDTH:])
    s_axis_rq_seq_num_valid_0 = Signal(bool(0))
    s_axis_rq_seq_num_1 = Signal(intbv(0)[RQ_SEQ_NUM_WIDTH:])
    s_axis_rq_seq_num_valid_1 = Signal(bool(0))
    pcie_tx_fc_nph_av = Signal(intbv(0)[8:])
    s_axis_read_desc_pcie_addr = Signal(intbv(0)[PCIE_ADDR_WIDTH:])
    s_axis_read_desc_ram_sel = Signal(intbv(0)[SEG_SEL_WIDTH:])
    s_axis_read_desc_ram_addr = Signal(intbv(0)[RAM_ADDR_WIDTH:])
    s_axis_read_desc_len = Signal(intbv(0)[LEN_WIDTH:])
    s_axis_read_desc_tag = Signal(intbv(0)[TAG_WIDTH:])
    s_axis_read_desc_valid = Signal(bool(0))
    ram_wr_cmd_ready = Signal(intbv(0)[SEG_COUNT:])
    enable = Signal(bool(0))
    ext_tag_enable = Signal(bool(0))
    requester_id = Signal(intbv(0)[16:])
    requester_id_enable = Signal(bool(0))
    max_read_request_size = Signal(intbv(0)[3:])

    # Outputs
    s_axis_rc_tready = Signal(bool(0))
    m_axis_rq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
    m_axis_rq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
    m_axis_rq_tvalid = Signal(bool(0))
    m_axis_rq_tlast = Signal(bool(0))
    m_axis_rq_tuser = Signal(intbv(0)[AXIS_PCIE_RQ_USER_WIDTH:])
    s_axis_read_desc_ready = Signal(bool(0))
    m_axis_read_desc_status_tag = Signal(intbv(0)[TAG_WIDTH:])
    m_axis_read_desc_status_valid = Signal(bool(0))
    ram_wr_cmd_be = Signal(intbv(0)[SEG_COUNT * SEG_BE_WIDTH:])
    ram_wr_cmd_sel = Signal(intbv(0)[SEG_COUNT * SEG_SEL_WIDTH:])
    ram_wr_cmd_addr = Signal(intbv(0)[SEG_COUNT * SEG_ADDR_WIDTH:])
    ram_wr_cmd_data = Signal(intbv(0)[SEG_COUNT * SEG_DATA_WIDTH:])
    ram_wr_cmd_valid = Signal(intbv(0)[SEG_COUNT:])
    status_error_cor = Signal(bool(0))
    status_error_uncor = Signal(bool(0))

    # Clock and Reset Interface
    user_clk = Signal(bool(0))
    user_reset = Signal(bool(0))
    sys_clk = Signal(bool(0))
    sys_reset = Signal(bool(0))

    # PCIe DMA RAM
    dma_ram_inst = dma_ram.PSDPRam(2**16)
    dma_ram_pause = Signal(bool(0))

    dma_ram_port0 = dma_ram_inst.create_write_ports(
        user_clk,
        ram_wr_cmd_be=ram_wr_cmd_be,
        ram_wr_cmd_addr=ram_wr_cmd_addr,
        ram_wr_cmd_data=ram_wr_cmd_data,
        ram_wr_cmd_valid=ram_wr_cmd_valid,
        ram_wr_cmd_ready=ram_wr_cmd_ready,
        pause=dma_ram_pause,
        name='port0')

    # sources and sinks
    read_desc_source = axis_ep.AXIStreamSource()

    read_desc_source_logic = read_desc_source.create_logic(
        user_clk,
        user_reset,
        tdata=(s_axis_read_desc_pcie_addr, s_axis_read_desc_ram_sel,
               s_axis_read_desc_ram_addr, s_axis_read_desc_len,
               s_axis_read_desc_tag),
        tvalid=s_axis_read_desc_valid,
        tready=s_axis_read_desc_ready,
        name='read_desc_source')

    read_desc_status_sink = axis_ep.AXIStreamSink()

    read_desc_status_sink_logic = read_desc_status_sink.create_logic(
        user_clk,
        user_reset,
        tdata=(m_axis_read_desc_status_tag, ),
        tvalid=m_axis_read_desc_status_valid,
        name='read_desc_status_sink')

    # PCIe devices
    rc = pcie.RootComplex()

    mem_base, mem_data = rc.alloc_region(16 * 1024 * 1024)

    dev = pcie_us.UltrascalePCIe()

    dev.pcie_generation = 3
    dev.pcie_link_width = 8
    dev.user_clock_frequency = 256e6

    rc.make_port().connect(dev)

    cq_pause = Signal(bool(0))
    cc_pause = Signal(bool(0))
    rq_pause = Signal(bool(0))
    rc_pause = Signal(bool(0))

    pcie_logic = dev.create_logic(
        # Completer reQuest Interface
        m_axis_cq_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
        m_axis_cq_tuser=Signal(intbv(0)[85:]),
        m_axis_cq_tlast=Signal(bool(0)),
        m_axis_cq_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
        m_axis_cq_tvalid=Signal(bool(0)),
        m_axis_cq_tready=Signal(bool(1)),
        pcie_cq_np_req=Signal(bool(1)),
        pcie_cq_np_req_count=Signal(intbv(0)[6:]),

        # Completer Completion Interface
        s_axis_cc_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
        s_axis_cc_tuser=Signal(intbv(0)[33:]),
        s_axis_cc_tlast=Signal(bool(0)),
        s_axis_cc_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
        s_axis_cc_tvalid=Signal(bool(0)),
        s_axis_cc_tready=Signal(bool(0)),

        # Requester reQuest Interface
        s_axis_rq_tdata=m_axis_rq_tdata,
        s_axis_rq_tuser=m_axis_rq_tuser,
        s_axis_rq_tlast=m_axis_rq_tlast,
        s_axis_rq_tkeep=m_axis_rq_tkeep,
        s_axis_rq_tvalid=m_axis_rq_tvalid,
        s_axis_rq_tready=m_axis_rq_tready,
        pcie_rq_seq_num=s_axis_rq_seq_num_0,
        pcie_rq_seq_num_vld=s_axis_rq_seq_num_valid_0,
        # pcie_rq_tag=pcie_rq_tag,
        # pcie_rq_tag_av=pcie_rq_tag_av,
        # pcie_rq_tag_vld=pcie_rq_tag_vld,

        # Requester Completion Interface
        m_axis_rc_tdata=s_axis_rc_tdata,
        m_axis_rc_tuser=s_axis_rc_tuser,
        m_axis_rc_tlast=s_axis_rc_tlast,
        m_axis_rc_tkeep=s_axis_rc_tkeep,
        m_axis_rc_tvalid=s_axis_rc_tvalid,
        m_axis_rc_tready=s_axis_rc_tready,

        # Transmit Flow Control Interface
        # pcie_tfc_nph_av=pcie_tfc_nph_av,
        # pcie_tfc_npd_av=pcie_tfc_npd_av,

        # Configuration Flow Control Interface
        #cfg_fc_ph=cfg_fc_ph,
        #cfg_fc_pd=cfg_fc_pd,
        cfg_fc_nph=pcie_tx_fc_nph_av,
        #cfg_fc_npd=cfg_fc_npd,
        #cfg_fc_cplh=cfg_fc_cplh,
        #cfg_fc_cpld=cfg_fc_cpld,
        cfg_fc_sel=Signal(intbv(0b100)[3:]),

        # Configuration Control Interface
        # cfg_hot_reset_in=cfg_hot_reset_in,
        # cfg_hot_reset_out=cfg_hot_reset_out,
        # cfg_config_space_enable=cfg_config_space_enable,
        # cfg_per_function_update_done=cfg_per_function_update_done,
        # cfg_per_function_number=cfg_per_function_number,
        # cfg_per_function_output_request=cfg_per_function_output_request,
        # cfg_dsn=cfg_dsn,
        # cfg_ds_bus_number=cfg_ds_bus_number,
        # cfg_ds_device_number=cfg_ds_device_number,
        # cfg_ds_function_number=cfg_ds_function_number,
        # cfg_power_state_change_ack=cfg_power_state_change_ack,
        # cfg_power_state_change_interrupt=cfg_power_state_change_interrupt,
        # cfg_err_cor_in=cfg_err_cor_in,
        # cfg_err_uncor_in=cfg_err_uncor_in,
        # cfg_flr_done=cfg_flr_done,
        # cfg_vf_flr_done=cfg_vf_flr_done,
        # cfg_flr_in_process=cfg_flr_in_process,
        # cfg_vf_flr_in_process=cfg_vf_flr_in_process,
        # cfg_req_pm_transition_l23_ready=cfg_req_pm_transition_l23_ready,
        # cfg_link_training_enable=cfg_link_training_enable,

        # Clock and Reset Interface
        user_clk=user_clk,
        user_reset=user_reset,
        #user_lnk_up=user_lnk_up,
        sys_clk=sys_clk,
        sys_clk_gt=sys_clk,
        sys_reset=sys_reset,
        cq_pause=cq_pause,
        cc_pause=cc_pause,
        rq_pause=rq_pause,
        rc_pause=rc_pause)

    # DUT
    if os.system(build_cmd):
        raise Exception("Error running build command")

    dut = Cosimulation(
        "vvp -m myhdl %s.vvp -lxt2" % testbench,
        clk=user_clk,
        rst=user_reset,
        current_test=current_test,
        s_axis_rc_tdata=s_axis_rc_tdata,
        s_axis_rc_tkeep=s_axis_rc_tkeep,
        s_axis_rc_tvalid=s_axis_rc_tvalid,
        s_axis_rc_tready=s_axis_rc_tready,
        s_axis_rc_tlast=s_axis_rc_tlast,
        s_axis_rc_tuser=s_axis_rc_tuser,
        m_axis_rq_tdata=m_axis_rq_tdata,
        m_axis_rq_tkeep=m_axis_rq_tkeep,
        m_axis_rq_tvalid=m_axis_rq_tvalid,
        m_axis_rq_tready=m_axis_rq_tready,
        m_axis_rq_tlast=m_axis_rq_tlast,
        m_axis_rq_tuser=m_axis_rq_tuser,
        s_axis_rq_seq_num_0=s_axis_rq_seq_num_0,
        s_axis_rq_seq_num_valid_0=s_axis_rq_seq_num_valid_0,
        s_axis_rq_seq_num_1=s_axis_rq_seq_num_1,
        s_axis_rq_seq_num_valid_1=s_axis_rq_seq_num_valid_1,
        pcie_tx_fc_nph_av=pcie_tx_fc_nph_av,
        s_axis_read_desc_pcie_addr=s_axis_read_desc_pcie_addr,
        s_axis_read_desc_ram_sel=s_axis_read_desc_ram_sel,
        s_axis_read_desc_ram_addr=s_axis_read_desc_ram_addr,
        s_axis_read_desc_len=s_axis_read_desc_len,
        s_axis_read_desc_tag=s_axis_read_desc_tag,
        s_axis_read_desc_valid=s_axis_read_desc_valid,
        s_axis_read_desc_ready=s_axis_read_desc_ready,
        m_axis_read_desc_status_tag=m_axis_read_desc_status_tag,
        m_axis_read_desc_status_valid=m_axis_read_desc_status_valid,
        ram_wr_cmd_sel=ram_wr_cmd_sel,
        ram_wr_cmd_be=ram_wr_cmd_be,
        ram_wr_cmd_addr=ram_wr_cmd_addr,
        ram_wr_cmd_data=ram_wr_cmd_data,
        ram_wr_cmd_valid=ram_wr_cmd_valid,
        ram_wr_cmd_ready=ram_wr_cmd_ready,
        enable=enable,
        ext_tag_enable=ext_tag_enable,
        requester_id=requester_id,
        requester_id_enable=requester_id_enable,
        max_read_request_size=max_read_request_size,
        status_error_cor=status_error_cor,
        status_error_uncor=status_error_uncor)

    @always(delay(4))
    def clkgen():
        clk.next = not clk

    @always_comb
    def clk_logic():
        sys_clk.next = clk
        sys_reset.next = not rst

    status_error_cor_asserted = Signal(bool(0))
    status_error_uncor_asserted = Signal(bool(0))

    @always(clk.posedge)
    def monitor():
        if (status_error_cor):
            status_error_cor_asserted.next = 1
        if (status_error_uncor):
            status_error_uncor_asserted.next = 1

    cq_pause_toggle = Signal(bool(0))
    cc_pause_toggle = Signal(bool(0))
    rq_pause_toggle = Signal(bool(0))
    rc_pause_toggle = Signal(bool(0))

    @instance
    def pause_toggle():
        while True:
            if (cq_pause_toggle or cc_pause_toggle or rq_pause_toggle
                    or rc_pause_toggle):
                cq_pause.next = cq_pause_toggle
                cc_pause.next = cc_pause_toggle
                rq_pause.next = rq_pause_toggle
                rc_pause.next = rc_pause_toggle

                yield user_clk.posedge
                yield user_clk.posedge
                yield user_clk.posedge

                cq_pause.next = 0
                cc_pause.next = 0
                rq_pause.next = 0
                rc_pause.next = 0

            yield user_clk.posedge

    @instance
    def check():
        yield delay(100)
        yield clk.posedge
        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge
        yield delay(100)
        yield clk.posedge

        # testbench stimulus

        cur_tag = 1

        max_read_request_size.next = 2

        enable.next = 1

        yield user_clk.posedge
        print("test 1: enumeration")
        current_test.next = 1

        yield rc.enumerate(enable_bus_mastering=True)

        yield delay(100)

        yield user_clk.posedge
        print("test 2: PCIe read")
        current_test.next = 2

        pcie_addr = 0x00000000
        ram_addr = 0x00000000
        test_data = b'\x11\x22\x33\x44'

        mem_data[pcie_addr:pcie_addr + len(test_data)] = test_data

        data = mem_data[pcie_addr:pcie_addr + 32]
        for i in range(0, len(data), 16):
            print(" ".join(
                ("{:02x}".format(c) for c in bytearray(data[i:i + 16]))))

        read_desc_source.send([(pcie_addr, 0, ram_addr, len(test_data),
                                cur_tag)])

        yield read_desc_status_sink.wait(2000)

        yield delay(50)

        status = read_desc_status_sink.recv()

        print(status)

        data = dma_ram_inst.read_mem(ram_addr, 32)
        for i in range(0, len(data), 16):
            print(" ".join(
                ("{:02x}".format(c) for c in bytearray(data[i:i + 16]))))

        assert dma_ram_inst.read_mem(ram_addr, len(test_data)) == test_data

        cur_tag = (cur_tag + 1) % 256

        yield delay(100)

        yield user_clk.posedge
        print("test 3: various reads")
        current_test.next = 3

        for length in list(range(1, 35)) + list(range(128 - 4,
                                                      128 + 4)) + [1024]:
            for pcie_offset in list(range(8, 13)) + list(
                    range(4096 - 4, 4096 + 4)):
                for ram_offset in list(range(8, 73)) + list(
                        range(4096 - 64, 4096)):
                    for pause in [False, True]:
                        print("length %d, pcie_offset %d, ram_offset %d" %
                              (length, pcie_offset, ram_offset))
                        #pcie_addr = length * 0x100000000 + pcie_offset * 0x10000 + offset
                        pcie_addr = pcie_offset
                        ram_addr = ram_offset
                        test_data = bytearray([x % 256 for x in range(length)])

                        mem_data[pcie_addr:pcie_addr +
                                 len(test_data)] = test_data

                        data = mem_data[pcie_addr
                                        & 0xffff80:(pcie_addr & 0xffff80) + 64]
                        for i in range(0, len(data), 16):
                            print(" ".join(
                                ("{:02x}".format(c)
                                 for c in bytearray(data[i:i + 16]))))

                        dma_ram_inst.write_mem(
                            ram_addr & 0xffff80,
                            b'\xaa' * (len(test_data) + 256))

                        rq_pause_toggle.next = pause
                        rc_pause_toggle.next = pause

                        read_desc_source.send([(pcie_addr, 0, ram_addr,
                                                len(test_data), cur_tag)])

                        yield read_desc_status_sink.wait(4000)

                        rq_pause_toggle.next = 0
                        rc_pause_toggle.next = 0

                        status = read_desc_status_sink.recv()

                        print(status)

                        assert status.data[0][0] == cur_tag

                        data = dma_ram_inst.read_mem(ram_addr & 0xfffff0, 64)
                        for i in range(0, len(data), 16):
                            print(" ".join(
                                ("{:02x}".format(c)
                                 for c in bytearray(data[i:i + 16]))))

                        assert dma_ram_inst.read_mem(
                            ram_addr - 8,
                            len(test_data) +
                            16) == b'\xaa' * 8 + test_data + b'\xaa' * 8

                        cur_tag = (cur_tag + 1) % 256

                        yield delay(50)

        raise StopSimulation

    return instances()
Beispiel #9
0
def bench():

    # Parameters

    # Inputs
    clk = Signal(bool(0))
    rst = Signal(bool(0))
    current_test = Signal(intbv(0)[8:])

    btnu = Signal(bool(0))
    btnl = Signal(bool(0))
    btnd = Signal(bool(0))
    btnr = Signal(bool(0))
    btnc = Signal(bool(0))
    sw = Signal(intbv(0)[4:])
    m_axis_rq_tready = Signal(bool(0))
    s_axis_rc_tdata = Signal(intbv(0)[256:])
    s_axis_rc_tkeep = Signal(intbv(0)[8:])
    s_axis_rc_tlast = Signal(bool(0))
    s_axis_rc_tuser = Signal(intbv(0)[75:])
    s_axis_rc_tvalid = Signal(bool(0))
    s_axis_cq_tdata = Signal(intbv(0)[256:])
    s_axis_cq_tkeep = Signal(intbv(0)[8:])
    s_axis_cq_tlast = Signal(bool(0))
    s_axis_cq_tuser = Signal(intbv(0)[85:])
    s_axis_cq_tvalid = Signal(bool(0))
    m_axis_cc_tready = Signal(bool(0))
    cfg_max_payload = Signal(intbv(0)[3:])
    cfg_max_read_req = Signal(intbv(0)[3:])
    cfg_mgmt_read_data = Signal(intbv(0)[32:])
    cfg_mgmt_read_write_done = Signal(bool(0))
    cfg_interrupt_msi_enable = Signal(intbv(0)[4:])
    cfg_interrupt_msi_vf_enable = Signal(intbv(0)[8:])
    cfg_interrupt_msi_mmenable = Signal(intbv(0)[12:])
    cfg_interrupt_msi_mask_update = Signal(bool(0))
    cfg_interrupt_msi_data = Signal(intbv(0)[32:])
    cfg_interrupt_msi_sent = Signal(bool(0))
    cfg_interrupt_msi_fail = Signal(bool(0))

    # Outputs
    led = Signal(intbv(0)[8:])
    m_axis_rq_tdata = Signal(intbv(0)[256:])
    m_axis_rq_tkeep = Signal(intbv(0)[8:])
    m_axis_rq_tlast = Signal(bool(0))
    m_axis_rq_tuser = Signal(intbv(0)[60:])
    m_axis_rq_tvalid = Signal(bool(0))
    s_axis_rc_tready = Signal(bool(0))
    s_axis_cq_tready = Signal(bool(0))
    m_axis_cc_tdata = Signal(intbv(0)[256:])
    m_axis_cc_tkeep = Signal(intbv(0)[8:])
    m_axis_cc_tlast = Signal(bool(0))
    m_axis_cc_tuser = Signal(intbv(0)[33:])
    m_axis_cc_tvalid = Signal(bool(0))
    status_error_cor = Signal(bool(0))
    status_error_uncor = Signal(bool(0))
    cfg_mgmt_addr = Signal(intbv(0)[19:])
    cfg_mgmt_write = Signal(bool(0))
    cfg_mgmt_write_data = Signal(intbv(0)[32:])
    cfg_mgmt_byte_enable = Signal(intbv(0)[4:])
    cfg_mgmt_read = Signal(bool(0))
    cfg_interrupt_msi_int = Signal(intbv(0)[32:])
    cfg_interrupt_msi_pending_status = Signal(intbv(0)[32:])
    cfg_interrupt_msi_select = Signal(intbv(0)[4:])
    cfg_interrupt_msi_pending_status_function_num = Signal(intbv(0)[4:])
    cfg_interrupt_msi_pending_status_data_enable = Signal(bool(0))
    cfg_interrupt_msi_attr = Signal(intbv(0)[3:])
    cfg_interrupt_msi_tph_present = Signal(bool(0))
    cfg_interrupt_msi_tph_type = Signal(intbv(0)[2:])
    cfg_interrupt_msi_tph_st_tag = Signal(intbv(0)[9:])
    cfg_interrupt_msi_function_number = Signal(intbv(0)[4:])

    # Clock and Reset Interface
    user_clk = Signal(bool(0))
    user_reset = Signal(bool(0))
    sys_clk = Signal(bool(0))
    sys_reset = Signal(bool(0))

    # PCIe devices
    rc = pcie.RootComplex()

    mem_base, mem_data = rc.alloc_region(16 * 1024 * 1024)

    dev = pcie_us.UltrascalePCIe()

    dev.pcie_generation = 3
    dev.pcie_link_width = 8
    dev.user_clk_frequency = 250e6

    dev.functions[0].msi_multiple_message_capable = 5

    dev.functions[0].configure_bar(0, 4 * 1024 * 1024)
    dev.functions[0].configure_bar(1, 4 * 1024 * 1024)

    rc.make_port().connect(dev)

    pcie_logic = dev.create_logic(
        # Completer reQuest Interface
        m_axis_cq_tdata=s_axis_cq_tdata,
        m_axis_cq_tuser=s_axis_cq_tuser,
        m_axis_cq_tlast=s_axis_cq_tlast,
        m_axis_cq_tkeep=s_axis_cq_tkeep,
        m_axis_cq_tvalid=s_axis_cq_tvalid,
        m_axis_cq_tready=s_axis_cq_tready,
        #pcie_cq_np_req=pcie_cq_np_req,
        pcie_cq_np_req=Signal(bool(1)),
        #pcie_cq_np_req_count=pcie_cq_np_req_count,

        # Completer Completion Interface
        s_axis_cc_tdata=m_axis_cc_tdata,
        s_axis_cc_tuser=m_axis_cc_tuser,
        s_axis_cc_tlast=m_axis_cc_tlast,
        s_axis_cc_tkeep=m_axis_cc_tkeep,
        s_axis_cc_tvalid=m_axis_cc_tvalid,
        s_axis_cc_tready=m_axis_cc_tready,

        # Requester reQuest Interface
        s_axis_rq_tdata=m_axis_rq_tdata,
        s_axis_rq_tuser=m_axis_rq_tuser,
        s_axis_rq_tlast=m_axis_rq_tlast,
        s_axis_rq_tkeep=m_axis_rq_tkeep,
        s_axis_rq_tvalid=m_axis_rq_tvalid,
        s_axis_rq_tready=m_axis_rq_tready,
        #pcie_rq_seq_num=pcie_rq_seq_num,
        #pcie_rq_seq_num_vld=pcie_rq_seq_num_vld,
        #pcie_rq_tag=pcie_rq_tag,
        #pcie_rq_tag_vld=pcie_rq_tag_vld,

        # Requester Completion Interface
        m_axis_rc_tdata=s_axis_rc_tdata,
        m_axis_rc_tuser=s_axis_rc_tuser,
        m_axis_rc_tlast=s_axis_rc_tlast,
        m_axis_rc_tkeep=s_axis_rc_tkeep,
        m_axis_rc_tvalid=s_axis_rc_tvalid,
        m_axis_rc_tready=s_axis_rc_tready,

        # Transmit Flow Control Interface
        #pcie_tfc_nph_av=pcie_tfc_nph_av,
        #pcie_tfc_npd_av=pcie_tfc_npd_av,

        # Configuration Management Interface
        cfg_mgmt_addr=cfg_mgmt_addr,
        cfg_mgmt_write=cfg_mgmt_write,
        cfg_mgmt_write_data=cfg_mgmt_write_data,
        cfg_mgmt_byte_enable=cfg_mgmt_byte_enable,
        cfg_mgmt_read=cfg_mgmt_read,
        cfg_mgmt_read_data=cfg_mgmt_read_data,
        cfg_mgmt_read_write_done=cfg_mgmt_read_write_done,
        #cfg_mgmt_type1_cfg_reg_access=cfg_mgmt_type1_cfg_reg_access,

        # Configuration Status Interface
        #cfg_phy_link_down=cfg_phy_link_down,
        #cfg_phy_link_status=cfg_phy_link_status,
        #cfg_negotiated_width=cfg_negotiated_width,
        #cfg_current_speed=cfg_current_speed,
        cfg_max_payload=cfg_max_payload,
        cfg_max_read_req=cfg_max_read_req,
        #cfg_function_status=cfg_function_status,
        #cfg_vf_status=cfg_vf_status,
        #cfg_function_power_state=cfg_function_power_state,
        #cfg_vf_power_state=cfg_vf_power_state,
        #cfg_link_power_state=cfg_link_power_state,
        #cfg_err_cor_out=cfg_err_cor_out,
        #cfg_err_nonfatal_out=cfg_err_nonfatal_out,
        #cfg_err_fatal_out=cfg_err_fatal_out,
        #cfg_ltr_enable=cfg_ltr_enable,
        #cfg_ltssm_state=cfg_ltssm_state,
        #cfg_rcb_status=cfg_rcb_status,
        #cfg_dpa_substate_change=cfg_dpa_substate_change,
        #cfg_obff_enable=cfg_obff_enable,
        #cfg_pl_status_change=cfg_pl_status_change,
        #cfg_tph_requester_enable=cfg_tph_requester_enable,
        #cfg_tph_st_mode=cfg_tph_st_mode,
        #cfg_vf_tph_requester_enable=cfg_vf_tph_requester_enable,
        #cfg_vf_tph_st_mode=cfg_vf_tph_st_mode,

        # Configuration Received Message Interface
        #cfg_msg_received=cfg_msg_received,
        #cfg_msg_received_data=cfg_msg_received_data,
        #cfg_msg_received_type=cfg_msg_received_type,

        # Configuration Transmit Message Interface
        #cfg_msg_transmit=cfg_msg_transmit,
        #cfg_msg_transmit_type=cfg_msg_transmit_type,
        #cfg_msg_transmit_data=cfg_msg_transmit_data,
        #cfg_msg_transmit_done=cfg_msg_transmit_done,

        # Configuration Flow Control Interface
        #cfg_fc_ph=cfg_fc_ph,
        #cfg_fc_pd=cfg_fc_pd,
        #cfg_fc_nph=cfg_fc_nph,
        #cfg_fc_npd=cfg_fc_npd,
        #cfg_fc_cplh=cfg_fc_cplh,
        #cfg_fc_cpld=cfg_fc_cpld,
        #cfg_fc_sel=cfg_fc_sel,

        # Per-Function Status Interface
        #cfg_per_func_status_control=cfg_per_func_status_control,
        #cfg_per_func_status_data=cfg_per_func_status_data,

        # Configuration Control Interface
        #cfg_hot_reset_in=cfg_hot_reset_in,
        #cfg_hot_reset_out=cfg_hot_reset_out,
        #cfg_config_space_enable=cfg_config_space_enable,
        #cfg_per_function_update_done=cfg_per_function_update_done,
        #cfg_per_function_number=cfg_per_function_number,
        #cfg_per_function_output_request=cfg_per_function_output_request,
        #cfg_dsn=cfg_dsn,
        #cfg_ds_bus_number=cfg_ds_bus_number,
        #cfg_ds_device_number=cfg_ds_device_number,
        #cfg_ds_function_number=cfg_ds_function_number,
        #cfg_power_state_change_ack=cfg_power_state_change_ack,
        #cfg_power_state_change_interrupt=cfg_power_state_change_interrupt,
        cfg_err_cor_in=status_error_cor,
        cfg_err_uncor_in=status_error_uncor,
        #cfg_flr_done=cfg_flr_done,
        #cfg_vf_flr_done=cfg_vf_flr_done,
        #cfg_flr_in_process=cfg_flr_in_process,
        #cfg_vf_flr_in_process=cfg_vf_flr_in_process,
        #cfg_req_pm_transition_l23_ready=cfg_req_pm_transition_l23_ready,
        #cfg_link_training_enable=cfg_link_training_enable,

        # Configuration Interrupt Controller Interface
        #cfg_interrupt_int=cfg_interrupt_int,
        #cfg_interrupt_sent=cfg_interrupt_sent,
        #cfg_interrupt_pending=cfg_interrupt_pending,
        cfg_interrupt_msi_enable=cfg_interrupt_msi_enable,
        cfg_interrupt_msi_vf_enable=cfg_interrupt_msi_vf_enable,
        cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
        cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
        cfg_interrupt_msi_data=cfg_interrupt_msi_data,
        cfg_interrupt_msi_select=cfg_interrupt_msi_select,
        cfg_interrupt_msi_int=cfg_interrupt_msi_int,
        cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
        cfg_interrupt_msi_pending_status_data_enable=
        cfg_interrupt_msi_pending_status_data_enable,
        cfg_interrupt_msi_pending_status_function_num=
        cfg_interrupt_msi_pending_status_function_num,
        cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
        cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
        #cfg_interrupt_msix_enable=cfg_interrupt_msix_enable,
        #cfg_interrupt_msix_mask=cfg_interrupt_msix_mask,
        #cfg_interrupt_msix_vf_enable=cfg_interrupt_msix_vf_enable,
        #cfg_interrupt_msix_vf_mask=cfg_interrupt_msix_vf_mask,
        #cfg_interrupt_msix_address=cfg_interrupt_msix_address,
        #cfg_interrupt_msix_data=cfg_interrupt_msix_data,
        #cfg_interrupt_msix_int=cfg_interrupt_msix_int,
        #cfg_interrupt_msix_sent=cfg_interrupt_msix_sent,
        #cfg_interrupt_msix_fail=cfg_interrupt_msix_fail,
        cfg_interrupt_msi_attr=cfg_interrupt_msi_attr,
        cfg_interrupt_msi_tph_present=cfg_interrupt_msi_tph_present,
        cfg_interrupt_msi_tph_type=cfg_interrupt_msi_tph_type,
        cfg_interrupt_msi_tph_st_tag=cfg_interrupt_msi_tph_st_tag,
        cfg_interrupt_msi_function_number=cfg_interrupt_msi_function_number,

        # Configuration Extend Interface
        #cfg_ext_read_received=cfg_ext_read_received,
        #cfg_ext_write_received=cfg_ext_write_received,
        #cfg_ext_register_number=cfg_ext_register_number,
        #cfg_ext_function_number=cfg_ext_function_number,
        #cfg_ext_write_data=cfg_ext_write_data,
        #cfg_ext_write_byte_enable=cfg_ext_write_byte_enable,
        #cfg_ext_read_data=cfg_ext_read_data,
        #cfg_ext_read_data_valid=cfg_ext_read_data_valid,

        # Clock and Reset Interface
        user_clk=user_clk,
        user_reset=user_reset,
        sys_clk=sys_clk,
        sys_clk_gt=sys_clk,
        sys_reset=sys_reset,
        #pcie_perstn0_out=pcie_perstn0_out,
        #pcie_perstn1_in=pcie_perstn1_in,
        #pcie_perstn1_out=pcie_perstn1_out
    )

    # DUT
    if os.system(build_cmd):
        raise Exception("Error running build command")

    dut = Cosimulation(
        "vvp -m myhdl %s.vvp -lxt2" % testbench,
        clk=user_clk,
        rst=user_reset,
        current_test=current_test,
        btnu=btnu,
        btnl=btnl,
        btnd=btnd,
        btnr=btnr,
        btnc=btnc,
        sw=sw,
        led=led,
        m_axis_rq_tdata=m_axis_rq_tdata,
        m_axis_rq_tkeep=m_axis_rq_tkeep,
        m_axis_rq_tlast=m_axis_rq_tlast,
        m_axis_rq_tready=m_axis_rq_tready,
        m_axis_rq_tuser=m_axis_rq_tuser,
        m_axis_rq_tvalid=m_axis_rq_tvalid,
        s_axis_rc_tdata=s_axis_rc_tdata,
        s_axis_rc_tkeep=s_axis_rc_tkeep,
        s_axis_rc_tlast=s_axis_rc_tlast,
        s_axis_rc_tready=s_axis_rc_tready,
        s_axis_rc_tuser=s_axis_rc_tuser,
        s_axis_rc_tvalid=s_axis_rc_tvalid,
        s_axis_cq_tdata=s_axis_cq_tdata,
        s_axis_cq_tkeep=s_axis_cq_tkeep,
        s_axis_cq_tlast=s_axis_cq_tlast,
        s_axis_cq_tready=s_axis_cq_tready,
        s_axis_cq_tuser=s_axis_cq_tuser,
        s_axis_cq_tvalid=s_axis_cq_tvalid,
        m_axis_cc_tdata=m_axis_cc_tdata,
        m_axis_cc_tkeep=m_axis_cc_tkeep,
        m_axis_cc_tlast=m_axis_cc_tlast,
        m_axis_cc_tready=m_axis_cc_tready,
        m_axis_cc_tuser=m_axis_cc_tuser,
        m_axis_cc_tvalid=m_axis_cc_tvalid,
        cfg_max_payload=cfg_max_payload,
        cfg_max_read_req=cfg_max_read_req,
        cfg_mgmt_addr=cfg_mgmt_addr,
        cfg_mgmt_write=cfg_mgmt_write,
        cfg_mgmt_write_data=cfg_mgmt_write_data,
        cfg_mgmt_byte_enable=cfg_mgmt_byte_enable,
        cfg_mgmt_read=cfg_mgmt_read,
        cfg_mgmt_read_data=cfg_mgmt_read_data,
        cfg_mgmt_read_write_done=cfg_mgmt_read_write_done,
        cfg_interrupt_msi_enable=cfg_interrupt_msi_enable,
        cfg_interrupt_msi_vf_enable=cfg_interrupt_msi_vf_enable,
        cfg_interrupt_msi_int=cfg_interrupt_msi_int,
        cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
        cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
        cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
        cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
        cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
        cfg_interrupt_msi_select=cfg_interrupt_msi_select,
        cfg_interrupt_msi_data=cfg_interrupt_msi_data,
        cfg_interrupt_msi_pending_status_function_num=
        cfg_interrupt_msi_pending_status_function_num,
        cfg_interrupt_msi_pending_status_data_enable=
        cfg_interrupt_msi_pending_status_data_enable,
        cfg_interrupt_msi_attr=cfg_interrupt_msi_attr,
        cfg_interrupt_msi_tph_present=cfg_interrupt_msi_tph_present,
        cfg_interrupt_msi_tph_type=cfg_interrupt_msi_tph_type,
        cfg_interrupt_msi_tph_st_tag=cfg_interrupt_msi_tph_st_tag,
        cfg_interrupt_msi_function_number=cfg_interrupt_msi_function_number,
        status_error_cor=status_error_cor,
        status_error_uncor=status_error_uncor)

    @always(delay(5))
    def clkgen():
        clk.next = not clk

    @always_comb
    def clk_logic():
        sys_clk.next = clk
        sys_reset.next = not rst

    @instance
    def check():
        yield delay(100)
        yield clk.posedge
        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge
        yield delay(100)
        yield clk.posedge

        # testbench stimulus

        current_tag = 1

        yield clk.posedge
        print("test 1: enumeration")
        current_test.next = 1

        yield rc.enumerate(enable_bus_mastering=True, configure_msi=True)

        dev_pf0_bar0 = dev.functions[0].bar[0] & 0xfffffffc
        dev_pf0_bar1 = dev.functions[0].bar[1] & 0xfffffffc

        yield delay(100)

        yield clk.posedge
        print("test 2: memory write to bar 1")
        current_test.next = 2

        yield rc.mem_write(dev_pf0_bar1, b'\x11\x22\x33\x44')

        yield delay(100)

        yield clk.posedge
        print("test 3: memory read from bar 1")
        current_test.next = 3

        val = yield from rc.mem_read(dev_pf0_bar1, 4, 1000)
        print(val)
        assert val == b'\x11\x22\x33\x44'

        yield delay(100)

        yield clk.posedge
        print("test 4: test DMA")
        current_test.next = 4

        # write packet data
        mem_data[0:1024] = bytearray([x % 256 for x in range(1024)])

        # enable DMA
        yield rc.mem_write(dev_pf0_bar0 + 0x100000, struct.pack('<L', 1))

        # write pcie read descriptor
        yield rc.mem_write(dev_pf0_bar0 + 0x100100,
                           struct.pack('<L', (mem_base + 0x0000) & 0xffffffff))
        yield rc.mem_write(
            dev_pf0_bar0 + 0x100104,
            struct.pack('<L', (mem_base + 0x0000 >> 32) & 0xffffffff))
        yield rc.mem_write(dev_pf0_bar0 + 0x100108,
                           struct.pack('<L', (0x100) & 0xffffffff))
        yield rc.mem_write(dev_pf0_bar0 + 0x10010C,
                           struct.pack('<L', (0x100 >> 32) & 0xffffffff))
        yield rc.mem_write(dev_pf0_bar0 + 0x100110, struct.pack('<L', 0x400))
        yield rc.mem_write(dev_pf0_bar0 + 0x100114, struct.pack('<L', 0xAA))

        yield delay(2000)

        # read status
        val = yield from rc.mem_read(dev_pf0_bar0 + 0x100118, 4)
        print(val)

        # write pcie write descriptor
        yield rc.mem_write(dev_pf0_bar0 + 0x100200,
                           struct.pack('<L', (mem_base + 0x1000) & 0xffffffff))
        yield rc.mem_write(
            dev_pf0_bar0 + 0x100204,
            struct.pack('<L', (mem_base + 0x1000 >> 32) & 0xffffffff))
        yield rc.mem_write(dev_pf0_bar0 + 0x100208,
                           struct.pack('<L', (0x100) & 0xffffffff))
        yield rc.mem_write(dev_pf0_bar0 + 0x10020C,
                           struct.pack('<L', (0x100 >> 32) & 0xffffffff))
        yield rc.mem_write(dev_pf0_bar0 + 0x100210, struct.pack('<L', 0x400))
        yield rc.mem_write(dev_pf0_bar0 + 0x100214, struct.pack('<L', 0x55))

        yield delay(2000)

        # read status
        val = yield from rc.mem_read(dev_pf0_bar0 + 0x100218, 4)
        print(val)

        data = mem_data[0x1000:(0x1000) + 64]
        for i in range(0, len(data), 16):
            print(" ".join(
                ("{:02x}".format(c) for c in bytearray(data[i:i + 16]))))

        assert mem_data[0:1024] == mem_data[0x1000:0x1000 + 1024]

        yield delay(100)

        raise StopSimulation

    return instances()
def bench():

    # Parameters
    AXIS_PCIE_DATA_WIDTH = 128
    AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH / 32)
    AXIS_PCIE_RQ_USER_WIDTH = 60
    RQ_SEQ_NUM_WIDTH = 4 if AXIS_PCIE_RQ_USER_WIDTH == 60 else 6
    RQ_SEQ_NUM_ENABLE = 1
    AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH
    AXI_ADDR_WIDTH = 64
    AXI_STRB_WIDTH = (AXI_DATA_WIDTH / 8)
    AXI_ID_WIDTH = 8
    AXI_MAX_BURST_LEN = 256
    PCIE_ADDR_WIDTH = 64
    LEN_WIDTH = 20
    TAG_WIDTH = 8
    OP_TABLE_SIZE = 2**(RQ_SEQ_NUM_WIDTH - 1)
    TX_LIMIT = 2**(RQ_SEQ_NUM_WIDTH - 1)
    TX_FC_ENABLE = 1

    # Inputs
    clk = Signal(bool(0))
    rst = Signal(bool(0))
    current_test = Signal(intbv(0)[8:])

    s_axis_rq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
    s_axis_rq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
    s_axis_rq_tvalid = Signal(bool(0))
    s_axis_rq_tlast = Signal(bool(0))
    s_axis_rq_tuser = Signal(intbv(0)[AXIS_PCIE_RQ_USER_WIDTH:])
    m_axis_rq_tready = Signal(bool(0))
    s_axis_rq_seq_num_0 = Signal(intbv(0)[RQ_SEQ_NUM_WIDTH:])
    s_axis_rq_seq_num_valid_0 = Signal(bool(0))
    s_axis_rq_seq_num_1 = Signal(intbv(0)[RQ_SEQ_NUM_WIDTH:])
    s_axis_rq_seq_num_valid_1 = Signal(bool(0))
    pcie_tx_fc_ph_av = Signal(intbv(0)[8:])
    pcie_tx_fc_pd_av = Signal(intbv(0)[12:])
    s_axis_write_desc_pcie_addr = Signal(intbv(0)[PCIE_ADDR_WIDTH:])
    s_axis_write_desc_axi_addr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
    s_axis_write_desc_len = Signal(intbv(0)[LEN_WIDTH:])
    s_axis_write_desc_tag = Signal(intbv(0)[TAG_WIDTH:])
    s_axis_write_desc_valid = Signal(bool(0))
    m_axi_arready = Signal(bool(0))
    m_axi_rid = Signal(intbv(0)[AXI_ID_WIDTH:])
    m_axi_rdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
    m_axi_rresp = Signal(intbv(0)[2:])
    m_axi_rlast = Signal(bool(0))
    m_axi_rvalid = Signal(bool(0))
    enable = Signal(bool(0))
    requester_id = Signal(intbv(0)[16:])
    requester_id_enable = Signal(bool(0))
    max_payload_size = Signal(intbv(0)[3:])

    # Outputs
    s_axis_rq_tready = Signal(bool(0))
    m_axis_rq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
    m_axis_rq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
    m_axis_rq_tvalid = Signal(bool(0))
    m_axis_rq_tlast = Signal(bool(0))
    m_axis_rq_tuser = Signal(intbv(0)[AXIS_PCIE_RQ_USER_WIDTH:])
    m_axis_rq_seq_num_0 = Signal(intbv(0)[RQ_SEQ_NUM_WIDTH:])
    m_axis_rq_seq_num_valid_0 = Signal(bool(0))
    m_axis_rq_seq_num_1 = Signal(intbv(0)[RQ_SEQ_NUM_WIDTH:])
    m_axis_rq_seq_num_valid_1 = Signal(bool(0))
    s_axis_write_desc_ready = Signal(bool(0))
    m_axis_write_desc_status_tag = Signal(intbv(0)[TAG_WIDTH:])
    m_axis_write_desc_status_valid = Signal(bool(0))
    m_axi_arid = Signal(intbv(0)[AXI_ID_WIDTH:])
    m_axi_araddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
    m_axi_arlen = Signal(intbv(0)[8:])
    m_axi_arsize = Signal(intbv(4)[3:])
    m_axi_arburst = Signal(intbv(1)[2:])
    m_axi_arlock = Signal(bool(0))
    m_axi_arcache = Signal(intbv(3)[4:])
    m_axi_arprot = Signal(intbv(2)[3:])
    m_axi_arvalid = Signal(bool(0))
    m_axi_rready = Signal(bool(0))

    # Clock and Reset Interface
    user_clk = Signal(bool(0))
    user_reset = Signal(bool(0))
    sys_clk = Signal(bool(0))
    sys_reset = Signal(bool(0))

    # AXI4 RAM model
    axi_ram_inst = axi.AXIRam(2**16)

    axi_ram_port0 = axi_ram_inst.create_port(user_clk,
                                             s_axi_arid=m_axi_arid,
                                             s_axi_araddr=m_axi_araddr,
                                             s_axi_arlen=m_axi_arlen,
                                             s_axi_arsize=m_axi_arsize,
                                             s_axi_arburst=m_axi_arburst,
                                             s_axi_arlock=m_axi_arlock,
                                             s_axi_arcache=m_axi_arcache,
                                             s_axi_arprot=m_axi_arprot,
                                             s_axi_arvalid=m_axi_arvalid,
                                             s_axi_arready=m_axi_arready,
                                             s_axi_rid=m_axi_rid,
                                             s_axi_rdata=m_axi_rdata,
                                             s_axi_rresp=m_axi_rresp,
                                             s_axi_rlast=m_axi_rlast,
                                             s_axi_rvalid=m_axi_rvalid,
                                             s_axi_rready=m_axi_rready,
                                             name='port0')

    write_desc_source = axis_ep.AXIStreamSource()

    write_desc_source_logic = write_desc_source.create_logic(
        user_clk,
        user_reset,
        tdata=(s_axis_write_desc_pcie_addr, s_axis_write_desc_axi_addr,
               s_axis_write_desc_len, s_axis_write_desc_tag),
        tvalid=s_axis_write_desc_valid,
        tready=s_axis_write_desc_ready,
        name='write_desc_source')

    write_desc_status_sink = axis_ep.AXIStreamSink()

    write_desc_status_sink_logic = write_desc_status_sink.create_logic(
        user_clk,
        user_reset,
        tdata=(m_axis_write_desc_status_tag, ),
        tvalid=m_axis_write_desc_status_valid,
        name='write_desc_status_sink')

    # PCIe devices
    rc = pcie.RootComplex()

    mem_base, mem_data = rc.alloc_region(16 * 1024 * 1024)

    dev = pcie_us.UltrascalePCIe()

    dev.pcie_generation = 3
    dev.pcie_link_width = 4
    dev.user_clock_frequency = 250e6

    rc.make_port().connect(dev)

    cq_pause = Signal(bool(0))
    cc_pause = Signal(bool(0))
    rq_pause = Signal(bool(0))
    rc_pause = Signal(bool(0))

    pcie_logic = dev.create_logic(
        # Completer reQuest Interface
        m_axis_cq_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
        m_axis_cq_tuser=Signal(intbv(0)[85:]),
        m_axis_cq_tlast=Signal(bool(0)),
        m_axis_cq_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
        m_axis_cq_tvalid=Signal(bool(0)),
        m_axis_cq_tready=Signal(bool(1)),
        #pcie_cq_np_req=pcie_cq_np_req,
        #pcie_cq_np_req_count=pcie_cq_np_req_count,

        # Completer Completion Interface
        s_axis_cc_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
        s_axis_cc_tuser=Signal(intbv(0)[33:]),
        s_axis_cc_tlast=Signal(bool(0)),
        s_axis_cc_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
        s_axis_cc_tvalid=Signal(bool(0)),
        s_axis_cc_tready=Signal(bool(0)),

        # Requester reQuest Interface
        s_axis_rq_tdata=m_axis_rq_tdata,
        s_axis_rq_tuser=m_axis_rq_tuser,
        s_axis_rq_tlast=m_axis_rq_tlast,
        s_axis_rq_tkeep=m_axis_rq_tkeep,
        s_axis_rq_tvalid=m_axis_rq_tvalid,
        s_axis_rq_tready=m_axis_rq_tready,
        pcie_rq_seq_num=s_axis_rq_seq_num_0,
        pcie_rq_seq_num_vld=s_axis_rq_seq_num_valid_0,
        # pcie_rq_tag=pcie_rq_tag,
        # pcie_rq_tag_av=pcie_rq_tag_av,
        # pcie_rq_tag_vld=pcie_rq_tag_vld,

        # Requester Completion Interface
        m_axis_rc_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
        m_axis_rc_tuser=Signal(intbv(0)[75:]),
        m_axis_rc_tlast=Signal(bool(0)),
        m_axis_rc_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
        m_axis_rc_tvalid=Signal(bool(0)),
        m_axis_rc_tready=Signal(bool(0)),

        # Transmit Flow Control Interface
        # pcie_tfc_nph_av=pcie_tfc_nph_av,
        # pcie_tfc_npd_av=pcie_tfc_npd_av,

        # Configuration Flow Control Interface
        cfg_fc_ph=pcie_tx_fc_ph_av,
        cfg_fc_pd=pcie_tx_fc_pd_av,
        #cfg_fc_nph=cfg_fc_nph,
        #cfg_fc_npd=cfg_fc_npd,
        #cfg_fc_cplh=cfg_fc_cplh,
        #cfg_fc_cpld=cfg_fc_cpld,
        cfg_fc_sel=Signal(intbv(0b100)[3:]),

        # Configuration Control Interface
        # cfg_hot_reset_in=cfg_hot_reset_in,
        # cfg_hot_reset_out=cfg_hot_reset_out,
        # cfg_config_space_enable=cfg_config_space_enable,
        # cfg_per_function_update_done=cfg_per_function_update_done,
        # cfg_per_function_number=cfg_per_function_number,
        # cfg_per_function_output_request=cfg_per_function_output_request,
        # cfg_dsn=cfg_dsn,
        # cfg_ds_bus_number=cfg_ds_bus_number,
        # cfg_ds_device_number=cfg_ds_device_number,
        # cfg_ds_function_number=cfg_ds_function_number,
        # cfg_power_state_change_ack=cfg_power_state_change_ack,
        # cfg_power_state_change_interrupt=cfg_power_state_change_interrupt,
        # cfg_err_cor_in=cfg_err_cor_in,
        # cfg_err_uncor_in=cfg_err_uncor_in,
        # cfg_flr_done=cfg_flr_done,
        # cfg_vf_flr_done=cfg_vf_flr_done,
        # cfg_flr_in_process=cfg_flr_in_process,
        # cfg_vf_flr_in_process=cfg_vf_flr_in_process,
        # cfg_req_pm_transition_l23_ready=cfg_req_pm_transition_l23_ready,
        # cfg_link_training_enable=cfg_link_training_enable,

        # Clock and Reset Interface
        user_clk=user_clk,
        user_reset=user_reset,
        #user_lnk_up=user_lnk_up,
        sys_clk=sys_clk,
        sys_clk_gt=sys_clk,
        sys_reset=sys_reset,
        cq_pause=cq_pause,
        cc_pause=cc_pause,
        rq_pause=rq_pause,
        rc_pause=rc_pause)

    # DUT
    if os.system(build_cmd):
        raise Exception("Error running build command")

    dut = Cosimulation(
        "vvp -m myhdl %s.vvp -lxt2" % testbench,
        clk=user_clk,
        rst=user_reset,
        current_test=current_test,
        s_axis_rq_tdata=s_axis_rq_tdata,
        s_axis_rq_tkeep=s_axis_rq_tkeep,
        s_axis_rq_tvalid=s_axis_rq_tvalid,
        s_axis_rq_tready=s_axis_rq_tready,
        s_axis_rq_tlast=s_axis_rq_tlast,
        s_axis_rq_tuser=s_axis_rq_tuser,
        m_axis_rq_tdata=m_axis_rq_tdata,
        m_axis_rq_tkeep=m_axis_rq_tkeep,
        m_axis_rq_tvalid=m_axis_rq_tvalid,
        m_axis_rq_tready=m_axis_rq_tready,
        m_axis_rq_tlast=m_axis_rq_tlast,
        m_axis_rq_tuser=m_axis_rq_tuser,
        s_axis_rq_seq_num_0=s_axis_rq_seq_num_0,
        s_axis_rq_seq_num_valid_0=s_axis_rq_seq_num_valid_0,
        s_axis_rq_seq_num_1=s_axis_rq_seq_num_1,
        s_axis_rq_seq_num_valid_1=s_axis_rq_seq_num_valid_1,
        m_axis_rq_seq_num_0=m_axis_rq_seq_num_0,
        m_axis_rq_seq_num_valid_0=m_axis_rq_seq_num_valid_0,
        m_axis_rq_seq_num_1=m_axis_rq_seq_num_1,
        m_axis_rq_seq_num_valid_1=m_axis_rq_seq_num_valid_1,
        pcie_tx_fc_ph_av=pcie_tx_fc_ph_av,
        pcie_tx_fc_pd_av=pcie_tx_fc_pd_av,
        s_axis_write_desc_pcie_addr=s_axis_write_desc_pcie_addr,
        s_axis_write_desc_axi_addr=s_axis_write_desc_axi_addr,
        s_axis_write_desc_len=s_axis_write_desc_len,
        s_axis_write_desc_tag=s_axis_write_desc_tag,
        s_axis_write_desc_valid=s_axis_write_desc_valid,
        s_axis_write_desc_ready=s_axis_write_desc_ready,
        m_axis_write_desc_status_tag=m_axis_write_desc_status_tag,
        m_axis_write_desc_status_valid=m_axis_write_desc_status_valid,
        m_axi_arid=m_axi_arid,
        m_axi_araddr=m_axi_araddr,
        m_axi_arlen=m_axi_arlen,
        m_axi_arsize=m_axi_arsize,
        m_axi_arburst=m_axi_arburst,
        m_axi_arlock=m_axi_arlock,
        m_axi_arcache=m_axi_arcache,
        m_axi_arprot=m_axi_arprot,
        m_axi_arvalid=m_axi_arvalid,
        m_axi_arready=m_axi_arready,
        m_axi_rid=m_axi_rid,
        m_axi_rdata=m_axi_rdata,
        m_axi_rresp=m_axi_rresp,
        m_axi_rlast=m_axi_rlast,
        m_axi_rvalid=m_axi_rvalid,
        m_axi_rready=m_axi_rready,
        enable=enable,
        requester_id=requester_id,
        requester_id_enable=requester_id_enable,
        max_payload_size=max_payload_size)

    @always(delay(4))
    def clkgen():
        clk.next = not clk

    @always_comb
    def clk_logic():
        sys_clk.next = clk
        sys_reset.next = not rst

    cq_pause_toggle = Signal(bool(0))
    cc_pause_toggle = Signal(bool(0))
    rq_pause_toggle = Signal(bool(0))
    rc_pause_toggle = Signal(bool(0))

    @instance
    def pause_toggle():
        while True:
            if (cq_pause_toggle or cc_pause_toggle or rq_pause_toggle
                    or rc_pause_toggle):
                cq_pause.next = cq_pause_toggle
                cc_pause.next = cc_pause_toggle
                rq_pause.next = rq_pause_toggle
                rc_pause.next = rc_pause_toggle

                yield user_clk.posedge
                yield user_clk.posedge
                yield user_clk.posedge

                cq_pause.next = 0
                cc_pause.next = 0
                rq_pause.next = 0
                rc_pause.next = 0

            yield user_clk.posedge

    @instance
    def check():
        yield delay(100)
        yield clk.posedge
        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge
        yield delay(100)
        yield clk.posedge

        # testbench stimulus

        cur_tag = 1

        max_payload_size.next = 0

        enable.next = 1

        yield user_clk.posedge
        print("test 1: enumeration")
        current_test.next = 1

        yield rc.enumerate(enable_bus_mastering=True)

        yield delay(100)

        yield user_clk.posedge
        print("test 2: PCIe write")
        current_test.next = 2

        pcie_addr = 0x00000000
        axi_addr = 0x00000000
        test_data = b'\x11\x22\x33\x44'

        axi_ram_inst.write_mem(axi_addr, test_data)

        data = axi_ram_inst.read_mem(axi_addr, 32)
        for i in range(0, len(data), 16):
            print(" ".join(
                ("{:02x}".format(c) for c in bytearray(data[i:i + 16]))))

        write_desc_source.send([(mem_base + pcie_addr, axi_addr,
                                 len(test_data), cur_tag)])

        yield write_desc_status_sink.wait(1000)
        yield delay(50)

        status = write_desc_status_sink.recv()

        print(status)

        assert status.data[0][0] == cur_tag

        data = mem_data[pcie_addr:pcie_addr + 32]
        for i in range(0, len(data), 16):
            print(" ".join(
                ("{:02x}".format(c) for c in bytearray(data[i:i + 16]))))

        assert mem_data[pcie_addr:pcie_addr + len(test_data)] == test_data

        cur_tag = (cur_tag + 1) % 256

        yield delay(100)

        yield user_clk.posedge
        print("test 3: various writes")
        current_test.next = 3

        for length in list(range(1, 19)) + list(range(128 - 4,
                                                      128 + 4)) + [1024]:
            for pcie_offset in list(range(8, 13)) + list(
                    range(4096 - 4, 4096 + 4)):
                for axi_offset in list(range(8, 25)) + list(
                        range(4096 - 16, 4096)):
                    for pause in [False, True]:
                        print("length %d, pcie_offset %d, axi_offset %d" %
                              (length, pcie_offset, axi_offset))
                        #pcie_addr = length * 0x100000000 + pcie_offset * 0x10000 + offset
                        pcie_addr = pcie_offset
                        axi_addr = axi_offset
                        test_data = bytearray([x % 256 for x in range(length)])

                        axi_ram_inst.write_mem(
                            axi_addr & 0xffff80,
                            b'\x55' * (len(test_data) + 256))
                        mem_data[(pcie_addr - 1)
                                 & 0xffff80:((pcie_addr - 1) & 0xffff80) +
                                 len(test_data) +
                                 256] = b'\xaa' * (len(test_data) + 256)
                        axi_ram_inst.write_mem(axi_addr, test_data)

                        data = axi_ram_inst.read_mem(axi_addr & 0xfffff0, 64)
                        for i in range(0, len(data), 16):
                            print(" ".join(
                                ("{:02x}".format(c)
                                 for c in bytearray(data[i:i + 16]))))

                        rq_pause_toggle.next = pause

                        write_desc_source.send([
                            (mem_base + pcie_addr, axi_addr, len(test_data),
                             cur_tag)
                        ])

                        yield write_desc_status_sink.wait(4000)
                        yield delay(50)

                        rq_pause_toggle.next = 0

                        status = write_desc_status_sink.recv()

                        print(status)

                        assert status.data[0][0] == cur_tag

                        data = mem_data[pcie_addr
                                        & 0xfffff0:(pcie_addr & 0xfffff0) + 64]
                        for i in range(0, len(data), 16):
                            print(" ".join(
                                ("{:02x}".format(c)
                                 for c in bytearray(data[i:i + 16]))))

                        assert mem_data[pcie_addr - 1:pcie_addr +
                                        len(test_data) +
                                        1] == b'\xaa' + test_data + b'\xaa'

                        cur_tag = (cur_tag + 1) % 256

                        yield delay(100)

        raise StopSimulation

    return instances()
Beispiel #11
0
def bench():

    # Parameters


    # Inputs
    clk = Signal(bool(0))
    rst = Signal(bool(0))
    current_test = Signal(intbv(0)[8:])

    clk_156mhz = Signal(bool(0))
    rst_156mhz = Signal(bool(0))
    clk_250mhz = Signal(bool(0))
    rst_250mhz = Signal(bool(0))
    btnu = Signal(bool(0))
    btnl = Signal(bool(0))
    btnd = Signal(bool(0))
    btnr = Signal(bool(0))
    btnc = Signal(bool(0))
    sw = Signal(intbv(0)[4:])
    i2c_scl_i = Signal(bool(1))
    i2c_sda_i = Signal(bool(1))
    m_axis_rq_tready = Signal(bool(0))
    s_axis_rc_tdata = Signal(intbv(0)[256:])
    s_axis_rc_tkeep = Signal(intbv(0)[8:])
    s_axis_rc_tlast = Signal(bool(0))
    s_axis_rc_tuser = Signal(intbv(0)[75:])
    s_axis_rc_tvalid = Signal(bool(0))
    s_axis_cq_tdata = Signal(intbv(0)[256:])
    s_axis_cq_tkeep = Signal(intbv(0)[8:])
    s_axis_cq_tlast = Signal(bool(0))
    s_axis_cq_tuser = Signal(intbv(0)[85:])
    s_axis_cq_tvalid = Signal(bool(0))
    m_axis_cc_tready = Signal(bool(0))
    pcie_tfc_nph_av = Signal(intbv(0)[2:])
    pcie_tfc_npd_av = Signal(intbv(0)[2:])
    cfg_max_payload = Signal(intbv(0)[3:])
    cfg_max_read_req = Signal(intbv(0)[3:])
    cfg_mgmt_read_data = Signal(intbv(0)[32:])
    cfg_mgmt_read_write_done = Signal(bool(0))
    cfg_interrupt_msi_enable = Signal(intbv(0)[4:])
    cfg_interrupt_msi_vf_enable = Signal(intbv(0)[8:])
    cfg_interrupt_msi_mmenable = Signal(intbv(0)[12:])
    cfg_interrupt_msi_mask_update = Signal(bool(0))
    cfg_interrupt_msi_data = Signal(intbv(0)[32:])
    cfg_interrupt_msi_sent = Signal(bool(0))
    cfg_interrupt_msi_fail = Signal(bool(0))
    qsfp_tx_clk_1 = Signal(bool(0))
    qsfp_tx_rst_1 = Signal(bool(0))
    qsfp_rx_clk_1 = Signal(bool(0))
    qsfp_rx_rst_1 = Signal(bool(0))
    qsfp_rxd_1 = Signal(intbv(0)[64:])
    qsfp_rxc_1 = Signal(intbv(0)[8:])
    qsfp_tx_clk_2 = Signal(bool(0))
    qsfp_tx_rst_2 = Signal(bool(0))
    qsfp_rx_clk_2 = Signal(bool(0))
    qsfp_rx_rst_2 = Signal(bool(0))
    qsfp_rxd_2 = Signal(intbv(0)[64:])
    qsfp_rxc_2 = Signal(intbv(0)[8:])
    qsfp_tx_clk_3 = Signal(bool(0))
    qsfp_tx_rst_3 = Signal(bool(0))
    qsfp_rx_clk_3 = Signal(bool(0))
    qsfp_rx_rst_3 = Signal(bool(0))
    qsfp_rxd_3 = Signal(intbv(0)[64:])
    qsfp_rxc_3 = Signal(intbv(0)[8:])
    qsfp_tx_clk_4 = Signal(bool(0))
    qsfp_tx_rst_4 = Signal(bool(0))
    qsfp_rx_clk_4 = Signal(bool(0))
    qsfp_rx_rst_4 = Signal(bool(0))
    qsfp_rxd_4 = Signal(intbv(0)[64:])
    qsfp_rxc_4 = Signal(intbv(0)[8:])
    qsfp_modprsl = Signal(bool(1))
    qsfp_intl = Signal(bool(1))
    flash_dq_i = Signal(intbv(0)[16:])

    # Outputs
    led = Signal(intbv(0)[8:])
    i2c_scl_o = Signal(bool(1))
    i2c_scl_t = Signal(bool(1))
    i2c_sda_o = Signal(bool(1))
    i2c_sda_t = Signal(bool(1))
    m_axis_rq_tdata = Signal(intbv(0)[256:])
    m_axis_rq_tkeep = Signal(intbv(0)[8:])
    m_axis_rq_tlast = Signal(bool(0))
    m_axis_rq_tuser = Signal(intbv(0)[60:])
    m_axis_rq_tvalid = Signal(bool(0))
    s_axis_rc_tready = Signal(bool(0))
    s_axis_cq_tready = Signal(bool(0))
    m_axis_cc_tdata = Signal(intbv(0)[256:])
    m_axis_cc_tkeep = Signal(intbv(0)[8:])
    m_axis_cc_tlast = Signal(bool(0))
    m_axis_cc_tuser = Signal(intbv(0)[33:])
    m_axis_cc_tvalid = Signal(bool(0))
    status_error_cor = Signal(bool(0))
    status_error_uncor = Signal(bool(0))
    cfg_mgmt_addr = Signal(intbv(0)[19:])
    cfg_mgmt_write = Signal(bool(0))
    cfg_mgmt_write_data = Signal(intbv(0)[32:])
    cfg_mgmt_byte_enable = Signal(intbv(0)[4:])
    cfg_mgmt_read = Signal(bool(0))
    cfg_interrupt_msi_int = Signal(intbv(0)[32:])
    cfg_interrupt_msi_pending_status = Signal(intbv(0)[32:])
    cfg_interrupt_msi_select = Signal(intbv(0)[4:])
    cfg_interrupt_msi_pending_status_function_num = Signal(intbv(0)[4:])
    cfg_interrupt_msi_pending_status_data_enable = Signal(bool(0))
    cfg_interrupt_msi_attr = Signal(intbv(0)[3:])
    cfg_interrupt_msi_tph_present = Signal(bool(0))
    cfg_interrupt_msi_tph_type = Signal(intbv(0)[2:])
    cfg_interrupt_msi_tph_st_tag = Signal(intbv(0)[9:])
    cfg_interrupt_msi_function_number = Signal(intbv(0)[4:])
    qsfp_txd_1 = Signal(intbv(0)[64:])
    qsfp_txc_1 = Signal(intbv(0)[8:])
    qsfp_txd_2 = Signal(intbv(0)[64:])
    qsfp_txc_2 = Signal(intbv(0)[8:])
    qsfp_txd_3 = Signal(intbv(0)[64:])
    qsfp_txc_3 = Signal(intbv(0)[8:])
    qsfp_txd_4 = Signal(intbv(0)[64:])
    qsfp_txc_4 = Signal(intbv(0)[8:])
    qsfp_modsell = Signal(bool(0))
    qsfp_resetl = Signal(bool(1))
    qsfp_lpmode = Signal(bool(0))
    flash_dq_o = Signal(intbv(0)[16:])
    flash_dq_oe = Signal(bool(0))
    flash_addr = Signal(intbv(0)[23:])
    flash_region = Signal(bool(0))
    flash_region_oe = Signal(bool(0))
    flash_ce_n = Signal(bool(1))
    flash_oe_n = Signal(bool(1))
    flash_we_n = Signal(bool(1))
    flash_adv_n = Signal(bool(1))

    # sources and sinks
    qsfp_1_source = xgmii_ep.XGMIISource()
    qsfp_1_source_logic = qsfp_1_source.create_logic(qsfp_rx_clk_1, qsfp_rx_rst_1, txd=qsfp_rxd_1, txc=qsfp_rxc_1, name='qsfp_1_source')

    qsfp_1_sink = xgmii_ep.XGMIISink()
    qsfp_1_sink_logic = qsfp_1_sink.create_logic(qsfp_tx_clk_1, qsfp_tx_rst_1, rxd=qsfp_txd_1, rxc=qsfp_txc_1, name='qsfp_1_sink')

    qsfp_2_source = xgmii_ep.XGMIISource()
    qsfp_2_source_logic = qsfp_2_source.create_logic(qsfp_rx_clk_2, qsfp_rx_rst_2, txd=qsfp_rxd_2, txc=qsfp_rxc_2, name='qsfp_2_source')

    qsfp_2_sink = xgmii_ep.XGMIISink()
    qsfp_2_sink_logic = qsfp_2_sink.create_logic(qsfp_tx_clk_2, qsfp_tx_rst_2, rxd=qsfp_txd_2, rxc=qsfp_txc_2, name='qsfp_2_sink')

    qsfp_3_source = xgmii_ep.XGMIISource()
    qsfp_3_source_logic = qsfp_3_source.create_logic(qsfp_rx_clk_3, qsfp_rx_rst_3, txd=qsfp_rxd_3, txc=qsfp_rxc_3, name='qsfp_3_source')

    qsfp_3_sink = xgmii_ep.XGMIISink()
    qsfp_3_sink_logic = qsfp_3_sink.create_logic(qsfp_tx_clk_3, qsfp_tx_rst_3, rxd=qsfp_txd_3, rxc=qsfp_txc_3, name='qsfp_3_sink')

    qsfp_4_source = xgmii_ep.XGMIISource()
    qsfp_4_source_logic = qsfp_4_source.create_logic(qsfp_rx_clk_4, qsfp_rx_rst_4, txd=qsfp_rxd_4, txc=qsfp_rxc_4, name='qsfp_4_source')

    qsfp_4_sink = xgmii_ep.XGMIISink()
    qsfp_4_sink_logic = qsfp_4_sink.create_logic(qsfp_tx_clk_4, qsfp_tx_rst_4, rxd=qsfp_txd_4, rxc=qsfp_txc_4, name='qsfp_4_sink')

    # Clock and Reset Interface
    user_clk=Signal(bool(0))
    user_reset=Signal(bool(0))
    sys_clk=Signal(bool(0))
    sys_reset=Signal(bool(0))

    # PCIe devices
    rc = pcie.RootComplex()

    rc.max_payload_size = 0x1 # 256 bytes
    rc.max_read_request_size = 0x5 # 4096 bytes

    driver = mqnic.Driver(rc)

    dev = pcie_us.UltrascalePCIe()

    dev.pcie_generation = 3
    dev.pcie_link_width = 8
    dev.user_clock_frequency = 256e6

    dev.functions[0].msi_multiple_message_capable = 5

    dev.functions[0].configure_bar(0, 16*1024*1024)
    dev.functions[0].configure_bar(1, 16*1024*1024)

    rc.make_port().connect(dev)

    pcie_logic = dev.create_logic(
        # Completer reQuest Interface
        m_axis_cq_tdata=s_axis_cq_tdata,
        m_axis_cq_tuser=s_axis_cq_tuser,
        m_axis_cq_tlast=s_axis_cq_tlast,
        m_axis_cq_tkeep=s_axis_cq_tkeep,
        m_axis_cq_tvalid=s_axis_cq_tvalid,
        m_axis_cq_tready=s_axis_cq_tready,
        #pcie_cq_np_req=pcie_cq_np_req,
        pcie_cq_np_req=Signal(bool(1)),
        #pcie_cq_np_req_count=pcie_cq_np_req_count,

        # Completer Completion Interface
        s_axis_cc_tdata=m_axis_cc_tdata,
        s_axis_cc_tuser=m_axis_cc_tuser,
        s_axis_cc_tlast=m_axis_cc_tlast,
        s_axis_cc_tkeep=m_axis_cc_tkeep,
        s_axis_cc_tvalid=m_axis_cc_tvalid,
        s_axis_cc_tready=m_axis_cc_tready,

        # Requester reQuest Interface
        s_axis_rq_tdata=m_axis_rq_tdata,
        s_axis_rq_tuser=m_axis_rq_tuser,
        s_axis_rq_tlast=m_axis_rq_tlast,
        s_axis_rq_tkeep=m_axis_rq_tkeep,
        s_axis_rq_tvalid=m_axis_rq_tvalid,
        s_axis_rq_tready=m_axis_rq_tready,
        #pcie_rq_seq_num=pcie_rq_seq_num,
        #pcie_rq_seq_num_vld=pcie_rq_seq_num_vld,
        #pcie_rq_tag=pcie_rq_tag,
        #pcie_rq_tag_vld=pcie_rq_tag_vld,

        # Requester Completion Interface
        m_axis_rc_tdata=s_axis_rc_tdata,
        m_axis_rc_tuser=s_axis_rc_tuser,
        m_axis_rc_tlast=s_axis_rc_tlast,
        m_axis_rc_tkeep=s_axis_rc_tkeep,
        m_axis_rc_tvalid=s_axis_rc_tvalid,
        m_axis_rc_tready=s_axis_rc_tready,

        # Transmit Flow Control Interface
        pcie_tfc_nph_av=pcie_tfc_nph_av,
        pcie_tfc_npd_av=pcie_tfc_npd_av,

        # Configuration Management Interface
        cfg_mgmt_addr=cfg_mgmt_addr,
        cfg_mgmt_write=cfg_mgmt_write,
        cfg_mgmt_write_data=cfg_mgmt_write_data,
        cfg_mgmt_byte_enable=cfg_mgmt_byte_enable,
        cfg_mgmt_read=cfg_mgmt_read,
        cfg_mgmt_read_data=cfg_mgmt_read_data,
        cfg_mgmt_read_write_done=cfg_mgmt_read_write_done,
        #cfg_mgmt_type1_cfg_reg_access=cfg_mgmt_type1_cfg_reg_access,

        # Configuration Status Interface
        #cfg_phy_link_down=cfg_phy_link_down,
        #cfg_phy_link_status=cfg_phy_link_status,
        #cfg_negotiated_width=cfg_negotiated_width,
        #cfg_current_speed=cfg_current_speed,
        cfg_max_payload=cfg_max_payload,
        cfg_max_read_req=cfg_max_read_req,
        #cfg_function_status=cfg_function_status,
        #cfg_vf_status=cfg_vf_status,
        #cfg_function_power_state=cfg_function_power_state,
        #cfg_vf_power_state=cfg_vf_power_state,
        #cfg_link_power_state=cfg_link_power_state,
        #cfg_err_cor_out=cfg_err_cor_out,
        #cfg_err_nonfatal_out=cfg_err_nonfatal_out,
        #cfg_err_fatal_out=cfg_err_fatal_out,
        #cfg_ltr_enable=cfg_ltr_enable,
        #cfg_ltssm_state=cfg_ltssm_state,
        #cfg_rcb_status=cfg_rcb_status,
        #cfg_dpa_substate_change=cfg_dpa_substate_change,
        #cfg_obff_enable=cfg_obff_enable,
        #cfg_pl_status_change=cfg_pl_status_change,
        #cfg_tph_requester_enable=cfg_tph_requester_enable,
        #cfg_tph_st_mode=cfg_tph_st_mode,
        #cfg_vf_tph_requester_enable=cfg_vf_tph_requester_enable,
        #cfg_vf_tph_st_mode=cfg_vf_tph_st_mode,

        # Configuration Received Message Interface
        #cfg_msg_received=cfg_msg_received,
        #cfg_msg_received_data=cfg_msg_received_data,
        #cfg_msg_received_type=cfg_msg_received_type,

        # Configuration Transmit Message Interface
        #cfg_msg_transmit=cfg_msg_transmit,
        #cfg_msg_transmit_type=cfg_msg_transmit_type,
        #cfg_msg_transmit_data=cfg_msg_transmit_data,
        #cfg_msg_transmit_done=cfg_msg_transmit_done,

        # Configuration Flow Control Interface
        #cfg_fc_ph=cfg_fc_ph,
        #cfg_fc_pd=cfg_fc_pd,
        #cfg_fc_nph=cfg_fc_nph,
        #cfg_fc_npd=cfg_fc_npd,
        #cfg_fc_cplh=cfg_fc_cplh,
        #cfg_fc_cpld=cfg_fc_cpld,
        #cfg_fc_sel=cfg_fc_sel,

        # Per-Function Status Interface
        #cfg_per_func_status_control=cfg_per_func_status_control,
        #cfg_per_func_status_data=cfg_per_func_status_data,

        # Configuration Control Interface
        #cfg_hot_reset_in=cfg_hot_reset_in,
        #cfg_hot_reset_out=cfg_hot_reset_out,
        #cfg_config_space_enable=cfg_config_space_enable,
        #cfg_per_function_update_done=cfg_per_function_update_done,
        #cfg_per_function_number=cfg_per_function_number,
        #cfg_per_function_output_request=cfg_per_function_output_request,
        #cfg_dsn=cfg_dsn,
        #cfg_ds_bus_number=cfg_ds_bus_number,
        #cfg_ds_device_number=cfg_ds_device_number,
        #cfg_ds_function_number=cfg_ds_function_number,
        #cfg_power_state_change_ack=cfg_power_state_change_ack,
        #cfg_power_state_change_interrupt=cfg_power_state_change_interrupt,
        cfg_err_cor_in=status_error_cor,
        cfg_err_uncor_in=status_error_uncor,
        #cfg_flr_done=cfg_flr_done,
        #cfg_vf_flr_done=cfg_vf_flr_done,
        #cfg_flr_in_process=cfg_flr_in_process,
        #cfg_vf_flr_in_process=cfg_vf_flr_in_process,
        #cfg_req_pm_transition_l23_ready=cfg_req_pm_transition_l23_ready,
        #cfg_link_training_enable=cfg_link_training_enable,

        # Configuration Interrupt Controller Interface
        #cfg_interrupt_int=cfg_interrupt_int,
        #cfg_interrupt_sent=cfg_interrupt_sent,
        #cfg_interrupt_pending=cfg_interrupt_pending,
        cfg_interrupt_msi_enable=cfg_interrupt_msi_enable,
        cfg_interrupt_msi_vf_enable=cfg_interrupt_msi_vf_enable,
        cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
        cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
        cfg_interrupt_msi_data=cfg_interrupt_msi_data,
        cfg_interrupt_msi_select=cfg_interrupt_msi_select,
        cfg_interrupt_msi_int=cfg_interrupt_msi_int,
        cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
        cfg_interrupt_msi_pending_status_data_enable=cfg_interrupt_msi_pending_status_data_enable,
        cfg_interrupt_msi_pending_status_function_num=cfg_interrupt_msi_pending_status_function_num,
        cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
        cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
        #cfg_interrupt_msix_enable=cfg_interrupt_msix_enable,
        #cfg_interrupt_msix_mask=cfg_interrupt_msix_mask,
        #cfg_interrupt_msix_vf_enable=cfg_interrupt_msix_vf_enable,
        #cfg_interrupt_msix_vf_mask=cfg_interrupt_msix_vf_mask,
        #cfg_interrupt_msix_address=cfg_interrupt_msix_address,
        #cfg_interrupt_msix_data=cfg_interrupt_msix_data,
        #cfg_interrupt_msix_int=cfg_interrupt_msix_int,
        #cfg_interrupt_msix_sent=cfg_interrupt_msix_sent,
        #cfg_interrupt_msix_fail=cfg_interrupt_msix_fail,
        cfg_interrupt_msi_attr=cfg_interrupt_msi_attr,
        cfg_interrupt_msi_tph_present=cfg_interrupt_msi_tph_present,
        cfg_interrupt_msi_tph_type=cfg_interrupt_msi_tph_type,
        cfg_interrupt_msi_tph_st_tag=cfg_interrupt_msi_tph_st_tag,
        cfg_interrupt_msi_function_number=cfg_interrupt_msi_function_number,

        # Configuration Extend Interface
        #cfg_ext_read_received=cfg_ext_read_received,
        #cfg_ext_write_received=cfg_ext_write_received,
        #cfg_ext_register_number=cfg_ext_register_number,
        #cfg_ext_function_number=cfg_ext_function_number,
        #cfg_ext_write_data=cfg_ext_write_data,
        #cfg_ext_write_byte_enable=cfg_ext_write_byte_enable,
        #cfg_ext_read_data=cfg_ext_read_data,
        #cfg_ext_read_data_valid=cfg_ext_read_data_valid,

        # Clock and Reset Interface
        user_clk=user_clk,
        user_reset=user_reset,
        sys_clk=sys_clk,
        sys_clk_gt=sys_clk,
        sys_reset=sys_reset,
        #pcie_perstn0_out=pcie_perstn0_out,
        #pcie_perstn1_in=pcie_perstn1_in,
        #pcie_perstn1_out=pcie_perstn1_out
    )

    # DUT
    if os.system(build_cmd):
        raise Exception("Error running build command")

    dut = Cosimulation(
        "vvp -m myhdl %s.vvp -lxt2" % testbench,
        clk=clk,
        rst=rst,
        current_test=current_test,
        clk_156mhz=clk_156mhz,
        rst_156mhz=rst_156mhz,
        clk_250mhz=user_clk,
        rst_250mhz=user_reset,
        btnu=btnu,
        btnl=btnl,
        btnd=btnd,
        btnr=btnr,
        btnc=btnc,
        sw=sw,
        led=led,
        i2c_scl_i=i2c_scl_i,
        i2c_scl_o=i2c_scl_o,
        i2c_scl_t=i2c_scl_t,
        i2c_sda_i=i2c_sda_i,
        i2c_sda_o=i2c_sda_o,
        i2c_sda_t=i2c_sda_t,
        m_axis_rq_tdata=m_axis_rq_tdata,
        m_axis_rq_tkeep=m_axis_rq_tkeep,
        m_axis_rq_tlast=m_axis_rq_tlast,
        m_axis_rq_tready=m_axis_rq_tready,
        m_axis_rq_tuser=m_axis_rq_tuser,
        m_axis_rq_tvalid=m_axis_rq_tvalid,
        s_axis_rc_tdata=s_axis_rc_tdata,
        s_axis_rc_tkeep=s_axis_rc_tkeep,
        s_axis_rc_tlast=s_axis_rc_tlast,
        s_axis_rc_tready=s_axis_rc_tready,
        s_axis_rc_tuser=s_axis_rc_tuser,
        s_axis_rc_tvalid=s_axis_rc_tvalid,
        s_axis_cq_tdata=s_axis_cq_tdata,
        s_axis_cq_tkeep=s_axis_cq_tkeep,
        s_axis_cq_tlast=s_axis_cq_tlast,
        s_axis_cq_tready=s_axis_cq_tready,
        s_axis_cq_tuser=s_axis_cq_tuser,
        s_axis_cq_tvalid=s_axis_cq_tvalid,
        m_axis_cc_tdata=m_axis_cc_tdata,
        m_axis_cc_tkeep=m_axis_cc_tkeep,
        m_axis_cc_tlast=m_axis_cc_tlast,
        m_axis_cc_tready=m_axis_cc_tready,
        m_axis_cc_tuser=m_axis_cc_tuser,
        m_axis_cc_tvalid=m_axis_cc_tvalid,
        pcie_tfc_nph_av=pcie_tfc_nph_av,
        pcie_tfc_npd_av=pcie_tfc_npd_av,
        cfg_max_payload=cfg_max_payload,
        cfg_max_read_req=cfg_max_read_req,
        cfg_mgmt_addr=cfg_mgmt_addr,
        cfg_mgmt_write=cfg_mgmt_write,
        cfg_mgmt_write_data=cfg_mgmt_write_data,
        cfg_mgmt_byte_enable=cfg_mgmt_byte_enable,
        cfg_mgmt_read=cfg_mgmt_read,
        cfg_mgmt_read_data=cfg_mgmt_read_data,
        cfg_mgmt_read_write_done=cfg_mgmt_read_write_done,
        cfg_interrupt_msi_enable=cfg_interrupt_msi_enable,
        cfg_interrupt_msi_vf_enable=cfg_interrupt_msi_vf_enable,
        cfg_interrupt_msi_int=cfg_interrupt_msi_int,
        cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
        cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
        cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
        cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
        cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
        cfg_interrupt_msi_select=cfg_interrupt_msi_select,
        cfg_interrupt_msi_data=cfg_interrupt_msi_data,
        cfg_interrupt_msi_pending_status_function_num=cfg_interrupt_msi_pending_status_function_num,
        cfg_interrupt_msi_pending_status_data_enable=cfg_interrupt_msi_pending_status_data_enable,
        cfg_interrupt_msi_attr=cfg_interrupt_msi_attr,
        cfg_interrupt_msi_tph_present=cfg_interrupt_msi_tph_present,
        cfg_interrupt_msi_tph_type=cfg_interrupt_msi_tph_type,
        cfg_interrupt_msi_tph_st_tag=cfg_interrupt_msi_tph_st_tag,
        cfg_interrupt_msi_function_number=cfg_interrupt_msi_function_number,
        status_error_cor=status_error_cor,
        status_error_uncor=status_error_uncor,
        qsfp_tx_clk_1=qsfp_tx_clk_1,
        qsfp_tx_rst_1=qsfp_tx_rst_1,
        qsfp_txd_1=qsfp_txd_1,
        qsfp_txc_1=qsfp_txc_1,
        qsfp_rx_clk_1=qsfp_rx_clk_1,
        qsfp_rx_rst_1=qsfp_rx_rst_1,
        qsfp_rxd_1=qsfp_rxd_1,
        qsfp_rxc_1=qsfp_rxc_1,
        qsfp_tx_clk_2=qsfp_tx_clk_2,
        qsfp_tx_rst_2=qsfp_tx_rst_2,
        qsfp_txd_2=qsfp_txd_2,
        qsfp_txc_2=qsfp_txc_2,
        qsfp_rx_clk_2=qsfp_rx_clk_2,
        qsfp_rx_rst_2=qsfp_rx_rst_2,
        qsfp_rxd_2=qsfp_rxd_2,
        qsfp_rxc_2=qsfp_rxc_2,
        qsfp_tx_clk_3=qsfp_tx_clk_3,
        qsfp_tx_rst_3=qsfp_tx_rst_3,
        qsfp_txd_3=qsfp_txd_3,
        qsfp_txc_3=qsfp_txc_3,
        qsfp_rx_clk_3=qsfp_rx_clk_3,
        qsfp_rx_rst_3=qsfp_rx_rst_3,
        qsfp_rxd_3=qsfp_rxd_3,
        qsfp_rxc_3=qsfp_rxc_3,
        qsfp_tx_clk_4=qsfp_tx_clk_4,
        qsfp_tx_rst_4=qsfp_tx_rst_4,
        qsfp_txd_4=qsfp_txd_4,
        qsfp_txc_4=qsfp_txc_4,
        qsfp_rx_clk_4=qsfp_rx_clk_4,
        qsfp_rx_rst_4=qsfp_rx_rst_4,
        qsfp_rxd_4=qsfp_rxd_4,
        qsfp_rxc_4=qsfp_rxc_4,
        qsfp_modsell=qsfp_modsell,
        qsfp_resetl=qsfp_resetl,
        qsfp_modprsl=qsfp_modprsl,
        qsfp_intl=qsfp_intl,
        qsfp_lpmode=qsfp_lpmode,
        flash_dq_i=flash_dq_i,
        flash_dq_o=flash_dq_o,
        flash_dq_oe=flash_dq_oe,
        flash_addr=flash_addr,
        flash_region=flash_region,
        flash_region_oe=flash_region_oe,
        flash_ce_n=flash_ce_n,
        flash_oe_n=flash_oe_n,
        flash_we_n=flash_we_n,
        flash_adv_n=flash_adv_n
    )

    @always(delay(5))
    def clkgen():
        clk.next = not clk

    @always(delay(3))
    def clkgen2():
        qsfp_tx_clk_1.next = not qsfp_tx_clk_1
        qsfp_rx_clk_1.next = not qsfp_rx_clk_1
        qsfp_tx_clk_2.next = not qsfp_tx_clk_2
        qsfp_rx_clk_2.next = not qsfp_rx_clk_2
        qsfp_tx_clk_3.next = not qsfp_tx_clk_3
        qsfp_rx_clk_3.next = not qsfp_rx_clk_3
        qsfp_tx_clk_4.next = not qsfp_tx_clk_4
        qsfp_rx_clk_4.next = not qsfp_rx_clk_4

    @always_comb
    def clk_logic():
        sys_clk.next = clk
        sys_reset.next = not rst

    loopback_enable = Signal(bool(0))

    @instance
    def loopback():
        while True:

            yield clk.posedge

            if loopback_enable:
                if not qsfp_1_sink.empty():
                    pkt = qsfp_1_sink.recv()
                    qsfp_1_source.send(pkt)
                if not qsfp_2_sink.empty():
                    pkt = qsfp_2_sink.recv()
                    qsfp_2_source.send(pkt)
                if not qsfp_3_sink.empty():
                    pkt = qsfp_3_sink.recv()
                    qsfp_3_source.send(pkt)
                if not qsfp_4_sink.empty():
                    pkt = qsfp_4_sink.recv()
                    qsfp_4_source.send(pkt)

    @instance
    def check():
        yield delay(100)
        yield clk.posedge
        rst.next = 1
        qsfp_tx_rst_1.next = 1
        qsfp_rx_rst_1.next = 1
        qsfp_tx_rst_2.next = 1
        qsfp_rx_rst_2.next = 1
        qsfp_tx_rst_3.next = 1
        qsfp_rx_rst_3.next = 1
        qsfp_tx_rst_4.next = 1
        qsfp_rx_rst_4.next = 1
        yield clk.posedge
        rst.next = 0
        qsfp_tx_rst_1.next = 0
        qsfp_rx_rst_1.next = 0
        qsfp_tx_rst_2.next = 0
        qsfp_rx_rst_2.next = 0
        qsfp_tx_rst_3.next = 0
        qsfp_rx_rst_3.next = 0
        qsfp_tx_rst_4.next = 0
        qsfp_rx_rst_4.next = 0
        yield clk.posedge
        yield delay(100)
        yield clk.posedge

        # testbench stimulus

        current_tag = 1

        yield clk.posedge
        print("test 1: enumeration")
        current_test.next = 1

        yield rc.enumerate(enable_bus_mastering=True, configure_msi=True)

        dev_pf0_bar0 = dev.functions[0].bar[0] & 0xfffffffc
        dev_pf0_bar1 = dev.functions[0].bar[1] & 0xfffffffc

        yield from rc.mem_write_dword(dev_pf0_bar0+0x270, 0);
        yield from rc.mem_write_dword(dev_pf0_bar0+0x274, 0);
        yield from rc.mem_write_dword(dev_pf0_bar0+0x278, 0);
        yield from rc.mem_write_dword(dev_pf0_bar0+0x27C, 0);

        yield from rc.mem_write_dword(dev_pf0_bar0+0x290, 0);
        yield from rc.mem_write_dword(dev_pf0_bar0+0x294, 1000);
        yield from rc.mem_write_dword(dev_pf0_bar0+0x298, 0);
        yield from rc.mem_write_dword(dev_pf0_bar0+0x29C, 0);

        yield from rc.mem_write_dword(dev_pf0_bar0+0x280, 0);
        yield from rc.mem_write_dword(dev_pf0_bar0+0x284, 2000);
        yield from rc.mem_write_dword(dev_pf0_bar0+0x288, 0);
        yield from rc.mem_write_dword(dev_pf0_bar0+0x28C, 0);

        yield delay(100)

        yield clk.posedge
        print("test 2: init NIC")
        current_test.next = 2

        yield from driver.init_dev(dev.functions[0].get_id())
        yield from driver.interfaces[0].open()

        # enable queues
        yield from rc.mem_write_dword(driver.interfaces[0].ports[0].schedulers[0].hw_addr+0x0200, 0xffffffff)
        yield from rc.mem_write_dword(driver.interfaces[0].ports[0].schedulers[0].hw_addr+0x0300, 0xffffffff)

        yield from rc.mem_read(driver.hw_addr, 4) # wait for all writes to complete

        yield delay(100)

        yield clk.posedge
        print("test 3: send and receive a packet")
        current_test.next = 3

        data = bytearray([x%256 for x in range(1024)])

        yield from driver.interfaces[0].start_xmit(data, 0)

        yield qsfp_1_sink.wait()

        pkt = qsfp_1_sink.recv()
        print(pkt)

        qsfp_1_source.send(pkt)

        yield driver.interfaces[0].wait()

        pkt = driver.interfaces[0].recv()

        print(pkt)

        yield delay(100)

        yield clk.posedge
        print("test 4: multiple small packets")
        current_test.next = 4

        count = 64

        pkts = [bytearray([(x+k)%256 for x in range(64)]) for k in range(count)]

        loopback_enable.next = True

        for p in pkts:
            yield from driver.interfaces[0].start_xmit(p, 0)

        for k in range(count):
            pkt = driver.interfaces[0].recv()

            if not pkt:
                yield driver.interfaces[0].wait()
                pkt = driver.interfaces[0].recv()

            print(pkt)
            assert pkt.data == pkts[k]
            assert frame_checksum(pkt.data) == pkt.rx_checksum

        loopback_enable.next = False

        yield delay(100)

        yield clk.posedge
        print("test 5: multiple large packets")
        current_test.next = 5

        count = 64

        pkts = [bytearray([(x+k)%256 for x in range(1514)]) for k in range(count)]

        loopback_enable.next = True

        for p in pkts:
            yield from driver.interfaces[0].start_xmit(p, 0)

        for k in range(count):
            pkt = driver.interfaces[0].recv()

            if not pkt:
                yield driver.interfaces[0].wait()
                pkt = driver.interfaces[0].recv()

            print(pkt)
            assert pkt.data == pkts[k]
            assert frame_checksum(pkt.data) == pkt.rx_checksum

        loopback_enable.next = False

        yield delay(1000)

        yield clk.posedge
        print("test 6: TDMA")
        current_test.next = 6

        count = 16

        pkts = [bytearray([(x+k)%256 for x in range(1514)]) for k in range(count)]

        loopback_enable.next = True

        # configure TDMA

        # configure TDMA scheduler
        yield from rc.mem_write_dword(driver.interfaces[0].ports[0].schedulers[0].hw_addr+0x00120, 0) # schedule period fns
        yield from rc.mem_write_dword(driver.interfaces[0].ports[0].schedulers[0].hw_addr+0x00124, 40000) # schedule period ns
        yield from rc.mem_write_dword(driver.interfaces[0].ports[0].schedulers[0].hw_addr+0x00128, 0) # schedule period sec (low)
        yield from rc.mem_write_dword(driver.interfaces[0].ports[0].schedulers[0].hw_addr+0x0012c, 0) # schedule period sec (high)
        yield from rc.mem_write_dword(driver.interfaces[0].ports[0].schedulers[0].hw_addr+0x00130, 0) # timeslot period fns
        yield from rc.mem_write_dword(driver.interfaces[0].ports[0].schedulers[0].hw_addr+0x00134, 10000) # timeslot period ns
        yield from rc.mem_write_dword(driver.interfaces[0].ports[0].schedulers[0].hw_addr+0x00138, 0) # timeslot period sec (low)
        yield from rc.mem_write_dword(driver.interfaces[0].ports[0].schedulers[0].hw_addr+0x0013c, 0) # timeslot period sec (high)
        yield from rc.mem_write_dword(driver.interfaces[0].ports[0].schedulers[0].hw_addr+0x00140, 0) # active period fns
        yield from rc.mem_write_dword(driver.interfaces[0].ports[0].schedulers[0].hw_addr+0x00144, 5000) # active period ns
        yield from rc.mem_write_dword(driver.interfaces[0].ports[0].schedulers[0].hw_addr+0x00148, 0) # active period sec (low)
        yield from rc.mem_write_dword(driver.interfaces[0].ports[0].schedulers[0].hw_addr+0x0014c, 0) # active period sec (high)
        yield from rc.mem_write_dword(driver.interfaces[0].ports[0].schedulers[0].hw_addr+0x00110, 0) # schedule start fns
        yield from rc.mem_write_dword(driver.interfaces[0].ports[0].schedulers[0].hw_addr+0x00114, 200000) # schedule start ns
        yield from rc.mem_write_dword(driver.interfaces[0].ports[0].schedulers[0].hw_addr+0x00118, 0) # schedule start sec (low)
        yield from rc.mem_write_dword(driver.interfaces[0].ports[0].schedulers[0].hw_addr+0x0011c, 0) # schedule start sec (high)
        yield from rc.mem_write_dword(driver.interfaces[0].ports[0].schedulers[0].hw_addr+0x00100, 0x00000001)

        # enable queues
        yield from rc.mem_write_dword(driver.interfaces[0].ports[0].schedulers[0].hw_addr+0x00200, 0xffffffff)
        # disable global enable
        yield from rc.mem_write_dword(driver.interfaces[0].ports[0].schedulers[0].hw_addr+0x00300, 0x00000000)

        # configure slots
        yield from rc.mem_write_dword(driver.interfaces[0].ports[0].schedulers[0].hw_addr+0x10000, 0x00000001)
        yield from rc.mem_write_dword(driver.interfaces[0].ports[0].schedulers[0].hw_addr+0x10100, 0x00000002)
        yield from rc.mem_write_dword(driver.interfaces[0].ports[0].schedulers[0].hw_addr+0x10200, 0x00000004)
        yield from rc.mem_write_dword(driver.interfaces[0].ports[0].schedulers[0].hw_addr+0x10300, 0x00000008)

        yield from rc.mem_read(driver.hw_addr, 4) # wait for all writes to complete

        # send packets
        for k in range(count):
            yield from driver.interfaces[0].start_xmit(pkts[k], k%4)

        for k in range(count):
            pkt = driver.interfaces[0].recv()

            if not pkt:
                yield driver.interfaces[0].wait()
                pkt = driver.interfaces[0].recv()

            print(pkt)
            #assert pkt.data == pkts[k]
            #assert frame_checksum(pkt.data) == pkt.rx_checksum

        loopback_enable.next = False

        yield delay(100)

        raise StopSimulation

    return instances()
Beispiel #12
0
def bench():

    # Parameters
    AXIS_PCIE_DATA_WIDTH = 256
    AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
    AXIS_PCIE_RC_USER_WIDTH = 75
    AXIS_PCIE_RQ_USER_WIDTH = 60
    AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH
    AXI_ADDR_WIDTH = 64
    AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8)
    AXI_ID_WIDTH = 8
    AXI_MAX_BURST_LEN = 256
    PCIE_ADDR_WIDTH = 64
    PCIE_TAG_COUNT = 64 if AXIS_PCIE_RQ_USER_WIDTH == 60 else 256
    PCIE_TAG_WIDTH = (PCIE_TAG_COUNT-1).bit_length()
    PCIE_EXT_TAG_ENABLE = 1
    LEN_WIDTH = 20
    TAG_WIDTH = 8

    # Inputs
    clk = Signal(bool(0))
    rst = Signal(bool(0))
    current_test = Signal(intbv(0)[8:])

    s_axis_rc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
    s_axis_rc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
    s_axis_rc_tvalid = Signal(bool(0))
    s_axis_rc_tlast = Signal(bool(0))
    s_axis_rc_tuser = Signal(intbv(0)[AXIS_PCIE_RC_USER_WIDTH:])
    m_axis_rq_tready = Signal(bool(0))
    s_axis_read_desc_pcie_addr = Signal(intbv(0)[PCIE_ADDR_WIDTH:])
    s_axis_read_desc_axi_addr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
    s_axis_read_desc_len = Signal(intbv(0)[LEN_WIDTH:])
    s_axis_read_desc_tag = Signal(intbv(0)[TAG_WIDTH:])
    s_axis_read_desc_valid = Signal(bool(0))
    s_axis_write_desc_pcie_addr = Signal(intbv(0)[PCIE_ADDR_WIDTH:])
    s_axis_write_desc_axi_addr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
    s_axis_write_desc_len = Signal(intbv(0)[LEN_WIDTH:])
    s_axis_write_desc_tag = Signal(intbv(0)[TAG_WIDTH:])
    s_axis_write_desc_valid = Signal(bool(0))
    m_axi_awready = Signal(bool(0))
    m_axi_wready = Signal(bool(0))
    m_axi_bid = Signal(intbv(0)[AXI_ID_WIDTH:])
    m_axi_bresp = Signal(intbv(0)[2:])
    m_axi_bvalid = Signal(bool(0))
    m_axi_arready = Signal(bool(0))
    m_axi_rid = Signal(intbv(0)[AXI_ID_WIDTH:])
    m_axi_rdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
    m_axi_rresp = Signal(intbv(0)[2:])
    m_axi_rlast = Signal(bool(0))
    m_axi_rvalid = Signal(bool(0))
    read_enable = Signal(bool(0))
    write_enable = Signal(bool(0))
    ext_tag_enable = Signal(bool(0))
    requester_id = Signal(intbv(0)[16:])
    requester_id_enable = Signal(bool(0))
    max_read_request_size = Signal(intbv(0)[3:])
    max_payload_size = Signal(intbv(0)[3:])

    # Outputs
    s_axis_rc_tready = Signal(bool(0))
    m_axis_rq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
    m_axis_rq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
    m_axis_rq_tvalid = Signal(bool(0))
    m_axis_rq_tlast = Signal(bool(0))
    m_axis_rq_tuser = Signal(intbv(0)[AXIS_PCIE_RQ_USER_WIDTH:])
    s_axis_read_desc_ready = Signal(bool(0))
    m_axis_read_desc_status_tag = Signal(intbv(0)[TAG_WIDTH:])
    m_axis_read_desc_status_valid = Signal(bool(0))
    s_axis_write_desc_ready = Signal(bool(0))
    m_axis_write_desc_status_tag = Signal(intbv(0)[TAG_WIDTH:])
    m_axis_write_desc_status_valid = Signal(bool(0))
    m_axi_awid = Signal(intbv(0)[AXI_ID_WIDTH:])
    m_axi_awaddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
    m_axi_awlen = Signal(intbv(0)[8:])
    m_axi_awsize = Signal(intbv(5)[3:])
    m_axi_awburst = Signal(intbv(1)[2:])
    m_axi_awlock = Signal(bool(0))
    m_axi_awcache = Signal(intbv(3)[4:])
    m_axi_awprot = Signal(intbv(2)[3:])
    m_axi_awvalid = Signal(bool(0))
    m_axi_wdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
    m_axi_wstrb = Signal(intbv(0)[AXI_STRB_WIDTH:])
    m_axi_wlast = Signal(bool(0))
    m_axi_wvalid = Signal(bool(0))
    m_axi_bready = Signal(bool(0))
    m_axi_arid = Signal(intbv(0)[AXI_ID_WIDTH:])
    m_axi_araddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
    m_axi_arlen = Signal(intbv(0)[8:])
    m_axi_arsize = Signal(intbv(5)[3:])
    m_axi_arburst = Signal(intbv(1)[2:])
    m_axi_arlock = Signal(bool(0))
    m_axi_arcache = Signal(intbv(3)[4:])
    m_axi_arprot = Signal(intbv(2)[3:])
    m_axi_arvalid = Signal(bool(0))
    m_axi_rready = Signal(bool(0))
    status_error_cor = Signal(bool(0))
    status_error_uncor = Signal(bool(0))

    # Clock and Reset Interface
    user_clk=Signal(bool(0))
    user_reset=Signal(bool(0))
    sys_clk=Signal(bool(0))
    sys_reset=Signal(bool(0))

    # AXI4 RAM model
    axi_ram_inst = axi.AXIRam(2**16)

    axi_ram_port0 = axi_ram_inst.create_port(
        user_clk,
        s_axi_awid=m_axi_awid,
        s_axi_awaddr=m_axi_awaddr,
        s_axi_awlen=m_axi_awlen,
        s_axi_awsize=m_axi_awsize,
        s_axi_awburst=m_axi_awburst,
        s_axi_awlock=m_axi_awlock,
        s_axi_awcache=m_axi_awcache,
        s_axi_awprot=m_axi_awprot,
        s_axi_awvalid=m_axi_awvalid,
        s_axi_awready=m_axi_awready,
        s_axi_wdata=m_axi_wdata,
        s_axi_wstrb=m_axi_wstrb,
        s_axi_wlast=m_axi_wlast,
        s_axi_wvalid=m_axi_wvalid,
        s_axi_wready=m_axi_wready,
        s_axi_bid=m_axi_bid,
        s_axi_bresp=m_axi_bresp,
        s_axi_bvalid=m_axi_bvalid,
        s_axi_bready=m_axi_bready,
        s_axi_arid=m_axi_arid,
        s_axi_araddr=m_axi_araddr,
        s_axi_arlen=m_axi_arlen,
        s_axi_arsize=m_axi_arsize,
        s_axi_arburst=m_axi_arburst,
        s_axi_arlock=m_axi_arlock,
        s_axi_arcache=m_axi_arcache,
        s_axi_arprot=m_axi_arprot,
        s_axi_arvalid=m_axi_arvalid,
        s_axi_arready=m_axi_arready,
        s_axi_rid=m_axi_rid,
        s_axi_rdata=m_axi_rdata,
        s_axi_rresp=m_axi_rresp,
        s_axi_rlast=m_axi_rlast,
        s_axi_rvalid=m_axi_rvalid,
        s_axi_rready=m_axi_rready,
        name='port0'
    )

    # sources and sinks
    read_desc_source = axis_ep.AXIStreamSource()

    read_desc_source_logic = read_desc_source.create_logic(
        user_clk,
        user_reset,
        tdata=(s_axis_read_desc_pcie_addr, s_axis_read_desc_axi_addr, s_axis_read_desc_len, s_axis_read_desc_tag),
        tvalid=s_axis_read_desc_valid,
        tready=s_axis_read_desc_ready,
        name='read_desc_source'
    )

    read_desc_status_sink = axis_ep.AXIStreamSink()

    read_desc_status_sink_logic = read_desc_status_sink.create_logic(
        user_clk,
        user_reset,
        tdata=(m_axis_read_desc_status_tag,),
        tvalid=m_axis_read_desc_status_valid,
        name='read_desc_status_sink'
    )

    write_desc_source = axis_ep.AXIStreamSource()

    write_desc_source_logic = write_desc_source.create_logic(
        user_clk,
        user_reset,
        tdata=(s_axis_write_desc_pcie_addr, s_axis_write_desc_axi_addr, s_axis_write_desc_len, s_axis_write_desc_tag),
        tvalid=s_axis_write_desc_valid,
        tready=s_axis_write_desc_ready,
        name='write_desc_source'
    )

    write_desc_status_sink = axis_ep.AXIStreamSink()

    write_desc_status_sink_logic = write_desc_status_sink.create_logic(
        user_clk,
        user_reset,
        tdata=(m_axis_write_desc_status_tag,),
        tvalid=m_axis_write_desc_status_valid,
        name='write_desc_status_sink'
    )

    # PCIe devices
    rc = pcie.RootComplex()

    mem_base, mem_data = rc.alloc_region(16*1024*1024)

    dev = pcie_us.UltrascalePCIe()

    dev.pcie_generation = 3
    dev.pcie_link_width = 8
    dev.user_clock_frequency = 256e6

    rc.make_port().connect(dev)

    pcie_logic = dev.create_logic(
        # Completer reQuest Interface
        m_axis_cq_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
        m_axis_cq_tuser=Signal(intbv(0)[85:]),
        m_axis_cq_tlast=Signal(bool(0)),
        m_axis_cq_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
        m_axis_cq_tvalid=Signal(bool(0)),
        m_axis_cq_tready=Signal(bool(1)),
        pcie_cq_np_req=Signal(bool(1)),
        pcie_cq_np_req_count=Signal(intbv(0)[6:]),

        # Completer Completion Interface
        s_axis_cc_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
        s_axis_cc_tuser=Signal(intbv(0)[33:]),
        s_axis_cc_tlast=Signal(bool(0)),
        s_axis_cc_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
        s_axis_cc_tvalid=Signal(bool(0)),
        s_axis_cc_tready=Signal(bool(0)),

        # Requester reQuest Interface
        s_axis_rq_tdata=m_axis_rq_tdata,
        s_axis_rq_tuser=m_axis_rq_tuser,
        s_axis_rq_tlast=m_axis_rq_tlast,
        s_axis_rq_tkeep=m_axis_rq_tkeep,
        s_axis_rq_tvalid=m_axis_rq_tvalid,
        s_axis_rq_tready=m_axis_rq_tready,
        # pcie_rq_seq_num=pcie_rq_seq_num,
        # pcie_rq_seq_num_vld=pcie_rq_seq_num_vld,
        # pcie_rq_tag=pcie_rq_tag,
        # pcie_rq_tag_av=pcie_rq_tag_av,
        # pcie_rq_tag_vld=pcie_rq_tag_vld,

        # Requester Completion Interface
        m_axis_rc_tdata=s_axis_rc_tdata,
        m_axis_rc_tuser=s_axis_rc_tuser,
        m_axis_rc_tlast=s_axis_rc_tlast,
        m_axis_rc_tkeep=s_axis_rc_tkeep,
        m_axis_rc_tvalid=s_axis_rc_tvalid,
        m_axis_rc_tready=s_axis_rc_tready,

        # Transmit Flow Control Interface
        # pcie_tfc_nph_av=pcie_tfc_nph_av,
        # pcie_tfc_npd_av=pcie_tfc_npd_av,

        # Configuration Control Interface
        # cfg_hot_reset_in=cfg_hot_reset_in,
        # cfg_hot_reset_out=cfg_hot_reset_out,
        # cfg_config_space_enable=cfg_config_space_enable,
        # cfg_per_function_update_done=cfg_per_function_update_done,
        # cfg_per_function_number=cfg_per_function_number,
        # cfg_per_function_output_request=cfg_per_function_output_request,
        # cfg_dsn=cfg_dsn,
        # cfg_ds_bus_number=cfg_ds_bus_number,
        # cfg_ds_device_number=cfg_ds_device_number,
        # cfg_ds_function_number=cfg_ds_function_number,
        # cfg_power_state_change_ack=cfg_power_state_change_ack,
        # cfg_power_state_change_interrupt=cfg_power_state_change_interrupt,
        # cfg_err_cor_in=cfg_err_cor_in,
        # cfg_err_uncor_in=cfg_err_uncor_in,
        # cfg_flr_done=cfg_flr_done,
        # cfg_vf_flr_done=cfg_vf_flr_done,
        # cfg_flr_in_process=cfg_flr_in_process,
        # cfg_vf_flr_in_process=cfg_vf_flr_in_process,
        # cfg_req_pm_transition_l23_ready=cfg_req_pm_transition_l23_ready,
        # cfg_link_training_enable=cfg_link_training_enable,

        # Clock and Reset Interface
        user_clk=user_clk,
        user_reset=user_reset,
        #user_lnk_up=user_lnk_up,
        sys_clk=sys_clk,
        sys_clk_gt=sys_clk,
        sys_reset=sys_reset
    )

    # DUT
    if os.system(build_cmd):
        raise Exception("Error running build command")

    dut = Cosimulation(
        "vvp -m myhdl %s.vvp -lxt2" % testbench,
        clk=user_clk,
        rst=user_reset,
        current_test=current_test,
        s_axis_rc_tdata=s_axis_rc_tdata,
        s_axis_rc_tkeep=s_axis_rc_tkeep,
        s_axis_rc_tvalid=s_axis_rc_tvalid,
        s_axis_rc_tready=s_axis_rc_tready,
        s_axis_rc_tlast=s_axis_rc_tlast,
        s_axis_rc_tuser=s_axis_rc_tuser,
        m_axis_rq_tdata=m_axis_rq_tdata,
        m_axis_rq_tkeep=m_axis_rq_tkeep,
        m_axis_rq_tvalid=m_axis_rq_tvalid,
        m_axis_rq_tready=m_axis_rq_tready,
        m_axis_rq_tlast=m_axis_rq_tlast,
        m_axis_rq_tuser=m_axis_rq_tuser,
        s_axis_read_desc_pcie_addr=s_axis_read_desc_pcie_addr,
        s_axis_read_desc_axi_addr=s_axis_read_desc_axi_addr,
        s_axis_read_desc_len=s_axis_read_desc_len,
        s_axis_read_desc_tag=s_axis_read_desc_tag,
        s_axis_read_desc_valid=s_axis_read_desc_valid,
        s_axis_read_desc_ready=s_axis_read_desc_ready,
        m_axis_read_desc_status_tag=m_axis_read_desc_status_tag,
        m_axis_read_desc_status_valid=m_axis_read_desc_status_valid,
        s_axis_write_desc_pcie_addr=s_axis_write_desc_pcie_addr,
        s_axis_write_desc_axi_addr=s_axis_write_desc_axi_addr,
        s_axis_write_desc_len=s_axis_write_desc_len,
        s_axis_write_desc_tag=s_axis_write_desc_tag,
        s_axis_write_desc_valid=s_axis_write_desc_valid,
        s_axis_write_desc_ready=s_axis_write_desc_ready,
        m_axis_write_desc_status_tag=m_axis_write_desc_status_tag,
        m_axis_write_desc_status_valid=m_axis_write_desc_status_valid,
        m_axi_awid=m_axi_awid,
        m_axi_awaddr=m_axi_awaddr,
        m_axi_awlen=m_axi_awlen,
        m_axi_awsize=m_axi_awsize,
        m_axi_awburst=m_axi_awburst,
        m_axi_awlock=m_axi_awlock,
        m_axi_awcache=m_axi_awcache,
        m_axi_awprot=m_axi_awprot,
        m_axi_awvalid=m_axi_awvalid,
        m_axi_awready=m_axi_awready,
        m_axi_wdata=m_axi_wdata,
        m_axi_wstrb=m_axi_wstrb,
        m_axi_wlast=m_axi_wlast,
        m_axi_wvalid=m_axi_wvalid,
        m_axi_wready=m_axi_wready,
        m_axi_bid=m_axi_bid,
        m_axi_bresp=m_axi_bresp,
        m_axi_bvalid=m_axi_bvalid,
        m_axi_bready=m_axi_bready,
        m_axi_arid=m_axi_arid,
        m_axi_araddr=m_axi_araddr,
        m_axi_arlen=m_axi_arlen,
        m_axi_arsize=m_axi_arsize,
        m_axi_arburst=m_axi_arburst,
        m_axi_arlock=m_axi_arlock,
        m_axi_arcache=m_axi_arcache,
        m_axi_arprot=m_axi_arprot,
        m_axi_arvalid=m_axi_arvalid,
        m_axi_arready=m_axi_arready,
        m_axi_rid=m_axi_rid,
        m_axi_rdata=m_axi_rdata,
        m_axi_rresp=m_axi_rresp,
        m_axi_rlast=m_axi_rlast,
        m_axi_rvalid=m_axi_rvalid,
        m_axi_rready=m_axi_rready,
        read_enable=read_enable,
        write_enable=write_enable,
        ext_tag_enable=ext_tag_enable,
        requester_id=requester_id,
        requester_id_enable=requester_id_enable,
        max_read_request_size=max_read_request_size,
        max_payload_size=max_payload_size,
        status_error_cor=status_error_cor,
        status_error_uncor=status_error_uncor
    )

    @always(delay(4))
    def clkgen():
        clk.next = not clk

    @always_comb
    def clk_logic():
        sys_clk.next = clk
        sys_reset.next = not rst

    @instance
    def check():
        yield delay(100)
        yield clk.posedge
        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge
        yield delay(100)
        yield clk.posedge

        # testbench stimulus

        cur_tag = 1

        max_payload_size.next = 0
        max_read_request_size.next = 2

        read_enable.next = 1
        write_enable.next = 1

        yield user_clk.posedge
        print("test 1: enumeration")
        current_test.next = 1

        yield rc.enumerate(enable_bus_mastering=True)

        yield delay(100)

        yield user_clk.posedge
        print("test 2: PCIe write")
        current_test.next = 2

        pcie_addr = 0x00000000
        axi_addr = 0x00000000
        test_data = b'\x11\x22\x33\x44'

        axi_ram_inst.write_mem(axi_addr, test_data)
        mem_data[pcie_addr:pcie_addr+len(test_data)] = b'\x00'*len(test_data)

        data = axi_ram_inst.read_mem(axi_addr, 32)
        for i in range(0, len(data), 16):
            print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))

        write_desc_source.send([(mem_base+pcie_addr, axi_addr, len(test_data), cur_tag)])

        yield write_desc_status_sink.wait(1000)
        yield delay(50)

        status = write_desc_status_sink.recv()

        print(status)

        assert status.data[0][0] == cur_tag

        data = mem_data[pcie_addr:pcie_addr+32]
        for i in range(0, len(data), 16):
            print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))

        assert mem_data[pcie_addr:pcie_addr+len(test_data)] == test_data

        cur_tag = (cur_tag + 1) % 256

        yield delay(100)

        yield user_clk.posedge
        print("test 3: PCIe read")
        current_test.next = 3

        pcie_addr = 0x00000000
        axi_addr = 0x00000000
        test_data = b'\x11\x22\x33\x44'

        axi_ram_inst.write_mem(axi_addr, b'\x00'*len(test_data))
        mem_data[pcie_addr:pcie_addr+len(test_data)] = test_data

        data = mem_data[pcie_addr:pcie_addr+32]
        for i in range(0, len(data), 16):
            print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))

        read_desc_source.send([(pcie_addr, axi_addr, len(test_data), cur_tag)])

        yield read_desc_status_sink.wait(2000)

        status = read_desc_status_sink.recv()

        print(status)

        assert status.data[0][0] == cur_tag

        data = axi_ram_inst.read_mem(axi_addr, 32)
        for i in range(0, len(data), 16):
            print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))

        assert axi_ram_inst.read_mem(axi_addr, len(test_data)) == test_data

        cur_tag = (cur_tag + 1) % 256

        yield delay(100)

        raise StopSimulation

    return instances()