Personal tools

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

From iis-projects

Jump to: navigation, search
GNU debugger (GDB) logo


Status: In progress


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. It is also extremely portable, any RISC-V core with a JTAG debugging interface can reuse the same infrastructure. However, simulating the serial 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 the requests of a GDB client and replay the execution of a RISC-V program by reading the information contained in the execution trace. Compared 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 possibly run faster.

You will follow the same approach of GDBWave, which is very well documented 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 mainly includes:

  • Single-stepping
  • Breakpoints

The output of this project would be an open source reusable GDB server written in C/C++ or Python, which you can optionally connect to through an IDE providing a fully-featured software debugging experience to lengthy RTL simulations. The project may prove valuable even beyond the RTL simulation domain, as we can connect to any RISC-V simulator which outputs a program trace, potentially including emulators such as Banshee [6]. This sets another advantage of our approach w.r.t. GDBWave.

What you will learn

From this project you will gain hands-on experience with GDB's remote serial protocol interface and functionalities. Needless to say, this is by far the most common debugging interface used in the embedded systems world, and shall be thus considered valuable knowledge if you want to later work in that field.

You will also be working directly with RISC-V assembly code, and you will practice understanding (and reconstructing) a program's behaviour from RISC-V assembly traces. You will also learn which major signals determine the state of a RISC-V core and need to be logged by the tracer to reconstruct the program execution.

Finally, you can boast your contributions to the RISC-V ecosystem, with the development of a reusable debugging tool which we would like to see being adopted by multiple RISC-V parties.

Optional stretch goals

Additional stretch goals may include:

  • Testing the connection to GDBTrace through an IDE such as Eclipse [5]
  • Evaluate the possibility of publishing this work
  • 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 and if it can be improved


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


  • Interest in computer architecture
  • Experience in programming in C/C++ or Python
  • Ability to read and understand Verilog RTL code, preferably gained in the VLSI I lectures
  • Preferred: Prior experience with debugging tools
  • Preferred: Knowledge or prior experience with RISC-V