/* ===================================================================== * Container for the Altro/Channel data block. * We assume RCU Firmware V2. The structure is: * * 1) FEE_CONFIGURE for ALTRO or Channel block, parameter = number of words (235+1+9). * 2) HW_Address * 3) Checksum * * 4) RCU_EXEC_INSTRUCTION, parameter = number of words * * 5) Payload: Up to 4096 words for Rcu Fw v2; config data for several ALTROs * or Pedestal data for one channel * * For 1 ALTRO: (7*16+5)*2+1 = 117*2+1 = 234+1 words * * * 6) CE_CMD_TAILER - End of RCU_EXEC_INSTRUCTION * * 7) FEE_VERIFICATION (ALTRO or Channel Block) * 8) CE_CMD_TAILER - End of FEE_VERIFICATION * * 9) FEE_CONFIGURE_END - End of FEE_CONFIGURE (ALTRO or Channel Block) * 10) HW_Address, same as above * 11) CE_CMD_TAILER - End of FEE_CONFIGURE_END * * 12) CE_CMD_TAILER - End of FEE_CONFIGURE (ALTRO or Channel Block) * ===================================================================== */ /* *Author: C. Lippmann, Christian.Lippmann@cern.ch */ #include "AltroContainer.h" //=========================================================================== // Altro Container derived class //=========================================================================== //=========================================================================== AltroContainer::AltroContainer() : InstructionMemoryContainer() { fDeviceType = fRCUce.deviceAltro(); fMaxSize = 0xfff+1; fStore = false; fRead = false; } //=========================================================================== AltroContainer::AltroContainer(uint32_t hardwareAddress) : InstructionMemoryContainer(hardwareAddress) { fDeviceType = fRCUce.deviceAltro(); fMaxSize = 0xfff+1; fStore = false; fRead = false; } //=========================================================================== void AltroContainer::setAltroInstructionStore(bool store) { fStore = store; if (store) fMaxSize = 0xffff; else fMaxSize = 0xfff+1; } //=========================================================================== void AltroContainer::reset() { fHardwareAddress = 0; fConfigId = 0; fCheckSum = 0; fPayload.clear(); fVerif = false; fStore = false; fRead = false; } //=========================================================================== bool AltroContainer::empty() { if (size() > 0) return false; return true; } //=========================================================================== void AltroContainer::finalize() { // // Finalise the data block, including the header and tailer. // NOTE 1: Call this function only once! Otherwise you get each header and tailer twice! // NOTE 2: Calling getDataBlock() or size() before finalize() does not make sense! // uint32_t bsize = size(); if ( bsize > fMaxSize ) throw TpcException( (string) "AltroContainer: Size of block too large."); // The global registers and channel registers if ( bsize > 0 ) { if ( fStore ) { fPayload.insert(fPayload.begin(), fRCUce.sendRCU_ALTRO_INSTRUCTION_STORE(bsize)); fPayload.push_back(fRCUce.sendCE_CMD_TAILER()); // ends RCU_ALTRO_INSTRUCTION_STORE } else { // IMEM has room for 4096 words. If there is no RCU_END word, all IMEM will be // executed. This should be the case only if the full size of the IMEM is used. if ( bsize < fMaxSize ) { fPayload.push_back(fRCU.sendEND()); // RCU_END bsize++; } fPayload.insert(fPayload.begin(), fRCUce.sendRCU_EXEC_INSTRUCTION(bsize)); fPayload.push_back(fRCUce.sendCE_CMD_TAILER()); // ends RCU_EXEC_INSTRUCTION } } if (fVerif) fPayload.push_back(fRCUce.sendFEE_VERIFICATION()); // if (fVerif) fPayload.push_back(fRCUce.sendCE_CMD_TAILER()); // ends FEE_VERIFICATION if (fRead) fPayload.push_back(fRCUce.sendFEE_CONFIGURE_END_NOSTATE()); else fPayload.push_back(fRCUce.sendFEE_CONFIGURE_END()); fPayload.push_back(fRCUce.sendFEE_CONFIGURE_END_1Word(fConfigId, fDeviceType, fHardwareAddress)); fPayload.push_back(fRCUce.sendCE_CMD_TAILER()); // ends FEE_CONFIGURE_END bsize = size(); fPayload.insert(fPayload.begin(), fCheckSum); fPayload.insert(fPayload.begin(), fRCUce.sendFEE_CONFIGURE_1Word(fConfigId, fDeviceType, fHardwareAddress)); if (fRead) fPayload.insert(fPayload.begin(), fRCUce.sendFEE_CONFIGURE_NOSTATE(bsize)); else fPayload.insert(fPayload.begin(), fRCUce.sendFEE_CONFIGURE(bsize)); fPayload.push_back(fRCUce.sendCE_CMD_TAILER()); // ends FEE_CONFIGURE } //=========================================================================== uint32_t* AltroContainer::getDataBlock() { // // Return the data block, including the header and tailer. // return &fPayload[0]; } //=========================================================================== // Channel Container derived class //=========================================================================== //=========================================================================== ChannelContainer::ChannelContainer() : InstructionMemoryContainer() { fDeviceType = fRCUce.deviceChannel(); fMaxSize = 0xfff+1; } //=========================================================================== ChannelContainer::ChannelContainer(uint32_t hardwareAddress) : InstructionMemoryContainer(hardwareAddress) { fDeviceType = fRCUce.deviceChannel(); fMaxSize = 0xfff+1; } //=========================================================================== // Instruction Memory Container base class //=========================================================================== //=========================================================================== InstructionMemoryContainer::InstructionMemoryContainer() { // Constructor reset(); fPayload.reserve(250); fCheckSum = 0; fRead = false; } //=========================================================================== InstructionMemoryContainer::InstructionMemoryContainer(uint32_t hardwareAddress) { // Constructor reset(); fHardwareAddress = hardwareAddress; fPayload.reserve(250); fCheckSum = 0; fRead = false; } //=========================================================================== void InstructionMemoryContainer::reset() { fHardwareAddress = 0; fConfigId = 0; fCheckSum = 0; fPayload.clear(); fVerif = false; fRead = false; } //=========================================================================== bool InstructionMemoryContainer::empty() { if (fPayload.size() == 0) return true; return false; } //=========================================================================== void InstructionMemoryContainer::setHardwareAddress(uint32_t hardwareAddress) { fHardwareAddress = hardwareAddress; } //=========================================================================== void InstructionMemoryContainer::setVerification(bool verif) { fVerif = verif; } //=========================================================================== void InstructionMemoryContainer::finalize() { // // Finalize the data block, including the header and tailer. // NOTE 1: Call this function only once! Otherwise you get each header and tailer twice! // NOTE 2: Calling getDataBlock() or size() before finalize() does not make sense! // uint32_t bsize = size(); if ( bsize < fMaxSize ) { // IMEM has room for 4096 words. If there is no RCU_END word, all IMEM will be // executed. This should be the case only if the full size of the IMEM is used. fPayload.push_back(fRCU.sendEND()); // RCU_END } else if ( bsize > fMaxSize ) throw TpcException( (string) "InstructionMemoryContainer: Size of block too large."); calculateCheckSum(); fPayload.insert(fPayload.begin(), fRCUce.sendRCU_EXEC_INSTRUCTION(bsize)); fPayload.push_back(fRCUce.sendCE_CMD_TAILER()); // ends RCU_EXEC_INSTRUCTION if (fVerif) fPayload.push_back(fRCUce.sendFEE_VERIFICATION()); // if (fVerif) fPayload.push_back(fRCUce.sendCE_CMD_TAILER()); // ends FEE_VERIFICATION if (fRead) fPayload.push_back(fRCUce.sendFEE_CONFIGURE_END_NOSTATE()); else fPayload.push_back(fRCUce.sendFEE_CONFIGURE_END()); fPayload.push_back(fRCUce.sendFEE_CONFIGURE_END_1Word(fConfigId, fDeviceType, fHardwareAddress)); fPayload.push_back(fRCUce.sendCE_CMD_TAILER()); // ends FEE_CONFIGURE_END bsize = size(); fPayload.insert(fPayload.begin(), fCheckSum); fPayload.insert(fPayload.begin(), fRCUce.sendFEE_CONFIGURE_1Word(fConfigId, fDeviceType, fHardwareAddress)); if (fRead) fPayload.insert(fPayload.begin(), fRCUce.sendFEE_CONFIGURE_NOSTATE(bsize)); else fPayload.insert(fPayload.begin(), fRCUce.sendFEE_CONFIGURE(bsize)); fPayload.push_back(fRCUce.sendCE_CMD_TAILER()); // ends FEE_CONFIGURE } //=========================================================================== uint32_t* InstructionMemoryContainer::getDataBlock() { // // Return the data block, including the header and tailer. // return &fPayload[0]; } //=========================================================================== void InstructionMemoryContainer::fill(uint32_t data) { // Insert Altro register data fPayload.push_back(data); } //=========================================================================== void InstructionMemoryContainer::fill(uint64_t data) { // Insert Altro register data fPayload.push_back(data>>32); fPayload.push_back(data&0xFFFFFFFF); } //=========================================================================== void InstructionMemoryContainer::calculateCheckSum() { // To be implemented fCheckSum = 0; }