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/isignal.h
File deleted
/coreservices/ikeylistener.h
File deleted
/coreservices/iudp.h
File deleted
/coreservices/isignallistener.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
+/** 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
static const uint16_t CSR_mepc = 0x341; |
/** Machine trap cause */ |
static const uint16_t CSR_mcause = 0x342; |