Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:08:33

0001 
0002 #include "DQM/SiStripCommissioningDbClients/interface/LatencyHistosUsingDb.h"
0003 #include "DataFormats/SiStripCommon/interface/SiStripConstants.h"
0004 #include "DataFormats/SiStripCommon/interface/SiStripFecKey.h"
0005 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0006 #include "DataFormats/DetId/interface/DetId.h"
0007 #include <iostream>
0008 
0009 #define MAXFEDCOARSE 15
0010 
0011 using namespace sistrip;
0012 
0013 // -----------------------------------------------------------------------------
0014 /** */
0015 LatencyHistosUsingDb::LatencyHistosUsingDb(const edm::ParameterSet& pset,
0016                                            DQMStore* bei,
0017                                            SiStripConfigDb* const db,
0018                                            edm::ESGetToken<TrackerTopology, TrackerTopologyRcd> tTopoToken)
0019     : CommissioningHistograms(pset.getParameter<edm::ParameterSet>("LatencyParameters"), bei, sistrip::APV_LATENCY),
0020       CommissioningHistosUsingDb(db, tTopoToken, sistrip::APV_LATENCY),
0021       SamplingHistograms(pset.getParameter<edm::ParameterSet>("LatencyParameters"), bei, sistrip::APV_LATENCY) {
0022   LogTrace(mlDqmClient_) << "[LatencyHistosUsingDb::" << __func__ << "]"
0023                          << " Constructing object...";
0024 }
0025 
0026 // -----------------------------------------------------------------------------
0027 /** */
0028 LatencyHistosUsingDb::~LatencyHistosUsingDb() {
0029   LogTrace(mlDqmClient_) << "[LatencyHistosUsingDb::" << __func__ << "]"
0030                          << " Destructing object...";
0031 }
0032 
0033 // -----------------------------------------------------------------------------
0034 /** */
0035 void LatencyHistosUsingDb::uploadConfigurations() {
0036   if (!db()) {
0037     edm::LogWarning(mlDqmClient_) << "[LatencyHistosUsingDb::" << __func__ << "]"
0038                                   << " NULL pointer to SiStripConfigDb interface!"
0039                                   << " Aborting upload...";
0040     return;
0041   }
0042 
0043   SiStripConfigDb::DeviceDescriptionsRange devices = db()->getDeviceDescriptions();
0044   SiStripConfigDb::FedDescriptionsRange feds = db()->getFedDescriptions();
0045   bool upload = update(devices, feds);
0046   // Check if new PLL settings are valid
0047   if (!upload) {
0048     edm::LogWarning(mlDqmClient_) << "[LatencyHistosUsingDb::" << __func__ << "]"
0049                                   << " Found invalid PLL settings (coarse > 15)"
0050                                   << " Aborting update to database...";
0051     return;
0052   }
0053 
0054   if (doUploadConf()) {
0055     // Update APV descriptions with new Latency settings
0056     LogTrace(mlDqmClient_) << "[LatencyHistosUsingDb::" << __func__ << "]"
0057                            << " Uploading APV settings to DB...";
0058     db()->uploadDeviceDescriptions();
0059     LogTrace(mlDqmClient_) << "[LatencyHistosUsingDb::" << __func__ << "]"
0060                            << " Upload of APV settings to DB finished!";
0061     // Update FED descriptions
0062     LogTrace(mlDqmClient_) << "[LatencyHistosUsingDb::" << __func__ << "]"
0063                            << " Uploading FED delays to DB...";
0064     db()->uploadFedDescriptions();
0065     LogTrace(mlDqmClient_) << "[LatencyHistosUsingDb::" << __func__ << "]"
0066                            << " Upload of FED delays to DB finished!";
0067   } else {
0068     edm::LogWarning(mlDqmClient_) << "[LatencyHistosUsingDb::" << __func__ << "]"
0069                                   << " TEST only! No APV settings will be uploaded to DB...";
0070   }
0071 }
0072 
0073 // -----------------------------------------------------------------------------
0074 /** */
0075 bool LatencyHistosUsingDb::update(SiStripConfigDb::DeviceDescriptionsRange devices,
0076                                   SiStripConfigDb::FedDescriptionsRange feds) {
0077   // Obtain the latency from the analysis object
0078   if (data().empty() || !data().begin()->second->isValid()) {
0079     edm::LogVerbatim(mlDqmClient_) << "[LatencyHistosUsingDb::" << __func__ << "]"
0080                                    << " Updated NO Latency settings. No analysis result available !";
0081     return false;
0082   }
0083 
0084   // Compute the minimum coarse delay
0085   uint16_t minCoarseDelay = 256;
0086   SiStripConfigDb::DeviceDescriptionsV::const_iterator idevice;
0087   for (idevice = devices.begin(); idevice != devices.end(); idevice++) {
0088     // Check device type
0089     if ((*idevice)->getDeviceType() == PLL) {
0090       // Cast to retrieve appropriate description object
0091       pllDescription* desc = dynamic_cast<pllDescription*>(*idevice);
0092       if (desc) {
0093         /*
0094         // add 1 to aim at 1 and not 0 (just to avoid a special 0 value for security)
0095         int delayCoarse = desc->getDelayCoarse() - 1;
0096         delayCoarse = delayCoarse < 0 ? 0 : delayCoarse;
0097         minCoarseDelay = minCoarseDelay < delayCoarse ? minCoarseDelay : delayCoarse;
0098 */
0099         int delayCoarse = desc->getDelayCoarse();
0100         minCoarseDelay = minCoarseDelay < delayCoarse ? minCoarseDelay : delayCoarse;
0101       }
0102     }
0103   }
0104 
0105   // Compute latency and PLL shift from the sampling measurement
0106   SamplingAnalysis* anal = nullptr;
0107   for (CommissioningHistograms::Analysis it = data().begin(); it != data().end(); ++it) {
0108     if (dynamic_cast<SamplingAnalysis*>(it->second) &&
0109         dynamic_cast<SamplingAnalysis*>(it->second)->granularity() == sistrip::TRACKER)
0110       anal = dynamic_cast<SamplingAnalysis*>(it->second);
0111   }
0112   if (!anal)
0113     return false;
0114   uint16_t globalLatency = uint16_t(ceil(anal->maximum() / (-25.)));
0115   float globalShift = anal->maximum() - (globalLatency * (-25));
0116 
0117   // Compute latency and PLL shift per partition... this is an option
0118   uint16_t latency = globalLatency;
0119   float shift[5] = {0.};
0120   for (CommissioningHistograms::Analysis it = data().begin(); it != data().end(); ++it) {
0121     if (dynamic_cast<SamplingAnalysis*>(it->second) &&
0122         dynamic_cast<SamplingAnalysis*>(it->second)->granularity() == sistrip::PARTITION) {
0123       anal = dynamic_cast<SamplingAnalysis*>(it->second);
0124       latency = uint16_t(ceil(anal->maximum() / (-25.))) > latency ? uint16_t(ceil(anal->maximum() / (-25.))) : latency;
0125     }
0126   }
0127   for (CommissioningHistograms::Analysis it = data().begin(); it != data().end(); ++it) {
0128     if (dynamic_cast<SamplingAnalysis*>(it->second) &&
0129         dynamic_cast<SamplingAnalysis*>(it->second)->granularity() == sistrip::PARTITION) {
0130       anal = dynamic_cast<SamplingAnalysis*>(it->second);
0131       shift[SiStripFecKey(anal->fecKey()).fecCrate()] = anal->maximum() - (latency * (-25));
0132     }
0133   }
0134   if (!perPartition_) {
0135     latency = globalLatency;
0136     for (int i = 0; i < 5; i++)
0137       shift[i] = globalShift;
0138   }
0139 
0140   // Take into account the minimum coarse delay to bring the coarse delay down
0141   // the same quantity is subtracted to the coarse delay of each APV
0142   latency -= minCoarseDelay;
0143 
0144   // Iterate through devices and update device descriptions
0145   uint16_t updatedAPV = 0;
0146   uint16_t updatedPLL = 0;
0147   std::vector<SiStripFecKey> invalid;
0148   for (idevice = devices.begin(); idevice != devices.end(); idevice++) {
0149     // Check device type
0150     if ((*idevice)->getDeviceType() != APV25) {
0151       continue;
0152     }
0153     // Cast to retrieve appropriate description object
0154     apvDescription* desc = dynamic_cast<apvDescription*>(*idevice);
0155     if (!desc) {
0156       continue;
0157     }
0158     // Retrieve device addresses from device description
0159     const SiStripConfigDb::DeviceAddress& addr = db()->deviceAddress(*desc);
0160     // Do it!
0161     std::stringstream ss;
0162     ss << "[LatencyHistosUsingDb::" << __func__ << "]"
0163        << " Updating latency APV settings for crate/FEC/slot/ring/CCU/i2cAddr " << addr.fecCrate_ << "/"
0164        << addr.fecSlot_ << "/" << addr.fecRing_ << "/" << addr.ccuAddr_ << "/" << addr.ccuChan_ << "/" << addr.i2cAddr_
0165        << " from " << static_cast<uint16_t>(desc->getLatency());
0166     desc->setLatency(latency);
0167     ss << " to " << static_cast<uint16_t>(desc->getLatency());
0168     LogTrace(mlDqmClient_) << ss.str();
0169     updatedAPV++;
0170   }
0171 
0172   // Change also the PLL delay
0173   for (idevice = devices.begin(); idevice != devices.end(); idevice++) {
0174     // Check device type
0175     if ((*idevice)->getDeviceType() != PLL) {
0176       continue;
0177     }
0178     // Cast to retrieve appropriate description object
0179     pllDescription* desc = dynamic_cast<pllDescription*>(*idevice);
0180     if (!desc) {
0181       continue;
0182     }
0183     if (desc->getDelayCoarse() >= 15) {
0184       continue;
0185     }
0186     // Retrieve device addresses from device description
0187     const SiStripConfigDb::DeviceAddress& addr = db()->deviceAddress(*desc);
0188     // Construct key from device description
0189     uint32_t fec_key =
0190         SiStripFecKey(addr.fecCrate_, addr.fecSlot_, addr.fecRing_, addr.ccuAddr_, addr.ccuChan_, 0).key();
0191     SiStripFecKey fec_path = SiStripFecKey(fec_key);
0192     // Do it!
0193     float delay = desc->getDelayCoarse() * 25 + desc->getDelayFine() * 25. / 24. + shift[addr.fecCrate_];
0194     int delayCoarse = int(delay / 25);
0195     int delayFine = int(round((delay - 25 * delayCoarse) * 24. / 25.));
0196     if (delayFine == 24) {
0197       delayFine = 0;
0198       ++delayCoarse;
0199     }
0200     delayCoarse -= minCoarseDelay;
0201     //  maximum coarse setting
0202     if (delayCoarse > 15) {
0203       invalid.push_back(fec_key);
0204       delayCoarse = sistrip::invalid_;
0205     }
0206     // Update PLL settings
0207     if (delayCoarse != sistrip::invalid_ && delayFine != sistrip::invalid_) {
0208       std::stringstream ss;
0209       ss << "[LatencyHistosUsingDb::" << __func__ << "]"
0210          << " Updating coarse/fine PLL settings"
0211          << " for Crate/FEC/slot/ring/CCU " << fec_path.fecCrate() << "/" << fec_path.fecSlot() << "/"
0212          << fec_path.fecRing() << "/" << fec_path.ccuAddr() << "/" << fec_path.ccuChan() << " from "
0213          << static_cast<uint16_t>(desc->getDelayCoarse()) << "/" << static_cast<uint16_t>(desc->getDelayFine());
0214       desc->setDelayCoarse(delayCoarse);
0215       desc->setDelayFine(delayFine);
0216       updatedPLL++;
0217       ss << " to " << static_cast<uint16_t>(desc->getDelayCoarse()) << "/"
0218          << static_cast<uint16_t>(desc->getDelayFine());
0219       LogTrace(mlDqmClient_) << ss.str();
0220     }
0221   }
0222 
0223   // Retrieve FED ids from cabling
0224   auto ids = cabling()->fedIds();
0225 
0226   // loop over the FED ids to determine min and max values of coarse delay
0227   uint16_t minDelay = 256;
0228   uint16_t maxDelay = 0;
0229   uint16_t fedDelayCoarse = 0;
0230   for (auto ifed = feds.begin(); ifed != feds.end(); ifed++) {
0231     // If FED id not found in list (from cabling), then continue
0232     if (find(ids.begin(), ids.end(), (*ifed)->getFedId()) == ids.end()) {
0233       continue;
0234     }
0235     auto conns = cabling()->fedConnections((*ifed)->getFedId());
0236     // loop over the connections for that FED
0237     for (auto iconn = conns.begin(); iconn != conns.end(); iconn++) {
0238       // check that this is a tracker module
0239       if (DetId(iconn->detId()).det() != DetId::Tracker)
0240         continue;
0241       // build the Fed9UAddress for that channel. Used to update the description.
0242       Fed9U::Fed9UAddress fedChannel = Fed9U::Fed9UAddress(iconn->fedCh());
0243       // retreive the current value for the delays
0244       fedDelayCoarse = (*ifed)->getCoarseDelay(fedChannel);
0245       // update min and max
0246       minDelay = minDelay < fedDelayCoarse ? minDelay : fedDelayCoarse;
0247       maxDelay = maxDelay > fedDelayCoarse ? maxDelay : fedDelayCoarse;
0248     }
0249   }
0250 
0251   // compute the FED coarse global offset
0252   int offset = (10 - minDelay) * 25;  // try to ensure 10BX room for later fine delay scan
0253   if (maxDelay + (offset / 25) > MAXFEDCOARSE)
0254     offset = (MAXFEDCOARSE - maxDelay) * 25;  // otherwise, take the largest possible
0255 
0256   // loop over the FED ids
0257   for (SiStripConfigDb::FedDescriptionsV::const_iterator ifed = feds.begin(); ifed != feds.end(); ifed++) {
0258     // If FED id not found in list (from cabling), then continue
0259     if (find(ids.begin(), ids.end(), (*ifed)->getFedId()) == ids.end()) {
0260       continue;
0261     }
0262     auto conns = cabling()->fedConnections((*ifed)->getFedId());
0263     // loop over the connections for that FED
0264     for (auto iconn = conns.begin(); iconn != conns.end(); iconn++) {
0265       // check that this is a tracker module
0266       if (DetId(iconn->detId()).det() != DetId::Tracker)
0267         continue;
0268       // build the Fed9UAddress for that channel. Used to update the description.
0269       Fed9U::Fed9UAddress fedChannel = Fed9U::Fed9UAddress(iconn->fedCh());
0270       // retreive the current value for the delays
0271       int fedDelayCoarse = (*ifed)->getCoarseDelay(fedChannel);
0272       int fedDelayFine = (*ifed)->getFineDelay(fedChannel);
0273       // compute the FED delay
0274       // this is done by substracting the best (PLL) delay to the present value (from the db)
0275       int fedDelay = int(fedDelayCoarse * 25. - fedDelayFine * 24. / 25. - round(shift[iconn->fecCrate()]) + offset);
0276       fedDelayCoarse = (fedDelay / 25) + 1;
0277       fedDelayFine = fedDelayCoarse * 25 - fedDelay;
0278       if (fedDelayFine == 25) {
0279         fedDelayFine = 0;
0280         --fedDelayCoarse;
0281       }
0282       // update the FED delay
0283       std::stringstream ss;
0284       ss << "[LatencyHistosUsingDb::" << __func__ << "]"
0285          << " Updating the FED delay"
0286          << " for loop FED id/ch " << (*ifed)->getFedId() << "/" << iconn->fedCh() << " from "
0287          << (*ifed)->getCoarseDelay(fedChannel) << "/" << (*ifed)->getFineDelay(fedChannel) << " to ";
0288       (*ifed)->setDelay(fedChannel, fedDelayCoarse, fedDelayFine);
0289       ss << (*ifed)->getCoarseDelay(fedChannel) << "/" << (*ifed)->getFineDelay(fedChannel);
0290       LogTrace(mlDqmClient_) << ss.str();
0291     }
0292   }
0293 
0294   // Summary output
0295   edm::LogVerbatim(mlDqmClient_) << "[LatencyHistosUsingDb::" << __func__ << "]"
0296                                  << " Updated FED delays for " << ids.size() << " FEDs!";
0297 
0298   // Check if invalid settings were found
0299   if (!invalid.empty()) {
0300     std::stringstream ss;
0301     ss << "[LatencyHistosUsingDb::" << __func__ << "]"
0302        << " Found PLL coarse setting of 15"
0303        << " (not allowed!) for following channels"
0304        << " (Crate/FEC/slot/ring/CCU/LLD): ";
0305     std::vector<SiStripFecKey>::iterator ikey = invalid.begin();
0306     std::vector<SiStripFecKey>::iterator jkey = invalid.end();
0307     for (; ikey != jkey; ++ikey) {
0308       ss << ikey->fecCrate() << "/" << ikey->fecSlot() << "/" << ikey->fecRing() << "/" << ikey->ccuAddr() << "/"
0309          << ikey->ccuChan() << ", ";
0310     }
0311     edm::LogWarning(mlDqmClient_) << ss.str();
0312     return false;
0313   }
0314 
0315   // Summary output
0316   edm::LogVerbatim(mlDqmClient_) << "[LatencyHistosUsingDb::" << __func__ << "] "
0317                                  << "Updated settings for " << updatedAPV << " APV devices and " << updatedPLL
0318                                  << " PLL devices.";
0319   return true;
0320 }
0321 
0322 // -----------------------------------------------------------------------------
0323 /** */
0324 void LatencyHistosUsingDb::create(SiStripConfigDb::AnalysisDescriptionsV& desc, Analysis analysis) {
0325   SamplingAnalysis* anal = dynamic_cast<SamplingAnalysis*>(analysis->second);
0326   if (!anal) {
0327     return;
0328   }
0329 
0330   SiStripFecKey fec_key(anal->fecKey());  //@@ analysis->first
0331   SiStripFedKey fed_key(anal->fedKey());
0332 
0333   uint16_t latency = static_cast<uint16_t>((anal->maximum() / (-25.)) + 0.5);
0334 
0335   ApvLatencyAnalysisDescription* tmp;
0336   tmp = new ApvLatencyAnalysisDescription(latency,
0337                                           0,
0338                                           0,
0339                                           0,
0340                                           0,
0341                                           0,
0342                                           0,
0343                                           db()->dbParams().partitions().begin()->second.partitionName(),
0344                                           db()->dbParams().partitions().begin()->second.runNumber(),
0345                                           anal->isValid(),
0346                                           "",
0347                                           fed_key.fedId(),
0348                                           fed_key.feUnit(),
0349                                           fed_key.feChan(),
0350                                           fed_key.fedApv());
0351 
0352   // Add comments
0353   typedef std::vector<std::string> Strings;
0354   Strings errors = anal->getErrorCodes();
0355   Strings::const_iterator istr = errors.begin();
0356   Strings::const_iterator jstr = errors.end();
0357   for (; istr != jstr; ++istr) {
0358     tmp->addComments(*istr);
0359   }
0360 
0361   // Store description
0362   desc.push_back(tmp);
0363 }
0364 
0365 void LatencyHistosUsingDb::configure(const edm::ParameterSet& pset, const edm::EventSetup& es) {
0366   CommissioningHistosUsingDb::configure(pset, es);
0367   perPartition_ = this->pset().getParameter<bool>("OptimizePerPartition");
0368 }