CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/DQM/SiStripCommissioningDbClients/src/LatencyHistosUsingDb.cc

Go to the documentation of this file.
00001 // Last commit: $Id: LatencyHistosUsingDb.cc,v 1.22 2009/11/10 14:49:02 lowette Exp $
00002 
00003 #include "DQM/SiStripCommissioningDbClients/interface/LatencyHistosUsingDb.h"
00004 #include "DataFormats/SiStripCommon/interface/SiStripConstants.h"
00005 #include "DataFormats/SiStripCommon/interface/SiStripFecKey.h"
00006 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00007 #include "DataFormats/DetId/interface/DetId.h"
00008 #include <iostream>
00009 
00010 #define MAXFEDCOARSE 15
00011 
00012 using namespace sistrip;
00013 
00014 // -----------------------------------------------------------------------------
00016 LatencyHistosUsingDb::LatencyHistosUsingDb( const edm::ParameterSet & pset,
00017                                             DQMStore* bei,
00018                                             SiStripConfigDb* const db )
00019   : CommissioningHistograms( pset.getParameter<edm::ParameterSet>("LatencyParameters"),
00020                              bei,
00021                              sistrip::APV_LATENCY ),
00022     CommissioningHistosUsingDb( db,
00023                                 sistrip::APV_LATENCY ),
00024     SamplingHistograms( pset.getParameter<edm::ParameterSet>("LatencyParameters"),
00025                         bei,
00026                         sistrip::APV_LATENCY )
00027 {
00028   LogTrace(mlDqmClient_) 
00029     << "[LatencyHistosUsingDb::" << __func__ << "]"
00030     << " Constructing object...";
00031 }
00032 
00033 // -----------------------------------------------------------------------------
00035 LatencyHistosUsingDb::~LatencyHistosUsingDb() {
00036   LogTrace(mlDqmClient_) 
00037     << "[LatencyHistosUsingDb::" << __func__ << "]"
00038     << " Destructing object...";
00039 }
00040 
00041 // -----------------------------------------------------------------------------
00043 void LatencyHistosUsingDb::uploadConfigurations() {
00044   
00045   if ( !db() ) {
00046     edm::LogWarning(mlDqmClient_) 
00047       << "[LatencyHistosUsingDb::" << __func__ << "]"
00048       << " NULL pointer to SiStripConfigDb interface!"
00049       << " Aborting upload...";
00050     return;
00051   }
00052 
00053   SiStripConfigDb::DeviceDescriptionsRange devices = db()->getDeviceDescriptions(); 
00054   SiStripConfigDb::FedDescriptionsRange feds = db()->getFedDescriptions();
00055   bool upload = update( devices, feds );
00056   // Check if new PLL settings are valid
00057   if ( !upload ) {
00058     edm::LogWarning(mlDqmClient_)
00059       << "[LatencyHistosUsingDb::" << __func__ << "]"
00060       << " Found invalid PLL settings (coarse > 15)"
00061       << " Aborting update to database...";
00062     return;
00063   }
00064   
00065   if ( doUploadConf() ) { 
00066     // Update APV descriptions with new Latency settings
00067     LogTrace(mlDqmClient_) 
00068       << "[LatencyHistosUsingDb::" << __func__ << "]"
00069       << " Uploading APV settings to DB...";
00070     db()->uploadDeviceDescriptions(); 
00071     LogTrace(mlDqmClient_) 
00072       << "[LatencyHistosUsingDb::" << __func__ << "]"
00073       << " Upload of APV settings to DB finished!";
00074     // Update FED descriptions 
00075     LogTrace(mlDqmClient_)
00076       << "[LatencyHistosUsingDb::" << __func__ << "]"
00077       << " Uploading FED delays to DB...";
00078     db()->uploadFedDescriptions();
00079     LogTrace(mlDqmClient_)
00080       << "[LatencyHistosUsingDb::" << __func__ << "]"
00081       << " Upload of FED delays to DB finished!";
00082   } else {
00083     edm::LogWarning(mlDqmClient_) 
00084       << "[LatencyHistosUsingDb::" << __func__ << "]"
00085       << " TEST only! No APV settings will be uploaded to DB...";
00086   }
00087 
00088 }
00089 
00090 // -----------------------------------------------------------------------------
00092 bool LatencyHistosUsingDb::update( SiStripConfigDb::DeviceDescriptionsRange devices, 
00093                                    SiStripConfigDb::FedDescriptionsRange feds ) {
00094   
00095   // Obtain the latency from the analysis object
00096   if(!data().size() || !data().begin()->second->isValid() ) {
00097     edm::LogVerbatim(mlDqmClient_) 
00098       << "[LatencyHistosUsingDb::" << __func__ << "]"
00099       << " Updated NO Latency settings. No analysis result available !" ;
00100     return false;
00101   }
00102 
00103   // Compute the minimum coarse delay
00104   uint16_t minCoarseDelay = 256;
00105   SiStripConfigDb::DeviceDescriptionsV::const_iterator idevice;
00106   for ( idevice = devices.begin(); idevice != devices.end(); idevice++ ) {
00107     // Check device type
00108     if ( (*idevice)->getDeviceType() == PLL ) {
00109       // Cast to retrieve appropriate description object
00110       pllDescription* desc = dynamic_cast<pllDescription*>( *idevice );
00111       if ( desc ) { 
00112 /*
00113         // add 1 to aim at 1 and not 0 (just to avoid a special 0 value for security)
00114         int delayCoarse = desc->getDelayCoarse() - 1;
00115         delayCoarse = delayCoarse < 0 ? 0 : delayCoarse;
00116         minCoarseDelay = minCoarseDelay < delayCoarse ? minCoarseDelay : delayCoarse;
00117 */
00118         int delayCoarse = desc->getDelayCoarse();
00119         minCoarseDelay = minCoarseDelay < delayCoarse ? minCoarseDelay : delayCoarse;
00120       }
00121     }
00122   }
00123 
00124   // Compute latency and PLL shift from the sampling measurement
00125   SamplingAnalysis* anal = NULL;
00126   for( CommissioningHistograms::Analysis it = data().begin(); it!=data().end();++it) {
00127     if(dynamic_cast<SamplingAnalysis*>( it->second ) && 
00128        dynamic_cast<SamplingAnalysis*>( it->second )->granularity()==sistrip::TRACKER)
00129       anal = dynamic_cast<SamplingAnalysis*>( it->second );
00130   }
00131   if(!anal) return false;
00132   uint16_t globalLatency = uint16_t(ceil(anal->maximum()/(-25.)));
00133   float globalShift = anal->maximum()-(globalLatency*(-25));
00134 
00135   // Compute latency and PLL shift per partition... this is an option
00136   uint16_t latency = globalLatency;
00137   float shift[5] = {0.};
00138   for( CommissioningHistograms::Analysis it = data().begin(); it!=data().end();++it) {
00139     if(dynamic_cast<SamplingAnalysis*>( it->second ) &&
00140        dynamic_cast<SamplingAnalysis*>( it->second )->granularity()==sistrip::PARTITION       )
00141       anal = dynamic_cast<SamplingAnalysis*>( it->second );
00142       latency = uint16_t(ceil(anal->maximum()/(-25.)))>latency ? uint16_t(ceil(anal->maximum()/(-25.))) : latency;
00143   }
00144   for( CommissioningHistograms::Analysis it = data().begin(); it!=data().end();++it) {
00145     if(dynamic_cast<SamplingAnalysis*>( it->second ) &&
00146        dynamic_cast<SamplingAnalysis*>( it->second )->granularity()==sistrip::PARTITION       )
00147       anal = dynamic_cast<SamplingAnalysis*>( it->second );
00148       shift[SiStripFecKey(anal->fecKey()).fecCrate()] = anal->maximum()-(latency*(-25));
00149   }
00150   if(!perPartition_) {
00151     latency = globalLatency;
00152     for(int i=0;i<5;i++) shift[i] = globalShift;
00153   }
00154 
00155   // Take into account the minimum coarse delay to bring the coarse delay down
00156   // the same quantity is subtracted to the coarse delay of each APV 
00157   latency -= minCoarseDelay;
00158   
00159   // Iterate through devices and update device descriptions
00160   uint16_t updatedAPV = 0;
00161   uint16_t updatedPLL = 0;
00162   std::vector<SiStripFecKey> invalid;
00163   for ( idevice = devices.begin(); idevice != devices.end(); idevice++ ) {
00164     // Check device type
00165     if ( (*idevice)->getDeviceType() != APV25 ) { continue; }
00166     // Cast to retrieve appropriate description object
00167     apvDescription* desc = dynamic_cast<apvDescription*>( *idevice );
00168     if ( !desc ) { continue; }
00169     // Retrieve device addresses from device description
00170     const SiStripConfigDb::DeviceAddress& addr = db()->deviceAddress(*desc);
00171     // Do it!
00172     std::stringstream ss;
00173     ss << "[LatencyHistosUsingDb::" << __func__ << "]"
00174        << " Updating latency APV settings for crate/FEC/slot/ring/CCU/i2cAddr "
00175        << addr.fecCrate_ << "/"
00176        << addr.fecSlot_ << "/"
00177        << addr.fecRing_ << "/"
00178        << addr.ccuAddr_ << "/"
00179        << addr.ccuChan_ << "/"
00180        << addr.i2cAddr_
00181        << " from "
00182        << static_cast<uint16_t>(desc->getLatency());
00183     desc->setLatency(latency);
00184     ss << " to "
00185        << static_cast<uint16_t>(desc->getLatency());
00186     LogTrace(mlDqmClient_) << ss.str();
00187     updatedAPV++;
00188   }
00189 
00190   // Change also the PLL delay
00191   for ( idevice = devices.begin(); idevice != devices.end(); idevice++ ) {
00192     // Check device type
00193     if ( (*idevice)->getDeviceType() != PLL ) { continue; }
00194     // Cast to retrieve appropriate description object
00195     pllDescription* desc = dynamic_cast<pllDescription*>( *idevice );
00196     if ( !desc ) { continue; }
00197     if ( desc->getDelayCoarse() >= 15 ) { continue; }
00198     // Retrieve device addresses from device description
00199     const SiStripConfigDb::DeviceAddress& addr = db()->deviceAddress(*desc);
00200     // Construct key from device description
00201     uint32_t fec_key = SiStripFecKey( addr.fecCrate_,
00202                                       addr.fecSlot_,
00203                                       addr.fecRing_,
00204                                       addr.ccuAddr_,
00205                                       addr.ccuChan_,
00206                                       0 ).key();
00207     SiStripFecKey fec_path = SiStripFecKey( fec_key );    
00208     // Do it!
00209     float delay = desc->getDelayCoarse()*25+desc->getDelayFine()*25./24. + shift[addr.fecCrate_];
00210     int delayCoarse = int(delay/25);
00211     int delayFine   = int(round((delay-25*delayCoarse)*24./25.));
00212     if(delayFine==24) { delayFine=0; ++delayCoarse; }
00213     delayCoarse -= minCoarseDelay;
00214     //  maximum coarse setting
00215     if ( delayCoarse > 15 ) { invalid.push_back(fec_key); delayCoarse = sistrip::invalid_; }
00216     // Update PLL settings
00217     if ( delayCoarse != sistrip::invalid_ &&
00218          delayFine != sistrip::invalid_ ) {
00219       std::stringstream ss;
00220       ss << "[LatencyHistosUsingDb::" << __func__ << "]"
00221          << " Updating coarse/fine PLL settings"
00222          << " for Crate/FEC/slot/ring/CCU "
00223          << fec_path.fecCrate() << "/"
00224          << fec_path.fecSlot() << "/"
00225          << fec_path.fecRing() << "/"
00226          << fec_path.ccuAddr() << "/"
00227          << fec_path.ccuChan()
00228          << " from "
00229          << static_cast<uint16_t>( desc->getDelayCoarse() ) << "/"
00230          << static_cast<uint16_t>( desc->getDelayFine() );
00231       desc->setDelayCoarse(delayCoarse);
00232       desc->setDelayFine(delayFine);
00233       updatedPLL++;
00234       ss << " to "
00235          << static_cast<uint16_t>( desc->getDelayCoarse() ) << "/"
00236          << static_cast<uint16_t>( desc->getDelayFine() );
00237       LogTrace(mlDqmClient_) << ss.str();
00238     }
00239   }
00240   
00241   // Retrieve FED ids from cabling
00242   std::vector<uint16_t> ids = cabling()->feds() ;
00243 
00244   // loop over the FED ids to determine min and max values of coarse delay
00245   uint16_t minDelay = 256;
00246   uint16_t maxDelay = 0;
00247   uint16_t fedDelayCoarse = 0;
00248   for ( SiStripConfigDb::FedDescriptionsV::const_iterator ifed = feds.begin(); ifed != feds.end(); ifed++ ) {
00249     // If FED id not found in list (from cabling), then continue
00250     if ( find( ids.begin(), ids.end(), (*ifed)->getFedId() ) == ids.end() ) { continue; }
00251     const std::vector<FedChannelConnection>& conns = cabling()->connections((*ifed)->getFedId());
00252     // loop over the connections for that FED
00253     for ( std::vector<FedChannelConnection>::const_iterator iconn = conns.begin(); iconn != conns.end(); iconn++ ) {
00254       // check that this is a tracker module
00255       if(DetId(iconn->detId()).det()!=DetId::Tracker) continue;
00256       // build the Fed9UAddress for that channel. Used to update the description.
00257       Fed9U::Fed9UAddress fedChannel = Fed9U::Fed9UAddress(iconn->fedCh());
00258       // retreive the current value for the delays
00259       fedDelayCoarse = (*ifed)->getCoarseDelay(fedChannel);
00260       // update min and max
00261       minDelay = minDelay<fedDelayCoarse ? minDelay : fedDelayCoarse;
00262       maxDelay = maxDelay>fedDelayCoarse ? maxDelay : fedDelayCoarse;
00263     }
00264   }
00265 
00266   // compute the FED coarse global offset
00267   int offset = (10-minDelay)*25;  // try to ensure 10BX room for later fine delay scan
00268   if(maxDelay+(offset/25)>MAXFEDCOARSE) offset = (MAXFEDCOARSE-maxDelay)*25; // otherwise, take the largest possible
00269 
00270   // loop over the FED ids
00271   for ( SiStripConfigDb::FedDescriptionsV::const_iterator ifed = feds.begin(); ifed != feds.end(); ifed++ ) {
00272     // If FED id not found in list (from cabling), then continue
00273     if ( find( ids.begin(), ids.end(), (*ifed)->getFedId() ) == ids.end() ) { continue; }
00274     const std::vector<FedChannelConnection>& conns = cabling()->connections((*ifed)->getFedId());
00275     // loop over the connections for that FED
00276     for ( std::vector<FedChannelConnection>::const_iterator iconn = conns.begin(); iconn != conns.end(); iconn++ ) {
00277       // check that this is a tracker module
00278       if(DetId(iconn->detId()).det()!=DetId::Tracker) continue;
00279       // build the Fed9UAddress for that channel. Used to update the description.
00280       Fed9U::Fed9UAddress fedChannel = Fed9U::Fed9UAddress(iconn->fedCh());
00281       // retreive the current value for the delays
00282       int fedDelayCoarse = (*ifed)->getCoarseDelay(fedChannel);
00283       int fedDelayFine = (*ifed)->getFineDelay(fedChannel);
00284       // compute the FED delay
00285       // this is done by substracting the best (PLL) delay to the present value (from the db)
00286       int fedDelay = int(fedDelayCoarse*25. - fedDelayFine*24./25. - round(shift[iconn->fecCrate()]) + offset);
00287       fedDelayCoarse = (fedDelay/25)+1;
00288       fedDelayFine = fedDelayCoarse*25-fedDelay;
00289       if(fedDelayFine==25) { fedDelayFine = 0; --fedDelayCoarse; }
00290       // update the FED delay
00291       std::stringstream ss;
00292       ss << "[LatencyHistosUsingDb::" << __func__ << "]"
00293          << " Updating the FED delay"
00294          << " for loop FED id/ch "
00295          << (*ifed)->getFedId() << "/" << iconn->fedCh()
00296          << " from "
00297          << (*ifed)->getCoarseDelay( fedChannel) << "/" << (*ifed)->getFineDelay( fedChannel)
00298          << " to ";
00299       (*ifed)->setDelay(fedChannel, fedDelayCoarse, fedDelayFine);
00300       ss << (*ifed)->getCoarseDelay(fedChannel) << "/" << (*ifed)->getFineDelay( fedChannel);
00301       LogTrace(mlDqmClient_) << ss.str();
00302     }
00303   }
00304 
00305   // Summary output
00306   edm::LogVerbatim(mlDqmClient_)
00307     << "[LatencyHistosUsingDb::" << __func__ << "]"
00308     << " Updated FED delays for " << ids.size() << " FEDs!";
00309   
00310   // Check if invalid settings were found
00311   if ( !invalid.empty() ) {
00312     std::stringstream ss;
00313     ss << "[LatencyHistosUsingDb::" << __func__ << "]"
00314        << " Found PLL coarse setting of 15"
00315        << " (not allowed!) for following channels"
00316        << " (Crate/FEC/slot/ring/CCU/LLD): ";
00317     std::vector<SiStripFecKey>::iterator ikey = invalid.begin();
00318     std::vector<SiStripFecKey>::iterator jkey = invalid.end();
00319     for ( ; ikey != jkey; ++ikey ) {
00320       ss << ikey->fecCrate() << "/"
00321          << ikey->fecSlot() << "/"
00322          << ikey->fecRing() << "/"
00323          << ikey->ccuAddr() << "/"
00324          << ikey->ccuChan() << ", ";
00325     }
00326     edm::LogWarning(mlDqmClient_) << ss.str();
00327     return false;
00328   }
00329 
00330   // Summary output
00331   edm::LogVerbatim(mlDqmClient_) 
00332     << "[LatencyHistosUsingDb::" << __func__ << "] "
00333     << "Updated settings for " << updatedAPV << " APV devices and " << updatedPLL << " PLL devices.";
00334   return true;
00335 }
00336 
00337 // -----------------------------------------------------------------------------
00339 void LatencyHistosUsingDb::create( SiStripConfigDb::AnalysisDescriptionsV& desc,
00340                                    Analysis analysis ) {
00341 
00342   SamplingAnalysis* anal = dynamic_cast<SamplingAnalysis*>( analysis->second );
00343   if ( !anal ) { return; }
00344   
00345   SiStripFecKey fec_key( anal->fecKey() ); //@@ analysis->first
00346   SiStripFedKey fed_key( anal->fedKey() );
00347   
00348   uint16_t latency = static_cast<uint16_t>( ( anal->maximum() / (-25.) ) + 0.5 );
00349 
00350   ApvLatencyAnalysisDescription* tmp;
00351   tmp = new ApvLatencyAnalysisDescription( latency, 
00352                                            0,
00353                                            0,
00354                                            0,
00355                                            0,
00356                                            0,
00357                                            0, 
00358                                            db()->dbParams().partitions().begin()->second.partitionName(),
00359                                            db()->dbParams().partitions().begin()->second.runNumber(),
00360                                            anal->isValid(),
00361                                            "",
00362                                            fed_key.fedId(),
00363                                            fed_key.feUnit(),
00364                                            fed_key.feChan(),
00365                                            fed_key.fedApv() );
00366     
00367   // Add comments
00368   typedef std::vector<std::string> Strings;
00369   Strings errors = anal->getErrorCodes();
00370   Strings::const_iterator istr = errors.begin();
00371   Strings::const_iterator jstr = errors.end();
00372   for ( ; istr != jstr; ++istr ) { tmp->addComments( *istr ); }
00373     
00374   // Store description
00375   desc.push_back( tmp );
00376     
00377 }
00378 
00379 void LatencyHistosUsingDb::configure( const edm::ParameterSet& pset, const edm::EventSetup& es)
00380 {
00381   perPartition_ = this->pset().getParameter<bool>("OptimizePerPartition");
00382 }
00383