1 #include "otsdaq/FECore/FEVInterface.h"
2 #include "otsdaq/CoreSupervisors/CoreSupervisorBase.h"
3 #include "otsdaq/FECore/FEVInterfacesManager.h"
4 #include "otsdaq/NetworkUtilities/UDPDataStreamerBase.h"
13 FEVInterface::FEVInterface(
const std::string& interfaceUID,
15 const std::string& configurationPath)
17 ,
Configurable(theXDAQContextConfigTree, configurationPath)
18 , slowControlsWorkLoop_(interfaceUID +
"-SlowControls", this)
19 , interfaceUID_(interfaceUID)
28 __COUT__ <<
"'" << interfaceUID <<
"' Constructed." << __E__;
32 FEVInterface::~FEVInterface(
void)
36 __COUT__ << FEVInterface::interfaceUID_ <<
" Destructed." << __E__;
40 void FEVInterface::configureSlowControls(
void)
43 if(metricMan && !metricMan->Running() && metricMan->Initialized())
44 metricMan->do_start();
46 mapOfSlowControlsChannels_.clear();
48 addSlowControlsChannels(theXDAQContextConfigTree_.getBackNode(theConfigurationPath_)
49 .getNode(
"LinkToSlowControlsChannelTable"),
51 &mapOfSlowControlsChannels_);
59 void FEVInterface::addSlowControlsChannels(
61 const std::string& subInterfaceID,
62 std::map<std::string /* ROC UID*/, FESlowControlsChannel>* mapOfSlowControlsChannels)
64 if(slowControlsGroupLink.isDisconnected())
67 <<
"slowControlsGroupLink is disconnected, so done configuring slow controls."
71 __FE_COUT__ <<
"slowControlsGroupLink is valid! Adding slow controls channels..."
74 std::vector<std::pair<std::string, ConfigurationTree> > groupLinkChildren =
75 slowControlsGroupLink.getChildren();
76 for(
auto& groupLinkChild : groupLinkChildren)
79 if(!(groupLinkChild.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
83 __FE_COUT__ <<
"Channel:" << getInterfaceUID() << subInterfaceID <<
"/"
84 << groupLinkChild.first
85 <<
"\t Type:" << groupLinkChild.second.getNode(
"ChannelDataType")
88 mapOfSlowControlsChannels->insert(std::pair<std::string, FESlowControlsChannel>(
91 getInterfaceUID() + subInterfaceID,
93 groupLinkChild.second.getNode(
"ChannelDataType").getValue<std::string>(),
95 universalAddressSize_,
96 groupLinkChild.second.getNode(
"UniversalInterfaceAddress")
97 .getValue<std::string>(),
98 groupLinkChild.second.getNode(
"UniversalDataBitOffset")
99 .getValue<
unsigned int>(),
100 groupLinkChild.second.getNode(
"ReadAccess").getValue<
bool>(),
101 groupLinkChild.second.getNode(
"WriteAccess").getValue<
bool>(),
102 groupLinkChild.second.getNode(
"MonitoringEnabled").getValue<
bool>(),
103 groupLinkChild.second.getNode(
"RecordChangesOnly").getValue<
bool>(),
104 groupLinkChild.second.getNode(
"DelayBetweenSamplesInSeconds")
106 groupLinkChild.second.getNode(
"LocalSavingEnabled").getValue<
bool>(),
107 groupLinkChild.second.getNode(
"LocalFilePath").getValue<std::string>(),
108 groupLinkChild.second.getNode(
"RadixFileName").getValue<std::string>(),
109 groupLinkChild.second.getNode(
"SaveBinaryFile").getValue<
bool>(),
110 groupLinkChild.second.getNode(
"AlarmsEnabled").getValue<
bool>(),
111 groupLinkChild.second.getNode(
"LatchAlarms").getValue<
bool>(),
112 groupLinkChild.second.getNode(
"LowLowThreshold").getValue<std::string>(),
113 groupLinkChild.second.getNode(
"LowThreshold").getValue<std::string>(),
114 groupLinkChild.second.getNode(
"HighThreshold").getValue<std::string>(),
115 groupLinkChild.second.getNode(
"HighHighThreshold")
116 .getValue<std::string>())));
122 void FEVInterface::resetSlowControlsChannelIterator(
void)
124 slowControlsChannelsIterator_ = mapOfSlowControlsChannels_.begin();
131 if(slowControlsChannelsIterator_ == mapOfSlowControlsChannels_.end())
135 (slowControlsChannelsIterator_++)->second);
141 std::string& readValue)
143 readValue.resize(universalDataSize_);
144 universalRead(channel.getUniversalAddress(), &readValue[0]);
149 unsigned int FEVInterface::getSlowControlsChannelCount(
void)
151 return mapOfSlowControlsChannels_.size();
155 bool FEVInterface::slowControlsRunning(
void)
try
157 __FE_COUT__ <<
"slowControlsRunning" << __E__;
159 if(getSlowControlsChannelCount() == 0)
162 <<
"No slow controls channels to monitor, exiting slow controls workloop."
167 readVal.resize(universalDataSize_);
171 const unsigned int txBufferSz = 1500;
172 const unsigned int txBufferFullThreshold = 750;
173 std::string txBuffer;
174 txBuffer.reserve(txBufferSz);
177 theXDAQContextConfigTree_.getBackNode(theConfigurationPath_);
180 std::unique_ptr<UDPDataStreamerBase> slowContrlolsTxSocket;
181 std::string slowControlsSupervisorIPAddress =
"", slowControlsSelfIPAddress =
"";
182 int slowControlsSupervisorPort = 0, slowControlsSelfPort = 0;
186 FEInterfaceNode.getNode(
"LinkToSlowControlsSupervisorTable");
188 if(slowControlsInterfaceLink.isDisconnected())
190 __FE_SS__ <<
"slowControlsInterfaceLink is disconnected, so no socket made."
195 slowControlsSelfIPAddress =
196 FEInterfaceNode.getNode(
"SlowControlsTxSocketIPAddress")
197 .getValue<std::string>();
198 slowControlsSelfPort =
199 FEInterfaceNode.getNode(
"SlowControlsTxSocketPort").getValue<
int>();
200 slowControlsSupervisorIPAddress =
201 slowControlsInterfaceLink.getNode(
"IPAddress").getValue<std::string>();
202 slowControlsSupervisorPort =
203 slowControlsInterfaceLink.getNode(
"Port").getValue<
int>();
207 __FE_COUT__ <<
"Link to slow controls supervisor is missing, so no socket made."
211 if(slowControlsSupervisorPort && slowControlsSelfPort &&
212 slowControlsSupervisorIPAddress !=
"" && slowControlsSelfIPAddress !=
"")
214 __FE_COUT__ <<
"slowControlsInterfaceLink is valid! Create tx socket..." << __E__;
215 slowContrlolsTxSocket.reset(
217 slowControlsSelfPort,
218 slowControlsSupervisorIPAddress,
219 slowControlsSupervisorPort));
223 __FE_COUT__ <<
"Invalid Slow Controls socket parameters, so no socket made."
230 bool aggregateFileIsBinaryFormat =
false;
231 if(FEInterfaceNode.getNode(
"SlowControlsLocalAggregateSavingEnabled")
234 aggregateFileIsBinaryFormat =
235 FEInterfaceNode.getNode(
"SlowControlsSaveBinaryFile").getValue<
bool>();
237 __FE_COUT_INFO__ <<
"Slow Controls Aggregate Saving turned On BinaryFormat="
238 << aggregateFileIsBinaryFormat << __E__;
240 std::string saveFullFileName =
241 FEInterfaceNode.getNode(
"SlowControlsLocalFilePath").getValue<std::string>() +
243 FEInterfaceNode.getNode(
"SlowControlsRadixFileName").getValue<std::string>() +
244 "-" + FESlowControlsChannel::underscoreString(getInterfaceUID()) +
"-" +
245 std::to_string(time(0)) + (aggregateFileIsBinaryFormat ?
".dat" :
".txt");
247 fp = fopen(saveFullFileName.c_str(), aggregateFileIsBinaryFormat ?
"ab" :
"a");
250 __FE_COUT_ERR__ <<
"Failed to open slow controls channel file: "
251 << saveFullFileName << __E__;
255 __FE_COUT_INFO__ <<
"Slow controls aggregate file opened: "
256 << saveFullFileName << __E__;
259 __FE_COUT_INFO__ <<
"Slow Controls Aggregate Saving turned off." << __E__;
261 time_t timeCounter = 0;
263 unsigned int numOfReadAccessChannels = 0;
264 bool firstTime =
true;
266 while(slowControlsWorkLoop_.getContinueWorkLoop())
268 __FE_COUT__ <<
"..." << __E__;
274 __FE_COUT__ <<
"txBuffer sz=" << txBuffer.size() << __E__;
281 resetSlowControlsChannelIterator();
282 while((channel = getNextSlowControlsChannel()) !=
nullptr)
285 if(!channel->readAccess_)
289 ++numOfReadAccessChannels;
292 if(timeCounter % channel->delayBetweenSamples_)
295 __FE_COUT__ <<
"Reading Channel:" << channel->fullChannelName_ << __E__;
297 getSlowControlsValue(*channel, readVal);
309 channel->handleSample(readVal, txBuffer, fp, aggregateFileIsBinaryFormat);
311 __FE_COUT__ <<
"txBuffer sz=" << txBuffer.size() << __E__;
314 if(channel->monitoringEnabled_ && metricMan && metricMan->Running() &&
315 universalAddressSize_ <= 8)
318 for(
size_t ii = 0; ii < universalAddressSize_; ++ii)
319 val += (uint8_t)readVal[ii] << (ii * 4);
321 __FE_COUT__ <<
"Sending sample to Metric Manager..." << __E__;
322 metricMan->sendMetric(
323 channel->fullChannelName_, val,
"", 3, artdaq::MetricMode::LastPoint);
327 if(txBuffer.size() > txBufferSz)
329 __FE_SS__ <<
"This should never happen hopefully!" << __E__;
334 if(slowContrlolsTxSocket && txBuffer.size() > txBufferFullThreshold)
336 __FE_COUT__ <<
"Sending now! txBufferFullThreshold="
337 << txBufferFullThreshold << __E__;
338 slowContrlolsTxSocket->send(txBuffer);
344 __FE_COUT__ <<
"txBuffer sz=" << txBuffer.size() << __E__;
347 if(slowContrlolsTxSocket && txBuffer.size())
349 __FE_COUT__ <<
"Sending now!" << __E__;
350 slowContrlolsTxSocket->send(txBuffer);
358 if(numOfReadAccessChannels == 0)
360 __MCOUT_WARN__(
"There are no slow controls channels with read access!"
365 __COUT__ <<
"There are " << getSlowControlsChannelCount()
366 <<
" slow controls channels total. " << numOfReadAccessChannels
367 <<
" with read access enabled." << __E__;
375 __FE_COUT__ <<
"Slow controls workloop done." << __E__;
384 bool isSoftError =
false;
392 ss <<
"SOFT Error was caught during slow controls running thread: " << e.what()
396 catch(
const std::runtime_error& e)
398 ss <<
"Caught an error during slow controls running thread of FE Interface '"
399 << Configurable::theConfigurationRecordName_ <<
"': " << e.what() << __E__;
403 ss <<
"Caught an unknown error during slow controls running thread." << __E__;
411 __FE_COUT_ERR__ << ss.str();
414 [](
FEVInterface* fe,
const std::string errorMessage,
bool isSoftError) {
415 FEVInterface::sendAsyncErrorToGateway(fe, errorMessage, isSoftError);
434 void FEVInterface::sendAsyncErrorToGateway(
FEVInterface* fe,
435 const std::string& errorMessage,
436 bool isSoftError)
try
438 std::stringstream feHeader;
439 feHeader <<
":FE:" << fe->getInterfaceType() <<
":" << fe->getInterfaceUID() <<
":"
440 << fe->theConfigurationRecordName_ <<
"\t";
443 __COUT_ERR__ << feHeader.str() <<
"Sending FE Async SOFT Running Error... \n"
444 << errorMessage << __E__;
446 __COUT_ERR__ << feHeader.str() <<
"Sending FE Async Running Error... \n"
447 << errorMessage << __E__;
449 XDAQ_CONST_CALL xdaq::ApplicationDescriptor* gatewaySupervisor =
450 fe->VStateMachine::parentSupervisor_->allSupervisorInfo_.getGatewayInfo()
454 parameters.addParameter(
"ErrorMessage", errorMessage);
456 xoap::MessageReference replyMessage =
457 fe->VStateMachine::parentSupervisor_->SOAPMessenger::sendWithSOAPReply(
458 gatewaySupervisor, isSoftError ?
"AsyncSoftError" :
"AsyncError", parameters);
460 std::stringstream replyMessageSStream;
461 replyMessageSStream << SOAPUtilities::translate(replyMessage);
462 __COUT__ << feHeader.str() <<
"Received... " << replyMessageSStream.str()
465 if(replyMessageSStream.str().find(
"Fault") != std::string::npos)
467 __COUT_ERR__ << feHeader.str() <<
"Failure to indicate fault to Gateway..."
472 catch(
const xdaq::exception::Exception& e)
475 __COUT__ <<
"SOAP message failure indicating front-end asynchronous running SOFT "
476 "error back to Gateway: "
477 << e.what() << __E__;
479 __COUT__ <<
"SOAP message failure indicating front-end asynchronous running "
480 "error back to Gateway: "
481 << e.what() << __E__;
487 __COUT__ <<
"Unknown error encounter indicating front-end asynchronous running "
488 "SOFT error back to Gateway."
491 __COUT__ <<
"Unknown error encounter indicating front-end asynchronous running "
492 "error back to Gateway."
500 bool FEVInterface::workLoopThread(toolbox::task::WorkLoop* workLoop)
512 bool isSoftError =
false;
520 ss <<
"SOFT Error was caught while configuring: " << e.what() << std::endl;
523 catch(
const std::runtime_error& e)
525 ss <<
"Caught an error during running at FE Interface '"
526 << Configurable::theConfigurationRecordName_ <<
"': " << e.what() << __E__;
530 ss <<
"Caught an unknown error during running." << __E__;
538 __FE_COUT_ERR__ << ss.str();
541 [](
FEVInterface* fe,
const std::string errorMessage,
bool isSoftError) {
542 FEVInterface::sendAsyncErrorToGateway(fe, errorMessage, isSoftError);
553 return continueWorkLoop_;
564 void FEVInterface::registerFEMacroFunction(
565 const std::string& feMacroName,
566 frontEndMacroFunction_t feMacroFunction,
567 const std::vector<std::string>& namesOfInputArgs,
568 const std::vector<std::string>& namesOfOutputArgs,
569 uint8_t requiredUserPermissions,
570 const std::string& allowedCallingFEs)
572 if(mapOfFEMacroFunctions_.find(feMacroName) != mapOfFEMacroFunctions_.end())
574 __FE_SS__ <<
"feMacroName '" << feMacroName <<
"' already exists! Not allowed."
576 __FE_COUT_ERR__ <<
"\n" << ss.str();
580 mapOfFEMacroFunctions_.insert(std::pair<std::string, frontEndMacroStruct_t>(
582 frontEndMacroStruct_t(feMacroName,
586 requiredUserPermissions,
587 allowedCallingFEs)));
595 const std::string& FEVInterface::getFEMacroConstArgument(frontEndMacroConstArgs_t& args,
596 const std::string& argName)
598 for(
const frontEndMacroArg_t& pair : args)
600 if(pair.first == argName)
602 __COUT__ <<
"argName : " << pair.second << __E__;
606 __SS__ <<
"Requested input argument not found with name '" << argName <<
"'" << __E__;
614 std::string ots::getFEMacroConstArgumentValue<std::string>(
615 FEVInterface::frontEndMacroConstArgs_t& args,
const std::string& argName)
617 return FEVInterface::getFEMacroConstArgument(args, argName);
624 std::string ots::getFEMacroArgumentValue<std::string>(
625 FEVInterface::frontEndMacroArgs_t& args,
const std::string& argName)
627 return FEVInterface::getFEMacroArgument(args, argName);
635 std::string& FEVInterface::getFEMacroArgument(frontEndMacroArgs_t& args,
636 const std::string& argName)
638 for(std::pair<
const std::string ,
639 std::string >& pair : args)
641 if(pair.first == argName)
644 __SS__ <<
"Requested argument not found with name '" << argName <<
"'" << __E__;
653 void FEVInterface::runSequenceOfCommands(
const std::string& treeLinkName)
655 std::map<uint64_t, uint64_t> writeHistory;
656 uint64_t writeAddress, writeValue, bitMask;
659 std::string writeBuffer;
660 std::string readBuffer;
662 bool ignoreError =
true;
668 theXDAQContextConfigTree_.getNode(theConfigurationPath_)
669 .getNode(treeLinkName);
674 if(configSeqLink.isDisconnected())
675 __FE_COUT__ <<
"Disconnected configure sequence" << __E__;
678 __FE_COUT__ <<
"Handling configure sequence." << __E__;
679 auto childrenMap = configSeqLink.getChildrenMap();
680 for(
const auto& child : childrenMap)
685 child.second.getNode(
"WriteAddress").getValue<uint64_t>();
686 writeValue = child.second.getNode(
"WriteValue").getValue<uint64_t>();
688 child.second.getNode(
"StartingBitPosition").getValue<uint8_t>();
690 (1 << child.second.getNode(
"BitFieldSize").getValue<uint8_t>()) -
693 writeValue &= bitMask;
694 writeValue <<= bitPosition;
695 bitMask = ~(bitMask << bitPosition);
698 if(writeHistory.find(writeAddress) == writeHistory.end())
699 writeHistory[writeAddress] = 0;
701 writeHistory[writeAddress] &= bitMask;
702 writeHistory[writeAddress] |= writeValue;
705 "\t Writing %s: \t %ld(0x%lX) \t %ld(0x%lX)",
709 writeHistory[writeAddress],
710 writeHistory[writeAddress]);
712 __FE_COUT__ << msg << __E__;
714 universalWrite((
char*)&writeAddress,
715 (
char*)&(writeHistory[writeAddress]));
731 <<
"Unable to access sequence of commands through configuration tree. "
732 <<
"Assuming no sequence. " << __E__;
744 void FEVInterface::runSelfFrontEndMacro(
745 const std::string& feMacroName,
748 const std::vector<FEVInterface::frontEndMacroArg_t>& argsIn,
749 std::vector<FEVInterface::frontEndMacroArg_t>& argsOut)
752 auto FEMacroIt = this->getMapOfFEMacroFunctions().find(feMacroName);
753 if(FEMacroIt == this->getMapOfFEMacroFunctions().end())
755 __CFG_SS__ <<
"FE Macro '" << feMacroName <<
"' of interfaceID '"
756 << getInterfaceUID() <<
"' was not found!" << __E__;
757 __CFG_COUT_ERR__ <<
"\n" << ss.str();
763 for(
unsigned int i = 0; i < argsIn.size(); ++i)
764 if(argsIn[i].first != feMacro.namesOfInputArguments_[i])
766 __CFG_SS__ <<
"FE Macro '" << feMacro.feMacroName_ <<
"' of interfaceID '"
767 << getInterfaceUID() <<
"' was attempted with a mismatch in"
768 <<
" a name of an input argument. " << argsIn[i].first
769 <<
" was given. " << feMacro.namesOfInputArguments_[i]
770 <<
" expected." << __E__;
771 __CFG_COUT_ERR__ <<
"\n" << ss.str();
776 if(feMacro.namesOfInputArguments_.size() != argsIn.size())
778 __CFG_SS__ <<
"FE Macro '" << feMacro.feMacroName_ <<
"' of interfaceID '"
779 << getInterfaceUID() <<
"' was attempted with a mismatch in"
780 <<
" number of input arguments. " << argsIn.size() <<
" were given. "
781 << feMacro.namesOfInputArguments_.size() <<
" expected." << __E__;
782 __CFG_COUT_ERR__ <<
"\n" << ss.str();
786 __CFG_COUT__ <<
"# of input args = " << argsIn.size() << __E__;
787 for(
auto& argIn : argsIn)
788 __CFG_COUT__ << argIn.first <<
": " << argIn.second << __E__;
790 __CFG_COUT__ <<
"Launching FE Macro '" << feMacro.feMacroName_ <<
"' ..." << __E__;
793 for(
unsigned int i = 0; i < feMacro.namesOfOutputArguments_.size(); ++i)
794 argsOut.push_back(FEVInterface::frontEndMacroArg_t(
795 feMacro.namesOfOutputArguments_[i],
"DEFAULT"));
798 (this->*(feMacro.macroFunction_))(feMacro, argsIn, argsOut);
800 __CFG_COUT__ <<
"FE Macro complete!" << __E__;
802 __CFG_COUT__ <<
"# of output args = " << argsOut.size() << __E__;
803 for(
const auto& arg : argsOut)
804 __CFG_COUT__ << arg.first <<
": " << arg.second << __E__;
812 void FEVInterface::runFrontEndMacro(
813 const std::string& targetInterfaceID,
814 const std::string& feMacroName,
815 const std::vector<FEVInterface::frontEndMacroArg_t>& inputArgs,
816 std::vector<FEVInterface::frontEndMacroArg_t>& outputArgs)
const
818 __FE_COUTV__(targetInterfaceID);
819 __FE_COUTV__(VStateMachine::parentSupervisor_);
821 std::string inputArgsStr = StringMacros::vectorToString(
822 inputArgs,
";" ,
"," );
824 __FE_COUTV__(inputArgsStr);
826 xoap::MessageReference message =
827 SOAPUtilities::makeSOAPMessageReference(
"FECommunication");
830 parameters.addParameter(
"type",
"feMacro");
831 parameters.addParameter(
"requester", FEVInterface::interfaceUID_);
832 parameters.addParameter(
"targetInterfaceID", targetInterfaceID);
833 parameters.addParameter(
"feMacroName", feMacroName);
834 parameters.addParameter(
"inputArgs", inputArgsStr);
835 SOAPUtilities::addParameters(message, parameters);
837 __FE_COUT__ <<
"Sending FE communication: " << SOAPUtilities::translate(message)
840 xoap::MessageReference replyMessage =
841 VStateMachine::parentSupervisor_->SOAPMessenger::sendWithSOAPReply(
842 VStateMachine::parentSupervisor_->allSupervisorInfo_
843 .getAllMacroMakerTypeSupervisorInfo()
845 ->second.getDescriptor(),
848 __FE_COUT__ <<
"Response received: " << SOAPUtilities::translate(replyMessage)
852 rxParameters.addParameter(
"Error");
853 SOAPUtilities::receive(replyMessage, rxParameters);
855 std::string error = rxParameters.getValue(
"Error");
860 __FE_SS__ <<
"Error transmitting request to target interface '"
861 << targetInterfaceID <<
"' from '" << FEVInterface::interfaceUID_
862 <<
".' " << error << __E__;
868 argsOutParameter.addParameter(
"outputArgs");
869 SOAPUtilities::receive(replyMessage, argsOutParameter);
871 std::string outputArgsStr = argsOutParameter.getValue(
"outputArgs");
872 std::set<char> pairDelimiter({
';'}), nameValueDelimiter({
','});
874 std::map<std::string, std::string> mapToReturn;
875 StringMacros::getMapFromString(
876 outputArgsStr, mapToReturn, pairDelimiter, nameValueDelimiter);
879 for(
auto& mapPair : mapToReturn)
880 outputArgs.push_back(mapPair);
889 void FEVInterface::receiveFromFrontEnd(
const std::string& requester,
890 std::string& retValue,
891 unsigned int timeoutInSeconds)
const
893 __FE_COUTV__(requester);
894 __FE_COUTV__(parentSupervisor_);
896 std::string data =
"0";
902 std::lock_guard<std::mutex> lock(
903 parentInterfaceManager_->frontEndCommunicationReceiveMutex_);
905 auto receiveBuffersForTargetIt =
906 parentInterfaceManager_->frontEndCommunicationReceiveBuffer_.find(
907 FEVInterface::interfaceUID_);
908 if(receiveBuffersForTargetIt !=
909 parentInterfaceManager_->frontEndCommunicationReceiveBuffer_.end())
911 __FE_COUT__ <<
"Number of source buffers found for front-end '"
912 << FEVInterface::interfaceUID_
913 <<
"': " << receiveBuffersForTargetIt->second.size() << __E__;
915 for(
auto& buffPair : receiveBuffersForTargetIt->second)
916 __FE_COUTV__(buffPair.first);
919 std::string sourceBufferId =
"";
920 std::queue<std::string >& sourceBuffer =
921 StringMacros::getWildCardMatchFromMap(
922 requester, receiveBuffersForTargetIt->second, &sourceBufferId);
924 __FE_COUT__ <<
"Found source buffer '" << sourceBufferId <<
"' with size "
925 << sourceBuffer.size() << __E__;
927 if(sourceBuffer.size())
929 __FE_COUT__ <<
"Found a value in queue of size "
930 << sourceBuffer.size() << __E__;
933 retValue = sourceBuffer.front();
938 __FE_COUT__ <<
"Source buffer empty for '" << requester <<
"'"
945 if(!timeoutInSeconds)
947 __FE_SS__ <<
"Timeout (" << timeoutInSeconds
948 <<
" s) waiting for front-end communication from " << requester
957 __FE_COUT__ <<
"Waiting for front-end communication from " << requester <<
" for "
958 << timeoutInSeconds <<
" more seconds..." << __E__;
972 std::string FEVInterface::receiveFromFrontEnd(
const std::string& requester,
973 unsigned int timeoutInSeconds)
const
975 std::string retValue;
976 FEVInterface::receiveFromFrontEnd(requester, retValue, timeoutInSeconds);
982 FEVInterface::macroStruct_t::macroStruct_t(
const std::string& macroString)
984 __COUTV__(macroString);
990 std::vector<std::string> extractVec;
991 StringMacros::getVectorFromString(macroString, extractVec, {
'"'});
993 __COUTV__(StringMacros::vectorToString(extractVec,
" ||| "));
997 MACRONAME_NAME_INDEX = 1,
998 MACRONAME_VALUE_INDEX = 3,
999 SEQUENCE_NAME_INDEX = 5,
1000 SEQUENCE_VALUE_INDEX = 7,
1001 LSBF_NAME_INDEX = 17,
1002 LSFBF_VALUE_INDEX = 19,
1006 if(MACRONAME_NAME_INDEX >= extractVec.size() ||
1007 extractVec[MACRONAME_NAME_INDEX] !=
"name")
1009 __SS__ <<
"Invalid sequence, 'name' expected in position " << MACRONAME_NAME_INDEX
1013 if(SEQUENCE_NAME_INDEX >= extractVec.size() ||
1014 extractVec[SEQUENCE_NAME_INDEX] !=
"sequence")
1016 __SS__ <<
"Invalid sequence, 'sequence' expected in position "
1017 << SEQUENCE_NAME_INDEX << __E__;
1020 if(LSBF_NAME_INDEX >= extractVec.size() || extractVec[LSBF_NAME_INDEX] !=
"LSBF")
1022 __SS__ <<
"Invalid sequence, 'LSBF' expected in position " << LSBF_NAME_INDEX
1026 macroName_ = extractVec[MACRONAME_VALUE_INDEX];
1027 __COUTV__(macroName_);
1028 lsbf_ = extractVec[LSFBF_VALUE_INDEX] ==
"false" ?
false :
true;
1030 std::string& sequence = extractVec[SEQUENCE_VALUE_INDEX];
1031 __COUTV__(sequence);
1033 std::vector<std::string> sequenceCommands;
1034 StringMacros::getVectorFromString(sequence, sequenceCommands, {
','});
1036 __COUTV__(StringMacros::vectorToString(sequenceCommands,
" ### "));
1038 for(
auto& command : sequenceCommands)
1045 std::vector<std::string> commandPieces;
1046 StringMacros::getVectorFromString(command, commandPieces, {
':'});
1048 __COUTV__(StringMacros::vectorToString(commandPieces,
" ### "));
1050 __COUTV__(commandPieces.size());
1061 if(commandPieces.size() < 3 || commandPieces.size() > 4 ||
1062 commandPieces[1].size() != 1)
1064 __SS__ <<
"Invalid command type specified in command string: " << command
1071 std::function<bool(
const std::string&
1073 localIsVariable = [](
const std::string& fieldValue) {
1075 std::string mfSubject_ =
"isVar";
1076 __GEN_COUTV__(fieldValue);
1079 for(
const auto& c : fieldValue)
1080 if(!((c >=
'0' && c <=
'9') || (c >=
'a' && c <=
'f') ||
1081 (c >=
'A' && c <=
'F')))
1087 if(commandPieces[1][0] ==
'r' && commandPieces.size() == 4)
1089 __COUT__ <<
"Read type found." << __E__;
1093 operations_.push_back(
1094 std::make_pair(macroStruct_t::OP_TYPE_READ, readOps_.size()));
1096 readOps_.push_back(macroStruct_t::readOp_t());
1097 readOps_.back().addressIsVar_ = localIsVariable(commandPieces[2]);
1098 readOps_.back().dataIsVar_ = localIsVariable(commandPieces[3]);
1100 if(!readOps_.back().addressIsVar_)
1104 std::string lsbfData =
"";
1107 commandPieces[2] =
"0" + commandPieces[2];
1108 for(
unsigned int i = 0; i < commandPieces[2].size() / 2; ++i)
1110 __COUTV__(commandPieces[2].size() - 2 * (i + 1));
1113 commandPieces[2][commandPieces[2].size() - 2 * (i + 1)];
1115 commandPieces[2][commandPieces[2].size() - 2 * (i + 1) + 1];
1116 __COUTV__(lsbfData);
1118 __COUTV__(lsbfData);
1119 StringMacros::getNumber(
"0x" + lsbfData, readOps_.back().address_);
1122 StringMacros::getNumber(
"0x" + commandPieces[2],
1123 readOps_.back().address_);
1127 readOps_.back().addressVarName_ = commandPieces[2];
1128 __COUTV__(readOps_.back().addressVarName_);
1130 namesOfInputArguments_.emplace(readOps_.back().addressVarName_);
1133 if(readOps_.back().dataIsVar_)
1135 readOps_.back().dataVarName_ = commandPieces[3];
1136 __COUTV__(readOps_.back().dataVarName_);
1138 namesOfOutputArguments_.emplace(readOps_.back().dataVarName_);
1141 else if(commandPieces[1][0] ==
'w' && commandPieces.size() == 4)
1143 __COUT__ <<
"Write type found." << __E__;
1147 operations_.push_back(
1148 std::make_pair(macroStruct_t::OP_TYPE_WRITE, writeOps_.size()));
1150 writeOps_.push_back(macroStruct_t::writeOp_t());
1151 writeOps_.back().addressIsVar_ = localIsVariable(commandPieces[2]);
1152 writeOps_.back().dataIsVar_ = localIsVariable(commandPieces[3]);
1154 if(!writeOps_.back().addressIsVar_)
1158 std::string lsbfData =
"";
1161 commandPieces[2] =
"0" + commandPieces[2];
1162 for(
unsigned int i = 0; i < commandPieces[2].size() / 2; ++i)
1164 __COUTV__(commandPieces[2].size() - 2 * (i + 1));
1167 commandPieces[2][commandPieces[2].size() - 2 * (i + 1)];
1169 commandPieces[2][commandPieces[2].size() - 2 * (i + 1) + 1];
1170 __COUTV__(lsbfData);
1172 __COUTV__(lsbfData);
1173 StringMacros::getNumber(
"0x" + lsbfData, writeOps_.back().address_);
1176 StringMacros::getNumber(
"0x" + commandPieces[2],
1177 writeOps_.back().address_);
1181 writeOps_.back().addressVarName_ = commandPieces[2];
1182 __COUTV__(writeOps_.back().addressVarName_);
1184 namesOfInputArguments_.emplace(writeOps_.back().addressVarName_);
1187 if(!writeOps_.back().dataIsVar_)
1191 std::string lsbfData =
"";
1194 commandPieces[2] =
"0" + commandPieces[3];
1195 for(
unsigned int i = 0; i < commandPieces[3].size() / 2; ++i)
1197 __COUTV__(commandPieces[3].size() - 2 * (i + 1));
1200 commandPieces[3][commandPieces[3].size() - 2 * (i + 1)];
1202 commandPieces[3][commandPieces[3].size() - 2 * (i + 1) + 1];
1203 __COUTV__(lsbfData);
1205 __COUTV__(lsbfData);
1206 StringMacros::getNumber(
"0x" + lsbfData, writeOps_.back().data_);
1209 StringMacros::getNumber(
"0x" + commandPieces[3],
1210 writeOps_.back().data_);
1214 writeOps_.back().dataVarName_ = commandPieces[3];
1215 __COUTV__(writeOps_.back().dataVarName_);
1217 namesOfInputArguments_.emplace(writeOps_.back().dataVarName_);
1220 else if(commandPieces[1][0] ==
'd' && commandPieces.size() == 3)
1222 __COUT__ <<
"Delay type found." << __E__;
1225 operations_.push_back(
1226 std::make_pair(macroStruct_t::OP_TYPE_DELAY, delayOps_.size()));
1228 delayOps_.push_back(macroStruct_t::delayOp_t());
1229 delayOps_.back().delayIsVar_ = localIsVariable(commandPieces[2]);
1231 if(!delayOps_.back().delayIsVar_)
1232 StringMacros::getNumber(
"0x" + commandPieces[2], delayOps_.back().delay_);
1235 delayOps_.back().delayVarName_ = commandPieces[2];
1236 __COUTV__(delayOps_.back().delayVarName_);
1238 namesOfInputArguments_.emplace(delayOps_.back().delayVarName_);
1243 __SS__ <<
"Invalid command type '" << commandPieces[1][0]
1244 <<
"' specified with " << commandPieces.size() <<
" components."
1251 __COUT__ << operations_.size() <<
" operations extracted: \n\t" << readOps_.size()
1252 <<
" reads \n\t" << writeOps_.size() <<
" writes \n\t" << delayOps_.size()
1253 <<
" delays" << __E__;
1255 __COUT__ <<
"Input arguments: " << __E__;
1256 for(
const auto& inputArg : namesOfInputArguments_)
1257 __COUT__ <<
"\t" << inputArg << __E__;
1259 __COUT__ <<
"Output arguments: " << __E__;
1260 for(
const auto& outputArg : namesOfOutputArguments_)
1261 __COUT__ <<
"\t" << outputArg << __E__;
1267 void FEVInterface::runMacro(
1269 std::map<std::string /*name*/, uint64_t /*value*/>& variableMap)
1273 __FE_COUT__ <<
"Running Macro '" << macro.macroName_ <<
"' of "
1274 << macro.operations_.size() <<
" operations." << __E__;
1276 for(
auto& op : macro.operations_)
1278 if(op.first == macroStruct_t::OP_TYPE_READ)
1280 __FE_COUT__ <<
"Doing read op..." << __E__;
1281 macroStruct_t::readOp_t& readOp = macro.readOps_[op.second];
1282 if(readOp.addressIsVar_)
1284 __FE_COUTV__(readOp.addressVarName_);
1285 readOp.address_ = variableMap.at(readOp.addressVarName_);
1288 uint64_t dataValue = 0;
1290 __FE_COUT__ << std::hex <<
"Read address: \t 0x" << readOp.address_ << __E__
1293 universalRead((
char*)&readOp.address_, (
char*)&dataValue);
1295 __FE_COUT__ << std::hex <<
"Read data: \t 0x" << dataValue << __E__
1298 if(readOp.dataIsVar_)
1300 __FE_COUTV__(readOp.dataVarName_);
1301 variableMap.at(readOp.dataVarName_) = dataValue;
1305 else if(op.first == macroStruct_t::OP_TYPE_WRITE)
1307 __FE_COUT__ <<
"Doing write op..." << __E__;
1308 macroStruct_t::writeOp_t& writeOp = macro.writeOps_[op.second];
1309 if(writeOp.addressIsVar_)
1311 __FE_COUTV__(writeOp.addressVarName_);
1312 writeOp.address_ = variableMap.at(writeOp.addressVarName_);
1314 if(writeOp.dataIsVar_)
1316 __FE_COUTV__(writeOp.dataVarName_);
1317 writeOp.data_ = variableMap.at(writeOp.dataVarName_);
1320 __FE_COUT__ << std::hex <<
"Write address: \t 0x" << writeOp.address_ << __E__
1322 __FE_COUT__ << std::hex <<
"Write data: \t 0x" << writeOp.data_ << __E__
1325 universalWrite((
char*)&writeOp.address_, (
char*)&writeOp.data_);
1328 else if(op.first == macroStruct_t::OP_TYPE_DELAY)
1330 __FE_COUT__ <<
"Doing delay op..." << __E__;
1332 macroStruct_t::delayOp_t& delayOp = macro.delayOps_[op.second];
1333 if(delayOp.delayIsVar_)
1335 __FE_COUTV__(delayOp.delayVarName_);
1336 delayOp.delay_ = variableMap.at(delayOp.delayVarName_);
1339 __FE_COUT__ << std::dec <<
"Delay ms: \t " << delayOp.delay_ << __E__;
1341 usleep(delayOp.delay_ * 1000);
1346 __FE_SS__ <<
"Invalid command type '" << op.first <<
"!'" << __E__;