From 7ff2be689d1211582968cb016c53a943903f8ffa Mon Sep 17 00:00:00 2001 From: Jonathan Hanks <jonathan.hanks@ligo.org> Date: Fri, 2 Aug 2019 18:27:24 -0700 Subject: [PATCH] Add another debug tool, fe_check. This tool can scan a rmIpcStr based mbuf continually and print some information out. It was written to help debug fe or fe_stream_test issues. --- src/fe_stream_test/CMakeLists.txt | 6 + src/fe_stream_test/fe_check.cc | 236 ++++++++++++++++++++++++++++++ 2 files changed, 242 insertions(+) create mode 100644 src/fe_stream_test/fe_check.cc diff --git a/src/fe_stream_test/CMakeLists.txt b/src/fe_stream_test/CMakeLists.txt index 1860b4853..ccbe6c8de 100644 --- a/src/fe_stream_test/CMakeLists.txt +++ b/src/fe_stream_test/CMakeLists.txt @@ -22,6 +22,12 @@ target_link_libraries(fe_stream_check rt driver::shmem) +add_executable(fe_check fe_check.cc) +target_link_libraries(fe_check + PRIVATE + rt + driver::shmem) + if (${libNDS2Client_FOUND}) # add_executable(fe_stream_check diff --git a/src/fe_stream_test/fe_check.cc b/src/fe_stream_test/fe_check.cc new file mode 100644 index 000000000..305e1e9d6 --- /dev/null +++ b/src/fe_stream_test/fe_check.cc @@ -0,0 +1,236 @@ +// +// Created by jonathan.hanks on 8/2/19. +// +#include <algorithm> +#include <deque> +#include <iostream> +#include <iterator> +#include <string> +#include <vector> + +#include <unistd.h> + +#include <drv/shmem.h> +#include "daqmap.h" + +struct model_stats { + unsigned int dcuid; + unsigned int cycle; + unsigned int gps_sec; + unsigned int gps_nsec; + unsigned int size; +}; + +struct model +{ + model(): name(""), mbuf_name(""), data(0) {} + explicit model(const std::string& mod_name): name(mod_name), + mbuf_name(mod_name + "_daq"), data(0) {} + model(const model& other): name(other.name), + mbuf_name(other.mbuf_name), data(other.data) {} + + model& operator=(const model& other) + { + name = other.name; + mbuf_name = other.mbuf_name; + data = other.data; + } + + volatile char* + open() + { + if (data) + { + return data; + } + if (mbuf_name.empty()) + { + return 0; + } + data = (volatile char*)shmem_open_segment(mbuf_name.c_str(), 64*1024*1024); + return data; + } + + std::string name; + std::string mbuf_name; + volatile char* data; +}; + +struct config_t { + config_t(): models(), + all_samples(false), + show_help(false), + error_message("") + {} + + void + set_error(const char* msg) + { + show_help = true; + error_message = msg; + } + + void + consistency_check() + { + if (models.empty()) + { + set_error("You must specify at least one model"); + } + } + + std::vector<std::string> models; + bool all_samples; + bool show_help; + std::string error_message; +}; + +config_t +parse_args(int argc, char* argv[]) +{ + config_t opts; + + std::deque<std::string> args; + for (int i = 1; i < argc; ++i) + { + args.push_back(argv[i]); + } + while (!args.empty()) + { + std::string arg = args.front(); + args.pop_front(); + if (arg == "-h" || arg == "--help") + { + opts.show_help = true; + break; + } + else if (arg == "-s") + { + if (args.empty()) + { + opts.set_error("You must specify a model name when using -s"); + break; + } + opts.models.push_back(args.front()); + args.pop_front(); + } + else if (arg == "-a") + { + opts.all_samples = true; + } + else + { + opts.set_error("Unknown option"); + } + } + opts.consistency_check(); + return opts; +} + +void +usage(const char* progname) +{ + std::cout << "Usage:\n\t" << progname << " [options]\n\n"; + std::cout << "Where options is one of:\n"; + std::cout << "-h,--help\t\tThis help\n"; + std::cout << "-s [model]\t\tSpecify a model\n"; + std::cout << "-a\t\tTry to sample all cycles\n"; + std::cout << "\nMore than one instance of -s may be used.\n"; +} + +model +to_model(const std::string& s) +{ + model m(s); + m.open(); + return m; +} + +model_stats +extract_stats(const model& m) +{ + model_stats stats; + + volatile rmIpcStr* ipc = (volatile rmIpcStr*)(m.data); + + stats.dcuid = ipc->dcuId; + stats.cycle = ipc->cycle; + if (stats.cycle >= 16) + { + stats.cycle = 0xff; + stats.size = 0; + stats.gps_sec = 0; + stats.gps_nsec = 0; + } + else + { + stats.size = ipc->bp[stats.cycle].crc; + stats.gps_sec = ipc->bp[stats.cycle].timeSec; + stats.gps_nsec = ipc->bp[stats.cycle].timeNSec; + } + return stats; +} + +void +wait_for_cycle(int target, std::vector<model>& models) +{ + while (true) + { + for (int i = 0; i < models.size(); ++i) + { + volatile rmIpcStr* ipc = (volatile rmIpcStr*)(models[i].data); + if (ipc->cycle == target) + { + return; + } + } + usleep(5000); + } +} + + +int +main(int argc, char* argv[]) +{ + config_t opts = parse_args(argc, argv); + if (opts.show_help) + { + usage(argv[0]); + if (!opts.error_message.empty()) + { + std::cout << opts.error_message << "\n"; + return 1; + } + } + + std::vector<model> models; + std::transform(opts.models.begin(), opts.models.end(), std::back_inserter(models), to_model); + + std::vector<model_stats> stats(models.size()); + + int next_cycle = 0; + while (true) + { + if (opts.all_samples) + { + wait_for_cycle(next_cycle, models); + usleep(2000); + next_cycle++; + next_cycle %= 16; + } + else + { + sleep(1); + } + + std::transform(models.begin(), models.end(), stats.begin(), extract_stats); + for (int i = 0; i < models.size(); ++i) + { + model& m = models[i]; + model_stats& s = stats[i]; + std::cout << m.name << ": dcuid: " << s.dcuid << " cycle: " << s.cycle; + std::cout << " size: " << s.size << " gps: " << s.gps_sec << ":" << s.gps_nsec << "\n"; + } + std::cout << "\n"; + } +} \ No newline at end of file -- GitLab