Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions tools/ctrace/src/decode/DwtPacketDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ enum class DwtPacketSource : std::uint8_t {
EventCounter = 0U,
ExceptionTrace = 1U,
PeriodicPcSample = 2U,
PmuOverflow = 3U,
PmuTraceOnOverflow = 3U,
};

/** @brief Identifies address and value variants of DWT data-trace packets. */
Expand Down Expand Up @@ -50,6 +50,7 @@ constexpr std::uint8_t kDataTracePacketTypeShift = 3U;
constexpr std::uint32_t kExceptionNumberMask = 0x1ffU;
constexpr std::uint32_t kExceptionActionMask = 0x3U;
constexpr std::uint32_t kExceptionActionShift = 12U;
constexpr std::uint32_t kPmuOverflowMask = 0xffU;

constexpr std::uint8_t kArmv7MFullPcBytes = 4U;
constexpr std::uint8_t kArmv7MAddressOffsetBytes = 2U;
Expand All @@ -60,11 +61,20 @@ std::vector<TraceEvent> DwtPacketDecoder::decode(const DwtPayloadPacket& payload
const auto discriminator = payload.discriminator;

const auto source = static_cast<DwtPacketSource>(discriminator);
if (source == DwtPacketSource::EventCounter || source == DwtPacketSource::PmuOverflow) {
if (source == DwtPacketSource::EventCounter) {
output = flush(payload.quality, payload.tcyc);
TraceEvent packet = source == DwtPacketSource::EventCounter
? TraceEvent(DwtEventTraceEvent{discriminator, payload.size, payload.value})
: TraceEvent(PmuTraceEvent{discriminator, payload.size, payload.value});
TraceEvent packet{DwtEventTraceEvent{discriminator, payload.size, payload.value}};
packet.index = payload.index;
packet.traceBusId = payload.traceBusId;
packet.tcyc = payload.tcyc;
packet.quality = payload.quality;
output.push_back(std::move(packet));
return output;
}

if (source == DwtPacketSource::PmuTraceOnOverflow) {
output = flush(payload.quality, payload.tcyc);
TraceEvent packet{PmuTraceEvent{static_cast<std::uint8_t>(payload.value & kPmuOverflowMask)}};
packet.index = payload.index;
packet.traceBusId = payload.traceBusId;
packet.tcyc = payload.tcyc;
Expand Down
6 changes: 2 additions & 4 deletions tools/ctrace/src/model/TraceEvent.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,11 +132,9 @@ struct DwtEventTraceEvent {
std::uint32_t value = 0;
};

/** @brief Contains a decoded PMU overflow packet. */
/** @brief Contains the OVn counter mask from a decoded PMU trace-on-overflow packet. */
struct PmuTraceEvent {
std::uint32_t discriminator = 0;
std::uint8_t size = 0;
std::uint32_t value = 0;
std::uint8_t overflowMask = 0;
};

/** @brief Contains a periodic DWT PC sample or its processor-sleep indication. */
Expand Down
22 changes: 22 additions & 0 deletions tools/ctrace/test/integration/src/CtraceIntegTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,28 @@ TEST_F(CtraceIntegTests, GeneratesAllOutputs)
expectNonEmptyFile(workDirectory() / "Minimal.SWO.traceanalysis.xml");
}

TEST_F(CtraceIntegTests, IgnoresPmuPacketsUntilOutputSemanticsExist)
{
writeFile(workDirectory() / "Pmu.ctrace-run.yml", R"yml(ctrace-run:
ctrace-setup:
- timestamps:
clock: 400000000
ctrace-refs: []
)yml");

const std::string raw{"\0\0\0\0\0\x80\x1d\x81\x09\x41", 10U};
writeFile(workDirectory() / "Pmu.SWO.raw", raw);

const auto result = run({"ctrace", workDirectory().string(), "--target", "Pmu", "--all"});
EXPECT_EQ(0, result.exitCode) << result.stderrText;
EXPECT_EQ("cycles,stream,type,source,value,pc,offset,note\n"
"0,,itm,1,0x41,,,\n",
readTextFile(workDirectory() / "Pmu.SWO.csv"));
expectNonEmptyFile(workDirectory() / "Pmu.ctf" / "metadata");
expectNonEmptyFile(workDirectory() / "Pmu.ctf" / "stream_0");
expectNonEmptyFile(workDirectory() / "Pmu.SWO.traceanalysis.xml");
}

TEST_F(CtraceIntegTests, RejectsInvalidOptionCombination)
{
const auto result = run({"ctrace", "--version", "--type", "DWT"});
Expand Down
24 changes: 24 additions & 0 deletions tools/ctrace/test/unit/src/decode/CortexMPostDecoderTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,27 @@ TEST(CtraceUnitTests, testCortexMPostDecoderMapsDiscontinuityTimestamp)
ASSERT_TRUE(sink.events().size() == 3) << "timestamp discontinuity event count mismatch";
ASSERT_TRUE(sink.events()[2].tcyc == 207U) << "post-decoder explicit discontinuity timestamp mismatch";
}

TEST(CtraceUnitTests, testCortexMPostDecoderLabelsPmuTraceOnOverflowPacket)
{
CollectingEventSink sink;
CortexMPostDecoder decoder(sink);

decoder.append(openCsdTimestampElement(100U, 10U, 5U));
auto pmuElement = openCsdElement(OpenCsdTraceElement::Kind::Hardware, 24U, 5U);
pmuElement.discriminator = 3U;
pmuElement.size = 1U;
pmuElement.value = 0x81U;
decoder.append(pmuElement);
decoder.finish();

ASSERT_TRUE(sink.events().size() == 2U) << "post-decoder PMU event count mismatch";
const auto& packet = sink.events().back();
const auto* pmu = traceEventPayload<PmuTraceEvent>(packet);
ASSERT_TRUE(pmu != nullptr && pmu->overflowMask == 0x81U)
<< "post-decoder must label discriminator 3 as a PMU trace-on-overflow event";
ASSERT_TRUE(packet.index == 24U && packet.traceBusId == 5U && packet.tcyc == 100U)
<< "post-decoder PMU event context mismatch";
ASSERT_TRUE(packet.quality.has_value() && packet.quality->timestampReliable)
<< "post-decoder PMU timestamp quality mismatch";
}
2 changes: 1 addition & 1 deletion tools/ctrace/test/unit/src/decode/DecodePipelineTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ TEST(CtraceUnitTests, testDecodePipelinePreservesDwtEventAndPmuPackets)
const auto* pmu = traceEventPayload<PmuTraceEvent>(packet);
foundEvent =
foundEvent || (event != nullptr && event->discriminator == 0U && event->size == 1U && event->value == 0x21U);
foundPmu = foundPmu || (pmu != nullptr && pmu->discriminator == 3U && pmu->size == 1U && pmu->value == 0x81U);
foundPmu = foundPmu || (pmu != nullptr && pmu->overflowMask == 0x81U);
}
ASSERT_TRUE(foundEvent) << "OpenCSD DWT event-counter packet must survive post-decoding";
ASSERT_TRUE(foundPmu) << "OpenCSD PMU-overflow packet must survive post-decoding";
Expand Down
11 changes: 6 additions & 5 deletions tools/ctrace/test/unit/src/decode/DwtPacketDecoderTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,12 @@ TEST(CtraceUnitTests, testDwtCounterPacketsArePreservedUntilOutputSemanticsExist
ASSERT_TRUE((discriminator == 0U && event != nullptr && pmu == nullptr) ||
(discriminator == 3U && event == nullptr && pmu != nullptr))
<< "DWT counter semantic event type mismatch";
const auto actualDiscriminator = event != nullptr ? event->discriminator : pmu->discriminator;
const auto actualSize = event != nullptr ? event->size : pmu->size;
const auto actualValue = event != nullptr ? event->value : pmu->value;
ASSERT_TRUE(actualDiscriminator == discriminator) << "DWT counter discriminator mismatch";
ASSERT_TRUE(actualSize == 1U && actualValue == 0x21U) << "DWT counter payload mismatch";
if (event != nullptr) {
ASSERT_TRUE(event->discriminator == discriminator && event->size == 1U && event->value == 0x21U)
<< "DWT event-counter payload mismatch";
} else {
ASSERT_TRUE(pmu->overflowMask == 0x21U) << "PMU OVn counter mask mismatch";
}
ASSERT_TRUE(packet.index == 23U && packet.traceBusId == 4U) << "DWT counter identity mismatch";
ASSERT_TRUE(packet.tcyc == 949339100U) << "DWT counter timestamp mismatch";
ASSERT_TRUE(packet.quality.has_value() && packet.quality->overflow) << "DWT counter overflow status mismatch";
Expand Down
Loading