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