RegisterTester.cc 37.7 KB
Newer Older
1
#include "RegisterTester.h"
2
3
4
5

using namespace Ph2_HwDescription;
using namespace Ph2_HwInterface;
using namespace Ph2_System;
6

Fabio Ravera's avatar
Fabio Ravera committed
7
RegisterTester::RegisterTester() : Tool() { fNBadRegisters = 0; }
8
9
10

// D'tor
RegisterTester::~RegisterTester() {}
11

12
13
14
15
void RegisterTester::Initialise()
{
    // this is needed if you're going to use groups anywhere
    initializeRecycleBin();
Sarah Seif El Nasr's avatar
Sarah Seif El Nasr committed
16

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
    // read back original masks
    const auto cTimeStart = std::chrono::system_clock::now();
    fStartTime            = std::chrono::duration_cast<std::chrono::seconds>(cTimeStart.time_since_epoch()).count();
    LOG(INFO) << BOLDMAGENTA << "RegisterTester::Initialise at " << fStartTime << " s from epoch." << RESET;

    // clear map of modified registers
    fReadoutChipInterface->ClearModifiedRegisterMap();
    bool cIsPS = false;
    for(auto cBoard: *fDetectorContainer)
    {
        for(auto cOpticalGroup: *cBoard)
        {
            bool cWithLpGBT = (cOpticalGroup->flpGBT != nullptr);
            for(auto cHybrid: *cOpticalGroup)
            {
                if(cIsPS) continue;

                auto cType    = FrontEndType::SSA;
                bool cWithSSA = (std::find_if(cHybrid->begin(), cHybrid->end(), [&cType](Ph2_HwDescription::Chip* x) { return x->getFrontEndType() == cType; }) != cHybrid->end());
                cType         = FrontEndType::MPA;
                bool cWithMPA = (std::find_if(cHybrid->begin(), cHybrid->end(), [&cType](Ph2_HwDescription::Chip* x) { return x->getFrontEndType() == cType; }) != cHybrid->end());
                cIsPS         = (cWithSSA && cWithMPA) && cWithLpGBT;
            }
        }
    }
    if(cIsPS) static_cast<PSInterface*>(fReadoutChipInterface)->ResetModifiedRegisterMap();
}

void RegisterTester::RegisterTest()
{
47
    std::vector<std::string> cRegsToSkip{"Bandgap","ChipIDFuse","FeCtrl&TrgLat2"};
48
    size_t  cAttempts = 1;
49
    uint8_t cTestFlavor = 0; 
50
    // first just test page toggle 
51
52
    LOG(INFO) << BOLDMAGENTA << "Test" << +cTestFlavor << " of I2C registers in CBCs .... just going to toggle the page without writing..." << RESET;
    uint8_t cSortOrder=0;       
53
54
    //uint8_t cFirstPage=(cSortOrder==0)? 0 : 1; 
    std::vector<uint8_t> cPages{1,0};//static_cast<uint8_t>(~cFirstPage&0x01),cFirstPage,static_cast<uint8_t>(~cFirstPage&0x01)};
55

56
57
58
59
60
61
62
63
    
    // first I want to record the register map for this map
    // retreive original settings for all chips and all back-end boards
    DetectorDataContainer cRegListContainer;
    ContainerFactory::copyAndInitChip<Registers>(*fDetectorContainer, cRegListContainer);
    for(auto cBoard: *fDetectorContainer)
    {
        for(auto cOpticalGroup: *cBoard)
64
        {
65
            for(auto cHybrid: *cOpticalGroup)
66
            {
67
                for(auto cChip: *cHybrid)
68
                {
69
70
71
72
73
74
75
76
77
78
                    Registers&        cRegList = cRegListContainer.at(cBoard->getIndex())->at(cOpticalGroup->getIndex())->at(cHybrid->getIndex())->at(cChip->getIndex())->getSummary<Registers>();
                    const ChipRegMap& cOriginalMap = cChip->getRegMap();
                    for(auto cMapItem: cOriginalMap) { 
                        if( std::find( cRegsToSkip.begin(), cRegsToSkip.end(), cMapItem.first ) != cRegsToSkip.end() ) continue; 
                        LOG (DEBUG) << BOLDMAGENTA << "Will configure register " << cMapItem.first 
                            << " on page " << +cMapItem.second.fPage 
                            << " with address " << +cMapItem.second.fAddress 
                            << " with value 0x" << std::hex << +cMapItem.second.fValue  << std::dec
                            << RESET;
                        cRegList.push_back(std::make_pair(cMapItem.first, cMapItem.second)); 
79
                    }
80
81
82
                    // registers sorted by ... all on page 0 then all on page 1
                    if(cSortOrder == 0) std::sort(cRegList.begin(), cRegList.end(), customLessThanPage);    // all to page0 then page 1
                    if(cSortOrder == 1) std::sort(cRegList.begin(), cRegList.end(), customGreaterThanPage); // all to page1 then page 0
83
                }
84
            }
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
        }
    } // board loop to save record of registers

    // so here .. I need to send a hard reset to the ROCs
    LOG(INFO) << BOLDMAGENTA << "Sending hard reste to ROCs..." << RESET;
    for(auto cBoard: *fDetectorContainer)
    {
        auto cWithLpGBT = fReadoutChipInterface->lpGBTCheck(cBoard);
        if(!cWithLpGBT)
        {
            fBeBoardInterface->ChipReset(cBoard);
            continue;
        }
        for(auto cOpticalGroup: *cBoard)
        {
            auto& clpGBT = cOpticalGroup->flpGBT;
            for(auto cHybrid: *cOpticalGroup)
            {
                auto cType    = FrontEndType::CBC3;
                bool cWithCBC = (std::find_if(cHybrid->begin(), cHybrid->end(), [&cType](Ph2_HwDescription::Chip* x) { return x->getFrontEndType() == cType; }) != cHybrid->end());
                cType         = FrontEndType::SSA;
                bool cWithSSA = (std::find_if(cHybrid->begin(), cHybrid->end(), [&cType](Ph2_HwDescription::Chip* x) { return x->getFrontEndType() == cType; }) != cHybrid->end());
                cType         = FrontEndType::MPA;
                bool cWithMPA = (std::find_if(cHybrid->begin(), cHybrid->end(), [&cType](Ph2_HwDescription::Chip* x) { return x->getFrontEndType() == cType; }) != cHybrid->end());

                if(cWithCBC) static_cast<D19clpGBTInterface*>(flpGBTInterface)->resetCBC(clpGBT, cHybrid->getId() % 2);
                if(cWithSSA) static_cast<D19clpGBTInterface*>(flpGBTInterface)->resetSSA(clpGBT, cHybrid->getId() % 2);
                if(cWithMPA) static_cast<D19clpGBTInterface*>(flpGBTInterface)->resetMPA(clpGBT, cHybrid->getId() % 2);
            }
        }
    } // board loop to send hard reset

117
    
118
    // container to store default register values after a hard reset
119
    LOG(INFO) << BOLDMAGENTA << "Reading back default register values after a hard reset ... using values stored in register map " << RESET;
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
    DetectorDataContainer cDefRegListContainer;
    ContainerFactory::copyAndInitChip<Registers>(*fDetectorContainer, cDefRegListContainer);
    for(auto cBoard: *fDetectorContainer)
    {
        for(auto cOpticalGroup: *cBoard)
        {
            for(auto cHybrid: *cOpticalGroup)
            {
                for(auto cChip: *cHybrid)
                {
                    Registers& cOriginaList = cRegListContainer.at(cBoard->getIndex())->at(cOpticalGroup->getIndex())->at(cHybrid->getIndex())->at(cChip->getIndex())->getSummary<Registers>();
                    Registers& cList        = cDefRegListContainer.at(cBoard->getIndex())->at(cOpticalGroup->getIndex())->at(cHybrid->getIndex())->at(cChip->getIndex())->getSummary<Registers>();
                    // set page to that of the first register in the map
                    // if( cChip->getFrontEndType() == FrontEndType::CBC3 ) static_cast<CbcInterface*>(fReadoutChipInterface)->ConfigurePage( cChip, 1);//(*cOriginalMap.begin()).second.fPage );
                    for(auto cListItem: cOriginaList)
                    {
                        if( std::find( cRegsToSkip.begin(), cRegsToSkip.end(), cListItem.first ) != cRegsToSkip.end() ) continue; 
                        
                        auto cRegItem   = cListItem.second;
139
                        cRegItem.fValue = (uint8_t)( cChip->getRegItem( cListItem.first ).fDefValue );//fReadoutChipInterface->ReadChipReg(cChip, cListItem.first);
140
141
142
143
144
145
146
147
148
149
                        cList.push_back(std::make_pair(cListItem.first, cRegItem));
                        LOG (DEBUG) << BOLDMAGENTA << "Default value after a hard reset of register " << cListItem.first << " is 0x"
                            << std::hex << +cRegItem.fValue << std::dec
                            << " value after configuration should be 0x" << std::hex << cListItem.second.fValue << std::dec
                            << RESET;
                    } // map
                }     // chip
            }         // hybrid
        }             // OG
    }                 // board loop to save record of registers
150

151
152
    for(size_t cAttempt = 0; cAttempt < cAttempts; cAttempt++)
    {
153
        // so here .. I need to send a hard reset to the ROCs
154
        LOG(INFO) << BOLDMAGENTA << "Sending hard reste to ROCs...[Test Attempt#" << +cAttempt << "]" << RESET;
155
156
157
158
        for(auto cBoard: *fDetectorContainer)
        {
            auto cWithLpGBT = fReadoutChipInterface->lpGBTCheck(cBoard);
            if(!cWithLpGBT)
Sarah Seif El Nasr's avatar
Sarah Seif El Nasr committed
159
            {
160
161
162
163
164
165
166
                fBeBoardInterface->ChipReset(cBoard);
                continue;
            }
            for(auto cOpticalGroup: *cBoard)
            {
                auto& clpGBT = cOpticalGroup->flpGBT;
                for(auto cHybrid: *cOpticalGroup)
167
                {
168
169
170
171
172
173
174
175
176
177
                    auto cType    = FrontEndType::CBC3;
                    bool cWithCBC = (std::find_if(cHybrid->begin(), cHybrid->end(), [&cType](Ph2_HwDescription::Chip* x) { return x->getFrontEndType() == cType; }) != cHybrid->end());
                    cType         = FrontEndType::SSA;
                    bool cWithSSA = (std::find_if(cHybrid->begin(), cHybrid->end(), [&cType](Ph2_HwDescription::Chip* x) { return x->getFrontEndType() == cType; }) != cHybrid->end());
                    cType         = FrontEndType::MPA;
                    bool cWithMPA = (std::find_if(cHybrid->begin(), cHybrid->end(), [&cType](Ph2_HwDescription::Chip* x) { return x->getFrontEndType() == cType; }) != cHybrid->end());

                    if(cWithCBC) static_cast<D19clpGBTInterface*>(flpGBTInterface)->resetCBC(clpGBT, cHybrid->getId() % 2);
                    if(cWithSSA) static_cast<D19clpGBTInterface*>(flpGBTInterface)->resetSSA(clpGBT, cHybrid->getId() % 2);
                    if(cWithMPA) static_cast<D19clpGBTInterface*>(flpGBTInterface)->resetMPA(clpGBT, cHybrid->getId() % 2);
178
                }
179
180
181
            }
        } // board loop to send hard reset

182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
        // reset page map 
        LOG(INFO) << BOLDMAGENTA << "Resetting page map ..." << RESET;
        for(auto cBoard: *fDetectorContainer)
        {
            for(auto cOpticalGroup: *cBoard)
            {
                for(auto cHybrid: *cOpticalGroup)
                {
                    for(auto cChip: *cHybrid)
                    {
                        if( cChip->getFrontEndType() != FrontEndType::CBC3 ) continue;
                        static_cast<CbcInterface*>(fReadoutChipInterface)->resetPageMap(); 
                    } // chip
                } // hybrid
            } // OG
        } 
198

199
200
201
202
        // now .. try and change page after config and look for mis-matches
        for(auto cBoard: *fDetectorContainer)
        {
            for(auto cOpticalGroup: *cBoard)
203
            {
204
                for(auto cHybrid: *cOpticalGroup)
205
                {
206
                    for(auto cChip: *cHybrid)
207
                    {
208
                        LOG (INFO) << BOLDMAGENTA << "Chip#" << +cChip->getId() << " on hybrid" << +cHybrid->getId() << RESET;
209
210
211
212
213
214
                        Registers& cExpectedLst = cDefRegListContainer.at(cBoard->getIndex())->at(cOpticalGroup->getIndex())->at(cHybrid->getIndex())->at(cChip->getIndex())->getSummary<Registers>();
                        Registers  cSensitiveRegisters;
                        cSensitiveRegisters.clear();
                        std::vector<int> cPageToggles(0);
                        uint8_t cPreviousPage = static_cast<CbcInterface*>(fReadoutChipInterface)->GetLastPage(cChip);
                        for(auto cPage : cPages )
215
                        {
216
                            LOG (INFO) << BOLDMAGENTA << "\t\t.. Going to select page " << +cPage
217
                                << " - previous page was " << +cPreviousPage << RESET;
218
219
220
221

                            static_cast<CbcInterface*>(fReadoutChipInterface)->ConfigurePage( cChip, cPage );
                            // check for mismatches
                            size_t cMatches = 0;
222
                            size_t cNRegs  = 0; 
223
                            for(auto& cItem: cExpectedLst) // loop over what I think the current values are
224
                            {
225
226
                                if( cItem.second.fPage == cPage ) continue; 

227
                                // compare the value read back from the chip against what is expected
228
                                LOG (DEBUG) << BOLDMAGENTA << "\t... Reading back value from register " << cItem.first << " on page " << +cItem.second.fPage << " with value 0x" 
229
230
231
                                    << std::hex << +cItem.second.fValue << std::dec << RESET;
                                auto cReadBack = fReadoutChipInterface->ReadChipReg(cChip, cItem.first);
                                auto cValue    = cItem.second.fValue;
Sarah Seif El Nasr's avatar
Sarah Seif El Nasr committed
232

233
234
235
236
237
238
239
240
241
                                bool cCorrupted = cReadBack != cValue;
                                if(cCorrupted)
                                {
                                    std::string cRegName = cItem.first;
                                    if(std::find_if(cSensitiveRegisters.begin(), cSensitiveRegisters.end(), [&cRegName](Register x) { return x.first == cRegName; }) == cSensitiveRegisters.end())
                                    {
                                        cSensitiveRegisters.push_back(cItem);
                                        cPageToggles.push_back( cPreviousPage - cPage );
                                    }
242
                                    LOG (INFO) << BOLDRED << "\t\t\t\t..When switching from page " << +cPreviousPage
243
                                            << " to page " << +cPage
244
                                            << " register# " << +cNRegs 
245
246
                                            << "\t\t...Mismatch in I2C register " << cItem.first << " value stored in map is 0x" << std::hex << +cItem.second.fValue << std::dec
                                            << " value read-back from chip is 0x" << std::hex << +cReadBack << std::dec << RESET;
247
248
249
                                    // if register value does not match 
                                    // then update value in memory 
                                    cItem.second.fValue =cReadBack; 
250
251
252
                                }
                                else
                                {
253
                                    LOG (DEBUG) << BOLDGREEN << "\t\t...Match in I2C register " << cItem.first
254
255
256
257
258
                                        << " value stored in map is 0x" << std::hex << +cItem.second.fValue << std::dec
                                        << " value read-back from chip is 0x" << std::hex << +cReadBack << std::dec
                                        << RESET;
                                    cMatches++;
                                }
259
                                cNRegs++;
260

261
                            } // loop over current values and compare what I read back against what I have stored in memory
262
                            float cMatchedPerc = cMatches / (float)(cExpectedLst.size() );
263
                            if( cMatches == cNRegs )
264
                                LOG(INFO) << BOLDGREEN << "\t\t.. Found read-back matched fraction from other registers to be " << 100 * cMatchedPerc << " percent. Found " 
265
266
                                  << +cSensitiveRegisters.size() << " sensitive registers." <<  RESET;
                            else
267
                                LOG(INFO) << BOLDRED << "\t\t.. Found read-back matched fraction from other registers to be " << 100 * cMatchedPerc << " percent. Found " 
268
269
                                  << +cSensitiveRegisters.size() << " sensitive registers." <<  RESET;
                            
270
271
272
273
                            cPreviousPage = cPage;
                        } // register write loop
                        std::sort(cSensitiveRegisters.begin(), cSensitiveRegisters.end(), customGreaterThanAddress);
                        for( auto cSensitiveRegister : cSensitiveRegisters ) 
274
                        {
275
276
277
278
279
280
                            LOG (INFO) << BOLDRED << "Sensitive register " << cSensitiveRegister.first << " on page " << +cSensitiveRegister.second.fPage << RESET;
                        }
                    }     // chip
                }         // hybrid
            }             // OG
        }                 // board loop to run test
281
    
282
    }
283
    cTestFlavor++;
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387

    // // 0, increasing page order
    // // 1, decreasing page order
    // // 2, don't sort
    // size_t  cLimitPerPage = 2;
   // for(uint8_t cSortOrder = 0; cSortOrder < 2; cSortOrder++)
    // {
    //     for(size_t cAttempt = 0; cAttempt < cAttempts; cAttempt++)
    //     {
    //         LOG(INFO) << BOLDMAGENTA << "Test#" << +cAttempt << " I2C registers .... sort oder is " << +cSortOrder << RESET;
                            
    //         // first I want to record the register map for this map
    //         // retreive original settings for all chips and all back-end boards
    //         DetectorDataContainer cRegListContainer;
    //         ContainerFactory::copyAndInitChip<Registers>(*fDetectorContainer, cRegListContainer);
    //         for(auto cBoard: *fDetectorContainer)
    //         {
    //             for(auto cOpticalGroup: *cBoard)
    //             {
    //                 for(auto cHybrid: *cOpticalGroup)
    //                 {
    //                     for(auto cChip: *cHybrid)
    //                     {
    //                         Registers&        cRegList = cRegListContainer.at(cBoard->getIndex())->at(cOpticalGroup->getIndex())->at(cHybrid->getIndex())->at(cChip->getIndex())->getSummary<Registers>();
    //                         const ChipRegMap& cOriginalMap = cChip->getRegMap();
    //                         for(auto cMapItem: cOriginalMap) { 
    //                             if( std::find( cRegsToSkip.begin(), cRegsToSkip.end(), cMapItem.first ) != cRegsToSkip.end() ) continue; 
    //                             LOG (DEBUG) << BOLDMAGENTA << "Will configure register " << cMapItem.first 
    //                                 << " on page " << +cMapItem.second.fPage 
    //                                 << " with address " << +cMapItem.second.fAddress 
    //                                 << " with value 0x" << std::hex << +cMapItem.second.fValue  << std::dec
    //                                 << RESET;
    //                             cRegList.push_back(std::make_pair(cMapItem.first, cMapItem.second)); 
    //                         }
    //                         // registers sorted by ... all on page 0 then all on page 1
    //                         if(cSortOrder == 0) std::sort(cRegList.begin(), cRegList.end(), customLessThanPage);    // all to page0 then page 1
    //                         if(cSortOrder == 1) std::sort(cRegList.begin(), cRegList.end(), customGreaterThanPage); // all to page1 then page 0
    //                     }
    //                 }
    //             }
    //         } // board loop to save record of registers

    //         // so here .. I need to send a hard reset to the ROCs
    //         for(auto cBoard: *fDetectorContainer)
    //         {
    //             auto cWithLpGBT = fReadoutChipInterface->lpGBTCheck(cBoard);
    //             if(!cWithLpGBT)
    //             {
    //                 fBeBoardInterface->ChipReset(cBoard);
    //                 continue;
    //             }
    //             for(auto cOpticalGroup: *cBoard)
    //             {
    //                 auto& clpGBT = cOpticalGroup->flpGBT;
    //                 for(auto cHybrid: *cOpticalGroup)
    //                 {
    //                     auto cType    = FrontEndType::CBC3;
    //                     bool cWithCBC = (std::find_if(cHybrid->begin(), cHybrid->end(), [&cType](Ph2_HwDescription::Chip* x) { return x->getFrontEndType() == cType; }) != cHybrid->end());
    //                     cType         = FrontEndType::SSA;
    //                     bool cWithSSA = (std::find_if(cHybrid->begin(), cHybrid->end(), [&cType](Ph2_HwDescription::Chip* x) { return x->getFrontEndType() == cType; }) != cHybrid->end());
    //                     cType         = FrontEndType::MPA;
    //                     bool cWithMPA = (std::find_if(cHybrid->begin(), cHybrid->end(), [&cType](Ph2_HwDescription::Chip* x) { return x->getFrontEndType() == cType; }) != cHybrid->end());

    //                     if(cWithCBC) static_cast<D19clpGBTInterface*>(flpGBTInterface)->resetCBC(clpGBT, cHybrid->getId() % 2);
    //                     if(cWithSSA) static_cast<D19clpGBTInterface*>(flpGBTInterface)->resetSSA(clpGBT, cHybrid->getId() % 2);
    //                     if(cWithMPA) static_cast<D19clpGBTInterface*>(flpGBTInterface)->resetMPA(clpGBT, cHybrid->getId() % 2);
    //                 }
    //             }
    //         } // board loop to send hard reset

    //         // reset page map 
    //         for(auto cBoard: *fDetectorContainer)
    //         {
    //             for(auto cOpticalGroup: *cBoard)
    //             {
    //                 for(auto cHybrid: *cOpticalGroup)
    //                 {
    //                     for(auto cChip: *cHybrid)
    //                     {
    //                         if( cChip->getFrontEndType() != FrontEndType::CBC3 ) continue;
    //                         static_cast<CbcInterface*>(fReadoutChipInterface)->resetPageMap(); 
    //                     } // chip
    //                 } // hybrid
    //             } // OG
    //         } 

    //         // container to store default register values after a hard reset
    //         DetectorDataContainer cDefRegListContainer;
    //         ContainerFactory::copyAndInitChip<Registers>(*fDetectorContainer, cDefRegListContainer);
    //         for(auto cBoard: *fDetectorContainer)
    //         {
    //             for(auto cOpticalGroup: *cBoard)
    //             {
    //                 for(auto cHybrid: *cOpticalGroup)
    //                 {
    //                     for(auto cChip: *cHybrid)
    //                     {
    //                         Registers& cOriginaList = cRegListContainer.at(cBoard->getIndex())->at(cOpticalGroup->getIndex())->at(cHybrid->getIndex())->at(cChip->getIndex())->getSummary<Registers>();
    //                         Registers& cList        = cDefRegListContainer.at(cBoard->getIndex())->at(cOpticalGroup->getIndex())->at(cHybrid->getIndex())->at(cChip->getIndex())->getSummary<Registers>();
    //                         // set page to that of the first register in the map
    //                         // if( cChip->getFrontEndType() == FrontEndType::CBC3 ) static_cast<CbcInterface*>(fReadoutChipInterface)->ConfigurePage( cChip, 1);//(*cOriginalMap.begin()).second.fPage );
    //                         for(auto cListItem: cOriginaList)
    //                         {
    //                             if( std::find( cRegsToSkip.begin(), cRegsToSkip.end(), cListItem.first ) != cRegsToSkip.end() ) continue; 
388
                                
389
390
391
392
393
394
395
396
397
398
399
400
401
402
    //                             auto cRegItem   = cListItem.second;
    //                             cRegItem.fValue = fReadoutChipInterface->ReadChipReg(cChip, cListItem.first);
    //                             cList.push_back(std::make_pair(cListItem.first, cRegItem));
    //                             LOG (DEBUG) << BOLDMAGENTA << "Default value after a hard reset of register " << cListItem.first << " is 0x"
    //                                 << std::hex << +cRegItem.fValue << std::dec
    //                                 << " value after configuration should be 0x" << std::hex << cListItem.second.fValue << std::dec
    //                                 << RESET;
    //                         } // map
    //                     }     // chip
    //                 }         // hybrid
    //             }             // OG
    //         }                 // board loop to save record of registers

    //         //continue;
403

404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
    //         // now .. try and re-write original values after config and look for mis-matches
    //         for(auto cBoard: *fDetectorContainer)
    //         {
    //             for(auto cOpticalGroup: *cBoard)
    //             {
    //                 for(auto cHybrid: *cOpticalGroup)
    //                 {
    //                     for(auto cChip: *cHybrid)
    //                     {
    //                         LOG (INFO) << BOLDMAGENTA << "Chip#" << +cChip->getId() << RESET;
    //                         Registers& cListToCnfig = cRegListContainer.at(cBoard->getIndex())->at(cOpticalGroup->getIndex())->at(cHybrid->getIndex())->at(cChip->getIndex())->getSummary<Registers>();
    //                         Registers  cCnfgList;
    //                         size_t     cNPage0Regs, cNPage1Regs = 0;
    //                         cNPage0Regs = cNPage1Regs;
    //                         for(auto cItem: cListToCnfig)
    //                         {
    //                             if( std::find( cRegsToSkip.begin(), cRegsToSkip.end(), cItem.first ) != cRegsToSkip.end() ) continue; 
                                
    //                             bool cPushBack = (cItem.second.fPage == 0 && cNPage0Regs < cLimitPerPage) || (cItem.second.fPage == 1 && cNPage1Regs < cLimitPerPage);
    //                             if(!cPushBack) continue;

    //                             cCnfgList.push_back(cItem);
    //                             if(cItem.second.fPage == 0) cNPage0Regs++;
    //                             if(cItem.second.fPage == 1) cNPage1Regs++;
    //                         }
429
                            
430
431
432
433
434
435
436
    //                         LOG (DEBUG) << BOLDMAGENTA << "Going to test using " << +cNPage0Regs << " register(s) on Page0 and " << +cNPage1Regs << " register(s) on Page1 " << RESET;
    //                         Registers& cExpectedLst = cDefRegListContainer.at(cBoard->getIndex())->at(cOpticalGroup->getIndex())->at(cHybrid->getIndex())->at(cChip->getIndex())->getSummary<Registers>();
    //                         Registers  cSensitiveRegisters;
    //                         cSensitiveRegisters.clear();
    //                         std::vector<int> cPageToggles(0);
    //                         std::vector<std::string> cRegistersChecked;
    //                         cRegistersChecked.clear();
437
                            
438
439
440
441
442
443
444
445
446
447
448
449
    //                         uint8_t cPage = static_cast<CbcInterface*>(fReadoutChipInterface)->GetLastPage(cChip);
    //                         uint8_t cPreviousPage; 
    //                         for(auto cConfigItem: cCnfgList)
    //                         {
    //                             cPreviousPage = cPage;
    //                             cPage = cConfigItem.second.fPage;
    //                             LOG (DEBUG) << BOLDMAGENTA << "Going to configure register " << cConfigItem.first 
    //                                 << " on page " << +cConfigItem.second.fPage 
    //                                 << " with address " << +cConfigItem.second.fAddress 
    //                                 << " with value 0x" << std::hex << +cConfigItem.second.fValue  << std::dec
    //                                 << " page toggle from Page " << +(cPreviousPage) << " to page " << +cPage
    //                                 << RESET;
450

451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
    //                             // so .. first thing I want to do is write the test value to this register
    //                             // first make sure chips local map is  updated
    //                             cChip->setReg(cConfigItem.first, cConfigItem.second.fValue, cConfigItem.second.fPrmptCfg, cConfigItem.second.fStatusReg);
    //                             // write register 
    //                             fReadoutChipInterface->WriteChipReg(cChip, cConfigItem.first, cConfigItem.second.fValue);
    //                             // check for mismatches
    //                             size_t cMatches = 0;
    //                             for(auto& cItem: cExpectedLst) // loop over what I think the current values are
    //                             {
    //                                 // skip checking a register against itself
    //                                 // but update expected value in current list 
    //                                 if(cItem.first == cConfigItem.first){ 
    //                                     cItem.second = cConfigItem.second;
    //                                     continue;
    //                                 }
466

467
468
469
470
471
    //                                 // compare the value read back from the chip against what is expected
    //                                 LOG (DEBUG) << BOLDMAGENTA << "\t... Reading back value from register " << cItem.first << " on page " << +cItem.second.fPage << " with value 0x" 
    //                                     << std::hex << +cItem.second.fValue << std::dec << RESET;
    //                                 auto cReadBack = fReadoutChipInterface->ReadChipReg(cChip, cItem.first);
    //                                 auto cValue    = cItem.second.fValue;
472

473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
    //                                 bool cCorrupted = cReadBack != cValue;
    //                                 if(cCorrupted)
    //                                 {
    //                                     std::string cRegName = cItem.first;
    //                                     if(std::find_if(cSensitiveRegisters.begin(), cSensitiveRegisters.end(), [&cRegName](Register x) { return x.first == cRegName; }) == cSensitiveRegisters.end())
    //                                     {
    //                                         cSensitiveRegisters.push_back(cItem);
    //                                         cPageToggles.push_back( cPreviousPage - cPage );
    //                                     }
    //                                     LOG (INFO) << BOLDRED << "When configuring register " << cConfigItem.first 
    //                                             << " on page " << +cConfigItem.second.fPage 
    //                                             << " with address " << +cConfigItem.second.fAddress 
    //                                             << " with value 0x" << std::hex << +cConfigItem.second.fValue  << std::dec
    //                                             << " page toggle from Page " << +(cPreviousPage) << " to page " << +cPage
    //                                             << "\t\t...Mismatch in I2C register " << cItem.first << " value stored in map is 0x" << std::hex << +cItem.second.fValue << std::dec
    //                                             << " value read-back from chip is 0x" << std::hex << +cReadBack << std::dec << RESET;
    //                                     // if register value does not match
    //                                     // re-write 
    //                                     fReadoutChipInterface->WriteChipReg(cChip, cRegName, cItem.second.fValue);
    //                                 }
    //                                 else
    //                                 {
    //                                     LOG (DEBUG) << BOLDGREEN << "\t\t...Match in I2C register " << cItem.first
    //                                         << " value stored in map is 0x" << std::hex << +cItem.second.fValue << std::dec
    //                                         << " value read-back from chip is 0x" << std::hex << +cReadBack << std::dec
    //                                         << RESET;
    //                                     cMatches++;
    //                                 }
501

502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
    //                             } // loop over current values and compare what I read back against what I have stored in memory
    //                             cRegistersChecked.push_back(cConfigItem.first);
    //                             float cMatchedPerc = cMatches / (float)(cExpectedLst.size() - 1);
    //                             if( cMatches != (cExpectedLst.size()-1) )
    //                                 LOG(INFO) << BOLDRED << " When writing register " << cConfigItem.first << " on page " << +cConfigItem.second.fPage
    //                                   << " found read-back matched fraction from other registers to be " << 100 * cMatchedPerc << " percent. Found " 
    //                                   << +cSensitiveRegisters.size() << " sensitive registers."
    //                                   << RESET;
    //                             else
    //                                 LOG(DEBUG) << BOLDGREEN << " When writing register " << cConfigItem.first << " on page " << +cConfigItem.second.fPage
    //                                   << " found read-back matched fraction from other registers to be " << 100 * cMatchedPerc << " percent. Found " 
    //                                   << +cSensitiveRegisters.size() << " sensitive registers."
    //                                   << RESET;
    //                         } // register write loop
    //                         std::sort(cSensitiveRegisters.begin(), cSensitiveRegisters.end(), customGreaterThanAddress);
    //                         for( auto cSensitiveRegister : cSensitiveRegisters ) 
    //                         {
    //                             LOG (INFO) << BOLDRED << "Sensitive register " << cSensitiveRegister.first << " on page " << +cSensitiveRegister.second.fPage << RESET;
    //                         }
    //                     }     // chip
    //                 }         // hybrid
    //             }             // OG
    //         }                 // board loop to run test
    //     }
    // } 
527
}
528
529
530
void RegisterTester::TestRegisters()
{
    // two bit patterns to rest registers with
Fabio Ravera's avatar
Fabio Ravera committed
531
    uint8_t cFirstBitPattern  = 0xAA;
532
533
    uint8_t cSecondBitPattern = 0x55;

534
    std::ofstream report;
Fabio Ravera's avatar
Fabio Ravera committed
535
    report.open(fDirectoryName + "/TestReport.txt", std::ofstream::out | std::ofstream::app);
536
537
    char line[240];

Fabio Ravera's avatar
Fabio Ravera committed
538
    for(auto cBoard: *fDetectorContainer)
539
    {
Fabio Ravera's avatar
Fabio Ravera committed
540
        for(auto cOpticalGroup: *cBoard)
541
        {
Fabio Ravera's avatar
Fabio Ravera committed
542
            for(auto cFe: *cOpticalGroup)
543
            {
544
                for(auto cChip: *cFe)
545
                {
Sarah Seif El Nasr's avatar
Sarah Seif El Nasr committed
546
                    auto cMap = cChip->getRegMap();
Mykyta Haranko's avatar
Mykyta Haranko committed
547

Fabio Ravera's avatar
Fabio Ravera committed
548
                    for(const auto& cReg: cMap)
549
                    {
550
                        if(!fReadoutChipInterface->WriteChipReg(cChip, cReg.first, cFirstBitPattern, true))
551
                        {
Fabio Ravera's avatar
Fabio Ravera committed
552
553
554
                            sprintf(line, "# Writing 0x%.2x to CBC Register %s FAILED.\n", cFirstBitPattern, (cReg.first).c_str());
                            LOG(INFO) << BOLDRED << line << RESET;
                            report << line;
555
                            fBadRegisters[cChip->getId()].insert(cReg.first);
556
557
558
559
                            fNBadRegisters++;
                        }

                        // sleep for 100 ns between register writes
Fabio Ravera's avatar
Fabio Ravera committed
560
                        std::this_thread::sleep_for(std::chrono::nanoseconds(100));
561

562
                        if(!fReadoutChipInterface->WriteChipReg(cChip, cReg.first, cSecondBitPattern, true))
563
                        {
Fabio Ravera's avatar
Fabio Ravera committed
564
565
566
                            sprintf(line, "# Writing 0x%.2x to CBC Register %s FAILED.\n", cSecondBitPattern, (cReg.first).c_str());
                            LOG(INFO) << BOLDRED << line << RESET;
                            report << line;
567
                            fBadRegisters[cChip->getId()].insert(cReg.first);
568
569
570
571
                            fNBadRegisters++;
                        }

                        // sleep for 100 ns between register writes
Fabio Ravera's avatar
Fabio Ravera committed
572
                        std::this_thread::sleep_for(std::chrono::nanoseconds(100));
573
                    }
574

575
                    fBeBoardInterface->ChipReSync(cBoard);
576
577
578
579
                }
            }
        }
    }
580

581
582
583
    report.close();
}

Fabio Ravera's avatar
Fabio Ravera committed
584
585
586
// Reload CBC registers from file found in directory.
// If no directory is given use the default files for the different operational modes found in Ph2_ACF/settings
void RegisterTester::ReconfigureRegisters(std::string pDirectoryName)
587
{
Fabio Ravera's avatar
Fabio Ravera committed
588
    for(auto cBoard: *fDetectorContainer)
589
    {
590
        fBeBoardInterface->ChipReset(cBoard);
591

Fabio Ravera's avatar
Fabio Ravera committed
592
        for(auto cOpticalGroup: *cBoard)
593
        {
Fabio Ravera's avatar
Fabio Ravera committed
594
            for(auto cFe: *cOpticalGroup)
595
            {
596
                for(auto cChip: *cFe)
597
                {
Sarah Seif El Nasr's avatar
Sarah Seif El Nasr committed
598
                    std::string pRegFile;
599

Fabio Ravera's avatar
Fabio Ravera committed
600
                    if(pDirectoryName.empty())
601
602
603
604
                        pRegFile = "settings/CbcFiles/Cbc_default_electron.txt";
                    else
                    {
                        char buffer[120];
605
                        sprintf(buffer, "%s/FE%dCBC%d.txt", pDirectoryName.c_str(), cFe->getId(), cChip->getId());
606
607
608
                        pRegFile = buffer;
                    }

609
610
611
                    cChip->loadfRegMap(pRegFile);
                    fReadoutChipInterface->ConfigureChip(cChip);
                    LOG(INFO) << GREEN << "\t\t Successfully (re)configured ROC" << int(cChip->getId()) << "'s regsiters from " << pRegFile << " ." << RESET;
612
                }
613
614
615
            }
        }

616
        fBeBoardInterface->ChipReSync(cBoard);
617
618
619
620
    }
}
void RegisterTester::PrintTestReport()
{
Fabio Ravera's avatar
Fabio Ravera committed
621
622
    std::ofstream report(fDirectoryName + "/registers_test.txt"); // Creates a file in the current directory
    PrintTestResults(report);
623
624
    report.close();
}
Fabio Ravera's avatar
Fabio Ravera committed
625
void RegisterTester::PrintTestResults(std::ostream& os)
626
{
Lorenzo Uplegger's avatar
Lorenzo Uplegger committed
627
    os << "Testing Chip Registers one-by-one with complimentary bit-patterns (0xAA, 0x55)" << std::endl;
628

Fabio Ravera's avatar
Fabio Ravera committed
629
    for(const auto& cCbc: fBadRegisters)
630
    {
Lorenzo Uplegger's avatar
Lorenzo Uplegger committed
631
        os << "Malfunctioning Registers on Chip " << cCbc.first << " : " << std::endl;
632

Fabio Ravera's avatar
Fabio Ravera committed
633
        for(const auto& cReg: cCbc.second) os << cReg << std::endl;
634
    }
635

Fabio Ravera's avatar
Fabio Ravera committed
636
    LOG(INFO) << BOLDBLUE << "Channels diagnosis report written to: " + fDirectoryName + "/registers_test.txt" << RESET;
637
638
639
640
}

bool RegisterTester::PassedTest()
{
Fabio Ravera's avatar
Fabio Ravera committed
641
    bool passFlag = ((int)(fNBadRegisters) == 0) ? true : false;
642
    return passFlag;
643
}
644

645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
//
void RegisterTester::writeObjects()
{
    this->SaveResults();
#ifdef __USE_ROOT__
    fResultFile->Flush();
#endif
}
// State machine control functions
void RegisterTester::Running() { Initialise(); }

void RegisterTester::Stop()
{
    this->SaveResults();
#ifdef __USE_ROOT__
    fResultFile->Flush();
#endif

    SaveResults();
#ifdef __USE_ROOT__
    CloseResultFile();
#endif
    Destroy();
}

void RegisterTester::Pause() {}

void RegisterTester::Resume() {}