#ifndef ARM_OCSD_DCD_TREE_H_INCLUDED
#define ARM_OCSD_DCD_TREE_H_INCLUDED
#include <vector>
#include <list>
#include "opencsd.h"
#include "ocsd_dcd_tree_elem.h"
class DecodeTree : public ITrcDataIn
{
public:
DecodeTree(); ~DecodeTree();
static DecodeTree *CreateDecodeTree(const ocsd_dcd_tree_src_t src_type, const uint32_t formatterCfgFlags);
static void DestroyDecodeTree(DecodeTree *p_dcd_tree);
static ocsdDefaultErrorLogger* getDefaultErrorLogger() { return &s_error_logger; };
static ITraceErrorLog *getCurrentErrorLogI() { return s_i_error_logger; };
static void setAlternateErrorLogger(ITraceErrorLog *p_error_logger);
std::vector<ItemPrinter *> &getPrinterList() { return m_printer_list; };
ocsd_err_t addPacketPrinter(uint8_t CSID, bool bMonitor, ItemPrinter **ppPrinter);
ocsd_err_t addRawFramePrinter(RawFramePrinter **ppPrinter, uint32_t flags);
ocsd_err_t addGenElemPrinter(TrcGenericElementPrinter **ppPrinter);
virtual ocsd_datapath_resp_t TraceDataIn( const ocsd_datapath_op_t op,
const ocsd_trc_index_t index,
const uint32_t dataBlockSize,
const uint8_t *pDataBlock,
uint32_t *numBytesProcessed);
void setGenTraceElemOutI(ITrcGenElemIn *i_gen_trace_elem);
ITrcGenElemIn *getGenTraceElemOutI() const { return m_i_gen_elem_out; };
ocsd_err_t createDecoder(const std::string &decoderName, const int createFlags, const CSConfig *pConfig);
ocsd_err_t removeDecoder(const uint8_t CSID);
ocsd_err_t getDecoderStats(const uint8_t CSID, ocsd_decode_stats_t **p_stats_block);
ocsd_err_t resetDecoderStats(const uint8_t CSID);
DecodeTreeElement *getDecoderElement(const uint8_t CSID) const;
DecodeTreeElement *getFirstElement(uint8_t &elemID);
DecodeTreeElement *getNextElement(uint8_t &elemID);
void setInstrDecoder(IInstrDecode *i_instr_decode);
void setMemAccessI(ITargetMemAccess *i_mem_access);
ocsd_err_t createMemAccMapper(memacc_mapper_t type = MEMACC_MAP_GLOBAL);
TrcMemAccMapper *getMemAccMapper() const { return m_default_mapper; };
void setExternMemAccMapper(TrcMemAccMapper * pMapper);
const bool hasMemAccMapper() const { return (bool)(m_default_mapper != 0); };
void logMappedRanges();
ocsd_err_t setMemAccCacheing(const bool enable, const uint16_t page_size, const int nr_pages);
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);
ocsd_err_t addBinFileMemAcc(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const std::string &filepath);
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);
ocsd_err_t updateBinFileRegionMemAcc(const ocsd_file_mem_region_t *region_array, const int num_regions, const ocsd_mem_space_acc_t mem_space, const std::string &filepath);
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);
ocsd_err_t addCallbackIDMemAcc(const ocsd_vaddr_t st_address, const ocsd_vaddr_t en_address, const ocsd_mem_space_acc_t mem_space, Fn_MemAccID_CB p_cb_func, const void *p_context);
ocsd_err_t removeMemAccByAddress(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space);
TraceFormatterFrameDecoder *getFrameDeformatter() const { return m_frame_deformatter_root; };
ocsd_err_t setIDFilter(std::vector<uint8_t> &ids);
ocsd_err_t clearIDFilter();
private:
bool initialise(const ocsd_dcd_tree_src_t type, uint32_t formatterCfgFlags);
const bool usingFormatter() const { return (bool)(m_dcd_tree_type == OCSD_TRC_SRC_FRAME_FORMATTED); };
void setSingleRoot(TrcPktProcI *pComp);
ocsd_err_t createDecodeElement(const uint8_t CSID);
void destroyDecodeElement(const uint8_t CSID);
void destroyMemAccMapper();
ocsd_err_t initCallbackMemAcc(const ocsd_vaddr_t st_address, const ocsd_vaddr_t en_address,
const ocsd_mem_space_acc_t mem_space, void *p_cb_func, bool IDfn, const void *p_context);
TrcPktProcI *getPktProcI(const uint8_t CSID);
void addMemAccessorToList(TrcMemAccessorBase* p_accessor);
void destroyMemAccessors();
ocsd_dcd_tree_src_t m_dcd_tree_type;
IInstrDecode *m_i_instr_decode;
ITargetMemAccess *m_i_mem_access;
ITrcGenElemIn *m_i_gen_elem_out;
ITrcDataIn* m_i_decoder_root;
TraceFormatterFrameDecoder *m_frame_deformatter_root;
DecodeTreeElement *m_decode_elements[0x80];
uint8_t m_decode_elem_iter;
TrcMemAccMapper *m_default_mapper; bool m_created_mapper;
std::vector<ItemPrinter *> m_printer_list;
static ITraceErrorLog *s_i_error_logger;
static std::list<DecodeTree *> s_trace_dcd_trees;
static ocsdDefaultErrorLogger s_error_logger;
static TrcIDecode s_instruction_decoder;
ocsd_demux_stats_t m_demux_stats;
std::list<TrcMemAccessorBase*> m_mem_accessors;
};
#endif