aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Schink <swo-dev@marcschink.de>2017-08-04 21:25:15 +0200
committerMarc Schink <swo-dev@marcschink.de>2017-08-19 19:29:45 +0200
commit48907a8206012380f7cf2a9e960f2908482cbe41 (patch)
treee3f581b4b3f9c697b2a445154b39fde0f5f1a6c1
parent87cc5c149eb0f471cb8c8349f315040340666485 (diff)
Add example for C++ bindings
-rw-r--r--examples/decoder.cpp282
1 files changed, 282 insertions, 0 deletions
diff --git a/examples/decoder.cpp b/examples/decoder.cpp
new file mode 100644
index 0000000..556f930
--- /dev/null
+++ b/examples/decoder.cpp
@@ -0,0 +1,282 @@
+/*
+ * This file is part of the libswo project.
+ *
+ * Copyright (C) 2017 Marc Schink <swo-dev@marcschink.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <string.h>
+#include <errno.h>
+
+#include <iostream>
+#include <fstream>
+
+#include <libswocxx/libswocxx.h>
+
+#define BUFFER_SIZE 1024
+
+using namespace libswo;
+
+static void handle_unknown_packet(const Unknown &packet)
+{
+ printf("Unknown data (size = %zu bytes)\n", packet.get_size());
+}
+
+static void handle_sync_packet(const Synchronization &packet)
+{
+ if (packet.get_size() % 8)
+ printf("Synchronization (size = %zu bits)\n", packet.get_size());
+ else
+ printf("Synchronization (size = %zu bytes)\n", packet.get_size() / 8);
+}
+
+static void handle_overflow_packet(const Overflow &packet)
+{
+ printf("Overflow\n");
+}
+
+static void handle_lts_packet(const LocalTimestamp &packet)
+{
+ const char *tc;
+
+ switch (packet.get_relation()) {
+ case LocalTimestampRelation::SYNC:
+ tc = "synchronous";
+ break;
+ case LocalTimestampRelation::TS:
+ tc = "timestamp delayed";
+ break;
+ case LocalTimestampRelation::SRC:
+ tc = "data delayed";
+ break;
+ case LocalTimestampRelation::BOTH:
+ tc = "data and timestamp delayed";
+ break;
+ default:
+ return;
+ }
+
+ printf("Local timestamp (relation = %s, value = %x)\n", tc,
+ packet.get_value());
+}
+
+static void handle_gts1_packet(const GlobalTimestamp1 &packet)
+{
+ printf("Global timestamp (GTS1) (wrap = %u, clkch = %u, value = %x)\n",
+ packet.get_wrap(), packet.get_clkch(), packet.get_value());
+}
+
+static void handle_gts2_packet(const GlobalTimestamp2 &packet)
+{
+ printf("Global timestamp (GTS2) (value = %x)\n", packet.get_value());
+}
+
+static void handle_ext_packet(const Extension &packet)
+{
+ const char *src;
+
+ switch (packet.get_source()) {
+ case ExtensionSource::ITM:
+ src = "ITM";
+ break;
+ case ExtensionSource::HW:
+ src = "HW";
+ break;
+ default:
+ return;
+ }
+
+ printf("Extension (source = %s, value = %x)\n", src, packet.get_value());
+}
+
+static void handle_inst_packet(const Instrumentation &packet)
+{
+ printf("Instrumentation (address = %u, value = %x, size = %zu bytes)\n",
+ packet.get_address(), packet.get_value(), packet.get_size() - 1);
+}
+
+static void handle_hw_packet(const Hardware &packet)
+{
+ printf("Hardware source (address = %u, value = %x, size = %zu bytes)\n",
+ packet.get_address(), packet.get_value(),
+ packet.get_size() - 1);
+}
+
+static void handle_evtcnt_packet(const EventCounter &packet)
+{
+ printf("Event counter (CPI = %u, exc = %u, sleep = %u, LSU = %u, "
+ "fold = %u, cyc = %u)\n", packet.get_cpi(), packet.get_exc(),
+ packet.get_sleep(), packet.get_lsu(), packet.get_fold(),
+ packet.get_cyc());
+}
+
+static void handle_exctrace_packet(const ExceptionTrace &packet)
+{
+ const char *function;
+
+ switch (packet.get_function()) {
+ case ExceptionTraceFunction::ENTER:
+ function = "enter";
+ break;
+ case ExceptionTraceFunction::EXIT:
+ function = "exit";
+ break;
+ case ExceptionTraceFunction::RETURN:
+ function = "return";
+ break;
+ default:
+ function = "reserved";
+ }
+
+ printf("Exception trace (function = %s, exception = %u)\n", function,
+ packet.get_exception());
+}
+
+static void handle_pc_sample_packet(const PCSample &packet)
+{
+ if (packet.get_sleep())
+ printf("Periodic PC sleep\n");
+ else
+ printf("Periodic PC sample (value = %x)\n", packet.get_value());
+}
+
+static void handle_pc_value_packet(const PCValue &packet)
+{
+ printf("Data trace PC value (comparator = %u, value = %x)\n",
+ packet.get_comparator(), packet.get_value());
+}
+
+static void handle_addr_offset_packet(const AddressOffset &packet)
+{
+ printf("Data trace address offset (comparator = %u, value = %x)\n",
+ packet.get_comparator(), packet.get_value());
+}
+
+static void handle_data_value_packet(const DataValue &packet)
+{
+ printf("Data trace data value (comparator = %u, WnR = %u, value = %x, "
+ "size = %zu bytes)\n", packet.get_comparator(),
+ packet.get_wnr(), packet.get_value(), packet.get_size());
+}
+
+int packet_callback(const Packet &packet, void *user_data)
+{
+ switch (packet.get_type()) {
+ case PacketType::UNKNOWN:
+ handle_unknown_packet(dynamic_cast<const Unknown &>(packet));
+ break;
+ case PacketType::SYNC:
+ handle_sync_packet(dynamic_cast<const Synchronization &>(packet));
+ break;
+ case PacketType::OF:
+ handle_overflow_packet(dynamic_cast<const Overflow &>(packet));
+ break;
+ case PacketType::LTS:
+ handle_lts_packet(dynamic_cast<const LocalTimestamp &>(packet));
+ break;
+ case PacketType::GTS1:
+ handle_gts1_packet(dynamic_cast<const GlobalTimestamp1 &>(packet));
+ break;
+ case PacketType::GTS2:
+ handle_gts2_packet(dynamic_cast<const GlobalTimestamp2 &>(packet));
+ break;
+ case PacketType::EXT:
+ handle_ext_packet(dynamic_cast<const Extension &>(packet));
+ break;
+ case PacketType::INST:
+ handle_inst_packet(dynamic_cast<const Instrumentation &>(packet));
+ break;
+ case PacketType::HW:
+ handle_hw_packet(dynamic_cast<const Hardware &>(packet));
+ break;
+ case PacketType::DWT_EVTCNT:
+ handle_evtcnt_packet(dynamic_cast<const EventCounter &>(packet));
+ break;
+ case PacketType::DWT_EXCTRACE:
+ handle_exctrace_packet(dynamic_cast<const ExceptionTrace &>(packet));
+ break;
+ case PacketType::DWT_PC_SAMPLE:
+ handle_pc_sample_packet(dynamic_cast<const PCSample &>(packet));
+ break;
+ case PacketType::DWT_PC_VALUE:
+ handle_pc_value_packet(dynamic_cast<const PCValue &>(packet));
+ break;
+ case PacketType::DWT_ADDR_OFFSET:
+ handle_addr_offset_packet(dynamic_cast<const AddressOffset &>(packet));
+ break;
+ case PacketType::DWT_DATA_VALUE:
+ handle_data_value_packet(dynamic_cast<const DataValue &>(packet));
+ break;
+ default:
+ std::cerr << "Unknown packet type" << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
+int main(int argc, char **argv)
+{
+ std::ifstream *file;
+ Context ctx(2 * BUFFER_SIZE);
+ char buffer[BUFFER_SIZE];
+ int length;
+ bool eof;
+
+ if (argc != 2) {
+ std::cerr << "Usage: " << argv[0] << " <filename>" << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ file = new std::ifstream(argv[1], std::ios::in | std::ios::binary);
+
+ if (!file->is_open()) {
+ std::cerr << argv[1] << ": " << strerror(errno) << std::endl;
+ delete file;
+ return EXIT_FAILURE;
+ }
+
+ ctx.set_callback(&packet_callback);
+ eof = file->eof();
+
+ while (!eof) {
+ file->read(buffer, BUFFER_SIZE);
+ length = file->gcount();
+
+ eof = file->eof();
+
+ try {
+ ctx.feed(reinterpret_cast<const uint8_t *>(buffer), length);
+ ctx.decode();
+ } catch (Error &e) {
+ std::cerr << e.what() << std::endl;
+ break;
+ }
+ }
+
+ file->close();
+ delete file;
+
+ if (!eof)
+ return EXIT_FAILURE;
+
+ try {
+ ctx.decode(DecoderFlags::EOS);
+ } catch (Error &e) {
+ std::cerr << e.what() << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}