LCOV - code coverage report
Current view: top level - flxlibs/apps - emu_confgen.cxx (source / functions) Coverage Total Hit
Test: code.result Lines: 0.0 % 146 0
Test Date: 2025-12-21 13:07:08 Functions: 0.0 % 13 0

            Line data    Source code
       1              : /**
       2              :  * @file emu_confgen.cxx Generates files tad can be loaded by flx-config
       3              :  *
       4              :  * This is part of the DUNE DAQ , copyright 2020.
       5              :  * Licensing/copyright details are in the COPYING file that you should have
       6              :  * received with this code.
       7              :  */
       8              : #include "logging/Logging.hpp"
       9              : 
      10              : #include <cstdint>
      11              : #include <cstdlib>
      12              : #include <fstream>
      13              : #include <iostream>
      14              : #include <sstream>
      15              : #include <string>
      16              : #include <vector>
      17              : 
      18              : // IDLE=K28.5, SOP=K28.1, EOP=K28.6, SOB=K28.2, EOB=K28.3
      19              : const constexpr uint64_t FM_KCHAR_IDLE = (((uint64_t)1 << 32) | 0xBC); // NOLINT
      20              : const constexpr uint64_t FM_KCHAR_SOP = (((uint64_t)1 << 32) | 0x3C);  // NOLINT
      21              : const constexpr uint64_t FM_KCHAR_EOP = (((uint64_t)1 << 32) | 0xDC);  // NOLINT
      22              : const constexpr uint64_t FM_KCHAR_SOB = (((uint64_t)1 << 32) | 0x5C);  // NOLINT
      23              : const constexpr uint64_t FM_KCHAR_EOB = (((uint64_t)1 << 32) | 0x7C);  // NOLINT
      24              : 
      25              : // CRC constants
      26              : const constexpr uint64_t CRC_WIDTH = 20;                    // NOLINT
      27              : const constexpr uint64_t CRC_MASK = ((1 << CRC_WIDTH) - 1); // NOLINT
      28              : const constexpr uint64_t CRC_POLYNOM_1 = 0xC1ACF;           // NOLINT
      29              : const constexpr uint64_t CRC_POLYNOM_2 = 0x8359F;           // NOLINT
      30              : const constexpr uint64_t CRC_INITVAL = 0xFFFFF;             // NOLINT
      31              : 
      32              : // Chunk constants
      33              : const constexpr uint64_t CHUNKHDR_SIZE = 8; // NOLINT
      34              : 
      35              : // EMU constant
      36              : const constexpr size_t EMU_SIZE = 8192; // NOLINT
      37              : 
      38              : uint64_t                                             // NOLINT
      39            0 : crc20(uint64_t* data, uint64_t length, bool crc_new) // NOLINT
      40              : {
      41              :   // Initialize
      42            0 :   uint64_t crc = CRC_INITVAL; // NOLINT
      43            0 :   uint64_t polynomial;        // NOLINT
      44            0 :   if (crc_new) {
      45              :     polynomial = CRC_POLYNOM_2;
      46              :   } else {
      47            0 :     polynomial = CRC_POLYNOM_1;
      48              :   }
      49              : 
      50            0 :   unsigned int i, k; // NOLINT
      51            0 :   for (k = 0; k < CRC_WIDTH; ++k) {
      52            0 :     if ((crc & 1)) {
      53            0 :       crc = (crc >> 1) ^ ((1 << (CRC_WIDTH - 1)) | (polynomial >> 1));
      54              :     } else {
      55            0 :       crc = (crc >> 1);
      56              :     }
      57              :   }
      58              : 
      59              :   // Calculate CRC
      60            0 :   for (i = 0; i < length; i++) {
      61            0 :     for (k = 1; k <= 32; k++) {
      62            0 :       if (crc & (1 << (CRC_WIDTH - 1))) {
      63            0 :         crc = ((crc << 1) | ((data[i] >> (32 - k)) & 1)) ^ polynomial;
      64              :       } else {
      65            0 :         crc = ((crc << 1) | ((data[i] >> (32 - k)) & 1));
      66              :       }
      67              :     }
      68            0 :     crc &= CRC_MASK;
      69              :   }
      70              : 
      71              :   // One more loop
      72            0 :   for (k = 0; k < CRC_WIDTH; k++) {
      73            0 :     if (crc & (1 << (CRC_WIDTH - 1))) {
      74            0 :       crc = (crc << 1) ^ polynomial;
      75              :     } else {
      76            0 :       crc = (crc << 1);
      77              :     }
      78              :   }
      79            0 :   crc &= CRC_MASK;
      80              : 
      81            0 :   return crc;
      82              : }
      83              : 
      84              : bool
      85            0 : generateFm(uint64_t* emudata,      // NOLINT
      86              :            uint64_t emusize,       // NOLINT
      87              :            uint32_t req_chunksize, // NOLINT
      88              :            uint32_t pattern_id,    // NOLINT
      89              :            uint32_t idle_chars,    // NOLINT
      90              :            bool random_sz,
      91              :            bool crc_new,
      92              :            bool use_streamid,
      93              :            bool add_busy,
      94              :            bool omit_one_soc,
      95              :            bool omit_one_eoc,
      96              :            bool add_crc_err)
      97              : {
      98              :   // Initialize emudata to all zeroes
      99            0 :   unsigned i; // NOLINT
     100            0 :   for (i = 0; i < emusize; ++i) {
     101            0 :     emudata[i] = 0;
     102              :   }
     103              : 
     104              :   // Determine the number of chunks that will fit
     105              :   // (chunk size includes 8-byte header): 2 IDLEs, SOP, chunk, EOP
     106            0 :   uint32_t max_chunkcnt = (emusize - 2) / (1 + req_chunksize / 4 + 1 + idle_chars); // NOLINT
     107            0 :   uint32_t index = 0;                                                               // NOLINT
     108            0 :   bool success = true;
     109              :   // g_chunk_count = max_chunkcnt;
     110              : 
     111              :   // Start with some IDLE symbols
     112            0 :   emudata[index++] = FM_KCHAR_IDLE; // NOLINT(runtime/increment_decrement)
     113            0 :   emudata[index++] = FM_KCHAR_IDLE; // NOLINT(runtime/increment_decrement)
     114              : 
     115              :   // Multiple chunks
     116            0 :   uint32_t next_index, chunkcntr = 0, chunksz, chunk_datasz; // NOLINT
     117            0 :   while (index < emusize && chunkcntr < max_chunkcnt) {
     118            0 :     if (random_sz && req_chunksize > 8) { // Size not less than 8
     119              :       // Determine a random (data) size to use for the next chunk
     120              :       // (here: size between req_chunksize/2 and req_chunksize,
     121              :       //  but rounded up to a multiple of 4 bytes)
     122            0 :       uint32_t sz = (req_chunksize + 1) / 2;             // NOLINT
     123            0 :       double r = static_cast<double>(rand()) / RAND_MAX; // NOLINT
     124            0 :       double d = 0.5 * static_cast<double>(1 - (req_chunksize & 1));
     125            0 :       chunksz = ((sz + static_cast<uint32_t>(static_cast<double>(sz) * r + d) + 3) / 4) * 4; // NOLINT
     126              : 
     127              :     } else {
     128              :       chunksz = req_chunksize;
     129              :     }
     130              : 
     131              :     // Check if the next chunk will fit
     132              :     // (chunksz includes header)
     133            0 :     next_index = index + (1 + chunksz / 4 + 1);
     134            0 :     if (next_index >= emusize) {
     135              :       // It won't fit, so forget it: from here onwards fill with IDLEs
     136            0 :       for (; index < emusize; ++index) {
     137            0 :         emudata[index] = FM_KCHAR_IDLE;
     138              :       }
     139              :       // Should exit the while-loop on the basis of the chunk counter
     140              :       // so we consider this an error...
     141            0 :       success = false;
     142            0 :       continue; // Jump to start of while-loop
     143              :     }
     144              : 
     145              :     // SOP
     146            0 :     emudata[index++] = FM_KCHAR_SOP; // NOLINT
     147            0 :     if (omit_one_soc && chunkcntr == 2) {
     148            0 :       --index; // For testing
     149              :     }
     150              : 
     151              :     // Add chunk header
     152            0 :     chunk_datasz = chunksz - CHUNKHDR_SIZE;
     153            0 :     if (use_streamid) {
     154            0 :       emudata[index++] = ((chunkcntr & 0xFF) | // Chunk counter = StreamID // NOLINT
     155            0 :                           (chunk_datasz & 0xF00) | ((chunk_datasz & 0x0FF) << 16) | ((chunkcntr & 0xFF) << 24));
     156              :     } else {
     157            0 :       emudata[index++] = // NOLINT
     158            0 :         (0xAA | (chunk_datasz & 0xF00) | ((chunk_datasz & 0x0FF) << 16) | ((chunkcntr & 0xFF) << 24));
     159              :     }
     160              : 
     161            0 :     emudata[index++] = 0x10AABB00; // ewidth=0x10=16 bits // NOLINT
     162              : 
     163              :     // Add chunk data according to 'pattern_id'
     164            0 :     if (pattern_id == 1) {
     165            0 :       for (i = 0; i < chunk_datasz / 4; ++i) {
     166            0 :         emudata[index++] = 0xAA55AA55; // NOLINT
     167              :       }
     168            0 :     } else if (pattern_id == 2) {
     169            0 :       for (i = 0; i < chunk_datasz / 4; ++i) {
     170            0 :         emudata[index++] = 0xFFFFFFFF; // NOLINT
     171              :       }
     172            0 :     } else if (pattern_id == 3) {
     173            0 :       for (i = 0; i < chunk_datasz / 4; ++i) {
     174            0 :         emudata[index++] = 0x00000000; // NOLINT
     175              :       }
     176              :     } else {
     177              :       unsigned int cntr = 0; // NOLINT
     178            0 :       for (i = 0; i < chunk_datasz / 4; ++i, cntr += 4) {
     179            0 :         emudata[index++] = // NOLINT
     180            0 :           ((((cntr + 3) & 0xFF) << 24) | (((cntr + 2) & 0xFF) << 16) | (((cntr + 1) & 0xFF) << 8) |
     181            0 :            (((cntr + 0) & 0xFF) << 0));
     182              :       }
     183              :     }
     184              : 
     185              :     // EOP (+ 20-bits CRC)
     186            0 :     uint64_t crc = crc20(&emudata[index - chunksz / 4], chunksz / 4, crc_new); // NOLINT
     187              : 
     188            0 :     if (add_crc_err && chunkcntr == 3) {
     189            0 :       ++crc; // For testing
     190              :     }
     191              : 
     192            0 :     emudata[index++] = FM_KCHAR_EOP | (crc << 8); // NOLINT
     193              : 
     194            0 :     if (omit_one_eoc && chunkcntr == 2) {
     195            0 :       --index; // For testing
     196              :     }
     197              : 
     198            0 :     if (add_busy && chunkcntr == 0) {
     199            0 :       emudata[index++] = FM_KCHAR_SOB; // NOLINT
     200              :     }
     201              : 
     202              :     // A configurable number of comma symbols in between chunks
     203            0 :     for (i = 0; i < idle_chars; ++i) {
     204            0 :       emudata[index++] = FM_KCHAR_IDLE; // NOLINT
     205              :     }
     206              : 
     207            0 :     if (add_busy && chunkcntr == 0) {
     208            0 :       emudata[index++] = FM_KCHAR_EOB; // NOLINT
     209              :     }
     210              : 
     211            0 :     ++chunkcntr;
     212              :   }
     213              : 
     214              :   // Fill any remaining uninitialised array locations with IDLE symbols
     215            0 :   for (; index < emusize; ++index) {
     216            0 :     emudata[index] = FM_KCHAR_IDLE;
     217              :   }
     218              : 
     219              :   // We expect to have generated max_chunkcnt chunks!
     220            0 :   if (chunkcntr < max_chunkcnt) {
     221            0 :     success = false;
     222              :   }
     223              : 
     224            0 :   return success;
     225              : } // NOLINT(readability/fn_size)
     226              : 
     227              : int
     228            0 : main(int argc, char* argv[])
     229              : {
     230              : 
     231              :   // "-h", "--help", "--filename", "--emuSize", "--chunkSize", "--idles", "--pattern"
     232              : 
     233            0 :   const std::vector<std::string> cmdArgs = { argv,
     234            0 :                                              argv + argc }; // store arguments, options and flags from the command line
     235              : 
     236              :   // set default values
     237            0 :   uint32_t emusize = 8192;      // NOLINT
     238            0 :   uint32_t req_chunksize = 464; // NOLINT
     239            0 :   uint32_t pattern_id = 0;      // NOLINT
     240            0 :   uint32_t idle_chars = 1;      // NOLINT
     241            0 :   bool random_sz = false;
     242            0 :   bool crc_new = true;
     243            0 :   bool use_streamid = false;
     244            0 :   bool add_busy = false;
     245            0 :   bool omit_one_soc = false;
     246            0 :   bool omit_one_eoc = false;
     247            0 :   bool add_crc_err = false;
     248            0 :   std::string filename = "emuconfigreg";
     249              : 
     250              :   // parse command line information
     251            0 :   for (unsigned j = 0; j < cmdArgs.size(); j++) { // NOLINT
     252            0 :     std::string arg = cmdArgs[j];
     253            0 :     if (arg == "-h" || arg == "--help") {
     254            0 :       std::ostringstream oss;
     255            0 :       oss
     256              :         << "\nThis app is used to create basic emulator configurations for the FELIX to use with flx-config. Usage: \n"
     257              :         << " -h/--help   : display help messege \n"
     258              :         << " --filename  : output configuration filename \n"
     259              :         //<< " --emuSize   : total number of lines of data \n"
     260              :         << " --chunkSize : chunk sie of each block of data \n"
     261              :         << " --idles     : number of idle charachters between chunks \n"
     262              :         << " --pattern   : type of data to write \n"
     263              :         << "               0 is incrimental \n"
     264              :         << "               1 sets all to 0xAA55AA55 \n"
     265              :         << "               2 sets all to 0xFFFFFFFF \n"
     266            0 :         << "               3 sets all to 0x00000000";
     267            0 :       TLOG() << oss.str();
     268            0 :       exit(0);
     269            0 :     } else if (arg == "--filename") {
     270              :       // get input file name, then print it
     271            0 :       if (j >= cmdArgs.size() - 1) // check if the arguement is at the end of the line without an input
     272              :       {
     273            0 :         TLOG() << "No file name was specified";
     274            0 :         break;
     275              :       }
     276            0 :       filename = cmdArgs[j + 1];
     277              : 
     278              :       //} else if (arg == "--emuSize") {
     279              :       //  if (j >= cmdArgs.size() - 1) {
     280              :       //    TLOG() << "No value was specified \n";
     281              :       //    break;
     282              :       //  }
     283              :       //  emusize = std::stoi(cmdArgs[j + 1]);
     284              : 
     285            0 :     } else if (arg == "--chunkSize") {
     286            0 :       if (j >= cmdArgs.size() - 1) {
     287            0 :         TLOG() << "No value was specified";
     288            0 :         break;
     289              :       }
     290            0 :       req_chunksize = std::stoi(cmdArgs[j + 1]);
     291              : 
     292            0 :     } else if (arg == "--idles") {
     293            0 :       if (j >= cmdArgs.size() - 1) {
     294            0 :         TLOG() << "No value was specified";
     295            0 :         break;
     296              :       }
     297            0 :       idle_chars = std::stoi(cmdArgs[j + 1]);
     298              : 
     299            0 :     } else if (arg == "--pattern") {
     300            0 :       if (j >= cmdArgs.size() - 1) {
     301            0 :         TLOG() << "No value was specified";
     302            0 :         break;
     303              :       }
     304            0 :       pattern_id = std::stoi(cmdArgs[j + 1]);
     305              :     }
     306            0 :   }
     307              :   // TLOG() << "number of lines : " << emusize;
     308            0 :   TLOG() << "chunk size      : " << req_chunksize;
     309            0 :   TLOG() << "idle characters : " << idle_chars;
     310            0 :   TLOG() << "pattern type    : " << pattern_id;
     311              : 
     312            0 :   filename += "_" + std::to_string(req_chunksize) + "_" + std::to_string(idle_chars) + "_" + std::to_string(pattern_id);
     313            0 :   TLOG() << "output file     : " << filename;
     314              : 
     315            0 :   uint64_t emudata[EMU_SIZE]; // NOLINT
     316            0 :   std::ofstream output;
     317            0 :   output.open(filename);
     318              : 
     319            0 :   generateFm(emudata,
     320              :              emusize,
     321              :              req_chunksize,
     322              :              pattern_id,
     323              :              idle_chars,
     324              :              random_sz,
     325              :              crc_new,
     326              :              use_streamid,
     327              :              add_busy,
     328              :              omit_one_soc,
     329              :              omit_one_eoc,
     330              :              add_crc_err);
     331              : 
     332            0 :   for (unsigned i = 0; i < emusize; i++) { // NOLINT
     333            0 :     output << "FE_EMU_CONFIG_WRADDR=0x" << std::hex << i << std::endl;
     334            0 :     output << "FE_EMU_CONFIG_WRDATA=0x" << std::hex << emudata[i] << std::endl;
     335            0 :     output << "FE_EMU_CONFIG_WE=1" << std::endl;
     336            0 :     output << "FE_EMU_CONFIG_WE=0" << std::endl;
     337              :   }
     338              : 
     339            0 :   output.close();
     340              : 
     341            0 :   TLOG() << "Config file written.";
     342              : 
     343            0 : } // NOLINT(readability/fn_size)
        

Generated by: LCOV version 2.0-1