/* * TPCpedConfig.c * Run on LDC and write pedestal data into ALTRO pedestal memories * Author: C. Lippmann: Christian.Lippmann@cern.ch */ #include #include #include #include #include #include #include #include #include #include #define LOG_TPCPEDCONFIG "TPC_PEDCFG" FILE* mainlogfile; //FILE** rorclogfile; #include "TPCpedConfig.h" int32_t ii; rcu_model_t **rcu; //======================================================================== int32_t switchFecs(rcu_model_t* rcu) { // // Switch the FECs // log_rorc(rcu, LOG_DEBUG, "Entering function switchFecs()"); uint32_t data; // 1) Switch cards if ( !arguments.active_fecs ) { // switch FECs log_rorc(rcu, LOG_INFO, "Writing new ACTFECLIST"); if ( Write_ACTFECLIST(rcu, arguments.fecs) ) { log_rorc(rcu, LOG_ERROR, "Function switchFecs(): Write_ACTFECLIST() failed!"); return 1; } } // Read ACTFECLIST if ( Read_ACTFECLIST(rcu, &data) ) { log_rorc(rcu, LOG_ERROR, "Function switchFecs(): Read_ACTFECLIST failed!"); return 1; } if (data == 0) { log_rorc(rcu, LOG_INFO, "Warning: All FECs are off!"); if ( arguments.fecs ) return 1; } char desc[256]; sprintf(desc, "Content of Register ACTFECLIST: %x", (int)data); log_rorc(rcu, LOG_DEBUG, desc); sleep(1); log_rorc(rcu, LOG_DEBUG, "Exiting function switchFecs()"); return 0; } //======================================================================== int32_t clearall(rcu_model_t* rcu) { // // Clear RCU error and status registers. Check for ALTRO errors // log_rorc(rcu, LOG_DEBUG, "Entering function clearall(). Clear RCU error and status registers"); uint32_t data; int32_t retval; char desc[256]; // 1) Reset ALL log_rorc(rcu, LOG_DEBUG, "Reset ALL"); retval = rcu_resetALL(rcu->key); if ( retval ) { log_rorc(rcu, LOG_ERROR, "Reset ALL failed!"); return retval; } // 2) Clear RCU ERROR and Status registers retval = rcu_clearCLERRREG(rcu->key); if ( retval ) { log_rorc(rcu, LOG_ERROR, "RCU_clearCLERRREG failed!"); return retval; } // 3) Read FECERR_A ii = 0; do { retval = rcu_readReg(rcu->key, FECERRA, &data); if ( retval != 1 ) { log_rorc(rcu, LOG_ERROR, "rcu_readReg() failed (FECERRA)!"); return 1; } data = data&0xFFFFFFFF; sprintf(desc, "Function clearall(): Content of Register FECERRA: 0x%x", (int)data); log_rorc(rcu, LOG_DEBUG, desc); if (data&0x1) { if (ii<3) { log_rorc(rcu, LOG_ERROR, "ALTRO ERROR asserted on Branch A!"); log_rorc(rcu, LOG_INFO, "Resetting ALL"); sleep(1); if ( rcu_resetALL(rcu->key) ) { log_rorc(rcu, LOG_ERROR, "Reset ALL failed!"); return 1; } log_rorc(rcu, LOG_INFO, "Clearing RCU ERROR and Status registers"); if ( rcu_clearCLERRREG(rcu->key) ) { log_rorc(rcu, LOG_ERROR, "RCU_clearCLERRREG failed!"); return retval; } } else { log_rorc(rcu, LOG_ERROR, "ALTRO ERROR on Branch A can not be recovered!!"); return 1; } ii++; } else break; } while (ii<3); // 4) Read FECERR_B ii = 0; do { retval = rcu_readReg(rcu->key, FECERRB, &data); if ( retval != 1 ) { log_rorc(rcu, LOG_ERROR, "rcu_readReg() failed (FECERRB)!"); return 1; } data = data&0xFFFFFFFF; sprintf(desc, "Function clearall(): Content of Register FECERRB: 0x%x", (int)data); log_rorc(rcu, LOG_DEBUG, desc); if (data&0x1) { if (ii<3) { log_rorc(rcu, LOG_ERROR, "ALTRO ERROR asserted on Branch B.!"); log_rorc(rcu, LOG_INFO, "Resetting FECs"); sleep(1); if ( rcu_resetALL(rcu->key) ) { log_rorc(rcu, LOG_ERROR, "Reset ALL failed!"); return 1; } log_rorc(rcu, LOG_INFO, "Clearing RCU ERROR and Status registers!"); if ( rcu_clearCLERRREG(rcu->key) ) { log_rorc(rcu, LOG_ERROR, "RCU_clearCLERRREG failed!"); return retval; } } else { log_rorc(rcu, LOG_ERROR, "ALTRO ERROR on Branch B can not be recovered!!"); return 1; } ii++; } else break; } while (ii<3); log_rorc(rcu, LOG_DEBUG, "Exiting function clearall()"); return 0; } //======================================================================== int32_t config4pedmemRdo(rcu_model_t* rcu) { // // Write data in ALTRO and RCU registers to get ready for read out // The configuration is such to readout the data from the pedestal memory (f(t) -fpd) // int32_t timebins = 1000; int32_t retval; uint32_t data; char desc[256]; log_rorc(rcu, LOG_DEBUG, "Entering function config4pedmemRdo()"); log_rorc(rcu, LOG_INFO, "Configure RCU/ALTRO registers"); // 1) Clear all if ( clearall(rcu) ) { log_rorc(rcu, LOG_ERROR, "resetall() failed!"); return 1; } // 2) write ALTROIF if ( rcu_writeReg(rcu->key, ALTROIF, ((0x3<<14) | (0x1<<10) | timebins)) ) { log_rorc(rcu, LOG_ERROR, "rcu_writeReg failed (ALTROIF)!"); return 1; } // 3) write TRGCONF if ( rcu_writeReg(rcu->key, TRGCONF, ((0x4<<14) | (0<<13) | 0x1FFF)) ) { log_rorc(rcu, LOG_ERROR, "rcu_writeReg failed (TRGCONF)!"); return 1; } // 4) write RDOMOD (sparse rdo) if ( rcu_writeReg(rcu->key, RDOMOD, ((0x0<<5) | (0x0<<4) | (0x0<<3) | (0x0<<2) | (0x0<<1) | 0x0)) ) { log_rorc(rcu, LOG_ERROR, "rcu_writeReg failed (RDOMOD)!"); return 1; } // 5) write TTC_L1_LATENCY if ( rcu_writeReg(rcu->key, L1_LATENCY, ((2<<12) | 0x104)) ) { log_rorc(rcu, LOG_ERROR, "rcu_writeReg failed (TTC_L1_LATENCY)!"); return 1; } // 6) write TTC_L1_MSG_LATENCY if ( rcu_writeReg(rcu->key, L1_MSG_LATENCY, ((0xe04<<12) | 0xe20)) ) { log_rorc(rcu, LOG_ERROR, "rcu_writeReg failed (TTC_L1_LATENCY)!"); return 1; } // 7) Write TRCFG to all ALTROs in broadcast if ( FEC_ALTROREG_Write(rcu, 0, 1, 0xA, timebins) ) { log_rorc(rcu, LOG_ERROR, "FEC_ALTROREG_Write into ALTRO registers TRGCFG (broadcast) failed!"); return 1; } // 8) Write DPCFG to all ALTROs in broadcast [ zero suppression and test pattern mode: f(t)-fpd ] if ( FEC_ALTROREG_Write(rcu, 0, 1, 0xB, (1<<19) | 0xA) ) { log_rorc(rcu, LOG_ERROR, "FEC_ALTROREG_Write into ALTRO registers DPCFG (broadcast) failed!"); return 1; } // 9) Write ZSTHR to all ALTROs in broadcast if ( FEC_ALTROREG_Write(rcu, 0, 1, 0x8, 0x3) ) { log_rorc(rcu, LOG_ERROR, "FEC_ALTROREG_Write into ALTRO registers ZSTHR (broadcast) failed!"); return 1; } // 10) Read FECERR_A retval = rcu_readReg(rcu->key, FECERRA, &data); if ( retval != 1 ) { log_rorc(rcu, LOG_ERROR, "rcu_readReg() failed (FECERRA)!"); return 1; } data = data&0xFFFFFFFF; sprintf(desc, "Content of Register FECERRA: 0x%x", (int)data); log_rorc(rcu, LOG_DEBUG, desc); if (data&0x1) { log_rorc(rcu, LOG_ERROR, "ALTRO ERROR asserted on Branch A!"); return 1; } // 11) Read FECERR_B retval = rcu_readReg(rcu->key, FECERRB, &data); if ( retval != 1 ) { log_rorc(rcu, LOG_ERROR, "rcu_readReg() failed (FECERRB)!"); return 1; } data = data&0xFFFFFFFF; sprintf(desc, "Content of Register FECERRB: 0x%x", (int)data); if (data&0x1) { log_rorc(rcu, LOG_ERROR, "ALTRO ERROR asserted on Branch B!"); return 1; } log_rorc(rcu, LOG_DEBUG, "Exiting function config4pedmemRdo()"); return 0; } //======================================================================== int32_t writeDummyBroadcast(rcu_model_t* rcu) { // // Write ramp data to all pedestal memories for testing // log_rorc(rcu, LOG_DEBUG, "Entering function writeDummyBroadcast()"); int32_t retval = 0; uint32_t imem[RCU_INSTRUCTION_MEM_SZ]; char desc[256]; // Dummy Pedestal Data for ( ii = 0; ii < RCU_INSTRUCTION_MEM_SZ; ii+=4 ) { imem[ii+0] = (2<<20) | (1<<18) | 0xD; // PMADD broadcast imem[ii+1] = ii/4; // time bin 0 ... 1023 imem[ii+2] = (2<<20) | (1<<18) | 0x7; // PMDTA broadcast imem[ii+3] = ii/4; // dummy value (ramp) } //imem[4096] = PEDCONF_RCU_END; // no space for PEDCONF_RCU_END; Will be executed anyway. /* Write to rcu */ retval = FEC_IMEM_Write(rcu, imem, RCU_INSTRUCTION_MEM_SZ); log_rorc(rcu, LOG_DEBUG, "Exiting function writeDummyBroadcast()"); return retval; } //======================================================================== int32_t writeTestPatternBroadcast(rcu_model_t* rcu) { // // Write test pattern into RCU Pedestal Memory. // log_rorc(rcu, LOG_DEBUG, "Entering function writeTestPatternBroadcast()"); char desc[256]; int32_t retval = 0; uint32_t pedestal_data[1024]; for ( ii = 0; ii < 1024; ii++ ) pedestal_data[ii] = 0; uint32_t imem[RCU_INSTRUCTION_MEM_SZ]; for ( ii = 0; ii < RCU_INSTRUCTION_MEM_SZ; ii++ ) imem[ii] = 0; // Dummy Pedestal Data filltestarray(pedestal_data, arguments.occupancy, 0); for ( ii = 0; ii < RCU_INSTRUCTION_MEM_SZ; ii+=4 ) { imem[ii+0] = (2<<20) | (1<<18) | 0xD; // PMADD broadcast imem[ii+1] = ii/4; // time bin 0 ... 1023 imem[ii+2] = (2<<20) | (1<<18) | 0x7; // PMDTA broadcast imem[ii+3] = pedestal_data[ii/4]; // value for this time bin } //imem[4096] = PEDCONF_RCU_END; // no space for PEDCONF_RCU_END; Will be executed anyway. /* Write to rcu */ retval = FEC_IMEM_Write(rcu, imem, RCU_INSTRUCTION_MEM_SZ); log_rorc(rcu, LOG_DEBUG, "Exiting function writeTestPatternBroadcast()"); return retval; } //======================================================================== int32_t writeTestPattern(rcu_model_t* rcu) { // // Write test pattern into RCU Pedestal Memory. Not in broadcast. // This is much slower. // log_rorc(rcu, LOG_DEBUG, "Entering function writeTestPattern()"); char desc[256]; uint32_t pedestal_data[1024]; uint32_t imem[RCU_INSTRUCTION_MEM_SZ]; for ( ii = 0; ii < RCU_INSTRUCTION_MEM_SZ; ii++ ) imem[ii] = 0; int32_t branch, fec, altro, channel, nfec; for (branch=0; branch<2; branch++) { if ( (rcu->id == 0) || (rcu->id == 2) ) nfec = 9; // rcu 0, 2 else if ( (rcu->id > 2) && (rcu->id < 6) ) nfec = 10; // rcu 3, 4, 5 else if ( branch == 0 ) nfec = 13; // rcu 1, branch A else nfec = 12; // rcu 1, branch A for ( fec = 0; fec < nfec; fec++ ) { // Check if this fec is on if ( !checkFecOn(rcu, (branch<<4)|fec) ) continue; for (altro=0; altro<8; altro++) { for (channel=0; channel<16; channel++) { int32_t hwaddr = codeAddress(branch, fec, altro, channel); int32_t chipaddr = (hwaddr>>4) & 0xff; // branch, FEC and ALTRO bits for ( ii = 0; ii < 1024; ii++ ) pedestal_data[ii] = 0; filltestarray(pedestal_data, arguments.occupancy, 0); // Dummy Pedestal Data // Create IMEM block - Dummy Pedestal Data for ( ii = 0; ii < RCU_INSTRUCTION_MEM_SZ; ii += 4 ) { // 0 ... 4092 imem[ii+0] = (uint32_t)((2<<20) | (chipaddr<<9) | 0xD); // PMADD imem[ii+1] = (uint32_t)(ii/4); // time bin 0 ... 1023 imem[ii+2] = (uint32_t)((2<<20) | (hwaddr<<5) | 0x7); // PMDTA imem[ii+3] = (uint32_t)pedestal_data[ii/4]; // value for this time bin } //imem[4096] = PEDCONF_RCU_END; // no space for PEDCONF_RCU_END; Will be executed anyway. // Write the pedestal data to the RCU_INSTRUCTION_MEMORY if ( FEC_IMEM_Write(rcu, imem, RCU_INSTRUCTION_MEM_SZ) ) { log_rorc(rcu, LOG_ERROR, "FEC_IMEM_Write failed!"); return 1; } } // end channel loop } // end altro loop } // end fec loop } // end branch loop log_rorc(rcu, LOG_DEBUG, "Exiting function writeTestPattern()"); return 0; } //======================================================================== int32_t writePattern(rcu_model_t* rcu) { // // Read pedestal files with time dependent data (one value per channel and time bin) // and write this to RCU Pedestal Mememory. // log_rorc(rcu, LOG_DEBUG, "Entering function writePattern()"); char desc[256]; int32_t tmp, side, sector, patch, hwaddr, chipaddr, fecaddr; int32_t ok = 1; // open file with data FILE *input_file; sprintf(desc, "Opening file %s ...", arguments.input_file); log_rorc(rcu, LOG_INFO, desc); if ( (input_file = fopen(arguments.input_file, "r")) == NULL ) { sprintf(desc, "Cannot open file %s!", arguments.input_file); log_rorc(rcu, LOG_ERROR, desc); return 1; } // The pedestal buffer uint32_t pedestal_data[1024]; for ( ii = 0; ii < 1024; ii++ ) pedestal_data[ii] = 0; uint32_t imem[RCU_INSTRUCTION_MEM_SZ]; for ( ii = 0; ii < RCU_INSTRUCTION_MEM_SZ; ii++ ) imem[ii] = 0; // read the first number in the file to check if it is pedmem file int32_t test = readint(&ok, input_file); if ( test != 12 ) { log_rorc(rcu, LOG_ERROR, "Wrong file type (not a pedestal mem file)!"); return 1; } log_rorc(rcu, LOG_INFO, "Reading file and writing to RCU.."); // Loop over all channels found in file while ( 1 ) { // read the first numbers from next line in the file ii = readint(&ok, input_file); side = readint(&ok, input_file); sector = readint(&ok, input_file); patch = readint(&ok, input_file); hwaddr = readint(&ok, input_file); if ( ok & ((side<0) || (side>1)) ) { sprintf(desc, "Wrong side number: %d!", side); logger(LOG_ERROR, desc); return 1; } if ( ok & ((sector<0) || (sector>17)) ) { sprintf(desc, "Wrong sector number: %d!", sector); logger(LOG_ERROR, desc); return 1; } if ( ok & ((patch<0) || (patch>5)) ) { sprintf(desc, "Wrong rcu number: %d!", patch); logger(LOG_ERROR, desc); return 1; } chipaddr = (hwaddr>>4) & 0xff; // branch, FEC and ALTRO bits /* Read pedestal data, skip 14 pretrigger samples (in the files there are 15 pretrigger samples) */ for ( ii = 0; ii < 1024; ii++ ) { tmp = roundtoint(readfloat(&ok, input_file)); tmp += arguments.add; if (tmp<0 ) tmp=0; if (tmp>1023) tmp=1023; if (ii<15) pedestal_data[1024-1-ii] = 0; else pedestal_data[ii-15 ] = tmp; } if ( ok && (rcu->id == patch) ) { // only configure this rcu // Check if this fec is on if ( !checkFecOn(rcu, (hwaddr>>7)&0x1f) ) continue; sprintf(desc, "Writing pattern: Channel %d, altro %d, fec %d, branch %d (hwaddr %d)", decodedAddressChanneladdr(hwaddr), decodedAddressChipaddr(hwaddr), decodedAddressFECaddr(hwaddr), decodedAddressBranch(hwaddr), hwaddr); log_rorc(rcu, LOG_DEBUG, desc); // Create IMEM block int32_t ctr = 0; for ( ii = 0; ii < 1024; ii++ ) { if ( (iiarguments.maxtb) ) continue; imem[ctr+0] = (uint32_t)((2<<20) | (chipaddr<<9) | 0xD); // PMADD imem[ctr+1] = (uint32_t)ii; // time bin 0 ... 1023 imem[ctr+2] = (uint32_t)((2<<20) | (hwaddr<<5) | 0x7); // PMDTA imem[ctr+3] = (uint32_t)pedestal_data[ii]; // value for this time bin ctr += 4; } if (ctr<4096) imem[ctr] = PEDCONF_RCU_END; // if no space for PEDCONF_RCU_END, sequence will be executed anyway. // Write the pedestal data to the RCU_INSTRUCTION_MEMORY if ( FEC_IMEM_Write(rcu, imem, RCU_INSTRUCTION_MEM_SZ) ) { log_rorc(rcu, LOG_ERROR, "FEC_IMEM_Write failed!!"); return 1; } } // end if (patch == rcu->id) } // end while (file loop) // close the file fclose(input_file); log_rorc(rcu, LOG_DEBUG, "Exiting function writePattern()"); return 0; } //======================================================================== int32_t writePattern2(rcu_model_t* rcu) { // // Read pedestal files with fixed pedestal data and write this to RCU // Pedestal Mememory as constant values. // log_rorc(rcu, LOG_DEBUG, "Entering function writePattern2()"); char desc[256]; float tmp; uint32_t pedValue; int32_t side, sector, patch, hwaddr, chipaddr; int32_t ok = 1; // open file with data FILE *input_file; sprintf(desc, "Opening file %s ...!", arguments.input_file); log_rorc(rcu, LOG_INFO, desc); if ( (input_file = fopen(arguments.input_file, "r")) == NULL ) { sprintf(desc, "Cannot open file %s!", arguments.input_file); log_rorc(rcu, LOG_ERROR, desc); return 1; } uint32_t imem[RCU_INSTRUCTION_MEM_SZ]; for ( ii = 0; ii < RCU_INSTRUCTION_MEM_SZ; ii++ ) imem[ii] = 0; // read the first number in the file to check if it is pedestal file int32_t test = readint(&ok, input_file); if ( test != 10 ) { log_rorc(rcu, LOG_ERROR, "Wrong file type (not a pedestal file)!"); return 1; } log_rorc(rcu, LOG_INFO, "Reading file and writing to RCU!"); while ( 1 ) { /* Loop over all channels found in file */ /* read numbers from one line in the file */ ii = readint(&ok, input_file); side = readint(&ok, input_file); sector = readint(&ok, input_file); patch = readint(&ok, input_file); hwaddr = readint(&ok, input_file); tmp = readfloat(&ok, input_file); if ( ok & ((side<0) || (side>1)) ) { sprintf(desc, "Wrong side number: %d!", side); logger(LOG_ERROR, desc); return 1; } if ( ok & ((sector<0) || (sector>17)) ) { sprintf(desc, "Wrong sector number: %d!", sector); logger(LOG_ERROR, desc); return 1; } if ( ok & ((patch<0) || (patch>5)) ) { sprintf(desc, "Wrong rcu number: %d!", patch); logger(LOG_ERROR, desc); return 1; } chipaddr = (hwaddr>>4) & 0xff; // branch, FEC and ALTRO bits tmp += arguments.add; if (tmp<0 ) tmp=0; if (tmp>1023) tmp=1023; pedValue = roundtoint(tmp); //if (pedValue == 0) continue; if ( ok && (rcu->id == patch) ) { // only configure the rcu connected to this rorc! // Check if this fec is on if ( !checkFecOn(rcu, (hwaddr>>7)&0x1f) ) continue; sprintf(desc, "Writing pattern: Channel %d, altro %d, fec %d, branch %d (hwaddr %d)", decodedAddressChanneladdr(hwaddr), decodedAddressChipaddr(hwaddr), decodedAddressFECaddr(hwaddr), decodedAddressBranch(hwaddr), hwaddr); log_rorc(rcu, LOG_DEBUG, desc); // Create IMEM block int32_t ctr = 0; for ( ii = 0; ii < 1024; ii++ ) { if ( (iiarguments.maxtb) ) continue; imem[ctr+0] = (uint32_t)((2<<20) | (chipaddr<<9) | 0xD); // PMADD imem[ctr+1] = (uint32_t)ii; // time bin 0 ... 1023 imem[ctr+2] = (uint32_t)((2<<20) | (hwaddr<<5) | 0x7); // PMDTA imem[ctr+3] = pedValue; // value for this time bin ctr += 4; } if (ctr<4096) imem[ctr] = PEDCONF_RCU_END; // if no space for PEDCONF_RCU_END, sequence will be executed anyway. // Write the pedestal data to the RCU_INSTRUCTION_MEMORY if ( FEC_IMEM_Write(rcu, imem, RCU_INSTRUCTION_MEM_SZ) ) { log_rorc(rcu, LOG_ERROR, "FEC_IMEM_Write failed!!"); return 1; } } // end if (rcu->id == patch) if ( !ok ) break; } // end while (file loop) // close the file fclose(input_file); log_rorc(rcu, LOG_DEBUG, "Exiting function writePattern2()"); return 0; } //======================================================================== int32_t writeFPED(rcu_model_t* rcu) { // // Write the fixed pedestal values from file to ALTROs // char desc[256]; log_rorc(rcu, LOG_DEBUG, "Entering function writeFPED()"); uint32_t pedValue; int32_t side, sector, patch, hwaddr; int32_t ok = 1; // open file with data FILE *input_file; sprintf(desc, "Opening file %s ...!", arguments.input_file); log_rorc(rcu, LOG_INFO, desc); if ( (input_file = fopen(arguments.input_file, "r")) == NULL ) { sprintf(desc, "Cannot open file %s!", arguments.input_file); log_rorc(rcu, LOG_ERROR, desc); return 1; } uint32_t imem[RCU_INSTRUCTION_MEM_SZ]; int32_t memctr = 0; // read the first number in the file to check if it is pedestal file int32_t test = readint(&ok, input_file); if ( test != 10 ) { log_rorc(rcu, LOG_ERROR, "Wrong file type (not a pedestal file)!"); return 1; } log_rorc(rcu, LOG_INFO, "Reading file and writing to RCU...!"); while ( 1 ) { /* Loop over all channels found in file */ /* read numbers from one line in the file */ ii = readint(&ok, input_file); side = readint(&ok, input_file); sector = readint(&ok, input_file); patch = readint(&ok, input_file); hwaddr = readint(&ok, input_file); pedValue = roundtoint(readfloat(&ok, input_file)); if ( ok & ((side<0) || (side>1)) ) { sprintf(desc, "Wrong side number: %d!", side); logger(LOG_ERROR, desc); return 1; } if ( ok & ((sector<0) || (sector>17)) ) { sprintf(desc, "Wrong sector number: %d!", sector); logger(LOG_ERROR, desc); return 1; } if ( ok & ((patch<0) || (patch>5)) ) { sprintf(desc, "Wrong rcu number: %d!", patch); logger(LOG_ERROR, desc); return 1; } //if (pedValue == 0) continue; if ( ok && (rcu->id == patch) ) { // only configure the rcu connected to this rorc! // Check if this fec is on if ( !checkFecOn(rcu, (hwaddr>>7)&0x1f) ) continue; sprintf(desc, "Writing FPED=%d: Channel %d, altro %d, fec %d, branch %d (hardware address %d)!", (int)pedValue, decodedAddressChanneladdr(hwaddr), decodedAddressChipaddr(hwaddr), decodedAddressFECaddr(hwaddr), decodedAddressBranch(hwaddr), hwaddr); log_rorc(rcu, LOG_DEBUG, desc); imem[memctr++] = ((0x200000 | (hwaddr<<5)) | 0x6); // 0x6 -> FPED register adress imem[memctr++] = pedValue&0x3ff; // 10bit wide fixed pedestal value } if ( memctr >= (RCU_INSTRUCTION_MEM_SZ - 4) ) log_rorc(rcu, LOG_INFO, "IMEM full! "); if ( !ok ) log_rorc(rcu, LOG_INFO, "End of file!"); if ( (memctr >= (RCU_INSTRUCTION_MEM_SZ - 4)) || !ok ) { // IMEM almost full or finished imem[memctr++] = PEDCONF_RCU_END; /* RCU_END instruction */ /* write to IMEM */ if ( FEC_IMEM_Write(rcu, imem, RCU_INSTRUCTION_MEM_SZ) ) { log_rorc(rcu, LOG_ERROR, "FEC_IMEM_Write failed!!"); return 1; } memctr = 0; } // end if if ( !ok ) break; } // end while (file loop) // close the file fclose(input_file); log_rorc(rcu, LOG_DEBUG, "Exiting function writeFPED()"); return 0; } //======================================================================== int32_t writeBCTHR(rcu_model_t* rcu) { // // Write the thresholds for the moving average filter (second baseline restoration filter) // log_rorc(rcu, LOG_DEBUG, "Entering function writeBCTHR()"); char desc[256]; uint32_t THR_HI, THR_LO; int32_t side, sector, patch, hwaddr; int32_t ok = 1; // open file with data FILE *input_file; sprintf(desc, "Opening file %s ...!", arguments.input_file); log_rorc(rcu, LOG_INFO, desc); if ( (input_file = fopen(arguments.input_file, "r")) == NULL ) { sprintf(desc, "Cannot open file %s!", arguments.input_file); log_rorc(rcu, LOG_ERROR, desc); return 1; } uint32_t imem[RCU_INSTRUCTION_MEM_SZ]; int32_t memctr = 0; // read the first number in the file and check if it is noise file int32_t test = readint(&ok, input_file); if ( test != 11 ) { log_rorc(rcu, LOG_ERROR, "Wrong file type (not a noise file)!"); return 1; } log_rorc(rcu, LOG_INFO, "Reading file and writing to RCU!"); while ( 1 ) { /* Loop over all channels found in file */ /* read numbers from one line in the file */ ii = readint(&ok, input_file); side = readint(&ok, input_file); sector = readint(&ok, input_file); patch = readint(&ok, input_file); hwaddr = readint(&ok, input_file); if ( ok & ((side<0) || (side>1)) ) { sprintf(desc, "Wrong side number: %d!", side); logger(LOG_ERROR, desc); return 1; } if ( ok & ((sector<0) || (sector>17)) ) { sprintf(desc, "Wrong sector number: %d!", sector); logger(LOG_ERROR, desc); return 1; } if ( ok & ((patch<0) || (patch>5)) ) { sprintf(desc, "Wrong rcu number: %d!", patch); logger(LOG_ERROR, desc); return 1; } // Read the noise value float tmp = readfloat(&ok, input_file) * arguments.factor; THR_LO = roundtoint(tmp); if ( THR_LO > arguments.max ) THR_LO = arguments.max; if ( THR_LO < arguments.min ) THR_LO = arguments.min; THR_HI = THR_LO; // at the moment we have the same thresholds hi and lo if ( ok && (rcu->id == patch) ) { // only configure the rcu connected to this rorc! // Check if this fec is on if ( !checkFecOn(rcu, (hwaddr>>7)&0x1f) ) continue; sprintf(desc, "Writing Writing BCTHR (Lo=%d, Hi=%d): Rcu %d, br %d, fec %d, chip %d, ch %d (hwaddr %d)!", (int)(THR_LO&0x3ff), (int)(THR_HI&0x3ff), rcu->id, decodedAddressBranch(hwaddr), decodedAddressFECaddr(hwaddr), decodedAddressChipaddr(hwaddr), decodedAddressChanneladdr(hwaddr), hwaddr); log_rorc(rcu, LOG_DEBUG, desc); imem[memctr++] = ((0x200000 | (hwaddr << 5) ) | 0x9); // 0x9 -> BCTHR register adress imem[memctr++] = ((THR_HI&0x3ff)<<10) | (THR_LO&0x3ff); // Two 10bit wide values } if ( memctr >= (RCU_INSTRUCTION_MEM_SZ - 4) ) log_rorc(rcu, LOG_INFO, "IMEM full! "); if ( !ok ) log_rorc(rcu, LOG_INFO, "End of file!"); if ( (memctr >= (RCU_INSTRUCTION_MEM_SZ - 4)) || !ok ) { // IMEM almost full or finished imem[memctr++] = PEDCONF_RCU_END; // RCU_END instruction /* write to IMEM */ if ( FEC_IMEM_Write(rcu, imem, RCU_INSTRUCTION_MEM_SZ) ) { log_rorc(rcu, LOG_ERROR, "FEC_IMEM_Write failed!!"); return 1; } memctr = 0; } if ( !ok ) break; } // end while (file loop) // close the file fclose(input_file); log_rorc(rcu, LOG_DEBUG, "Exiting function writeBCTHR()"); return 0; } //======================================================================== int32_t writeZSTHR(rcu_model_t* rcu) { // // Write the thresholds for the zero suppression filter // log_rorc(rcu, LOG_DEBUG, "Entering function writeZSTHR()"); char desc[256]; uint32_t OFFSET, ZS_THR; int32_t side, sector, patch, hwaddr; int32_t ok = 1; OFFSET = arguments.offset; // open file with data FILE *input_file; sprintf(desc, "Opening file %s ...!", arguments.input_file); log_rorc(rcu, LOG_INFO, desc); if ( (input_file = fopen(arguments.input_file, "r")) == NULL ) { sprintf(desc, "Cannot open file %s!", arguments.input_file); log_rorc(rcu, LOG_ERROR, desc); return 1; } uint32_t imem[RCU_INSTRUCTION_MEM_SZ]; int32_t memctr = 0; // read the first number in the file and check if it is noise file int32_t test = readint(&ok, input_file); if ( test != 11 ) { log_rorc(rcu, LOG_ERROR, "Wrong file type (not a noise file)!"); return 1; } log_rorc(rcu, LOG_INFO, "Reading file and writing to RCU!"); while ( 1 ) { /* Loop over all channels found in file */ /* read the three numbers from one line in the file */ ii = readint(&ok, input_file); side = readint(&ok, input_file); sector = readint(&ok, input_file); patch = readint(&ok, input_file); hwaddr = readint(&ok, input_file); if ( ok & ((side<0) || (side>1)) ) { sprintf(desc, "Wrong side number: %d!", side); logger(LOG_ERROR, desc); return 1; } if ( ok & ((sector<0) || (sector>17)) ) { sprintf(desc, "Wrong sector number: %d!", sector); logger(LOG_ERROR, desc); return 1; } if ( ok & ((patch<0) || (patch>5)) ) { sprintf(desc, "Wrong rcu number: %d!", patch); logger(LOG_ERROR, desc); return 1; } /* Read the noise value */ float tmp = readfloat(&ok, input_file) * arguments.factor; ZS_THR = roundtoint(tmp); if ( ZS_THR > arguments.max ) ZS_THR = arguments.max; if ( ZS_THR < arguments.min ) ZS_THR = arguments.min; if ( ok && (rcu->id == patch) ) { // only configure the rcu connected to this rorc! // Check if this fec is on if ( !checkFecOn(rcu, (hwaddr>>7)&0x1f) ) continue; sprintf(desc, "Writing ZSTHR=%d: Rcu %d, br %d, fec %d, chip %d, ch %d (hwaddr %d)!", (int)(ZS_THR&0x3ff), rcu->id, decodedAddressBranch(hwaddr), decodedAddressFECaddr(hwaddr), decodedAddressChipaddr(hwaddr), decodedAddressChanneladdr(hwaddr), hwaddr); log_rorc(rcu, LOG_DEBUG, desc); imem[memctr++] = ((0x200000 | (hwaddr<<5)) | 0x8); // 0x8 -> ZSTHR register adress imem[memctr++] = ((OFFSET&0x3ff)<<10) | (ZS_THR&0x3ff); // Two 10bit wide values } if ( memctr >= (RCU_INSTRUCTION_MEM_SZ - 4) ) log_rorc(rcu, LOG_INFO, "IMEM full! "); if ( !ok ) log_rorc(rcu, LOG_INFO, "End of file!"); if ( (memctr >= (RCU_INSTRUCTION_MEM_SZ - 4)) || !ok ) { // IMEM almost full or finished imem[memctr++] = PEDCONF_RCU_END; /* RCU_END instruction */ /* write to IMEM */ if ( FEC_IMEM_Write(rcu, imem, RCU_INSTRUCTION_MEM_SZ) ) { log_rorc(rcu, LOG_ERROR, "FEC_IMEM_Write failed!"); return 1; } memctr = 0; } if ( !ok ) break; } // end while (file loop) // close the file fclose(input_file); log_rorc(rcu, LOG_DEBUG, "Exiting function writeZSTHR()"); return 0; } //======================================================================== //======================================================================== //======================================================================== int main( int argc, char** argv ) { int status = 0; int eq = 0; mainlogfile = fopen("/tmp/TPCPEDCONFIG_MAIN.log", "w"); if (mainlogfile == NULL) printf("ERROR: open main logfile failed!"); /* get hostname of this LDC */ if (gethostname (hostname, 255) != 0) { log_main(LOG_FATAL, "gethostname() failed!"); if (mainlogfile) fclose(mainlogfile); return 1; } // Default values arguments.on_ldc = true; arguments.rdo_conf = true; arguments.reset = true; arguments.active_fecs = true; arguments.command = 0; arguments.offset = 0; arguments.factor = 3.0; arguments.min = 2; arguments.max = 2; arguments.mintb = 0; arguments.maxtb = 1023; arguments.add = 0.0; // Rorc information for RCU lab setup arguments.rev = 4; arguments.serial = 5046; arguments.minor = 0; arguments.channel = 0; arguments.rcu = -1; // Parse arguments; every option seen by parse_opt will be reflected in arguments argp_parse(&argp, argc, argv, 0, 0, &arguments); // prepare pointers to the RCU models log_main(LOG_DEBUG, "Preparing pointers to the RCU models"); rcu = calloc(6, sizeof(*rcu)); if (rcu == NULL) { log_main(LOG_FATAL, "Allocation of rcu failed"); if (mainlogfile) fclose(mainlogfile); return 1; } for ( eq = 0; eq < 6; eq++ ) rcu[eq] = NULL; log_main(LOG_DEBUG, "Successfully prepared pointers to the RCU models"); int retval[6] = { 0, 0, 0, 0, 0, 0}; // return values for 6 equipments int eqid_array[6] = {-1,-1,-1,-1,-1,-1}; // The equipment IDs pid_t eqid_pid[6] = {-1,-1,-1,-1,-1,-1}; // The process ids int num_eqid = -1; log_main(LOG_DEBUG, "Start loop over RCU models. Check individual logfiles!"); if ( !arguments.on_ldc ) { // rorc details are provided by user num_eqid = 6; if ( arguments.rcu == -1 ) { log_main(LOG_FATAL, "Readout partition (0...5) needs to be specified!"); if (mainlogfile) fclose(mainlogfile); return 1; } if ( (arguments.rcu<0) || (arguments.rcu>5) ) { log_main(LOG_FATAL, "rp has to be in range [0...5]!"); if (mainlogfile) fclose(mainlogfile); return 1; } for ( eq = 0; eq < num_eqid; eq++ ) eqid_array[eq] = -2; /* allocate a new RCU model and set values */ rcu[arguments.rcu] = get_new_rcu_model(); rcu[arguments.rcu]->id = arguments.rcu; rcu[arguments.rcu]->ddl_revision = arguments.rev; rcu[arguments.rcu]->ddl_serial = arguments.serial; rcu[arguments.rcu]->ddl_channel = arguments.channel; eqid_array[arguments.rcu] = rcu[arguments.rcu]->eqid; char filename[256]; sprintf(filename, "/tmp/TPCPEDCONFIG_%d.log", arguments.rcu); rcu[arguments.rcu]->logfile = fopen(filename, "w"); if ( rcu[arguments.rcu]->logfile == NULL ) { char desc[256]; sprintf(desc, "Open rorc logfile failed for rp=%d!", arguments.rcu); log_main(LOG_ERROR, desc); } } else { /* rorc details are provided by mysql */ num_eqid = get_eqid(eqid_array, 6); if (num_eqid <= 0) { log_main(LOG_FATAL, "No configured RorcData equipment found!"); if (mainlogfile) fclose(mainlogfile); return 1; } if (num_eqid > 6) { char desc[256]; sprintf(desc, "Too many configured RorcData equipments found: Configured=%d, maximum=6", num_eqid); log_main(LOG_FATAL, desc); if (mainlogfile) fclose(mainlogfile); return 1; } char desc[256]; sprintf(desc, "%d configured RorcData equipments found", num_eqid); log_main(LOG_INFO, desc); for ( eq = 0; eq < num_eqid; eq++ ) { /* for each rcu */ rcu[eq] = get_new_rcu_model(); /* allocate a new RCU model */ rcu[eq]->eqid = eqid_array[eq]; /* set the eqId in the RCU model */ rcu[eq]->id = getPatchFromEquipmentID(eqid_array[eq]); char filename[256]; sprintf(filename, "/tmp/TPCPEDCONFIG_%d.log", rcu[eq]->id); rcu[eq]->logfile = fopen(filename, "w"); if ( rcu[eq]->logfile == NULL ) { char desc[256]; sprintf(desc, "Open rorc logfile failed for rp=%d!", rcu[eq]->id); log_main(LOG_ERROR, desc); } /* load from the DATE database the active RORCs for this eqId into the RCU model */ retval[eq] = get_ddl_details(rcu[eq]); if (retval[eq] != 0) { log_rorc(rcu[eq], LOG_ERROR, "No configured RORC found!"); continue; } } // end loop for getting rcu details } // end if on_ldc for ( eq = 0; eq < num_eqid; eq++ ) { // RORC/RCU loop char desc[256]; if ( eqid_array[eq] < 0 ) { // No RCU found if ( (eqid_array[eq] == -1) ) log_rorc(rcu[eq], LOG_DEBUG, "Not properly configured EqID found!"); continue; } /* Open the RORC */ log_rorc(rcu[eq], LOG_DEBUG, "Opening the RORC channel"); rcu[eq]->key = get_channel(rcu[eq]->ddl_revision, rcu[eq]->ddl_serial, rcu[eq]->ddl_channel); if (rcu[eq]->key->err != 0) { sprintf (desc, "Failed to open RORC with S/N=%d (rev=%d, channel=%d)", rcu[eq]->ddl_serial, rcu[eq]->ddl_revision, rcu[eq]->ddl_channel); log_rorc(rcu[eq], LOG_ERROR, desc); continue; } sprintf(desc, "Opened RORC with S/N=%d (rev=%d, channel=%d)", rcu[eq]->ddl_serial, rcu[eq]->ddl_revision, rcu[eq]->ddl_channel); log_rorc(rcu[eq], LOG_DEBUG, desc); /*** FORK ***/ log_rorc(rcu[eq], LOG_DEBUG, "Start the fork"); pid_t pid = fork(); if ( pid < 0 ) { log_rorc(rcu[eq], LOG_ERROR, "Fork failed!"); if (mainlogfile) fclose(mainlogfile); return (-1); } /* child process starts here */ if (pid == 0) { /* execute reset for one RCU */ retval[eq] = 0; if ( arguments.reset ) { log_rorc(rcu[eq], LOG_INFO, "Reset RORC/DIU/SIU"); retval[eq] = RORC_Reset_all(rcu[eq]); } uint32_t data = 0; if ( !retval[eq] ) { // Reset went ok? /* execute the commands for one RCU */ switch ( arguments.command ) { case PEDCONF_CLEAR_ALL: // Clear all log_rorc(rcu[eq], LOG_INFO, "Clear Status and Error registers"); retval[eq] = clearall(rcu[eq]); break; case PEDCONF_FECS_OFF: // Just switch off all FECs log_rorc(rcu[eq], LOG_INFO, "Switching off FECs"); retval[eq] = switchFecs(rcu[eq]); break; case PEDCONF_WRITE_RAMP_BROADCAST: // dummy pedestal memory configuration (ramp) retval[eq] = clearall(rcu[eq]); if ( !retval[eq] ) retval[eq] = switchFecs(rcu[eq]); if ( !retval[eq] ) { log_rorc(rcu[eq], LOG_INFO, "Executing WRITE_RAMP_BROADCAST"); retval[eq] = writeDummyBroadcast(rcu[eq]); } break; case PEDCONF_WRITE_TESTPATTERN: // test pattern with given occupancy, written channel by channel retval[eq] = clearall(rcu[eq]); if ( !retval[eq] ) retval[eq] = switchFecs(rcu[eq]); if ( !retval[eq] && arguments.rdo_conf ) retval[eq] = config4pedmemRdo(rcu[eq]); if ( !retval[eq] ) { log_rorc(rcu[eq], LOG_INFO, "Executing WRITE_TESTPATTERN"); retval[eq] = writeTestPattern(rcu[eq]); } break; case PEDCONF_WRITE_TESTPATTERN_BROADCAST: // test pattern with given occupancy, written in broadcast mode retval[eq] = clearall(rcu[eq]); if ( !retval[eq] ) retval[eq] = switchFecs(rcu[eq]); if ( !retval[eq] && arguments.rdo_conf ) retval[eq] = config4pedmemRdo(rcu[eq]); if ( !retval[eq] ) { log_rorc(rcu[eq], LOG_INFO, "Executing WRITE_TESTPATTERN_BROADCAST"); retval[eq] = writeTestPatternBroadcast(rcu[eq]); } break; case PEDCONF_WRITE_PATTERN: // configure pedestal memories with data from file retval[eq] = clearall(rcu[eq]); if ( !retval[eq] ) retval[eq] = Read_ACTFECLIST(rcu[eq], &data); if ( !retval[eq] ) { log_rorc(rcu[eq], LOG_INFO, "Executing WRITE_PATTERN"); retval[eq] = writePattern(rcu[eq]); } break; case PEDCONF_WRITE_PATTERN2: // configure pedestal memories with FPED data from file retval[eq] = clearall(rcu[eq]); if ( !retval[eq] ) retval[eq] = Read_ACTFECLIST(rcu[eq], &data); if ( !retval[eq] ) { log_rorc(rcu[eq], LOG_INFO, "Executing WRITE_PATTERN2"); retval[eq] = writePattern2(rcu[eq]); } break; case PEDCONF_WRITE_FPED: // configure FPED register with data from file retval[eq] = clearall(rcu[eq]); if ( !retval[eq] ) retval[eq] = Read_ACTFECLIST(rcu[eq], &data); if ( !retval[eq] ) { log_rorc(rcu[eq], LOG_INFO, "Executing WRITE_FPED"); retval[eq] = writeFPED(rcu[eq]); } break; case PEDCONF_WRITE_ZSTHR: // configure ZSTHR register as a function of noise data from file retval[eq] = clearall(rcu[eq]); if ( !retval[eq] ) retval[eq] = Read_ACTFECLIST(rcu[eq], &data); if ( !retval[eq] ) { log_rorc(rcu[eq], LOG_INFO, "Executing WRITE_ZSTHR"); retval[eq] = writeZSTHR(rcu[eq]); } break; case PEDCONF_WRITE_BCTHR: // configure BCTHR register as a function of noise data from file retval[eq] = clearall(rcu[eq]); if ( !retval[eq] ) retval[eq] = Read_ACTFECLIST(rcu[eq], &data); if ( !retval[eq] ) { log_rorc(rcu[eq], LOG_INFO, "Executing WRITE_BCTHR"); retval[eq] = writeBCTHR(rcu[eq]); } break; default: // Do nothing log_rorc(rcu[eq], LOG_ERROR, "No option chosen. Executing nothing"); ;; } //end switch } // end if (!retval[eq]) /* report errors */ if ( retval[eq] != 0 ) log_rorc(rcu[eq], LOG_ERROR, "Command execution failed!"); /* child process ends here */ exit(retval[eq]); } // end if pid==0 /*** parent process continues here ***/ if (pid > 0) eqid_pid[eq] = pid; } // end equipment loop log_main(LOG_DEBUG, "End loop over RCU models. Check individual logfiles!"); int ctr = 0; /* waiting for the child processes */ for ( eq = 0; eq < num_eqid; eq++ ) { if ( eqid_array[eq] < 0 ) continue; char desc[256]; sprintf(desc, "Waiting for child with pid %i", eqid_pid[eq]); log_rorc(rcu[eq], LOG_DEBUG, desc); waitpid(eqid_pid[eq], &status, 0); sprintf(desc, "Child with pid %i exited ok", eqid_pid[eq]); log_rorc(rcu[eq], LOG_DEBUG, desc); ctr++; } /* releasing the opened RORCs */ log_main(LOG_DEBUG, "Releasing RORC channels"); for ( eq = 0; eq < num_eqid; eq++ ) { if ( eqid_array[eq] < 0 ) continue; if ((rcu[eq]->key != NULL) && (rcu[eq]->key->err == 0)) { usleep (2000); release_channel(rcu[eq]->key); } } log_main(LOG_DEBUG, "Successfully released RORC channels"); /* deallocate the RCU models */ for ( eq = 0; eq < num_eqid; eq++ ) { if ( eqid_array[eq] < 0 ) continue; free_rcu_model (rcu[eq]); } char desc[256]; sprintf(desc, "Program finished on %d equipment(s)", ctr); log_main(LOG_INFO, desc); // close main logfile if (mainlogfile) fclose(mainlogfile); return 0; } //EOF