1c120c564SAndrew Turner /*!
2c120c564SAndrew Turner * \file trc_pkt_decode_etmv3.cpp
3c120c564SAndrew Turner * \brief OpenCSD : ETMv3 trace packet decode.
4c120c564SAndrew Turner *
5c120c564SAndrew Turner * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved.
6c120c564SAndrew Turner */
7c120c564SAndrew Turner
8c120c564SAndrew Turner /*
9c120c564SAndrew Turner * Redistribution and use in source and binary forms, with or without modification,
10c120c564SAndrew Turner * are permitted provided that the following conditions are met:
11c120c564SAndrew Turner *
12c120c564SAndrew Turner * 1. Redistributions of source code must retain the above copyright notice,
13c120c564SAndrew Turner * this list of conditions and the following disclaimer.
14c120c564SAndrew Turner *
15c120c564SAndrew Turner * 2. Redistributions in binary form must reproduce the above copyright notice,
16c120c564SAndrew Turner * this list of conditions and the following disclaimer in the documentation
17c120c564SAndrew Turner * and/or other materials provided with the distribution.
18c120c564SAndrew Turner *
19c120c564SAndrew Turner * 3. Neither the name of the copyright holder nor the names of its contributors
20c120c564SAndrew Turner * may be used to endorse or promote products derived from this software without
21c120c564SAndrew Turner * specific prior written permission.
22c120c564SAndrew Turner *
23c120c564SAndrew Turner * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
24c120c564SAndrew Turner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25c120c564SAndrew Turner * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26c120c564SAndrew Turner * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27c120c564SAndrew Turner * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28c120c564SAndrew Turner * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29c120c564SAndrew Turner * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30c120c564SAndrew Turner * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31c120c564SAndrew Turner * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32c120c564SAndrew Turner * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33c120c564SAndrew Turner */
34c120c564SAndrew Turner
35c120c564SAndrew Turner #include "opencsd/etmv3/trc_pkt_decode_etmv3.h"
36c120c564SAndrew Turner
37c120c564SAndrew Turner #define DCD_NAME "DCD_ETMV3"
38c120c564SAndrew Turner
TrcPktDecodeEtmV3()39c120c564SAndrew Turner TrcPktDecodeEtmV3::TrcPktDecodeEtmV3() :
40c120c564SAndrew Turner TrcPktDecodeBase(DCD_NAME)
41c120c564SAndrew Turner {
42c120c564SAndrew Turner initDecoder();
43c120c564SAndrew Turner }
44c120c564SAndrew Turner
TrcPktDecodeEtmV3(int instIDNum)45c120c564SAndrew Turner TrcPktDecodeEtmV3::TrcPktDecodeEtmV3(int instIDNum) :
46c120c564SAndrew Turner TrcPktDecodeBase(DCD_NAME, instIDNum)
47c120c564SAndrew Turner {
48c120c564SAndrew Turner initDecoder();
49c120c564SAndrew Turner }
50c120c564SAndrew Turner
~TrcPktDecodeEtmV3()51c120c564SAndrew Turner TrcPktDecodeEtmV3::~TrcPktDecodeEtmV3()
52c120c564SAndrew Turner {
53c120c564SAndrew Turner }
54c120c564SAndrew Turner
55c120c564SAndrew Turner
56c120c564SAndrew Turner /* implementation packet decoding interface */
processPacket()57c120c564SAndrew Turner ocsd_datapath_resp_t TrcPktDecodeEtmV3::processPacket()
58c120c564SAndrew Turner {
59c120c564SAndrew Turner ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
60c120c564SAndrew Turner bool bPktDone = false;
61c120c564SAndrew Turner
62c120c564SAndrew Turner if(!m_config)
63c120c564SAndrew Turner return OCSD_RESP_FATAL_NOT_INIT;
64c120c564SAndrew Turner
65c120c564SAndrew Turner // iterate round the state machine, waiting for sync, then decoding packets.
66c120c564SAndrew Turner while(!bPktDone)
67c120c564SAndrew Turner {
68c120c564SAndrew Turner switch(m_curr_state)
69c120c564SAndrew Turner {
70c120c564SAndrew Turner case NO_SYNC:
71c120c564SAndrew Turner // output the initial not synced packet to the sink
72c120c564SAndrew Turner resp = sendUnsyncPacket();
73c120c564SAndrew Turner m_curr_state = WAIT_ASYNC; // immediate wait for ASync and actually check out the packet
74c120c564SAndrew Turner break;
75c120c564SAndrew Turner
76c120c564SAndrew Turner case WAIT_ASYNC:
77c120c564SAndrew Turner // if async, wait for ISync, but this packet done.
78c120c564SAndrew Turner if(m_curr_packet_in->getType() == ETM3_PKT_A_SYNC)
79c120c564SAndrew Turner m_curr_state = WAIT_ISYNC;
80c120c564SAndrew Turner bPktDone = true;
81c120c564SAndrew Turner break;
82c120c564SAndrew Turner
83c120c564SAndrew Turner case WAIT_ISYNC:
84c120c564SAndrew Turner m_bWaitISync = true; // we are waiting for ISync
85c120c564SAndrew Turner if((m_curr_packet_in->getType() == ETM3_PKT_I_SYNC) ||
86c120c564SAndrew Turner (m_curr_packet_in->getType() == ETM3_PKT_I_SYNC_CYCLE))
87c120c564SAndrew Turner {
88c120c564SAndrew Turner // process the ISync immediately as the first ISync seen.
89c120c564SAndrew Turner resp = processISync((m_curr_packet_in->getType() == ETM3_PKT_I_SYNC_CYCLE),true);
90c120c564SAndrew Turner m_curr_state = SEND_PKTS;
91c120c564SAndrew Turner m_bWaitISync = false;
92c120c564SAndrew Turner }
93c120c564SAndrew Turner // something like TS, CC, PHDR+CC, which after ASYNC may be valid prior to ISync
94c120c564SAndrew Turner else if(preISyncValid(m_curr_packet_in->getType()))
95c120c564SAndrew Turner {
96c120c564SAndrew Turner // decode anything that might be valid - send will be set automatically
97c120c564SAndrew Turner resp = decodePacket(bPktDone);
98c120c564SAndrew Turner }
99c120c564SAndrew Turner else
100c120c564SAndrew Turner bPktDone = true;
101c120c564SAndrew Turner break;
102c120c564SAndrew Turner
103c120c564SAndrew Turner case DECODE_PKTS:
104c120c564SAndrew Turner resp = decodePacket(bPktDone);
105c120c564SAndrew Turner break;
106c120c564SAndrew Turner
107c120c564SAndrew Turner case SEND_PKTS:
108c120c564SAndrew Turner resp = m_outputElemList.sendElements();
109c120c564SAndrew Turner if(OCSD_DATA_RESP_IS_CONT(resp))
110c120c564SAndrew Turner m_curr_state = m_bWaitISync ? WAIT_ISYNC : DECODE_PKTS;
111c120c564SAndrew Turner bPktDone = true;
112c120c564SAndrew Turner break;
113c120c564SAndrew Turner
114c120c564SAndrew Turner default:
115c120c564SAndrew Turner bPktDone = true;
116c120c564SAndrew Turner LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_FAIL,m_index_curr_pkt,"Unknown Decoder State"));
117c120c564SAndrew Turner resetDecoder(); // mark decoder as unsynced - dump any current state.
118c120c564SAndrew Turner resp = OCSD_RESP_FATAL_SYS_ERR;
119c120c564SAndrew Turner break;
120c120c564SAndrew Turner }
121c120c564SAndrew Turner }
122c120c564SAndrew Turner
123c120c564SAndrew Turner return resp;
124c120c564SAndrew Turner }
125c120c564SAndrew Turner
onEOT()126c120c564SAndrew Turner ocsd_datapath_resp_t TrcPktDecodeEtmV3::onEOT()
127c120c564SAndrew Turner {
128c120c564SAndrew Turner ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
129c120c564SAndrew Turner OcsdTraceElement *pElem = 0;
130c120c564SAndrew Turner try {
131c120c564SAndrew Turner pElem = GetNextOpElem(resp);
132c120c564SAndrew Turner pElem->setType(OCSD_GEN_TRC_ELEM_EO_TRACE);
133*b6aadd18SAndrew Turner pElem->setUnSyncEOTReason(UNSYNC_EOT);
134c120c564SAndrew Turner m_outputElemList.commitAllPendElem();
135c120c564SAndrew Turner m_curr_state = SEND_PKTS;
136c120c564SAndrew Turner resp = m_outputElemList.sendElements();
137c120c564SAndrew Turner if(OCSD_DATA_RESP_IS_CONT(resp))
138c120c564SAndrew Turner m_curr_state = DECODE_PKTS;
139c120c564SAndrew Turner }
140c120c564SAndrew Turner catch(ocsdError &err)
141c120c564SAndrew Turner {
142c120c564SAndrew Turner LogError(err);
143c120c564SAndrew Turner resetDecoder(); // mark decoder as unsynced - dump any current state.
144c120c564SAndrew Turner }
145c120c564SAndrew Turner return resp;
146c120c564SAndrew Turner }
147c120c564SAndrew Turner
onReset()148c120c564SAndrew Turner ocsd_datapath_resp_t TrcPktDecodeEtmV3::onReset()
149c120c564SAndrew Turner {
150c120c564SAndrew Turner ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
151*b6aadd18SAndrew Turner m_unsync_info = UNSYNC_RESET_DECODER;
152c120c564SAndrew Turner resetDecoder();
153c120c564SAndrew Turner return resp;
154c120c564SAndrew Turner }
155c120c564SAndrew Turner
onFlush()156c120c564SAndrew Turner ocsd_datapath_resp_t TrcPktDecodeEtmV3::onFlush()
157c120c564SAndrew Turner {
158c120c564SAndrew Turner ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
159c120c564SAndrew Turner if(m_curr_state == SEND_PKTS)
160c120c564SAndrew Turner {
161c120c564SAndrew Turner resp = m_outputElemList.sendElements();
162c120c564SAndrew Turner if(OCSD_DATA_RESP_IS_CONT(resp))
163c120c564SAndrew Turner m_curr_state = m_bWaitISync ? WAIT_ISYNC : DECODE_PKTS;
164c120c564SAndrew Turner }
165c120c564SAndrew Turner return resp;
166c120c564SAndrew Turner }
167c120c564SAndrew Turner
onProtocolConfig()168c120c564SAndrew Turner ocsd_err_t TrcPktDecodeEtmV3::onProtocolConfig()
169c120c564SAndrew Turner {
170c120c564SAndrew Turner ocsd_err_t err = OCSD_OK;
171c120c564SAndrew Turner if(m_config)
172c120c564SAndrew Turner {
173c120c564SAndrew Turner // set some static config elements
174c120c564SAndrew Turner m_CSID = m_config->getTraceID();
175c120c564SAndrew Turner
176c120c564SAndrew Turner // check config compatible with current decoder support level.
177c120c564SAndrew Turner // at present no data trace;
178c120c564SAndrew Turner if(m_config->GetTraceMode() != EtmV3Config::TM_INSTR_ONLY)
179c120c564SAndrew Turner {
180c120c564SAndrew Turner err = OCSD_ERR_HW_CFG_UNSUPP;
181c120c564SAndrew Turner LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,"ETMv3 trace decoder : data trace decode not yet supported"));
182c120c564SAndrew Turner }
183c120c564SAndrew Turner
184c120c564SAndrew Turner // need to set up core profile info in follower
185c120c564SAndrew Turner ocsd_arch_profile_t arch_profile;
186c120c564SAndrew Turner arch_profile.arch = m_config->getArchVersion();
187c120c564SAndrew Turner arch_profile.profile = m_config->getCoreProfile();
188c120c564SAndrew Turner m_code_follower.setArchProfile(arch_profile);
189c120c564SAndrew Turner m_code_follower.setMemSpaceCSID(m_CSID);
190c120c564SAndrew Turner m_outputElemList.initCSID(m_CSID);
191c120c564SAndrew Turner }
192c120c564SAndrew Turner else
193c120c564SAndrew Turner err = OCSD_ERR_NOT_INIT;
194c120c564SAndrew Turner return err;
195c120c564SAndrew Turner }
196c120c564SAndrew Turner
197c120c564SAndrew Turner /* local decode methods */
198c120c564SAndrew Turner
199c120c564SAndrew Turner // initialise on creation
initDecoder()200c120c564SAndrew Turner void TrcPktDecodeEtmV3::initDecoder()
201c120c564SAndrew Turner {
202c120c564SAndrew Turner m_CSID = 0;
203c120c564SAndrew Turner resetDecoder();
204*b6aadd18SAndrew Turner m_unsync_info = UNSYNC_INIT_DECODER;
205c120c564SAndrew Turner m_code_follower.initInterfaces(getMemoryAccessAttachPt(),getInstrDecodeAttachPt());
206c120c564SAndrew Turner m_outputElemList.initSendIf(getTraceElemOutAttachPt());
207c120c564SAndrew Turner }
208c120c564SAndrew Turner
209c120c564SAndrew Turner // reset for first use / re-use.
resetDecoder()210c120c564SAndrew Turner void TrcPktDecodeEtmV3::resetDecoder()
211c120c564SAndrew Turner {
212c120c564SAndrew Turner m_curr_state = NO_SYNC; // mark as not synced
213c120c564SAndrew Turner m_bNeedAddr = true;
214c120c564SAndrew Turner m_bSentUnknown = false;
215c120c564SAndrew Turner m_bWaitISync = false;
216c120c564SAndrew Turner m_outputElemList.reset();
217c120c564SAndrew Turner }
218c120c564SAndrew Turner
GetNextOpElem(ocsd_datapath_resp_t & resp)219c120c564SAndrew Turner OcsdTraceElement *TrcPktDecodeEtmV3::GetNextOpElem(ocsd_datapath_resp_t &resp)
220c120c564SAndrew Turner {
221c120c564SAndrew Turner OcsdTraceElement *pElem = m_outputElemList.getNextElem(m_index_curr_pkt);
222c120c564SAndrew Turner if(pElem == 0)
223c120c564SAndrew Turner {
224c120c564SAndrew Turner resp = OCSD_RESP_FATAL_NOT_INIT;
225c120c564SAndrew Turner throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_MEM,m_index_curr_pkt,m_CSID,"Memory Allocation Error - fatal");
226c120c564SAndrew Turner }
227c120c564SAndrew Turner return pElem;
228c120c564SAndrew Turner }
229c120c564SAndrew Turner
preISyncValid(ocsd_etmv3_pkt_type pkt_type)230c120c564SAndrew Turner bool TrcPktDecodeEtmV3::preISyncValid(ocsd_etmv3_pkt_type pkt_type)
231c120c564SAndrew Turner {
232c120c564SAndrew Turner bool bValid = false;
233c120c564SAndrew Turner // its a timestamp
234c120c564SAndrew Turner if((pkt_type == ETM3_PKT_TIMESTAMP) ||
235c120c564SAndrew Turner // or we are cycleacc and its a packet that can have CC in it
236c120c564SAndrew Turner (m_config->isCycleAcc() && ((pkt_type == ETM3_PKT_CYCLE_COUNT) || (pkt_type == ETM3_PKT_P_HDR)))
237c120c564SAndrew Turner )
238c120c564SAndrew Turner bValid = true;
239c120c564SAndrew Turner return bValid;
240c120c564SAndrew Turner }
241c120c564SAndrew Turner
242c120c564SAndrew Turner // simple packet transforms handled here, more complex processing passed on to specific routines.
decodePacket(bool & pktDone)243c120c564SAndrew Turner ocsd_datapath_resp_t TrcPktDecodeEtmV3::decodePacket(bool &pktDone)
244c120c564SAndrew Turner {
245c120c564SAndrew Turner ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
246c120c564SAndrew Turner bool bISyncHasCC = false;
247c120c564SAndrew Turner OcsdTraceElement *pElem = 0;
248c120c564SAndrew Turner pktDone = false;
249c120c564SAndrew Turner
250c120c564SAndrew Turner // there may be pended packets that can now be committed.
251c120c564SAndrew Turner // only the branch address with exception and cancel element can cancel
252c120c564SAndrew Turner // if not one of those, commit immediately, otherwise defer to branch address handler.
253c120c564SAndrew Turner if(m_curr_packet_in->getType() != ETM3_PKT_BRANCH_ADDRESS)
254c120c564SAndrew Turner m_outputElemList.commitAllPendElem();
255c120c564SAndrew Turner
256c120c564SAndrew Turner try {
257c120c564SAndrew Turner
258c120c564SAndrew Turner switch(m_curr_packet_in->getType())
259c120c564SAndrew Turner {
260c120c564SAndrew Turner
261c120c564SAndrew Turner case ETM3_PKT_NOTSYNC:
262c120c564SAndrew Turner // mark as not synced - must have lost sync in the packet processor somehow
263c120c564SAndrew Turner throw ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ,m_index_curr_pkt,m_CSID,"Trace Packet Synchronisation Lost");
264c120c564SAndrew Turner break;
265c120c564SAndrew Turner
266c120c564SAndrew Turner // no action for these packets - ignore and continue
267c120c564SAndrew Turner case ETM3_PKT_INCOMPLETE_EOT:
268c120c564SAndrew Turner case ETM3_PKT_A_SYNC:
269c120c564SAndrew Turner case ETM3_PKT_IGNORE:
270c120c564SAndrew Turner break;
271c120c564SAndrew Turner
272c120c564SAndrew Turner // markers for valid packets
273c120c564SAndrew Turner case ETM3_PKT_CYCLE_COUNT:
274c120c564SAndrew Turner pElem = GetNextOpElem(resp);
275c120c564SAndrew Turner pElem->setType(OCSD_GEN_TRC_ELEM_CYCLE_COUNT);
276c120c564SAndrew Turner pElem->setCycleCount(m_curr_packet_in->getCycleCount());
277c120c564SAndrew Turner break;
278c120c564SAndrew Turner
279c120c564SAndrew Turner case ETM3_PKT_TRIGGER:
280c120c564SAndrew Turner pElem = GetNextOpElem(resp);
281c120c564SAndrew Turner pElem->setType(OCSD_GEN_TRC_ELEM_EVENT);
282c120c564SAndrew Turner pElem->setEvent(EVENT_TRIGGER,0);
283c120c564SAndrew Turner break;
284c120c564SAndrew Turner
285c120c564SAndrew Turner case ETM3_PKT_BRANCH_ADDRESS:
286c120c564SAndrew Turner resp = processBranchAddr();
287c120c564SAndrew Turner break;
288c120c564SAndrew Turner
289c120c564SAndrew Turner case ETM3_PKT_I_SYNC_CYCLE:
290c120c564SAndrew Turner bISyncHasCC = true;
291c120c564SAndrew Turner case ETM3_PKT_I_SYNC:
292c120c564SAndrew Turner resp = processISync(bISyncHasCC);
293c120c564SAndrew Turner break;
294c120c564SAndrew Turner
295c120c564SAndrew Turner case ETM3_PKT_P_HDR:
296c120c564SAndrew Turner resp = processPHdr();
297c120c564SAndrew Turner break;
298c120c564SAndrew Turner
299c120c564SAndrew Turner case ETM3_PKT_CONTEXT_ID:
300c120c564SAndrew Turner pElem = GetNextOpElem(resp);
301c120c564SAndrew Turner pElem->setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT);
302c120c564SAndrew Turner m_PeContext.setCtxtID(m_curr_packet_in->getCtxtID());
303c120c564SAndrew Turner pElem->setContext(m_PeContext);
304c120c564SAndrew Turner break;
305c120c564SAndrew Turner
306c120c564SAndrew Turner case ETM3_PKT_VMID:
307c120c564SAndrew Turner pElem = GetNextOpElem(resp);
308c120c564SAndrew Turner pElem->setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT);
309c120c564SAndrew Turner m_PeContext.setVMID(m_curr_packet_in->getVMID());
310c120c564SAndrew Turner pElem->setContext(m_PeContext);
311c120c564SAndrew Turner break;
312c120c564SAndrew Turner
313c120c564SAndrew Turner case ETM3_PKT_EXCEPTION_ENTRY:
314c120c564SAndrew Turner pElem = GetNextOpElem(resp);
315c120c564SAndrew Turner pElem->setType(OCSD_GEN_TRC_ELEM_EXCEPTION);
316c120c564SAndrew Turner pElem->setExcepMarker(); // exception entries are always v7M data markers in ETMv3 trace.
317c120c564SAndrew Turner break;
318c120c564SAndrew Turner
319c120c564SAndrew Turner case ETM3_PKT_EXCEPTION_EXIT:
320c120c564SAndrew Turner pElem = GetNextOpElem(resp);
321c120c564SAndrew Turner pElem->setType(OCSD_GEN_TRC_ELEM_EXCEPTION_RET);
322c120c564SAndrew Turner pendExceptionReturn();
323c120c564SAndrew Turner break;
324c120c564SAndrew Turner
325c120c564SAndrew Turner case ETM3_PKT_TIMESTAMP:
326c120c564SAndrew Turner pElem = GetNextOpElem(resp);
327c120c564SAndrew Turner pElem->setType(OCSD_GEN_TRC_ELEM_TIMESTAMP);
328c120c564SAndrew Turner pElem->setTS(m_curr_packet_in->getTS());
329c120c564SAndrew Turner break;
330c120c564SAndrew Turner
331c120c564SAndrew Turner // data packets - data trace not supported at present
332c120c564SAndrew Turner case ETM3_PKT_STORE_FAIL:
333c120c564SAndrew Turner case ETM3_PKT_OOO_DATA:
334c120c564SAndrew Turner case ETM3_PKT_OOO_ADDR_PLC:
335c120c564SAndrew Turner case ETM3_PKT_NORM_DATA:
336c120c564SAndrew Turner case ETM3_PKT_DATA_SUPPRESSED:
337c120c564SAndrew Turner case ETM3_PKT_VAL_NOT_TRACED:
338c120c564SAndrew Turner case ETM3_PKT_BAD_TRACEMODE:
339c120c564SAndrew Turner resp = OCSD_RESP_FATAL_INVALID_DATA;
340c120c564SAndrew Turner 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.");
341c120c564SAndrew Turner break;
342c120c564SAndrew Turner
343c120c564SAndrew Turner // packet errors
344c120c564SAndrew Turner case ETM3_PKT_BAD_SEQUENCE:
345c120c564SAndrew Turner resp = OCSD_RESP_FATAL_INVALID_DATA;
346c120c564SAndrew Turner throw ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ,m_index_curr_pkt,m_CSID,"Bad Packet sequence.");
347c120c564SAndrew Turner break;
348c120c564SAndrew Turner
349c120c564SAndrew Turner default:
350c120c564SAndrew Turner case ETM3_PKT_RESERVED:
351c120c564SAndrew Turner resp = OCSD_RESP_FATAL_INVALID_DATA;
352c120c564SAndrew Turner throw ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ,m_index_curr_pkt,m_CSID,"Reserved or unknown packet ID.");
353c120c564SAndrew Turner break;
354c120c564SAndrew Turner }
355c120c564SAndrew Turner m_curr_state = m_outputElemList.elemToSend() ? SEND_PKTS : DECODE_PKTS;
356c120c564SAndrew Turner pktDone = !m_outputElemList.elemToSend();
357c120c564SAndrew Turner }
358c120c564SAndrew Turner catch(ocsdError &err)
359c120c564SAndrew Turner {
360c120c564SAndrew Turner LogError(err);
361*b6aadd18SAndrew Turner m_unsync_info = UNSYNC_BAD_PACKET;
362c120c564SAndrew Turner resetDecoder(); // mark decoder as unsynced - dump any current state.
363c120c564SAndrew Turner pktDone = true;
364c120c564SAndrew Turner }
365c120c564SAndrew Turner catch(...)
366c120c564SAndrew Turner {
367c120c564SAndrew Turner LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_FAIL,m_index_curr_pkt,m_CSID,"Bad Packet sequence."));
368c120c564SAndrew Turner resp = OCSD_RESP_FATAL_SYS_ERR;
369*b6aadd18SAndrew Turner m_unsync_info = UNSYNC_BAD_PACKET;
370c120c564SAndrew Turner resetDecoder(); // mark decoder as unsynced - dump any current state.
371c120c564SAndrew Turner pktDone = true;
372c120c564SAndrew Turner }
373c120c564SAndrew Turner return resp;
374c120c564SAndrew Turner }
375c120c564SAndrew Turner
sendUnsyncPacket()376c120c564SAndrew Turner ocsd_datapath_resp_t TrcPktDecodeEtmV3::sendUnsyncPacket()
377c120c564SAndrew Turner {
378c120c564SAndrew Turner ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
379c120c564SAndrew Turner OcsdTraceElement *pElem = 0;
380c120c564SAndrew Turner try {
381c120c564SAndrew Turner pElem = GetNextOpElem(resp);
382c120c564SAndrew Turner pElem->setType(OCSD_GEN_TRC_ELEM_NO_SYNC);
383*b6aadd18SAndrew Turner pElem->setUnSyncEOTReason(m_unsync_info);
384c120c564SAndrew Turner resp = m_outputElemList.sendElements();
385c120c564SAndrew Turner }
386c120c564SAndrew Turner catch(ocsdError &err)
387c120c564SAndrew Turner {
388c120c564SAndrew Turner LogError(err);
389*b6aadd18SAndrew Turner m_unsync_info = UNSYNC_BAD_PACKET;
390c120c564SAndrew Turner resetDecoder(); // mark decoder as unsynced - dump any current state.
391c120c564SAndrew Turner }
392c120c564SAndrew Turner return resp;
393c120c564SAndrew Turner }
394c120c564SAndrew Turner
setNeedAddr(bool bNeedAddr)395c120c564SAndrew Turner void TrcPktDecodeEtmV3::setNeedAddr(bool bNeedAddr)
396c120c564SAndrew Turner {
397c120c564SAndrew Turner m_bNeedAddr = bNeedAddr;
398c120c564SAndrew Turner m_bSentUnknown = false;
399c120c564SAndrew Turner }
400c120c564SAndrew Turner
processISync(const bool withCC,const bool firstSync)401c120c564SAndrew Turner ocsd_datapath_resp_t TrcPktDecodeEtmV3::processISync(const bool withCC, const bool firstSync /* = false */)
402c120c564SAndrew Turner {
403c120c564SAndrew Turner // map ISync reason to generic reason codes.
404c120c564SAndrew Turner static trace_on_reason_t on_map[] = { TRACE_ON_NORMAL, TRACE_ON_NORMAL,
405c120c564SAndrew Turner TRACE_ON_OVERFLOW, TRACE_ON_EX_DEBUG };
406c120c564SAndrew Turner
407c120c564SAndrew Turner ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
408c120c564SAndrew Turner bool ctxtUpdate = m_curr_packet_in->isCtxtUpdated();
409c120c564SAndrew Turner OcsdTraceElement *pElem = 0;
410c120c564SAndrew Turner
411c120c564SAndrew Turner try {
412c120c564SAndrew Turner
413c120c564SAndrew Turner pElem = GetNextOpElem(resp);
414c120c564SAndrew Turner
415c120c564SAndrew Turner if(firstSync || (m_curr_packet_in->getISyncReason() != iSync_Periodic))
416c120c564SAndrew Turner {
417c120c564SAndrew Turner pElem->setType(OCSD_GEN_TRC_ELEM_TRACE_ON);
418c120c564SAndrew Turner pElem->setTraceOnReason(on_map[(int)m_curr_packet_in->getISyncReason()]);
419c120c564SAndrew Turner pElem = GetNextOpElem(resp);
420c120c564SAndrew Turner }
421c120c564SAndrew Turner
422c120c564SAndrew Turner // look for context changes....
423c120c564SAndrew Turner if(ctxtUpdate || firstSync)
424c120c564SAndrew Turner {
425c120c564SAndrew Turner // if not first time out, read existing context in output element,
426c120c564SAndrew Turner // otherwise we are setting it new.
427c120c564SAndrew Turner if(firstSync)
428c120c564SAndrew Turner m_PeContext.resetCtxt();
429c120c564SAndrew Turner
430c120c564SAndrew Turner if(m_curr_packet_in->isCtxtIDUpdated())
431c120c564SAndrew Turner m_PeContext.setCtxtID(m_curr_packet_in->getCtxtID());
432c120c564SAndrew Turner if(m_curr_packet_in->isVMIDUpdated())
433c120c564SAndrew Turner m_PeContext.setVMID(m_curr_packet_in->getVMID());
434c120c564SAndrew Turner if(m_curr_packet_in->isCtxtFlagsUpdated())
435c120c564SAndrew Turner {
436c120c564SAndrew Turner m_PeContext.setEL(m_curr_packet_in->isHyp() ? ocsd_EL2 : ocsd_EL_unknown);
437c120c564SAndrew Turner m_PeContext.setSecLevel(m_curr_packet_in->isNS() ? ocsd_sec_nonsecure : ocsd_sec_secure);
438c120c564SAndrew Turner }
439c120c564SAndrew Turner
440c120c564SAndrew Turner // prepare the context packet
441c120c564SAndrew Turner pElem->setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT);
442c120c564SAndrew Turner pElem->setContext(m_PeContext);
443c120c564SAndrew Turner pElem->setISA(m_curr_packet_in->ISA());
444c120c564SAndrew Turner
445c120c564SAndrew Turner // with cycle count...
446c120c564SAndrew Turner if(m_curr_packet_in->getISyncHasCC())
447c120c564SAndrew Turner pElem->setCycleCount(m_curr_packet_in->getCycleCount());
448c120c564SAndrew Turner
449c120c564SAndrew Turner }
450c120c564SAndrew Turner
451c120c564SAndrew Turner // set ISync address - if it is a valid I address
452c120c564SAndrew Turner if(!m_curr_packet_in->getISyncNoAddr())
453c120c564SAndrew Turner {
454c120c564SAndrew Turner if(m_curr_packet_in->getISyncIsLSiPAddr())
455c120c564SAndrew Turner {
456c120c564SAndrew Turner // TBD: handle extra data processing instruction for data trace
457c120c564SAndrew Turner // need to output E atom relating to the data instruction
458c120c564SAndrew Turner // rare - on start-up case.
459c120c564SAndrew Turner
460c120c564SAndrew Turner // main instruction address saved in data address for this packet type.
461c120c564SAndrew Turner m_IAddr = m_curr_packet_in->getDataAddr();
462c120c564SAndrew Turner }
463c120c564SAndrew Turner else
464c120c564SAndrew Turner {
465c120c564SAndrew Turner m_IAddr = m_curr_packet_in->getAddr();
466c120c564SAndrew Turner }
467c120c564SAndrew Turner setNeedAddr(false); // ready to process atoms.
468c120c564SAndrew Turner }
469c120c564SAndrew Turner m_curr_state = m_outputElemList.elemToSend() ? SEND_PKTS : DECODE_PKTS;
470c120c564SAndrew Turner }
471c120c564SAndrew Turner catch(ocsdError &err)
472c120c564SAndrew Turner {
473c120c564SAndrew Turner LogError(err);
474*b6aadd18SAndrew Turner m_unsync_info = UNSYNC_BAD_PACKET;
475c120c564SAndrew Turner resetDecoder(); // mark decoder as unsynced - dump any current state.
476c120c564SAndrew Turner }
477c120c564SAndrew Turner return resp;
478c120c564SAndrew Turner }
479c120c564SAndrew Turner
processBranchAddr()480c120c564SAndrew Turner ocsd_datapath_resp_t TrcPktDecodeEtmV3::processBranchAddr()
481c120c564SAndrew Turner {
482c120c564SAndrew Turner ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
483c120c564SAndrew Turner OcsdTraceElement *pElem = 0;
484c120c564SAndrew Turner bool bUpdatePEContext = false;
485c120c564SAndrew Turner
486c120c564SAndrew Turner // might need to cancel something ... if the last output was an instruction range or excep return
487c120c564SAndrew Turner if(m_curr_packet_in->isExcepCancel())
488c120c564SAndrew Turner m_outputElemList.cancelPendElem();
489c120c564SAndrew Turner else
490c120c564SAndrew Turner m_outputElemList.commitAllPendElem(); // otherwise commit any pending elements.
491c120c564SAndrew Turner
492c120c564SAndrew Turner // record the address
493c120c564SAndrew Turner m_IAddr = m_curr_packet_in->getAddr();
494c120c564SAndrew Turner setNeedAddr(false); // no longer need an address.
495c120c564SAndrew Turner
496c120c564SAndrew Turner // exception packet - may need additional output
497c120c564SAndrew Turner if(m_curr_packet_in->isExcepPkt())
498c120c564SAndrew Turner {
499c120c564SAndrew Turner // exeception packet may have exception, context change, or both.
500c120c564SAndrew Turner // check for context change
501c120c564SAndrew Turner if(m_curr_packet_in->isCtxtUpdated())
502c120c564SAndrew Turner {
503c120c564SAndrew Turner
504c120c564SAndrew Turner ocsd_sec_level sec = m_curr_packet_in->isNS() ? ocsd_sec_nonsecure : ocsd_sec_secure;
505c120c564SAndrew Turner if(sec != m_PeContext.getSecLevel())
506c120c564SAndrew Turner {
507c120c564SAndrew Turner m_PeContext.setSecLevel(sec);
508c120c564SAndrew Turner bUpdatePEContext = true;
509c120c564SAndrew Turner }
510c120c564SAndrew Turner ocsd_ex_level pkt_el = m_curr_packet_in->isHyp() ? ocsd_EL2 : ocsd_EL_unknown;
511c120c564SAndrew Turner if(pkt_el != m_PeContext.getEL())
512c120c564SAndrew Turner {
513c120c564SAndrew Turner m_PeContext.setEL(pkt_el);
514c120c564SAndrew Turner bUpdatePEContext = true;
515c120c564SAndrew Turner }
516c120c564SAndrew Turner }
517c120c564SAndrew Turner
518c120c564SAndrew Turner // now decide if we need to send any packets out.
519c120c564SAndrew Turner try {
520c120c564SAndrew Turner
521c120c564SAndrew Turner if(bUpdatePEContext)
522c120c564SAndrew Turner {
523c120c564SAndrew Turner pElem = GetNextOpElem(resp);
524c120c564SAndrew Turner pElem->setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT);
525c120c564SAndrew Turner pElem->setContext(m_PeContext);
526c120c564SAndrew Turner }
527c120c564SAndrew Turner
528c120c564SAndrew Turner // check for exception
529c120c564SAndrew Turner if(m_curr_packet_in->excepNum() != 0)
530c120c564SAndrew Turner {
531c120c564SAndrew Turner pElem = GetNextOpElem(resp);
532c120c564SAndrew Turner pElem->setType(OCSD_GEN_TRC_ELEM_EXCEPTION);
533c120c564SAndrew Turner pElem->setExceptionNum(m_curr_packet_in->excepNum());
534c120c564SAndrew Turner }
535c120c564SAndrew Turner
536c120c564SAndrew Turner // finally - do we have anything to send yet?
537c120c564SAndrew Turner m_curr_state = m_outputElemList.elemToSend() ? SEND_PKTS : DECODE_PKTS;
538c120c564SAndrew Turner }
539c120c564SAndrew Turner catch(ocsdError &err)
540c120c564SAndrew Turner {
541c120c564SAndrew Turner LogError(err);
542*b6aadd18SAndrew Turner m_unsync_info = UNSYNC_BAD_PACKET;
543c120c564SAndrew Turner resetDecoder(); // mark decoder as unsynced - dump any current state.
544c120c564SAndrew Turner }
545c120c564SAndrew Turner }
546c120c564SAndrew Turner return resp;
547c120c564SAndrew Turner }
548c120c564SAndrew Turner
549c120c564SAndrew Turner
processPHdr()550c120c564SAndrew Turner ocsd_datapath_resp_t TrcPktDecodeEtmV3::processPHdr()
551c120c564SAndrew Turner {
552c120c564SAndrew Turner ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
553c120c564SAndrew Turner OcsdTraceElement *pElem = 0;
554c120c564SAndrew Turner ocsd_isa isa;
555c120c564SAndrew Turner Etmv3Atoms atoms(m_config->isCycleAcc());
556c120c564SAndrew Turner
557c120c564SAndrew Turner atoms.initAtomPkt(m_curr_packet_in,m_index_curr_pkt);
558c120c564SAndrew Turner isa = m_curr_packet_in->ISA();
559c120c564SAndrew Turner m_code_follower.setMemSpaceAccess((m_PeContext.getSecLevel() == ocsd_sec_secure) ? OCSD_MEM_SPACE_S : OCSD_MEM_SPACE_N);
560c120c564SAndrew Turner
561c120c564SAndrew Turner try
562c120c564SAndrew Turner {
563c120c564SAndrew Turner do
564c120c564SAndrew Turner {
565c120c564SAndrew Turner // if we do not have a valid address then send any cycle count elements
566c120c564SAndrew Turner // and stop processing
567c120c564SAndrew Turner if(m_bNeedAddr)
568c120c564SAndrew Turner {
569c120c564SAndrew Turner // output unknown address packet or a cycle count packet
570c120c564SAndrew Turner if(!m_bSentUnknown || m_config->isCycleAcc())
571c120c564SAndrew Turner {
572c120c564SAndrew Turner pElem = GetNextOpElem(resp);
573c120c564SAndrew Turner if(m_bSentUnknown || !atoms.numAtoms())
574c120c564SAndrew Turner pElem->setType(OCSD_GEN_TRC_ELEM_CYCLE_COUNT);
575c120c564SAndrew Turner else
576c120c564SAndrew Turner pElem->setType(OCSD_GEN_TRC_ELEM_ADDR_UNKNOWN);
577c120c564SAndrew Turner if(m_config->isCycleAcc())
578c120c564SAndrew Turner pElem->setCycleCount(atoms.getRemainCC());
579c120c564SAndrew Turner m_bSentUnknown = true;
580c120c564SAndrew Turner }
581c120c564SAndrew Turner atoms.clearAll(); // skip remaining atoms
582c120c564SAndrew Turner }
583c120c564SAndrew Turner else // have an address, can process atoms
584c120c564SAndrew Turner {
585c120c564SAndrew Turner pElem = GetNextOpElem(resp);
586c120c564SAndrew Turner pElem->setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE);
587c120c564SAndrew Turner
588c120c564SAndrew Turner // cycle accurate may have a cycle count to use
589c120c564SAndrew Turner if(m_config->isCycleAcc())
590c120c564SAndrew Turner {
591c120c564SAndrew Turner // note: it is possible to have a CC only atom packet.
592c120c564SAndrew Turner if(!atoms.numAtoms()) // override type if CC only
593c120c564SAndrew Turner pElem->setType(OCSD_GEN_TRC_ELEM_CYCLE_COUNT);
594c120c564SAndrew Turner // set cycle count
595c120c564SAndrew Turner pElem->setCycleCount(atoms.getAtomCC());
596c120c564SAndrew Turner }
597c120c564SAndrew Turner
598c120c564SAndrew Turner // now process the atom
599c120c564SAndrew Turner if(atoms.numAtoms())
600c120c564SAndrew Turner {
601c120c564SAndrew Turner m_code_follower.setISA(isa);
602c120c564SAndrew Turner m_code_follower.followSingleAtom(m_IAddr,atoms.getCurrAtomVal());
603c120c564SAndrew Turner
604c120c564SAndrew Turner // valid code range
605c120c564SAndrew Turner if(m_code_follower.hasRange())
606c120c564SAndrew Turner {
607c120c564SAndrew Turner pElem->setAddrRange(m_IAddr,m_code_follower.getRangeEn());
608c120c564SAndrew Turner pElem->setLastInstrInfo(atoms.getCurrAtomVal() == ATOM_E,
609c120c564SAndrew Turner m_code_follower.getInstrType(),
610c120c564SAndrew Turner m_code_follower.getInstrSubType(),m_code_follower.getInstrSize());
611c120c564SAndrew Turner pElem->setLastInstrCond(m_code_follower.isCondInstr());
612c120c564SAndrew Turner pElem->setISA(isa);
613c120c564SAndrew Turner if(m_code_follower.hasNextAddr())
614c120c564SAndrew Turner m_IAddr = m_code_follower.getNextAddr();
615c120c564SAndrew Turner else
616c120c564SAndrew Turner setNeedAddr(true);
617c120c564SAndrew Turner }
618c120c564SAndrew Turner
619c120c564SAndrew Turner // next address has new ISA?
620c120c564SAndrew Turner if(m_code_follower.ISAChanged())
621c120c564SAndrew Turner isa = m_code_follower.nextISA();
622c120c564SAndrew Turner
623c120c564SAndrew Turner // there is a nacc
624c120c564SAndrew Turner if(m_code_follower.isNacc())
625c120c564SAndrew Turner {
626c120c564SAndrew Turner if(m_code_follower.hasRange())
627c120c564SAndrew Turner {
628c120c564SAndrew Turner pElem = GetNextOpElem(resp);
629c120c564SAndrew Turner pElem->setType(OCSD_GEN_TRC_ELEM_ADDR_NACC);
630c120c564SAndrew Turner }
631c120c564SAndrew Turner else
632c120c564SAndrew Turner pElem->updateType(OCSD_GEN_TRC_ELEM_ADDR_NACC);
633c120c564SAndrew Turner pElem->setAddrStart(m_code_follower.getNaccAddr());
634c120c564SAndrew Turner setNeedAddr(true);
635c120c564SAndrew Turner m_code_follower.clearNacc(); // we have generated some code for the nacc.
636c120c564SAndrew Turner }
637c120c564SAndrew Turner }
638c120c564SAndrew Turner
639c120c564SAndrew Turner atoms.clearAtom(); // next atom
640c120c564SAndrew Turner }
641c120c564SAndrew Turner }
642c120c564SAndrew Turner while(atoms.numAtoms());
643c120c564SAndrew Turner
644c120c564SAndrew Turner // is tha last element an atom?
645c120c564SAndrew Turner int numElem = m_outputElemList.getNumElem();
646c120c564SAndrew Turner if(numElem >= 1)
647c120c564SAndrew Turner {
648c120c564SAndrew Turner // if the last thing is an instruction range, pend it - could be cancelled later.
649c120c564SAndrew Turner if(m_outputElemList.getElemType(numElem-1) == OCSD_GEN_TRC_ELEM_INSTR_RANGE)
650c120c564SAndrew Turner m_outputElemList.pendLastNElem(1);
651c120c564SAndrew Turner }
652c120c564SAndrew Turner
653c120c564SAndrew Turner // finally - do we have anything to send yet?
654c120c564SAndrew Turner m_curr_state = m_outputElemList.elemToSend() ? SEND_PKTS : DECODE_PKTS;
655c120c564SAndrew Turner }
656c120c564SAndrew Turner catch(ocsdError &err)
657c120c564SAndrew Turner {
658c120c564SAndrew Turner LogError(err);
659*b6aadd18SAndrew Turner m_unsync_info = UNSYNC_BAD_PACKET;
660c120c564SAndrew Turner resetDecoder(); // mark decoder as unsynced - dump any current state.
661c120c564SAndrew Turner }
662c120c564SAndrew Turner return resp;
663c120c564SAndrew Turner }
664c120c564SAndrew Turner
665c120c564SAndrew Turner // if v7M -> pend only ERET, if V7A/R pend ERET and prev instr.
pendExceptionReturn()666c120c564SAndrew Turner void TrcPktDecodeEtmV3::pendExceptionReturn()
667c120c564SAndrew Turner {
668c120c564SAndrew Turner int pendElem = 1;
669c120c564SAndrew Turner if(m_config->getCoreProfile() != profile_CortexM)
670c120c564SAndrew Turner {
671c120c564SAndrew Turner int nElem = m_outputElemList.getNumElem();
672c120c564SAndrew Turner if(nElem > 1)
673c120c564SAndrew Turner {
674c120c564SAndrew Turner if(m_outputElemList.getElemType(nElem - 2) == OCSD_GEN_TRC_ELEM_INSTR_RANGE)
675c120c564SAndrew Turner pendElem = 2; // need to pend instr+eret for A/R
676c120c564SAndrew Turner }
677c120c564SAndrew Turner }
678c120c564SAndrew Turner m_outputElemList.pendLastNElem(pendElem);
679c120c564SAndrew Turner }
680c120c564SAndrew Turner
681c120c564SAndrew Turner /* End of File trc_pkt_decode_etmv3.cpp */
682