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    ocsd_trace_protocol_t m_builtInProtocol;    //!< Protocol ID if built in type.
84};
85
86template <class P, class Pt, class Pc>
87DecoderMngrBase<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
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 configuration
119    TrcPktProcBase<P,Pt,Pc> *pProcBase = dynamic_cast< TrcPktProcBase<P,Pt,Pc> *>(pkt_proc);
120    if(pProcBase == 0)
121        return OCSD_ERR_INVALID_PARAM_TYPE;
122
123    if(!bUnConfigured)
124        pProcBase->setProtocolConfig(pConf);
125
126    *ppTrcComp = pkt_proc;
127
128    // may need a packet decoder
129    if(bDecoder)
130    {
131        // create the decoder
132        pkt_dcd = createPktDecode(bUseInstID, instID);
133        if(!pkt_dcd)
134            return OCSD_ERR_MEM;
135
136        // get the decoder base
137        TrcPktDecodeBase<P,Pc> *pBase = dynamic_cast< TrcPktDecodeBase<P,Pc> *>(pkt_dcd);
138        if(pBase == 0)
139            return OCSD_ERR_INVALID_PARAM_TYPE;
140
141        if(!bUnConfigured)
142            pBase->setProtocolConfig(pConf);
143
144        // associate decoder with packet processor
145        // -> this means a TraceComponent with an associated component is a packet decoder.
146        //    the associated component is the connected packet processor.
147        pkt_dcd->setAssocComponent(pkt_proc);
148
149        // connect packet processor and decoder
150        pProcBase->getPacketOutAttachPt()->attach(pBase);
151
152        *ppTrcComp = pkt_dcd;
153    }
154    return OCSD_OK;
155}
156
157template <class P, class Pt, class Pc>
158ocsd_err_t DecoderMngrBase<P,Pt,Pc>::destroyDecoder(TraceComponent *pComponent)
159{
160    if(pComponent->getAssocComponent() != 0)
161        delete pComponent->getAssocComponent();
162    delete pComponent;
163    return OCSD_OK;
164}
165
166template <class P, class Pt, class Pc>
167ocsd_err_t DecoderMngrBase<P,Pt,Pc>::attachErrorLogger(TraceComponent *pComponent, ITraceErrorLog *pIErrorLog)
168{
169    return pComponent->getErrorLogAttachPt()->replace_first(pIErrorLog);
170}
171
172template <class P, class Pt, class Pc>
173ocsd_err_t DecoderMngrBase<P,Pt,Pc>::attachInstrDecoder(TraceComponent *pComponent, IInstrDecode *pIInstrDec)
174{
175    ocsd_err_t err = OCSD_ERR_DCD_INTERFACE_UNUSED;
176
177    if(pComponent->getAssocComponent() == 0)    // no associated component - so this is a packet processor
178        return OCSD_ERR_INVALID_PARAM_TYPE;
179
180    TrcPktDecodeI *pDcdI = dynamic_cast< TrcPktDecodeI * >(pComponent);
181    if(pDcdI == 0)
182        return OCSD_ERR_INVALID_PARAM_TYPE;
183
184    if(pDcdI->getUsesIDecode())
185        err = pDcdI->getInstrDecodeAttachPt()->replace_first(pIInstrDec);
186
187    return err;
188}
189
190template <class P, class Pt, class Pc>
191ocsd_err_t DecoderMngrBase<P,Pt,Pc>::attachMemAccessor(TraceComponent *pComponent, ITargetMemAccess *pMemAccessor)
192{
193    ocsd_err_t err = OCSD_ERR_DCD_INTERFACE_UNUSED;
194
195    if(pComponent->getAssocComponent() == 0)    // no associated component - so this is a packet processor
196        return OCSD_ERR_INVALID_PARAM_TYPE;
197
198    TrcPktDecodeI *pDcdI = dynamic_cast< TrcPktDecodeI * >(pComponent);
199    if(pDcdI == 0)
200        return OCSD_ERR_INVALID_PARAM_TYPE;
201
202    if(pDcdI->getUsesMemAccess())
203        err = pDcdI->getMemoryAccessAttachPt()->replace_first(pMemAccessor);
204
205    return err;
206}
207
208template <class P, class Pt, class Pc>
209ocsd_err_t DecoderMngrBase<P,Pt,Pc>::attachOutputSink(TraceComponent *pComponent, ITrcGenElemIn *pOutSink)
210{
211    ocsd_err_t err = OCSD_ERR_INVALID_PARAM_TYPE;
212
213    if(pComponent->getAssocComponent() == 0)    // no associated component - so this is a packet processor
214        return err;
215
216    TrcPktDecodeI *pDcdI = dynamic_cast< TrcPktDecodeI * >(pComponent);
217    if(pDcdI == 0)
218        return OCSD_ERR_INVALID_PARAM_TYPE;
219
220    err = pDcdI->getTraceElemOutAttachPt()->replace_first(pOutSink);
221
222    return err;
223}
224
225template <class P, class Pt, class Pc>
226ocsd_err_t DecoderMngrBase<P,Pt,Pc>::getDataInputI(TraceComponent *pComponent, ITrcDataIn **ppDataIn)
227{
228    // find the packet processor
229    TraceComponent *pPktProc = pComponent;
230    if(pComponent->getAssocComponent() != 0)
231        pPktProc = pComponent->getAssocComponent();
232
233    TrcPktProcI *pPPI = dynamic_cast< TrcPktProcI * >(pPktProc);
234    if(pPPI == 0)
235        return OCSD_ERR_INVALID_PARAM_TYPE;
236
237    *ppDataIn = pPPI;
238
239    return OCSD_OK;
240}
241
242template <class P, class Pt, class Pc>
243ocsd_err_t DecoderMngrBase<P,Pt,Pc>::attachPktMonitor(TraceComponent *pComponent, ITrcTypedBase *pPktRawDataMon)
244{
245    // find the packet processor
246    TraceComponent *pPktProc = pComponent;
247    if(pComponent->getAssocComponent() != 0)
248        pPktProc = pComponent->getAssocComponent();
249
250    // get the packet processor
251    TrcPktProcBase<P,Pt,Pc> *pPktProcBase = dynamic_cast< TrcPktProcBase<P,Pt,Pc> * >(pPktProc);
252    if(pPktProcBase == 0)
253        return OCSD_ERR_INVALID_PARAM_TYPE;
254
255    // get the interface
256    IPktRawDataMon<P> *p_If =  dynamic_cast< IPktRawDataMon<P> * >(pPktRawDataMon);
257    if(p_If == 0)
258        return  OCSD_ERR_INVALID_PARAM_TYPE;
259
260    return pPktProcBase->getRawPacketMonAttachPt()->replace_first(p_If);
261}
262
263template <class P, class Pt, class Pc>
264ocsd_err_t DecoderMngrBase<P,Pt,Pc>::attachPktIndexer(TraceComponent *pComponent, ITrcTypedBase *pPktIndexer)
265{
266    // find the packet processor
267    TraceComponent *pPktProc = pComponent;
268    if(pComponent->getAssocComponent() != 0)
269        pPktProc = pComponent->getAssocComponent();
270
271    // get the packet processor
272    TrcPktProcBase<P,Pt,Pc> *pPktProcBase = dynamic_cast< TrcPktProcBase<P,Pt,Pc> * >(pPktProc);
273    if(pPktProcBase == 0)
274        return OCSD_ERR_INVALID_PARAM_TYPE;
275
276    // get the interface
277    ITrcPktIndexer<Pt> *p_If =  dynamic_cast< ITrcPktIndexer<Pt> * >(pPktIndexer);
278    if(p_If == 0)
279        return  OCSD_ERR_INVALID_PARAM_TYPE;
280
281    return pPktProcBase->getTraceIDIndexerAttachPt()->replace_first(p_If);
282}
283
284template <class P, class Pt, class Pc>
285ocsd_err_t DecoderMngrBase<P,Pt,Pc>::attachPktSink(TraceComponent *pComponent, ITrcTypedBase *pPktDataInSink)
286{
287    // must be solo packet processor
288    if(pComponent->getAssocComponent() != 0)
289        return OCSD_ERR_INVALID_PARAM_TYPE;
290
291    // interface must be the correct one.
292    IPktDataIn<P> *pkt_in_i = dynamic_cast< IPktDataIn<P> * >(pPktDataInSink);
293    if(pkt_in_i == 0)
294        return OCSD_ERR_INVALID_PARAM_TYPE;
295
296    // get the packet processor
297    TrcPktProcBase<P,Pt,Pc> *pPktProcBase = dynamic_cast< TrcPktProcBase<P,Pt,Pc> * >(pComponent);
298    if(pPktProcBase == 0)
299        return OCSD_ERR_INVALID_PARAM_TYPE;
300
301    // attach
302    return  pPktProcBase->getPacketOutAttachPt()->replace_first(pkt_in_i);
303}
304
305template <class P, class Pt, class Pc>
306ocsd_err_t DecoderMngrBase<P,Pt,Pc>::createConfigFromDataStruct(CSConfig **pConfigBase, const void *pDataStruct)
307{
308    CSConfig *pConfig = createConfig(pDataStruct);
309    if(!pConfig)
310        return OCSD_ERR_MEM;
311    *pConfigBase = pConfig;
312    return OCSD_OK;
313}
314
315/****************************************************************************************************/
316/* Full decoder / packet process pair, templated base for creating decoder objects                  */
317/****************************************************************************************************/
318
319template<   class P,            // Packet class.
320            class Pt,           // Packet enum type ID.
321            class Pc,           // Processor config class.
322            class PcSt,         // Processor config struct type
323            class PktProc,      // Packet processor class.
324            class PktDcd>       // Packet decoder class.
325class DecodeMngrFullDcd : public DecoderMngrBase<P,Pt,Pc>
326{
327public:
328    DecodeMngrFullDcd (const std::string &name, ocsd_trace_protocol_t builtInProtocol)
329        : DecoderMngrBase<P,Pt,Pc>(name,builtInProtocol) {};
330
331    virtual ~DecodeMngrFullDcd() {};
332
333    virtual TraceComponent *createPktProc(const bool useInstID, const int instID)
334    {
335        TraceComponent *pComp;
336        if(useInstID)
337            pComp = new (std::nothrow) PktProc(instID);
338        else
339            pComp = new (std::nothrow) PktProc();
340        return pComp;
341    }
342
343    virtual TraceComponent *createPktDecode(const bool useInstID, const int instID)
344    {
345        TraceComponent *pComp;
346        if(useInstID)
347            pComp = new (std::nothrow)PktDcd(instID);
348        else
349            pComp = new (std::nothrow)PktDcd();
350        return pComp;
351    }
352
353    virtual CSConfig *createConfig(const void *pDataStruct)
354    {
355       return new (std::nothrow) Pc((PcSt *)pDataStruct);
356    }
357};
358
359/****************************************************************************************************/
360/* Packet processor only, templated base for creating decoder objects                               */
361/****************************************************************************************************/
362
363template<   class P,            // Packet class.
364            class Pt,           // Packet enum type ID.
365            class Pc,           // Processor config class.
366            class PcSt,         // Processor config struct type
367            class PktProc>      // Packet processor class.
368class DecodeMngrPktProc : public DecoderMngrBase<P,Pt,Pc>
369{
370public:
371    DecodeMngrPktProc (const std::string &name, ocsd_trace_protocol_t builtInProtocol)
372        : DecoderMngrBase<P,Pt,Pc>(name,builtInProtocol) {};
373
374    virtual ~DecodeMngrPktProc() {};
375
376    virtual TraceComponent *createPktProc(const bool useInstID, const int instID)
377    {
378        TraceComponent *pComp;
379        if(useInstID)
380            pComp = new (std::nothrow) PktProc(instID);
381        else
382            pComp = new (std::nothrow) PktProc();
383        return pComp;
384    }
385
386    virtual CSConfig *createConfig(const void *pDataStruct)
387    {
388       return new (std::nothrow) Pc((PcSt *)pDataStruct);
389    }
390};
391
392
393
394#endif // ARM_OCSD_DCD_MNGR_H_INCLUDED
395
396/* End of File ocsd_dcd_mngr.h */
397