diff options
| -rw-r--r-- | tools/kitchen_sink/kitchen_sink.cpp | 161 | 
1 files changed, 139 insertions, 22 deletions
diff --git a/tools/kitchen_sink/kitchen_sink.cpp b/tools/kitchen_sink/kitchen_sink.cpp index c7265bea4..62bf89375 100644 --- a/tools/kitchen_sink/kitchen_sink.cpp +++ b/tools/kitchen_sink/kitchen_sink.cpp @@ -278,12 +278,16 @@ typedef struct RxParams {      bool single_packets;      bool size_map;      size_t rx_sample_limit; -    std::ofstream* capture_file; +    std::vector<std::ofstream*> capture_files;      bool set_rx_freq;      double rx_freq;      double rx_freq_delay;      double rx_lo_offset;      bool interleave_rx_file_samples; +    bool ignore_late_start; +    bool ignore_bad_packets; +    bool ignore_timeout; +    bool ignore_unexpected_error;  } RX_PARAMS;  static uint64_t recv_samp_count_progress = 0; @@ -465,25 +469,37 @@ void benchmark_rx_rate(                          recv_done.notify_one();                      } -                    if (params.capture_file != NULL) +                    if (params.capture_files.empty() == false)                      { -                        if (params.interleave_rx_file_samples) +                        size_t channel_count = rx_stream->get_num_channels(); + +                        if ((channel_count == 1) || ((channel_count > 1) && (params.capture_files.size() == 1)))                          { -                            for (size_t i = 0; i < recv_samps; ++i) +                            if (params.interleave_rx_file_samples) +                            { +                                for (size_t i = 0; i < recv_samps; ++i) +                                { +                                    for (size_t j = 0; j < channel_count; ++j) +                                    { +                                        params.capture_files[0]->write((const char*)buffs[j] + (bytes_per_samp * i), bytes_per_samp); +                                    } +                                } +                            } +                            else                              { -                                size_t channel_count = rx_stream->get_num_channels(); -                                for (size_t j = 0; j < channel_count; ++j) +                                for (size_t i = 0; i < channel_count; ++i)                                  { -                                    params.capture_file->write((const char*)buffs[j] + (bytes_per_samp * i), bytes_per_samp); +                                    size_t num_bytes = recv_samps * bytes_per_samp; +                                    params.capture_files[0]->write((const char*)buffs[i], num_bytes);                                  }                              }                          }                          else                          { -                            for (size_t i = 0; i < rx_stream->get_num_channels(); ++i) +                            for (size_t n = 0; n < channel_count; ++n)                              {                                  size_t num_bytes = recv_samps * bytes_per_samp; -                                params.capture_file->write((const char*)buffs[i], num_bytes); +                                params.capture_files[n]->write((const char*)buffs[n], num_bytes);                              }                          }                      } @@ -498,13 +514,17 @@ void benchmark_rx_rate(              //}              //handle the error codes -            switch(md.error_code) { +            switch(md.error_code) +            {                  case uhd::rx_metadata_t::ERROR_CODE_NONE: -                    if (had_an_overflow) { +                { +                    if (had_an_overflow) +                    {                          had_an_overflow = false;                          num_dropped_samps += (md.time_spec - last_time).to_ticks(rate); // FIXME: Check this as 'num_dropped_samps' has come out -ve                      }                      break; +                }                  // ERROR_CODE_OVERFLOW can indicate overflow or sequence error                  case uhd::rx_metadata_t::ERROR_CODE_OVERFLOW:   // 'recv_samps' should be 0 @@ -523,13 +543,43 @@ void benchmark_rx_rate(                      ss << HEADER_RX"(" << get_stringified_time() << ") ";                      ss << boost::format("Timeout") << std::endl;                      std::cout << ss.str(); +                    if (params.ignore_timeout == false) +                        sig_int_handler(-1); +                    break; +                } + +                case uhd::rx_metadata_t::ERROR_CODE_LATE_COMMAND: +                { +                    std::stringstream ss; +                    ss << HEADER_RX"(" << get_stringified_time() << ") "; +                    ss << boost::format("Late command") << std::endl; +                    std::cout << ss.str(); +                    if (params.ignore_late_start == false) +                        sig_int_handler(-1); +                    break; +                } + +                case uhd::rx_metadata_t::ERROR_CODE_BAD_PACKET: +                { +                    std::stringstream ss; +                    ss << HEADER_RX"(" << get_stringified_time() << ") "; +                    ss << boost::format("Bad packet") << std::endl; +                    std::cout << ss.str(); +                    if (params.ignore_bad_packets == false) +                        sig_int_handler(-1);                      break;                  }                  default: -                    std::cerr << HEADER_RX"Error code: " << md.error_code << std::endl; -                    std::cerr << HEADER_RX"Unexpected error on recv, continuing..." << std::endl; +                { +                    std::stringstream ss; +                    ss << HEADER_RX"(" << get_stringified_time() << ") "; +                    ss << (boost::format("Unexpected error (code: %d)") % md.error_code) << std::endl; +                    std::cout << ss.str(); +                    if (params.ignore_unexpected_error == false) +                        sig_int_handler(-1);                      break; +                }              }              print_msgs(); @@ -550,11 +600,14 @@ void benchmark_rx_rate(          rx_stream->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);      } -    if (params.capture_file != NULL) +    if (params.capture_files.empty() == false)      { -        std::cout << HEADER_RX"Closing capture file..." << std::endl; -        delete params.capture_file; -        params.capture_file = NULL; +        std::cout << HEADER_RX"Closing capture files..." << std::endl; + +        for (size_t n = 0; n < params.capture_files.size(); ++n) +            delete params.capture_files[n]; + +        params.capture_files.clear();      }      l.lock(); @@ -628,7 +681,7 @@ void benchmark_tx_rate(      size_t total_packet_count = (total_length / max_samps_per_packet) + ((total_length % max_samps_per_packet) ? 1 : 0);      if ((params.use_tx_eob) && (params.tx_time_between_bursts > 0))          packet_time += uhd::time_spec_t(params.tx_time_between_bursts); -    size_t max_late_count = (size_t)(rate / (double)packet_time.to_ticks(rate)) * total_packet_count; +    size_t max_late_count = (size_t)(rate / (double)packet_time.to_ticks(rate)) * total_packet_count * tx_stream->get_num_channels();   // Also need to take into account number of radios      // Will be much higher L values (e.g. 31K) on e.g. B200 when entire TX pipeline is full of late packets (large size due to total TX buffering throughout transport & DSP) @@ -1139,7 +1192,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){          ("progress-interval", po::value<double>(&progress_interval)->default_value(progress_interval), "seconds between bandwidth updates (0 disables)")          ("rx-progress-interval", po::value<double>(&rx_progress_interval), "seconds between RX bandwidth updates (0 disables)")          ("tx-progress-interval", po::value<double>(&tx_progress_interval), "seconds between TX bandwidth updates (0 disables)") -        ("tx-offset", po::value<double>(&tx_time_offset), "seconds that TX should be in front of RX when following") +        ("tx-offset", po::value<double>(&tx_time_offset)->default_value(0.0), "seconds that TX should be in front of RX when following")          ("tx-length", po::value<size_t>(&tx_burst_length)->default_value(0), "TX burst length in samples (0: maximum packet size)")          ("tx-flush", po::value<size_t>(&tx_flush_length)->default_value(0), "samples to flush TX with after burst")          ("tx-burst-separation", po::value<double>(&tx_time_between_bursts), "seconds between TX bursts") @@ -1177,6 +1230,10 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){          ("recover-late", "recover from excessive late TX packets")          ("disable-async", "disable the async message thread")          ("interleave-rx-file-samples", "interleave individual samples (default is interleaving buffers)") +        ("ignore-late-start", "continue receiving even if stream command was late") +        ("ignore-bad-packets", "continue receiving after a bad packet") +        ("ignore-timeout", "continue receiving after timeout") +        ("ignore-unexpected", "continue receiving after unexpected error")          // record TX/RX times          // Optional interruption          // simulate u / o at random / pulses @@ -1234,6 +1291,10 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){      bool recover_late = (vm.count("recover-late") > 0);      bool enable_async = (vm.count("disable-async") == 0);      bool interleave_rx_file_samples = (vm.count("interleave-rx-file-samples") > 0); +    bool ignore_late_start = (vm.count("ignore-late-start") > 0); +    bool ignore_bad_packets = (vm.count("ignore-bad-packets") > 0); +    bool ignore_timeout = (vm.count("ignore-timeout") > 0); +    bool ignore_unexpected_error = (vm.count("ignore-unexpected") > 0);      boost::posix_time::time_duration interrupt_timeout_duration(boost::posix_time::seconds(long(interrupt_timeout)) + boost::posix_time::microseconds(long((interrupt_timeout - floor(interrupt_timeout))*1e6))); @@ -1273,6 +1334,36 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){              return ~0;          } +        bool rx_filename_has_format = false; +        if (rx_channel_nums.size() > 0) +        { +            std::string str0; +            try +            { +                str0 = boost::str(boost::format(rx_file) % 0); +                rx_filename_has_format = true; +            } +            catch (...) +            { +            } + +            bool format_different = false; +            try +            { +                std::string str1(boost::str(boost::format(rx_file) % 1)); +                format_different = (str0 != str1); +            } +            catch (...) +            { +            } + +            if ((rx_filename_has_format) && (format_different == false)) +            { +                std::cout << HEADER_ERROR "Multi-channel RX capture filename format did not produce unique names" << std::endl; +                return ~0; +            } +        } +          if ((tx_rx_sync) || (tx_follows_rx))          {              if (tx_channel_nums.size() == 0) @@ -1462,11 +1553,33 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){                      }                  } -                rx_params.capture_file = NULL;                  if (rx_file.empty() == false)                  { -                    std::cout << boost::format(HEADER_RX"Capturing to \"%s\"") % rx_file << std::endl; -                    rx_params.capture_file = new std::ofstream(rx_file.c_str(), std::ios::out); +                    if (rx_filename_has_format == false) +                    { +                        if (rx_stream->get_num_channels() == 1) +                        { +                            std::cout << boost::format(HEADER_RX"Capturing single channel to \"%s\"") % rx_file << std::endl; +                        } +                        else +                        { +                            if (interleave_rx_file_samples) +                                std::cout << boost::format(HEADER_RX"Capturing all %d channels as interleaved samples to \"%s\"") % rx_stream->get_num_channels() % rx_file << std::endl; +                            else +                                std::cout << boost::format(HEADER_RX"Capturing all %d channels as interleaved buffers to \"%s\"") % rx_stream->get_num_channels() % rx_file << std::endl; +                        } + +                        rx_params.capture_files.push_back(new std::ofstream(rx_file.c_str(), std::ios::out)); +                    } +                    else +                    { +                        for (size_t n = 0; n < rx_stream->get_num_channels(); ++n) +                        { +                            std::cout << boost::format(HEADER_RX"Capturing channel %d to \"%s\"") % n % (boost::str(boost::format(rx_file) % n)) << std::endl; +                            std::string rx_file_name(boost::str(boost::format(rx_file) % n)); +                            rx_params.capture_files.push_back(new std::ofstream(rx_file_name.c_str(), std::ios::out)); +                        } +                    }                  }                  std::cout << boost::format( @@ -1488,6 +1601,10 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){                  rx_params.rx_freq_delay = rx_freq_delay;                  rx_params.rx_lo_offset = rx_lo_offset;                  rx_params.interleave_rx_file_samples = interleave_rx_file_samples; +                rx_params.ignore_late_start = ignore_late_start; +                rx_params.ignore_bad_packets = ignore_bad_packets; +                rx_params.ignore_timeout = ignore_timeout; +                rx_params.ignore_unexpected_error = ignore_unexpected_error;                  thread_group.create_thread(boost::bind(                      &benchmark_rx_rate,  | 
