|
| 1 | +// Copyright CERN and copyright holders of ALICE O2. This software is |
| 2 | +// distributed under the terms of the GNU General Public License v3 (GPL |
| 3 | +// Version 3), copied verbatim in the file "COPYING". |
| 4 | +// |
| 5 | +// See http://alice-o2.web.cern.ch/license for full licensing information. |
| 6 | +// |
| 7 | +// In applying this license CERN does not waive the privileges and immunities |
| 8 | +// granted to it by virtue of its status as an Intergovernmental Organization |
| 9 | +// or submit itself to any jurisdiction. |
| 10 | + |
| 11 | +/// \file MID/Workflow/src/RawGBTDecoderSpec.cxx |
| 12 | +/// \brief Data processor spec for MID GBT raw decoder device |
| 13 | +/// \author Diego Stocco <Diego.Stocco at cern.ch> |
| 14 | +/// \date 06 April 2020 |
| 15 | + |
| 16 | +#include "MIDWorkflow/RawGBTDecoderSpec.h" |
| 17 | + |
| 18 | +#include <chrono> |
| 19 | +#include <vector> |
| 20 | +#include "DPLUtils/DPLRawParser.h" |
| 21 | +#include "DetectorsRaw/RDHUtils.h" |
| 22 | +#include "Framework/ConfigParamRegistry.h" |
| 23 | +#include "Framework/ControlService.h" |
| 24 | +#include "Framework/DataSpecUtils.h" |
| 25 | +#include "Framework/Logger.h" |
| 26 | +#include "Framework/Output.h" |
| 27 | +#include "Framework/ParallelContext.h" |
| 28 | +#include "Framework/Task.h" |
| 29 | +#include "Headers/RDHAny.h" |
| 30 | +#include "DetectorsRaw/RDHUtils.h" |
| 31 | +#include "DataFormatsMID/ROFRecord.h" |
| 32 | +#include "MIDRaw/GBTDecoder.h" |
| 33 | +#include "MIDRaw/LocalBoardRO.h" |
| 34 | + |
| 35 | +namespace o2 |
| 36 | +{ |
| 37 | +namespace mid |
| 38 | +{ |
| 39 | + |
| 40 | +class RawGBTDecoderDeviceDPL |
| 41 | +{ |
| 42 | + public: |
| 43 | + RawGBTDecoderDeviceDPL(bool isDebugMode, const std::vector<uint16_t>& feeIds, const CrateMasks& crateMasks, const ElectronicsDelay& electronicsDelay) : mIsDebugMode(isDebugMode), mFeeIds(feeIds), mCrateMasks(crateMasks), mElectronicsDelay(electronicsDelay) {} |
| 44 | + |
| 45 | + void init(o2::framework::InitContext& ic) |
| 46 | + { |
| 47 | + auto stop = [this]() { |
| 48 | + double scaleFactor = 1.e6 / mNROFs; |
| 49 | + LOG(INFO) << "Processing time / " << mNROFs << " ROFs: full: " << mTimer.count() * scaleFactor << " us decoding: " << mTimerAlgo.count() * scaleFactor << " us"; |
| 50 | + }; |
| 51 | + ic.services().get<o2::framework::CallbackService>().set(o2::framework::CallbackService::Id::Stop, stop); |
| 52 | + |
| 53 | + auto idx = ic.services().get<o2::framework::ParallelContext>().index1D(); |
| 54 | + mFeeId = mFeeIds[idx]; |
| 55 | + } |
| 56 | + |
| 57 | + void run(o2::framework::ProcessingContext& pc) |
| 58 | + { |
| 59 | + auto tStart = std::chrono::high_resolution_clock::now(); |
| 60 | + |
| 61 | + o2::framework::DPLRawParser parser(pc.inputs()); |
| 62 | + |
| 63 | + auto tAlgoStart = std::chrono::high_resolution_clock::now(); |
| 64 | + |
| 65 | + o2::header::DataHeader const* dh = nullptr; |
| 66 | + |
| 67 | + if (!mDecoder) { |
| 68 | + auto const* rdhPtr = reinterpret_cast<const o2::header::RDHAny*>(parser.begin().raw()); |
| 69 | + mDecoder = createGBTDecoder(*rdhPtr, mFeeId, mIsDebugMode, mCrateMasks.getMask(mFeeId), mElectronicsDelay); |
| 70 | + } |
| 71 | + |
| 72 | + std::vector<LocalBoardRO> data; |
| 73 | + std::vector<ROFRecord> rofRecords; |
| 74 | + |
| 75 | + for (auto it = parser.begin(), end = parser.end(); it != end; ++it) { |
| 76 | + dh = it.o2DataHeader(); |
| 77 | + auto const* rdhPtr = reinterpret_cast<const o2::header::RDHAny*>(it.raw()); |
| 78 | + gsl::span<const uint8_t> payload(it.data(), it.size()); |
| 79 | + mDecoder->process(payload, o2::raw::RDHUtils::getHeartBeatOrbit(rdhPtr), data, rofRecords); |
| 80 | + } |
| 81 | + |
| 82 | + mTimerAlgo += std::chrono::high_resolution_clock::now() - tAlgoStart; |
| 83 | + |
| 84 | + pc.outputs().snapshot(o2::framework::Output{header::gDataOriginMID, "DECODED", dh->subSpecification, o2::framework::Lifetime::Timeframe}, data); |
| 85 | + pc.outputs().snapshot(o2::framework::Output{header::gDataOriginMID, "DECODEDROF", dh->subSpecification, o2::framework::Lifetime::Timeframe}, rofRecords); |
| 86 | + |
| 87 | + mTimer += std::chrono::high_resolution_clock::now() - tStart; |
| 88 | + mNROFs += rofRecords.size(); |
| 89 | + } |
| 90 | + |
| 91 | + private: |
| 92 | + std::unique_ptr<GBTDecoder> mDecoder{nullptr}; |
| 93 | + bool mIsDebugMode{false}; |
| 94 | + std::vector<uint16_t> mFeeIds{}; |
| 95 | + CrateMasks mCrateMasks{}; |
| 96 | + ElectronicsDelay mElectronicsDelay{}; |
| 97 | + uint16_t mFeeId{0}; |
| 98 | + std::chrono::duration<double> mTimer{0}; ///< full timer |
| 99 | + std::chrono::duration<double> mTimerAlgo{0}; ///< algorithm timer |
| 100 | + unsigned int mNROFs{0}; /// Total number of processed ROFs |
| 101 | +}; |
| 102 | + |
| 103 | +framework::DataProcessorSpec getRawGBTDecoderSpec(bool isDebugMode, const std::vector<uint16_t>& feeIds, const CrateMasks& crateMasks, const ElectronicsDelay& electronicsDelay) |
| 104 | +{ |
| 105 | + std::vector<o2::framework::InputSpec> inputSpecs{o2::framework::InputSpec{"mid_raw", header::gDataOriginMID, header::gDataDescriptionRawData, 0, o2::framework::Lifetime::Timeframe}}; |
| 106 | + std::vector<o2::framework::OutputSpec> outputSpecs{o2::framework::OutputSpec{header::gDataOriginMID, "DECODED", 0, o2::framework::Lifetime::Timeframe}, o2::framework::OutputSpec{header::gDataOriginMID, "DECODEDROF", 0, o2::framework::Lifetime::Timeframe}}; |
| 107 | + |
| 108 | + return o2::framework::DataProcessorSpec{ |
| 109 | + "MIDRawGBTDecoder", |
| 110 | + {inputSpecs}, |
| 111 | + {outputSpecs}, |
| 112 | + o2::framework::adaptFromTask<RawGBTDecoderDeviceDPL>(isDebugMode, feeIds, crateMasks, electronicsDelay)}; |
| 113 | +} |
| 114 | + |
| 115 | +} // namespace mid |
| 116 | +} // namespace o2 |
0 commit comments