Personal tools

GDBTrace: A Post-Simulation Trace-Based RISC-V GDB Debugging Server (1S)

From iis-projects

Revision as of 10:51, 13 October 2022 by Colluca (talk | contribs) (Introduction)
Jump to: navigation, search


Overview

Status: Available

Introduction

In any chip design project, a lot of effort is spent on verifying the design before it can be delivered for tapeout. For general purpose processor designs, verifying the functionality involves running some code on the core(s) and comparing the outputs of the program with the expected results. On a mismatch, we will have to identify where the bug originates in the hardware and, for this to be possible, we need to identify at what point the program behaviour deviates from our expectations.

If your processor has a debugging interface (exposed e.g. over JTAG) and can be implemented on an FPGA, you will possibly be able to connect a debugger to your FPGA board and benefit of a fully-featured debugging experience, as you might be used to from programming embedded systems. However, this is not always the case, as bringing a design onto an FPGA requires additional effort, and for large designs which do not fit on a single FPGA it might not be possible to have an exact 1-to-1 correspondence between the FPGA implementation and the original design.

If testing your design on an FPGA is not an option, you will have to debug your code directly in RTL simulation. In this setting, you can forget the bells and whistles of integrated development environments (IDEs) with their powerful debugging features and convenient graphical interfaces. Oftentimes, your best tool at hand is the core's bare execution trace, i.e. a flat record of the instructions which were executed by the core during the simulation, accompanied by auxiliary information such as the values of the registers involved in each instruction at the time of its execution.

Is this really the best way we can inspect our program's execution? Alternative methodologies do exist, but come with their own shortcomings which we want to address in this thesis. We aim for a source-centric debugging experience, i.e. in which the program execution can be inspected at the source (or high-level language) level. We thus do not mention any approach which aims at making the trace-centric debugging experience more "comfortable".

Again, if your processor has a debugging interface (exposed e.g. over JTAG), you can actually connect a debugger to the simulation and communicate with the processor through the JTAG port [1]. This method is extremely powerful, as the debugger provides us with the desired fully-featured source-centric debugging experience. This method is also extremely portable, any RISC-V core with a JTAG debugging interface can reuse the same infrastructure. However, simulating the serial connection on the JTAG interface can significantly slow down the simulation to the point where it becomes unpractical to use. This is especially true when dealing with large and complex designs.

More recently, as of February 2022, the GDBWave tool [2,3] was released, providing a solution which does not incur the significant slowdown from simulating the serial debugging connection. The underlying idea is to log, during the simulation, all the information which is needed to reconstruct the program execution after the simulation has completed. Specifically, GDBWave takes a waveform dump from the simulation as input. So long as it can identify and interpret the relevant signals, such as the program counter and the write port to the register file, it can replay the execution of the program as requested by the debugger. Unfortunately, as these signals are implementation dependent, this approach suffers of poor portability.

Project description

In this project, you will develop a GDB server, similar in its essence to GDBWave, which can process a RISC-V program trace and interact with a GDB client, providing a fully-featured debugging experience. In comparison to GDBWave, this approach is implementation-agnostic and can virtually support any RISC-V core, as long as it complies with our trace format. In addition, by removing the need to log any waveforms, the simulator might be able to optimize the design more aggressively, and can possibly run faster.

You will follow the same approach of GDBWave, which is very well explained in a blog post from the author [2]. In particular, you will be interfacing to the GDB client via GDB's remote serial protocol (RSP) [4]. You are not expected to implement the whole RSP interface. Instead, the minimal functionality we would like to support is the same as described in the GDBWave blog post and that mainly includes:

  • Single-stepping
  • Breakpoints

Optional stretch goals

Additional stretch goals may include:

  • Connecting to GDBTrace through an IDE such as Eclipse [5]
  • Study the feasibility of connecting to a running simulation by inspecting mid-simulation partially dumped traces
  • Review existing multicore debugging strategies and understand how GDBTrace would fit in this scenario

Character

  • 20% Literature and documentation review
  • 20% Code review
  • 60% C or Python programming

Prerequisites

  • Interest in computer architecture
  • Experience in programming in C/C++ or Python
  • Preferred: Prior experience with debugging tools
  • Preferred: Knowledge or prior experience with RISC-V

References

[1] https://github.com/pulp-platform/pulp-debug-bridge
[2] https://tomverbeure.github.io/2022/02/20/GDBWave-Post-Simulation-RISCV-SW-Debugging.html
[3] https://github.com/tomverbeure/gdbwave
[4] https://www.embecosm.com/appnotes/ean4/embecosm-howto-rsp-server-ean4-issue-2.html
[5] https://projects.eclipse.org/projects/tools.cdt