Commit 50107d0d authored by Joerg Stelzer's avatar Joerg Stelzer Committed by Vakhtang Tsulaia
Browse files

Rework topo algo parameter specification and access

* Also unify input and output
* Fix float values in some parameters (L1Topo expects int here)
parent 7e7fea0e
......@@ -106,7 +106,7 @@ namespace TrigConf {
*/
bool hasAttribute(const std::string & key) const;
/** Check for attribute
/** Check if child exists
* @param path The path to the child, relative to the current one in form "path.to.child"
* @return true if path exists
*/
......
......@@ -66,6 +66,9 @@ namespace TrigConf {
/** Accessor to the connector type */
ConnectorType type() const;
/** names of all trigger lines */
std::vector<std::string> triggerLineNames() const;
/** Accessor to the triggerlines on the connector
*
* For electrical connectors from the L1Topo boards a triggerline vector holds up to 16 signals, which come from
......@@ -91,6 +94,8 @@ namespace TrigConf {
ConnectorType m_type;
std::vector<TrigConf::TriggerLine> m_triggerLines[2][2];
std::map<std::string, TrigConf::TriggerLine*> m_lineByName;
std::size_t m_maxFpga{1};
std::size_t m_maxClock{1};
bool m_isLegacy;
};
......
......@@ -89,12 +89,35 @@ namespace TrigConf {
/** Access to extra info for threshold types */
const L1ThrExtraInfo & thrExtraInfo() const;
/** Access to topo algorithm names
* @param category must be one of "TOPO", "MUTOPO", "MULTTOPO", or "R2TOPO"
*
* TOPO ... new topo algorithms,
* R2TOPO ... Run-2 topo algorithms
* MUTOPO ... MUCTPI topo algorithms
* MULTTOPO ... multiplicity algorithms
*/
std::vector<std::string> topoAlgorithmNames(const std::string & category) const;
/** Access to topo algoritm output names */
std::vector<std::string> topoAlgorithmOutputNames(const std::string & category) const;
/** Access to topo algorithm by name */
const TrigConf::L1TopoAlgorithm & algorithm(const std::string & algoName) const;
const TrigConf::L1TopoAlgorithm & algorithm(const std::string & algoName, const std::string & category) const;
/** Access to topo algorithm by output */
const TrigConf::L1TopoAlgorithm & algorithmFromOutput(const std::string & outputName) const;
/** Access to topo algorithm by name of triggerline as given in topo connector specification
* @param triggerlineName string name of the triggerline
* @return reference to the algorithm that produces this output
*
* The name of the triggerline starts with "TOPO_", "MUTOPO_", or "R2TOPO_", except in the case of multiplicity output lines which are just the threshold name
*/
const TrigConf::L1TopoAlgorithm & algorithmFromTriggerline(const std::string & triggerlineName) const;
/** Access to topo algorithm by name of the output as given in the algorithm definition
* @param fullOutputName string name of the output prefixed with the category, e.g. ("HT150-J20s5.ETA31","TOPO") or ("0INVM9-EM7ab-EMab","R2TOPO")
* @return reference to the algorithm that produces this output
*/
const TrigConf::L1TopoAlgorithm & algorithmFromOutput(const std::string & bareOutputName, const std::string & category) const;
/** Access to boards by name */
const TrigConf::L1Board & board(const std::string & boardName) const;
......@@ -109,6 +132,8 @@ namespace TrigConf {
/** Connector names */
std::vector<std::string> connectorNames() const;
/** Name of connector from name of threshold or triggerline */
const std::string & connectorNameFromThreshold(const std::string & thresholdName) const;
/** print overview of L1 Menu */
void printMenu(bool full = false) const;
......@@ -121,19 +146,25 @@ namespace TrigConf {
/** the supermasterkey */
unsigned int m_smk {0};
/** connector by name */
std::map<std::string, TrigConf::L1Connector> m_connectors{};
/** connector name by threshold name */
std::map<std::string, std::string> m_threshold2ConnectorName{};
/** board by name */
std::map<std::string, TrigConf::L1Board> m_boards{};
/** threshold maps */
std::map<std::string, std::vector<std::shared_ptr<TrigConf::L1Threshold>>> m_thresholdsByType{};
std::map<std::string, std::shared_ptr<TrigConf::L1Threshold>> m_thresholdsByName{};
TrigConf::L1ThrExtraInfo m_thrExtraInfo;
std::map<std::string, std::vector<TrigConf::L1TopoAlgorithm>> m_algorithmsByType{};
std::map<std::string, TrigConf::L1TopoAlgorithm*> m_algorithmsByName{};
std::map<std::string, TrigConf::L1TopoAlgorithm*> m_algorithmsByOutput{};
/** algorithm maps */
std::map<std::string, std::vector<TrigConf::L1TopoAlgorithm>> m_algorithmsByCategory{}; // primary set of vectors of algos, one per category (TOPO, R2TOPO, MUTOPO, MULTTOPO)
std::map<std::string, std::map<std::string, TrigConf::L1TopoAlgorithm*>> m_algorithmsByName{}; // map from category and algorithm name to algorithm
std::map<std::string, std::map<std::string, TrigConf::L1TopoAlgorithm*>> m_algorithmsByOutput{}; // map from category and output name to algorithm
};
......
......@@ -19,10 +19,18 @@ namespace TrigConf {
class L1TopoAlgorithm final : public DataStructure {
public:
enum class AlgorithmType { SORTING, DECISION, MULTIPLICITY, INIT };
enum class AlgorithmType { SORTING, DECISION, MULTIPLICITY, UNKNOWN };
struct VariableParameter {
VariableParameter(const std::string & _name, int _value, unsigned int _selection)
: name(_name), value(_value), selection(_selection) {}
std::string name{""};
int value{0};
unsigned int selection{0};
};
/** Constructor */
L1TopoAlgorithm();
L1TopoAlgorithm() = default;
L1TopoAlgorithm(const L1TopoAlgorithm &) = delete;
L1TopoAlgorithm& operator=(const L1TopoAlgorithm&) = delete;
......@@ -31,7 +39,7 @@ namespace TrigConf {
/** Constructor initialized with configuration data
* @param data The data containing the L1Topo menu
*/
L1TopoAlgorithm(const std::string & algoName, AlgorithmType algoType, const ptree & data);
L1TopoAlgorithm(const std::string & algoName, AlgorithmType algoType, const std::string & algoCategory, const ptree & data);
/** Destructor */
~L1TopoAlgorithm();
......@@ -43,30 +51,52 @@ namespace TrigConf {
AlgorithmType type() const;
const std::string & category() const;
/** Accessor to algorithm class type */
const std::string & klass() const;
/** Accessor to list of input data collections */
std::vector<DataStructure> inputs() const;
/** Accessor to input collections
* Sorting and Multiplicity algorithms have only one input
*/
const std::vector<std::string> & inputs() const;
/** Accessor to output collection */
/** Accessor to output collections
* Sorting and Multiplicity algorithms have only one output
*/
const std::vector<std::string> & outputs() const;
std::vector<std::string> fullOutputs() const;
/** Accessors to generic parameters */
DataStructure generics() const;
/** Accessor to generic parameters */
std::vector<DataStructure> generics() const;
std::string genericParameter(const std::string & parName) const;
template<class T>
T genericParameter(const std::string & parName) const {
return getAttribute<T>("fixedParameters.generics." + parName + ".value");
}
/** Accessor to register parameters which can change for each algorithm instance */
std::vector<DataStructure> parameters() const;
const std::vector<VariableParameter> & parameters() const;
/** print main info */
void print(std::ostream & os = std::cout) const override;
private:
/** Update the internal data after modification of the data object */
virtual void update() override;
AlgorithmType m_type{ AlgorithmType::INIT };
AlgorithmType m_type{ AlgorithmType::UNKNOWN };
std::string m_category{};
std::vector<std::string> m_inputs{};
std::vector<std::string> m_outputs{};
std::vector<VariableParameter> m_parameters;
};
}
......
......@@ -42,10 +42,12 @@ TrigConf::L1Connector::update()
}
// triggerlines
size_t loopsize = (m_type == ConnectorType::ELECTRICAL) ? 2 : 1;
if(m_type == ConnectorType::ELECTRICAL) {
m_maxFpga = m_maxClock = 2;
}
for( size_t fpga = 0; fpga < loopsize; ++fpga ) {
for( size_t clock = 0; clock < loopsize; ++clock ) {
for( size_t fpga = 0; fpga < m_maxFpga; ++fpga ) {
for( size_t clock = 0; clock < m_maxClock; ++clock ) {
std::string path = "triggerlines";
if( m_type == ConnectorType::ELECTRICAL ) {
path += ".fpga";
......@@ -78,7 +80,27 @@ TrigConf::L1Connector::type() const
std::size_t
TrigConf::L1Connector::size() const
{
return m_triggerLines[0][0].size() + m_triggerLines[0][1].size() + m_triggerLines[1][0].size() + m_triggerLines[1][1].size();
size_t nlines{0};
for( size_t fpga = 0; fpga<m_maxFpga; ++fpga) {
for( size_t clock = 0; clock<m_maxClock; ++clock) {
nlines += m_triggerLines[fpga][clock].size();
}
}
return nlines;
}
std::vector<std::string>
TrigConf::L1Connector::triggerLineNames() const
{
std::vector<std::string> tln{};
for( size_t fpga = 0; fpga<m_maxFpga; ++fpga) {
for( size_t clock = 0; clock<m_maxClock; ++clock) {
for( auto & tl : m_triggerLines[fpga][clock] ) {
tln.emplace_back(tl.name());
}
}
}
return tln;
}
const std::vector<TrigConf::TriggerLine> &
......
......@@ -65,37 +65,46 @@ TrigConf::L1Menu::update()
// connectors
for( auto & conn : data().get_child( "connectors" ) ) {
m_connectors.emplace( std::piecewise_construct,
std::forward_as_tuple(conn.first),
std::forward_as_tuple(conn.first, conn.second) );
auto res = m_connectors.emplace( std::piecewise_construct,
std::forward_as_tuple(conn.first),
std::forward_as_tuple(conn.first, conn.second) );
for( auto & tl : res.first->second.triggerLineNames() ) {
m_threshold2ConnectorName.emplace( std::piecewise_construct,
std::forward_as_tuple(tl),
std::forward_as_tuple(conn.first));
}
}
// algorithms
for( const std::string & path : { "TOPO", "MULTTOPO", "MUTOPO", "R2TOPO" } ) {
auto & v = m_algorithmsByType[path] = std::vector<TrigConf::L1TopoAlgorithm>();
if(path == "MULTTOPO") {
for( auto & alg : data().get_child( "topoAlgorithms." + path + ".multiplicityAlgorithms" ) ) {
v.emplace_back( alg.first, L1TopoAlgorithm::AlgorithmType::MULTIPLICITY, alg.second );
for( const std::string & algoCategory : { "TOPO", "MULTTOPO", "MUTOPO", "R2TOPO" } ) {
auto & v = m_algorithmsByCategory[algoCategory] = std::vector<TrigConf::L1TopoAlgorithm>();
if(algoCategory == "MULTTOPO") {
for( auto & alg : data().get_child( "topoAlgorithms." + algoCategory + ".multiplicityAlgorithms" ) ) {
v.emplace_back( alg.first, L1TopoAlgorithm::AlgorithmType::MULTIPLICITY, algoCategory, alg.second );
}
} else {
for( L1TopoAlgorithm::AlgorithmType algoType : { L1TopoAlgorithm::AlgorithmType::DECISION, L1TopoAlgorithm::AlgorithmType::SORTING } ) {
std::string subpath = "topoAlgorithms." + path + (algoType==L1TopoAlgorithm::AlgorithmType::DECISION ? ".decisionAlgorithms" : ".sortingAlgorithms" );
std::string subpath = "topoAlgorithms." + algoCategory + (algoType==L1TopoAlgorithm::AlgorithmType::DECISION ? ".decisionAlgorithms" : ".sortingAlgorithms" );
for( auto & algorithm : data().get_child( subpath ) ) {
v.emplace_back( algorithm.first, algoType, algorithm.second );
v.emplace_back( algorithm.first, algoType, algoCategory, algorithm.second );
}
}
}
for( auto & algo : v ) {
m_algorithmsByName[ algo.name() ] = & algo;
for( auto & algo : v ) {
if( m_algorithmsByName[algoCategory].count(algo.name()) > 0 ) {
std::cerr << "ERROR : Topo algorithm with name " << algo.name() << " and of type " << algoCategory << " already exists" << std::endl;
throw std::runtime_error("Found duplicate topo algorithm name " + algo.name() + " of type " + algoCategory);
}
m_algorithmsByName[ algoCategory ][ algo.name() ] = & algo;
for( const std::string & output : algo.outputs() ) {
// multiplicity outputs (legacy and from multiplicity L1Topo) just have the name of the threshold
// outputs from topo algorithms carry the name of the topo board type (TOPO, R2TOPO, MUTOPO) as it is not guarateed that
// legacy and new topo algorithms define different outputs
auto key = (path == "MULTTOPO") ? output : (path + "_" + output);
m_algorithmsByOutput[key] = & algo;
if( m_algorithmsByOutput[algoCategory].count(output) > 0 ) {
std::cerr << "ERROR : Topo algorithm output " << output << " already exists" << std::endl;
throw std::runtime_error("Found duplicate topo algorithm output " + output + " of type " + algoCategory);
}
m_algorithmsByOutput[algoCategory][output] = & algo;
}
}
}
}
......@@ -223,6 +232,18 @@ TrigConf::L1Menu::thrExtraInfo() const
return m_thrExtraInfo;
}
const std::string &
TrigConf::L1Menu::connectorNameFromThreshold(const std::string & thresholdName) const
{
try {
return m_threshold2ConnectorName.at(thresholdName);
}
catch(...) {
std::cerr << "Threshold '" << thresholdName << "' not defined as triggerline in the L1 menu" << std::endl;
throw;
}
}
std::vector<std::string>
TrigConf::L1Menu::connectorNames() const {
std::vector<std::string> connNames;
......@@ -244,26 +265,80 @@ TrigConf::L1Menu::connector(const std::string & connectorName) const {
}
}
/** Access to topo algorithm names */
std::vector<std::string>
TrigConf::L1Menu::topoAlgorithmNames(const std::string & category) const
{
std::vector<std::string> algoNames;
try {
for(auto & entry : m_algorithmsByName.at(category) ) {
algoNames.push_back(entry.first);
}
}
catch(std::exception & ex) {
std::cerr << "No algorithm category '" << category << "' defined in the L1 menu" << std::endl;
throw;
}
return algoNames;
}
/** Access to topo algoritm output names */
std::vector<std::string>
TrigConf::L1Menu::topoAlgorithmOutputNames(const std::string & category) const
{
std::vector<std::string> outputNames;
try {
for(auto & entry : m_algorithmsByOutput.at(category) ) {
outputNames.push_back(entry.first);
}
}
catch(std::exception & ex) {
std::cerr << "No algorithm category '" << category << "' defined in the L1 menu" << std::endl;
throw;
}
return outputNames;
}
const TrigConf::L1TopoAlgorithm &
TrigConf::L1Menu::algorithm(const std::string & algoName) const
TrigConf::L1Menu::algorithm(const std::string & algoName, const std::string & category) const
{
try {
return * m_algorithmsByName.at(algoName);
return * m_algorithmsByName.at(category).at(algoName);
}
catch(std::exception & ex) {
std::cerr << "No algorithm " << algoName << " of category " << category << " defined in the L1 menu" << std::endl;
throw;
}
}
const TrigConf::L1TopoAlgorithm &
TrigConf::L1Menu::algorithmFromTriggerline(const std::string & triggerlineName) const
{
std::string category {"MULTTOPO"};
std::string outputName {triggerlineName};
if( std::size_t pos = triggerlineName.find('_'); pos != std::string::npos ) {
category = triggerlineName.substr(0,pos);
outputName = triggerlineName.substr(pos+1);
}
try {
return * m_algorithmsByOutput.at(category).at(outputName);
}
catch(std::exception & ex) {
std::cerr << "No algorithm " << algoName << " defined in the L1 menu" << std::endl;
std::cerr << "No output " << outputName << " defined by any algorithm of category " << category << " in the L1 menu. (It was asked for " << triggerlineName << ")" << std::endl;
throw;
}
}
const TrigConf::L1TopoAlgorithm &
TrigConf::L1Menu::algorithmFromOutput(const std::string & outputName) const
TrigConf::L1Menu::algorithmFromOutput(const std::string & bareOutputName, const std::string & type) const
{
try {
return * m_algorithmsByOutput.at(outputName);
return * m_algorithmsByOutput.at(type).at(bareOutputName);
}
catch(std::exception & ex) {
std::cerr << "No output '" << outputName << "' defined by any algorithm in the L1 menu" << std::endl;
std::cerr << "No output " << bareOutputName << " defined by any algorithm of type " << type << " in the L1 menu" << std::endl;
throw;
}
}
......
......@@ -3,14 +3,16 @@
*/
#include "TrigConfData/L1TopoAlgorithm.h"
#include <map>
TrigConf::L1TopoAlgorithm::L1TopoAlgorithm()
{}
TrigConf::L1TopoAlgorithm::L1TopoAlgorithm(const std::string & algoName, AlgorithmType algoType, const boost::property_tree::ptree & data)
TrigConf::L1TopoAlgorithm::L1TopoAlgorithm(const std::string & algoName, AlgorithmType algoType, const std::string & algoCategory, const boost::property_tree::ptree & data)
: DataStructure(data),
m_type(algoType)
m_type(algoType),
m_category(algoCategory)
{
if( m_category != "TOPO" && m_category != "MUTOPO" && m_category != "R2TOPO" && m_category != "MULTTOPO") {
throw std::runtime_error("Algorithm category must be TOPO, R2TOPO, MUTOPO or MULTTOPO, but is '" + algoCategory + "'");
}
m_name = algoName;
update();
}
......@@ -29,13 +31,41 @@ TrigConf::L1TopoAlgorithm::update()
if(! isInitialized() || empty() ) {
return;
}
if( m_type == AlgorithmType::DECISION ) {
if( m_type == AlgorithmType::DECISION ) { // DECISION algo
if( hasChild("input") ) {
for( auto & inp : getList("input")) {
m_inputs.push_back(inp.getValue());
}
} else if( hasChild("fixedParameters.inputs") ) { // backwards compatibility, to be removed when we stop using DEV db
for( auto & inp : getList("fixedParameters.inputs")) {
m_inputs.push_back(inp["value"]);
}
}
for( auto & o : getList("output")) {
m_outputs.push_back(o.getValue());
}
} else {
} else if( m_type == AlgorithmType::MULTIPLICITY ) { // MULTIPLICITY algo
m_inputs.push_back(getAttribute("input"));
m_outputs.push_back(getAttribute("output"));
} else { // SORTING algo
if( hasAttribute("input") ) {
m_inputs.push_back( getAttribute("input") );
} else if( hasChild("fixedParameters.input") ) { // backwards compatibility, to be removed when we stop using DEV db
auto inp = getObject("fixedParameters.input");
for( auto & k : inp.getKeys() ) {
m_inputs.push_back(inp[k]);
break;
}
}
m_outputs.push_back(getAttribute("output"));
}
if( m_type == AlgorithmType::DECISION || m_type == AlgorithmType::SORTING ) {
for( auto & p : getList("variableParameters") ) {
m_parameters.emplace_back(p["name"], p.getAttribute<int>("value"), p.getAttribute<unsigned int>("selection", /*ignore-if-missing*/true, 0));
}
}
}
......@@ -51,17 +81,25 @@ TrigConf::L1TopoAlgorithm::type() const
return m_type;
}
const std::string &
TrigConf::L1TopoAlgorithm::category() const
{
return m_category;
}
const std::string &
TrigConf::L1TopoAlgorithm::klass() const
{
if(hasAttribute("klass")) {
return getAttribute("klass");
}
return getAttribute("type");
}
std::vector<TrigConf::DataStructure>
const std::vector<std::string> &
TrigConf::L1TopoAlgorithm::inputs() const
{
return getList("fixedParameters.inputs");
return m_inputs;
}
const std::vector<std::string> &
......@@ -70,15 +108,66 @@ TrigConf::L1TopoAlgorithm::outputs() const
return m_outputs;
}
std::vector<TrigConf::DataStructure>
std::vector<std::string>
TrigConf::L1TopoAlgorithm::fullOutputs() const
{
std::vector<std::string> out;
for( auto & s : m_outputs ) {
out.push_back(m_category + "_" + s);
}
return out;
}
std::string
TrigConf::L1TopoAlgorithm::genericParameter(const std::string & parName) const
{
return operator[]("fixedParameters.generics." + parName + ".value");
}
TrigConf::DataStructure
TrigConf::L1TopoAlgorithm::generics() const
{
return getList("fixedParameters.generics");
return getObject("fixedParameters.generics");
}
std::vector<TrigConf::DataStructure>
const std::vector<TrigConf::L1TopoAlgorithm::VariableParameter> &
TrigConf::L1TopoAlgorithm::parameters() const
{
return getList("variableParameters.parameters");
return m_parameters;
}
void
TrigConf::L1TopoAlgorithm::print(std::ostream & os) const
{
os << "Algorithm " << name() << " (class " << klass() << ", category " << m_category << ")" << std::endl;
os << " input:" << std::endl;
for( auto & input : inputs() ) {
os << " " << input << std::endl;
}
os << " output:" << std::endl;
for( auto & output : outputs() ) {
os << " " << output << std::endl;
}
os << " full output:" << std::endl;
for( auto & output : fullOutputs() ) {
os << " " << output << std::endl;
}
if(type() == AlgorithmType::MULTIPLICITY) {
os << " threshold definition: " << getAttribute("threshold") << std::endl;
os << " number of output bits: " << getAttribute<unsigned int>("nbits") << std::endl;
} else {
os << " generic parameters:" << std::endl;
auto genPars = generics();
for( auto & k : genPars.getKeys() ) {
os << " " << k << " ==> " << genericParameter(k) << std::endl;
}
os << " parameters:" << std::endl;
auto pars =