Commit eea2c1cc authored by dauncey's avatar dauncey

More DAQ buffering classes

parent 6bdfd169
...@@ -54,7 +54,7 @@ public: ...@@ -54,7 +54,7 @@ public:
} }
unsigned used() const { unsigned used() const {
if(fReadPtr<fWritePtr) return fWritePtr-fReadPtr; if(fReadPtr<=fWritePtr) return fWritePtr-fReadPtr;
return fWritePtr+CircularBufferLength-fReadPtr; return fWritePtr+CircularBufferLength-fReadPtr;
} }
......
#ifndef CircularBufferUR_HH
#define CircularBufferUR_HH
// Write pointer points to next location to write to
// Read pointer points to next location to read from
#include "MultipleUltraRam.hh"
template <unsigned NumberOfUltraRams>
class CircularBufferUR {
public:
enum {
CircularBufferURLength=NumberOfUltraRams*UltraRam::UltraRamBufferLength
};
CircularBufferUR() {
reset();
}
bool writeAndIncrementPtr(uint64_t d) {
if(((fWritePtr+1)%CircularBufferURLength)==fReadPtr) return false;
fMultipleUltraRam.write(fWritePtr,d);
fWritePtr++;
if(fWritePtr>=CircularBufferURLength) fWritePtr-=CircularBufferURLength;
return true;
}
bool read(uint64_t& d) const {
if(fReadPtr==fWritePtr) return false;
d=fMultipleUltraRam.read(fReadPtr);
return true;
}
bool incrementReadPtr() {
if(fReadPtr==fWritePtr) return false;
fReadPtr++;
if(fReadPtr>=CircularBufferURLength) fReadPtr-=CircularBufferURLength;
return true;
}
bool readAndIncrementPtr(uint64_t& d) {
if(!read(d)) return false;
return incrementReadPtr();
}
unsigned space() const {
if(fWritePtr<fReadPtr) return fReadPtr-fWritePtr-1;
return fReadPtr+CircularBufferURLength-fWritePtr-1;
}
unsigned used() const {
if(fReadPtr<=fWritePtr) return fWritePtr-fReadPtr;
return fWritePtr+CircularBufferURLength-fReadPtr;
}
bool empty() const {
return fWritePtr==fReadPtr;
}
void reset() {
fWritePtr=0;
fReadPtr=0;
}
private:
MultipleUltraRam<NumberOfUltraRams> fMultipleUltraRam;
unsigned fWritePtr;
unsigned fReadPtr;
};
#endif
#ifndef EconAna_HH
#define EconAna_HH
#include <iostream>
#include <iomanip>
#include <cassert>
#include "TH1D.h"
#include "TH2D.h"
#include "TH1I.h"
#include "Buffering/EconSim.hh"
class EconAna {
public:
EconAna(const EconSim &e, unsigned nHistory=100000) :
fEconSim(e) {
std::ostringstream sout;
sout << "EconAna" << std::setw(2) << std::setfill('0')
<< fEconSim.econNumber();
std::string sHgcroc[18]={"00","01","02","03","04","05","06","07","08",
"09","10","11","12","13","14","15","16","17"};
hMapWordsVsChannels=new TH1I((sout.str()+"MapWordsVsChannels").c_str(),
";Number of channels per HGCROC packet;Number of words per HGCROC packet",73,0,73);
hLabelWordsVsChannels=new TH1I((sout.str()+"LabelWordsVsChannels").c_str(),
";Number of channels per HGCROC packet;Number of words per HGCROC packet",73,0,73);
hTotalWords=new TH1D((sout.str()+"TotalWords").c_str(),
";Total number of words",1000,0,1000);
hEventBufferUsed=new TH1D((sout.str()+"EventBufferUsed").c_str(),
";Number of event buffer words used",10000,0,10000);
hEventBufferUsedHistory=new TH1I((sout.str()+"EventBufferUsedHistory").c_str(),
";BX;Number of event buffer words used",nHistory,0,nHistory);
for(unsigned c(0);c<=72;c++) {
hMapWordsVsChannels->Fill(c,fEconSim.channelsToWords(c,true));
hLabelWordsVsChannels->Fill(c,fEconSim.channelsToWords(c,false));
}
for(unsigned h(0);h<18;h++) {
hChannels[h]=new TH1D((sout.str()+"Hgcroc"+sHgcroc[h]+"Channels").c_str(),
";Number of channels per HGCROC packet",73,0,73);
hWords[h]=new TH1D((sout.str()+"Hgcroc"+sHgcroc[h]+"Words").c_str(),
";Number of words per HGCROC packet",60,0,60);
hWordsVsChannels[h]=new TH2D((sout.str()+"Hgcroc"+sHgcroc[h]+"WordsVsChannels").c_str(),
";Number of channels per HGCROC packet;Number of words per HGCROC packet",73,0,73,60,0,60);
}
}
void analyseZs(uint64_t bx) {
unsigned nWords(0);
for(unsigned h(0);h<18;h++) {
hChannels[h]->Fill(fEconSim.numberOfChannels(h));
hWords[h]->Fill(fEconSim.numberOfWords(h));
hWordsVsChannels[h]->Fill(fEconSim.numberOfChannels(h),fEconSim.numberOfWords(h));
nWords+=fEconSim.numberOfWords(h);
}
hTotalWords->Fill(nWords);
}
void analyseBx(uint64_t bx) {
hEventBufferUsed->Fill(fEconSim.fEventBuffer.used());
hEventBufferUsedHistory->Fill(bx,fEconSim.fEventBuffer.used());
}
private:
const EconSim &fEconSim;
TH1I *hMapWordsVsChannels;
TH1I *hLabelWordsVsChannels;
TH1D *hChannels[18];
TH1D *hWords[18];
TH2D *hWordsVsChannels[18];
TH1D *hTotalWords;
TH1D *hEventBufferUsed;
TH1I *hEventBufferUsedHistory;
};
#endif
#ifndef EconSim_HH
#define EconSim_HH
// DO BINOMIAL, FLAT, CONSTANT RANDOM METHODS
#include <iostream>
#include <iomanip>
#include <cassert>
#include "Buffering/HgcrocBoe.hh"
class EconSim {
friend class EconAna;
public:
enum DataFormatMethod {
FixedChannelMap,
FixedChannelLabels,
FixedMixture,
VariableMixture
};
enum DataFlowMethod {
FixedHgcrocMap,
VariableHgcrocMap,
EventBuild
};
EconSim(unsigned e, unsigned h=18, unsigned m=0) : fEcon(e), fHgcroc(h) {
if(fPrintLevel>0) {
std::cout << "EconSim::ctor(" << e << "," << h << "," << m << ") "
<< "Entered" << std::endl;
}
assert(fHgcroc<=18);
setFormatBreakEven();
fActiveBuffer=0;
fReadHgcroc=18;
fReadWord=0xffffffff;
fWriteElink=0;
// Random values for now
/*
for(unsigned h(0);h<fHgcroc;h++) {
fMean[h]=0.5*h+1;
fHgcrocToElink[h]=(h%7);
}
*/
for(unsigned h(0);h<18;h++) {
fFirstBuffer[0][h].resize(channelsToWords(72,false));
fFirstBuffer[1][h].resize(channelsToWords(72,false));
fMean[h]=0.0;
}
for(unsigned h(0);h<fHgcroc;h++) {
if(m==0) {
fMean[h]=10;
if(h<14) fMean[h]=20;
if(h< 7) fMean[h]=35;
}
if(m==1) {
fMean[h]=5;
if(h<14) fMean[h]=10;
if(h< 7) fMean[h]=15;
}
if(m==2) {
fMean[h]=3;
if(h<14) fMean[h]=7;
if(h< 7) fMean[h]=10;
}
if(m==3) {
fMean[h]=2;
if(h<14) fMean[h]=4;
if(h< 7) fMean[h]=5;
}
if(m>=4) {
fMean[h]=1;
if(h<14) fMean[h]=2;
if(h< 7) fMean[h]=3;
}
fHgcrocToElink[h]=(h%7);
}
std::cout << std::endl << "Econ::ctor() number of HGCROCs = "
<< fHgcroc << std::endl;
double elinkNum[7]={0,0,0,0,0,0,0};
double elinkMean[7]={0,0,0,0,0,0,0};
for(unsigned h(0);h<fHgcroc;h++) {
std::cout << " HGCROC " << std::setw(2) << h
<< ", average number of channels = " << fMean[h]
<< ", assigned to Elink = " << fHgcrocToElink[h] << std::endl;
elinkNum[fHgcrocToElink[h]]++;
elinkMean[fHgcrocToElink[h]]+=fMean[h];
}
fTotalNum=0;
fTotalMean=0;
for(unsigned e(0);e<7;e++) {
fTotalNum+=elinkNum[e];
fTotalMean+=elinkMean[e];
std::cout << " Elink " << e << ", number of HGCROCs = " << elinkNum[e]
<< ", total average number of channels = "
<< elinkMean[e] << ", average number of 32-bit words = "
<< 3*elinkNum[e]+0.5*elinkMean[e]
<< std::endl;
}
fTotalWords=3*fTotalNum+0.5*fTotalMean;
std::cout << " ECON, total average number of channels = "
<< fTotalMean << ", average number of 32-bit words = "
<< fTotalWords
<< std::endl;
}
double mean(unsigned h) {
assert(h<18);
return fMean[h];
}
void processZs(uint8_t bx, uint8_t l1a, bool randomChannels=true) {
if(fPrintLevel>3) {
std::cout << "EconSim" << fEcon << "::processZs(" << unsigned(bx)
<< "," << unsigned(l1a) << ","
<< (randomChannels?"true":"false") << ") "
<< "Entered" << std::endl;
}
TRandom &random(Random::random());
for(unsigned h(0);h<fHgcroc;h++) {
if(randomChannels) fNumberOfChannels[h]=random.Binomial(72,fMean[h]/72.0);
else fNumberOfChannels[h]=unsigned(fMean[h]+0.5);
if(fDataFormatMethod==FixedChannelMap) {
fNumberOfWords[h]=channelsToWords(fNumberOfChannels[h],true);
} else if(fDataFormatMethod==FixedChannelLabels) {
fNumberOfWords[h]=channelsToWords(fNumberOfChannels[h],false);
} else if(fDataFormatMethod==FixedMixture) {
fNumberOfWords[h]=channelsToWords(fNumberOfChannels[h],fMean[h]>fFormatBreakEven);
} else if(fDataFormatMethod==VariableMixture) {
fNumberOfWords[h]=channelsToWords(fNumberOfChannels[h],fNumberOfChannels[h]>fFormatBreakEven);
} else {
assert(false);
}
if(fPrintLevel>4) {
std::cout << "EconSim" << fEcon << "::processZs(" << unsigned(bx)
<< "," << unsigned(l1a) << ","
<< (randomChannels?"true":"false") << ") "
<< "Hgcroc " << h << ", number of channels = "
<< fNumberOfChannels[h] << ", words = "
<< fNumberOfWords[h] << std::endl;
}
HgcrocBoe hboe(fEcon,h,bx,l1a,fNumberOfWords[h]);
assert((fActiveBuffer&0xff)==l1a);
fFirstBuffer[0][h][0]=hboe.word();
//assert(fElink[fHgcrocToElink[h]].writeAndIncrementPtr(hboe.word()));
if(fPrintLevel>4) {
std::cout << "EconSim" << fEcon << "::processZs(" << unsigned(bx)
<< "," << unsigned(l1a) << ","
<< (randomChannels?"true":"false") << ") "
<< "Hgcroc " << h << " BOE written" << std::endl;
hboe.print();
}
for(unsigned i(1);i<fNumberOfWords[h];i++) {
fFirstBuffer[0][h][i]=(l1a<<24)+i;
//assert(fElink[fHgcrocToElink[h]].writeAndIncrementPtr(i));
}
// Add zero padding word if odd
//if((nWords%2)==1) assert(fElink[fHgcrocToElink[h]].writeAndIncrementPtr(0));
}
fReadHgcroc=0;
fReadWord=0;
fActiveBuffer++;
}
void processBx(uint32_t *a) {
// SWITCH DEPENDING ON DATAFLOWMETHOD
if(fDataFlowMethod==FixedHgcrocMap) {
} else if(fDataFlowMethod==VariableHgcrocMap) {
} else if(fDataFlowMethod==EventBuild) {
if(fPrintLevel>3) {
std::cout << "EconSim" << fEcon << "::processBx() "
<< "Data flow method = event build, reading HGCROC "
<< fReadHgcroc << ", word " << fReadWord << std::endl;
}
for(unsigned w(0);w<24 && fReadHgcroc<fHgcroc;) {
for(;fReadWord<fNumberOfWords[fReadHgcroc] && w<24;fReadWord++) {
if(fPrintLevel>4) {
std::cout << "EconSim" << fEcon << "::processBx() "
<< "Writing word " << w << " from HGCROC " << fReadHgcroc
<< ", word " << fReadWord
<< " of " << fNumberOfWords[fReadHgcroc] << " = "
<< std::hex << fFirstBuffer[0][fReadHgcroc][fReadWord]
<< std::dec << std::endl;
}
assert(fEventBuffer.writeAndIncrementPtr(fFirstBuffer[0][fReadHgcroc][fReadWord]));
w++;
}
if(fReadWord==fNumberOfWords[fReadHgcroc]) {
fReadWord=0;
fReadHgcroc++;
}
}
uint64_t d;
for(unsigned e(0);e<7;e++) {
if(fEventBuffer.readAndIncrementPtr(d)) a[e]=(d&0xffffffff);
else a[e]=0;
if(fPrintLevel>4) {
std::cout << "EconSim" << fEcon << "::processBx() "
<< "Reading eLink " << e << " = "
<< std::hex << a[e]
<< std::dec << std::endl;
}
}
} else {
assert(false);
}
/*
if(nReadHgcroc<18) {
//for(unsigned n
assert(fElink[fWriteElink].writeAndIncrementPtr(fFirstBuffer[fActiveBuffer%2][fReadHgcroc][fReadWord]));
}
}
// Copy data from first buffers to FIFO
// assert(fElink[fHgcrocToElink[h]].writeAndIncrementPtr(fFirstBuffer[fActiveBuffer%2][h][n]));
*/
/*
uint64_t d;
for(unsigned e(0);e<7;e++) {
if(fElink[e].readAndIncrementPtr(d)) a[e]=(d&0xffffffff);
else a[e]=0;
}
*/
}
unsigned nHgcroc() const {
return fHgcroc;
}
unsigned space(unsigned elink) {
assert(elink<7);
return fElink[elink].space();
}
unsigned used(unsigned elink) {
assert(elink<7);
return fElink[elink].used();
}
unsigned numberOfChannels(unsigned h) const {
assert(h<18);
return fNumberOfChannels[h];
}
unsigned numberOfWords(unsigned h) const {
assert(h<18);
return fNumberOfWords[h];
}
void reset() {
for(unsigned e(0);e<7;e++) {
fElink[e].reset();
}
}
static unsigned channelsToWords(unsigned c, bool map) {
if(map) return 3+(c+1)/2;
else return 1+3*(c+1)/4;
}
/*
unsigned channelsToWords(unsigned c, double m) const {
if(fDataFormatMethod==FixedChannelMap) {
return channelsToWords(c,true);
} else if(fDataFormatMethod==FixedChannelLabels) {
return channelsToWords(c,false);
} else if(fDataFormatMethod==FixedMixture) {
return channelsToWords(c,m>fFormatBreakEven);
} else if(fDataFormatMethod==VariableMixture) {
return channelsToWords(c,c>fFormatBreakEven);
} else {
assert(false);
}
return -1;
}
*/
static void setFormatBreakEven() {
if(fFormatBreakEven==0) {
if(fPrintLevel>1) {
std::cout << "EconSim::setFormatBreakEven() "
<< "Entered" << std::endl;
}
unsigned wMap,wLabel;
for(unsigned c(0);c<72;c++) {
wMap=channelsToWords(c,true);
wLabel=channelsToWords(c,false);
if(fPrintLevel>1) {
std::cout << "EconSim::setFormatBreakEven() "
<< "Channels = " << c << ", map words = "
<< wMap << ", label words = " << wLabel
<< std::endl;
}
if(wLabel<=wMap) fFormatBreakEven=c;
else break;
}
if(fPrintLevel>0) {
std::cout << "EconSim::setFormatBreakEvent() "
<< "Break-even channel number = " << fFormatBreakEven
<< std::endl;
}
}
}
unsigned econNumber() const {
return fEcon;
}
public:
static unsigned fPrintLevel;
static DataFormatMethod fDataFormatMethod;
static DataFlowMethod fDataFlowMethod;
static unsigned fFormatBreakEven;
double fTotalNum;
double fTotalMean;
double fTotalWords;
protected:
private:
const unsigned fEcon;
const unsigned fHgcroc;
double fMean[18];
unsigned fHgcrocToElink[18];
CircularBuffer<1> fElink[7];
CircularBuffer<16> fEventBuffer;
unsigned fNumberOfChannels[18];
unsigned fNumberOfWords[18];
unsigned fReadHgcroc;
unsigned fReadWord;
unsigned fWriteElink;
unsigned fActiveBuffer;
std::vector<uint32_t> fFirstBuffer[2][18];
};
unsigned EconSim::fPrintLevel(1);
EconSim::DataFormatMethod EconSim::fDataFormatMethod(EconSim::FixedChannelMap);
EconSim::DataFlowMethod EconSim::fDataFlowMethod(EconSim::FixedHgcrocMap);
unsigned EconSim::fFormatBreakEven(0);
#endif
#ifndef HgcrocAna_HH
#define HgcrocAna_HH
#include <iostream>
#include <iomanip>
#include <cassert>
#include "TH1D.h"
#include "TH1I.h"
#include "Buffering/HgcrocSim.hh"
class HgcrocAna {
public:
HgcrocAna(const HgcrocSim &h, unsigned nHistory=100000) :
fHgcrocSim(h), fBusyLength(0) {
unsigned bd(fHgcrocSim.bufferDepth());
std::string sName("HgcrocAna");
hEvents=new TH1D((sName+"Events").c_str(),
";Number of events in buffer;BXs",bd,0,bd);
hL1AEvents=new TH1D((sName+"L1AEvents").c_str(),
";Number of events in buffer;L1Accepts",bd,0,bd);
hBusyLength=new TH1D((sName+"BusyLength").c_str(),
";Length of continuous output (Events);Number",1000,0,1000);
hL1AcceptHistory=new TH1I((sName+"L1AcceptHistory").c_str(),
";BX;L1Accept",nHistory,0,nHistory);
hEventCompleteHistory=new TH1I((sName+"EventCompleteHistory").c_str(),
";BX;Event complete",nHistory,0,nHistory);