aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Schink <swo-dev@marcschink.de>2016-09-19 20:13:41 +0200
committerMarc Schink <swo-dev@marcschink.de>2016-09-30 21:40:49 +0200
commit0d5949e1cb68553bd76c25b25708c1875ed85db9 (patch)
treea93fb77eb8ec72cb83fdb0640eda5548d18ca25a
parentc9444c67d42f6a81f3c93555771368a4caac9882 (diff)
Add Data Watchpoint and Trace (DWT) support
-rw-r--r--bindings/cxx/AddressOffset.cpp60
-rw-r--r--bindings/cxx/Context.cpp18
-rw-r--r--bindings/cxx/DataValue.cpp65
-rw-r--r--bindings/cxx/EventCounter.cpp82
-rw-r--r--bindings/cxx/ExceptionTrace.cpp74
-rw-r--r--bindings/cxx/Makefile.am6
-rw-r--r--bindings/cxx/PCSample.cpp63
-rw-r--r--bindings/cxx/PCValue.cpp58
-rw-r--r--bindings/cxx/libswocxx.h92
-rw-r--r--bindings/python/swopy.i21
-rw-r--r--libswo/Makefile.am1
-rw-r--r--libswo/decoder.c17
-rw-r--r--libswo/dwt.c271
-rw-r--r--libswo/libswo-internal.h5
-rw-r--r--libswo/libswo.h168
15 files changed, 992 insertions, 9 deletions
diff --git a/bindings/cxx/AddressOffset.cpp b/bindings/cxx/AddressOffset.cpp
new file mode 100644
index 0000000..b75dffa
--- /dev/null
+++ b/bindings/cxx/AddressOffset.cpp
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the libswo project.
+ *
+ * Copyright (C) 2016 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 <sstream>
+
+#include "libswocxx.h"
+
+namespace libswo
+{
+
+AddressOffset::AddressOffset(
+ const struct libswo_packet_dwt_addr_offset *packet) :
+ Hardware((const struct libswo_packet_hw *)packet)
+{
+}
+
+AddressOffset::AddressOffset(const union libswo_packet *packet) :
+ Hardware(packet)
+{
+}
+
+uint8_t AddressOffset::get_comparator(void) const
+{
+ return _packet.addr_offset.cmpn;
+}
+
+uint16_t AddressOffset::get_offset(void) const
+{
+ return _packet.addr_offset.offset;
+}
+
+const std::string AddressOffset::to_string(void) const
+{
+ std::stringstream ss;
+
+ ss << "Data trace address offset (comparator = ";
+ ss << (unsigned int)get_comparator();
+ ss << ", offset = " << std::hex << get_offset();
+ ss << ", size = " << get_size() << " bytes)";
+
+ return ss.str();
+}
+
+}
diff --git a/bindings/cxx/Context.cpp b/bindings/cxx/Context.cpp
index e85d5b3..6061186 100644
--- a/bindings/cxx/Context.cpp
+++ b/bindings/cxx/Context.cpp
@@ -204,6 +204,24 @@ static int packet_callback(struct libswo_context *ctx,
case LIBSWO_PACKET_TYPE_UNKNOWN:
tmp = new Unknown(packet);
break;
+ case LIBSWO_PACKET_TYPE_DWT_EVTCNT:
+ tmp = new EventCounter(packet);
+ break;
+ case LIBSWO_PACKET_TYPE_DWT_EXCTRACE:
+ tmp = new ExceptionTrace(packet);
+ break;
+ case LIBSWO_PACKET_TYPE_DWT_PC_SAMPLE:
+ tmp = new PCSample(packet);
+ break;
+ case LIBSWO_PACKET_TYPE_DWT_PC_VALUE:
+ tmp = new PCValue(packet);
+ break;
+ case LIBSWO_PACKET_TYPE_DWT_ADDR_OFFSET:
+ tmp = new AddressOffset(packet);
+ break;
+ case LIBSWO_PACKET_TYPE_DWT_DATA_VALUE:
+ tmp = new DataValue(packet);
+ break;
default:
return LIBSWO_ERR;
}
diff --git a/bindings/cxx/DataValue.cpp b/bindings/cxx/DataValue.cpp
new file mode 100644
index 0000000..0573516
--- /dev/null
+++ b/bindings/cxx/DataValue.cpp
@@ -0,0 +1,65 @@
+/*
+ * This file is part of the libswo project.
+ *
+ * Copyright (C) 2016 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 <sstream>
+
+#include "libswocxx.h"
+
+namespace libswo
+{
+
+DataValue::DataValue(const struct libswo_packet_dwt_data_value *packet) :
+ Hardware((const struct libswo_packet_hw *)packet)
+{
+}
+
+DataValue::DataValue(const union libswo_packet *packet) :
+ Hardware(packet)
+{
+}
+
+bool DataValue::get_wnr(void) const
+{
+ return _packet.data_value.wnr;
+}
+
+uint8_t DataValue::get_comparator(void) const
+{
+ return _packet.data_value.cmpn;
+}
+
+uint32_t DataValue::get_data_value(void) const
+{
+ return _packet.data_value.data_value;
+}
+
+const std::string DataValue::to_string(void) const
+{
+ std::stringstream ss;
+
+ ss << "Data trace data value (comparator = ";
+ ss << (unsigned int)get_comparator();
+ ss << ", WnR = " << get_wnr();
+ ss << ", value = " << std::hex << get_data_value();
+ ss << ", size = " << get_size() << " bytes)";
+
+ return ss.str();
+}
+
+}
diff --git a/bindings/cxx/EventCounter.cpp b/bindings/cxx/EventCounter.cpp
new file mode 100644
index 0000000..430a6c8
--- /dev/null
+++ b/bindings/cxx/EventCounter.cpp
@@ -0,0 +1,82 @@
+/*
+ * This file is part of the libswo project.
+ *
+ * Copyright (C) 2016 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 <sstream>
+
+#include "libswocxx.h"
+
+namespace libswo
+{
+
+EventCounter::EventCounter(const struct libswo_packet_dwt_evtcnt *packet) :
+ Hardware((const struct libswo_packet_hw *)packet)
+{
+}
+
+EventCounter::EventCounter(const union libswo_packet *packet) :
+ Hardware(packet)
+{
+}
+
+bool EventCounter::get_cpi(void) const
+{
+ return _packet.evtcnt.cpi;
+}
+
+bool EventCounter::get_exc(void) const
+{
+ return _packet.evtcnt.exc;
+}
+
+bool EventCounter::get_sleep(void) const
+{
+ return _packet.evtcnt.sleep;
+}
+
+bool EventCounter::get_lsu(void) const
+{
+ return _packet.evtcnt.lsu;
+}
+
+bool EventCounter::get_fold(void) const
+{
+ return _packet.evtcnt.fold;
+}
+
+bool EventCounter::get_cyc(void) const
+{
+ return _packet.evtcnt.cyc;
+}
+
+const std::string EventCounter::to_string(void) const
+{
+ std::stringstream ss;
+
+ ss << "Event counter (CPI = " << get_cpi();
+ ss << ", exc = " << get_exc();
+ ss << ", sleep = " << get_sleep();
+ ss << ", LSU = " << get_lsu();
+ ss << ", fold = " << get_fold();
+ ss << ", cyc = " << get_cyc();
+ ss << ", size = " << get_size() << " bytes)";
+
+ return ss.str();
+}
+
+}
diff --git a/bindings/cxx/ExceptionTrace.cpp b/bindings/cxx/ExceptionTrace.cpp
new file mode 100644
index 0000000..6cf522a
--- /dev/null
+++ b/bindings/cxx/ExceptionTrace.cpp
@@ -0,0 +1,74 @@
+/*
+ * This file is part of the libswo project.
+ *
+ * Copyright (C) 2016 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 <sstream>
+
+#include "libswocxx.h"
+
+namespace libswo
+{
+
+ExceptionTrace::ExceptionTrace(
+ const struct libswo_packet_dwt_exctrace *packet) :
+ Hardware((const struct libswo_packet_hw *)packet)
+{
+}
+
+ExceptionTrace::ExceptionTrace(const union libswo_packet *packet) :
+ Hardware(packet)
+{
+}
+
+uint16_t ExceptionTrace::get_exception(void) const
+{
+ return _packet.exctrace.exception;
+}
+
+enum ExceptionTraceFunction ExceptionTrace::get_function(void) const
+{
+ return static_cast<ExceptionTraceFunction>(_packet.exctrace.function);
+}
+
+const std::string ExceptionTrace::to_string(void) const
+{
+ std::stringstream ss;
+
+ ss << "Exception trace (exception = " << get_exception();
+ ss << ", function = ";
+
+ switch (get_function()) {
+ case EXCTRACE_FUNC_ENTER:
+ ss << "enter";
+ break;
+ case EXCTRACE_FUNC_EXIT:
+ ss << "exit";
+ break;
+ case EXCTRACE_FUNC_RETURN:
+ ss << "return";
+ break;
+ default:
+ ss << "reserved";
+ }
+
+ ss << ", size = " << get_size() << " bytes)";
+
+ return ss.str();
+}
+
+}
diff --git a/bindings/cxx/Makefile.am b/bindings/cxx/Makefile.am
index b0c1d62..8e4d67e 100644
--- a/bindings/cxx/Makefile.am
+++ b/bindings/cxx/Makefile.am
@@ -20,8 +20,12 @@
lib_LTLIBRARIES = libswocxx.la
libswocxx_la_SOURCES = \
+ AddressOffset.cpp \
Context.cpp \
+ DataValue.cpp \
Error.cpp \
+ EventCounter.cpp \
+ ExceptionTrace.cpp \
Extension.cpp \
GlobalTimestamp1.cpp \
GlobalTimestamp2.cpp \
@@ -31,6 +35,8 @@ libswocxx_la_SOURCES = \
Overflow.cpp \
Packet.cpp \
PayloadPacket.cpp \
+ PCSample.cpp \
+ PCValue.cpp \
Synchronization.cpp \
Unknown.cpp \
Version.cpp
diff --git a/bindings/cxx/PCSample.cpp b/bindings/cxx/PCSample.cpp
new file mode 100644
index 0000000..6fbc357
--- /dev/null
+++ b/bindings/cxx/PCSample.cpp
@@ -0,0 +1,63 @@
+/*
+ * This file is part of the libswo project.
+ *
+ * Copyright (C) 2016 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 <sstream>
+
+#include "libswocxx.h"
+
+namespace libswo
+{
+
+PCSample::PCSample(const struct libswo_packet_dwt_pc_sample *packet) :
+ Hardware((const struct libswo_packet_hw *)packet)
+{
+}
+
+PCSample::PCSample(const union libswo_packet *packet) :
+ Hardware(packet)
+{
+}
+
+bool PCSample::get_sleep(void) const
+{
+ return _packet.pc_sample.sleep;
+}
+
+uint32_t PCSample::get_pc(void) const
+{
+ return _packet.pc_sample.pc;
+}
+
+const std::string PCSample::to_string(void) const
+{
+ std::stringstream ss;
+
+ if (get_sleep()) {
+ ss << "Periodic PC sleep (";
+ } else {
+ ss << "Periodic PC sample (PC = ";
+ ss << std::hex << get_pc() << ", ";
+ }
+
+ ss << "size = " << get_size() << " bytes)";
+
+ return ss.str();
+}
+
+}
diff --git a/bindings/cxx/PCValue.cpp b/bindings/cxx/PCValue.cpp
new file mode 100644
index 0000000..c1de390
--- /dev/null
+++ b/bindings/cxx/PCValue.cpp
@@ -0,0 +1,58 @@
+/*
+ * This file is part of the libswo project.
+ *
+ * Copyright (C) 2016 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 <sstream>
+
+#include "libswocxx.h"
+
+namespace libswo
+{
+PCValue::PCValue(const struct libswo_packet_dwt_pc_value *packet) :
+ Hardware((const struct libswo_packet_hw *)packet)
+{
+}
+
+PCValue::PCValue(const union libswo_packet *packet) :
+ Hardware(packet)
+{
+}
+
+uint8_t PCValue::get_comparator(void) const
+{
+ return _packet.pc_value.cmpn;
+}
+
+uint32_t PCValue::get_pc(void) const
+{
+ return _packet.pc_value.pc;
+}
+
+const std::string PCValue::to_string(void) const
+{
+ std::stringstream ss;
+
+ ss << "Data trace PC value (comperator = ";
+ ss << (unsigned int)get_comparator();
+ ss << ", PC = " << std::hex << get_pc();
+ ss << ", size = " << get_size() << " bytes)";
+
+ return ss.str();
+}
+
+}
diff --git a/bindings/cxx/libswocxx.h b/bindings/cxx/libswocxx.h
index 906fd81..01f92ff 100644
--- a/bindings/cxx/libswocxx.h
+++ b/bindings/cxx/libswocxx.h
@@ -49,7 +49,13 @@ enum PacketType {
PACKET_TYPE_GTS2 = LIBSWO_PACKET_TYPE_GTS2,
PACKET_TYPE_EXT = LIBSWO_PACKET_TYPE_EXT,
PACKET_TYPE_INST = LIBSWO_PACKET_TYPE_INST,
- PACKET_TYPE_HW = LIBSWO_PACKET_TYPE_HW
+ PACKET_TYPE_HW = LIBSWO_PACKET_TYPE_HW,
+ PACKET_TYPE_DWT_EVTCNT = LIBSWO_PACKET_TYPE_DWT_EVTCNT,
+ PACKET_TYPE_DWT_EXCTRACE = LIBSWO_PACKET_TYPE_DWT_EXCTRACE,
+ PACKET_TYPE_DWT_PC_SAMPLE = LIBSWO_PACKET_TYPE_DWT_PC_SAMPLE,
+ PACKET_TYPE_DWT_PC_VALUE = LIBSWO_PACKET_TYPE_DWT_PC_VALUE,
+ PACKET_TYPE_DWT_ADDR_OFFSET = LIBSWO_PACKET_TYPE_DWT_ADDR_OFFSET,
+ PACKET_TYPE_DWT_DATA_VALUE = LIBSWO_PACKET_TYPE_DWT_DATA_VALUE
};
enum LocalTimestampRelation {
@@ -64,6 +70,13 @@ enum ExtensionSource {
EXT_SRC_HW = LIBSWO_EXT_SRC_HW
};
+enum ExceptionTraceFunction {
+ EXCTRACE_FUNC_RESERVED = LIBSWO_EXCTRACE_FUNC_RESERVED,
+ EXCTRACE_FUNC_ENTER = LIBSWO_EXCTRACE_FUNC_ENTER,
+ EXCTRACE_FUNC_EXIT = LIBSWO_EXCTRACE_FUNC_EXIT,
+ EXCTRACE_FUNC_RETURN = LIBSWO_EXCTRACE_FUNC_RETURN
+};
+
enum DecoderFlags {
DF_EOS = LIBSWO_DF_EOS
};
@@ -203,6 +216,83 @@ public:
const string to_string(void) const;
};
+class LIBSWO_API EventCounter : public Hardware
+{
+public:
+ EventCounter(const struct libswo_packet_dwt_evtcnt *packet);
+ EventCounter(const union libswo_packet *packet);
+
+ bool get_cpi(void) const;
+ bool get_exc(void) const;
+ bool get_sleep(void) const;
+ bool get_lsu(void) const;
+ bool get_fold(void) const;
+ bool get_cyc(void) const;
+
+ const string to_string(void) const;
+};
+
+class LIBSWO_API ExceptionTrace : public Hardware
+{
+public:
+ ExceptionTrace(const struct libswo_packet_dwt_exctrace *packet);
+ ExceptionTrace(const union libswo_packet *packet);
+
+ uint16_t get_exception(void) const;
+ enum ExceptionTraceFunction get_function(void) const;
+
+ const string to_string(void) const;
+};
+
+class LIBSWO_API PCSample : public Hardware
+{
+public:
+ PCSample(const struct libswo_packet_dwt_pc_sample *packet);
+ PCSample(const union libswo_packet *packet);
+
+ bool get_sleep(void) const;
+ uint32_t get_pc(void) const;
+
+ const string to_string(void) const;
+};
+
+class LIBSWO_API PCValue : public Hardware
+{
+public:
+ PCValue(const struct libswo_packet_dwt_pc_value *packet);
+ PCValue(const union libswo_packet *packet);
+
+ uint8_t get_comparator(void) const;
+ uint32_t get_pc(void) const;
+
+ const string to_string(void) const;
+};
+
+class LIBSWO_API AddressOffset : public Hardware
+{
+public:
+ AddressOffset(const struct libswo_packet_dwt_addr_offset *packet);
+ AddressOffset(const union libswo_packet *packet);
+
+ uint8_t get_comparator(void) const;
+ uint16_t get_offset(void) const;
+
+ const string to_string(void) const;
+};
+
+class LIBSWO_API DataValue : public Hardware
+{
+public:
+ DataValue(const struct libswo_packet_dwt_data_value *packet);
+ DataValue(const union libswo_packet *packet);
+
+ bool get_wnr(void) const;
+ uint8_t get_comparator(void) const;
+ uint32_t get_data_value(void) const;
+
+ const string to_string(void) const;
+};
+
class LIBSWO_PRIV DecoderCallbackHelper
{
public:
diff --git a/bindings/python/swopy.i b/bindings/python/swopy.i
index f42a5d2..7fbb621 100644
--- a/bindings/python/swopy.i
+++ b/bindings/python/swopy.i
@@ -195,6 +195,27 @@ static PyObject *packet_object(const libswo::Packet &packet)
case libswo::PACKET_TYPE_HW:
ret = SWIG_NewPointerObj(tmp, SWIGTYPE_p_libswo__Hardware, 0);
break;
+ case libswo::PACKET_TYPE_DWT_EVTCNT:
+ ret = SWIG_NewPointerObj(tmp, SWIGTYPE_p_libswo__EventCounter,
+ 0);
+ break;
+ case libswo::PACKET_TYPE_DWT_EXCTRACE:
+ ret = SWIG_NewPointerObj(tmp,
+ SWIGTYPE_p_libswo__ExceptionTrace, 0);
+ break;
+ case libswo::PACKET_TYPE_DWT_PC_SAMPLE:
+ ret = SWIG_NewPointerObj(tmp, SWIGTYPE_p_libswo__PCSample, 0);
+ break;
+ case libswo::PACKET_TYPE_DWT_PC_VALUE:
+ ret = SWIG_NewPointerObj(tmp, SWIGTYPE_p_libswo__PCValue, 0);
+ break;
+ case libswo::PACKET_TYPE_DWT_ADDR_OFFSET:
+ ret = SWIG_NewPointerObj(tmp,
+ SWIGTYPE_p_libswo__AddressOffset, 0);
+ break;
+ case libswo::PACKET_TYPE_DWT_DATA_VALUE:
+ ret = SWIG_NewPointerObj(tmp, SWIGTYPE_p_libswo__DataValue, 0);
+ break;
default:
ret = NULL;
}
diff --git a/libswo/Makefile.am b/libswo/Makefile.am
index a58d108..ff32dea 100644
--- a/libswo/Makefile.am
+++ b/libswo/Makefile.am
@@ -23,6 +23,7 @@ libswo_la_SOURCES = \
buffer.c \
core.c \
decoder.c \
+ dwt.c \
error.c \
log.c \
version.c
diff --git a/libswo/decoder.c b/libswo/decoder.c
index c866674..0888eef 100644
--- a/libswo/decoder.c
+++ b/libswo/decoder.c
@@ -419,22 +419,25 @@ static bool decode_inst_packet(struct libswo_context *ctx, uint8_t header)
static bool decode_hw_packet(struct libswo_context *ctx, uint8_t header)
{
uint8_t payload_size;
+ struct libswo_packet_hw hw;
payload_size = 1 << ((header & SRC_SIZE_MASK) - 1);
- if (!buffer_peek(ctx, ctx->packet.hw.payload, payload_size, 1)) {
+ if (!buffer_peek(ctx, hw.payload, payload_size, 1)) {
log_dbg(ctx, "Not enough bytes available to decode hardware "
"source packet.");
return false;
}
- ctx->packet.type = LIBSWO_PACKET_TYPE_HW;
- ctx->packet.hw.size = payload_size + 1;
- ctx->packet.hw.address = (header & SRC_ADDR_MASK) >> SRC_ADDR_OFFSET;
- ctx->packet.hw.value = decode_payload(ctx->packet.hw.payload,
- payload_size);
+ hw.type = LIBSWO_PACKET_TYPE_HW;
+ hw.size = payload_size + 1;
+ hw.address = (header & SRC_ADDR_MASK) >> SRC_ADDR_OFFSET;
+ hw.value = decode_payload(hw.payload, payload_size);
- log_dbg(ctx, "Hardware source packet decoded.");
+ if (!dwt_decode_packet(ctx, &hw)) {
+ log_dbg(ctx, "Hardware source packet decoded.");
+ ctx->packet.hw = hw;
+ }
return true;
}
diff --git a/libswo/dwt.c b/libswo/dwt.c
new file mode 100644
index 0000000..75c436e
--- /dev/null
+++ b/libswo/dwt.c
@@ -0,0 +1,271 @@
+/*
+ * This file is part of the libswo project.
+ *
+ * Copyright (C) 2016 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 <stdint.h>
+#include <stdbool.h>
+
+#include "libswo-internal.h"
+
+/* Event counter packet discriminator ID. */
+#define EVTCNT_ID 0
+
+/* Size of an event counter packet in bytes. */
+#define EVTCNT_SIZE 2
+
+/* Bitmask for the CPI flag of an event counter packet. */
+#define EVTCNT_CPI_MASK 0x01
+
+/* Bitmask for the Exc flag of an event counter packet. */
+#define EVTCNT_EXC_MASK 0x02
+
+/* Bitmask for the Sleep flag of an event counter packet. */
+#define EVTCNT_SLEEP_MASK 0x04
+
+/* Bitmask for the LSU flag of an event counter packet. */
+#define EVTCNT_LSU_MASK 0x08
+
+/* Bitmask for the Fold flag of an event counter packet. */
+#define EVTCNT_FOLD_MASK 0x10
+
+/* Bitmask for the Cyc flag of an event counter packet. */
+#define EVTCNT_CYC_MASK 0x20
+
+/* Exception trace packet discriminator ID. */
+#define EXCTRACE_ID 1
+
+/* Size of an exception trace packet in bytes. */
+#define EXCTRACE_SIZE 3
+
+/* Bitmask for the exception number of an exception trace packet. */
+#define EXCTRACE_EX_MASK 0x01
+
+/* Offset of the exception number of an exception trace packet. */
+#define EXCTRACE_EX_OFFSET 8
+
+/* Bitmask for the function of an exception trace packet. */
+#define EXCTRACE_FN_MASK 0x30
+
+/* Offset of the function of an exception trace packet. */
+#define EXCTRACE_FN_OFFSET 4
+
+/* Periodic PC sample packet discriminator ID. */
+#define PC_SAMPLE_ID 2
+
+/* Size of a periodic PC sleep packet in bytes. */
+#define PC_SAMPLE_SLEEP_SIZE 2
+
+/* Size of a periodic PC sample packet in bytes. */
+#define PC_SAMPLE_SIZE 5
+
+/* Bitmask for the comparator number of a data trace packet. */
+#define CMPN_MASK 0x06
+
+/* Offset of the comparator number of a data trace packet. */
+#define CMPN_OFFSET 1
+
+/* Bitmask for the WnR flag of a data trace data value packet. */
+#define WNR_MASK 0x01
+
+/* Bitmask for the data trace PC value packet header. */
+#define PC_VALUE_HEADER_MASK 0x19
+
+/* Data trace PC value packet header. */
+#define PC_VALUE_HEADER 0x08
+
+/* Size of a data trace PC value packet in bytes. */
+#define PC_VALUE_SIZE 5
+
+/* Bitmask for the data trace address offset packet header. */
+#define ADDR_OFFSET_HEADER_MASK 0x19
+
+/* Data trace address offset packet header. */
+#define ADDR_OFFSET_HEADER 0x09
+
+/* Size of a data trace address offset packet in bytes. */
+#define ADDR_OFFSET_SIZE 3
+
+/* Bitmask for the data trace data value packet header. */
+#define DATA_VALUE_HEADER_MASK 0x18
+
+/* Data trace data value packet header. */
+#define DATA_VALUE_HEADER 0x10
+
+static bool decode_evtcnt_packet(struct libswo_context *ctx,
+ const struct libswo_packet_hw *hw)
+{
+ if (hw->size != EVTCNT_SIZE) {
+ log_warn(ctx, "Event counter packet with invalid size of %zu "
+ "bytes.", hw->size);
+ return false;
+ }
+
+ ctx->packet.hw = *hw;
+ ctx->packet.evtcnt.type = LIBSWO_PACKET_TYPE_DWT_EVTCNT;
+
+ ctx->packet.evtcnt.cpi = hw->payload[0] & EVTCNT_CPI_MASK;
+ ctx->packet.evtcnt.exc = hw->payload[0] & EVTCNT_EXC_MASK;
+ ctx->packet.evtcnt.sleep = hw->payload[0] & EVTCNT_SLEEP_MASK;
+ ctx->packet.evtcnt.lsu = hw->payload[0] & EVTCNT_LSU_MASK;
+ ctx->packet.evtcnt.fold = hw->payload[0] & EVTCNT_FOLD_MASK;
+ ctx->packet.evtcnt.cyc = hw->payload[0] & EVTCNT_CYC_MASK;
+
+ log_dbg(ctx, "Event counter packet decoded.");
+
+ return true;
+}
+
+static bool decode_exctrace_packet(struct libswo_context *ctx,
+ const struct libswo_packet_hw *hw)
+{
+ uint16_t exception;
+ uint8_t tmp;
+
+ if (hw->size != EXCTRACE_SIZE) {
+ log_warn(ctx, "Exception trace packet with invalid size of "
+ "%zu bytes.", hw->size);
+ return false;
+ }
+
+ ctx->packet.hw = *hw;
+ ctx->packet.type = LIBSWO_PACKET_TYPE_DWT_EXCTRACE;
+
+ exception = hw->payload[0];
+ exception |= (hw->payload[1] & EXCTRACE_EX_MASK) << EXCTRACE_EX_OFFSET;
+ tmp = (hw->payload[1] & EXCTRACE_FN_MASK) >> EXCTRACE_FN_OFFSET;
+
+ ctx->packet.exctrace.exception = exception;
+ ctx->packet.exctrace.function = tmp;
+
+ log_dbg(ctx, "Exception trace packet decoded.");
+
+ return true;
+}
+
+static bool decode_pc_sample_packet(struct libswo_context *ctx,
+ const struct libswo_packet_hw *hw)
+{
+ ctx->packet.hw = *hw;
+ ctx->packet.type = LIBSWO_PACKET_TYPE_DWT_PC_SAMPLE;
+
+ if (hw->size == PC_SAMPLE_SLEEP_SIZE) {
+ if (hw->value > 0) {
+ log_warn(ctx, "Periodic PC sleep packet contains "
+ "invalid value: %x.", hw->value);
+ return false;
+ }
+
+ ctx->packet.pc_sample.sleep = true;
+ log_dbg(ctx, "Periodic PC sleep packet decoded.");
+ } else if (hw->size == PC_SAMPLE_SIZE) {
+ ctx->packet.pc_sample.sleep = false;
+ log_dbg(ctx, "Periodic PC sample packet decoded.");
+ } else {
+ log_warn(ctx, "Periodic PC sample packet with invalid size of "
+ "%zu bytes.", hw->size);
+ return false;
+ }
+
+ ctx->packet.pc_sample.pc = hw->value;
+
+ return true;
+}
+
+static bool decode_pc_value_packet(struct libswo_context *ctx,
+ const struct libswo_packet_hw *hw)
+{
+ if (hw->size != PC_VALUE_SIZE) {
+ log_warn(ctx, "Data trace PC value packet with invalid size "
+ "of %zu bytes.", hw->size);
+ return false;
+ }
+
+ ctx->packet.hw = *hw;
+ ctx->packet.type = LIBSWO_PACKET_TYPE_DWT_PC_VALUE;
+
+ ctx->packet.pc_value.cmpn = (hw->address & CMPN_MASK) >> CMPN_OFFSET;
+ ctx->packet.pc_value.pc = hw->value;
+
+ log_dbg(ctx, "Data trace PC value packet decoded.");
+
+ return true;
+}
+
+static bool decode_address_offset_packet(struct libswo_context *ctx,
+ const struct libswo_packet_hw *hw)
+{
+ if (hw->size != ADDR_OFFSET_SIZE) {
+ log_warn(ctx, "Data trace address offset packet with invalid "
+ "size of %zu bytes.", hw->size);
+ return false;
+ }
+
+ ctx->packet.hw = *hw;
+ ctx->packet.type = LIBSWO_PACKET_TYPE_DWT_ADDR_OFFSET;
+
+ ctx->packet.addr_offset.cmpn = (hw->address & CMPN_MASK) >> \
+ CMPN_OFFSET;
+ ctx->packet.addr_offset.offset = hw->value;
+
+ log_dbg(ctx, "Data trace address offset packet decoded.");
+
+ return true;
+}
+
+static bool decode_data_value_packet(struct libswo_context *ctx,
+ const struct libswo_packet_hw *hw)
+{
+ ctx->packet.hw = *hw;
+ ctx->packet.type = LIBSWO_PACKET_TYPE_DWT_DATA_VALUE;
+
+ ctx->packet.data_value.wnr = hw->address & WNR_MASK;
+ ctx->packet.data_value.cmpn = (hw->address & CMPN_MASK) >> CMPN_OFFSET;
+ ctx->packet.data_value.data_value = hw->value;
+
+ log_dbg(ctx, "Data trace data value packet decoded.");
+
+ return true;
+}
+
+/**
+ * Decode hardware packet as Data Watchpoint and Trace (DWT) packet.
+ *
+ * @param[in,out] ctx libswo context.
+ * @param[in] hw Hardware packet.
+ *
+ * @retval true Packet decoded successfully.
+ * @retval false Packet could not be decoded.
+ */
+LIBSWO_PRIV bool dwt_decode_packet(struct libswo_context *ctx,
+ const struct libswo_packet_hw *hw)
+{
+ if (hw->address == EVTCNT_ID)
+ return decode_evtcnt_packet(ctx, hw);
+ else if (hw->address == EXCTRACE_ID)
+ return decode_exctrace_packet(ctx, hw);
+ else if (hw->address == PC_SAMPLE_ID)
+ return decode_pc_sample_packet(ctx, hw);
+ else if ((hw->address & PC_VALUE_HEADER_MASK) == PC_VALUE_HEADER)
+ return decode_pc_value_packet(ctx, hw);
+ else if ((hw->address & ADDR_OFFSET_HEADER_MASK) == ADDR_OFFSET_HEADER)
+ return decode_address_offset_packet(ctx, hw);
+ else if ((hw->address & DATA_VALUE_HEADER_MASK) == DATA_VALUE_HEADER)
+ return decode_data_value_packet(ctx, hw);
+
+ return false;
+}
diff --git a/libswo/libswo-internal.h b/libswo/libswo-internal.h
index b2903a4..7c2c4cc 100644
--- a/libswo/libswo-internal.h
+++ b/libswo/libswo-internal.h
@@ -77,6 +77,11 @@ LIBSWO_PRIV bool buffer_peek(const struct libswo_context *ctx, uint8_t *buffer,
LIBSWO_PRIV bool buffer_remove(struct libswo_context *ctx, size_t length);
LIBSWO_PRIV void buffer_flush(struct libswo_context *ctx);
+/*--- dwt.c -----------------------------------------------------------------*/
+
+LIBSWO_PRIV bool dwt_decode_packet(struct libswo_context *ctx,
+ const struct libswo_packet_hw *hw);
+
/*--- log.c -----------------------------------------------------------------*/
LIBSWO_PRIV int log_vprintf(struct libswo_context *ctx,
diff --git a/libswo/libswo.h b/libswo/libswo.h
index e4f508c..2a9f4f1 100644
--- a/libswo/libswo.h
+++ b/libswo/libswo.h
@@ -87,7 +87,19 @@ enum libswo_packet_type {
/** Instrumentation packet. */
LIBSWO_PACKET_TYPE_INST = 7,
/** Hardware source packet. */
- LIBSWO_PACKET_TYPE_HW = 8
+ LIBSWO_PACKET_TYPE_HW = 8,
+ /** DWT: Event counter packet. */
+ LIBSWO_PACKET_TYPE_DWT_EVTCNT = 16,
+ /** DWT: Exception trace packet. */
+ LIBSWO_PACKET_TYPE_DWT_EXCTRACE = 17,
+ /** DWT: Periodic PC sample packet. */
+ LIBSWO_PACKET_TYPE_DWT_PC_SAMPLE = 18,
+ /** DWT: Data trace PC value packet. */
+ LIBSWO_PACKET_TYPE_DWT_PC_VALUE = 19,
+ /** DWT: Data trace address offset packet. */
+ LIBSWO_PACKET_TYPE_DWT_ADDR_OFFSET = 20,
+ /** DWT: Data trace data value packet. */
+ LIBSWO_PACKET_TYPE_DWT_DATA_VALUE = 21
};
/** Local timestamp relation information. */
@@ -121,6 +133,18 @@ enum libswo_decoder_flags {
LIBSWO_DF_EOS = (1 << 0)
};
+/** Exception trace functions. */
+enum libswo_exctrace_function {
+ /** Reserved. */
+ LIBSWO_EXCTRACE_FUNC_RESERVED = 0,
+ /** Enter exception. */
+ LIBSWO_EXCTRACE_FUNC_ENTER = 1,
+ /** Exit exception. */
+ LIBSWO_EXCTRACE_FUNC_EXIT = 2,
+ /** Return to exception. */
+ LIBSWO_EXCTRACE_FUNC_RETURN = 3
+};
+
/** Maximum payload size of a packet in bytes. */
#define LIBSWO_MAX_PAYLOAD_SIZE 4
@@ -284,6 +308,136 @@ struct libswo_packet_hw {
uint32_t value;
};
+/** DWT: Event counter packet. */
+struct libswo_packet_dwt_evtcnt {
+ /** Packet type. */
+ enum libswo_packet_type type;
+ /** Packet size including the header in bytes. */
+ size_t size;
+ /** Packet data. */
+ uint8_t data[1 + LIBSWO_MAX_PAYLOAD_SIZE];
+ /** Address. */
+ uint8_t address;
+ /** Hardware source data. */
+ uint8_t payload[LIBSWO_MAX_PAYLOAD_SIZE];
+ /** Integer representation of the payload. */
+ uint32_t value;
+ /** Indicates whether the CPICNT value wrapped around to zero. */
+ bool cpi;
+ /** Indicates whether the EXCCNT value wrapped around to zero. */
+ bool exc;
+ /** Indicates whether the SLEEPCNT value wrapped around to zero. */
+ bool sleep;
+ /** Indicates whether the LSUCNT value wrapped around to zero. */
+ bool lsu;
+ /** Indicates whether the FOLDCNT value wrapped around to zero. */
+ bool fold;
+ /** Indicates whether the CYCCNT value wrapped around to zero. */
+ bool cyc;
+};
+
+/** DWT: Exception trace packet. */
+struct libswo_packet_dwt_exctrace {
+ /** Packet type. */
+ enum libswo_packet_type type;
+ /** Packet size including the header in bytes. */
+ size_t size;
+ /** Packet data. */
+ uint8_t data[1 + LIBSWO_MAX_PAYLOAD_SIZE];
+ /** Address. */
+ uint8_t address;
+ /** Hardware source data. */
+ uint8_t payload[LIBSWO_MAX_PAYLOAD_SIZE];
+ /** Integer representation of the payload. */
+ uint32_t value;
+ /** Exception number. */
+ uint16_t exception;
+ /** Action taken by the processor. */
+ enum libswo_exctrace_function function;
+};
+
+/** DWT: Periodic PC sample packet. */
+struct libswo_packet_dwt_pc_sample {
+ /** Packet type. */
+ enum libswo_packet_type type;
+ /** Packet size including the header in bytes. */
+ size_t size;
+ /** Packet data. */
+ uint8_t data[1 + LIBSWO_MAX_PAYLOAD_SIZE];
+ /** Address. */
+ uint8_t address;
+ /** Hardware source data. */
+ uint8_t payload[LIBSWO_MAX_PAYLOAD_SIZE];
+ /** Integer representation of the payload. */
+ uint32_t value;
+ /** Indicates whether the processor is in sleep mode. */
+ bool sleep;
+ /** Program counter (PC) value. */
+ uint32_t pc;
+};
+
+/** DWT: Data trace PC value packet. */
+struct libswo_packet_dwt_pc_value {
+ /** Packet type. */
+ enum libswo_packet_type type;
+ /** Packet size including the header in bytes. */
+ size_t size;
+ /** Packet data. */
+ uint8_t data[1 + LIBSWO_MAX_PAYLOAD_SIZE];
+ /** Address. */
+ uint8_t address;
+ /** Hardware source data. */
+ uint8_t payload[LIBSWO_MAX_PAYLOAD_SIZE];
+ /** Integer representation of the payload. */
+ uint32_t value;
+ /** Number of the comparator that generated the packet. */
+ uint8_t cmpn;
+ /** Program counter (PC) value. */
+ uint32_t pc;
+};
+
+/** DWT: Data trace address offset packet. */
+struct libswo_packet_dwt_addr_offset {
+ /** Packet type. */
+ enum libswo_packet_type type;
+ /** Packet size including the header in bytes. */
+ size_t size;
+ /** Packet data. */
+ uint8_t data[1 + LIBSWO_MAX_PAYLOAD_SIZE];
+ /** Address. */
+ uint8_t address;
+ /** Hardware source data. */
+ uint8_t payload[LIBSWO_MAX_PAYLOAD_SIZE];
+ /** Integer representation of the payload. */
+ uint32_t value;
+ /** Number of the comparator that generated the packet. */
+ uint8_t cmpn;
+ /** Address offset. */
+ uint16_t offset;
+};
+
+/** DWT: Data trace data value packet. */
+struct libswo_packet_dwt_data_value {
+ /** Packet type. */
+ enum libswo_packet_type type;
+ /** Packet size including the header in bytes. */
+ size_t size;
+ /** Packet data. */
+ uint8_t data[1 + LIBSWO_MAX_PAYLOAD_SIZE];
+ /** Address. */
+ uint8_t address;
+ /** Hardware source data. */
+ uint8_t payload[LIBSWO_MAX_PAYLOAD_SIZE];
+ /** Integer representation of the payload. */
+ uint32_t value;
+ /** Indicates whether it was a write or read access. */
+ bool wnr;
+ /** Number of the comparator that generated the packet. */
+ uint8_t cmpn;
+ /** Data value. */
+ uint32_t data_value;
+};
+
/** Union of all packet types. */
union libswo_packet {
/** Packet type. */
@@ -308,6 +462,18 @@ union libswo_packet {
struct libswo_packet_inst inst;
/** Hardware source packet. */
struct libswo_packet_hw hw;
+ /** DWT: Event counter packet. */
+ struct libswo_packet_dwt_evtcnt evtcnt;
+ /** DWT: Exception trace packet. */
+ struct libswo_packet_dwt_exctrace exctrace;
+ /** DWT: Periodic PC sample packet. */
+ struct libswo_packet_dwt_pc_sample pc_sample;
+ /** DWT: Data trace PC value packet. */
+ struct libswo_packet_dwt_pc_value pc_value;
+ /** DWT: Data trace address offset packet. */
+ struct libswo_packet_dwt_addr_offset addr_offset;
+ /** DWT: Data trace data value packet. */
+ struct libswo_packet_dwt_data_value data_value;
};
/**