RegisterTester.cc 35.8 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
51
    // first just test page toggle 
    for(size_t cAttempt = 0; cAttempt < cAttempts; cAttempt++)
52
    {
53

54
        LOG(INFO) << BOLDMAGENTA << "Test" << +cTestFlavor << " attempt#" << +cAttempt << " I2C registers .... just going to toggle the page without writing..." << RESET;
55
        uint8_t cSortOrder=0;       
56
57
        uint8_t cFirstPage=(cSortOrder==0)? 0 : 1; 
        std::vector<uint8_t> cPages{cFirstPage, static_cast<uint8_t>(~cFirstPage&0x01),cFirstPage};
58

59
        
60
61
62
63
64
        // 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)
65
        {
66
            for(auto cOpticalGroup: *cBoard)
67
            {
68
                for(auto cHybrid: *cOpticalGroup)
69
                {
70
                    for(auto cChip: *cHybrid)
71
                    {
72
73
74
75
76
77
78
79
80
81
                        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)); 
82
                        }
83
84
85
                        // 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
86
87
                    }
                }
88
89
            }
        } // board loop to save record of registers
90

91
92
93
94
95
        // so here .. I need to send a hard reset to the ROCs
        for(auto cBoard: *fDetectorContainer)
        {
            auto cWithLpGBT = fReadoutChipInterface->lpGBTCheck(cBoard);
            if(!cWithLpGBT)
Sarah Seif El Nasr's avatar
Sarah Seif El Nasr committed
96
            {
97
98
99
100
101
102
103
                fBeBoardInterface->ChipReset(cBoard);
                continue;
            }
            for(auto cOpticalGroup: *cBoard)
            {
                auto& clpGBT = cOpticalGroup->flpGBT;
                for(auto cHybrid: *cOpticalGroup)
104
                {
105
106
107
108
109
110
111
112
113
114
                    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);
115
                }
116
117
118
119
120
121
122
123
124
            }
        } // board loop to send hard reset

        // reset page map 
        for(auto cBoard: *fDetectorContainer)
        {
            for(auto cOpticalGroup: *cBoard)
            {
                for(auto cHybrid: *cOpticalGroup)
125
                {
126
                    for(auto cChip: *cHybrid)
127
                    {
128
129
130
131
132
133
                        if( cChip->getFrontEndType() != FrontEndType::CBC3 ) continue;
                        static_cast<CbcInterface*>(fReadoutChipInterface)->resetPageMap(); 
                    } // chip
                } // hybrid
            } // OG
        } 
134

135
136
137
138
139
140
        // 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)
141
            {
142
                for(auto cHybrid: *cOpticalGroup)
143
                {
144
                    for(auto cChip: *cHybrid)
145
                    {
146
147
148
149
150
                        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)
151
                        {
152
153
154
155
156
                            if( std::find( cRegsToSkip.begin(), cRegsToSkip.end(), cListItem.first ) != cRegsToSkip.end() ) continue; 
                            
                            auto cRegItem   = cListItem.second;
                            cRegItem.fValue = fReadoutChipInterface->ReadChipReg(cChip, cListItem.first);
                            cList.push_back(std::make_pair(cListItem.first, cRegItem));
157
                            LOG (DEBUG) << BOLDMAGENTA << "Default value after a hard reset of register " << cListItem.first << " is 0x"
158
159
160
161
162
163
164
165
                                << 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
166

167
168
169
170
171
        
        // now .. try and change page after config and look for mis-matches
        for(auto cBoard: *fDetectorContainer)
        {
            for(auto cOpticalGroup: *cBoard)
172
            {
173
                for(auto cHybrid: *cOpticalGroup)
174
                {
175
                    for(auto cChip: *cHybrid)
176
                    {
177
                        LOG (INFO) << BOLDMAGENTA << "Chip#" << +cChip->getId() << " on hybrid" << +cHybrid->getId() << RESET;
178
179
180
181
182
                        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);
183
                        
184
                        for(auto cPage : cPages )
185
                        {
186
                            LOG (INFO) << BOLDMAGENTA << "Going to select page " << +cPage
187
                                << " - previous page was " << +cPreviousPage << RESET;
188
189
190
191
192

                            static_cast<CbcInterface*>(fReadoutChipInterface)->ConfigurePage( cChip, cPage );
                            // check for mismatches
                            size_t cMatches = 0;
                            for(auto& cItem: cExpectedLst) // loop over what I think the current values are
193
                            {
194
                                // compare the value read back from the chip against what is expected
195
                                LOG (DEBUG) << BOLDMAGENTA << "\t... Reading back value from register " << cItem.first << " on page " << +cItem.second.fPage << " with value 0x" 
196
197
198
                                    << 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
199

200
201
202
203
204
205
206
207
208
                                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 );
                                    }
209
                                    LOG (INFO) << BOLDRED << "\t\t\t..When switching from page " << +cPreviousPage
210
211
212
213
214
215
216
217
218
                                            << " 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
                                {
219
                                    LOG (DEBUG) << BOLDGREEN << "\t\t...Match in I2C register " << cItem.first
220
221
222
223
224
                                        << " 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++;
                                }
225

226
                            } // loop over current values and compare what I read back against what I have stored in memory
227
                            float cMatchedPerc = cMatches / (float)(cExpectedLst.size() );
228
                            if( cMatches == cExpectedLst.size() )
229
230
231
232
233
234
                                LOG(INFO) << BOLDGREEN << "Found read-back matched fraction from other registers to be " << 100 * cMatchedPerc << " percent. Found " 
                                  << +cSensitiveRegisters.size() << " sensitive registers." <<  RESET;
                            else
                                LOG(INFO) << BOLDRED << "Found read-back matched fraction from other registers to be " << 100 * cMatchedPerc << " percent. Found " 
                                  << +cSensitiveRegisters.size() << " sensitive registers." <<  RESET;
                            
235
236
237
238
                            cPreviousPage = cPage;
                        } // register write loop
                        std::sort(cSensitiveRegisters.begin(), cSensitiveRegisters.end(), customGreaterThanAddress);
                        for( auto cSensitiveRegister : cSensitiveRegisters ) 
239
                        {
240
241
242
243
244
245
246
247
                            LOG (INFO) << BOLDRED << "Sensitive register " << cSensitiveRegister.first << " on page " << +cSensitiveRegister.second.fPage << RESET;
                        }
                    }     // chip
                }         // hybrid
            }             // OG
        }                 // board loop to run test
        
    }
248
    cTestFlavor++;
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
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

    // // 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; 
353
                                
354
355
356
357
358
359
360
361
362
363
364
365
366
367
    //                             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;
368

369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
    //         // 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++;
    //                         }
394
                            
395
396
397
398
399
400
401
    //                         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();
402
                            
403
404
405
406
407
408
409
410
411
412
413
414
    //                         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;
415

416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
    //                             // 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;
    //                                 }
431

432
433
434
435
436
    //                                 // 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;
437

438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
    //                                 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++;
    //                                 }
466

467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
    //                             } // 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
    //     }
    // } 
492
}
493
494
495
void RegisterTester::TestRegisters()
{
    // two bit patterns to rest registers with
Fabio Ravera's avatar
Fabio Ravera committed
496
    uint8_t cFirstBitPattern  = 0xAA;
497
498
    uint8_t cSecondBitPattern = 0x55;

499
    std::ofstream report;
Fabio Ravera's avatar
Fabio Ravera committed
500
    report.open(fDirectoryName + "/TestReport.txt", std::ofstream::out | std::ofstream::app);
501
502
    char line[240];

Fabio Ravera's avatar
Fabio Ravera committed
503
    for(auto cBoard: *fDetectorContainer)
504
    {
Fabio Ravera's avatar
Fabio Ravera committed
505
        for(auto cOpticalGroup: *cBoard)
506
        {
Fabio Ravera's avatar
Fabio Ravera committed
507
            for(auto cFe: *cOpticalGroup)
508
            {
509
                for(auto cChip: *cFe)
510
                {
Sarah Seif El Nasr's avatar
Sarah Seif El Nasr committed
511
                    auto cMap = cChip->getRegMap();
Mykyta Haranko's avatar
Mykyta Haranko committed
512

Fabio Ravera's avatar
Fabio Ravera committed
513
                    for(const auto& cReg: cMap)
514
                    {
515
                        if(!fReadoutChipInterface->WriteChipReg(cChip, cReg.first, cFirstBitPattern, true))
516
                        {
Fabio Ravera's avatar
Fabio Ravera committed
517
518
519
                            sprintf(line, "# Writing 0x%.2x to CBC Register %s FAILED.\n", cFirstBitPattern, (cReg.first).c_str());
                            LOG(INFO) << BOLDRED << line << RESET;
                            report << line;
520
                            fBadRegisters[cChip->getId()].insert(cReg.first);
521
522
523
524
                            fNBadRegisters++;
                        }

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

527
                        if(!fReadoutChipInterface->WriteChipReg(cChip, cReg.first, cSecondBitPattern, true))
528
                        {
Fabio Ravera's avatar
Fabio Ravera committed
529
530
531
                            sprintf(line, "# Writing 0x%.2x to CBC Register %s FAILED.\n", cSecondBitPattern, (cReg.first).c_str());
                            LOG(INFO) << BOLDRED << line << RESET;
                            report << line;
532
                            fBadRegisters[cChip->getId()].insert(cReg.first);
533
534
535
536
                            fNBadRegisters++;
                        }

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

540
                    fBeBoardInterface->ChipReSync(cBoard);
541
542
543
544
                }
            }
        }
    }
545

546
547
548
    report.close();
}

Fabio Ravera's avatar
Fabio Ravera committed
549
550
551
// 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)
552
{
Fabio Ravera's avatar
Fabio Ravera committed
553
    for(auto cBoard: *fDetectorContainer)
554
    {
555
        fBeBoardInterface->ChipReset(cBoard);
556

Fabio Ravera's avatar
Fabio Ravera committed
557
        for(auto cOpticalGroup: *cBoard)
558
        {
Fabio Ravera's avatar
Fabio Ravera committed
559
            for(auto cFe: *cOpticalGroup)
560
            {
561
                for(auto cChip: *cFe)
562
                {
Sarah Seif El Nasr's avatar
Sarah Seif El Nasr committed
563
                    std::string pRegFile;
564

Fabio Ravera's avatar
Fabio Ravera committed
565
                    if(pDirectoryName.empty())
566
567
568
569
                        pRegFile = "settings/CbcFiles/Cbc_default_electron.txt";
                    else
                    {
                        char buffer[120];
570
                        sprintf(buffer, "%s/FE%dCBC%d.txt", pDirectoryName.c_str(), cFe->getId(), cChip->getId());
571
572
573
                        pRegFile = buffer;
                    }

574
575
576
                    cChip->loadfRegMap(pRegFile);
                    fReadoutChipInterface->ConfigureChip(cChip);
                    LOG(INFO) << GREEN << "\t\t Successfully (re)configured ROC" << int(cChip->getId()) << "'s regsiters from " << pRegFile << " ." << RESET;
577
                }
578
579
580
            }
        }

581
        fBeBoardInterface->ChipReSync(cBoard);
582
583
584
585
    }
}
void RegisterTester::PrintTestReport()
{
Fabio Ravera's avatar
Fabio Ravera committed
586
587
    std::ofstream report(fDirectoryName + "/registers_test.txt"); // Creates a file in the current directory
    PrintTestResults(report);
588
589
    report.close();
}
Fabio Ravera's avatar
Fabio Ravera committed
590
void RegisterTester::PrintTestResults(std::ostream& os)
591
{
Lorenzo Uplegger's avatar
Lorenzo Uplegger committed
592
    os << "Testing Chip Registers one-by-one with complimentary bit-patterns (0xAA, 0x55)" << std::endl;
593

Fabio Ravera's avatar
Fabio Ravera committed
594
    for(const auto& cCbc: fBadRegisters)
595
    {
Lorenzo Uplegger's avatar
Lorenzo Uplegger committed
596
        os << "Malfunctioning Registers on Chip " << cCbc.first << " : " << std::endl;
597

Fabio Ravera's avatar
Fabio Ravera committed
598
        for(const auto& cReg: cCbc.second) os << cReg << std::endl;
599
    }
600

Fabio Ravera's avatar
Fabio Ravera committed
601
    LOG(INFO) << BOLDBLUE << "Channels diagnosis report written to: " + fDirectoryName + "/registers_test.txt" << RESET;
602
603
604
605
}

bool RegisterTester::PassedTest()
{
Fabio Ravera's avatar
Fabio Ravera committed
606
    bool passFlag = ((int)(fNBadRegisters) == 0) ? true : false;
607
    return passFlag;
608
}
609

610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
//
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() {}