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
44template <class P, class Pt, class Pc>
45class DecoderMngrBase : public IDecoderMngr
46{
47public:
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
82private:
83    const ocsd_trace_protocol_t m_builtInProtocol;    //!< Protocol ID if built in type.
84};
85
86template <class P, class Pt, class Pc>
87    DecoderMngrBase<P,Pt,Pc>::DecoderMngrBase(const std::string &decoderTypeName, ocsd_trace_protocol_t builtInProtocol) :
88        m_builtInProtocol(builtInProtocol)
89{
90    OcsdLibDcdRegister *pDcdReg = OcsdLibDcdRegister::getDecoderRegister();
91    if(pDcdReg)
92        pDcdReg->registerDecoderTypeByName(decoderTypeName,this);
93}
94
95template <class P, class Pt, class Pc>
96ocsd_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
163template <class P, class Pt, class Pc>
164ocsd_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
172template <class P, class Pt, class Pc>
173ocsd_err_t DecoderMngrBase<P,Pt,Pc>::attachErrorLogger(TraceComponent *pComponent, ITraceErrorLog *pIErrorLog)
174{
175    return pComponent->getErrorLogAttachPt()->replace_first(pIErrorLog);
176}
177
178template <class P, class Pt, class Pc>
179ocsd_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
196template <class P, class Pt, class Pc>
197ocsd_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
214template <class P, class Pt, class Pc>
215ocsd_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
231template <class P, class Pt, class Pc>
232ocsd_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
248template <class P, class Pt, class Pc>
249ocsd_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
269template <class P, class Pt, class Pc>
270ocsd_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
290template <class P, class Pt, class Pc>
291ocsd_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
311template <class P, class Pt, class Pc>
312ocsd_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
325template<   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.
331class DecodeMngrFullDcd : public DecoderMngrBase<P,Pt,Pc>
332{
333public:
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/* full decode - extended config object - base + derived. */
366template<   class P,            // Packet class.
367            class Pt,           // Packet enum type ID.
368            class Pc,           // Processor config base class.
369            class PcEx,         // Processor config derived class
370            class PcSt,         // Processor config struct type
371            class PktProc,      // Packet processor class.
372            class PktDcd>       // Packet decoder class.
373            class DecodeMngrFullDcdExCfg : public DecoderMngrBase<P, Pt, Pc>
374{
375public:
376    DecodeMngrFullDcdExCfg(const std::string &name, ocsd_trace_protocol_t builtInProtocol)
377        : DecoderMngrBase<P, Pt, Pc>(name, builtInProtocol) {};
378
379    virtual ~DecodeMngrFullDcdExCfg() {};
380
381    virtual TraceComponent *createPktProc(const bool useInstID, const int instID)
382    {
383        TraceComponent *pComp;
384        if (useInstID)
385            pComp = new (std::nothrow) PktProc(instID);
386        else
387            pComp = new (std::nothrow) PktProc();
388        return pComp;
389    }
390
391    virtual TraceComponent *createPktDecode(const bool useInstID, const int instID)
392    {
393        TraceComponent *pComp;
394        if (useInstID)
395            pComp = new (std::nothrow)PktDcd(instID);
396        else
397            pComp = new (std::nothrow)PktDcd();
398        return pComp;
399    }
400
401    virtual CSConfig *createConfig(const void *pDataStruct)
402    {
403        return new (std::nothrow) PcEx((PcSt *)pDataStruct);
404    }
405};
406
407
408/****************************************************************************************************/
409/* Packet processor only, templated base for creating decoder objects                               */
410/****************************************************************************************************/
411
412template<   class P,            // Packet class.
413            class Pt,           // Packet enum type ID.
414            class Pc,           // Processor config class.
415            class PcSt,         // Processor config struct type
416            class PktProc>      // Packet processor class.
417class DecodeMngrPktProc : public DecoderMngrBase<P,Pt,Pc>
418{
419public:
420    DecodeMngrPktProc (const std::string &name, ocsd_trace_protocol_t builtInProtocol)
421        : DecoderMngrBase<P,Pt,Pc>(name,builtInProtocol) {};
422
423    virtual ~DecodeMngrPktProc() {};
424
425    virtual TraceComponent *createPktProc(const bool useInstID, const int instID)
426    {
427        TraceComponent *pComp;
428        if(useInstID)
429            pComp = new (std::nothrow) PktProc(instID);
430        else
431            pComp = new (std::nothrow) PktProc();
432        return pComp;
433    }
434
435    virtual CSConfig *createConfig(const void *pDataStruct)
436    {
437       return new (std::nothrow) Pc((PcSt *)pDataStruct);
438    }
439};
440
441
442
443#endif // ARM_OCSD_DCD_MNGR_H_INCLUDED
444
445/* End of File ocsd_dcd_mngr.h */
446