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 
38 TrcPktDecodeStm::TrcPktDecodeStm()
39     : TrcPktDecodeBase(DCD_NAME)
40 {
41     initDecoder();
42 }
43 
44 TrcPktDecodeStm::TrcPktDecodeStm(int instIDNum)
45     : TrcPktDecodeBase(DCD_NAME, instIDNum)
46 {
47     initDecoder();
48 }
49 
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 */
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             resp = outputTraceElement(m_output_elem);
72             m_curr_state = WAIT_SYNC;
73             break;
74 
75         case WAIT_SYNC:
76             if(m_curr_packet_in->getPktType() == STM_PKT_ASYNC)
77                 m_curr_state = DECODE_PKTS;
78             bPktDone = true;
79             break;
80 
81         case DECODE_PKTS:
82             resp = decodePacket(bPktDone);
83             break;
84         }
85     }
86     return resp;
87 }
88 
89 ocsd_datapath_resp_t TrcPktDecodeStm::onEOT()
90 {
91     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
92     m_output_elem.setType(OCSD_GEN_TRC_ELEM_EO_TRACE);
93     resp = outputTraceElement(m_output_elem);
94     return resp;
95 }
96 
97 ocsd_datapath_resp_t TrcPktDecodeStm::onReset()
98 {
99     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
100     resetDecoder();
101     return resp;
102 }
103 
104 ocsd_datapath_resp_t TrcPktDecodeStm::onFlush()
105 {
106     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
107     // don't currently save unsent packets so nothing to flush
108     return resp;
109 }
110 
111 ocsd_err_t TrcPktDecodeStm::onProtocolConfig()
112 {
113     if(m_config == 0)
114         return OCSD_ERR_NOT_INIT;
115 
116     // static config - copy of CSID for easy reference
117     m_CSID = m_config->getTraceID();
118     return OCSD_OK;
119 }
120 
121 void TrcPktDecodeStm::initDecoder()
122 {
123     m_payload_buffer = 0;
124     m_num_pkt_correlation = 1;  // fixed at single packet payload correlation - add feature later
125     m_CSID = 0;
126 
127     // base decoder state - STM requires no memory and instruction decode.
128     setUsesMemAccess(false);
129     setUsesIDecode(false);
130 
131     resetDecoder();
132 }
133 
134 void TrcPktDecodeStm::resetDecoder()
135 {
136     m_curr_state = NO_SYNC;
137     m_payload_size = 0;
138     m_payload_used = 0;
139     m_payload_odd_nibble = false;
140     m_output_elem.init();
141     m_swt_packet_info.swt_flag_bits = 0;	// zero out everything
142     initPayloadBuffer();
143 }
144 
145 void TrcPktDecodeStm::initPayloadBuffer()
146 {
147     // set up the payload buffer. If we are correlating indentical packets then
148     // need a buffer that is a multiple of 64bit packets.
149     // otherwise a single packet length will do.
150     if(m_payload_buffer)
151         delete [] m_payload_buffer;
152     m_payload_buffer = new (std::nothrow) uint8_t[m_num_pkt_correlation * sizeof(uint64_t)];
153 }
154 
155 ocsd_datapath_resp_t TrcPktDecodeStm::decodePacket(bool &bPktDone)
156 {
157     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
158     bool bSendPacket = false;       // flag to indicate output required.
159 
160     bPktDone = true;    // assume complete unless 2nd pass required.
161     m_output_elem.setType(OCSD_GEN_TRC_ELEM_SWTRACE);
162     clearSWTPerPcktInfo();
163 
164     switch (m_curr_packet_in->getPktType())
165     {
166     case STM_PKT_BAD_SEQUENCE:   /**< Incorrect protocol sequence */
167     case STM_PKT_RESERVED:
168         resp = OCSD_RESP_FATAL_INVALID_DATA;
169     case STM_PKT_NOTSYNC:
170         resetDecoder();
171         break;
172 
173     case STM_PKT_VERSION:    /**< Version packet  - not relevant to generic (versionless) o/p */
174     case STM_PKT_ASYNC:      /**< Alignment synchronisation packet */
175     case STM_PKT_INCOMPLETE_EOT:     /**< Incomplete packet flushed at end of trace. */
176         // no action required.
177         break;
178 
179 /* markers for valid packets*/
180     case STM_PKT_NULL:       /**< Null packet */
181         if(m_curr_packet_in->isTSPkt())
182             bSendPacket = true;     // forward NULL packet if associated timestamp.
183         break;
184 
185     case STM_PKT_FREQ:       /**< Frequency packet */
186         m_swt_packet_info.swt_frequency = 1;
187         updatePayload(bSendPacket);
188         break;
189 
190     case STM_PKT_TRIG:       /**< Trigger event packet. */
191         m_swt_packet_info.swt_trigger_event = 1;
192         updatePayload(bSendPacket);
193         break;
194 
195     case STM_PKT_GERR:       /**< Global error packet - protocol error but unknown which master had error */
196         m_swt_packet_info.swt_master_id = m_curr_packet_in->getMaster();
197         m_swt_packet_info.swt_channel_id = m_curr_packet_in->getChannel();
198         m_swt_packet_info.swt_global_err = 1;
199         m_swt_packet_info.swt_id_valid = 0;
200         updatePayload(bSendPacket);
201         break;
202 
203     case STM_PKT_MERR:       /**< Master error packet - current master detected an error (e.g. dropped trace) */
204         m_swt_packet_info.swt_channel_id = m_curr_packet_in->getChannel();
205         m_swt_packet_info.swt_master_err = 1;
206         updatePayload(bSendPacket);
207         break;
208 
209     case STM_PKT_M8:         /**< Set current master */
210         m_swt_packet_info.swt_master_id = m_curr_packet_in->getMaster();
211         m_swt_packet_info.swt_channel_id = m_curr_packet_in->getChannel();  // forced to 0
212         m_swt_packet_info.swt_id_valid = 1;
213         break;
214 
215     case STM_PKT_C8:         /**< Set lower 8 bits of current channel - packet proc hadnles this */
216     case STM_PKT_C16:        /**< Set current channel */
217         m_swt_packet_info.swt_channel_id = m_curr_packet_in->getChannel();
218         break;
219 
220     case STM_PKT_FLAG:       /**< Flag packet */
221         m_swt_packet_info.swt_marker_packet = 1;
222         bSendPacket = true;  // send 0 payload marker packet./
223         break;
224 
225 
226     case STM_PKT_D4:         /**< 4 bit data payload packet */
227     case STM_PKT_D8:         /**< 8 bit data payload packet */
228     case STM_PKT_D16:        /**< 16 bit data payload packet */
229     case STM_PKT_D32:        /**< 32 bit data payload packet */
230     case STM_PKT_D64:        /**< 64 bit data payload packet */
231         updatePayload(bSendPacket);
232         break;
233 
234     }
235 
236     if(bSendPacket)
237     {
238         if(m_curr_packet_in->isTSPkt())
239         {
240             m_output_elem.setTS(m_curr_packet_in->getTSVal());
241             m_swt_packet_info.swt_has_timestamp = 1;
242         }
243         m_output_elem.setSWTInfo(m_swt_packet_info);
244         resp = outputTraceElement(m_output_elem);
245     }
246 
247     return resp;
248 }
249 
250 void TrcPktDecodeStm::clearSWTPerPcktInfo()
251 {
252     m_swt_packet_info.swt_flag_bits &= (uint32_t)(0x0 | SWT_ID_VALID_MASK);    // clear flags and current payload size (save id valid flag).
253 }
254 
255 void TrcPktDecodeStm::updatePayload(bool &bSendPacket)
256 {
257     // without buffering similar packets - this function is quite simple
258     bSendPacket = true;
259     m_swt_packet_info.swt_payload_num_packets = 1;
260 
261     switch(m_curr_packet_in->getPktType())
262     {
263     case STM_PKT_D4:         /**< 4 bit data payload packet */
264         m_swt_packet_info.swt_payload_pkt_bitsize = 4;
265         *(uint8_t *)m_payload_buffer = m_curr_packet_in->getD4Val();
266         break;
267 
268     case STM_PKT_D8:         /**< 8 bit data payload packet */
269     case STM_PKT_TRIG:       /**< Trigger event packet - 8 bits. */
270     case STM_PKT_GERR:       /**< error packet - 8 bits. */
271     case STM_PKT_MERR:       /**< error packet - 8 bits. */
272         m_swt_packet_info.swt_payload_pkt_bitsize = 8;
273         *(uint8_t *)m_payload_buffer = m_curr_packet_in->getD8Val();
274         break;
275 
276     case STM_PKT_D16:        /**< 16 bit data payload packet */
277         m_swt_packet_info.swt_payload_pkt_bitsize = 16;
278         *(uint16_t *)m_payload_buffer = m_curr_packet_in->getD16Val();
279         break;
280 
281     case STM_PKT_D32:        /**< 32 bit data payload packet */
282     case STM_PKT_FREQ:       /**< Frequency packet */
283         m_swt_packet_info.swt_payload_pkt_bitsize = 32;
284         *(uint32_t *)m_payload_buffer = m_curr_packet_in->getD32Val();
285         break;
286 
287 
288     case STM_PKT_D64:        /**< 64 bit data payload packet */
289         m_swt_packet_info.swt_payload_pkt_bitsize = 64;
290         *(uint64_t *)m_payload_buffer = m_curr_packet_in->getD64Val();
291         break;
292     }
293     m_output_elem.setExtendedDataPtr(m_payload_buffer);
294     if (m_curr_packet_in->isMarkerPkt())
295         m_swt_packet_info.swt_marker_packet = 1;
296 
297 }
298 
299 /* End of File trc_pkt_decode_stm.cpp */
300