diff --git a/et-common-libs/include/etsoc/isa/tensors.h b/et-common-libs/include/etsoc/isa/tensors.h index bc0310a59..ca7d1435e 100644 --- a/et-common-libs/include/etsoc/isa/tensors.h +++ b/et-common-libs/include/etsoc/isa/tensors.h @@ -454,7 +454,7 @@ tensor_fma(bool use_tmask, uint64_t b_num_col, uint64_t a_num_rows, uint64_t a_n uint64_t csr_enc = (((uint64_t)use_tmask & 1) << 63) | ((b_num_col & 0x3) << 55) | ((a_num_rows & 0xF) << 51) | ((a_num_cols & 0xF) << 47) | ((offset & 0xF) << 43) | (((uint64_t)tenc_loc & 1) << 23) | - (((uint64_t)tena_unsigned & 1) << 22) | (((uint64_t)tenb_unsigned & 1) << 21) | + (((uint64_t)tenb_unsigned & 1) << 22) | (((uint64_t)tena_unsigned & 1) << 21) | (((uint64_t)tenb_loc & 1) << 20) | ((scp_loc_b & 0xFF) << 12) | ((scp_loc_a & 0xFF) << 4) | ((opcode & 0x7) << 1) | ((uint64_t)first_pass & 1); diff --git a/gp-sdk/device/tests/CMakeLists.txt b/gp-sdk/device/tests/CMakeLists.txt index ceebc76d3..6cf8a9dae 100644 --- a/gp-sdk/device/tests/CMakeLists.txt +++ b/gp-sdk/device/tests/CMakeLists.txt @@ -105,6 +105,9 @@ add_etsoc_test_kernel(syncShire2EP.elf barrier/syncShire2EP.cpp) add_etsoc_test_kernel(txfma.elf txfma/txfma.cpp) target_include_directories(txfma.elf INTERFACE .) +add_etsoc_test_kernel(tima_unsigned_bits.elf tima_unsigned_bits/tima_unsigned_bits.cpp) +target_include_directories(tima_unsigned_bits.elf INTERFACE .) + add_etsoc_test_kernel(oneTrapOnSync.elf trapping/oneTrapOnSync.cpp) add_etsoc_test_kernel(busy10sec.elf busy10sec/busy10sec.cc) diff --git a/gp-sdk/device/tests/tima_unsigned_bits/tima_unsigned_bits.cpp b/gp-sdk/device/tests/tima_unsigned_bits/tima_unsigned_bits.cpp new file mode 100644 index 000000000..1fd29f3ce --- /dev/null +++ b/gp-sdk/device/tests/tima_unsigned_bits/tima_unsigned_bits.cpp @@ -0,0 +1,151 @@ +/*------------------------------------------------------------------------- + * Copyright (c) 2026 AIFoundry + * SPDX-License-Identifier: Apache-2.0 + *------------------------------------------------------------------------- + */ + +#if __has_include() +#include +#include +#else +#include +#include +#endif + +#include "entryPoint.h" +#include "tima_unsigned_bits_kernel_arguments.h" + +int entryPoint_0(KernelArguments* args); +int entryPoint_1(KernelArguments* args); +DECLARE_KERNEL_ENTRY_POINTS(entryPoint_0, entryPoint_1); + +static inline uint64_t tensor_ima8a32_csr(bool bit22, bool bit21) { + constexpr uint64_t use_tmask = 0; + constexpr uint64_t b_num_col = 0; + constexpr uint64_t a_num_rows = 0; + constexpr uint64_t a_num_cols = 0; + constexpr uint64_t a_start_col = 0; + constexpr uint64_t dst_rf = 1; + constexpr uint64_t tenb_loc = 0; + constexpr uint64_t b_start_line = 1; + constexpr uint64_t a_start_line = 0; + constexpr uint64_t opcode_ima8a32 = 3; + constexpr uint64_t first_pass = 1; + + return (use_tmask << 63) | (b_num_col << 55) | (a_num_rows << 51) | + (a_num_cols << 47) | (a_start_col << 43) | (dst_rf << 23) | + ((uint64_t(bit22) & 1) << 22) | ((uint64_t(bit21) & 1) << 21) | + (tenb_loc << 20) | (b_start_line << 12) | (a_start_line << 4) | + (opcode_ima8a32 << 1) | first_pass; +} + +static inline int32_t run_ima8a32_case(const uint8_t* a_line, const uint8_t* b_line, + bool bit22, bool bit21, uint32_t sentinel) { + tensor_load(false, false, 0, 0, 0, (uint64_t)a_line, 0, 0, 64, 0); + tensor_wait(TENSOR_LOAD_WAIT_0); + + tensor_load(false, false, 1, 0, 0, (uint64_t)b_line, 0, 0, 64, 0); + tensor_wait(TENSOR_LOAD_WAIT_0); + + __asm__ __volatile__("fmv.s.x f0, %[sentinel]\n" : : [sentinel] "r"(sentinel) : "f0", "memory"); + + uint64_t csr_enc = tensor_ima8a32_csr(bit22, bit21); + __asm__ __volatile__("csrw 0x801, %[csr_enc]\n" : : [csr_enc] "r"(csr_enc) : "memory"); + tensor_wait(TENSOR_FMA_WAIT); + + uint32_t raw; + __asm__ __volatile__("fmv.x.s %[raw], f0\n" : [raw] "=r"(raw) : : "memory"); + return static_cast(raw); +} + +static inline int32_t run_helper_ima8a32_case(const uint8_t* a_line, const uint8_t* b_line, + bool tenb_unsigned, bool tena_unsigned, + uint32_t sentinel) { + tensor_load(false, false, 0, 0, 0, (uint64_t)a_line, 0, 0, 64, 0); + tensor_wait(TENSOR_LOAD_WAIT_0); + + tensor_load(false, false, 1, 0, 0, (uint64_t)b_line, 0, 0, 64, 0); + tensor_wait(TENSOR_LOAD_WAIT_0); + + __asm__ __volatile__("fmv.s.x f0, %[sentinel]\n" : : [sentinel] "r"(sentinel) : "f0", "memory"); + + tensor_fma(false, 0, 0, 0, 0, true, tenb_unsigned, tena_unsigned, false, 1, 0, 3, true); + tensor_wait(TENSOR_FMA_WAIT); + + uint32_t raw; + __asm__ __volatile__("fmv.x.s %[raw], f0\n" : [raw] "=r"(raw) : : "memory"); + return static_cast(raw); +} + +static inline TimaUnsignedBitsRecord* record_for(KernelArguments* args, uint32_t hart_id) { + if (args == nullptr || args->records == nullptr || hart_id >= args->max_records) { + return nullptr; + } + return &args->records[hart_id]; +} + +static inline void fill_identity(TimaUnsignedBitsRecord* record) { + uint32_t hart_id = get_hart_id(); + uint32_t global_minion_id = hart_id >> 1; + + record->magic = TIMA_UNSIGNED_BITS_MAGIC; + record->hart_id = hart_id; + record->relative_thread_id = get_relative_thread_id(); + record->shire_id = global_minion_id >> 5; + record->minion_id = global_minion_id & 0x1f; + record->thread_id = hart_id & 1; +} + +static inline int run_probe(KernelArguments* args) { + uint32_t hart_id = get_hart_id(); + TimaUnsignedBitsRecord* record = record_for(args, hart_id); + if (record == nullptr) { + return 0; + } + + fill_identity(record); + record->result_no_unsigned = run_ima8a32_case(args->a_line, args->b_line, false, false, 0xdead0000); + record->result_bit21 = run_ima8a32_case(args->a_line, args->b_line, false, true, 0xdead0001); + record->result_bit22 = run_ima8a32_case(args->a_line, args->b_line, true, false, 0xdead0002); + record->result_bit21_bit22 = run_ima8a32_case(args->a_line, args->b_line, true, true, 0xdead0003); + + record->helper_no_unsigned = run_helper_ima8a32_case(args->a_line, args->b_line, false, false, 0xfeed0000); + record->helper_tenb_unsigned = run_helper_ima8a32_case(args->a_line, args->b_line, true, false, 0xfeed0001); + record->helper_tena_unsigned = run_helper_ima8a32_case(args->a_line, args->b_line, false, true, 0xfeed0002); + record->helper_both_unsigned = run_helper_ima8a32_case(args->a_line, args->b_line, true, true, 0xfeed0003); + record->status = TIMA_UNSIGNED_BITS_PROBE_COMPLETE; + __asm__ __volatile__("fence\n" ::: "memory"); + return 0; +} + +int entryPoint_0(KernelArguments* args) { + if (args == nullptr || args->probe_mode != TIMA_UNSIGNED_BITS_PROBE_THREAD0_ALL) { + return 0; + } + + return run_probe(args); +} + +int entryPoint_1(KernelArguments* args) { + uint32_t hart_id = get_hart_id(); + TimaUnsignedBitsRecord* record = record_for(args, hart_id); + if (record != nullptr) { + fill_identity(record); + record->status = TIMA_UNSIGNED_BITS_MARKED_NO_TENSOR; + } + + if (args == nullptr) { + return 0; + } + + if (args->probe_mode == TIMA_UNSIGNED_BITS_PROBE_THREAD1_SELECTED && + get_relative_thread_id() == args->selected_relative_thread) { + return run_probe(args); + } + + if (args->probe_mode == TIMA_UNSIGNED_BITS_PROBE_THREAD1_ALL) { + return run_probe(args); + } + + return 0; +} diff --git a/gp-sdk/device/tests/tima_unsigned_bits/tima_unsigned_bits_kernel_arguments.h b/gp-sdk/device/tests/tima_unsigned_bits/tima_unsigned_bits_kernel_arguments.h new file mode 100644 index 000000000..ccf6e3dbd --- /dev/null +++ b/gp-sdk/device/tests/tima_unsigned_bits/tima_unsigned_bits_kernel_arguments.h @@ -0,0 +1,55 @@ +#ifndef TIMA_UNSIGNED_BITS_KERNEL_ARGUMENTS_H +#define TIMA_UNSIGNED_BITS_KERNEL_ARGUMENTS_H + +/*------------------------------------------------------------------------- + * Copyright (c) 2026 AIFoundry + * SPDX-License-Identifier: Apache-2.0 + *------------------------------------------------------------------------- + */ + +#include + +static constexpr uint32_t TIMA_UNSIGNED_BITS_MAGIC = 0x54494d41; +static constexpr uint32_t TIMA_UNSIGNED_BITS_MAX_RECORDS = 4096; + +enum TimaUnsignedBitsProbeMode : uint32_t { + TIMA_UNSIGNED_BITS_PROBE_THREAD0_ALL = 0, + TIMA_UNSIGNED_BITS_PROBE_THREAD1_SELECTED = 1, + TIMA_UNSIGNED_BITS_PROBE_THREAD1_ALL = 2, +}; + +enum TimaUnsignedBitsStatus : uint32_t { + TIMA_UNSIGNED_BITS_NOT_RUN = 0, + TIMA_UNSIGNED_BITS_MARKED_NO_TENSOR = 1, + TIMA_UNSIGNED_BITS_PROBE_COMPLETE = 2, +}; + +struct TimaUnsignedBitsRecord { + uint32_t magic; + uint32_t hart_id; + uint32_t relative_thread_id; + uint32_t shire_id; + uint32_t minion_id; + uint32_t thread_id; + uint32_t status; + uint32_t reserved; + int32_t result_no_unsigned; + int32_t result_bit21; + int32_t result_bit22; + int32_t result_bit21_bit22; + int32_t helper_no_unsigned; + int32_t helper_tenb_unsigned; + int32_t helper_tena_unsigned; + int32_t helper_both_unsigned; +}; + +struct KernelArguments { + const uint8_t* a_line; + const uint8_t* b_line; + TimaUnsignedBitsRecord* records; + uint32_t max_records; + uint32_t probe_mode; + uint32_t selected_relative_thread; +} __attribute__((packed)); + +#endif diff --git a/gp-sdk/host/sdk/CMakeLists.txt b/gp-sdk/host/sdk/CMakeLists.txt index 2cef11fec..89b0fd525 100644 --- a/gp-sdk/host/sdk/CMakeLists.txt +++ b/gp-sdk/host/sdk/CMakeLists.txt @@ -82,6 +82,13 @@ target_link_libraries(txfma_launcher etsoc_gpsdk ) +add_executable(tima_unsigned_bits_launcher src/tima_unsigned_bits/tima_unsigned_bits.cpp) +target_include_directories(tima_unsigned_bits_launcher PRIVATE ${DEVICE_KERNELS_DIR}/tima_unsigned_bits) +target_link_libraries(tima_unsigned_bits_launcher + PRIVATE + etsoc_gpsdk +) + add_executable(multiDevice_launcher src/multi_device/multiDevice.cpp) target_include_directories(multiDevice_launcher PRIVATE ${DEVICE_KERNELS_DIR}/saxpy) target_link_libraries(multiDevice_launcher diff --git a/gp-sdk/host/sdk/src/tima_unsigned_bits/tima_unsigned_bits.cpp b/gp-sdk/host/sdk/src/tima_unsigned_bits/tima_unsigned_bits.cpp new file mode 100644 index 000000000..f014add2d --- /dev/null +++ b/gp-sdk/host/sdk/src/tima_unsigned_bits/tima_unsigned_bits.cpp @@ -0,0 +1,318 @@ +//****************************************************************************** +// Copyright (c) 2026 AIFoundry +// SPDX-License-Identifier: Apache-2.0 +//------------------------------------------------------------------------------ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "GenericLauncher.h" +#include "tima_unsigned_bits_kernel_arguments.h" + +struct Options { + fs::path kernel_path = ""; + int kernel_launch_timeout = 10; + std::string device_type = "sysemu"; + uint64_t shire_mask = 0xffffffffULL; + uint32_t probe_mode = TIMA_UNSIGNED_BITS_PROBE_THREAD0_ALL; + uint32_t selected_relative_thread = 1; + bool show_records = false; +}; + +Options parse_args(int argc, char* const* argv, std::vector& nextlevel) { + static constexpr const char* help_msg = + "Usage: [options]\n\n" + "TensorIMA8A32 unsigned-bit probe.\n\n" + "Required:\n" + " -k, --kernel_path path to kernel ELF file.\n\n" + "Optional:\n" + " -t, --kernel_launch_timeout timeout in seconds.\n" + " -d, --device_type device type (sysemu, fake, silicon).\n" + " -m, --shire_mask shire mask in decimal or hex.\n" + " -p, --probe_mode 0=thread0 all, 1=thread1 selected, 2=thread1 all.\n" + " -r, --selected_relative_thread relative thread for probe_mode=1.\n" + " -s, --show_records print every completed record.\n"; + + static constexpr const char* short_opts = "k:t:d:m:p:r:sh"; + static const std::vector long_opts_vect{ + {"kernel_path", required_argument, nullptr, 'k'}, + {"kernel_launch_timeout", required_argument, nullptr, 't'}, + {"device_type", required_argument, nullptr, 'd'}, + {"shire_mask", required_argument, nullptr, 'm'}, + {"probe_mode", required_argument, nullptr, 'p'}, + {"selected_relative_thread", required_argument, nullptr, 'r'}, + {"show_records", no_argument, nullptr, 's'}, + {"help", no_argument, nullptr, 'h'}, + {nullptr, 0, nullptr, 0}}; + + Options opts; + int ret = 0; + int index = 0; + opterr = 0; + + while ((ret = getopt_long(argc, argv, short_opts, long_opts_vect.data(), &index)) != -1) { + switch (ret) { + case 'k': + opts.kernel_path = optarg; + break; + case 't': + opts.kernel_launch_timeout = std::atoi(optarg); + break; + case 'd': + opts.device_type = optarg; + break; + case 'm': + opts.shire_mask = std::stoull(optarg, nullptr, 0); + break; + case 'p': + opts.probe_mode = static_cast(std::stoul(optarg, nullptr, 0)); + break; + case 'r': + opts.selected_relative_thread = static_cast(std::stoul(optarg, nullptr, 0)); + break; + case 's': + opts.show_records = true; + break; + case 'h': + std::cout << help_msg << GenericLauncher::help_msg << std::endl; + std::exit(0); + case '?': + nextlevel.emplace_back(argv[optind - 1]); + break; + default: + std::cerr << "error: unknown option " << argv[optind - 1] << "\n"; + std::exit(1); + } + } + + return opts; +} + +class TimaUnsignedBitsLauncher : public GenericLauncher { +public: + TimaUnsignedBitsLauncher() = delete; + using GenericLauncher::GenericLauncher; + + void prepareInput() { + a_line_.fill(0); + b_line_.fill(0); + records_.assign(TIMA_UNSIGNED_BITS_MAX_RECORDS, {}); + + a_line_[0] = 0xff; + b_line_[0] = 0xfe; + } + + void performDeviceAllocs() { + deviceA_ = runtime_->mallocDevice(devices_[devIdx_], a_line_.size()); + deviceB_ = runtime_->mallocDevice(devices_[devIdx_], b_line_.size()); + deviceRecords_ = runtime_->mallocDevice(devices_[devIdx_], records_.size() * sizeof(TimaUnsignedBitsRecord)); + } + + void programHost2DevCopies() { + runtime_->memcpyHostToDevice(defaultStreams_[devIdx_], reinterpret_cast(a_line_.data()), deviceA_, + a_line_.size()); + runtime_->memcpyHostToDevice(defaultStreams_[devIdx_], reinterpret_cast(b_line_.data()), deviceB_, + b_line_.size()); + runtime_->memcpyHostToDevice(defaultStreams_[devIdx_], reinterpret_cast(records_.data()), + deviceRecords_, records_.size() * sizeof(TimaUnsignedBitsRecord)); + } + + void programDev2HostCopies() { + runtime_->memcpyDeviceToHost(defaultStreams_[devIdx_], deviceRecords_, + reinterpret_cast(records_.data()), + records_.size() * sizeof(TimaUnsignedBitsRecord)); + } + + void freeDeviceAllocs() { + runtime_->freeDevice(devices_[devIdx_], deviceA_); + runtime_->freeDevice(devices_[devIdx_], deviceB_); + runtime_->freeDevice(devices_[devIdx_], deviceRecords_); + } + + std::array a_line_{}; + std::array b_line_{}; + std::vector records_{TIMA_UNSIGNED_BITS_MAX_RECORDS}; + std::byte* deviceA_ = nullptr; + std::byte* deviceB_ = nullptr; + std::byte* deviceRecords_ = nullptr; +}; + +static bool matches_prm(const TimaUnsignedBitsRecord& record) { + return record.result_no_unsigned == 2 && record.result_bit21 == -510 && + record.result_bit22 == -254 && record.result_bit21_bit22 == 64770; +} + +static bool matches_swapped(const TimaUnsignedBitsRecord& record) { + return record.result_no_unsigned == 2 && record.result_bit21 == -254 && + record.result_bit22 == -510 && record.result_bit21_bit22 == 64770; +} + +static bool matches_zero_result(const TimaUnsignedBitsRecord& record) { + return record.result_no_unsigned == 0 && record.result_bit21 == 0 && + record.result_bit22 == 0 && record.result_bit21_bit22 == 0; +} + +static bool helper_matches_contract(const TimaUnsignedBitsRecord& record) { + return record.helper_no_unsigned == 2 && record.helper_tenb_unsigned == -254 && + record.helper_tena_unsigned == -510 && record.helper_both_unsigned == 64770; +} + +static bool helper_matches_current_swap(const TimaUnsignedBitsRecord& record) { + return record.helper_no_unsigned == 2 && record.helper_tenb_unsigned == -510 && + record.helper_tena_unsigned == -254 && record.helper_both_unsigned == 64770; +} + +static bool helper_matches_zero_result(const TimaUnsignedBitsRecord& record) { + return record.helper_no_unsigned == 0 && record.helper_tenb_unsigned == 0 && + record.helper_tena_unsigned == 0 && record.helper_both_unsigned == 0; +} + +static void print_record(const TimaUnsignedBitsRecord& record) { + std::cout << std::hex << "hart=" << record.hart_id << " rel=" << record.relative_thread_id + << " shire=" << record.shire_id << " minion=" << record.minion_id + << std::dec << " thread=" << record.thread_id << " status=" << record.status + << " results={none:" << record.result_no_unsigned << ", bit21:" << record.result_bit21 + << ", bit22:" << record.result_bit22 << ", both:" << record.result_bit21_bit22 << "}" + << " helper={none:" << record.helper_no_unsigned << ", tenb:" << record.helper_tenb_unsigned + << ", tena:" << record.helper_tena_unsigned << ", both:" << record.helper_both_unsigned << "}\n"; +} + +static int analyze_records(const std::vector& records, bool show_records) { + size_t marked = 0; + size_t complete = 0; + size_t prm = 0; + size_t swapped = 0; + size_t zero = 0; + size_t other = 0; + size_t helper_contract = 0; + size_t helper_swapped = 0; + size_t helper_zero = 0; + size_t helper_other = 0; + + for (const auto& record : records) { + if (record.magic != TIMA_UNSIGNED_BITS_MAGIC) { + continue; + } + if (record.status == TIMA_UNSIGNED_BITS_MARKED_NO_TENSOR) { + ++marked; + if (show_records) { + print_record(record); + } + continue; + } + if (record.status != TIMA_UNSIGNED_BITS_PROBE_COMPLETE) { + continue; + } + + ++complete; + if (matches_prm(record)) { + ++prm; + } else if (matches_swapped(record)) { + ++swapped; + } else if (matches_zero_result(record)) { + ++zero; + } else { + ++other; + } + + if (helper_matches_contract(record)) { + ++helper_contract; + } else if (helper_matches_current_swap(record)) { + ++helper_swapped; + } else if (helper_matches_zero_result(record)) { + ++helper_zero; + } else { + ++helper_other; + } + + if (show_records) { + print_record(record); + } + } + + std::cout << std::dec << "TensorIMA8A32 unsigned-bit probe summary:\n" + << " marked thread1 records: " << marked << "\n" + << " completed tensor probes: " << complete << "\n" + << " PRM mapping matches: " << prm << "\n" + << " swapped mapping matches: " << swapped << "\n" + << " zero/inactive results: " << zero << "\n" + << " other results: " << other << "\n" + << " helper contract matches: " << helper_contract << "\n" + << " helper current-swap matches: " << helper_swapped << "\n" + << " helper zero/inactive results: " << helper_zero << "\n" + << " helper other results: " << helper_other << "\n" + << "Expected raw PRM mapping for A=0xff, B=0xfe is none=2, bit21(A unsigned)=-510, " + "bit22(B unsigned)=-254, both=64770.\n" + << "Expected tensor_fma() contract mapping is none=2, tenb_unsigned=-254, " + "tena_unsigned=-510, both=64770.\n"; + + if (complete == 0) { + std::cerr << "error: no tensor probe records completed\n"; + return 2; + } + if (prm == 0) { + std::cerr << "error: no completed tensor probe matched the PRM mapping\n"; + return 1; + } + if (swapped != 0 || other != 0) { + std::cerr << "error: TensorIMA8A32 unsigned-bit mapping produced swapped or unexpected nonzero results\n"; + return 1; + } + if (helper_contract == 0) { + std::cerr << "error: no tensor_fma() helper probe matched the documented argument contract\n"; + return 1; + } + if (helper_swapped != 0 || helper_other != 0) { + std::cerr << "error: tensor_fma() helper produced swapped or unexpected nonzero results\n"; + return 1; + } + return 0; +} + +int main(int argc, char** argv) { + std::vector argvPendingToParse{argv[0]}; + Options opt = parse_args(argc, argv, argvPendingToParse); + + Config config{modeFromString(opt.device_type), 1}; + config.dump(); + std::cout << "Probe mode: " << opt.probe_mode << "\n"; + std::cout << "Shire mask: 0x" << std::hex << opt.shire_mask << std::dec << "\n"; + + TimaUnsignedBitsLauncher launcher(config, static_cast(argvPendingToParse.size()), argvPendingToParse.data()); + launcher.initialize(); + auto kernelId = launcher.loadKernel(opt.kernel_path); + launcher.performDeviceAllocs(); + launcher.prepareInput(); + launcher.programHost2DevCopies(); + + KernelArguments kernelArgs; + kernelArgs.a_line = reinterpret_cast(launcher.deviceA_); + kernelArgs.b_line = reinterpret_cast(launcher.deviceB_); + kernelArgs.records = reinterpret_cast(launcher.deviceRecords_); + kernelArgs.max_records = static_cast(launcher.records_.size()); + kernelArgs.probe_mode = opt.probe_mode; + kernelArgs.selected_relative_thread = opt.selected_relative_thread; + + launcher.kernelLaunch(kernelId, &kernelArgs, nullptr, 0, 0, opt.shire_mask); + launcher.programDev2HostCopies(); + launcher.waitKernelCompletion(std::chrono::seconds(opt.kernel_launch_timeout)); + launcher.dumpTracesToFile(); + + if (launcher.checkKernelExecutionErrors()) { + return -1; + } + + int result = analyze_records(launcher.records_, opt.show_records); + + launcher.freeDeviceAllocs(); + launcher.unLoadKernel(kernelId); + launcher.tearDown(); + + return result; +}