137 bool enable_ctrl_pkts =
false,
138 int num_trailing_params = 0) {
142 constexpr int num_inputs =
sizeof...(TIns);
149 const int num_real_inputs = num_inputs - num_trailing_params;
154 std::cout <<
"Sequence instr count: " << instr_v.size() <<
"\n";
165 constexpr int kFirstDataArg = 3;
167 const int out_arg = kFirstDataArg + num_real_inputs;
170 auto data_arg_slot = [&](
int idx) {
171 return (idx < num_real_inputs) ? (kFirstDataArg + idx)
172 : (out_arg + 1 + (idx - num_real_inputs));
176 auto bo_instr = xrt::bo(device, instr_v.size() *
sizeof(
int),
177 XCL_BO_FLAGS_CACHEABLE, kernel.group_id(1));
178 void *bufInstr = bo_instr.map<
void *>();
179 memcpy(bufInstr, instr_v.data(), instr_v.size() *
sizeof(
int));
180 bo_instr.sync(XCL_BO_SYNC_BO_TO_DEVICE);
183 std::cout <<
"Writing data into buffer objects.\n";
187 std::vector<xrt::bo> in_bos;
188 in_bos.reserve(num_inputs);
189 std::tuple<TIns *...> in_ptrs;
193 int first_in_volume = 0;
195 auto alloc_inputs = [&](
auto &...inb) {
197 auto one = [&](
auto &desc,
auto &ptr_slot) {
198 using T =
typename std::remove_reference_t<
decltype(desc)>::elem_type;
199 auto bo = xrt::bo(device, desc.volume *
sizeof(T), XRT_BO_FLAGS_HOST_ONLY,
200 kernel.group_id(data_arg_slot(idx)));
201 T *mapped = bo.template map<T *>();
202 desc.init(mapped, desc.volume);
203 bo.sync(XCL_BO_SYNC_BO_TO_DEVICE);
205 in_bos.push_back(std::move(bo));
207 first_in_volume = desc.volume;
210 std::apply([&](
auto &...slots) { (one(inb, slots), ...); }, in_ptrs);
212 std::apply(alloc_inputs, inputs);
215 auto bo_out = xrt::bo(device, output.
volume *
sizeof(TOut),
216 XRT_BO_FLAGS_HOST_ONLY, kernel.group_id(out_arg));
217 TOut *bufOut = bo_out.map<TOut *>();
219 bo_out.sync(XCL_BO_SYNC_BO_TO_DEVICE);
225 const bool use_ctrl_pkts = enable_ctrl_pkts && myargs.
trace_size > 0;
226 int next_arg = out_arg + 1 + num_trailing_params;
229 uint32_t *bufCtrlPkts =
nullptr;
230 int ctrlpkt_arg = -1;
232 ctrlpkt_arg = next_arg++;
233 bo_ctrlpkts = xrt::bo(device, 8, XRT_BO_FLAGS_HOST_ONLY,
234 kernel.group_id(ctrlpkt_arg));
235 bufCtrlPkts = bo_ctrlpkts.map<uint32_t *>();
239 char *bufTrace =
nullptr;
242 trace_arg = next_arg++;
246 bo_trace = xrt::bo(device, alloc_trace_size, XRT_BO_FLAGS_HOST_ONLY,
247 kernel.group_id(trace_arg));
248 bufTrace = bo_trace.map<
char *>();
257 std::cout <<
"bufCtrlPkts[0]:" << std::hex << bufCtrlPkts[0] << std::endl;
258 std::cout <<
"bufCtrlPkts[1]:" << std::hex << bufCtrlPkts[1] << std::endl;
264 bo_trace.sync(XCL_BO_SYNC_BO_TO_DEVICE);
266 bo_ctrlpkts.sync(XCL_BO_SYNC_BO_TO_DEVICE);
273 float npu_time_total = 0;
274 float npu_time_min = 9999999;
275 float npu_time_max = 0;
282 for (
unsigned iter = 0; iter < num_iter; iter++) {
285 std::cout <<
"Running Kernel.\n";
287 auto start = std::chrono::high_resolution_clock::now();
288 unsigned int opcode = 3;
292 xrt::run run(kernel);
293 run.set_arg(0, opcode);
294 run.set_arg(1, bo_instr);
295 run.set_arg(2, instr_v.size());
296 for (
int i = 0; i < num_inputs; i++)
297 run.set_arg(data_arg_slot(i), in_bos[i]);
298 run.set_arg(out_arg, bo_out);
299 if (ctrlpkt_arg >= 0)
300 run.set_arg(ctrlpkt_arg, bo_ctrlpkts);
302 run.set_arg(trace_arg, bo_trace);
306 auto stop = std::chrono::high_resolution_clock::now();
307 bo_out.sync(XCL_BO_SYNC_BO_FROM_DEVICE);
309 bo_trace.sync(XCL_BO_SYNC_BO_FROM_DEVICE);
318 std::cout <<
"Verifying results ..." << std::endl;
319 auto vstart = std::chrono::system_clock::now();
322 errors += std::apply(
323 [&](
auto *...in_ptr) {
324 return verify_results(in_ptr..., bufOut, first_in_volume,
329 auto vstop = std::chrono::system_clock::now();
331 std::chrono::duration_cast<std::chrono::seconds>(vstop - vstart)
334 std::cout <<
"Verify time: " << vtime <<
"secs." << std::endl;
337 std::cout <<
"WARNING: results not verified." << std::endl;
348 uint32_t *ctrl_pkt_out =
349 (uint32_t *)(((
char *)bufTrace) + myargs.
trace_size);
351 std::cout <<
"ctrl_pkt_out[0]:" << std::hex << ctrl_pkt_out[0]
353 std::cout <<
"ctrl_pkt_out[1]:" << std::hex << ctrl_pkt_out[1]
356 int col = (ctrl_pkt_out[0] >> 21) & 0x7F;
357 int row = (ctrl_pkt_out[0] >> 16) & 0x1F;
358 if ((ctrl_pkt_out[1] >> 8) == 3)
359 std::cout <<
"WARNING: Trace overflow detected in tile(" << row <<
","
360 << col <<
". Trace results may be invalid." << std::endl;
365 std::chrono::duration_cast<std::chrono::microseconds>(stop - start)
368 npu_time_total += npu_time;
369 npu_time_min = (npu_time < npu_time_min) ? npu_time : npu_time_min;
370 npu_time_max = (npu_time > npu_time_max) ? npu_time : npu_time_max;
380 std::cout << std::endl
381 <<
"Avg NPU time: " << npu_time_total / myargs.
n_iterations <<
"us."
384 std::cout <<
"Avg NPU gflops: "
388 std::cout << std::endl
389 <<
"Min NPU time: " << npu_time_min <<
"us." << std::endl;
391 std::cout <<
"Max NPU gflops: " << macs / (1000 * npu_time_min)
394 std::cout << std::endl
395 <<
"Max NPU time: " << npu_time_max <<
"us." << std::endl;
397 std::cout <<
"Min NPU gflops: " << macs / (1000 * npu_time_max)
401 std::cout <<
"\nPASS!\n\n";
404 std::cout <<
"\nError count: " << errors <<
"\n\n";
405 std::cout <<
"\nFailed.\n\n";