Newer
Older
/*
Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
*/
#include <numeric>
#include <set>
#include <utility>
#include "GaudiKernel/IInterface.h"
#include "GaudiKernel/MsgStream.h"
#include "GaudiKernel/StatusCode.h"
#include "ByteStreamCnvSvcBase/FullEventAssembler.h"
#include "TrigT1CaloEvent/CMMJetHits.h"
#include "TrigT1CaloEvent/CMMEtSums.h"
#include "TrigT1CaloEvent/JEMHits.h"
#include "TrigT1CaloEvent/JEMEtSums.h"
#include "TrigT1CaloEvent/JEPBSCollectionV1.h"
#include "TrigT1CaloEvent/JetElement.h"
#include "TrigT1CaloUtils/DataError.h"
#include "TrigT1CaloUtils/JetElementKey.h"
#include "TrigT1CaloToolInterfaces/IL1CaloMappingTool.h"
#include "CmmEnergySubBlock.h"
#include "CmmJetSubBlock.h"
#include "CmmSubBlock.h"
#include "JemJetElement.h"
#include "JemSubBlockV1.h"
#include "L1CaloErrorByteStreamTool.h"
#include "L1CaloSrcIdMap.h"
#include "L1CaloSubBlock.h"
#include "L1CaloUserHeader.h"
#include "ModifySlices.h"
#include "JepByteStreamV1Tool.h"
namespace LVL1BS {
// Interface ID
static const InterfaceID IID_IJepByteStreamV1Tool("JepByteStreamV1Tool", 1, 1);
const InterfaceID& JepByteStreamV1Tool::interfaceID()
{
return IID_IJepByteStreamV1Tool;
}
// Constructor
JepByteStreamV1Tool::JepByteStreamV1Tool(const std::string& type,
const std::string& name,
const IInterface* parent)
: AthAlgTool(type, name, parent),
m_jemMaps("LVL1::JemMappingTool/JemMappingTool"),
m_errorTool("LVL1BS::L1CaloErrorByteStreamTool/L1CaloErrorByteStreamTool"),
m_channels(44), m_crates(2), m_modules(16),
m_subDetector(eformat::TDAQ_CALO_JET_PROC_DAQ)
{
declareInterface<JepByteStreamV1Tool>(this);
declareProperty("JemMappingTool", m_jemMaps,
"Crate/Module/Channel to Eta/Phi/Layer mapping tool");
declareProperty("ErrorTool", m_errorTool,
"Tool to collect errors for monitoring");
declareProperty("CrateOffsetHw", m_crateOffsetHw = 12,
"Offset of JEP crate numbers in bytestream");
declareProperty("CrateOffsetSw", m_crateOffsetSw = 0,
"Offset of JEP crate numbers in RDOs");
declareProperty("SlinksPerCrate", m_slinks = 4,
"The number of S-Links per crate");
// Properties for reading bytestream only
declareProperty("ROBSourceIDs", m_sourceIDsProp,
"ROB fragment source identifiers");
// Properties for writing bytestream only
declareProperty("DataVersion", m_version = 1,
"Format version number in sub-block header");
declareProperty("DataFormat", m_dataFormat = 1,
"Format identifier (0-1) in sub-block header");
declareProperty("SimulSlices", m_dfltSlices = 1,
"The number of slices in the simulation");
declareProperty("ForceSlices", m_forceSlices = 0,
"If >0, the number of slices in bytestream");
declareProperty("CrateMin", m_crateMin = 0,
"Minimum crate number, allows partial output");
declareProperty("CrateMax", m_crateMax = m_crates - 1,
"Maximum crate number, allows partial output");
}
// Destructor
JepByteStreamV1Tool::~JepByteStreamV1Tool()
{
}
// Initialize
StatusCode JepByteStreamV1Tool::initialize()
{
ATH_MSG_INFO ("Initializing " << name() << " - package version "
<< PACKAGE_VERSION);
ATH_CHECK( m_jemMaps.retrieve() );
ATH_CHECK( m_errorTool.retrieve() );
return StatusCode::SUCCESS;
}
// Finalize
StatusCode JepByteStreamV1Tool::finalize()
{
return StatusCode::SUCCESS;
}
// Conversion bytestream to jet elements
StatusCode JepByteStreamV1Tool::convert(
const std::string& sgKey,
const IROBDataProviderSvc::VROBFRAG& robFrags,
DataVector<LVL1::JetElement>* const jeCollection) const
{
JetElementData data (jeCollection);
return convertBs(sgKey, robFrags, data);
}
// Conversion bytestream to jet hits
StatusCode JepByteStreamV1Tool::convert(
const std::string& sgKey,
const IROBDataProviderSvc::VROBFRAG& robFrags,
DataVector<LVL1::JEMHits>* const hitCollection) const
{
JetHitsData data (hitCollection);
return convertBs(sgKey, robFrags, data);
}
// Conversion bytestream to energy sums
StatusCode JepByteStreamV1Tool::convert(
const std::string& sgKey,
const IROBDataProviderSvc::VROBFRAG& robFrags,
DataVector<LVL1::JEMEtSums>* const etCollection) const
{
EnergySumsData data (etCollection);
return convertBs(sgKey, robFrags, data);
}
// Conversion bytestream to CMM hits
StatusCode JepByteStreamV1Tool::convert(
const std::string& sgKey,
const IROBDataProviderSvc::VROBFRAG& robFrags,
DataVector<LVL1::CMMJetHits>* const hitCollection) const
{
CmmHitsData data (hitCollection);
return convertBs(sgKey, robFrags, data);
}
// Conversion bytestream to CMM energy sums
StatusCode JepByteStreamV1Tool::convert(
const std::string& sgKey,
const IROBDataProviderSvc::VROBFRAG& robFrags,
DataVector<LVL1::CMMEtSums>* const etCollection) const
{
CmmSumsData data (etCollection);
return convertBs(sgKey, robFrags, data);
}
// Conversion of JEP container to bytestream
StatusCode JepByteStreamV1Tool::convert(const LVL1::JEPBSCollectionV1* const jep,
RawEventWrite* const re) const
{
const bool debug = msgLvl(MSG::DEBUG);
if (debug) msg(MSG::DEBUG);
// Clear the event assembler
FullEventAssembler<L1CaloSrcIdMap> fea;
fea.clear();
const uint16_t minorVersion = m_srcIdMap.minorVersionPreLS1();
fea.setRodMinorVersion(minorVersion);
// Pointer to ROD data vector
FullEventAssembler<L1CaloSrcIdMap>::RODDATA* theROD = 0;
// Jet element key provider
LVL1::JetElementKey elementKey;
// Set up the container maps
// Jet element map
ConstJetElementMap jeMap;
setupJeMap(jep->JetElements(), jeMap, elementKey);
// Jet hits map
ConstJetHitsMap hitsMap;
setupHitsMap(jep->JetHits(), hitsMap);
// Energy sums map
ConstEnergySumsMap etMap;
setupEtMap(jep->EnergySums(), etMap);
// CMM hits map
ConstCmmHitsMap cmmHitsMap;
setupCmmHitsMap(jep->CmmHits(), cmmHitsMap);
// CMM energy sums map
ConstCmmSumsMap cmmEtMap;
setupCmmEtMap(jep->CmmSums(), cmmEtMap);
// Loop over data
const bool neutralFormat = m_dataFormat == L1CaloSubBlock::NEUTRAL;
const int modulesPerSlink = m_modules / m_slinks;
int timeslices = 1;
int trigJem = 0;
int timeslicesNew = 1;
int trigJemNew = 0;
for (int crate = m_crateMin; crate <= m_crateMax; ++crate) {
const int hwCrate = crate + m_crateOffsetHw;
for (int module = 0; module < m_modules; ++module) {
// Pack required number of modules per slink
if (module % modulesPerSlink == 0) {
const int daqOrRoi = 0;
const int slink = module / modulesPerSlink;
if (debug) {
msg() << "Treating crate " << hwCrate

Sasha Mazurov
committed
<< " slink " << slink << endmsg;
}
// Get number of JEM slices and triggered slice offset
// for this slink
if ( ! slinkSlices(crate, module, modulesPerSlink,
timeslices, trigJem,
jeMap,
hitsMap,
etMap,
cmmHitsMap,
cmmEtMap,
elementKey))
{
msg(MSG::ERROR) << "Inconsistent number of slices or "
<< "triggered slice offsets in data for crate "

Sasha Mazurov
committed
<< hwCrate << " slink " << slink << endmsg;
}
timeslicesNew = (m_forceSlices) ? m_forceSlices : timeslices;
trigJemNew = ModifySlices::peak(trigJem, timeslices, timeslicesNew);
if (debug) {

Sasha Mazurov
committed
<< " " << m_dataFormat << endmsg
<< "Slices/offset: " << timeslices << " " << trigJem;
if (timeslices != timeslicesNew) {
msg() << " modified to " << timeslicesNew << " " << trigJemNew;
}

Sasha Mazurov
committed
msg() << endmsg;
}
L1CaloUserHeader userHeader;
userHeader.setJem(trigJemNew);
const uint32_t rodIdJem = m_srcIdMap.getRodID(hwCrate, slink, daqOrRoi,
theROD = fea.getRodData(rodIdJem);
}

Sasha Mazurov
committed
if (debug) msg() << "Module " << module << endmsg;
// Create a sub-block for each slice (except Neutral format)
// Vector for current JEM sub-blocks
DataVector<JemSubBlockV1> jemBlocks;
for (int slice = 0; slice < timeslicesNew; ++slice) {
JemSubBlockV1* const subBlock = new JemSubBlockV1();
subBlock->setJemHeader(m_version, m_dataFormat, slice,
hwCrate, module, timeslicesNew);
jemBlocks.push_back(subBlock);
}
// Find jet elements corresponding to each eta/phi pair and fill
// sub-blocks
for (int chan = 0; chan < m_channels; ++chan) {
double eta = 0.;
double phi = 0.;
int layer = 0;
if (m_jemMaps->mapping(crate, module, chan, eta, phi, layer)) {
const LVL1::JetElement* const je = findJetElement(eta, phi, jeMap, elementKey);
if (je ) {
std::vector<int> emData;
std::vector<int> hadData;
std::vector<int> emErrors;
std::vector<int> hadErrors;
ModifySlices::data(je->emEnergyVec(), emData, timeslicesNew);
ModifySlices::data(je->hadEnergyVec(), hadData, timeslicesNew);
ModifySlices::data(je->emErrorVec(), emErrors, timeslicesNew);
ModifySlices::data(je->hadErrorVec(), hadErrors, timeslicesNew);
for (int slice = 0; slice < timeslicesNew; ++slice) {
const LVL1::DataError emErrBits(emErrors[slice]);
const LVL1::DataError hadErrBits(hadErrors[slice]);
const int index = ( neutralFormat ) ? 0 : slice;
JemSubBlockV1* const subBlock = jemBlocks[index];
const JemJetElement jetEle(chan, emData[slice], hadData[slice],
emErrBits.get(LVL1::DataError::Parity),
hadErrBits.get(LVL1::DataError::Parity),
emErrBits.get(LVL1::DataError::LinkDown) +
(hadErrBits.get(LVL1::DataError::LinkDown) << 1));
subBlock->fillJetElement(slice, jetEle);
}
}
}
// Add jet hits and energy subsums
const LVL1::JEMHits* const hits = findJetHits(crate, module, hitsMap);
if (hits) {
std::vector<unsigned int> vec;
ModifySlices::data(hits->JetHitsVec(), vec, timeslicesNew);
for (int slice = 0; slice < timeslicesNew; ++slice) {
const int index = ( neutralFormat ) ? 0 : slice;
JemSubBlockV1* const subBlock = jemBlocks[index];
}
}
const LVL1::JEMEtSums* const et = findEnergySums(crate, module, etMap);
if (et) {
std::vector<unsigned int> exVec;
std::vector<unsigned int> eyVec;
std::vector<unsigned int> etVec;
ModifySlices::data(et->ExVec(), exVec, timeslicesNew);
ModifySlices::data(et->EyVec(), eyVec, timeslicesNew);
ModifySlices::data(et->EtVec(), etVec, timeslicesNew);
for (int slice = 0; slice < timeslicesNew; ++slice) {
const int index = ( neutralFormat ) ? 0 : slice;
JemSubBlockV1* const subBlock = jemBlocks[index];
subBlock->setEnergySubsums(slice, exVec[slice], eyVec[slice],
etVec[slice]);
}
}
// Pack and write the sub-blocks
for (pos = jemBlocks.begin(); pos != jemBlocks.end(); ++pos) {
JemSubBlockV1* const subBlock = *pos;

Sasha Mazurov
committed
msg(MSG::ERROR) << "JEM sub-block packing failed" << endmsg;
return StatusCode::FAILURE;
}
if (debug) {
msg() << "JEM sub-block data words: "

Sasha Mazurov
committed
<< subBlock->dataWords() << endmsg;
}
}
// Append CMMs to last S-Link of the crate
// Create a sub-block for each slice (except Neutral format)
// Vector for current CMM-Energy sub-blocks
DataVector<CmmEnergySubBlock> cmmEnergyBlocks;
// Vector for current CMM-Jet sub-blocks
DataVector<CmmJetSubBlock> cmmJetBlocks;
const int summing = (crate == m_crates - 1) ? CmmSubBlock::SYSTEM
for (int slice = 0; slice < timeslicesNew; ++slice) {
CmmEnergySubBlock* const enBlock = new CmmEnergySubBlock();
const int cmmEnergyVersion = 2; // with Missing-ET-Sig
enBlock->setCmmHeader(cmmEnergyVersion, m_dataFormat, slice, hwCrate,
summing, CmmSubBlock::CMM_ENERGY,
cmmEnergyBlocks.push_back(enBlock);
CmmJetSubBlock* const jetBlock = new CmmJetSubBlock();
jetBlock->setCmmHeader(m_version, m_dataFormat, slice, hwCrate,
summing, CmmSubBlock::CMM_JET,
cmmJetBlocks.push_back(jetBlock);
if (neutralFormat) break;
}
// CMM-Energy
int maxDataID = static_cast<int>(LVL1::CMMEtSums::MAXID);
for (int dataID = 0; dataID < maxDataID; ++dataID) {
int source = dataID;
if (dataID >= m_modules) {
if (summing == CmmSubBlock::CRATE &&
dataID != LVL1::CMMEtSums::LOCAL) continue;
// coverity[mixed_enums : FALSE]
// coverity[switch_on_enum : FALSE]
// coverity[first_enum_type : FALSE]
switch (dataID) {
case LVL1::CMMEtSums::LOCAL:
source = CmmEnergySubBlock::LOCAL;
break;
case LVL1::CMMEtSums::REMOTE:
source = CmmEnergySubBlock::REMOTE;
break;
case LVL1::CMMEtSums::TOTAL:
source = CmmEnergySubBlock::TOTAL;
break;
case LVL1::CMMEtSums::MISSING_ET_MAP:
case LVL1::CMMEtSums::SUM_ET_MAP:
case LVL1::CMMEtSums::MISSING_ET_SIG_MAP:
break;
default:
continue;
}
}
const LVL1::CMMEtSums* const sums = findCmmSums(crate, dataID, cmmEtMap);
if ( sums ) {
std::vector<unsigned int> ex;
std::vector<unsigned int> ey;
std::vector<unsigned int> et;
std::vector<int> exErr;
std::vector<int> eyErr;
std::vector<int> etErr;
ModifySlices::data(sums->ExVec(), ex, timeslicesNew);
ModifySlices::data(sums->EyVec(), ey, timeslicesNew);
ModifySlices::data(sums->EtVec(), et, timeslicesNew);
ModifySlices::data(sums->ExErrorVec(), exErr, timeslicesNew);
ModifySlices::data(sums->EyErrorVec(), eyErr, timeslicesNew);
ModifySlices::data(sums->EtErrorVec(), etErr, timeslicesNew);
for (int slice = 0; slice < timeslicesNew; ++slice) {
const LVL1::DataError exErrBits(exErr[slice]);
const LVL1::DataError eyErrBits(eyErr[slice]);
const LVL1::DataError etErrBits(etErr[slice]);
int exError = exErrBits.get(LVL1::DataError::Parity);
int eyError = eyErrBits.get(LVL1::DataError::Parity);
int etError = etErrBits.get(LVL1::DataError::Parity);
if (dataID == LVL1::CMMEtSums::LOCAL ||
dataID == LVL1::CMMEtSums::REMOTE ||
dataID == LVL1::CMMEtSums::TOTAL) {
exError = (exError << 1) + exErrBits.get(LVL1::DataError::Overflow);
eyError = (eyError << 1) + eyErrBits.get(LVL1::DataError::Overflow);
etError = (etError << 1) + etErrBits.get(LVL1::DataError::Overflow);
}
const int index = ( neutralFormat ) ? 0 : slice;
CmmEnergySubBlock* const subBlock = cmmEnergyBlocks[index];
if (dataID == LVL1::CMMEtSums::MISSING_ET_MAP) {
subBlock->setMissingEtHits(slice, et[slice]);
} else if (dataID == LVL1::CMMEtSums::SUM_ET_MAP) {
subBlock->setSumEtHits(slice, et[slice]);
} else if (dataID == LVL1::CMMEtSums::MISSING_ET_SIG_MAP) {
subBlock->setMissingEtSigHits(slice, et[slice]);
} else {
subBlock->setSubsums(slice, source,
ex[slice], ey[slice], et[slice],
exError, eyError, etError);
}
}
}
}
pos = cmmEnergyBlocks.begin();
for (; pos != cmmEnergyBlocks.end(); ++pos) {
CmmEnergySubBlock* const subBlock = *pos;
if ( !subBlock->pack()) {

Sasha Mazurov
committed
msg(MSG::ERROR) << "CMM-Energy sub-block packing failed" << endmsg;
}
if (debug) {

Sasha Mazurov
committed
<< subBlock->dataWords() << endmsg;
}
subBlock->write(theROD);
}
// CMM-Jet
maxDataID = static_cast<int>(LVL1::CMMJetHits::MAXID);
for (int dataID = 0; dataID < maxDataID; ++dataID) {
int source = dataID;
if (dataID >= m_modules) {
if (summing == CmmSubBlock::CRATE &&
dataID != LVL1::CMMJetHits::LOCAL_MAIN &&
dataID != LVL1::CMMJetHits::LOCAL_FORWARD) continue;
// coverity[mixed_enums : FALSE]
// coverity[switch_on_enum : FALSE]
// coverity[first_enum_type : FALSE]
switch (dataID) {
case LVL1::CMMJetHits::LOCAL_MAIN:
source = CmmJetSubBlock::LOCAL_MAIN;
break;
case LVL1::CMMJetHits::REMOTE_MAIN:
source = CmmJetSubBlock::REMOTE_MAIN;
break;
case LVL1::CMMJetHits::TOTAL_MAIN:
source = CmmJetSubBlock::TOTAL_MAIN;
break;
case LVL1::CMMJetHits::LOCAL_FORWARD:
source = CmmJetSubBlock::LOCAL_FORWARD;
break;
case LVL1::CMMJetHits::REMOTE_FORWARD:
source = CmmJetSubBlock::REMOTE_FORWARD;
break;
case LVL1::CMMJetHits::TOTAL_FORWARD:
source = CmmJetSubBlock::TOTAL_FORWARD;
break;
case LVL1::CMMJetHits::ET_MAP:
break;
default:
continue;
}
}
const LVL1::CMMJetHits* const ch = findCmmHits(crate, dataID, cmmHitsMap);
if ( ch ) {
std::vector<unsigned int> hits;
std::vector<int> errs;
ModifySlices::data(ch->HitsVec(), hits, timeslicesNew);
ModifySlices::data(ch->ErrorVec(), errs, timeslicesNew);
for (int slice = 0; slice < timeslicesNew; ++slice) {
const LVL1::DataError errBits(errs[slice]);
const int index = ( neutralFormat ) ? 0 : slice;
CmmJetSubBlock* const subBlock = cmmJetBlocks[index];
if (dataID == LVL1::CMMJetHits::ET_MAP) {
subBlock->setJetEtMap(slice, hits[slice]);
} else {
subBlock->setJetHits(slice, source, hits[slice],
errBits.get(LVL1::DataError::Parity));
}
}
}
}
jos = cmmJetBlocks.begin();
for (; jos != cmmJetBlocks.end(); ++jos) {
CmmJetSubBlock* const subBlock = *jos;
if ( !subBlock->pack()) {

Sasha Mazurov
committed
msg(MSG::ERROR) << "CMM-Jet sub-block packing failed" << endmsg;
}
if (debug) {

Sasha Mazurov
committed
<< subBlock->dataWords() << endmsg;
}
subBlock->write(theROD);
}
}
// Fill the raw event
fea.fill(re, msg());
return StatusCode::SUCCESS;
}
// Return reference to vector with all possible Source Identifiers
std::vector<uint32_t> JepByteStreamV1Tool::makeSourceIDs() const
{
std::vector<uint32_t> sourceIDs;
if (!m_sourceIDsProp.empty()) {
sourceIDs = m_sourceIDsProp;
}
else {
const int maxCrates = m_crates + m_crateOffsetHw;
const int maxSlinks = m_srcIdMap.maxSlinks();
for (int hwCrate = m_crateOffsetHw; hwCrate < maxCrates; ++hwCrate)
{
for (int slink = 0; slink < maxSlinks; ++slink)
{
const int daqOrRoi = 0;
const uint32_t rodId = m_srcIdMap.getRodID(hwCrate, slink, daqOrRoi,
m_subDetector);
const uint32_t robId = m_srcIdMap.getRobID(rodId);
sourceIDs.push_back(robId);
}
}
}
return sourceIDs;
}
const std::vector<uint32_t>& JepByteStreamV1Tool::sourceIDs() const
{
static const std::vector<uint32_t> sourceIDs = makeSourceIDs();
return sourceIDs;
}
// Convert bytestream to given container type
StatusCode JepByteStreamV1Tool::convertBs(
const std::string& sgKey,
const IROBDataProviderSvc::VROBFRAG& robFrags,
JepByteStreamToolData& data) const
{
LocalData ld;
// Check if overlap jet element channels wanted
const std::string flag("Overlap");
const std::string::size_type pos = sgKey.find(flag);
ld.coreOverlap =
(pos == std::string::npos || pos != sgKey.length() - flag.length()) ? 0 : 1;
const bool debug = msgLvl(MSG::DEBUG);
if (debug) msg(MSG::DEBUG);
// JemSubBlock for unpacking
JemSubBlockV1 jemSubBlock;
// CmmEnergySubBlock for unpacking
CmmEnergySubBlock cmmEnergySubBlock;
// CmmJetSubBlock for unpacking
CmmJetSubBlock cmmJetSubBlock;
// Loop over ROB fragments
int robCount = 0;
std::set<uint32_t> dupCheck;
ROBIterator rob = robFrags.begin();
ROBIterator robEnd = robFrags.end();
for (; rob != robEnd; ++rob) {
if (debug) {
++robCount;

Sasha Mazurov
committed
msg() << "Treating ROB fragment " << robCount << endmsg;
}
// Skip fragments with ROB status errors
uint32_t robid = (*rob)->source_id();
if ((*rob)->nstatus() > 0) {
ROBPointer robData;
(*rob)->status(robData);
if (*robData != 0) {
m_errorTool->robError(robid, *robData);

Sasha Mazurov
committed
if (debug) msg() << "ROB status error - skipping fragment" << endmsg;
}
}
// Skip duplicate fragments
if (!dupCheck.insert(robid).second) {
m_errorTool->rodError(robid, L1CaloSubBlock::ERROR_DUPLICATE_ROB);

Sasha Mazurov
committed
if (debug) msg() << "Skipping duplicate ROB fragment" << endmsg;
continue;
}
// Unpack ROD data (slinks)
RODPointer payloadBeg;
RODPointer payload;
RODPointer payloadEnd;
(*rob)->rod_data(payloadBeg);
payloadEnd = payloadBeg + (*rob)->rod_ndata();
payload = payloadBeg;
if (payload == payloadEnd) {

Sasha Mazurov
committed
if (debug) msg() << "ROB fragment empty" << endmsg;
continue;
}
// Check identifier
const uint32_t sourceID = (*rob)->rod_source_id();
if (m_srcIdMap.getRobID(sourceID) != robid ||
m_srcIdMap.subDet(sourceID) != m_subDetector ||
m_srcIdMap.daqOrRoi(sourceID) != 0 ||
m_srcIdMap.slink(sourceID) >= m_slinks ||
m_srcIdMap.crate(sourceID) < m_crateOffsetHw ||
m_srcIdMap.crate(sourceID) >= m_crateOffsetHw + m_crates) {
m_errorTool->rodError(robid, L1CaloSubBlock::ERROR_ROD_ID);
if (debug) {
msg() << "Wrong source identifier in data: ROD "
<< MSG::hex << sourceID << " ROB " << robid

Sasha Mazurov
committed
<< MSG::dec << endmsg;
}
continue;
}
// Check minor version
const int minorVersion = (*rob)->rod_version() & 0xffff;
if (minorVersion > m_srcIdMap.minorVersionPreLS1()) {

Sasha Mazurov
committed
if (debug) msg() << "Skipping post-LS1 data" << endmsg;
continue;
}
const int rodCrate = m_srcIdMap.crate(sourceID);
if (debug) {
<< " slink " << m_srcIdMap.slink(sourceID) << endmsg;
}
// First word should be User Header
if ( !L1CaloUserHeader::isValid(*payload) ) {
m_errorTool->rodError(robid, L1CaloSubBlock::ERROR_USER_HEADER);

Sasha Mazurov
committed
if (debug) msg() << "Invalid or missing user header" << endmsg;
continue;
}
L1CaloUserHeader userHeader(*payload);
userHeader.setVersion(minorVersion);
const int headerWords = userHeader.words();
if (headerWords != 1) {
m_errorTool->rodError(robid, L1CaloSubBlock::ERROR_USER_HEADER);
if (debug) msg() << "Unexpected number of user header words: "

Sasha Mazurov
committed
<< headerWords << endmsg;
continue;
}
for (int i = 0; i < headerWords; ++i) ++payload;
// triggered slice offsets
int trigJem = userHeader.jem();
int trigCmm = userHeader.jepCmm();
if (debug) {
msg() << "Minor format version number: " << MSG::hex

Sasha Mazurov
committed
<< minorVersion << MSG::dec << endmsg
<< "JEM triggered slice offset: " << trigJem << endmsg
<< "CMM triggered slice offset: " << trigCmm << endmsg;
}
if (trigJem != trigCmm) {
const int newTrig = (trigJem > trigCmm) ? trigJem : trigCmm;
trigJem = newTrig;
trigCmm = newTrig;

Sasha Mazurov
committed
if (debug) msg() << "Changed both offsets to " << newTrig << endmsg;
}
// Loop over sub-blocks
ld.rodErr = L1CaloSubBlock::ERROR_NONE;
while (payload != payloadEnd) {
if (L1CaloSubBlock::wordType(*payload) != L1CaloSubBlock::HEADER) {

Sasha Mazurov
committed
if (debug) msg() << "Unexpected data sequence" << endmsg;
ld.rodErr = L1CaloSubBlock::ERROR_MISSING_HEADER;
}
if (CmmSubBlock::cmmBlock(*payload)) {
// CMMs
if (CmmSubBlock::cmmType(*payload) == CmmSubBlock::CMM_JET) {
cmmJetSubBlock.clear();
payload = cmmJetSubBlock.read(payload, payloadEnd);
if (cmmJetSubBlock.crate() != rodCrate) {
if (debug) msg() << "Inconsistent crate number in ROD source ID"

Sasha Mazurov
committed
<< endmsg;
ld.rodErr = L1CaloSubBlock::ERROR_CRATE_NUMBER;
}
if (data.m_collection == CMM_HITS) {
decodeCmmJet(&cmmJetSubBlock, trigCmm, static_cast<CmmHitsData&>(data), ld);
if (ld.rodErr != L1CaloSubBlock::ERROR_NONE) {

Sasha Mazurov
committed
if (debug) msg() << "decodeCmmJet failed" << endmsg;
}
} else if (CmmSubBlock::cmmType(*payload) == CmmSubBlock::CMM_ENERGY) {
cmmEnergySubBlock.clear();
payload = cmmEnergySubBlock.read(payload, payloadEnd);
if (cmmEnergySubBlock.crate() != rodCrate) {
if (debug) msg() << "Inconsistent crate number in ROD source ID"

Sasha Mazurov
committed
<< endmsg;
ld.rodErr = L1CaloSubBlock::ERROR_CRATE_NUMBER;
}
if (data.m_collection == CMM_SUMS) {
decodeCmmEnergy(&cmmEnergySubBlock, trigCmm, static_cast<CmmSumsData&>(data), ld);
if (ld.rodErr != L1CaloSubBlock::ERROR_NONE) {

Sasha Mazurov
committed
if (debug) msg() << "decodeCmmEnergy failed" << endmsg;
}

Sasha Mazurov
committed
if (debug) msg() << "Invalid CMM type in module field" << endmsg;
ld.rodErr = L1CaloSubBlock::ERROR_MODULE_NUMBER;
}
} else {
// JEM
jemSubBlock.clear();
payload = jemSubBlock.read(payload, payloadEnd);
if (jemSubBlock.crate() != rodCrate) {
if (debug) msg() << "Inconsistent crate number in ROD source ID"

Sasha Mazurov
committed
<< endmsg;
ld.rodErr = L1CaloSubBlock::ERROR_CRATE_NUMBER;
}
if (data.m_collection == JET_ELEMENTS || data.m_collection == JET_HITS ||
data.m_collection == ENERGY_SUMS) {
decodeJem(&jemSubBlock, trigJem, data, ld);
if (ld.rodErr != L1CaloSubBlock::ERROR_NONE) {

Sasha Mazurov
committed
if (debug) msg() << "decodeJem failed" << endmsg;
}
}
}
if (ld.rodErr != L1CaloSubBlock::ERROR_NONE)
m_errorTool->rodError(robid, ld.rodErr);
}
return StatusCode::SUCCESS;
}
// Unpack CMM-Energy sub-block
void JepByteStreamV1Tool::decodeCmmEnergy(CmmEnergySubBlock* subBlock,
CmmSumsData& data,
LocalData& ld) const
{
const bool debug = msgLvl(MSG::DEBUG);
if (debug) msg(MSG::DEBUG);
const int hwCrate = subBlock->crate();
const int module = subBlock->cmmPosition();
const int firmware = subBlock->cmmFirmware();
const int summing = subBlock->cmmSumming();
const int timeslices = subBlock->timeslices();
const int sliceNum = subBlock->slice();
if (debug) {
msg() << "CMM-Energy: Crate " << hwCrate
<< " Module " << module
<< " Firmware " << firmware
<< " Summing " << summing
<< " Total slices " << timeslices

Sasha Mazurov
committed
<< " Slice " << sliceNum << endmsg;
}
if (timeslices <= trigCmm) {
if (debug) msg() << "Triggered CMM slice from header "

Sasha Mazurov
committed
<< trigCmm << ", " << timeslices << endmsg;
ld.rodErr = L1CaloSubBlock::ERROR_SLICES;
return;
}
if (timeslices <= sliceNum) {
if (debug) msg() << "Total slices inconsistent with slice number: "

Sasha Mazurov
committed
<< timeslices << ", " << sliceNum << endmsg;
ld.rodErr = L1CaloSubBlock::ERROR_SLICES;
return;
}
// Unpack sub-block
if (subBlock->dataWords() && !subBlock->unpack()) {
if (debug) {
std::string errMsg(subBlock->unpackErrorMsg());

Sasha Mazurov
committed
msg() << "CMM-Energy sub-block unpacking failed: " << errMsg << endmsg;
}
ld.rodErr = subBlock->unpackErrorCode();
return;
}
// Retrieve required data
const bool neutralFormat = subBlock->format() == L1CaloSubBlock::NEUTRAL;
const int crate = hwCrate - m_crateOffsetHw;
const int swCrate = crate + m_crateOffsetSw;
const int maxSid = static_cast<int>(CmmEnergySubBlock::MAX_SOURCE_ID);
LVL1::DataError derr;
derr.set(LVL1::DataError::SubStatusWord, subBlock->subStatus());
const int ssError = derr.error();
const int sliceBeg = ( neutralFormat ) ? 0 : sliceNum;
const int sliceEnd = ( neutralFormat ) ? timeslices : sliceNum + 1;
for (int slice = sliceBeg; slice < sliceEnd; ++slice) {
// Energy sums
for (int source = 0; source < maxSid; ++source) {
int dataID = source;
if (source >= m_modules) {
if (summing == CmmSubBlock::CRATE &&
source != CmmEnergySubBlock::LOCAL) continue;
switch (source) {
case CmmEnergySubBlock::LOCAL:
dataID = LVL1::CMMEtSums::LOCAL;
break;
case CmmEnergySubBlock::REMOTE:
dataID = LVL1::CMMEtSums::REMOTE;
break;
case CmmEnergySubBlock::TOTAL:
dataID = LVL1::CMMEtSums::TOTAL;
break;
default:
continue;
}
}
const unsigned int ex = subBlock->ex(slice, source);
const unsigned int ey = subBlock->ey(slice, source);
const unsigned int et = subBlock->et(slice, source);
int exErr = subBlock->exError(slice, source);
int eyErr = subBlock->eyError(slice, source);
int etErr = subBlock->etError(slice, source);
LVL1::DataError exErrBits(ssError);
LVL1::DataError eyErrBits(ssError);
LVL1::DataError etErrBits(ssError);
if (dataID == LVL1::CMMEtSums::LOCAL ||
dataID == LVL1::CMMEtSums::REMOTE ||
exErrBits.set(LVL1::DataError::Overflow, exErr);
exErrBits.set(LVL1::DataError::Parity, exErr >> 1);
eyErrBits.set(LVL1::DataError::Overflow, eyErr);
eyErrBits.set(LVL1::DataError::Parity, eyErr >> 1);
etErrBits.set(LVL1::DataError::Overflow, etErr);
etErrBits.set(LVL1::DataError::Parity, etErr >> 1);
} else {
exErrBits.set(LVL1::DataError::Parity, exErr);
eyErrBits.set(LVL1::DataError::Parity, eyErr);
etErrBits.set(LVL1::DataError::Parity, etErr);
}
exErr = exErrBits.error();
eyErr = eyErrBits.error();
etErr = etErrBits.error();
if (ex || ey || et || exErr || eyErr || etErr) {
LVL1::CMMEtSums* sums = findCmmSums(data, crate, dataID);
ld.exVec.assign(timeslices, 0);
ld.eyVec.assign(timeslices, 0);
ld.etVec.assign(timeslices, 0);
ld.exErrVec.assign(timeslices, 0);
ld.eyErrVec.assign(timeslices, 0);
ld.etErrVec.assign(timeslices, 0);
ld.exVec[slice] = ex;
ld.eyVec[slice] = ey;
ld.etVec[slice] = et;
ld.exErrVec[slice] = exErr;
ld.eyErrVec[slice] = eyErr;
ld.etErrVec[slice] = etErr;
std::make_unique<LVL1::CMMEtSums>(swCrate, dataID, ld.etVec, ld.exVec, ld.eyVec,
ld.etErrVec, ld.exErrVec, ld.eyErrVec, trigCmm);
data.m_cmmEtMap.insert(std::make_pair(key, sumsp.get()));
data.m_cmmEtCollection->push_back(std::move(sumsp));
} else {
ld.exVec = sums->ExVec();
ld.eyVec = sums->EyVec();
ld.etVec = sums->EtVec();
ld.exErrVec = sums->ExErrorVec();
ld.eyErrVec = sums->EyErrorVec();
ld.etErrVec = sums->EtErrorVec();
const int nsl = ld.exVec.size();
if (timeslices != nsl) {
if (debug) msg() << "Inconsistent number of slices in sub-blocks"

Sasha Mazurov
committed
<< endmsg;
ld.rodErr = L1CaloSubBlock::ERROR_SLICES;
}
if (ld.exVec[slice] != 0 || ld.eyVec[slice] != 0 || ld.etVec[slice] != 0 ||
ld.exErrVec[slice] != 0 || ld.eyErrVec[slice] != 0 ||
ld.etErrVec[slice] != 0) {

Sasha Mazurov
committed
if (debug) msg() << "Duplicate data for slice " << slice << endmsg;
ld.rodErr = L1CaloSubBlock::ERROR_DUPLICATE_DATA;
}
ld.exVec[slice] = ex;
ld.eyVec[slice] = ey;
ld.etVec[slice] = et;
ld.exErrVec[slice] = exErr;
ld.eyErrVec[slice] = eyErr;
ld.etErrVec[slice] = etErr;
sums->addEx(ld.exVec, ld.exErrVec);
sums->addEy(ld.eyVec, ld.eyErrVec);
sums->addEt(ld.etVec, ld.etErrVec);
}
}
}
// Hit maps - store as Et
if (summing == CmmSubBlock::SYSTEM) {
const unsigned int missEt = subBlock->missingEtHits(slice);
if ( missEt || ssError ) {
const int dataID = LVL1::CMMEtSums::MISSING_ET_MAP;
LVL1::CMMEtSums* map = findCmmSums(data, crate, dataID);
if ( ! map ) {
ld.etVec.assign(timeslices, 0);
ld.etErrVec.assign(timeslices, 0);
ld.etVec[slice] = missEt;
ld.etErrVec[slice] = ssError;
auto mapp =
std::make_unique<LVL1::CMMEtSums>(swCrate, dataID,
ld.etVec, ld.etVec, ld.etVec,
ld.etErrVec, ld.etErrVec, ld.etErrVec, trigCmm);
data.m_cmmEtMap.insert(std::make_pair(key, mapp.get()));
data.m_cmmEtCollection->push_back(std::move(mapp));
} else {
ld.etVec = map->EtVec();
ld.etErrVec = map->EtErrorVec();
const int nsl = ld.etVec.size();
if (timeslices != nsl) {
if (debug) msg() << "Inconsistent number of slices in sub-blocks"

Sasha Mazurov
committed
<< endmsg;
ld.rodErr = L1CaloSubBlock::ERROR_SLICES;
}
if (ld.etVec[slice] != 0 || ld.etErrVec[slice] != 0) {

Sasha Mazurov
committed
if (debug) msg() << "Duplicate data for slice " << slice << endmsg;
ld.rodErr = L1CaloSubBlock::ERROR_DUPLICATE_DATA;