/* -*- c++ -*- */ /* * Copyright 2007,2008 Free Software Foundation, Inc. * * This file is part of GNU Radio * * GNU Radio is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * GNU Radio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef usrp_inband_usb_packet transport_pkt; // makes conversion to gigabit easy static bool verbose = false; static pmt_t s_timeout = pmt_intern("%timeout"); // ---------------------------------------------------------------------------------------------- class qa_alloc_top : public mb_mblock { mb_port_sptr d_tx; mb_port_sptr d_rx; mb_port_sptr d_cs; long d_nmsgs_to_recv; long d_nrecvd; long d_max_capacity; long d_ntx_chan, d_nrx_chan; long d_nstatus; long d_nstatus_to_recv; public: qa_alloc_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg); ~qa_alloc_top(); void initial_transition(); void handle_message(mb_message_sptr msg); protected: void check_message(mb_message_sptr msg); void run_tests(); }; qa_alloc_top::qa_alloc_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg) : mb_mblock(runtime, instance_name, user_arg) { d_nrecvd=0; d_nmsgs_to_recv = 6; d_nstatus=0; d_nstatus_to_recv = 50; d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL); d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL); d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL); // Use the stub with the usrp_server pmt_t usrp_server_dict = pmt_make_dict(); pmt_dict_set(usrp_server_dict, pmt_intern("fake-usrp"),PMT_T); // Test the TX side define_component("server", "usrp_server", usrp_server_dict); connect("self", "tx0", "server", "tx0"); connect("self", "rx0", "server", "rx0"); connect("self", "cs", "server", "cs"); } qa_alloc_top::~qa_alloc_top(){} void qa_alloc_top::initial_transition() { // Allocations should fail before open d_tx->send(s_cmd_allocate_channel, pmt_list2(pmt_list2(s_response_allocate_channel, s_err_usrp_not_opened), pmt_from_long(1))); d_rx->send(s_cmd_allocate_channel, pmt_list2(pmt_list2(s_response_allocate_channel, s_err_usrp_not_opened), pmt_from_long(1))); // Retrieve information about the USRP, then run tests d_cs->send(s_cmd_open, pmt_list2(pmt_list2(s_response_open, PMT_T), pmt_from_long(0))); d_cs->send(s_cmd_max_capacity, pmt_list1(pmt_list2(s_response_max_capacity, PMT_T))); d_cs->send(s_cmd_ntx_chan, pmt_list1(pmt_list2(s_response_ntx_chan, PMT_T))); d_cs->send(s_cmd_nrx_chan, pmt_list1(pmt_list2(s_response_nrx_chan,PMT_T))); } void qa_alloc_top::run_tests() { if(verbose) std::cout << "[qa_alloc_top] Starting tests...\n"; // should be able to allocate 1 byte d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1))); // should not be able to allocate max capacity after 100 bytes were allocated d_tx->send(s_cmd_allocate_channel, pmt_list2(s_err_requested_capacity_unavailable, pmt_from_long(d_max_capacity))); // keep allocating a little more until all of the channels are used and test // the error response we start at 1 since we've already allocated 1 channel for(int i=1; i < d_ntx_chan; i++) { if(verbose) std::cout << "[qa_alloc_top] Sent allocation request...\n"; d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1))); d_nmsgs_to_recv++; } // No more channels after allocating all of them is expected d_tx->send(s_cmd_allocate_channel, pmt_list2(s_err_channel_unavailable, pmt_from_long(1))); // test out the same on the RX side d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1))); d_rx->send(s_cmd_allocate_channel, pmt_list2(s_err_requested_capacity_unavailable, pmt_from_long(d_max_capacity))); for(int i=1; i < d_nrx_chan; i++) { d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1))); d_nmsgs_to_recv++; } d_rx->send(s_cmd_allocate_channel, pmt_list2(s_err_channel_unavailable, pmt_from_long(1))); // when all is said and done, there should be d_ntx_chan+d_ntx_chan bytes // allocated d_cs->send(s_cmd_current_capacity_allocation, pmt_list1(pmt_from_long(d_ntx_chan+d_nrx_chan))); } void qa_alloc_top::handle_message(mb_message_sptr msg) { pmt_t data = msg->data(); if ((pmt_eq(msg->port_id(), d_tx->port_symbol()) || pmt_eq(msg->port_id(), d_rx->port_symbol())) && pmt_eq(msg->signal(), s_response_allocate_channel)) check_message(msg); if (pmt_eq(msg->port_id(), d_cs->port_symbol())) { if(pmt_eq(msg->signal(), s_response_max_capacity)) { d_max_capacity = pmt_to_long(pmt_nth(2, data)); if(verbose) std::cout << "[qa_alloc_top] USRP has max capacity of " << d_max_capacity << "\n"; } else if(pmt_eq(msg->signal(), s_response_ntx_chan)) { d_ntx_chan = pmt_to_long(pmt_nth(2, data)); if(verbose) std::cout << "[qa_alloc_top] USRP tx channels: " << d_ntx_chan << "\n"; } else if(pmt_eq(msg->signal(), s_response_nrx_chan)) { d_nrx_chan = pmt_to_long(pmt_nth(2, data)); if(verbose) std::cout << "[qa_alloc_top] USRP rx channels: " << d_nrx_chan << "\n"; } else if(pmt_eq(msg->signal(), s_response_current_capacity_allocation)) { check_message(msg); } d_nstatus++; check_message(msg); if(d_nstatus==d_nstatus_to_recv) run_tests(); } } void qa_alloc_top::check_message(mb_message_sptr msg) { pmt_t data = msg->data(); pmt_t event = msg->signal(); pmt_t expected = pmt_nth(0, data); pmt_t status = pmt_nth(1, data); pmt_t e_event = pmt_nth(0, expected); pmt_t e_status = pmt_nth(1, expected); d_nrecvd++; if(!pmt_eqv(e_status, status) || !pmt_eqv(e_event, event)) { if(verbose) std::cout << "Got: " << status << " Expected: " << e_status << "\n"; shutdown_all(PMT_F); return; } else { if(verbose) std::cout << "[qa_alloc_top] Received expected response for message " << d_nrecvd << " (" << event << ")\n"; } if(d_nrecvd == d_nmsgs_to_recv) shutdown_all(PMT_T); } REGISTER_MBLOCK_CLASS(qa_alloc_top); // ---------------------------------------------------------------------------------------------- class qa_dealloc_top : public mb_mblock { mb_port_sptr d_tx; mb_port_sptr d_rx; mb_port_sptr d_cs; long d_max_capacity; long d_ntx_chan, d_nrx_chan; long d_nstatus; long d_nstatus_to_recv; long d_nalloc_to_recv; long d_nalloc_recvd; long d_ndealloc_to_recv; long d_ndealloc_recvd; std::vector d_tx_chans; std::vector d_rx_chans; public: qa_dealloc_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg); ~qa_dealloc_top(); void initial_transition(); void handle_message(mb_message_sptr msg); protected: void check_allocation(mb_message_sptr msg); void check_deallocation(mb_message_sptr msg); void allocate_max(); void deallocate_all(); }; qa_dealloc_top::qa_dealloc_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg) : mb_mblock(runtime, instance_name, user_arg) { d_ndealloc_recvd=0; d_ndealloc_to_recv = 0; d_nalloc_recvd=0; d_nalloc_to_recv = 0; // auto-set d_nstatus=0; d_nstatus_to_recv = 4; d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL); d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL); d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL); // Use the stub with the usrp_server pmt_t usrp_server_dict = pmt_make_dict(); pmt_dict_set(usrp_server_dict, pmt_intern("fake-usrp"),PMT_T); // Test the TX side define_component("server", "usrp_server", usrp_server_dict); connect("self", "tx0", "server", "tx0"); connect("self", "rx0", "server", "rx0"); connect("self", "cs", "server", "cs"); } qa_dealloc_top::~qa_dealloc_top(){} void qa_dealloc_top::initial_transition() { if(verbose) std::cout << "[qa_dealloc_top] Initializing...\n"; // Retrieve information about the USRP, then run tests d_cs->send(s_cmd_open, pmt_list2(pmt_list2(s_response_open,PMT_T), pmt_from_long(0))); d_cs->send(s_cmd_max_capacity, pmt_list1(pmt_list2(s_response_max_capacity,PMT_T))); d_cs->send(s_cmd_ntx_chan, pmt_list1(pmt_list2(s_response_ntx_chan,PMT_T))); d_cs->send(s_cmd_nrx_chan, pmt_list1(pmt_list2(s_response_nrx_chan,PMT_T))); } void qa_dealloc_top::allocate_max() { // Keep allocating until we hit the maximum number of channels for(int i=0; i < d_ntx_chan; i++) { d_tx->send(s_cmd_allocate_channel, pmt_list2(pmt_list2(s_response_allocate_channel,PMT_T), pmt_from_long(1))); // 1 byte is good enough d_nalloc_to_recv++; } for(int i=0; i < d_nrx_chan; i++) { d_rx->send(s_cmd_allocate_channel, pmt_list2(pmt_list2(s_response_allocate_channel,PMT_T), pmt_from_long(1))); d_nalloc_to_recv++; } } void qa_dealloc_top::deallocate_all() { // Deallocate all of the channels that were allocated from allocate_max() for(int i=0; i < (int)d_tx_chans.size(); i++) { if(verbose) std::cout << "[qa_dealloc_top] Trying to dealloc TX " << d_tx_chans[i] << std::endl; d_tx->send(s_cmd_deallocate_channel, pmt_list2(pmt_list2(s_response_deallocate_channel,PMT_T), pmt_from_long(d_tx_chans[i]))); d_ndealloc_to_recv++; } // Deallocate the RX side now for(int i=0; i < (int)d_rx_chans.size(); i++) { if(verbose) std::cout << "[qa_dealloc_top] Trying to dealloc RX " << d_tx_chans[i] << std::endl; d_rx->send(s_cmd_deallocate_channel, pmt_list2(pmt_list2(s_response_deallocate_channel,PMT_T), pmt_from_long(d_rx_chans[i]))); d_ndealloc_to_recv++; } // Should get permission denied errors trying to re-dealloc the channels, as // we no longer have permission to them after deallocating for(int i=0; i < (int)d_tx_chans.size(); i++) { d_tx->send(s_cmd_deallocate_channel, pmt_list2(pmt_list2(s_response_deallocate_channel, s_err_channel_permission_denied), pmt_from_long(d_tx_chans[i]))); d_ndealloc_to_recv++; } // Same for RX for(int i=0; i < (int)d_rx_chans.size(); i++) { d_rx->send(s_cmd_deallocate_channel, pmt_list2(pmt_list2(s_response_deallocate_channel, s_err_channel_permission_denied), pmt_from_long(d_rx_chans[i]))); d_ndealloc_to_recv++; } // Try to deallocate a channel that doesn't exist on both sides, the last // element in the vectors is the highest channel number, so we take that plus // 1 d_ndealloc_to_recv+=2; d_tx->send(s_cmd_deallocate_channel, pmt_list2(pmt_list2(s_response_deallocate_channel, s_err_channel_invalid), pmt_from_long(d_rx_chans.back()+1))); d_rx->send(s_cmd_deallocate_channel, pmt_list2(pmt_list2(s_response_deallocate_channel, s_err_channel_invalid), pmt_from_long(d_rx_chans.back()+1))); // The used capacity should be back to 0 now that we've deallocated everything d_cs->send(s_cmd_current_capacity_allocation, pmt_list1(pmt_list2(s_response_current_capacity_allocation, PMT_T))); } void qa_dealloc_top::handle_message(mb_message_sptr msg) { pmt_t data = msg->data(); pmt_t event = msg->signal(); if(pmt_eq(event, pmt_intern("%shutdown"))) return; pmt_t expected = pmt_nth(0, data); pmt_t status = pmt_nth(1, data); pmt_t e_event = pmt_nth(0, expected); pmt_t e_status = pmt_nth(1, expected); if(!pmt_eqv(e_status, status) || !pmt_eqv(e_event, event)) { if(verbose) std::cout << "Got: " << status << " Expected: " << e_status << "\n"; shutdown_all(PMT_F); return; } else { if(verbose) std::cout << "[qa_alloc_top] Received expected response for message " << d_ndealloc_recvd << " (" << event << ")\n"; } if (pmt_eq(msg->port_id(), d_tx->port_symbol()) || pmt_eq(msg->port_id(), d_rx->port_symbol())) { if(pmt_eq(msg->signal(), s_response_allocate_channel)) { check_allocation(msg); } } if (pmt_eq(msg->port_id(), d_cs->port_symbol())) { if(pmt_eq(msg->signal(), s_response_max_capacity)) { d_max_capacity = pmt_to_long(pmt_nth(2, data)); } else if(pmt_eq(msg->signal(), s_response_ntx_chan)) { d_ntx_chan = pmt_to_long(pmt_nth(2, data)); } else if(pmt_eq(msg->signal(), s_response_nrx_chan)) { d_nrx_chan = pmt_to_long(pmt_nth(2, data)); } else if(pmt_eq(msg->signal(), s_response_current_capacity_allocation)) { // the final command is a capacity check which should be 0, then we // shutdown pmt_t expected_result = pmt_from_long(0); pmt_t result = pmt_nth(2, data); if(pmt_eqv(expected_result, result)) { shutdown_all(PMT_T); return; } else { shutdown_all(PMT_F); return; } } d_nstatus++; if(d_nstatus==d_nstatus_to_recv) allocate_max(); } } void qa_dealloc_top::check_allocation(mb_message_sptr msg) { pmt_t data = msg->data(); pmt_t event = msg->signal(); pmt_t expected = pmt_nth(0, data); pmt_t status = pmt_nth(1, data); pmt_t channel = pmt_nth(2, data); d_nalloc_recvd++; if(!pmt_eqv(status, PMT_T)) { shutdown_all(PMT_F); return; } else { // store all of the allocate channel numbers if(pmt_eq(msg->port_id(), d_tx->port_symbol())) d_tx_chans.push_back(pmt_to_long(channel)); if(pmt_eq(msg->port_id(), d_rx->port_symbol())) d_rx_chans.push_back(pmt_to_long(channel)); } if(d_nalloc_recvd == d_nalloc_to_recv) { if(verbose) { std::cout << "[qa_dealloc_top] Allocated TX channels: "; for(int i=0; i < (int)d_tx_chans.size(); i++) std::cout << d_tx_chans[i] << " "; std::cout << "\n[qa_dealloc_top] Allocated RX channels: "; for(int i=0; i < (int)d_rx_chans.size(); i++) std::cout << d_rx_chans[i] << " "; std::cout << "\n"; } deallocate_all(); // once we've allocated all of our channels, try to // dealloc them } } REGISTER_MBLOCK_CLASS(qa_dealloc_top); // ---------------------------------------------------------------------------------------------- class qa_open_close_top : public mb_mblock { mb_port_sptr d_cs; long d_max_capacity; long d_nmsg_to_recv; long d_nmsg_recvd; public: qa_open_close_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg); ~qa_open_close_top(); void initial_transition(); void handle_message(mb_message_sptr msg); protected: void check_cs(mb_message_sptr msg); void run_tests(); }; qa_open_close_top::qa_open_close_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg) : mb_mblock(runtime, instance_name, user_arg) { d_nmsg_to_recv=7; d_nmsg_recvd=0; d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL); // Use the stub with the usrp_server pmt_t usrp_server_dict = pmt_make_dict(); pmt_dict_set(usrp_server_dict, pmt_intern("fake-usrp"),PMT_T); // Test the TX side define_component("server", "usrp_server", usrp_server_dict); connect("self", "cs", "server", "cs"); } qa_open_close_top::~qa_open_close_top(){} void qa_open_close_top::initial_transition() { run_tests(); } void qa_open_close_top::run_tests() { // std::cout << "[qa_open_close_top] Starting tests\n"; // A close before an open should fail d_cs->send(s_cmd_close, pmt_list1(pmt_list2(s_response_close, s_err_usrp_already_closed))); // Perform an open, and a second open which should fail d_cs->send(s_cmd_open, pmt_list2(pmt_list2(s_response_open,PMT_T), pmt_from_long(0))); d_cs->send(s_cmd_open, pmt_list2(pmt_list2(s_response_open, s_err_usrp_already_opened), pmt_from_long(0))); // A close should now be successful since the interface is open d_cs->send(s_cmd_close, pmt_list1(pmt_list2(s_response_close,PMT_T))); // But, a second close should fail d_cs->send(s_cmd_close, pmt_list1(pmt_list2(s_response_close, s_err_usrp_already_closed))); // Just to be thorough, try an open and close again d_cs->send(s_cmd_open, pmt_list2(pmt_list2(s_response_open,PMT_T), pmt_from_long(0))); d_cs->send(s_cmd_close, pmt_list1(pmt_list2(s_response_close,PMT_T))); } void qa_open_close_top::handle_message(mb_message_sptr msg) { pmt_t data = msg->data(); if (pmt_eq(msg->port_id(), d_cs->port_symbol())) { check_cs(msg); } d_nmsg_recvd++; if(d_nmsg_to_recv == d_nmsg_recvd) shutdown_all(PMT_T); } void qa_open_close_top::check_cs(mb_message_sptr msg) { pmt_t data = msg->data(); pmt_t event = msg->signal(); pmt_t expected = pmt_nth(0, data); pmt_t status = pmt_nth(1, data); pmt_t e_event = pmt_nth(0, expected); pmt_t e_status = pmt_nth(1, expected); if(!pmt_eqv(e_status, status) || !pmt_eqv(e_event, event)) { if(verbose) std::cout << "[qa_open_close_top] FAILED check_cs... Got: " << status << " Expected: " << e_status << " for event " << event << "\n"; shutdown_all(PMT_F); } else { if(verbose) std::cout << "[qa_open_close_top] Received expected CS response (" << event << ")\n"; } } REGISTER_MBLOCK_CLASS(qa_open_close_top); // ---------------------------------------------------------------------------------------------- class qa_tx_top : public mb_mblock { mb_port_sptr d_tx; mb_port_sptr d_rx; mb_port_sptr d_cs; long d_max_capacity; long d_ntx_chan, d_nrx_chan; long d_tx_chan; long d_rx_chan; long d_nmsg_to_recv; long d_nmsg_recvd; public: qa_tx_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg); ~qa_tx_top(); void initial_transition(); void handle_message(mb_message_sptr msg); protected: void check_allocation(mb_message_sptr msg); void check_deallocation(mb_message_sptr msg); void check_xmit(mb_message_sptr msg); void check_cs(mb_message_sptr msg); void run_tests(); }; qa_tx_top::qa_tx_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg) : mb_mblock(runtime, instance_name, user_arg) { d_nmsg_to_recv=10; d_nmsg_recvd=0; d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL); d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL); d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL); // Use the stub with the usrp_server pmt_t usrp_server_dict = pmt_make_dict(); pmt_dict_set(usrp_server_dict, pmt_intern("fake-usrp"),PMT_T); // Test the TX side define_component("server", "usrp_server", usrp_server_dict); connect("self", "tx0", "server", "tx0"); connect("self", "rx0", "server", "rx0"); connect("self", "cs", "server", "cs"); } qa_tx_top::~qa_tx_top(){} void qa_tx_top::initial_transition() { run_tests(); } void qa_tx_top::run_tests() { if(verbose) std::cout << "[qa_tx_top] Starting tests\n"; // A transmit before an open should fail d_tx->send(s_cmd_xmit_raw_frame, pmt_list4(pmt_list2(s_response_xmit_raw_frame, s_err_usrp_not_opened), pmt_from_long(0), pmt_make_u32vector(transport_pkt::max_payload()/4, 0), pmt_from_long(0))); // Now open d_cs->send(s_cmd_open, pmt_list2(pmt_list2(s_response_open,PMT_T), pmt_from_long(0))); // Try to transmit on a channel that we have no allocation for d_tx->send(s_cmd_xmit_raw_frame, pmt_list4(pmt_list2(s_response_xmit_raw_frame, s_err_channel_permission_denied), pmt_from_long(0), pmt_make_u32vector(transport_pkt::max_payload()/4, 0), pmt_from_long(0))); // Get a channel allocation and send on it, we assume 0 (FIXME) until 'defer' // is implemented for simplicity d_tx->send(s_cmd_allocate_channel, pmt_list2(pmt_list2(s_response_allocate_channel, PMT_T), pmt_from_long(1))); d_tx->send(s_cmd_xmit_raw_frame, pmt_list4(pmt_list2(s_response_xmit_raw_frame, PMT_T), pmt_from_long(0), pmt_make_u32vector(transport_pkt::max_payload()/4, 0), pmt_from_long(0))); // Close should be successful d_cs->send(s_cmd_close, pmt_list1(pmt_list2(s_response_close,PMT_T))); // After closing, a new transmit raw frame should fail again d_tx->send(s_cmd_xmit_raw_frame, pmt_list4(pmt_list2(s_response_xmit_raw_frame, s_err_usrp_not_opened), pmt_from_long(0), pmt_make_u32vector(transport_pkt::max_payload()/4, 0), pmt_from_long(0))); // Reopen and retry before getting an allocation, the first xmit should fail, // after we allocate it should work again d_cs->send(s_cmd_open, pmt_list2(pmt_list2(s_response_open, PMT_T), pmt_from_long(0))); d_tx->send(s_cmd_xmit_raw_frame, pmt_list4(pmt_list2(s_response_xmit_raw_frame, s_err_channel_permission_denied), pmt_from_long(0), pmt_make_u32vector(transport_pkt::max_payload()/4, 0), pmt_from_long(0))); d_tx->send(s_cmd_allocate_channel, pmt_list2(pmt_list2(s_response_allocate_channel, PMT_T), pmt_from_long(1))); d_tx->send(s_cmd_xmit_raw_frame, pmt_list4(pmt_list2(s_response_xmit_raw_frame,PMT_T), pmt_from_long(0), pmt_make_u32vector(transport_pkt::max_payload()/4, 0), pmt_from_long(0))); // A final close which should be successful d_cs->send(s_cmd_close, pmt_list1(pmt_list2(s_response_close,PMT_T))); } void qa_tx_top::handle_message(mb_message_sptr msg) { pmt_t data = msg->data(); pmt_t event = msg->signal(); if(pmt_eq(event, pmt_intern("%shutdown"))) return; pmt_t expected = pmt_nth(0, data); pmt_t status = pmt_nth(1, data); pmt_t e_event = pmt_nth(0, expected); pmt_t e_status = pmt_nth(1, expected); if(!pmt_eqv(e_status, status) || !pmt_eqv(e_event, event)) { if(verbose) std::cout << "[qa_xmit_top] Got: " << status << " Expected: " << e_status << "For signal: " << event << "\n"; shutdown_all(PMT_F); return; } else { if(verbose) std::cout << "[qa_xmit_top] Received expected response for message " << d_nmsg_recvd << " (" << event << ")\n"; } if (pmt_eq(msg->port_id(), d_tx->port_symbol()) || pmt_eq(msg->port_id(), d_rx->port_symbol())) { if(pmt_eq(msg->signal(), s_response_allocate_channel)) check_allocation(msg); } d_nmsg_recvd++; if(d_nmsg_to_recv == d_nmsg_recvd){ shutdown_all(PMT_T); return; } } void qa_tx_top::check_allocation(mb_message_sptr msg) { pmt_t data = msg->data(); pmt_t event = msg->signal(); pmt_t expected = pmt_nth(0, data); pmt_t status = pmt_nth(1, data); pmt_t channel = pmt_nth(2, data); if(pmt_eqv(status, PMT_T)) { // store all of the allocate channel numbers if(pmt_eq(msg->port_id(), d_tx->port_symbol())) d_tx_chan = pmt_to_long(channel); if(pmt_eq(msg->port_id(), d_rx->port_symbol())) d_rx_chan = pmt_to_long(channel); } } REGISTER_MBLOCK_CLASS(qa_tx_top); // ---------------------------------------------------------------------------------------------- class qa_rx_top : public mb_mblock { mb_port_sptr d_rx; mb_port_sptr d_cs; long d_max_capacity; long d_ntx_chan, d_nrx_chan; long d_rx_chan; bool d_got_response_recv; mb_time d_t0; double d_delta_t; public: qa_rx_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg); ~qa_rx_top(); void initial_transition(); void handle_message(mb_message_sptr msg); protected: void check_allocation(mb_message_sptr msg); void check_deallocation(mb_message_sptr msg); void check_xmit(mb_message_sptr msg); void check_cs(mb_message_sptr msg); void run_tests(); }; qa_rx_top::qa_rx_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg) : mb_mblock(runtime, instance_name, user_arg), d_got_response_recv(false) { d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL); d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL); // Use the stub with the usrp_server pmt_t usrp_dict = pmt_make_dict(); // Set TX and RX interpolations pmt_dict_set(usrp_dict, pmt_intern("decim-rx"), pmt_from_long(128)); pmt_dict_set(usrp_dict, pmt_intern("fake-usrp"), PMT_T); // Test the TX side define_component("server", "usrp_server", usrp_dict); connect("self", "rx0", "server", "rx0"); connect("self", "cs", "server", "cs"); } qa_rx_top::~qa_rx_top(){} void qa_rx_top::initial_transition() { run_tests(); } void qa_rx_top::run_tests() { if(verbose) std::cout << "[qa_rx_top] Starting tests\n"; d_cs->send(s_cmd_open, pmt_list2(pmt_list2(s_response_open,PMT_T), pmt_from_long(0))); d_rx->send(s_cmd_allocate_channel, pmt_list2(pmt_list2(s_response_allocate_channel,PMT_T), pmt_from_long(1))); d_rx->send(s_cmd_start_recv_raw_samples, pmt_list2(PMT_NIL, pmt_from_long(0))); // Schedule a small timeout in which we expect to have received at least one // packet worth of samples from the stub d_t0 = mb_time::time(); schedule_one_shot_timeout(d_t0 + 0.01, PMT_NIL); } void qa_rx_top::handle_message(mb_message_sptr msg) { pmt_t data = msg->data(); pmt_t event = msg->signal(); if(pmt_eq(event, pmt_intern("%shutdown"))) return; pmt_t expected = pmt_nth(0, data); pmt_t status = pmt_nth(1, data); // If we get a timeout we shutdown if(pmt_eq(event, s_timeout)) { if(verbose) std::cout << "[qa_rx_top] Got timeout\n"; d_rx->send(s_cmd_stop_recv_raw_samples, pmt_list2(PMT_NIL, pmt_from_long(0))); d_cs->send(s_cmd_close, pmt_list1(pmt_list2(s_response_close,PMT_T))); return; } // For testing RX, an invocation handle is not generated by the stub, // therefore the same approach for testing is not used. We simply // expect all responses to be true. if(pmt_eq(event, s_response_recv_raw_samples)) { if(pmt_eqv(status, PMT_T)) { if(verbose) std::cout << "[qa_rx_top] Received expected response for message " << " (" << event << ")\n"; // All we want is 1 response receive! Can't guarantee exact numbers d_got_response_recv = true; } else { if(verbose) std::cout << "Got: " << status << " Expected: " << PMT_T << "\n"; shutdown_all(PMT_F); } return; } pmt_t e_event = pmt_nth(0, expected); pmt_t e_status = pmt_nth(1, expected); if(!pmt_eqv(e_status, status) || !pmt_eqv(e_event, event)) { if(verbose) std::cout << "Got: " << status << " Expected: " << e_status << "\n"; shutdown_all(PMT_F); return; } else { if(verbose) std::cout << "[qa_rx_top] Received expected response for message " << " (" << event << ")\n"; } if (pmt_eq(msg->port_id(), d_rx->port_symbol())) { if(pmt_eq(msg->signal(), s_response_allocate_channel)) check_allocation(msg); } // We stop when we get a close, we are successful if we // got a response from recv, fail if we never got a recv response if(pmt_eq(msg->signal(), s_response_close)) { if(d_got_response_recv) { shutdown_all(PMT_T); return; } else { shutdown_all(PMT_F); if(verbose) std::cout << "[qa_rx_top] No response message before close\n"; return; } } } void qa_rx_top::check_allocation(mb_message_sptr msg) { pmt_t data = msg->data(); pmt_t event = msg->signal(); pmt_t expected = pmt_nth(0, data); pmt_t status = pmt_nth(1, data); pmt_t channel = pmt_nth(2, data); if(pmt_eqv(status, PMT_T)) { // store all of the allocate channel numbers if(pmt_eq(msg->port_id(), d_rx->port_symbol())) d_rx_chan = pmt_to_long(channel); } } REGISTER_MBLOCK_CLASS(qa_rx_top); // ---------------------------------------------------------------------------------------------- class qa_rid_top : public mb_mblock { mb_port_sptr d_tx; mb_port_sptr d_rx; mb_port_sptr d_cs; long d_npongs; long d_tcycles; long d_cycles; long d_max_rid; mb_time d_t0; double d_delta_t; public: qa_rid_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg); ~qa_rid_top(); void initial_transition(); void handle_message(mb_message_sptr msg); protected: void run_tests(); void send_max_pings(); }; qa_rid_top::qa_rid_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg) : mb_mblock(runtime, instance_name, user_arg) { d_npongs = 0; d_tcycles = 3; d_cycles = d_tcycles; d_max_rid = usrp_server::D_MAX_RID; d_delta_t = 0.1; d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL); d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL); d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL); // Use the stub with the usrp_server pmt_t usrp_server_dict = pmt_make_dict(); pmt_dict_set(usrp_server_dict, pmt_intern("fake-usrp"),PMT_T); // Test the TX side define_component("server", "usrp_server", usrp_server_dict); connect("self", "tx0", "server", "tx0"); connect("self", "rx0", "server", "rx0"); connect("self", "cs", "server", "cs"); } qa_rid_top::~qa_rid_top(){} void qa_rid_top::initial_transition() { run_tests(); } void qa_rid_top::run_tests() { if(verbose) std::cout << "[qa_rid_top] Starting tests...\n"; // Retrieve information about the USRP, then run tests d_cs->send(s_cmd_open, pmt_list2(pmt_list2(s_response_open, PMT_T), pmt_from_long(0))); // should be able to allocate 1 byte d_tx->send(s_cmd_allocate_channel, pmt_list2(pmt_list2(s_response_allocate_channel, PMT_T), pmt_from_long(1))); d_rx->send(s_cmd_allocate_channel, pmt_list2(pmt_list2(s_response_allocate_channel, PMT_T), pmt_from_long(1))); // Need to start receiving to read from the USRP to get C/S responses d_rx->send(s_cmd_start_recv_raw_samples, pmt_list2(PMT_NIL, pmt_from_long(0))); // Build a subpacket of MAX_RID pings and wait a small amount for all of the // responses and fire off another MAX_RID. If MAX_RID*2 responses are // received, the RID recycling is working correctly. // Schedule a timer in which we expect to have received all of the responses, // which will send off another MAX_RID worth. send_max_pings(); d_t0 = mb_time::time(); schedule_one_shot_timeout(d_t0 + d_delta_t, PMT_NIL); } void qa_rid_top::send_max_pings() { pmt_t ping = pmt_list2(s_op_ping_fixed, pmt_list2(pmt_from_long(0), pmt_from_long(0))); pmt_t sub_packets = PMT_NIL; for(int i=0; isend(s_cmd_to_control_channel, pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T), sub_packets)); } void qa_rid_top::handle_message(mb_message_sptr msg) { pmt_t data = msg->data(); pmt_t event = msg->signal(); // If we get a timeout we ensure we got a maximum RID number of responses. if(pmt_eq(event, s_timeout)) { if(verbose) std::cout << "[qa_rid_top] Got timeout, received so far: " << d_npongs << "\n"; d_cycles--; if(d_cycles==0 && d_npongs == d_max_rid*d_tcycles) { shutdown_all(PMT_T); } else if(d_cycles==0) { std::cout << "[qa_rid_top] d_npongs: " << d_npongs << " expected: " << d_max_rid*d_tcycles << std::endl; shutdown_all(PMT_F); } else { send_max_pings(); d_t0 = mb_time::time(); schedule_one_shot_timeout(d_t0 + d_delta_t, PMT_NIL); } } else if(pmt_eq(event, s_response_from_control_channel)) { d_npongs++; } } REGISTER_MBLOCK_CLASS(qa_rid_top); // ---------------------------------------------------------------------------------------------- class qa_cs_top : public mb_mblock { mb_port_sptr d_tx; mb_port_sptr d_rx; mb_port_sptr d_cs; long d_nmsgs_to_recv; long d_nrecvd; long d_max_capacity; long d_ntx_chan, d_nrx_chan; long d_nstatus; long d_nstatus_to_recv; public: qa_cs_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg); ~qa_cs_top(); void initial_transition(); void handle_message(mb_message_sptr msg); protected: void check_message(mb_message_sptr msg); void run_tests(); }; qa_cs_top::qa_cs_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg) : mb_mblock(runtime, instance_name, user_arg) { d_nrecvd=0; d_nmsgs_to_recv = 8; d_nstatus=0; d_nstatus_to_recv = 50; d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL); d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL); d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL); // Use the stub with the usrp_server pmt_t usrp_server_dict = pmt_make_dict(); pmt_dict_set(usrp_server_dict, pmt_intern("fake-usrp"),PMT_T); // Test the TX side define_component("server", "usrp_server", usrp_server_dict); connect("self", "tx0", "server", "tx0"); connect("self", "rx0", "server", "rx0"); connect("self", "cs", "server", "cs"); } qa_cs_top::~qa_cs_top(){} void qa_cs_top::initial_transition() { run_tests(); } void qa_cs_top::run_tests() { if(verbose) std::cout << "[qa_cs_top] Starting tests...\n"; // Retrieve information about the USRP, then run tests d_cs->send(s_cmd_open, pmt_list2(pmt_list2(s_response_open, PMT_T), pmt_from_long(0))); // should be able to allocate 1 byte d_tx->send(s_cmd_allocate_channel, pmt_list2(pmt_list2(s_response_allocate_channel, PMT_T), pmt_from_long(1))); d_rx->send(s_cmd_allocate_channel, pmt_list2(pmt_list2(s_response_allocate_channel, PMT_T), pmt_from_long(1))); // Need to start receiving to read from the USRP to get C/S responses d_rx->send(s_cmd_start_recv_raw_samples, pmt_list2(PMT_NIL, pmt_from_long(0))); d_tx->send(s_cmd_to_control_channel, pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T), pmt_list1( pmt_list2(s_op_ping_fixed, pmt_list2(pmt_from_long(3), pmt_from_long(0)))))); d_tx->send(s_cmd_to_control_channel, pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T), pmt_list1( pmt_list2(s_op_write_reg, pmt_list2( pmt_from_long(0x3), pmt_from_long(0x4)))))); d_tx->send(s_cmd_to_control_channel, pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T), pmt_list1( pmt_list2(s_op_write_reg_masked, pmt_list3( pmt_from_long(0x3), pmt_from_long(0x4), pmt_from_long(0x5)))))); d_tx->send(s_cmd_to_control_channel, pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T), pmt_list1( pmt_list2(s_op_read_reg, pmt_list2(pmt_from_long(0), pmt_from_long(0x6)))))); d_tx->send(s_cmd_to_control_channel, pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T), pmt_list1( pmt_list2(s_op_delay, pmt_list1(pmt_from_long(0x7)))))); pmt_t subpackets = pmt_list5( pmt_list2(s_op_ping_fixed, pmt_list2(pmt_from_long(0), pmt_from_long(0))), pmt_list2(s_op_delay, pmt_list1(pmt_from_long(0x7))), pmt_list2(s_op_write_reg_masked, pmt_list3(pmt_from_long(3), pmt_from_long(4), pmt_from_long(5))), pmt_list2(s_op_write_reg, pmt_list2(pmt_from_long(3), pmt_from_long(4))), pmt_list2(s_op_read_reg, pmt_list2(pmt_from_long(0), pmt_from_long(6))) ); d_tx->send(s_cmd_to_control_channel, pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T), subpackets)); pmt_t i2c_data = pmt_make_u8vector(8, 0xff); subpackets = pmt_list2( pmt_list2(s_op_i2c_write, pmt_list2(pmt_from_long(8), i2c_data)), pmt_list2(s_op_i2c_read, pmt_list3(pmt_from_long(0), pmt_from_long(9), pmt_from_long(1))) ); d_tx->send(s_cmd_to_control_channel, pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T), subpackets)); } void qa_cs_top::handle_message(mb_message_sptr msg) { pmt_t data = msg->data(); if ((pmt_eq(msg->port_id(), d_tx->port_symbol()) || pmt_eq(msg->port_id(), d_rx->port_symbol())) && pmt_eq(msg->signal(), s_response_allocate_channel)) check_message(msg); if (pmt_eq(msg->port_id(), d_tx->port_symbol()) && pmt_eq(msg->signal(), s_response_from_control_channel)) check_message(msg); if (pmt_eq(msg->port_id(), d_cs->port_symbol())) { if(pmt_eq(msg->signal(), s_response_max_capacity)) { d_max_capacity = pmt_to_long(pmt_nth(2, data)); if(verbose) std::cout << "[qa_cs_top] USRP has max capacity of " << d_max_capacity << "\n"; } else if(pmt_eq(msg->signal(), s_response_ntx_chan)) { d_ntx_chan = pmt_to_long(pmt_nth(2, data)); if(verbose) std::cout << "[qa_cs_top] USRP tx channels: " << d_ntx_chan << "\n"; } else if(pmt_eq(msg->signal(), s_response_nrx_chan)) { d_nrx_chan = pmt_to_long(pmt_nth(2, data)); if(verbose) std::cout << "[qa_cs_top] USRP rx channels: " << d_nrx_chan << "\n"; } else if(pmt_eq(msg->signal(), s_response_current_capacity_allocation)) { check_message(msg); } d_nstatus++; check_message(msg); if(d_nstatus==d_nstatus_to_recv) run_tests(); } } void qa_cs_top::check_message(mb_message_sptr msg) { pmt_t data = msg->data(); pmt_t event = msg->signal(); pmt_t expected = pmt_nth(0, data); pmt_t status = pmt_nth(1, data); pmt_t e_event = pmt_nth(0, expected); pmt_t e_status = pmt_nth(1, expected); d_nrecvd++; if(!pmt_eqv(e_status, status) || !pmt_eqv(e_event, event)) { if(verbose) std::cout << "[qa_cs_top] Got: " << status << " Expected: " << e_status << "\n"; shutdown_all(PMT_F); return; } else { if(verbose) std::cout << "[qa_cs_top] Received expected response for message " << d_nrecvd << " (" << event << ")\n"; } if(d_nrecvd == d_nmsgs_to_recv) shutdown_all(PMT_T); } REGISTER_MBLOCK_CLASS(qa_cs_top); // ---------------------------------------------------------------------------------------------- void qa_inband_usrp_server::test_open_close() { mb_runtime_sptr rt = mb_make_runtime(); pmt_t result = PMT_T; // std::cout << "\n\n----------------------------\n"; // std::cout << " RUNNING OPEN/CLOSE TESTS \n"; rt->run("top", "qa_open_close_top", PMT_F, &result); CPPUNIT_ASSERT(pmt_equal(PMT_T, result)); } void qa_inband_usrp_server::test_chan_allocation() { mb_runtime_sptr rt = mb_make_runtime(); pmt_t result = PMT_T; // std::cout << "\n\n----------------------------\n"; // std::cout << " RUNNING ALLOCATION TESTS \n"; rt->run("qa_alloc_top", "qa_alloc_top", PMT_F, &result); CPPUNIT_ASSERT(pmt_equal(PMT_T, result)); } void qa_inband_usrp_server::test_chan_deallocation() { mb_runtime_sptr rt = mb_make_runtime(); pmt_t result = PMT_T; // std::cout << "\n\n----------------------------\n"; // std::cout << " RUNNING DEALLOCATION TESTS \n"; rt->run("qa_dealloc_top", "qa_dealloc_top", PMT_F, &result); CPPUNIT_ASSERT(pmt_equal(PMT_T, result)); } void qa_inband_usrp_server::test_tx() { mb_runtime_sptr rt = mb_make_runtime(); pmt_t result = PMT_T; // std::cout << "\n\n-----------------\n"; // std::cout << " RUNNING TX TESTS \n"; rt->run("top", "qa_tx_top", PMT_F, &result); CPPUNIT_ASSERT(pmt_equal(PMT_T, result)); } void qa_inband_usrp_server::test_rx() { mb_runtime_sptr rt = mb_make_runtime(); pmt_t result = PMT_T; // std::cout << "\n\n-----------------\n"; // std::cout << " RUNNING RX TESTS \n"; rt->run("top", "qa_rx_top", PMT_F, &result); CPPUNIT_ASSERT(pmt_equal(PMT_T, result)); } void qa_inband_usrp_server::test_cs() { // FIXME This test is disabled because it hangs with the change to use usrp_standard_*_sptr's return; mb_runtime_sptr rt = mb_make_runtime(); pmt_t result = PMT_T; // std::cout << "\n\n-----------------\n"; // std::cout << " RUNNING CS TESTS \n"; rt->run("top", "qa_cs_top", PMT_F, &result); CPPUNIT_ASSERT(pmt_equal(PMT_T, result)); } void qa_inband_usrp_server::test_rid() { // FIXME This test is disabled because it hangs with the change to use usrp_standard_*_sptr's return; mb_runtime_sptr rt = mb_make_runtime(); pmt_t result = PMT_T; // std::cout << "\n\n-----------------\n"; // std::cout << " RUNNING RID TESTS \n"; rt->run("top", "qa_rid_top", PMT_F, &result); CPPUNIT_ASSERT(pmt_equal(PMT_T, result)); }