ATLAS Offline Software
F600IntegrationAlg.cxx
Go to the documentation of this file.
1 /*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
7 #include "AthenaKernel/Chrono.h"
9 
11 {
12  std::string F600IntegrationAlg::get_cu_name(const std::string& kernel_name, int cu) {
13  std::string full_cu_name = kernel_name + ":{" + kernel_name + "_" + std::to_string(cu) + "}";
14  ATH_MSG_DEBUG("LOADING " + full_cu_name);
15  return full_cu_name;
16  }
17 
18  void F600IntegrationAlg::outputHexData(size_t dataLen, uint64_t *data, const std::string dataDescriptor) const {
19  ATH_MSG_DEBUG("STARTING " << dataDescriptor << " words:");
20  for (size_t i = 0; i < dataLen; i++) {
21  ATH_MSG_DEBUG(std::hex << std::setw(16) << std::setfill('0') << data[i]);
22  }
23  ATH_MSG_DEBUG("ENDING " << dataDescriptor << " words");
24  }
25 
27  {
28  ATH_MSG_INFO("Running on the FPGA accelerator");
29 
30  ATH_CHECK(m_chronoSvc.retrieve());
31 
32  {
33  Athena::Chrono chrono("Platform and device initlize", m_chronoSvc.get());
35 
36  ATH_MSG_INFO("Initializing xrt::device");
37  m_xrt_accelerator = xrt::opencl::get_xrt_device(m_accelerator.get());
38  ATH_MSG_INFO("xrt::device bdf: " + m_xrt_accelerator.get_info<xrt::info::device::bdf>() + " with name: " + m_xrt_accelerator.get_info<xrt::info::device::name>());
39  }
40 
41  {
42  Athena::Chrono chrono("CL::loadProgram", m_chronoSvc.get());
43  ATH_MSG_INFO("LOADING PROGRAM: " + m_xclbin);
45  }
46 
47  cl_int err = CL_SUCCESS;
48 
49  xrt::uuid loaded_xclbin_uuid = m_xrt_accelerator.get_xclbin_uuid();
50  int cu = 1;
51 
52  // Pixel clustering
53  m_pixelClusterL2GKernels.push_back(cl::Kernel(m_program, get_cu_name(m_pixelClusteringKernelName, cu).c_str(), &err));
54 
55  // Slicing Engine
56  for (int i = 0; i < 1; ++i) {
57  m_pixelFirstStageSlicingIPs.push_back(xrt::ip(m_xrt_accelerator, loaded_xclbin_uuid, get_cu_name(m_pixelFirstStageSlicingIPName, cu + i)));
58  m_pixelFirstStageSlicingInputKernels.push_back(cl::Kernel(m_program, get_cu_name(m_pixelFirstStageInputKernelName, cu + i).c_str(), &err));
59  m_pixelFirstStageSlicingOutputKernels.push_back(cl::Kernel(m_program, get_cu_name(m_pixelFirstStageOutputKernelName, cu + i).c_str(), &err));
60  }
61 
62  m_insideOutInputKernels.push_back(cl::Kernel(m_program, get_cu_name(m_memReadKernelName, cu).c_str(), &err));
63  m_insideOutOutputKernels.push_back(cl::Kernel(m_program, get_cu_name(m_memWriteKernelName, cu).c_str(), &err));
64 
65  m_queue = cl::CommandQueue(m_context, m_accelerator, CL_QUEUE_PROFILING_ENABLE , &err);
66 
67  if (err != CL_SUCCESS) {
68  return StatusCode::FAILURE;
69  }
70 
71  ATH_CHECK(m_xaodClusterMaker.retrieve());
72  ATH_CHECK(m_testVectorTool.retrieve());
73  ATH_CHECK(m_FPGADataFormatTool.retrieve());
76  return StatusCode::SUCCESS;
77  }
78 
79  int F600IntegrationAlg::readTVLength(std::string filepath) const {
80  int n_words;
81  int size = 0;
82  ATH_MSG_DEBUG("Reading len of: " << filepath);
83  size = std::filesystem::file_size(filepath);
84  n_words = size / (16 + 1);
85  ATH_MSG_DEBUG("Num TV words (64b): " << n_words);
86  return n_words;
87  }
88 
89  void F600IntegrationAlg::readTV(const std::string filepath, int n_words, uint64_t *data) const {
90  std::ifstream file_in;
91  std::string line_in = "";
92 
93  std::fill(data, data + n_words, 0);
94 
95  ATH_MSG_DEBUG("Reading data from file: " + filepath);
96  file_in.open(filepath);
97  if (file_in.is_open()) {
98  for(int i = 0; i < n_words; i++) {
99  std::getline (file_in, line_in);
100  data[i] = std::stoul(line_in.c_str(), NULL, 16);
101  }
102  } else {
103  ATH_MSG_INFO("ERROR! Unable to open data file: " + filepath);
104  }
105  ATH_MSG_DEBUG("Closing " << filepath);
106  file_in.close();
107  }
108 
109  StatusCode F600IntegrationAlg::execute(const EventContext &ctx) const
110  {
111  ATH_MSG_DEBUG("Executing F600IntegrationAlg");
112 
113  int n_pixel_words = readTVLength(m_pixelClusterInputPath);
114  int n_pixel_ghitz_words = readTVLength(m_pixelStageOneSlicingInputPath);
115  int n_pixel_first_sliced_words = readTVLength(m_insideOutInputPath);
116  int n_inside_out_words = 4 * 1024;
117 
118  ATH_MSG_DEBUG("Pixel Clustering TV words = " << n_pixel_words << " (64b)");
119  ATH_MSG_DEBUG("Pixel GHITZ TV words = " << n_pixel_ghitz_words << " (64b)");
120  ATH_MSG_DEBUG("Pixel Sliced TV words = " << n_pixel_first_sliced_words << " (64b)");
121 
122  uint64_t pixel_cls_input_data[n_pixel_words];
123  uint64_t pixel_ghitz_data[n_pixel_ghitz_words];
124  uint64_t pixel_first_sliced_data[n_pixel_first_sliced_words];
125 
126  readTV(m_pixelClusterInputPath, n_pixel_words, pixel_cls_input_data);
127  readTV(m_pixelStageOneSlicingInputPath, n_pixel_ghitz_words, pixel_ghitz_data);
128  readTV(m_insideOutInputPath, n_pixel_first_sliced_words, pixel_first_sliced_data);
129 
130  std::unique_lock lock(m_fpgaHandleMtx);
131 
132  cl_int err = 0;
133  size_t pixel_size_bytes = n_pixel_words * sizeof(uint64_t);
134  size_t pixel_ghitz_size_bytes = n_pixel_ghitz_words * sizeof(uint64_t);
135  size_t pixel_first_sliced_size_bytes = n_pixel_first_sliced_words * sizeof(uint64_t);
136  size_t inside_out_size_bytes = n_inside_out_words * sizeof(uint64_t);
137 
138  ATH_MSG_DEBUG("Allocating pxl cls input buffer");
139  m_pixelClusterL2GInputBufferList.push_back(cl::Buffer(m_context, CL_MEM_READ_WRITE, pixel_size_bytes, NULL, &err));
140  ATH_MSG_DEBUG("Allocating pxl cls out buffer");
141  m_pixelClusterL2GOutputBufferList.push_back(cl::Buffer(m_context, CL_MEM_READ_WRITE, pixel_ghitz_size_bytes, NULL, &err));
142  ATH_MSG_DEBUG("Allocating pxl cls EDM out buffer");
143  m_pixelClusterL2GEDMOutputBufferList.push_back(cl::Buffer(m_context, CL_MEM_READ_WRITE, pixel_ghitz_size_bytes, NULL, &err));
144  ATH_MSG_DEBUG("Allocating Input Buffer in Global Memory");
145  m_pixelFirstStageSlicingInputBufferList.push_back(cl::Buffer(m_context, CL_MEM_READ_WRITE, pixel_ghitz_size_bytes, NULL, &err));
146  ATH_MSG_DEBUG("Allocating Output Buffer in Global Memory");
147  m_pixelFirstStageSlicingOutputBufferList.push_back(cl::Buffer(m_context, CL_MEM_READ_WRITE, pixel_first_sliced_size_bytes, NULL, &err));
148  ATH_MSG_DEBUG("Allocating Inside PR Input Buffer in Global Memory");
149  m_insideOutInputBufferList.push_back(cl::Buffer(m_context, CL_MEM_READ_WRITE, pixel_first_sliced_size_bytes, NULL, &err));
150  ATH_MSG_DEBUG("Allocating Inside PR Output Buffer in Global Memory");
151  m_insideOutOutputBufferList.push_back(cl::Buffer(m_context, CL_MEM_READ_WRITE, inside_out_size_bytes, NULL, &err));
152 
153  // Create Input/Output Kernel runs and set arguments
154  ATH_MSG_DEBUG("Setting buffer for pxl cls input.");
155  m_pixelClusterL2GKernels[0].setArg(0, m_pixelClusterL2GInputBufferList[0]);
156  ATH_MSG_DEBUG("Setting buffer for pxl cls output.");
157  m_pixelClusterL2GKernels[0].setArg(1, m_pixelClusterL2GOutputBufferList[0]);
158  ATH_MSG_DEBUG("Setting buffer for pxl cls EDM output.");
159  m_pixelClusterL2GKernels[0].setArg(2, m_pixelClusterL2GEDMOutputBufferList[0]);
160 
161  ATH_MSG_DEBUG("Setting buffer for Input kernel run.");
162  m_pixelFirstStageSlicingInputKernels[0].setArg(0, m_pixelFirstStageSlicingInputBufferList[0]);
163  ATH_MSG_DEBUG("Setting # words for Input kernel run.");
164  m_pixelFirstStageSlicingInputKernels[0].setArg(1, n_pixel_ghitz_words);
165 
166  ATH_MSG_DEBUG("Setting buffer for Output kernel run.");
167  m_pixelFirstStageSlicingOutputKernels[0].setArg(0, m_pixelFirstStageSlicingOutputBufferList[0]);
168  ATH_MSG_DEBUG("Setting # words for Output kernel run.");
169  m_pixelFirstStageSlicingOutputKernels[0].setArg(1, n_pixel_first_sliced_words);
170 
171  ATH_MSG_DEBUG("Setting buffer for Input kernel run INSIDE OUT.");
172  m_insideOutInputKernels[0].setArg(0, m_insideOutInputBufferList[0]);
173 
174  ATH_MSG_DEBUG("Setting buffer for Output kernel run INSIDE OUT.");
175  m_insideOutOutputKernels[0].setArg(0, m_insideOutOutputBufferList[0]);
176 
177  // Pixel Clustering
178  // Write
179  ATH_MSG_DEBUG("Loading input data to pixel clustering kernel...");
180  m_queue.enqueueWriteBuffer(m_pixelClusterL2GInputBufferList[0], CL_TRUE, 0, pixel_size_bytes, &pixel_cls_input_data, NULL, NULL);
181 
182  // Verify write
183  outputHexData(n_pixel_words, pixel_cls_input_data, "Pixel Clustering Input");
184 
185  // Execute
186  ATH_MSG_DEBUG("Executing pixel clustering");
187  m_queue.enqueueTask(m_pixelClusterL2GKernels[0]);
188  m_queue.finish();
189 
190  // Read
191  ATH_MSG_DEBUG("Reading pixel clustering output");
192  uint64_t cls_out_data[n_pixel_ghitz_words];
193  m_queue.enqueueReadBuffer(m_pixelClusterL2GOutputBufferList[0], CL_TRUE, 0, pixel_ghitz_size_bytes, &cls_out_data);
194 
195  outputHexData(n_pixel_ghitz_words, cls_out_data, "Real Pixel Clustering Output");
196 
197  // Read
198  ATH_MSG_DEBUG("Reading pixel clustering EDM output");
199  uint64_t cls_out_edm_data[n_pixel_ghitz_words];
200  m_queue.enqueueReadBuffer(m_pixelClusterL2GEDMOutputBufferList[0], CL_TRUE, 0, pixel_ghitz_size_bytes, &cls_out_edm_data);
201 
202  outputHexData(n_pixel_ghitz_words, cls_out_edm_data, "Real Pixel Clustering EDM Output");
203 
204 
205  ATH_MSG_DEBUG("Loading input data to Slicing Engine...");
206  m_queue.enqueueWriteBuffer(m_pixelFirstStageSlicingInputBufferList[0], CL_TRUE, 0, pixel_ghitz_size_bytes, &pixel_ghitz_data, NULL, NULL);
207 
208  outputHexData(n_pixel_ghitz_words, pixel_ghitz_data, "Ideal Pixel Clustering Output");
209 
210  // Reset slicing engine event counters
211  m_pixelFirstStageSlicingIPs[0].write_register(USER_CTRL_OFFSET, EVENT_COUNT_RST);
212 
213  ATH_MSG_DEBUG("------------------------------------------------------------------------------------------------");
214 
215  // Start Input/Output Kernel runs
216  ATH_MSG_DEBUG("Starting Input kernel run.");
217  m_queue.enqueueTask(m_pixelFirstStageSlicingInputKernels[0]);
218  ATH_MSG_DEBUG("Starting Output kernel run.");
219  m_queue.enqueueTask(m_pixelFirstStageSlicingOutputKernels[0]);
220  m_queue.finish();
221 
222  // Get the output;
223  ATH_MSG_DEBUG("Synchronize output buffer data from device global memory");
224  uint64_t se_out_data[n_pixel_first_sliced_words];
225  m_queue.enqueueReadBuffer(m_pixelFirstStageSlicingOutputBufferList[0], CL_TRUE, 0, pixel_first_sliced_size_bytes, &se_out_data);
226 
227  outputHexData(n_pixel_first_sliced_words, se_out_data, "Slicing Engine Output");
228 
229  ATH_MSG_DEBUG("Write SE output to inside out input (cross DDR banks)");
230  m_queue.enqueueWriteBuffer(m_insideOutInputBufferList[0], CL_TRUE, 0, pixel_first_sliced_size_bytes, &pixel_first_sliced_data, NULL, NULL);
231 
232  ATH_MSG_DEBUG("Starting Inside Out Input kernel run.");
233  m_queue.enqueueTask(m_insideOutInputKernels[0]);
234  m_queue.finish();
235  ATH_MSG_DEBUG("Starting Inside Out Output kernel run.");
236  m_queue.enqueueTask(m_insideOutOutputKernels[0]);
237  m_queue.finish();
238 
239 
240  ATH_MSG_DEBUG("Slicing Engine System Done");
241  ATH_MSG_DEBUG("------------------------------------------------------------------------------------------------");
242 
243 
244  return StatusCode::SUCCESS;
245  }
246 
248  {
249  ATH_MSG_INFO("Average Kernel execution time: " << m_sum_kernelTime /m_num_Events /1e6 << " ms");
250  return StatusCode::SUCCESS;
251  }
252 }
EFTrackingFPGAIntegration::F600IntegrationAlg::readTV
void readTV(const std::string filepath, int n_words, uint64_t *data) const
Definition: F600IntegrationAlg.cxx:89
EFTrackingFPGAIntegration::F600IntegrationAlg::outputHexData
void outputHexData(size_t dataLen, uint64_t *data, const std::string dataDescriptor) const
Definition: F600IntegrationAlg.cxx:18
EFTrackingFPGAIntegration::F600IntegrationAlg::m_pixelFirstStageOutputKernelName
Gaudi::Property< std::string > m_pixelFirstStageOutputKernelName
Definition: F600IntegrationAlg.h:100
IntegrationBase::m_accelerator
cl::Device m_accelerator
Device object for the accelerator card.
Definition: IntegrationBase.h:66
data
char data[hepevt_bytes_allocation_ATLAS]
Definition: HepEvt.cxx:11
IntegrationBase::initialize
virtual StatusCode initialize() override
Detect the OpenCL devices and prepare OpenCL context.
Definition: IntegrationBase.cxx:16
EFTrackingFPGAIntegration::F600IntegrationAlg::finalize
virtual StatusCode finalize() override final
Definition: F600IntegrationAlg.cxx:247
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
F600IntegrationAlg.h
EFTrackingFPGAIntegration::F600IntegrationAlg::m_queue
cl::CommandQueue m_queue
Definition: F600IntegrationAlg.h:176
IntegrationBase::m_context
cl::Context m_context
Context object for the application.
Definition: IntegrationBase.h:67
EFTrackingFPGAIntegration::F600IntegrationAlg::m_insideOutInputPath
Gaudi::Property< std::string > m_insideOutInputPath
Definition: F600IntegrationAlg.h:132
python.RatesEmulationExample.lock
lock
Definition: RatesEmulationExample.py:148
Chrono.h
Exception-safe IChronoSvc caller.
EFTrackingFPGAIntegration::F600IntegrationAlg::m_pixelFirstStageSlicingIPName
Gaudi::Property< std::string > m_pixelFirstStageSlicingIPName
Definition: F600IntegrationAlg.h:96
USER_CTRL_OFFSET
#define USER_CTRL_OFFSET
Definition: F600IntegrationAlg.h:41
EFTrackingFPGAIntegration::F600IntegrationAlg::m_pixelClusterInputPath
Gaudi::Property< std::string > m_pixelClusterInputPath
Definition: F600IntegrationAlg.h:128
EFTrackingFPGAIntegration::F600IntegrationAlg::m_FPGADataFormatTool
ToolHandle< FPGADataFormatTool > m_FPGADataFormatTool
Tool for formatting FPGA data.
Definition: F600IntegrationAlg.h:69
EFTrackingFPGAIntegration::F600IntegrationAlg::m_sum_kernelTime
std::atomic< cl_ulong > m_sum_kernelTime
Sum for the average time of the kernel execution.
Definition: F600IntegrationAlg.h:138
Muon::nsw::STGTPPad::n_words
constexpr std::size_t n_words
Definition: NSWSTGTPDecodeBitmaps.h:62
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
EFTrackingFPGAIntegration::F600IntegrationAlg::initialize
virtual StatusCode initialize() override final
Detect the OpenCL devices and prepare OpenCL context.
Definition: F600IntegrationAlg.cxx:26
DataPreparationPipeline.h
Athena::Chrono
Exception-safe IChronoSvc caller.
Definition: Chrono.h:50
EFTrackingFPGAIntegration::F600IntegrationAlg::m_FPGATrackKey
SG::ReadHandleKey< FPGATrackSimTrackCollection > m_FPGATrackKey
Definition: F600IntegrationAlg.h:75
dqt_zlumi_pandas.err
err
Definition: dqt_zlumi_pandas.py:183
lumiFormat.i
int i
Definition: lumiFormat.py:85
EFTrackingFPGAIntegration::F600IntegrationAlg::execute
virtual StatusCode execute(const EventContext &ctx) const override final
Should be overriden by derived classes to perform meaningful work.
Definition: F600IntegrationAlg.cxx:109
EFTrackingFPGAIntegration::F600IntegrationAlg::m_pixelClusteringKernelName
Gaudi::Property< std::string > m_pixelClusteringKernelName
Definition: F600IntegrationAlg.h:82
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
EFTrackingFPGAIntegration::F600IntegrationAlg::get_cu_name
std::string get_cu_name(const std::string &kernel_name, int cu)
Definition: F600IntegrationAlg.cxx:12
EFTrackingFPGAIntegration::F600IntegrationAlg::m_xaodClusterMaker
ToolHandle< xAODClusterMaker > m_xaodClusterMaker
Tool for creating xAOD containers.
Definition: F600IntegrationAlg.h:60
EFTrackingFPGAIntegration::F600IntegrationAlg::m_memReadKernelName
Gaudi::Property< std::string > m_memReadKernelName
Definition: F600IntegrationAlg.h:104
EFTrackingFPGAIntegration::F600IntegrationAlg::m_testVectorTool
ToolHandle< TestVectorTool > m_testVectorTool
Tool for preparing test vectors.
Definition: F600IntegrationAlg.h:66
find_tgc_unfilled_channelids.ip
ip
Definition: find_tgc_unfilled_channelids.py:3
EFTrackingFPGAIntegration::F600IntegrationAlg::m_xclbin
Gaudi::Property< std::string > m_xclbin
Path and name of the xclbin file.
Definition: F600IntegrationAlg.h:72
xAOD::uint64_t
uint64_t
Definition: EventInfo_v1.cxx:123
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
SG::VarHandleKey::initialize
StatusCode initialize(bool used=true)
If this object is used as a property, then this should be called during the initialize phase.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:103
EFTrackingFPGAIntegration
The class for enconding RDO to FPGA format.
Definition: BenchmarkAlg.h:28
IntegrationBase::loadProgram
StatusCode loadProgram(const std::string &xclbin)
Find the xclbin file and load it into the OpenCL program object.
Definition: IntegrationBase.cxx:115
EFTrackingFPGAIntegration::F600IntegrationAlg::m_memWriteKernelName
Gaudi::Property< std::string > m_memWriteKernelName
Definition: F600IntegrationAlg.h:106
EFTrackingFPGAIntegration::F600IntegrationAlg::m_num_Events
std::atomic< ulonglong > m_num_Events
Number of events for the average time of the kernel execution.
Definition: F600IntegrationAlg.h:139
EFTrackingTransient.h
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
EFTrackingFPGAIntegration::F600IntegrationAlg::m_outputConversionTool
ToolHandle< OutputConversionTool > m_outputConversionTool
Definition: F600IntegrationAlg.h:78
lumiFormat.fill
fill
Definition: lumiFormat.py:104
EFTrackingFPGAIntegration::F600IntegrationAlg::m_xrt_accelerator
xrt::device m_xrt_accelerator
Definition: F600IntegrationAlg.h:142
EFTrackingFPGAIntegration::F600IntegrationAlg::readTVLength
int readTVLength(std::string filepath) const
Definition: F600IntegrationAlg.cxx:79
EFTrackingFPGAIntegration::F600IntegrationAlg::m_chronoSvc
ServiceHandle< IChronoSvc > m_chronoSvc
Service for timing the algorithm.
Definition: F600IntegrationAlg.h:57
EFTrackingFPGAIntegration::F600IntegrationAlg::m_pixelStageOneSlicingInputPath
Gaudi::Property< std::string > m_pixelStageOneSlicingInputPath
Definition: F600IntegrationAlg.h:130
IntegrationBase::m_program
cl::Program m_program
Program object containing the kernel.
Definition: IntegrationBase.h:68
EVENT_COUNT_RST
#define EVENT_COUNT_RST
Definition: F600IntegrationAlg.h:39
EFTrackingFPGAIntegration::F600IntegrationAlg::m_pixelFirstStageInputKernelName
Gaudi::Property< std::string > m_pixelFirstStageInputKernelName
Definition: F600IntegrationAlg.h:98