PothosUtilRunTopology.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. // Copyright (c) 2014-2017 Josh Blum
  2. // SPDX-License-Identifier: BSL-1.0
  3. #include "PothosUtil.hpp"
  4. #include <Pothos/Framework.hpp>
  5. #include <Pothos/Exception.hpp>
  6. #include <Poco/Path.h>
  7. #include <fstream>
  8. #include <thread>
  9. #include <iostream>
  10. #include <json.hpp>
  11. using json = nlohmann::json;
  12. void PothosUtilBase::runTopology(void)
  13. {
  14. Pothos::ScopedInit init;
  15. //sanity check the file
  16. const auto path = this->config().getString("inputFile");
  17. if (Poco::Path(path).getExtension() == "pothos" or
  18. Poco::Path(path).getExtension() == "pth")
  19. {
  20. throw Pothos::DataFormatException("Cannot load "+path+"!\n"
  21. "Please export the design to the JSON topology format.");
  22. }
  23. std::ifstream ifs(Poco::Path::expand(path));
  24. if (not ifs) throw Pothos::FileException("Can't open "+path+" for reading!");
  25. //parse the json formatted string into a JSON object
  26. json topObj;
  27. try
  28. {
  29. topObj = json::parse(ifs);
  30. }
  31. catch (const std::exception &ex)
  32. {
  33. throw Pothos::DataFormatException(ex.what());
  34. }
  35. //apply the global variable overlays
  36. if (topObj.count("globals") == 0) topObj["globals"] = json::array();
  37. auto &globalsArray = topObj["globals"];
  38. for (const auto &pair : _vars)
  39. {
  40. //look for a match in the existing globals and override its value
  41. for (auto &globalVarObj : globalsArray)
  42. {
  43. if (globalVarObj.value<std::string>("name", "") == pair.first)
  44. {
  45. globalVarObj["value"] = pair.second;
  46. goto nextVar;
  47. }
  48. }
  49. //otherwise add to the end of the globals array
  50. {
  51. std::cout << "add name " << pair.first << std::endl;
  52. json globalVarObj;
  53. globalVarObj["name"] = pair.first;
  54. globalVarObj["value"] = pair.second;
  55. globalsArray.push_back(globalVarObj);
  56. }
  57. nextVar: continue;
  58. }
  59. //create the topology from the JSON string
  60. std::cout << ">>> Create Topology: " << path << std::endl;
  61. auto topology = Pothos::Topology::make(topObj.dump());
  62. //commit the topology and wait for specified time for CTRL+C
  63. if (this->config().has("idleTime"))
  64. {
  65. const auto idleTime = this->config().getDouble("idleTime");
  66. double timeout = 0.0;
  67. std::string timeoutMsg = "no timeout";
  68. if (this->config().has("runDuration"))
  69. {
  70. timeout = this->config().getDouble("runDuration");
  71. timeoutMsg = "timeout " + std::to_string(timeout) + " seconds";
  72. }
  73. std::cout << ">>> Running topology until idle with " << timeoutMsg << std::endl;
  74. topology->commit();
  75. if (not topology->waitInactive(idleTime, timeout))
  76. {
  77. throw Pothos::RuntimeException("Topology::waitInactive() reached timeout");
  78. }
  79. }
  80. else if (this->config().has("runDuration"))
  81. {
  82. const auto runDuration = this->config().getDouble("runDuration");
  83. std::cout << ">>> Running topology for " << runDuration << " seconds" << std::endl;
  84. topology->commit();
  85. std::this_thread::sleep_for(std::chrono::milliseconds(long(runDuration*1000)));
  86. }
  87. else
  88. {
  89. std::cout << ">>> Running topology, press CTRL+C to exit" << std::endl;
  90. topology->commit();
  91. this->waitForTerminationRequest();
  92. }
  93. //dump the stats to file if specified
  94. if (this->config().has("outputFile"))
  95. {
  96. const auto statsFile = this->config().getString("outputFile");
  97. std::cout << ">>> Dumping stats: " << statsFile << std::endl;
  98. std::ofstream ofs(Poco::Path::expand(statsFile));
  99. ofs << topology->queryJSONStats() << std::endl;
  100. }
  101. }