1 #include "otsdaq-core/FECore/FEVInterface.h"
2 #include "otsdaq-core/CoreSupervisors/CoreSupervisorBase.h"
3 #include "otsdaq-core/FECore/FEVInterfacesManager.h"
4 #include "otsdaq-core/NetworkUtilities/UDPDataStreamerBase.h"
13 FEVInterface::FEVInterface(
const std::string& interfaceUID,
15 const std::string& configurationPath)
17 ,
Configurable(theXDAQContextConfigTree, configurationPath)
18 , interfaceUID_(interfaceUID)
23 , slowControlsWorkLoop_(interfaceUID +
"-SlowControls", this)
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();
47 theXDAQContextConfigTree_.getBackNode(theConfigurationPath_)
48 .getNode(
"LinkToSlowControlsChannelTable");
50 if(slowControlsGroupLink.isDisconnected())
53 <<
"slowControlsGroupLink is disconnected, so done configuring slow controls."
57 __FE_COUT__ <<
"slowControlsGroupLink is valid! Configuring slow controls..."
60 mapOfSlowControlsChannels_.clear();
61 std::vector<std::pair<std::string, ConfigurationTree> > groupLinkChildren =
62 slowControlsGroupLink.getChildren();
63 for(
auto& groupLinkChild : groupLinkChildren)
66 if(!(groupLinkChild.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
70 __FE_COUT__ <<
"Channel:" << getInterfaceUID() <<
"/" << groupLinkChild.first
71 <<
"\t Type:" << groupLinkChild.second.getNode(
"ChannelDataType")
74 mapOfSlowControlsChannels_.insert(std::pair<std::string, FESlowControlsChannel>(
79 groupLinkChild.second.getNode(
"ChannelDataType").getValue<std::string>(),
81 universalAddressSize_,
82 groupLinkChild.second.getNode(
"UniversalInterfaceAddress")
83 .getValue<std::string>(),
84 groupLinkChild.second.getNode(
"UniversalDataBitOffset")
85 .getValue<
unsigned int>(),
86 groupLinkChild.second.getNode(
"ReadAccess").getValue<
bool>(),
87 groupLinkChild.second.getNode(
"WriteAccess").getValue<
bool>(),
88 groupLinkChild.second.getNode(
"MonitoringEnabled").getValue<
bool>(),
89 groupLinkChild.second.getNode(
"RecordChangesOnly").getValue<
bool>(),
90 groupLinkChild.second.getNode(
"DelayBetweenSamplesInSeconds")
92 groupLinkChild.second.getNode(
"LocalSavingEnabled").getValue<
bool>(),
93 groupLinkChild.second.getNode(
"LocalFilePath").getValue<std::string>(),
94 groupLinkChild.second.getNode(
"RadixFileName").getValue<std::string>(),
95 groupLinkChild.second.getNode(
"SaveBinaryFile").getValue<
bool>(),
96 groupLinkChild.second.getNode(
"AlarmsEnabled").getValue<
bool>(),
97 groupLinkChild.second.getNode(
"LatchAlarms").getValue<
bool>(),
98 groupLinkChild.second.getNode(
"LowLowThreshold").getValue<std::string>(),
99 groupLinkChild.second.getNode(
"LowThreshold").getValue<std::string>(),
100 groupLinkChild.second.getNode(
"HighThreshold").getValue<std::string>(),
101 groupLinkChild.second.getNode(
"HighHighThreshold")
102 .getValue<std::string>())));
107 bool FEVInterface::slowControlsRunning(
void)
110 __FE_COUT__ <<
"slowControlsRunning" << __E__;
112 if(mapOfSlowControlsChannels_.size() == 0)
115 <<
"No slow controls channels to monitor, exiting slow controls workloop."
120 readVal.resize(universalDataSize_);
124 const unsigned int txBufferSz = 1500;
125 const unsigned int txBufferFullThreshold = 750;
126 std::string txBuffer;
127 txBuffer.reserve(txBufferSz);
130 theXDAQContextConfigTree_.getBackNode(theConfigurationPath_);
134 std::unique_ptr<UDPDataStreamerBase> slowContrlolsTxSocket;
135 std::string slowControlsSupervisorIPAddress =
"", slowControlsSelfIPAddress =
"";
136 int slowControlsSupervisorPort = 0, slowControlsSelfPort = 0;
140 FEInterfaceNode.getNode(
"LinkToSlowControlsSupervisorTable");
143 if(slowControlsInterfaceLink.isDisconnected())
145 __FE_SS__ <<
"slowControlsInterfaceLink is disconnected, so no socket made."
150 slowControlsSelfIPAddress = FEInterfaceNode.getNode(
"SlowControlsTxSocketIPAddress")
151 .getValue<std::string>();
152 slowControlsSelfPort = FEInterfaceNode.getNode(
"SlowControlsTxSocketPort").getValue<
int>();
153 slowControlsSupervisorIPAddress = slowControlsInterfaceLink.getNode(
154 "IPAddress").getValue<std::string>();
155 slowControlsSupervisorPort = slowControlsInterfaceLink.getNode(
"Port").getValue<
int>();
159 __FE_COUT__ <<
"Link to slow controls supervisor is missing, so no socket made."
163 if(slowControlsSupervisorPort && slowControlsSelfPort &&
164 slowControlsSupervisorIPAddress !=
"" &&
165 slowControlsSelfIPAddress !=
"")
168 __FE_COUT__ <<
"slowControlsInterfaceLink is valid! Create tx socket..." << __E__;
170 slowControlsSelfIPAddress,
171 slowControlsSelfPort,
172 slowControlsSupervisorIPAddress,
173 slowControlsSupervisorPort));
177 __FE_COUT__ <<
"Invalid Slow Controls socket parameters, so no socket made." << __E__;
184 bool aggregateFileIsBinaryFormat =
false;
185 if(FEInterfaceNode.getNode(
"SlowControlsLocalAggregateSavingEnabled")
188 aggregateFileIsBinaryFormat =
189 FEInterfaceNode.getNode(
"SlowControlsSaveBinaryFile").getValue<
bool>();
191 __FE_COUT_INFO__ <<
"Slow Controls Aggregate Saving turned On BinaryFormat="
192 << aggregateFileIsBinaryFormat << __E__;
194 std::string saveFullFileName =
195 FEInterfaceNode.getNode(
"SlowControlsLocalFilePath").getValue<std::string>() +
197 FEInterfaceNode.getNode(
"SlowControlsRadixFileName").getValue<std::string>() +
198 "-" + FESlowControlsChannel::underscoreString(getInterfaceUID()) +
"-" +
199 std::to_string(time(0)) + (aggregateFileIsBinaryFormat ?
".dat" :
".txt");
201 fp = fopen(saveFullFileName.c_str(), aggregateFileIsBinaryFormat ?
"ab" :
"a");
204 __FE_COUT_ERR__ <<
"Failed to open slow controls channel file: "
205 << saveFullFileName << __E__;
209 __FE_COUT_INFO__ <<
"Slow controls aggregate file opened: "
210 << saveFullFileName << __E__;
213 __FE_COUT_INFO__ <<
"Slow Controls Aggregate Saving turned off." << __E__;
215 time_t timeCounter = 0;
217 while(slowControlsWorkLoop_.getContinueWorkLoop())
223 __FE_COUT__ <<
"txBuffer sz=" << txBuffer.size() << __E__;
230 for(
auto& slowControlsChannelPair : mapOfSlowControlsChannels_)
232 channel = &slowControlsChannelPair.second;
235 if(!channel->readAccess_)
239 if(timeCounter % channel->delayBetweenSamples_)
242 __FE_COUT__ <<
"Channel:" << getInterfaceUID() <<
"/"
243 << slowControlsChannelPair.first << __E__;
244 __FE_COUT__ <<
"Monitoring..." << __E__;
246 universalRead(channel->getUniversalAddress(), &readVal[0]);
258 channel->handleSample(readVal, txBuffer, fp, aggregateFileIsBinaryFormat);
260 __FE_COUT__ <<
"txBuffer sz=" << txBuffer.size() << __E__;
267 if(metricMan && universalAddressSize_ <= 8)
271 for(
size_t ii = 0; ii < universalAddressSize_; ++ii)
272 val += (uint8_t)readVal[ii] << (ii * 4);
276 __FE_COUT__ <<
"Sending sample to Metric Manager..." << __E__;
277 metricMan->sendMetric(
278 getInterfaceUID() +
"/" + slowControlsChannelPair.first,
282 artdaq::MetricMode::LastPoint);
286 if(txBuffer.size() > txBufferSz)
288 __FE_SS__ <<
"This should never happen hopefully!" << __E__;
293 if(slowContrlolsTxSocket && txBuffer.size() > txBufferFullThreshold)
295 __FE_COUT__ <<
"Sending now! txBufferFullThreshold="
296 << txBufferFullThreshold << __E__;
297 slowContrlolsTxSocket->send(txBuffer);
303 __FE_COUT__ <<
"txBuffer sz=" << txBuffer.size() << __E__;
306 if(slowContrlolsTxSocket && txBuffer.size())
308 __FE_COUT__ <<
"Sending now!" << __E__;
309 slowContrlolsTxSocket->send(txBuffer);
321 catch(
const std::runtime_error& e)
323 __FE_COUT__ <<
"Error caught during slow controls running thread: " << e.what() << __E__;
328 __FE_COUT__ <<
"Unknown error caught during slow controls running thread." << __E__;
337 void FEVInterface::sendAsyncErrorToGateway(
FEVInterface* fe,
338 const std::string& errorMessage,
339 bool isSoftError)
try
342 __COUT_ERR__ <<
":FE:" << fe->getInterfaceType() <<
":" << fe->getInterfaceUID()
343 <<
":" << fe->theConfigurationRecordName_ <<
":"
344 <<
"Sending FE Async SOFT Running Error... \n"
345 << errorMessage << __E__;
347 __COUT_ERR__ <<
":FE:" << fe->getInterfaceType() <<
":" << fe->getInterfaceUID()
348 <<
":" << fe->theConfigurationRecordName_ <<
":"
349 <<
"Sending FE Async Running Error... \n"
350 << errorMessage << __E__;
352 XDAQ_CONST_CALL xdaq::ApplicationDescriptor* gatewaySupervisor =
353 fe->VStateMachine::parentSupervisor_->allSupervisorInfo_.getGatewayInfo()
357 parameters.addParameter(
"ErrorMessage", errorMessage);
359 xoap::MessageReference replyMessage =
360 fe->VStateMachine::parentSupervisor_->SOAPMessenger::sendWithSOAPReply(
361 gatewaySupervisor, isSoftError ?
"AsyncSoftError" :
"AsyncError", parameters);
363 std::stringstream replyMessageSStream;
364 replyMessageSStream << SOAPUtilities::translate(replyMessage);
365 __COUT__ <<
":FE:" << fe->getInterfaceType() <<
":" << fe->getInterfaceUID() <<
":"
366 << fe->theConfigurationRecordName_ <<
":"
367 <<
"Received... " << replyMessageSStream.str() << std::endl;
369 if(replyMessageSStream.str().find(
"Fault") != std::string::npos)
371 __COUT_ERR__ <<
":FE:" << fe->getInterfaceType() <<
":" << fe->getInterfaceUID()
372 <<
":" << fe->theConfigurationRecordName_ <<
":"
373 <<
"Failure to indicate fault to Gateway..." << __E__;
377 catch(
const xdaq::exception::Exception& e)
380 __COUT__ <<
"SOAP message failure indicating front-end asynchronous running SOFT "
381 "error back to Gateway: "
382 << e.what() << __E__;
384 __COUT__ <<
"SOAP message failure indicating front-end asynchronous running "
385 "error back to Gateway: "
386 << e.what() << __E__;
391 __COUT__ <<
"Unknown error encounter indicating front-end asynchronous running "
392 "SOFT error back to Gateway."
395 __COUT__ <<
"Unknown error encounter indicating front-end asynchronous running "
396 "error back to Gateway."
403 bool FEVInterface::workLoopThread(toolbox::task::WorkLoop* workLoop)
415 bool isSoftError =
false;
423 ss <<
"SOFT Error was caught while configuring: " << e.what() << std::endl;
426 catch(
const std::runtime_error& e)
428 ss <<
"Caught an error during running at FE Interface '"
429 << Configurable::theConfigurationRecordName_ <<
"': " << e.what() << __E__;
433 ss <<
"Caught an unknown error during running." << __E__;
440 __FE_COUT_ERR__ << ss.str();
443 [](
FEVInterface* fe,
const std::string errorMessage,
bool isSoftError) {
444 FEVInterface::sendAsyncErrorToGateway(fe, errorMessage, isSoftError);
455 return continueWorkLoop_;
466 void FEVInterface::registerFEMacroFunction(
467 const std::string& feMacroName,
468 frontEndMacroFunction_t feMacroFunction,
469 const std::vector<std::string>& namesOfInputArgs,
470 const std::vector<std::string>& namesOfOutputArgs,
471 uint8_t requiredUserPermissions,
472 const std::string& allowedCallingFEs)
474 if(mapOfFEMacroFunctions_.find(feMacroName) != mapOfFEMacroFunctions_.end())
476 __FE_SS__ <<
"feMacroName '" << feMacroName <<
"' already exists! Not allowed."
478 __FE_COUT_ERR__ <<
"\n" << ss.str();
482 mapOfFEMacroFunctions_.insert(std::pair<std::string, frontEndMacroStruct_t>(
484 frontEndMacroStruct_t(feMacroName,
488 requiredUserPermissions,
489 allowedCallingFEs)));
497 const std::string& FEVInterface::getFEMacroConstArgument(frontEndMacroConstArgs_t& args,
498 const std::string& argName)
500 for(
const frontEndMacroArg_t& pair : args)
502 if(pair.first == argName)
504 __COUT__ <<
"argName : " << pair.second << __E__;
508 __SS__ <<
"Requested input argument not found with name '" << argName <<
"'" << __E__;
516 std::string getFEMacroConstArgumentValue<std::string>(
517 FEVInterface::frontEndMacroConstArgs_t& args,
const std::string& argName)
519 return FEVInterface::getFEMacroConstArgument(args, argName);
526 std::string getFEMacroArgumentValue<std::string>(FEVInterface::frontEndMacroArgs_t& args,
527 const std::string& argName)
529 return FEVInterface::getFEMacroArgument(args, argName);
537 std::string& FEVInterface::getFEMacroArgument(frontEndMacroArgs_t& args,
538 const std::string& argName)
540 for(std::pair<
const std::string ,
541 std::string >& pair : args)
543 if(pair.first == argName)
546 __SS__ <<
"Requested argument not found with name '" << argName <<
"'" << __E__;
555 void FEVInterface::runSequenceOfCommands(
const std::string& treeLinkName)
557 std::map<uint64_t, uint64_t> writeHistory;
558 uint64_t writeAddress, writeValue, bitMask;
561 std::string writeBuffer;
562 std::string readBuffer;
564 bool ignoreError =
true;
570 theXDAQContextConfigTree_.getNode(theConfigurationPath_)
571 .getNode(treeLinkName);
576 if(configSeqLink.isDisconnected())
577 __FE_COUT__ <<
"Disconnected configure sequence" << __E__;
580 __FE_COUT__ <<
"Handling configure sequence." << __E__;
581 auto childrenMap = configSeqLink.getChildrenMap();
582 for(
const auto& child : childrenMap)
587 child.second.getNode(
"WriteAddress").getValue<uint64_t>();
588 writeValue = child.second.getNode(
"WriteValue").getValue<uint64_t>();
590 child.second.getNode(
"StartingBitPosition").getValue<uint8_t>();
592 (1 << child.second.getNode(
"BitFieldSize").getValue<uint8_t>()) -
595 writeValue &= bitMask;
596 writeValue <<= bitPosition;
597 bitMask = ~(bitMask << bitPosition);
600 if(writeHistory.find(writeAddress) == writeHistory.end())
601 writeHistory[writeAddress] = 0;
603 writeHistory[writeAddress] &= bitMask;
604 writeHistory[writeAddress] |= writeValue;
607 "\t Writing %s: \t %ld(0x%lX) \t %ld(0x%lX)",
611 writeHistory[writeAddress],
612 writeHistory[writeAddress]);
614 __FE_COUT__ << msg << __E__;
616 universalWrite((
char*)&writeAddress,
617 (
char*)&(writeHistory[writeAddress]));
633 <<
"Unable to access sequence of commands through configuration tree. "
634 <<
"Assuming no sequence. " << __E__;
646 void FEVInterface::runSelfFrontEndMacro(
647 const std::string& feMacroName,
650 const std::vector<FEVInterface::frontEndMacroArg_t>& argsIn,
651 std::vector<FEVInterface::frontEndMacroArg_t>& argsOut)
654 auto FEMacroIt = this->getMapOfFEMacroFunctions().find(feMacroName);
655 if(FEMacroIt == this->getMapOfFEMacroFunctions().end())
657 __CFG_SS__ <<
"FE Macro '" << feMacroName <<
"' of interfaceID '"
658 << getInterfaceUID() <<
"' was not found!" << __E__;
659 __CFG_COUT_ERR__ <<
"\n" << ss.str();
665 for(
unsigned int i = 0; i < argsIn.size(); ++i)
666 if(argsIn[i].first != feMacro.namesOfInputArguments_[i])
668 __CFG_SS__ <<
"FE Macro '" << feMacro.feMacroName_ <<
"' of interfaceID '"
669 << getInterfaceUID() <<
"' was attempted with a mismatch in"
670 <<
" a name of an input argument. " << argsIn[i].first
671 <<
" was given. " << feMacro.namesOfInputArguments_[i]
672 <<
" expected." << __E__;
673 __CFG_COUT_ERR__ <<
"\n" << ss.str();
678 if(feMacro.namesOfInputArguments_.size() != argsIn.size())
680 __CFG_SS__ <<
"FE Macro '" << feMacro.feMacroName_ <<
"' of interfaceID '"
681 << getInterfaceUID() <<
"' was attempted with a mismatch in"
682 <<
" number of input arguments. " << argsIn.size() <<
" were given. "
683 << feMacro.namesOfInputArguments_.size() <<
" expected." << __E__;
684 __CFG_COUT_ERR__ <<
"\n" << ss.str();
688 __CFG_COUT__ <<
"# of input args = " << argsIn.size() << __E__;
689 for(
auto& argIn : argsIn)
690 __CFG_COUT__ << argIn.first <<
": " << argIn.second << __E__;
692 __CFG_COUT__ <<
"Launching FE Macro '" << feMacro.feMacroName_ <<
"' ..." << __E__;
695 for(
unsigned int i = 0; i < feMacro.namesOfOutputArguments_.size(); ++i)
696 argsOut.push_back(FEVInterface::frontEndMacroArg_t(
697 feMacro.namesOfOutputArguments_[i],
"DEFAULT"));
700 (this->*(feMacro.macroFunction_))(feMacro, argsIn, argsOut);
702 __CFG_COUT__ <<
"FE Macro complete!" << __E__;
704 __CFG_COUT__ <<
"# of output args = " << argsOut.size() << __E__;
705 for(
const auto& arg : argsOut)
706 __CFG_COUT__ << arg.first <<
": " << arg.second << __E__;
714 void FEVInterface::runFrontEndMacro(
715 const std::string& targetInterfaceID,
716 const std::string& feMacroName,
717 const std::vector<FEVInterface::frontEndMacroArg_t>& inputArgs,
718 std::vector<FEVInterface::frontEndMacroArg_t>& outputArgs)
const
720 __FE_COUTV__(targetInterfaceID);
721 __FE_COUTV__(VStateMachine::parentSupervisor_);
723 std::string inputArgsStr = StringMacros::vectorToString(
724 inputArgs,
";" ,
"," );
726 __FE_COUTV__(inputArgsStr);
728 xoap::MessageReference message =
729 SOAPUtilities::makeSOAPMessageReference(
"FECommunication");
732 parameters.addParameter(
"type",
"feMacro");
733 parameters.addParameter(
"requester", FEVInterface::interfaceUID_);
734 parameters.addParameter(
"targetInterfaceID", targetInterfaceID);
735 parameters.addParameter(
"feMacroName", feMacroName);
736 parameters.addParameter(
"inputArgs", inputArgsStr);
737 SOAPUtilities::addParameters(message, parameters);
739 __FE_COUT__ <<
"Sending FE communication: " << SOAPUtilities::translate(message)
742 xoap::MessageReference replyMessage =
743 VStateMachine::parentSupervisor_->SOAPMessenger::sendWithSOAPReply(
744 VStateMachine::parentSupervisor_->allSupervisorInfo_
745 .getAllMacroMakerTypeSupervisorInfo()
747 ->second.getDescriptor(),
750 __FE_COUT__ <<
"Response received: " << SOAPUtilities::translate(replyMessage)
754 rxParameters.addParameter(
"Error");
755 SOAPUtilities::receive(replyMessage, rxParameters);
757 std::string error = rxParameters.getValue(
"Error");
762 __FE_SS__ <<
"Error transmitting request to target interface '"
763 << targetInterfaceID <<
"' from '" << FEVInterface::interfaceUID_
764 <<
".' " << error << __E__;
770 argsOutParameter.addParameter(
"outputArgs");
771 SOAPUtilities::receive(replyMessage, argsOutParameter);
773 std::string outputArgsStr = argsOutParameter.getValue(
"outputArgs");
774 std::set<char> pairDelimiter({
';'}), nameValueDelimiter({
','});
776 std::map<std::string, std::string> mapToReturn;
777 StringMacros::getMapFromString(
778 outputArgsStr, mapToReturn, pairDelimiter, nameValueDelimiter);
781 for(
auto& mapPair : mapToReturn)
782 outputArgs.push_back(mapPair);
791 void FEVInterface::receiveFromFrontEnd(
const std::string& requester,
792 std::string& retValue,
793 unsigned int timeoutInSeconds)
const
795 __FE_COUTV__(requester);
796 __FE_COUTV__(parentSupervisor_);
798 std::string data =
"0";
804 std::lock_guard<std::mutex> lock(
805 parentInterfaceManager_->frontEndCommunicationReceiveMutex_);
807 auto receiveBuffersForTargetIt =
808 parentInterfaceManager_->frontEndCommunicationReceiveBuffer_.find(
809 FEVInterface::interfaceUID_);
810 if(receiveBuffersForTargetIt !=
811 parentInterfaceManager_->frontEndCommunicationReceiveBuffer_.end())
813 __FE_COUT__ <<
"Number of source buffers found for front-end '"
814 << FEVInterface::interfaceUID_
815 <<
"': " << receiveBuffersForTargetIt->second.size() << __E__;
817 for(
auto& buffPair : receiveBuffersForTargetIt->second)
818 __FE_COUTV__(buffPair.first);
821 std::string sourceBufferId =
"";
822 std::queue<std::string >& sourceBuffer =
823 StringMacros::getWildCardMatchFromMap(
824 requester, receiveBuffersForTargetIt->second, &sourceBufferId);
826 __FE_COUT__ <<
"Found source buffer '" << sourceBufferId <<
"' with size "
827 << sourceBuffer.size() << __E__;
829 if(sourceBuffer.size())
831 __FE_COUT__ <<
"Found a value in queue of size "
832 << sourceBuffer.size() << __E__;
835 retValue = sourceBuffer.front();
840 __FE_COUT__ <<
"Source buffer empty for '" << requester <<
"'"
847 if(!timeoutInSeconds)
849 __FE_SS__ <<
"Timeout (" << timeoutInSeconds
850 <<
" s) waiting for front-end communication from " << requester
859 __FE_COUT__ <<
"Waiting for front-end communication from " << requester <<
" for "
860 << timeoutInSeconds <<
" more seconds..." << __E__;
874 std::string FEVInterface::receiveFromFrontEnd(
const std::string& requester,
875 unsigned int timeoutInSeconds)
const
877 std::string retValue;
878 FEVInterface::receiveFromFrontEnd(requester, retValue, timeoutInSeconds);
884 FEVInterface::macroStruct_t::macroStruct_t(
const std::string& macroString)
886 __COUTV__(macroString);
892 std::vector<std::string> extractVec;
893 StringMacros::getVectorFromString(macroString, extractVec, {
'"'});
895 __COUTV__(StringMacros::vectorToString(extractVec,
" ||| "));
899 MACRONAME_NAME_INDEX = 1,
900 MACRONAME_VALUE_INDEX = 3,
901 SEQUENCE_NAME_INDEX = 5,
902 SEQUENCE_VALUE_INDEX = 7,
903 LSBF_NAME_INDEX = 17,
904 LSFBF_VALUE_INDEX = 19,
908 if(MACRONAME_NAME_INDEX >= extractVec.size() ||
909 extractVec[MACRONAME_NAME_INDEX] !=
"name")
911 __SS__ <<
"Invalid sequence, 'name' expected in position " << MACRONAME_NAME_INDEX
915 if(SEQUENCE_NAME_INDEX >= extractVec.size() ||
916 extractVec[SEQUENCE_NAME_INDEX] !=
"sequence")
918 __SS__ <<
"Invalid sequence, 'sequence' expected in position "
919 << SEQUENCE_NAME_INDEX << __E__;
922 if(LSBF_NAME_INDEX >= extractVec.size() || extractVec[LSBF_NAME_INDEX] !=
"LSBF")
924 __SS__ <<
"Invalid sequence, 'LSBF' expected in position " << LSBF_NAME_INDEX
928 macroName_ = extractVec[MACRONAME_VALUE_INDEX];
929 __COUTV__(macroName_);
930 lsbf_ = extractVec[LSFBF_VALUE_INDEX] ==
"false" ?
false :
true;
932 std::string& sequence = extractVec[SEQUENCE_VALUE_INDEX];
935 std::vector<std::string> sequenceCommands;
936 StringMacros::getVectorFromString(sequence, sequenceCommands, {
','});
938 __COUTV__(StringMacros::vectorToString(sequenceCommands,
" ### "));
940 for(
auto& command : sequenceCommands)
947 std::vector<std::string> commandPieces;
948 StringMacros::getVectorFromString(command, commandPieces, {
':'});
950 __COUTV__(StringMacros::vectorToString(commandPieces,
" ### "));
952 __COUTV__(commandPieces.size());
963 if(commandPieces.size() < 3 || commandPieces.size() > 4 ||
964 commandPieces[1].size() != 1)
966 __SS__ <<
"Invalid command type specified in command string: " << command
973 std::function<bool(
const std::string&
975 localIsVariable = [](
const std::string& fieldValue) {
977 std::string mfSubject_ =
"isVar";
978 __GEN_COUTV__(fieldValue);
981 for(
const auto& c : fieldValue)
982 if(!((c >=
'0' && c <=
'9') || (c >=
'a' && c <=
'f') ||
983 (c >=
'A' && c <=
'F')))
989 if(commandPieces[1][0] ==
'r' && commandPieces.size() == 4)
991 __COUT__ <<
"Read type found." << __E__;
995 operations_.push_back(
996 std::make_pair(macroStruct_t::OP_TYPE_READ, readOps_.size()));
998 readOps_.push_back(macroStruct_t::readOp_t());
999 readOps_.back().addressIsVar_ = localIsVariable(commandPieces[2]);
1000 readOps_.back().dataIsVar_ = localIsVariable(commandPieces[3]);
1002 if(!readOps_.back().addressIsVar_)
1006 std::string lsbfData =
"";
1009 commandPieces[2] =
"0" + commandPieces[2];
1010 for(
unsigned int i = 0; i < commandPieces[2].size() / 2; ++i)
1012 __COUTV__(commandPieces[2].size() - 2 * (i + 1));
1015 commandPieces[2][commandPieces[2].size() - 2 * (i + 1)];
1017 commandPieces[2][commandPieces[2].size() - 2 * (i + 1) + 1];
1018 __COUTV__(lsbfData);
1020 __COUTV__(lsbfData);
1021 StringMacros::getNumber(
"0x" + lsbfData, readOps_.back().address_);
1024 StringMacros::getNumber(
"0x" + commandPieces[2],
1025 readOps_.back().address_);
1029 readOps_.back().addressVarName_ = commandPieces[2];
1030 __COUTV__(readOps_.back().addressVarName_);
1032 namesOfInputArguments_.emplace(readOps_.back().addressVarName_);
1035 if(readOps_.back().dataIsVar_)
1037 readOps_.back().dataVarName_ = commandPieces[3];
1038 __COUTV__(readOps_.back().dataVarName_);
1040 namesOfOutputArguments_.emplace(readOps_.back().dataVarName_);
1043 else if(commandPieces[1][0] ==
'w' && commandPieces.size() == 4)
1045 __COUT__ <<
"Write type found." << __E__;
1049 operations_.push_back(
1050 std::make_pair(macroStruct_t::OP_TYPE_WRITE, writeOps_.size()));
1052 writeOps_.push_back(macroStruct_t::writeOp_t());
1053 writeOps_.back().addressIsVar_ = localIsVariable(commandPieces[2]);
1054 writeOps_.back().dataIsVar_ = localIsVariable(commandPieces[3]);
1056 if(!writeOps_.back().addressIsVar_)
1060 std::string lsbfData =
"";
1063 commandPieces[2] =
"0" + commandPieces[2];
1064 for(
unsigned int i = 0; i < commandPieces[2].size() / 2; ++i)
1066 __COUTV__(commandPieces[2].size() - 2 * (i + 1));
1069 commandPieces[2][commandPieces[2].size() - 2 * (i + 1)];
1071 commandPieces[2][commandPieces[2].size() - 2 * (i + 1) + 1];
1072 __COUTV__(lsbfData);
1074 __COUTV__(lsbfData);
1075 StringMacros::getNumber(
"0x" + lsbfData, writeOps_.back().address_);
1078 StringMacros::getNumber(
"0x" + commandPieces[2],
1079 writeOps_.back().address_);
1083 writeOps_.back().addressVarName_ = commandPieces[2];
1084 __COUTV__(writeOps_.back().addressVarName_);
1086 namesOfInputArguments_.emplace(writeOps_.back().addressVarName_);
1089 if(!writeOps_.back().dataIsVar_)
1093 std::string lsbfData =
"";
1096 commandPieces[2] =
"0" + commandPieces[3];
1097 for(
unsigned int i = 0; i < commandPieces[3].size() / 2; ++i)
1099 __COUTV__(commandPieces[3].size() - 2 * (i + 1));
1102 commandPieces[3][commandPieces[3].size() - 2 * (i + 1)];
1104 commandPieces[3][commandPieces[3].size() - 2 * (i + 1) + 1];
1105 __COUTV__(lsbfData);
1107 __COUTV__(lsbfData);
1108 StringMacros::getNumber(
"0x" + lsbfData, writeOps_.back().data_);
1111 StringMacros::getNumber(
"0x" + commandPieces[3],
1112 writeOps_.back().data_);
1116 writeOps_.back().dataVarName_ = commandPieces[3];
1117 __COUTV__(writeOps_.back().dataVarName_);
1119 namesOfInputArguments_.emplace(writeOps_.back().dataVarName_);
1122 else if(commandPieces[1][0] ==
'd' && commandPieces.size() == 3)
1124 __COUT__ <<
"Delay type found." << __E__;
1127 operations_.push_back(
1128 std::make_pair(macroStruct_t::OP_TYPE_DELAY, delayOps_.size()));
1130 delayOps_.push_back(macroStruct_t::delayOp_t());
1131 delayOps_.back().delayIsVar_ = localIsVariable(commandPieces[2]);
1133 if(!delayOps_.back().delayIsVar_)
1134 StringMacros::getNumber(
"0x" + commandPieces[2], delayOps_.back().delay_);
1137 delayOps_.back().delayVarName_ = commandPieces[2];
1138 __COUTV__(delayOps_.back().delayVarName_);
1140 namesOfInputArguments_.emplace(delayOps_.back().delayVarName_);
1145 __SS__ <<
"Invalid command type '" << commandPieces[1][0]
1146 <<
"' specified with " << commandPieces.size() <<
" components."
1153 __COUT__ << operations_.size() <<
" operations extracted: \n\t" << readOps_.size()
1154 <<
" reads \n\t" << writeOps_.size() <<
" writes \n\t" << delayOps_.size()
1155 <<
" delays" << __E__;
1157 __COUT__ <<
"Input arguments: " << __E__;
1158 for(
const auto& inputArg : namesOfInputArguments_)
1159 __COUT__ <<
"\t" << inputArg << __E__;
1161 __COUT__ <<
"Output arguments: " << __E__;
1162 for(
const auto& outputArg : namesOfOutputArguments_)
1163 __COUT__ <<
"\t" << outputArg << __E__;
1169 void FEVInterface::runMacro(
1171 std::map<std::string /*name*/, uint64_t /*value*/>& variableMap)
1175 __FE_COUT__ <<
"Running Macro '" << macro.macroName_ <<
"' of "
1176 << macro.operations_.size() <<
" operations." << __E__;
1178 for(
auto& op : macro.operations_)
1180 if(op.first == macroStruct_t::OP_TYPE_READ)
1182 __FE_COUT__ <<
"Doing read op..." << __E__;
1183 macroStruct_t::readOp_t& readOp = macro.readOps_[op.second];
1184 if(readOp.addressIsVar_)
1186 __FE_COUTV__(readOp.addressVarName_);
1187 readOp.address_ = variableMap.at(readOp.addressVarName_);
1190 uint64_t dataValue = 0;
1192 __FE_COUT__ << std::hex <<
"Read address: \t 0x" << readOp.address_ << __E__
1195 universalRead((
char*)&readOp.address_, (
char*)&dataValue);
1197 __FE_COUT__ << std::hex <<
"Read data: \t 0x" << dataValue << __E__
1200 if(readOp.dataIsVar_)
1202 __FE_COUTV__(readOp.dataVarName_);
1203 variableMap.at(readOp.dataVarName_) = dataValue;
1207 else if(op.first == macroStruct_t::OP_TYPE_WRITE)
1209 __FE_COUT__ <<
"Doing write op..." << __E__;
1210 macroStruct_t::writeOp_t& writeOp = macro.writeOps_[op.second];
1211 if(writeOp.addressIsVar_)
1213 __FE_COUTV__(writeOp.addressVarName_);
1214 writeOp.address_ = variableMap.at(writeOp.addressVarName_);
1216 if(writeOp.dataIsVar_)
1218 __FE_COUTV__(writeOp.dataVarName_);
1219 writeOp.data_ = variableMap.at(writeOp.dataVarName_);
1222 __FE_COUT__ << std::hex <<
"Write address: \t 0x" << writeOp.address_ << __E__
1224 __FE_COUT__ << std::hex <<
"Write data: \t 0x" << writeOp.data_ << __E__
1227 universalWrite((
char*)&writeOp.address_, (
char*)&writeOp.data_);
1230 else if(op.first == macroStruct_t::OP_TYPE_DELAY)
1232 __FE_COUT__ <<
"Doing delay op..." << __E__;
1234 macroStruct_t::delayOp_t& delayOp = macro.delayOps_[op.second];
1235 if(delayOp.delayIsVar_)
1237 __FE_COUTV__(delayOp.delayVarName_);
1238 delayOp.delay_ = variableMap.at(delayOp.delayVarName_);
1241 __FE_COUT__ << std::dec <<
"Delay ms: \t " << delayOp.delay_ << __E__;
1243 usleep(delayOp.delay_ * 1000);
1248 __FE_SS__ <<
"Invalid command type '" << op.first <<
"!'" << __E__;