1 /*
2  * \file       trc_pkt_proc_stm.h
3  * \brief      OpenCSD : STM packet processing
4  *
5  * \copyright  Copyright (c) 2015, 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 #ifndef ARM_TRC_PKT_PROC_STM_H_INCLUDED
36 #define ARM_TRC_PKT_PROC_STM_H_INCLUDED
37 
38 #include <vector>
39 
40 #include "trc_pkt_types_stm.h"
41 #include "common/trc_pkt_proc_base.h"
42 #include "trc_pkt_elem_stm.h"
43 #include "trc_cmp_cfg_stm.h"
44 
45 /** @addtogroup ocsd_pkt_proc
46 @{*/
47 
48 class TrcPktProcStm : public TrcPktProcBase<StmTrcPacket, ocsd_stm_pkt_type, STMConfig>
49 {
50 public:
51     TrcPktProcStm();
52     TrcPktProcStm(int instIDNum);
53     virtual ~TrcPktProcStm();
54 
55 protected:
56     /* implementation packet processing interface */
57     virtual ocsd_datapath_resp_t processData(  const ocsd_trc_index_t index,
58                                                 const uint32_t dataBlockSize,
59                                                 const uint8_t *pDataBlock,
60                                                 uint32_t *numBytesProcessed);
61     virtual ocsd_datapath_resp_t onEOT();
62     virtual ocsd_datapath_resp_t onReset();
63     virtual ocsd_datapath_resp_t onFlush();
64     virtual ocsd_err_t onProtocolConfig();
65     virtual const bool isBadPacket() const;
66 
67 
68     typedef enum _process_state {
69         WAIT_SYNC,
70         PROC_HDR,
71         PROC_DATA,
72         SEND_PKT
73     } process_state;
74 
75     process_state m_proc_state;
76 
77 private:
78 
79     void initObj();
80     void initProcessorState();
81     void initNextPacket();
82     void waitForSync(const ocsd_trc_index_t blk_st_index);
83 
84     ocsd_datapath_resp_t outputPacket();   //!< send packet on output
85     void sendPacket();                      //!< mark packet for send.
86     void setProcUnsynced();                 //!< set processor state to unsynced
87     void throwBadSequenceError(const char *pszMessage = "");
88     void throwReservedHdrError(const char *pszMessage = "");
89 
90     // packet processing routines
91     // 1 nibble opcodes
92     void stmPktReserved();
93     void stmPktNull();
94     void stmPktM8();
95     void stmPktMERR();
96     void stmPktC8();
97     void stmPktD4();
98     void stmPktD8();
99     void stmPktD16();
100     void stmPktD32();
101     void stmPktD64();
102     void stmPktD4MTS();
103     void stmPktD8MTS();
104     void stmPktD16MTS();
105     void stmPktD32MTS();
106     void stmPktD64MTS();
107     void stmPktFlagTS();
108     void stmPktFExt();
109 
110     // 2 nibble opcodes 0xFn
111     void stmPktReservedFn();
112     void stmPktF0Ext();
113     void stmPktGERR();
114     void stmPktC16();
115     void stmPktD4TS();
116     void stmPktD8TS();
117     void stmPktD16TS();
118     void stmPktD32TS();
119     void stmPktD64TS();
120     void stmPktD4M();
121     void stmPktD8M();
122     void stmPktD16M();
123     void stmPktD32M();
124     void stmPktD64M();
125     void stmPktFlag();
126     void stmPktASync();
127 
128     // 3 nibble opcodes 0xF0n
129     void stmPktReservedF0n();
130     void stmPktVersion();
131     void stmPktNullTS();
132     void stmPktTrigger();
133     void stmPktTriggerTS();
134     void stmPktFreq();
135 
136     void stmExtractTS(); // extract a TS in packets that require it.
137     void stmExtractVal8(uint8_t nibbles_to_val);
138     void stmExtractVal16(uint8_t nibbles_to_val);
139     void stmExtractVal32(uint8_t nibbles_to_val);
140     void stmExtractVal64(uint8_t nibbles_to_val);
141 
142     uint64_t bin_to_gray(uint64_t bin_value);
143     uint64_t gray_to_bin(uint64_t gray_value);
144 	void pktNeedsTS();	// init the TS extraction routines
145 
146     // data processing op function tables
147     void buildOpTables();
148 
149     typedef void (TrcPktProcStm::*PPKTFN)(void);
150     PPKTFN m_pCurrPktFn;    // current active processing function.
151 
152     PPKTFN m_1N_ops[0x10];
153     PPKTFN m_2N_ops[0x10];
154     PPKTFN m_3N_ops[0x10];
155 
156     // read a nibble from the input data - may read a byte and set spare or return spare.
157     // handles setting up packet data block and end of input
158     bool readNibble();
159 
160     const bool dataToProcess() const;       //!< true if data to process, or packet to send
161 
162     void savePacketByte(const uint8_t val);       //!< save data to packet buffer if we need it for monitor.
163 
164     // packet data
165     StmTrcPacket m_curr_packet;     //!< current packet.
166     bool m_bNeedsTS;                //!< packet requires a TS
167     bool m_bIsMarker;
168 
169 
170     bool m_bStreamSync;             //!< packet stream is synced
171 
172     // input data handling
173     uint8_t  m_num_nibbles;                 //!< number of nibbles in the current packet
174     uint8_t  m_nibble;                      //!< current nibble being processed.
175     uint8_t  m_nibble_2nd;                  //!< 2nd unused nibble from a processed byte.
176     bool     m_nibble_2nd_valid;            //!< 2nd nibble is valid;
177     uint8_t  m_num_data_nibbles;            //!< number of nibbles needed to acheive payload.
178 
179     const uint8_t *m_p_data_in;             //!< pointer to input data.
180     uint32_t  m_data_in_size;               //!< amount of data in.
181     uint32_t  m_data_in_used;               //!< amount of data processed.
182     ocsd_trc_index_t m_packet_index;       //!< byte index for start of current packet
183 
184     std::vector<uint8_t> m_packet_data;     //!< current packet data (bytes) - only saved if needed to output to monitor.
185     bool m_bWaitSyncSaveSuppressed;         //!< don't save byte at a time when waitsync
186 
187     // payload data
188     uint8_t   m_val8;                       //!< 8 bit payload.
189     uint16_t  m_val16;                      //!< 16 bit payload
190     uint32_t  m_val32;                      //!< 32 bit payload
191     uint64_t  m_val64;                      //!< 64 bit payload
192 
193     // timestamp handling
194 	uint8_t   m_req_ts_nibbles;
195 	uint8_t   m_curr_ts_nibbles;
196 	uint64_t  m_ts_update_value;
197 	bool m_ts_req_set;
198 
199 
200     // sync handling - need to spot sync mid other packet in case of wrap / discontinuity
201     uint8_t   m_num_F_nibbles;              //!< count consecutive F nibbles.
202     bool m_sync_start;                      //!< possible start of sync
203     bool m_is_sync;                         //!< true if found sync at current nibble
204     ocsd_trc_index_t m_sync_index;         //!< index of start of possible sync packet
205 
206     void checkSyncNibble();                 //!< check current nibble as part of sync.
207     void clearSyncCount();                  //!< valid packet, so clear sync counters (i.e. a trailing ffff is not part of sync).
208 
209     class monAttachNotify : public IComponentAttachNotifier
210     {
211     public:
212         monAttachNotify() { m_bInUse = false; };
213         virtual ~monAttachNotify() {};
214         virtual void attachNotify(const int num_attached) { m_bInUse = (num_attached > 0); };
215 
216         const bool usingMonitor() const { return m_bInUse; };
217 
218     private:
219         bool m_bInUse;
220     } mon_in_use;
221 };
222 
223 inline const bool TrcPktProcStm::dataToProcess() const
224 {
225     // data to process if
226     // 1) not processed all the input bytes
227     // 2) there is still a nibble available from the last byte.
228     // 3) bytes processed, but there is a full packet to send
229     return (m_data_in_used < m_data_in_size) || m_nibble_2nd_valid || (m_proc_state == SEND_PKT);
230 }
231 
232 
233 inline void TrcPktProcStm::checkSyncNibble()
234 {
235     if(m_nibble != 0xF)
236     {
237         if(!m_sync_start)
238             return;
239 
240         if((m_nibble == 0) && (m_num_F_nibbles >= 21))
241         {
242             m_is_sync = true;   //this nibble marks a sync sequence - keep the F nibble count
243         }
244         else
245         {
246             clearSyncCount();   // clear all sync counters
247         }
248         return;
249     }
250 
251     m_num_F_nibbles++;
252     if(!m_sync_start)
253     {
254         m_sync_start = true;
255         m_sync_index = m_packet_index + ((m_num_nibbles - 1) / 2);
256     }
257 }
258 
259 inline void TrcPktProcStm::clearSyncCount()
260 {
261     m_num_F_nibbles = 0;
262     m_sync_start = false;
263     m_is_sync = false;
264 }
265 
266 inline void TrcPktProcStm::sendPacket()
267 {
268     m_proc_state = SEND_PKT;
269 }
270 
271 inline void TrcPktProcStm::setProcUnsynced()
272 {
273     m_proc_state = WAIT_SYNC;
274     m_bStreamSync = false;
275 }
276 
277 
278 inline void TrcPktProcStm::savePacketByte(const uint8_t val)
279 {
280     // save packet data if using monitor and synchronised.
281     if(mon_in_use.usingMonitor() && !m_bWaitSyncSaveSuppressed)
282         m_packet_data.push_back(val);
283 }
284 
285 /** @}*/
286 
287 #endif // ARM_TRC_PKT_PROC_STM_H_INCLUDED
288 
289 /* End of File trc_pkt_proc_stm.h */
290