1 /*
2  * \file       ocsd_dcd_mngr.h
3  * \brief      OpenCSD : Decoder manager base class.
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 #ifndef ARM_OCSD_DCD_MNGR_H_INCLUDED
36 #define ARM_OCSD_DCD_MNGR_H_INCLUDED
37 
38 #include "opencsd/ocsd_if_types.h"
39 #include "common/ocsd_dcd_mngr_i.h"
40 #include "common/ocsd_lib_dcd_register.h"
41 #include "common/trc_pkt_decode_base.h"
42 #include "common/trc_pkt_proc_base.h"
43 
44 template <class P, class Pt, class Pc>
45 class DecoderMngrBase : public IDecoderMngr
46 {
47 public:
48     DecoderMngrBase(const std::string &decoderTypeName, ocsd_trace_protocol_t builtInProtocol);
49     virtual ~DecoderMngrBase() {};
50 
51     // create decoder interface.
52     virtual ocsd_err_t createDecoder(const int create_flags, const int instID, const CSConfig *p_config,  TraceComponent **p_component);
53     virtual ocsd_err_t destroyDecoder(TraceComponent *p_component);
54 
55     virtual const ocsd_trace_protocol_t getProtocolType() const { return m_builtInProtocol; }
56 
57 // common
58     virtual ocsd_err_t attachErrorLogger(TraceComponent *pComponent, ITraceErrorLog *pIErrorLog);
59 
60 // pkt decoder
61     virtual ocsd_err_t attachInstrDecoder(TraceComponent *pComponent, IInstrDecode *pIInstrDec);
62     virtual ocsd_err_t attachMemAccessor(TraceComponent *pComponent, ITargetMemAccess *pMemAccessor);
63     virtual ocsd_err_t attachOutputSink(TraceComponent *pComponent, ITrcGenElemIn *pOutSink);
64 
65 // pkt processor
66     virtual ocsd_err_t attachPktMonitor(TraceComponent *pComponent, ITrcTypedBase *pPktRawDataMon);
67     virtual ocsd_err_t attachPktIndexer(TraceComponent *pComponent, ITrcTypedBase *pPktIndexer);
68     virtual ocsd_err_t attachPktSink(TraceComponent *pComponent, ITrcTypedBase *pPktDataInSink);
69 
70 // data input connection interface
71     virtual ocsd_err_t getDataInputI(TraceComponent *pComponent, ITrcDataIn **ppDataIn);
72 
73 // generate a Config object from opaque config struct pointer.
74     virtual ocsd_err_t createConfigFromDataStruct(CSConfig **pConfigBase, const void *pDataStruct);
75 
76 // implemented by decoder handler derived classes
77     virtual TraceComponent *createPktProc(const bool useInstID, const int instID) = 0;
78     virtual TraceComponent *createPktDecode(const bool useInstID, const int instID) { return 0; };
79     virtual CSConfig *createConfig(const void *pDataStruct) = 0;
80 
81 
82 private:
83     ocsd_trace_protocol_t m_builtInProtocol;    //!< Protocol ID if built in type.
84 };
85 
86 template <class P, class Pt, class Pc>
87 DecoderMngrBase<P,Pt,Pc>::DecoderMngrBase(const std::string &decoderTypeName, ocsd_trace_protocol_t builtInProtocol)
88 {
89     OcsdLibDcdRegister *pDcdReg = OcsdLibDcdRegister::getDecoderRegister();
90     if(pDcdReg)
91         pDcdReg->registerDecoderTypeByName(decoderTypeName,this);
92     m_builtInProtocol = builtInProtocol;
93 }
94 
95 template <class P, class Pt, class Pc>
96 ocsd_err_t  DecoderMngrBase<P,Pt,Pc>::createDecoder(const int create_flags, const int instID, const CSConfig *pConfig,  TraceComponent **ppTrcComp)
97 {
98     TraceComponent *pkt_proc = 0;
99     TraceComponent *pkt_dcd = 0;
100     bool bUseInstID =  (create_flags & OCSD_CREATE_FLG_INST_ID) != 0;
101     bool bDecoder = (create_flags & OCSD_CREATE_FLG_FULL_DECODER) != 0;
102     bool bUnConfigured = (pConfig == 0);
103 
104     const Pc *pConf = dynamic_cast< const Pc * >(pConfig);
105 
106     // check inputs valid...
107     if((pConf == 0) && !bUnConfigured)
108         return OCSD_ERR_INVALID_PARAM_TYPE;
109 
110      if((create_flags & (OCSD_CREATE_FLG_PACKET_PROC | OCSD_CREATE_FLG_FULL_DECODER)) == 0)
111         return OCSD_ERR_INVALID_PARAM_VAL;
112 
113     // always need a packet processor
114     pkt_proc = createPktProc(bUseInstID, instID);
115     if(!pkt_proc)
116         return OCSD_ERR_MEM;
117 
118     // set the op mode flags
119     pkt_proc->setComponentOpMode(create_flags & (OCSD_OPFLG_COMP_MODE_MASK | OCSD_OPFLG_PKTPROC_COMMON));
120 
121     // set the configuration
122     TrcPktProcBase<P,Pt,Pc> *pProcBase = dynamic_cast< TrcPktProcBase<P,Pt,Pc> *>(pkt_proc);
123     if(pProcBase == 0)
124         return OCSD_ERR_INVALID_PARAM_TYPE;
125 
126     if(!bUnConfigured)
127         pProcBase->setProtocolConfig(pConf);
128 
129     *ppTrcComp = pkt_proc;
130 
131     // may need a packet decoder
132     if(bDecoder)
133     {
134         // create the decoder
135         pkt_dcd = createPktDecode(bUseInstID, instID);
136         if(!pkt_dcd)
137             return OCSD_ERR_MEM;
138 
139         // set the op mode flags
140         pkt_dcd->setComponentOpMode(create_flags & (OCSD_OPFLG_COMP_MODE_MASK | OCSD_OPFLG_PKTDEC_COMMON));
141 
142         // get the decoder base
143         TrcPktDecodeBase<P,Pc> *pBase = dynamic_cast< TrcPktDecodeBase<P,Pc> *>(pkt_dcd);
144         if(pBase == 0)
145             return OCSD_ERR_INVALID_PARAM_TYPE;
146 
147         if(!bUnConfigured)
148             pBase->setProtocolConfig(pConf);
149 
150         // associate decoder with packet processor
151         // -> this means a TraceComponent with an associated component is a packet decoder.
152         //    the associated component is the connected packet processor.
153         pkt_dcd->setAssocComponent(pkt_proc);
154 
155         // connect packet processor and decoder
156         pProcBase->getPacketOutAttachPt()->attach(pBase);
157 
158         *ppTrcComp = pkt_dcd;
159     }
160     return OCSD_OK;
161 }
162 
163 template <class P, class Pt, class Pc>
164 ocsd_err_t DecoderMngrBase<P,Pt,Pc>::destroyDecoder(TraceComponent *pComponent)
165 {
166     if(pComponent->getAssocComponent() != 0)
167         delete pComponent->getAssocComponent();
168     delete pComponent;
169     return OCSD_OK;
170 }
171 
172 template <class P, class Pt, class Pc>
173 ocsd_err_t DecoderMngrBase<P,Pt,Pc>::attachErrorLogger(TraceComponent *pComponent, ITraceErrorLog *pIErrorLog)
174 {
175     return pComponent->getErrorLogAttachPt()->replace_first(pIErrorLog);
176 }
177 
178 template <class P, class Pt, class Pc>
179 ocsd_err_t DecoderMngrBase<P,Pt,Pc>::attachInstrDecoder(TraceComponent *pComponent, IInstrDecode *pIInstrDec)
180 {
181     ocsd_err_t err = OCSD_ERR_DCD_INTERFACE_UNUSED;
182 
183     if(pComponent->getAssocComponent() == 0)    // no associated component - so this is a packet processor
184         return OCSD_ERR_INVALID_PARAM_TYPE;
185 
186     TrcPktDecodeI *pDcdI = dynamic_cast< TrcPktDecodeI * >(pComponent);
187     if(pDcdI == 0)
188         return OCSD_ERR_INVALID_PARAM_TYPE;
189 
190     if(pDcdI->getUsesIDecode())
191         err = pDcdI->getInstrDecodeAttachPt()->replace_first(pIInstrDec);
192 
193     return err;
194 }
195 
196 template <class P, class Pt, class Pc>
197 ocsd_err_t DecoderMngrBase<P,Pt,Pc>::attachMemAccessor(TraceComponent *pComponent, ITargetMemAccess *pMemAccessor)
198 {
199     ocsd_err_t err = OCSD_ERR_DCD_INTERFACE_UNUSED;
200 
201     if(pComponent->getAssocComponent() == 0)    // no associated component - so this is a packet processor
202         return OCSD_ERR_INVALID_PARAM_TYPE;
203 
204     TrcPktDecodeI *pDcdI = dynamic_cast< TrcPktDecodeI * >(pComponent);
205     if(pDcdI == 0)
206         return OCSD_ERR_INVALID_PARAM_TYPE;
207 
208     if(pDcdI->getUsesMemAccess())
209         err = pDcdI->getMemoryAccessAttachPt()->replace_first(pMemAccessor);
210 
211     return err;
212 }
213 
214 template <class P, class Pt, class Pc>
215 ocsd_err_t DecoderMngrBase<P,Pt,Pc>::attachOutputSink(TraceComponent *pComponent, ITrcGenElemIn *pOutSink)
216 {
217     ocsd_err_t err = OCSD_ERR_INVALID_PARAM_TYPE;
218 
219     if(pComponent->getAssocComponent() == 0)    // no associated component - so this is a packet processor
220         return err;
221 
222     TrcPktDecodeI *pDcdI = dynamic_cast< TrcPktDecodeI * >(pComponent);
223     if(pDcdI == 0)
224         return OCSD_ERR_INVALID_PARAM_TYPE;
225 
226     err = pDcdI->getTraceElemOutAttachPt()->replace_first(pOutSink);
227 
228     return err;
229 }
230 
231 template <class P, class Pt, class Pc>
232 ocsd_err_t DecoderMngrBase<P,Pt,Pc>::getDataInputI(TraceComponent *pComponent, ITrcDataIn **ppDataIn)
233 {
234     // find the packet processor
235     TraceComponent *pPktProc = pComponent;
236     if(pComponent->getAssocComponent() != 0)
237         pPktProc = pComponent->getAssocComponent();
238 
239     TrcPktProcI *pPPI = dynamic_cast< TrcPktProcI * >(pPktProc);
240     if(pPPI == 0)
241         return OCSD_ERR_INVALID_PARAM_TYPE;
242 
243     *ppDataIn = pPPI;
244 
245     return OCSD_OK;
246 }
247 
248 template <class P, class Pt, class Pc>
249 ocsd_err_t DecoderMngrBase<P,Pt,Pc>::attachPktMonitor(TraceComponent *pComponent, ITrcTypedBase *pPktRawDataMon)
250 {
251     // find the packet processor
252     TraceComponent *pPktProc = pComponent;
253     if(pComponent->getAssocComponent() != 0)
254         pPktProc = pComponent->getAssocComponent();
255 
256     // get the packet processor
257     TrcPktProcBase<P,Pt,Pc> *pPktProcBase = dynamic_cast< TrcPktProcBase<P,Pt,Pc> * >(pPktProc);
258     if(pPktProcBase == 0)
259         return OCSD_ERR_INVALID_PARAM_TYPE;
260 
261     // get the interface
262     IPktRawDataMon<P> *p_If =  dynamic_cast< IPktRawDataMon<P> * >(pPktRawDataMon);
263     if(p_If == 0)
264         return  OCSD_ERR_INVALID_PARAM_TYPE;
265 
266     return pPktProcBase->getRawPacketMonAttachPt()->replace_first(p_If);
267 }
268 
269 template <class P, class Pt, class Pc>
270 ocsd_err_t DecoderMngrBase<P,Pt,Pc>::attachPktIndexer(TraceComponent *pComponent, ITrcTypedBase *pPktIndexer)
271 {
272     // find the packet processor
273     TraceComponent *pPktProc = pComponent;
274     if(pComponent->getAssocComponent() != 0)
275         pPktProc = pComponent->getAssocComponent();
276 
277     // get the packet processor
278     TrcPktProcBase<P,Pt,Pc> *pPktProcBase = dynamic_cast< TrcPktProcBase<P,Pt,Pc> * >(pPktProc);
279     if(pPktProcBase == 0)
280         return OCSD_ERR_INVALID_PARAM_TYPE;
281 
282     // get the interface
283     ITrcPktIndexer<Pt> *p_If =  dynamic_cast< ITrcPktIndexer<Pt> * >(pPktIndexer);
284     if(p_If == 0)
285         return  OCSD_ERR_INVALID_PARAM_TYPE;
286 
287     return pPktProcBase->getTraceIDIndexerAttachPt()->replace_first(p_If);
288 }
289 
290 template <class P, class Pt, class Pc>
291 ocsd_err_t DecoderMngrBase<P,Pt,Pc>::attachPktSink(TraceComponent *pComponent, ITrcTypedBase *pPktDataInSink)
292 {
293     // must be solo packet processor
294     if(pComponent->getAssocComponent() != 0)
295         return OCSD_ERR_INVALID_PARAM_TYPE;
296 
297     // interface must be the correct one.
298     IPktDataIn<P> *pkt_in_i = dynamic_cast< IPktDataIn<P> * >(pPktDataInSink);
299     if(pkt_in_i == 0)
300         return OCSD_ERR_INVALID_PARAM_TYPE;
301 
302     // get the packet processor
303     TrcPktProcBase<P,Pt,Pc> *pPktProcBase = dynamic_cast< TrcPktProcBase<P,Pt,Pc> * >(pComponent);
304     if(pPktProcBase == 0)
305         return OCSD_ERR_INVALID_PARAM_TYPE;
306 
307     // attach
308     return  pPktProcBase->getPacketOutAttachPt()->replace_first(pkt_in_i);
309 }
310 
311 template <class P, class Pt, class Pc>
312 ocsd_err_t DecoderMngrBase<P,Pt,Pc>::createConfigFromDataStruct(CSConfig **pConfigBase, const void *pDataStruct)
313 {
314     CSConfig *pConfig = createConfig(pDataStruct);
315     if(!pConfig)
316         return OCSD_ERR_MEM;
317     *pConfigBase = pConfig;
318     return OCSD_OK;
319 }
320 
321 /****************************************************************************************************/
322 /* Full decoder / packet process pair, templated base for creating decoder objects                  */
323 /****************************************************************************************************/
324 
325 template<   class P,            // Packet class.
326             class Pt,           // Packet enum type ID.
327             class Pc,           // Processor config class.
328             class PcSt,         // Processor config struct type
329             class PktProc,      // Packet processor class.
330             class PktDcd>       // Packet decoder class.
331 class DecodeMngrFullDcd : public DecoderMngrBase<P,Pt,Pc>
332 {
333 public:
334     DecodeMngrFullDcd (const std::string &name, ocsd_trace_protocol_t builtInProtocol)
335         : DecoderMngrBase<P,Pt,Pc>(name,builtInProtocol) {};
336 
337     virtual ~DecodeMngrFullDcd() {};
338 
339     virtual TraceComponent *createPktProc(const bool useInstID, const int instID)
340     {
341         TraceComponent *pComp;
342         if(useInstID)
343             pComp = new (std::nothrow) PktProc(instID);
344         else
345             pComp = new (std::nothrow) PktProc();
346         return pComp;
347     }
348 
349     virtual TraceComponent *createPktDecode(const bool useInstID, const int instID)
350     {
351         TraceComponent *pComp;
352         if(useInstID)
353             pComp = new (std::nothrow)PktDcd(instID);
354         else
355             pComp = new (std::nothrow)PktDcd();
356         return pComp;
357     }
358 
359     virtual CSConfig *createConfig(const void *pDataStruct)
360     {
361        return new (std::nothrow) Pc((PcSt *)pDataStruct);
362     }
363 };
364 
365 /****************************************************************************************************/
366 /* Packet processor only, templated base for creating decoder objects                               */
367 /****************************************************************************************************/
368 
369 template<   class P,            // Packet class.
370             class Pt,           // Packet enum type ID.
371             class Pc,           // Processor config class.
372             class PcSt,         // Processor config struct type
373             class PktProc>      // Packet processor class.
374 class DecodeMngrPktProc : public DecoderMngrBase<P,Pt,Pc>
375 {
376 public:
377     DecodeMngrPktProc (const std::string &name, ocsd_trace_protocol_t builtInProtocol)
378         : DecoderMngrBase<P,Pt,Pc>(name,builtInProtocol) {};
379 
380     virtual ~DecodeMngrPktProc() {};
381 
382     virtual TraceComponent *createPktProc(const bool useInstID, const int instID)
383     {
384         TraceComponent *pComp;
385         if(useInstID)
386             pComp = new (std::nothrow) PktProc(instID);
387         else
388             pComp = new (std::nothrow) PktProc();
389         return pComp;
390     }
391 
392     virtual CSConfig *createConfig(const void *pDataStruct)
393     {
394        return new (std::nothrow) Pc((PcSt *)pDataStruct);
395     }
396 };
397 
398 
399 
400 #endif // ARM_OCSD_DCD_MNGR_H_INCLUDED
401 
402 /* End of File ocsd_dcd_mngr.h */
403