Skip to content

Commit 4da1cfc

Browse files
committed
docs: Incorporate RocketChip JTAG + GDB debugging instructions
Import detailed JTAG + GDB debugging instructions from the RocketChip README into Chipyard's documentation. This improves the Chip-Communication section with guidance for debugging RISC-V programs using the Remote Bit-Bang interface, OpenOCD, and GDB. Documentation was sourced from this archive of the RocketChip README: https://github.com/chipsalliance/rocket-chip/blob/0b7fef44f82b35bf289949b3f8fdc139641f8e10/README.md
1 parent bd3839c commit 4da1cfc

File tree

1 file changed

+231
-16
lines changed

1 file changed

+231
-16
lines changed

docs/Advanced-Concepts/Chip-Communication.rst

Lines changed: 231 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -129,35 +129,250 @@ The default Chipyard designs instantiate the DTM configured to use JTAG (i.e. ``
129129
However, they also use TSI/Serialized-TL with FESVR in case the JTAG interface isn't used.
130130
This allows users to choose how to communicate with the DUT (use TSI or JTAG).
131131

132-
Debugging with JTAG
133-
~~~~~~~~~~~~~~~~~~~
132+
Debugging with JTAG + GDB
133+
~~~~~~~~~~~~~~~~~~~~~~~~~~~
134134

135-
Roughly the steps to debug with JTAG in simulation are as follows:
135+
This section provides detailed instructions for using GNU debugger (GDB) to debug RISC-V programs running on the emulator, similar to debugging with Spike.
136136

137-
1. Build a Chipyard JTAG-enabled RTL design. Remember default Chipyard designs are JTAG ready.
137+
Generating the Remote Bit-Bang (RBB) Emulator
138+
+++++++++++++++++++++++++++++++++++++++++++++++++++
139+
140+
The objective of this section is to use GNU debugger to debug RISC-V programs running on the emulator in
141+
the same fashion as in `Spike <https://github.com/riscv/riscv-isa-sim#debugging-with-gdb>`_.
142+
143+
For that we need to add a Remote Bit-Bang client to the emulator. We can do so by extending our Config
144+
with ``JtagDTMSystem``, which will add a ``DebugTransportModuleJTAG`` to the DUT and connect a ``SimJTAG``
145+
module in the Test Harness. This will allow OpenOCD to interface with the emulator, and GDB can interface
146+
with OpenOCD. In the following example we add this Config alteration to
147+
``src/main/scala/system/Configs.scala``:
148+
149+
.. code-block:: scala
150+
151+
class DefaultConfigRBB extends Config(
152+
new WithJtagDTMSystem ++ new WithNBigCores(1) ++ new WithCoherentBusTopology ++ new BaseConfig)
153+
154+
class QuadCoreConfigRBB extends Config(
155+
new WithJtagDTMSystem ++ new WithNBigCores(4) ++ new WithCoherentBusTopology ++ new BaseConfig)
156+
157+
To build the emulator with ``DefaultConfigRBB`` configuration we use the command:
138158

139159
.. code-block:: bash
140160
141-
cd sims/verilator
142-
# or
143-
cd sims/vcs
161+
rocket-chip$ cd emulator
162+
emulator$ CONFIG=freechips.rocketchip.system.DefaultConfigRBB make
163+
164+
We can also build a debug version capable of generating VCD waveforms using the command:
165+
166+
.. code-block:: bash
167+
168+
emulator$ CONFIG=freechips.rocketchip.system.DefaultConfigRBB make debug
169+
170+
By default the emulator is generated under the name
171+
``emulator-freechips.rocketchip.system-DefaultConfigRBB`` in the first case and
172+
``emulator-freechips.rocketchip.system-DefaultConfigRBB-debug`` in the second.
173+
174+
Compiling and executing a custom program using the emulator
175+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
176+
177+
We suppose that ``helloworld`` is our program. You can use ``crt.S``, ``syscalls.c``, and the linker script
178+
``test.ld`` to construct your own program (see
179+
`riscv-tests <https://github.com/riscv/riscv-tests>`_). Note that ``test.ld`` loads the program at
180+
``0x80000000`` so you will need ``-mcmodel=medany`` (see
181+
`The RISC-V Code Models <https://www.sifive.com/blog/2017/09/11/all-aboard-part-4-risc-v-code-models/>`_).
182+
183+
.. code-block:: c
184+
185+
char text[] = "Vafgehpgvba frgf jnag gb or serr!";
144186
145-
make CONFIG=RocketConfig
187+
// Don't use the stack, because sp isn't set up.
188+
volatile int wait = 1;
146189
147-
2. Run the simulation with remote bit-bang enabled. Since we hope to load/run the binary using JTAG,
148-
we can pass ``none`` as a binary (prevents FESVR from loading the program). (Adapted from: https://github.com/chipsalliance/rocket-chip#3-launch-the-emulator)
190+
int main()
191+
{
192+
while (wait)
193+
;
194+
195+
// Doesn't actually go on the stack, because there are lots of GPRs.
196+
int i = 0;
197+
while (text[i]) {
198+
char lower = text[i] | 32;
199+
if (lower >= 'a' && lower <= 'm')
200+
text[i] += 13;
201+
else if (lower > 'm' && lower <= 'z')
202+
text[i] -= 13;
203+
i++;
204+
}
205+
206+
while (!wait)
207+
;
208+
}
209+
210+
First, we can test if this program executes correctly in the simpler emulator (non-RBB) before debugging:
149211

150212
.. code-block:: bash
151213
152-
# note: this uses Chipyard make invocation to run the simulation to properly wrap the simulation args
153-
make CONFIG=RocketConfig BINARY=none SIM_FLAGS="+jtag_rbb_enable=1 --rbb-port=9823" run-binary
214+
$ ./emulator-freechips.rocketchip.system-DefaultConfig helloworld
154215
155-
3. `Follow the instructions here to connect to the simulation using OpenOCD + GDB. <https://github.com/chipsalliance/rocket-chip#4-launch-openocd>`__
216+
Additional verbose information (clock cycle, pc, instruction being executed) can be printed:
217+
218+
.. code-block:: bash
219+
220+
$ ./emulator-freechips.rocketchip.system-DefaultConfig +verbose helloworld 2>&1 | spike-dasm
221+
222+
VCD output files can be obtained using the ``-debug`` version of the emulator and are specified using ``-v`` or
223+
``--vcd=FILE`` arguments. A detailed log file of all executed instructions can also be obtained from the emulator:
224+
225+
.. code-block:: bash
226+
227+
$ ./emulator-freechips.rocketchip.system-DefaultConfig-debug +verbose -v output.vcd helloworld 2>&1 | spike-dasm > output.log
228+
229+
.. note::
230+
Generated VCD waveforms and execution log files can be very voluminous depending on the size of the .elf file
231+
(i.e. code size + debugging symbols).
156232

157233
.. note::
158-
This section was adapted from the instruction in Rocket Chip and riscv-isa-sim. For more information refer
159-
to that documentation: `Rocket Chip GDB Docs <https://github.com/chipsalliance/rocket-chip#-debugging-with-gdb>`__,
160-
`riscv-isa-sim GDB Docs <https://github.com/riscv/riscv-isa-sim#debugging-with-gdb>`__
234+
The time it takes the emulator to load your program depends on executable size. Stripping the .elf executable
235+
will unsurprisingly make it run faster. For this you can use ``$RISCV/bin/riscv64-unknown-elf-strip`` tool to
236+
reduce the size. This is good for accelerating your simulation but not for debugging.
237+
238+
.. warning::
239+
The HTIF communication interface between our system and the emulator relies on ``tohost`` and ``fromhost``
240+
symbols to communicate. If you try to run a totally stripped executable on the emulator, you may get:
241+
242+
.. code-block:: text
243+
244+
$ ./emulator-freechips.rocketchip.system-DefaultConfig totally-stripped-helloworld
245+
This emulator compiled with JTAG Remote Bitbang client. To enable, use +jtag_rbb_enable=1.
246+
Listening on port 46529
247+
warning: tohost and fromhost symbols not in ELF; can't communicate with target
248+
249+
To resolve this, we need to strip all the .elf executable but keep ``tohost`` and ``fromhost`` symbols:
250+
251+
.. code-block:: bash
252+
253+
$ riscv64-unknown-elf-strip -s -Kfromhost -Ktohost helloworld
254+
255+
More details on the GNU strip tool can be found
256+
`here <https://www.thegeekstuff.com/2012/09/strip-command-examples/>`_.
257+
258+
The interest of this step is to make sure your program executes well. To perform debugging you need the original
259+
unstripped version, as explained in the following steps.
260+
261+
Launch the emulator
262+
+++++++++++++++++++++++++
263+
264+
First, do not forget to compile your program with ``-g -Og`` flags to provide debugging support.
265+
266+
We can then launch the Remote Bit-Bang enabled emulator with:
267+
268+
.. code-block:: bash
269+
270+
./emulator-freechips.rocketchip.system-DefaultConfigRBB +jtag_rbb_enable=1 --rbb-port=9823 helloworld
271+
272+
.. note::
273+
You can also use the ``emulator-freechips.rocketchip.system-DefaultConfigRBB-debug`` version instead if you
274+
would like to generate VCD waveforms.
275+
276+
.. note::
277+
If the argument ``--rbb-port`` is not passed, a default free TCP port on your computer will be chosen randomly.
278+
279+
.. note::
280+
When debugging with GDB, the .elf file is not actually loaded by the FESVR. In contrast with Spike, it must
281+
be loaded from GDB as explained in step 5. So the ``helloworld`` argument may be replaced by any dummy name.
282+
283+
Launch OpenOCD
284+
++++++++++++++++++++
285+
286+
You will need a RISC-V Enabled OpenOCD binary. This is installed with rocket-tools in ``$(RISCV)/bin/openocd``,
287+
or can be compiled manually from riscv-openocd. OpenOCD requires a configuration file, in which we define the RBB
288+
port we will use, which is in our case ``9823``.
289+
290+
.. code-block:: tcl
291+
292+
interface remote_bitbang
293+
remote_bitbang_host localhost
294+
remote_bitbang_port 9823
295+
296+
set _CHIPNAME riscv
297+
jtag newtap $_CHIPNAME cpu -irlen 5
298+
299+
set _TARGETNAME $_CHIPNAME.cpu
300+
target create $_TARGETNAME riscv -chain-position $_TARGETNAME
301+
302+
gdb_report_data_abort enable
303+
304+
init
305+
halt
306+
307+
Then we launch OpenOCD in another terminal using the command:
308+
309+
.. code-block:: bash
310+
311+
$(RISCV)/bin/openocd -f ./cemulator.cfg
312+
313+
.. note::
314+
A ``-d`` flag can be added to the command to show further debug information.
315+
316+
Launch GDB
317+
+++++++++++++++++
318+
319+
In another terminal launch GDB and point to the elf file you would like to load then run it with the debugger
320+
(in this example, ``helloworld``):
321+
322+
.. code-block:: bash
323+
324+
$ riscv64-unknown-elf-gdb helloworld
325+
326+
Compared to Spike, the C Emulator is very slow, so several problems may be encountered due to timeouts between
327+
issuing commands and response from the emulator. To solve this problem, we increase the timeout with the GDB
328+
``set remotetimeout`` command.
329+
330+
After that we load our program by performing a ``load`` command. This automatically sets the ``$PC`` to the
331+
``_start`` symbol in our .elf file:
332+
333+
.. code-block:: none
334+
335+
(gdb) set remotetimeout 2000
336+
(gdb) target remote localhost:3333
337+
Remote debugging using localhost:3333
338+
0x0000000000010050 in ?? ()
339+
(gdb) load
340+
Loading section .text.init, size 0x2cc lma 0x80000000
341+
Loading section .tohost, size 0x48 lma 0x80001000
342+
Loading section .text, size 0x98c lma 0x80001048
343+
Loading section .rodata, size 0x158 lma 0x800019d4
344+
Loading section .rodata.str1.8, size 0x20 lma 0x80001b30
345+
Loading section .data, size 0x22 lma 0x80001b50
346+
Loading section .sdata, size 0x4 lma 0x80001b74
347+
Start address 0x80000000, load size 3646
348+
Transfer rate: 40 bytes/sec, 520 bytes/write.
349+
350+
Now we can proceed as with Spike, debugging works in a similar way:
351+
352+
.. code-block:: none
353+
354+
(gdb) print wait
355+
$1 = 1
356+
(gdb) print wait=0
357+
$2 = 0
358+
(gdb) print text
359+
$3 = "Vafgehpgvba frgf jnag gb or serr!"
360+
(gdb) c
361+
Continuing.
362+
363+
^C
364+
Program received signal SIGINT, Interrupt.
365+
main (argc=0, argv=<optimized out>) at src/main.c:33
366+
33 while (!wait)
367+
(gdb) print wait
368+
$4 = 0
369+
(gdb) print text
370+
$5 = "Instruction sets want to be free!"
371+
372+
For more information on GDB debugging, refer to:
373+
374+
* `GDB User Manual <https://sourceware.org/gdb/onlinedocs/gdb/>`_
375+
* `GDB Remote Debugging <https://sourceware.org/gdb/onlinedocs/gdb/Remote-Debugging.html#Remote-Debugging>`_
161376

162377
Example Test Chip Bringup Communication
163378
---------------------------------------

0 commit comments

Comments
 (0)