Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-03 08:20:48

0001 #include "oncsSub_idmvtxv2.h"
0002 #include <cstring>
0003 #include <bitset>
0004 #include <map>
0005 #include <vector>
0006 #include <functional>
0007 
0008 #include <arpa/inet.h>
0009 
0010 using namespace std;
0011 
0012 oncsSub_idmvtxv2::oncsSub_idmvtxv2(subevtdata_ptr data)
0013     :oncsSubevent_w4 (data)
0014 {
0015     _is_decoded = 0;
0016     _highest_ruid = -1;
0017     _decoder_error = 0;
0018     for (int ruid=0; ruid<IDMVTXV2_MAXRUID+1; ruid++)
0019     {
0020         _bad_ruchns[ruid] = 0;
0021         _lanes_active[ruid] = -1;
0022         _lane_stops[ruid] = -1;
0023         _lane_timeouts[ruid] = -1;
0024         _inconsistent_bc[ruid] = -1;
0025         for ( int ruchn = 0; ruchn < IDMVTXV2_MAXRUCHN+1; ruchn++)
0026         {
0027             _chip_id[ruid][ruchn] = -1;
0028             _bad_bytes[ruid][ruchn] = 0;
0029             _excess_bytes[ruid][ruchn] = 0;
0030             _bunchcounter[ruid][ruchn] = -1;
0031             _header_found[ruid][ruchn] = false;
0032             _trailer_found[ruid][ruchn] = false;
0033             _readout_flags[ruid][ruchn] = -1;
0034         }
0035     }
0036     _unexpected_felix_counters = 0;
0037     _bad_ruids = 0;
0038 }
0039 
0040 oncsSub_idmvtxv2::~oncsSub_idmvtxv2()
0041 {
0042 
0043 }
0044 
0045 
0046 typedef struct
0047 {
0048     unsigned char d0[3][10];
0049     unsigned char counter;
0050     unsigned char ruid;
0051 }  data32;
0052 
0053 
0054 void oncsSub_idmvtxv2::print_stuff(OSTREAM& out, unsigned int data, int width, int shift, bool blank) const
0055 {
0056     unsigned int mask = 0xffffffff;
0057     if (width<8) mask = ((1 << width*4)-1);
0058     if (blank)
0059         for (int i=0;i<width;i++) out << " ";
0060     else
0061         out << std::hex << SETW(width) << std::setfill('0') << ((data>>shift) & mask);
0062 }
0063 
0064 int oncsSub_idmvtxv2::encode_hit(unsigned short row, unsigned short col) const
0065 {
0066     return (row << 16) + col;
0067 }
0068 
0069 unsigned short oncsSub_idmvtxv2::decode_row(int hit) const
0070 {
0071     return hit >> 16;
0072 }
0073 
0074 unsigned short oncsSub_idmvtxv2::decode_col(int hit) const
0075 {
0076     return hit & 0xffff;
0077 }
0078 
0079 bool oncsSub_idmvtxv2::mask_contains_ruchn ( int mask, int ruchn )
0080 {
0081     if (ruchn<=0) return false; //invalid ruchn
0082     if (mask<0) return false;
0083     return (((mask >> (ruchn-1)) & 1) == 1);
0084 }
0085 
0086 int *oncsSub_idmvtxv2::decode ()
0087 {
0088     if ( _is_decoded) return 0;
0089     _is_decoded = 1;
0090     _decoder_error = 0;
0091 
0092     unsigned int *payload = (unsigned int *) &SubeventHdr->data;  // here begins the payload
0093 
0094     int dlength = getDataLength() - getPadding() - 1; //padding is supposed to be in units of dwords, this assumes dwords
0095     unsigned char *the_end = ( unsigned char *) &payload[dlength];
0096 
0097     unsigned char *pos = (unsigned char *) payload;
0098 
0099     unsigned char b;
0100 
0101     vector<unsigned char> ruchn_stream[IDMVTXV2_MAXRUID+1][IDMVTXV2_MAXRUCHN+1];
0102 
0103     unsigned char felix_counter [IDMVTXV2_MAXRUID+1];
0104 
0105     for( int i=0; i < IDMVTXV2_MAXRUID+1; i++)
0106     {
0107         felix_counter[i] = 0;
0108     }
0109 
0110     while ( pos < the_end )
0111     {
0112 
0113         data32 *d32 = ( data32*) pos;
0114 
0115         //cout << hex << " pos = " << (unsigned long long ) pos << "  the end  " << (unsigned long long) the_end << dec << endl;
0116         if (d32->ruid > IDMVTXV2_MAXRUID)
0117         {
0118             cout << __FILE__ << " " << __LINE__ << " --- invalid ruid " << hex << (int) d32->ruid << " at pos " << (long) pos << dec << endl;
0119             _bad_ruids++;
0120             _decoder_error |= ( 1 << 0 );
0121             break;
0122         }
0123         else if (d32->ruid > _highest_ruid)
0124         {
0125             _highest_ruid = d32->ruid;
0126         }
0127         //FELIX counter is 8 bits, max value 256
0128         //check that the new counter value is consistent with the previous value (it should have increased by no more than 3, and the amount of the difference is the number of data chunks in this FELIX word)
0129         int counter_increment = (d32->counter + 256 - felix_counter[d32->ruid])%256;
0130         if (counter_increment > 3)
0131         {
0132             if (d32->counter != 0)
0133             {
0134                 //cout << __FILE__ << " " << __LINE__ << " --- unexpected FELIX counter " << hex << (int) d32->counter << " following previous counter value " << felix_counter << " at pos " << (long) pos << dec << endl;
0135                 _unexpected_felix_counters++;
0136             }
0137             break;
0138         }
0139         felix_counter[d32->ruid] = d32->counter;
0140 
0141         //for (int ichnk = 0; ichnk < 3; ichnk++)
0142         for (int ichnk = 0; ichnk < counter_increment; ichnk++)
0143         {
0144             unsigned char ruchn = d32->d0[ichnk][9];
0145             if (ruchn >> 4 == 0x2) {
0146               ruchn &= 0x1F;
0147               ruchn += 1;
0148             }
0149             if (ruchn == IDMVTXV2_RUHEADER)
0150             {
0151                 memcpy(&_lanes_active[d32->ruid],&d32->d0[ichnk][2],4);
0152             }
0153             else if (ruchn == IDMVTXV2_RUTRAILER)
0154             {
0155                 memcpy(&_lane_stops[d32->ruid],&d32->d0[ichnk][0],4);
0156                 memcpy(&_lane_timeouts[d32->ruid],&d32->d0[ichnk][4],4);
0157             }
0158             else if (ruchn > IDMVTXV2_MAXRUCHN)
0159             {
0160                 _bad_ruchns[d32->ruid]++;
0161                 cout << __FILE__ << " " << __LINE__ << " --- invalid ruchn " << hex << ruchn << ", full RU word: ";
0162                 _decoder_error |= ( 1 << 1 );
0163                 for (int ibyte=9;ibyte>=0;ibyte--)
0164                 {
0165                     cout << setfill('0') << setw(2) << hex << (unsigned int) d32->d0[ichnk][ibyte] << " ";
0166                 }
0167                 cout << setfill(' ') << setw(0) << dec << endl;
0168             }
0169             else for ( int ibyte = 0; ibyte < 9; ibyte++)
0170             {
0171                 //cout << __FILE__ << " " << __LINE__ << hex << " --- ruchn " << (unsigned int) ruchn << " byte " << (unsigned int) d32->d0[ichnk][ibyte] << dec << endl;
0172                 ruchn_stream[d32->ruid][ruchn].push_back(d32->d0[ichnk][ibyte]);
0173             }
0174         } // ichnk
0175 
0176         pos += sizeof(*d32);
0177     } // while (pos < the_end)
0178 
0179     //we ignore ruchn 0 (trigger information and padding words) for now
0180     /*
0181        if (ruchn_stream[0].size()!=9) for ( int ruchn = 0; ruchn < IDMVTXV2_MAXRUCHN+1; ruchn++)
0182        {
0183        cout << __FILE__ << " " << __LINE__ << " --- ruchn " << ruchn << " has " << ruchn_stream[ruchn].size() << " bytes" << endl;
0184        }
0185        */
0186 
0187     for ( int ruid = 1; ruid < IDMVTXV2_MAXRUID+1; ruid++)
0188     {
0189         for ( int ruchn = 1; ruchn < IDMVTXV2_MAXRUCHN+1; ruchn++)
0190         {
0191 
0192             bool header_seen=false;
0193             int status = 0;
0194             int ibyte_endofdata = -1;
0195             int the_region = -1;
0196             unsigned int address = 0;
0197             unsigned int encoder_id = 0;
0198             for (unsigned int ibyte = 0; ibyte < ruchn_stream[ruid][ruchn].size(); ibyte++)
0199             {
0200                 b = ruchn_stream[ruid][ruchn].at(ibyte);
0201 
0202                 //cout << __FILE__ << " " << __LINE__ << " --- ruchn " << hex << ruchn << " next value " << (unsigned int)  b << dec << " status:" << status << endl;
0203 
0204                 if (status) // we mop up what we started in the last round -
0205                     // these are all cases with more than one byte
0206                 {
0207                     switch (status)
0208                     {
0209                         case CHIPHEADER:
0210 
0211                             _bunchcounter[ruid][ruchn] = b;
0212                             //cout << __FILE__ << " " << __LINE__ << " chip header, ruchn= " << ruchn << " bunchctr= " << hex << _bunchcounter[ruchn] << dec << endl;
0213                             status = 0;
0214                             _header_found[ruid][ruchn] = true;
0215                             break;
0216 
0217                         case CHIPEMPTYFRAME:
0218 
0219                             _bunchcounter[ruid][ruchn] = b;
0220                             // cout << __FILE__ << " " << __LINE__ << " chip empty frame " << hex << ruchn << " " << _bunchcounter[ruchn] << dec << endl;
0221                             ibyte_endofdata = ibyte;
0222                             _header_found[ruid][ruchn] = true;
0223                             _trailer_found[ruid][ruchn] = true;
0224                             status = 0;
0225                             break;
0226 
0227                         case DATASHORT:
0228                             address += b;
0229                             //cout << __FILE__ << " " << __LINE__ << " data short report, hex:" << hex << address << dec << " enc. id " << encoder_id << " address= " << address << " the_region:" << the_region << " ruchn:" << ruchn;
0230                             // the numbering "snakes" its way through a column (fig. 4.5 in the Alpide manual)
0231                             //  0 1  > >    row 0
0232                             //  3 2  < <    row 1
0233                             //  4 5  > >    row 2
0234                             //  7 6  < <   so we need to know if we are in an even or odd row
0235                             if ( the_region >= 0 && encoder_id >=0 )
0236                             {
0237                                 unsigned int row = (address >> 1);
0238                                 unsigned int col = (the_region * 32);
0239                                 col += (encoder_id * 2) + ( (row & 1) ? ( (address & 1) ^ 1 ) : (address & 1) );
0240                                 if ( row < 0 || row >= NROW || col < 0 || col >= NCOL )
0241                                 {
0242                                     cout << __FILE__ << " " << __LINE__ << " impossible pixel coord: " << row
0243                                          << ", " << col << "." << endl;
0244                                     cout << "Check region " << the_region << ", encoder " <<  encoder_id
0245                                          << ", addr " << address << endl;
0246                                     _decoder_error |= ( 1 << 2);
0247                                 }
0248                                 _hit_vectors[ruid][ruchn].push_back(encode_hit(row,col));
0249                             }
0250 
0251                             //cout << endl;
0252                             status = 0;
0253                             break;
0254 
0255                         case DATALONG0:
0256                             address += b;
0257                             status = DATALONG1;
0258                             break;
0259 
0260                         case DATALONG1:
0261                             if ( (b & 0x80) != 0) //required to be 0
0262                             {
0263                                 //cout << __FILE__ << " " << __LINE__ << " unexpected word " << hex << (unsigned int) b << dec << " at ibyte " << ibyte << endl;
0264                                 _bad_bytes[ruid][ruchn]++;
0265                             }
0266                             //cout << __FILE__ << " " << __LINE__ << " data long report, hex:" << hex << address << dec << " enc. id " << encoder_id << " address= " << address << " the_region:" << the_region << " ruchn:" << ruchn << endl;
0267                             // Loop over the hits in the cluster. The pixel specified by the address always has a hit.
0268                             // The next 7 pixels (in priority encoder order) have hits if the corresponding bit in this byte is high.
0269                             // See ALPIDE manual section 3.4.1 on DATA LONG: page 63.
0270                             for (int ihit = 0; ihit<8; ihit++)
0271                             {
0272                                 if (ihit==0 || ((b >> (ihit-1)) & 1))
0273                                 {
0274                                     int hit_address = address + ihit;
0275                                     if ( the_region >= 0 && encoder_id >=0 )
0276                                     {
0277                                         unsigned int row = (hit_address >> 1);
0278                                         unsigned int col = the_region*32;
0279                                         col += (encoder_id * 2) + ( (row & 1) ? ( (hit_address & 1) ^ 1 ) : (hit_address & 1) );
0280                                         if ( row < 0 || row >= NROW || col < 0 || col >= NCOL )
0281                                         {
0282                                             cout << __FILE__ << " " << __LINE__ << " impossible pixel coord: " << row
0283                                                   << ", " << col << "." << endl;
0284                                             cout << "Check region " << the_region << ", encoder " <<  encoder_id
0285                                                   << ", addr " << hit_address << endl;
0286                                             _decoder_error |= ( 1 << 2);
0287                                         }
0288                                         _hit_vectors[ruid][ruchn].push_back(encode_hit(row,col));
0289                                     }
0290                                 }
0291                             }
0292                             status = 0;
0293                             break;
0294                     }
0295                     continue;
0296                 }
0297 
0298                 if (ibyte_endofdata != -1) break;
0299 
0300                 if ( b == 0xff)  // Idle byte, skip
0301                 {
0302                     //cout << __FILE__ << " " << __LINE__ << " IDLE byte " << hex << (unsigned int)  b << dec << endl;
0303                     status = 0;
0304                 }
0305 
0306                 else if ( ( b >> 4) == 0xa) // we have a chip header
0307                 {
0308                     _chip_id[ruid][ruchn] = ( b & 0xf);
0309                     header_seen = true;
0310                     status = CHIPHEADER;
0311                 }
0312 
0313                 else if ( ( b >> 4) == 0xb) // we have a chip trailer
0314                 {
0315                     // cout << __FILE__ << " " << __LINE__ << " chip trailer, ruchn= " << hex << ruchn << dec << endl;
0316                     // break out of the loop, done with this chip
0317                     ibyte_endofdata = ibyte;
0318                     _trailer_found[ruid][ruchn] = true;
0319                     if (!_header_found[ruid][ruchn]) // shouldn't see a trailer without having seen a header
0320                     {
0321                         _bad_bytes[ruid][ruchn]++;
0322                     }
0323                     else
0324                     {
0325                         _readout_flags[ruid][ruchn] = (b & 0xf);
0326                     }
0327                     break;
0328                 }
0329 
0330                 else if ( ( b >> 4) == 0xE) // we have a chip empty frame
0331                 {
0332                     _chip_id[ruid][ruchn] = ( b & 0xf);
0333                     header_seen = true;
0334                     status = CHIPEMPTYFRAME;
0335                 }
0336 
0337                 else if ( ( b >> 5) == 0x6) // we have a region header
0338                 {
0339                     unsigned int region_id = (b & 0x1f);
0340                     if ( region_id <32)
0341                     {
0342                         the_region = region_id;
0343                     }
0344                     else //this is impossible since the region ID is 5 bits
0345                     {
0346                         cout << __FILE__ << " " << __LINE__ << " wrong region header, id=  " << hex << region_id << dec << endl;
0347                         _decoder_error |= ( 1 << 3);
0348                     }
0349                 }
0350 
0351                 else if ( ( b >> 6) == 0x1) // we have a DATA short report
0352                 {
0353                     encoder_id = ( b>>2) & 0xf;
0354                     address = (b & 0x3) << 8;
0355                     status = DATASHORT;
0356                 }
0357 
0358                 else if ( ( b >> 6) == 0x0) // we have a DATA long report
0359                 {
0360                     encoder_id = ( b>>2) & 0xf;
0361                     address = (b & 0x3) << 8;
0362                     status = DATALONG0;
0363                 }
0364 
0365                 else if ( b == 0xF1) // we have a BUSY on
0366                 {
0367                     //cout << __FILE__ << " " << __LINE__ << " Busy on "  << endl;
0368                 }
0369 
0370                 else if ( b == 0xF0) // we have a BUSY off
0371                 {
0372                     //cout << __FILE__ << " " << __LINE__ << " Busy off "  << endl;
0373                 }
0374 
0375                 else
0376                 {
0377                     cout << __FILE__ << " " << __LINE__ << " unexpected word " << hex << (unsigned int) b << dec << " at ibyte " << ibyte << endl;
0378                     _bad_bytes[ruid][ruchn]++;
0379                     _decoder_error |= ( 1 << 4 );
0380                 }
0381 
0382                 if (ibyte==0 && !header_seen)
0383                 {
0384                   cout << __FILE__ << " " << __LINE__ << " " << "first byte of the ALPIDE stream must be a chip header or chip empty;" <<endl;
0385                   cout << "Aborting so we don't get confused by bad data." << endl;
0386                   _decoder_error |= ( 1 << 5 );
0387                    break;
0388                 }
0389 
0390             } // ibyte
0391 
0392             //cout << __FILE__ << " " << __LINE__ << "  ruchn " << ruchn << "  ibyte_endofdata " << ibyte_endofdata << endl;
0393             for (unsigned int ibyte = ibyte_endofdata+1; ibyte < ruchn_stream[ruid][ruchn].size(); ibyte++)
0394             {
0395                 b = ruchn_stream[ruid][ruchn].at(ibyte);
0396                 if (b!=0)
0397                 {
0398                     //cout << __FILE__ << " " << __LINE__ << " --- ruchn " << hex << ruchn << " unexpected nonzero value " << (unsigned int)  b << dec << " at ibyte " << ibyte << " after ibyte_endofdata " << ibyte_endofdata << endl;
0399                     _excess_bytes[ruid][ruchn]++;
0400                 }
0401             }
0402         } // ruchn
0403         if (_lanes_active[ruid] != -1)
0404         {
0405           _inconsistent_bc[ruid]  = this->checkBC(ruid);
0406         }
0407     } // ruid
0408 
0409 
0410     return 0;
0411 }
0412 
0413 int oncsSub_idmvtxv2::iValue(const int ruid, const char *what)
0414 {
0415     decode();
0416     if ( strcmp(what, "DECODER_ERROR") == 0 )
0417     {
0418         return _decoder_error;
0419     }
0420     if ( strcmp(what,"UNEXPECTED_FELIX_COUNTERS") == 0 )
0421     {
0422         return _unexpected_felix_counters;
0423     }
0424 
0425     else if ( strcmp(what,"BAD_RUIDS") == 0 )
0426     {
0427         return _bad_ruids;
0428     }
0429 
0430     if (ruid > _highest_ruid) return -1; // no such RU
0431     if (_lanes_active[ruid]==-1) return -1; // no such RU
0432 
0433     if ( strcmp(what,"BAD_RUCHNS") == 0 )
0434     {
0435         return _bad_ruchns[ruid];
0436     }
0437 
0438     else if ( strcmp(what,"LANE_STOPS") == 0 )
0439     {
0440         return _lane_stops[ruid];
0441     }
0442 
0443     else if ( strcmp(what,"LANE_TIMEOUTS") == 0 )
0444     {
0445         return _lane_timeouts[ruid];
0446     }
0447 
0448     else if ( strcmp(what,"CHECK_BC") == 0 )
0449     {
0450       return _inconsistent_bc[ruid];
0451     }
0452 
0453     return 0;
0454 }
0455 
0456 int oncsSub_idmvtxv2::iValue(const int ruid)
0457 {
0458     decode();
0459 
0460     if (ruid > _highest_ruid) return -1; // no such RU
0461     return _lanes_active[ruid];
0462 }
0463 
0464 int oncsSub_idmvtxv2::iValue(const int ruid, const int ruchn, const char *what)
0465 {
0466     decode();
0467 
0468     if (ruid > _highest_ruid) return -1; // no such RU
0469     if (_lanes_active[ruid]==-1) return -1; // no such RU
0470 
0471     if ( strcmp(what,"CHIP_ID") == 0 )
0472     {
0473         return _chip_id[ruid][ruchn];
0474     }
0475 
0476     else if ( strcmp(what,"BAD_BYTES") == 0 )
0477     {
0478         return _bad_bytes[ruid][ruchn];
0479     }
0480 
0481     else if ( strcmp(what,"EXCESS_BYTES") == 0 )
0482     {
0483         return _excess_bytes[ruid][ruchn];
0484     }
0485 
0486     else if ( strcmp(what,"BUNCHCOUNTER") == 0 )
0487     {
0488         return _bunchcounter[ruid][ruchn];
0489     }
0490 
0491     else if ( strcmp(what,"HEADER_FOUND") == 0 )
0492     {
0493         return _header_found[ruid][ruchn]?1:0;
0494     }
0495 
0496     else if ( strcmp(what,"TRAILER_FOUND") == 0 )
0497     {
0498         return _trailer_found[ruid][ruchn]?1:0;
0499     }
0500 
0501     else if ( strcmp(what,"READOUT_FLAGS") == 0 )
0502     {
0503         return _readout_flags[ruid][ruchn];
0504     }
0505 
0506     return 0;
0507 }
0508 
0509 int oncsSub_idmvtxv2::iValue(const int ruid, const int ruchn)
0510 {
0511     decode();
0512 
0513     if (ruid > _highest_ruid) return -1; // no such RU
0514     if (_lanes_active[ruid]==-1) return -1; // no such RU
0515     if (!mask_contains_ruchn(_lanes_active[ruid],ruchn)) return -1; // no such RU channel
0516     return _hit_vectors[ruid][ruchn].size();
0517 }
0518 
0519 int oncsSub_idmvtxv2::iValue(const int ruid, const int ruchn, const int i)
0520 {
0521     decode();
0522 
0523     if (ruid > _highest_ruid) return -1; // no such RU
0524     if (_lanes_active[ruid]==-1) return -1; // no such RU
0525     if (!mask_contains_ruchn(_lanes_active[ruid],ruchn)) return -1; // no such RU channel
0526     return _hit_vectors[ruid][ruchn].at(i);
0527 }
0528 
0529 void  oncsSub_idmvtxv2::dump ( OSTREAM& os )
0530 {
0531 
0532     identify(os);
0533 
0534     decode();
0535     bool first;
0536     for (int ruid=0; ruid<IDMVTXV2_MAXRUID+1; ruid++)
0537     {
0538         if (iValue(ruid)!=-1)
0539         {
0540             os << "RU ID: " << ruid;
0541             os << ", bad_ruchns=" << iValue(ruid,"BAD_RUCHNS");
0542             os << hex << setfill('0');
0543             os << ", lanes_active 0x" << setw(7) << iValue(ruid);
0544             os << dec;
0545             first=true;
0546             os << " (";
0547             for ( int ruchn = 0; ruchn < IDMVTXV2_MAXRUCHN+1; ruchn++)
0548             {
0549                 if (mask_contains_ruchn(iValue(ruid),ruchn))
0550                 {
0551                     if (!first)
0552                         os << ", ";
0553                     os << ruchn;
0554                     first = false;
0555                 }
0556             }
0557             os << "), inconsistent_bc=" << setw(1) << iValue(ruid,"CHECK_BC");
0558             os << hex << setfill('0');
0559             os << ", lane_stops=0x" << setw(7) << iValue(ruid,"LANE_STOPS");
0560             os << dec;
0561             first=true;
0562             os << " (";
0563             for ( int ruchn = 0; ruchn < IDMVTXV2_MAXRUCHN+1; ruchn++)
0564             {
0565                 if (mask_contains_ruchn(iValue(ruid,"LANE_STOPS"),ruchn))
0566                 {
0567                     if (!first)
0568                         os << ", ";
0569                     os << ruchn;
0570                     first = false;
0571                 }
0572             }
0573             os << hex << setfill('0');
0574             os << "), lane_timeouts=0x" << setw(7) << iValue(ruid,"LANE_TIMEOUTS");
0575             os << dec;
0576             first=true;
0577             os << " (";
0578             for ( int ruchn = 0; ruchn < IDMVTXV2_MAXRUCHN+1; ruchn++)
0579             {
0580                 if (mask_contains_ruchn(iValue(ruid,"LANE_TIMEOUTS"),ruchn))
0581                 {
0582                     if (!first)
0583                         os << ", ";
0584                     os << ruchn;
0585                     first = false;
0586                 }
0587             }
0588             os << ")";
0589             os << dec << setfill(' ') << endl;
0590             for ( int ruchn = 0; ruchn < IDMVTXV2_MAXRUCHN+1; ruchn++)
0591             {
0592                 if (iValue(ruid,ruchn)!=-1)
0593                 {
0594                     os << "RU channel " << setw(2) << ruchn;
0595                     os << " bad_bytes=" << iValue(ruid,ruchn,"BAD_BYTES") << " excess_bytes=" << iValue(ruid,ruchn,"EXCESS_BYTES") <<" header_found=" << iValue(ruid,ruchn,"HEADER_FOUND") << " trailer_found=" << iValue(ruid,ruchn,"TRAILER_FOUND");
0596                     os << " bunchcounter=" << setw(3) << iValue(ruid,ruchn,"BUNCHCOUNTER") << " flags=" << iValue(ruid,ruchn,"READOUT_FLAGS");
0597                     os << ", chip ID " << iValue(ruid,ruchn,"CHIP_ID") << ", " << iValue(ruid,ruchn) << " hits: ";
0598                     for (int i=0;i<iValue(ruid,ruchn);i++)
0599                     {
0600                         int hit = iValue(ruid,ruchn,i);
0601                         os << "(row " << decode_row(hit) << ", col " << decode_col(hit) << ") ";
0602                     }
0603                     os << endl;
0604                 }
0605             }
0606         }
0607     }
0608 }
0609 
0610 //copied from oncsSubevent.cc for a generic dump 12/21/17
0611 void oncsSub_idmvtxv2::gdump(const int i, OSTREAM& out) const
0612 {
0613 
0614     int *SubeventData = &SubeventHdr->data;
0615     unsigned int j,l;
0616     identify(out);
0617 
0618     int current_offset;
0619     const int DWORDS_PER_WORD = 8;
0620 
0621     switch (i)
0622     {
0623         case (EVT_HEXADECIMAL):
0624             //j = 0;
0625             current_offset = 0;
0626             while (1)
0627             {
0628                 //int dwords_remaining = getLength()-SEVTHEADERLENGTH - getPadding()/4 - current_offset; //padding is supposed to be in units of dwords, this assumes bytes
0629                 int dwords_remaining = getLength()-SEVTHEADERLENGTH - getPadding() - current_offset; //padding is supposed to be in units of dwords, this assumes dwords
0630 
0631                 out << SETW(5) << current_offset << " |  ";
0632                 //for (l=0;l<DWORDS_PER_WORD;l++)
0633 
0634                 //FELIX header
0635                 print_stuff(out, SubeventData[current_offset+7], 4, 16, (dwords_remaining<=7));
0636                 out << " ";
0637 
0638                 //RU word 2
0639                 print_stuff(out, SubeventData[current_offset+7], 4, 0, (dwords_remaining<=7));
0640                 print_stuff(out, SubeventData[current_offset+6], 8, 0, (dwords_remaining<=6));
0641                 print_stuff(out, SubeventData[current_offset+5], 8, 0, (dwords_remaining<=5));
0642                 out << " ";
0643 
0644                 //RU word 1
0645                 print_stuff(out, SubeventData[current_offset+4], 8, 0, (dwords_remaining<=4));
0646                 print_stuff(out, SubeventData[current_offset+3], 8, 0, (dwords_remaining<=3));
0647                 print_stuff(out, SubeventData[current_offset+2], 4, 16, (dwords_remaining<=2));
0648                 out << " ";
0649 
0650                 //RU word 0
0651                 print_stuff(out, SubeventData[current_offset+2], 4, 0, (dwords_remaining<=2));
0652                 print_stuff(out, SubeventData[current_offset+1], 8, 0, (dwords_remaining<=1));
0653                 print_stuff(out, SubeventData[current_offset+0], 8, 0, (dwords_remaining<=0));
0654                 out << " " << std::dec << std::endl << std::setfill(' ');
0655 
0656                 if (dwords_remaining<8) break;
0657 
0658                 current_offset += DWORDS_PER_WORD;
0659             }
0660             break;
0661 
0662         case (EVT_DECIMAL):
0663             j = 0;
0664             while (1)
0665             {
0666                 out << std::dec << std::endl << SETW(5) << j << " |  ";
0667 
0668                 for (l=0;l<6;l++)
0669                 {
0670                     out << SETW(10) << SubeventData[j++] << " ";
0671                     if (j >= SubeventHdr->sub_length-SEVTHEADERLENGTH - SubeventHdr->sub_padding) break;
0672                 }
0673                 if (j>=SubeventHdr->sub_length-SEVTHEADERLENGTH - SubeventHdr->sub_padding) break;
0674             }
0675             break;
0676 
0677         default:
0678             break;
0679     }
0680     out << std::endl;
0681 
0682 }
0683 
0684 bool oncsSub_idmvtxv2::checkBC(const int ruid)
0685 {
0686   bool first_active = true;
0687   unsigned int first_active_lane;
0688   for (int iruchn = 0; iruchn < IDMVTXV2_MAXRUCHN+1; ++iruchn)
0689   {
0690     if (this->mask_contains_ruchn(_lanes_active[ruid], iruchn))
0691     {
0692       if (first_active)
0693       {
0694         first_active_lane = iruchn;
0695         first_active = false;
0696       }
0697       else if (_bunchcounter[ruid][iruchn] != _bunchcounter[ruid][first_active_lane])
0698         return true;
0699     }
0700   }
0701 
0702   return false;
0703 }