openhwgroup / cva6

The CORE-V CVA6 is an Application class 6-stage RISC-V CPU capable of booting Linux
https://docs.openhwgroup.org/projects/cva6-user-manual/
Other
2.23k stars 679 forks source link

Debugging CVA6 APU on a KC705 board #1803

Closed Juan-Gg closed 8 months ago

Juan-Gg commented 8 months ago

I am attempting to get the CVA6 APU running on a KC705 board.

What I have done so far:

ubuntu@ubuntu-2204:~/Documents$ openocd -f ariane.cfg
Open On-Chip Debugger 0.11.0
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
DEPRECATED! use 'adapter speed' not 'adapter_khz'
DEPRECATED! use 'adapter driver' not 'interface'
Info : auto-selecting first available session transport "jtag". To override use 'transport select <transport>'.
Info : clock speed 1000 kHz
Error: JTAG scan chain interrogation failed: all ones
Error: Check JTAG interface, timings, target power, etc.
Error: Trying to use configured scan chain anyway...
Error: riscv.cpu: IR capture error; saw 0x1f not 0x01
Warn : Bypassing JTAG setup events due to errors
Error: Unsupported DTM version: 15
Warn : target riscv.cpu examination failed
Info : starting gdb server for riscv.cpu on 3333
Info : Listening on port 3333 for gdb connections
Error: Target not examined yet

Error: Unsupported DTM version: 15

Any ideas on what may be going wrong? What do the LEDs mean? I could not find any documentation on these. Thanks.

jquevremont commented 8 months ago

The SDK is adapted to the Genesys 2 board, which has been selected by OpenHW Group for most of its projects. As of now, the CVA6 team has no resource to provide such support for other boards. OpenHW members are welcome to propose such new projects and contributions.

jquevremont commented 8 months ago

I need to update the README to state the limitation.

(See https://github.com/openhwgroup/cva6-sdk/pull/92)

Juan-Gg commented 8 months ago

But even without sdk support, shouldn't I be able to at least see the core on the JTAG chain, with OpenOCD?

On the README for this repository, it does say:

We currently only provide support for the Genesys 2 board.

But the makefile has support for kc705 & vc707 boards, related scripts for these boards are in corev_apu/fpga/src and corev_apu/fpga/constraints. I understand these are not maintained?

jquevremont commented 8 months ago

Your understanding is right. More contributors to OpenHW projects are welcome to add more such maintenance.

Juan-Gg commented 6 months ago

Here is what I did to get it working. Hope somebody finds it useful.

Generating the bitstream

The LEDs I was mentioning have nothing to do with CVA6. There is no GPIO implemented at the time of writing. Programming the board with the MCS file did not work for some reason, but using the bitstream directly did work and the board booted. This is what the bootrom outputs, if the SD card with the linux image is present, it will boot Linux next.

..Hello World!
init SPI
status: 0x0000000000000025
status: 0x0000000000000025
SPI initialized!
initializing SD... 

In order to look at the Vivado project and be able to see the elaboration results, I changed the target in corev_apu/fpga/Makefile from \$ (mcs) to \$ (bit). This way the Vivado project is not overwritten for MCS generation.

Setting up the JTAG with BSCANE2

Turns out the Genesys 2 FT2232 IC has two JTAG ports broken out, one for the FPGA, one free to use, in this case, for debugging the cva6. The kc705 board, even though having the same IC, only has one JTAG port, used for the FPGA. The cva6 JTAG pins are connected to the FMC connectors, and could be used with an external JTAG adapter. Another option is using Xilinx BSCANE2 IPs, which expose some additional registers in the FPGA’s JTAG, which can be used to debug the processor through the FPGA’s JTAG. This functionality is available as part of the riscv-dbg repository , though a newer version than what is used currently in cva6.

The file “dmi_bscane_tap.sv” can replace “dmi_jtag_tap.sv” to use Xilinx BSCANE2 IPs instead of external pins. As they note “The file is pin-compatible so that by selecting the appropriate file for the target it can be transparently managed without relying on tick defines.”

Note: It may be a good idea to update riscv-dbg and common_cells to more recent versions so this BSCAN option is available by default.

OpenOCD configuration

Then, one can launch OpenOCD (setup, download, install)

I got it to work with the following configuration script, adapted from here.

# Adapted from core-v-mini-mcu-pynq-z2-bscan.cfg

adapter driver ftdi     
adapter speed 1000
transport select jtag

# FT2232HQ Adapter
ftdi_vid_pid 0x0403 0x6010

ftdi_channel 0
ftdi_layout_init 0x0088 0x008b

reset_config none

echo "ftdi setting..."

set _CHIPNAME riscv

jtag newtap $_CHIPNAME cpu -irlen 6 -expected-id 0x43651093

set _TARGETNAME $_CHIPNAME.cpu

target create $_TARGETNAME riscv -chain-position $_TARGETNAME -coreid 0x000

echo "target created..."

#log_output openocd_fpga.log

riscv set_ir idcode 0x09
riscv set_ir dtmcs 0x22
riscv set_ir dmi 0x23

riscv set_reset_timeout_sec 2000
riscv set_command_timeout_sec 2000

echo "setting preferences..."

scan_chain

init

echo "init routine started"

halt

echo "Ready for Remote Connections"

Running OpenOCD:

A sample execution:

$ openocd -f bscan_modified.cfg
xPack Open On-Chip Debugger 0.12.0-01004-g9ea7f3d64-dirty (2023-01-30-15:03)
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
DEPRECATED! use 'ftdi vid_pid' not 'ftdi_vid_pid'
DEPRECATED! use 'ftdi channel' not 'ftdi_channel'
DEPRECATED! use 'ftdi layout_init' not 'ftdi_layout_init'
ftdi setting...
target created...
setting preferences...
Info : clock speed 1000 kHz
Info : JTAG tap: riscv.cpu tap/device found: 0x43651093 (mfg: 0x049 (Xilinx), part: 0x3651, ver: 0x4)
Info : datacount=2 progbufsize=8
Info : Examined RISC-V core; found 1 harts
Info :  hart 0: XLEN=64, misa=0x800000000014112f
Info : starting gdb server for riscv.cpu on 3333
Info : Listening on port 3333 for gdb connections
init routine started
Ready for Remote Connections
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections

Running GDB (This onwards applies to any board):

After OpemOCD is running, one can launch gdb and use it, for example, to examine memory. Here we are looking at 0x10000, the first word in bootrom_64, which matches with the value in bootrom_64.sv.

$ riscv-none-elf-gdb -ex "target remote :3333" 
[...]
(gdb) x /xg 0x00010000
0x10000:    0x3049107300800913

Compiling a baremetal program:

One can take the corev_apu/fpga/src/bootrom as a starting point.

Then, running make results in an .elf file that can be loaded via gdb.

An example setup can be found here for the time being. Ideally, a similar example should be part of cva6's repository.

Running the baremetal program:

The baremetal program can be executed as follows:

$ riscv-none-elf-gdb -ex "target remote :3333" bootrom_64.elf

[...]

(gdb) load
Loading section .text.init, size 0x88 lma 0x80000000
Loading section .text, size 0x32a lma 0x80000100
Loading section .text.startup, size 0x24 lma 0x8000042a
Loading section .data, size 0x10 lma 0x80000500
Loading section .rodata, size 0x5d lma 0x80000600
Start address 0x000000008000042a, load size 1091
Transfer rate: 12 KB/sec, 218 bytes/write.
(gdb) continue
Continuing.

Terminal output can be seen in any terminal emulator, such as gtkterm. I used dmesg | grep tty to see which ttyUSBx was the board’s UART.

Summary: Once bitstream and .elf are ready:

Adding an Integrated Logic Analyzer (ILA)

[Here] (https://github.com/DvdBerg/cva6/commit/11799a6a082788255ec76ef3e8cb0c341cfff4b2) you can find the changes this guy made to use an ILA.

As a summary:

- Include the ILA in the main run.tcl:

read_ip { \ [...] "xilinx/xlnx_ila/xlnx_ila.srcs/sources_1/ip/xlnx_ila/xlnx_ila.xci" \ <------- Add here }

[...]

launch_runs synth_1 wait_on_run synth_1 open_run synth_1

write_debug_probes -force work-fpga/debug_nets.ltx <---------- Add this too

- Instantiate the ILA in the verilog code
```verilog
xlnx_ila ila_test (
        .clk(clk), <--- Watch this, choose the right clock.

        .probe0(your_signal),
        .probe1(your_signal_2),
[...]
    );

Using an Integrated Logic Analyzer (ILA) while running a program with GDB with a shared JTAG port

This one's easy. You don't.

But there is something you can do: Get a program running on the board, debug using the UART and use the JTAG port for the ILA.

To allow you to control the program flow from the UART, i.e. to start a transaction you wish to trigger on with the ILA, a function to receive on the UART comes in handy.

One can add something like this to uart.c

#define UART_LINE_STATUS_BIT_DATA_READY (1 << 0)

char uart_receive_char_blocking()
{
    while(!(read_reg_u8(UART_LINE_STATUS) & UART_LINE_STATUS_BIT_DATA_READY));
    return  read_reg_u8(UART_RBR); // Receive buffer register.
}
elialaz commented 6 months ago

Hi juan,

Could you plis share a baremetal c project example? I'm quite stuck and I cannot run anything successfully unfortunately.

Thanks

Juan-Gg commented 6 months ago

@elialaz, I have added a link on my previous post. I hope it works for you.

elialaz commented 6 months ago

Thanks very much!