11 #include "trg/cdc/modules/houghtracking/xsi_loader.h"
13 #include <trg/cdc/modules/houghtracking/CDCTrigger2DFinderFirmwareModule.h>
14 #include <trg/cdc/Cosim.h>
15 #include <trg/cdc/CDCTrigger.h>
16 #include <framework/datastore/StoreArray.h>
17 #include <framework/logging/Logger.h>
18 #include <trg/cdc/dataobjects/CDCTriggerSegmentHit.h>
19 #include <trg/cdc/dataobjects/CDCTriggerTrack.h>
20 #include <trg/cdc/dataobjects/Bitstream.h>
30 #include <experimental/array>
32 using std::experimental::to_array;
33 constexpr
double pi() {
return std::atan(1) * 4; }
35 int Xsi::Loader::get_port_number_or_exit(std::string name)
37 int portNumber = get_port_number(name.c_str());
39 std::cerr <<
"ERROR: " << name <<
" not found" << std::endl;
47 using namespace Cosim;
49 using namespace CDCTrigger;
59 setDescription(
"Firmware simulation of Hough tracking algorithm for CDC trigger.");
62 addParam(
"hitCollectionName", m_hitCollectionName,
63 "Name of the input StoreArray of CDCTriggerSegmentHits.",
65 addParam(
"outputCollectionName", m_outputCollectionName,
66 "Name of the StoreArray holding the tracks found in the Hough tracking.",
67 string(
"TRGCDC2DFinderFirmwareTracks"));
68 addParam(
"bitstreamNameTo2D", m_bitstreamNameTo2D,
69 "Name of the StoreArray holding the raw bit content to 2D trackers",
70 string(
"BitstreamTSF-2D"));
71 addParam(
"fromFastSim", m_fromFastSim,
72 "flag to read TS hits from the output of TSF firmware simulation",
74 addParam(
"nClocks", m_nClockPerEvent,
75 "how many clocks to simulate in each event",
80 CDCTrigger2DFinderFirmwareModule::~CDCTrigger2DFinderFirmwareModule()
83 Xsi_Instance->close();
89 void CDCTrigger2DFinderFirmwareModule::initialize()
91 Xsi_Instance =
new Xsi::Loader(design_libname, simengine_libname);
96 tracks.registerInDataStore();
97 tracks.registerRelationTo(segmentHits);
99 m_debugLevel = getLogConfig().getDebugLevel();
100 std::cout <<
"Design DLL : " << design_libname << std::endl;
101 std::cout <<
"Sim Engine DLL : " << simengine_libname << std::endl;
103 memset(&info, 0,
sizeof(info));
104 char logName[] =
"firmware.log";
106 info.logFileName = logName;
107 char wdbName[] =
"test.wdb";
108 info.wdbFileName = wdbName;
109 Xsi_Instance->open(&info);
110 Xsi_Instance->trace_all();
112 clk = Xsi_Instance->get_port_number_or_exit(
"Top_clkData_s");
113 for (
int iSL = 0; iSL < 5; ++iSL) {
114 string name =
"TSF" + to_string(iSL * 2) +
"_input_i";
115 tsfPort[iSL] = Xsi_Instance->get_port_number_or_exit(name);
117 Xsi_Instance->put_value(tsfPort[iSL], tsfInput[iSL].data());
119 out = Xsi_Instance->get_port_number_or_exit(
"Main_out");
122 Xsi_Instance->put_value(clk, &
zero_val);
123 Xsi_Instance->run(10);
124 }
catch (std::exception& e) {
125 std::cerr <<
"ERROR: An exception occurred: " << e.what() << std::endl;
127 std::cerr <<
"ERROR: An unknown exception occurred." << std::endl;
133 int CDCTrigger2DFinderFirmwareModule::localSegmentID(
int globalID)
135 std::array<int, 9> nWiresPerLayer = {160, 160, 192, 224, 256, 288, 320, 352, 384};
137 std::array<int, 10> nAccumulate;
138 std::partial_sum(nWiresPerLayer.begin(), nWiresPerLayer.end(), nAccumulate.begin() + 1);
140 if (globalID > nAccumulate[7]) {
143 auto nWiresInside = std::lower_bound(nAccumulate.begin(), nAccumulate.end(), globalID) - 1;
144 return globalID - *nWiresInside;
149 bitset<8> id(localSegmentID(hit->getSegmentID()));
150 bitset<9> priorityTime(hit->priorityTime());
151 bitset<2> LR(hit->getLeftRight());
152 bitset<2> priorityPosition(hit->getPriorityPosition());
153 string joined =
id.to_string() + priorityTime.to_string() +
154 LR.to_string() + priorityPosition.to_string();
155 bitset<m_tsVectorWidth> tsInfo(joined);
156 B2DEBUG(10,
"encoded ts hit: " << tsInfo <<
" with local ID " << localSegmentID(hit->getSegmentID()));
160 auto CDCTrigger2DFinderFirmwareModule::toTSSLV(
const std::bitset<m_tsVectorWidth> ts)
162 std::string word = ts.to_string();
163 std::array<char, m_tsVectorWidth> vec;
164 for (
unsigned i = 0; i < word.size(); ++i) {
172 constexpr
unsigned lenCharge = 2;
173 constexpr
unsigned lenOmega = 7;
174 constexpr
unsigned lenPhi0 = 7;
175 constexpr
unsigned lenTS = 21;
176 constexpr array<unsigned, 3> trackLens = {lenCharge, lenOmega, lenPhi0};
177 array<unsigned, 4> trackPos{ 0 };
178 partial_sum(trackLens.begin(), trackLens.end(), trackPos.begin() + 1);
179 const unsigned shift = 16 - lenOmega;
181 bitset<trackLens[1]> omega(trackIn.substr(trackPos[1], trackLens[1]));
184 int omegaFirm = (int16_t (omega.to_ulong() << shift)) >> shift;
185 trackOut.
omega = 29.97 * 1.5e-4 * omegaFirm;
186 int phi0 = bitset<trackLens[2]>(trackIn.substr(trackPos[2], trackLens[2])).to_ulong();
187 trackOut.
phi0 = pi() / 4 + pi() / 2 / 80 * (phi0 + 1);
188 for (
unsigned i = 0; i < 5; ++i) {
189 trackOut.
ts[i] = decodeTSHit(trackIn.substr(trackPos.back() + i * lenTS, lenTS));
194 void CDCTrigger2DFinderFirmwareModule::decodeOutput(
short latency)
196 const unsigned lenTrack = 121;
197 array<int, 4> posTrack;
198 for (
unsigned i = 0; i < posTrack.size(); ++i) {
199 posTrack[i] = 6 + lenTrack * i;
203 for (
unsigned i = 0; i < m_nOutTracksPerClock; ++i) {
204 if (finderOutput[i] ==
one_val) {
205 TRGFinderTrack trk = decodeTrack(strOutput.substr(posTrack[i], lenTrack));
207 storeTracks.appendNew(trk.
phi0, trk.
omega, 0., latency);
210 B2DEBUG(10,
"phi0:" << trk.
phi0 <<
", omega:" << trk.
omega
211 <<
", at clock " << latency);
216 void CDCTrigger2DFinderFirmwareModule::loadFromFirmware(
int iclock)
218 static constexpr
int inWidth = 429;
221 static constexpr
int nTSFs = 5;
222 using localInputVector = std::array<char, inWidth>;
223 using inputArray = std::array<localInputVector, nTrackers>;
224 using signalBus = std::array<inputArray, nTSFs>;
229 for (
const auto& sl : bitsTo2D[iclock]->signal()) {
231 std::copy(sl[0].cbegin(), sl[0].cbegin() + width_in, tsfInput[iAx].begin());
235 for (
auto& sl : tsfInput) {
241 void CDCTrigger2DFinderFirmwareModule::initializeFastSim()
245 B2DEBUG(10, tsHits.
getEntries() <<
" hits in this event");
249 std::vector<int> iHit;
250 for (
int i = 0; i < tsHits.
getEntries(); ++i) {
251 if (tsHits[i]->getISuperLayer() % 2 == 0) {
255 std::sort(iHit.begin(), iHit.end(), [tsHits](
int i,
int j) {
256 return tsHits[i]->foundTime() < tsHits[j]->foundTime();
259 for (
auto hit : iHit) {
260 B2DEBUG(10,
"sorted found time: " << tsHits[hit]->foundTime());
263 const int clockPeriod = 16;
267 int nClocks = tsHits[iHit.back()]->foundTime() / clockPeriod;
269 vector<vector<int> > seqHit(nClocks);
270 auto itrHit = iHit.begin();
272 for (
int i = 0; i < nClocks; ++i) {
273 if (tsHits[*itrHit]->foundTime() < 0) {
274 B2WARNING(
"Negative found time! The clock assignment will be wrong.");
277 while (tsHits[*itrHit]->foundTime() < (i + 1) * clockPeriod &&
278 itrHit != iHit.
end()) {
279 seqHit[i].push_back(*itrHit);
282 if (seqHit[i].size() > m_nInTSPerClock) {
283 B2WARNING(
"Oops! Too many input hits in a clock!");
287 m_tsHitVector.clear();
288 m_tsHitVector.resize(nClocks);
291 for (
unsigned iClock = 0; iClock < seqHit.size(); ++iClock) {
292 for (
auto iTS : seqHit[iClock]) {
293 B2DEBUG(10,
"encoding ts ID: " << tsHits[iTS]->getSegmentID() <<
294 ", SL " << tsHits[iTS]->getISuperLayer() <<
297 bitset<m_tsVectorWidth> ts(encodeTSHit(tsHits[iTS]));
298 m_tsHitVector[iClock][tsHits[iTS]->getISuperLayer() / 2].push_back(ts);
304 void CDCTrigger2DFinderFirmwareModule::loadFromFastSim(
unsigned iclock)
306 for (
unsigned iSL = 0; iSL < nAxialSuperLayer; ++iSL) {
311 auto itr = tsfInput[iSL].begin() + 9;
312 if (iclock < m_tsHitVector.size()) {
313 for (
auto ts : m_tsHitVector[iSL][iclock]) {
315 copy(inTS.begin(), inTS.end(), itr);
316 advance(itr, m_tsVectorWidth);
322 void CDCTrigger2DFinderFirmwareModule::event()
328 for (
int iClock = 0; iClock < m_nClockPerEvent; iClock++) {
330 loadFromFastSim(iClock);
332 loadFromFirmware(iClock);
334 std::cout <<
"------------------" <<
"\n";
335 std::cout <<
"clock #" << iClock <<
"\n";
339 Xsi_Instance->put_value(clk, &
one_val);
340 Xsi_Instance->run(10);
343 for (
int iAx = 0; iAx < 5; ++iAx) {
344 if (m_debugLevel >= 100 ||
345 std::any_of(tsfInput[iAx].cbegin() + 9, tsfInput[iAx].cend(), [](
char i) {
348 cout <<
"TSF" << iAx * 2 <<
" input: ";
352 Xsi_Instance->put_value(tsfPort[iAx], tsfInput[iAx].data());
355 Xsi_Instance->get_value(out, t2d_out);
358 Xsi_Instance->put_value(clk, &
zero_val);
359 Xsi_Instance->run(10);
362 if (m_debugLevel >= 100 ||
363 found.find(
"1") != std::string::npos) {
364 std::cout <<
"output: " << found <<
"\n";
365 for (
unsigned j = 0; j < count(found.begin(), found.end(),
'1'); j++) {
366 std::cout <<
display_value(t2d_out + 6 + 121 * j, 121) <<
"\n";
369 finderOutput = to_array(t2d_out);
370 decodeOutput(iClock);
371 }
catch (std::exception& e) {
372 std::cerr <<
"ERROR: An exception occurred: " << e.what() << std::endl;
375 std::cerr <<
"ERROR: An unknown exception occurred." << std::endl;
379 std::cout <<
"status code:" << status << std::endl;