xref: /aosp_15_r20/external/OpenCSD/decoder/source/stm/trc_pkt_decode_stm.cpp (revision 02ca8ccacfba7e0df68f3332a95f3180334d6649)
1 /*
2  * \file       trc_pkt_decode_stm.cpp
3  * \brief      OpenCSD : STM packet decoder - output generic SW trace packets.
4  *
5  * \copyright  Copyright (c) 2016, ARM Limited. All Rights Reserved.
6  */
7 
8 /*
9  * Redistribution and use in source and binary forms, with or without modification,
10  * are permitted provided that the following conditions are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  *
19  * 3. Neither the name of the copyright holder nor the names of its contributors
20  * may be used to endorse or promote products derived from this software without
21  * specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26  * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #include "opencsd/stm/trc_pkt_decode_stm.h"
36 #define DCD_NAME "DCD_STM"
37 
TrcPktDecodeStm()38 TrcPktDecodeStm::TrcPktDecodeStm()
39     : TrcPktDecodeBase(DCD_NAME)
40 {
41     initDecoder();
42 }
43 
TrcPktDecodeStm(int instIDNum)44 TrcPktDecodeStm::TrcPktDecodeStm(int instIDNum)
45     : TrcPktDecodeBase(DCD_NAME, instIDNum)
46 {
47     initDecoder();
48 }
49 
~TrcPktDecodeStm()50 TrcPktDecodeStm::~TrcPktDecodeStm()
51 {
52     if(m_payload_buffer)
53         delete [] m_payload_buffer;
54     m_payload_buffer = 0;
55 }
56 
57 /* implementation packet decoding interface */
processPacket()58 ocsd_datapath_resp_t TrcPktDecodeStm::processPacket()
59 {
60     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
61     bool bPktDone = false;
62 
63     m_decode_pass1 = true;
64 
65     while(!bPktDone)
66     {
67         switch(m_curr_state)
68         {
69         case NO_SYNC:
70             m_output_elem.setType(OCSD_GEN_TRC_ELEM_NO_SYNC);
71             m_output_elem.setUnSyncEOTReason(m_unsync_info);
72             resp = outputTraceElement(m_output_elem);
73             m_curr_state = WAIT_SYNC;
74             break;
75 
76         case WAIT_SYNC:
77             if(m_curr_packet_in->getPktType() == STM_PKT_ASYNC)
78                 m_curr_state = DECODE_PKTS;
79             bPktDone = true;
80             break;
81 
82         case DECODE_PKTS:
83             resp = decodePacket(bPktDone);
84             break;
85         }
86     }
87     return resp;
88 }
89 
onEOT()90 ocsd_datapath_resp_t TrcPktDecodeStm::onEOT()
91 {
92     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
93     m_output_elem.setType(OCSD_GEN_TRC_ELEM_EO_TRACE);
94     m_output_elem.setUnSyncEOTReason(UNSYNC_EOT);
95     resp = outputTraceElement(m_output_elem);
96     return resp;
97 }
98 
onReset()99 ocsd_datapath_resp_t TrcPktDecodeStm::onReset()
100 {
101     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
102     m_unsync_info = UNSYNC_RESET_DECODER;
103     resetDecoder();
104     return resp;
105 }
106 
onFlush()107 ocsd_datapath_resp_t TrcPktDecodeStm::onFlush()
108 {
109     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
110     // don't currently save unsent packets so nothing to flush
111     return resp;
112 }
113 
onProtocolConfig()114 ocsd_err_t TrcPktDecodeStm::onProtocolConfig()
115 {
116     if(m_config == 0)
117         return OCSD_ERR_NOT_INIT;
118 
119     // static config - copy of CSID for easy reference
120     m_CSID = m_config->getTraceID();
121     return OCSD_OK;
122 }
123 
initDecoder()124 void TrcPktDecodeStm::initDecoder()
125 {
126     m_payload_buffer = 0;
127     m_num_pkt_correlation = 1;  // fixed at single packet payload correlation - add feature later
128     m_CSID = 0;
129 
130     // base decoder state - STM requires no memory and instruction decode.
131     setUsesMemAccess(false);
132     setUsesIDecode(false);
133     m_unsync_info = UNSYNC_INIT_DECODER;
134     resetDecoder();
135 }
136 
resetDecoder()137 void TrcPktDecodeStm::resetDecoder()
138 {
139     m_curr_state = NO_SYNC;
140     m_payload_size = 0;
141     m_payload_used = 0;
142     m_payload_odd_nibble = false;
143     m_output_elem.init();
144     m_swt_packet_info.swt_flag_bits = 0;	// zero out everything
145     m_swt_packet_info.swt_master_id = 0;
146     m_swt_packet_info.swt_channel_id = 0;
147     initPayloadBuffer();
148 }
149 
initPayloadBuffer()150 void TrcPktDecodeStm::initPayloadBuffer()
151 {
152     // set up the payload buffer. If we are correlating indentical packets then
153     // need a buffer that is a multiple of 64bit packets.
154     // otherwise a single packet length will do.
155     if(m_payload_buffer)
156         delete [] m_payload_buffer;
157     m_payload_buffer = new (std::nothrow) uint8_t[m_num_pkt_correlation * sizeof(uint64_t)];
158 }
159 
decodePacket(bool & bPktDone)160 ocsd_datapath_resp_t TrcPktDecodeStm::decodePacket(bool &bPktDone)
161 {
162     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
163     bool bSendPacket = false;       // flag to indicate output required.
164 
165     bPktDone = true;    // assume complete unless 2nd pass required.
166     m_output_elem.setType(OCSD_GEN_TRC_ELEM_SWTRACE);
167     clearSWTPerPcktInfo();
168 
169     switch (m_curr_packet_in->getPktType())
170     {
171     case STM_PKT_BAD_SEQUENCE:   /**< Incorrect protocol sequence */
172     case STM_PKT_RESERVED:
173         resp = OCSD_RESP_FATAL_INVALID_DATA;
174         m_unsync_info = UNSYNC_BAD_PACKET;
175     case STM_PKT_NOTSYNC:
176         resetDecoder();
177         break;
178 
179     case STM_PKT_VERSION:    /**< Version packet - no output but forces current IDs to 0 */
180         m_swt_packet_info.swt_master_id = m_curr_packet_in->getMaster();
181         m_swt_packet_info.swt_channel_id = m_curr_packet_in->getChannel();
182         break;
183 
184     case STM_PKT_ASYNC:      /**< Alignment synchronisation packet */
185     case STM_PKT_INCOMPLETE_EOT:     /**< Incomplete packet flushed at end of trace. */
186         // no action required.
187         break;
188 
189 /* markers for valid packets*/
190     case STM_PKT_NULL:       /**< Null packet */
191         if(m_curr_packet_in->isTSPkt())
192             bSendPacket = true;     // forward NULL packet if associated timestamp.
193         break;
194 
195     case STM_PKT_FREQ:       /**< Frequency packet */
196         m_swt_packet_info.swt_frequency = 1;
197         updatePayload(bSendPacket);
198         break;
199 
200     case STM_PKT_TRIG:       /**< Trigger event packet. */
201         m_swt_packet_info.swt_trigger_event = 1;
202         updatePayload(bSendPacket);
203         break;
204 
205     case STM_PKT_GERR:       /**< Global error packet - protocol error but unknown which master had error */
206         m_swt_packet_info.swt_master_id = m_curr_packet_in->getMaster();
207         m_swt_packet_info.swt_channel_id = m_curr_packet_in->getChannel();
208         m_swt_packet_info.swt_global_err = 1;
209         m_swt_packet_info.swt_id_valid = 0;
210         updatePayload(bSendPacket);
211         break;
212 
213     case STM_PKT_MERR:       /**< Master error packet - current master detected an error (e.g. dropped trace) */
214         m_swt_packet_info.swt_channel_id = m_curr_packet_in->getChannel();
215         m_swt_packet_info.swt_master_err = 1;
216         updatePayload(bSendPacket);
217         break;
218 
219     case STM_PKT_M8:         /**< Set current master */
220         m_swt_packet_info.swt_master_id = m_curr_packet_in->getMaster();
221         m_swt_packet_info.swt_channel_id = m_curr_packet_in->getChannel();  // forced to 0
222         m_swt_packet_info.swt_id_valid = 1;
223         break;
224 
225     case STM_PKT_C8:         /**< Set lower 8 bits of current channel - packet proc handles this */
226     case STM_PKT_C16:        /**< Set current channel */
227         m_swt_packet_info.swt_channel_id = m_curr_packet_in->getChannel();
228         break;
229 
230     case STM_PKT_FLAG:       /**< Flag packet */
231         m_swt_packet_info.swt_marker_packet = 1;
232         bSendPacket = true;  // send 0 payload marker packet./
233         break;
234 
235 
236     case STM_PKT_D4:         /**< 4 bit data payload packet */
237     case STM_PKT_D8:         /**< 8 bit data payload packet */
238     case STM_PKT_D16:        /**< 16 bit data payload packet */
239     case STM_PKT_D32:        /**< 32 bit data payload packet */
240     case STM_PKT_D64:        /**< 64 bit data payload packet */
241         updatePayload(bSendPacket);
242         break;
243 
244     }
245 
246     if(bSendPacket)
247     {
248         if(m_curr_packet_in->isTSPkt())
249         {
250             m_output_elem.setTS(m_curr_packet_in->getTSVal());
251             m_swt_packet_info.swt_has_timestamp = 1;
252         }
253         m_output_elem.setSWTInfo(m_swt_packet_info);
254         resp = outputTraceElement(m_output_elem);
255     }
256 
257     return resp;
258 }
259 
clearSWTPerPcktInfo()260 void TrcPktDecodeStm::clearSWTPerPcktInfo()
261 {
262     m_swt_packet_info.swt_flag_bits &= (uint32_t)(0x0 | SWT_ID_VALID_MASK);    // clear flags and current payload size (save id valid flag).
263 }
264 
updatePayload(bool & bSendPacket)265 void TrcPktDecodeStm::updatePayload(bool &bSendPacket)
266 {
267     // without buffering similar packets - this function is quite simple
268     bSendPacket = true;
269     m_swt_packet_info.swt_payload_num_packets = 1;
270 
271     switch(m_curr_packet_in->getPktType())
272     {
273     case STM_PKT_D4:         /**< 4 bit data payload packet */
274         m_swt_packet_info.swt_payload_pkt_bitsize = 4;
275         *(uint8_t *)m_payload_buffer = m_curr_packet_in->getD4Val();
276         break;
277 
278     case STM_PKT_D8:         /**< 8 bit data payload packet */
279     case STM_PKT_TRIG:       /**< Trigger event packet - 8 bits. */
280     case STM_PKT_GERR:       /**< error packet - 8 bits. */
281     case STM_PKT_MERR:       /**< error packet - 8 bits. */
282         m_swt_packet_info.swt_payload_pkt_bitsize = 8;
283         *(uint8_t *)m_payload_buffer = m_curr_packet_in->getD8Val();
284         break;
285 
286     case STM_PKT_D16:        /**< 16 bit data payload packet */
287         m_swt_packet_info.swt_payload_pkt_bitsize = 16;
288         *(uint16_t *)m_payload_buffer = m_curr_packet_in->getD16Val();
289         break;
290 
291     case STM_PKT_D32:        /**< 32 bit data payload packet */
292     case STM_PKT_FREQ:       /**< Frequency packet */
293         m_swt_packet_info.swt_payload_pkt_bitsize = 32;
294         *(uint32_t *)m_payload_buffer = m_curr_packet_in->getD32Val();
295         break;
296 
297 
298     case STM_PKT_D64:        /**< 64 bit data payload packet */
299         m_swt_packet_info.swt_payload_pkt_bitsize = 64;
300         *(uint64_t *)m_payload_buffer = m_curr_packet_in->getD64Val();
301         break;
302     }
303     m_output_elem.setExtendedDataPtr(m_payload_buffer);
304     if (m_curr_packet_in->isMarkerPkt())
305         m_swt_packet_info.swt_marker_packet = 1;
306 
307 }
308 
309 /* End of File trc_pkt_decode_stm.cpp */
310