/* ===================================================================== * The Readout List. This class provides some functionality around * it. This is used in the RCU Firmware V2 to define the order of readout * of the channels of all ALTROs on the FECs connected to an RCU. * On the RCU it is 12bit x 4096. * ===================================================================== */ /* *Author: C. Lippmann, Christian.Lippmann@cern.ch */ #include "ReadoutList.h" ReadoutList::ReadoutList() { // // Constructor // fVersion = 20; // RCU Fw Version 2.0 (readout list memory for full rcu) fMaxSize = 0x1000; reset(); fLogger=Logger::getInstance(); } ReadoutList::~ReadoutList() { // // Destructor // } uint32_t ReadoutList::size() { // // Get size. Warning: Final size is only available after finalize() was called! // return fReadoutList.size(); } void ReadoutList::reset() { // // Reset // fACL.reset(); fReadoutList.clear(); fListBranchA.clear(); fListBranchB.clear(); } void ReadoutList::makeReadoutListFromAclHLT(int32_t rcu) { // // Make Readout List from Acl. For this we need to know which rcu it is (0...5). // We read pad after pad per padrow, then next padrow. // This is cool for the HLT to do clustering already while reading raw data. // fReadoutList.clear(); for ( uint32_t row = fPm.GetMinPadRow(rcu); row <= fPm.GetMaxPadRow(rcu); row++ ) { for ( uint32_t pad = 0; pad < fPm.GetNPads(row, rcu); pad++ ) addActiveChannelFromACL(fPm.GetHWAddress(row, pad, rcu)); } } void ReadoutList::makeReadoutListFromAclHwAdd() { // // Make Readout List from Acl. // We read the pads ordered by theit Hardware Address. // fReadoutList.clear(); for ( int32_t hwAddr = 0; hwAddr < 0xfff; hwAddr++ ) addActiveChannelFromACL(hwAddr); } void ReadoutList::makeReadoutListFromAclFast(int32_t rcu) { // // Make Readout List from Acl. For this we need to know which rcu it is (0...5). // We read pad after pad per padrow but alternating branches. // This is the fastest readout on the ALTRO bus and cool for the HLT (agreed with Torsten!). // fReadoutList.clear(); int32_t ctr0 = 0; int32_t ctr1 = 0; bool act0, act1; for ( uint32_t row = fPm.GetMinPadRow(rcu); row <= fPm.GetMaxPadRow(rcu); row++ ) { int32_t nPads = (int32_t)fPm.GetNPads(row, rcu); int32_t centerPad = (int32_t)fPm.GetCenterPad(row, rcu); // start at center of padplane ctr1 = centerPad; ctr0 = 0; while ( (ctr0 2.1. The two halves of the readout list emory are used for the // two branches // Make Readout List from Acl. For this we need to know which rcu it is (0...5). // We read pad after pad per padrow but alternating branches. // This is the fastest readout on the ALTRO bus and cool for the HLT (agreed with Torsten!). // fVersion = 21; // Rcu Fw V 2.1 fReadoutList.clear(); fListBranchA.clear(); fListBranchB.clear(); for ( uint32_t row = fPm.GetMinPadRow(rcu); row <= fPm.GetMaxPadRow(rcu); row++ ) { int32_t nPads = (int32_t)fPm.GetNPads(row, rcu); int32_t ctr = 0; while (ctrappendDebug(desc); return false; } branch = fPm.DecodedHWAddressBranch(hwAddr); fec = fPm.DecodedHWAddressFECaddr(hwAddr); altro = fPm.DecodedHWAddressChipaddr(hwAddr); channel = fPm.DecodedHWAddressChanneladdr(hwAddr); if (fACL.isChannelActive(branch, fec, altro, channel)) { fReadoutList.push_back(hwAddr); return true; } return false; } bool ReadoutList::addActiveChannelFromACLv21(int32_t hwAddr) { // // Check if this channel is active in the active channel list (ACL). // If yes, add it to the readout list // int32_t branch, fec, altro, channel; if ( hwAddr < 0 ) { // Can happen where padrow is shared between two RCUs char desc[256]; sprintf(desc, "ReadoutList::addActiveChannelFromACLv21: hwAddress=%d! For some padrows this is ok", (int32_t)hwAddr); fLogger->appendDebug(desc); return false; } branch = fPm.DecodedHWAddressBranch(hwAddr); fec = fPm.DecodedHWAddressFECaddr(hwAddr); altro = fPm.DecodedHWAddressChipaddr(hwAddr); channel = fPm.DecodedHWAddressChanneladdr(hwAddr); if (fACL.isChannelActive(branch, fec, altro, channel)) { if (branch == 0) fListBranchA.push_back(hwAddr); if (branch == 1) fListBranchB.push_back(hwAddr); return true; } return false; } void ReadoutList::finalize() { // // Add the last word // if ( fVersion == 21 ) { // copy branch A data uint32_t *mem = &fListBranchA[0]; fReadoutList.insert(fReadoutList.begin(), mem, mem+fListBranchA.size()); // Add many 0xfff do { fReadoutList.push_back(0xfff); } while ( fReadoutList.size() < 0x800 ); // copy branch B data mem = &fListBranchB[0]; fReadoutList.insert(fReadoutList.end(), mem, mem+fListBranchB.size()); // Add 0xfff at end fReadoutList.push_back(0xfff); } else if (abs((int32_t)fReadoutList[fReadoutList.size()-1]-0xfff)>0) fReadoutList.push_back(0xfff); } void ReadoutList::fillACL(uint32_t branch, uint32_t fec, uint32_t altro, uint32_t channel, bool chOn) { // // Fill only the ACL. This can be later extracted or converted to a readout List // with certain order. // fACL.fill(branch, fec, altro, channel, chOn); } void ReadoutList::fillACL(int32_t hwAddr, bool chOn) { // // Fill only the ACL. This can be later extracted or converted to a readout List // with certain order. // int32_t branch = fPm.DecodedHWAddressBranch(hwAddr); int32_t fec = fPm.DecodedHWAddressFECaddr(hwAddr); int32_t altro = fPm.DecodedHWAddressChipaddr(hwAddr); int32_t channel = fPm.DecodedHWAddressChanneladdr(hwAddr); fACL.fill(branch, fec, altro, channel, chOn); } void ReadoutList::fillFCFS(uint32_t branch, uint32_t fec, uint32_t altro, uint32_t channel, bool chOn) { // // Fill the ReadoutList with one channel value // First come, first served // if ( branch > 1 ) { char desc[256]; sprintf(desc, "ReadoutList::fillFCFS: fec branch out of range: %d", branch); fLogger->appendError(desc); //throw TpcException( (string) desc); return; } if ( fec > 15 ) { char desc[256]; sprintf(desc, "ReadoutList::fillFCFS: fec number out of range: %d", fec); fLogger->appendError(desc); //throw TpcException( (string) desc); return; } if ( altro > 7 ) { char desc[256]; sprintf(desc, "ReadoutList::fillFCFS: altro number out of range: %d", altro); fLogger->appendError(desc); //throw TpcException( (string) desc); return; } if ( channel > 15 ) { char desc[256]; sprintf(desc, "ReadoutList::fillFCFS: channel number out of range: %d", channel); fLogger->appendError(desc); //throw TpcException( (string) desc); return; } if ( size() >= fMaxSize - 2 ) { char desc[256]; sprintf(desc, "ReadoutList::fillFCFS: Size is getting too big: %d", size()); fLogger->appendError(desc); //throw TpcException( (string) desc); return; } fillFCFS(fPm.codeAddress(branch, fec, altro, channel)); } void ReadoutList::fillFCFS(int32_t hwAddr, bool chOn) { // // Fill the ReadoutList with value // First come, first served // if (chOn) fReadoutList.push_back(hwAddr); } void ReadoutList::fill(uint32_t branch, uint32_t fec, uint32_t altro, uint32_t channel, bool chOn) { // // Fill the ReadoutList and ACL with one channel value // First come, first served // fillFCFS(branch, fec, altro, channel, chOn); fACL.fill(branch, fec, altro, channel, chOn); } void ReadoutList::fill(int32_t hwAddr, bool chOn) { // // Fill the ReadoutList with one channel value // First come, first served // Also fill ACL // int32_t branch = fPm.DecodedHWAddressBranch(hwAddr); int32_t fec = fPm.DecodedHWAddressFECaddr(hwAddr); int32_t altro = fPm.DecodedHWAddressChipaddr(hwAddr); int32_t channel = fPm.DecodedHWAddressChanneladdr(hwAddr); if ( (branch>=0) && (fec>=0) && (altro>=0) && (channel>=0) ) { fillFCFS(branch, fec, altro, channel, chOn); fACL.fill(branch, fec, altro, channel, chOn); } } uint32_t ReadoutList::at(uint32_t position) { // // Get value at certain position // if ( position >= size() ) { char desc[256]; sprintf(desc, "ReadoutList::at(): position out of range: %d", position); fLogger->appendError(desc); //throw TpcException( (string) desc); return 0; } return fReadoutList.at(position); } uint32_t* ReadoutList::get() { // // Get the ReadoutList. // return &fReadoutList[0]; } Acl *ReadoutList::getAcl() { // // get the Acl object // return &fACL; }