Commit 01e548d4 authored by Simon Spannagel's avatar Simon Spannagel
Browse files

CMake/Modules: allow specifying type on which module operates

parent 90f2fdd2
......@@ -77,6 +77,17 @@ MACRO(corryvreckan_detector_module name)
TARGET_COMPILE_DEFINITIONS(${${name}} PRIVATE CORRYVRECKAN_MODULE_DUT=0)
ENDMACRO()
# Append list of possible detector types as compile definition
MACRO(corryvreckan_detector_type name)
SET(extra_macro_args ${ARGN})
LIST(LENGTH extra_macro_args num_extra_args)
IF(${num_extra_args} GREATER 0)
STRING(REPLACE ";" "," TYPESLIST "${extra_macro_args}")
TARGET_COMPILE_DEFINITIONS(${name} PRIVATE CORRYVRECKAN_DETECTOR_TYPE=${TYPESLIST})
ENDIF()
ENDMACRO()
# Put this at the start of every detector module
MACRO(corryvreckan_dut_module name)
_corryvreckan_module_define_common(${name} ${ARGN})
......
......@@ -27,6 +27,7 @@
#define CORRYVRECKAN_GENERATOR_FUNCTION "corryvreckan_module_generator"
#define CORRYVRECKAN_GLOBAL_FUNCTION "corryvreckan_module_is_global"
#define CORRYVRECKAN_DUT_FUNCTION "corryvreckan_module_is_dut"
#define CORRYVRECKAN_TYPE_FUNCTION "corryvreckan_detector_types"
using namespace corryvreckan;
......@@ -278,26 +279,19 @@ void ModuleManager::load_modules() {
loaded_libraries_[lib_name] = lib;
// Check if this module is produced once, or once per detector
bool global = true;
bool dut_only = false;
void* globalFunction = dlsym(loaded_libraries_[lib_name], CORRYVRECKAN_GLOBAL_FUNCTION);
void* dutFunction = dlsym(loaded_libraries_[lib_name], CORRYVRECKAN_DUT_FUNCTION);
void* typeFunction = dlsym(loaded_libraries_[lib_name], CORRYVRECKAN_TYPE_FUNCTION);
// If the global function was not found, throw an error
if(globalFunction == nullptr) {
if(globalFunction == nullptr || dutFunction == nullptr || typeFunction == nullptr) {
LOG(ERROR) << "Module library is invalid or outdated: required interface function not found!";
throw corryvreckan::DynamicLibraryError(config.getName());
} else {
global = reinterpret_cast<bool (*)()>(globalFunction)(); // NOLINT
}
// If the DUT function was not found, throw an error
if(dutFunction == nullptr) {
LOG(ERROR) << "Module library is invalid or outdated: required interface function not found!";
throw corryvreckan::DynamicLibraryError(config.getName());
} else {
dut_only = reinterpret_cast<bool (*)()>(dutFunction)(); // NOLINT
}
bool global = reinterpret_cast<bool (*)()>(globalFunction)(); // NOLINT
bool dut_only = reinterpret_cast<bool (*)()>(dutFunction)(); // NOLINT
std::vector<std::string> types = reinterpret_cast<std::vector<std::string> (*)()>(typeFunction)(); // NOLINT
// Apply the module specific options to the module configuration
conf_mgr_->applyOptions(config.getName(), config);
......@@ -311,11 +305,11 @@ void ModuleManager::load_modules() {
// Create the modules from the library
if(global) {
auto module = create_unique_module(loaded_libraries_[lib_name], config);
auto module = create_unique_module(loaded_libraries_[lib_name], config, types);
m_modules.push_back(module.second);
m_modules.back()->set_identifier(module.first);
} else {
auto modules = create_detector_modules(loaded_libraries_[lib_name], config, dut_only);
auto modules = create_detector_modules(loaded_libraries_[lib_name], config, dut_only, types);
for(const auto& mod : modules) {
m_modules.push_back(mod.second);
m_modules.back()->set_identifier(mod.first);
......@@ -330,7 +324,8 @@ void ModuleManager::load_modules() {
LOG_PROGRESS(STATUS, "MOD_LOAD_LOOP") << "Loaded " << configs.size() << " modules";
}
std::pair<ModuleIdentifier, Module*> ModuleManager::create_unique_module(void* library, Configuration config) {
std::pair<ModuleIdentifier, Module*>
ModuleManager::create_unique_module(void* library, Configuration config, std::vector<std::string>) {
// Create the identifier
ModuleIdentifier identifier(config.getName(), "", 0);
......@@ -396,7 +391,7 @@ std::pair<ModuleIdentifier, Module*> ModuleManager::create_unique_module(void* l
}
std::vector<std::pair<ModuleIdentifier, Module*>>
ModuleManager::create_detector_modules(void* library, Configuration config, bool dut_only) {
ModuleManager::create_detector_modules(void* library, Configuration config, bool dut_only, std::vector<std::string> types) {
LOG(TRACE) << "Creating instantiations for module " << config.getName() << ", using generator \""
<< CORRYVRECKAN_GENERATOR_FUNCTION << "\"";
......@@ -449,6 +444,14 @@ ModuleManager::create_detector_modules(void* library, Configuration config, bool
LOG(TRACE) << "Skipping instantiation \"" << identifier.getUniqueName() << "\", detector is no DUT";
continue;
}
// Do not instantiate module if detector type is not mentioned as supported:
auto detectortype = detector->type();
std::transform(detectortype.begin(), detectortype.end(), detectortype.begin(), ::tolower);
if(!types.empty() && std::find(types.begin(), types.end(), detectortype) == types.end()) {
LOG(TRACE) << "Skipping instantiation \"" << identifier.getUniqueName() << "\", detector type mismatch";
continue;
}
LOG(TRACE) << "Creating instantiation \"" << identifier.getUniqueName() << "\"";
// Set the log section header
......
......@@ -78,9 +78,10 @@ namespace corryvreckan {
std::atomic<bool> m_terminate;
std::unique_ptr<corryvreckan::ConfigManager> conf_mgr_;
std::pair<ModuleIdentifier, Module*> create_unique_module(void* library, corryvreckan::Configuration config);
std::pair<ModuleIdentifier, Module*>
create_unique_module(void* library, corryvreckan::Configuration config, std::vector<std::string> types);
std::vector<std::pair<ModuleIdentifier, Module*>>
create_detector_modules(void* library, Configuration config, bool dut_only);
create_detector_modules(void* library, Configuration config, bool dut_only, std::vector<std::string> types);
std::tuple<LogLevel, LogFormat> set_module_before(const std::string&, const Configuration& config);
void set_module_after(std::tuple<LogLevel, LogFormat> prev);
......
......@@ -18,7 +18,11 @@
#error "This header should only be automatically included during the build"
#endif
#define XSTR(...) #__VA_ARGS__
#define STR(...) XSTR(__VA_ARGS__)
#include <memory>
#include <sstream>
#include <utility>
#include "core/config/Configuration.hpp"
......@@ -43,6 +47,28 @@ namespace corryvreckan {
*/
bool corryvreckan_module_is_dut();
/**
* @brief Returns a list of detector types this module can run on
*
* Used by the ModuleManager to determine if module should instantiate for a given detector
*/
std::vector<std::string> corryvreckan_detector_types();
std::vector<std::string> corryvreckan_detector_types() {
#if defined(CORRYVRECKAN_DETECTOR_TYPE) || defined(DOXYGEN)
auto tokenstream = std::stringstream(STR(CORRYVRECKAN_DETECTOR_TYPE));
std::vector<std::string> tokens;
while(tokenstream.good()) {
std::string token;
getline(tokenstream, token, ',');
std::transform(token.begin(), token.end(), token.begin(), ::tolower);
tokens.push_back(token);
}
return tokens;
#else
return std::vector<std::string>();
#endif
}
#if CORRYVRECKAN_MODULE_GLOBAL || defined(DOXYGEN)
/**
* @brief Instantiates an unique module
......@@ -62,7 +88,6 @@ namespace corryvreckan {
bool corryvreckan_module_is_global() { return true; }
// Globale modules cannot be DUT modules
bool corryvreckan_module_is_dut() { return false; }
#endif
#if(!CORRYVRECKAN_MODULE_GLOBAL && !CORRYVRECKAN_MODULE_DUT) || defined(DOXYGEN)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment