OpenCores
URL https://opencores.org/ocsvn/riscv_vhdl/riscv_vhdl/trunk

Subversion Repositories riscv_vhdl

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /riscv_vhdl/trunk/debugger/src/common
    from Rev 3 to Rev 4
    Reverse comparison

Rev 3 → Rev 4

/api_core.h
1,426 → 1,201
/**
* @file
* @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Core API methods declaration.
*/
/**
* @page dbg_overview Overview
*
* @par Overview
* This debugger was specially developed as a software utility to interact
* with our SOC implementation in \c riscv_soc repository. The main
* purpose was to provide convinient way to develop and debug our
* Satellite Navigation firmware that can not be debugged by any other
* tool provided RISC-V community. Additionally, we would like to use
* the single unified application capable to work with Real and Simulated
* platforms without any modification of source code.
* Debugger provides base functionality such as: run control,
* read/write memory, registers and CSRs, breakpoints. It allows to
* reload FW image and reset target.
* Also we are developing own version of the CPU simulator
* (analog of \c spike) that can be extended with peripheries models to
* Full SOC simulator. These extensions for the debugger simplify
* porting procedure (Zephyr OS for an example) so that
* simulation doesn't require any hardware and allows to develop SW and HW
* simultaneously.
*
*/
 
/**
* @defgroup dbg_prj_structure_g Project structure
* @ingroup debugger_group
* @page dbg_prj_structure Project structure
*
* General idea of the project is to develop one \c Core library
* providing API methods for registering \c classes, \c services, \c attributes
* and methods to interact with them. Each extension plugin registers one or
* several class services performing some usefull work. All plugins are
* built as an independent libraries that are opening by \c Core library
* at initialization stage with the call of method <b>plugin_init()</b>.
* All Core API methods start with \c RISCV_... prefix:
* @code
* void RISCV_register_class(IFace *icls);
*
* IFace *RISCV_create_service(IFace *iclass, const char *name,
* AttributeType *args);
*
* IFace *RISCV_get_service(const char *name);
* ...
* @endcode
*
* Configuration of the debugger and plugins is fully described in JSON
* formatted configuration files <b>targets/target_name.json</b>.
* These files store all instantiated services names, attributes values
* and interconnect among plugins.
* This configuration can be saved to/load from file at any
* time. By default command \c exit will save current debugger state into
* file (including full command history).
*
* @note You can manually add/change new Registers/CSRs names and indexes
* by modifying this config file without changing source code.
*
* @par Folders description
* -# \b libdgb64g - Core library (so/dll) that provides standard API
* methods defined in file \c api_core.h.
* -# \b appdbg64g - Executable (exe) file implements functionality of
* the console debugger.
* -# \a Plugins:
* -# \b simple_plugin - Simple plugin (so/dll library) just for
* demonstration of the integration with debugger.
* -# \b cpu_fnc_plugin - Functional model of the RISC-V CPU
* (so/dll library).
* -# \b cpu_sysc_plugin - Precise SystemC model of RIVER CPU
* (so/dll library).
* -# \b socsim_plugin - Functional models of the peripheries
* and assembled board (so/dll library). This plugin
* registers several classes: \c UART, \c GPIO, \c SRAM,
* \c ROMs and etc.
*/
 
/**
* @defgroup dbg_connect_g Debug session
* @ingroup debugger_group
* @page dbg_connect Debug session
*
* @section dbg_connect_1 Plugins interaction
*
* Core library uses UDP protocol to communicate with all targets: FPGA or
* simulators. The general structure is looking like on the following figure:
*
* <img src="pics/dbg_sim.png" alt="sim debug">
* @latexonly {\includegraphics[scale=0.9]{pics/dbg_sim.png}} @endlatexonly
*
* or with real Hardware
*
* <img src="pics/dbg_fpga.png" alt="fpga debug">
* @latexonly {\includegraphics[scale=0.8]{pics/dbg_fpga.png}} @endlatexonly
*
* GUI plugin uses QT-libraries and interacts with the core library using the
* text console input interface. GUI generates the same text commands
* that are available in debugger console for any who's using this debugger.
* That's why any presented in GUI widgets information can be achieved
* in console mode.
*
* @section dbg_connect_2 Start Debugger
*
* We provide several targets that can run software (bootloader, firmware
* or user specific application) without any source code modifications:
*
* Start Configuration | Description
* -------------------------------|-----------------
* $ ./_run_functional_sim.sh[bat]| Functional RISC-V Full System Model
* $ ./_run_systemc_sim.sh[bat] | Use SystemC Precise Model of RIVER CPU
* $ ./_run_fpga_gui.sh[bat] | FPGA board. Default port 'COM3', TAP IP = 192.168.0.51
*
* To run debugger with the real FPGA target connected via Ethernet do:
* @code
* # cd rocket_soc/debugger/win32build/debug
* # _run_functional_sim.bat
* @endcode
*
* The result should look like on the picture below:
*
* <img src="pics/dbg_gui_start.png" alt="debugger 1-st look">
* @latexonly {\includegraphics[scale=0.8]{pics/dbg_gui_start.png}} @endlatexonly
*
* @par Example of the debug session
* Switch ON all User LEDs on board:
* @code
* riscv# help -- Print full list of commands
* riscv# csr MCPUID -- Read supported ISA extensions
* riscv# read 0xfffff000 20 -- Read 20 bytes from PNP module
* riscv# write 0x80000000 4 0xff -- Write into GPIO new LED value
* riscv# loadelf helloworld -- Load elf-file to board RAM and run
* @endcode
*
* Console mode view
*
* <img src="pics/dbg_testhw.png" alt="HW debug example">
* @latexonly {\includegraphics{pics/dbg_testhw.png}} @endlatexonly
*
* @section dbg_connect_3 Debug Zephyr OS kernel with symbols
*
* Build Zephyr kernel from scratch using our patches enabling 64-bits RISC-V
* architecture support:
* @code
* $ mkdir zephyr_160
* $ cd zephyr_160
* $ git clone https://gerrit.zephyrproject.org/r/zephyr
* $ cd zephyr
* $ git checkout tags/v1.6.0
* $ cp ../../riscv_vhdl/zephyr/v1.6.0-riscv64-base.diff .
* $ cp ../../riscv_vhdl/zephyr/v1.6.0-riscv64-exten.diff .
* $ git apply v1.6.0-riscv64-base.diff
* $ git apply v1.6.0-riscv64-exten.diff
* @endcode
*
* Then build elf-file:
* @code
* $ export ZEPHYR_BASE=/home/zephyr_160/zephyr
* $ cd zephyr/samples/shell
* $ make ARCH=riscv64 CROSS_COMPILE=/home/your_path/gnu-toolchain-rv64ima/bin/riscv64-unknown-elf- BOARD=riscv_gnss 2>&1
* @endcode
*
* Load debug symbols from elf-file without target reprogramming (or with):
* @code
* riscv# loadelf zephyr.elf
* riscv# loadelf zephyr.elf nocode
* @endcode
*
* <img src="pics/dbg_gui_symb.png" alt="debugger symbols">
* @latexonly {\includegraphics[scale=0.8]{pics/dbg_gui_symb.png}} @endlatexonly
*
* Now becomes available the following features:
* - Stack trace with function names
* - Function names in Disassembler including additional information for
* branch and jump instructions in column \c 'comment'.
* - Symbol Browser with filter.
* - Opening Disassembler and Memory Viewer widgets in a new window by name.
*
* Debugger provides additional features that could simplify software
* development:
* - Clock Per Instruction (CPI) hardware measure
* - Bus utilization information
* - Others. List of a new features is constantly increasing.
*
* <img src="pics/dbg_fpga_gui1.png" alt="debugger FPGA+GUI">
* @latexonly {\includegraphics[scale=0.8]{pics/dbg_fpga_gui1.png}} @endlatexonly
*
*/
 
/**
* @defgroup dbg_troubles_g Troubleshooting
* @ingroup debugger_group
* @page dbg_troubles Troubleshooting
*
* @subpage dbg_trouble_1
*
* @subpage dbg_trouble_2
*
* @subpage dbg_trouble_3
*
*/
 
/**
* @defgroup dbg_trouble_1_g Image Files not found
* @ingroup dbg_troubles_g
* @page dbg_trouble_1 Image Files not found
*
* If you'll get the error messages that image files not found
*
* <img src="pics/dbg_err1.png" alt="File not found">
* @latexonly {\includegraphics[scale=0.8]{pics/dbg_err1.png}} @endlatexonly
*
* To fix this problem do the following steps:
* -# Close debugger console using \c exit command.
* -# Open <em>config_file_name.json</em> file in any editor.
* -# Find strings that specify these paths and correct them. Simulator
* uses the same images as VHDL platform for ROMs intialization. You can find
* them in <em>'rocket_soc/fw_images'</em> directory. After that you should
* see something like follow:
*
* <img src="pics/dbg_simout1.png" alt="Simulator output">
* @latexonly {\includegraphics[scale=0.8]{pics/dbg_simout1.png}} @endlatexonly
*
* Debug your target. All commands that are available for Real Hardware
* absolutely valid for the Simulation. Users shouldn't see any difference
* between these targets this is our purpose.
*/
 
/**
* @defgroup dbg_trouble_2_g Can't open COM3 when FPGA is used
* @ingroup dbg_troubles_g
* @page dbg_trouble_2 Can't open COM3 when FPGA is used
*
* -# Open <em>fpga_gui.json</em>
* -# Change value <b>['ComPortName','COM3'],</b> on your one
* (for an example on \c ttyUSB0).
*
*/
 
/**
* @defgroup dbg_trouble_3_g EDCL: No response. Break read transaction
* @ingroup dbg_troubles_g
* @page dbg_trouble_3 EDCL: No response. Break read transaction
*
* This error means that host cannot locate board with specified IP address.
* Before you continue pass through the following checklist:
* -# You should properly @link eth_link setup network connection @endlink
* and see FPGA board in ARP-table.
* -# If you've changed default FPGA IP address:
* -# Open <em>_run_fpga_gui.bat (*.sh)</em>
* -# Change value <b>['BoardIP','192.168.0.51']</b> on your one.
* -# Run debugger
*
*/
 
#ifndef __DEBUGGER_API_CORE_H__
#define __DEBUGGER_API_CORE_H__
 
#include "api_utils.h"
#include "iface.h"
#include "attribute.h"
 
namespace debugger {
 
#ifdef __cplusplus
extern "C" {
#endif
 
/**
* @defgroup dbg_core_api_g Core API methods
* @ingroup debugger_group
* @details Core methods that allow create, modify and delete base library
* objects such as: Attributes, Classes, Services and Interfaces
* @{
*/
 
/**
* @brief Library initialization.
* @details This method must be called before any other from this library.
*/
int RISCV_init();
 
/**
* @brief Destroy and cleanup all dynamically allocated objects.
* @details This method allows gracefully close library by stopping all running
* threads and free allocated resources.
*/
void RISCV_cleanup();
 
/**
* @brief Set core library configuration.
* @details Configuration specify all instantiated services and interconnect
* among them.
* @param [in] cfg Configuration attribute.
*/
int RISCV_set_configuration(AttributeType *cfg);
 
/**
* @brief Read library configuration.
* @details This method allows serialize library state and save configuration
* into the file in JSON format. Afterward configuration can be
* restored.
*/
const char *RISCV_get_configuration();
 
/**
* @brief Get current core configuration.
* @details JSON configuration string implements special section \c 'Global'
* that contains parameters not related to any specific service or
* class.
*/
const AttributeType *RISCV_get_global_settings();
 
/**
* @brief Registration of the class in the library kernel.
* @details Registering interface pointer will be put into kernel list of
* classes. Any plugin can add its own class interfaces.
* @param [in] icls Pointer on new class interface.
*/
void RISCV_register_class(IFace *icls);
 
/**
* @brief Registration of the system event (hap) listener.
* @details Haps are used to synchronized different threads by a specific
* events in a system. Now there's used such haps as:
* - ConfigDone
* - Breakpoint
*/
void RISCV_register_hap(IFace *ihap);
 
/**
* @brief Trigger system event (hap) from Service.
* @details This method allows to call all registered listeneres of a specific
* event from running Service.
*/
void RISCV_trigger_hap(IFace *isrc, int type, const char *descr);
 
/**
* @brief Get registred class interface by its name.
* @details This method generally used to create instances of a specific
* service.
*/
IFace *RISCV_get_class(const char *name);
 
/**
* @brief Create service of the specified class.
* @details This method creates intstance of Service and assignes all
* registered attributes to its initial values.
*/
IFace *RISCV_create_service(IFace *iclass, const char *name,
AttributeType *args);
 
/**
* @brief Get IService interface by its name.
* @details This method is used for interaction of different services in a
* system.
*/
IFace *RISCV_get_service(const char *name);
 
/**
* @brief Get interface of the specified ervice.
* @details This method can be used in runtime to implement dynamic connection
* of different services
* @code
* ...
* IUdp *iudp1 = static_cast<IUdp *>
* (RISCV_get_service_iface("udpboard", IFACE_UDP));
* ...
* @endcode
*/
IFace *RISCV_get_service_iface(const char *servname, const char *facename);
 
/**
* @brief Get list of services implementing specific interface.
* @details This method can return list of services of different classes
* and implementing different functionality.
*/
void RISCV_get_services_with_iface(const char *iname, AttributeType *list);
 
 
/**
* @brief Get list of all clock generators.
* @details Clock generator must implement IClock (and usually IThread)
* interfaces. CPU is a most general clock generator.
*/
void RISCV_get_clock_services(AttributeType *list);
 
 
/**
* @brief Break all threads that could be run by different services.
* @details This method gracefully stops all threads and allows to avoid
* simulation hanging on library closing stage.
*/
void RISCV_break_simulation();
 
/**
* @brief Run main loop in main thread
*/
void RISCV_dispatcher_start();
 
/**
* @brief callback from the main thread function prototype
*/
typedef void (*timer_callback_type)(void *args);
 
/**
* @brief Register timer's callback in main loop
*/
void RISCV_register_timer(int msec, int single_shot,
timer_callback_type cb, void *args);
 
/**
* @brief Unregister timer's callback from main loop
*/
void RISCV_unregister_timer(timer_callback_type cb);
 
 
#ifdef __cplusplus
}
#endif
 
} // namespace debugger
 
#endif // __DEBUGGER_API_CORE_H__
/*
* Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
#ifndef __DEBUGGER_API_CORE_H__
#define __DEBUGGER_API_CORE_H__
 
#include <api_utils.h>
#include <iface.h>
#include <attribute.h>
 
namespace debugger {
 
#ifdef __cplusplus
extern "C" {
#endif
 
/**
* @defgroup dbg_core_api_g Core API methods
* @ingroup debugger_group
* @details Core methods that allow create, modify and delete base library
* objects such as: Attributes, Classes, Services and Interfaces
* @{
*/
 
/**
* @brief Library initialization.
* @details This method must be called before any other from this library.
*/
int RISCV_init();
 
/**
* @brief Destroy and cleanup all dynamically allocated objects.
* @details This method allows gracefully close library by stopping all running
* threads and free allocated resources.
*/
void RISCV_cleanup();
 
/**
* @brief Set core library configuration.
* @details Configuration specify all instantiated services and interconnect
* among them.
* @param [in] cfg Configuration attribute.
*/
int RISCV_set_configuration(AttributeType *cfg);
 
/**
* @brief Read library configuration.
* @details This method allows serialize library state and save configuration
* into the file in JSON format. Afterward configuration can be
* restored.
*/
void RISCV_get_configuration(AttributeType *cfg);
 
/**
* @brief Get current core configuration.
* @details JSON configuration string implements special section \c 'Global'
* that contains parameters not related to any specific service or
* class.
*/
const AttributeType *RISCV_get_global_settings();
 
/**
* @brief Registration of the class in the library kernel.
* @details Registering interface pointer will be put into kernel list of
* classes. Any plugin can add its own class interfaces.
* @param [in] icls Pointer on new class interface.
*/
void RISCV_register_class(IFace *icls);
 
/**
* @brief Registration of the system event (hap) listener.
* @details Haps are used to synchronized different threads by a specific
* events in a system. Now there's used such haps as:
* - ConfigDone
* - Breakpoint
*/
void RISCV_register_hap(IFace *ihap);
 
/**
* @brief Trigger system event (hap) from Service.
* @details This method allows to call all registered listeneres of a specific
* event from running Service.
*/
void RISCV_trigger_hap(IFace *isrc, int type, const char *descr);
 
/**
* @brief Get registred class interface by its name.
* @details This method generally used to create instances of a specific
* service.
*/
IFace *RISCV_get_class(const char *name);
 
/**
* @brief Create service of the specified class.
* @details This method creates intstance of Service and assignes all
* registered attributes to its initial values.
*/
IFace *RISCV_create_service(IFace *iclass, const char *name,
AttributeType *args);
 
/**
* @brief Get IService interface by its name.
* @details This method is used for interaction of different services in a
* system.
*/
IFace *RISCV_get_service(const char *name);
 
/**
* @brief Get interface of the specified device.
* @details This method can be used in runtime to implement dynamic connection
* of different services
* @code
* ...
* IUdp *iudp1 = static_cast<IUdp *>
* (RISCV_get_service_iface("udpboard", IFACE_UDP));
* ...
* @endcode
*/
IFace *RISCV_get_service_iface(const char *servname, const char *facename);
 
/**
* @brief Get interface of the specified device:port.
* @details This method can be used in runtime to implement dynamic connection
* of different services and their ports
* @code
* ...
* IMemoryOperation *imem = static_cast<IMemoryOperation *>
* (RISCV_get_service_port_iface("mem0", "port0",
* IFACE_MEMORY_OPERATION));
* ...
* @endcode
*/
IFace *RISCV_get_service_port_iface(const char *servname,
const char *portname,
const char *facename);
 
/**
* @brief Get list of services implementing specific interface.
* @details This method can return list of services of different classes
* and implementing different functionality.
*/
void RISCV_get_services_with_iface(const char *iname, AttributeType *list);
 
 
/**
* @brief Get list of all clock generators.
* @details Clock generator must implement IClock (and usually IThread)
* interfaces. CPU is a most general clock generator.
*/
void RISCV_get_clock_services(AttributeType *list);
 
 
/**
* @brief Break all threads that could be run by different services.
* @details This method gracefully stops all threads and allows to avoid
* simulation hanging on library closing stage.
*/
void RISCV_break_simulation();
 
/**
* @brief Run main loop in main thread
*/
void RISCV_dispatcher_start();
 
/**
* @brief callback from the main thread function prototype
*/
typedef void (*timer_callback_type)(void *args);
 
/**
* @brief Register timer's callback in main loop
*/
void RISCV_register_timer(int msec, int single_shot,
timer_callback_type cb, void *args);
 
/**
* @brief Unregister timer's callback from main loop
*/
void RISCV_unregister_timer(timer_callback_type cb);
 
 
#ifdef __cplusplus
}
#endif
 
} // namespace debugger
 
#endif // __DEBUGGER_API_CORE_H__
/api_types.h
1,89 → 1,175
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Common library types definition.
*/
 
#ifndef __DEBUGGER_API_TYPES_H__
#define __DEBUGGER_API_TYPES_H__
 
#include <inttypes.h>
#if defined(_WIN32) || defined(__CYGWIN__)
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <windows.h>
#include <ws2tcpip.h>
#include <process.h>
#include <conio.h> // console input/output
#else /* Linux */
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netdb.h>
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include <pthread.h>
#include <fcntl.h>
#include <termios.h> // work with console
#endif
 
namespace debugger {
 
#if defined(_WIN32) || defined(__CYGWIN__)
typedef SOCKET socket_def;
typedef int addr_size_t;
 
typedef CRITICAL_SECTION mutex_def;
typedef void *thread_def; // HANDLE = void*
typedef struct event_def {
void *cond; // HANDLE = void*
bool state;
} event_def;
typedef unsigned thread_return_t;
typedef thread_return_t (__stdcall* lib_thread_func)(void *args);
 
#define RV_PRI64 "I64"
#else /* Linux */
typedef int socket_def;
typedef unsigned int addr_size_t;
typedef pthread_t thread_def;
typedef pthread_mutex_t mutex_def;
typedef struct event_def {
pthread_mutex_t mut;
pthread_cond_t cond;
bool state;
} event_def;
typedef void *thread_return_t;
typedef thread_return_t (*lib_thread_func)(void *args);
 
# if defined(__WORDSIZE) && (__WORDSIZE == 64)
# define RV_PRI64 "l"
# else
# define RV_PRI64 "ll"
# endif
#endif
 
typedef struct LibThreadType
{
lib_thread_func func;
void *args;
thread_def Handle;
} LibThreadType;
 
union Reg64Type {
uint8_t buf[8];
uint16_t buf16[4];
uint32_t buf32[2];
uint64_t val;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_API_TYPES_H__
/*
* Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
#ifndef __DEBUGGER_COMMON_API_TYPES_H__
#define __DEBUGGER_COMMON_API_TYPES_H__
 
#include <inttypes.h>
#if defined(_WIN32) || defined(__CYGWIN__)
// Exclude rarely-used stuff from Windows headers
#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <windows.h>
#include <ws2tcpip.h>
#include <process.h>
#include <conio.h> // console input/output
#else /* Linux */
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netdb.h>
#define __STDC_FORMAT_MACROS
#include <pthread.h>
#include <fcntl.h>
#include <termios.h> // work with console
#include <errno.h>
#endif
 
namespace debugger {
 
#if defined(_WIN32) || defined(__CYGWIN__)
typedef SOCKET socket_def;
typedef int addr_size_t;
 
typedef CRITICAL_SECTION mutex_def;
typedef void *thread_def; // HANDLE = void*
typedef struct event_def {
void *cond; // HANDLE = void*
bool state;
} event_def;
typedef unsigned thread_return_t;
typedef thread_return_t (__stdcall* lib_thread_func)(void *args);
typedef void *sharemem_def; // HANDLE = void*
 
#define RV_PRI64 "I64"
#else /* Linux */
typedef int socket_def;
typedef unsigned int addr_size_t;
typedef pthread_t thread_def;
typedef pthread_mutex_t mutex_def;
typedef struct event_def {
pthread_mutex_t mut;
pthread_cond_t cond;
bool state;
} event_def;
typedef void *thread_return_t;
typedef thread_return_t (*lib_thread_func)(void *args);
typedef int sharemem_def;
 
# if defined(__WORDSIZE) && (__WORDSIZE == 64)
# define RV_PRI64 "l"
# else
# define RV_PRI64 "ll"
# endif
#endif
 
typedef struct LibThreadType {
lib_thread_func func;
void *args;
thread_def Handle;
} LibThreadType;
 
union Reg8Type {
uint8_t byte;
int8_t sbyte;
struct bits_type {
uint8_t b0 : 1;
uint8_t b1 : 1;
uint8_t b2 : 1;
uint8_t b3 : 1;
uint8_t b4 : 1;
uint8_t b5 : 1;
uint8_t b6 : 1;
uint8_t b7 : 1;
} bits;
};
 
union Reg16Type {
uint8_t buf[2];
uint16_t word;
Reg8Type r8[2];
struct bits_type {
uint16_t b0 : 1;
uint16_t b1 : 1;
uint16_t b2 : 1;
uint16_t b3 : 1;
uint16_t b4 : 1;
uint16_t b5 : 1;
uint16_t b6 : 1;
uint16_t b7 : 1;
uint16_t b8 : 1;
uint16_t b9 : 1;
uint16_t b10 : 1;
uint16_t b11 : 1;
uint16_t b12 : 1;
uint16_t b13 : 1;
uint16_t b14 : 1;
uint16_t b15 : 1;
} bits;
};
 
union Reg64Type {
uint8_t buf[8];
uint16_t buf16[4];
uint32_t buf32[2];
uint64_t val;
Reg8Type r8[8];
Reg16Type r16[4];
struct bits_type {
uint64_t b0 : 1;
uint64_t b1 : 1;
uint64_t b2 : 1;
uint64_t b3 : 1;
uint64_t b4 : 1;
uint64_t b5 : 1;
uint64_t b6 : 1;
uint64_t b7 : 1;
uint64_t b8 : 1;
uint64_t b9 : 1;
uint64_t b10 : 1;
uint64_t b11 : 1;
uint64_t b12 : 1;
uint64_t b13 : 1;
uint64_t b14 : 1;
uint64_t b15 : 1;
uint64_t b16 : 1;
uint64_t b17 : 1;
uint64_t b18 : 1;
uint64_t b19 : 1;
uint64_t b20 : 1;
uint64_t b21 : 1;
uint64_t b22 : 1;
uint64_t b23 : 1;
uint64_t b24 : 1;
uint64_t b25 : 1;
uint64_t b26 : 1;
uint64_t b27 : 1;
uint64_t b28 : 1;
uint64_t b29 : 1;
uint64_t b30 : 1;
uint64_t b31 : 1;
} bits;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_COMMON_API_TYPES_H__
/api_utils.h
1,111 → 1,133
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Core API utils methods declaration.
*/
 
#ifndef __DEBUGGER_API_UTILS_H__
#define __DEBUGGER_API_UTILS_H__
 
#include <stdarg.h>
#include "api_types.h"
#include "attribute.h"
 
namespace debugger {
 
#define LOG_ERROR 1
#define LOG_INFO 3
#define LOG_DEBUG 4
 
#ifdef __cplusplus
extern "C" {
#endif
 
/** Generate unique string. */
void RISCV_generate_name(AttributeType *name);
 
/** Redirect output to specified console. */
void RISCV_add_default_output(void *iout);
void RISCV_remove_default_output(void *iout);
 
/**
* @brief Write output to logfile.
* @return 0 on success, 1 when failed
*/
int RISCV_enable_log(const char *filename);
 
void RISCV_disable_log();
 
/** Format output to string. */
int RISCV_sprintf(char *s, size_t len, const char *fmt, ...);
 
/** Format output to the default stream. */
int RISCV_printf(void *iface, int level, const char *fmt, ...);
 
/** Output always */
#define RISCV_printf0(fmt, ...) \
RISCV_printf(getInterface(IFACE_SERVICE), 0, fmt, __VA_ARGS__)
 
/** Output with the maximal logging level */
#define RISCV_error(fmt, ...) \
RISCV_printf(getInterface(IFACE_SERVICE), LOG_ERROR, "%s:%d " fmt, \
__FILE__, __LINE__, __VA_ARGS__)
 
/** Output with the information logging level */
#define RISCV_info(fmt, ...) \
RISCV_printf(getInterface(IFACE_SERVICE), LOG_INFO, fmt, __VA_ARGS__)
 
/** Output with the lower logging level */
#define RISCV_debug(fmt, ...) \
RISCV_printf(getInterface(IFACE_SERVICE), LOG_DEBUG, fmt, __VA_ARGS__)
 
/** Suspend thread on certain number of milliseconds */
void RISCV_sleep_ms(int ms);
 
/** Get current time in milliseconds. */
uint64_t RISCV_get_time_ms();
 
/** Get process ID. */
int RISCV_get_pid();
 
void RISCV_thread_create(void *data);
uint64_t RISCV_thread_id();
 
int RISCV_mutex_init(mutex_def *mutex);
int RISCV_mutex_lock(mutex_def *mutex);
int RISCV_mutex_unlock(mutex_def *mutex);
int RISCV_mutex_destroy(mutex_def *mutex);
void RISCV_thread_join(thread_def th, int ms);
 
void RISCV_event_create(event_def *ev, const char *name);
void RISCV_event_close(event_def *ev);
void RISCV_event_set(event_def *ev);
int RISCV_event_is_set(event_def *ev);
void RISCV_event_clear(event_def *ev);
void RISCV_event_wait(event_def *ev);
int RISCV_event_wait_ms(event_def *ev, int ms);
 
/** Memory allocator/de-allocator */
void *RISCV_malloc(uint64_t sz);
void RISCV_free(void *p);
 
/** Get absolute directory where core library is placed. */
int RISCV_get_core_folder(char *out, int sz);
 
/** Set $(pwd) directory equals to executable location */
void RISCV_set_current_dir();
 
/** Reading configuration from JSON formatted file. */
int RISCV_read_json_file(const char *filename, void *outattr);
 
/** Write configuration string to JSON formatted file. */
void RISCV_write_json_file(const char *filename, const char *s);
 
#ifdef __cplusplus
}
#endif
 
} // namespace debugger
 
#endif // __DEBUGGER_API_UTILS_H__
/*
* Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
#ifndef __DEBUGGER_API_UTILS_H__
#define __DEBUGGER_API_UTILS_H__
 
#include <stdarg.h>
#include <api_types.h>
#include <attribute.h>
 
namespace debugger {
 
#define LOG_ERROR 1
#define LOG_IMPORTANT 2 // can be used for the autotest messages
#define LOG_INFO 3
#define LOG_DEBUG 4
 
#ifdef __cplusplus
extern "C" {
#endif
 
/** Generate unique string. */
void RISCV_generate_name(AttributeType *name);
 
/** Redirect output to specified console. */
void RISCV_add_default_output(void *iout);
void RISCV_remove_default_output(void *iout);
 
/**
* @brief Write output to logfile.
* @return 0 on success, 1 when failed
*/
int RISCV_enable_log(const char *filename);
 
void RISCV_disable_log();
 
/** Format output to string. */
int RISCV_sprintf(char *s, size_t len, const char *fmt, ...);
 
/** Format output to the default stream. */
int RISCV_printf(void *iface, int level, const char *fmt, ...);
 
/** Output always */
#define RISCV_printf0(fmt, ...) \
RISCV_printf(getInterface(IFACE_SERVICE), 0, fmt, __VA_ARGS__)
 
/** Output with the maximal logging level */
#define RISCV_error(fmt, ...) \
RISCV_printf(getInterface(IFACE_SERVICE), LOG_ERROR, "%s:%d " fmt, \
__FILE__, __LINE__, __VA_ARGS__)
 
/** Output with the information logging level */
#define RISCV_important(fmt, ...) \
RISCV_printf(getInterface(IFACE_SERVICE), LOG_IMPORTANT, fmt, __VA_ARGS__)
 
/** Output with the information logging level */
#define RISCV_info(fmt, ...) \
RISCV_printf(getInterface(IFACE_SERVICE), LOG_INFO, fmt, __VA_ARGS__)
 
/** Output with the lower logging level */
#define RISCV_debug(fmt, ...) \
RISCV_printf(getInterface(IFACE_SERVICE), LOG_DEBUG, fmt, __VA_ARGS__)
 
/** Suspend thread on certain number of milliseconds */
void RISCV_sleep_ms(int ms);
 
/** Get current time in milliseconds. */
uint64_t RISCV_get_time_ms();
 
/** Get process ID. */
int RISCV_get_pid();
 
/** Memory barrier */
void RISCV_memory_barrier();
 
void RISCV_thread_create(void *data);
uint64_t RISCV_thread_id();
 
int RISCV_mutex_init(mutex_def *mutex);
int RISCV_mutex_lock(mutex_def *mutex);
int RISCV_mutex_unlock(mutex_def *mutex);
int RISCV_mutex_destroy(mutex_def *mutex);
void RISCV_thread_join(thread_def th, int ms);
 
void RISCV_event_create(event_def *ev, const char *name);
void RISCV_event_close(event_def *ev);
void RISCV_event_set(event_def *ev);
int RISCV_event_is_set(event_def *ev);
void RISCV_event_clear(event_def *ev);
void RISCV_event_wait(event_def *ev);
int RISCV_event_wait_ms(event_def *ev, int ms);
 
sharemem_def RISCV_memshare_create(const char *name, int sz);
void* RISCV_memshare_map(sharemem_def h, int sz);
void RISCV_memshare_unmap(void *buf);
void RISCV_memshare_delete(sharemem_def h);
 
/** Memory allocator/de-allocator */
void *RISCV_malloc(uint64_t sz);
void RISCV_free(void *p);
 
/** Get absolute directory where core library is placed. */
int RISCV_get_core_folder(char *out, int sz);
 
/** Set $(pwd) directory equals to executable location */
void RISCV_set_current_dir();
 
/** Reading configuration from JSON formatted file. */
int RISCV_read_json_file(const char *filename, void *outattr);
 
/** Write configuration string to JSON formatted file. */
void RISCV_write_json_file(const char *filename, const char *s);
 
#ifdef __cplusplus
}
#endif
 
} // namespace debugger
 
#endif // __DEBUGGER_API_UTILS_H__
/async_tqueue.cpp
1,22 → 1,29
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Asynchronous queue with time markers.
/*
* Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
#include "api_utils.h"
#include "async_tqueue.h"
#include <api_utils.h>
#include <async_tqueue.h>
 
namespace debugger {
 
AsyncTQueueType::AsyncTQueueType() {
preLen_ = 0;
curLen_ = 0;
stepPreQueued_.make_list(0);
stepQueue_.make_list(16); /** it will be auto reallocated if needed */
item_.make_list(Queue_Total);
RISCV_mutex_init(&mutex_);
hardReset();
}
 
AsyncTQueueType::~AsyncTQueueType() {
23,10 → 30,13
RISCV_mutex_destroy(&mutex_);
}
 
void AsyncTQueueType::put(uint64_t time, IFace *cb) {
RISCV_mutex_lock(&mutex_);
item_[Queue_Time].make_uint64(time);
item_[Queue_IFace].make_iface(cb);
void AsyncTQueueType::hardReset() {
preLen_ = 0;
curLen_ = 0;
curIdx_ = 0;
}
 
void AsyncTQueueType::put(AttributeType *item) {
if (preLen_ == stepPreQueued_.size()) {
unsigned new_sz = 2 * stepPreQueued_.size();
if (new_sz == 0) {
35,10 → 45,10
stepPreQueued_.realloc_list(new_sz);
}
stepPreQueued_[preLen_].attr_free();
stepPreQueued_[preLen_] = item_;
stepPreQueued_[preLen_] = *item;
preLen_++;
RISCV_mutex_unlock(&mutex_);
}
 
void AsyncTQueueType::pushPreQueued() {
if (preLen_ == 0) {
return;
53,7 → 63,7
}
curLen_++;
}
preLen_= 0;
preLen_ = 0;
RISCV_mutex_unlock(&mutex_);
}
 
61,7 → 71,21
curIdx_ = 0;
}
 
IFace *AsyncTQueueType::getNext(uint64_t step_cnt) {
/** Clock queue */
ClockAsyncTQueueType::ClockAsyncTQueueType() : AsyncTQueueType() {
item_.make_list(Queue_Total);
}
 
void ClockAsyncTQueueType::put(uint64_t time, IFace *cb) {
RISCV_mutex_lock(&mutex_);
item_[Queue_Time].make_uint64(time);
item_[Queue_IFace].make_iface(cb);
 
AsyncTQueueType::put(&item_);
RISCV_mutex_unlock(&mutex_);
}
 
IFace *ClockAsyncTQueueType::getNext(uint64_t step_cnt) {
IFace *ret = 0;
if (curIdx_ >= curLen_) {
return ret;
69,6 → 93,7
for (unsigned i = curIdx_; i < curLen_; i++) {
uint64_t ev_time = stepQueue_[i][Queue_Time].to_uint64();
 
curIdx_ = i;
if (step_cnt < ev_time) {
continue;
}
76,13 → 101,66
 
// remove item from list using swap function to avoid usage
// of allocation/deallocation calls.
stepQueue_.swap_list_item(i, curLen_ - 1);
if (i < (curLen_ - 1)) {
stepQueue_.swap_list_item(i, curLen_ - 1);
}
curLen_--;
curIdx_--;
break;
}
return ret;
}
 
 
/** GUI queue */
GuiAsyncTQueueType::GuiAsyncTQueueType() : AsyncTQueueType() {
item_.make_list(Queue_Total);
dbg_cnt_ = 0;
}
 
void GuiAsyncTQueueType::put(IFace *src, AttributeType *cmd, bool silent) {
RISCV_mutex_lock(&mutex_);
item_[Queue_Source].make_iface(src);
item_[Queue_Command] = *cmd;
item_[Queue_Silent].make_boolean(silent);
 
AsyncTQueueType::put(&item_);
dbg_cnt_++;
RISCV_mutex_unlock(&mutex_);
}
 
bool GuiAsyncTQueueType::getNext(IFace **src, AttributeType &cmd,
bool &silent) {
*src = 0;
if (curIdx_ >= curLen_) {
curIdx_ = 0;
curLen_ = 0;
return false;
}
AttributeType &item = stepQueue_[curIdx_++];
dbg_cnt_--;
 
*src = item[Queue_Source].to_iface();
cmd = item[Queue_Command];
silent = item[Queue_Silent].to_bool();
return true;
}
 
void GuiAsyncTQueueType::remove(IFace *src) {
RISCV_mutex_lock(&mutex_);
for (unsigned i = 0; i < preLen_; i++) {
AttributeType &item = stepPreQueued_[i];
if (item[Queue_Source].to_iface() == src) {
item[Queue_Source].make_iface(0);
}
}
for (unsigned i = 0; i < curLen_; i++) {
AttributeType &item = stepQueue_[i];
if (item[Queue_Source].to_iface() == src) {
item[Queue_Source].make_iface(0);
}
}
RISCV_mutex_unlock(&mutex_);
}
 
} // namespace debugger
 
/async_tqueue.h
1,27 → 1,39
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Asynchronous queue with time markers.
/*
* Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
#ifndef __DEBUGGER_ASYNC_TQUEUE_H__
#define __DEBUGGER_ASYNC_TQUEUE_H__
 
#include "api_types.h"
#include "iface.h"
#include "attribute.h"
#include <api_types.h>
#include <iface.h>
#include <attribute.h>
 
namespace debugger {
 
class AsyncTQueueType {
public:
public:
AsyncTQueueType();
~AsyncTQueueType();
 
/** Thread safe method of the calbacks registration */
void put(uint64_t time, IFace *cb);
/** Power ON/OFF cycle */
void hardReset();
 
/** Thread safe method of the callbacks registration */
void put(AttributeType *item);
 
/** push registered to the main queue */
void pushPreQueued();
 
28,26 → 40,57
/** Reset proccessed counter at the begining of each iteration */
void initProc();
 
protected:
AttributeType item_;
AttributeType stepQueue_;
AttributeType stepPreQueued_;
unsigned curIdx_;
unsigned preLen_;
unsigned curLen_; // to avoid reallocation
mutex_def mutex_;
};
 
 
class ClockAsyncTQueueType : public AsyncTQueueType {
public:
ClockAsyncTQueueType();
 
/** Thread safe method of the callbacks registration */
void put(uint64_t time, IFace *cb);
 
/**
* Get next registered interface with counter less or equal to 'step_cnt'
*/
IFace *getNext(uint64_t step_cnt);
 
private:
private:
enum QueueItemNames {
Queue_Time,
Queue_IFace,
Queue_Time,
Queue_IFace,
Queue_Total
};
AttributeType item_;
AttributeType stepQueue_;
AttributeType stepPreQueued_;
unsigned curIdx_;
unsigned preLen_;
unsigned curLen_; // to avoid reallocation
mutex_def mutex_;
};
 
 
class GuiAsyncTQueueType : public AsyncTQueueType {
public:
GuiAsyncTQueueType();
 
/** Thread safe method of the callbacks registration */
void put(IFace *src, AttributeType *cmd, bool silent);
bool getNext(IFace **src, AttributeType &cmd, bool &silent);
void remove(IFace *src);
 
private:
enum QueueItemNames {
Queue_Source,
Queue_Command,
Queue_Silent,
Queue_Total
};
int dbg_cnt_;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_ASYNC_TQUEUE_H__
/attribute.cpp
1,680 → 1,754
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Core attribute methods implementation.
*/
 
#include "api_core.h"
#include "autobuffer.h"
#include "iservice.h"
#include "api_utils.h"
#include <cstdlib>
 
namespace debugger {
 
static const int64_t MIN_ALLOC_BYTES = 1 << 12;
static AttributeType NilAttribute;
static AutoBuffer strBuffer;
 
char *attribute_to_string(const AttributeType *attr);
int string_to_attribute(const char *cfg, int &off, AttributeType *out);
 
void AttributeType::attr_free() {
if (size()) {
if (is_string()) {
RISCV_free(u_.string);
} else if (is_data() && size() > 8) {
RISCV_free(u_.data);
} else if (is_list()) {
for (unsigned i = 0; i < size(); i++) {
u_.list[i].attr_free();
}
RISCV_free(u_.list);
} else if (is_dict()) {
for (unsigned i = 0; i < size(); i++) {
u_.dict[i].key_.attr_free();
u_.dict[i].value_.attr_free();
}
RISCV_free(u_.dict);
}
}
kind_ = Attr_Invalid;
size_ = 0;
u_.integer = 0;
}
 
void AttributeType::clone(const AttributeType *v) {
attr_free();
 
if (v->is_string()) {
this->make_string(v->to_string());
} else if (v->is_data()) {
this->make_data(v->size(), v->data());
} else if (v->is_list()) {
make_list(v->size());
for (unsigned i = 0; i < v->size(); i++ ) {
u_.list[i].clone(v->list(i));
}
} else if (v->is_dict()) {
make_dict();
realloc_dict(v->size());
for (unsigned i = 0; i < v->size(); i++ ) {
u_.dict[i].key_.make_string(v->dict_key(i)->to_string());
u_.dict[i].value_.clone(v->dict_value(i));
}
} else {
this->kind_ = v->kind_;
this->u_ = v->u_;
this->size_ = v->size_;
}
}
 
bool AttributeType::is_equal(const char *v) {
if (!is_string()) {
return false;
}
return !strcmp(to_string(), v);
}
 
 
AttributeType &AttributeType::operator=(const AttributeType& other) {
if (&other != this) {
clone(&other);
}
return *this;
}
 
 
const AttributeType &AttributeType::operator[](unsigned idx) const {
if (is_list()) {
return u_.list[idx];
} else if (is_dict()) {
return u_.dict[idx].value_;
} else {
RISCV_printf(NULL, LOG_ERROR, "%s", "Non-indexed attribute type");
}
return NilAttribute;
}
 
AttributeType &AttributeType::operator[](unsigned idx) {
if (is_list()) {
return u_.list[idx];
} else if (is_dict()) {
return u_.dict[idx].value_;
} else {
RISCV_printf(NULL, LOG_ERROR, "%s", "Non-indexed attribute type");
}
return NilAttribute;
}
 
const AttributeType &AttributeType::operator[](const char *key) const {
for (unsigned i = 0; i < size(); i++) {
if (strcmp(key, u_.dict[i].key_.to_string()) == 0) {
return u_.dict[i].value_;
}
}
AttributeType *pthis = const_cast<AttributeType*>(this);
pthis->realloc_dict(size()+1);
pthis->u_.dict[size()-1].key_.make_string(key);
pthis->u_.dict[size()-1].value_.make_nil();
return u_.dict[size()-1].value_;
}
 
AttributeType &AttributeType::operator[](const char *key) {
for (unsigned i = 0; i < size(); i++) {
if (strcmp(key, u_.dict[i].key_.to_string()) == 0) {
return u_.dict[i].value_;
}
}
realloc_dict(size()+1);
u_.dict[size()-1].key_.make_string(key);
u_.dict[size()-1].value_.make_nil();
return u_.dict[size()-1].value_;
}
 
const uint8_t &AttributeType::operator()(unsigned idx) const {
if (idx > size()) {
RISCV_printf(NULL, LOG_ERROR, "Data index '%d' out of range.", idx);
return u_.data[0];
}
if (size_ > 8) {
return u_.data[idx];
}
return u_.data_bytes[idx];
}
 
void AttributeType::make_string(const char *value) {
attr_free();
if (value) {
kind_ = Attr_String;
size_ = (unsigned)strlen(value);
u_.string = static_cast<char *>(RISCV_malloc(size_ + 1));
memcpy(u_.string, value, size_ + 1);
} else {
kind_ = Attr_Nil;
}
}
 
void AttributeType::make_data(unsigned size) {
attr_free();
kind_ = Attr_Data;
size_ = size;
if (size > 8) {
u_.data = static_cast<uint8_t *>(RISCV_malloc(size_));
}
}
 
void AttributeType::make_data(unsigned size, const void *data) {
attr_free();
kind_ = Attr_Data;
size_ = size;
if (size > 8) {
u_.data = static_cast<uint8_t *>(RISCV_malloc(size_));
memcpy(u_.data, data, size);
} else {
memcpy(u_.data_bytes, data, size);
}
}
 
void AttributeType::make_list(unsigned size) {
attr_free();
kind_ = Attr_List;
if (size) {
realloc_list(size);
}
}
 
void AttributeType::realloc_list(unsigned size) {
size_t req_sz = (size * sizeof(AttributeType) + MIN_ALLOC_BYTES - 1)
/ MIN_ALLOC_BYTES;
size_t cur_sz = (size_ * sizeof(AttributeType) + MIN_ALLOC_BYTES - 1)
/ MIN_ALLOC_BYTES;
if (req_sz > cur_sz ) {
AttributeType * t1 = static_cast<AttributeType *>(
RISCV_malloc(MIN_ALLOC_BYTES * req_sz));
memcpy(t1, u_.list, size_ * sizeof(AttributeType));
memset(&t1[size_], 0,
(MIN_ALLOC_BYTES * req_sz) - size_ * sizeof(AttributeType));
if (size_) {
RISCV_free(u_.list);
}
u_.list = t1;
}
size_ = size;
}
 
void AttributeType::insert_to_list(unsigned idx, const AttributeType *item) {
if (idx > size_) {
RISCV_printf(NULL, LOG_ERROR, "%s", "Insert index out of bound");
return;
}
size_t new_sz = ((size_ + 1) * sizeof(AttributeType) + MIN_ALLOC_BYTES - 1)
/ MIN_ALLOC_BYTES;
AttributeType * t1 = static_cast<AttributeType *>(
RISCV_malloc(MIN_ALLOC_BYTES * new_sz));
memset(t1 + idx, 0, sizeof(AttributeType)); // Fix bug request #4
 
memcpy(t1, u_.list, idx * sizeof(AttributeType));
t1[idx].clone(item);
memcpy(&t1[idx + 1], &u_.list[idx], (size_ - idx) * sizeof(AttributeType));
memset(&t1[size_ + 1], 0,
(MIN_ALLOC_BYTES * new_sz) - (size_ + 1) * sizeof(AttributeType));
if (size_) {
RISCV_free(u_.list);
}
u_.list = t1;
size_++;
}
 
void AttributeType::remove_from_list(unsigned idx) {
if (idx >= size_) {
RISCV_printf(NULL, LOG_ERROR, "%s", "Remove index out of range");
return;
}
(*this)[idx].attr_free();
if (idx == (size() - 1)) {
size_ -= 1;
} else if (idx < size ()) {
swap_list_item(idx, size() - 1);
size_ -= 1;
}
}
 
void AttributeType::trim_list(unsigned start, unsigned end) {
for (unsigned i = start; i < (size_ - end); i++) {
u_.list[start + i].attr_free();
u_.list[start + i] = u_.list[end + i];
}
size_ -= (end - start);
}
 
void AttributeType::swap_list_item(unsigned n, unsigned m) {
if (n == m) {
return;
}
unsigned tsize = u_.list[n].size_;
KindType tkind = u_.list[n].kind_;
int64_t tinteger = u_.list[n].u_.integer;
u_.list[n].size_ = u_.list[m].size_;
u_.list[n].kind_ = u_.list[m].kind_;
u_.list[n].u_.integer = u_.list[m].u_.integer;
u_.list[m].size_ = tsize;
u_.list[m].kind_ = tkind;
u_.list[m].u_.integer = tinteger;
}
 
 
int partition(AttributeType *A, int lo, int hi, int lst_idx) {
AttributeType *pivot = &(*A)[hi];
bool do_swap;
int i = lo - 1;
for (int j = lo; j < hi; j++) {
AttributeType &item = (*A)[j];
do_swap = false;
if (item.is_string()) {
if (strcmp(item.to_string(), pivot->to_string()) <= 0) {
do_swap = true;
}
} else if (item.is_int64()) {
if (item.to_int64() <= pivot->to_int64()) {
do_swap = true;
}
} else if (item.is_uint64()) {
if (item.to_uint64() <= pivot->to_uint64()) {
do_swap = true;
}
} else if (item.is_list()) {
AttributeType &t1 = item[lst_idx];
if (t1.is_string() &&
strcmp(t1.to_string(), (*pivot)[lst_idx].to_string()) <= 0) {
do_swap = true;
} else if (t1.is_int64() &&
t1.to_int64() <= (*pivot)[lst_idx].to_int64()) {
do_swap = true;
} else if (t1.is_uint64() &&
t1.to_uint64() <= (*pivot)[lst_idx].to_uint64()) {
do_swap = true;
}
} else {
RISCV_printf(NULL, LOG_ERROR, "%s",
"Not supported attribute type for sorting");
return i + 1;
}
 
if (do_swap) {
i = i + 1;
A->swap_list_item(i, j);
}
}
A->swap_list_item(i + 1, hi);
return i + 1;
}
 
void quicksort(AttributeType *A, int lo, int hi, int lst_idx) {
if (lo >= hi) {
return;
}
int p = partition(A, lo, hi, lst_idx);
quicksort(A, lo, p - 1, lst_idx);
quicksort(A, p + 1, hi, lst_idx);
}
 
void AttributeType::sort(int idx) {
if (!is_list()) {
RISCV_printf(NULL, LOG_ERROR, "%s",
"Sort algorithm can applied only to list attribute");
}
quicksort(this, 0, static_cast<int>(size()) - 1, idx);
}
 
bool AttributeType::has_key(const char *key) const {
for (unsigned i = 0; i < size(); i++) {
if (strcmp(u_.dict[i].key_.to_string(), key) == 0
&& !u_.dict[i].value_.is_nil()) {
return true;
}
}
return false;
}
 
const AttributeType *AttributeType::dict_key(unsigned idx) const {
return &u_.dict[idx].key_;
}
AttributeType *AttributeType::dict_key(unsigned idx) {
return &u_.dict[idx].key_;
}
 
const AttributeType *AttributeType::dict_value(unsigned idx) const {
return &u_.dict[idx].value_;
}
AttributeType *AttributeType::dict_value(unsigned idx) {
return &u_.dict[idx].value_;
}
 
void AttributeType::make_dict() {
attr_free();
kind_ = Attr_Dict;
size_ = 0;
u_.dict = NULL;
}
 
void AttributeType::realloc_dict(unsigned size) {
size_t req_sz = (size * sizeof(AttributePairType) + MIN_ALLOC_BYTES - 1)
/ MIN_ALLOC_BYTES;
size_t cur_sz = (size_ * sizeof(AttributePairType) + MIN_ALLOC_BYTES - 1)
/ MIN_ALLOC_BYTES;
if (req_sz > cur_sz ) {
AttributePairType * t1 = static_cast<AttributePairType *>(
RISCV_malloc(MIN_ALLOC_BYTES * req_sz));
memcpy(t1, u_.dict, size_ * sizeof(AttributePairType));
memset(&t1[size_], 0,
(MIN_ALLOC_BYTES * req_sz) - size_ * sizeof(AttributePairType));
if (size_) {
RISCV_free(u_.dict);
}
u_.dict = t1;
}
size_ = size;
}
 
char *AttributeType::to_config() {
strBuffer.clear();
attribute_to_string(this);
return strBuffer.getBuffer();
}
 
void AttributeType::from_config(const char *str) {
int off = 0;
string_to_attribute(str, off, this);
}
 
char *attribute_to_string(const AttributeType *attr) {
IService *iserv;
AutoBuffer *buf = &strBuffer;
if (attr->is_nil()) {
buf->write_string("None");
} else if (attr->is_int64() || attr->is_uint64()) {
buf->write_uint64(attr->to_uint64());
} else if (attr->is_string()) {
buf->write_string('\'');
buf->write_string(attr->to_string());
buf->write_string('\'');
} else if (attr->is_bool()) {
if (attr->to_bool()) {
buf->write_string("true");
} else {
buf->write_string("false");
}
} else if (attr->is_list()) {
AttributeType list_item;
unsigned list_sz = attr->size();
buf->write_string('[');
for (unsigned i = 0; i < list_sz; i++) {
list_item = (*attr)[i];
attribute_to_string(&list_item);
if (i < (list_sz - 1)) {
buf->write_string(',');
}
}
buf->write_string(']');
} else if (attr->is_dict()) {
AttributeType dict_item;
unsigned dict_sz = attr->size();;
buf->write_string('{');
 
for (unsigned i = 0; i < dict_sz; i++) {
buf->write_string('\'');
buf->write_string(attr->u_.dict[i].key_.to_string());
buf->write_string('\'');
buf->write_string(':');
const AttributeType &dict_value = (*attr)[i];
attribute_to_string(&dict_value);
if (i < (dict_sz - 1)) {
buf->write_string(',');
}
}
buf->write_string('}');
} else if (attr->is_data()) {
buf->write_string('(');
if (attr->size() > 0) {
for (unsigned n = 0; n < attr->size()-1; n++) {
buf->write_byte((*attr)(n));
buf->write_string(',');
}
buf->write_byte((*attr)(attr->size()-1));
}
buf->write_string(')');
} else if (attr->is_iface()) {
IFace *iface = attr->to_iface();
if (strcmp(iface->getFaceName(), IFACE_SERVICE) == 0) {
iserv = static_cast<IService *>(iface);
buf->write_string('{');
buf->write_string("'Type':'");
buf->write_string(iface->getFaceName());
buf->write_string("','ModuleName':'");
buf->write_string(iserv->getObjName());
buf->write_string("'}");
} else {
RISCV_printf(NULL, LOG_ERROR,
"Not implemented interface to dict. method");
}
} else if (attr->is_floating()) {
char fstr[64];
RISCV_sprintf(fstr, sizeof(fstr), "%.4f", attr->to_float());
buf->write_string(fstr);
}
return buf->getBuffer();
}
 
int skip_special_symbols(const char *cfg, int off) {
const char *pcur = &cfg[off];
while (*pcur == ' ' || *pcur == '\r' || *pcur == '\n' || *pcur == '\t') {
pcur++;
off++;
}
return off;
}
 
int string_to_attribute(const char *cfg, int &off,
AttributeType *out) {
off = skip_special_symbols(cfg, off);
int checkstart = off;
if (cfg[off] == '\'' || cfg[off] == '"') {
AutoBuffer buf;
uint8_t t1 = cfg[off];
int str_sz = 0;
const char *pcur = &cfg[++off];
while (*pcur != t1 && *pcur != '\0') {
pcur++;
str_sz++;
}
buf.write_bin(&cfg[off], str_sz);
out->make_string(buf.getBuffer());
off += str_sz;
if (cfg[off] != t1) {
RISCV_printf(NULL, LOG_ERROR,
"JSON parser error: Wrong string format");
out->attr_free();
return -1;
}
off = skip_special_symbols(cfg, off + 1);
} else if (cfg[off] == '[') {
off = skip_special_symbols(cfg, off + 1);
AttributeType new_item;
out->make_list(0);
while (cfg[off] != ']' && cfg[off] != '\0') {
if (string_to_attribute(cfg, off, &new_item)) {
/* error handling */
out->attr_free();
return -1;
}
out->realloc_list(out->size() + 1);
(*out)[out->size() - 1] = new_item;
 
off = skip_special_symbols(cfg, off);
if (cfg[off] == ',') {
off = skip_special_symbols(cfg, off + 1);
}
}
if (cfg[off] != ']') {
RISCV_printf(NULL, LOG_ERROR,
"JSON parser error: Wrong list format");
out->attr_free();
return -1;
}
off = skip_special_symbols(cfg, off + 1);
} else if (cfg[off] == '{') {
AttributeType new_key;
AttributeType new_value;
out->make_dict();
off = skip_special_symbols(cfg, off + 1);
while (cfg[off] != '}' && cfg[off] != '\0') {
if (string_to_attribute(cfg, off, &new_key)) {
RISCV_printf(NULL, LOG_ERROR,
"JSON parser error: Wrong dictionary key");
out->attr_free();
return -1;
}
off = skip_special_symbols(cfg, off);
if (cfg[off] != ':') {
out->attr_free();
RISCV_printf(NULL, LOG_ERROR,
"JSON parser error: Wrong dictionary delimiter");
return -1;
}
off = skip_special_symbols(cfg, off + 1);
if (string_to_attribute(cfg, off, &new_value)) {
RISCV_printf(NULL, LOG_ERROR,
"JSON parser error: Wrong dictionary value");
out->attr_free();
return -1;
}
 
(*out)[new_key.to_string()] = new_value;
 
off = skip_special_symbols(cfg, off);
if (cfg[off] == ',') {
off = skip_special_symbols(cfg, off + 1);
}
}
if (cfg[off] != '}') {
RISCV_printf(NULL, LOG_ERROR,
"JSON parser error: Wrong dictionary format");
out->attr_free();
return -1;
}
off = skip_special_symbols(cfg, off + 1);
 
if (out->has_key("Type")) {
if (strcmp((*out)["Type"].to_string(), IFACE_SERVICE) == 0) {
IService *iserv;
iserv = static_cast<IService *>(
RISCV_get_service((*out)["ModuleName"].to_string()));
out->attr_free();
*out = AttributeType(iserv);
} else {
RISCV_printf(NULL, LOG_ERROR,
"Not implemented string to dict. attribute");
}
}
} else if (cfg[off] == '(') {
AutoBuffer buf;
char byte_value;
off = skip_special_symbols(cfg, off);
while (cfg[off] != ')' && cfg[off] != '\0') {
byte_value = 0;
for (int n = 0; n < 2; n++) {
if (cfg[off] >= 'A' && cfg[off] <= 'F') {
byte_value = (byte_value << 4) | ((cfg[off] - 'A') + 10);
} else {
byte_value = (byte_value << 4) | (cfg[off] - '0');
}
off++;
}
buf.write_bin(&byte_value, 1);
 
off = skip_special_symbols(cfg, off);
if (cfg[off] != ',') {
RISCV_printf(NULL, LOG_ERROR,
"JSON parser error: Wrong data dytes delimiter");
out->attr_free();
return -1;
}
off = skip_special_symbols(cfg, off + 1);
}
if (cfg[off] != ')') {
RISCV_printf(NULL, LOG_ERROR,
"JSON parser error: Wrong data format");
out->attr_free();
return -1;
}
out->make_data(buf.size(), buf.getBuffer());
off = skip_special_symbols(cfg, off + 1);
} else if (cfg[off] == 'N' && cfg[off + 1] == 'o' && cfg[off + 2] == 'n'
&& cfg[off + 3] == 'e') {
out->make_nil();
off = skip_special_symbols(cfg, off + 4);
} else if (cfg[off] == 'f' && cfg[off + 1] == 'a' && cfg[off + 2] == 'l'
&& cfg[off + 3] == 's' && cfg[off + 4] == 'e') {
out->make_boolean(false);
off = skip_special_symbols(cfg, off + 5);
} else if (cfg[off] == 't' && cfg[off + 1] == 'r' && cfg[off + 2] == 'u'
&& cfg[off + 3] == 'e') {
out->make_boolean(true);
off = skip_special_symbols(cfg, off + 4);
} else {
char digits[64] = {0};
int digits_cnt = 0;
bool negative = false;
if (cfg[off] == '0' && cfg[off + 1] == 'x') {
off += 2;
digits[digits_cnt++] = '0';
digits[digits_cnt++] = 'x';
} else if (cfg[off] == '-') {
negative = true;
off++;
}
while (digits_cnt < 63 && ((cfg[off] >= '0' && cfg[off] <= '9')
|| (cfg[off] >= 'a' && cfg[off] <= 'f')
|| (cfg[off] >= 'A' && cfg[off] <= 'F'))) {
digits[digits_cnt++] = cfg[off++];
digits[digits_cnt] = 0;
}
int64_t t1 = strtoull(digits, NULL, 0);
if (cfg[off] == '.') {
digits_cnt = 0;
digits[0] = 0;
double divrate = 1.0;
double d1 = static_cast<double>(t1);
off++;
while (digits_cnt < 63 && cfg[off] >= '0' && cfg[off] <= '9') {
digits[digits_cnt++] = cfg[off++];
digits[digits_cnt] = 0;
divrate *= 10.0;
}
t1 = strtoull(digits, NULL, 0);
d1 += static_cast<double>(t1)/divrate;
if (negative) {
d1 = -d1;
}
out->make_floating(d1);
} else {
if (negative) {
t1 = -t1;
}
out->make_int64(t1);
}
off = skip_special_symbols(cfg, off);
}
/** Guard to skip wrong formatted string and avoid hanging: */
if (off == checkstart) {
RISCV_printf(NULL, LOG_ERROR,
"JSON parser error: Can't detect format");
out->attr_free();
return -1;
}
return 0;
}
 
} // namespace debugger
/*
* Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
#include <attribute.h>
#include <api_core.h>
#include <autobuffer.h>
#include <iservice.h>
#include <api_utils.h>
#include <cstdlib>
#include <string>
#include <algorithm>
 
namespace debugger {
 
static const int64_t MIN_ALLOC_BYTES = 1 << 12;
static AttributeType NilAttribute;
 
void attribute_to_string(const AttributeType *attr, AutoBuffer *buf);
int string_to_attribute(const char *cfg, int &off, AttributeType *out);
 
void AttributeType::allocAttrName(const char *name) {
size_t len = strlen(name) + 1;
attr_name_ = static_cast<char *>(RISCV_malloc(len));
memcpy(attr_name_, name, len);
}
 
void AttributeType::freeAttrName() {
if (attr_name_) {
RISCV_free(attr_name_);
}
}
 
void AttributeType::allocAttrDescription(const char *descr) {
size_t len = strlen(descr) + 1;
attr_descr_ = static_cast<char *>(RISCV_malloc(len));
memcpy(attr_descr_, descr, len);
}
 
void AttributeType::freeAttrDescription() {
if (attr_descr_) {
RISCV_free(attr_descr_);
}
}
 
void AttributeType::attr_free() {
if (size()) {
if (is_string()) {
RISCV_free(u_.string);
} else if (is_data() && size() > 8) {
RISCV_free(u_.data);
} else if (is_list()) {
for (unsigned i = 0; i < size(); i++) {
u_.list[i].attr_free();
}
RISCV_free(u_.list);
} else if (is_dict()) {
for (unsigned i = 0; i < size(); i++) {
u_.dict[i].key_.attr_free();
u_.dict[i].value_.attr_free();
}
RISCV_free(u_.dict);
}
}
kind_ = Attr_Invalid;
size_ = 0;
u_.integer = 0;
}
 
void AttributeType::clone(const AttributeType *v) {
attr_free();
 
if (v->is_string()) {
this->make_string(v->to_string());
} else if (v->is_data()) {
this->make_data(v->size(), v->data());
} else if (v->is_list()) {
make_list(v->size());
for (unsigned i = 0; i < v->size(); i++) {
u_.list[i].clone(v->list(i));
}
} else if (v->is_dict()) {
make_dict();
realloc_dict(v->size());
for (unsigned i = 0; i < v->size(); i++) {
u_.dict[i].key_.make_string(v->dict_key(i)->to_string());
u_.dict[i].value_.clone(v->dict_value(i));
}
} else {
this->kind_ = v->kind_;
this->u_ = v->u_;
this->size_ = v->size_;
}
}
 
bool AttributeType::is_equal(const char *v) {
if (!is_string()) {
return false;
}
return !strcmp(to_string(), v);
}
 
 
AttributeType &AttributeType::operator=(const AttributeType& other) {
if (&other != this) {
clone(&other);
}
return *this;
}
 
 
const AttributeType &AttributeType::operator[](unsigned idx) const {
if (is_list()) {
return u_.list[idx];
} else if (is_dict()) {
return u_.dict[idx].value_;
} else {
RISCV_printf(NULL, LOG_ERROR, "%s", "Non-indexed attribute type");
}
return NilAttribute;
}
 
AttributeType &AttributeType::operator[](unsigned idx) {
if (is_list()) {
return u_.list[idx];
} else if (is_dict()) {
return u_.dict[idx].value_;
} else {
RISCV_printf(NULL, LOG_ERROR, "%s", "Non-indexed attribute type");
}
return NilAttribute;
}
 
const AttributeType &AttributeType::operator[](const char *key) const {
for (unsigned i = 0; i < size(); i++) {
if (strcmp(key, u_.dict[i].key_.to_string()) == 0) {
return u_.dict[i].value_;
}
}
AttributeType *pthis = const_cast<AttributeType*>(this);
pthis->realloc_dict(size()+1);
pthis->u_.dict[size()-1].key_.make_string(key);
pthis->u_.dict[size()-1].value_.make_nil();
return u_.dict[size()-1].value_;
}
 
AttributeType &AttributeType::operator[](const char *key) {
for (unsigned i = 0; i < size(); i++) {
if (strcmp(key, u_.dict[i].key_.to_string()) == 0) {
return u_.dict[i].value_;
}
}
realloc_dict(size()+1);
u_.dict[size()-1].key_.make_string(key);
u_.dict[size()-1].value_.make_nil();
return u_.dict[size()-1].value_;
}
 
const uint8_t &AttributeType::operator()(unsigned idx) const {
if (idx > size()) {
RISCV_printf(NULL, LOG_ERROR, "Data index '%d' out of range.", idx);
return u_.data[0];
}
if (size_ > 8) {
return u_.data[idx];
}
return u_.data_bytes[idx];
}
 
void AttributeType::make_string(const char *value) {
attr_free();
if (value) {
kind_ = Attr_String;
size_ = (unsigned)strlen(value);
u_.string = static_cast<char *>(RISCV_malloc(size_ + 1));
memcpy(u_.string, value, size_ + 1);
} else {
kind_ = Attr_Nil;
}
}
 
void AttributeType::make_data(unsigned size) {
attr_free();
kind_ = Attr_Data;
size_ = size;
if (size > 8) {
u_.data = static_cast<uint8_t *>(RISCV_malloc(size_));
}
}
 
void AttributeType::make_data(unsigned size, const void *data) {
attr_free();
kind_ = Attr_Data;
size_ = size;
if (size > 8) {
u_.data = static_cast<uint8_t *>(RISCV_malloc(size_));
memcpy(u_.data, data, size);
} else {
memcpy(u_.data_bytes, data, size);
}
}
 
void AttributeType::realloc_data(unsigned size) {
if (!is_data()) {
return;
}
if (size <= 8) {
if (size_ > 8) {
memcpy(u_.data_bytes, u_.data, size);
RISCV_free(u_.data);
}
size_ = size;
return;
}
uint8_t *pnew = static_cast<uint8_t *>(RISCV_malloc(size));
unsigned sz = size;
if (size_ < sz) {
sz = size_;
}
if (sz > 8) {
memcpy(pnew, u_.data, sz);
RISCV_free(u_.data);
} else {
memcpy(pnew, u_.data_bytes, sz);
}
u_.data = pnew;
size_ = size;
}
 
void AttributeType::make_list(unsigned size) {
attr_free();
kind_ = Attr_List;
if (size) {
realloc_list(size);
}
}
 
void AttributeType::realloc_list(unsigned size) {
size_t req_sz = (size * sizeof(AttributeType) + MIN_ALLOC_BYTES - 1)
/ MIN_ALLOC_BYTES;
size_t cur_sz = (size_ * sizeof(AttributeType) + MIN_ALLOC_BYTES - 1)
/ MIN_ALLOC_BYTES;
if (req_sz > cur_sz) {
AttributeType * t1 = static_cast<AttributeType *>(
RISCV_malloc(MIN_ALLOC_BYTES * req_sz));
memcpy(t1, u_.list, size_ * sizeof(AttributeType));
memset(&t1[size_], 0,
(MIN_ALLOC_BYTES * req_sz) - size_ * sizeof(AttributeType));
if (size_) {
RISCV_free(u_.list);
}
u_.list = t1;
}
size_ = size;
}
 
void AttributeType::insert_to_list(unsigned idx, const AttributeType *item) {
if (idx > size_) {
RISCV_printf(NULL, LOG_ERROR, "%s", "Insert index out of bound");
return;
}
size_t new_sz = ((size_ + 1) * sizeof(AttributeType) + MIN_ALLOC_BYTES - 1)
/ MIN_ALLOC_BYTES;
AttributeType * t1 = static_cast<AttributeType *>(
RISCV_malloc(MIN_ALLOC_BYTES * new_sz));
memset(t1 + idx, 0, sizeof(AttributeType)); // Fix bug request #4
 
memcpy(t1, u_.list, idx * sizeof(AttributeType));
t1[idx].clone(item);
memcpy(&t1[idx + 1], &u_.list[idx], (size_ - idx) * sizeof(AttributeType));
memset(&t1[size_ + 1], 0,
(MIN_ALLOC_BYTES * new_sz) - (size_ + 1) * sizeof(AttributeType));
if (size_) {
RISCV_free(u_.list);
}
u_.list = t1;
size_++;
}
 
void AttributeType::remove_from_list(unsigned idx) {
if (idx >= size_) {
RISCV_printf(NULL, LOG_ERROR, "%s", "Remove index out of range");
return;
}
(*this)[idx].attr_free();
if (idx == (size() - 1)) {
size_ -= 1;
} else if (idx < size()) {
swap_list_item(idx, size() - 1);
size_ -= 1;
}
}
 
void AttributeType::trim_list(unsigned start, unsigned end) {
for (unsigned i = start; i < (size_ - end); i++) {
u_.list[start + i].attr_free();
u_.list[start + i] = u_.list[end + i];
}
size_ -= (end - start);
}
 
void AttributeType::swap_list_item(unsigned n, unsigned m) {
if (n == m) {
return;
}
unsigned tsize = u_.list[n].size_;
KindType tkind = u_.list[n].kind_;
int64_t tinteger = u_.list[n].u_.integer;
u_.list[n].size_ = u_.list[m].size_;
u_.list[n].kind_ = u_.list[m].kind_;
u_.list[n].u_.integer = u_.list[m].u_.integer;
u_.list[m].size_ = tsize;
u_.list[m].kind_ = tkind;
u_.list[m].u_.integer = tinteger;
}
 
 
int partition(AttributeType *A, int lo, int hi, int lst_idx) {
AttributeType *pivot = &(*A)[hi];
bool do_swap;
int i = lo - 1;
for (int j = lo; j < hi; j++) {
AttributeType &item = (*A)[j];
do_swap = false;
if (item.is_string()) {
if (strcmp(item.to_string(), pivot->to_string()) <= 0) {
do_swap = true;
}
} else if (item.is_int64()) {
if (item.to_int64() <= pivot->to_int64()) {
do_swap = true;
}
} else if (item.is_uint64()) {
if (item.to_uint64() <= pivot->to_uint64()) {
do_swap = true;
}
} else if (item.is_list()) {
AttributeType &t1 = item[lst_idx];
if (t1.is_string() &&
strcmp(t1.to_string(), (*pivot)[lst_idx].to_string()) <= 0) {
do_swap = true;
} else if (t1.is_int64() &&
t1.to_int64() <= (*pivot)[lst_idx].to_int64()) {
do_swap = true;
} else if (t1.is_uint64() &&
t1.to_uint64() <= (*pivot)[lst_idx].to_uint64()) {
do_swap = true;
}
} else {
RISCV_printf(NULL, LOG_ERROR, "%s",
"Not supported attribute type for sorting");
return i + 1;
}
 
if (do_swap) {
i = i + 1;
A->swap_list_item(i, j);
}
}
A->swap_list_item(i + 1, hi);
return i + 1;
}
 
void quicksort(AttributeType *A, int lo, int hi, int lst_idx) {
if (lo >= hi) {
return;
}
int p = partition(A, lo, hi, lst_idx);
quicksort(A, lo, p - 1, lst_idx);
quicksort(A, p + 1, hi, lst_idx);
}
 
void AttributeType::sort(int idx) {
if (!is_list()) {
RISCV_printf(NULL, LOG_ERROR, "%s",
"Sort algorithm can applied only to list attribute");
}
quicksort(this, 0, static_cast<int>(size()) - 1, idx);
}
 
bool AttributeType::has_key(const char *key) const {
for (unsigned i = 0; i < size(); i++) {
AttributePairType &pair = u_.dict[i];
if (pair.key_.is_equal(key) && !pair.value_.is_nil()) {
return true;
}
}
return false;
}
 
const AttributeType *AttributeType::dict_key(unsigned idx) const {
return &u_.dict[idx].key_;
}
AttributeType *AttributeType::dict_key(unsigned idx) {
return &u_.dict[idx].key_;
}
 
const AttributeType *AttributeType::dict_value(unsigned idx) const {
return &u_.dict[idx].value_;
}
AttributeType *AttributeType::dict_value(unsigned idx) {
return &u_.dict[idx].value_;
}
 
void AttributeType::make_dict() {
attr_free();
kind_ = Attr_Dict;
size_ = 0;
u_.dict = NULL;
}
 
void AttributeType::realloc_dict(unsigned size) {
size_t req_sz = (size * sizeof(AttributePairType) + MIN_ALLOC_BYTES - 1)
/ MIN_ALLOC_BYTES;
size_t cur_sz = (size_ * sizeof(AttributePairType) + MIN_ALLOC_BYTES - 1)
/ MIN_ALLOC_BYTES;
if (req_sz > cur_sz) {
AttributePairType * t1 = static_cast<AttributePairType *>(
RISCV_malloc(MIN_ALLOC_BYTES * req_sz));
memcpy(t1, u_.dict, size_ * sizeof(AttributePairType));
memset(&t1[size_], 0,
(MIN_ALLOC_BYTES * req_sz) - size_ * sizeof(AttributePairType));
if (size_) {
RISCV_free(u_.dict);
}
u_.dict = t1;
}
size_ = size;
}
 
const AttributeType& AttributeType::to_config() {
AutoBuffer strBuffer;
attribute_to_string(this, &strBuffer);
make_string(strBuffer.getBuffer());
return (*this);
}
 
void AttributeType::from_config(const char *str) {
int off = 0;
string_to_attribute(str, off, this);
}
 
void attribute_to_string(const AttributeType *attr, AutoBuffer *buf) {
IService *iserv;
if (attr->is_nil()) {
buf->write_string("None");
} else if (attr->is_int64() || attr->is_uint64()) {
buf->write_uint64(attr->to_uint64());
} else if (attr->is_string()) {
buf->write_string('\'');
buf->write_string(attr->to_string());
buf->write_string('\'');
} else if (attr->is_bool()) {
if (attr->to_bool()) {
buf->write_string("True");
} else {
buf->write_string("False");
}
} else if (attr->is_list()) {
AttributeType list_item;
unsigned list_sz = attr->size();
buf->write_string('[');
for (unsigned i = 0; i < list_sz; i++) {
list_item = (*attr)[i];
attribute_to_string(&list_item, buf);
if (i < (list_sz - 1)) {
buf->write_string(',');
}
}
buf->write_string(']');
} else if (attr->is_dict()) {
AttributeType dict_item;
unsigned dict_sz = attr->size();;
buf->write_string('{');
 
for (unsigned i = 0; i < dict_sz; i++) {
buf->write_string('\'');
buf->write_string(attr->u_.dict[i].key_.to_string());
buf->write_string('\'');
buf->write_string(':');
const AttributeType &dict_value = (*attr)[i];
attribute_to_string(&dict_value, buf);
if (i < (dict_sz - 1)) {
buf->write_string(',');
}
}
buf->write_string('}');
} else if (attr->is_data()) {
buf->write_string('(');
if (attr->size() > 0) {
for (unsigned n = 0; n < attr->size()-1; n++) {
buf->write_byte((*attr)(n));
buf->write_string(',');
}
buf->write_byte((*attr)(attr->size()-1));
}
buf->write_string(')');
} else if (attr->is_iface()) {
IFace *iface = attr->to_iface();
if (strcmp(iface->getFaceName(), IFACE_SERVICE) == 0) {
iserv = static_cast<IService *>(iface);
buf->write_string('{');
buf->write_string("'Type':'");
buf->write_string(iface->getFaceName());
buf->write_string("','ModuleName':'");
buf->write_string(iserv->getObjName());
buf->write_string("'}");
} else {
RISCV_printf(NULL, LOG_ERROR,
"Not implemented interface to dict. method");
}
} else if (attr->is_floating()) {
char fstr[64];
RISCV_sprintf(fstr, sizeof(fstr), "%.4f", attr->to_float());
buf->write_string(fstr);
}
}
 
int skip_special_symbols(const char *cfg, int off) {
const char *pcur = &cfg[off];
while (*pcur == ' ' || *pcur == '\r' || *pcur == '\n' || *pcur == '\t') {
pcur++;
off++;
}
return off;
}
 
int string_to_attribute(const char *cfg, int &off,
AttributeType *out) {
off = skip_special_symbols(cfg, off);
int checkstart = off;
if (cfg[off] == '\'' || cfg[off] == '"') {
AutoBuffer buf;
uint8_t t1 = cfg[off];
int str_sz = 0;
const char *pcur = &cfg[++off];
while (*pcur != t1 && *pcur != '\0') {
pcur++;
str_sz++;
}
buf.write_bin(&cfg[off], str_sz);
out->make_string(buf.getBuffer());
off += str_sz;
if (cfg[off] != t1) {
RISCV_printf(NULL, LOG_ERROR,
"JSON parser error: Wrong string format");
out->attr_free();
return -1;
}
off = skip_special_symbols(cfg, off + 1);
} else if (cfg[off] == '[') {
off = skip_special_symbols(cfg, off + 1);
AttributeType new_item;
out->make_list(0);
while (cfg[off] != ']' && cfg[off] != '\0') {
if (string_to_attribute(cfg, off, &new_item)) {
/* error handling */
out->attr_free();
return -1;
}
out->realloc_list(out->size() + 1);
(*out)[out->size() - 1] = new_item;
 
off = skip_special_symbols(cfg, off);
if (cfg[off] == ',') {
off = skip_special_symbols(cfg, off + 1);
}
}
if (cfg[off] != ']') {
RISCV_printf(NULL, LOG_ERROR,
"JSON parser error: Wrong list format");
out->attr_free();
return -1;
}
off = skip_special_symbols(cfg, off + 1);
} else if (cfg[off] == '{') {
AttributeType new_key;
AttributeType new_value;
out->make_dict();
off = skip_special_symbols(cfg, off + 1);
while (cfg[off] != '}' && cfg[off] != '\0') {
if (string_to_attribute(cfg, off, &new_key)) {
RISCV_printf(NULL, LOG_ERROR,
"JSON parser error: Wrong dictionary key");
out->attr_free();
return -1;
}
off = skip_special_symbols(cfg, off);
if (cfg[off] != ':') {
out->attr_free();
RISCV_printf(NULL, LOG_ERROR,
"JSON parser error: Wrong dictionary delimiter");
return -1;
}
off = skip_special_symbols(cfg, off + 1);
if (string_to_attribute(cfg, off, &new_value)) {
RISCV_printf(NULL, LOG_ERROR,
"JSON parser error: Wrong dictionary value");
out->attr_free();
return -1;
}
 
(*out)[new_key.to_string()] = new_value;
 
off = skip_special_symbols(cfg, off);
if (cfg[off] == ',') {
off = skip_special_symbols(cfg, off + 1);
}
}
if (cfg[off] != '}') {
RISCV_printf(NULL, LOG_ERROR,
"JSON parser error: Wrong dictionary format");
out->attr_free();
return -1;
}
off = skip_special_symbols(cfg, off + 1);
 
if (out->has_key("Type")) {
if (strcmp((*out)["Type"].to_string(), IFACE_SERVICE) == 0) {
IService *iserv;
iserv = static_cast<IService *>(
RISCV_get_service((*out)["ModuleName"].to_string()));
out->attr_free();
*out = AttributeType(iserv);
} else {
RISCV_printf(NULL, LOG_ERROR,
"Not implemented string to dict. attribute");
}
}
} else if (cfg[off] == '(') {
AutoBuffer buf;
char byte_value;
off = skip_special_symbols(cfg, off + 1);
while (cfg[off] != ')' && cfg[off] != '\0') {
byte_value = 0;
for (int n = 0; n < 2; n++) {
if (cfg[off] >= 'A' && cfg[off] <= 'F') {
byte_value = (byte_value << 4) | ((cfg[off] - 'A') + 10);
} else if (cfg[off] >= 'a' && cfg[off] <= 'f') {
byte_value = (byte_value << 4) | ((cfg[off] - 'a') + 10);
} else {
byte_value = (byte_value << 4) | (cfg[off] - '0');
}
off++;
}
buf.write_bin(&byte_value, 1);
 
off = skip_special_symbols(cfg, off);
if (cfg[off] == ')') {
break;
}
if (cfg[off] != ',') {
RISCV_printf(NULL, LOG_ERROR,
"JSON parser error: Wrong data dytes delimiter");
out->attr_free();
return -1;
}
off = skip_special_symbols(cfg, off + 1);
}
if (cfg[off] != ')') {
RISCV_printf(NULL, LOG_ERROR,
"JSON parser error: Wrong data format");
out->attr_free();
return -1;
}
out->make_data(buf.size(), buf.getBuffer());
off = skip_special_symbols(cfg, off + 1);
} else if (cfg[off] == 'N' && cfg[off + 1] == 'o' && cfg[off + 2] == 'n'
&& cfg[off + 3] == 'e') {
out->make_nil();
off = skip_special_symbols(cfg, off + 4);
} else if ((cfg[off] == 'f' || cfg[off] == 'F') && cfg[off + 1] == 'a'
&& cfg[off + 2] == 'l' && cfg[off + 3] == 's'
&& cfg[off + 4] == 'e') {
out->make_boolean(false);
off = skip_special_symbols(cfg, off + 5);
} else if ((cfg[off] == 't' || cfg[off] == 'T') && cfg[off + 1] == 'r'
&& cfg[off + 2] == 'u' && cfg[off + 3] == 'e') {
out->make_boolean(true);
off = skip_special_symbols(cfg, off + 4);
} else {
char digits[64] = {0};
int digits_cnt = 0;
bool negative = false;
if (cfg[off] == '0' && cfg[off + 1] == 'x') {
off += 2;
digits[digits_cnt++] = '0';
digits[digits_cnt++] = 'x';
} else if (cfg[off] == '-') {
negative = true;
off++;
}
while (digits_cnt < 63 && ((cfg[off] >= '0' && cfg[off] <= '9')
|| (cfg[off] >= 'a' && cfg[off] <= 'f')
|| (cfg[off] >= 'A' && cfg[off] <= 'F'))) {
digits[digits_cnt++] = cfg[off++];
digits[digits_cnt] = 0;
}
int64_t t1 = strtoull(digits, NULL, 0);
if (cfg[off] == '.') {
digits_cnt = 0;
digits[0] = 0;
double divrate = 1.0;
double d1 = static_cast<double>(t1);
off++;
bool trim_zeros = true;
while (digits_cnt < 63 && cfg[off] >= '0' && cfg[off] <= '9') {
if (trim_zeros && cfg[off] == '0') {
off++;
divrate *= 10; // Fix: strtoull(0008) gives 0
continue;
}
trim_zeros = false;
digits[digits_cnt++] = cfg[off++];
digits[digits_cnt] = 0;
divrate *= 10.0;
}
t1 = strtoull(digits, NULL, 0);
d1 += static_cast<double>(t1)/divrate;
if (negative) {
d1 = -d1;
}
out->make_floating(d1);
} else {
if (negative) {
t1 = -t1;
}
out->make_int64(t1);
}
off = skip_special_symbols(cfg, off);
}
/** Guard to skip wrong formatted string and avoid hanging: */
if (off == checkstart) {
RISCV_printf(NULL, LOG_ERROR,
"JSON parser error: Can't detect format");
out->attr_free();
return -1;
}
return 0;
}
 
} // namespace debugger
/attribute.h
1,335 → 1,352
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Core attribute class declaration.
*/
 
#ifndef __DEBUGGER_ATTRIBUTE_H__
#define __DEBUGGER_ATTRIBUTE_H__
 
#include <stdint.h>
#include <string.h>
#include "iattr.h"
 
namespace debugger {
 
enum KindType {
Attr_Invalid,
Attr_String,
Attr_Integer,
Attr_UInteger,
Attr_Floating,
Attr_List,
Attr_Data,
Attr_Nil,
Attr_Dict,
Attr_Boolean,
Attr_Interface,
Attr_PyObject,
};
 
class AttributePairType;
 
class AttributeType : public IAttribute {
public:
KindType kind_;
unsigned size_;
union {
char *string;
int64_t integer;
bool boolean;
double floating;
AttributeType *list;
AttributePairType *dict;
uint8_t *data;
uint8_t data_bytes[8]; // Data without allocation
void *py_object;
IFace *iface;
char *uobject;
} u_;
 
AttributeType(const AttributeType& other) {
size_ = 0;
clone(&other);
}
 
AttributeType() {
kind_ = Attr_Invalid;
size_ = 0;
u_.integer = 0;
}
~AttributeType() {
attr_free();
}
 
void attr_free();
 
explicit AttributeType(const char *str) {
make_string(str);
}
 
explicit AttributeType(IFace *mod) {
kind_ = Attr_Interface;
u_.iface = mod;
}
 
explicit AttributeType(KindType type) {
kind_ = type;
size_ = 0;
u_.integer = 0;
}
 
explicit AttributeType(bool val) {
kind_ = Attr_Boolean;
size_ = 0;
u_.boolean = val;
}
 
AttributeType(KindType type, uint64_t v) {
if (type == Attr_Integer) {
make_int64(static_cast<int64_t>(v));
} else if (type == Attr_UInteger) {
make_uint64(v);
}
}
 
unsigned size() const { return size_; }
 
bool is_floating() const {
return kind_ == Attr_Floating;
}
 
double to_float() const {
return u_.floating;
}
 
bool is_integer() const {
return kind_ == Attr_Integer || kind_ == Attr_UInteger;
}
 
bool is_int64() const {
return kind_ == Attr_Integer;
}
 
int to_int() const {
return static_cast<int>(u_.integer);
}
 
int to_uint32() const {
return static_cast<uint32_t>(u_.integer);
}
 
int64_t to_int64() const {
return u_.integer;
}
 
bool is_uint64() const {
return kind_ == Attr_UInteger;
}
 
uint64_t to_uint64() const {
return u_.integer;
}
 
bool is_bool() const {
return kind_ == Attr_Boolean;
}
 
bool to_bool() const { return u_.boolean; }
 
bool is_string() const {
return kind_ == Attr_String;
}
 
const char * to_string() const {
return u_.string;
}
 
bool is_equal(const char *v);
 
// capitalize letters in string;
const char * to_upper() const {
if (kind_ != Attr_String) {
return 0;
}
char *p = u_.string;
while (*p) {
if (p[0] >= 'a' && p[0] <= 'z') {
p[0] = p[0] - 'a' + 'A';
}
p++;
}
return u_.string;
}
 
bool is_list() const {
return kind_ == Attr_List;
}
 
bool is_dict() const {
return kind_ == Attr_Dict;
}
 
bool is_data() const {
return kind_ == Attr_Data;
}
 
bool is_iface() const {
return kind_ == Attr_Interface;
}
 
IFace *to_iface() const {
return u_.iface;
}
 
bool is_nil() const {
return kind_ == Attr_Nil;
}
 
bool is_invalid() const {
return kind_ == Attr_Invalid;
}
 
 
void clone(const AttributeType *v);
 
void make_nil() {
kind_ = Attr_Nil;
size_ = 0;
u_.integer = 0;
}
 
void make_iface(IFace *value) {
kind_ = Attr_Interface;
u_.iface = value;
}
 
void make_floating(double value) {
kind_ = Attr_Floating;
size_ = 0;
u_.floating = value;
}
 
void force_to_floating() {
kind_ = Attr_Floating;
}
 
void make_int64(int64_t value) {
kind_ = Attr_Integer;
size_ = 0;
u_.integer = value;
}
 
void make_uint64(uint64_t value) {
kind_ = Attr_UInteger;
size_ = 0;
u_.integer = value;
}
 
void make_boolean(bool value) {
kind_ = Attr_Boolean;
size_ = 0;
u_.boolean = value;
}
 
void make_string(const char *value);
 
void make_data(unsigned size);
 
void make_data(unsigned size, const void *data);
 
void make_list(unsigned size);
 
void add_to_list(const AttributeType *item) {
realloc_list(size()+1);
(*this)[size()-1] = (*item);
}
 
void insert_to_list(unsigned idx, const AttributeType *item);
 
void remove_from_list(unsigned idx);
 
void trim_list(unsigned start, unsigned end);
 
void swap_list_item(unsigned n, unsigned m);
 
void realloc_list(unsigned size);
 
void make_dict();
void realloc_dict(unsigned size);
 
// Getter:
double floating() const { return u_.floating; }
 
int64_t integer() const { return u_.integer; }
 
const char *string() const { return u_.string; }
 
bool boolean() const { return u_.boolean; }
 
const AttributeType *list(unsigned idx) const {
return &u_.list[idx];
}
AttributeType *list(unsigned idx) {
return &u_.list[idx];
}
 
/* Quicksort algorithm with 'list' attribute */
void sort(int idx = 0);
 
bool has_key(const char *key) const;
 
const AttributeType *dict_key(unsigned idx) const;
AttributeType *dict_key(unsigned idx);
 
const AttributeType *dict_value(unsigned idx) const;
AttributeType *dict_value(unsigned idx);
 
const uint8_t *data() const {
if (size_ > 8) {
return u_.data;
}
return u_.data_bytes;
}
uint8_t *data() {
if (size_ > 8) {
return u_.data;
}
return u_.data_bytes;
}
 
AttributeType& operator=(const AttributeType& other);
 
/**
* @brief Access to the single element of the 'list' attribute:
*/
const AttributeType& operator[](unsigned idx) const;
/** @overload */
AttributeType& operator[](unsigned idx);
 
/**
* @brief Access to the single value attribute of the 'dictionary':
*/
const AttributeType& operator[](const char *key) const;
/** @overload */
AttributeType& operator[](const char *key);
 
/**
* @brief Access to the single byte of the 'data' attribute:
*/
const uint8_t& operator()(unsigned idx) const;
 
char *to_config();
void from_config(const char *str);
};
 
class AttributePairType {
public:
AttributeType key_;
AttributeType value_;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_ATTRIBUTE_H__
/*
* Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
#ifndef __DEBUGGER_ATTRIBUTE_H__
#define __DEBUGGER_ATTRIBUTE_H__
 
#include <stdint.h>
#include <string.h>
#include <iattr.h>
 
namespace debugger {
 
enum KindType {
Attr_Invalid,
Attr_String,
Attr_Integer,
Attr_UInteger,
Attr_Floating,
Attr_List,
Attr_Data,
Attr_Nil,
Attr_Dict,
Attr_Boolean,
Attr_Interface,
Attr_PyObject,
};
 
class AttributePairType;
 
class AttributeType : public IAttribute {
public:
KindType kind_;
unsigned size_;
union {
char *string;
int64_t integer;
bool boolean;
double floating;
AttributeType *list;
AttributePairType *dict;
uint8_t *data;
uint8_t data_bytes[8]; // Data without allocation
void *py_object;
IFace *iface;
char *uobject;
} u_;
 
AttributeType(const AttributeType& other) {
size_ = 0;
clone(&other);
}
 
AttributeType() {
kind_ = Attr_Invalid;
size_ = 0;
u_.integer = 0;
}
~AttributeType() {
attr_free();
}
 
/** IAttribute */
virtual void allocAttrName(const char *name);
virtual void freeAttrName();
virtual void allocAttrDescription(const char *descr);
virtual void freeAttrDescription();
 
void attr_free();
 
explicit AttributeType(const char *str) {
make_string(str);
}
 
explicit AttributeType(IFace *mod) {
kind_ = Attr_Interface;
u_.iface = mod;
}
 
explicit AttributeType(KindType type) {
kind_ = type;
size_ = 0;
u_.integer = 0;
}
 
explicit AttributeType(bool val) {
kind_ = Attr_Boolean;
size_ = 0;
u_.boolean = val;
}
 
AttributeType(KindType type, uint64_t v) {
if (type == Attr_Integer) {
make_int64(static_cast<int64_t>(v));
} else if (type == Attr_UInteger) {
make_uint64(v);
}
}
 
unsigned size() const { return size_; }
 
bool is_floating() const {
return kind_ == Attr_Floating;
}
 
double to_float() const {
return u_.floating;
}
 
bool is_integer() const {
return kind_ == Attr_Integer || kind_ == Attr_UInteger;
}
 
bool is_int64() const {
return kind_ == Attr_Integer;
}
 
int to_int() const {
return static_cast<int>(u_.integer);
}
 
uint32_t to_uint32() const {
return static_cast<uint32_t>(u_.integer);
}
 
int64_t to_int64() const {
return u_.integer;
}
 
bool is_uint64() const {
return kind_ == Attr_UInteger;
}
 
uint64_t to_uint64() const {
return u_.integer;
}
 
bool is_bool() const {
return kind_ == Attr_Boolean;
}
 
bool to_bool() const { return u_.boolean; }
 
bool is_string() const {
return kind_ == Attr_String;
}
 
const char * to_string() const {
return u_.string;
}
 
bool is_equal(const char *v);
 
// capitalize letters in string;
const char * to_upper() const {
if (kind_ != Attr_String) {
return 0;
}
char *p = u_.string;
while (*p) {
if (p[0] >= 'a' && p[0] <= 'z') {
p[0] = p[0] - 'a' + 'A';
}
p++;
}
return u_.string;
}
 
bool is_list() const {
return kind_ == Attr_List;
}
 
bool is_dict() const {
return kind_ == Attr_Dict;
}
 
bool is_data() const {
return kind_ == Attr_Data;
}
 
bool is_iface() const {
return kind_ == Attr_Interface;
}
 
IFace *to_iface() const {
return u_.iface;
}
 
bool is_nil() const {
return kind_ == Attr_Nil;
}
 
bool is_invalid() const {
return kind_ == Attr_Invalid;
}
 
 
void clone(const AttributeType *v);
 
void make_nil() {
kind_ = Attr_Nil;
size_ = 0;
u_.integer = 0;
}
 
void make_iface(IFace *value) {
kind_ = Attr_Interface;
u_.iface = value;
}
 
void make_floating(double value) {
kind_ = Attr_Floating;
size_ = 0;
u_.floating = value;
}
 
void force_to_floating() {
kind_ = Attr_Floating;
}
 
void make_int64(int64_t value) {
kind_ = Attr_Integer;
size_ = 0;
u_.integer = value;
}
 
void make_uint64(uint64_t value) {
kind_ = Attr_UInteger;
size_ = 0;
u_.integer = value;
}
 
void make_boolean(bool value) {
kind_ = Attr_Boolean;
size_ = 0;
u_.boolean = value;
}
 
void make_string(const char *value);
 
void make_data(unsigned size);
 
void make_data(unsigned size, const void *data);
 
void realloc_data(unsigned size);
 
void make_list(unsigned size);
 
void add_to_list(const AttributeType *item) {
realloc_list(size()+1);
(*this)[size()-1] = (*item);
}
 
void insert_to_list(unsigned idx, const AttributeType *item);
 
void remove_from_list(unsigned idx);
 
void trim_list(unsigned start, unsigned end);
 
void swap_list_item(unsigned n, unsigned m);
 
void realloc_list(unsigned size);
 
void make_dict();
void realloc_dict(unsigned size);
 
// Getter:
double floating() const { return u_.floating; }
 
int64_t integer() const { return u_.integer; }
 
const char *string() const { return u_.string; }
 
bool boolean() const { return u_.boolean; }
 
const AttributeType *list(unsigned idx) const {
return &u_.list[idx];
}
AttributeType *list(unsigned idx) {
return &u_.list[idx];
}
 
/* Quicksort algorithm with 'list' attribute */
void sort(int idx = 0);
 
bool has_key(const char *key) const;
 
const AttributeType *dict_key(unsigned idx) const;
AttributeType *dict_key(unsigned idx);
 
const AttributeType *dict_value(unsigned idx) const;
AttributeType *dict_value(unsigned idx);
 
const uint8_t *data() const {
if (size_ > 8) {
return u_.data;
}
return u_.data_bytes;
}
uint8_t *data() {
if (size_ > 8) {
return u_.data;
}
return u_.data_bytes;
}
 
AttributeType& operator=(const AttributeType& other);
 
/**
* @brief Access to the single element of the 'list' attribute:
*/
const AttributeType& operator[](unsigned idx) const;
/** @overload */
AttributeType& operator[](unsigned idx);
 
/**
* @brief Access to the single value attribute of the 'dictionary':
*/
const AttributeType& operator[](const char *key) const;
/** @overload */
AttributeType& operator[](const char *key);
 
/**
* @brief Access to the single byte of the 'data' attribute:
*/
const uint8_t& operator()(unsigned idx) const;
 
const AttributeType& to_config();
void from_config(const char *str);
};
 
class AttributePairType {
public:
AttributeType key_;
AttributeType value_;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_ATTRIBUTE_H__
/autobuffer.cpp
1,67 → 1,76
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Dynamically allocated buffer implementation.
*/
 
#include "api_core.h"
#include "autobuffer.h"
#include <cstdio>
#include <cstring> // memcpy definition
 
namespace debugger {
 
AutoBuffer::AutoBuffer() {
buf_ = NULL;
buf_len_ = 0;
buf_size_ = 0;
}
 
AutoBuffer::~AutoBuffer() {
if (buf_) {
delete [] buf_;
}
}
 
void AutoBuffer::write_bin(const char *p, int sz) {
if (buf_len_ + sz >= buf_size_) {
if (buf_size_ == 0) {
buf_size_ = 1024;
buf_ = new char[buf_size_];
} else {
while (buf_len_ + sz >= buf_size_) {
buf_size_ <<= 1;
}
char *t1 = new char[buf_size_];
memcpy(t1, buf_, buf_len_);
delete [] buf_;
buf_ = t1;
}
}
memcpy(&buf_[buf_len_], p, sz);
buf_len_ += sz;
buf_[buf_len_] = '\0';
}
 
void AutoBuffer::write_string(const char s) {
write_bin(&s, 1);
}
 
void AutoBuffer::write_string(const char *s) {
write_bin(s, static_cast<int>(strlen(s)));
}
 
void AutoBuffer::write_uint64(uint64_t v) {
char tmp[128];
int sz = RISCV_sprintf(tmp, sizeof(tmp),"0x%" RV_PRI64 "x", v);
write_bin(tmp, sz);
}
 
void AutoBuffer::write_byte(uint8_t v) {
char tmp[8];
int sz = RISCV_sprintf(tmp, sizeof(tmp), "%02X", v);
write_bin(tmp, sz);
}
 
} // namespace debugger
/*
* Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
#include <autobuffer.h>
#include <api_core.h>
#include <cstdio>
#include <cstring> // memcpy definition
 
namespace debugger {
 
AutoBuffer::AutoBuffer() {
buf_ = NULL;
buf_len_ = 0;
buf_size_ = 0;
}
 
AutoBuffer::~AutoBuffer() {
if (buf_) {
delete [] buf_;
}
}
 
void AutoBuffer::write_bin(const char *p, int sz) {
if (buf_len_ + sz >= buf_size_) {
if (buf_size_ == 0) {
buf_size_ = 1024;
buf_ = new char[buf_size_];
} else {
while (buf_len_ + sz >= buf_size_) {
buf_size_ <<= 1;
}
char *t1 = new char[buf_size_];
memcpy(t1, buf_, buf_len_);
delete [] buf_;
buf_ = t1;
}
}
memcpy(&buf_[buf_len_], p, sz);
buf_len_ += sz;
buf_[buf_len_] = '\0';
}
 
void AutoBuffer::write_string(const char s) {
write_bin(&s, 1);
}
 
void AutoBuffer::write_string(const char *s) {
write_bin(s, static_cast<int>(strlen(s)));
}
 
void AutoBuffer::write_uint64(uint64_t v) {
char tmp[128];
int sz = RISCV_sprintf(tmp, sizeof(tmp), "0x%" RV_PRI64 "x", v);
write_bin(tmp, sz);
}
 
void AutoBuffer::write_byte(uint8_t v) {
char tmp[8];
int sz = RISCV_sprintf(tmp, sizeof(tmp), "0x%02X", v);
write_bin(tmp, sz);
}
 
} // namespace debugger
/autobuffer.h
1,79 → 1,88
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Dynamically allocated buffer declaration.
*/
 
#ifndef __DEBUGGER_AUTOBUFFER_H__
#define __DEBUGGER_AUTOBUFFER_H__
 
#include <stdint.h>
#include <string.h>
 
namespace debugger {
 
/**
* @brief String buffer declaration.
* @details This buffer is used to form configuration string of the kernel.
*/
class AutoBuffer {
public:
/** Create empty string buffer. */
AutoBuffer();
~AutoBuffer();
 
/**
* @brief Write input data of the specified size into buffer's memory.
* @param[in] p Pointer on input data.
* @param[in] sz Input buffer size in bytes.
*/
void write_bin(const char *p, int sz);
/**
* @brief Write single symbol into buffer's memory.
* @param[in] s Input character value.
*/
void write_string(const char s);
/**
* @brief Write input string into buffer's memory.
* @param[in] s Pointer on string buffer.
*/
void write_string(const char *s);
/**
* @brief Write integer value as a hex string into buffer's memory.
* @param[in] s Input integer value.
*/
void write_uint64(uint64_t v);
/**
* @brief Write a single byte into buffer's memory.
* @details This method is very usefull to write special characters, like
* '\0', '\n' etc.
* @param[in] s Input byte value.
*/
void write_byte(uint8_t v);
 
/**
* @brief Get allocated memory pointer.
* @return Pointer on allocated memory region.
*/
char *getBuffer() { return buf_; }
 
/** Get total number of written symbols. */
int size() { return buf_len_; }
/** Reset buffer's value. */
void clear() {
buf_len_ = 0;
if (buf_) {
buf_[buf_len_] = 0;
}
}
 
private:
char *buf_;
int buf_len_;
int buf_size_;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_AUTOBUFFER_H__
/*
* Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
#ifndef __DEBUGGER_AUTOBUFFER_H__
#define __DEBUGGER_AUTOBUFFER_H__
 
#include <stdint.h>
#include <string.h>
 
namespace debugger {
 
/**
* @brief String buffer declaration.
* @details This buffer is used to form configuration string of the kernel.
*/
class AutoBuffer {
public:
/** Create empty string buffer. */
AutoBuffer();
~AutoBuffer();
 
/**
* @brief Write input data of the specified size into buffer's memory.
* @param[in] p Pointer on input data.
* @param[in] sz Input buffer size in bytes.
*/
void write_bin(const char *p, int sz);
/**
* @brief Write single symbol into buffer's memory.
* @param[in] s Input character value.
*/
void write_string(const char s);
/**
* @brief Write input string into buffer's memory.
* @param[in] s Pointer on string buffer.
*/
void write_string(const char *s);
/**
* @brief Write integer value as a hex string into buffer's memory.
* @param[in] s Input integer value.
*/
void write_uint64(uint64_t v);
/**
* @brief Write a single byte into buffer's memory.
* @details This method is very usefull to write special characters, like
* '\0', '\n' etc.
* @param[in] s Input byte value.
*/
void write_byte(uint8_t v);
 
/**
* @brief Get allocated memory pointer.
* @return Pointer on allocated memory region.
*/
char *getBuffer() { return buf_; }
 
/** Get total number of written symbols. */
int size() { return buf_len_; }
/** Reset buffer's value. */
void clear() {
buf_len_ = 0;
if (buf_) {
buf_[buf_len_] = 0;
}
}
 
private:
char *buf_;
int buf_len_;
int buf_size_;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_AUTOBUFFER_H__
/coreservices/iudp.h File deleted
/coreservices/ibus.h File deleted
/coreservices/iautocomplete.h
5,11 → 5,11
* @brief Autocompleter's interface.
*/
 
#ifndef __DEBUGGER_IAUTOCOMPLETE_H__
#define __DEBUGGER_IAUTOCOMPLETE_H__
#ifndef __DEBUGGER_COMMON_CORESERVICES_IAUTOCOMPLETE_H__
#define __DEBUGGER_COMMON_CORESERVICES_IAUTOCOMPLETE_H__
 
#include "iface.h"
#include "attribute.h"
#include <iface.h>
#include <attribute.h>
 
namespace debugger {
 
16,7 → 16,7
static const char *IFACE_AUTO_COMPLETE = "IAutoComplete";
 
/** Qt Compatible Virtual Keys */
#if defined(_WIN32) || defined(__CYGWIN__)
#if defined(_WIN32) || defined(__CYGWIN__)
static const uint32_t KB_Backspace = 0x0008;
static const uint32_t KB_Tab = 0x0009;
static const uint32_t KB_Return = 0x000d;
44,8 → 44,8
static const uint32_t KB_Escape = 0xff1b;
static const uint32_t KB_PageUp = 0xff25;
static const uint32_t KB_PageDown = 0xffe4;
//static const uint32_t KB_End = 0x0000;
//static const uint32_t KB_Home = 0x0000;
// static const uint32_t KB_End = 0x0000;
// static const uint32_t KB_Home = 0x0000;
static const uint32_t KB_Left = 0xff23;
static const uint32_t KB_Up = 0xff26;
static const uint32_t KB_Right = 0xff22;
56,7 → 56,7
 
 
class IAutoComplete : public IFace {
public:
public:
IAutoComplete() : IFace(IFACE_AUTO_COMPLETE) {}
 
/**
63,9 → 63,9
* @return New command ready flag
*/
virtual bool processKey(uint32_t qt_key, AttributeType *cmd,
AttributeType *cursor) =0;
AttributeType *cursor) = 0;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_IAUTOCOMPLETE_H__
#endif // __DEBUGGER_COMMON_CORESERVICES_IAUTOCOMPLETE_H__
/coreservices/iclklistener.h
1,27 → 1,27
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Clock listener interface.
*/
 
#ifndef __DEBUGGER_PLUGIN_ICLOCK_LISTENER_H__
#define __DEBUGGER_PLUGIN_ICLOCK_LISTENER_H__
 
#include "iface.h"
#include <inttypes.h>
 
namespace debugger {
 
static const char *const IFACE_CLOCK_LISTENER = "IClockListener";
 
class IClockListener : public IFace {
public:
IClockListener() : IFace(IFACE_CLOCK_LISTENER) {}
 
virtual void stepCallback(uint64_t t) =0;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_PLUGIN_ICLOCK_LISTENER_H__
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Clock listener interface.
*/
 
#ifndef __DEBUGGER_COMMON_CORESERVICES_ICLKLISTENER_H__
#define __DEBUGGER_COMMON_CORESERVICES_ICLKLISTENER_H__
 
#include <inttypes.h>
#include <iface.h>
 
namespace debugger {
 
static const char *const IFACE_CLOCK_LISTENER = "IClockListener";
 
class IClockListener : public IFace {
public:
IClockListener() : IFace(IFACE_CLOCK_LISTENER) {}
 
virtual void stepCallback(uint64_t t) = 0;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_COMMON_CORESERVICES_ICLKLISTENER_H__
/coreservices/iclock.h
1,37 → 1,48
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Clock interface.
*/
 
#ifndef __DEBUGGER_PLUGIN_ICLOCK_H__
#define __DEBUGGER_PLUGIN_ICLOCK_H__
 
#include "iface.h"
#include <inttypes.h>
#include "iclklistener.h"
#include "attribute.h"
 
namespace debugger {
 
static const char *const IFACE_CLOCK = "IClock";
 
class IClock : public IFace {
public:
IClock() : IFace(IFACE_CLOCK) {}
 
virtual uint64_t getStepCounter() =0;
 
/** Executed instruction counter.
*
* One executed instruction = 1 step for functional simulation.
* And it can be more than 1 for precise SystemC model if enabled
* GENERATE_CORE_TRACE.
*/
virtual void registerStepCallback(IClockListener *cb, uint64_t t) =0;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_PLUGIN_ICLOCK_H__
/*
* Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
#ifndef __DEBUGGER_COMMON_CORESERVICES_ICLOCK_H__
#define __DEBUGGER_COMMON_CORESERVICES_ICLOCK_H__
 
#include <inttypes.h>
#include <iface.h>
#include <attribute.h>
#include "iclklistener.h"
 
namespace debugger {
 
static const char *const IFACE_CLOCK = "IClock";
 
class IClock : public IFace {
public:
IClock() : IFace(IFACE_CLOCK) {}
 
virtual uint64_t getStepCounter() = 0;
 
/** Executed instruction counter.
*
* One executed instruction = 1 step for functional simulation.
* And it can be more than 1 for precise SystemC model if enabled
* GENERATE_CORE_TRACE.
*/
virtual void registerStepCallback(IClockListener *cb, uint64_t t) = 0;
 
virtual double getFreqHz() = 0;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_COMMON_CORESERVICES_ICLOCK_H__
/coreservices/icmdexec.h
5,11 → 5,11
* @brief Command executer's interface.
*/
 
#ifndef __DEBUGGER_ICMDEXEC_H__
#define __DEBUGGER_ICMDEXEC_H__
#ifndef __DEBUGGER_COMMON_CODESERVICES_ICMDEXEC_H__
#define __DEBUGGER_COMMON_CODESERVICES_ICMDEXEC_H__
 
#include "iface.h"
#include "attribute.h"
#include <iface.h>
#include <attribute.h>
#include "icommand.h"
 
namespace debugger {
17,20 → 17,20
static const char *IFACE_CMD_EXECUTOR = "ICmdExecutor";
 
class ICmdExecutor : public IFace {
public:
public:
ICmdExecutor() : IFace(IFACE_CMD_EXECUTOR) {}
 
/** Register command with ICommand interface */
virtual void registerCommand(ICommand *icmd) =0;
virtual void unregisterCommand(ICommand *icmd) =0;
virtual void registerCommand(ICommand *icmd) = 0;
virtual void unregisterCommand(ICommand *icmd) = 0;
 
/** Execute string as a command */
virtual void exec(const char *line, AttributeType *res, bool silent) =0;
virtual void exec(const char *line, AttributeType *res, bool silent) = 0;
 
/** Get list of supported comands starting with substring 'substr' */
virtual void commands(const char *substr, AttributeType *res) =0;
virtual void commands(const char *substr, AttributeType *res) = 0;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_ICMDEXEC_H__
#endif // __DEBUGGER_COMMON_CODESERVICES_ICMDEXEC_H__
/coreservices/icommand.h
5,15 → 5,14
* @brief User's command interface.
*/
 
#ifndef __DEBUGGER_ICOMMAND_H__
#define __DEBUGGER_ICOMMAND_H__
#ifndef __DEBUGGER_COMMON_CORESERVICES_ICOMMAND_H__
#define __DEBUGGER_COMMON_CORESERVICES_ICOMMAND_H__
 
#include "iface.h"
#include "attribute.h"
#include <iface.h>
#include <attribute.h>
#include "coreservices/itap.h"
#include "coreservices/isocinfo.h"
 
 
namespace debugger {
 
static const char *IFACE_COMMAND = "ICommand";
22,8 → 21,8
static const bool CMD_INVALID = false;
 
class ICommand : public IFace {
public:
ICommand(const char *name, ITap *tap, ISocInfo *info)
public:
ICommand(const char *name, ITap *tap, ISocInfo *info)
: IFace(IFACE_COMMAND) {
cmdName_.make_string(name);
tap_ = tap;
35,8 → 34,8
virtual const char *briefDescr() { return briefDescr_.to_string(); }
virtual const char *detailedDescr() { return detailedDescr_.to_string(); }
 
virtual bool isValid(AttributeType *args) =0;
virtual void exec(AttributeType *args, AttributeType *res) =0;
virtual bool isValid(AttributeType *args) = 0;
virtual void exec(AttributeType *args, AttributeType *res) = 0;
 
virtual void generateError(AttributeType *res, const char *descr) {
res->make_list(3);
45,7 → 44,7
(*res)[2].make_string(descr);
}
 
protected:
protected:
AttributeType cmdName_;
AttributeType briefDescr_;
AttributeType detailedDescr_;
55,4 → 54,4
 
} // namespace debugger
 
#endif // __DEBUGGER_ICOMMAND_H__
#endif // __DEBUGGER_COMMON_CORESERVICES_ICOMMAND_H__
/coreservices/icpuriscv.h
1,52 → 1,29
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief RISC-V simulating CPU interface.
*/
 
#ifndef __DEBUGGER_SOCSIM_PLUGIN_CPU_RISCV_H__
#define __DEBUGGER_SOCSIM_PLUGIN_CPU_RISCV_H__
 
#include "iface.h"
#include <inttypes.h>
 
namespace debugger {
 
static const char *const IFACE_CPU_RISCV = "ICpuRiscV";
static const char *const IFACE_DBG_NB_RESPONSE = "IDbgNbResponse";
 
static const uint64_t REG_INVALID = ~0;
/** Signal types */
static const int CPU_SIGNAL_RESET = 0;
static const int CPU_SIGNAL_EXT_IRQ = 1;
 
struct DebugPortTransactionType {
bool write;
uint8_t region;
uint16_t addr;
uint64_t wdata;
uint64_t rdata;
};
 
class IDbgNbResponse : public IFace {
public:
IDbgNbResponse() : IFace(IFACE_DBG_NB_RESPONSE) {}
 
virtual void nb_response_debug_port(DebugPortTransactionType *trans) =0;
};
 
 
class ICpuRiscV : public IFace {
public:
ICpuRiscV() : IFace(IFACE_CPU_RISCV) {}
 
virtual void raiseSignal(int idx) =0;
virtual void lowerSignal(int idx) =0;
virtual void nb_transport_debug_port(DebugPortTransactionType *trans,
IDbgNbResponse *cb) =0;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_SOCSIM_PLUGIN_CPU_RISCV_H__
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief RISC-V simulating CPU interface.
*/
 
#ifndef __DEBUGGER_SOCSIM_PLUGIN_CPU_RISCV_H__
#define __DEBUGGER_SOCSIM_PLUGIN_CPU_RISCV_H__
 
#include "iface.h"
#include <inttypes.h>
 
namespace debugger {
 
static const char *const IFACE_CPU_RISCV = "ICpuRiscV";
 
/** Signal types */
//static const int CPU_SIGNAL_RESET = 0;
//static const int CPU_SIGNAL_EXT_IRQ = 1;
 
class ICpuRiscV : public IFace {
public:
ICpuRiscV() : IFace(IFACE_CPU_RISCV) {}
};
 
} // namespace debugger
 
#endif // __DEBUGGER_SOCSIM_PLUGIN_CPU_RISCV_H__
/coreservices/ielfreader.h
1,57 → 1,38
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Interface of elf-file reader.
*/
 
#ifndef __DEBUGGER_ELFREADER_H__
#define __DEBUGGER_ELFREADER_H__
 
#include <stdint.h>
#include "iface.h"
#include "attribute.h"
 
namespace debugger {
 
static const char *const IFACE_ELFREADER = "IElfReader";
 
enum ESymbolType {
SYMBOL_TYPE_FILE = 0x01,
SYMBOL_TYPE_FUNCTION = 0x02,
SYMBOL_TYPE_DATA = 0x04
};
 
enum ESymbolInfoListItem {
Symbol_Name,
Symbol_Addr,
Symbol_Size,
Symbol_Type,
Symbol_Total
};
 
 
class IElfReader : public IFace {
public:
IElfReader() : IFace(IFACE_ELFREADER) {}
 
virtual int readFile(const char *filename) =0;
 
virtual unsigned loadableSectionTotal() =0;
 
virtual const char *sectionName(unsigned idx) =0;
 
virtual uint64_t sectionAddress(unsigned idx) =0;
 
virtual uint64_t sectionSize(unsigned idx) =0;
 
virtual uint8_t *sectionData(unsigned idx) =0;
 
virtual void getSymbols(AttributeType *list) =0;
 
virtual void addressToSymbol(uint64_t addr, AttributeType *info) =0;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_ELFREADER_H__
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Interface of elf-file reader.
*/
 
#ifndef __DEBUGGER_ELFREADER_H__
#define __DEBUGGER_ELFREADER_H__
 
#include <stdint.h>
#include <iface.h>
#include <attribute.h>
 
namespace debugger {
 
static const char *const IFACE_ELFREADER = "IElfReader";
 
class IElfReader : public IFace {
public:
IElfReader() : IFace(IFACE_ELFREADER) {}
 
virtual int readFile(const char *filename) = 0;
 
virtual unsigned loadableSectionTotal() = 0;
 
virtual const char *sectionName(unsigned idx) = 0;
 
virtual uint64_t sectionAddress(unsigned idx) = 0;
 
virtual uint64_t sectionSize(unsigned idx) = 0;
 
virtual uint8_t *sectionData(unsigned idx) = 0;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_ELFREADER_H__
/coreservices/imemop.h
1,92 → 1,128
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Memory Operation interface implemented by slave devices on bus.
*/
 
#ifndef __DEBUGGER_IMEMOP_PLUGIN_H__
#define __DEBUGGER_IMEMOP_PLUGIN_H__
 
#include "iface.h"
#include <inttypes.h>
#include "isocinfo.h"
 
namespace debugger {
 
static const char *const IFACE_MEMORY_OPERATION = "IMemoryOperation";
static const char *const IFACE_AXI4_NB_RESPONSE = "IAxi4NbResponse";
 
static const int PAYLOAD_MAX_BYTES = 8;
 
enum EAxi4Action {
MemAction_Read,
MemAction_Write,
MemAction_Total
};
 
enum EAxi4Response {
MemResp_Valid,
MemResp_Accepted,
MemResp_Error
};
 
typedef struct Axi4TransactionType {
EAxi4Action action;
EAxi4Response response;
uint32_t xsize; // [Bytes] Isn't used XSize AXI format!!!.
uint32_t wstrb; // 1 bit per byte
uint64_t addr;
union {
uint8_t b8[PAYLOAD_MAX_BYTES];
uint16_t b16[PAYLOAD_MAX_BYTES/sizeof(uint16_t)];
uint32_t b32[PAYLOAD_MAX_BYTES/sizeof(uint32_t)];
uint64_t b64[PAYLOAD_MAX_BYTES/sizeof(uint64_t)];
} rpayload, wpayload;
int source_idx; // Need for bus utilization statistic
} Axi4TransactionType;
 
/**
* Non-blocking memory access response interface (Initiator/Master)
*/
class IAxi4NbResponse : public IFace {
public:
IAxi4NbResponse() : IFace(IFACE_AXI4_NB_RESPONSE) {}
 
virtual void nb_response(Axi4TransactionType *trans) =0;
};
 
/**
* Slave/Targer interface
*/
class IMemoryOperation : public IFace {
public:
IMemoryOperation() : IFace(IFACE_MEMORY_OPERATION) {}
 
/**
* Blocking transaction
*
* Must be implemented by any functional/systemc device mapped into memory
*/
virtual void b_transport(Axi4TransactionType *trans) =0;
 
/**
* Non-blocking transaction
*
* Can be implemented for interaction with the SystemC model for an example.
* Default implementation re-direct to blocking transport
*/
virtual void nb_transport(Axi4TransactionType *trans,
IAxi4NbResponse *cb) {
b_transport(trans);
cb->nb_response(trans);
}
 
virtual uint64_t getBaseAddress() =0;
 
virtual uint64_t getLength() =0;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_IMEMOP_PLUGIN_H__
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Memory Operation interface implemented by slave devices on bus.
*/
 
#ifndef __DEBUGGER_IMEMOP_PLUGIN_H__
#define __DEBUGGER_IMEMOP_PLUGIN_H__
 
#include <inttypes.h>
#include <iface.h>
#include <attribute.h>
 
namespace debugger {
class IService;
 
static const char *const IFACE_MEMORY_OPERATION = "IMemoryOperation";
static const char *const IFACE_AXI4_NB_RESPONSE = "IAxi4NbResponse";
 
static const int PAYLOAD_MAX_BYTES = 8;
 
enum EAxi4Action {
MemAction_Read,
MemAction_Write,
MemAction_Total
};
 
enum EAxi4Response {
MemResp_Valid,
MemResp_Accepted,
MemResp_Error
};
 
enum ETransStatus {
TRANS_OK,
TRANS_ERROR
};
 
typedef struct Axi4TransactionType {
EAxi4Action action;
EAxi4Response response;
uint32_t xsize; // [Bytes] Isn't used XSize AXI format!!!.
uint32_t wstrb; // 1 bit per byte
uint64_t addr;
union {
uint8_t b8[PAYLOAD_MAX_BYTES];
uint16_t b16[PAYLOAD_MAX_BYTES/sizeof(uint16_t)];
uint32_t b32[PAYLOAD_MAX_BYTES/sizeof(uint32_t)];
uint64_t b64[PAYLOAD_MAX_BYTES/sizeof(uint64_t)];
} rpayload, wpayload;
int source_idx; // Need for bus utilization statistic
} Axi4TransactionType;
 
/**
* Non-blocking memory access response interface (Initiator/Master)
*/
class IAxi4NbResponse : public IFace {
public:
IAxi4NbResponse() : IFace(IFACE_AXI4_NB_RESPONSE) {}
 
virtual void nb_response(Axi4TransactionType *trans) = 0;
};
 
/**
* Slave/Targer interface
*/
class IMemoryOperation : public IFace {
public:
IMemoryOperation() : IFace(IFACE_MEMORY_OPERATION) {
imap_.make_list(0);
listMap_.make_list(0);
baseAddress_.make_uint64(0);
length_.make_uint64(0);
}
 
/**
* Add new device to memory space. Mapping device has to implement
* IMemoryOperaton interface.
*/
virtual void map(IMemoryOperation *imemop) {
AttributeType t1(imemop);
imap_.add_to_list(&t1);
}
 
/**
* Blocking transaction
*
* Must be implemented by any functional/systemc device mapped into memory
*/
virtual ETransStatus b_transport(Axi4TransactionType *trans) = 0;
 
/**
* Non-blocking transaction
*
* Can be implemented for interaction with the SystemC model for an example.
* Default implementation re-direct to blocking transport
*/
virtual ETransStatus nb_transport(Axi4TransactionType *trans,
IAxi4NbResponse *cb) {
ETransStatus ret = b_transport(trans);
cb->nb_response(trans);
return ret;
}
 
virtual uint64_t getBaseAddress() { return baseAddress_.to_uint64(); }
virtual void setBaseAddress(uint64_t addr) {
baseAddress_.make_uint64(addr);
}
 
virtual uint64_t getLength() { return length_.to_uint64(); }
 
/** Higher value, higher priority */
virtual int getPriority() { return priority_.to_int(); }
virtual void setPriority(int v) { priority_.make_int64(v); }
 
protected:
friend class IService;
AttributeType listMap_;
AttributeType imap_;
AttributeType baseAddress_;
AttributeType length_;
AttributeType priority_;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_IMEMOP_PLUGIN_H__
/coreservices/irawlistener.h
1,26 → 1,26
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Raw Data listener interface declaration.
*/
 
#ifndef __DEBUGGER_IRAW_LISTENER_H__
#define __DEBUGGER_IRAW_LISTENER_H__
 
#include "iface.h"
 
namespace debugger {
 
static const char *IFACE_RAW_LISTENER = "IRawListener";
 
class IRawListener : public IFace {
public:
IRawListener() : IFace(IFACE_RAW_LISTENER) {}
 
virtual void updateData(const char *buf, int buflen) =0;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_IRAW_LISTENER_H__
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Raw Data listener interface declaration.
*/
 
#ifndef __DEBUGGER_COMMON_CORESERVICES_IRAWLISTENER_H__
#define __DEBUGGER_COMMON_CORESERVICES_IRAWLISTENER_H__
 
#include <iface.h>
 
namespace debugger {
 
static const char *IFACE_RAW_LISTENER = "IRawListener";
 
class IRawListener : public IFace {
public:
IRawListener() : IFace(IFACE_RAW_LISTENER) {}
 
virtual void updateData(const char *buf, int buflen) = 0;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_COMMON_CORESERVICES_IRAWLISTENER_H__
/coreservices/iserial.h
1,33 → 1,37
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Serial Interface declaration.
*/
 
#ifndef __DEBUGGER_ISERIAL_H__
#define __DEBUGGER_ISERIAL_H__
 
#include "iface.h"
 
namespace debugger {
 
static const char *IFACE_SERIAL = "ISerial";
 
class ISerial : public IFace {
public:
ISerial() : IFace(IFACE_SERIAL) {}
 
/**
* @brief Write data buffer from external module.
* @return Number of written bytes.
*/
virtual int writeData(const char *buf, int sz) =0;
 
virtual void registerRawListener(IFace *listener) =0;
virtual void unregisterRawListener(IFace *listener) =0;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_ISERIAL_H__
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Serial Interface declaration.
*/
 
#ifndef __DEBUGGER_ISERIAL_H__
#define __DEBUGGER_ISERIAL_H__
 
#include <iface.h>
 
namespace debugger {
 
static const char *IFACE_SERIAL = "ISerial";
 
class ISerial : public IFace {
public:
ISerial() : IFace(IFACE_SERIAL) {}
 
/**
* @brief Write data buffer from external module.
* @return Number of written bytes.
*/
virtual int writeData(const char *buf, int sz) = 0;
 
virtual void registerRawListener(IFace *listener) = 0;
virtual void unregisterRawListener(IFace *listener) = 0;
 
virtual void getListOfPorts(AttributeType *list) = 0;
virtual int openPort(const char *port, AttributeType settings) = 0;
virtual void closePort() = 0;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_ISERIAL_H__
/coreservices/isocinfo.h
5,11 → 5,12
* @brief SOC Information interface.
*/
 
#ifndef __DEBUGGER_ISOCINFO_H__
#define __DEBUGGER_ISOCINFO_H__
#ifndef __DEBUGGER_COMMON_CORESERVICES_ISOCINFO_H__
#define __DEBUGGER_COMMON_CORESERVICES_ISOCINFO_H__
 
#include "iface.h"
#include "attribute.h"
#include <iface.h>
#include <attribute.h>
#include "debug/debugmap.h"
 
namespace debugger {
 
18,7 → 19,8
static const int CFG_NASTI_MASTER_CACHED = 0;
static const int CFG_NASTI_MASTER_UNCACHED = 1;
static const int CFG_NASTI_MASTER_ETHMAC = 2;
static const int CFG_NASTI_MASTER_TOTAL = 3;
static const int CFG_NASTI_MASTER_MSTUART = 3;
static const int CFG_NASTI_MASTER_TOTAL = 4;
 
static const uint16_t MST_DID_EMPTY = 0x7755;
static const uint16_t SLV_DID_EMPTY = 0x5577;
30,6 → 32,7
static const uint16_t GAISLER_ETH_MAC_MASTER = 0x0502;
static const uint16_t GAISLER_ETH_EDCL_MASTER = 0x0503;
static const uint16_t RISCV_RIVER_CPU = 0x0505;
static const uint16_t GNSSSENSOR_UART_TAP = 0x050A;
 
// Slaves IDs
static const uint16_t GNSSSENSOR_ENGINE_STUB = 0x0068;
104,13 → 107,13
} bits;
uint32_t val;
} tech; /// 0xfffff008: RO: technology index
uint32_t rsrv1; /// 0xfffff00c:
uint64_t idt; /// 0xfffff010:
uint64_t malloc_addr; /// 0xfffff018: RW: debuggind memalloc pointer 0x18
uint64_t malloc_size; /// 0xfffff020: RW: debugging memalloc size 0x20
uint32_t rsrv1; /// 0xfffff00c:
uint64_t idt; /// 0xfffff010:
uint64_t malloc_addr; /// 0xfffff018: RW: memalloc pointer 0x18
uint64_t malloc_size; /// 0xfffff020: RW: memalloc size 0x20
uint64_t fwdbg1; /// 0xfffff028: RW: FW debug register
uint64_t rsrv[2]; /// 0xfffff030, 0xfffff038
uint8_t cfg_table[(1 << 12) - 0x40];/// 0xfffff040: RO: PNP configuration
uint8_t cfg_table[(1 << 12) - 0x40]; /// 0xfffff040: RO: PNP configuration
} PnpMapType;
 
struct GpioType {
131,14 → 134,14
union ureg_type {
uint8_t buf[1 << (12 + 3)];
struct regs_type {
uint64_t iregs[32]; // integer registers
uint64_t pc; // index = 32
uint64_t npc; // index = 33
uint64_t stack_trace_cnt; // index 34
uint64_t iregs[32]; // integer registers
uint64_t pc;
uint64_t npc;
uint64_t stack_trace_cnt; // index 34
uint64_t rsrv1[128 - 35];
uint64_t stack_trace_buf[1];
uint64_t rsrv2[128 - 1];
uint64_t instr_buf[4]; // index 256..259: Bits[63:0] (addr,instr)
uint64_t instr_buf[4]; // Bits[63:0] (addr,instr)
uint64_t dbg1[4];
} v;
} ureg;
146,23 → 149,7
union udbg_type {
uint8_t buf[1 << (12 + 3)];
struct debug_region_type {
union control_reg {
uint64_t val;
struct {
uint64_t halt : 1;
uint64_t stepping : 1;
uint64_t breakpoint : 1;
uint64_t rsv1 : 1;
uint64_t core_id : 16;
uint64_t rsv2 : 12;
uint64_t istate : 2; // [33:32] icache state
uint64_t rsv3 : 2; // [35:34]
uint64_t dstate : 2; // [37:36] dcache state
uint64_t rsv4 : 2; // [39:38]
uint64_t cstate : 2; // [41:40] cachetop state
uint64_t rsv5 : 22;
} bits;
} control;
GenericCpuControlType control;
uint64_t stepping_mode_steps;
uint64_t clock_cnt;
uint64_t executed_cnt;
211,25 → 198,20
 
const uint64_t REG_ADDR_ERROR = 0xFFFFFFFFFFFFFFFFull;
 
#define DSUREG(x) (reinterpret_cast<uint64_t>(& \
(reinterpret_cast<DsuMapType*>(0))->x))
 
class ISocInfo : public IFace {
public:
public:
ISocInfo() : IFace(IFACE_SOC_INFO) {}
 
virtual unsigned getMastersTotal() =0;
virtual unsigned getSlavesTotal() =0;
virtual unsigned getRegsTotal() =0;
virtual void getRegsList(AttributeType *lst) =0;
virtual unsigned getCsrTotal() =0;
virtual void getCsrList(AttributeType *lst) =0;
virtual uint64_t csr2addr(const char *name) =0;
virtual uint64_t reg2addr(const char *name) =0;
virtual unsigned getRegsTotal() = 0;
virtual void getRegsList(AttributeType *lst) = 0;
virtual uint64_t reg2addr(const char *name) = 0;
 
virtual DsuMapType *getpDsu() =0;
 
virtual uint64_t addressPlugAndPlay() =0;
virtual uint64_t addressGpio() =0;
virtual DsuMapType *getpDsu() = 0;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_ISOCINFO_H__
#endif // __DEBUGGER_COMMON_CORESERVICES_ISOCINFO_H__
/coreservices/isrccode.h
8,18 → 8,33
#ifndef __DEBUGGER_PLUGIN_ISRCCODE_H__
#define __DEBUGGER_PLUGIN_ISRCCODE_H__
 
#include "iface.h"
#include <inttypes.h>
#include "attribute.h"
#include <iface.h>
#include <attribute.h>
 
namespace debugger {
 
static const char *const IFACE_SOURCE_CODE = "ISourceCode";
 
enum ESymbolType {
SYMBOL_TYPE_FILE = 0x01,
SYMBOL_TYPE_FUNCTION = 0x02,
SYMBOL_TYPE_DATA = 0x04
};
 
enum ESymbolInfoListItem {
Symbol_Name,
Symbol_Addr,
Symbol_Size,
Symbol_Type,
Symbol_Total
};
 
 
enum EBreakList {
BrkList_address,
BrkList_flags,
BrkList_instr,
BrkList_hwflag,
BrkList_Total
};
 
43,9 → 58,26
static const uint64_t BreakFlag_HW = (1 << 0);
 
class ISourceCode : public IFace {
public:
public:
ISourceCode() : IFace(IFACE_SOURCE_CODE) {}
 
/** Control Debug Symbols */
virtual void addFileSymbol(const char *name, uint64_t addr, int sz) = 0;
 
virtual void addFunctionSymbol(const char *name, uint64_t addr,
int sz) = 0;
 
virtual void addDataSymbol(const char *name, uint64_t addr, int sz) = 0;
 
virtual void clearSymbols() = 0;
virtual void addSymbols(AttributeType *list) = 0;
 
virtual void getSymbols(AttributeType *list) = 0;
 
virtual void addressToSymbol(uint64_t addr, AttributeType *info) = 0;
 
virtual int symbol2Address(const char *name, uint64_t *addr) = 0;
 
/** Disasm input data buffer.
*
* @return disassembled instruction length
54,10 → 86,10
uint8_t *data,
int offset,
AttributeType *mnemonic,
AttributeType *comment) =0;
AttributeType *comment) = 0;
virtual void disasm(uint64_t pc,
AttributeType *idata,
AttributeType *asmlist) =0;
AttributeType *asmlist) = 0;
 
 
/** Register breakpoint at specified address.
67,25 → 99,29
* For HW breakpoint may have any value so that memory
* won't be modified.
* @param[in] hw Breakpoint flags
* @param[in] instr Original opcode before EBREAK instruction injection.
*/
virtual void registerBreakpoint(uint64_t addr, uint32_t instr,
uint64_t flags) =0;
virtual void registerBreakpoint(uint64_t addr, uint64_t flags,
uint64_t instr) = 0;
 
/** Unregister breakpoint at specified address.
*
* @param[in] addr Breakpoint location
* @param[out] instr Original instruction value.
* @param[out] flags Breakpoint flags.
* @param[out] instr Original opcode rewriten by EBREAK instruction.
* @return 0 if no errors
*/
virtual int unregisterBreakpoint(uint64_t addr, uint32_t *instr,
uint64_t *flags) =0;
virtual int unregisterBreakpoint(uint64_t addr, uint64_t *flags,
uint64_t *instr) = 0;
 
/** Get list of breakpoints.
*
* @param[out] lst Breakpoint list.
*/
virtual void getBreakpointList(AttributeType *list) =0;
virtual void getBreakpointList(AttributeType *list) = 0;
 
/** Check specified address on breakpoint */
virtual bool isBreakpoint(uint64_t addr, AttributeType *outbr) = 0;
};
 
} // namespace debugger
/coreservices/itap.h
1,42 → 1,42
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief General interface of the hardware access.
*/
 
#ifndef __DEBUGGER_ITAP_H__
#define __DEBUGGER_ITAP_H__
 
#include "iface.h"
#include "attribute.h"
#include <inttypes.h>
 
namespace debugger {
 
static const char *const IFACE_TAP = "ITap";
 
static const char *const ITap_brief =
"Test Access Point (TAP) software interface.";
 
static const char *const ITap_detail =
"This interface is used for the direct access to the Hardware. "
"Typically, it is doing via JTAG or other transport interface.";
 
static const int TAP_ERROR = -1;
 
class ITap : public IFace {
public:
ITap() : IFace(IFACE_TAP) {}
 
virtual const char *getBrief() { return ITap_brief; }
 
virtual const char *getDetail() { return ITap_detail; }
 
virtual int read(uint64_t addr, int bytes, uint8_t *obuf) =0;
virtual int write(uint64_t addr, int bytes, uint8_t *ibuf) =0;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_ITAP_H__
/**
* @file
* @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief General interface of the hardware access.
*/
 
#ifndef __DEBUGGER_COMMON_CORESERVICES_ITAP_H__
#define __DEBUGGER_COMMON_CORESERVICES_ITAP_H__
 
#include <inttypes.h>
#include <iface.h>
#include <attribute.h>
 
namespace debugger {
 
static const char *const IFACE_TAP = "ITap";
 
static const char *const ITap_brief =
"Test Access Point (TAP) software interface.";
 
static const char *const ITap_detail =
"This interface is used for the direct access to the Hardware. "
"Typically, it is doing via JTAG or other transport interface.";
 
static const int TAP_ERROR = -1;
 
class ITap : public IFace {
public:
ITap() : IFace(IFACE_TAP) {}
 
virtual const char *getBrief() { return ITap_brief; }
 
virtual const char *getDetail() { return ITap_detail; }
 
virtual int read(uint64_t addr, int bytes, uint8_t *obuf) = 0;
virtual int write(uint64_t addr, int bytes, uint8_t *ibuf) = 0;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_COMMON_CORESERVICES_ITAP_H__
/coreservices/ithread.h
1,66 → 1,69
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Thread interface declaration.
*/
 
#ifndef __DEBUGGER_ITHREAD_H__
#define __DEBUGGER_ITHREAD_H__
 
#include "iface.h"
#include "api_core.h"
 
namespace debugger {
 
static const char *const IFACE_THREAD = "IThread";
 
class IThread : public IFace {
public:
IThread() : IFace(IFACE_THREAD) {
AttributeType t1;
RISCV_generate_name(&t1);
RISCV_event_create(&loopEnable_, t1.to_string());
threadInit_.Handle = 0;
}
 
/** create and start seperate thread */
virtual bool run() {
threadInit_.func = reinterpret_cast<lib_thread_func>(runThread);
threadInit_.args = this;
RISCV_thread_create(&threadInit_);
 
if (threadInit_.Handle) {
RISCV_event_set(&loopEnable_);
}
return loopEnable_.state;
}
 
/** @brief Stop and join thread */
virtual void stop() {
RISCV_event_clear(&loopEnable_);
if (threadInit_.Handle) {
RISCV_thread_join(threadInit_.Handle, 50000);
}
threadInit_.Handle = 0;
}
 
/** check thread status */
virtual bool isEnabled() { return loopEnable_.state; }
 
protected:
/** working cycle function */
virtual void busyLoop() =0;
 
static void runThread(void *arg) {
reinterpret_cast<IThread *>(arg)->busyLoop();
}
 
protected:
event_def loopEnable_;
LibThreadType threadInit_;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_ITHREAD_H__
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Thread interface declaration.
*/
 
#ifndef __DEBUGGER_ITHREAD_H__
#define __DEBUGGER_ITHREAD_H__
 
#include <iface.h>
#include <api_core.h>
 
namespace debugger {
 
static const char *const IFACE_THREAD = "IThread";
 
class IThread : public IFace {
public:
IThread() : IFace(IFACE_THREAD) {
AttributeType t1;
RISCV_generate_name(&t1);
RISCV_event_create(&loopEnable_, t1.to_string());
threadInit_.Handle = 0;
}
 
/** create and start seperate thread */
virtual bool run() {
threadInit_.func = reinterpret_cast<lib_thread_func>(runThread);
threadInit_.args = this;
RISCV_thread_create(&threadInit_);
 
if (threadInit_.Handle) {
RISCV_event_set(&loopEnable_);
}
return loopEnable_.state;
}
 
/** @brief Stop and join thread */
virtual void stop() {
RISCV_event_clear(&loopEnable_);
if (threadInit_.Handle) {
RISCV_thread_join(threadInit_.Handle, 50000);
}
threadInit_.Handle = 0;
}
 
/** check thread status */
virtual bool isEnabled() { return loopEnable_.state; }
 
/** Pass data from the parent thread */
virtual void setExtArgument(void *args) {}
 
protected:
/** working cycle function */
virtual void busyLoop() =0;
 
static void runThread(void *arg) {
reinterpret_cast<IThread *>(arg)->busyLoop();
}
 
protected:
event_def loopEnable_;
LibThreadType threadInit_;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_ITHREAD_H__
/coreservices/iwire.h
1,29 → 1,60
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Single wire interface.
*/
 
#ifndef __DEBUGGER_PLUGIN_IWIRE_H__
#define __DEBUGGER_PLUGIN_IWIRE_H__
 
#include "iface.h"
#include <inttypes.h>
 
namespace debugger {
 
static const char *const IFACE_WIRE = "IWire";
 
class IWire : public IFace {
public:
IWire() : IFace(IFACE_WIRE) {}
 
virtual void raiseLine(int idx) =0;
virtual void lowerLine() =0;
virtual void setLevel(bool level) =0;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_PLUGIN_IWIRE_H__
/**
* @file
* @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Single wire interface.
*/
 
#ifndef __DEBUGGER_COMMON_CORESERVICES_IWIRE_H__
#define __DEBUGGER_COMMON_CORESERVICES_IWIRE_H__
 
#include <inttypes.h>
#include <iface.h>
#include <attribute.h>
#include <iservice.h>
 
namespace debugger {
 
static const char *const IFACE_WIRE = "IWire";
 
class IWire : public IFace {
public:
IWire() : IFace(IFACE_WIRE) {}
 
virtual void raiseLine() = 0;
virtual void lowerLine() = 0;
virtual void setLevel(bool level) = 0;
virtual bool getLevel() = 0;
};
 
class GenericWireAttribute : public AttributeType,
public IWire {
public:
GenericWireAttribute(IService *parent, const char *name)
: parent_(parent) {
parent->registerAttribute(name, static_cast<IAttribute *>(this));
parent->registerPortInterface(name, static_cast<IWire *>(this));
wireName_.make_string(name);
make_boolean(false);
}
 
/** IWire */
virtual void raiseLine() { make_boolean(true); }
virtual void lowerLine() { make_boolean(false); }
virtual void setLevel(bool level) { make_boolean(level); }
virtual bool getLevel() { return to_bool(); }
 
protected:
// Debug output compatibility
IFace *getInterface(const char *name) {
return parent_->getInterface(name);
}
 
protected:
IService *parent_;
AttributeType wireName_;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_COMMON_CORESERVICES_IWIRE_H__
/iattr.h
1,36 → 1,48
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Core Attribute interface declaration.
*/
 
#ifndef __DEBUGGER_IATTRIBUTE_H__
#define __DEBUGGER_IATTRIBUTE_H__
 
#include "iface.h"
 
namespace debugger {
 
static const char *const IFACE_ATTRIBUTE = "IAttribute";
 
class IAttribute : public IFace {
public:
IAttribute() : IFace(IFACE_ATTRIBUTE), attr_name_ (NULL) {}
 
virtual void setAttrName(const char *name) { attr_name_ = name; }
 
virtual const char *getAttrName() { return attr_name_; }
 
virtual void setAttrDescription(const char *descr) { attr_descr_ = descr; }
 
virtual const char *getAttrDescription() { return attr_descr_; }
 
protected:
const char *attr_name_;
const char *attr_descr_;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_IATTRIBUTE_H__
/*
* Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
#ifndef __DEBUGGER_IATTRIBUTE_H__
#define __DEBUGGER_IATTRIBUTE_H__
 
#include <iface.h>
 
namespace debugger {
 
static const char *const IFACE_ATTRIBUTE = "IAttribute";
 
class IAttribute : public IFace {
public:
IAttribute() :
IFace(IFACE_ATTRIBUTE), attr_name_(NULL), attr_descr_(NULL) {}
 
virtual void allocAttrName(const char *name) = 0;
virtual void freeAttrName() = 0;
virtual const char *getAttrName() { return attr_name_; }
 
virtual void allocAttrDescription(const char *descr) = 0;
virtual void freeAttrDescription() = 0;
virtual const char *getAttrDescription() { return attr_descr_; }
 
virtual void postinitAttribute() {}
 
protected:
char *attr_name_;
char *attr_descr_;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_IATTRIBUTE_H__
/iclass.h
1,109 → 1,119
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Base Class interface declaration.
*/
 
#ifndef __DEBUGGER_CLASS_H__
#define __DEBUGGER_CLASS_H__
 
#include "iface.h"
#include "iservice.h"
#include "api_core.h"
 
namespace debugger {
 
static const char *const IFACE_CLASS = "IClass";
 
class IClass : public IFace {
public:
IClass(const char *class_name)
: IFace(IFACE_CLASS), class_name_(class_name) {
RISCV_register_class(static_cast<IClass *>(this));
listInstances_ = AttributeType(Attr_List);
}
virtual ~IClass() {
for (unsigned i = 0; i < listInstances_.size(); i++) {
delete static_cast<IService *>(listInstances_[i].to_iface());
}
}
 
virtual IService *createService(const char *obj_name) =0;
 
virtual void postinitServices() {
IService *tmp = NULL;
for (unsigned i = 0; i < listInstances_.size(); i++) {
tmp = static_cast<IService *>(listInstances_[i].to_iface());
tmp->postinitService();
}
}
 
virtual void predeleteServices() {
IService *tmp = NULL;
for (unsigned i = 0; i < listInstances_.size(); i++) {
tmp = static_cast<IService *>(listInstances_[i].to_iface());
tmp->predeleteService();
}
}
 
virtual const char *getClassName() { return class_name_; }
 
virtual IService *getInstance(const char *name) {
IService *ret = NULL;
for (unsigned i = 0; i < listInstances_.size(); i++) {
ret = static_cast<IService *>(listInstances_[i].to_iface());
if (strcmp(name, ret->getObjName()) == 0) {
return ret;
}
}
return NULL;
}
 
virtual AttributeType getConfiguration() {
AttributeType ret(Attr_Dict);
ret["Class"] = AttributeType(getClassName());
ret["Instances"] = AttributeType(Attr_List);
 
IService *tmp = NULL;
for (unsigned i = 0; i < listInstances_.size(); i++) {
tmp = static_cast<IService *>(listInstances_[i].to_iface());
AttributeType val = tmp->getConfiguration();
ret["Instances"].add_to_list(&val);
}
return ret;
}
 
virtual const AttributeType *getInstanceList() { return &listInstances_; }
 
protected:
const char *class_name_;
AttributeType listInstances_;
};
 
/**
* @brief Unified macros of plugin class declaration.
* @see simple_plugin.cpp example
*/
#define DECLARE_CLASS(name) \
class name ## Class : public IClass { \
public: \
name ## Class () : IClass(# name "Class") {} \
virtual IService *createService(const char *obj_name) { \
name *serv = new name(obj_name); \
AttributeType item(static_cast<IService *>(serv)); \
listInstances_.add_to_list(&item); \
return serv; \
} \
};
 
/**
* @brief Unified macros of plugin class registration in kernel library.
* @see simple_plugin.cpp example
*/
#define REGISTER_CLASS(name) static name ## Class local_class;
#define REGISTER_CLASS_IDX(name, idx) static name ## Class local_class_ ## idx;
 
} // namespace debugger
 
#endif // __DEBUGGER_CLASS_H__
/*
* Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
#ifndef __DEBUGGER_CLASS_H__
#define __DEBUGGER_CLASS_H__
 
#include <iface.h>
#include <iservice.h>
#include <api_core.h>
 
namespace debugger {
 
static const char *const IFACE_CLASS = "IClass";
 
class IClass : public IFace {
public:
explicit IClass(const char *class_name)
: IFace(IFACE_CLASS) {
class_name_.make_string(class_name);
RISCV_register_class(static_cast<IClass *>(this));
listInstances_ = AttributeType(Attr_List);
}
virtual ~IClass() {
for (unsigned i = 0; i < listInstances_.size(); i++) {
delete static_cast<IService *>(listInstances_[i].to_iface());
}
}
 
virtual IService *createService(const char *obj_name) = 0;
 
virtual void postinitServices() {
IService *tmp = NULL;
for (unsigned i = 0; i < listInstances_.size(); i++) {
tmp = static_cast<IService *>(listInstances_[i].to_iface());
tmp->postinitService();
}
}
 
virtual void predeleteServices() {
IService *tmp = NULL;
for (unsigned i = 0; i < listInstances_.size(); i++) {
tmp = static_cast<IService *>(listInstances_[i].to_iface());
tmp->predeleteService();
}
}
 
virtual const char *getClassName() { return class_name_.to_string(); }
 
virtual IService *getInstance(const char *name) {
IService *ret = NULL;
for (unsigned i = 0; i < listInstances_.size(); i++) {
ret = static_cast<IService *>(listInstances_[i].to_iface());
if (strcmp(name, ret->getObjName()) == 0) {
return ret;
}
}
return NULL;
}
 
virtual AttributeType getConfiguration() {
AttributeType ret(Attr_Dict);
ret["Class"] = AttributeType(getClassName());
ret["Instances"] = AttributeType(Attr_List);
 
IService *tmp = NULL;
for (unsigned i = 0; i < listInstances_.size(); i++) {
tmp = static_cast<IService *>(listInstances_[i].to_iface());
AttributeType val = tmp->getConfiguration();
ret["Instances"].add_to_list(&val);
}
return ret;
}
 
virtual const AttributeType *getInstanceList() { return &listInstances_; }
 
protected:
AttributeType class_name_;
AttributeType listInstances_;
};
 
/**
* @brief Unified macros of plugin class declaration.
* @see simple_plugin.cpp example
*/
#define DECLARE_CLASS(name) \
class name ## Class : public IClass { \
public: \
name ## Class() : IClass(# name "Class") {} \
virtual IService *createService(const char *obj_name) { \
name *serv = new name(obj_name); \
AttributeType item(static_cast<IService *>(serv)); \
listInstances_.add_to_list(&item); \
return serv; \
} \
};
 
/**
* @brief Unified macros of plugin class registration in kernel library.
* @see simple_plugin.cpp example
*/
#define REGISTER_CLASS(name) static name ## Class local_class;
#define REGISTER_CLASS_IDX(name, idx) static name ## Class local_class_ ## idx;
 
} // namespace debugger
 
#endif // __DEBUGGER_CLASS_H__
/iface.h
1,33 → 1,42
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Base interface declaration of the Core.
*/
 
#ifndef __DEBUGGER_IFACE_H__
#define __DEBUGGER_IFACE_H__
 
namespace debugger {
 
class IFace {
public:
IFace(const char *name) : ifname_(name) {}
virtual ~IFace() {}
 
/** Get brief information. */
virtual const char *getBrief() { return "Brief info not defined"; }
 
/** Get detailed description. */
virtual const char *getDetail() { return "Detail info not defined"; }
 
/** Get interface name. */
const char *getFaceName() { return ifname_; }
 
protected:
const char *ifname_;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_IFACE_H__
/*
* Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
#ifndef __DEBUGGER_IFACE_H__
#define __DEBUGGER_IFACE_H__
 
namespace debugger {
 
class IFace {
public:
explicit IFace(const char *name) : ifname_(name) {}
virtual ~IFace() {}
 
/** Get brief information. */
virtual const char *getBrief() { return "Brief info not defined"; }
 
/** Get detailed description. */
virtual const char *getDetail() { return "Detail info not defined"; }
 
/** Get interface name. */
const char *getFaceName() { return ifname_; }
 
protected:
const char *ifname_;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_IFACE_H__
/ihap.h
1,39 → 1,51
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Hap interface declaration.
*/
 
#ifndef __DEBUGGER_IHAP_H__
#define __DEBUGGER_IHAP_H__
 
#include "iface.h"
#include <stdarg.h>
 
namespace debugger {
 
static const char *const IFACE_HAP = "IHap";
 
enum EHapType {
HAP_All,
HAP_ConfigDone,
HAP_BreakSimulation
};
 
class IHap : public IFace {
public:
IHap(EHapType type = HAP_All) : IFace(IFACE_HAP), type_(type) {}
 
EHapType getType() { return type_; }
 
virtual void hapTriggered(IFace *isrc, EHapType type,
const char *descr) =0;
 
protected:
EHapType type_;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_IHAP_H__
/*
* Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
#ifndef __DEBUGGER_IHAP_H__
#define __DEBUGGER_IHAP_H__
 
#include <iface.h>
#include <stdarg.h>
 
namespace debugger {
 
static const char *const IFACE_HAP = "IHap";
 
enum EHapType {
HAP_All,
HAP_ConfigDone,
HAP_Halt,
HAP_BreakSimulation,
HAP_CpuTurnON,
HAP_CpuTurnOFF
};
 
class IHap : public IFace {
public:
explicit IHap(EHapType type = HAP_All) : IFace(IFACE_HAP), type_(type) {}
 
EHapType getType() { return type_; }
 
virtual void hapTriggered(IFace *isrc, EHapType type,
const char *descr) = 0;
 
protected:
EHapType type_;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_IHAP_H__
/iservice.h
1,129 → 1,178
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Core Service interface declaration.
*/
 
#ifndef __DEBUGGER_SERVICE_H__
#define __DEBUGGER_SERVICE_H__
 
#include "iface.h"
#include "attribute.h"
#include "api_utils.h"
 
namespace debugger {
 
static const char *const IFACE_SERVICE = "IService";
 
class IService : public IFace {
public:
IService(const char *obj_name)
: IFace(IFACE_SERVICE) {
listInterfaces_ = AttributeType(Attr_List);
listAttributes_ = AttributeType(Attr_List);
registerInterface(static_cast<IService *>(this));
registerAttribute("LogLevel", &logLevel_);
obj_name_ = obj_name;
logLevel_.make_int64(LOG_ERROR);
}
virtual ~IService() {}
 
virtual void initService(const AttributeType *args) {
if (!args || !args->is_list()) {
return;
}
AttributeType *cur_attr;
for (unsigned i = 0; i < args->size(); i++) {
const AttributeType &item = (*args)[i];
if (item.size() < 2 || !item[0u].is_string()) {
continue;
}
cur_attr = static_cast<AttributeType *>(
getAttribute(item[0u].to_string()));
if (cur_attr == NULL) {
RISCV_error("Attribute '%s' not found", item[0u].to_string());
continue;
}
(*cur_attr) = item[1];
if (item.size() >= 3 && item[2].is_string()) {
static_cast<IAttribute *>(cur_attr)->setAttrDescription(
item[2].to_string());
}
}
}
 
virtual void postinitService() {}
virtual void predeleteService() {}
 
virtual void registerInterface(IFace *iface) {
AttributeType item(iface);
listInterfaces_.add_to_list(&item);
}
 
virtual void unregisterInterface(IFace *iface) {
for (unsigned i = 0; i < listInterfaces_.size(); i++) {
if (listInterfaces_[i].to_iface() == iface) {
listInterfaces_.remove_from_list(i);
break;
}
}
}
 
virtual IFace *getInterface(const char *name) {
IFace *tmp;
for (unsigned i = 0; i < listInterfaces_.size(); i++) {
tmp = listInterfaces_[i].to_iface();
if (strcmp(name, tmp->getFaceName()) == 0) {
return tmp;
}
}
return NULL;
}
 
virtual void registerAttribute(const char *name, IAttribute *iface) {
AttributeType item(iface);
iface->setAttrName(name);
listAttributes_.add_to_list(&item);
}
 
virtual IAttribute *getAttribute(const char *name) {
IAttribute *tmp;
for (unsigned i = 0; i < listAttributes_.size(); i++) {
tmp = static_cast<IAttribute *>(listAttributes_[i].to_iface());
if (strcmp(name, tmp->getAttrName()) == 0) {
return tmp;
}
}
return NULL;
}
 
virtual const char *getObjName() { return obj_name_; }
 
virtual AttributeType getConfiguration() {
AttributeType ret(Attr_Dict);
ret["Name"] = AttributeType(getObjName());
ret["Attr"] = AttributeType(Attr_List);
 
IAttribute *tmp = NULL;
for (unsigned i = 0; i < listAttributes_.size(); i++) {
tmp = static_cast<IAttribute *>(listAttributes_[i].to_iface());
AttributeType item;
item.make_list(2);
item[0u].make_string(tmp->getAttrName());
item[1] = *static_cast<AttributeType *>(tmp);
ret["Attr"].add_to_list(&item);
}
return ret;
}
 
protected:
AttributeType listInterfaces_;
AttributeType listAttributes_;
AttributeType logLevel_;
const char *obj_name_;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_SERVICE_H__
/*
* Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
#ifndef __DEBUGGER_COMMON_ISERVICE_H__
#define __DEBUGGER_COMMON_ISERVICE_H__
 
#include <iface.h>
#include <attribute.h>
#include <api_utils.h>
#include "coreservices/imemop.h"
 
namespace debugger {
 
static const char *const IFACE_SERVICE = "IService";
 
class IService : public IFace {
public:
explicit IService(const char *obj_name) : IFace(IFACE_SERVICE) {
listInterfaces_ = AttributeType(Attr_List);
listAttributes_ = AttributeType(Attr_List);
listPorts_ = AttributeType(Attr_List);
registerInterface(static_cast<IService *>(this));
registerAttribute("LogLevel", &logLevel_);
obj_name_.make_string(obj_name);
logLevel_.make_int64(LOG_ERROR);
}
virtual ~IService() {
// @warning: NEED to unregister attribute from class destructor
/*for (unsigned i = 0; i < listAttributes_.size(); i++) {
IAttribute *iattr = static_cast<IAttribute *>(
listAttributes_[i].to_iface());
iattr->freeAttrName();
iattr->freeAttrDescription();
}*/
}
 
virtual void initService(const AttributeType *args) {
if (!args || !args->is_list()) {
return;
}
AttributeType *cur_attr;
for (unsigned i = 0; i < args->size(); i++) {
const AttributeType &item = (*args)[i];
if (item.size() < 2 || !item[0u].is_string()) {
continue;
}
cur_attr = static_cast<AttributeType *>(
getAttribute(item[0u].to_string()));
if (cur_attr == NULL) {
RISCV_error("Attribute '%s' not found", item[0u].to_string());
continue;
}
(*cur_attr) = item[1];
if (item.size() >= 3 && item[2].is_string()) {
static_cast<IAttribute *>(cur_attr)->allocAttrDescription(
item[2].to_string());
}
}
}
 
virtual void postinitService() {}
virtual void predeleteService() {}
 
virtual void registerInterface(IFace *iface) {
AttributeType item(iface);
listInterfaces_.add_to_list(&item);
if (strcmp(iface->getFaceName(), IFACE_MEMORY_OPERATION) == 0) {
IMemoryOperation *imemop = static_cast<IMemoryOperation *>(iface);
registerAttribute("MapList", &imemop->listMap_);
registerAttribute("BaseAddress", &imemop->baseAddress_);
registerAttribute("Length", &imemop->length_);
registerAttribute("Priority", &imemop->priority_);
}
}
virtual void registerPortInterface(const char *portname, IFace *iface) {
AttributeType item;
item.make_list(2);
item[0u].make_string(portname);
item[1].make_iface(iface);
listPorts_.add_to_list(&item);
}
 
virtual void unregisterInterface(IFace *iface) {
for (unsigned i = 0; i < listInterfaces_.size(); i++) {
if (listInterfaces_[i].to_iface() == iface) {
listInterfaces_.remove_from_list(i);
break;
}
}
}
 
virtual IFace *getInterface(const char *name) {
IFace *tmp;
for (unsigned i = 0; i < listInterfaces_.size(); i++) {
tmp = listInterfaces_[i].to_iface();
if (strcmp(name, tmp->getFaceName()) == 0) {
return tmp;
}
}
return NULL;
}
 
virtual IFace *getPortInterface(const char *portname,
const char *facename) {
IFace *tmp;
for (unsigned i = 0; i < listPorts_.size(); i++) {
AttributeType &item = listPorts_[i];
if (!item[0u].is_equal(portname)) {
continue;
}
tmp = item[1].to_iface();
if (strcmp(facename, tmp->getFaceName()) == 0) {
return tmp;
}
}
return NULL;
}
 
virtual void registerAttribute(const char *name, IAttribute *iface) {
AttributeType item(iface);
iface->allocAttrName(name);
listAttributes_.add_to_list(&item);
}
 
virtual IAttribute *getAttribute(const char *name) {
IAttribute *tmp;
for (unsigned i = 0; i < listAttributes_.size(); i++) {
tmp = static_cast<IAttribute *>(listAttributes_[i].to_iface());
if (strcmp(name, tmp->getAttrName()) == 0) {
return tmp;
}
}
return NULL;
}
 
virtual const char *getObjName() { return obj_name_.to_string(); }
 
virtual AttributeType getConfiguration() {
AttributeType ret(Attr_Dict);
ret["Name"] = AttributeType(getObjName());
ret["Attr"] = AttributeType(Attr_List);
 
IAttribute *tmp = NULL;
for (unsigned i = 0; i < listAttributes_.size(); i++) {
tmp = static_cast<IAttribute *>(listAttributes_[i].to_iface());
AttributeType item;
item.make_list(2);
item[0u].make_string(tmp->getAttrName());
item[1] = *static_cast<AttributeType *>(tmp);
ret["Attr"].add_to_list(&item);
}
return ret;
}
 
protected:
AttributeType listInterfaces_;
AttributeType listPorts_; // [['portname',iface],*]
AttributeType listAttributes_;
AttributeType logLevel_;
AttributeType obj_name_;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_COMMON_ISERVICE_H__
/riscv-isa.h
1,9 → 1,19
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief RISC-V ISA specified structures and constants.
/*
* Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
#ifndef __DEBUGGER_RISCV_ISA_H__
#define __DEBUGGER_RISCV_ISA_H__
 
13,12 → 23,12
 
union ISA_R_type {
struct bits_type {
uint32_t opcode : 7; // [6:0]
uint32_t rd : 5; // [11:7]
uint32_t funct3 : 3; // [14:12]
uint32_t rs1 : 5; // [19:15]
uint32_t rs2 : 5; // [24:20]
uint32_t funct7 : 7; // [31:25]
uint32_t opcode : 7; // [6:0]
uint32_t rd : 5; // [11:7]
uint32_t funct3 : 3; // [14:12]
uint32_t rs1 : 5; // [19:15]
uint32_t rs2 : 5; // [24:20]
uint32_t funct7 : 7; // [31:25]
} bits;
uint32_t value;
};
25,11 → 35,11
 
union ISA_I_type {
struct bits_type {
uint32_t opcode : 7; // [6:0]
uint32_t rd : 5; // [11:7]
uint32_t funct3 : 3; // [14:12]
uint32_t rs1 : 5; // [19:15]
uint32_t imm : 12; // [31:20]
uint32_t opcode : 7; // [6:0]
uint32_t rd : 5; // [11:7]
uint32_t funct3 : 3; // [14:12]
uint32_t rs1 : 5; // [19:15]
uint32_t imm : 12; // [31:20]
} bits;
uint32_t value;
};
36,12 → 46,12
 
union ISA_S_type {
struct bits_type {
uint32_t opcode : 7; // [6:0]
uint32_t imm4_0 : 5; // [11:7]
uint32_t funct3 : 3; // [14:12]
uint32_t rs1 : 5; // [19:15]
uint32_t rs2 : 5; // [24:20]
uint32_t imm11_5 : 7; // [31:25]
uint32_t opcode : 7; // [6:0]
uint32_t imm4_0 : 5; // [11:7]
uint32_t funct3 : 3; // [14:12]
uint32_t rs1 : 5; // [19:15]
uint32_t rs2 : 5; // [24:20]
uint32_t imm11_5 : 7; // [31:25]
} bits;
uint32_t value;
};
48,14 → 58,14
 
union ISA_SB_type {
struct bits_type {
uint32_t opcode : 7; // [6:0]
uint32_t imm11 : 1; // [7]
uint32_t imm4_1 : 4; // [11:8]
uint32_t funct3 : 3; // [14:12]
uint32_t rs1 : 5; // [19:15]
uint32_t rs2 : 5; // [24:20]
uint32_t imm10_5 : 6; // [30:25]
uint32_t imm12 : 1; // [31]
uint32_t opcode : 7; // [6:0]
uint32_t imm11 : 1; // [7]
uint32_t imm4_1 : 4; // [11:8]
uint32_t funct3 : 3; // [14:12]
uint32_t rs1 : 5; // [19:15]
uint32_t rs2 : 5; // [24:20]
uint32_t imm10_5 : 6; // [30:25]
uint32_t imm12 : 1; // [31]
} bits;
uint32_t value;
};
62,9 → 72,9
 
union ISA_U_type {
struct bits_type {
uint32_t opcode : 7; // [6:0]
uint32_t rd : 5; // [11:7]
uint32_t imm31_12 : 20; // [31:12]
uint32_t opcode : 7; // [6:0]
uint32_t rd : 5; // [11:7]
uint32_t imm31_12 : 20; // [31:12]
} bits;
uint32_t value;
};
71,17 → 81,176
 
union ISA_UJ_type {
struct bits_type {
uint32_t opcode : 7; // [6:0]
uint32_t rd : 5; // [11:7]
uint32_t imm19_12 : 8; // [19:12]
uint32_t imm11 : 1; // [20]
uint32_t imm10_1 : 10; // [30:21]
uint32_t imm20 : 1; // [31]
uint32_t opcode : 7; // [6:0]
uint32_t rd : 5; // [11:7]
uint32_t imm19_12 : 8; // [19:12]
uint32_t imm11 : 1; // [20]
uint32_t imm10_1 : 10; // [30:21]
uint32_t imm20 : 1; // [31]
} bits;
uint32_t value;
};
 
static const uint64_t EXT_SIGN_8 = 0xFFFFFFFFFFFFFF00LL;
/**
* Compressed extension types:
*/
 
// Regsiter
union ISA_CR_type {
struct bits_type {
uint16_t opcode : 2; // [1:0]
uint16_t rs2 : 5; // [6:2]
uint16_t rdrs1 : 5; // [11:7]
uint16_t funct4 : 4; // [15:12]
} bits;
uint16_t value;
};
 
// Immediate
union ISA_CI_type {
struct bits_type {
uint16_t opcode : 2; // [1:0]
uint16_t imm : 5; // [6:2]
uint16_t rdrs : 5; // [11:7]
uint16_t imm6 : 1; // [12]
uint16_t funct3 : 3; // [15:13]
} bits;
struct sp_bits_type {
uint16_t opcode : 2; // [1:0]
uint16_t imm5 : 1; // [2]
uint16_t imm8_7 : 2; // [4:3]
uint16_t imm6 : 1; // [5]
uint16_t imm4 : 1; // [6]
uint16_t sp : 5; // [11:7]
uint16_t imm9 : 1; // [12]
uint16_t funct3 : 3; // [15:13]
} spbits;
struct ldsp_bits_type {
uint16_t opcode : 2; // [1:0]
uint16_t off8_6 : 3; // [4:2]
uint16_t off4_3 : 2; // [6:5]
uint16_t rd : 5; // [11:7]
uint16_t off5 : 1; // [12]
uint16_t funct3 : 3; // [15:13]
} ldspbits;
struct lwsp_bits_type {
uint16_t opcode : 2; // [1:0]
uint16_t off7_6 : 2; // [3:2]
uint16_t off4_2 : 3; // [6:4]
uint16_t rd : 5; // [11:7]
uint16_t off5 : 1; // [12]
uint16_t funct3 : 3; // [15:13]
} lwspbits;
uint16_t value;
};
 
// Stack relative Store
union ISA_CSS_type {
struct w_bits_type {
uint16_t opcode : 2; // [1:0]
uint16_t rs2 : 5; // [6:2]
uint16_t imm7_6 : 2; // [8:7]
uint16_t imm5_2 : 4; // [12:9]
uint16_t funct3 : 3; // [15:13]
} wbits;
struct d_bits_type {
uint16_t opcode : 2; // [1:0]
uint16_t rs2 : 5; // [6:2]
uint16_t imm8_6 : 3; // [9:7]
uint16_t imm5_3 : 3; // [12:10]
uint16_t funct3 : 3; // [15:13]
} dbits;
uint16_t value;
};
 
// Wide immediate
union ISA_CIW_type {
struct bits_type {
uint16_t opcode : 2; // [1:0]
uint16_t rd : 3; // [4:2]
uint16_t imm3 : 1; // [5]
uint16_t imm2 : 1; // [6]
uint16_t imm9_6 : 4; // [10:7]
uint16_t imm5_4 : 2; // [12:11]
uint16_t funct3 : 3; // [15:13]
} bits;
uint16_t value;
};
 
// Load
union ISA_CL_type {
struct bits_type {
uint16_t opcode : 2; // [1:0]
uint16_t rd : 3; // [4:2]
uint16_t imm6 : 1; // [5]
uint16_t imm27 : 1; // [6]
uint16_t rs1 : 3; // [9:7]
uint16_t imm5_3 : 3; // [12:10]
uint16_t funct3 : 3; // [15:13]
} bits;
uint16_t value;
};
 
// Store
union ISA_CS_type {
struct bits_type {
uint16_t opcode : 2; // [1:0]
uint16_t rs2 : 3; // [4:2]
uint16_t imm6 : 1; // [5]
uint16_t imm27 : 1; // [6]
uint16_t rs1 : 3; // [9:7]
uint16_t imm5_3 : 3; // [12:10]
uint16_t funct3 : 3; // [15:13]
} bits;
uint16_t value;
};
 
// Branch
union ISA_CB_type {
struct bits_type {
uint16_t opcode : 2; // [1:0]
uint16_t off5 : 1; // [2]
uint16_t off2_1 : 2; // [4:3]
uint16_t off7_6 : 2; // [6:5]
uint16_t rs1 : 3; // [9:7]
uint16_t off4_3 : 2; // [11:10]
uint16_t off8 : 1; // [12]
uint16_t funct3 : 3; // [15:13]
} bits;
struct sh_bits_type {
uint16_t opcode : 2; // [1:0]
uint16_t shamt : 5; // [6:2]
uint16_t rd : 3; // [9:7]
uint16_t funct2 : 2; // [11:10]
uint16_t shamt5 : 1; // [12]
uint16_t funct3 : 3; // [15:13]
} shbits;
uint16_t value;
};
 
// Jump
union ISA_CJ_type {
struct bits_type {
uint16_t opcode : 2; // [1:0]
uint16_t off5 : 1; // [2]
uint16_t off3_1 : 3; // [5:3]
uint16_t off7 : 1; // [6]
uint16_t off6 : 1; // [7]
uint16_t off10 : 1; // [8]
uint16_t off9_8 : 2; // [10:9]
uint16_t off4 : 1; // [11]
uint16_t off11 : 1; // [12]
uint16_t funct3 : 3; // [15:13]
} bits;
uint16_t value;
};
 
 
static const uint64_t EXT_SIGN_5 = 0xFFFFFFFFFFFFFFF0LL;
static const uint64_t EXT_SIGN_6 = 0xFFFFFFFFFFFFFFE0LL;
static const uint64_t EXT_SIGN_8 = 0xFFFFFFFFFFFFFF80LL;
static const uint64_t EXT_SIGN_9 = 0xFFFFFFFFFFFFFF00LL;
static const uint64_t EXT_SIGN_11 = 0xFFFFFFFFFFFFF800LL;
static const uint64_t EXT_SIGN_12 = 0xFFFFFFFFFFFFF000LL;
static const uint64_t EXT_SIGN_16 = 0xFFFFFFFFFFFF0000LL;
static const uint64_t EXT_SIGN_32 = 0xFFFFFFFF00000000LL;
115,10 → 284,10
"s9", // [25] Saved register 9
"s10", // [26] Saved register 10
"s11", // [27] Saved register 11
"t3", // [28]
"t4", // [29]
"t5", // [30]
"t6" // [31]
"t3", // [28]
"t4", // [29]
"t5", // [30]
"t6" // [31]
};
 
const char *const FREGS_NAME[] = {
128,56 → 297,65
"fs8", "fs9", "fs10", "fs11", "ft8", "ft9", "ft10", "ft11"
};
 
enum ERegNames {
Reg_Zero,
Reg_ra,// = 1; // [1] Return address
Reg_sp,// = 2; // [2] Stack pointer
Reg_gp,// = 3; // [3] Global pointer
Reg_tp,// = 4; // [4] Thread pointer
Reg_t0,// = 5; // [5] Temporaries 0 s3
Reg_t1,// = 6; // [6] Temporaries 1 s4
Reg_t2,// = 7; // [7] Temporaries 2 s5
Reg_s0,// = 8; // [8] s0/fp Saved register/frame pointer
Reg_s1,// = 9; // [9] Saved register 1
Reg_a0,// = 10; // [10] Function argumentes 0
Reg_a1,// = 11; // [11] Function argumentes 1
Reg_a2,// = 12; // [12] Function argumentes 2
Reg_a3,// = 13; // [13] Function argumentes 3
Reg_a4,// = 14; // [14] Function argumentes 4
Reg_a5,// = 15; // [15] Function argumentes 5
Reg_a6,// = 16; // [16] Function argumentes 6
Reg_a7,// = 17; // [17] Function argumentes 7
Reg_s2,// = 18; // [18] Saved register 2
Reg_s3,// = 19; // [19] Saved register 3
Reg_s4,// = 20; // [20] Saved register 4
Reg_s5,// = 21; // [21] Saved register 5
Reg_s6,// = 22; // [22] Saved register 6
Reg_s7,// = 23; // [23] Saved register 7
Reg_s8,// = 24; // [24] Saved register 8
Reg_s9,// = 25; // [25] Saved register 9
Reg_s10,// = 26; // [26] Saved register 10
Reg_s11,// = 27; // [27] Saved register 11
Reg_t3,// = 28; // [28]
Reg_t4,// = 29; // [29]
Reg_t5,// = 30; // [30]
Reg_t6,// = 31; // [31]
Reg_Total
};
enum ERegNames {
Reg_Zero,
Reg_ra, // [1] Return address
Reg_sp, // [2] Stack pointer
Reg_gp, // [3] Global pointer
Reg_tp, // [4] Thread pointer
Reg_t0, // [5] Temporaries 0 s3
Reg_t1, // [6] Temporaries 1 s4
Reg_t2, // [7] Temporaries 2 s5
Reg_s0, // [8] s0/fp Saved register/frame pointer
Reg_s1, // [9] Saved register 1
Reg_a0, // [10] Function argumentes 0
Reg_a1, // [11] Function argumentes 1
Reg_a2, // [12] Function argumentes 2
Reg_a3, // [13] Function argumentes 3
Reg_a4, // [14] Function argumentes 4
Reg_a5, // [15] Function argumentes 5
Reg_a6, // [16] Function argumentes 6
Reg_a7, // [17] Function argumentes 7
Reg_s2, // [18] Saved register 2
Reg_s3, // [19] Saved register 3
Reg_s4, // [20] Saved register 4
Reg_s5, // [21] Saved register 5
Reg_s6, // [22] Saved register 6
Reg_s7, // [23] Saved register 7
Reg_s8, // [24] Saved register 8
Reg_s9, // [25] Saved register 9
Reg_s10, // [26] Saved register 10
Reg_s11, // [27] Saved register 11
Reg_t3, // [28]
Reg_t4, // [29]
Reg_t5, // [30]
Reg_t6, // [31]
Reg_Total
};
 
 
union csr_mstatus_type {
struct bits_type {
uint64_t UIE : 1; // [0]: User level interrupts ena for current priv. mode
uint64_t SIE : 1; // [1]: Super-User level interrupts ena for current priv. mode
uint64_t HIE : 1; // [2]: Hypervisor level interrupts ena for current priv. mode
uint64_t MIE : 1; // [3]: Machine level interrupts ena for current priv. mode
uint64_t UPIE : 1; // [4]: User level interrupts ena previous value (before interrupt)
uint64_t SPIE : 1; // [5]: Super-User level interrupts ena previous value (before interrupt)
uint64_t HPIE : 1; // [6]: Hypervisor level interrupts ena previous value (before interrupt)
uint64_t MPIE : 1; // [7]: Machine level interrupts ena previous value (before interrupt)
uint64_t SPP : 1; // [8]: One bit wide. Supper-user previously priviledged level
uint64_t HPP : 2; // [10:9]: the Hypervisor previous privilege mode
uint64_t MPP : 2; // [12:11]: the Machine previous privilege mode
uint64_t UIE : 1; // [0]: User level interrupts ena for current
// priv. mode
uint64_t SIE : 1; // [1]: Super-User level interrupts ena for
// current priv. mode
uint64_t HIE : 1; // [2]: Hypervisor level interrupts ena for
// current priv. mode
uint64_t MIE : 1; // [3]: Machine level interrupts ena for
// current priv. mode
uint64_t UPIE : 1; // [4]: User level interrupts ena previous
// value (before interrupt)
uint64_t SPIE : 1; // [5]: Super-User level interrupts ena
// previous value (before interrupt)
uint64_t HPIE : 1; // [6]: Hypervisor level interrupts ena
// previous value (before interrupt)
uint64_t MPIE : 1; // [7]: Machine level interrupts ena previous
// value (before interrupt)
uint64_t SPP : 1; // [8]: One bit wide. Supper-user previously
// priviledged level
uint64_t HPP : 2; // [10:9]: the Hypervisor previous priv mode
uint64_t MPP : 2; // [12:11]: the Machine previous priv mode
uint64_t FS : 2; // [14:13]: RW: FPU context status
uint64_t XS : 2; // [16:15]: RW: extension context status
uint64_t MPRV : 1; // [17] Memory privilege bit
184,8 → 362,8
uint64_t PUM : 1; // [18]
uint64_t MXR : 1; // [19]
uint64_t rsrv1 : 4; // [23:20]
uint64_t VM : 5; // [28:24] Virtualization management field (WARL)
uint64_t rsrv2 : 64-30;// [62:29]
uint64_t VM : 5; // [28:24] Virtualization management field
uint64_t rsv2 : 64-30; // [62:29]
uint64_t SD : 1; // RO: [63] Bit summarizes FS/XS bits
} bits;
uint64_t value;
233,13 → 411,13
*/
/// @{
/// User-mode
static const uint64_t PRV_U = 0;
/// super-visor mode
static const uint64_t PRV_S = 1;
/// hyper-visor mode
static const uint64_t PRV_H = 2;
//// machine mode
static const uint64_t PRV_M = 3;
static const uint64_t PRV_U = 0;
/// super-visor mode
static const uint64_t PRV_S = 1;
/// hyper-visor mode
static const uint64_t PRV_H = 2;
//// machine mode
static const uint64_t PRV_M = 3;
/// @}
 
/**
280,7 → 458,7
static const uint16_t CSR_mepc = 0x341;
/** Machine trap cause */
static const uint16_t CSR_mcause = 0x342;
+/** Machine bad address. */ static const uint16_t CSR_mbadaddr = 0x343; /** Machine interrupt pending */ static const uint16_t CSR_mip = 0x344; @@ -287,58 +465,59 @@ /// @} /** Exceptions */ -enum EExeption { +enum ESignals { // Instruction address misaligned - EXCEPTION_InstrMisalign = 0, + EXCEPTION_InstrMisalign, // Instruction access fault - EXCEPTION_InstrFault = 1, + EXCEPTION_InstrFault, // Illegal instruction - EXCEPTION_InstrIllegal = 2, + EXCEPTION_InstrIllegal, // Breakpoint - EXCEPTION_Breakpoint = 3, + EXCEPTION_Breakpoint, // Load address misaligned - EXCEPTION_LoadMisalign = 4, + EXCEPTION_LoadMisalign, // Load access fault - EXCEPTION_LoadFault = 5, - //Store/AMO address misaligned - EXCEPTION_StoreMisalign = 6, + EXCEPTION_LoadFault, + // Store/AMO address misaligned + EXCEPTION_StoreMisalign, // Store/AMO access fault - EXCEPTION_StoreFault = 7, + EXCEPTION_StoreFault, // Environment call from U-mode - EXCEPTION_CallFromUmode = 8, + EXCEPTION_CallFromUmode, // Environment call from S-mode - EXCEPTION_CallFromSmode = 9, + EXCEPTION_CallFromSmode, // Environment call from H-mode - EXCEPTION_CallFromHmode = 10, + EXCEPTION_CallFromHmode, // Environment call from M-mode - EXCEPTION_CallFromMmode = 11 -}; + EXCEPTION_CallFromMmode, -enum EInterrupt { // User software interrupt - INTERRUPT_USoftware = 0, + INTERRUPT_USoftware, // Superuser software interrupt - INTERRUPT_SSoftware = 1, + INTERRUPT_SSoftware, // Hypervisor software itnerrupt - INTERRUPT_HSoftware = 2, + INTERRUPT_HSoftware, // Machine software interrupt - INTERRUPT_MSoftware = 3, + INTERRUPT_MSoftware, // User timer interrupt - INTERRUPT_UTimer = 4, + INTERRUPT_UTimer, // Superuser timer interrupt - INTERRUPT_STimer = 5, + INTERRUPT_STimer, // Hypervisor timer interrupt - INTERRUPT_HTimer = 6, + INTERRUPT_HTimer, // Machine timer interrupt - INTERRUPT_MTimer = 7, + INTERRUPT_MTimer, // User external interrupt - INTERRUPT_UExternal = 8, + INTERRUPT_UExternal, // Superuser external interrupt - INTERRUPT_SExternal = 9, + INTERRUPT_SExternal, // Hypervisor external interrupt - INTERRUPT_HExternal = 10, + INTERRUPT_HExternal, // Machine external interrupt (from PLIC) - INTERRUPT_MExternal = 11, + INTERRUPT_MExternal, + + SIGNAL_HardReset, + SIGNAL_Total }; } // namespace debugger

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.