On 3 June 2016 at 02:26, Mike Leach mike.leach@linaro.org wrote:
Full decoder now complete.
Tested against TC2 snapshot. C-API updated and test program run to check consistency
Signed-off-by: Mike Leach mike.leach@linaro.org
.../ref_trace_decode_lib.vcxproj | 2 + .../ref_trace_decode_lib.vcxproj.filters | 6 + decoder/include/c_api/opencsd_c_api.h | 13 + decoder/include/common/ocsd_code_follower.h | 6 + decoder/include/common/ocsd_dcd_tree_elem.h | 4 +- decoder/include/common/ocsd_gen_elem_list.h | 153 +++++ decoder/include/common/ocsd_pe_context.h | 22 + decoder/include/common/trc_gen_elem.h | 80 ++- decoder/include/etmv3/trc_cmp_cfg_etmv3.h | 10 + decoder/include/etmv3/trc_pkt_decode_etmv3.h | 167 +++++- decoder/include/etmv3/trc_pkt_elem_etmv3.h | 24 +- decoder/include/etmv3/trc_pkt_types_etmv3.h | 12 +- decoder/include/ocsd_if_types.h | 4 +- decoder/include/trc_gen_elem_types.h | 3 +- decoder/include/trc_pkt_types.h | 2 +- decoder/source/c_api/ocsd_c_api.cpp | 17 + decoder/source/etmv3/trc_pkt_decode_etmv3.cpp | 619 ++++++++++++++++----- decoder/source/ocsd_code_follower.cpp | 3 +- decoder/source/ocsd_dcd_tree.cpp | 29 +- decoder/source/ocsd_error.cpp | 3 +- decoder/source/ocsd_gen_elem_list.cpp | 168 ++++++ decoder/source/trc_gen_elem.cpp | 19 +- decoder/tests/source/simple_pkt_c_api.c | 18 +- 23 files changed, 1179 insertions(+), 205 deletions(-) create mode 100644 decoder/include/common/ocsd_gen_elem_list.h create mode 100644 decoder/source/ocsd_gen_elem_list.cpp
diff --git a/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj b/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj index 2dc5f0c..929df5a 100644 --- a/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj +++ b/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj @@ -309,6 +309,7 @@ <ClInclude Include="..\..\..\include\common\ocsd_dcd_tree_elem.h" /> <ClInclude Include="..\..\..\include\common\ocsd_error.h" /> <ClInclude Include="..\..\..\include\common\ocsd_error_logger.h" />
<ClInclude Include="..\..\..\include\common\ocsd_gen_elem_list.h" /> <ClInclude Include="..\..\..\include\common\ocsd_msg_logger.h" /> <ClInclude Include="..\..\..\include\common\ocsd_pe_context.h" /> <ClInclude Include="..\..\..\include\common\ocsd_version.h" />
@@ -395,6 +396,7 @@ <ClCompile Include="..\..\..\source\ocsd_dcd_tree.cpp" /> <ClCompile Include="..\..\..\source\ocsd_error.cpp" /> <ClCompile Include="..\..\..\source\ocsd_error_logger.cpp" />
<ClCompile Include="..\..\..\source\ocsd_gen_elem_list.cpp" /> <ClCompile Include="..\..\..\source\ocsd_msg_logger.cpp" /> <ClCompile Include="..\..\..\source\ocsd_version.cpp" /> <ClCompile Include="..\..\..\source\ptm\trc_cmp_cfg_ptm.cpp" />
diff --git a/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj.filters b/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj.filters index c221d2f..efb3183 100644 --- a/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj.filters +++ b/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj.filters @@ -287,6 +287,9 @@ <ClInclude Include="..\..\..\include\common\ocsd_code_follower.h"> <Filter>Header Files\common</Filter> </ClInclude>
<ClInclude Include="..\..\..\include\common\ocsd_gen_elem_list.h">
<Filter>Header Files\common</Filter>
</ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="..\..\..\source\trc_component.cpp">
@@ -394,5 +397,8 @@ <ClCompile Include="..\..\..\source\ocsd_code_follower.cpp"> <Filter>Source Files</Filter> </ClCompile>
<ClCompile Include="..\..\..\source\ocsd_gen_elem_list.cpp">
<Filter>Source Files</Filter>
</ClCompile> </ItemGroup>
</Project> \ No newline at end of file diff --git a/decoder/include/c_api/opencsd_c_api.h b/decoder/include/c_api/opencsd_c_api.h index 480969c..5574f19 100644 --- a/decoder/include/c_api/opencsd_c_api.h +++ b/decoder/include/c_api/opencsd_c_api.h @@ -207,6 +207,19 @@ OCSD_C_API ocsd_err_t ocsd_dt_create_etmv3_pkt_proc(const dcd_tree_handle_t hand
/*!
- Creates a packet processor + packet decoder pair for the supplied configuration structure.
- Uses the output function set in ocsd_dt_set_gen_elem_outfn() as the output sink.
- @param handle : Handle to decode tree.
- @param *etmv4_cfg : pointer to valid Etmv4 configuration structure.
- @return ocsd_err_t : Library error code - RCDTL_OK if successful.
- */
+OCSD_C_API ocsd_err_t ocsd_dt_create_etmv3_decoder(const dcd_tree_handle_t handle, const void *etmv3_cfg);
+/*!
- Attach a callback function to the packet processor monitor point defined by the CoreSight ID.
- Packet processor must exist for the trace ID and be an ETMv3 processor.
diff --git a/decoder/include/common/ocsd_code_follower.h b/decoder/include/common/ocsd_code_follower.h index e8df24a..7063266 100644 --- a/decoder/include/common/ocsd_code_follower.h +++ b/decoder/include/common/ocsd_code_follower.h @@ -83,6 +83,7 @@ public: //*********************** results API const ocsd_vaddr_t getRangeSt() const; //!< inclusive start address of decoded range (value passed in) const ocsd_vaddr_t getRangeEn() const; //!< exclusive end address of decoded range (first instruction _not_ executed / potential next instruction).
const bool hasRange() const; //!< we have a valid range executed (may be false if nacc).
const bool hasNextAddr() const; //!< we have calulated the next address - otherwise this is needed from trace packets. const ocsd_vaddr_t getNextAddr() const; //!< next address - valid if hasNextAddr() true.
@@ -165,6 +166,11 @@ inline const ocsd_vaddr_t OcsdCodeFollower::getRangeEn() const return m_en_range_addr; }
+inline const bool OcsdCodeFollower::hasRange() const +{
- return m_st_range_addr < m_en_range_addr;
+}
inline const bool OcsdCodeFollower::hasNextAddr() const { return m_b_next_valid; diff --git a/decoder/include/common/ocsd_dcd_tree_elem.h b/decoder/include/common/ocsd_dcd_tree_elem.h index b1b14d0..31fe011 100644 --- a/decoder/include/common/ocsd_dcd_tree_elem.h +++ b/decoder/include/common/ocsd_dcd_tree_elem.h @@ -49,7 +49,7 @@ typedef struct _decoder_elements union { struct { TrcPktProcEtmV3 *proc;
void * /*TrcPktDecodeEtmV3 * */ dcd; //** TBD
TrcPktDecodeEtmV3 *dcd; } etmv3; /**< ETMv3 decoders */ struct { TrcPktProcEtmV4I *proc;
@@ -155,7 +155,7 @@ public: switch(protocol) { case OCSD_PROTOCOL_ETMV3:
//pDecoder = dynamic_cast<TrcPktDecodeI *>(decoder.etmv3.dcd);
pDecoder = dynamic_cast<TrcPktDecodeI *>(decoder.etmv3.dcd); break; case OCSD_PROTOCOL_ETMV4I: pDecoder = dynamic_cast<TrcPktDecodeI *>(decoder.etmv4i.dcd);
diff --git a/decoder/include/common/ocsd_gen_elem_list.h b/decoder/include/common/ocsd_gen_elem_list.h new file mode 100644 index 0000000..0ff1bd5 --- /dev/null +++ b/decoder/include/common/ocsd_gen_elem_list.h @@ -0,0 +1,153 @@ +/*
- \file ocsd_gen_elem_stack.h
- \brief OpenCSD : Generic element output stack.
- \copyright Copyright (c) 2016, ARM Limited. All Rights Reserved.
- */
+/*
- Redistribution and use in source and binary forms, with or without modification,
- are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
- Neither the name of the copyright holder nor the names of its contributors
- may be used to endorse or promote products derived from this software without
- specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
+#include <list> +#include "trc_gen_elem.h" +#include "comp_attach_pt_t.h" +#include "interfaces/trc_gen_elem_in_i.h"
+/*!
- @class OcsdGenElemList
- @brief Maintain a list of elements to be output
- Each incoming packet can result in multiple output elements.
- These are stacked in this class prior to entering the output phase of processing.
- This should remove some of the requirement on the packet processing to be re-enterant,
- simplifying this code.
- Last element(s) on this stack can be marked pending to allow for later cancellation.
- (This required for cancel element in ETMv3 exeception branch).
- The "list" is actually a ring buffer - maintaining pointers to indicate current valid elements.
- This buffer can increase on demand, but will only be released at the end of a decode session.
- */
+class OcsdGenElemList +{ +public:
- OcsdGenElemList();
- ~OcsdGenElemList();
- void initSendIf(componentAttachPt<ITrcGenElemIn> *pGenElemIf);
- void initCSID(const uint8_t CSID) { m_CSID = CSID; };
- void reset(); //!< reset the element list.
- OcsdTraceElement *getNextElem(const ocsd_trc_index_t trc_pkt_idx); //!< get next free element on the stack (add one to the output)
- const int getNumElem() const; //!< return the total number of elements on the stack (inlcuding any pended ones).
- const ocsd_gen_trc_elem_t getElemType(const int entryN) const; //!< get the type for the nth element in the stack (0 indexed)
- void pendLastNElem(int numPend); //!< Last element to be pended prior to cancel/commit decision.
- void commitAllPendElem(); //!< commit all pended elements.
- void cancelPendElem(); //!< cancel the last pended element on the stack.
- const int numPendElem() const; //!< return the number of pended elements.
- /*! Send all of the none pended elements
Stop sending when all sent or _CONT response.
*/
- ocsd_datapath_resp_t sendElements();
- const bool elemToSend() const; //!< true if any none-pending elements left to send.
+private:
- void growArray();
- const int getAdjustedIdx(int idxIn) const; //!< get adjusted index into circular buffer.
- // list element contains pointer and byte index in trace stream
- typedef struct _elemPtr {
OcsdTraceElement *pElem; //!< pointer to the listed trace element
ocsd_trc_index_t trc_pkt_idx; //!< packet index in the trace stream
- } elemPtr_t;
- elemPtr_t *m_pElemArray; //!< an array of pointers to elements.
- int m_elemArraySize; //!< number of element pointers in the array
- int m_firstElemIdx; //!< internal index in array of first element in use.
- int m_numUsed; //!< number of elements in use
- int m_numPend; //!< internal count of pended elements.
- uint8_t m_CSID;
- componentAttachPt<ITrcGenElemIn> *m_sendIf; //!< element send interface.
+};
+inline const int OcsdGenElemList::getAdjustedIdx(int idxIn) const +{
- if(idxIn >= m_elemArraySize)
idxIn -= m_elemArraySize;
- return idxIn;
+}
+inline const int OcsdGenElemList::getNumElem() const +{
- return m_numUsed;
+}
+inline const int OcsdGenElemList::numPendElem() const +{
- return m_numPend;
+}
+inline void OcsdGenElemList::pendLastNElem(int numPend) +{
- if(numPend >= getNumElem())
m_numPend = numPend;
+}
+inline void OcsdGenElemList::commitAllPendElem() +{
m_numPend = 0;
+}
+inline void OcsdGenElemList::cancelPendElem() +{
- if(m_numPend > 0)
- {
m_numUsed -= m_numPend;
- }
+}
+inline const bool OcsdGenElemList::elemToSend() const +{
- return ((getNumElem() - m_numPend) > 0);
+}
+inline void OcsdGenElemList::initSendIf(componentAttachPt<ITrcGenElemIn> *pGenElemIf) +{
- m_sendIf = pGenElemIf;
+}
+/* End of File ocsd_gen_elem_stack.h */ diff --git a/decoder/include/common/ocsd_pe_context.h b/decoder/include/common/ocsd_pe_context.h index fe06e90..1ad4676 100644 --- a/decoder/include/common/ocsd_pe_context.h +++ b/decoder/include/common/ocsd_pe_context.h @@ -46,8 +46,12 @@ class OcsdPeContext { public: OcsdPeContext();
OcsdPeContext(const ocsd_pe_context *context); ~OcsdPeContext() {};
OcsdPeContext &operator =(const OcsdPeContext &ctxt);
OcsdPeContext &operator =(const ocsd_pe_context *context);
void resetCtxt();
void setSecLevel(const ocsd_sec_level sl) { m_context.security_level = sl; };
@@ -76,6 +80,11 @@ inline OcsdPeContext::OcsdPeContext() resetCtxt(); }
+inline OcsdPeContext::OcsdPeContext(const ocsd_pe_context *context) +{
- m_context = *context;
+}
inline void OcsdPeContext::resetCtxt() { // initialise the context @@ -89,6 +98,19 @@ inline void OcsdPeContext::resetCtxt() m_context.vmid_valid = 0; }
+inline OcsdPeContext & OcsdPeContext::operator =(const OcsdPeContext &ctxt) +{
- m_context = ctxt;
- return *this;
+}
+inline OcsdPeContext & OcsdPeContext::operator =(const ocsd_pe_context *context) +{
- m_context = *context;
- return *this;
+}
#endif // ARM_OCSD_PE_CONTEXT_H_INCLUDED
/* End of File ocsd_pe_context.h */ diff --git a/decoder/include/common/trc_gen_elem.h b/decoder/include/common/trc_gen_elem.h index d5fbe41..4f99c378 100644 --- a/decoder/include/common/trc_gen_elem.h +++ b/decoder/include/common/trc_gen_elem.h @@ -36,6 +36,8 @@
#include "trc_gen_elem_types.h" #include "trc_printable_elem.h" +#include "ocsd_pe_context.h"
/** @addtogroup gen_trc_elem @{*/
@@ -53,18 +55,47 @@ public:
void init();
- const ocsd_gen_trc_elem_t getType() const { return elem_type; };
- void setType(const ocsd_gen_trc_elem_t type);
+// set elements API
- void setType(const ocsd_gen_trc_elem_t type); //!< set type and init flags
- void updateType(const ocsd_gen_trc_elem_t type); //!< change type only - no init
- void setContext(const ocsd_pe_context &new_context) { context = new_context; };
- void setISA(const ocsd_isa isa_update);
- void setCycleCount(const uint32_t cycleCount); void setEvent(const event_t ev_type, const uint16_t number); void setTS(const uint64_t ts, const bool freqChange = false) { timestamp = ts; cpu_freq_change = freqChange ? 1 : 0; };
- void setExcepMarker() { excep_data_marker = 1; };
- void setExceptionNum(uint32_t excepNum) { exception_number = excepNum; };
- void setTraceOnReason(const trace_on_reason_t reason);
- void setAddrRange(const ocsd_vaddr_t st_addr, const ocsd_vaddr_t en_addr);
- void setLastInstrInfo(const bool exec, const ocsd_instr_type last_i_type, const ocsd_instr_subtype last_i_subtype);
- void setAddrStart(const ocsd_vaddr_t st_addr) { this->st_addr = st_addr; };
+// stringize the element
virtual void toString(std::string &str) const;
+// get elements API
OcsdTraceElement &operator =(const ocsd_generic_trace_elem* p_elem);
const ocsd_gen_trc_elem_t getType() const { return elem_type; };
// return current context
const ocsd_pe_context &getContext() const { return context; };
+private:
- void clearPerPktData(); //!< clear flags that indicate validity / have values on a per packet basis
};
inline OcsdTraceElement::OcsdTraceElement(ocsd_gen_trc_elem_t type) @@ -89,16 +120,30 @@ inline void OcsdTraceElement::setEvent(const event_t ev_type, const uint16_t num trace_event.ev_number = ev_type == EVENT_NUMBERED ? number : 0; }
+inline void OcsdTraceElement::setAddrRange(const ocsd_vaddr_t st_addr, const ocsd_vaddr_t en_addr) +{
- this->st_addr = st_addr;
- this->en_addr = en_addr;
+}
+inline void OcsdTraceElement::setLastInstrInfo(const bool exec, const ocsd_instr_type last_i_type, const ocsd_instr_subtype last_i_subtype) +{
- last_instr_exec = exec ? 1 : 0;
- this->last_i_type = last_i_type;
- this->last_i_subtype = last_i_subtype;
+}
inline void OcsdTraceElement::setType(const ocsd_gen_trc_elem_t type) { // set the type and clear down the per element flags elem_type = type;
- has_cc = 0;
- last_instr_exec = 0;
- last_i_type = OCSD_INSTR_OTHER;
- excep_ret_addr = 0;
- exception_number = 0;
- excep_data_marker = 0;
- clearPerPktData();
+}
+inline void OcsdTraceElement::updateType(const ocsd_gen_trc_elem_t type) +{
- elem_type = type;
}
inline void OcsdTraceElement::init() @@ -107,13 +152,32 @@ inline void OcsdTraceElement::init() context.vmid_valid = 0; context.el_valid = 0;
- last_i_type = OCSD_INSTR_OTHER;
- last_i_subtype = OCSD_S_INSTR_NONE;
- clearPerPktData();
+}
+inline void OcsdTraceElement::clearPerPktData() +{ cpu_freq_change = 0; has_cc = 0; last_instr_exec = 0; excep_ret_addr = 0;
- exception_number = 0; // union with trace_on_reason / trace_event excep_data_marker = 0;
}
+inline void OcsdTraceElement::setTraceOnReason(const trace_on_reason_t reason) +{
- trace_on_reason = reason;
+}
+inline void OcsdTraceElement::setISA(const ocsd_isa isa_update) +{
- isa = isa_update;
+}
/** @}*/
#endif // ARM_TRC_GEN_ELEM_H_INCLUDED diff --git a/decoder/include/etmv3/trc_cmp_cfg_etmv3.h b/decoder/include/etmv3/trc_cmp_cfg_etmv3.h index a169375..f2da178 100644 --- a/decoder/include/etmv3/trc_cmp_cfg_etmv3.h +++ b/decoder/include/etmv3/trc_cmp_cfg_etmv3.h @@ -214,6 +214,16 @@ inline const uint8_t EtmV3Config::getTraceID() const return (uint8_t)(m_cfg.reg_trc_id & 0x7F); }
+inline const ocsd_arch_version_t EtmV3Config::getArchVersion() const +{
- return m_cfg.arch_ver;
+}
+inline const ocsd_core_profile_t EtmV3Config::getCoreProfile() const +{
- return m_cfg.core_prof;
+}
/** @}*/
/** @}*/ diff --git a/decoder/include/etmv3/trc_pkt_decode_etmv3.h b/decoder/include/etmv3/trc_pkt_decode_etmv3.h index 5dd78e4..c8487ec 100644 --- a/decoder/include/etmv3/trc_pkt_decode_etmv3.h +++ b/decoder/include/etmv3/trc_pkt_decode_etmv3.h @@ -39,11 +39,151 @@ #include "common/trc_gen_elem.h" #include "common/ocsd_pe_context.h" #include "common/ocsd_code_follower.h" +#include "common/ocsd_gen_elem_list.h"
#include "etmv3/trc_pkt_elem_etmv3.h" #include "etmv3/trc_cmp_cfg_etmv3.h"
+/**************** Atom handling class **************************************/ +class Etmv3Atoms +{ +public:
- Etmv3Atoms(const bool isCycleAcc);
- ~Etmv3Atoms() {};
- //! initialise the atom and index values
- void initAtomPkt(const EtmV3TrcPacket *in_pkt, const ocsd_trc_index_t &root_index);
- const ocsd_atm_val getCurrAtomVal() const;
- const int numAtoms() const; //!< number of atoms
- const ocsd_trc_index_t pktIndex() const; //!< originating packet index
- const bool hasAtomCC() const; //!< cycle count for current atom?
- const uint32_t getAtomCC() const; //!< cycle count for current atom
- const uint32_t getRemainCC() const; //!< get residual cycle count for remaining atoms
- void clearAtom(); //!< clear the current atom, set the next.
- void clearAll(); //!< clear all
+private:
- ocsd_pkt_atom m_atom; /**< atom elements - non zero number indicates valid atom count */
- uint8_t m_p_hdr_fmt; /**< if atom elements, associated phdr format */
- uint32_t m_cycle_count;
- ocsd_trc_index_t m_root_index; //!< root index for the atom packet
- bool m_isCCPacket;
+};
+inline Etmv3Atoms::Etmv3Atoms(const bool isCycleAcc) +{
- m_isCCPacket = isCycleAcc;
+}
+//! initialise the atom and index values +inline void Etmv3Atoms::initAtomPkt(const EtmV3TrcPacket *in_pkt, const ocsd_trc_index_t &root_index) +{
- m_atom = in_pkt->getAtom();
- m_p_hdr_fmt = in_pkt->getPHdrFmt();
- m_cycle_count = in_pkt->getCycleCount();
+}
+inline const ocsd_atm_val Etmv3Atoms::getCurrAtomVal() const +{
- return (m_atom.En_bits & 0x1) ? ATOM_E : ATOM_N;
+}
+inline const int Etmv3Atoms::numAtoms() const +{
- return m_atom.num;
+}
+inline const ocsd_trc_index_t Etmv3Atoms::pktIndex() const +{
- return m_root_index;
+}
+inline const bool Etmv3Atoms::hasAtomCC() const +{
- bool hasCC = false;
- if(m_isCCPacket)
- {
switch(m_p_hdr_fmt)
{
case 4:
default:
break;
case 3:
case 1:
hasCC = true;
break;
case 2:
hasCC = (m_atom.num > 1); // first of 2 has W state
break;
}
Please explain the hard coded values.
- }
- return hasCC;
+}
+inline const uint32_t Etmv3Atoms::getAtomCC() const +{
- uint32_t CC = 0;
- if(m_isCCPacket)
if (!m_isCCPacket) return CC;
- {
switch(m_p_hdr_fmt)
{
case 4: // no CC in format 4
default: break;
case 3: // single CC with optional E atom
CC = m_cycle_count; break;
case 2: // single W on first of 2 atoms
CC = (m_atom.num > 1) ? 1: 0; break;
case 1: // each atom has 1 CC.
CC = 1; break;
Putting the "break" on a line by itself will definitely help reading the code.
}
- }
- return CC;
+}
+inline const uint32_t Etmv3Atoms::getRemainCC() const +{
- uint32_t CC = 0;
- if(m_isCCPacket)
- {
switch(m_p_hdr_fmt)
{
case 4: // no CC in format 4
default: break;
case 3:
CC = m_cycle_count; break;
case 2:
CC = (m_atom.num > 1) ? 1: 0; break;
case 1:
CC = m_atom.num; break;
}
- }
Same comment as above.
- return CC;
+}
+inline void Etmv3Atoms::clearAtom() +{
- m_atom.En_bits >>=1;
- if(m_atom.num)
m_atom.num--;
+}
+inline void Etmv3Atoms::clearAll() +{
- m_atom.num = 0;
+}
+/********** Main decode class ****************************************************/ class TrcPktDecodeEtmV3 : public TrcPktDecodeBase<EtmV3TrcPacket, EtmV3Config> { public: @@ -64,24 +204,33 @@ protected: void initDecoder(); //!< initial state on creation (zeros all config) void resetDecoder(); //!< reset state to start of decode. (moves state, retains config)
- ocsd_datapath_resp_t decodePacket(); //!< decode a packet
- ocsd_datapath_resp_t decodePacket(bool &pktDone); //!< decode a packet
- ocsd_datapath_resp_t processISync(const bool withCC);
- ocsd_datapath_resp_t processISync(const bool withCC, const bool firstSync = false); ocsd_datapath_resp_t processBranchAddr(); ocsd_datapath_resp_t processPHdr();
- void pendPacket(); //!< save current packet for re-assess next pass
- ocsd_datapath_resp_t sendUnsyncPacket(); //!< send an initial unsync packet when decoder starts
- OcsdTraceElement *GetNextOpElem(ocsd_datapath_resp_t &resp); //!< get the next element from the element list.
private:
- void setNeedAddr(bool bNeedAddr);
- void pendExceptionReturn();
- bool preISyncValid(ocsd_etmv3_pkt_type pkt_type);
//** intra packet state;
OcsdCodeFollower m_code_follower; //!< code follower for instruction trace ocsd_vaddr_t m_IAddr; //!< next instruction address
- OcsdPeContext m_pe_context; //!< context for the PE
- bool m_bNeedAddr; //!< true if an address is needed (current out of date / invalid)
- bool m_bSentUnknown; //!< true if we have sent an unknown address packet for this phase of needing an address.
- bool m_bWaitISync; //!< true if waiting for first ISync packet
- OcsdPeContext m_PeContext; //!< save context data before sending in output packet
- OcsdGenElemList m_outputElemList; //!< list of output elements
- EtmV3TrcPacket m_pended_packet; //! Saved packet when processing pended.
//** Other packet decoder state;
@@ -91,16 +240,12 @@ private: WAIT_ASYNC, //!< waiting for a-sync packet. WAIT_ISYNC, //!< waiting for i-sync packet. DECODE_PKTS, //!< processing a packet
PEND_INSTR, //!< instruction output pended - need to check next packet for cancel - data in output element
PEND_PACKET, //!< packet decode pended - save previous none decoded packet data - prev pended instr had wait response.
SEND_PKTS, //!< sending packets.
} processor_state_t;
processor_state_t m_curr_state;
uint8_t m_CSID; //!< Coresight trace ID for this decoder.
-//** output element
- OcsdTraceElement m_output_elem;
};
diff --git a/decoder/include/etmv3/trc_pkt_elem_etmv3.h b/decoder/include/etmv3/trc_pkt_elem_etmv3.h index 6e70ade..68438f9 100644 --- a/decoder/include/etmv3/trc_pkt_elem_etmv3.h +++ b/decoder/include/etmv3/trc_pkt_elem_etmv3.h @@ -62,7 +62,7 @@ public: operator const ocsd_etmv3_pkt*() const { return &m_pkt_data; }; operator const ocsd_etmv3_pkt&() const { return m_pkt_data; };
-// update interace - set packet values +// update interface - set packet values void Clear(); //!< clear update data in packet ready for new one. void ResetState(); //!< reset intra packet state data -on full decoder reset.
@@ -103,6 +103,9 @@ public: const ocsd_isa ISA() const { return m_pkt_data.curr_isa; }; const bool changedISA() const { return m_pkt_data.curr_isa != m_pkt_data.prev_isa; };
- // any of the context elements updated?
- const bool isCtxtUpdated() const;
- const bool isCtxtFlagsUpdated() const { return (m_pkt_data.context.updated == 1); }; const bool isNS() const { return m_pkt_data.context.curr_NS; }; const bool isHyp() const { return m_pkt_data.context.curr_Hyp; };
@@ -119,6 +122,18 @@ public: const uint16_t excepNum() const { return m_pkt_data.exception.number; }; const bool isExcepCancel() const { return (m_pkt_data.exception.bits.present == 1) && (m_pkt_data.exception.bits.cancel == 1); };
- const ocsd_iSync_reason getISyncReason() const { return m_pkt_data.isync_info.reason; };
- const bool getISyncHasCC() const { return m_pkt_data.isync_info.has_cycle_count; };
- const bool getISyncIsLSiPAddr() const { return m_pkt_data.isync_info.has_LSipAddress; };
- const bool getISyncNoAddr() const { return m_pkt_data.isync_info.no_address; };
- const ocsd_vaddr_t getAddr() const { return m_pkt_data.addr.val; };
- const ocsd_vaddr_t getDataAddr() const { return m_pkt_data.data.addr.val; };
- const ocsd_pkt_atom &getAtom() const { return m_pkt_data.atom; };
- const uint8_t getPHdrFmt() const { return m_pkt_data.p_hdr_fmt; };
// printing virtual void toString(std::string &str) const; virtual void toStringFmt(const uint32_t fmtFlags, std::string &str) const; @@ -228,6 +243,13 @@ inline void EtmV3TrcPacket::SetISyncNoAddr() m_pkt_data.isync_info.no_address = 1; }
+inline const bool EtmV3TrcPacket::isCtxtUpdated() const +{
return (m_pkt_data.context.updated_v == 1) ||
(m_pkt_data.context.updated == 1) ||
(m_pkt_data.context.updated_c == 1);
+}
/** @}*/ #endif // ARM_TRC_PKT_ELEM_ETMV3_H_INCLUDED
diff --git a/decoder/include/etmv3/trc_pkt_types_etmv3.h b/decoder/include/etmv3/trc_pkt_types_etmv3.h index 9a615e5..0be9d98 100644 --- a/decoder/include/etmv3/trc_pkt_types_etmv3.h +++ b/decoder/include/etmv3/trc_pkt_types_etmv3.h @@ -138,14 +138,14 @@ typedef struct _ocsd_etmv3_pkt ocsd_isa curr_isa; /**< current ISA */ ocsd_isa prev_isa; /**< ISA in previous packet */
- etmv3_context_t context; /**< current context */
etmv3_context_t context; /**< current context */ ocsd_pkt_vaddr addr; /**< current Addr */
etmv3_isync_t isync_info;
ocsd_etmv3_excep exception;
- ocsd_pkt_atom atom; /**< atom elements - non zerom number indicates valid atom count */
- ocsd_pkt_atom atom; /**< atom elements - non zerom number indicates valid atom count */ uint8_t p_hdr_fmt; /**< if atom elements, associated phdr format */ uint32_t cycle_count; /**< cycle count associated with this packet (ETMv3 has counts in atom packets and as individual packets */
@@ -160,10 +160,10 @@ typedef struct _ocsd_etmv3_pkt
typedef struct _ocsd_etmv3_cfg {
- uint32_t reg_idr; /**< ID register */
- uint32_t reg_ctrl; /**< Control Register */
- uint32_t reg_ccer; /**< CCER register */
- uint32_t reg_trc_id; /**< Trace Stream ID register */
- uint32_t reg_idr; /**< ID register */
- uint32_t reg_ctrl; /**< Control Register */
- uint32_t reg_ccer; /**< CCER register */
- uint32_t reg_trc_id; /**< Trace Stream ID register */ ocsd_arch_version_t arch_ver; /**< Architecture version */ ocsd_core_profile_t core_prof; /**< Core Profile */
} ocsd_etmv3_cfg; diff --git a/decoder/include/ocsd_if_types.h b/decoder/include/ocsd_if_types.h index 9e4b051..00f8604 100644 --- a/decoder/include/ocsd_if_types.h +++ b/decoder/include/ocsd_if_types.h @@ -48,8 +48,8 @@ /** @name Library Versioning @{*/ #define OCSD_VER_MAJOR 0x0 /**< Library Major Version */ -#define OCSD_VER_MINOR 0x2 /**< Library Minor Version */ -#define OCSD_VER_STRING "0.002" /**< Library Version string */ +#define OCSD_VER_MINOR 0x3 /**< Library Minor Version */ +#define OCSD_VER_STRING "0.003" /**< Library Version string */ #define OCSD_LIB_NAME "OpenCSD Library" /**< Library name string */ #define OCSD_LIB_SHORT_NAME "OCSD" /**< Library Short name string */ /** @}*/ diff --git a/decoder/include/trc_gen_elem_types.h b/decoder/include/trc_gen_elem_types.h index e0714c0..a274eb8 100644 --- a/decoder/include/trc_gen_elem_types.h +++ b/decoder/include/trc_gen_elem_types.h @@ -53,7 +53,8 @@ typedef enum _ocsd_gen_trc_elem_t OCSD_GEN_TRC_ELEM_PE_CONTEXT, /*!< PE status update / change (arch, ctxtid, vmid etc). */ OCSD_GEN_TRC_ELEM_INSTR_RANGE, /*!< traced N consecutive instructions from addr (no intervening events or data elements), may have data assoc key */ OCSD_GEN_TRC_ELEM_ADDR_NACC, /*!< tracing in inaccessible memory area */
- OCSD_GEN_TRC_ELEM_EXCEPTION, /*!< exception - trace range executed up to an exception occurring */
- OCSD_GEN_TRC_ELEM_ADDR_UNKNOWN, /*!< address currently unknown - need address packet update */
- OCSD_GEN_TRC_ELEM_EXCEPTION, /*!< exception - start address may be exception target, end address may be preferred ret addr. */ OCSD_GEN_TRC_ELEM_EXCEPTION_RET, /*!< expection return */ OCSD_GEN_TRC_ELEM_TIMESTAMP, /*!< Timestamp - preceding elements happeded before this time. */ OCSD_GEN_TRC_ELEM_CYCLE_COUNT, /*!< Cycle count - cycles since last cycle count value - associated with a preceding instruction range. */
diff --git a/decoder/include/trc_pkt_types.h b/decoder/include/trc_pkt_types.h index 01e3f48..f705875 100644 --- a/decoder/include/trc_pkt_types.h +++ b/decoder/include/trc_pkt_types.h @@ -93,7 +93,7 @@ typedef struct _ocsd_pkt_atom
/** Isync Reason - common to PTM and ETMv3 **/ typedef enum _ocsd_iSync_reason {
- iSync_Periodic,
- iSync_Periodic = 0, iSync_TraceEnable, iSync_TraceRestartAfterOverflow, iSync_DebugExit
diff --git a/decoder/source/c_api/ocsd_c_api.cpp b/decoder/source/c_api/ocsd_c_api.cpp index 1dae2d3..c1d8215 100644 --- a/decoder/source/c_api/ocsd_c_api.cpp +++ b/decoder/source/c_api/ocsd_c_api.cpp @@ -249,6 +249,23 @@ OCSD_C_API ocsd_err_t ocsd_dt_create_etmv3_pkt_proc(const dcd_tree_handle_t hand return err; }
+OCSD_C_API ocsd_err_t ocsd_dt_create_etmv3_decoder(const dcd_tree_handle_t handle, const void *etmv3_cfg) +{
- ocsd_err_t err = OCSD_OK;
- if(handle != C_API_INVALID_TREE_HANDLE)
- {
EtmV3Config cfg;
cfg = static_cast<const ocsd_etmv3_cfg *>(etmv3_cfg);
// no need for a spcific CB object here - standard generic elements output used.
if(err == OCSD_OK)
err = ((DecodeTree *)handle)->createETMv3Decoder(&cfg);
- }
- else
err = OCSD_ERR_INVALID_PARAM_VAL;
- return err;
+}
OCSD_C_API ocsd_err_t ocsd_dt_attach_etmv3_pkt_mon(const dcd_tree_handle_t handle, const uint8_t trc_chan_id, FnEtmv3PktMonDataIn pPktFn, const void *p_context) { ocsd_err_t err = OCSD_OK; diff --git a/decoder/source/etmv3/trc_pkt_decode_etmv3.cpp b/decoder/source/etmv3/trc_pkt_decode_etmv3.cpp index c5bf8d2..24b753b 100644 --- a/decoder/source/etmv3/trc_pkt_decode_etmv3.cpp +++ b/decoder/source/etmv3/trc_pkt_decode_etmv3.cpp @@ -69,61 +69,47 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV3::processPacket() { case NO_SYNC: // output the initial not synced packet to the sink
m_output_elem.setType(OCSD_GEN_TRC_ELEM_NO_SYNC);
resp = outputTraceElement(m_output_elem);
m_curr_state = WAIT_ASYNC;
resp = sendUnsyncPacket();
m_curr_state = WAIT_ASYNC; // immediate wait for ASync and actually check out the packet break; case WAIT_ASYNC:
// if async, wait for ISync, but this packet done. if(m_curr_packet_in->getType() == ETM3_PKT_A_SYNC) m_curr_state = WAIT_ISYNC; bPktDone = true; break; case WAIT_ISYNC:
m_bWaitISync = true; // we are waiting for ISync if((m_curr_packet_in->getType() == ETM3_PKT_I_SYNC) || (m_curr_packet_in->getType() == ETM3_PKT_I_SYNC_CYCLE))
m_curr_state = DECODE_PKTS;
else
bPktDone = true; // not I-sync - done.
break;
case DECODE_PKTS:
resp = decodePacket();
bPktDone = true;
break;
case PEND_INSTR:
// check the current packet for cancel
if(!m_curr_packet_in->isExcepCancel())
// if not output the last instruction
resp = outputTraceElement(m_output_elem);
if( OCSD_DATA_RESP_IS_CONT(resp))
m_curr_state = DECODE_PKTS;
else {
pendPacket();
bPktDone = true;
// process the ISync immediately as the first ISync seen.
resp = processISync((m_curr_packet_in->getType() == ETM3_PKT_I_SYNC_CYCLE),true);
m_curr_state = SEND_PKTS;
m_bWaitISync = false; }
break;
case PEND_PACKET:
// something like TS, CC, PHDR+CC, which after ASYNC may be valid prior to ISync
else if(preISyncValid(m_curr_packet_in->getType())) {
const EtmV3TrcPacket *p_temp_pkt = m_curr_packet_in;
m_curr_packet_in = &m_pended_packet;
m_curr_state = DECODE_PKTS;
resp = decodePacket();
m_curr_packet_in = p_temp_pkt;
if(!OCSD_DATA_RESP_IS_CONT(resp))
{
// previous packet pended returned a wait, so pend current
pendPacket();
bPktDone = true;
}
// decode anything that might be valid - send will be set automatically
resp = decodePacket(bPktDone); }
else
bPktDone = true;
break;
case DECODE_PKTS:
resp = decodePacket(bPktDone); break;
case SEND_PKTS:
resp = m_outputElemList.sendElements();
if(OCSD_DATA_RESP_IS_CONT(resp))
m_curr_state = m_bWaitISync ? WAIT_ISYNC : DECODE_PKTS;
bPktDone = true;
break;
"default" statements are a good way to catch memory corruptions and unexpected conditions...
} }
@@ -133,7 +119,21 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV3::processPacket() ocsd_datapath_resp_t TrcPktDecodeEtmV3::onEOT() { ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
- OcsdTraceElement *pElem = 0;
- try {
pElem = GetNextOpElem(resp);
pElem->setType(OCSD_GEN_TRC_ELEM_EO_TRACE);
m_outputElemList.commitAllPendElem();
m_curr_state = SEND_PKTS;
resp = m_outputElemList.sendElements();
if(OCSD_DATA_RESP_IS_CONT(resp))
m_curr_state = DECODE_PKTS;
- }
- catch(ocsdError &err)
- {
LogError(err);
resetDecoder(); // mark decoder as unsynced - dump any current state.
- } return resp;
}
@@ -147,7 +147,12 @@ ocsd_datapath_resp_t TrcPktDecodeEtmV3::onReset() ocsd_datapath_resp_t TrcPktDecodeEtmV3::onFlush() { ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
- if(m_curr_state == SEND_PKTS)
- {
resp = m_outputElemList.sendElements();
if(OCSD_DATA_RESP_IS_CONT(resp))
m_curr_state = m_bWaitISync ? WAIT_ISYNC : DECODE_PKTS;
- } return resp;
}
@@ -173,6 +178,7 @@ ocsd_err_t TrcPktDecodeEtmV3::onProtocolConfig() arch_profile.profile = m_config->getCoreProfile(); m_code_follower.setArchProfile(arch_profile); m_code_follower.setMemSpaceCSID(m_CSID);
} else err = OCSD_ERR_NOT_INIT;m_outputElemList.initCSID(m_CSID);
@@ -187,168 +193,473 @@ void TrcPktDecodeEtmV3::initDecoder() m_CSID = 0; resetDecoder(); m_code_follower.initInterfaces(getMemoryAccessAttachPt(),getInstrDecodeAttachPt());
- m_outputElemList.initSendIf(getTraceElemOutAttachPt());
}
// reset for first use / re-use. void TrcPktDecodeEtmV3::resetDecoder() { m_curr_state = NO_SYNC; // mark as not synced
- m_pe_context.resetCtxt();
- m_output_elem.init();
- m_bNeedAddr = true;
- m_bSentUnknown = false;
- m_bWaitISync = false;
- m_outputElemList.reset();
+}
+OcsdTraceElement *TrcPktDecodeEtmV3::GetNextOpElem(ocsd_datapath_resp_t &resp) +{
- OcsdTraceElement *pElem = m_outputElemList.getNextElem(m_index_curr_pkt);
- if(pElem == 0)
- {
resp = OCSD_RESP_FATAL_NOT_INIT;
throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_MEM,m_index_curr_pkt,m_CSID,"Memory Allocation Error - fatal");
- }
- return pElem;
+}
+bool TrcPktDecodeEtmV3::preISyncValid(ocsd_etmv3_pkt_type pkt_type) +{
- bool bValid = false;
- // its a timestamp
- if((pkt_type == ETM3_PKT_TIMESTAMP) ||
// or we are cycleacc and its a packet that can have CC in it
(m_config->isCycleAcc() && ((pkt_type == ETM3_PKT_CYCLE_COUNT) || (pkt_type == ETM3_PKT_P_HDR)))
)
bValid = true;
- return bValid;
}
// simple packet transforms handled here, more complex processing passed on to specific routines. -ocsd_datapath_resp_t TrcPktDecodeEtmV3::decodePacket() +ocsd_datapath_resp_t TrcPktDecodeEtmV3::decodePacket(bool &pktDone) { ocsd_datapath_resp_t resp = OCSD_RESP_CONT; bool bOutputElem = false; bool bISyncHasCC = false;
- OcsdTraceElement *pElem = 0;
- pktDone = false;
- switch(m_curr_packet_in->getType())
- {
- // there may be pended packets that can now be committed.
- // only the branch address with exception and cancel element can cancel
- // if not one of those, commit immediately, otherwise defer to branch address handler.
- if(m_curr_packet_in->getType() != ETM3_PKT_BRANCH_ADDRESS)
m_outputElemList.commitAllPendElem();
- case ETM3_PKT_NOTSYNC:
// mark as not synced - must have lost sync in the packet processor somehow
LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ,m_index_curr_pkt,m_CSID,"Trace Packet Synchronisation Lost"));
resetDecoder(); // mark decoder as unsynced - dump any current state.
break;
// no action for these packets - ignore and continue
- case ETM3_PKT_INCOMPLETE_EOT:
- case ETM3_PKT_A_SYNC:
- case ETM3_PKT_IGNORE:
break;
-// markers for valid packets
- case ETM3_PKT_CYCLE_COUNT:
m_output_elem.setType(OCSD_GEN_TRC_ELEM_CYCLE_COUNT);
m_output_elem.setCycleCount(m_curr_packet_in->getCycleCount());
bOutputElem = true;
break;
- case ETM3_PKT_TRIGGER:
m_output_elem.setType(OCSD_GEN_TRC_ELEM_EVENT);
m_output_elem.setEvent(EVENT_TRIGGER,0);
bOutputElem = true;
break;
- case ETM3_PKT_BRANCH_ADDRESS:
resp = processBranchAddr();
break;
- case ETM3_PKT_I_SYNC_CYCLE:
bISyncHasCC = true;
- case ETM3_PKT_I_SYNC:
resp = processISync(bISyncHasCC);
break;
- case ETM3_PKT_P_HDR:
resp = processPHdr();
break;
- case ETM3_PKT_CONTEXT_ID:
m_output_elem.setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT);
m_pe_context.setCtxtID(m_curr_packet_in->getCtxtID());
m_output_elem.setContext(m_pe_context);
bOutputElem = true;
break;
- case ETM3_PKT_VMID:
m_output_elem.setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT);
m_pe_context.setVMID(m_curr_packet_in->getVMID());
m_output_elem.setContext(m_pe_context);
bOutputElem = true;
break;
- case ETM3_PKT_EXCEPTION_ENTRY:
m_output_elem.setType(OCSD_GEN_TRC_ELEM_EXCEPTION);
m_output_elem.setExcepMarker(); // exception entries are always v7M data markers in ETMv3 trace.
bOutputElem = true;
break;
- case ETM3_PKT_EXCEPTION_EXIT:
m_output_elem.setType(OCSD_GEN_TRC_ELEM_EXCEPTION_RET);
bOutputElem = true;
break;
- case ETM3_PKT_TIMESTAMP:
m_output_elem.setType(OCSD_GEN_TRC_ELEM_TIMESTAMP);
m_output_elem.setTS(m_curr_packet_in->getTS());
bOutputElem = true;
break;
// data packets - data trace not supported at present
- case ETM3_PKT_STORE_FAIL:
- case ETM3_PKT_OOO_DATA:
- case ETM3_PKT_OOO_ADDR_PLC:
- case ETM3_PKT_NORM_DATA:
- case ETM3_PKT_DATA_SUPPRESSED:
- case ETM3_PKT_VAL_NOT_TRACED:
- case ETM3_PKT_BAD_TRACEMODE:
LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,m_index_curr_pkt,m_CSID,"Invalid packet type : Data Tracing decode not supported."));
resp = OCSD_RESP_FATAL_INVALID_DATA;
resetDecoder(); // mark decoder as unsynced - dump any current state.
break;
try {
switch(m_curr_packet_in->getType())
{
-// packet errors
- case ETM3_PKT_BAD_SEQUENCE:
LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ,m_index_curr_pkt,m_CSID,"Bad Packet sequence."));
resp = OCSD_RESP_FATAL_INVALID_DATA;
resetDecoder(); // mark decoder as unsynced - dump any current state.
break;
case ETM3_PKT_NOTSYNC:
// mark as not synced - must have lost sync in the packet processor somehow
throw ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ,m_index_curr_pkt,m_CSID,"Trace Packet Synchronisation Lost");
break;
- default:
- case ETM3_PKT_RESERVED:
LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ,m_index_curr_pkt,m_CSID,"Reserved or unknown packet ID."));
resp = OCSD_RESP_FATAL_INVALID_DATA;
resetDecoder(); // mark decoder as unsynced - dump any current state.
break;
- }
// no action for these packets - ignore and continue
case ETM3_PKT_INCOMPLETE_EOT:
case ETM3_PKT_A_SYNC:
case ETM3_PKT_IGNORE:
break;
- // markers for valid packets
case ETM3_PKT_CYCLE_COUNT:
pElem = GetNextOpElem(resp);
pElem->setType(OCSD_GEN_TRC_ELEM_CYCLE_COUNT);
pElem->setCycleCount(m_curr_packet_in->getCycleCount());
break;
case ETM3_PKT_TRIGGER:
pElem = GetNextOpElem(resp);
pElem->setType(OCSD_GEN_TRC_ELEM_EVENT);
pElem->setEvent(EVENT_TRIGGER,0);
break;
case ETM3_PKT_BRANCH_ADDRESS:
resp = processBranchAddr();
break;
case ETM3_PKT_I_SYNC_CYCLE:
bISyncHasCC = true;
case ETM3_PKT_I_SYNC:
resp = processISync(bISyncHasCC);
break;
case ETM3_PKT_P_HDR:
resp = processPHdr();
break;
case ETM3_PKT_CONTEXT_ID:
pElem = GetNextOpElem(resp);
pElem->setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT);
m_PeContext.setCtxtID(m_curr_packet_in->getCtxtID());
pElem->setContext(m_PeContext);
break;
case ETM3_PKT_VMID:
pElem = GetNextOpElem(resp);
pElem->setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT);
m_PeContext.setVMID(m_curr_packet_in->getVMID());
pElem->setContext(m_PeContext);
break;
case ETM3_PKT_EXCEPTION_ENTRY:
pElem = GetNextOpElem(resp);
pElem->setType(OCSD_GEN_TRC_ELEM_EXCEPTION);
pElem->setExcepMarker(); // exception entries are always v7M data markers in ETMv3 trace.
break;
case ETM3_PKT_EXCEPTION_EXIT:
pElem = GetNextOpElem(resp);
pElem->setType(OCSD_GEN_TRC_ELEM_EXCEPTION_RET);
pendExceptionReturn();
break;
case ETM3_PKT_TIMESTAMP:
pElem = GetNextOpElem(resp);
pElem->setType(OCSD_GEN_TRC_ELEM_TIMESTAMP);
pElem->setTS(m_curr_packet_in->getTS());
break;
- if(bOutputElem)
resp = outputTraceElementIdx(m_index_curr_pkt,m_output_elem);
// data packets - data trace not supported at present
case ETM3_PKT_STORE_FAIL:
case ETM3_PKT_OOO_DATA:
case ETM3_PKT_OOO_ADDR_PLC:
case ETM3_PKT_NORM_DATA:
case ETM3_PKT_DATA_SUPPRESSED:
case ETM3_PKT_VAL_NOT_TRACED:
case ETM3_PKT_BAD_TRACEMODE:
resp = OCSD_RESP_FATAL_INVALID_DATA;
throw ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,m_index_curr_pkt,m_CSID,"Invalid packet type : Data Tracing decode not supported.");
break;
// packet errors
case ETM3_PKT_BAD_SEQUENCE:
resp = OCSD_RESP_FATAL_INVALID_DATA;
throw ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ,m_index_curr_pkt,m_CSID,"Bad Packet sequence.");
break;
default:
case ETM3_PKT_RESERVED:
resp = OCSD_RESP_FATAL_INVALID_DATA;
throw ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ,m_index_curr_pkt,m_CSID,"Reserved or unknown packet ID.");
break;
}
m_curr_state = m_outputElemList.elemToSend() ? SEND_PKTS : DECODE_PKTS;
pktDone = !m_outputElemList.elemToSend();
}
catch(ocsdError &err)
{
LogError(err);
resetDecoder(); // mark decoder as unsynced - dump any current state.
pktDone = true;
}
catch(...)
{
LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_FAIL,m_index_curr_pkt,m_CSID,"Bad Packet sequence."));
resp = OCSD_RESP_FATAL_SYS_ERR;
resetDecoder(); // mark decoder as unsynced - dump any current state.
pktDone = true;
}
return resp;
+}
+ocsd_datapath_resp_t TrcPktDecodeEtmV3::sendUnsyncPacket() +{
- ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
- OcsdTraceElement *pElem = 0;
- try {
pElem = GetNextOpElem(resp);
pElem->setType(OCSD_GEN_TRC_ELEM_NO_SYNC);
resp = m_outputElemList.sendElements();
- }
- catch(ocsdError &err)
- {
LogError(err);
resetDecoder(); // mark decoder as unsynced - dump any current state.
- } return resp;
}
-void TrcPktDecodeEtmV3::pendPacket() +void TrcPktDecodeEtmV3::setNeedAddr(bool bNeedAddr) {
- m_pended_packet = *m_curr_packet_in;
- m_curr_state = PEND_PACKET;
- m_bNeedAddr = bNeedAddr;
- m_bSentUnknown = false;
}
-ocsd_datapath_resp_t TrcPktDecodeEtmV3::processISync(const bool withCC)
+ocsd_datapath_resp_t TrcPktDecodeEtmV3::processISync(const bool withCC, const bool firstSync /* = false */) {
- // map ISync reason to generic reason codes.
- static trace_on_reason_t on_map[] = { TRACE_ON_NORMAL, TRACE_ON_NORMAL,
TRACE_ON_OVERFLOW, TRACE_ON_EX_DEBUG };
- ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
- // look for context changes....
- if(m_curr_packet_in->isCtxtIDUpdated())
- {
- bool ctxtUpdate = m_curr_packet_in->isCtxtUpdated();
- OcsdTraceElement *pElem = 0;
- }
- try {
- if(m_config->CtxtIDBytes())
- {
pElem = GetNextOpElem(resp);
- }
if(firstSync || (m_curr_packet_in->getISyncReason() != iSync_Periodic))
{
pElem->setType(OCSD_GEN_TRC_ELEM_TRACE_ON);
pElem->setTraceOnReason(on_map[(int)m_curr_packet_in->getISyncReason()]);
pElem = GetNextOpElem(resp);
}
// look for context changes....
if(ctxtUpdate || firstSync)
{
// if not first time out, read existing context in output element,
// otherwise we are setting it new.
if(firstSync)
m_PeContext.resetCtxt();
if(m_curr_packet_in->isCtxtIDUpdated())
m_PeContext.setCtxtID(m_curr_packet_in->getCtxtID());
if(m_curr_packet_in->isVMIDUpdated())
m_PeContext.setVMID(m_curr_packet_in->getVMID());
if(m_curr_packet_in->isCtxtFlagsUpdated())
{
m_PeContext.setEL(m_curr_packet_in->isHyp() ? ocsd_EL2 : ocsd_EL_unknown);
m_PeContext.setSecLevel(m_curr_packet_in->isNS() ? ocsd_sec_nonsecure : ocsd_sec_secure);
}
// prepare the context packet
pElem->setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT);
pElem->setContext(m_PeContext);
pElem->setISA(m_curr_packet_in->ISA());
// with cycle count...
if(m_curr_packet_in->getISyncHasCC())
pElem->setCycleCount(m_curr_packet_in->getCycleCount());
}
// set ISync address - if it is a valid I address
if(!m_curr_packet_in->getISyncNoAddr())
{
if(m_curr_packet_in->getISyncIsLSiPAddr())
{
// TBD: handle extra data processing instruction for data trace
// need to output E atom relating to the data instruction
// rare - on start-up case.
// main instruction address saved in data address for this packet type.
m_IAddr = m_curr_packet_in->getDataAddr();
}
else
{
m_IAddr = m_curr_packet_in->getAddr();
}
setNeedAddr(false); // ready to process atoms.
}
m_curr_state = m_outputElemList.elemToSend() ? SEND_PKTS : DECODE_PKTS;
}
catch(ocsdError &err)
{
LogError(err);
resetDecoder(); // mark decoder as unsynced - dump any current state.
} return resp;
}
ocsd_datapath_resp_t TrcPktDecodeEtmV3::processBranchAddr() { ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
OcsdTraceElement *pElem = 0;
bool bUpdatePEContext = false;
// might need to cancel something ... if the last output was an instruction range or excep return
if(m_curr_packet_in->isExcepCancel())
m_outputElemList.cancelPendElem();
else
m_outputElemList.commitAllPendElem(); // otherwise commit any pending elements.
// record the address
m_IAddr = m_curr_packet_in->getAddr();
setNeedAddr(false); // no longer need an address.
// exception packet - may need additional output
if(m_curr_packet_in->isExcepPkt())
{
// exeception packet may have exception, context change, or both.
// check for context change
if(m_curr_packet_in->isCtxtUpdated())
{
ocsd_sec_level sec = m_curr_packet_in->isNS() ? ocsd_sec_nonsecure : ocsd_sec_secure;
if(sec != m_PeContext.getSecLevel())
{
m_PeContext.setSecLevel(sec);
bUpdatePEContext = true;
}
ocsd_ex_level pkt_el = m_curr_packet_in->isHyp() ? ocsd_EL2 : ocsd_EL_unknown;
if(pkt_el != m_PeContext.getEL())
{
m_PeContext.setEL(pkt_el);
bUpdatePEContext = true;
}
}
// now decide if we need to send any packets out.
try {
if(bUpdatePEContext)
{
pElem = GetNextOpElem(resp);
pElem->setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT);
pElem->setContext(m_PeContext);
}
// check for exception
if(m_curr_packet_in->excepNum() != 0)
{
pElem = GetNextOpElem(resp);
pElem->setType(OCSD_GEN_TRC_ELEM_EXCEPTION);
pElem->setExceptionNum(m_curr_packet_in->excepNum());
}
// finally - do we have anything to send yet?
m_curr_state = m_outputElemList.elemToSend() ? SEND_PKTS : DECODE_PKTS;
}
catch(ocsdError &err)
{
LogError(err);
resetDecoder(); // mark decoder as unsynced - dump any current state.
}
} return resp;
}
ocsd_datapath_resp_t TrcPktDecodeEtmV3::processPHdr() { ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
OcsdTraceElement *pElem = 0;
uint32_t CC = 0;
ocsd_isa isa;
Etmv3Atoms atoms(m_config->isCycleAcc());
atoms.initAtomPkt(m_curr_packet_in,m_index_curr_pkt);
isa = m_curr_packet_in->ISA();
m_code_follower.setMemSpaceAccess((m_PeContext.getSecLevel() == ocsd_sec_secure) ? OCSD_MEM_SPACE_S : OCSD_MEM_SPACE_N);
try
{
do
{
// if we do not have a valid address then send any cycle count elements
// and stop processing
if(m_bNeedAddr)
{
// output unknown address packet or a cycle count packet
if(!m_bSentUnknown || m_config->isCycleAcc())
{
pElem = GetNextOpElem(resp);
if(m_bSentUnknown || !atoms.numAtoms())
pElem->setType(OCSD_GEN_TRC_ELEM_CYCLE_COUNT);
else
pElem->setType(OCSD_GEN_TRC_ELEM_ADDR_UNKNOWN);
if(m_config->isCycleAcc())
pElem->setCycleCount(atoms.getRemainCC());
m_bSentUnknown = true;
}
atoms.clearAll(); // skip remaining atoms
}
else // have an address, can process atoms
{
pElem = GetNextOpElem(resp);
pElem->setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE);
// cycle accurate may have a cycle count to use
if(m_config->isCycleAcc())
{
// note: it is possible to have a CC only atom packet.
if(!atoms.numAtoms()) // override type if CC only
pElem->setType(OCSD_GEN_TRC_ELEM_CYCLE_COUNT);
// set cycle count
pElem->setCycleCount(atoms.getAtomCC());
}
// now process the atom
if(atoms.numAtoms())
{
m_code_follower.setISA(isa);
m_code_follower.followSingleAtom(m_IAddr,atoms.getCurrAtomVal());
// valid code range
if(m_code_follower.hasRange())
{
pElem->setAddrRange(m_IAddr,m_code_follower.getRangeEn());
pElem->setLastInstrInfo(atoms.getCurrAtomVal() == ATOM_E,
m_code_follower.getInstrType(),
m_code_follower.getInstrSubType());
pElem->setISA(isa);
if(m_code_follower.hasNextAddr())
m_IAddr = m_code_follower.getNextAddr();
else
setNeedAddr(true);
}
// next address has new ISA?
if(m_code_follower.ISAChanged())
isa = m_code_follower.nextISA();
// there is a nacc
if(m_code_follower.isNacc())
{
if(m_code_follower.hasRange())
{
pElem = GetNextOpElem(resp);
pElem->setType(OCSD_GEN_TRC_ELEM_ADDR_NACC);
}
else
pElem->updateType(OCSD_GEN_TRC_ELEM_ADDR_NACC);
pElem->setAddrStart(m_code_follower.getNaccAddr());
setNeedAddr(true);
m_code_follower.clearNacc(); // we have generated some code for the nacc.
}
}
atoms.clearAtom(); // next atom
}
}
while(atoms.numAtoms());
// is tha last element an atom?
int numElem = m_outputElemList.getNumElem();
if(numElem >= 1)
{
// if the last thing is an instruction range, pend it - could be cancelled later.
if(m_outputElemList.getElemType(numElem-1) == OCSD_GEN_TRC_ELEM_INSTR_RANGE)
m_outputElemList.pendLastNElem(1);
}
// finally - do we have anything to send yet?
m_curr_state = m_outputElemList.elemToSend() ? SEND_PKTS : DECODE_PKTS;
}
catch(ocsdError &err)
{
LogError(err);
resetDecoder(); // mark decoder as unsynced - dump any current state.
} return resp;
}
+// if v7M -> pend only ERET, if V7A/R pend ERET and prev instr. +void TrcPktDecodeEtmV3::pendExceptionReturn() +{
- int pendElem = 1;
- if(m_config->getCoreProfile() != profile_CortexM)
- {
int nElem = m_outputElemList.getNumElem();
if(nElem > 1)
{
if(m_outputElemList.getElemType(nElem - 2) == OCSD_GEN_TRC_ELEM_INSTR_RANGE)
pendElem = 2; // need to pend instr+eret for A/R
}
- }
- m_outputElemList.pendLastNElem(pendElem);
+}
/* End of File trc_pkt_decode_etmv3.cpp */ diff --git a/decoder/source/ocsd_code_follower.cpp b/decoder/source/ocsd_code_follower.cpp index b52704e..b03ec1a 100644 --- a/decoder/source/ocsd_code_follower.cpp +++ b/decoder/source/ocsd_code_follower.cpp @@ -99,7 +99,7 @@ ocsd_err_t OcsdCodeFollower::followSingleAtom(const ocsd_vaddr_t addrStart, cons ocsd_err_t err = OCSD_ERR_NOT_INIT; if(initFollowerState()) {
m_st_range_addr = m_instr_info.instr_addr = addrStart;
m_en_range_addr = m_st_range_addr = m_instr_info.instr_addr = addrStart; err = decodeSingleOpCode(); if(err == OCSD_OK) {
@@ -128,7 +128,6 @@ ocsd_err_t OcsdCodeFollower::followSingleAtom(const ocsd_vaddr_t addrStart, cons return err; }
ocsd_err_t OcsdCodeFollower::decodeSingleOpCode() { ocsd_err_t err = OCSD_OK; diff --git a/decoder/source/ocsd_dcd_tree.cpp b/decoder/source/ocsd_dcd_tree.cpp index cf5a30d..8f14af1 100644 --- a/decoder/source/ocsd_dcd_tree.cpp +++ b/decoder/source/ocsd_dcd_tree.cpp @@ -61,7 +61,7 @@ void DecodeTreeElement::DestroyElem() case OCSD_PROTOCOL_ETMV3: delete decoder.etmv3.proc; decoder.etmv3.proc = 0;
//TBD: delete decoder.etmv3.dcd;
delete decoder.etmv3.dcd; decoder.etmv3.dcd = 0; break;
@@ -533,16 +533,33 @@ ocsd_err_t DecodeTree::createSTMPktProcessor(STMConfig *p_config, IPktDataIn<Stm ocsd_err_t DecodeTree::createETMv3Decoder(EtmV3Config *p_config) { ocsd_err_t err = OCSD_ERR_NOT_INIT; -#if 0 //TBD: uint8_t CSID = 0; // default for single stream decoder (no deformatter) - we ignore the ID if(usingFormatter()) CSID = p_config->getTraceID();
- /* err = */ createETMv3PktProcessor(p_config);
- if(err == OCSD_OK) // created the packet processor and the decoder element*/
- TrcPktDecodeEtmV3 *pProc = 0;
- pProc = new (std::nothrow) TrcPktDecodeEtmV3(CSID);
- if(!pProc)
return OCSD_ERR_MEM;
- err = createETMv3PktProcessor(p_config,pProc);
- if(err == OCSD_OK) {
//** TBD
m_decode_elements[CSID]->SetDecoderElement(pProc);
err = pProc->setProtocolConfig(p_config);
if(m_i_instr_decode && (err == OCSD_OK))
err = pProc->getInstrDecodeAttachPt()->attach(m_i_instr_decode);
if(m_i_mem_access && (err == OCSD_OK))
err = pProc->getMemoryAccessAttachPt()->attach(m_i_mem_access);
if( m_i_gen_elem_out && (err == OCSD_OK))
err = pProc->getTraceElemOutAttachPt()->attach(m_i_gen_elem_out);
if(err == OCSD_OK)
err = pProc->getErrorLogAttachPt()->attach(DecodeTree::s_i_error_logger);
if(err != OCSD_OK)
}destroyDecodeElement(CSID);
-#endif
- return err;
}
diff --git a/decoder/source/ocsd_error.cpp b/decoder/source/ocsd_error.cpp index 844fca5..a94b7b2 100644 --- a/decoder/source/ocsd_error.cpp +++ b/decoder/source/ocsd_error.cpp @@ -66,10 +66,11 @@ static const char *s_errorCodeDescs[][2] = { {"OCSD_ERR_PKT_INTERP_FAIL","Interpreter failed - cannot recover - bad data or sequence"}, /* packet decoder errors */ {"OCSD_ERR_UNSUPPORTED_ISA","ISA not supported in decoder"},
- {"OCSD_ERR_HW_CFG_UNSUPP","Programmed trace configuration not supported by decoder."},
- {"OCSD_ERR_HW_CFG_UNSUPP","Programmed trace configuration not supported by decodUer."}, {"OCSD_ERR_UNSUPP_DECODE_PKT","Packet not supported in decoder"}, {"OCSD_ERR_BAD_DECODE_PKT","Reserved or unknown packet in decoder."}, {"OCSD_ERR_COMMIT_PKT_OVERRUN","Overrun in commit packet stack - tried to commit more than available"},
- {"OCSD_ERR_MEM_NACC","Unable to access required memory address."}, /* decode tree errors */ {"OCSD_ERR_DCDT_NO_FORMATTER","No formatter in use - operation not valid."}, /* target memory access errors */
diff --git a/decoder/source/ocsd_gen_elem_list.cpp b/decoder/source/ocsd_gen_elem_list.cpp new file mode 100644 index 0000000..1a568ec --- /dev/null +++ b/decoder/source/ocsd_gen_elem_list.cpp @@ -0,0 +1,168 @@ +/*
- \file ocsd_gen_elem_list.cpp
- \brief OpenCSD : List of Generic trace elements for output.
- \copyright Copyright (c) 2016, ARM Limited. All Rights Reserved.
- */
+/*
- Redistribution and use in source and binary forms, with or without modification,
- are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
- Neither the name of the copyright holder nor the names of its contributors
- may be used to endorse or promote products derived from this software without
- specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
+#include "common/ocsd_gen_elem_list.h"
+OcsdGenElemList::OcsdGenElemList() +{
- m_firstElemIdx=0;
- m_numUsed=0;
- m_numPend=0;
- m_elemArraySize = 0;
- m_sendIf = 0;
- m_CSID = 0;
- m_pElemArray = 0;
+}
+OcsdGenElemList::~OcsdGenElemList() +{
- for(int i = 0; i<m_elemArraySize; i++)
- {
delete m_pElemArray[i].pElem;
- }
- delete [] m_pElemArray;
- m_pElemArray = 0;
+}
+void OcsdGenElemList::reset() +{
- m_firstElemIdx=0;
- m_numUsed=0;
- m_numPend=0;
+}
+OcsdTraceElement *OcsdGenElemList::getNextElem(const ocsd_trc_index_t trc_pkt_idx) +{
- OcsdTraceElement *pElem = 0;
- if(getNumElem() == m_elemArraySize) // all in use
growArray();
- if(m_pElemArray != 0)
- {
m_numUsed++;
int idx = getAdjustedIdx(m_firstElemIdx + m_numUsed - 1);
pElem = m_pElemArray[idx].pElem;
m_pElemArray[idx].trc_pkt_idx = trc_pkt_idx;
- }
- return pElem;
+}
+const ocsd_gen_trc_elem_t OcsdGenElemList::getElemType(const int entryN) const +{
- ocsd_gen_trc_elem_t elem_type = OCSD_GEN_TRC_ELEM_UNKNOWN;
- if(entryN < getNumElem())
- {
int idx = getAdjustedIdx(m_firstElemIdx + entryN);
elem_type = m_pElemArray[idx].pElem->getType();
- }
- return elem_type;
+}
+ocsd_datapath_resp_t OcsdGenElemList::sendElements() +{
- ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
- if((m_elemArraySize == 0) || (m_sendIf == 0))
return OCSD_RESP_FATAL_NOT_INIT;
- if(!m_sendIf->hasAttachedAndEnabled())
return OCSD_RESP_FATAL_NOT_INIT;
- while(elemToSend() && OCSD_DATA_RESP_IS_CONT(resp))
- {
resp = m_sendIf->first()->TraceElemIn(m_pElemArray[m_firstElemIdx].trc_pkt_idx, m_CSID, *(m_pElemArray[m_firstElemIdx].pElem));
m_firstElemIdx++;
if(m_firstElemIdx >= m_elemArraySize)
m_firstElemIdx = 0;
m_numUsed--;
- }
- return resp;
+}
+// this function will enlarge the array, and create extra element objects. +// existing objects will be moved to the front of the array +// called if all elements are in use. (sets indexes accordingly) +void OcsdGenElemList::growArray() +{
- elemPtr_t *p_new_array = 0;
- int increment;
- if(m_elemArraySize == 0)
// starting from scratch...
increment = 8;
- else
increment = m_elemArraySize / 2; // grow by 50%
- p_new_array = new (std::nothrow) elemPtr_t[m_elemArraySize+increment];
- if(p_new_array != 0)
- {
// fill the last increment elements with new objects
for(int i=0; i < increment; i++)
{
p_new_array[m_elemArraySize+i].pElem = new (std::nothrow) OcsdTraceElement();
}
// copy the existing objects from the old array to the start of the new one
// and adjust the indices.
if(m_elemArraySize > 0)
{
int inIdx = m_firstElemIdx;
for(int i = 0; i < m_elemArraySize; i++)
{
p_new_array[i].pElem = m_pElemArray[inIdx].pElem;
p_new_array[i].trc_pkt_idx = m_pElemArray[inIdx].trc_pkt_idx;
inIdx++;
if(inIdx >= m_elemArraySize)
inIdx = 0;
}
}
// delete the old pointer array.
delete [] m_pElemArray;
m_elemArraySize += increment;
- }
- else
m_elemArraySize = 0;
- // update the internal array pointers to the new array
- if(m_firstElemIdx >= 0)
m_firstElemIdx = 0;
- m_pElemArray = p_new_array;
+}
+/* End of File ocsd_gen_elem_list.cpp */ diff --git a/decoder/source/trc_gen_elem.cpp b/decoder/source/trc_gen_elem.cpp index 912760d..aef8820 100644 --- a/decoder/source/trc_gen_elem.cpp +++ b/decoder/source/trc_gen_elem.cpp @@ -47,6 +47,7 @@ static const char *s_elem_descs[][2] = {"OCSD_GEN_TRC_ELEM_PE_CONTEXT","PE status update / change (arch, ctxtid, vmid etc)."}, {"OCSD_GEN_TRC_ELEM_INSTR_RANGE","Traced N consecutive instructions from addr (no intervening events or data elements), may have data assoc key"}, {"OCSD_GEN_TRC_ELEM_ADDR_NACC","Tracing in inaccessible memory area."},
- {"OCSD_GEN_TRC_ELEM_ADDR_UNKNOWN","Tracing unknown address area."}, {"OCSD_GEN_TRC_ELEM_EXCEPTION","Exception"}, {"OCSD_GEN_TRC_ELEM_EXCEPTION_RET","Expection return"}, {"OCSD_GEN_TRC_ELEM_TIMESTAMP","Timestamp - preceding elements happeded before this time."},
@@ -79,6 +80,16 @@ static const char *s_trace_on_reason[] = { "debug restart" };
+static const char *s_isa_str[] = {
- "A32", /**< V7 ARM 32, V8 AArch32 */
- "T32", /**< Thumb2 -> 16/32 bit instructions */
- "A64", /**< V8 AArch64 */
- "TEE", /**< Thumb EE - unsupported */
- "Jaz", /**< Jazelle - unsupported in trace */
- "Unk" /**< ISA not yet known */
+};
void OcsdTraceElement::toString(std::string &str) const { std::ostringstream oss; @@ -91,6 +102,7 @@ void OcsdTraceElement::toString(std::string &str) const { case OCSD_GEN_TRC_ELEM_INSTR_RANGE: oss << "exec range=0x" << std::hex << st_addr << ":[0x" << en_addr << "] ";
oss << "(ISA=" << s_isa_str[(int)isa] << ") "; oss << ((last_instr_exec == 1) ? "E " : "N "); if((int)last_i_type < T_SIZE) oss << instr_type[last_i_type];
@@ -111,7 +123,12 @@ void OcsdTraceElement::toString(std::string &str) const break;
case OCSD_GEN_TRC_ELEM_PE_CONTEXT:
oss << "EL" << std::dec << (int)(context.exception_level) << (context.security_level == ocsd_sec_secure ? " S; " : "N; ") << (context.bits64 ? "AArch64; " : "AArch32; ");
oss << "(ISA=" << s_isa_str[(int)isa] << ") ";
if(context.exception_level >= 0)
{
oss << "EL" << std::dec << (int)(context.exception_level);
}
oss << (context.security_level == ocsd_sec_secure ? " S; " : "N; ") << (context.bits64 ? "64-bit; " : "32-bit; "); if(context.vmid_valid) oss << "VMID=0x" << std::hex << context.vmid << "; "; if(context.ctxt_id_valid)
diff --git a/decoder/tests/source/simple_pkt_c_api.c b/decoder/tests/source/simple_pkt_c_api.c index 45c2611..6c6e503 100644 --- a/decoder/tests/source/simple_pkt_c_api.c +++ b/decoder/tests/source/simple_pkt_c_api.c @@ -62,7 +62,8 @@ const char *tc2_snapshot = "../../../snapshots/TC2/"; const char *trace_data_filename = "cstrace.bin"; const char *stmtrace_data_filename = "cstraceitm.bin"; const char *memory_dump_filename = "kernel_dump.bin"; -const ocsd_vaddr_t mem_dump_address=0xFFFFFFC000081000; +ocsd_vaddr_t mem_dump_address=0xFFFFFFC000081000; +const ocsd_vaddr_t mem_dump_address_tc2=0xC0008000;
static int using_mem_acc_cb = 0; static int use_region_file = 0; @@ -150,11 +151,13 @@ static void process_cmd_line(int argc, char *argv[]) { test_protocol = OCSD_PROTOCOL_ETMV3; default_path_to_snapshot = tc2_snapshot;
mem_dump_address = mem_dump_address_tc2; } else if(strcmp(argv[idx],"-ptm") == 0) { test_protocol = OCSD_PROTOCOL_PTM; default_path_to_snapshot = tc2_snapshot;
mem_dump_address = mem_dump_address_tc2; } else if(strcmp(argv[idx],"-stm") == 0) {
@@ -506,7 +509,8 @@ ocsd_datapath_resp_t etm_v3_packet_handler(const void *p_context, const ocsd_dat return packet_handler(op,index_sop,(const void *)p_packet_in); }
-void etm_v3_packet_monitor( const ocsd_datapath_op_t op, +void etm_v3_packet_monitor( const void *p_context,
const ocsd_datapath_op_t op, const ocsd_trc_index_t index_sop, const ocsd_etmv3_pkt *p_packet_in, const uint32_t size,
@@ -518,7 +522,7 @@ void etm_v3_packet_monitor( const ocsd_datapath_op_t op, static ocsd_err_t create_decoder_etmv3(dcd_tree_handle_t dcd_tree_h) { ocsd_err_t ret = OCSD_OK;
- /*char mem_file_path[512];*/
char mem_file_path[512];
/* populate the ETMv3 configuration structure */ set_config_struct_etmv3();
@@ -536,14 +540,14 @@ static ocsd_err_t create_decoder_etmv3(dcd_tree_handle_t dcd_tree_h) /* Full decode - need decoder, and memory dump */ /* not supported in library at present */
-#if 0
/* create the packet decoder and packet processor pair */ ret = ocsd_dt_create_etmv3_decoder(dcd_tree_h,&trace_config_etmv3); if(ret == OCSD_OK) { if((op != TEST_PKT_DECODEONLY) && (ret == OCSD_OK)) {
ret = ocsd_dt_attach_etmv3_pkt_mon(dcd_tree_h, (uint8_t)(trace_config_etmv3.reg_trc_id & 0x7F), etm_v4i_packet_monitor);
ret = ocsd_dt_attach_etmv3_pkt_mon(dcd_tree_h, (uint8_t)(trace_config_etmv3.reg_trc_id & 0x7F), etm_v3_packet_monitor,0); } }
@@ -556,10 +560,6 @@ static ocsd_err_t create_decoder_etmv3(dcd_tree_handle_t dcd_tree_h) /* create a memory file accessor */ ret = ocsd_dt_add_binfile_mem_acc(dcd_tree_h,mem_dump_address,OCSD_MEM_SPACE_ANY,mem_file_path); } -#else
printf("ETMv3 Full decode not supported in library at present. Packet print only\n");
ret = OCSD_ERR_RDR_NO_DECODER;
-#endif } return ret; } -- 1.9.1
CoreSight mailing list CoreSight@lists.linaro.org https://lists.linaro.org/mailman/listinfo/coresight