LDMX Software
trackproducer_hw.cxx
1#include <stdio.h>
2
3#include <iostream>
4
5#include "TrigScint/Firmware/objdef.h"
6#include "TrigScint/Firmware/trackproducer.h"
7
8void trackproducerHw(Cluster pad1[NTRK], Cluster pad2[NCLUS],
9 Cluster pad3[NCLUS], Track outTrk[NTRK],
10 ap_int<12> lookup[NCENT][COMBO][2]) {
11#ifdef TS_NOT_EMULATION
12#pragma HLS ARRAY_PARTITION variable = pad1 dim = 0 complete
13#pragma HLS ARRAY_PARTITION variable = pad2 dim = 0 complete
14#pragma HLS ARRAY_PARTITION variable = pad3 dim = 0 complete
15#pragma HLS ARRAY_PARTITION variable = outTrk dim = 0 complete
16#pragma HLS ARRAY_PARTITION variable = lookup dim = 0 complete
17#pragma HLS PIPELINE II = 10
18#endif
19 Track test;
20#ifdef TS_NOT_EMULATION
21#pragma HLS ARRAY_PARTITION variable = test complete
22#endif
23
24 // This firmware module loops over first the pad1 seeds (NTRK) and then the
25 // patterns (COMBO) For each seed it check 9 combinations of tracks. These
26 // combinations, which depend on alignment essentially consist of the clusters
27 // that have channels immediattely above or below the pad1 cluster in the
28 // first layer, which you may observe from the LUT if you printed it. I would
29 // only need to check the pattern without all these continue statements, but
30 // the continue statements further reduce the pattern collection size by only
31 // applying certain patterns iff a secondary hit is there Thats why this looks
32 // complicated at all: the continues just include logic on whether a pattern
33 // should have a secondary hit. It also checks the track residual, only
34 // keeping one pattern for each pad1 cluster.
35 for (int i = 0; i < NTRK; i++) {
36 if (2 * pad1[i].seed_.b_id_ > 2 * NCHAN) {
37 continue;
38 }
39 for (int j = 0; j < COMBO; j++) {
40 clearTrack(test);
41 if (not(pad1[i].seed_.amp_ > 0)) {
42 continue;
43 } // Continue if.seed_.not Satisfied
44 ap_int<12> centroid = 2 * pad1[i].seed_.b_id_;
45 if (pad1[i].sec_.amp_ > 0) {
46 centroid += 1;
47 }
48 cpyCluster(test.pad1_, pad1[i]);
49 if ((lookup[centroid][j][0] == -1) or (lookup[centroid][j][1] == -1)) {
50 continue;
51 } // Pattern Empty
52 if (not(pad2[lookup[centroid][j][0] / 4].seed_.amp_ > 0)) {
53 continue;
54 } // Continue if.seed_.not Satisfied
55 if ((lookup[centroid][j][0] % 4 == 0) and
56 ((pad2[lookup[centroid][j][0] / 4].sec_.b_id_ >= 0) or
57 (pad2[lookup[centroid][j][0] / 4].seed_.b_id_ % 2 == 1))) {
58 continue;
59 } // Continue if sec_ is not Expected, and not Empty
60 if ((lookup[centroid][j][0] % 4 == 1) and
61 ((pad2[lookup[centroid][j][0] / 4].sec_.b_id_ < 0) or
62 (pad2[lookup[centroid][j][0] / 4].seed_.b_id_ % 2 == 1))) {
63 continue;
64 } // Continue if sec_ is Expected, and Empty
65 if ((lookup[centroid][j][0] % 4 == 2) and
66 ((pad2[lookup[centroid][j][0] / 4].sec_.b_id_ >= 0) or
67 (pad2[lookup[centroid][j][0] / 4].seed_.b_id_ % 2 == 0))) {
68 continue;
69 } // Continue if sec_ is not Expected, and not Empty
70 if ((lookup[centroid][j][0] % 4 == 3) and
71 ((pad2[lookup[centroid][j][0] / 4].sec_.b_id_ < 0) or
72 (pad2[lookup[centroid][j][0] / 4].seed_.b_id_ % 2 == 0))) {
73 continue;
74 } // Continue if sec_ is Expected, and Empty
75 if (not(pad3[lookup[centroid][j][1] / 4].seed_.amp_ > 0)) {
76 continue;
77 } // Continue if.seed_.not Satisfied
78 if ((lookup[centroid][j][1] % 4 == 0) and
79 ((pad3[lookup[centroid][j][1] / 4].sec_.b_id_ >= 0) or
80 (pad3[lookup[centroid][j][1] / 4].seed_.b_id_ % 2 == 1))) {
81 continue;
82 } // Continue if sec_ is not Expected, and not Empty
83 if ((lookup[centroid][j][1] % 4 == 1) and
84 ((pad3[lookup[centroid][j][1] / 4].sec_.b_id_ < 0) or
85 (pad3[lookup[centroid][j][1] / 4].seed_.b_id_ % 2 == 1))) {
86 continue;
87 } // Continue if sec_ is Expected, and Empty
88 if ((lookup[centroid][j][1] % 4 == 2) and
89 ((pad3[lookup[centroid][j][1] / 4].sec_.b_id_ >= 0) or
90 (pad3[lookup[centroid][j][1] / 4].seed_.b_id_ % 2 == 0))) {
91 continue;
92 } // Continue if sec_ is not Expected, and not Empty
93 if ((lookup[centroid][j][1] % 4 == 3) and
94 ((pad3[lookup[centroid][j][1] / 4].sec_.b_id_ < 0) or
95 (pad3[lookup[centroid][j][1] / 4].seed_.b_id_ % 2 == 0))) {
96 continue;
97 } // Continue if sec_ is Expected, and Empty
98 cpyCluster(test.pad2_, pad2[lookup[centroid][j][0] / 4]);
99 cpyCluster(test.pad3_, pad3[lookup[centroid][j][1] / 4]);
100 calcResid(test);
101 if (test.resid_ < outTrk[i].resid_) {
102 cpyTrack(outTrk[i], test);
103 }
104 } // end loop on COMBO
105 } // end loop on NTRK
106 // While we ultimately envision having the firmware do duplicate track removal
107 // in the other two layers in a separate firmware module, they are done here
108 // so as to not have track over counting and to validate the processor. Thats
109 // what occurs here below.
110 for (int i = 1; i < NTRK - 1; i++) {
111 if ((outTrk[i - 1].pad2_.seed_.b_id_ == outTrk[i].pad2_.seed_.b_id_) and
112 (outTrk[i].pad2_.seed_.b_id_ >= 0)) {
113 if (outTrk[i - 1].resid_ <= outTrk[i].resid_) {
114 clearTrack(outTrk[i]);
115 } else {
116 clearTrack(outTrk[i - 1]);
117 }
118 }
119 if ((outTrk[i].pad2_.seed_.b_id_ == outTrk[i + 1].pad2_.seed_.b_id_) and
120 (outTrk[i + 1].pad2_.seed_.b_id_ >= 0)) {
121 if (outTrk[i + 1].resid_ <= outTrk[i].resid_) {
122 clearTrack(outTrk[i]);
123 } else {
124 clearTrack(outTrk[i + 1]);
125 }
126 }
127 if ((outTrk[i - 1].pad2_.seed_.b_id_ == outTrk[i + 1].pad2_.seed_.b_id_) and
128 (outTrk[i + 1].pad2_.seed_.b_id_ >= 0)) {
129 if (outTrk[i - 1].resid_ <= outTrk[i + 1].resid_) {
130 clearTrack(outTrk[i + 1]);
131 } else {
132 clearTrack(outTrk[i - 1]);
133 }
134 }
135 } // end loop on NTRK
136 for (int i = 1; i < NTRK - 1; i++) {
137 if ((outTrk[i - 1].pad3_.seed_.b_id_ == outTrk[i].pad3_.seed_.b_id_) and
138 (outTrk[i].pad3_.seed_.b_id_ >= 0)) {
139 if (outTrk[i - 1].resid_ <= outTrk[i].resid_) {
140 clearTrack(outTrk[i]);
141 } else {
142 clearTrack(outTrk[i - 1]);
143 }
144 }
145 if ((outTrk[i].pad3_.seed_.b_id_ == outTrk[i + 1].pad3_.seed_.b_id_) and
146 (outTrk[i + 1].pad3_.seed_.b_id_ >= 0)) {
147 if (outTrk[i + 1].resid_ <= outTrk[i].resid_) {
148 clearTrack(outTrk[i]);
149 } else {
150 clearTrack(outTrk[i + 1]);
151 }
152 }
153 if ((outTrk[i - 1].pad3_.seed_.b_id_ == outTrk[i + 1].pad3_.seed_.b_id_) and
154 (outTrk[i + 1].pad3_.seed_.b_id_ >= 0)) {
155 if (outTrk[i - 1].resid_ <= outTrk[i + 1].resid_) {
156 clearTrack(outTrk[i + 1]);
157 } else {
158 clearTrack(outTrk[i - 1]);
159 }
160 }
161 } // end loop on NTRK again
162 return;
163}
Sign Arbitrary Precision Type.
Definition ap_int.h:28