1 |
2 |
sergeykhbr |
/**
|
2 |
|
|
* @file
|
3 |
|
|
* @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved.
|
4 |
|
|
* @author Sergey Khabarov - sergeykhbr@gmail.com
|
5 |
|
|
* @brief Core API methods declaration.
|
6 |
|
|
*/
|
7 |
|
|
/**
|
8 |
|
|
* @page dbg_overview Overview
|
9 |
|
|
*
|
10 |
|
|
* @par Overview
|
11 |
|
|
* This debugger was specially developed as a software utility to interact
|
12 |
|
|
* with our SOC implementation in \c riscv_soc repository. The main
|
13 |
|
|
* purpose was to provide convinient way to develop and debug our
|
14 |
|
|
* Satellite Navigation firmware that can not be debugged by any other
|
15 |
|
|
* tool provided RISC-V community. Additionally, we would like to use
|
16 |
|
|
* the single unified application capable to work with Real and Simulated
|
17 |
|
|
* platforms without any modification of source code.
|
18 |
|
|
* Debugger provides base functionality such as: run control,
|
19 |
|
|
* read/write memory, registers and CSRs, breakpoints. It allows to
|
20 |
|
|
* reload FW image and reset target.
|
21 |
|
|
* Also we are developing own version of the CPU simulator
|
22 |
|
|
* (analog of \c spike) that can be extended with peripheries models to
|
23 |
|
|
* Full SOC simulator. These extensions for the debugger simplify
|
24 |
|
|
* porting procedure (Zephyr OS for an example) so that
|
25 |
|
|
* simulation doesn't require any hardware and allows to develop SW and HW
|
26 |
|
|
* simultaneously.
|
27 |
|
|
*
|
28 |
|
|
*/
|
29 |
|
|
|
30 |
|
|
/**
|
31 |
|
|
* @defgroup dbg_prj_structure_g Project structure
|
32 |
|
|
* @ingroup debugger_group
|
33 |
|
|
* @page dbg_prj_structure Project structure
|
34 |
|
|
*
|
35 |
|
|
* General idea of the project is to develop one \c Core library
|
36 |
|
|
* providing API methods for registering \c classes, \c services, \c attributes
|
37 |
|
|
* and methods to interact with them. Each extension plugin registers one or
|
38 |
|
|
* several class services performing some usefull work. All plugins are
|
39 |
|
|
* built as an independent libraries that are opening by \c Core library
|
40 |
|
|
* at initialization stage with the call of method <b>plugin_init()</b>.
|
41 |
|
|
* All Core API methods start with \c RISCV_... prefix:
|
42 |
|
|
* @code
|
43 |
|
|
* void RISCV_register_class(IFace *icls);
|
44 |
|
|
*
|
45 |
|
|
* IFace *RISCV_create_service(IFace *iclass, const char *name,
|
46 |
|
|
* AttributeType *args);
|
47 |
|
|
*
|
48 |
|
|
* IFace *RISCV_get_service(const char *name);
|
49 |
|
|
* ...
|
50 |
|
|
* @endcode
|
51 |
|
|
*
|
52 |
|
|
* Configuration of the debugger and plugins is fully described in JSON
|
53 |
|
|
* formatted configuration files <b>targets/target_name.json</b>.
|
54 |
|
|
* These files store all instantiated services names, attributes values
|
55 |
|
|
* and interconnect among plugins.
|
56 |
|
|
* This configuration can be saved to/load from file at any
|
57 |
|
|
* time. By default command \c exit will save current debugger state into
|
58 |
|
|
* file (including full command history).
|
59 |
|
|
*
|
60 |
|
|
* @note You can manually add/change new Registers/CSRs names and indexes
|
61 |
|
|
* by modifying this config file without changing source code.
|
62 |
|
|
*
|
63 |
|
|
* @par Folders description
|
64 |
|
|
* -# \b libdgb64g - Core library (so/dll) that provides standard API
|
65 |
|
|
* methods defined in file \c api_core.h.
|
66 |
|
|
* -# \b appdbg64g - Executable (exe) file implements functionality of
|
67 |
|
|
* the console debugger.
|
68 |
|
|
* -# \a Plugins:
|
69 |
|
|
* -# \b simple_plugin - Simple plugin (so/dll library) just for
|
70 |
|
|
* demonstration of the integration with debugger.
|
71 |
|
|
* -# \b cpu_fnc_plugin - Functional model of the RISC-V CPU
|
72 |
|
|
* (so/dll library).
|
73 |
|
|
* -# \b cpu_sysc_plugin - Precise SystemC model of RIVER CPU
|
74 |
|
|
* (so/dll library).
|
75 |
|
|
* -# \b socsim_plugin - Functional models of the peripheries
|
76 |
|
|
* and assembled board (so/dll library). This plugin
|
77 |
|
|
* registers several classes: \c UART, \c GPIO, \c SRAM,
|
78 |
|
|
* \c ROMs and etc.
|
79 |
|
|
*/
|
80 |
|
|
|
81 |
|
|
/**
|
82 |
|
|
* @defgroup dbg_connect_g Debug session
|
83 |
|
|
* @ingroup debugger_group
|
84 |
|
|
* @page dbg_connect Debug session
|
85 |
|
|
*
|
86 |
|
|
* @section dbg_connect_1 Plugins interaction
|
87 |
|
|
*
|
88 |
|
|
* Core library uses UDP protocol to communicate with all targets: FPGA or
|
89 |
|
|
* simulators. The general structure is looking like on the following figure:
|
90 |
|
|
*
|
91 |
|
|
* <img src="pics/dbg_sim.png" alt="sim debug">
|
92 |
|
|
* @latexonly {\includegraphics[scale=0.9]{pics/dbg_sim.png}} @endlatexonly
|
93 |
|
|
*
|
94 |
|
|
* or with real Hardware
|
95 |
|
|
*
|
96 |
|
|
* <img src="pics/dbg_fpga.png" alt="fpga debug">
|
97 |
|
|
* @latexonly {\includegraphics[scale=0.8]{pics/dbg_fpga.png}} @endlatexonly
|
98 |
|
|
*
|
99 |
|
|
* GUI plugin uses QT-libraries and interacts with the core library using the
|
100 |
|
|
* text console input interface. GUI generates the same text commands
|
101 |
|
|
* that are available in debugger console for any who's using this debugger.
|
102 |
|
|
* That's why any presented in GUI widgets information can be achieved
|
103 |
|
|
* in console mode.
|
104 |
|
|
*
|
105 |
|
|
* @section dbg_connect_2 Start Debugger
|
106 |
|
|
*
|
107 |
|
|
* We provide several targets that can run software (bootloader, firmware
|
108 |
|
|
* or user specific application) without any source code modifications:
|
109 |
|
|
*
|
110 |
|
|
* Start Configuration | Description
|
111 |
|
|
* -------------------------------|-----------------
|
112 |
|
|
* $ ./_run_functional_sim.sh[bat]| Functional RISC-V Full System Model
|
113 |
|
|
* $ ./_run_systemc_sim.sh[bat] | Use SystemC Precise Model of RIVER CPU
|
114 |
|
|
* $ ./_run_fpga_gui.sh[bat] | FPGA board. Default port 'COM3', TAP IP = 192.168.0.51
|
115 |
|
|
*
|
116 |
|
|
* To run debugger with the real FPGA target connected via Ethernet do:
|
117 |
|
|
* @code
|
118 |
|
|
* # cd rocket_soc/debugger/win32build/debug
|
119 |
|
|
* # _run_functional_sim.bat
|
120 |
|
|
* @endcode
|
121 |
|
|
*
|
122 |
|
|
* The result should look like on the picture below:
|
123 |
|
|
*
|
124 |
|
|
* <img src="pics/dbg_gui_start.png" alt="debugger 1-st look">
|
125 |
|
|
* @latexonly {\includegraphics[scale=0.8]{pics/dbg_gui_start.png}} @endlatexonly
|
126 |
|
|
*
|
127 |
|
|
* @par Example of the debug session
|
128 |
|
|
* Switch ON all User LEDs on board:
|
129 |
|
|
* @code
|
130 |
|
|
* riscv# help -- Print full list of commands
|
131 |
|
|
* riscv# csr MCPUID -- Read supported ISA extensions
|
132 |
|
|
* riscv# read 0xfffff000 20 -- Read 20 bytes from PNP module
|
133 |
|
|
* riscv# write 0x80000000 4 0xff -- Write into GPIO new LED value
|
134 |
|
|
* riscv# loadelf helloworld -- Load elf-file to board RAM and run
|
135 |
|
|
* @endcode
|
136 |
|
|
*
|
137 |
|
|
* Console mode view
|
138 |
|
|
*
|
139 |
|
|
* <img src="pics/dbg_testhw.png" alt="HW debug example">
|
140 |
|
|
* @latexonly {\includegraphics{pics/dbg_testhw.png}} @endlatexonly
|
141 |
|
|
*
|
142 |
|
|
* @section dbg_connect_3 Debug Zephyr OS kernel with symbols
|
143 |
|
|
*
|
144 |
|
|
* Build Zephyr kernel from scratch using our patches enabling 64-bits RISC-V
|
145 |
|
|
* architecture support:
|
146 |
|
|
* @code
|
147 |
|
|
* $ mkdir zephyr_160
|
148 |
|
|
* $ cd zephyr_160
|
149 |
|
|
* $ git clone https://gerrit.zephyrproject.org/r/zephyr
|
150 |
|
|
* $ cd zephyr
|
151 |
|
|
* $ git checkout tags/v1.6.0
|
152 |
|
|
* $ cp ../../riscv_vhdl/zephyr/v1.6.0-riscv64-base.diff .
|
153 |
|
|
* $ cp ../../riscv_vhdl/zephyr/v1.6.0-riscv64-exten.diff .
|
154 |
|
|
* $ git apply v1.6.0-riscv64-base.diff
|
155 |
|
|
* $ git apply v1.6.0-riscv64-exten.diff
|
156 |
|
|
* @endcode
|
157 |
|
|
*
|
158 |
|
|
* Then build elf-file:
|
159 |
|
|
* @code
|
160 |
|
|
* $ export ZEPHYR_BASE=/home/zephyr_160/zephyr
|
161 |
|
|
* $ cd zephyr/samples/shell
|
162 |
|
|
* $ make ARCH=riscv64 CROSS_COMPILE=/home/your_path/gnu-toolchain-rv64ima/bin/riscv64-unknown-elf- BOARD=riscv_gnss 2>&1
|
163 |
|
|
* @endcode
|
164 |
|
|
*
|
165 |
|
|
* Load debug symbols from elf-file without target reprogramming (or with):
|
166 |
|
|
* @code
|
167 |
|
|
* riscv# loadelf zephyr.elf
|
168 |
|
|
* riscv# loadelf zephyr.elf nocode
|
169 |
|
|
* @endcode
|
170 |
|
|
*
|
171 |
|
|
* <img src="pics/dbg_gui_symb.png" alt="debugger symbols">
|
172 |
|
|
* @latexonly {\includegraphics[scale=0.8]{pics/dbg_gui_symb.png}} @endlatexonly
|
173 |
|
|
*
|
174 |
|
|
* Now becomes available the following features:
|
175 |
|
|
* - Stack trace with function names
|
176 |
|
|
* - Function names in Disassembler including additional information for
|
177 |
|
|
* branch and jump instructions in column \c 'comment'.
|
178 |
|
|
* - Symbol Browser with filter.
|
179 |
|
|
* - Opening Disassembler and Memory Viewer widgets in a new window by name.
|
180 |
|
|
*
|
181 |
|
|
* Debugger provides additional features that could simplify software
|
182 |
|
|
* development:
|
183 |
|
|
* - Clock Per Instruction (CPI) hardware measure
|
184 |
|
|
* - Bus utilization information
|
185 |
|
|
* - Others. List of a new features is constantly increasing.
|
186 |
|
|
*
|
187 |
|
|
* <img src="pics/dbg_fpga_gui1.png" alt="debugger FPGA+GUI">
|
188 |
|
|
* @latexonly {\includegraphics[scale=0.8]{pics/dbg_fpga_gui1.png}} @endlatexonly
|
189 |
|
|
*
|
190 |
|
|
*/
|
191 |
|
|
|
192 |
|
|
/**
|
193 |
|
|
* @defgroup dbg_troubles_g Troubleshooting
|
194 |
|
|
* @ingroup debugger_group
|
195 |
|
|
* @page dbg_troubles Troubleshooting
|
196 |
|
|
*
|
197 |
|
|
* @subpage dbg_trouble_1
|
198 |
|
|
*
|
199 |
|
|
* @subpage dbg_trouble_2
|
200 |
|
|
*
|
201 |
|
|
* @subpage dbg_trouble_3
|
202 |
|
|
*
|
203 |
|
|
*/
|
204 |
|
|
|
205 |
|
|
/**
|
206 |
|
|
* @defgroup dbg_trouble_1_g Image Files not found
|
207 |
|
|
* @ingroup dbg_troubles_g
|
208 |
|
|
* @page dbg_trouble_1 Image Files not found
|
209 |
|
|
*
|
210 |
|
|
* If you'll get the error messages that image files not found
|
211 |
|
|
*
|
212 |
|
|
* <img src="pics/dbg_err1.png" alt="File not found">
|
213 |
|
|
* @latexonly {\includegraphics[scale=0.8]{pics/dbg_err1.png}} @endlatexonly
|
214 |
|
|
*
|
215 |
|
|
* To fix this problem do the following steps:
|
216 |
|
|
* -# Close debugger console using \c exit command.
|
217 |
|
|
* -# Open <em>config_file_name.json</em> file in any editor.
|
218 |
|
|
* -# Find strings that specify these paths and correct them. Simulator
|
219 |
|
|
* uses the same images as VHDL platform for ROMs intialization. You can find
|
220 |
|
|
* them in <em>'rocket_soc/fw_images'</em> directory. After that you should
|
221 |
|
|
* see something like follow:
|
222 |
|
|
*
|
223 |
|
|
* <img src="pics/dbg_simout1.png" alt="Simulator output">
|
224 |
|
|
* @latexonly {\includegraphics[scale=0.8]{pics/dbg_simout1.png}} @endlatexonly
|
225 |
|
|
*
|
226 |
|
|
* Debug your target. All commands that are available for Real Hardware
|
227 |
|
|
* absolutely valid for the Simulation. Users shouldn't see any difference
|
228 |
|
|
* between these targets this is our purpose.
|
229 |
|
|
*/
|
230 |
|
|
|
231 |
|
|
/**
|
232 |
|
|
* @defgroup dbg_trouble_2_g Can't open COM3 when FPGA is used
|
233 |
|
|
* @ingroup dbg_troubles_g
|
234 |
|
|
* @page dbg_trouble_2 Can't open COM3 when FPGA is used
|
235 |
|
|
*
|
236 |
|
|
* -# Open <em>fpga_gui.json</em>
|
237 |
|
|
* -# Change value <b>['ComPortName','COM3'],</b> on your one
|
238 |
|
|
* (for an example on \c ttyUSB0).
|
239 |
|
|
*
|
240 |
|
|
*/
|
241 |
|
|
|
242 |
|
|
/**
|
243 |
|
|
* @defgroup dbg_trouble_3_g EDCL: No response. Break read transaction
|
244 |
|
|
* @ingroup dbg_troubles_g
|
245 |
|
|
* @page dbg_trouble_3 EDCL: No response. Break read transaction
|
246 |
|
|
*
|
247 |
|
|
* This error means that host cannot locate board with specified IP address.
|
248 |
|
|
* Before you continue pass through the following checklist:
|
249 |
|
|
* -# You should properly @link eth_link setup network connection @endlink
|
250 |
|
|
* and see FPGA board in ARP-table.
|
251 |
|
|
* -# If you've changed default FPGA IP address:
|
252 |
|
|
* -# Open <em>_run_fpga_gui.bat (*.sh)</em>
|
253 |
|
|
* -# Change value <b>['BoardIP','192.168.0.51']</b> on your one.
|
254 |
|
|
* -# Run debugger
|
255 |
|
|
*
|
256 |
|
|
*/
|
257 |
|
|
|
258 |
|
|
#ifndef __DEBUGGER_API_CORE_H__
|
259 |
|
|
#define __DEBUGGER_API_CORE_H__
|
260 |
|
|
|
261 |
|
|
#include "api_utils.h"
|
262 |
|
|
#include "iface.h"
|
263 |
|
|
#include "attribute.h"
|
264 |
|
|
|
265 |
|
|
namespace debugger {
|
266 |
|
|
|
267 |
|
|
#ifdef __cplusplus
|
268 |
|
|
extern "C" {
|
269 |
|
|
#endif
|
270 |
|
|
|
271 |
|
|
/**
|
272 |
|
|
* @defgroup dbg_core_api_g Core API methods
|
273 |
|
|
* @ingroup debugger_group
|
274 |
|
|
* @details Core methods that allow create, modify and delete base library
|
275 |
|
|
* objects such as: Attributes, Classes, Services and Interfaces
|
276 |
|
|
* @{
|
277 |
|
|
*/
|
278 |
|
|
|
279 |
|
|
/**
|
280 |
|
|
* @brief Library initialization.
|
281 |
|
|
* @details This method must be called before any other from this library.
|
282 |
|
|
*/
|
283 |
|
|
int RISCV_init();
|
284 |
|
|
|
285 |
|
|
/**
|
286 |
|
|
* @brief Destroy and cleanup all dynamically allocated objects.
|
287 |
|
|
* @details This method allows gracefully close library by stopping all running
|
288 |
|
|
* threads and free allocated resources.
|
289 |
|
|
*/
|
290 |
|
|
void RISCV_cleanup();
|
291 |
|
|
|
292 |
|
|
/**
|
293 |
|
|
* @brief Set core library configuration.
|
294 |
|
|
* @details Configuration specify all instantiated services and interconnect
|
295 |
|
|
* among them.
|
296 |
|
|
* @param [in] cfg Configuration attribute.
|
297 |
|
|
*/
|
298 |
|
|
int RISCV_set_configuration(AttributeType *cfg);
|
299 |
|
|
|
300 |
|
|
/**
|
301 |
|
|
* @brief Read library configuration.
|
302 |
|
|
* @details This method allows serialize library state and save configuration
|
303 |
|
|
* into the file in JSON format. Afterward configuration can be
|
304 |
|
|
* restored.
|
305 |
|
|
*/
|
306 |
|
|
const char *RISCV_get_configuration();
|
307 |
|
|
|
308 |
|
|
/**
|
309 |
|
|
* @brief Get current core configuration.
|
310 |
|
|
* @details JSON configuration string implements special section \c 'Global'
|
311 |
|
|
* that contains parameters not related to any specific service or
|
312 |
|
|
* class.
|
313 |
|
|
*/
|
314 |
|
|
const AttributeType *RISCV_get_global_settings();
|
315 |
|
|
|
316 |
|
|
/**
|
317 |
|
|
* @brief Registration of the class in the library kernel.
|
318 |
|
|
* @details Registering interface pointer will be put into kernel list of
|
319 |
|
|
* classes. Any plugin can add its own class interfaces.
|
320 |
|
|
* @param [in] icls Pointer on new class interface.
|
321 |
|
|
*/
|
322 |
|
|
void RISCV_register_class(IFace *icls);
|
323 |
|
|
|
324 |
|
|
/**
|
325 |
|
|
* @brief Registration of the system event (hap) listener.
|
326 |
|
|
* @details Haps are used to synchronized different threads by a specific
|
327 |
|
|
* events in a system. Now there's used such haps as:
|
328 |
|
|
* - ConfigDone
|
329 |
|
|
* - Breakpoint
|
330 |
|
|
*/
|
331 |
|
|
void RISCV_register_hap(IFace *ihap);
|
332 |
|
|
|
333 |
|
|
/**
|
334 |
|
|
* @brief Trigger system event (hap) from Service.
|
335 |
|
|
* @details This method allows to call all registered listeneres of a specific
|
336 |
|
|
* event from running Service.
|
337 |
|
|
*/
|
338 |
|
|
void RISCV_trigger_hap(IFace *isrc, int type, const char *descr);
|
339 |
|
|
|
340 |
|
|
/**
|
341 |
|
|
* @brief Get registred class interface by its name.
|
342 |
|
|
* @details This method generally used to create instances of a specific
|
343 |
|
|
* service.
|
344 |
|
|
*/
|
345 |
|
|
IFace *RISCV_get_class(const char *name);
|
346 |
|
|
|
347 |
|
|
/**
|
348 |
|
|
* @brief Create service of the specified class.
|
349 |
|
|
* @details This method creates intstance of Service and assignes all
|
350 |
|
|
* registered attributes to its initial values.
|
351 |
|
|
*/
|
352 |
|
|
IFace *RISCV_create_service(IFace *iclass, const char *name,
|
353 |
|
|
AttributeType *args);
|
354 |
|
|
|
355 |
|
|
/**
|
356 |
|
|
* @brief Get IService interface by its name.
|
357 |
|
|
* @details This method is used for interaction of different services in a
|
358 |
|
|
* system.
|
359 |
|
|
*/
|
360 |
|
|
IFace *RISCV_get_service(const char *name);
|
361 |
|
|
|
362 |
|
|
/**
|
363 |
|
|
* @brief Get interface of the specified ervice.
|
364 |
|
|
* @details This method can be used in runtime to implement dynamic connection
|
365 |
|
|
* of different services
|
366 |
|
|
* @code
|
367 |
|
|
* ...
|
368 |
|
|
* IUdp *iudp1 = static_cast<IUdp *>
|
369 |
|
|
* (RISCV_get_service_iface("udpboard", IFACE_UDP));
|
370 |
|
|
* ...
|
371 |
|
|
* @endcode
|
372 |
|
|
*/
|
373 |
|
|
IFace *RISCV_get_service_iface(const char *servname, const char *facename);
|
374 |
|
|
|
375 |
|
|
/**
|
376 |
|
|
* @brief Get list of services implementing specific interface.
|
377 |
|
|
* @details This method can return list of services of different classes
|
378 |
|
|
* and implementing different functionality.
|
379 |
|
|
*/
|
380 |
|
|
void RISCV_get_services_with_iface(const char *iname, AttributeType *list);
|
381 |
|
|
|
382 |
|
|
|
383 |
|
|
/**
|
384 |
|
|
* @brief Get list of all clock generators.
|
385 |
|
|
* @details Clock generator must implement IClock (and usually IThread)
|
386 |
|
|
* interfaces. CPU is a most general clock generator.
|
387 |
|
|
*/
|
388 |
|
|
void RISCV_get_clock_services(AttributeType *list);
|
389 |
|
|
|
390 |
|
|
|
391 |
|
|
/**
|
392 |
|
|
* @brief Break all threads that could be run by different services.
|
393 |
|
|
* @details This method gracefully stops all threads and allows to avoid
|
394 |
|
|
* simulation hanging on library closing stage.
|
395 |
|
|
*/
|
396 |
|
|
void RISCV_break_simulation();
|
397 |
|
|
|
398 |
|
|
/**
|
399 |
|
|
* @brief State of the core library.
|
400 |
|
|
* @details Core library is active while woudln't break
|
401 |
|
|
* by RISCV_break_simulation()
|
402 |
|
|
*/
|
403 |
|
|
int RISCV_is_active();
|
404 |
|
|
|
405 |
|
|
/**
|
406 |
|
|
* @}
|
407 |
|
|
*/
|
408 |
|
|
|
409 |
|
|
|
410 |
|
|
#ifdef __cplusplus
|
411 |
|
|
}
|
412 |
|
|
#endif
|
413 |
|
|
|
414 |
|
|
} // namespace debugger
|
415 |
|
|
|
416 |
|
|
#endif // __DEBUGGER_API_CORE_H__
|