aboutsummaryrefslogtreecommitdiffstats
path: root/host/tests/device3_test.cpp
blob: 62b90920ec5fda993ae3d17eb588f0de9de4934f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//
// Copyright 2014 Ettus Research LLC
// Copyright 2018 Ettus Research, a National Instruments Company
//
// SPDX-License-Identifier: GPL-3.0-or-later
//

#include "../lib/rfnoc/ctrl_iface.hpp"
#include <uhd/property_tree.hpp>
#include <uhd/types/wb_iface.hpp>
#include <uhd/device3.hpp>
#include <uhd/rfnoc/block_ctrl.hpp>
#include <uhd/rfnoc/graph.hpp>
#include <boost/test/unit_test.hpp>
#include <exception>
#include <iostream>

using namespace uhd;
using namespace uhd::rfnoc;

static const uint64_t TEST_NOC_ID = 0xAAAABBBBCCCCDDDD;
static const sid_t TEST_SID0 = 0x00000200; // 0.0.2.0
static const sid_t TEST_SID1 = 0x00000210; // 0.0.2.F

// Pseudo-wb-iface
class pseudo_ctrl_iface_impl : public ctrl_iface
{
  public:
    pseudo_ctrl_iface_impl() {};
    ~pseudo_ctrl_iface_impl() {};

    uint64_t send_cmd_pkt(
            const size_t addr,
            const size_t data,
            const bool readback=false,
            const uint64_t timestamp=0
    ) {
        if (not readback) {
            std::cout << str(boost::format("[PSEUDO] poke to addr: %016X, data == %016X") % addr % data) << std::endl;
        } else {
            std::cout << str(boost::format("[PSEUDO] peek64 to addr: %016X") % data) << std::endl;
            switch (data) {
                case SR_READBACK_REG_ID:
                    return TEST_NOC_ID;
                case SR_READBACK_REG_FIFOSIZE:
                    return 0x000000000000000B;
                case SR_READBACK_REG_USER:
                    return 0x0123456789ABCDEF;
                default:
                    return 0;
            }
        }
        return 0;
    }
};

// Pseudo-device
class pseudo_device3_impl : public uhd::device3
{
  public:
    pseudo_device3_impl()
    {
        _tree = uhd::property_tree::make();
        _tree->create<std::string>("/name").set("Test Pseudo-Device3");

        // We can re-use this:
        std::map<size_t, ctrl_iface::sptr> ctrl_ifaces = boost::assign::map_list_of
            (0, ctrl_iface::sptr(new pseudo_ctrl_iface_impl()))
        ;

        // Add two block controls:
        uhd::rfnoc::make_args_t make_args;
        make_args.ctrl_ifaces = ctrl_ifaces;
        make_args.base_address = TEST_SID0.get_dst();
        make_args.device_index = 0;
        make_args.tree = _tree;
        std::cout << "[PSEUDO] Generating block controls 1/2:" << std::endl;
        _rfnoc_block_ctrl.push_back( block_ctrl_base::make(make_args) );

        std::cout << "[PSEUDO] Generating block controls 2/2:" << std::endl;
        make_args.base_address = TEST_SID1.get_dst();
        _rfnoc_block_ctrl.push_back( block_ctrl::make(make_args) );
    }

    rx_streamer::sptr get_rx_stream(const stream_args_t &args) {
        throw uhd::not_implemented_error(args.args.to_string());
    }

    tx_streamer::sptr get_tx_stream(const stream_args_t &args) {
        throw uhd::not_implemented_error(args.args.to_string());
    }

    bool recv_async_msg(async_metadata_t &async_metadata, double timeout) {
        throw uhd::not_implemented_error(str(boost::format("%d %f") % async_metadata.channel % timeout));
    }

    rfnoc::graph::sptr create_graph(const std::string &) { return rfnoc::graph::sptr(); }
};

device3::sptr make_pseudo_device()
{
    return device3::sptr(new pseudo_device3_impl());
}

class dummy_block_ctrl : public block_ctrl {
    int foo;
};

BOOST_AUTO_TEST_CASE(test_device3) {
    device3::sptr my_device = make_pseudo_device();

    std::cout << "Checking block 0..." << std::endl;
    BOOST_REQUIRE(my_device->find_blocks("Block").size());

    std::cout << "Getting block 0..." << std::endl;
    block_ctrl_base::sptr block0 = my_device->get_block_ctrl(my_device->find_blocks("Block")[0]);
    BOOST_REQUIRE(block0);
    BOOST_CHECK_EQUAL(block0->get_block_id(), "0/Block_0");

    std::cout << "Checking block 1..." << std::endl;
    BOOST_REQUIRE(my_device->has_block(block_id_t("0/Block_1")));

    std::cout << "Getting block 1..." << std::endl;
    block_ctrl_base::sptr block1 = my_device->get_block_ctrl(block_id_t("0/Block_1"));
    BOOST_REQUIRE(block1);
    BOOST_CHECK_EQUAL(block1->get_block_id(), "0/Block_1");
}

BOOST_AUTO_TEST_CASE(test_device3_cast) {
    device3::sptr my_device = make_pseudo_device();

    std::cout << "Getting block 0..." << std::endl;
    block_ctrl::sptr block0 = my_device->get_block_ctrl<block_ctrl>(block_id_t("0/Block_0"));
    BOOST_REQUIRE(block0);
    BOOST_CHECK_EQUAL(block0->get_block_id(), "0/Block_0");

    std::cout << "Getting block 1..." << std::endl;
    block_ctrl_base::sptr block1 = my_device->get_block_ctrl<block_ctrl>(block_id_t("0/Block_1"));
    BOOST_CHECK_EQUAL(block1->get_block_id(), "0/Block_1");
}

BOOST_AUTO_TEST_CASE(test_device3_fail) {
    device3::sptr my_device = make_pseudo_device();

    BOOST_CHECK(not my_device->has_block(block_id_t("0/FooBarBlock_0")));
    BOOST_CHECK(not my_device->has_block<dummy_block_ctrl>(block_id_t("0/Block_1")));

    BOOST_CHECK(my_device->find_blocks("FooBarBlock").size() == 0);
    BOOST_CHECK(my_device->find_blocks<block_ctrl>("FooBarBlock").size() == 0);

    BOOST_REQUIRE_THROW(
        my_device->get_block_ctrl(block_id_t("0/FooBarBlock_17")),
        uhd::lookup_error
    );
    BOOST_REQUIRE_THROW(
        my_device->get_block_ctrl<dummy_block_ctrl>(block_id_t("0/Block_1")),
        uhd::lookup_error
    );
}

// vim: sw=4 et: