aboutsummaryrefslogtreecommitdiffstats
path: root/host/examples/benchmark_rate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'host/examples/benchmark_rate.cpp')
-rw-r--r--host/examples/benchmark_rate.cpp571
1 files changed, 277 insertions, 294 deletions
diff --git a/host/examples/benchmark_rate.cpp b/host/examples/benchmark_rate.cpp
index 5e997f59a..b97de09ac 100644
--- a/host/examples/benchmark_rate.cpp
+++ b/host/examples/benchmark_rate.cpp
@@ -5,49 +5,50 @@
// SPDX-License-Identifier: GPL-3.0-or-later
//
-#include <uhd/utils/thread.hpp>
#include <uhd/convert.hpp>
-#include <uhd/utils/safe_main.hpp>
#include <uhd/usrp/multi_usrp.hpp>
-#include <boost/program_options.hpp>
-#include <boost/format.hpp>
-#include <boost/thread/thread.hpp>
+#include <uhd/utils/safe_main.hpp>
+#include <uhd/utils/thread.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
-#include <iostream>
-#include <complex>
-#include <cstdlib>
+#include <boost/format.hpp>
+#include <boost/program_options.hpp>
+#include <boost/thread/thread.hpp>
#include <atomic>
#include <chrono>
+#include <complex>
+#include <cstdlib>
+#include <iostream>
#include <thread>
namespace po = boost::program_options;
namespace {
- constexpr int64_t CLOCK_TIMEOUT = 1000; // 1000mS timeout for external clock locking
- constexpr float INIT_DELAY = 0.05; // 50mS initial delay before transmit
-}
+constexpr int64_t CLOCK_TIMEOUT = 1000; // 1000mS timeout for external clock locking
+constexpr float INIT_DELAY = 0.05; // 50mS initial delay before transmit
+} // namespace
/***********************************************************************
* Test result variables
**********************************************************************/
-unsigned long long num_overruns = 0;
-unsigned long long num_underruns = 0;
-unsigned long long num_rx_samps = 0;
-unsigned long long num_tx_samps = 0;
+unsigned long long num_overruns = 0;
+unsigned long long num_underruns = 0;
+unsigned long long num_rx_samps = 0;
+unsigned long long num_tx_samps = 0;
unsigned long long num_dropped_samps = 0;
-unsigned long long num_seq_errors = 0;
-unsigned long long num_seqrx_errors = 0; // "D"s
+unsigned long long num_seq_errors = 0;
+unsigned long long num_seqrx_errors = 0; // "D"s
unsigned long long num_late_commands = 0;
-unsigned long long num_timeouts_rx = 0;
-unsigned long long num_timeouts_tx = 0;
+unsigned long long num_timeouts_rx = 0;
+unsigned long long num_timeouts_tx = 0;
-inline boost::posix_time::time_duration time_delta(const boost::posix_time::ptime &ref_time)
+inline boost::posix_time::time_duration time_delta(
+ const boost::posix_time::ptime& ref_time)
{
return boost::posix_time::microsec_clock::local_time() - ref_time;
}
-inline std::string time_delta_str(const boost::posix_time::ptime &ref_time)
+inline std::string time_delta_str(const boost::posix_time::ptime& ref_time)
{
return boost::posix_time::to_simple_string(time_delta(ref_time));
}
@@ -57,44 +58,45 @@ inline std::string time_delta_str(const boost::posix_time::ptime &ref_time)
/***********************************************************************
* Benchmark RX Rate
**********************************************************************/
-void benchmark_rx_rate(
- uhd::usrp::multi_usrp::sptr usrp,
- const std::string &rx_cpu,
- uhd::rx_streamer::sptr rx_stream,
- bool random_nsamps,
- const boost::posix_time::ptime &start_time,
- std::atomic<bool>& burst_timer_elapsed
-) {
+void benchmark_rx_rate(uhd::usrp::multi_usrp::sptr usrp,
+ const std::string& rx_cpu,
+ uhd::rx_streamer::sptr rx_stream,
+ bool random_nsamps,
+ const boost::posix_time::ptime& start_time,
+ std::atomic<bool>& burst_timer_elapsed)
+{
uhd::set_thread_priority_safe();
- //print pre-test summary
- std::cout << boost::format(
- "[%s] Testing receive rate %f Msps on %u channels"
- ) % NOW() % (usrp->get_rx_rate()/1e6) % rx_stream->get_num_channels() << std::endl;
+ // print pre-test summary
+ std::cout << boost::format("[%s] Testing receive rate %f Msps on %u channels") % NOW()
+ % (usrp->get_rx_rate() / 1e6) % rx_stream->get_num_channels()
+ << std::endl;
- //setup variables and allocate buffer
+ // setup variables and allocate buffer
uhd::rx_metadata_t md;
const size_t max_samps_per_packet = rx_stream->get_max_num_samps();
- std::vector<char> buff(max_samps_per_packet*uhd::convert::get_bytes_per_item(rx_cpu));
- std::vector<void *> buffs;
+ std::vector<char> buff(
+ max_samps_per_packet * uhd::convert::get_bytes_per_item(rx_cpu));
+ std::vector<void*> buffs;
for (size_t ch = 0; ch < rx_stream->get_num_channels(); ch++)
- buffs.push_back(&buff.front()); //same buffer for each channel
+ buffs.push_back(&buff.front()); // same buffer for each channel
bool had_an_overflow = false;
uhd::time_spec_t last_time;
const double rate = usrp->get_rx_rate();
uhd::stream_cmd_t cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
- cmd.time_spec = usrp->get_time_now() + uhd::time_spec_t(INIT_DELAY);
+ cmd.time_spec = usrp->get_time_now() + uhd::time_spec_t(INIT_DELAY);
cmd.stream_now = (buffs.size() == 1);
rx_stream->issue_stream_cmd(cmd);
const float burst_pkt_time =
- std::max<float>(0.100f, (2 * max_samps_per_packet/rate));
+ std::max<float>(0.100f, (2 * max_samps_per_packet / rate));
float recv_timeout = burst_pkt_time + INIT_DELAY;
bool stop_called = false;
while (true) {
- //if (burst_timer_elapsed.load(boost::memory_order_relaxed) and not stop_called) {
+ // if (burst_timer_elapsed.load(boost::memory_order_relaxed) and not stop_called)
+ // {
if (burst_timer_elapsed and not stop_called) {
rx_stream->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
stop_called = true;
@@ -104,71 +106,78 @@ void benchmark_rx_rate(
rx_stream->issue_stream_cmd(cmd);
}
try {
- num_rx_samps += rx_stream->recv(buffs, max_samps_per_packet, md, recv_timeout)*rx_stream->get_num_channels();
+ num_rx_samps += rx_stream->recv(buffs, max_samps_per_packet, md, recv_timeout)
+ * rx_stream->get_num_channels();
recv_timeout = burst_pkt_time;
- }
- catch (uhd::io_error &e) {
+ } catch (uhd::io_error& e) {
std::cerr << "[" << NOW() << "] Caught an IO exception. " << std::endl;
std::cerr << e.what() << std::endl;
return;
}
- //handle the error codes
- switch(md.error_code){
- case uhd::rx_metadata_t::ERROR_CODE_NONE:
- if (had_an_overflow) {
- had_an_overflow = false;
- const long dropped_samps =
- (md.time_spec - last_time).to_ticks(rate);
- if (dropped_samps < 0) {
- std::cerr
- << "[" << NOW() << "] Timestamp after overrun recovery "
- "ahead of error timestamp! Unable to calculate "
- "number of dropped samples."
- "(Delta: " << dropped_samps << " ticks)\n";
+ // handle the error codes
+ switch (md.error_code) {
+ case uhd::rx_metadata_t::ERROR_CODE_NONE:
+ if (had_an_overflow) {
+ had_an_overflow = false;
+ const long dropped_samps = (md.time_spec - last_time).to_ticks(rate);
+ if (dropped_samps < 0) {
+ std::cerr << "[" << NOW()
+ << "] Timestamp after overrun recovery "
+ "ahead of error timestamp! Unable to calculate "
+ "number of dropped samples."
+ "(Delta: "
+ << dropped_samps << " ticks)\n";
+ }
+ num_dropped_samps += std::max<long>(1, dropped_samps);
}
- num_dropped_samps += std::max<long>(1, dropped_samps);
- }
- if ((burst_timer_elapsed or stop_called) and md.end_of_burst) {
- return;
- }
- break;
-
- // ERROR_CODE_OVERFLOW can indicate overflow or sequence error
- case uhd::rx_metadata_t::ERROR_CODE_OVERFLOW:
- last_time = md.time_spec;
- had_an_overflow = true;
- // check out_of_sequence flag to see if it was a sequence error or overflow
- if (!md.out_of_sequence) {
- num_overruns++;
- } else {
- num_seqrx_errors++;
- std::cerr << "[" << NOW() << "] Detected Rx sequence error." << std::endl;
- }
- break;
-
- case uhd::rx_metadata_t::ERROR_CODE_LATE_COMMAND:
- std::cerr << "[" << NOW() << "] Receiver error: " << md.strerror() << ", restart streaming..."<< std::endl;
- num_late_commands++;
- // Radio core will be in the idle state. Issue stream command to restart streaming.
- cmd.time_spec = usrp->get_time_now() + uhd::time_spec_t(0.05);
- cmd.stream_now = (buffs.size() == 1);
- rx_stream->issue_stream_cmd(cmd);
- break;
-
- case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT:
- if (burst_timer_elapsed) {
- return;
- }
- std::cerr << "[" << NOW() << "] Receiver error: " << md.strerror() << ", continuing..." << std::endl;
- num_timeouts_rx++;
- break;
-
- // Otherwise, it's an error
- default:
- std::cerr << "[" << NOW() << "] Receiver error: " << md.strerror() << std::endl;
- std::cerr << "[" << NOW() << "] Unexpected error on recv, continuing..." << std::endl;
- break;
+ if ((burst_timer_elapsed or stop_called) and md.end_of_burst) {
+ return;
+ }
+ break;
+
+ // ERROR_CODE_OVERFLOW can indicate overflow or sequence error
+ case uhd::rx_metadata_t::ERROR_CODE_OVERFLOW:
+ last_time = md.time_spec;
+ had_an_overflow = true;
+ // check out_of_sequence flag to see if it was a sequence error or
+ // overflow
+ if (!md.out_of_sequence) {
+ num_overruns++;
+ } else {
+ num_seqrx_errors++;
+ std::cerr << "[" << NOW() << "] Detected Rx sequence error."
+ << std::endl;
+ }
+ break;
+
+ case uhd::rx_metadata_t::ERROR_CODE_LATE_COMMAND:
+ std::cerr << "[" << NOW() << "] Receiver error: " << md.strerror()
+ << ", restart streaming..." << std::endl;
+ num_late_commands++;
+ // Radio core will be in the idle state. Issue stream command to restart
+ // streaming.
+ cmd.time_spec = usrp->get_time_now() + uhd::time_spec_t(0.05);
+ cmd.stream_now = (buffs.size() == 1);
+ rx_stream->issue_stream_cmd(cmd);
+ break;
+
+ case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT:
+ if (burst_timer_elapsed) {
+ return;
+ }
+ std::cerr << "[" << NOW() << "] Receiver error: " << md.strerror()
+ << ", continuing..." << std::endl;
+ num_timeouts_rx++;
+ break;
+
+ // Otherwise, it's an error
+ default:
+ std::cerr << "[" << NOW() << "] Receiver error: " << md.strerror()
+ << std::endl;
+ std::cerr << "[" << NOW() << "] Unexpected error on recv, continuing..."
+ << std::endl;
+ break;
}
}
}
@@ -176,71 +185,75 @@ void benchmark_rx_rate(
/***********************************************************************
* Benchmark TX Rate
**********************************************************************/
-void benchmark_tx_rate(
- uhd::usrp::multi_usrp::sptr usrp,
- const std::string &tx_cpu,
- uhd::tx_streamer::sptr tx_stream,
- std::atomic<bool>& burst_timer_elapsed,
- const boost::posix_time::ptime &start_time,
- bool random_nsamps=false
-) {
+void benchmark_tx_rate(uhd::usrp::multi_usrp::sptr usrp,
+ const std::string& tx_cpu,
+ uhd::tx_streamer::sptr tx_stream,
+ std::atomic<bool>& burst_timer_elapsed,
+ const boost::posix_time::ptime& start_time,
+ bool random_nsamps = false)
+{
uhd::set_thread_priority_safe();
- //print pre-test summary
- std::cout << boost::format(
- "[%s] Testing transmit rate %f Msps on %u channels"
- ) % NOW() % (usrp->get_tx_rate()/1e6) % tx_stream->get_num_channels() << std::endl;
+ // print pre-test summary
+ std::cout << boost::format("[%s] Testing transmit rate %f Msps on %u channels")
+ % NOW() % (usrp->get_tx_rate() / 1e6) % tx_stream->get_num_channels()
+ << std::endl;
- //setup variables and allocate buffer
+ // setup variables and allocate buffer
const size_t max_samps_per_packet = tx_stream->get_max_num_samps();
- std::vector<char> buff(max_samps_per_packet*uhd::convert::get_bytes_per_item(tx_cpu));
- std::vector<const void *> buffs;
+ std::vector<char> buff(
+ max_samps_per_packet * uhd::convert::get_bytes_per_item(tx_cpu));
+ std::vector<const void*> buffs;
for (size_t ch = 0; ch < tx_stream->get_num_channels(); ch++)
- buffs.push_back(&buff.front()); //same buffer for each channel
+ buffs.push_back(&buff.front()); // same buffer for each channel
// Create the metadata, and populate the time spec at the latest possible moment
uhd::tx_metadata_t md;
md.has_time_spec = (buffs.size() != 1);
- md.time_spec = usrp->get_time_now() + uhd::time_spec_t(INIT_DELAY);
+ md.time_spec = usrp->get_time_now() + uhd::time_spec_t(INIT_DELAY);
if (random_nsamps) {
std::srand((unsigned int)time(NULL));
while (not burst_timer_elapsed) {
size_t total_num_samps = rand() % max_samps_per_packet;
- size_t num_acc_samps = 0;
- const float timeout = 1;
+ size_t num_acc_samps = 0;
+ const float timeout = 1;
usrp->set_time_now(uhd::time_spec_t(0.0));
- while(num_acc_samps < total_num_samps){
- //send a single packet
- num_tx_samps += tx_stream->send(buffs, max_samps_per_packet, md, timeout)*tx_stream->get_num_channels();
- num_acc_samps += std::min(total_num_samps-num_acc_samps, tx_stream->get_max_num_samps());
+ while (num_acc_samps < total_num_samps) {
+ // send a single packet
+ num_tx_samps += tx_stream->send(buffs, max_samps_per_packet, md, timeout)
+ * tx_stream->get_num_channels();
+ num_acc_samps += std::min(
+ total_num_samps - num_acc_samps, tx_stream->get_max_num_samps());
}
}
} else {
while (not burst_timer_elapsed) {
- const size_t num_tx_samps_sent_now = tx_stream->send(buffs, max_samps_per_packet, md)*tx_stream->get_num_channels();
+ const size_t num_tx_samps_sent_now =
+ tx_stream->send(buffs, max_samps_per_packet, md)
+ * tx_stream->get_num_channels();
num_tx_samps += num_tx_samps_sent_now;
if (num_tx_samps_sent_now == 0) {
num_timeouts_tx++;
if ((num_timeouts_tx % 10000) == 1) {
- std::cerr << "[" << NOW() << "] Tx timeouts: " << num_timeouts_tx << std::endl;
+ std::cerr << "[" << NOW() << "] Tx timeouts: " << num_timeouts_tx
+ << std::endl;
}
}
md.has_time_spec = false;
}
}
- //send a mini EOB packet
+ // send a mini EOB packet
md.end_of_burst = true;
tx_stream->send(buffs, 0, md);
}
-void benchmark_tx_rate_async_helper(
- uhd::tx_streamer::sptr tx_stream,
- const boost::posix_time::ptime &start_time,
- std::atomic<bool>& burst_timer_elapsed
-) {
- //setup variables and allocate buffer
+void benchmark_tx_rate_async_helper(uhd::tx_streamer::sptr tx_stream,
+ const boost::posix_time::ptime& start_time,
+ std::atomic<bool>& burst_timer_elapsed)
+{
+ // setup variables and allocate buffer
uhd::async_metadata_t async_md;
bool exit_flag = false;
@@ -255,25 +268,26 @@ void benchmark_tx_rate_async_helper(
continue;
}
- //handle the error codes
- switch(async_md.event_code){
- case uhd::async_metadata_t::EVENT_CODE_BURST_ACK:
- return;
-
- case uhd::async_metadata_t::EVENT_CODE_UNDERFLOW:
- case uhd::async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET:
- num_underruns++;
- break;
-
- case uhd::async_metadata_t::EVENT_CODE_SEQ_ERROR:
- case uhd::async_metadata_t::EVENT_CODE_SEQ_ERROR_IN_BURST:
- num_seq_errors++;
- break;
+ // handle the error codes
+ switch (async_md.event_code) {
+ case uhd::async_metadata_t::EVENT_CODE_BURST_ACK:
+ return;
- default:
- std::cerr << "[" << NOW() << "] Event code: " << async_md.event_code << std::endl;
- std::cerr << "Unexpected event on async recv, continuing..." << std::endl;
- break;
+ case uhd::async_metadata_t::EVENT_CODE_UNDERFLOW:
+ case uhd::async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET:
+ num_underruns++;
+ break;
+
+ case uhd::async_metadata_t::EVENT_CODE_SEQ_ERROR:
+ case uhd::async_metadata_t::EVENT_CODE_SEQ_ERROR_IN_BURST:
+ num_seq_errors++;
+ break;
+
+ default:
+ std::cerr << "[" << NOW() << "] Event code: " << async_md.event_code
+ << std::endl;
+ std::cerr << "Unexpected event on async recv, continuing..." << std::endl;
+ break;
}
}
}
@@ -281,10 +295,11 @@ void benchmark_tx_rate_async_helper(
/***********************************************************************
* Main code + dispatcher
**********************************************************************/
-int UHD_SAFE_MAIN(int argc, char *argv[]){
+int UHD_SAFE_MAIN(int argc, char* argv[])
+{
uhd::set_thread_priority_safe();
- //variables to be set by po
+ // variables to be set by po
std::string args;
std::string rx_subdev, tx_subdev;
double duration;
@@ -297,7 +312,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
std::atomic<bool> burst_timer_elapsed(false);
size_t overrun_threshold, underrun_threshold, drop_threshold, seq_threshold;
- //setup the program options
+ // setup the program options
po::options_description desc("Allowed options");
// clang-format off
desc.add_options()
@@ -333,45 +348,52 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
po::store(po::parse_command_line(argc, argv, desc), vm);
po::notify(vm);
- //print the help message
- if (vm.count("help") or (vm.count("rx_rate") + vm.count("tx_rate")) == 0){
+ // print the help message
+ if (vm.count("help") or (vm.count("rx_rate") + vm.count("tx_rate")) == 0) {
std::cout << boost::format("UHD Benchmark Rate %s") % desc << std::endl;
- std::cout <<
- " Specify --rx_rate for a receive-only test.\n"
- " Specify --tx_rate for a transmit-only test.\n"
- " Specify both options for a full-duplex test.\n"
- << std::endl;
+ std::cout << " Specify --rx_rate for a receive-only test.\n"
+ " Specify --tx_rate for a transmit-only test.\n"
+ " Specify both options for a full-duplex test.\n"
+ << std::endl;
return ~0;
}
// Random number of samples?
if (vm.count("random")) {
- std::cout << "Using random number of samples in send() and recv() calls." << std::endl;
+ std::cout << "Using random number of samples in send() and recv() calls."
+ << std::endl;
random_nsamps = true;
}
if (vm.count("mode")) {
if (vm.count("pps") or vm.count("ref")) {
- std::cout << "ERROR: The \"mode\" parameter cannot be used with the \"ref\" and \"pps\" parameters.\n" << std::endl;
+ std::cout << "ERROR: The \"mode\" parameter cannot be used with the \"ref\" "
+ "and \"pps\" parameters.\n"
+ << std::endl;
return -1;
} else if (mode == "mimo") {
ref = pps = "mimo";
- std::cout << "The use of the \"mode\" parameter is deprecated. Please use \"ref\" and \"pps\" parameters instead\n" << std::endl;
+ std::cout << "The use of the \"mode\" parameter is deprecated. Please use "
+ "\"ref\" and \"pps\" parameters instead\n"
+ << std::endl;
}
}
- //create a usrp device
+ // create a usrp device
std::cout << std::endl;
uhd::device_addrs_t device_addrs = uhd::device::find(args, uhd::device::USRP);
- if (not device_addrs.empty() and device_addrs.at(0).get("type", "") == "usrp1"){
+ if (not device_addrs.empty() and device_addrs.at(0).get("type", "") == "usrp1") {
std::cerr << "*** Warning! ***" << std::endl;
- std::cerr << "Benchmark results will be inaccurate on USRP1 due to insufficient features.\n" << std::endl;
+ std::cerr << "Benchmark results will be inaccurate on USRP1 due to insufficient "
+ "features.\n"
+ << std::endl;
}
boost::posix_time::ptime start_time(boost::posix_time::microsec_clock::local_time());
- std::cout << boost::format("[%s] Creating the usrp device with: %s...") % NOW() % args << std::endl;
+ std::cout << boost::format("[%s] Creating the usrp device with: %s...") % NOW() % args
+ << std::endl;
uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args);
- //always select the subdevice first, the channel mapping affects the other settings
+ // always select the subdevice first, the channel mapping affects the other settings
if (vm.count("rx_subdev")) {
usrp->set_rx_subdev_spec(rx_subdev);
}
@@ -384,34 +406,35 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
boost::thread_group thread_group;
- if(vm.count("ref"))
- {
- if (ref == "mimo")
- {
+ if (vm.count("ref")) {
+ if (ref == "mimo") {
if (num_mboards != 2) {
- std::cerr << "ERROR: ref = \"mimo\" implies 2 motherboards; your system has " << num_mboards << " boards" << std::endl;
+ std::cerr
+ << "ERROR: ref = \"mimo\" implies 2 motherboards; your system has "
+ << num_mboards << " boards" << std::endl;
return -1;
}
- usrp->set_clock_source("mimo",1);
+ usrp->set_clock_source("mimo", 1);
} else {
usrp->set_clock_source(ref);
}
- if(ref != "internal") {
+ if (ref != "internal") {
std::cout << "Now confirming lock on clock signals..." << std::endl;
bool is_locked = false;
auto end_time =
- boost::get_system_time() +
- boost::posix_time::milliseconds(CLOCK_TIMEOUT);
+ boost::get_system_time() + boost::posix_time::milliseconds(CLOCK_TIMEOUT);
for (int i = 0; i < num_mboards; i++) {
- if (ref == "mimo" and i == 0) continue;
- while((is_locked = usrp->get_mboard_sensor("ref_locked",i).to_bool()) == false and
- boost::get_system_time() < end_time )
- {
+ if (ref == "mimo" and i == 0)
+ continue;
+ while ((is_locked = usrp->get_mboard_sensor("ref_locked", i).to_bool())
+ == false
+ and boost::get_system_time() < end_time) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
if (is_locked == false) {
- std::cerr << "ERROR: Unable to confirm clock signal locked on board:" << i << std::endl;
+ std::cerr << "ERROR: Unable to confirm clock signal locked on board:"
+ << i << std::endl;
return -1;
}
is_locked = false;
@@ -419,22 +442,22 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
}
}
- if(vm.count("pps"))
- {
- if(pps == "mimo")
- {
- if (num_mboards != 2) {
- std::cerr << "ERROR: ref = \"mimo\" implies 2 motherboards; your system has " << num_mboards << " boards" << std::endl;
- return -1;
- }
- //make mboard 1 a slave over the MIMO Cable
- usrp->set_time_source("mimo", 1);
- } else {
- usrp->set_time_source(pps);
- }
+ if (vm.count("pps")) {
+ if (pps == "mimo") {
+ if (num_mboards != 2) {
+ std::cerr
+ << "ERROR: ref = \"mimo\" implies 2 motherboards; your system has "
+ << num_mboards << " boards" << std::endl;
+ return -1;
+ }
+ // make mboard 1 a slave over the MIMO Cable
+ usrp->set_time_source("mimo", 1);
+ } else {
+ usrp->set_time_source(pps);
+ }
}
- //check that the device has sufficient RX and TX channels available
+ // check that the device has sufficient RX and TX channels available
std::vector<std::string> channel_strings;
std::vector<size_t> rx_channel_nums;
if (vm.count("rx_rate")) {
@@ -470,7 +493,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
}
}
- std::cout << boost::format("[%s] Setting device timestamp to 0...") % NOW() << std::endl;
+ std::cout << boost::format("[%s] Setting device timestamp to 0...") % NOW()
+ << std::endl;
if (pps == "mimo" or ref == "mimo") {
// only set the master's time, the slave's is automatically sync'd
usrp->set_time_now(uhd::time_spec_t(0.0), 0);
@@ -484,144 +508,103 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
usrp->set_time_now(0.0);
}
- //spawn the receive test thread
- if (vm.count("rx_rate")){
+ // spawn the receive test thread
+ if (vm.count("rx_rate")) {
usrp->set_rx_rate(rx_rate);
- //create a receive streamer
+ // create a receive streamer
uhd::stream_args_t stream_args(rx_cpu, rx_otw);
- stream_args.channels = rx_channel_nums;
+ stream_args.channels = rx_channel_nums;
uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args);
- auto rx_thread = thread_group.create_thread([=, &burst_timer_elapsed](){
+ auto rx_thread = thread_group.create_thread([=, &burst_timer_elapsed]() {
benchmark_rx_rate(
- usrp,
- rx_cpu,
- rx_stream,
- random_nsamps,
- start_time,
- burst_timer_elapsed
- );
+ usrp, rx_cpu, rx_stream, random_nsamps, start_time, burst_timer_elapsed);
});
uhd::set_thread_name(rx_thread, "bmark_rx_stream");
}
- //spawn the transmit test thread
- if (vm.count("tx_rate")){
+ // spawn the transmit test thread
+ if (vm.count("tx_rate")) {
usrp->set_tx_rate(tx_rate);
- //create a transmit streamer
+ // create a transmit streamer
uhd::stream_args_t stream_args(tx_cpu, tx_otw);
- stream_args.channels = tx_channel_nums;
+ stream_args.channels = tx_channel_nums;
uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args);
- auto tx_thread = thread_group.create_thread([=, &burst_timer_elapsed](){
+ auto tx_thread = thread_group.create_thread([=, &burst_timer_elapsed]() {
benchmark_tx_rate(
- usrp,
- tx_cpu,
- tx_stream,
- burst_timer_elapsed,
- start_time,
- random_nsamps
- );
+ usrp, tx_cpu, tx_stream, burst_timer_elapsed, start_time, random_nsamps);
});
uhd::set_thread_name(tx_thread, "bmark_tx_stream");
- auto tx_async_thread = thread_group.create_thread([=, &burst_timer_elapsed](){
- benchmark_tx_rate_async_helper(
- tx_stream,
- start_time,
- burst_timer_elapsed
- );
+ auto tx_async_thread = thread_group.create_thread([=, &burst_timer_elapsed]() {
+ benchmark_tx_rate_async_helper(tx_stream, start_time, burst_timer_elapsed);
});
uhd::set_thread_name(tx_async_thread, "bmark_tx_helper");
}
- //sleep for the required duration
+ // sleep for the required duration
const bool wait_for_multichan =
(rx_channel_nums.size() <= 1 and tx_channel_nums.size() <= 1);
- const int64_t secs =
- int64_t(duration + (wait_for_multichan ? 0 : INIT_DELAY * 1000));
- const int64_t usecs = int64_t((duration - secs)*1e6);
+ const int64_t secs = int64_t(duration + (wait_for_multichan ? 0 : INIT_DELAY * 1000));
+ const int64_t usecs = int64_t((duration - secs) * 1e6);
std::this_thread::sleep_for(
- std::chrono::seconds(secs) +
- std::chrono::microseconds(usecs)
- );
+ std::chrono::seconds(secs) + std::chrono::microseconds(usecs));
- //interrupt and join the threads
+ // interrupt and join the threads
burst_timer_elapsed = true;
thread_group.join_all();
std::cout << "[" << NOW() << "] Benchmark complete." << std::endl << std::endl;
- //print summary
+ // print summary
const std::string threshold_err(" ERROR: Exceeds threshold!");
- const bool overrun_threshold_err =
- vm.count("overrun-threshold") and
- num_overruns > overrun_threshold;
- const bool underrun_threshold_err =
- vm.count("underrun-threshold") and
- num_underruns > underrun_threshold;
- const bool drop_threshold_err =
- vm.count("drop-threshold") and
- num_seqrx_errors > drop_threshold;
- const bool seq_threshold_err =
- vm.count("seq-threshold") and
- num_seq_errors > seq_threshold;
+ const bool overrun_threshold_err = vm.count("overrun-threshold")
+ and num_overruns > overrun_threshold;
+ const bool underrun_threshold_err = vm.count("underrun-threshold")
+ and num_underruns > underrun_threshold;
+ const bool drop_threshold_err = vm.count("drop-threshold")
+ and num_seqrx_errors > drop_threshold;
+ const bool seq_threshold_err = vm.count("seq-threshold")
+ and num_seq_errors > seq_threshold;
std::cout << std::endl
- << boost::format(
- "Benchmark rate summary:\n"
- " Num received samples: %u\n"
- " Num dropped samples: %u\n"
- " Num overruns detected: %u\n"
- " Num transmitted samples: %u\n"
- " Num sequence errors (Tx): %u\n"
- " Num sequence errors (Rx): %u\n"
- " Num underruns detected: %u\n"
- " Num late commands: %u\n"
- " Num timeouts (Tx): %u\n"
- " Num timeouts (Rx): %u\n"
- ) % num_rx_samps
- % num_dropped_samps
- % num_overruns
- % num_tx_samps
- % num_seq_errors
- % num_seqrx_errors
- % num_underruns
- % num_late_commands
- % num_timeouts_tx
- % num_timeouts_rx
- << std::endl;
- //finished
+ << boost::format("Benchmark rate summary:\n"
+ " Num received samples: %u\n"
+ " Num dropped samples: %u\n"
+ " Num overruns detected: %u\n"
+ " Num transmitted samples: %u\n"
+ " Num sequence errors (Tx): %u\n"
+ " Num sequence errors (Rx): %u\n"
+ " Num underruns detected: %u\n"
+ " Num late commands: %u\n"
+ " Num timeouts (Tx): %u\n"
+ " Num timeouts (Rx): %u\n")
+ % num_rx_samps % num_dropped_samps % num_overruns % num_tx_samps
+ % num_seq_errors % num_seqrx_errors % num_underruns
+ % num_late_commands % num_timeouts_tx % num_timeouts_rx
+ << std::endl;
+ // finished
std::cout << std::endl << "Done!" << std::endl << std::endl;
- if (overrun_threshold_err
- || underrun_threshold_err
- || drop_threshold_err
- || seq_threshold_err) {
+ if (overrun_threshold_err || underrun_threshold_err || drop_threshold_err
+ || seq_threshold_err) {
std::cout << "The following error thresholds were exceeded:\n";
if (overrun_threshold_err) {
- std::cout
- << boost::format(" * Overruns (%d/%d)")
- % num_overruns
- % overrun_threshold
- << std::endl;
+ std::cout << boost::format(" * Overruns (%d/%d)") % num_overruns
+ % overrun_threshold
+ << std::endl;
}
if (underrun_threshold_err) {
- std::cout
- << boost::format(" * Underruns (%d/%d)")
- % num_underruns
- % underrun_threshold
- << std::endl;
+ std::cout << boost::format(" * Underruns (%d/%d)") % num_underruns
+ % underrun_threshold
+ << std::endl;
}
if (drop_threshold_err) {
- std::cout
- << boost::format(" * Dropped packets (RX) (%d/%d)")
- % num_seqrx_errors
- % drop_threshold
- << std::endl;
+ std::cout << boost::format(" * Dropped packets (RX) (%d/%d)")
+ % num_seqrx_errors % drop_threshold
+ << std::endl;
}
if (seq_threshold_err) {
- std::cout
- << boost::format(" * Dropped packets (TX) (%d/%d)")
- % num_seq_errors
- % seq_threshold
- << std::endl;
+ std::cout << boost::format(" * Dropped packets (TX) (%d/%d)")
+ % num_seq_errors % seq_threshold
+ << std::endl;
}
return EXIT_FAILURE;
}