xref: /aosp_15_r20/external/OpenCSD/decoder/docs/prog_guide/prog_guide_main.md (revision 02ca8ccacfba7e0df68f3332a95f3180334d6649)
1OpenCSD Library - Programmers Guide    {#prog_guide}
2===================================
3
4@brief  A guide to programming the OpenCSD library.
5
6Introduction and review of Coresight Hardware
7---------------------------------------------
8
9The OpenCSD trace decode library is designed to allow programmers to decode ARM CoreSight trace
10data. This guide will describe the various stages of configuring and programming a decoder instance
11for a given CoreSight system.
12
13The diagram below shows a typical Coresight trace hardware arrangement
14
15![Example CoreSight Trace Capture Hardware](cs_trace_hw.jpg)
16
17The design shown has four Cortex cores, each with an ETM, along with a system STM all of which generate trace into the
18trace funnel. The output of the funnel is fed into a trace sink, which might be an ETB or ETR, saving the trace
19which is multiplexed into CoreSight trace frames in the trace sink memory. The colours represent the sources
20of trace data, each of which will be tagged with a CoreSight Trace ID.
21
22### CoreSight Trace ID ###
23The CoreSight Trace ID - also referred to as the Trace Source Channel ID - is a unique 8 bit number programmed
24into each trace source in a system (ETM,PTM,STM) which identifies the source to both the hardware components
25downstream and the software trace decoders. This ID is used
26
27Overview of Configuration and Decode
28------------------------------------
29
30The OpenCSD library will take the trace data from the trace sink, and when correctly configured and programmed, will
31demultiplex and decode each of the trace sources.
32
33The library supports ETMV3, PTM, ETMv4 and STM trace protocols. The decode occurs in three stages:
34- __Demultiplex__ - the combined trace streams in CoreSight trace frame format are split into their constituent streams according to the CoreSight trace ID.
35- __Packet Processing__ - the individual trace ID streams are resolved into discrete trace packets.
36- __Packet Decode__ - the trace packets are interpreted to produce a decoded representation of instructions executed.
37
38There are input configuration requirements for each stage of the decode process - these allow the decode process to correctly
39interpret the incoming byte stream.
40- __Demultiplex__ - Input flags are set to indicate if the frames are 16 byte aligned or if the stream contains alignment
41bytes between frames.
42- __Packet Processing__ - The hardware configuration of the trace source must be provided. This consists of a sub-set of the
43hardware register values for the source.  Each protocol has differing requirements, represented by an input structure of the
44register values.
45- __Packet Decode__ - For ETM/PTM packet decode, this stage requires the memory images of the code executed in order
46to determine the path through the code. These are provided either as memory dumps, or as links to binary code files.
47
48_Note_ : STM, being a largely software generated data trace, does not require memory images to recover the data written by the source
49processors.
50
51The diagram below shows the basic stages of decode for the library when used in a client application:
52
53![Example Library Usage for Trace Decode](lib_usage.jpg)
54
55The DecodeTree object is a representation of the structure of the CoreSight hardware, but in reverse in that the data is pushed into the
56tree, through the demultiplexor and then along the individual trace stream decode paths till the output decode packets are produced.
57
58These outpup packets are referred to as Generic Trace packets, and are at this stage protocol independent. They consist primarily of
59PE context information and address ranges representing the instructions processed.
60
61### Decode Tree ###
62
63The DecodeTree is the principal wrapper for all the decoders the library supports. This provides a programming
64API which allows the creation of protocol packet processors and decoders.
65
66The API allows the client application to configure the de-multiplexor, create and connect packet processors and
67packet decoders to the trace data streams and collect the output generic decoded trace packets. The DecodeTree
68provides a built in instruction decoder to allow correct trace decode, and an additional API through a memory
69access handler to allow the client applications to provide the images of the traced code in file or memory dump
70format.
71
72Once a DecodeTree is configured, then it can be re-used for multiple sets of captured trace data where the same
73set of applications has been traced, or by changing only the supplied memory images, different traced applications
74on the same hardware configuration.
75
76The process for programming a decode tree for a specific set of trace hardware is as follows;-
771. Create the decode tree and specify the de-multiplexor options.
782. For each trace protocol of interest, use the API to create a decoder, providing the hardware configuration,
79including the CoreSight trace ID for that trace stream. Specify packet processing only, or full decode. Client
80program must know the correct protocol to use for each trace stream.
813. Attach callback(s) to receive the decoded generic trace output (ITrcGenElemIn).
824. Provide the memory images if using full decode.
83
84The DecodeTree can now be used to process the trace data by pushing the captured trace data through the trace
85 data input API call (ITrcDataIn) and analyzing as required the resulting decoded trace (ITrcGenElemIn).
86
87 The objects and connections used for a single trace stream are shown below.
88
89 ![Decode Tree objects - single trace stream](dt_components.jpg)
90
91 All these components can be created and used outside of a DecodeTree, but that is beyond the scope of this
92 guide and expected to be used for custom implementations only.
93
94Programming Examples - decoder configuration.
95---------------------------------------------
96
97The remainder of this programming guide will provide programming exceprts for each of the required stages
98to get a working decode tree, capable of processing trace data.
99
100The guide will be based on an ETMv4 system, similar to the example above, using the C++ interface, but
101equivalent calls from the C-API wrapper library will also be provided.
102
103The source code for the two test applications `trc_pkt_lister` and `c_api_pkt_print_test` may be used as
104further programming guidance.
105
106### Create the decode tree ###
107
108The first step is to create the decode tree. Key choices here are the flags defining expected trace data
109input format and de-mux operations.
110
111~~~{.cpp}
112	uint32_t formatterCfgFlags = OCSD_DFRMTR_FRAME_MEM_ALIGN; /* basic operational mode for on-chip captured trace */
113	DecodeTree *pTree = DecodeTree::CreateDecodeTree(OCSD_TRC_SRC_FRAME_FORMATTED, formatterCfgFlags);
114~~~
115
116This creates a decode tree that is usable in the majority of cases - that is for trace captured in on chip
117RAM via ETB or ETR. Additional flags are available if a TPIU is used that will indicate to the frame de-mux
118that additional frame synchronisation data is present.
119
120In limited cases where the hardware has a single trace source, or only a single source is being used, then
121it is possible to switch off the hardware frame formatter in the ETB/ETR/TPIU. In this case @ref OCSD_TRC_SRC_SINGLE
122 (from enum @ref ocsd_dcd_tree_src_t) may be defined as the first parameter to the function.
123
124C-API version of above code:
125~~~{.c}
126	dcd_tree_handle_t dcdtree_handle = ocsd_create_dcd_tree(OCSD_TRC_SRC_FRAME_FORMATTED, OCSD_DFRMTR_FRAME_MEM_ALIGN);
127~~~
128
129### Error loggers and printers ###
130
131The library defines a standard error logging interface ITraceErrorLog which many of the key components can register
132with to output errors. The process of registering the source means that errors can be tied to a particular component,
133or CoreSight Trace ID. The library provides a standard error logger object - ocsdDefaultErrorLogger - which
134keeps a copy of the last error logged, plus a copy of the last error logged for each data stream associated
135with a CoreSight trace ID.
136
137The error logger can be attached to an output logger - ocsdMsgLogger - which can print text versions of the
138error, or other error messages, out to screen or logging file. Errors can be filtered according to a severity rating,
139defined by @ref ocsd_err_severity_t.
140
141The DecodeTree can use a default error logger from the library - with a message logger that will output to `stderr`.
142
143Client applications can create and adjust the configuration of this error logger and message logger by getting and intialising
144 the logger.
145
146~~~{.cpp}
147	// ** Initialise default error logger.
148	DecodeTree::getDefaultErrorLogger()->initErrorLogger(verbosity,true);
149~~~
150
151Alternatively clients may provide their own configured error logger / message logger pair.
152
153The test program `trc_pkt_lister` provides a customised version of an `ocsdMsgLogger` / `ocsdDefaultErrorLogger` pair
154to ensure that messages and errors are logged to the screen and a file of its choice. This logger is eventually
155passed through to the decode tree.
156
157Code excerpts below (trc_pkt_lister.cpp):
158
159~~~{.cpp}
160	static ocsdMsgLogger logger;
161	static int logOpts = ocsdMsgLogger::OUT_STDOUT | ocsdMsgLogger::OUT_FILE;
162	static std::string logfileName = "trc_pkt_lister.ppl";
163
164	// ** other vars
165
166	main() {
167
168		// ** some init code
169
170	    logger.setLogOpts(logOpts);
171		logger.setLogFileName(logfileName.c_str());
172
173
174		ocsdDefaultErrorLogger err_log;
175		err_log.initErrorLogger(OCSD_ERR_SEV_INFO);
176		err_log.setOutputLogger(&logger);
177
178		// pass err_log reference into snapshot library code
179		SnapShotReader ss_reader;
180		ss_reader.setErrorLogger(&err_log);
181
182		// ** rest of program
183	}
184~~~
185
186In the library code for the snapshot reader (ss_to_dcd_tree.cpp):
187
188~~~{.cpp}
189	bool CreateDcdTreeFromSnapShot::createDecodeTree()
190	{
191		// ** create a decode tree
192
193	    // use our error logger - don't use the tree default.
194        m_pDecodeTree->setAlternateErrorLogger(m_pErrLogInterface);
195	}
196
197~~~
198
199__Note__:  The Snapshot reader library is test code designed to allow the test application read trace snapshots
200which are in the form defined by the open specification in `./decoder/docs/specs/ARM Trace and Debug Snapshot file format 0v2.pdf`
201
202This format is used in ARM's DS-5 debugger, and the open source CoreSight Access Library (CSAL).
203
204### Configuring decoders ###
205
206The next task is to configure the requried decoders. The client program must know the type of ETM/PTM in use
207to correctly set the decoder configuration.
208
209Each class of trace source has a specific set of register values that the decoder requires to correctly interpret the
210raw trace data and convert it to packets then fully decode.
211
212Configuration of an ETMv4 decoder requires initialisation of the EtmV4Config class, which is achieved by filling in a
213@ref ocsd_etmv4_cfg structure:-
214
215~~~{.c}
216	typedef struct _ocsd_etmv4_cfg
217	{
218		uint32_t                reg_idr0;    /**< ID0 register */
219		uint32_t                reg_idr1;    /**< ID1 register */
220		uint32_t                reg_idr2;    /**< ID2 register */
221		uint32_t                reg_idr8;
222		uint32_t                reg_idr9;
223		uint32_t                reg_idr10;
224		uint32_t                reg_idr11;
225		uint32_t                reg_idr12;
226		uint32_t                reg_idr13;
227		uint32_t                reg_configr;  /**< Config Register */
228		uint32_t                reg_traceidr;  /**< Trace Stream ID register */
229		ocsd_arch_version_t    arch_ver;   /**< Architecture version */
230		ocsd_core_profile_t    core_prof;  /**< Core Profile */
231	} ocsd_etmv4_cfg;
232~~~
233
234The structure contains a number of read-only ID registers, and key programmable control registers that define
235the trace output features - such as if the ETM will output timestamps or cycle counts - and the CoreSight Trace ID.
236
237Once this structure is filled in then the decoder can be configured in the decode tree:-
238
239~~~{.cpp}
240	ocsd_etmv4_cfg config;
241
242	// ...
243	// code to fill in config from programmed registers and id registers
244	// ...
245
246	EtmV4Config configObj(&config);		// initialise decoder config class
247	std::string decoderName(OCSD_BUILTIN_DCD_ETMV4I);  // use built in ETMv4 instruction decoder.
248	int decoderCreateFlags = OCSD_CREATE_FLG_FULL_DECODER; // decoder type to create - OCSD_CREATE_FLG_PACKET_PROC for packet processor only
249	ocsd_err_t err = pDecodeTree->createDecoder(decoderName, decoderCreateFlags,&configObj);
250~~~
251
252This code creates a full trace decoder for an ETMv4 source, which consists of a packet processor and packet decoder pair. The decoder is automatically associated with the
253CoreSight Trace ID programmed into the register provided in the `config` structure.
254
255It is also possible to create a packet processor only decoder if the `OCSD_CREATE_FLG_PACKET_PROC` flag is
256used instead. These packet only decoders can be used to create a dump of the raw trace as discrete trace packets.
257
258All decoders a registered with the library using a name - the standard ARM protocols are considered built in
259decoders and are registered automatically. The library contains defined names for these decoders - `OCSD_BUILTIN_DCD_ETMV4I`
260 being the name used for ETMv4 protocol.
261
262The C-API uses the call create_generic_decoder() with the same configuration structure:-
263
264~~~{.c}
265	ocsd_etmv4_cfg config;
266
267	// ...
268	// code to fill in config from programmed registers and id registers
269	// ...
270
271	const char * decoderName = OCSD_BUILTIN_DCD_ETMV4I);  // use built in ETMv4 instruction decoder.
272	int decoderCreateFlags = OCSD_CREATE_FLG_FULL_DECODER; // decoder type to create - OCSD_CREATE_FLG_PACKET_PROC for packet processor only
273	void *p_context =  // <some_client_context>
274	ocsd_err_t err = create_generic_decoder(dcdtree_handle,decoderName,(void *)&config,p_context);
275~~~
276
277The configuration must be completed for each trace source in the decode tree which requires decoding.
278
279The different trace source types have different configuration structures, classes and names
280
281| protocol  | config struct       |  class      |  name define                 |
282|:----------|:--------------------|:------------|:-----------------------------|
283| __ETE__   | @ref ocsd_ete_cfg   | ETEConfig   | @ref OCSD_BUILTIN_DCD_ETE    |
284| __ETMv4__ | @ref ocsd_etmv4_cfg | EtmV4Config | @ref OCSD_BUILTIN_DCD_ETMV4I |
285| __ETMv3__ | @ref ocsd_etmv3_cfg | EtmV3Config | @ref OCSD_BUILTIN_DCD_ETMV3  |
286| __PTM__   | @ref ocsd_ptm_cfg   | PtmConfig   | @ref OCSD_BUILTIN_DCD_PTM    |
287| __STM__   | @ref ocsd_stm_cfg   | STMConfig   | @ref OCSD_BUILTIN_DCD_STM    |
288
289There are a number of additional flags that can be set on `decoderCreateFlags` when creating a decoder.
290
291Key ones are:-
292- `OCSD_OPFLG_PKTDEC_HALT_BAD_PKTS`   : Halt decoder on bad packets. Default behaviour is to try to re-sync and recover.
293
294There are consistency checks to attempt to spot mismatches between the supplied program image from the client and the trace data.
295An incorrect program image can result in N atoms (not take branch) associated with unconditional branches which should always be taken.
296
297- `OCSD_OPFLG_N_UNCOND_DIR_BR_CHK`    : This flag will throw an error when a N atom is associated with an unconditional direct branch.
298									    (note: restricted to direct branches as some ETM ip incorrectly traces branches to next instruction as N rather then E).
299- `OCSD_OPFLG_STRICT_N_UNCOND_BR_CHK` : Check for N atoms on any unconditional branches. Use for known correct IP.
300- `OCSD_OPFLG_CHK_RANGE_CONTINUE`     : Check the start address of the range after a not taken branch is contiguous from the previous range.
301
302Each of these options will result in a decoder reset and resync - there will be an output of `OCSD_GEN_TRC_ELEM_NO_SYNC` with a reason of `UNSYNC_BAD_IMAGE`.
303
304Additional flag  `ETM4_OPFLG_PKTDEC_AA64_OPCODE_CHK` is for ETMv4 / ETE decode that adds in checks on AA64 opcodes for validity.
305
306The check ensures that the top 16 bits are not 0x0000 - which is not possible in a legal opcode.
307This can catch errors were incorrect program images can potentially cause decode to enter uninitialised data areas.
308
309
310### Adding in Memory Images ###
311
312Memory images are needed when a full trace decode is required. Memory images consist of a base address and length, and
313contain instruction opcodes that may be executed during the operation of the traced program. The images are used by
314the decoder to follow the path of the traced program by interpreting the information contained within the trace that
315defines which program branches are taken and the target addresses of those branches.
316
317Memory images are associated with a memory space. This is a combination of exception level and security state. The images can
318be associated with a specific memory space, or a larger, more generic memory space. For example a memory image can be associated
319with all secure states (@ref OCSD_MEM_SPACE_S) or just the EL2 secure state (@ref OCSD_MEM_SPACE_EL2S).
320
321The library defined memory image accessor objects, which can be simple memory buffers, files containing the binary
322code image, or a callback that allows the client to handle memory accesses directly. When files are used, the
323 object may contain a set of base addresses and lengths, with offsets into the file - allowing the decoder
324 to directly access multiple code segments in executable image files.
325
326Memory image accessor objects are collated by a memory mapper. This interfaces to the decoder through the ITargetMemAccess interface,
327and selects the correct image object for the address requested by the decoder. The memory mapper will also validate image
328objects as they are added to the decoder.
329
330![Memory Mapper and Memory Images](memacc_objs.jpg)
331
332The mapper will not permit overlapping images in a given memory space - or between a specific and more generic memory space.
333
334For example, an image registered with address 0x00000000, size 0x8000, memory space @ref OCSD_MEM_SPACE_EL2S, ( `mem[0x0000000, 0x8000, OCSD_MEM_SPACE_EL2S]`),
335will not overlap with `mem[0x0000000, 0x8000, OCSD_MEM_SPACE_EL2N]`, which has an overlapping address range but distinct memory space,
336but will overlap with `mem[0x00001000, 0x4000, OCSD_MEM_SPACE_S]`, which has both an overlappring memory range and the same memory space, as the any secure
337space OCSD_MEM_SPACE_S matches the specific EL2 secure space OCSD_MEM_SPACE_EL2S.
338
339When the decoder needs to access memory, it will call the mapper with an address, size and a specific memory space. The mapper will
340then attempt to match by address and memory space to fulfil the request. If the decoder asks for `mem[0x800000, 0x4, OCSD_MEM_SPACE_EL1N]`,
341this will match with an image object which inclues the address, in memory space OCSD_MEM_SPACE_EL1N, OCSD_MEM_SPACE_N or OCSD_MEM_SPACE_ANY.
342The prevention of overlapped memory spaces means that there will only be a single match available.
343
344__Adding and Using Memory Images__
345
346The client can add memory images to the decoder via API calls to the decode tree. These methods add memory image accessors of various
347types to be managed by a memory access mapper:-
348
349~~~{.cpp}
350	class DecodeTree {
351		// ...
352		ocsd_err_t createMemAccMapper(memacc_mapper_t type = MEMACC_MAP_GLOBAL);
353		// ...
354		ocsd_err_t addBufferMemAcc(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const uint8_t *p_mem_buffer, const uint32_t mem_length);
355		ocsd_err_t addBinFileMemAcc(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const std::string &filepath);
356		ocsd_err_t addBinFileRegionMemAcc(const ocsd_file_mem_region_t *region_array, const int num_regions, const ocsd_mem_space_acc_t mem_space, const std::string &filepath);     */
357		ocsd_err_t addCallbackMemAcc(const ocsd_vaddr_t st_address, const ocsd_vaddr_t en_address, const ocsd_mem_space_acc_t mem_space, Fn_MemAcc_CB p_cb_func, const void *p_context);
358		// ...
359	}
360~~~
361
362The `createMemAccMapper()` function must be called to create the mapper, before the `add...MemAcc()` calls are used.
363
364The C-API contains a similar set of calls to set up memory access objects:-
365
366~~~{.c}
367	OCSD_C_API ocsd_err_t ocsd_dt_add_buffer_mem_acc(const dcd_tree_handle_t handle, const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const uint8_t *p_mem_buffer, const uint32_t mem_length);
368	OCSD_C_API ocsd_err_t ocsd_dt_add_binfile_mem_acc(const dcd_tree_handle_t handle, const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const char *filepath);
369	OCSD_C_API ocsd_err_t ocsd_dt_add_binfile_region_mem_acc(const dcd_tree_handle_t handle, const ocsd_file_mem_region_t *region_array, const int num_regions, const ocsd_mem_space_acc_t mem_space, const char *filepath);
370	OCSD_C_API ocsd_err_t ocsd_dt_add_callback_mem_acc(const dcd_tree_handle_t handle, const ocsd_vaddr_t st_address, const ocsd_vaddr_t en_address, const ocsd_mem_space_acc_t mem_space, Fn_MemAcc_CB p_cb_func, const void *p_context);
371~~~
372
373Note that the C-API will automatically create a default mapper when the first memory access object is added.
374
375The global mapper currently available in the library assumes that any images loaded apply to all cores in the system,
376throughout the decode session. There is currently no mapper in the library that will distinguish memory accessors by both memory space and cpu.
377
378Therefore the choice of memory image accessor added will depend on the client.
379
380For a session where the images are static throughout the session, apply to all the cores in a system, the client can add file or buffer type memory accessor can
381be used. This is the model used by the library test program `trc_pkt_lister`.
382
383Where the memory images can change over time, and/or differ according to the processor executing the code, then a callback memory accessor is
384generally used by the client. The `perf` tool used in the Linux kernel uses a callback memory accessor when decoding trace. The tool has
385a database of loaded programs on a per cpu basis over the time of trace recording. `perf` uses the callback accessor with the address and size
386set to the entire system memory area, with a memory space set to @ref OCSD_MEM_SPACE_ANY. This allows the decoder to callback into the `perf`
387client which will then determine the correct program image according to information collected and the cpu and progress through the trace session,
388and return the correct block of memory to the decode library.
389
390
391### Adding the output callbacks ###
392
393The decoded trace output ia collect by the client application through callback functions registered with the library.
394
395Depending on the decode configuration chosen, this can be in the form of the fully decoded trace output as generic trace
396packets, or discrete trace packets for each trace stream ID.
397
398__Full Decode__
399
400When full decode is chosen then all output is via the generic packet interface:
401
402~~~{.cpp}
403	class ITrcGenElemIn
404	{
405		///...
406
407		virtual ocsd_datapath_resp_t TraceElemIn(const ocsd_trc_index_t index_sop,
408                                              const uint8_t trc_chan_id,
409                                              const OcsdTraceElement &el);
410    }
411~~~
412
413The client application registers a callback class or function with this signature.
414
415For each output packet the libary calls the registered function,  providing the byte index into the raw trace for the first
416byte of the trace protocol packet that resulted in its generation, plus the CoreSight trace ID of the source stream,
417#and the output packet itself.
418
419The client callback must process the packet before returning the call - the reference to the packet data is only
420valid for the duration of the call. This means that the client will either have to copy and buffer packets for later
421processing if required, process immediately, or use an appropriate combination, dependent on the requirements of the
422client.
423
424The client callback provides a ocsd_datapath_resp_t response code to indicate to the input side of the library if decoding is to continue.
425
426~~~{.cpp}
427	DecodeTree *pTree;
428	TrcGenericElementPrinter genElemPrinter; // derived from ITrcGenElemIn, overrides TraceElemIn() to print incoming packet to logger.
429
430	///...
431
432	pTree->setGenTraceElemOutI(genElemPrinter);
433
434~~~
435
436Alternatively in C-API, the callback function pointer type is defined:-
437
438~~~{.c}
439	typedef ocsd_datapath_resp_t (* FnTraceElemIn)( const void *p_context,
440													const ocsd_trc_index_t index_sop,
441													const uint8_t trc_chan_id,
442													const ocsd_generic_trace_elem *elem);
443~~~
444
445giving API calls to set up:-
446
447~~~{.c}
448	FnTraceElemIn gen_pkt_fn = &gen_trace_elem_analyze; // set to function matching signature.
449	dcd_tree_handle_t dcdtree_handle;
450
451	// ...
452
453	ret = ocsd_dt_set_gen_elem_outfn(dcdtree_handle, gen_pkt_fn, 0);
454~~~
455
456The output packets and their intepretatation are described here [prog_guide_generic_pkts.md](@ref generic_pkts).
457
458__Packet Process only, or Monitor packets in Full Decode__
459
460The client can set up the library for packet processing only, in which case the library output is
461the trace packets only, so these packets need a sink callback for each channel being output.
462
463When full decode is in operation, then the principle output is the generic packets that are output for
464all channels in operation to the single callback mentioned above. Additional callbacks can be added to
465each of the trace channels to monitor the packet processing stage as it happens at point that the packets
466are passed to the full decoder.
467
468Both methods of processing the discrete trace packets require callbacks to be registered on a
469per Trace ID / channel basis. The specifics of the callback and the resulting packet will vary according to
470the protocol of the trace source.
471
472The .cpp interface registers a packet sink / packet monitor object with the relevant decoder object.
473
474This sink object is based on the tempated IPktDataIn interface.
475
476~~~{.cpp}
477template<class P> class IPktDataIn : public ITrcTypedBase {
478	// ...
479	    virtual ocsd_datapath_resp_t PacketDataIn( const ocsd_datapath_op_t op,
480                                                const ocsd_trc_index_t index_sop,
481                                                const P *p_packet_in) = 0;
482}
483~~~
484
485The template type parameter will be the protocol type for the trace source in question - e.g. EtmV4ITrcPacket.
486This interface contains a method that will be called with trace packets.
487
488The monitor object must be based on the IPktRawDataMon class, with a similarly typed template parameter and callback
489function.
490
491~~~{.cpp}
492template<class P> class IPktRawDataMon : public ITrcTypedBase {
493	// ...
494	    virtual void RawPacketDataMon( const ocsd_datapath_op_t op,
495                                   const ocsd_trc_index_t index_sop,
496                                   const P *pkt,
497                                   const uint32_t size,
498                                   const uint8_t *p_data) = 0;
499}
500~~~
501
502Given a suitable callback object the process for attaching to the decode is as follows:-
503
504~~~{.cpp}
505	// client custom packet sink for ETMv4 - derived from IPktDataIn
506	class MyTracePacketSinkETMv4 : public IPktDataIn<EtmV4ITrcPacket> {
507		// ...
508	};
509
510	uint8_t CSID;
511	DecodeTree *pTree;	// pointer to decode tree
512    MyTracePacketSinkETMv4 *pSink;
513
514	// ... obtain CSID and decode tree object
515
516	// decode trees manage decode elements using a tree element object, registered against CSID.
517    DecodeTreeElement *pElement = pTree->getDecoderElement(CSID);
518	pSink = new MyTracePacketSinkETMv4();
519	if (pElement && pSink)
520		err = pElement->getDecoderMngr()->attachPktSink(pElement->getDecoderHandle(), pSink);
521
522~~~
523
524The decode tree object is used to obtain the decode tree element associated with the Coresight trace ID.
525The IDecoderMngr interface on this object is used to attach the packet sink object to the required decoder.
526
527For monitor objects use an attachPktMonitor() call with a suitably derived monitor sink object.
528
529The key difference between the packet sink, and the packet monitor is that the monitor is not in the trace decode
530data path, so does not return ocsd_datapath_resp_t values. The monitor callback also provides the raw trace byte
531data for the packet.
532
533Device tree call for registering a callback in C-API and the function signatures for each type of shown below..
534The C-API code contains underlying managment code that connects the callback with the correct packet decoder object.
535
536~~~{.c}
537OCSD_C_API ocsd_err_t ocsd_dt_attach_packet_callback(  const dcd_tree_handle_t handle,    // decode tree handle
538                                                const unsigned char CSID,				  // trace channel ID
539                                                const ocsd_c_api_cb_types callback_type,  // defines packet only processing sink or monitor function signature.
540                                                void *p_fn_callback_data,                 // pointer to the callback function for the packet data.
541                                                const void *p_context);				      // opaque context to use inside the callback.
542~~~
543
544Callback definition for packet only sink callback type:
545~~~{.c}
546/** function pointer type for packet processor packet output sink, packet analyser/decoder input - generic declaration */
547typedef ocsd_datapath_resp_t (* FnDefPktDataIn)(const void *p_context,
548                                                const ocsd_datapath_op_t op,
549                                                const ocsd_trc_index_t index_sop,
550                                                const void *p_packet_in
551												);
552~~~
553
554Callback  definition for packet monitor callback type
555~~~{.c}
556/** function pointer type for packet processor packet monitor sink, raw packet monitor / display input - generic declaration */
557typedef void (* FnDefPktDataMon)(const void *p_context,
558                                 const ocsd_datapath_op_t op,
559                                 const ocsd_trc_index_t index_sop,
560                                 const void *p_packet_in,
561                                 const uint32_t size,
562                                 const uint8_t *p_data
563								 );
564~~~
565
566As with the `.cpp` code, the monitor callback does not have a return value, but also has the raw trace bytes for the packet as part of
567the monitor.
568
569In both cases in the C-API, the `void *p_packet_in` must be cast to packet structure appropriate to the trace protocol associated with the
570CSID value. e.g. for ETMv4 this would be @ref ocsd_etmv4_i_pkt.
571
572
573Programming Examples - using the configured Decode Tree.
574--------------------------------------------------------
575
576Once the decode tree has been configured then data raw trace data can be processed through the decode tree.
577
578The client program will require two functions to use the library. The first is on the input side of the library
579which must be driven with raw data, until the data is complete, or an error occurs. This processing routine must
580check the library returns and respond appropriately.
581
582The second consists of output callback(s) which process the decoded generic packets, or trace packets.
583This routine will return response codes according to the needs of the client.
584
585![Trace Data call and response path](decode_data_path_resp.jpg)
586
587The diagram shows the data input and response path. The data is driven into the decoding library by the client raw data input
588routine on the left. Processed packets are received by the client packet callback(s) on the right, and push response codes back
589through the library.
590
591The raw data input routine calls the standard ITrcDataIn interface with an operation code, and if appropriate some raw
592trace data. The input operation code will define how the library treats the input parameters.
593
594
595| Operation          | Description                                                      | Trace Data provided |
596|:-------------------|:-----------------------------------------------------------------|:--------------------|
597| @ref OCSD_OP_DATA  | Process data provided by data pointer parameters.                | Yes                 |
598| @ref OCSD_OP_FLUSH | Call after prior wait response - finish processing previous data | No                  |
599| @ref OCSD_OP_EOT   | End of trace data. Library will complete any pending decode.     | No                  |
600| @ref OCSD_OP_RESET | Hard reset of decoder state - use current config for new data    | No                  |
601
602A set of standard responses is used to indicate to the raw data input whether it should continue to push data through the library,
603pause and then flush, or if a fatal processing error has occurred.
604
605The response codes can come from the internal library decoder, or from the part of the client that is handling the processing of the
606output packets on the right of the diagram.
607
608_Response Codes_: The are contained in the @ref _ocsd_datapath_resp_t enum.
609
610- __OCSD_RESP_CONT, OCSD_RESP_CONT_xxx__: 	Indicates that processing is to continue. Generated either internally by the library if more data
611										is needed to generate an output packet, or by the output packet processors to indicate processing
612										is to continue.
613- __OCSD_RESP_WAIT, OCSD_RESP_WAIT_xxx:__   Sent by the client processors to pause processing. This will freeze the internal state of the library
614									    and cause the WAIT response to be propogated through to the input side, with an indication of the number
615									    of bytes processed. After a WAIT, the input side must respond with flush operations, until a CONT is
616										seen again and further data can then be input into the library.
617- __OCSR_RESP_FATAL_xxx__:                  Fatal processing error. No further processing can take place. See error response logger for reason.
618                                        Normally the result of corrupt or incorrect trace data.
619
620The user should note that the client program controls routines on both the input and output side of the library. The output routine may be buffering
621output packets, and when the buffer is full, returns a WAIT ressponse. This will be propgated through to the input routine. This should now terminate
622data processing, saving state and the client will run a routine to empty / process the full packet buffer. Once the necessary processing is done,
623then the input routine can be restarted, but __must__ follow the FLUSH operational rule described above.
624
625Excerpts from the data input routine used by the `trc_pkt_lister` program are shown below:
626
627~~~{.cpp}
628                   // process the current buffer load until buffer done, or fatal error occurs
629                    while((nBuffProcessed < nBuffRead) && !OCSD_DATA_RESP_IS_FATAL(dataPathResp))
630                    {
631                        if(OCSD_DATA_RESP_IS_CONT(dataPathResp))
632                        {
633                            dataPathResp = dcd_tree->TraceDataIn(
634                                OCSD_OP_DATA,
635                                trace_index,
636                                (uint32_t)(nBuffRead - nBuffProcessed),
637                                &(trace_buffer[0])+nBuffProcessed,
638                                &nUsedThisTime);
639
640                            nBuffProcessed += nUsedThisTime;
641                            trace_index += nUsedThisTime;
642
643                        }
644                        else // last response was _WAIT
645                        {
646                            // may need to acknowledge a wait from the gen elem printer
647                            if(genElemPrinter->needAckWait())
648                                genElemPrinter->ackWait();
649
650                            // dataPathResp not continue or fatal so must be wait...
651                            dataPathResp = dcd_tree->TraceDataIn(OCSD_OP_FLUSH,0,0,0,0);
652                        }
653                    }
654
655~~~
656
657_Note_: in this test program, the WAIT response is an artificial test condition, so the input routine does not terminate on seeing it - it is cleared down
658and FLUSH is immediately sent. Normal client routines would most likely drop out of the processing loop, take actions to clear the WAIT condition, then
659resume processing with a FLUSH.
660
661See the `trc_pkt_lister` and `c_api_pkt_print_test` test program source code for further examples of driving data through the library.
662