diff --git a/Detectors/TOF/compression/CMakeLists.txt b/Detectors/TOF/compression/CMakeLists.txt index 78debc8f8f445..9dcbfc25f2c94 100644 --- a/Detectors/TOF/compression/CMakeLists.txt +++ b/Detectors/TOF/compression/CMakeLists.txt @@ -11,7 +11,6 @@ o2_add_library(TOFCompression SOURCES src/Compressor.cxx src/CompressorTask.cxx - src/CompressedInspectorTask.cxx PUBLIC_LINK_LIBRARIES O2::TOFBase O2::Framework O2::Headers O2::DataFormatsTOF O2::DetectorsRaw ) @@ -25,5 +24,7 @@ o2_add_executable(compressor o2_add_executable(compressed-inspector COMPONENT_NAME tof SOURCES src/tof-compressed-inspector.cxx - PUBLIC_LINK_LIBRARIES O2::TOFCompression + PUBLIC_LINK_LIBRARIES O2::TOFWorkflowUtils ) + + diff --git a/Detectors/TOF/compression/src/CompressedInspectorTask.cxx b/Detectors/TOF/compression/src/CompressedInspectorTask.cxx deleted file mode 100644 index cbd4e47884198..0000000000000 --- a/Detectors/TOF/compression/src/CompressedInspectorTask.cxx +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright CERN and copyright holders of ALICE O2. This software is -// distributed under the terms of the GNU General Public License v3 (GPL -// Version 3), copied verbatim in the file "COPYING". -// -// See http://alice-o2.web.cern.ch/license for full licensing information. -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// @file CompressedInspectorTask.cxx -/// @author Roberto Preghenella -/// @since 2020-01-25 -/// @brief TOF compressed data inspector task - -#include "TOFCompression/CompressedInspectorTask.h" -#include "Framework/ControlService.h" -#include "Framework/ConfigParamRegistry.h" - -#include "Headers/RAWDataHeader.h" -#include "DataFormatsTOF/CompressedDataFormat.h" -#include "DetectorsRaw/HBFUtils.h" - -#include "TFile.h" -#include "TH1F.h" -#include "TH2F.h" - -using namespace o2::framework; - -namespace o2 -{ -namespace tof -{ - -void CompressedInspectorTask::init(InitContext& ic) -{ - LOG(INFO) << "CompressedInspector init"; - auto filename = ic.options().get("tof-inspector-filename"); - - /** open file **/ - if (mFile && mFile->IsOpen()) { - LOG(WARNING) << "a file was already open, closing"; - mFile->Close(); - delete mFile; - } - mFile = TFile::Open(filename.c_str(), "RECREATE"); - if (!mFile || !mFile->IsOpen()) { - LOG(ERROR) << "cannot open output file: " << filename; - mStatus = true; - return; - } - - mHistos1D["hHisto"] = new TH1F("hHisto", "", 1000, 0., 1000.); - mHistos1D["time"] = new TH1F("hTime", ";time (24.4 ps)", 2097152, 0., 2097152.); - mHistos1D["tot"] = new TH1F("hTOT", ";ToT (48.8 ps)", 2048, 0., 2048.); - mHistos1D["indexE"] = new TH1F("hIndexE", ";index EO", 172800, 0., 172800.); - mHistos2D["slotEnableMask"] = new TH2F("hSlotEnableMask", ";crate;slot", 72, 0., 72., 12, 1., 13.); - mHistos2D["diagnostic"] = new TH2F("hDiagnostic", ";crate;slot", 72, 0., 72., 12, 1., 13.); - - auto finishFunction = [this]() { - LOG(INFO) << "CompressedInspector finish"; - for (auto& histo : mHistos1D) - histo.second->Write(); - for (auto& histo : mHistos2D) - histo.second->Write(); - mFile->Close(); - }; - ic.services().get().set(CallbackService::Id::Stop, finishFunction); -} - -void CompressedInspectorTask::run(ProcessingContext& pc) -{ - LOG(DEBUG) << "CompressedInspector run"; - - /** check status **/ - if (mStatus) { - pc.services().get().readyToQuit(QuitRequest::Me); - return; - } - - /** receive input **/ - for (auto& input : pc.inputs()) { - - /** input **/ - const auto* headerIn = DataRefUtils::getHeader(input); - auto payloadIn = const_cast(input.payload); - auto payloadInSize = headerIn->payloadSize; - - /** process input **/ - auto pointer = payloadIn; - while (pointer < (payloadIn + payloadInSize)) { - auto rdh = reinterpret_cast(pointer); - - /** RDH close detected **/ - if (rdh->stop) { -#ifdef VERBOSE - std::cout << "--- RDH close detected" << std::endl; - o2::raw::HBFUtils::printRDH(*rdh); -#endif - pointer += rdh->offsetToNext; - continue; - } - -#ifdef VERBOSE - std::cout << "--- RDH open detected" << std::endl; - o2::raw::HBFUtils::printRDH(*rdh); -#endif - - pointer += rdh->headerSize; - - while (pointer < (reinterpret_cast(rdh) + rdh->memorySize)) { - - auto word = reinterpret_cast(pointer); - if ((*word & 0x80000000) != 0x80000000) { - printf(" %08x [ERROR] \n ", *(uint32_t*)pointer); - return; - } - - /** crate header detected **/ - auto crateHeader = reinterpret_cast(pointer); -#ifdef VERBOSE - printf(" %08x CrateHeader (drmID=%d) \n ", *(uint32_t*)pointer, crateHeader->drmID); -#endif - for (int ibit = 0; ibit < 11; ++ibit) - if (crateHeader->slotEnableMask & (1 << ibit)) - mHistos2D["slotEnableMask"]->Fill(crateHeader->drmID, ibit + 2); - pointer += 4; - - /** crate orbit expected **/ - auto crateOrbit = reinterpret_cast(pointer); -#ifdef VERBOSE - printf(" %08x CrateOrbit (orbit=0x%08x) \n ", *(uint32_t*)pointer, crateOrbit->orbitID); -#endif - pointer += 4; - - while (true) { - word = reinterpret_cast(pointer); - - /** crate trailer detected **/ - if (*word & 0x80000000) { - auto crateTrailer = reinterpret_cast(pointer); -#ifdef VERBOSE - printf(" %08x CrateTrailer (numberOfDiagnostics=%d) \n ", *(uint32_t*)pointer, crateTrailer->numberOfDiagnostics); -#endif - pointer += 4; - - /** loop over diagnostics **/ - for (int i = 0; i < crateTrailer->numberOfDiagnostics; ++i) { - auto diagnostic = reinterpret_cast(pointer); -#ifdef VERBOSE - printf(" %08x Diagnostic (slotId=%d) \n ", *(uint32_t*)pointer, diagnostic->slotID); -#endif - mHistos2D["diagnostic"]->Fill(crateHeader->drmID, diagnostic->slotID); - pointer += 4; - } - - break; - } - - /** frame header detected **/ - auto frameHeader = reinterpret_cast(pointer); -#ifdef VERBOSE - printf(" %08x FrameHeader (numberOfHits=%d) \n ", *(uint32_t*)pointer, frameHeader->numberOfHits); -#endif - mHistos1D["hHisto"]->Fill(frameHeader->numberOfHits); - pointer += 4; - - /** loop over hits **/ - for (int i = 0; i < frameHeader->numberOfHits; ++i) { - auto packedHit = reinterpret_cast(pointer); -#ifdef VERBOSE - printf(" %08x PackedHit (tdcID=%d) \n ", *(uint32_t*)pointer, packedHit->tdcID); -#endif - auto indexE = packedHit->channel + - 8 * packedHit->tdcID + - 120 * packedHit->chain + - 240 * (frameHeader->trmID - 3) + - 2400 * crateHeader->drmID; - int time = packedHit->time; - time += (frameHeader->frameID << 13); - - mHistos1D["indexE"]->Fill(indexE); - mHistos1D["time"]->Fill(time); - mHistos1D["tot"]->Fill(packedHit->tot); - pointer += 4; - } - } - } - - pointer = reinterpret_cast(rdh) + rdh->offsetToNext; - } - } -} - -} // namespace tof -} // namespace o2 diff --git a/Detectors/TOF/compression/src/Compressor.cxx b/Detectors/TOF/compression/src/Compressor.cxx index 7494d1e79ce11..16242b40abebf 100644 --- a/Detectors/TOF/compression/src/Compressor.cxx +++ b/Detectors/TOF/compression/src/Compressor.cxx @@ -20,11 +20,11 @@ #include #include -#define DECODER_PARANOID -#define DECODER_VERBOSE -#define ENCODER_VERBOSE -#define CHECKER_VERBOSE -#define CHECKER_COUNTER +//#define DECODER_PARANOID +//#define DECODER_VERBOSE +//#define ENCODER_VERBOSE +//#define CHECKER_VERBOSE +//#define CHECKER_COUNTER #ifdef DECODER_PARANOID #warning "Building code with DecoderParanoid option. This may limit the speed." diff --git a/Detectors/TOF/compression/src/tof-compressed-inspector.cxx b/Detectors/TOF/compression/src/tof-compressed-inspector.cxx index 23a42623033c7..a0f0b20a8ef06 100644 --- a/Detectors/TOF/compression/src/tof-compressed-inspector.cxx +++ b/Detectors/TOF/compression/src/tof-compressed-inspector.cxx @@ -13,7 +13,7 @@ /// @since 2019-12-18 /// @brief Basic DPL workflow for TOF raw data compression -#include "TOFCompression/CompressedInspectorTask.h" +#include "TOFWorkflow/CompressedInspectorTask.h" #include "Framework/WorkflowSpec.h" #include "Framework/ConfigParamSpec.h" #include "FairLogger.h" diff --git a/Detectors/TOF/reconstruction/CMakeLists.txt b/Detectors/TOF/reconstruction/CMakeLists.txt index 15f96109faad0..3bdd192d96c42 100644 --- a/Detectors/TOF/reconstruction/CMakeLists.txt +++ b/Detectors/TOF/reconstruction/CMakeLists.txt @@ -11,6 +11,7 @@ o2_add_library(TOFReconstruction SOURCES src/DataReader.cxx src/Clusterer.cxx src/ClustererTask.cxx src/Encoder.cxx + src/DecoderBase.cxx src/Decoder.cxx PUBLIC_LINK_LIBRARIES O2::TOFBase O2::DataFormatsTOF O2::SimulationDataFormat @@ -21,4 +22,5 @@ o2_target_root_dictionary(TOFReconstruction include/TOFReconstruction/Clusterer.h include/TOFReconstruction/ClustererTask.h include/TOFReconstruction/Encoder.h + include/TOFReconstruction/DecoderBase.h include/TOFReconstruction/Decoder.h) diff --git a/Detectors/TOF/reconstruction/include/TOFReconstruction/DecoderBase.h b/Detectors/TOF/reconstruction/include/TOFReconstruction/DecoderBase.h new file mode 100644 index 0000000000000..34a4fb991b27b --- /dev/null +++ b/Detectors/TOF/reconstruction/include/TOFReconstruction/DecoderBase.h @@ -0,0 +1,93 @@ +// Copyright CERN and copyright holders of ALICE O2. This software is +// distributed under the terms of the GNU General Public License v3 (GPL +// Version 3), copied verbatim in the file "COPYING". +// +// See http://alice-o2.web.cern.ch/license for full licensing information. +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// @file Decoder.h +/// @author Roberto Preghenella +/// @since 2020-02-24 +/// @brief TOF compressed data decoder + +#ifndef O2_TOF_DECODERBASE +#define O2_TOF_DECODERBASE + +#include +#include +#include +#include +#include "Headers/RAWDataHeader.h" +#include "DataFormatsTOF/CompressedDataFormat.h" + +namespace o2 +{ +namespace tof +{ +namespace compressed +{ + +class DecoderBase +{ + + public: + DecoderBase() = default; + ~DecoderBase() = default; + + inline bool run() + { + rewind(); + while (!processHBF()) + ; + return false; + }; + + inline void rewind() + { + decoderRewind(); + }; + + void setDecoderVerbose(bool val) { mDecoderVerbose = val; }; + void setDecoderBuffer(char* val) { mDecoderBuffer = val; }; + void setDecoderBufferSize(long val) { mDecoderBufferSize = val; }; + + private: + /** handlers **/ + + virtual void rdhHandler(const o2::header::RAWDataHeader* rdh){}; + virtual void headerHandler(const CrateHeader_t* crateHeader, const CrateOrbit_t* crateOrbit){}; + + virtual void frameHandler(const CrateHeader_t* crateHeader, const CrateOrbit_t* crateOrbit, + const FrameHeader_t* frameHeader, const PackedHit_t* packedHits){}; + + virtual void trailerHandler(const CrateHeader_t* crateHeader, const CrateOrbit_t* crateOrbit, + const CrateTrailer_t* crateTrailer, const Diagnostic_t* diagnostics){}; + + bool processHBF(); + bool processDRM(); + + /** decoder private functions and data members **/ + inline void decoderRewind() { mDecoderPointer = reinterpret_cast(mDecoderBuffer); }; + + char* mDecoderBuffer = nullptr; + long mDecoderBufferSize; + uint32_t* mDecoderPointer = nullptr; + uint32_t* mDecoderPointerMax = nullptr; + uint32_t* mDecoderPointerNext = nullptr; + o2::header::RAWDataHeader* mDecoderRDH; + bool mDecoderVerbose = false; + bool mDecoderError = false; + bool mDecoderFatal = false; + char mDecoderSaveBuffer[1048576]; + uint32_t mDecoderSaveBufferDataSize = 0; + uint32_t mDecoderSaveBufferDataLeft = 0; +}; + +} // namespace compressed +} // namespace tof +} // namespace o2 + +#endif /** O2_TOF_DECODERBASE **/ diff --git a/Detectors/TOF/reconstruction/src/DecoderBase.cxx b/Detectors/TOF/reconstruction/src/DecoderBase.cxx new file mode 100644 index 0000000000000..04ac3c3c96711 --- /dev/null +++ b/Detectors/TOF/reconstruction/src/DecoderBase.cxx @@ -0,0 +1,237 @@ +// Copyright CERN and copyright holders of ALICE O2. This software is +// distributed under the terms of the GNU General Public License v3 (GPL +// Version 3), copied verbatim in the file "COPYING". +// +// See http://alice-o2.web.cern.ch/license for full licensing information. +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// @file Decoder.cxx +/// @author Roberto Preghenella +/// @since 2020-02-24 +/// @brief TOF compressed data decoder base class + +#include "TOFReconstruction/DecoderBase.h" +#include "DetectorsRaw/HBFUtils.h" + +#include +#include + +//#define DECODER_PARANOID +//#define DECODER_VERBOSE + +#ifdef DECODER_PARANOID +#warning "Building code with DecoderParanoid option. This may limit the speed." +#endif +#ifdef DECODER_VERBOSE +#warning "Building code with DecoderVerbose option. This may limit the speed." +#endif + +#define colorReset "\033[0m" +#define colorRed "\033[1;31m" +#define colorGreen "\033[1;32m" +#define colorYellow "\033[1;33m" +#define colorBlue "\033[1;34m" + +namespace o2 +{ +namespace tof +{ +namespace compressed +{ + +bool DecoderBase::processHBF() +{ + +#ifdef DECODER_VERBOSE + if (mDecoderVerbose) { + std::cout << colorBlue + << "--- PROCESS HBF" + << colorReset + << std::endl; + } +#endif + + mDecoderRDH = reinterpret_cast(mDecoderPointer); + auto rdh = mDecoderRDH; + + /** loop until RDH close **/ + while (!rdh->stop) { + +#ifdef DECODER_VERBOSE + if (mDecoderVerbose) { + std::cout << colorBlue + << "--- RDH open/continue detected" + << colorReset + << std::endl; + o2::raw::HBFUtils::printRDH(*rdh); + } +#endif + + /** rdh handler **/ + rdhHandler(rdh); + + auto headerSize = rdh->headerSize; + auto memorySize = rdh->memorySize; + auto offsetToNext = rdh->offsetToNext; + auto drmPayload = memorySize - headerSize; + + /** copy DRM payload to save buffer **/ + std::memcpy(mDecoderSaveBuffer + mDecoderSaveBufferDataSize, reinterpret_cast(rdh) + headerSize, drmPayload); + mDecoderSaveBufferDataSize += drmPayload; + + /** move to next RDH **/ + rdh = reinterpret_cast(reinterpret_cast(rdh) + offsetToNext); + + /** check next RDH is within buffer **/ + if (reinterpret_cast(rdh) < mDecoderBuffer + mDecoderBufferSize) + continue; + + /** otherwise return **/ + return true; + } + +#ifdef DECODER_VERBOSE + if (mDecoderVerbose) { + std::cout << colorBlue + << "--- RDH close detected" + << colorReset + << std::endl; + o2::raw::HBFUtils::printRDH(*rdh); + } +#endif + + /** process DRM data **/ + mDecoderPointer = reinterpret_cast(mDecoderSaveBuffer); + mDecoderPointerMax = reinterpret_cast(mDecoderSaveBuffer + mDecoderSaveBufferDataSize); + while (mDecoderPointer < mDecoderPointerMax) { + if (processDRM()) + break; + } + mDecoderSaveBufferDataSize = 0; + + /** rdh handler **/ + rdhHandler(rdh); + +#ifdef DECODER_VERBOSE + if (mDecoderVerbose) { + std::cout << colorBlue + << "--- END PROCESS HBF" + << colorReset + << std::endl; + } +#endif + + /** move to next RDH **/ + mDecoderPointer = reinterpret_cast(reinterpret_cast(rdh) + rdh->offsetToNext); + + /** check next RDH is within buffer **/ + if (reinterpret_cast(mDecoderPointer) < mDecoderBuffer + mDecoderBufferSize) + return false; + + /** otherwise return **/ + return true; +} + +bool DecoderBase::processDRM() +{ + +#ifdef DECODER_VERBOSE + if (mDecoderVerbose) { + std::cout << colorBlue << "--- PROCESS DRM" + << colorReset + << std::endl; + } +#endif + + if ((*mDecoderPointer & 0x80000000) != 0x80000000) { +#ifdef DECODER_VERBOSE + if (mDecoderVerbose) { + printf(" %08x [ERROR] \n ", *mDecoderPointer); + } +#endif + return true; + } + + /** crate header detected **/ + auto crateHeader = reinterpret_cast(mDecoderPointer); +#ifdef DECODER_VERBOSE + if (mDecoderVerbose) { + printf(" %08x CrateHeader (drmID=%d) \n ", *mDecoderPointer, crateHeader->drmID); + } +#endif + mDecoderPointer++; + + /** crate orbit expected **/ + auto crateOrbit = reinterpret_cast(mDecoderPointer); +#ifdef DECODER_VERBOSE + if (mDecoderVerbose) { + printf(" %08x CrateOrbit (orbit=0x%08x) \n ", *mDecoderPointer, crateOrbit->orbitID); + } +#endif + mDecoderPointer++; + + /** header handler **/ + headerHandler(crateHeader, crateOrbit); + + while (true) { + + /** crate trailer detected **/ + if (*mDecoderPointer & 0x80000000) { + auto crateTrailer = reinterpret_cast(mDecoderPointer); +#ifdef DECODER_VERBOSE + if (mDecoderVerbose) { + printf(" %08x CrateTrailer (numberOfDiagnostics=%d) \n ", *mDecoderPointer, crateTrailer->numberOfDiagnostics); + } +#endif + mDecoderPointer++; + auto diagnostics = reinterpret_cast(mDecoderPointer); +#ifdef DECODER_VERBOSE + if (mDecoderVerbose) { + for (int i = 0; i < crateTrailer->numberOfDiagnostics; ++i) { + auto diagnostic = reinterpret_cast(mDecoderPointer + i); + printf(" %08x Diagnostic (slotId=%d) \n ", *(mDecoderPointer + i), diagnostic->slotID); + } + } +#endif + mDecoderPointer += crateTrailer->numberOfDiagnostics; + + /** trailer handler **/ + trailerHandler(crateHeader, crateOrbit, crateTrailer, diagnostics); + + return false; + } + + /** frame header detected **/ + auto frameHeader = reinterpret_cast(mDecoderPointer); +#ifdef DECODER_VERBOSE + if (mDecoderVerbose) { + printf(" %08x FrameHeader (numberOfHits=%d) \n ", *mDecoderPointer, frameHeader->numberOfHits); + } +#endif + mDecoderPointer++; + auto packedHits = reinterpret_cast(mDecoderPointer); +#ifdef DECODER_VERBOSE + if (mDecoderVerbose) { + for (int i = 0; i < frameHeader->numberOfHits; ++i) { + auto packedHit = reinterpret_cast(mDecoderPointer + 1); + printf(" %08x PackedHit (tdcID=%d) \n ", *(mDecoderPointer + 1), packedHit->tdcID); + packedHits++; + } + } +#endif + mDecoderPointer += frameHeader->numberOfHits; + + /** frame handler **/ + frameHandler(crateHeader, crateOrbit, frameHeader, packedHits); + } + + /** should never reach here **/ + return false; +} + +} // namespace compressed +} // namespace tof +} // namespace o2 diff --git a/Detectors/TOF/workflow/CMakeLists.txt b/Detectors/TOF/workflow/CMakeLists.txt index 25fd0dd508a1b..6711de02442c8 100644 --- a/Detectors/TOF/workflow/CMakeLists.txt +++ b/Detectors/TOF/workflow/CMakeLists.txt @@ -16,6 +16,6 @@ o2_add_library(TOFWorkflowUtils src/TOFDigitWriterSpec.cxx src/TOFRawWriterSpec.cxx src/CompressedDecodingTask.cxx + src/CompressedInspectorTask.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::TOFBase O2::DataFormatsTOF O2::TOFReconstruction) - diff --git a/Detectors/TOF/workflow/include/TOFWorkflow/CompressedDecodingTask.h b/Detectors/TOF/workflow/include/TOFWorkflow/CompressedDecodingTask.h index 94cfa13fde891..22d68aa53afc0 100644 --- a/Detectors/TOF/workflow/include/TOFWorkflow/CompressedDecodingTask.h +++ b/Detectors/TOF/workflow/include/TOFWorkflow/CompressedDecodingTask.h @@ -19,6 +19,7 @@ #include "Framework/Task.h" #include "Framework/DataProcessorSpec.h" #include +#include "TOFReconstruction/DecoderBase.h" #include "TOFReconstruction/Decoder.h" #include "TOFBase/Digit.h" @@ -29,7 +30,9 @@ namespace o2 namespace tof { -class CompressedDecodingTask : public Task +using namespace compressed; + +class CompressedDecodingTask : public DecoderBase, public Task { public: CompressedDecodingTask() = default; @@ -40,6 +43,11 @@ class CompressedDecodingTask : public Task void postData(ProcessingContext& pc); private: + /** decoding handlers **/ + void rdhHandler(const o2::header::RAWDataHeader* rdh); + void frameHandler(const CrateHeader_t* crateHeader, const CrateOrbit_t* crateOrbit, + const FrameHeader_t* frameHeader, const PackedHit_t* packedHits); + bool mStatus = false; o2::tof::compressed::Decoder mDecoder; std::vector> mDigits; diff --git a/Detectors/TOF/compression/include/TOFCompression/CompressedInspectorTask.h b/Detectors/TOF/workflow/include/TOFWorkflow/CompressedInspectorTask.h similarity index 67% rename from Detectors/TOF/compression/include/TOFCompression/CompressedInspectorTask.h rename to Detectors/TOF/workflow/include/TOFWorkflow/CompressedInspectorTask.h index 365a700cf30ba..d4987dcfa8950 100644 --- a/Detectors/TOF/compression/include/TOFCompression/CompressedInspectorTask.h +++ b/Detectors/TOF/workflow/include/TOFWorkflow/CompressedInspectorTask.h @@ -18,6 +18,7 @@ #include "Framework/Task.h" #include "Framework/DataProcessorSpec.h" +#include "TOFReconstruction/DecoderBase.h" #include class TFile; @@ -31,7 +32,9 @@ namespace o2 namespace tof { -class CompressedInspectorTask : public Task +using namespace compressed; + +class CompressedInspectorTask : public DecoderBase, public Task { public: CompressedInspectorTask() = default; @@ -40,6 +43,15 @@ class CompressedInspectorTask : public Task void run(ProcessingContext& pc) final; private: + /** decoding handlers **/ + void headerHandler(const CrateHeader_t* crateHeader, const CrateOrbit_t* crateOrbit) override; + + void frameHandler(const CrateHeader_t* crateHeader, const CrateOrbit_t* crateOrbit, + const FrameHeader_t* frameHeader, const PackedHit_t* packedHits) override; + + void trailerHandler(const CrateHeader_t* crateHeader, const CrateOrbit_t* crateOrbit, + const CrateTrailer_t* crateTrailer, const Diagnostic_t* diagnostics) override; + bool mStatus = false; TFile* mFile = nullptr; std::map mHistos1D; diff --git a/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx b/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx index 3657df5ed54f7..69620da39e069 100644 --- a/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx +++ b/Detectors/TOF/workflow/src/CompressedDecodingTask.cxx @@ -91,114 +91,9 @@ void CompressedDecodingTask::run(ProcessingContext& pc) auto payloadIn = const_cast(input.payload); auto payloadInSize = headerIn->payloadSize; - /** process input **/ - auto pointer = payloadIn; - while (pointer < (payloadIn + payloadInSize)) { - auto rdh = reinterpret_cast(pointer); - - /** RDH close detected **/ - if (rdh->stop) { -#ifdef VERBOSE - std::cout << "--- RDH close detected" << std::endl; - o2::raw::HBFUtils::printRDH(*rdh); -#endif - if (rdh->heartbeatOrbit == 255 + mInitOrbit) { - mNCrateCloseTF++; - printf("New TF close RDH %d\n", rdh->feeId); - } - pointer += rdh->offsetToNext; - continue; - } - -#ifdef VERBOSE - std::cout << "--- RDH open detected" << std::endl; - o2::raw::HBFUtils::printRDH(*rdh); -#endif - - if ((rdh->pageCnt == 0) && (rdh->triggerType & o2::trigger::TF)) { - mNCrateOpenTF++; - mInitOrbit = rdh->heartbeatOrbit; - printf("New TF open RDH %d\n", rdh->feeId); - } - - pointer += rdh->headerSize; - - while (pointer < (reinterpret_cast(rdh) + rdh->memorySize)) { - - auto word = reinterpret_cast(pointer); - if ((*word & 0x80000000) != 0x80000000) { - printf(" %08x [ERROR] \n ", *(uint32_t*)pointer); - return; - } - - /** crate header detected **/ - auto crateHeader = reinterpret_cast(pointer); -#ifdef VERBOSE - printf(" %08x CrateHeader (drmID=%d) \n ", *(uint32_t*)pointer, crateHeader->drmID); -#endif - pointer += 4; - - /** crate orbit expected **/ - auto crateOrbit = reinterpret_cast(pointer); -#ifdef VERBOSE - printf(" %08x CrateOrbit (orbit=0x%08x) \n ", *(uint32_t*)pointer, crateOrbit->orbitID); -#endif - pointer += 4; - - while (true) { - word = reinterpret_cast(pointer); - - /** crate trailer detected **/ - if (*word & 0x80000000) { - auto crateTrailer = reinterpret_cast(pointer); -#ifdef VERBOSE - printf(" %08x CrateTrailer (numberOfDiagnostics=%d) \n ", *(uint32_t*)pointer, crateTrailer->numberOfDiagnostics); -#endif - pointer += 4; - - /** loop over diagnostics **/ - for (int i = 0; i < crateTrailer->numberOfDiagnostics; ++i) { - auto diagnostic = reinterpret_cast(pointer); -#ifdef VERBOSE - printf(" %08x Diagnostic (slotId=%d) \n ", *(uint32_t*)pointer, diagnostic->slotID); -#endif - pointer += 4; - } - - break; - } - - /** frame header detected **/ - auto frameHeader = reinterpret_cast(pointer); -#ifdef VERBOSE - printf(" %08x FrameHeader (numberOfHits=%d) \n ", *(uint32_t*)pointer, frameHeader->numberOfHits); -#endif - pointer += 4; - - /** loop over hits **/ - for (int i = 0; i < frameHeader->numberOfHits; ++i) { - auto packedHit = reinterpret_cast(pointer); -#ifdef VERBOSE - printf(" %08x PackedHit (tdcID=%d) \n ", *(uint32_t*)pointer, packedHit->tdcID); -#endif - auto indexE = packedHit->channel + - 8 * packedHit->tdcID + - 120 * packedHit->chain + - 240 * (frameHeader->trmID - 3) + - 2400 * crateHeader->drmID; - int time = packedHit->time; - time += (frameHeader->frameID << 13); - - // fill hit - mDecoder.InsertDigit(crateHeader->drmID, frameHeader->trmID, packedHit->tdcID, packedHit->chain, packedHit->channel, crateOrbit->orbitID, crateHeader->bunchID, frameHeader->frameID << 13, packedHit->time, packedHit->tot); - - pointer += 4; - } - } - } - - pointer = reinterpret_cast(rdh) + rdh->offsetToNext; - } + DecoderBase::setDecoderBuffer(payloadIn); + DecoderBase::setDecoderBufferSize(payloadInSize); + DecoderBase::run(); } if (mNCrateOpenTF == 72 && mNCrateOpenTF == mNCrateCloseTF) @@ -209,6 +104,33 @@ void CompressedDecodingTask::run(ProcessingContext& pc) } } +void CompressedDecodingTask::rdhHandler(const o2::header::RAWDataHeader* rdh) +{ + + // rdh close + if (rdh->stop && rdh->heartbeatOrbit == 255 + mInitOrbit) { + mNCrateCloseTF++; + printf("New TF close RDH %d\n", rdh->feeId); + return; + } + + // rdh open + if ((rdh->pageCnt == 0) && (rdh->triggerType & o2::trigger::TF)) { + mNCrateOpenTF++; + mInitOrbit = rdh->heartbeatOrbit; + printf("New TF open RDH %d\n", rdh->feeId); + } +}; + +void CompressedDecodingTask::frameHandler(const CrateHeader_t* crateHeader, const CrateOrbit_t* crateOrbit, + const FrameHeader_t* frameHeader, const PackedHit_t* packedHits) +{ + for (int i = 0; i < frameHeader->numberOfHits; ++i) { + auto packedHit = packedHits + i; + mDecoder.InsertDigit(crateHeader->drmID, frameHeader->trmID, packedHit->tdcID, packedHit->chain, packedHit->channel, crateOrbit->orbitID, crateHeader->bunchID, frameHeader->frameID << 13, packedHit->time, packedHit->tot); + } +}; + DataProcessorSpec getCompressedDecodingSpec(std::string inputDesc) { std::vector outputs; diff --git a/Detectors/TOF/workflow/src/CompressedInspectorTask.cxx b/Detectors/TOF/workflow/src/CompressedInspectorTask.cxx new file mode 100644 index 0000000000000..6357ac351d2b0 --- /dev/null +++ b/Detectors/TOF/workflow/src/CompressedInspectorTask.cxx @@ -0,0 +1,134 @@ +// Copyright CERN and copyright holders of ALICE O2. This software is +// distributed under the terms of the GNU General Public License v3 (GPL +// Version 3), copied verbatim in the file "COPYING". +// +// See http://alice-o2.web.cern.ch/license for full licensing information. +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// @file CompressedInspectorTask.cxx +/// @author Roberto Preghenella +/// @since 2020-01-25 +/// @brief TOF compressed data inspector task + +#include "TOFWorkflow/CompressedInspectorTask.h" +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" + +#include "Headers/RAWDataHeader.h" +#include "DataFormatsTOF/CompressedDataFormat.h" + +#include "TFile.h" +#include "TH1F.h" +#include "TH2F.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace tof +{ + +void CompressedInspectorTask::init(InitContext& ic) +{ + LOG(INFO) << "CompressedInspector init"; + auto filename = ic.options().get("tof-inspector-filename"); + + /** open file **/ + if (mFile && mFile->IsOpen()) { + LOG(WARNING) << "a file was already open, closing"; + mFile->Close(); + delete mFile; + } + mFile = TFile::Open(filename.c_str(), "RECREATE"); + if (!mFile || !mFile->IsOpen()) { + LOG(ERROR) << "cannot open output file: " << filename; + mStatus = true; + return; + } + + mHistos1D["hHisto"] = new TH1F("hHisto", "", 1000, 0., 1000.); + mHistos1D["time"] = new TH1F("hTime", ";time (24.4 ps)", 2097152, 0., 2097152.); + mHistos1D["timebc"] = new TH1F("hTimeBC", ";time (24.4 ps)", 1024, 0., 1024.); + mHistos1D["tot"] = new TH1F("hTOT", ";ToT (48.8 ps)", 2048, 0., 2048.); + mHistos1D["indexE"] = new TH1F("hIndexE", ";index EO", 172800, 0., 172800.); + mHistos2D["slotEnableMask"] = new TH2F("hSlotEnableMask", ";crate;slot", 72, 0., 72., 12, 1., 13.); + mHistos2D["diagnostic"] = new TH2F("hDiagnostic", ";crate;slot", 72, 0., 72., 12, 1., 13.); + + auto finishFunction = [this]() { + LOG(INFO) << "CompressedInspector finish"; + for (auto& histo : mHistos1D) + histo.second->Write(); + for (auto& histo : mHistos2D) + histo.second->Write(); + mFile->Close(); + }; + ic.services().get().set(CallbackService::Id::Stop, finishFunction); +} + +void CompressedInspectorTask::run(ProcessingContext& pc) +{ + LOG(DEBUG) << "CompressedInspector run"; + + /** check status **/ + if (mStatus) { + pc.services().get().readyToQuit(QuitRequest::Me); + return; + } + + /** receive input **/ + for (auto& input : pc.inputs()) { + + /** input **/ + const auto* headerIn = DataRefUtils::getHeader(input); + auto payloadIn = const_cast(input.payload); + auto payloadInSize = headerIn->payloadSize; + + setDecoderBuffer(payloadIn); + setDecoderBufferSize(payloadInSize); + DecoderBase::run(); + } +} + +void CompressedInspectorTask::headerHandler(const CrateHeader_t* crateHeader, const CrateOrbit_t* crateOrbit) +{ + for (int ibit = 0; ibit < 11; ++ibit) + if (crateHeader->slotEnableMask & (1 << ibit)) + mHistos2D["slotEnableMask"]->Fill(crateHeader->drmID, ibit + 2); +}; + +void CompressedInspectorTask::frameHandler(const CrateHeader_t* crateHeader, const CrateOrbit_t* crateOrbit, + const FrameHeader_t* frameHeader, const PackedHit_t* packedHits) +{ + mHistos1D["hHisto"]->Fill(frameHeader->numberOfHits); + for (int i = 0; i < frameHeader->numberOfHits; ++i) { + auto packedHit = packedHits + i; + auto indexE = packedHit->channel + + 8 * packedHit->tdcID + + 120 * packedHit->chain + + 240 * (frameHeader->trmID - 3) + + 2400 * crateHeader->drmID; + int time = packedHit->time; + int timebc = time % 1024; + time += (frameHeader->frameID << 13); + + mHistos1D["indexE"]->Fill(indexE); + mHistos1D["time"]->Fill(time); + mHistos1D["timebc"]->Fill(timebc); + mHistos1D["tot"]->Fill(packedHit->tot); + } +}; + +void CompressedInspectorTask::trailerHandler(const CrateHeader_t* crateHeader, const CrateOrbit_t* crateOrbit, + const CrateTrailer_t* crateTrailer, const Diagnostic_t* diagnostics) +{ + for (int i = 0; i < crateTrailer->numberOfDiagnostics; ++i) { + auto diagnostic = diagnostics + i; + mHistos2D["diagnostic"]->Fill(crateHeader->drmID, diagnostic->slotID); + } +}; + +} // namespace tof +} // namespace o2