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>
33using 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)",
76TSF::~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;
249using WireSet = std::vector<unsigned short>;
250using 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 {
517template<MergerOut field,
size_t w
idth>
518void TSF::pack(inputVector::reverse_iterator& input,
unsigned number,
521 std::generate(input, input + number * width, [&, n = 0]()
mutable {
528 return (get<field>(output)[i / width][i % width]) ?
one_val :
zero_val;
530 input += number * width;
535 m_bitsTo2D.appendNew(outputToTracker);
542 const int ccWidth = 9;
544 const int widenedClocks = 16;
546 const int latency = 3;
550 for (
const auto& sl : outputToTracker) {
553 std::map<unsigned, int> foundTS;
554 unsigned short iTracker = 0;
555 for (
auto& tracker : sl) {
558 for (
int i = ccWidth; i < width_out; i += tsInfoWidth) {
559 string ts = output.substr(i, tsInfoWidth);
560 tsOut decoded = decodeTSHit(ts);
562 if (decoded[3] == 0) {
565 const unsigned nCellsInSL = nAxialMergers[iAx] * nCellsInLayer;
567 unsigned iTS = decoded[0] + nCellsInSL * iTracker / nTrackers;
569 if (iTS >= nCellsInSL) {
580 int firstClock = iclock - widenedClocks - latency;
581 if (firstClock < 0) {
584 int lastClock = iclock - latency;
585 B2DEBUG(10,
"iAx:" << iAx <<
", iTS:" << iTS <<
", iTracker: " << iTracker);
587 for (
int iclkPri = firstClock; iclkPri < lastClock; ++iclkPri) {
589 auto priMap = m_priorityHit[iclkPri][2 * iAx][iTS / nSegmentsInMerger];
590 unsigned itsInMerger = iTS % nSegmentsInMerger;
593 if (priMap.find(itsInMerger) != priMap.end() &&
594 toPriority(decoded[3]) == priority(priMap[itsInMerger])) {
595 iHit = priMap[itsInMerger];
596 B2DEBUG(10,
"iHit:" << iHit);
597 B2DEBUG(10,
"TDC: " << m_cdcHits[iHit]->getTDCCount() <<
", TSF: " << decoded[1]);
605 if (foundTS.find(iTS) != foundTS.end()) {
606 if (iHit != foundTS[iTS]) {
607 B2WARNING(
"Same TS ID exists, but they point to different CDC hit");
611 foundTS.insert({iTS, iHit});
613 B2WARNING(
"No corresponding priority CDC hit can be found.");
614 B2WARNING(
"Maybe the latency and number of widened clocks are wrong.");
616 B2DEBUG(20,
"priority " << decoded[3]);
617 for (
int iclkPri = 0; iclkPri < m_nClockPerEvent; ++iclkPri) {
618 auto priMap = m_priorityHit[iclkPri][2 * iAx][iTS / 16];
619 for (
auto& m : priMap) {
620 B2DEBUG(20,
"iWire: " << m.first <<
", iLayer: " <<
621 m_cdcHits[m.second]->getILayer() <<
", iClock: " << iclkPri);
625 B2WARNING(
"It could be the left over TS hits from the last event.\n" <<
626 "Try increasing m_nClockPerEvent");
629 CDCHit cdchit = (iHit < 0) ?
CDCHit() : *m_cdcHits[iHit];
630 m_tsHits.appendNew(cdchit,
631 globalSegmentID(iTS, 2 * iAx),
654 for (
unsigned iAx = 0; iAx < m_nSubModules; ++iAx) {
657 for (
int iClock = 0; iClock < m_nClockPerEvent; iClock++) {
658 B2INFO(
string(15,
'=') <<
" clock #" << iClock <<
" " <<
string(15,
'='));
659 if (iClock == m_nClockPerEvent - 1) {
660 cout <<
"Accumulative hitmap:" <<
"\n";
662 simulateMerger(iClock);
666 for (
const auto& sl : inputToTSF) {
668 for (
const auto& mergerOut : sl) {
669 if (std::any_of(mergerOut.begin(), mergerOut.end(), [](
char i) {
670 return i != zero_val;
672 cout <<
"Merger " << iSL * 2 <<
"-" << iMerger / 2 <<
" u" << iMerger % 2 <<
": ";
676 if (iClock == m_nClockPerEvent - 1) {
677 auto accuOut = dataAcrossClocks[2 * iSL][iMerger];
678 if (get<MergerOut::hitmap>(accuOut)[0].any()) {
679 cout <<
"Merger " << iSL * 2 <<
"-" << iMerger / 2 <<
" u" << iMerger % 2 <<
": ";
680 cout << get<MergerOut::hitmap>(accuOut)[0] <<
"\n";
681 string priTime, fasTime;
682 for (
int i = 0; i < 16; ++i) {
683 priTime += get<MergerOut::priorityTime>(accuOut)[i].to_string() +
",";
684 fasTime += get<MergerOut::fastestTime>(accuOut)[i].to_string() +
",";
686 cout <<
"pritime: " << priTime <<
"\n";
687 cout <<
"fastime: " << fasTime <<
"\n";
698 auto TSF0 = getData<0>(inputToTSF);
699 auto TSF2 = getData<1>(inputToTSF);
700 auto TSF4 = getData<2>(inputToTSF);
701 auto TSF6 = getData<3>(inputToTSF);
702 auto TSF8 = getData<4>(inputToTSF);
703 array<char*, m_nSubModules> rawInputToTSF = {TSF0, TSF2, TSF4, TSF6, TSF8};
705 for (
unsigned iSL = 0; iSL < m_nSubModules; ++iSL) {
706 B2DEBUG(100,
"input to TSF" << iSL * 2 <<
": \n" <<
708 write(rawInputToTSF[iSL], stream[iSL][0]);
711 if (m_debugLevel >= 50) {
712 usleep(2000 * m_debugLevel);
714 for (
unsigned iSL = 0; iSL < m_nSubModules; ++iSL) {
715 B2DEBUG(50,
"Reading buffer from TSF " << iSL * 2 <<
":");
716 outputToTracker[iSL] = read(stream[iSL][1]);
717 B2DEBUG(30,
"received TSF " << iSL * 2 <<
":");
718 if (m_debugLevel >= 30) {
719 for (
const auto& out : outputToTracker[iSL]) {
724 saveFirmwareOutput();
725 saveFastOutput(iClock);
727 }
catch (std::exception& e) {
728 B2ERROR(
"ERROR: An exception occurred: " << e.what());
731 B2ERROR(
"ERROR: An unknown exception occurred.");
734 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
void display_hex(const std::array< char, N > &signal)
Display signal in hex.
std::string slv_to_bin_string(std::array< char, N > signal, bool padding=false)
Transform into string.
std::string display_value(const char *count, int size)
Display value of the signal.
const char zero_val
'0' in XSI VHDL simulation