9 #include <trg/cdc/modules/trgcdc/CDCTriggerTSFFirmwareModule.h>
10 #include <trg/cdc/CDCTrigger.h>
11 #include <trg/cdc/Cosim.h>
12 #include <framework/datastore/StoreArray.h>
13 #include <framework/datastore/StoreObjPtr.h>
14 #include <framework/dataobjects/EventMetaData.h>
15 #include <trg/cdc/dataobjects/CDCTriggerSegmentHit.h>
16 #include <cdc/dataobjects/CDCHit.h>
17 #include <framework/logging/Logger.h>
31 using namespace Cosim;
33 using namespace CDCTrigger;
52 setDescription(
"Firmware simulation of the Track Segment Finder for CDC trigger.");
56 "Name of the input StoreArray of CDCHits.",
59 "Name of the StoreArray holding the found TS hits.",
60 string(
"CDCTriggerFirmwareSegmentHits"));
62 "Name of the StoreArray holding the raw bit content to 2D trackers",
63 string(
"BitstreamTSFto2D"));
65 "Flag to only simulate merger and not TSF",
68 "Flag to run the front-end clock counter",
72 "list of flags to run each TSF firmware simulation with dummy L/R LUT (to speed up loading)",
76 TSF::~CDCTriggerTSFFirmwareModule()
81 CDCHit* hit = m_cdcHits[index];
82 int offset = (hit->getISuperLayer() == 0) ? 1 : 0;
83 switch (hit->getILayer() - 2 - offset) {
84 case 0:
return Priority::first;
85 case 1:
return Priority::second;
86 default:
return Priority::nothing;
93 fprintf(outstream,
"%s\n" , message);
100 array<char, 2048> buffer;
103 if (fgets(buffer.data(), buffer.size(), instream) == NULL) {
104 B2ERROR(
"fgets reached end unexpectedly");
108 for (
auto i2d = 0; i2d < 4; ++i2d) {
109 B2DEBUG(50,
display_value(buffer.data() + width_out * i2d, width_out));
111 auto bufferItr = buffer.cbegin();
113 for (
int iTracker = nTrackers - 1; iTracker >= 0; --iTracker) {
114 copy(bufferItr, bufferItr + width_out, output[iTracker].begin());
115 bufferItr += width_out;
122 m_cdcHits.isRequired(m_hitCollectionName);
123 m_debugLevel = getLogConfig().getDebugLevel();
128 m_bitsTo2D.registerInDataStore(m_outputBitstreamNameTo2D);
129 m_tsHits.registerInDataStore(m_outputCollectionName);
130 for (
unsigned i = 0; i < m_nSubModules; ++i) {
134 pipe(inputFileDescriptor[i].data());
135 pipe(outputFileDescriptor[i].data());
136 string str_fd[] = {to_string(inputFileDescriptor[i][0]), to_string(outputFileDescriptor[i][1])};
141 B2FATAL(
"Fork failed!");
142 }
else if (pid == (pid_t) 0) {
145 close(inputFileDescriptor[i][1]);
146 close(outputFileDescriptor[i][0]);
148 design_libname_post =
"_stub" + design_libname_post;
150 string design = design_libname_pre + to_string(i * 2) + design_libname_post;
151 string waveform = wdbName_pre + to_string(i * 2) + wdbName_post;
153 execlp(
"CDCTriggerTSFFirmwareWorker",
"CDCTriggerTSFFirmwareWorker",
154 str_fd[0].c_str(), str_fd[1].c_str(), design.c_str(), waveform.c_str(),
155 to_string(nAxialMergers[i]).c_str(),
nullptr);
156 B2FATAL(
"The firmware simulation program didn't launch!");
159 B2DEBUG(100,
"parent " << i);
162 close(inputFileDescriptor[i][0]);
163 close(outputFileDescriptor[i][1]);
165 stream[i][0] = fdopen(inputFileDescriptor[i][1],
"w");
166 stream[i][1] = fdopen(outputFileDescriptor[i][0],
"r");
168 B2DEBUG(20,
"pid for TSF" << i * 2 <<
": " << m_pid[i]);
172 B2INFO(
"It can take a while for TSF0 to load the LUT.");
173 for (
unsigned i = 0; i < m_nSubModules; ++i) {
181 B2DEBUG(10,
"Waiting for TSF firmware termination...");
182 for (
unsigned i = 0; i < m_nSubModules; ++i) {
183 close(inputFileDescriptor[i][1]);
184 close(outputFileDescriptor[i][0]);
187 for (
unsigned i = 0; i < m_nSubModules; ++i) {
194 for (
unsigned short iEdge = 0; iEdge < 5; ++iEdge) {
195 for (
const auto& cell : innerInvEdge[iEdge]) {
196 m_edge[0][cell].push_back(iEdge);
199 for (
unsigned short iEdge = 0; iEdge < 3; ++iEdge) {
200 for (
const auto& cell : outerInvEdge[iEdge]) {
201 m_edge[1][cell].push_back(iEdge);
209 static array<char, mergerWidth* nAxialMergers[iSL]> data;
213 for (
const auto& merger : input[iSL]) {
214 copy(merger.begin(), merger.end(), itr);
222 if (m_allPositiveTime) {
223 return (m_cdcHits[iFirstHit]->getTDCCount() / 2 - m_cdcHits[index]->getTDCCount() / 2);
225 short time = (m_TDCCountForT0 / 2 - m_cdcHits[index]->getTDCCount() / 2);
226 return (time < 0) ? time + (1 << 9) : time;
232 return std::bitset<4> (trgTime(index, iFirstHit) % clockPeriod);
237 const CDCHit& hit = (*m_cdcHits[index]);
238 const unsigned offset = (hit.getISuperLayer() == 0) ? 3 : 0;
239 return (hit.getILayer() - offset) * nSegmentsInMerger +
240 hit.getIWire() % nSegmentsInMerger;
245 const CDCHit& hit = (*m_cdcHits[index]);
246 return hit.getIWire() / nSegmentsInMerger;
249 using WireSet = std::vector<unsigned short>;
250 using TSMap = std::unordered_map<int, WireSet>;
254 const bool innerMost = (m_cdcHits[iHit]->getISuperLayer() == 0);
255 const unsigned short iLayer = m_cdcHits[iHit]->getILayer();
256 const unsigned short iCell = mergerCellID(iHit);
257 TSMap& tsMap = m_tsMap[
static_cast<int>(! innerMost)];
258 tsMap.reserve(nWiresInMerger);
259 if (tsMap.find(iCell) != tsMap.end()) {
265 const unsigned short distance = (innerMost) ? iLayer - 3 : abs(iLayer - 2);
266 id.resize(distance + 1);
267 std::iota(
id.begin(),
id.end(), (iCell - distance / 2) % nCellsInLayer);
268 id.erase(std::remove_if(
id.begin(),
id.end(), [](
short i) {
269 return (i < 0 || i >= nCellsInLayer);
271 tsMap.insert({iCell,
id});
283 vector<int> iAxialHit;
284 for (
int i = 0; i < m_cdcHits.getEntries(); ++i) {
286 if ((m_cdcHits[i]->getISuperLayer() != 0 && m_cdcHits[i]->getILayer() == 5) ||
287 m_cdcHits[i]->getICLayer() < 3) {
290 if (m_cdcHits[i]->getISuperLayer() % 2 == 0) {
291 iAxialHit.push_back(i);
295 std::sort(iAxialHit.begin(), iAxialHit.end(), [
this](
int i,
int j) {
296 return m_cdcHits[i]->getTDCCount() > m_cdcHits[j]->getTDCCount();
300 iAxialHitInClock.clear();
301 iAxialHitInClock.resize(1 + trgTime(iAxialHit.back(), iAxialHit.front()) / clockPeriod);
302 auto itr = iAxialHitInClock.begin();
304 for (
const auto& ihit : iAxialHit) {
305 B2DEBUG(20,
"sorted TDC count: " << m_cdcHits[ihit]->getTDCCount() <<
306 ", SL" << m_cdcHits[ihit]->getISuperLayer() <<
", layer" << m_cdcHits[ihit]->getILayer() <<
307 ", wire " << m_cdcHits[ihit]->getIWire() <<
", ihit: " << ihit);
313 while (trgTime(ihit, iAxialHit.front()) >= clockEdge * clockPeriod) {
317 itr->push_back(ihit);
319 m_iFirstHit = iAxialHit.front();
322 for (
auto& clock : m_priorityHit) {
323 for (
auto& sl : clock) {
324 for (
auto& merger : sl.second) {
333 return ! reg[field][iTS];
349 timeVec& priorityTime = (get<MergerOut::priorityTime>(mergerData))[priTS];
351 if (notHit(MergerOut::priorityTime, priTS, registeredCell)) {
352 priorityTime = hitTime;
353 registerHit(MergerOut::priorityTime, priTS, registeredCell);
354 get<MergerOut::secondPriorityHit>(mergerData)[0].set(priTS, ! lr);
355 priorityHit.insert({priTS, iHit});
357 }
else if (priority(priorityHit[priTS]) == Priority::second &&
358 hitTime.to_ulong() == priorityTime.to_ulong() && lr == 1) {
359 get<MergerOut::secondPriorityHit>(mergerData)[0].reset(priTS);
360 priorityHit[priTS] = iHit;
367 for (
auto& sl : inputToTSF) {
368 for (
auto& merger : sl) {
373 if (iClock >= iAxialHitInClock.size()) {
382 map<unsigned, mergerStruct<5> > dataInClock;
383 map<unsigned, registeredStruct> registered;
384 for (
int iAx = 0; iAx < m_nSubModules; ++iAx) {
388 auto clock = iAxialHitInClock[iClock];
391 std::stable_partition(clock.begin(), clock.end(),
392 [
this](
int hit) {return priority(hit) == Priority::first;});
393 for (
const auto& iHit : clock) {
394 const CDCHit& hit = *m_cdcHits[iHit];
395 const unsigned short iSL = hit.getISuperLayer();
396 const short outer = (iSL == 0) ? 0 : 1;
397 const unsigned short iMerger = mergerNumber(iHit);
398 const unsigned short iCell = mergerCellID(iHit);
399 const WireSet tsList = segmentID(iHit);
400 const timeVec hitTime = timeStamp(iHit, m_iFirstHit);
401 auto& mergerData = dataInClock[iSL][iMerger];
402 auto& registeredCell = registered[iSL][iMerger];
404 auto& priorityHit = m_priorityHit[iClock][iSL][iMerger];
405 B2DEBUG(50,
"iHit: " << iHit <<
", Merger" << iSL <<
"-" << iMerger <<
406 ", iCell: " << iCell);
408 get<MergerOut::hitmap>(mergerData)[0].set(iCell);
410 for (
const auto& iTS : tsList) {
411 timeVec& fastestTime = (get<MergerOut::fastestTime>(mergerData))[iTS];
413 if (notHit(MergerOut::fastestTime, iTS, registeredCell) ||
415 hitTime.to_ulong() < fastestTime.to_ulong()) {
419 fastestTime = hitTime;
420 registerHit(MergerOut::fastestTime, iTS, registeredCell);
424 if (m_edge[outer].find(iCell) != m_edge[outer].end()) {
425 for (
auto& iEdgeTime : m_edge[outer][iCell]) {
426 timeVec& edgeTime = (get<MergerOut::edgeTime>(mergerData))[iEdgeTime];
427 if (notHit(MergerOut::edgeTime, iEdgeTime, registeredCell) ||
428 hitTime.to_ulong() < edgeTime.to_ulong()) {
430 registerHit(MergerOut::edgeTime, iEdgeTime, registeredCell);
434 switch (priority(iHit)) {
435 case Priority::first: {
437 unsigned priTS = iCell % nSegmentsInMerger;
439 timeVec& priorityTime = (get<MergerOut::priorityTime>(mergerData))[priTS];
441 if (notHit(MergerOut::priorityTime, priTS, registeredCell)) {
442 priorityTime = hitTime;
443 registerHit(MergerOut::priorityTime, priTS, registeredCell);
444 get<MergerOut::secondPriorityHit>(mergerData)[0].reset(priTS);
445 priorityHit.insert({priTS, iHit});
449 case Priority::second: {
451 for (
unsigned i = 0; i < 2; ++i) {
452 unsigned priTS = iCell % nSegmentsInMerger + i;
453 if (priTS == nSegmentsInMerger) {
457 const unsigned short iMergerPlus1 = (iMerger == nMergers[iSL] - 1) ? 0 : iMerger + 1;
458 auto& nextMergerData = dataInClock[iSL][iMergerPlus1];
459 auto& nextRegisteredCell = registered[iSL][iMergerPlus1];
460 auto& nextPriorityHit = m_priorityHit[iClock][iSL][iMergerPlus1];
461 setSecondPriority(priTS, iHit, hitTime, i, nextMergerData, nextRegisteredCell, nextPriorityHit);
463 setSecondPriority(priTS, iHit, hitTime, i, mergerData, registeredCell, priorityHit);
473 for (
auto iAx = 0; iAx < m_nSubModules; ++iAx) {
474 unsigned nEdges = (iAx == 0) ? 5 : 3;
475 for (
unsigned iMerger = 0; iMerger < inputToTSF[iAx].size(); ++iMerger) {
476 auto input = inputToTSF[iAx][iMerger].rbegin();
477 auto& output = dataInClock[2 * iAx][iMerger];
478 pack<MergerOut::hitmap, 1> (input, nWiresInMerger, output);
479 pack<MergerOut::priorityTime, timeWidth> (input, nCellsInLayer, output);
480 pack<MergerOut::fastestTime, timeWidth> (input, nCellsInLayer, output);
481 pack<MergerOut::secondPriorityHit, 1> (input, nCellsInLayer, output);
482 pack<MergerOut::edgeTime, timeWidth> (input, nEdges, output);
484 auto& outputAcrossClocks = dataAcrossClocks[2 * iAx][iMerger];
485 if (get<MergerOut::hitmap>(output)[0].any()) {
486 string priTime, fasTime, edgTime;
487 for (
int i = 0; i < nSegmentsInMerger; ++i) {
488 priTime += get<MergerOut::priorityTime>(output)[i].to_string() +
",";
489 fasTime += get<MergerOut::fastestTime>(output)[i].to_string() +
",";
490 edgTime += get<MergerOut::edgeTime>(output)[i].to_string() +
",";
491 get<MergerOut::priorityTime>(outputAcrossClocks)[i] |=
492 get<MergerOut::priorityTime>(output)[i];
493 get<MergerOut::fastestTime>(outputAcrossClocks)[i] |=
494 get<MergerOut::fastestTime>(output)[i];
496 B2DEBUG(150,
"merger " << iAx * 2 <<
"-" << iMerger <<
497 "\nhitmap: " << get<MergerOut::hitmap>(output)[0] <<
498 "\nsecond hit: " << get<MergerOut::secondPriorityHit>(output)[0] <<
499 "\nprioiry Time: " << priTime <<
500 "\nfastest Time: " << fasTime <<
501 "\nedge Time: " << edgTime);
502 get<MergerOut::hitmap>(outputAcrossClocks)[0] |= get<MergerOut::hitmap>(output)[0];
506 bitset<9> cc(iClock);
507 const int nBitsReserved = (iAx == 0) ? 3 : 4;
508 generate(inputToTSF[iAx][iMerger].rend() - 9 - nBitsReserved,
509 inputToTSF[iAx][iMerger].rend() - nBitsReserved,
510 [&cc, i = 0]()
mutable {
517 template<MergerOut field,
size_t w
idth>
518 void TSF::pack(inputVector::reverse_iterator& input,
unsigned number,
521 std::generate(input, input + number * width, [&, n = 0]()
mutable {
527 return (get<field>(output)[i / width][i % width]) ?
one_val :
zero_val;}});
528 input += number * width;
533 m_bitsTo2D.appendNew(outputToTracker);
540 const int ccWidth = 9;
542 const int widenedClocks = 16;
544 const int latency = 3;
548 for (
const auto& sl : outputToTracker) {
551 std::map<unsigned, int> foundTS;
552 unsigned short iTracker = 0;
553 for (
auto& tracker : sl) {
556 for (
int i = ccWidth; i < width_out; i += tsInfoWidth) {
557 string ts = output.substr(i, tsInfoWidth);
558 tsOut decoded = decodeTSHit(ts);
560 if (decoded[3] == 0) {
563 const unsigned nCellsInSL = nAxialMergers[iAx] * nCellsInLayer;
565 unsigned iTS = decoded[0] + nCellsInSL * iTracker / nTrackers;
567 if (iTS >= nCellsInSL) {
578 int firstClock = iclock - widenedClocks - latency;
579 if (firstClock < 0) {
582 int lastClock = iclock - latency;
583 B2DEBUG(10,
"iAx:" << iAx <<
", iTS:" << iTS <<
", iTracker: " << iTracker);
585 for (
int iclkPri = firstClock; iclkPri < lastClock; ++iclkPri) {
587 auto priMap = m_priorityHit[iclkPri][2 * iAx][iTS / nSegmentsInMerger];
588 unsigned itsInMerger = iTS % nSegmentsInMerger;
591 if (priMap.find(itsInMerger) != priMap.end() &&
592 toPriority(decoded[3]) == priority(priMap[itsInMerger])) {
593 iHit = priMap[itsInMerger];
594 B2DEBUG(10,
"iHit:" << iHit);
595 B2DEBUG(10,
"TDC: " << m_cdcHits[iHit]->getTDCCount() <<
", TSF: " << decoded[1]);
603 if (foundTS.find(iTS) != foundTS.end()) {
604 if (iHit != foundTS[iTS]) {
605 B2WARNING(
"Same TS ID exists, but they point to different CDC hit");
609 foundTS.insert({iTS, iHit});
611 B2WARNING(
"No corresponding priority CDC hit can be found.");
612 B2WARNING(
"Maybe the latency and number of widened clocks are wrong.");
614 B2DEBUG(20,
"priority " << decoded[3]);
615 for (
int iclkPri = 0; iclkPri < m_nClockPerEvent; ++iclkPri) {
616 auto priMap = m_priorityHit[iclkPri][2 * iAx][iTS / 16];
617 for (
auto& m : priMap) {
618 B2DEBUG(20,
"iWire: " << m.first <<
", iLayer: " <<
619 m_cdcHits[m.second]->getILayer() <<
", iClock: " << iclkPri);
623 B2WARNING(
"It could be the left over TS hits from the last event.\n" <<
624 "Try increasing m_nClockPerEvent");
627 CDCHit cdchit = (iHit < 0) ?
CDCHit() : *m_cdcHits[iHit];
628 m_tsHits.appendNew(cdchit,
629 globalSegmentID(iTS, 2 * iAx),
652 for (
unsigned iAx = 0; iAx < m_nSubModules; ++iAx) {
655 for (
int iClock = 0; iClock < m_nClockPerEvent; iClock++) {
656 B2INFO(
string(15,
'=') <<
" clock #" << iClock <<
" " <<
string(15,
'='));
657 if (iClock == m_nClockPerEvent - 1) {
658 cout <<
"Accumulative hitmap:" <<
"\n";
660 simulateMerger(iClock);
664 for (
const auto& sl : inputToTSF) {
666 for (
const auto& mergerOut : sl) {
667 if (std::any_of(mergerOut.begin(), mergerOut.end(), [](
char i) {
668 return i != zero_val;
670 cout <<
"Merger " << iSL * 2 <<
"-" << iMerger / 2 <<
" u" << iMerger % 2 <<
": ";
674 if (iClock == m_nClockPerEvent - 1) {
675 auto accuOut = dataAcrossClocks[2 * iSL][iMerger];
676 if (get<MergerOut::hitmap>(accuOut)[0].any()) {
677 cout <<
"Merger " << iSL * 2 <<
"-" << iMerger / 2 <<
" u" << iMerger % 2 <<
": ";
678 cout << get<MergerOut::hitmap>(accuOut)[0] <<
"\n";
679 string priTime, fasTime;
680 for (
int i = 0; i < 16; ++i) {
681 priTime += get<MergerOut::priorityTime>(accuOut)[i].to_string() +
",";
682 fasTime += get<MergerOut::fastestTime>(accuOut)[i].to_string() +
",";
684 cout <<
"pritime: " << priTime <<
"\n";
685 cout <<
"fastime: " << fasTime <<
"\n";
696 auto TSF0 = getData<0>(inputToTSF);
697 auto TSF2 = getData<1>(inputToTSF);
698 auto TSF4 = getData<2>(inputToTSF);
699 auto TSF6 = getData<3>(inputToTSF);
700 auto TSF8 = getData<4>(inputToTSF);
701 array<char*, m_nSubModules> rawInputToTSF = {TSF0, TSF2, TSF4, TSF6, TSF8};
703 for (
unsigned iSL = 0; iSL < m_nSubModules; ++iSL) {
704 B2DEBUG(100,
"input to TSF" << iSL * 2 <<
": \n" <<
706 write(rawInputToTSF[iSL], stream[iSL][0]);
709 if (m_debugLevel >= 50) {
710 usleep(2000 * m_debugLevel);
712 for (
unsigned iSL = 0; iSL < m_nSubModules; ++iSL) {
713 B2DEBUG(50,
"Reading buffer from TSF " << iSL * 2 <<
":");
714 outputToTracker[iSL] = read(stream[iSL][1]);
715 B2DEBUG(30,
"received TSF " << iSL * 2 <<
":");
716 if (m_debugLevel >= 30) {
717 for (
const auto& out : outputToTracker[iSL]) {
722 saveFirmwareOutput();
723 saveFastOutput(iClock);
725 }
catch (std::exception& e) {
726 B2ERROR(
"ERROR: An exception occurred: " << e.what());
729 B2ERROR(
"ERROR: An unknown exception occurred.");
732 B2DEBUG(50,
"status code:" << status);
Class containing the result of the unpacker in raw data and the result of the digitizer in simulation...
This class is the interface between TSim/basf2 TSF module and the firmware simulation core of XSim/IS...
std::vector< mergerStructElement< nEdges > > mergerStruct
data structure to hold merger output
void initializeMerger()
Get CDC hits from the DataStore and distribute them to clocks.
static constexpr std::array< int, 9 > nMergers
number of mergers in each super layer
void computeEdges()
Compute the map from merger cell ID to all its related edge fields.
bool m_simulateCC
flag to simulate front-end clock counter
void saveFirmwareOutput()
save firmware output
unsigned short trgTime(int index, int iFirstHit)
Get the trigger time of the CDC hit.
std::bitset< 4 > timeStamp(int index, int iFirstHit)
Get the trigger time stamp of a hit.
outputArray read(FILE *instream)
write TSF output signals from the worker
std::tuple< std::array< timeVec, nSegmentsInMerger >, std::array< timeVec, nSegmentsInMerger >, std::array< timeVec, nEdges >, std::array< std::bitset< nWiresInMerger >, 1 >, std::array< std::bitset< nSegmentsInMerger >, 1 > > mergerStructElement
data structure to hold merger output <priority time (4 bits x 16), fast time (4 bits x 16),...
std::vector< registeredStructElement > registeredStruct
vector of registeredStructElement
bool notHit(CDCTrigger::MergerOut field, unsigned iTS, registeredStructElement ®)
Whether a time field in a merger has been hit in the clock cycle.
priorityHitStruct m_priorityHit
list keeping the index of priority hit of a TS for making fastsim ts hit object
WireSet segmentID(int iHit)
Get the list of associated track segments with a hit.
void initialize() override
spawn child process for workers, open pipes to pass data
void pack(inputVector::reverse_iterator &rInput, unsigned number, mergerStructElement< 5 > &output)
Pack the merger output data structure to TSF input vector.
void event() override
Things to do for each event.
CDCTrigger::Priority priority(int index)
write TSF input signals to the worker
std::vector< short > WireSet
Wire set.
std::string m_outputCollectionName
Name of the StoreArray holding the found TS hits.
std::array< inputFromMerger, m_nSubModules > inputToTSFArray
input array to TSF
std::bitset< timeWidth > timeVec
element of data structure to hold merger output
std::string m_outputBitstreamNameTo2D
Name of the StoreArray holding the raw bit content to 2D trackers.
void terminate() override
close the pipes and wait for children to die.
std::array< outputVector, nTrackers > outputArray
output array
void setSecondPriority(unsigned priTS, unsigned iHit, timeVec hitTime, unsigned lr, mergerStructElement< 5 > &mergerData, registeredStructElement ®isteredCell, priorityHitInMerger &priorityHit)
set 2nd priority info
static constexpr std::array< int, m_nSubModules > nAxialMergers
number of mergers in axial super layers
CDCTriggerTSFFirmwareModule()
Constructor.
std::vector< bool > m_stubLUT
list of flags to run a TSF firmware simulation with dummy L/R LUT (to speed up loading)
char * getData(inputToTSFArray)
get the XSI compliant format from the bits format TSF input
void write(const char *message, FILE *outstream)
write TSF input signals to the worker
inputToTSFArray inputToTSF
XSI compliant format of input to TSF.
void saveFastOutput(short iclock)
save fast TSIM output
unsigned short mergerNumber(int index)
Get the merger unit ID in a super layer.
bool m_mergerOnly
flag to only simulation merger and not TSF
std::map< unsigned, mergerStruct< 5 > > dataAcrossClocks
data structure to hold merger output
void simulateMerger(unsigned iclock)
Simulate 1 clock of merger.
std::string m_hitCollectionName
Name of the StoreArray containing the input CDC hits.
std::array< std::bitset< nCellsInLayer >, 3 > registeredStructElement
record when a time slow has been registered by a hit <priority time, fast time, edge timing>
std::unordered_map< short, WireSet > TSMap
TS map.
static constexpr int m_nSubModules
number of TSF to simulate
std::vector< priorityHitInMerger > priorityHitStructInSL
priority hits map in Merger for a SL
std::map< unsigned, int > priorityHitInMerger
priority hits map in Merger
unsigned short mergerCellID(int index)
Get the cell ID in the merger.
void registerHit(CDCTrigger::MergerOut field, unsigned iTS, registeredStructElement ®)
Register the timing field so that later hits won't overwrite it.
void setDescription(const std::string &description)
Sets the description of the module.
Type-safe access to single objects in the data store.
void addParam(const std::string &name, T ¶mVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
static constexpr int mergerWidth
Merger data width.
Abstract base class for different kinds of events.
Helper class for software (C++) / firmware (VHDL) co-simulation.
const char one_val
'1' in XSI VHDL simulation
const char zero_val
'0' in XSI VHDL simulation
std::string slv_to_bin_string(std::array< char, N > signal, bool padding=false)
Transform into string.
void display_hex(const std::array< char, N > &signal)
Display signal in hex.
std::string display_value(const char *count, int size)
Display value of the signal.