From 9a2167bd64e91790ba14bc44ea860efcfd810fd8 Mon Sep 17 00:00:00 2001 From: Christian Babeux Date: Fri, 27 Sep 2013 17:10:43 -0400 Subject: [PATCH] Add Freescale Nexus decoder implementation MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This feature can be optionally enabled via the "--enable-nexus" configure option. This code is unsupported and is available on an "as is" basis. See converter/nexus/README for instructions on how to use the nexdump utility with Nexus hardware traces. Signed-off-by: Christian Babeux Signed-off-by: Jérémie Galarneau --- configure.ac | 10 +- converter/Makefile.am | 4 + converter/nexus/AUTHORS | 1 + converter/nexus/AUXMessageProtocol.cpp | 124 ++ converter/nexus/AUXMessageProtocol.h | 91 ++ converter/nexus/Application.cpp | 228 +++ converter/nexus/Application.h | 142 ++ converter/nexus/COPYING | 21 + converter/nexus/ChangeLog | 3 + converter/nexus/FManDebugLog.cpp | 874 ++++++++++++ converter/nexus/FManDebugLog.h | 631 +++++++++ converter/nexus/FManDebugLogVisitor.cpp | 99 ++ converter/nexus/FManDebugLogVisitor.h | 111 ++ converter/nexus/FullAddressVisitor.cpp | 109 ++ converter/nexus/FullAddressVisitor.h | 127 ++ converter/nexus/LICENSE.txt | 21 + converter/nexus/MSEState.cpp | 110 ++ converter/nexus/MSEState.h | 181 +++ converter/nexus/Makefile.am | 47 + converter/nexus/NEWS | 0 converter/nexus/NxMessage.cpp | 1677 +++++++++++++++++++++++ converter/nexus/NxMessage.h | 1213 ++++++++++++++++ converter/nexus/NxMessageDecoder.cpp | 78 ++ converter/nexus/NxMessageDecoder.h | 68 + converter/nexus/NxMessageVisitor.h | 104 ++ converter/nexus/NxPacketDecoder.cpp | 180 +++ converter/nexus/NxPacketDecoder.h | 65 + converter/nexus/NxPacketSet.cpp | 186 +++ converter/nexus/NxPacketSet.h | 153 +++ converter/nexus/README | 26 + converter/nexus/SizedAddress.cpp | 89 ++ converter/nexus/SizedAddress.h | 153 +++ converter/nexus/main.cpp | 113 ++ 33 files changed, 7038 insertions(+), 1 deletion(-) create mode 100644 converter/nexus/AUTHORS create mode 100644 converter/nexus/AUXMessageProtocol.cpp create mode 100644 converter/nexus/AUXMessageProtocol.h create mode 100644 converter/nexus/Application.cpp create mode 100644 converter/nexus/Application.h create mode 100644 converter/nexus/COPYING create mode 100644 converter/nexus/ChangeLog create mode 100644 converter/nexus/FManDebugLog.cpp create mode 100644 converter/nexus/FManDebugLog.h create mode 100644 converter/nexus/FManDebugLogVisitor.cpp create mode 100644 converter/nexus/FManDebugLogVisitor.h create mode 100644 converter/nexus/FullAddressVisitor.cpp create mode 100644 converter/nexus/FullAddressVisitor.h create mode 100644 converter/nexus/LICENSE.txt create mode 100644 converter/nexus/MSEState.cpp create mode 100644 converter/nexus/MSEState.h create mode 100644 converter/nexus/Makefile.am create mode 100644 converter/nexus/NEWS create mode 100644 converter/nexus/NxMessage.cpp create mode 100644 converter/nexus/NxMessage.h create mode 100644 converter/nexus/NxMessageDecoder.cpp create mode 100644 converter/nexus/NxMessageDecoder.h create mode 100644 converter/nexus/NxMessageVisitor.h create mode 100644 converter/nexus/NxPacketDecoder.cpp create mode 100644 converter/nexus/NxPacketDecoder.h create mode 100644 converter/nexus/NxPacketSet.cpp create mode 100644 converter/nexus/NxPacketSet.h create mode 100644 converter/nexus/README create mode 100644 converter/nexus/SizedAddress.cpp create mode 100644 converter/nexus/SizedAddress.h create mode 100644 converter/nexus/main.cpp diff --git a/configure.ac b/configure.ac index 067ef727..ca009c92 100644 --- a/configure.ac +++ b/configure.ac @@ -18,6 +18,7 @@ AC_SYS_LARGEFILE # Checks for programs. AC_PROG_CC_STDC +AC_PROG_CXX AC_PROG_MAKE_SET LT_INIT AC_PROG_YACC @@ -101,7 +102,6 @@ AC_CHECK_LIB([popt], [poptGetContext], [], [AC_MSG_ERROR([Cannot find popt.])] ) - # For Python # SWIG version needed or newer: swig_version=2.0.0 @@ -138,6 +138,13 @@ else fi +AC_ARG_ENABLE([nexus], + [AC_HELP_STRING([--enable-nexus], + [compile Nexus trace converter])], + [enable_nexus=yes], [enable_nexus=no]) + +AM_CONDITIONAL([BUILD_NEXUS], [test "x${enable_nexus}" = xyes]) + pkg_modules="gmodule-2.0 >= 2.0.0" PKG_CHECK_MODULES(GMODULE, [$pkg_modules]) AC_SUBST(PACKAGE_LIBS) @@ -170,6 +177,7 @@ AC_CONFIG_FILES([ formats/ctf/metadata/Makefile formats/ctf/writer/Makefile converter/Makefile + converter/nexus/Makefile doc/Makefile lib/Makefile lib/prio_heap/Makefile diff --git a/converter/Makefile.am b/converter/Makefile.am index 374d1d47..7ab36843 100644 --- a/converter/Makefile.am +++ b/converter/Makefile.am @@ -1,6 +1,10 @@ AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include AM_LDFLAGS = -lpopt +if BUILD_NEXUS +SUBDIRS = nexus +endif + bin_PROGRAMS = babeltrace babeltrace-log babeltrace_SOURCES = \ diff --git a/converter/nexus/AUTHORS b/converter/nexus/AUTHORS new file mode 100644 index 00000000..baae5760 --- /dev/null +++ b/converter/nexus/AUTHORS @@ -0,0 +1 @@ +freescale.com diff --git a/converter/nexus/AUXMessageProtocol.cpp b/converter/nexus/AUXMessageProtocol.cpp new file mode 100644 index 00000000..665fe557 --- /dev/null +++ b/converter/nexus/AUXMessageProtocol.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "AUXMessageProtocol.h" +#include "MSEState.h" +#include +#include +using std::cout; +using std::endl; + +AUXMessageProtocol::AUXMessageProtocol() : + verbose_(false) +{ + // create all the states we need + idle_ = new MSEIdle(); + start_message_ = new MSEStartMessage(); + normal_transfer_ = new MSENormalTransfer(); + end_packet_ = new MSEEndPacket(); + end_message_ = new MSEEndMessage(); + + // setup the state transitions based on IEEE-ISTO 5001 2003 page 91 + idle_->initialize_transitions(start_message_, end_packet_, end_message_, + idle_); + start_message_->initialize_transitions(normal_transfer_, end_packet_, + start_message_, end_message_); + normal_transfer_->initialize_transitions(normal_transfer_, end_packet_, + normal_transfer_/* ? */, end_message_); + end_packet_->initialize_transitions(normal_transfer_, end_packet_, + end_packet_/* ? */, end_message_); + end_message_->initialize_transitions(start_message_, end_packet_, + end_message_, idle_); + + // pick an initial state + current_state_ = idle_; +} + +AUXMessageProtocol::~AUXMessageProtocol() +{ + delete idle_; + delete start_message_; + delete normal_transfer_; + delete end_packet_; + delete end_message_; + + current_state_ = (MSEState*) 0; +} + +// process the MSE and return the outcome +bool AUXMessageProtocol::evaluate(uint32_t mse, Outcome &outcome) +{ + bool ret = true; + if (verbose_) { + cout << "MSE:" << mse; + cout << " " << current_state_->name() << " -> "; + + current_state_ = current_state_->nextState(mse); + outcome = current_state_->outcome(); + + cout << current_state_->name() << " Action: " + << outcomeText(outcome) << endl; + } else { + current_state_ = current_state_->nextState(mse); + outcome = current_state_->outcome(); + } + + return ret; +} + +// perform the action on the MDO for this state +bool AUXMessageProtocol::act(uint32_t mdo, NxPacketSet &pkt_set) +{ + if (verbose_) { + cout << "MDO: 0x" << std::hex << std::setfill('0') + << std::setw(8) << mdo << endl; + } + + // let the specific state handle the data + bool ret = current_state_->act(mdo, pkt_set); + return ret; +} + +// return text representing the outcome +const char * AUXMessageProtocol::outcomeText(Outcome outcome) const +{ + switch (outcome) { + case DISCARD: // MDO is invalid + return "DISCARD"; + break; + case ADD_NEW_MESSAGE: // MDO begins first packet of mew message + return "ADD NEW MESSAGE"; + break; + case ADD_CURRENT: // MDO adds to current packet + return "ADD CURRENT"; + break; + case ADD_LAST_PACKET: // MDO ends the current packet + return "ADD LAST PACKET"; + break; + case ADD_LAST_MESSAGE: // MDO ends the current message + return "ADD LAST MESSAGE"; + break; + default: + return "UNKNOWN"; // This is an error condition! + break; + }; +} diff --git a/converter/nexus/AUXMessageProtocol.h b/converter/nexus/AUXMessageProtocol.h new file mode 100644 index 00000000..a8bfd4dd --- /dev/null +++ b/converter/nexus/AUXMessageProtocol.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef AUXMESSAGEPROTOCOL_H +#define AUXMESSAGEPROTOCOL_H + +#include "NxPacketSet.h" +#include + +class MSEState; + +/*! + @discussion The AUXMessageProtocol is responsible for accepting MSEO data beats + and determining how the calling object is to disposition the MDO. + Implements the state machine on page 91 of the IEEE-ISTO 5001-2003 specification. + + The AUXMessageProtocl also provides the appropriate action on the data base on the current state + */ +class AUXMessageProtocol +{ +public: + + // all possible outcomes of the protocol + enum Outcome + { + DISCARD, // MDO is invalid + ADD_NEW_MESSAGE, // MDO begins first packet of mew message + ADD_CURRENT, // MDO adds to current packet + ADD_LAST_PACKET, // MDO ends the current packet + ADD_LAST_MESSAGE // MDO ends the current message + }; + + AUXMessageProtocol(); + ~AUXMessageProtocol(); + + // Evaluate the correct protocol state transition based on the current state and the MSE + // input mse - the MSE for each data beat + // output outcome - the result of the protocol evaluation + // return true if no processing errors + bool evaluate(uint32_t mse, Outcome &outcome); + + // input mdo - the MDO for each data beat + // input packet set - process the data into the packet set + // return true if no processing error + bool act(uint32_t mdo, NxPacketSet &pkt_set); + + // set the verbosity + void verbose(bool verbose) + { + verbose_ = verbose; + } + + // return text representing the outcome + const char * outcomeText(Outcome outcome) const; + +private: + + bool verbose_; + + // Create all the possible protocol states + MSEState *idle_; + MSEState *start_message_; + MSEState *normal_transfer_; + MSEState *end_packet_; + MSEState *end_message_; + + // current state + MSEState *current_state_; + +}; + +#endif // AUXMESSAGEPROTOCOL_H diff --git a/converter/nexus/Application.cpp b/converter/nexus/Application.cpp new file mode 100644 index 00000000..ced3fc08 --- /dev/null +++ b/converter/nexus/Application.cpp @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "Application.h" +#include "NxMessageDecoder.h" +#include "NxMessage.h" +#include "FManDebugLogVisitor.h" +#include "FullAddressVisitor.h" +#include "SizedAddress.h" +#include +#include +#include + +using std::cout; +using std::endl; +using std::hex; +using std::dec; +using std::setfill; +using std::setw; +using std::ifstream; + +Application::Application() : + verbose_(false), summary_(false), data_counter_(0), msg_counter_(0) +{ +} + +Application::~Application() +{ + vector::iterator it; + for (it = visitors_.begin(); it != visitors_.end(); it++) { + delete *it; + } + visitors_.clear(); +} + +// Enable the Full Address Log for the Application +void Application::enableFullAddrLog() +{ + NxMessageVisitor* v = new FullAddressVisitor(); + visitors_.push_back(v); +} + +// Enable the FMan Detail Log for the Application +void Application::enableFmanLog() +{ + NxMessageVisitor* v = new FManDebugLogVisitor(); + visitors_.push_back(v); +} + +// Main application entry +bool Application::process(const string & fn) +{ + bool ret; + + // test if file is available + ifstream infile(fn.c_str()); + if (!infile) { + cout << "Input Filename: \"" << fn << "\" cannot be opened! "; + return false; + } else { + infile.close(); + } + + if (verbose_) { + cout << "Input Filename: \"" << fn << "\" - "; + } + + // determine format for file + if (isBinFile_(fn)) { + if (verbose_) { + cout << "Binary" << endl; + } + ret = processBinFile_(fn); + } else { + if (verbose_) { + cout << "Text" << endl; + } + ret = processTextFile_(fn); + } + + if (ret && summary_) { + summarize(); + } + + return ret; +} + +// Determine if the name file contains Binary formatted data +bool Application::isBinFile_(const string &fn) const +{ + char data[12]; // if text then expecting 0x12345678\n + + // open the file as binary and read the first 12 bytes + ifstream infile(fn.c_str(), std::ios::in | std::ios::binary); + infile.read(data, 12); + infile.close(); + bool text_file = ((data[0] == '0') && (data[1] == 'x') + && ((data[10] == '\n') || (data[10] == ' '))); + return !text_file; +} + +// Open the named text file and process the Nexus data +bool Application::processTextFile_(const string &fn) +{ + bool ret; + uint32_t data; + + // open the file and feed the data to the decoder + ifstream infile(fn.c_str()); + while (!infile.eof()) { + infile >> hex >> data; + ret = process_(data); + if (!ret) { // error, so quit + break; + } + } + infile.close(); + + return ret; +} + +// Open the named text file and process the Nexus data +bool Application::processBinFile_(const string &fn) +{ + bool ret; + uint8_t byte[sizeof(uint32_t)]; + uint32_t data; + + // open the file and feed the data to the decoder + ifstream infile(fn.c_str(), std::ios::in | std::ios::binary); + while (!infile.eof()) { + infile.read((char*) &byte, sizeof(uint32_t)); + // Nexus binary files are Big Endian data + data = byte[0] << 24; + data |= byte[1] << 16; + data |= byte[2] << 8; + data |= byte[3]; + ret = process_(data); + if (!ret) { // error, so quit + break; + } + } + infile.close(); + + return ret; +} + +// Process the Nexus data +bool Application::process_(const uint32_t data) +{ + bool ret = true; + + NxMessage *msg = (NxMessage*) 0; + data_counter_++; + + if (verbose_) { + cout << dec << data_counter_ << ": MDO/MSEO: 0x" << hex + << setfill('0') << setw(8) << data << endl; + } + + ret = decoder_.accept(data, msg); + if (ret) { + if (msg != 0) { + ++msg_counter_; + // we have a message to output + cout << "Message # " << dec << msg_counter_ << endl; + cout << msg->asString() << endl; + + // count the messages + if (summary_) { + msg_count_[msg->tcodeString()]++; + } + + // Send all the visitors + vector::iterator it; + for (it = visitors_.begin(); it != visitors_.end(); + it++) { + msg->accept(**it); + // report on visit + cout << (*it)->asString() << endl; + } + + // nothing else to do for now so delete the message + delete msg; + msg = (NxMessage*) 0; + } + } else { + // error somewhere - quit + if (verbose_) { + cout << "NxMessageDecoder Failed. Quitting." << endl; + } + } + + return ret; +} + +// output a summary report on number of messages by type +void Application::summarize() +{ + cout << endl << "***********************" << endl; + cout << "Message Counts by TCODE" << endl; + + map::const_iterator iter; + for (iter = msg_count_.begin(); iter != msg_count_.end(); ++iter) { + cout << iter->first << "\t" << dec << setw(10) << setfill(' ') + << iter->second << endl; + } + +} diff --git a/converter/nexus/Application.h b/converter/nexus/Application.h new file mode 100644 index 00000000..7237b76a --- /dev/null +++ b/converter/nexus/Application.h @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef APPLICATION_H +#define APPLICATION_H + +#include +#include +#include +#include + +#include "NxMessageDecoder.h" + +using std::string; +using std::map; +using std::vector; + +class NxMessageVisitor; + +/*! + The Application is the top level driver delivering from a file + a stream of Nexus encoded 32bit words to the NexusDecoder. + The output will be the decoded Nexus messages. + */ +class Application +{ +public: + Application(); + ~Application(); + + /*! + @abstract Set the verbosity on or off for the Application + @param verbose Set true or false + */ + void verbose(bool verbose) + { + verbose_ = verbose; + decoder_.verbose(verbose_); + } + + /*! + @abstract Set the summary on or off for the Application + @param summary Set true or false + */ + void summary(bool summary) + { + summary_ = summary; + } + + /*! + @abstract Enable the Full Address Log for the Application + */ + void enableFullAddrLog(); + + /*! + @abstract Enable the FMan Detail Log for the Application + */ + void enableFmanLog(); + + /*! + @abstract Open the named file and process the Nexus data + @param fn filename containing data + @return true if no errors + */ + bool process(const string &fn); + + /*! + @abstract output a summary report on number of messages by type + */ + void summarize(); + +private: + + /*! + @abstract Determine if the name file contains binary formatted data + @param fn filename containing data + @return true if binary formatted file + */ + bool isBinFile_(const string &fn) const; + /*! + @abstract Open the named text file and process the Nexus data + @param fn filename containing data + @return true if no errors + */ + bool processTextFile_(const string &fn); + + /*! + @abstract Open the named text file and process the Nexus data + @param fn filename containing data + @return true if no errors + */ + bool processBinFile_(const string &fn); + + /*! + @abstract Process the Nexus data + @param data value + @return true if no errors + */ + bool process_(const uint32_t data); + + /*! @var verbose_ Holds the verbosity state */ + bool verbose_; + + /*! @var summary_ Holds state of summary count of all Messages */ + bool summary_; + + /*! @var decoder_ Provides the decoder */ + NxMessageDecoder decoder_; + + /* count of all data words */ + uint32_t data_counter_; + + /* count of all messages */ + uint32_t msg_counter_; + + /*! @var msg_count_ A count of messages by type */ + map msg_count_; + + // List of Visitors to handle the messages + vector visitors_; +}; + +#endif // APPLICATION_H diff --git a/converter/nexus/COPYING b/converter/nexus/COPYING new file mode 100644 index 00000000..f3f4399d --- /dev/null +++ b/converter/nexus/COPYING @@ -0,0 +1,21 @@ +# +# Copyright (C) 2013 Freescale Semiconductor, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# diff --git a/converter/nexus/ChangeLog b/converter/nexus/ChangeLog new file mode 100644 index 00000000..4dc70911 --- /dev/null +++ b/converter/nexus/ChangeLog @@ -0,0 +1,3 @@ +Ver 2.0 +Initial version for external distribution. +See file LICENSE.txt diff --git a/converter/nexus/FManDebugLog.cpp b/converter/nexus/FManDebugLog.cpp new file mode 100644 index 00000000..ad193370 --- /dev/null +++ b/converter/nexus/FManDebugLog.cpp @@ -0,0 +1,874 @@ +/* + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include +#include +#include + +#include "FManDebugLog.h" + +using std::ostringstream; +using std::endl; +using std::hex; +using std::dec; +using std::setfill; +using std::setw; + +// return the log to the initial state +void FManDebugLog::reset() +{ + log_complete_ = false; + log_parse_error_ = LOG_PARSE_NO_ERROR; + vector::iterator it; + for (it = logs_.begin(); it != logs_.end(); it++) { + delete *it; + } + logs_.clear(); + + context_complete_ = false; + context_data_.clear(); +} + +// add context data to the log +bool FManDebugLog::addContextData(uint32_t context_data) +{ + if (!context_complete_) { + context_data_.push_back(context_data); + } + return !context_complete_; +} + +// parse the context data into the defined sub module logs +bool FManDebugLog::parseContextData() +{ + FManModuleDebugLog *log; + + if (!context_complete_) { + log_complete_ = false; + return log_complete_; + } + + vector::iterator pos = context_data_.begin(); + while (pos < context_data_.end() && + log_parse_error_ == LOG_PARSE_NO_ERROR) { + + // size of this log entry context data in bytes + // except for Fman Controller where it denotes words + uint32_t data_len = (*pos >> NIA_SIZE_SHIFT & NIA_SIZE_MASK); + if (data_len == 0) { + log_parse_error_ = LOG_PARSE_DATA_LENGTH_ERROR; + break; + } + + // identify the type of log from the word at pos + int eng = *pos >> NIA_ENG_SHIFT & NIA_ENG_MASK; + switch (eng) { + case 0x0: { + // data_len is measured here in words (4bytes) + assert(data_len == 1 || data_len == 2 || data_len == 3); + vector::iterator frame_end = pos + data_len; + vector c_data(pos, frame_end); + log = new FManControllerDebugLog(); + log->parseContextData(c_data); + logs_.push_back(log); + pos = frame_end; + } + break; + case 0x11: // FManParser + { + // round up the data_len to the next 4 byte multiple + data_len = + data_len % 4 ? + (data_len & 0xfffffffc) + 4 : data_len; + assert(data_len % 4 == 0); + vector::iterator frame_end = pos + + data_len / 4; + vector c_data(pos, frame_end); + log = new FManParserDebugLog(); + log->parseContextData(c_data); + logs_.push_back(log); + pos = frame_end; + } + break; + case 0x12: // FManKeyGen + { + assert( + data_len == 4 || data_len == 8 + || data_len == 12); + vector::iterator frame_end = pos + + data_len / 4; + vector c_data(pos, frame_end); + log = new FManKeyGenDebugLog(); + log->parseContextData(c_data); + logs_.push_back(log); + pos = frame_end; + } + break; + case 0x13: // FmanPolicer + { + assert( + data_len == 8 || data_len == 16 + || data_len == 32); + vector::iterator frame_end = pos + + data_len / 4; + vector c_data(pos, frame_end); + log = new FManPolicerDebugLog(); + log->parseContextData(c_data); + logs_.push_back(log); + pos = frame_end; + } + break; + case 0x14: // FManBMI + { + assert( + data_len == 8 || data_len == 16 + || data_len == 32); + vector::iterator frame_end = pos + + data_len / 4; + if (frame_end <= context_data_.end()) { + vector c_data(pos, frame_end); + log = new FManBMIDebugLog(); + log->parseContextData(c_data); + logs_.push_back(log); + pos = frame_end; + } else { + log_parse_error_ = LOG_PARSE_DATA_LENGTH_ERROR; + } + } + break; + case 0x15: { + assert( + data_len == 4 || data_len == 8 + || data_len == 20); + vector::iterator frame_end = pos + + data_len / 4; + vector c_data(pos, frame_end); + log = new FManQMIEnqueueDebugLog(); + log->parseContextData(c_data); + logs_.push_back(log); + pos = frame_end; + } + break; + case 0x16: { + assert( + data_len == 4 || data_len == 8 + || data_len == 20); + vector::iterator frame_end = pos + + data_len / 4; + vector c_data(pos, frame_end); + log = new FManQMIDequeueDebugLog(); + log->parseContextData(c_data); + logs_.push_back(log); + pos = frame_end; + } + break; + default: + log_parse_error_ = LOG_PARSE_UNDEFINED_ENG_ERROR; + break; + } + } + + log_complete_ = true; + + return log_complete_; +} + +// Output logs as a string +// Enforces a format template for log output +string FManDebugLog::asString() const +{ + ostringstream os; + os << "Debug Trace Log for FMAN" << (fmanID_ + 1) << endl; + os << "-------------------------" << endl; + + // for debug only print out the context data + if (log_parse_error_ == LOG_PARSE_NO_ERROR) { + // print all the existing module specific (sub) logs + vector::const_iterator it; + for (it = logs_.begin(); it != logs_.end(); it++) { + os << (*it)->asString(); + } + os << endl; + } else { + os << "Warning: Detected error during evaluation of context data." + << endl; + switch (log_parse_error_) { + case LOG_PARSE_DATA_LENGTH_ERROR: + os << "Data length value is incorrect." << endl; + break; + case LOG_PARSE_UNDEFINED_ENG_ERROR: + os << "Undefined FMan Engine." << endl; + break; + default: + os << "PROGRAM ERROR: Report this!" << endl; + break; + } + os << "Context raw data follows:" + << endl; + vector::const_iterator i; + for (i = context_data_.begin(); i != context_data_.end(); i++) { + os << "0x" << hex << setw(8) << setfill('0') << *i + << dec << endl; + } + } + + return os.str(); +} +// output top level log as a string +string FManModuleDebugLog::asString() const +{ + ostringstream os; + + // module identifier + os << nameAsString() << endl; + + // Module generic information + os << "NIA VL : " << verbosity_level_; + switch (verbosity_level_) { + case FMAN_TRACE_DISABLED: + os << " - Trace Disabled"; + break; + case FMAN_TRACE_MINIMUM: + os << " - Minimal Trace"; + break; + case FMAN_TRACE_VERBOSE: + os << " - Verbose Trace"; + break; + case FMAN_TRACE_VERY_VERBOSE: + os << " - Very Verbose Trace"; + break; + default: + os << " - Invalid verbosity level"; + break; + } + os << endl; + + os << "NIA ORR : " << dec << order_restoration_required_ + << " - Order restoration " + << (order_restoration_required_ ? "is" : "is NOT") + << " required." << endl; + + // add the module specific information + os << asString_(); + + if (has_timestamp_) { + os << "FM TSTAMP : " << timestamp_ << " (0x" << hex << setw(8) + << setfill('0') << timestamp_ << ")" << dec << endl; + } + + return os.str(); +} + +// parse the context data header before calling the log specific parser +bool FManModuleDebugLog::parseContextData(vector &context_data) +{ + vector::iterator start = context_data.begin(); + + verbosity_level_ = *start >> NIA_VL_SHIFT & NIA_VL_MASK; + order_restoration_required_ = *start >> NIA_ORR_SHIFT & NIA_ORR_MASK; + + return parseContextData_(context_data); +} + +// output a port ID string +string FManModuleDebugLog::portIDasString_(uint32_t port_id) const +{ + ostringstream os; + + switch (port_id) { + case 0x1: + case 0x2: + case 0x3: + case 0x4: + case 0x5: + case 0x6: + case 0x7: + os << "Offline/Host " << dec << port_id; + break; + case 0x8: + case 0x9: + case 0xa: + case 0xb: + case 0xc: + case 0xd: + case 0xe: + case 0xf: + os << "1/2.5G Eth" << dec << port_id - 0x8 << " Rx"; + break; + case 0x10: + os << "(10G Eth1 - 1/2.5G Eth9) Rx"; + break; + case 0x11: + os << "(10G Eth2 - 1/2.5G Eth10) Rx"; + break; + case 0x28: + case 0x29: + case 0x2a: + case 0x2b: + case 0x2c: + case 0x2d: + case 0x2e: + case 0x2f: + os << "1/2.5G Eth" << dec << port_id - 0x8 << " Tx"; + break; + case 0x30: + os << "(10G Eth1 - 1/2.5G Eth9) Tx"; + break; + case 0x31: + os << "(10G Eth2 - 1/2.5G Eth10) Tx"; + break; + default: + os << "Unknown Port ID"; + break; + } + + return os.str(); +} + +// ------------------------------------------------------------------------------ + +// parse the context data +bool FManControllerDebugLog::parseContextData_(vector &context_data) +{ + bool ret = true; + + if (verbosity_level_ == FMAN_TRACE_VERBOSE + || verbosity_level_ == FMAN_TRACE_VERY_VERBOSE) { + timestamp_ = context_data[1]; + has_timestamp_ = true; + } + + if (verbosity_level_ == FMAN_TRACE_MINIMUM + || verbosity_level_ == FMAN_TRACE_VERBOSE + || verbosity_level_ == FMAN_TRACE_VERY_VERBOSE) { + action_code_ = context_data[0] >> NIA_AC_SHIFT & NIA_AC_MASK; + } + + return ret; +} + +// output log as a string +string FManControllerDebugLog::asString_() const +{ + ostringstream os; + + // Display the formatted Action code + os << "ACTION CD : 0x" << hex << setw(8) << setfill('0') << action_code_ + << dec << " - "; + switch (action_code_) { + case CTRL_CLASSIF_CMD: + os << "Coarse Classification"; + break; + case CTRL_INDEP_TX_CMD: + os << "Independent Mode Transmit"; + break; + case CTRL_INDEP_RX_CMD: + os << "Independent Mode Receive"; + break; + case CTRL_HOST_CMD: + os << "Host Commands"; + break; + default: + os << "Unknown Action Code"; + break; + } + os << endl; + + return os.str(); +} + +// parse the context data +bool FManParserDebugLog::parseContextData_(vector &context_data) +{ + bool ret = true; + + if (verbosity_level_ == FMAN_TRACE_VERY_VERBOSE) { + parse_start_point_ = context_data[2]; + // gather up to max program counters + // from the remaining data + } + + if (verbosity_level_ == FMAN_TRACE_VERBOSE + || verbosity_level_ == FMAN_TRACE_VERY_VERBOSE) { + timestamp_ = context_data[1]; + has_timestamp_ = true; + } + + if (verbosity_level_ == FMAN_TRACE_MINIMUM + || verbosity_level_ == FMAN_TRACE_VERBOSE + || verbosity_level_ == FMAN_TRACE_VERY_VERBOSE) { + hxs_id_ = context_data[0] >> NIA_AC_HXS_ID_SHIFT + & NIA_AC_HXS_ID_MASK; + } + + return ret; +} + +// output log as a string +string FManParserDebugLog::asString_() const +{ + ostringstream os; + + // Display the formatted Action code + os << "HXS ID : 0x" << hex << setw(8) << setfill('0') << hxs_id_ + << dec << " - "; + switch (hxs_id_) { + case PARSER_ETH_CMD: + os << "Ethernet HXS"; + break; + case PARSER_LLC_SNAP_CMD: + os << "LLC+SNAP HXS"; + break; + case PARSER_VLAN_CMD: + os << "VLAN HXS"; + break; + case PARSER_PPP_CMD: + os << "PPPoE+PPP HXS"; + break; + case PARSER_MPLS_CMD: + os << "MPLS HXS"; + break; + case PARSER_IPV4_CMD: + os << "IPV4 HXS"; + break; + case PARSER_IPV6_CMD: + os << "IPV6 HXS"; + break; + case PARSER_GRE_CMD: + os << "GRE HXS"; + break; + case PARSER_MINENCAP_CMD: + os << "MinEncap HXS"; + break; + case PARSER_OTHER_L3_CMD: + os << "Other L3 Shell HXS"; + break; + case PARSER_TCP_CMD: + os << "TCP HXS"; + break; + case PARSER_UDP_CMD: + os << "UDP HXS"; + break; + case PARSER_IPSEC_CMD: + os << "IPSec Shell HXS"; + break; + case PARSER_SCTP_CMD: + os << "SCTP Shell HXS"; + break; + case PARSER_DCCP_CMD: + os << "DCCP Shell HXS"; + break; + case PARSER_OTHER_L4_CMD: + os << "Other L4 Shell HXS"; + break; + case PARSER_NULL_CMD: + os << "Null Parsing"; + break; + default: + if (hxs_id_ >= 0x020 && hxs_id_ <= 0x3fd) { + os << "Soft Parse Program 0x" << hex << setw(8) + << setfill('0') << hxs_id_; + } else { + os << "unknown value"; + } + break; + } + os << endl; + + return os.str(); +} + +// parse the context data +bool FManKeyGenDebugLog::parseContextData_(vector &context_data) +{ + bool ret = true; + + if (verbosity_level_ == FMAN_TRACE_VERY_VERBOSE) { + selected_scheme_ = context_data[2] >> FMKG_SS_SHIFT & FMKG_SS_MASK; + int_frame_ptr_ = context_data[2] >> FMKG_IFP_SHIFT & FMKG_IFP_MASK; + } + + if (verbosity_level_ == FMAN_TRACE_VERBOSE + || verbosity_level_ == FMAN_TRACE_VERY_VERBOSE) { + timestamp_ = context_data[1]; + has_timestamp_ = true; + } + + if (verbosity_level_ == FMAN_TRACE_MINIMUM + || verbosity_level_ == FMAN_TRACE_VERBOSE + || verbosity_level_ == FMAN_TRACE_VERY_VERBOSE) { + ccen_ = context_data[0] >> NIA_AC_CCEN_SHIFT & NIA_AC_CCEN_MASK; + ss_ = context_data[0] >> NIA_AC_SS_SHIFT & NIA_AC_SS_MASK; + scheme_ = context_data[0] >> NIA_AC_SCHEME_SHIFT + & NIA_AC_SCHEME_MASK; + } + + return ret; +} + +// output log as a string +string FManKeyGenDebugLog::asString_() const +{ + ostringstream os; + + // Display the formatted Action code + os << "CCEN : " << ccen_ << " - Coarse Classification " + << (ccen_ ? "does" : "does NOT") + << " overwrite the IC field CCBASE" << endl; + os << "SCHEME SEL: " << ss_ << " - " + << (ss_ ? "Using SCHEME number" : + "Selected according to parse result") << endl; + if (ss_) { + os << "SCHEME : 0x" << setw(2) << setfill('0') + << scheme_ << dec << endl; + } + + if (verbosity_level_ == FMAN_TRACE_VERY_VERBOSE) { + os << "SEL SCHEME: 0x" << setw(2) << setfill('0') + << selected_scheme_ << dec << endl; + os << "IN FRM PTR: 0x" << setw(4) << setfill('0') + << int_frame_ptr_ << dec << endl; + } + + return os.str(); +} + +// parse the context data +bool FManPolicerDebugLog::parseContextData_(vector &context_data) +{ + bool ret = true; + + if (verbosity_level_ == FMAN_TRACE_VERY_VERBOSE) { + profile_cbs_ = context_data[4]; + profile_cts_ = context_data[5]; + profile_pbs_ebs_ = context_data[6]; + profile_ets_ = context_data[7]; + } + + if (verbosity_level_ == FMAN_TRACE_VERBOSE + || verbosity_level_ == FMAN_TRACE_VERY_VERBOSE) { + fcs_action_ = (uint8_t) (context_data[2] >> POLICE_FCS_SHIFT + & POLICE_FCS_MASK); + port_id_ = (uint8_t) (context_data[2] >> POLICE_PORTID_SHIFT + & POLICE_PORTID_MASK); + pkt_length_ = (context_data[3] >> POLICE_PKTLEN_LSB_SHIFT + & POLICE_PKTLEN_LSB_MASK) + | ((context_data[2] >> POLICE_PKTLEN_MSB_SHIFT + & POLICE_PKTLEN_MSB_MASK) << 16); + } + + if (verbosity_level_ == FMAN_TRACE_MINIMUM + || verbosity_level_ == FMAN_TRACE_VERBOSE + || verbosity_level_ == FMAN_TRACE_VERY_VERBOSE) { + timestamp_ = context_data[1]; + has_timestamp_ = true; + pmo_ = context_data[0] >> NIA_AC_PMO_SHIFT & NIA_AC_PMO_MASK; + pnum_ = context_data[0] >> NIA_AC_PNUM_SHIFT & NIA_AC_PNUM_MASK; + } + + return ret; +} + +// output log as a string +string FManPolicerDebugLog::asString_() const +{ + ostringstream os; + // Display the formatted Action code + + if (verbosity_level_ == FMAN_TRACE_MINIMUM + || verbosity_level_ == FMAN_TRACE_VERBOSE + || verbosity_level_ == FMAN_TRACE_VERY_VERBOSE) { + os << "NIA PMO : " << (uint32_t)pmo_ << endl; + os << "NIA PNUM : 0x" << hex << setw(2) << setfill('0') + << (uint32_t)pnum_ << dec << endl; + } + + if (verbosity_level_ == FMAN_TRACE_VERBOSE + || verbosity_level_ == FMAN_TRACE_VERY_VERBOSE) { + os << "FCS : " << (uint32_t)fcs_action_ << endl; + os << "PORT ID : 0x" << hex << setw(8) << setfill('0') + << (uint32_t)port_id_ << dec + << " - " << portIDasString_(port_id_) << endl; + os << "PKT LEN : 0x" << hex << setw(8) << setfill('0') + << pkt_length_ << dec << endl; + } + + if (verbosity_level_ == FMAN_TRACE_VERY_VERBOSE) { + os << "PRFL_CBS : 0x" << hex << setw(8) << setfill('0') + << profile_cbs_ << dec << endl; + os << "PRFL_CTS : 0x" << hex << setw(8) << setfill('0') + << profile_cts_ << dec << endl; + os << "PRFL_P/EBS: 0x" << hex << setw(8) << setfill('0') + << profile_pbs_ebs_ << dec << endl; + os << "PRFL_CTS : 0x" << hex << setw(8) << setfill('0') + << profile_cts_ << dec << endl; + } + + return os.str(); +} + +// parse the context data +bool FManBMIDebugLog::parseContextData_(vector &context_data) +{ + static const uint32_t BMI_PORTID_MASK = 0xff; + static const uint32_t BMI_PORTID_SHIFT = 0; + static const uint32_t BMI_TRAP_STATE_MASK = 0x7; + static const uint32_t BMI_TRAP_STATE_SHIFT = 8; + static const uint32_t BMI_FD_MASK = 0xffff; + static const uint32_t BMI_FD_SHIFT = 15; + + bool ret = true; + + // Special handling for the FD data + fd_[0] = fd_[1] = fd_[2] = fd_[3] = 0; + switch (verbosity_level_) { + case FMAN_TRACE_VERY_VERBOSE: + fd_[0] = context_data[4]; + fd_[1] = context_data[5]; + fd_[2] = context_data[6]; + fd_[3] = context_data[7]; + break; + case FMAN_TRACE_VERBOSE: + fd_[2] = context_data[1] >> BMI_FD_SHIFT & BMI_FD_MASK; + fd_[3] = context_data[3]; + break; + case FMAN_TRACE_MINIMUM: + fd_[2] = context_data[1] >> BMI_FD_SHIFT & BMI_FD_MASK; + break; + case FMAN_TRACE_DISABLED: + default: + break; + } + + if (verbosity_level_ == FMAN_TRACE_VERY_VERBOSE) { + } + + if (verbosity_level_ == FMAN_TRACE_VERBOSE + || verbosity_level_ == FMAN_TRACE_VERY_VERBOSE) { + timestamp_ = context_data[2]; + has_timestamp_ = true; + } + + if (verbosity_level_ == FMAN_TRACE_MINIMUM + || verbosity_level_ == FMAN_TRACE_VERBOSE + || verbosity_level_ == FMAN_TRACE_VERY_VERBOSE) { + port_id_ = context_data[1] >> BMI_PORTID_SHIFT + & BMI_PORTID_MASK; + debug_trap_state_ = context_data[1] >> BMI_TRAP_STATE_SHIFT + & BMI_TRAP_STATE_MASK; + action_code_ = context_data[0] >> NIA_AC_SHIFT & NIA_AC_MASK; + } + + return ret; +} + +// output log as a string +string FManBMIDebugLog::asString_() const +{ + ostringstream os; + + // Display the formatted Action code + os << "ACTION CD : 0x" << hex << setw(8) << setfill('0') << action_code_ + << dec << " - "; + switch (action_code_) { + case BMI_INI_CMD: + os << "Initialize"; + break; + case BMI_REL_INT_BUF_TNUM_TERM_CMD: + os + << "Release internal buffers and tnum. Termination of the task"; + break; + case BMI_REL_INT_IC_BUF_TNUM_TERM_CMD: + os + << "Release internal IC buffers and tnum. Termination of the task"; + break; + case BMI_TX_FR_REL_BUF_OR_ENQ_CMD: + os + << "Transmit frame and release external and internal buffers or enqueue to return FQID"; + break; + case BMI_TX_FR_NO_DMA_CMD: + os << "Transmit frame without DMA"; + break; + case BMI_TX_FR_NO_DMA_REL_INT_BUF_CMD: + os << "Transmit frame without DMA and release internal buffers"; + break; + case BMI_TX_FR_NO_DMA_REL_INT_BUF_TERM_CMD: + os + << "Transmit frame without DMA, release internal buffers and terminate"; + break; + case BMI_ENQ_FR_CMD: + os << "Prepare to enqueue frame"; + break; + case BMI_DISC_FR_TERM_CMD: + os << "Discard frame. Termination of the task"; + break; + case BMI_FETCH_FR_EXE_CMD: + os << "Fetch frame and execute"; + break; + case BMI_FETCH_FR_HDR_EXE_CMD: + os << "Fetch frame header and execute"; + break; + default: + os << "Unknown Action code"; + break; + } + os << endl; + + os << "PORT ID : 0x" << hex << port_id_ << dec + << " - " << portIDasString_(port_id_) << endl; + os << "TRAP STATE: 0x" << hex << debug_trap_state_ << dec << " -"; + os << (debug_trap_state_ & 0x4 ? " A:set" : " A:clr"); + os << (debug_trap_state_ & 0x2 ? " B:set" : " B:clr"); + os << (debug_trap_state_ & 0x1 ? " C:set" : " C:clr"); + os << endl; + os << "FD Addr : 0x" << hex << setw(8) << setfill('0') << fd_[0] + << ":" << setw(8) << setfill('0') << fd_[1] << ":" << setw(8) + << setfill('0') << fd_[2] << ":" << setw(8) << setfill('0') + << fd_[3] << dec << endl; + + return os.str(); +} + +// parse the context data +bool FManQMIDebugLog::parseContextData_(vector &context_data) +{ + bool ret = true; + + if (verbosity_level_ == FMAN_TRACE_VERY_VERBOSE) { + cfg_port_pri_ = (uint8_t) (context_data[3] + >> QMI_CFG_PORTPRI_SHIFT & QMI_CFG_PORTPRI_MASK); + cfg_deq_opt_ = (uint8_t) (context_data[3] + >> QMI_CFG_DEQOPT_SHIFT & QMI_CFG_DEQOPT_MASK); + cfg_port_en_ = (uint8_t) (context_data[3] + >> QMI_CFG_PORTEN_SHIFT & QMI_CFG_PORTEN_MASK); + cfg_pref_opt_ = (uint8_t) (context_data[3] + >> QMI_CFG_PREFOPT_SHIFT & QMI_CFG_PREFOPT_MASK); + cfg_frm_cnt_ = (uint8_t) (context_data[3] + >> QMI_CFG_FRMCNT_SHIFT & QMI_CFG_FRMCNT_MASK); + cfg_sub_port_ = (uint8_t) (context_data[3] + >> QMI_CFG_SUBPORT_SHIFT & QMI_CFG_SUBPORT_MASK); + cfg_byte_cnt_ = context_data[3] >> QMI_CFG_BYTECNT_SHIFT + & QMI_CFG_BYTECNT_MASK; + + fd_cmd_ = context_data[3]; + + res_sp_ = (uint8_t) (context_data[4] >> QMI_RES_SP_SHIFT + & QMI_RES_SP_MASK); + res_fqid_src_ = (uint8_t) (context_data[4] + >> QMI_RES_FQIDSRC_SHIFT & QMI_RES_FQIDSRC_MASK); + res_byte_cnt_ = (context_data[4] >> QMI_RES_BYTECNT_SHIFT + & QMI_RES_BYTECNT_MASK); + res_frm_cnt_ = (uint8_t) (context_data[4] + >> QMI_RES_FRMCNT_SHIFT & QMI_RES_FRMCNT_MASK); + res_tag_ = (uint8_t) (context_data[4] >> QMI_RES_TAG_SHIFT + & QMI_RES_TAG_MASK); + } + + if (verbosity_level_ == FMAN_TRACE_VERBOSE + || verbosity_level_ == FMAN_TRACE_VERY_VERBOSE) { + timestamp_ = context_data[1]; + has_timestamp_ = true; + } + + if (verbosity_level_ == FMAN_TRACE_MINIMUM + || verbosity_level_ == FMAN_TRACE_VERBOSE + || verbosity_level_ == FMAN_TRACE_VERY_VERBOSE) { + } + + return ret; +} + +// output log as a string +string FManQMIDebugLog::asString_() const +{ + ostringstream os; + + if (verbosity_level_ == FMAN_TRACE_VERY_VERBOSE) { + os << "PORT ENB : " << (uint32_t)cfg_port_en_ << " - Port " + << (cfg_port_en_ ? "is" : "is NOT") << " enabled" + << endl; + os << "PORT PRI : " << (uint32_t)cfg_port_pri_ + << (cfg_port_pri_ ? " - High" : " - Normal") + << " priority" << endl; + os << "DEQUE OPT : " << (uint32_t)cfg_deq_opt_ << " - "; + switch (cfg_deq_opt_) { + case 0: + os << "Reserved" << endl; + break; + case 1: + os + << "Dequeue with priority precedence and use intra-class scheduling" + << endl; + break; + case 2: + os + << "Dequeue with active FQ precedence and use intra-class scheduling" + << endl; + break; + case 3: + os + << "Dequeue with active FQ precedence and override intra-class scheduling" + << endl; + break; + default: + os << "Reserved" << endl; + break; + } + os << "PREF OPT : " << (uint32_t)cfg_pref_opt_ << endl; + os << "FRAME CNT : " << (uint32_t)cfg_frm_cnt_ << " - Dequeue " + << (cfg_frm_cnt_ ? "up to three" : "at most one") + << endl; + os << "CFG BYT CNT: 0x" << hex << setw(4) << setfill('0') + << cfg_byte_cnt_ << dec << endl; + os << "FD CMD : 0x" << hex << setw(8) << setfill('0') + << fd_cmd_ << dec << endl; + os << "SUB PORT : " << (uint32_t)cfg_sub_port_ + << " - Response sub portal" << endl; + os << "RES SP : " << (uint32_t)res_sp_ << endl; + os << "RES FQID : " << (uint32_t)res_fqid_src_; + switch (res_fqid_src_) { + case 0: + os << " - Default" << endl; + break; + case 1: + os << " - Context B" << endl; + break; + case 2: + os << " - FD command field" << endl; + break; + case 3: + os << " - TNUM has bypassed dequeue block" << endl; + break; + default: + os << " - Unknown" << endl; + break; + } + os << "RES BYT CNT: " << hex << setw(4) << setfill('0') + << res_byte_cnt_ << dec + << " - Response byte count level control" << endl; + os << "RES FRM CNT: " << (uint32_t)res_frm_cnt_ << endl; + os << "RES TAG : 0x" << hex << setw(2) << setfill('0') + << (uint32_t)res_tag_ << dec << endl; + } + + return os.str(); +} diff --git a/converter/nexus/FManDebugLog.h b/converter/nexus/FManDebugLog.h new file mode 100644 index 00000000..a8f0d0f5 --- /dev/null +++ b/converter/nexus/FManDebugLog.h @@ -0,0 +1,631 @@ +/* + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef FMANDEBUGLOG_H +#define FMANDEBUGLOG_H + +#include +#include +#include + +using std::vector; +using std::string; + +class FManModuleDebugLog; + +// Frame Manager Debug Log collects the context data from +// a related series of Nexus FMAN ICT messages before parsing +// the context data into the internal FMan module specific logs. +// +class FManDebugLog +{ +public: + + FManDebugLog() : + fmanID_(0), context_complete_(false), + log_parse_error_(LOG_PARSE_NO_ERROR), + log_complete_(false) + { + } + + ~FManDebugLog() + { + reset(); + } + + // Reset the log to the initial state. + void reset(); + + // Add context data to the log. + bool addContextData(uint32_t context_data); + + // Set last context data to close the log. + void setLastContextData() + { + context_complete_ = true; + } + + // Evaluate of the context data and return true + // if the log contains valid data. + bool parseContextData(); + + // Output log as a string. + string asString() const; + + // Set the Fman ID. + void setFManID(uint32_t fmanID) + { + fmanID_ = fmanID; + } + + // Return true if the log contains valid data. + bool logComplete() const + { + return log_complete_; + } + +protected: + + // Constants to access NIA data fields + static const uint32_t NIA_SIZE_MASK = 0x3f; + static const uint32_t NIA_SIZE_SHIFT = 24; + static const uint32_t NIA_ENG_MASK = 0x1f; + static const uint32_t NIA_ENG_SHIFT = 18; + +private: + // Fman instance ID + uint32_t fmanID_; + + // context data + vector context_data_; + + // context data complete + bool context_complete_; + + // maintain a list of module logs + vector logs_; + + // log parse error + enum log_parse_error { + LOG_PARSE_NO_ERROR = 0, + LOG_PARSE_DATA_LENGTH_ERROR, + LOG_PARSE_UNDEFINED_ENG_ERROR + } log_parse_error_; + + // log complete + bool log_complete_; +}; + +// Base class for all module specific log types +class FManModuleDebugLog +{ +public: + + FManModuleDebugLog() : + verbosity_level_(0), order_restoration_required_(false), + action_code_(0), has_timestamp_(false), timestamp_(0) + { + } + virtual ~FManModuleDebugLog() + { + } + + // parse the context data + bool parseContextData(vector &context_data); + + // output derived log name as string + virtual string nameAsString() const = 0; + + // output logs as a string + string asString() const; + +protected: + + // constants to access context data fields + static const uint32_t NIA_VL_MASK = 0x3; + static const uint32_t NIA_VL_SHIFT = 30; + static const uint32_t NIA_ORR_MASK = 0x1; + static const uint32_t NIA_ORR_SHIFT = 23; + static const uint32_t NIA_AC_MASK = 0x3ffff; + static const uint32_t NIA_AC_SHIFT = 0; + + // generic model Verbosity Levels + enum verbosity_level + { + FMAN_TRACE_DISABLED = 0, + FMAN_TRACE_MINIMUM = 1, + FMAN_TRACE_VERBOSE = 2, + FMAN_TRACE_VERY_VERBOSE = 3 + }; + + // parse header info + virtual bool parseContextData_(vector &context_data) = 0; + + // output logs as a string + virtual string asString_() const = 0; + + // output a port ID string + string portIDasString_( uint32_t port_id) const; + + // from NIA + uint32_t verbosity_level_; + bool order_restoration_required_; + + // common data + uint32_t action_code_; + + bool has_timestamp_; + uint32_t timestamp_; + +private: + +}; + +class FManControllerDebugLog: public FManModuleDebugLog +{ +public: + + FManControllerDebugLog() + { + } + virtual ~FManControllerDebugLog() + { + } + + // output log name as string + virtual string nameAsString() const + { + return "FMan Controller"; + } + +protected: + + enum action_code + { + CTRL_CLASSIF_CMD = 0x6, + CTRL_INDEP_TX_CMD = 0x8, + CTRL_INDEP_RX_CMD = 0xa, + CTRL_HOST_CMD = 0xc + }; + + // parse the context data + virtual bool parseContextData_(vector &context_data); + + // output log as a string + virtual string asString_() const; + +private: + +}; + +class FManParserDebugLog: public FManModuleDebugLog +{ +public: + FManParserDebugLog() : + hxs_id_(0), parse_start_point_(0) + { + for (uint32_t i = 0; i < MAX_NUM_PROG_CTRS; i++) { + program_counter_[i] = 0; + } + } + virtual ~FManParserDebugLog() + { + } + + // output log name as string + virtual string nameAsString() const + { + return "FMan Parser Engine"; + } + +protected: + + static const uint32_t MAX_NUM_PROG_CTRS = 16; + + static const uint32_t NIA_AC_HXS_ID_MASK = 0x3ff; + static const uint32_t NIA_AC_HXS_ID_SHIFT = 0; + + enum hxs_id + { + PARSER_ETH_CMD = 0x00, + PARSER_LLC_SNAP_CMD = 0x01, + PARSER_VLAN_CMD = 0x02, + PARSER_PPP_CMD = 0x03, + PARSER_MPLS_CMD = 0x04, + PARSER_IPV4_CMD = 0x05, + PARSER_IPV6_CMD = 0x06, + PARSER_GRE_CMD = 0x07, + PARSER_MINENCAP_CMD = 0x08, + PARSER_OTHER_L3_CMD = 0x09, + PARSER_TCP_CMD = 0x0a, + PARSER_UDP_CMD = 0x0b, + PARSER_IPSEC_CMD = 0x0c, + PARSER_SCTP_CMD = 0x0d, + PARSER_DCCP_CMD = 0x0e, + PARSER_OTHER_L4_CMD = 0x0f, + PARSER_NULL_CMD = 0x3ff + }; + // parse the context data + virtual bool parseContextData_(vector &context_data); + + // output log as a string + virtual string asString_() const; + +private: + + uint32_t hxs_id_; + uint32_t parse_start_point_; + uint32_t program_counter_[MAX_NUM_PROG_CTRS]; +}; + +class FManKeyGenDebugLog: public FManModuleDebugLog +{ +public: + + FManKeyGenDebugLog() : + ccen_(0), ss_(0), scheme_(0), + selected_scheme_(0), int_frame_ptr_(0) + { + } + virtual ~FManKeyGenDebugLog() + { + } + +protected: + + static const uint32_t NIA_AC_CCEN_MASK = 0x1; + static const uint32_t NIA_AC_CCEN_SHIFT = 9; + static const uint32_t NIA_AC_SS_MASK = 0x1; + static const uint32_t NIA_AC_SS_SHIFT = 8; + static const uint32_t NIA_AC_SCHEME_MASK = 0x1f; + static const uint32_t NIA_AC_SCHEME_SHIFT = 0; + + static const uint32_t FMKG_SS_MASK = 0xff; + static const uint32_t FMKG_SS_SHIFT = 24; + static const uint32_t FMKG_IFP_MASK = 0xff; + static const uint32_t FMKG_IFP_SHIFT = 16; + + // parse the context data + virtual bool parseContextData_(vector &context_data); + + // output log as a string + virtual string asString_() const; + + // output log name as string + virtual string nameAsString() const + { + return "FMan Key Generator Engine"; + } + +private: + + uint32_t ccen_; + uint32_t ss_; + uint32_t scheme_; + + uint32_t selected_scheme_; + uint32_t int_frame_ptr_; + +}; + +class FManPolicerDebugLog: public FManModuleDebugLog +{ +public: + + FManPolicerDebugLog() : + pmo_(0), + pnum_(0), + fcs_action_(0), + port_id_(0), + pi_(0), + cblnd_(0), + alg_(0), + fls_(0), + pkt_(0), + rbfls_(0), + flsres_(0), + fpp_(0), + flm_(0), + fatm_(0), + fbtm_(0), + fctm_(0), + abs_pnum_(0), + pcc_(0), + pc_(0), + pkt_length_(0), + profile_cbs_(0), + profile_cts_(0), + profile_pbs_ebs_(0), + profile_ets_(0) + { + } + virtual ~FManPolicerDebugLog() + { + } + +protected: + + static const uint32_t NIA_AC_PMO_MASK = 0x1; + static const uint32_t NIA_AC_PMO_SHIFT = 15; + static const uint32_t NIA_AC_PNUM_MASK = 0xff; + static const uint32_t NIA_AC_PNUM_SHIFT = 0; + + // verbose word 0 + static const uint32_t POLICE_FCS_MASK = 0x3; + static const uint32_t POLICE_FCS_SHIFT = 30; + static const uint32_t POLICE_PORTID_MASK = 0x3f; + static const uint32_t POLICE_PORTID_SHIFT = 24; + static const uint32_t POLICE_FLM_MASK = 0x1; + static const uint32_t POLICE_FLM_SHIFT = 23; + static const uint32_t POLICE_FATM_MASK = 0x1; + static const uint32_t POLICE_FATM_SHIFT = 22; + static const uint32_t POLICE_FBTM_MASK = 0x1; + static const uint32_t POLICE_FBTM_SHIFT = 21; + static const uint32_t POLICE_FCTM_MASK = 0x1; + static const uint32_t POLICE_FCTM_SHIFT = 20; + static const uint32_t POLICE_PNUM_MASK = 0xff; + static const uint32_t POLICE_PNUM_SHIFT = 8; + static const uint32_t POLICE_PPC_MASK = 0x3; + static const uint32_t POLICE_PPC_SHIFT = 6; + static const uint32_t POLICE_PC_MASK = 0x3; + static const uint32_t POLICE_PC_SHIFT = 4; + static const uint32_t POLICE_PKTLEN_MSB_MASK = 0xf; + static const uint32_t POLICE_PKTLEN_MSB_SHIFT = 0; + + // verbose word 1 + static const uint32_t POLICE_PKTLEN_LSB_MASK = 0xffff; + static const uint32_t POLICE_PKTLEN_LSB_SHIFT = 16; + static const uint32_t POLICE_PROF_INI_MASK = 0x1; + static const uint32_t POLICE_PROF_INI_SHIFT = 15; + static const uint32_t POLICE_CBLND_MASK = 0x1; + static const uint32_t POLICE_CBLND_SHIFT = 14; + static const uint32_t POLICE_ALG_MASK = 0x3; + static const uint32_t POLICE_ALG_SHIFT = 12; + static const uint32_t POLICE_FLS_MASK = 0xf; + static const uint32_t POLICE_FLS_SHIFT = 8; + static const uint32_t POLICE_PKT_MASK = 0x1; + static const uint32_t POLICE_PKT_SHIFT = 7; + static const uint32_t POLICE_RBFLS_MASK = 0x1; + static const uint32_t POLICE_RBFLS_SHIFT = 6; + static const uint32_t POLICE_FLSRES_MASK = 0x1; + static const uint32_t POLICE_FLSRES_SHIFT = 5; + static const uint32_t POLICE_FPP_MASK = 0xf; + static const uint32_t POLICE_FPP_SHIFT = 0; + + // parse the context data + virtual bool parseContextData_(vector &context_data); + + // output log as a string + virtual string asString_() const; + + // output log name as string + virtual string nameAsString() const + { + return "FMan Policer Engine"; + } + +private: + + // from NIA + uint8_t pmo_; + uint8_t pnum_; + + // FCS action + uint8_t fcs_action_; + uint8_t port_id_; + + // Debug flags and PNUM + uint8_t pi_; + uint8_t cblnd_; + uint8_t alg_; + uint8_t fls_; + uint8_t pkt_; + uint8_t rbfls_; + uint8_t flsres_; + uint8_t fpp_; + + uint8_t flm_; + uint8_t fatm_; + uint8_t fbtm_; + uint8_t fctm_; + uint8_t abs_pnum_; + uint8_t pcc_; + uint8_t pc_; + + // derived from multiple fields + uint32_t pkt_length_; + + // very verbose profile info + uint32_t profile_cbs_; + uint32_t profile_cts_; + uint32_t profile_pbs_ebs_; + uint32_t profile_ets_; +}; + +class FManBMIDebugLog: public FManModuleDebugLog +{ +public: + + FManBMIDebugLog() : + port_id_(0), + debug_trap_state_(0) + { + fd_[0] = 0; + fd_[1] = 0; + fd_[2] = 0; + fd_[3] = 0; + } + virtual ~FManBMIDebugLog() + { + } + + // output log name as string + virtual string nameAsString() const + { + return "FMan Buffer Manager Interface (BMI)"; + } + +protected: + + enum action_codes + { + BMI_INI_CMD = 0x000, + BMI_REL_INT_BUF_TNUM_TERM_CMD = 0x0C0, + BMI_REL_INT_IC_BUF_TNUM_TERM_CMD = 0x2C0, + BMI_TX_FR_REL_BUF_OR_ENQ_CMD = 0x274, + BMI_TX_FR_NO_DMA_CMD = 0x010, + BMI_TX_FR_NO_DMA_REL_INT_BUF_CMD = 0x050, + BMI_TX_FR_NO_DMA_REL_INT_BUF_TERM_CMD = 0x0D0, + BMI_ENQ_FR_CMD = 0x002, + BMI_DISC_FR_TERM_CMD = 0x0C1, + BMI_FETCH_FR_EXE_CMD = 0x20C, + BMI_FETCH_FR_HDR_EXE_CMD = 0x208 + }; + + // parse the context data + virtual bool parseContextData_(vector &context_data); + + // output log as a string + virtual string asString_() const; + +private: + + uint32_t port_id_; + uint32_t debug_trap_state_; + uint32_t fd_[4]; +}; + +// Base QMI class for the QMI Enqueue/Dequeue subclasses +class FManQMIDebugLog: public FManModuleDebugLog +{ +public: + + FManQMIDebugLog() : + cfg_port_pri_(0), + cfg_deq_opt_(0), + cfg_port_en_(0), + cfg_pref_opt_(0), + cfg_frm_cnt_(0), + cfg_sub_port_(0), + cfg_byte_cnt_(0), + fd_cmd_(0), + res_sp_(0), + res_fqid_src_(0), + res_byte_cnt_(0), + res_frm_cnt_(0), + res_tag_(0) + { + } + virtual ~FManQMIDebugLog() + { + } + +protected: + + static const uint32_t QMI_CFG_PORTPRI_MASK = 0x1; + static const uint32_t QMI_CFG_PORTPRI_SHIFT = 31; + static const uint32_t QMI_CFG_DEQOPT_MASK = 0x7; + static const uint32_t QMI_CFG_DEQOPT_SHIFT = 28; + static const uint32_t QMI_CFG_PORTEN_MASK = 0x1; + static const uint32_t QMI_CFG_PORTEN_SHIFT = 27; + static const uint32_t QMI_CFG_PREFOPT_MASK = 0x1; + static const uint32_t QMI_CFG_PREFOPT_SHIFT = 25; + static const uint32_t QMI_CFG_FRMCNT_MASK = 0x1; + static const uint32_t QMI_CFG_FRMCNT_SHIFT = 24; + static const uint32_t QMI_CFG_SUBPORT_MASK = 0xf; + static const uint32_t QMI_CFG_SUBPORT_SHIFT = 20; + static const uint32_t QMI_CFG_BYTECNT_MASK = 0xffff; + static const uint32_t QMI_CFG_BYTECNT_SHIFT = 0; + + static const uint32_t QMI_RES_SP_MASK = 0xf; + static const uint32_t QMI_RES_SP_SHIFT = 28; + static const uint32_t QMI_RES_FQIDSRC_MASK = 0x3; + static const uint32_t QMI_RES_FQIDSRC_SHIFT = 26; + static const uint32_t QMI_RES_BYTECNT_MASK = 0xffff; + static const uint32_t QMI_RES_BYTECNT_SHIFT = 10; + static const uint32_t QMI_RES_FRMCNT_MASK = 0x3; + static const uint32_t QMI_RES_FRMCNT_SHIFT = 8; + static const uint32_t QMI_RES_TAG_MASK = 0xff; + static const uint32_t QMI_RES_TAG_SHIFT = 0; + + // parse the context data + virtual bool parseContextData_(vector &context_data); + + // output log as a string + virtual string asString_() const; + +private: + + uint8_t cfg_port_pri_; + uint8_t cfg_deq_opt_; + uint8_t cfg_port_en_; + uint8_t cfg_pref_opt_; + uint8_t cfg_frm_cnt_; + uint8_t cfg_sub_port_; + uint32_t cfg_byte_cnt_; + + uint32_t fd_cmd_; + + uint8_t res_sp_; + uint8_t res_fqid_src_; + uint32_t res_byte_cnt_; + uint8_t res_frm_cnt_; + uint8_t res_tag_; +}; + +class FManQMIEnqueueDebugLog: public FManQMIDebugLog +{ +public: + + FManQMIEnqueueDebugLog() + { + } + virtual ~FManQMIEnqueueDebugLog() + { + } + + // output log name as string + virtual string nameAsString() const + { + return "FMan Enqueue Queue Manager Interface (QMI)"; + } +}; + +class FManQMIDequeueDebugLog: public FManQMIDebugLog +{ +public: + + FManQMIDequeueDebugLog() + { + } + virtual ~FManQMIDequeueDebugLog() + { + } + + // output log name as string + virtual string nameAsString() const + { + return "FMan Enqueue Queue Manager Interface (QMI)"; + } +}; + +#endif // FMANDEBUGLOG_H diff --git a/converter/nexus/FManDebugLogVisitor.cpp b/converter/nexus/FManDebugLogVisitor.cpp new file mode 100644 index 00000000..341fd177 --- /dev/null +++ b/converter/nexus/FManDebugLogVisitor.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include +#include +#include + +#include "FManDebugLogVisitor.h" +#include "NxMessageVisitor.h" +#include "NxMessage.h" +#include "FManDebugLog.h" + +using std::ostringstream; +using std::endl; +using std::hex; +using std::dec; +using std::setfill; +using std::setw; + +FManDebugLogVisitor::FManDebugLogVisitor() +{ + for (int i = 0; i < MAX_FMAN_LOGS; i++) { + log_[i] = new FManDebugLog(); + log_[i]->setFManID(i); + already_reported_[i] = false; + } +} + +FManDebugLogVisitor::~FManDebugLogVisitor() +{ + for (int i = 0; i < MAX_FMAN_LOGS; i++) { + delete log_[i]; + } +} + +void FManDebugLogVisitor::visit(NxDPFMInCircuitTraceMessage *m) +{ + // select the correct log + int fmsel = m->getFmsel(); + if ( fmsel < 0 || fmsel >= MAX_FMAN_LOGS) { + return; + } + FManDebugLog *log = log_[fmsel]; + + // if this is the first beat then reset the log + int beatcnt = m->getBtcnt(); + if (beatcnt == 0) { + already_reported_[fmsel] = false; + log->reset(); + } + + // capture the context data - always 4 words + const uint32_t *context = m->getContext(); + for (int i = 0; i < 4; i++) { + log->addContextData(context[i]); + } + + // begin parsing the log on the last beat + bool lastbeat = m->getLbeat(); + if (lastbeat) { + log->setLastContextData(); + log->parseContextData(); + } + useful_visit_ = true; +} + +// output message information as a string +string FManDebugLogVisitor::asString() const +{ + ostringstream os; + if (useful_visit_) { + for (int i = 0; i < MAX_FMAN_LOGS; i++) { + if (log_[i]->logComplete() && !already_reported_[i]) { + os << log_[i]->asString(); + already_reported_[i] = true; + } + } + } + return os.str(); +} diff --git a/converter/nexus/FManDebugLogVisitor.h b/converter/nexus/FManDebugLogVisitor.h new file mode 100644 index 00000000..15012f86 --- /dev/null +++ b/converter/nexus/FManDebugLogVisitor.h @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef FMANDEBUGLOGVISITOR_H +#define FMANDEBUGLOGVISITOR_H + +#include +#include +#include "NxMessageVisitor.h" + +using std::vector; +using std::string; + +class FManDebugLog; + +class NxDefaultMessage; +class NxDebugStatusMessage; +class NxDeviceIDMessage; +class NxOwnershipTraceMessage; +class NxDataAcquisitionMessage; +class NxErrorMessage; +class NxProgramTraceSync; +class NxDataTraceWrite; +class NxDataTraceRead; +class NxDataTraceWriteSync; +class NxDataTraceReadSync; +class NxWatchpointMessage; +class NxResourceFullMessage; +class NxProgramTraceIndirectBranch; +class NxProgramTraceIndirectBranchSync; +class NxProgramTraceCorrelation; +class NxDAMInCircuitTraceMessage; +class NxCAMInCircuitTraceMessage; +class NxCDMInCircuitTraceMessage; +class NxDPQMInCircuitTraceMessage; +class NxDPFMInCircuitTraceMessage; +class NxCoreInCircuitTraceMessage; +class NxInCircuitTraceMessage; +class NxTimeStampCorrelation; + +// Creates a detailed log for each FMan from the multiple +// ICT messages containing the context data. +class FManDebugLogVisitor: public NxMessageVisitor +{ +public: + + FManDebugLogVisitor(); + virtual ~FManDebugLogVisitor(); + + virtual void visit(NxDefaultMessage *m){useful_visit_ = false;} + virtual void visit(NxDebugStatusMessage *m){useful_visit_ = false;} + virtual void visit(NxDeviceIDMessage *m){useful_visit_ = false;} + virtual void visit(NxOwnershipTraceMessage *m){useful_visit_ = false;} + virtual void visit(NxDataAcquisitionMessage *m){useful_visit_ = false;} + virtual void visit(NxErrorMessage *m){useful_visit_ = false;} + virtual void visit(NxProgramTraceSync *m){useful_visit_ = false;} + virtual void visit(NxDataTraceWrite *m){useful_visit_ = false;} + virtual void visit(NxDataTraceRead *m){useful_visit_ = false;} + virtual void visit(NxDataTraceWriteSync *m){useful_visit_ = false;} + virtual void visit(NxDataTraceReadSync *m){useful_visit_ = false;} + virtual void visit(NxWatchpointMessage *m){useful_visit_ = false;} + virtual void visit(NxResourceFullMessage *m){useful_visit_ = false;} + virtual void visit(NxProgramTraceIndirectBranch *m){useful_visit_ = false;} + virtual void visit(NxProgramTraceIndirectBranchSync *m){useful_visit_ = false;} + virtual void visit(NxProgramTraceCorrelation *m){useful_visit_ = false;} + virtual void visit(NxDAMInCircuitTraceMessage *m){useful_visit_ = false;} + virtual void visit(NxCAMInCircuitTraceMessage *m){useful_visit_ = false;} + virtual void visit(NxCDMInCircuitTraceMessage *m){useful_visit_ = false;} + virtual void visit(NxDPQMInCircuitTraceMessage *m){useful_visit_ = false;} + virtual void visit(NxCoreInCircuitTraceMessage *m){useful_visit_ = false;} + virtual void visit(NxInCircuitTraceMessage *m){useful_visit_ = false;} + virtual void visit(NxTimeStampCorrelation *m){useful_visit_ = false;} + + // implement the specific visit + virtual void visit(NxDPFMInCircuitTraceMessage *m); + + // output message information as a string + virtual string asString() const; + +private: + + // define the number of concurrent FMAN logs + static const int MAX_FMAN_LOGS = 2; + + // FMan specific logs + FManDebugLog* log_[MAX_FMAN_LOGS]; + + // true if log is already reported via asString() + mutable bool already_reported_[MAX_FMAN_LOGS]; +}; + +#endif // FMANDEBUGLOGVISITOR_H diff --git a/converter/nexus/FullAddressVisitor.cpp b/converter/nexus/FullAddressVisitor.cpp new file mode 100644 index 00000000..6d95ca6a --- /dev/null +++ b/converter/nexus/FullAddressVisitor.cpp @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include +#include +#include + +#include "FullAddressVisitor.h" +#include "NxMessage.h" + +using std::ostringstream; +using std::endl; +using std::hex; +using std::dec; +using std::setfill; +using std::setw; + +// implement the specific visit +void FullAddressVisitor::visit(NxProgramTraceSync *m) +{ + last_key_ = m->sourceIdString(); + mismatch_addr_ = source_addr_[last_key_]; + data_mismatch_ = (m->address() != mismatch_addr_); + source_addr_[last_key_] = m->address(); + useful_visit_ = true; +} + +// implement the specific visit +void FullAddressVisitor::visit(NxProgramTraceIndirectBranch *m) +{ + last_key_ = m->sourceIdString(); + source_addr_[last_key_] ^= m->address(); + useful_visit_ = true; +} + +// implement the specific visit +void FullAddressVisitor::visit(NxProgramTraceIndirectBranchSync *m) +{ + last_key_ = m->sourceIdString(); + mismatch_addr_ = source_addr_[last_key_]; + data_mismatch_ = (m->address() != mismatch_addr_); + source_addr_[last_key_] = m->address(); + useful_visit_ = true; +} +// implement the specific visit +void FullAddressVisitor::visit(NxDAMInCircuitTraceMessage *m) +{ +// source_addr_[m->sourceIdString()] = m->address(); +// useful_visit_ = true; +} + +// implement the specific visit +void FullAddressVisitor::visit(NxCDMInCircuitTraceMessage *m) +{ +// source_addr_[m->sourceIdString()] = m->address(); +// useful_visit_ = true; +} + +// implement the specific visit +void FullAddressVisitor::visit(NxCAMInCircuitTraceMessage *m) +{ +// source_addr_[m->sourceIdString()] = m->address(); +// useful_visit_ = true; +} + +// output message information as a string +string FullAddressVisitor::asString() const +{ + ostringstream os; + + if (useful_visit_) { + map::const_iterator i = + source_addr_.find(last_key_); + os << "-----------UNCOMPRESSED ADDRESS-----------" << endl; + if (i != source_addr_.end()) { + os << "SRC : " << last_key_ << endl; + os << "F-ADDR : " << i->second.asString() << endl; + if (data_mismatch_) { + os << "Warning: Sync Address differs from calculated Address" << endl; + os << "CALC ADDR : " << mismatch_addr_.asString() << endl; + data_mismatch_ = false; + } + } else { + os << "ERROR resolving address source" << endl; + } + os << endl; + } + + return os.str(); +} diff --git a/converter/nexus/FullAddressVisitor.h b/converter/nexus/FullAddressVisitor.h new file mode 100644 index 00000000..72b3400b --- /dev/null +++ b/converter/nexus/FullAddressVisitor.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef FULLADDRESSVISITOR_h +#define FULLADDRESSVISITOR_h + +#include +#include +#include +#include "NxMessageVisitor.h" +#include "SizedAddress.h" + +using std::vector; +using std::string; +using std::map; + +class NxDefaultMessage; +class NxDebugStatusMessage; +class NxDeviceIDMessage; +class NxOwnershipTraceMessage; +class NxDataAcquisitionMessage; +class NxErrorMessage; +class NxProgramTraceSync; +class NxDataTraceWrite; +class NxDataTraceRead; +class NxDataTraceWriteSync; +class NxDataTraceReadSync; +class NxWatchpointMessage; +class NxResourceFullMessage; +class NxProgramTraceIndirectBranch; +class NxProgramTraceIndirectBranchSync; +class NxProgramTraceCorrelation; +class NxDAMInCircuitTraceMessage; +class NxCAMInCircuitTraceMessage; +class NxCDMInCircuitTraceMessage; +class NxDPQMInCircuitTraceMessage; +class NxDPFMInCircuitTraceMessage; +class NxCoreInCircuitTraceMessage; +class NxInCircuitTraceMessage; +class NxTimeStampCorrelation; + + +// Keeps track of the Full Address as calculated from the +// compressed addresses for the various components +class FullAddressVisitor: public NxMessageVisitor +{ +public: + + FullAddressVisitor() : data_mismatch_(false) + { + } + virtual ~FullAddressVisitor() + { + } + + virtual void visit(NxDefaultMessage *m){useful_visit_ = false;} + virtual void visit(NxDebugStatusMessage *m){useful_visit_ = false;} + virtual void visit(NxDeviceIDMessage *m){useful_visit_ = false;} + virtual void visit(NxOwnershipTraceMessage *m){useful_visit_ = false;} + virtual void visit(NxDataAcquisitionMessage *m){useful_visit_ = false;} + virtual void visit(NxErrorMessage *m){useful_visit_ = false;} + virtual void visit(NxDataTraceWrite *m){useful_visit_ = false;} + virtual void visit(NxDataTraceRead *m){useful_visit_ = false;} + virtual void visit(NxDataTraceWriteSync *m){useful_visit_ = false;} + virtual void visit(NxDataTraceReadSync *m){useful_visit_ = false;} + virtual void visit(NxWatchpointMessage *m){useful_visit_ = false;} + virtual void visit(NxResourceFullMessage *m){useful_visit_ = false;} + virtual void visit(NxProgramTraceCorrelation *m){useful_visit_ = false;} + virtual void visit(NxDPQMInCircuitTraceMessage *m){useful_visit_ = false;} + virtual void visit(NxDPFMInCircuitTraceMessage *m){useful_visit_ = false;} + virtual void visit(NxCoreInCircuitTraceMessage *m){useful_visit_ = false;} + virtual void visit(NxInCircuitTraceMessage *m){useful_visit_ = false;} + virtual void visit(NxTimeStampCorrelation *m){useful_visit_ = false;} + + // implement the specific visit + virtual void visit(NxProgramTraceSync *m); + + // implement the specific visit + virtual void visit(NxProgramTraceIndirectBranch *m); + + // implement the specific visit + virtual void visit(NxProgramTraceIndirectBranchSync *m); + + // implement the specific visit + virtual void visit(NxDAMInCircuitTraceMessage *m); + + // implement the specific visit + virtual void visit(NxCDMInCircuitTraceMessage *m); + + // implement the specific visit + virtual void visit(NxCAMInCircuitTraceMessage *m); + + // output message information as a string + virtual string asString() const; + +private: + + string last_key_; + + // track addresses per source name + map source_addr_; + + // address mismatch + mutable bool data_mismatch_; + SizedAddress mismatch_addr_; +}; + +#endif // FULLADDRESSVISITOR_h diff --git a/converter/nexus/LICENSE.txt b/converter/nexus/LICENSE.txt new file mode 100644 index 00000000..659c6fca --- /dev/null +++ b/converter/nexus/LICENSE.txt @@ -0,0 +1,21 @@ +# +# Copyright (C) 2013 Freescale Semiconductor, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# \ No newline at end of file diff --git a/converter/nexus/MSEState.cpp b/converter/nexus/MSEState.cpp new file mode 100644 index 00000000..73674ac3 --- /dev/null +++ b/converter/nexus/MSEState.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "MSEState.h" +#include + +// globally initialized +bool MSEState::start_optimized_message_ = false; + +// initialize the state transition table +void MSEState::initialize_transitions(MSEState *new_state_00, + MSEState *new_state_01, MSEState *new_state_10, MSEState *new_state_11) +{ + next_state_[0] = new_state_00; + next_state_[1] = new_state_01; + next_state_[2] = new_state_10; + next_state_[3] = new_state_11; +} + +// update to the next state +MSEState *MSEState::nextState(uint32_t index) +{ + assert(index < MAX_STATE_TRANSITIONS); + + // set the next state + return next_state_[index]; +} + +// update to the next state +MSEState * MSEIdle::nextState(uint32_t mse) +{ + if (mse == 0x1 || mse == 0x2) { + MSEState::start_optimized_message_ = true; + } + // set the next state + return MSEState::nextState(mse); +} +// perform the action on the MDO for this state +bool MSEIdle::act(uint32_t mdo, NxPacketSet &pkt_set) +{ + if (MSEState::start_optimized_message_) { + pkt_set.reset(); + MSEState::start_optimized_message_ = false; + } + return true; +} + +bool MSEStartMessage::act(uint32_t mdo, NxPacketSet &pkt_set) +{ + pkt_set.reset(); + bool ret = pkt_set.addToCurrent(mdo); + return ret; +} + +bool MSENormalTransfer::act(uint32_t mdo, NxPacketSet &pkt_set) +{ + bool ret = pkt_set.addToCurrent(mdo); + return ret; +} + +bool MSEEndPacket::act(uint32_t mdo, NxPacketSet &pkt_set) +{ + if (MSEState::start_optimized_message_) { + pkt_set.reset(); + MSEState::start_optimized_message_ = false; + } + bool ret = pkt_set.addToCurrent(mdo); + if (ret) { + ret = pkt_set.nextPacket(); + } + return ret; +} +bool MSEEndMessage::act(uint32_t mdo, NxPacketSet &pkt_set) +{ + if (MSEState::start_optimized_message_) { + pkt_set.reset(); + MSEState::start_optimized_message_ = false; + } + bool ret = pkt_set.addToCurrent(mdo); + return ret; +} + +// update to the next state +MSEState *MSEEndMessage::nextState(uint32_t mse) +{ + if (mse == 0x1 || mse == 0x2) { + MSEState::start_optimized_message_ = true; + } + // set the next state + return MSEState::nextState(mse); +} diff --git a/converter/nexus/MSEState.h b/converter/nexus/MSEState.h new file mode 100644 index 00000000..c6db23c8 --- /dev/null +++ b/converter/nexus/MSEState.h @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef MSESTATE_H +#define MSESTATE_H + +#include +#include "AUXMessageProtocol.h" +#include "NxPacketSet.h" + +#include +using std::string; + +// Abstract MSEState to contain the transition tables +// and the state specific outcomes. +class MSEState +{ +public: + + // Constructor to allow initialization of the state information + MSEState(AUXMessageProtocol::Outcome outcome, const char *name) : + outcome_(outcome), state_name_(name) + { + } + virtual ~MSEState() + { + } + + // update to the next state + virtual MSEState *nextState(uint32_t mse); + + // return the outcome for this state + virtual AUXMessageProtocol::Outcome outcome() const + { + return outcome_; + } + + // perform the action on the MDO for this state + virtual bool act(uint32_t mdo, NxPacketSet &pkt_set) = 0; + + // initialize the state transition table + void initialize_transitions(MSEState *new_state_00, + MSEState *new_state_01, MSEState *new_state_10, + MSEState *new_state_11); + + // state name + const char* name() const + { + return state_name_.c_str(); + } + + // indicates if an optimized single beat message is being processed + // shared across all states + static bool start_optimized_message_; + +private: + // Number of possible transitions from every state + static const uint32_t MAX_STATE_TRANSITIONS = 4; + + // table of next states based on MSE value + MSEState *next_state_[MAX_STATE_TRANSITIONS]; + + // The result of being in a state + AUXMessageProtocol::Outcome outcome_; + + // name of the state + const string state_name_; +}; + +// MSEIdle +class MSEIdle: public MSEState +{ +public: + + MSEIdle() : + MSEState(AUXMessageProtocol::DISCARD, "IDLE") + { + } + virtual ~MSEIdle() + { + } + + // update to the next state + virtual MSEState *nextState(uint32_t mse); + + // perform the action on the MDO for this state + virtual bool act(uint32_t mdo, NxPacketSet &pkt_set); + +}; + +// MSEStartMessage +class MSEStartMessage: public MSEState +{ +public: + + MSEStartMessage() : + MSEState(AUXMessageProtocol::ADD_NEW_MESSAGE, "START_MESSAGE") + { + } + virtual ~MSEStartMessage() + { + } + + // perform the action on the MDO for this state + virtual bool act(uint32_t mdo, NxPacketSet &pkt_set); +}; + +// MSENormalTransfer +class MSENormalTransfer: public MSEState +{ +public: + + MSENormalTransfer() : + MSEState(AUXMessageProtocol::ADD_CURRENT, "NORMAL_TRANSFER") + { + } + virtual ~MSENormalTransfer() + { + } + + // perform the action on the MDO for this state + virtual bool act(uint32_t mdo, NxPacketSet &pkt_set); +}; + +// MSEEndPacket +class MSEEndPacket: public MSEState +{ +public: + + MSEEndPacket() : + MSEState(AUXMessageProtocol::ADD_LAST_PACKET, "END_PACKET") + { + } + virtual ~MSEEndPacket() + { + } + + // perform the action on the MDO for this state + virtual bool act(uint32_t mdo, NxPacketSet &pkt_set); +}; + +// MSEEndMessage +class MSEEndMessage: public MSEState +{ +public: + + MSEEndMessage() : + MSEState(AUXMessageProtocol::ADD_LAST_MESSAGE, "END_MESSAGE") + { + } + virtual ~MSEEndMessage() + { + } + + // update to the next state + virtual MSEState *nextState(uint32_t mse); + + // perform the action on the MDO for this state + virtual bool act(uint32_t mdo, NxPacketSet &pkt_set); +}; + +#endif // MSESTATE_H diff --git a/converter/nexus/Makefile.am b/converter/nexus/Makefile.am new file mode 100644 index 00000000..3303ca3f --- /dev/null +++ b/converter/nexus/Makefile.am @@ -0,0 +1,47 @@ +# +# Copyright (C) 2013 Freescale Semiconductor, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# + +bin_PROGRAMS=nexdump +nexdump_SOURCES=main.cpp \ + Application.h \ + Application.cpp \ + AUXMessageProtocol.h \ + AUXMessageProtocol.cpp \ + FManDebugLog.h \ + FManDebugLog.cpp \ + FManDebugLogVisitor.h \ + FManDebugLogVisitor.cpp \ + FullAddressVisitor.h \ + FullAddressVisitor.cpp \ + MSEState.h \ + MSEState.cpp \ + NxMessage.h \ + NxMessage.cpp \ + NxMessageDecoder.h \ + NxMessageDecoder.cpp \ + NxMessageVisitor.h \ + NxPacketDecoder.h \ + NxPacketDecoder.cpp \ + NxPacketSet.h \ + NxPacketSet.cpp \ + SizedAddress.h \ + SizedAddress.cpp diff --git a/converter/nexus/NEWS b/converter/nexus/NEWS new file mode 100644 index 00000000..e69de29b diff --git a/converter/nexus/NxMessage.cpp b/converter/nexus/NxMessage.cpp new file mode 100644 index 00000000..b23d6229 --- /dev/null +++ b/converter/nexus/NxMessage.cpp @@ -0,0 +1,1677 @@ +/* + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "NxMessage.h" +#include +#include // for isprint() +#include +#include +using std::ostringstream; +using std::endl; +using std::hex; +using std::dec; +using std::setfill; +using std::setw; + +#define SWAPBYTES32(ui32) \ + (((ui32)<<24) | (((ui32) & 0xff00) << 8) |\ + (((ui32) & 0xff0000) >> 8) | ((ui32) >> 24)) + +string NxMessage::tcodeString() const +{ + ostringstream os; + os << "UNKNOWN-" << tcode_; + return os.str(); +} + +// decode the source id from the packet +uint32_t NxMessage::decodeSourceId(NxPacketSet &pkt_set) +{ + // packet index, start_pos, length + uint32_t src_id = pkt_set.getField32(0, 6, 6); + return src_id; +} + +// decode the timestamp from the packet +uint32_t NxMessage::decodeTimestamp(NxPacketSet &pkt_set, uint32_t index) +{ + // packet at index, start_pos, length + uint32_t ts = pkt_set.getField32(index, 0, 28); + return ts; +} + +// Returns the SRC_ID as a string +const char * NxMessage::sourceIdString() const +{ + switch (source_id_) { + case 0x0: + return "Core0 / CPU0 (Clst0:Core0:Thread0)"; + break; + case 0x1: + return "Nexus Port Controller"; + break; + case 0x2: + return "Core1 / CPU8 (Clst1:Core0:Thread0)"; + break; + case 0x3: + return "Nexus Trace Collector #1"; + break; + case 0x4: + return "Core2 / CPU16 (Clst2:Core0:Thread0)"; + break; + case 0x5: + return "Nexus Trace Collector #2"; + break; + case 0x6: + return "Core3"; + break; + case 0x8: + return "Core4 / CPU2 (Clst0:Core1:Thread0)"; + break; + case 0x9: + return "CoreNet Debug Client"; + break; + case 0xa: + return "Core5 / CPU10 (Clst1:Core1:Thread0)"; + break; + case 0xb: + return "Datapath Debug Client"; + break; + case 0xc: + return "Core6 / CPU18 (Clst2:Core1:Thread0)"; + break; + case 0xd: + return "DDR Debug Interface"; + break; + case 0xe: + return "Core7"; + break; + case 0x10: + return "CPU4 (Clst0:Core2:Thread0)"; + break; + case 0x12: + return "CPU12 (Clst1:Core2:Thread0)"; + break; + case 0x14: + return "CPU20 (Clst2:Core2:Thread0)"; + break; + case 0x18: + return "CPU6 (Clst0:Core3:Thread0)"; + break; + case 0x19: + return "CoreNet Debug Client"; + break; + case 0x1a: + return "CPU14 (Clst1:Core3:Thread0)"; + break; + case 0x1b: + return "Datapath Debug Interface"; + break; + case 0x1c: + return "CPU22 (Clst2:Core3:Thread0)"; + break; + case 0x1d: + return "Nexus Concentrator"; + break; + case 0x20: + return "CPU1 (Clst0:Core0:Thread1)"; + break; + case 0x22: + return "CPU9 (Clst1:Core0:Thread1)"; + break; + case 0x24: + return "CPU17 (Clst2:Core0:Thread1)"; + break; + case 0x28: + return "CPU3 (Clst0:Core1:Thread1)"; + break; + case 0x2a: + return "CPU11 (Clst1:Core1:Thread1)"; + break; + case 0x2b: + return "Datapath Debug Interface"; + break; + case 0x2c: + return "CPU19 (Clst2:Core1:Thread1)"; + break; + case 0x2d: + return "DDR Debug Interface"; + break; + case 0x30: + return "CPU5 (Clst0:Core2:Thread1)"; + break; + case 0x32: + return "CPU13 (Clst1:Core2:Thread1)"; + break; + case 0x34: + return "CPU21 (Clst2:Core2:Thread1)"; + break; + case 0x38: + return "CPU7 (Clst0:Core3:Thread1)"; + break; + case 0x3a: + return "CPU15 (Clst1:Core3:Thread1)"; + break; + case 0x3c: + return "CPU23 (Clst2:Core3:Thread1)"; + break; + case 0x3d: + return "Event Processing Unit"; + break; + case 0x4d: + return "Nexus Concentrator"; + break; + default: + return "Reserved"; + break; + }; + return "UNKNOWN"; +} + +// Determines if the TIMESTAMP value needs correction +bool NxMessage::timestampNeedsCorrection() const +{ + return (timestamp_ & 0x0f000000); +} + +// Returns the corrected TIMESTAMP value +uint32_t NxMessage::correctedTimestamp() const +{ + uint32_t correction = (timestamp_ & 0x0f000000) >> 24; + uint32_t ts = (timestamp_ & 0x00ffffff) - correction; + return ts; +} +// Returns a string representing the timestamp +string NxMessage::timestampAsString() const +{ + ostringstream os; + os << dec << correctedTimestamp() << " (0x" << hex + << correctedTimestamp() << ")"; + return os.str(); +} + +// represent this message as a formatted string +string NxMessage::asString() const +{ + ostringstream os; + os << "TCODE : " << dec << tcode() << " " << tcodeString() << endl; + os << "SRC ID : " << dec << sourceId() << " " << sourceIdString() + << endl; + os << "TIMESTAMP : " << timestampAsString() << endl; + return os.str(); +} + +// decode message info from the packet set +bool NxDebugStatusMessage::decode(NxPacketSet &pkt_set) +{ + bool ret = true; + source_id_ = decodeSourceId(pkt_set); + + // index, start_pos, length + status_ = pkt_set.getField32(0, 12, 16); + + // index, start_pos, length + timestamp_ = pkt_set.getField32(0, 28, 28); + + return ret; +} + +// represent this message as a formatted string +string NxDebugStatusMessage::asString() const +{ + ostringstream os; + os << "TCODE : " << dec << tcode() << " " << tcodeString() << endl; + os << "SRC ID : " << dec << sourceId() << " " << sourceIdString() + << endl; + os << "STATUS : 0x" << hex << setfill('0') << setw(4) << status_ + << endl; + os << "TIMESTAMP : " << timestampAsString() << endl; + return os.str(); +} + +// decode message info from the packet set +bool NxDeviceIDMessage::decode(NxPacketSet &pkt_set) +{ + bool ret = true; + source_id_ = decodeSourceId(pkt_set); + + return ret; +} + +// represent this message as a formatted string +string NxDeviceIDMessage::asString() const +{ + ostringstream os; + os << "TCODE : " << dec << tcode() << " " << tcodeString() << endl; + os << "SRC ID : " << dec << sourceId() << " " << sourceIdString() + << endl; + return os.str(); +} +// decode message info from the packet set +bool NxOwnershipTraceMessage::decode(NxPacketSet &pkt_set) +{ + bool ret = true; + source_id_ = decodeSourceId(pkt_set); + + // index, start_pos, length + pid_index_ = pkt_set.getField32(0, 12, 4); + + // index, start_pos, length + pid_value_ = pkt_set.getField64(0, 16, 40); + + // if there is a optional timestamp + if (pkt_set.packetAtIndexExists(1)) { + timestamp_ = decodeTimestamp(pkt_set, 1); + } + return ret; +} + +// represent this message as a formatted string +string NxOwnershipTraceMessage::asString() const +{ + ostringstream os; + os << "TCODE : " << dec << tcode() << " " << tcodeString() << endl; + os << "SRC ID : " << dec << sourceId() << " " << sourceIdString() + << endl; + os << "PID INDEX : 0x" << hex << setfill('0') << setw(2) << pid_index_; + os << " - " << pidIndexString() << endl; + if (pid_index_ < 2) { + os << "PID VALUE : " << dec << pid_value_; + } else { + os << "PID VALUE : 0x" << hex << setfill('0') << setw(10) + << pid_value_; + } + os << " - " << pidValueString() << endl; + os << "TIMESTAMP : " << timestampAsString() << endl; + return os.str(); +} + +// decode the data as a string +const char * NxOwnershipTraceMessage::pidIndexString() const +{ + switch (pid_index_) { + case 0: + return "OS PID"; + break; + case 1: + return "Hypervisor PID"; + break; + case 2: + return "Sync PID"; + break; + default: + return "Reserved"; + break; + }; + return "UNKNOWN"; +} + +// decode the data as a string +const char * NxOwnershipTraceMessage::pidValueString() const +{ + switch (pid_index_) { + case 0: + return "PID/NPIDR ref:DC1[OTS]"; + break; + case 1: + return "LPIDR"; + break; + case 2: + return "LPIDR, MSR[GS], PID/NPIDR (ref:DC1[OTS]), MSR[PR]"; + break; + default: + return "N/A"; + break; + }; + return "UNKNOWN"; +} + +// decode message info from the packet set +bool NxDataAcquisitionMessage::decode(NxPacketSet &pkt_set) +{ + bool ret = true; + source_id_ = decodeSourceId(pkt_set); + + // index, start_pos, length + idtag_ = pkt_set.getField32(0, 12, 8); + + // index, start_pos, length + dqdata_ = pkt_set.getField32(0, 20, 32); + + // if there is a optional timestamp + if (pkt_set.packetAtIndexExists(1)) { + timestamp_ = decodeTimestamp(pkt_set, 1); + } + return ret; +} + +// represent this message as a formatted string +string NxDataAcquisitionMessage::asString() const +{ + ostringstream os; + os << "TCODE : " << dec << tcode() << " " << tcodeString() << endl; + os << "SRC ID : " << dec << sourceId() << " " << sourceIdString() + << endl; + os << "IDTAG : 0x" << hex << setfill('0') << setw(2) << idtag_; + os << " - " << idtagString() << endl; + if (idtag_ == 6) { + os << "DQDATA : 0x" << hex << setfill('0') << setw(8) + << dqdata_; + os << " - \"" << dqdataString() << "\"" << endl; + } else { + os << "DQDATA : " << dec << dqdata_ << endl; + } + os << "TIMESTAMP : " << timestampAsString() << endl; + return os.str(); +} + +// decode the data as a string +const char * NxDataAcquisitionMessage::idtagString() const +{ + switch (idtag_) { + case 1: + return "Diagnostic"; + break; + case 3: + return "Parent PID"; + break; + case 4: + return "PID"; + break; + case 5: + return "TGID"; + break; + case 6: + return "Name"; + break; + case 7: + return "Address"; + break; + default: + return "Reserved"; + break; + }; + return "UNKNOWN"; +} + +// decode the data as a string +string NxDataAcquisitionMessage::dqdataString() const +{ + ostringstream os; + // display as ASCII + for (uint32_t i = 0; i < 4; ++i) { + char c = (dqdata_ >> ((3 - i) * 8)) & 0xff; + if (isprint(c)) { + os << c; + } else { + os << ' '; + } + } + return os.str(); +} + +// decode message info from the packet set +bool NxErrorMessage::decode(NxPacketSet &pkt_set) +{ + bool ret = true; + source_id_ = decodeSourceId(pkt_set); + + // index, start_pos, length + etype_ = pkt_set.getField32(0, 12, 4); + + // index, start_pos, length + ecode_ = pkt_set.getField32(0, 16, 8); + + // if there is a optional timestamp + if (pkt_set.packetAtIndexExists(1)) { + timestamp_ = decodeTimestamp(pkt_set, 1); + } + return ret; +} + +// represent this message as a formatted string +string NxErrorMessage::asString() const +{ + ostringstream os; + os << "TCODE : " << dec << tcode() << " " << tcodeString() << endl; + os << "SRC ID : " << dec << sourceId() << " " << sourceIdString() + << endl; + os << "ETYPE : 0x" << hex << setfill('0') << setw(2) << etype_; + os << " - " << etypeString() << endl; + os << "ECODE : 0x" << hex << setfill('0') << setw(8) << ecode_; + os << " - " << ecodeString() << endl; + os << "TIMESTAMP : " << timestampAsString() << endl; + return os.str(); +} +// decode the data as a string +const char * NxErrorMessage::etypeString() const +{ + switch (etype_) { + case 0: + return "Message Queue Overrun"; + break; + case 1: + return "Contention with higher priority message"; + break; + default: + return "Reserved"; + break; + }; + + return ""; +} +// decode the data as a string +string NxErrorMessage::ecodeString() const +{ + ostringstream os; + if ((ecode_ & 0x1) && (etype_ == 0)) { + os << "Watchpoint Trace "; + } + if ((ecode_ & 0x2) && (etype_ == 0)) { + os << "Data Trace "; + } + if (ecode_ & 0x4) { + os << "Program Trace "; + } + if ((ecode_ & 0x8) && (etype_ == 0)) { + os << "Ownership Trace "; + } + if ((ecode_ & 0x10) && (etype_ == 0)) { + os << "Debug (Status) Trace "; + } + if (ecode_ & 0x20) { + os << "Data Acquisition Trace "; + } + + return os.str(); +} + +// decode message info from the packet set +bool NxProgramTraceSync::decode(NxPacketSet &pkt_set) +{ + bool ret = true; + source_id_ = decodeSourceId(pkt_set); + + // index, start_pos, length + map_ = pkt_set.getField32(0, 12, 1); + + // index, start_pos, length + icnt_ = pkt_set.getField32(0, 13, 1); + + // index, start_pos, length + pc_.lower32(pkt_set.getField32(1, 0, 32)); + if (pkt_set.getNumMDO(1) > 1) { + // get the upper 32bits of 64bit address + pc_.upper32(pkt_set.getField32(1, 32, 32)); + } + + // if there is a optional timestamp + if (pkt_set.packetAtIndexExists(2)) { + timestamp_ = decodeTimestamp(pkt_set, 2); + } + return ret; +} + +// represent this message as a formatted string +string NxProgramTraceSync::asString() const +{ + ostringstream os; + os << "TCODE : " << dec << tcode() << " " << tcodeString() << endl; + os << "SRC ID : " << dec << sourceId() << " " << sourceIdString() + << endl; + os << "MAP : 0x" << hex << setw(1) << map_ << endl; + os << "I-CNT : " << dec << icnt_ << endl; + os << "PC : " << pc_.asString() << endl; + os << "TIMESTAMP : " << timestampAsString() << endl; + return os.str(); +} + +// decode the data as a string +const char * NxDataTraceBase::dszString() const +{ + switch (source_id_) { + case 0x0: // Core + { + switch (dsz_) { + case 0: + return "0 bytes (0-bit)"; + break; + case 1: + return "1 byte (8-bit)"; + break; + case 2: + return "2 bytes (16-bit/half word)"; + break; + case 3: + return "3 bytes (24-bit/string)"; + break; + case 4: + return "4 bytes (32-bit/word)"; + break; + case 5: + return "5 bytes (mis-aligned access)"; + break; + case 6: + return "6 bytes (mis-aligned access)"; + break; + case 7: + return "7 bytes (mis-aligned access)"; + break; + case 8: + return "8 bytes (64-bit/double)"; + break; + case 9: + return "16 bytes (128-bit)"; + break; + case 10: + return "32 bytes (256-bit)"; + break; + case 11: + return "64 bytes (512-bit)"; + break; + default: + return "Reserved"; + break; + }; + } + break; + case 0x1: // NPC + { + switch (dsz_) { + case 1: + return "2 bytes"; + break; + case 2: + return "3 bytes"; + break; + case 3: + return "4 bytes"; + break; + case 4: + return "5 bytes"; + break; + case 5: + return "6 bytes"; + break; + case 6: + return "7 bytes"; + break; + case 7: + return "8 bytes"; + break; + case 8: + return "16 bytes"; + break; + case 9: + return "32 bytes"; + break; + case 10: + return "64 bytes"; + break; + case 11: + return "128 bytes"; + break; + case 12: + return "256 bytes"; + break; + default: + return "Not Supported"; + break; + }; + } + break; + default: // All other sources + break; + }; + + return "UNKNOWN"; +} + +// decode message info from the packet set +bool NxDataTraceWrite::decode(NxPacketSet &pkt_set) +{ + bool ret = true; + source_id_ = decodeSourceId(pkt_set); + + // index, start_pos, length + dsz_ = pkt_set.getField32(0, 12, 4); + + // index, start_pos, length + addr_ = pkt_set.getField64(0, 16, 64); + + // index, start_pos, length + data_ = pkt_set.getField64(1, 0, 64); + + // if there is a optional timestamp + if (pkt_set.packetAtIndexExists(2)) { + timestamp_ = decodeTimestamp(pkt_set, 2); + } + return ret; +} + +// represent this message as a formatted string +string NxDataTraceWrite::asString() const +{ + ostringstream os; + os << "TCODE : " << dec << tcode() << " " << tcodeString() << endl; + os << "SRC ID : " << dec << sourceId() << " " << sourceIdString() + << endl; + os << "DSZ : 0x" << hex << setfill('0') << setw(1) << dsz_; + os << " - " << dszString() << endl; + os << "U-ADDR : 0x" << hex << setfill('0') << setw(16) << addr_ + << endl; + os << "DATA : 0x" << hex << setfill('0') << setw(16) << data_ + << endl; + os << "TIMESTAMP : " << timestampAsString() << endl; + return os.str(); +} + + +// decode message info from the packet set +bool NxDataTraceRead::decode(NxPacketSet &pkt_set) +{ + bool ret = true; + source_id_ = decodeSourceId(pkt_set); + + // index, start_pos, length + dsz_ = pkt_set.getField32(0, 12, 4); + + // index, start_pos, length + addr_ = pkt_set.getField64(0, 16, 64); + + // index, start_pos, length + data_ = pkt_set.getField64(1, 0, 64); + + // if there is a optional timestamp + if (pkt_set.packetAtIndexExists(2)) { + timestamp_ = decodeTimestamp(pkt_set, 2); + } + return ret; +} + +// represent this message as a formatted string +string NxDataTraceRead::asString() const +{ + ostringstream os; + os << "TCODE : " << dec << tcode() << " " << tcodeString() << endl; + os << "SRC ID : " << dec << sourceId() << " " << sourceIdString() + << endl; + os << "DSZ : 0x" << hex << setfill('0') << setw(1) << dsz_; + os << " - " << dszString() << endl; + os << "U-ADDR : 0x" << hex << setfill('0') << setw(16) << addr_ + << endl; + os << "DATA : 0x" << hex << setfill('0') << setw(16) << data_ + << endl; + os << "TIMESTAMP : " << timestampAsString() << endl; + return os.str(); +} + +// decode message info from the packet set +bool NxDataTraceWriteSync::decode(NxPacketSet &pkt_set) +{ + bool ret = true; + source_id_ = decodeSourceId(pkt_set); + + // index, start_pos, length + dsz_ = pkt_set.getField32(0, 12, 4); + + // index, start_pos, length + addr_ = pkt_set.getField64(0, 16, 64); + + // index, start_pos, length + data_ = pkt_set.getField64(1, 0, 64); + + // if there is a optional timestamp + if (pkt_set.packetAtIndexExists(2)) { + timestamp_ = decodeTimestamp(pkt_set, 2); + } + return ret; +} + +// represent this message as a formatted string +string NxDataTraceWriteSync::asString() const +{ + ostringstream os; + os << "TCODE : " << dec << tcode() << " " << tcodeString() << endl; + os << "SRC ID : " << dec << sourceId() << " " << sourceIdString() + << endl; + os << "DSZ : 0x" << hex << setfill('0') << setw(1) << dsz_; + os << " - " << dszString() << endl; + os << "F-ADDR : 0x" << hex << setfill('0') << setw(16) << addr_ + << endl; + os << "DATA : 0x" << hex << setfill('0') << setw(16) << data_ + << endl; + os << "TIMESTAMP : " << timestampAsString() << endl; + return os.str(); +} + + +// decode message info from the packet set +bool NxDataTraceReadSync::decode(NxPacketSet &pkt_set) +{ + bool ret = true; + source_id_ = decodeSourceId(pkt_set); + + // index, start_pos, length + dsz_ = pkt_set.getField32(0, 12, 4); + + // index, start_pos, length + addr_ = pkt_set.getField64(0, 16, 64); + + // index, start_pos, length + data_ = pkt_set.getField64(1, 0, 64); + + // if there is a optional timestamp + if (pkt_set.packetAtIndexExists(2)) { + timestamp_ = decodeTimestamp(pkt_set, 2); + } + return ret; +} + +// represent this message as a formatted string +string NxDataTraceReadSync::asString() const +{ + ostringstream os; + os << "TCODE : " << dec << tcode() << " " << tcodeString() << endl; + os << "SRC ID : " << dec << sourceId() << " " << sourceIdString() + << endl; + os << "DSZ : 0x" << hex << setfill('0') << setw(1) << dsz_; + os << " - " << dszString() << endl; + os << "F-ADDR : 0x" << hex << setfill('0') << setw(16) << addr_ + << endl; + os << "DATA : 0x" << hex << setfill('0') << setw(16) << data_ + << endl; + os << "TIMESTAMP : " << timestampAsString() << endl; + return os.str(); +} + +// decode message info from the packet set +bool NxWatchpointMessage::decode(NxPacketSet &pkt_set) +{ + bool ret = true; + source_id_ = decodeSourceId(pkt_set); + + // determine the number of bits used to represent wphit_ + if (pkt_set.getNumMDO(0) > 1) { + wphit_size_ = 32; + } + + // index, start_pos, length + wphit_ = pkt_set.getField32(0, 12, wphit_size_); + + // if there is a optional timestamp + if (pkt_set.packetAtIndexExists(1)) { + timestamp_ = decodeTimestamp(pkt_set, 1); + } + + return ret; +} + +// represent this message as a formatted string +string NxWatchpointMessage::asString() const +{ + ostringstream os; + os << "TCODE : " << dec << tcode() << " " << tcodeString() << endl; + os << "SRC ID : " << dec << sourceId() << " " << sourceIdString() + << endl; + os << "WPHIT : 0x" << hex << setfill('0') << setw(wphit_size_ / 4) + << wphit_ << " " << wphitString() << endl; + os << "TIMESTAMP : " << timestampAsString() << endl; + return os.str(); +} + +// decode the data as a string +string NxWatchpointMessage::wphitString() const +{ + ostringstream os; + switch (source_id_) { + case 0x0: // Cores 0-7 + case 0x2: + case 0x4: + case 0x6: + case 0x8: + case 0xa: + case 0xc: + case 0xe: + if (wphit_ & 0x4000) + os << "Reserved:"; + if (wphit_ & 0x2000) + os << "PMW2:"; + if (wphit_ & 0x1000) + os << "PMW1:"; + if (wphit_ & 0x0800) + os << "PMW0:"; + if (wphit_ & 0x0400) + os << "PID:"; + if (wphit_ & 0x0200) + os << "DVT1:"; + if (wphit_ & 0x0100) + os << "DVT0:"; + if (wphit_ & 0x0080) + os << "EVTI1:"; + if (wphit_ & 0x0040) + os << "EVTI0:"; + if (wphit_ & 0x0020) + os << "DAC2:"; + if (wphit_ & 0x0010) + os << "DAC1:"; + if (wphit_ & 0x0008) + os << "RFI:"; + if (wphit_ & 0x0004) + os << "INT:"; + if (wphit_ & 0x0002) + os << "IAC2:"; + if (wphit_ & 0x0001) + os << "IAC1:"; + break; + case 0x1: // Nexus Port Controller + if (wphit_ & 0x0040) + os << "Client Sync:"; + if (wphit_ & 0x0020) + os << "Enter Suppress:"; + if (wphit_ & 0x0010) + os << "Tracebuffer Wrap:"; + if (wphit_ & 0x0008) + os << "MB Overflow"; + if (wphit_ & 0x0004) + os << "AXI Full:"; + if (wphit_ & 0x0002) + os << "ALT Full:"; + if (wphit_ & 0x0001) + os << "MSP Full:"; + break; + case 0x3d: //Event Processing Unit + os << ((wphit_size_ == 16) ? "SCUEVT[15:0]" : "CTREVT[31:0]"); + break; + case 0x9: // CoreNet + if (wphit_ & 0x4000) + os << "EWE1(4):"; + if (wphit_ & 0x2000) + os << "EWE1(3):"; + if (wphit_ & 0x1000) + os << "EWE1(2):"; + if (wphit_ & 0x0800) + os << "EWE1(1):"; + if (wphit_ & 0x0400) + os << "Reserved"; + if (wphit_ & 0x0200) + os << "Reserved:"; + if (wphit_ & 0x0100) + os << "Reserved:"; + if (wphit_ & 0x0080) + os << "Reserved:"; + if (wphit_ & 0x0040) + os << "CDVC:"; + if (wphit_ & 0x0020) + os << "Reserved:"; + if (wphit_ & 0x0010) + os << "Reserved:"; + if (wphit_ & 0x0008) + os << "CDAC4:"; + if (wphit_ & 0x0004) + os << "CDAC3:"; + if (wphit_ & 0x0002) + os << "CDAC2:"; + if (wphit_ & 0x0001) + os << "CDAC1:"; + break; + default: + os << "Unknown Src:" << source_id_; + break; + }; + return os.str(); +} + +// decode message info from the packet set +bool NxResourceFullMessage::decode(NxPacketSet &pkt_set) +{ + bool ret = true; + source_id_ = decodeSourceId(pkt_set); + + // index, start_pos, length + rcode_ = pkt_set.getField32(0, 12, 4); + + // index, start_pos, length + rdata_ = pkt_set.getField32(0, 16, 30); + + // if there is a optional timestamp + if (pkt_set.packetAtIndexExists(1)) { + timestamp_ = decodeTimestamp(pkt_set, 1); + } + return ret; +} + +// represent this message as a formatted string +string NxResourceFullMessage::asString() const +{ + ostringstream os; + os << "TCODE : " << dec << tcode() << " " << tcodeString() << endl; + os << "SRC ID : " << dec << sourceId() << " " << sourceIdString() + << endl; + os << "RCODE : 0x" << hex << setfill('0') << setw(1) << rcode_; + os << " - " << rcodeString() << endl; + os << "RDATA : 0x" << hex << setfill('0') << setw(8) << rdata_ + << endl; + os << "TIMESTAMP : " << timestampAsString() << endl; + return os.str(); +} +// decode the data as a string +const char * NxResourceFullMessage::rcodeString() const +{ + switch (rcode_) { + case 0: + return "Instruction counter"; + break; + case 1: + return "Branch history buffer"; + break; + case 8: + return "Timestamp counter"; + break; + default: + return "Reserved"; + break; + }; + return "UNKNOWN"; +} + +// decode message info from the packet set +bool NxProgramTraceIndirectBranch::decode(NxPacketSet &pkt_set) +{ + bool ret = true; + source_id_ = decodeSourceId(pkt_set); + + // index, start_pos, length + btype_ = pkt_set.getField32(0, 12, 2); + + // index, start_pos, length + icnt_ = pkt_set.getField32(0, 14, 8); + + // index, start_pos, length + uaddr_.lower32(pkt_set.getField32(1, 0, 32)); + if (pkt_set.getNumMDO(1) > 1) { + // get the upper 32bits of 64bit address + uaddr_.upper32(pkt_set.getField32(1, 32, 32)); + } + + // index, start_pos, length + hist_ = pkt_set.getField32(2, 0, 30); + + // if there is a optional timestamp + if (pkt_set.packetAtIndexExists(3)) { + timestamp_ = decodeTimestamp(pkt_set, 3); + } + return ret; +} + +// represent this message as a formatted string +string NxProgramTraceIndirectBranch::asString() const +{ + ostringstream os; + os << "TCODE : " << dec << tcode() << " " << tcodeString() << endl; + os << "SRC ID : " << dec << sourceId() << " " << sourceIdString() + << endl; + os << "BTYPE : 0x" << hex << setfill('0') << setw(2) << btype_; + os << " - " << btypeString() << endl; + os << "I-CNT : " << dec << icnt_ << endl; + os << "U-ADDR : " << uaddr_.asString() << endl; + os << "HIST : 0x" << hex << setfill('0') << setw(8) << hist_ + << endl; + os << "TIMESTAMP : " << timestampAsString() << endl; + return os.str(); +} + +// decode the data as a string +const char * NxProgramTraceIndirectBranch::btypeString() const +{ + switch (btype_) { + case 0: + return "Branch Instruction"; + break; + case 1: + return "Interrupt"; + break; + default: + return "Reserved"; + break; + }; + return "UNKNOWN"; +} + +// decode message info from the packet set +bool NxProgramTraceIndirectBranchSync::decode(NxPacketSet &pkt_set) +{ + bool ret = true; + source_id_ = decodeSourceId(pkt_set); + + // index, start_pos, length + btype_ = pkt_set.getField32(0, 12, 2); + + // index, start_pos, length + icnt_ = pkt_set.getField32(0, 14, 8); + + // index, start_pos, length + faddr_.lower32(pkt_set.getField32(1, 0, 32)); + if (pkt_set.getNumMDO(1) > 1) { + // get the upper 32bits of 64bit address + faddr_.upper32(pkt_set.getField32(1, 32, 32)); + } + + // index, start_pos, length + hist_ = pkt_set.getField32(2, 0, 30); + + // if there is a optional timestamp + if (pkt_set.packetAtIndexExists(3)) { + timestamp_ = decodeTimestamp(pkt_set, 3); + } + return ret; +} + +// represent this message as a formatted string +string NxProgramTraceIndirectBranchSync::asString() const +{ + ostringstream os; + os << "TCODE : " << dec << tcode() << " " << tcodeString() << endl; + os << "SRC ID : " << dec << sourceId() << " " << sourceIdString() + << endl; + os << "BTYPE : 0x" << hex << setfill('0') << setw(1) << btype_; + os << " - " << btypeString() << endl; + os << "I-CNT : " << dec << icnt_ << endl; + os << "F-ADDR : " << faddr_.asString() << endl; + os << "HIST : 0x" << hex << setfill('0') << setw(8) << hist_ + << endl; + os << "TIMESTAMP : " << timestampAsString() << endl; + return os.str(); +} + +// decode the data as a string +const char * NxProgramTraceIndirectBranchSync::btypeString() const +{ + switch (btype_) { + case 0: + return "Branch Instruction"; + break; + case 1: + return "Interrupt"; + break; + default: + return "Reserved"; + break; + }; + return "UNKNOWN"; +} + +// decode message info from the packet set +bool NxProgramTraceCorrelation::decode(NxPacketSet &pkt_set) +{ + bool ret = true; + source_id_ = decodeSourceId(pkt_set); + + // index, start_pos, length + evcode_ = pkt_set.getField32(0, 12, 4); + + // index, start_pos, length + icnt_ = pkt_set.getField32(0, 16, 8); + + // index, start_pos, length + cdata_ = pkt_set.getField32(1, 0, 32); + + // if there is a optional timestamp + if (pkt_set.packetAtIndexExists(2)) { + timestamp_ = decodeTimestamp(pkt_set, 2); + } + return ret; +} + +// represent this message as a formatted string +string NxProgramTraceCorrelation::asString() const +{ + ostringstream os; + os << "TCODE : " << dec << tcode() << " " << tcodeString() << endl; + os << "SRC ID : " << dec << sourceId() << " " << sourceIdString() + << endl; + os << "EVCODE : 0x" << hex << setfill('0') << setw(1) << evcode_; + os << " - " << evcodeString() << endl; + os << "I-CNT : " << dec << icnt_ << endl; + os << "CDATA : 0x" << hex << setfill('0') << setw(8) << cdata_ + << endl; + os << "TIMESTAMP : " << timestampAsString() << endl; + return os.str(); +} + +// decode the data as a string +const char * NxProgramTraceCorrelation::evcodeString() const +{ + switch (evcode_) { + case 0: + return "Entry into Halted state for debug"; + break; + case 1: + return "Entry into Halted or Stopped state for Power Mgt."; + break; + case 4: + return "Program Trace disabled"; + break; + case 9: + return "Begin masking of program trace due to MSR[PMM] = 0"; + break; + case 10: + return "Branch and link occurrence"; + break; + default: + return "Reserved"; + break; + }; + return "UNKNOWN"; +} + +// ICT for both TCode 34,35 +string NxInCircuitTraceBase::tcodeString() const +{ + switch (tcode()) { + case 34: + return "In-Circuit Trace Message"; + break; + case 35: + return "In-Circuit Trace Sync Message"; + break; + default: + return "ICT Reserved"; + break; + }; + return "UNKNOWN"; +} + +// decode message info from the packet set +bool NxInCircuitTraceMessage::decode(NxPacketSet &pkt_set) +{ + bool ret = true; + source_id_ = decodeSourceId(pkt_set); + + // if there is a optional timestamp + if (pkt_set.packetAtIndexExists(1)) { + timestamp_ = decodeTimestamp(pkt_set, 1); + } + + return ret; +} + +// represent this message as a formatted string +string NxInCircuitTraceMessage::asString() const +{ + ostringstream os; + os << "TCODE : " << dec << tcode() << " " << tcodeString() << endl; + os << "SRC ID : " << dec << sourceId() << " " << sourceIdString() + << endl; + os << "MSG TYPE : " << ICTMessageType() << endl; + os << "TIMESTAMP : " << timestampAsString() << endl; + + return os.str(); +} + +// decode message info from the packet set +bool NxDAMInCircuitTraceMessage::decode(NxPacketSet &pkt_set) +{ + bool ret = true; + source_id_ = decodeSourceId(pkt_set); + + // index, start_pos, length + ddrmid_ = pkt_set.getField32(0, 12, 1); + ddrsid_ = pkt_set.getField32(0, 13, 8); + ddrtt_ = pkt_set.getField32(0, 21, 3); + if (ddrmid_) { + ddrsz_ = pkt_set.getField32(0, 24, 4); + uint32_t ddraddr_1 = pkt_set.getField32(0, 28, 2); + dddiec_ = pkt_set.getField32(0, 30, 11); + uint64_t ddraddr_2 = pkt_set.getField64(0, 41, 34); + ddraddr_ = (ddraddr_2 << 2) | (ddraddr_1 & 0x3); + } else { + ddraddr_ = pkt_set.getField64(0, 24, 36); + } + + // if there is a optional timestamp + if (pkt_set.packetAtIndexExists(1)) { + timestamp_ = decodeTimestamp(pkt_set, 1); + } + + return ret; +} + +// decode the type data as a string +const char * NxDAMInCircuitTraceMessage::ddrttString() const +{ + switch (ddrtt_) { + case 0: + return "Write Transaction"; + break; + case 1: + return "Read Transaction"; + break; + case 3: + return "Speculative Read Transaction"; + break; + case 4: + return "Atomic_Clr; RMW, Clear selected fields to zero"; + break; + case 5: + return "Atomic_Set; RMW, Set selected fields to zero"; + break; + case 6: + return "Atomic_Dec; RMW, Decrement selected field"; + break; + case 7: + return "Atomic_Inc; RMW, Increment selected field"; + break; + case 2: + // fall through to default + default: + return "Reserved"; + break; + }; + return "UNKNOWN"; +} + +// decode the size data as a string +string NxDAMInCircuitTraceMessage::ddrszString() const +{ + ostringstream os; + if (ddrsz_) + os << ddrsz_ << "DW"; + else + os << "16DW"; + + return os.str(); +} + +// represent this message as a formatted string +string NxDAMInCircuitTraceMessage::asString() const +{ + ostringstream os; + os << "TCODE : " << dec << tcode() << " " << tcodeString() << endl; + os << "SRC ID : " << dec << sourceId() << " " << sourceIdString() + << endl; + os << "MSG TYPE : " << ICTMessageType() << endl; + os << "DDR MID : " << ddrmid_ << " " + << (ddrmid_ ? "Verbose" : "Terse") << endl; + os << "DDR SID : " << dec << ddrsid_ << endl; + os << "DDR TT : " << dec << ddrtt_ << " " << ddrttString() << endl; + if (ddrmid_) { + os << "DDR SZ : " << dec << ddrsz_ << " " << ddrszString() + << endl; + os << "DDDIEC : " << dec << dddiec_ << endl; + } + if (isSyncMessage()) { + os << "F-ADDR : " << hex << "0x" << ddraddr_ << endl; + } else { + os << "U-ADDR : " << hex << "0x" << ddraddr_ << endl; + } + os << "TIMESTAMP : " << timestampAsString() << endl; + return os.str(); +} + +// decode message info from the packet set +bool NxDPQMInCircuitTraceMessage::decode(NxPacketSet &pkt_set) +{ + bool ret = true; + source_id_ = decodeSourceId(pkt_set); + + // index, start_pos, length + verb_ = pkt_set.getField32(0, 12, 1); + dpdm_ = pkt_set.getField32(0, 13, 2); + fqid_ = pkt_set.getField32(0, 15, 24); + cnum_ = pkt_set.getField32(0, 39, 13); + pnum_ = pkt_set.getField32(0, 52, 5); + ptype_ = pkt_set.getField32(0, 57, 1); + qet_ = pkt_set.getField32(0, 58, 2); + orf_ = pkt_set.getField32(0, 60, 1); + erf_ = pkt_set.getField32(0, 61, 1); + err_ = pkt_set.getField32(0, 62, 4); + + if (verb_) { + fmbpid_ = pkt_set.getField32(0, 66, 6); + fmsc_ = pkt_set.getField32(0, 72, 32); + fmol_ = pkt_set.getField32(0, 104, 29); + fmfmt_ = pkt_set.getField32(0, 133, 3); + fmpid_ = pkt_set.getField32(0, 136, 6); + fmaddr_ = pkt_set.getField64(0, 142, 48); + } + // if there is a optional timestamp + if (pkt_set.packetAtIndexExists(1)) { + timestamp_ = decodeTimestamp(pkt_set, 1); + } + + return ret; +} + +// decode the queue event type as a string +const char * NxDPQMInCircuitTraceMessage::queueEventTypeString() const +{ + switch (qet_) { + case 0: + return "Enqueue Command Event"; + break; + case 1: + return "Deferred Enqueue Complete"; + break; + case 2: + return "Dequeue Trace Event"; + break; + default: + return "Reserved"; + break; + }; + return "UNKNOWN"; +} + +// decode the enqueue rejection response code as a string +const char * NxDPQMInCircuitTraceMessage::enqueueRejectionString() const +{ + if (erf_) { + switch (err_) { + case 0: + return "Enqueue Command Event"; + break; + case 1: + return "Deferred Enqueue Complete"; + break; + case 2: + return "Dequeue Trace Event"; + break; + default: + return "Reserved"; + break; + }; + } + return "Undefined"; +} + +// represent this message as a formatted string +string NxDPQMInCircuitTraceMessage::asString() const +{ + ostringstream os; + os << "TCODE : " << dec << tcode() << " " << tcodeString() << endl; + os << "SRC ID : " << dec << sourceId() << " " << sourceIdString() + << endl; + os << "MSG TYPE : " << ICTMessageType() << endl; + os << "DBG MARK : " << dec << dpdm_ << endl; + os << "FQ ID : 0x" << hex << fqid_ << dec << endl; + os << "CH NUM : 0x" << hex << cnum_ << dec << endl; + os << "PORT NUM : " << dec << pnum_ << endl; + os << "PORT TYP : " << dec << ptype_ + << (ptype_ ? " Direct Connect" : " Software") << endl; + os << "QEVNT TYP : " << dec << qet_ << " " << queueEventTypeString() + << endl; + os << "ORD REST : " << dec << orf_ << " Order Restoration" + << (orf_ ? " was" : " was NOT") << " specified at enqueue" + << endl; + os << "ENQ REJCT : " << dec << orf_ << " Enqueue operation" + << (orf_ ? " was" : " was NOT") << " rejected" << endl; + os << "ENQ RESP : " << hex << "0x" << err_ << dec << " " + << enqueueRejectionString() << endl; + + if (verb_) { + os << "FRM BP ID : " << hex << "0x" << fmbpid_ << dec << endl; + os << "FRM STAT : " << hex << "0x" << fmsc_ << dec << endl; + os << "FRM OFSET : " << hex << "0x" << fmol_ << dec << endl; + os << "FRM FMT : " << hex << "0x" << fmfmt_ << dec << endl; + os << "FRM PRT ID: " << hex << "0x" << fmpid_ << dec << endl; + os << "FRM ADDR : " << hex << "0x" << hex << setfill('0') + << setw(16) << fmaddr_ << dec << endl; + } + + os << "TIMESTAMP : " << timestampAsString() << endl; + + return os.str(); +} +// decode message info from the packet set +bool NxDPFMInCircuitTraceMessage::decode(NxPacketSet &pkt_set) +{ + bool ret = true; + source_id_ = decodeSourceId(pkt_set); + + // index, start_pos, length + fmsel_ = pkt_set.getField32(0, 12, 1); + lbeat_ = pkt_set.getField32(0, 13, 1); + btcnt_ = pkt_set.getField32(0, 14, 6); + + // capture the 128bit context data + // Fman debug data is byte swapped on word boundries + for (int i = 0; i < 4; i++) { + context_[i] = SWAPBYTES32(pkt_set.getField32(0, 20+i*32, 32)); + } + + // if there is a optional timestamp + if (pkt_set.packetAtIndexExists(1)) { + timestamp_ = decodeTimestamp(pkt_set, 1); + } + + return ret; +} + +// represent this message as a formatted string +string NxDPFMInCircuitTraceMessage::asString() const +{ + ostringstream os; + os << "TCODE : " << dec << tcode() << " " << tcodeString() << endl; + os << "SRC ID : " << dec << sourceId() << " " << sourceIdString() + << endl; + os << "MSG TYPE : " << ICTMessageType() << endl; + os << "FMAN SEL : " << dec << fmsel_ << " FMAN" << (fmsel_ ? "2" : "1") + << endl; + os << "LAST BEAT : " << dec << lbeat_ << endl; + os << "BEAT CNT : " << dec << btcnt_ << endl; + os << "CONTEXT : " << hex << "0x" << hex << setfill('0') << setw(8) + << context_[0] << ":" << setfill('0') << setw(8) << context_[1] + << ":" << setfill('0') << setw(8) << context_[2] << ":" + << setfill('0') << setw(8) << context_[3] << dec << endl; + + os << "TIMESTAMP : " << timestampAsString() << endl; + + return os.str(); +} + +// decode message info from the packet set +bool NxCoreInCircuitTraceMessage::decode(NxPacketSet &pkt_set) +{ + bool ret = true; + source_id_ = decodeSourceId(pkt_set); + + // index, start_pos, length + cksrc_ = pkt_set.getField32(0, 12, 3); + sync_ = pkt_set.getField32(0, 15, 2); + ckdf_ = pkt_set.getField32(0, 17, 2); + switch (ckdf_) { + case 0: + ckdata1_ = pkt_set.getField32(0, 19, 32); + break; + case 1: + ckdata1_ = pkt_set.getField32(0, 19, 32); + ckdata2_ = pkt_set.getField32(1, 0, 32); + break; + default: + break; + }; + + // if there is a optional timestamp + if (pkt_set.packetAtIndexExists(2)) { + timestamp_ = decodeTimestamp(pkt_set, 2); + } + + return ret; +} + +// decode the sync code as a string +const char * NxCoreInCircuitTraceMessage::syncString() const +{ + switch (sync_) { + case 0: + return "Previous Message successful"; + break; + case 1: + return "Previous Message not sent due to contention"; + break; + case 2: + return "Previous Snapshot not completed"; + break; + default: + return "Reserved"; + break; + }; + + return "Reserved"; +} + +// decode the sync code as a string +const char * NxCoreInCircuitTraceMessage::cksrcString() const +{ + switch (cksrc_) { + case 0: + return "PCC[0:61]"; + break; + case 1: + return "PMCC0[32:64], PMCC1[32:64]"; + break; + case 2: + return "PMCC2[32:64], PMCC3[32:64]"; + break; + case 3: + return "PMCC4[32:64], PMCC5[32:64]"; + break; + default: + return "Reserved"; + break; + }; + + return "Reserved"; +} + +// represent this message as a formatted string +string NxCoreInCircuitTraceMessage::asString() const +{ + ostringstream os; + os << "TCODE : " << dec << tcode() << " " << tcodeString() << endl; + os << "SRC ID : " << dec << sourceId() << " " << sourceIdString() + << endl; + os << "MSG TYPE : " << ICTMessageType() << endl; + os << "CKSRC : " << cksrc_ << " - " << cksrcString() << endl; + os << "SYNC : " << sync_ << " - " << syncString() << endl; + os << "CKDF : " << ckdf_ << " - " << ckdf_+1 << " CKDATA fields included" << endl; + os << "CKDATA1 : " << "0x" << hex << setfill('0') << setw(8) << ckdata1_ << endl; + if (ckdf_) { + os << "CKDATA2 : " << "0x" << hex << setfill('0') << setw(8) << ckdata2_ << endl; + } + os << "TIMESTAMP : " << timestampAsString() << endl; + return os.str(); +} + +// decode message info from the packet set +bool NxTimeStampCorrelation::decode(NxPacketSet &pkt_set) +{ + bool ret = true; + source_id_ = decodeSourceId(pkt_set); + + // index, start_pos, length + tcorr_ = pkt_set.getField32(0, 12, 4); + ttype_ = pkt_set.getField32(0, 17, 6); + + // T4rev1 errata A-004813 + if ((source_id_ & 0x1) == 0) { + tcorr_ = pkt_set.getField32(0, 16, 4); + ttype_ = pkt_set.getField32(0, 20, 6); + } + + // if there is a optional timestamp + if (pkt_set.packetAtIndexExists(1)) { + timestamp_ = decodeTimestamp(pkt_set, 1); + } + + return ret; +} + +// represent this message as a formatted string +string NxTimeStampCorrelation::asString() const +{ + ostringstream os; + os << "TCODE : " << dec << tcode() << " " << tcodeString() << endl; + os << "SRC ID : " << dec << sourceId() << " " << sourceIdString() + << endl; + os << "TCORR : 0x" << hex << setfill('0') << setw(4) << tcorr_ + << endl; + os << "T-TYPE : 0x" << hex << setfill('0') << setw(6) << ttype_ + << " - " << ttypeString() << endl; + os << "TIMESTAMP : " << timestampAsString() << endl; + return os.str(); +} + +// decode the time stamp type code as a string +const char * NxTimeStampCorrelation::ttypeString() const +{ + switch (ttype_) { + case 0: + return "Periodic"; + break; + case 1: + return "Halt Mode Exit"; + break; + case 2: + return "Low Power Mode Exit"; + break; + case 3: + return "External Event"; + break; + case 8: + return "CLK1"; + break; + case 9: + return "CLK1/2"; + break; + case 10: + return "CLK1/4"; + break; + case 11: + return "CLK2"; + break; + case 12: + return "CLK2/2"; + break; + case 13: + return "CLK2/4"; + break; + case 14: + return "CLK3"; + break; + case 15: + return "CLK3/2"; + break; + case 16: + return "CLK3/4"; + break; + case 0x3f: + return "Unknown"; + break; + default: + return "Reserved"; + break; + }; + + return "Reserved"; +} diff --git a/converter/nexus/NxMessage.h b/converter/nexus/NxMessage.h new file mode 100644 index 00000000..a762ab01 --- /dev/null +++ b/converter/nexus/NxMessage.h @@ -0,0 +1,1213 @@ +/* + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef NXMESSAGE_H +#define NXMESSAGE_H + +#include "NxPacketSet.h" +#include "NxMessageVisitor.h" +#include "SizedAddress.h" +#include +#include + +using std::string; + +/*! + Base class for all types of Nexus Message structures. Type is based on a TCODE value. + */ +class NxMessage +{ +public: + /*! + @abstract Constructor + @param tcode Set the TCODE value. Default 0x3f which is an unused (unlikely) code value. + */ + NxMessage(uint32_t tcode) : + tcode_(tcode), source_id_(0), timestamp_(0) + { + } + virtual ~NxMessage() + { + } + + // NxMessage implements the standard visitor pattern. + virtual void accept(NxMessageVisitor &v) = 0; + + /*! + @abstract Returns the TCODE value + @return the tcode for this message + */ + uint32_t tcode() const + { + return tcode_; + } + + /*! + @abstract Returns the TCODE string + @return the tcode as a string + */ + virtual string tcodeString() const; + + /*! + @abstract Returns the SRC_ID value + @return the source_id for this message + */ + uint32_t sourceId() const + { + return source_id_; + } + + /*! + @abstract Annotates the SRC_ID as string + @return the SRC_ID as a string + */ + const char * sourceIdString() const; + + /*! + @abstract Returns the TIMESTAMP value + @return the timestamp for this message + */ + uint32_t timestamp() const + { + return timestamp_; + } + + /*! + @abstract Determines if the TIMESTAMP value needs correction + @return True if the timestamp needs correction + */ + bool timestampNeedsCorrection() const; + + /*! + @abstract Returns the corrected TIMESTAMP value + @return the corrected timestamp for this message + */ + uint32_t correctedTimestamp() const; + + /*! + @abstract Output timestamp information as a string + @return a string representing the timestamp + */ + string timestampAsString() const; + + /*! + @abstract Decode Nexus message info from the packet set + @param pkt_set Reference to a NxPackageSet containing the data to be decoded + @return True if no error + */ + virtual bool decode(NxPacketSet &pkt_set) = 0; + + /*! + @abstract Output message information as a string + @return a string representing the Nexus message content + */ + virtual string asString() const; + +protected: + + /*! + @abstract Decode the SRC ID from the packet set + @param pkt_set Reference to a NxPackageSet containing the data to be decoded + @return the SRC ID value + */ + uint32_t decodeSourceId(NxPacketSet &pkt_set); + + /*! + @abstract Decode the TIMESTAMP value from the packet set at index + @param pkt_set Reference to a NxPackageSet containing the data to be decoded + @param index The index of the NxPacket in the NxPacketSet collection + @return the TIMESTAMP value + */ + uint32_t decodeTimestamp(NxPacketSet &pkt_set, uint32_t index); + + /*! @var tcode_ contains the TCODE value which determines the type of NxMessage */ + uint32_t tcode_; + + /*! @var source_id_ contains the SRC ID value */ + uint32_t source_id_; + + /*! @var timestamp_ contains the optional TIMESTAMP value */ + uint32_t timestamp_; +}; + +// This type is the default for all unknown message types +class NxDefaultMessage: public NxMessage +{ +public: + NxDefaultMessage(uint32_t tcode) : + NxMessage(tcode) + { + } + ~NxDefaultMessage() + { + } + + // NxMessage implements the standard visitor pattern. + virtual void accept(NxMessageVisitor &v) + { + v.visit(this); + } + + // decode message info from the packet set + virtual bool decode(NxPacketSet &pkt_set) + { + return true; + } +}; + +class NxDebugStatusMessage: public NxMessage +{ +public: + NxDebugStatusMessage() : + NxMessage(0), status_(0) + { + } + ~NxDebugStatusMessage() + { + } + + // NxMessage implements the standard visitor pattern. + virtual void accept(NxMessageVisitor &v) + { + v.visit(this); + } + + /*! + @abstract Returns the TCODE string + @return the tcode as a string + */ + virtual string tcodeString() const + { + return "Debug Status Message"; + } + + // decode message info from the packet set + virtual bool decode(NxPacketSet &pkt_set); + + // output message information as a string + virtual string asString() const; + +private: + + // STATUS + uint32_t status_; +}; + +class NxDeviceIDMessage: public NxMessage +{ +public: + NxDeviceIDMessage() : + NxMessage(1) + { + } + ~NxDeviceIDMessage() + { + } + + // NxMessage implements the standard visitor pattern. + virtual void accept(NxMessageVisitor &v) + { + v.visit(this); + } + + /*! + @abstract Returns the TCODE string + @return the tcode as a string + */ + virtual string tcodeString() const + { + return "Device ID Message"; + } + + // decode message info from the packet set + virtual bool decode(NxPacketSet &pkt_set); + + // output message information as a string + virtual string asString() const; + +private: + +}; + +class NxOwnershipTraceMessage: public NxMessage +{ +public: + NxOwnershipTraceMessage() : + NxMessage(2), pid_index_(0), pid_value_(0) + { + } + ~NxOwnershipTraceMessage() + { + } + + // NxMessage implements the standard visitor pattern. + virtual void accept(NxMessageVisitor &v) + { + v.visit(this); + } + + /*! + @abstract Returns the TCODE string + @return the tcode as a string + */ + virtual string tcodeString() const + { + return "Ownership Trace Message"; + } + + // decode message info from the packet set + virtual bool decode(NxPacketSet &pkt_set); + + // output message information as a string + virtual string asString() const; + + // decode the data as a string + const char * pidIndexString() const; + + // decode the data as a string + const char * pidValueString() const; + +private: + + // PROCESS subfields + uint32_t pid_index_; + uint64_t pid_value_; + +}; + +class NxDataAcquisitionMessage: public NxMessage +{ +public: + NxDataAcquisitionMessage() : + NxMessage(7), idtag_(0), dqdata_(0) + { + } + ~NxDataAcquisitionMessage() + { + } + + // NxMessage implements the standard visitor pattern. + virtual void accept(NxMessageVisitor &v) + { + v.visit(this); + } + + /*! + @abstract Returns the TCODE string + @return the tcode as a string + */ + virtual string tcodeString() const + { + return "Data Acquisition Message"; + } + + // decode message info from the packet set + virtual bool decode(NxPacketSet &pkt_set); + + // output message information as a string + virtual string asString() const; + + // decode the data as a string + const char * idtagString() const; + + // decode the data as a string + string dqdataString() const; + +private: + + // IDTAG + uint32_t idtag_; + + // DQDATA + uint32_t dqdata_; +}; + +class NxErrorMessage: public NxMessage +{ +public: + NxErrorMessage() : + NxMessage(8), etype_(0), ecode_(0) + { + } + ~NxErrorMessage() + { + } + + // NxMessage implements the standard visitor pattern. + virtual void accept(NxMessageVisitor &v) + { + v.visit(this); + } + + /*! + @abstract Returns the TCODE string + @return the tcode as a string + */ + virtual string tcodeString() const + { + return "Error Message"; + } + + // decode message info from the packet set + virtual bool decode(NxPacketSet &pkt_set); + + // output message information as a string + virtual string asString() const; + + // decode the data as a string + const char * etypeString() const; + + // decode the data as a string + string ecodeString() const; + +private: + + // IDTAG + uint32_t etype_; + + // DQDATA + uint32_t ecode_; +}; + +// NxProgramTraceSync +class NxProgramTraceSync: public NxMessage +{ +public: + NxProgramTraceSync() : + NxMessage(9), map_(0), icnt_(0), hist_(0) + { + } + ~NxProgramTraceSync() + { + } + + // NxMessage implements the standard visitor pattern. + virtual void accept(NxMessageVisitor &v) + { + v.visit(this); + } + + /*! + @abstract Returns the TCODE string + @return the tcode as a string + */ + virtual string tcodeString() const + { + return "Program Trace Synchronization"; + } + + // decode message info from the packet set + virtual bool decode(NxPacketSet &pkt_set); + + // output message information as a string + virtual string asString() const; + + // get the address value + const SizedAddress& address() const + { + return pc_; + } + +private: + + // MAP + uint32_t map_; + + // I-CNT + uint32_t icnt_; + + // PC + SizedAddress pc_; + + // HIST + uint32_t hist_; +}; + +// NxDataTrace Base class +class NxDataTraceBase: public NxMessage +{ +public: + NxDataTraceBase(uint32_t tcode) : + NxMessage(tcode), + dsz_(0), + addr_(0), + data_(0) + { + } + virtual ~NxDataTraceBase() + { + } + +protected: + + // decode the data as a string + const char * dszString() const; + + // DSZ + uint32_t dsz_; + + // ADDR + uint64_t addr_; + + // Data + uint64_t data_; + +}; + +// NxDataTraceWrite +class NxDataTraceWrite: public NxDataTraceBase +{ +public: + NxDataTraceWrite() : + NxDataTraceBase(5) + { + } + ~NxDataTraceWrite() + { + } + + // NxMessage implements the standard visitor pattern. + virtual void accept(NxMessageVisitor &v) + { + v.visit(this); + } + + /*! + @abstract Returns the TCODE string + @return the tcode as a string + */ + virtual string tcodeString() const + { + return "Data Trace - Data Write"; + } + + // decode message info from the packet set + virtual bool decode(NxPacketSet &pkt_set); + + // output message information as a string + virtual string asString() const; + +private: + +}; + +// NxDataTraceRead +class NxDataTraceRead: public NxDataTraceBase +{ +public: + NxDataTraceRead() : + NxDataTraceBase(6) + { + } + ~NxDataTraceRead() + { + } + + // NxMessage implements the standard visitor pattern. + virtual void accept(NxMessageVisitor &v) + { + v.visit(this); + } + + /*! + @abstract Returns the TCODE string + @return the tcode as a string + */ + virtual string tcodeString() const + { + return "Data Trace - Data Read"; + } + + // decode message info from the packet set + virtual bool decode(NxPacketSet &pkt_set); + + // output message information as a string + virtual string asString() const; + +private: + +}; + +// NxDataTraceWriteSync +class NxDataTraceWriteSync: public NxDataTraceBase +{ +public: + NxDataTraceWriteSync() : + NxDataTraceBase(13) + { + } + ~NxDataTraceWriteSync() + { + } + + // NxMessage implements the standard visitor pattern. + virtual void accept(NxMessageVisitor &v) + { + v.visit(this); + } + + /*! + @abstract Returns the TCODE string + @return the tcode as a string + */ + virtual string tcodeString() const + { + return "Data Trace - Data Write w/sync"; + } + + // decode message info from the packet set + virtual bool decode(NxPacketSet &pkt_set); + + // output message information as a string + virtual string asString() const; + +private: + +}; + +// NxDataTraceReadSync +class NxDataTraceReadSync: public NxDataTraceBase +{ +public: + NxDataTraceReadSync() : + NxDataTraceBase(14) + { + } + ~NxDataTraceReadSync() + { + } + + // NxMessage implements the standard visitor pattern. + virtual void accept(NxMessageVisitor &v) + { + v.visit(this); + } + + /*! + @abstract Returns the TCODE string + @return the tcode as a string + */ + virtual string tcodeString() const + { + return "Data Trace - Data Read w/sync"; + } + + // decode message info from the packet set + virtual bool decode(NxPacketSet &pkt_set); + + // output message information as a string + virtual string asString() const; + +private: + +}; + +// NxWatchpointMessage +class NxWatchpointMessage: public NxMessage +{ +public: + NxWatchpointMessage() : + NxMessage(15), wphit_(0), wphit_size_(16) + { + } + ~NxWatchpointMessage() + { + } + + // NxMessage implements the standard visitor pattern. + virtual void accept(NxMessageVisitor &v) + { + v.visit(this); + } + + /*! + @abstract Returns the TCODE string + @return the tcode as a string + */ + virtual string tcodeString() const + { + return "Watchpoint Message"; + } + + // decode message info from the packet set + virtual bool decode(NxPacketSet &pkt_set); + + // output message information as a string + virtual string asString() const; + + // decode the data as a string + string wphitString() const; + +private: + + // Watchpoint Hit + uint32_t wphit_; + + // Watchpoint Hit bit size + uint32_t wphit_size_; +}; + +class NxResourceFullMessage: public NxMessage +{ +public: + NxResourceFullMessage() : + NxMessage(27), rcode_(0), rdata_(0) + { + } + ~NxResourceFullMessage() + { + } + + // NxMessage implements the standard visitor pattern. + virtual void accept(NxMessageVisitor &v) + { + v.visit(this); + } + + /*! + @abstract Returns the TCODE string + @return the tcode as a string + */ + virtual string tcodeString() const + { + return "Resource Full Message"; + } + + // decode message info from the packet set + virtual bool decode(NxPacketSet &pkt_set); + + // output message information as a string + virtual string asString() const; + + // decode the data as a string + const char * rcodeString() const; + +private: + + // RCODE + uint32_t rcode_; + + // RDATA + uint32_t rdata_; + +}; + +class NxProgramTraceIndirectBranch: public NxMessage +{ +public: + NxProgramTraceIndirectBranch() : + NxMessage(28), btype_(0), icnt_(0), hist_(0) + { + } + ~NxProgramTraceIndirectBranch() + { + } + + // NxMessage implements the standard visitor pattern. + virtual void accept(NxMessageVisitor &v) + { + v.visit(this); + } + + /*! + @abstract Returns the TCODE string + @return the tcode as a string + */ + virtual string tcodeString() const + { + return "Program Trace - Indirect Branch History"; + } + + // decode message info from the packet set + virtual bool decode(NxPacketSet &pkt_set); + + // output message information as a string + virtual string asString() const; + + // decode the data as a string + const char * btypeString() const; + + // get the address value + const SizedAddress& address() const + { + return uaddr_; + } + +private: + + // BTYPE + uint32_t btype_; + + // I-CNT + uint32_t icnt_; + + // U-ADDR + SizedAddress uaddr_; + + // HIST + uint32_t hist_; +}; + +class NxProgramTraceIndirectBranchSync: public NxMessage +{ +public: + NxProgramTraceIndirectBranchSync() : + NxMessage(29), btype_(0), icnt_(0), hist_(0) + { + } + ~NxProgramTraceIndirectBranchSync() + { + } + + // NxMessage implements the standard visitor pattern. + virtual void accept(NxMessageVisitor &v) + { + v.visit(this); + } + + /*! + @abstract Returns the TCODE string + @return the tcode as a string + */ + virtual string tcodeString() const + { + return "Program Trace - Indirect Branch History w/sync"; + } + + // decode message info from the packet set + virtual bool decode(NxPacketSet &pkt_set); + + // output message information as a string + virtual string asString() const; + + // decode the data as a string + const char * btypeString() const; + + // get the address value + const SizedAddress& address() const + { + return faddr_; + } + +private: + + // BTYPE + uint32_t btype_; + + // I-CNT + uint32_t icnt_; + + // F-ADDR + SizedAddress faddr_; + + // HIST + uint32_t hist_; +}; + +class NxProgramTraceCorrelation: public NxMessage +{ +public: + NxProgramTraceCorrelation() : + NxMessage(33), evcode_(0), icnt_(0), cdata_(0) + { + } + ~NxProgramTraceCorrelation() + { + } + + // NxMessage implements the standard visitor pattern. + virtual void accept(NxMessageVisitor &v) + { + v.visit(this); + } + + /*! + @abstract Returns the TCODE string + @return the tcode as a string + */ + virtual string tcodeString() const + { + return "Program Trace - Program Correlation"; + } + + // decode message info from the packet set + virtual bool decode(NxPacketSet &pkt_set); + + // output message information as a string + virtual string asString() const; + + // decode the data as a string + const char * evcodeString() const; + +private: + + // EVCODE + uint32_t evcode_; + + // I-CNT + uint32_t icnt_; + + // CDATA + uint32_t cdata_; +}; + +// Abstract base class for all ICT types +class NxInCircuitTraceBase: public NxMessage +{ +public: + NxInCircuitTraceBase(uint32_t tcode) : + NxMessage(tcode) + { + } + virtual ~NxInCircuitTraceBase() + { + } + + /*! + @abstract Returns the TCODE string + @return the tcode as a string + */ + virtual string tcodeString() const; + + // return true if this ICT Message has a "Sync" tcode + virtual bool isSyncMessage() const + { + return (tcode_ == 35); + } +}; + +class NxDAMInCircuitTraceMessage: public NxInCircuitTraceBase +{ +public: + NxDAMInCircuitTraceMessage(uint32_t tcode) : + NxInCircuitTraceBase(tcode), + ddrmid_(0), + ddrsid_(0), + ddrtt_(0), + ddrsz_(0), + ddraddr_(0), + dddiec_(0) + { + } + ~NxDAMInCircuitTraceMessage() + { + } + + // NxMessage implements the standard visitor pattern. + virtual void accept(NxMessageVisitor &v) + { + v.visit(this); + } + + /*! + @abstract Returns the ICT Message Type detail + @return the ICT Message type + */ + virtual const char * ICTMessageType() const + { + return "DDR Terse/Verbose Message (DAM)"; + } + + // decode message info from the packet set + virtual bool decode(NxPacketSet &pkt_set); + + // output message information as a string + virtual string asString() const; + + // decode the type data as a string + const char * ddrttString() const; + + // decode the size data as a string + string ddrszString() const; + +private: + uint32_t ddrmid_; + uint32_t ddrsid_; + uint32_t ddrtt_; + uint32_t ddrsz_; + uint64_t ddraddr_; + uint32_t dddiec_; +}; + +// DataPath Queuing Message (DPQM) In Circuit Trace +class NxDPQMInCircuitTraceMessage: public NxInCircuitTraceBase +{ +public: + NxDPQMInCircuitTraceMessage(uint32_t tcode) : + NxInCircuitTraceBase(tcode), + verb_(0), + dpdm_(0), + fqid_(0), + cnum_(0), + pnum_(0), + ptype_(0), + qet_(0), + orf_(0), + erf_(0), + err_(0), + fmbpid_(0), + fmsc_(0), + fmol_(0), + fmfmt_(0), + fmpid_(0), + fmaddr_(0) + { + } + ~NxDPQMInCircuitTraceMessage() + { + } + + // NxMessage implements the standard visitor pattern. + virtual void accept(NxMessageVisitor &v) + { + v.visit(this); + } + + // returns the ICT Message type + virtual const char * ICTMessageType() const + { + return "DataPath Queuing Message (DPQM)"; + } + + // decode the queue event type as a string + const char * queueEventTypeString() const; + + // decode the enqueue rejection response code as a string + const char * enqueueRejectionString() const; + + // decode message info from the packet set + virtual bool decode(NxPacketSet &pkt_set); + + // output message information as a string + virtual string asString() const; + +private: + uint32_t verb_; + uint32_t dpdm_; + uint32_t fqid_; + uint32_t cnum_; + uint32_t pnum_; + uint32_t ptype_; + uint32_t qet_; + uint32_t orf_; + uint32_t erf_; + uint32_t err_; + + // additional verbose fields + uint32_t fmbpid_; + uint32_t fmsc_; + uint32_t fmol_; + uint32_t fmfmt_; + uint32_t fmpid_; + uint64_t fmaddr_; +}; + +// DataPath Frame Message (DPFM) In Circuit Trace +class NxDPFMInCircuitTraceMessage: public NxInCircuitTraceBase +{ +public: + NxDPFMInCircuitTraceMessage(uint32_t tcode) : + NxInCircuitTraceBase(tcode), + fmsel_(0), + lbeat_(0), + btcnt_(0) + { + for (int i = 0; i < 4; i++ ) + context_[i] = 0; + + } + ~NxDPFMInCircuitTraceMessage() + { + } + + // NxMessage implements the standard visitor pattern. + virtual void accept(NxMessageVisitor &v) + { + v.visit(this); + } + + // returns the ICT Message type + virtual const char * ICTMessageType() const + { + return "DataPath Frame Message (DPFM)"; + } + + // decode message info from the packet set + virtual bool decode(NxPacketSet &pkt_set); + + // output message information as a string + virtual string asString() const; + + // acessors + uint32_t getFmsel() const + { + return fmsel_; + } + uint32_t getLbeat() const + { + return lbeat_; + } + uint32_t getBtcnt() const + { + return btcnt_; + } + const uint32_t * getContext() const + { + return context_; + } + +private: + uint32_t fmsel_; + uint32_t lbeat_; + uint32_t btcnt_; + uint32_t context_[4]; // 128 bits of context + +}; + +// Core Performance Profile Message +class NxCoreInCircuitTraceMessage: public NxInCircuitTraceBase +{ +public: + NxCoreInCircuitTraceMessage(uint32_t tcode) : + NxInCircuitTraceBase(tcode), + cksrc_(0), + sync_(0), + ckdf_(0), + ckdata1_(0), + ckdata2_(0) + { + } + ~NxCoreInCircuitTraceMessage() + { + } + + // NxMessage implements the standard visitor pattern. + virtual void accept(NxMessageVisitor &v) + { + v.visit(this); + } + + // returns the ICT Message type + virtual const char * ICTMessageType() const + { + return "Core Performance Profile Message (ICT)"; + } + + // decode message info from the packet set + virtual bool decode(NxPacketSet &pkt_set); + + // output message information as a string + virtual string asString() const; + + // decode the sync code as a string + const char * syncString() const; + + // decode the cksrc code as a string + const char * cksrcString() const; + +private: + uint32_t cksrc_; + uint32_t sync_; + uint32_t ckdf_; + uint32_t ckdata1_; + uint32_t ckdata2_; +}; + +// Prototype for a ICT message type. Also a default for an +// un-decoded type. +class NxInCircuitTraceMessage: public NxInCircuitTraceBase +{ +public: + NxInCircuitTraceMessage(uint32_t tcode) : + NxInCircuitTraceBase(tcode) + { + } + ~NxInCircuitTraceMessage() + { + } + + // NxMessage implements the standard visitor pattern. + virtual void accept(NxMessageVisitor &v) + { + v.visit(this); + } + + /*! + @abstract Returns the ICT Message Type detail + @return the ICT Message type + */ + virtual const char * ICTMessageType() const + { + return "Generic In-Circuit Trace Message"; + } + + // decode message info from the packet set + virtual bool decode(NxPacketSet &pkt_set); + + // output message information as a string + virtual string asString() const; + +private: + +}; + +class NxTimeStampCorrelation: public NxMessage +{ +public: + NxTimeStampCorrelation() : + NxMessage(56), tcorr_(0), ttype_(0) + { + } + ~NxTimeStampCorrelation() + { + } + + // NxMessage implements the standard visitor pattern. + virtual void accept(NxMessageVisitor &v) + { + v.visit(this); + } + + /*! + @abstract Returns the TCODE string + @return the tcode as a string + */ + virtual string tcodeString() const + { + return "Time Stamp Correlation"; + } + + // decode message info from the packet set + virtual bool decode(NxPacketSet &pkt_set); + + // output message information as a string + virtual string asString() const; + + // decode the data as a string + const char * ttypeString() const; + +private: + uint32_t tcorr_; + uint32_t ttype_; +}; + +#endif // NXMESSAGE_H diff --git a/converter/nexus/NxMessageDecoder.cpp b/converter/nexus/NxMessageDecoder.cpp new file mode 100644 index 00000000..377fb814 --- /dev/null +++ b/converter/nexus/NxMessageDecoder.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "NxMessageDecoder.h" +#include "NxMessage.h" +#include "AUXMessageProtocol.h" +#include "NxPacketDecoder.h" +#include "NxPacketSet.h" +#include +using std::cout; +using std::endl; + +NxMessageDecoder::NxMessageDecoder() : + verbose_(false) +{ + protocol_ = new AUXMessageProtocol(); + packet_decoder_ = new NxPacketDecoder(); + packet_set_ = new NxPacketSet(); +} + +NxMessageDecoder::~NxMessageDecoder() +{ + delete protocol_; + delete packet_decoder_; + delete packet_set_; +} + +void NxMessageDecoder::verbose(bool verbose) +{ + verbose_ = verbose; + protocol_->verbose(verbose); + packet_decoder_->verbose(verbose); + packet_set_->verbose(verbose); +} + +// input data - the MDO/MSEO for each data beat +// output msg - pointer will be set if NxMessage is available +// return true if no error +bool NxMessageDecoder::accept(uint32_t data, NxMessage* &msg) +{ + AUXMessageProtocol::Outcome outcome; + bool ret = protocol_->evaluate((data & 3), outcome); + if (ret) { + ret = protocol_->act((data >> 2), *packet_set_); + if (ret) { + if (outcome == AUXMessageProtocol::ADD_LAST_MESSAGE) { + // decode the NxPacketSet information into a NXMessage + if (verbose_) { + cout << "END OF MESSAGE - Starting Decode." + << endl; + } + ret = packet_decoder_->decode(*packet_set_, + msg); + } + } + } + + return ret; +} diff --git a/converter/nexus/NxMessageDecoder.h b/converter/nexus/NxMessageDecoder.h new file mode 100644 index 00000000..f63de2a2 --- /dev/null +++ b/converter/nexus/NxMessageDecoder.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef NXMESSAGEDECODER_H +#define NXMESSAGEDECODER_H + +#include + +class NxMessage; +class AUXMessageProtocol; +class NxPacketDecoder; +class NxPacketSet; + +// The NxMessageDecoder is responsible for accepting MDO/MSEO data beats +// and determining when a NXMessage can be decoded from the data. +// The NXMessage returned will contain all the appropriate data for the type of +// Nexus message. +// +class NxMessageDecoder +{ +public: + + NxMessageDecoder(); + ~NxMessageDecoder(); + + // input data - the MDO/MSEO for each data beat + // output msg - pointer will be set if NxMessage is available + // return true if no error + bool accept(uint32_t data, NxMessage* &msg); + + // set the verbosity + void verbose(bool verbose); + +private: + + bool verbose_; + + // delegate for handling MSE data + AUXMessageProtocol *protocol_; + + // delegate to decode the packets into a NxMessage + NxPacketDecoder *packet_decoder_; + + // a container for the packet data + NxPacketSet *packet_set_; + +}; + +#endif // NXMESSAGEDECODER_H diff --git a/converter/nexus/NxMessageVisitor.h b/converter/nexus/NxMessageVisitor.h new file mode 100644 index 00000000..8accc134 --- /dev/null +++ b/converter/nexus/NxMessageVisitor.h @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef NXMESSAGEVISITOR_H +#define NXMESSAGEVISITOR_H + +#include + +using std::string; + +class NxDefaultMessage; +class NxDebugStatusMessage; +class NxDeviceIDMessage; +class NxOwnershipTraceMessage; +class NxDataAcquisitionMessage; +class NxErrorMessage; +class NxProgramTraceSync; +class NxDataTraceWrite; +class NxDataTraceRead; +class NxDataTraceWriteSync; +class NxDataTraceReadSync; +class NxWatchpointMessage; +class NxResourceFullMessage; +class NxProgramTraceIndirectBranch; +class NxProgramTraceIndirectBranchSync; +class NxProgramTraceCorrelation; +class NxDAMInCircuitTraceMessage; +class NxCAMInCircuitTraceMessage; +class NxCDMInCircuitTraceMessage; +class NxDPQMInCircuitTraceMessage; +class NxDPFMInCircuitTraceMessage; +class NxCoreInCircuitTraceMessage; +class NxInCircuitTraceMessage; +class NxTimeStampCorrelation; + +// Nexus Message Visitor follows the standard visitor pattern. +// It is the base class for the visitor protocol. +class NxMessageVisitor +{ +public: + + NxMessageVisitor() : + useful_visit_(false) + { + } + + virtual ~NxMessageVisitor() + { + } + + // Must override in specific visitor. + virtual void visit(NxDefaultMessage *m) = 0; + virtual void visit(NxDebugStatusMessage *m) = 0; + virtual void visit(NxDeviceIDMessage *m) = 0; + virtual void visit(NxOwnershipTraceMessage *m) = 0; + virtual void visit(NxDataAcquisitionMessage *m) = 0; + virtual void visit(NxErrorMessage *m) = 0; + virtual void visit(NxProgramTraceSync *m) = 0; + virtual void visit(NxDataTraceWrite *m) = 0; + virtual void visit(NxDataTraceRead *m) = 0; + virtual void visit(NxDataTraceWriteSync *m) = 0; + virtual void visit(NxDataTraceReadSync *m) = 0; + virtual void visit(NxWatchpointMessage *m) = 0; + virtual void visit(NxResourceFullMessage *m) = 0; + virtual void visit(NxProgramTraceIndirectBranch *m) = 0; + virtual void visit(NxProgramTraceIndirectBranchSync *m) = 0; + virtual void visit(NxProgramTraceCorrelation *m) = 0; + virtual void visit(NxDAMInCircuitTraceMessage *m) = 0; + virtual void visit(NxCAMInCircuitTraceMessage *m) = 0; + virtual void visit(NxCDMInCircuitTraceMessage *m) = 0; + virtual void visit(NxDPQMInCircuitTraceMessage *m) = 0; + virtual void visit(NxDPFMInCircuitTraceMessage *m) = 0; + virtual void visit(NxCoreInCircuitTraceMessage *m) = 0; + virtual void visit(NxInCircuitTraceMessage *m) = 0; + virtual void visit(NxTimeStampCorrelation *m) = 0; + + // output message information as a string + virtual string asString() const = 0; + +protected: + + bool useful_visit_; +}; + +#endif // NXMESSAGEVISITOR_H diff --git a/converter/nexus/NxPacketDecoder.cpp b/converter/nexus/NxPacketDecoder.cpp new file mode 100644 index 00000000..00b25d46 --- /dev/null +++ b/converter/nexus/NxPacketDecoder.cpp @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "NxPacketDecoder.h" +#include +using std::cout; +using std::endl; + +void NxPacketDecoder::decodeICT_(uint32_t tcode, uint32_t source_id, + NxMessage* &msg) +{ + // allocate the correct NxInCircuitTraceMessage + // based on the source_id. + if ((source_id & 0x1) == 0) { + // all cores have source ids where LSB = 0 + msg = new NxCoreInCircuitTraceMessage(tcode); + } else { + switch (source_id) { + case 0xb: + // "Data Path Queueing Message"; + msg = new NxDPQMInCircuitTraceMessage(tcode); + break; + case 0x1b: + // "Data Path Frame Message"; + msg = new NxDPFMInCircuitTraceMessage(tcode); + break; + case 0x3b: + // "Data Path Cycle Trace Message"; + msg = new NxInCircuitTraceMessage(tcode); + break; + case 0x0d: + // "DDR Terse/Verbose Message"; + msg = new NxDAMInCircuitTraceMessage(tcode); + break; + case 0x1d: + // "Ocean Terse Address/Verbose Address/Header/Data"; + msg = new NxInCircuitTraceMessage(tcode); + break; + case 0x2d: + // "CCSR IPM Address/IPM Data DCSR IPM Address/IPM Data"; + msg = new NxInCircuitTraceMessage(tcode); + break; + case 0x3d: + // "EPU Counter Trace Message"; + msg = new NxInCircuitTraceMessage(tcode); + break; + default: + // "Reserved"; + msg = new NxInCircuitTraceMessage(tcode); + break; + }; + } +} + +// decode the packet set into a NxMessage +bool NxPacketDecoder::decode(NxPacketSet &pkt_set, NxMessage* &msg) +{ + bool ret = true; + + // get the tcode from the packet since its needed + // to create the correct NxMessage + uint32_t tcode = pkt_set.tcode(); + + // allocate the correct NxMessage from the tcode. + NxMessage *m; + switch (tcode) { + + case 0: + m = new NxDebugStatusMessage(); + break; + + case 1: + m = new NxDeviceIDMessage(); + break; + + case 2: + m = new NxOwnershipTraceMessage(); + break; + + case 5: + m = new NxDataTraceWrite(); + break; + + case 6: + m = new NxDataTraceRead(); + break; + + case 7: + m = new NxDataAcquisitionMessage(); + break; + + case 8: + m = new NxErrorMessage(); + break; + + case 9: + m = new NxProgramTraceSync(); + break; + + case 13: + m = new NxDataTraceWriteSync(); + break; + + case 14: + m = new NxDataTraceReadSync(); + break; + + case 15: + m = new NxWatchpointMessage(); + break; + + case 27: + m = new NxResourceFullMessage(); + break; + + case 28: + m = new NxProgramTraceIndirectBranch(); + break; + + case 29: + m = new NxProgramTraceIndirectBranchSync(); + break; + + case 33: + m = new NxProgramTraceCorrelation(); + break; + + case 34: { + uint32_t src = pkt_set.src(); + decodeICT_(tcode, src, m); + break; + } + case 35: { + uint32_t src = pkt_set.src(); + decodeICT_(tcode, src, m); + break; + } + case 56: + m = new NxTimeStampCorrelation(); + break; + default: + m = new NxDefaultMessage(tcode); + break; + }; + + // decode the rest of the data + ret = m->decode(pkt_set); + + if (ret) { + // Assign and return the message + // The caller will take ownership of the memory + msg = m; + } else { + // error + cout << "Failed to decode NxPacketSet data into NxMessage with TCODE: " + << tcode << endl; + delete m; + } + + return ret; +} diff --git a/converter/nexus/NxPacketDecoder.h b/converter/nexus/NxPacketDecoder.h new file mode 100644 index 00000000..19293ff7 --- /dev/null +++ b/converter/nexus/NxPacketDecoder.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef NXPACKETDECODER_H +#define NXPACKETDECODER_H + +#include "NxPacketSet.h" +#include "NxMessage.h" + +// The NxPacketDecoder is responsible for decoding packets into the +// correct NXMessage based on the TCODE contained in the packet. +// The NXMessage returned will contain all the appropriate fields for the type of +// Nexus message. +// +class NxPacketDecoder +{ +public: + + NxPacketDecoder() : + verbose_(false) + { + } + ~NxPacketDecoder() + { + } + ; + + // decode the packet set into a NxMessage + bool decode(NxPacketSet &pkt_set, NxMessage* &msg); + + // set the verbosity + void verbose(bool verbose) + { + verbose_ = verbose; + } + +private: + + // further decode packet set by source id into a specific NxInCircuitTraceMessage + void decodeICT_(uint32_t tcode, uint32_t source_id, NxMessage* &msg); + + bool verbose_; + +}; + +#endif // NXPACKETDECODER_H diff --git a/converter/nexus/NxPacketSet.cpp b/converter/nexus/NxPacketSet.cpp new file mode 100644 index 00000000..9299e97c --- /dev/null +++ b/converter/nexus/NxPacketSet.cpp @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "NxPacketSet.h" + +#include +#include + +using std::cout; +using std::endl; + +NxPacketSet::NxPacketSet() : + verbose_(false) +{ + reset(); +} + +void NxPacketSet::reset() +{ + // pointer to the first packet + current_packet_index_ = 0; + current_packet_ = &packet_[current_packet_index_]; + + for (uint32_t i = 0; i < MAX_NUM_PACKETS; ++i) { + packet_[i].reset(); + } +} + +// add len bits of mdo to the current packet +bool NxPacketSet::addToCurrent(uint32_t mdo) +{ + bool ret = current_packet_->add(mdo); + if (verbose_) { + if (ret) { + for (uint32_t i = 0; i <= current_packet_index_; ++i) { + cout << "Packet[" << i << "]: " + << packet_[i].packet_ << endl; + } + } else { + cout << "Error adding MDO to Packet[" + << current_packet_index_ << "]" << endl; + } + } + return ret; +} + +// advance to the next packet +bool NxPacketSet::nextPacket() +{ + assert(current_packet_index_ < (MAX_NUM_PACKETS - 1)); + + bool ret = current_packet_index_ < (MAX_NUM_PACKETS - 1); + if (ret) { + current_packet_index_++; + current_packet_ = &packet_[current_packet_index_]; + } + return ret; +} + +// get the value of len size from start (LSB) pos from packet at index +uint32_t NxPacketSet::getField32(uint32_t index, uint32_t start_pos, + uint32_t len) const +{ + assert(index < MAX_NUM_PACKETS); + return packet_[index].getField32(start_pos, len); + +} + +// get the value of len size from start (LSB) pos from packet at index +uint64_t NxPacketSet::getField64(uint32_t index, uint32_t start_pos, + uint32_t len) const +{ + assert(index < MAX_NUM_PACKETS); + return packet_[index].getField64(start_pos, len); +} + +// get the number of MDO from packet at index +uint32_t NxPacketSet::getNumMDO(uint32_t index) const +{ + assert(index < MAX_NUM_PACKETS); + return packet_[index].getNumMDO(); +} + +bool NxPacketSet::packetAtIndexExists(uint32_t index) const +{ + assert(index < MAX_NUM_PACKETS); + return index <= current_packet_index_; +} + +// return the TCODE +uint32_t NxPacketSet::tcode() const +{ + // index=0, start_pos=0, length=6 + uint32_t ret = getField32(0, 0, 6); + return ret; +} + +// return the TCODE +uint32_t NxPacketSet::src() const +{ + // index=0, start_pos=6, length=6 + uint32_t ret = getField32(0, 6, 6); + return ret; +} + +// NxPacket class + +NxPacket::NxPacket() +{ + reset(); +} + +// return the packet to the initial state +void NxPacket::reset() +{ + packet_.reset(); + current_pos_ = 0; + num_mdo_ = 0; +} + +// add len bits of mdo to the packet +bool NxPacket::add(uint32_t mdo) +{ + assert((mdo & 0xc0000000) == 0); + assert(num_mdo_ <= MAX_NUM_MDO_PER_PACKET); + + bool ret = true; + PktBits mdo_bits(mdo); + mdo_bits <<= current_pos_; + packet_ |= mdo_bits; + current_pos_ += MAX_NUM_MDO_BITS; + num_mdo_++; + + return ret; +} + +// get the value of len size from start (LSB) pos from packet +uint32_t NxPacket::getField32(uint32_t start_pos, uint32_t len) const +{ + assert(start_pos + len < MAX_NUM_PACKET_BITS); + assert(len <= 32); + + uint32_t val = 0; + uint32_t pos = start_pos + len - 1; + for (uint32_t i = 0; i < len; ++i) { + val <<= 1; + val |= packet_[pos]; + pos--; + } + return val; +} + +// get the value of len size from start (LSB) pos from packet +uint64_t NxPacket::getField64(uint32_t start_pos, uint32_t len) const +{ + assert(start_pos + len < MAX_NUM_PACKET_BITS); + assert(len <= 64); + + uint64_t val = 0; + uint32_t pos = start_pos + len - 1; + for (uint32_t i = 0; i < len; ++i) { + val <<= 1; + val |= packet_[pos]; + pos--; + } + return val; +} diff --git a/converter/nexus/NxPacketSet.h b/converter/nexus/NxPacketSet.h new file mode 100644 index 00000000..d966a799 --- /dev/null +++ b/converter/nexus/NxPacketSet.h @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef NXPACKETSET_H +#define NXPACKETSET_H + +#include +#include + +using std::bitset; + +// The internal representation of NxPacketSet is +// simplistic and is based on fixed limits on the +// number of vendor-defined fields and number of +// variable fields in the message set. + +// the max number of MDOs per packet +static const uint32_t MAX_NUM_MDO_PER_PACKET = 6; +// the max number of bits in a packet ( max num_mdo * bits/word) +static const uint32_t MAX_NUM_PACKET_BITS = 32 * MAX_NUM_MDO_PER_PACKET; + +typedef bitset PktBits; + +// Storage for a single Nexus packet +class NxPacket +{ +public: + + NxPacket(); + ~NxPacket() + { + } + + // return the packet to the initial state + void reset(); + + // add MDO to the packet + bool add(uint32_t mdo); + + // get the value of len size from start (LSB) pos from packet + uint32_t getField32(uint32_t start_pos, uint32_t len) const; + + // get the value of len size from start (LSB) pos from packet + uint64_t getField64(uint32_t start_pos, uint32_t len) const; + + // get the number of MDOs added to this packet + uint32_t getNumMDO() const + { + return num_mdo_; + } + +// TODO Need to hide packet_ except for debug output. +//private: + +// The internal implementation of packet + PktBits packet_; + +private: + + // Number of bits in MDO + static const uint32_t MAX_NUM_MDO_BITS = 30; + + // current position in the packet + uint32_t current_pos_; + + // number of times data added to packet + uint32_t num_mdo_; +}; + +// The NxPacketSet contains the max number of +// NxPackets required to capture a single message. +class NxPacketSet +{ +public: + + NxPacketSet(); + ~NxPacketSet() + { + } + + // return the packet set to the initial state + void reset(); + + // add MDO to the current packet + bool addToCurrent(uint32_t mdo); + + // advance to the next packet + bool nextPacket(); + + // return the TCODE + uint32_t tcode() const; + + // return the Source ID + uint32_t src() const; + + // get the value of len size from start (LSB) pos from packet at index + uint32_t getField32(uint32_t index, uint32_t start_pos, + uint32_t len) const; + + // get the value of len size from start (LSB) pos from packet at index + uint64_t getField64(uint32_t index, uint32_t start_pos, + uint32_t len) const; + + // get the number of MDO from packet at index + uint32_t getNumMDO(uint32_t index) const; + + // test if a packet at index exists + bool packetAtIndexExists(uint32_t index) const; + + // set the verbosity + void verbose(bool verbose) + { + verbose_ = verbose; + } + +private: + + // the max number of packets in the set + static const uint32_t MAX_NUM_PACKETS = 5; + + // allow output of some debug info + bool verbose_; + + // current packet + NxPacket *current_packet_; + + // current packet index + uint32_t current_packet_index_; + + // set of packets + NxPacket packet_[MAX_NUM_PACKETS]; +}; + +#endif // NXPACKETSET_H diff --git a/converter/nexus/README b/converter/nexus/README new file mode 100644 index 00000000..c8158851 --- /dev/null +++ b/converter/nexus/README @@ -0,0 +1,26 @@ +The nexdump utility will read and annotate Nexus encoded trace +data emitted from Freescale QorIQ products. + +This code is unsupported and is available on an "as is" basis. + +See ChangeLog file for release information. + +There are two ways to build nexdump: +1) mkdir bld + cd bld + ../configure + make + make install + +2) mkdir bld-cmake + cd bld-cmake + cmake .. + make + make install # /usr/local/bin + +nexdump --help +will provide usage and option information. + +Normal usage is simply "nexdump " +where is a Nexus data file containing +(32-bit big endian) binary or text (0x12345678) data. diff --git a/converter/nexus/SizedAddress.cpp b/converter/nexus/SizedAddress.cpp new file mode 100644 index 00000000..e4d2586a --- /dev/null +++ b/converter/nexus/SizedAddress.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "SizedAddress.h" +#include +#include +using std::ostringstream; +using std::endl; +using std::hex; +using std::dec; +using std::setfill; +using std::setw; + +bool SizedAddress::operator==(const SizedAddress &rhs) const +{ + bool ret = false; + if (valid_ && rhs.valid_) { + ret = address64() == rhs.address64(); + } + return ret; +} + +bool SizedAddress::operator!=(const SizedAddress &rhs) const +{ + return !(*this == rhs); +} + +SizedAddress& SizedAddress::operator^=(const SizedAddress &rhs) +{ + // both operands must be valid + if (!valid_ || !rhs.valid_) { + return *this; + } + + pc_lo_ ^= rhs.pc_lo_; + if (pc64_ && rhs.pc64_) { + pc_hi_ ^= rhs.pc_hi_; + } + + // promote to 64b if rhs is 64b + if (!pc64_ && rhs.pc64_) { + pc_hi_ = rhs.pc_hi_; + pc64_ = true; + } + + return *this; +} + +const SizedAddress SizedAddress::operator^(const SizedAddress &rhs) +{ + // return new object + return SizedAddress(*this) ^= rhs; +} + +// represent the SizedAddress as a formatted string +string SizedAddress::asString() const +{ + ostringstream os; + if (valid_) { + os << "0x"; + if (pc64_) { + os << hex << setfill('0') << setw(8) << pc_hi_ << ":"; + } + os << hex << setfill('0') << setw(8) << pc_lo_; + } else { + os << "uninitialized value"; + } + + return os.str(); +} diff --git a/converter/nexus/SizedAddress.h b/converter/nexus/SizedAddress.h new file mode 100644 index 00000000..179e23b7 --- /dev/null +++ b/converter/nexus/SizedAddress.h @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef SIZEDADDRESS_H +#define SIZEDADDRESS_H + +#include +#include + +using std::string; + +/*! + Class to handle 32 or 64bit (sized) Address data + */ +class SizedAddress +{ +public: + /*! + @Constructor + */ + SizedAddress() : + valid_(false), pc64_(false), pc_hi_(0), pc_lo_(0) + { + } + virtual ~SizedAddress() + { + } + + // Default copy and assignment operators are OK + + // Comparison operation + bool operator==(const SizedAddress &rhs) const; + bool operator!=(const SizedAddress &rhs) const; + + // XOR compound operation + SizedAddress& operator^=(const SizedAddress &rhs); + + // XOR operation + const SizedAddress operator^(const SizedAddress &rhs); + + /*! + @Returns the validity of the address value + @return true if the value is valid + */ + bool isValid() const + { + return valid_; + } + /*! + @Returns the address value + @return the address value + */ + uint32_t address32() const + { + return pc_lo_; + } + + /*! + @Returns the address value + @return the address value + */ + uint64_t address64() const + { + return ((uint64_t) pc_hi_ << 32) | (uint64_t) pc_lo_; + } + + /*! + @Returns the upper 32bits of the address + @return the upper 32bits of the address + */ + uint32_t upper32() const + { + return pc_hi_; + } + + /*! + @Returns the lower 32bits of the address + @return the lower 32bits of the address + */ + uint32_t lower32() const + { + return pc_lo_; + } + + /*! + @Tests if the address is 64 bit wide + @return if the address is 64 bits wide + */ + bool is64bits() const + { + return pc64_; + } + + /*! + @abstract Return the Address as a string + @return a string representing the Nexus Address + */ + string asString() const; + + /*! + @Sets the upper 32bits of the address + */ + void upper32(uint32_t val) + { + pc_hi_ = val; + pc64_ = true; + valid_ = true; + } + + /*! + @Sets the lower 32bits of the address + */ + void lower32(uint32_t val) + { + pc_lo_ = val; + valid_ = true; + } + +private: + + /*! @var valid_ true if represents an initialized value */ + bool valid_; + + /*! @var pc64_ determines if the received address is 64bits wide */ + bool pc64_; + + /*! @var pc_hi_ the upper 32bits of the Nexus address */ + uint32_t pc_hi_; + + /*! @var pc_lo_ the lower 32bits of the Nexus address */ + uint32_t pc_lo_; +}; + +#endif // SIZEDADDRESS_H diff --git a/converter/nexus/main.cpp b/converter/nexus/main.cpp new file mode 100644 index 00000000..062c53d8 --- /dev/null +++ b/converter/nexus/main.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include +#include +#include "Application.h" +#include "config.h" + +using std::cout; +using std::endl; +using std::string; + +void helpOption() +{ + cout << "Usage: nexdump [options] " << endl; + cout << "Options:" << endl; + cout << " --help Display this information" + << endl; + cout << " --version Display version information" + << endl; + cout + << " --verbose Display decoded debug/trace information" + << endl; + cout + << " --fmlog Display FMan detail trace information" + << endl; + cout + << " --faddr Display Full Addresses in trace information" + << endl; + cout + << " --summary Display a summary of message count information" + << endl; +} + +void versionOption() +{ + cout << PACKAGE << " v" << VERSION << endl; + cout << "Copyright (C) 2013 Freescale Semiconductor" << endl; +} + +int main(int argc, char * const argv[]) +{ + + Application app; + string in_filename; + + // process the options + for (int i = 1; i < argc; i++) { + + string argStr = argv[i]; + if (argStr.find("--help") == 0) { + helpOption(); + return 0; + + } else if (argStr.find("--version") == 0) { + versionOption(); + return 0; + + } else if (argStr.find("--verbose") == 0) { + app.verbose(true); + + } else if (argStr.find("--summary") == 0) { + app.summary(true); + + } else if (argStr.find("--faddr") == 0) { + app.enableFullAddrLog(); + + } else if (argStr.find("--fmlog") == 0) { + app.enableFmanLog(); + + } else if (in_filename.empty()) { + // treat as the filename + in_filename = argStr; + + } else { + // error + helpOption(); + return -1; + } + } + + // check if filename not found + if (in_filename.empty()) { + helpOption(); + return -1; + } + + // begin operation + if (app.process(in_filename) == false) { + return -1; + } + + return 0; +} -- 2.34.1