diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d140d6f61..5948f6dbf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -96,9 +96,37 @@ jobs: run: | ctest --test-dir build/sw -R sim_verilator -LE slow --output-on-failure -j $(nproc) - - name: Run debug test + verilator-debug-test: + runs-on: ["self-hosted", "nixos", "X64"] + needs: lint-check + + defaults: + run: + shell: "nix develop -c bash -e {0}" + + steps: + - uses: actions/checkout@v5 + + - name: Prepare Nix environment run: | - util/debug_test.sh + true + + - name: Generate software buildsystem + run: | + cmake -B build/sw -S sw + + - name: Build software + run: | + cmake --build build/sw -j $(nproc) --target bootrom --target infinite_loop + + - name: Build verilator + run: | + JOBS=$(($(nproc) / 4)) + MAKEFLAGS="-j$JOBS" fusesoc --cores-root=. run --target=sim --tool=verilator --setup --build lowrisc:mocha:top_chip_verilator + + - name: Run verilator debug test + run: | + util/debug_test_verilator.sh fpga-cache-check: runs-on: ["self-hosted", "nixos", "X64"] @@ -202,3 +230,8 @@ jobs: shell: "nix develop -c bash -e {0}" run: | ctest --test-dir build/sw -R fpga -LE slow --output-on-failure + + - name: Run FPGA debug test + shell: "nix develop -c bash -e {0}" + run: | + util/debug_test_fpga.sh diff --git a/doc/ref/dev_guide.md b/doc/ref/dev_guide.md index b18bf6d1e..438dda788 100644 --- a/doc/ref/dev_guide.md +++ b/doc/ref/dev_guide.md @@ -173,9 +173,11 @@ Some peripheral tests require additional hardware to be connected to the Genesys ## Debugging -You can connect to OpenOCD using GDB. -Currently we only support connecting to JTAG out of the box in Verilator simulation and FPGA debugging is unsupported. -You can build a custom FPGA bitstream by using the patch that is located in the [Genesys2 TCL script](../../util/genesys2-openocd-cfg.tcl). +FPGA debugging is supported through the PMOD header JD. +First connect your JTAG adapter to PMOD JD according to the pinout in [pins_genesys2.xdc](../../hw/top_chip/data/pins_genesys2.xdc), then connect OpenOCD to Mocha with the following command: +```sh +openocd -f util/genesys2-openocd-cfg.tcl +``` Once you have connected OpenOCD to your hardware target you can connect GDB by using the following command: ```sh diff --git a/hw/top_chip/data/pins_genesys2.xdc b/hw/top_chip/data/pins_genesys2.xdc index ca7427777..70e591fbd 100644 --- a/hw/top_chip/data/pins_genesys2.xdc +++ b/hw/top_chip/data/pins_genesys2.xdc @@ -48,7 +48,7 @@ set_property -dict { PACKAGE_PIN Y23 IOSTANDARD LVCMOS33 } [get_ports { uart_t set_property -dict { PACKAGE_PIN T26 IOSTANDARD LVCMOS33 PULLTYPE PULLUP } [get_ports { i2c_scl_io }]; set_property -dict { PACKAGE_PIN T27 IOSTANDARD LVCMOS33 PULLTYPE PULLUP } [get_ports { i2c_sda_io }]; -## SPI Device (PMOD Header JD) +## SPI Device (FT2232H) set_property -dict { PACKAGE_PIN W28 IOSTANDARD LVCMOS33 PULLTYPE PULLDOWN } [get_ports { spi_device_sd_o }]; set_property -dict { PACKAGE_PIN W27 IOSTANDARD LVCMOS33 PULLTYPE PULLDOWN } [get_ports { spi_device_sd_i }]; set_property -dict { PACKAGE_PIN W29 IOSTANDARD LVCMOS33 PULLTYPE PULLUP } [get_ports { spi_device_csb_i }]; @@ -86,3 +86,10 @@ set_property -dict { PACKAGE_PIN W26 IOSTANDARD LVCMOS33 } [get_ports { spi_ho set_property -dict { PACKAGE_PIN V25 IOSTANDARD LVCMOS33 } [get_ports { spi_host_sd_i_dbg_o }]; # JB2_P (PMOD 3) set_property -dict { PACKAGE_PIN V29 IOSTANDARD LVCMOS33 } [get_ports { spi_host_csb_o_dbg_o }]; # JB1_P (PMOD 1) set_property -dict { PACKAGE_PIN V30 IOSTANDARD LVCMOS33 } [get_ports { spi_host_sd_o_dbg_o }]; # JB1_N (PMOD 2) + +## Debug JTAG (PMOD Header JD) +set_property -dict { PACKAGE_PIN V27 IOSTANDARD LVCMOS33 PULLTYPE PULLUP } [get_ports { jtag_tck }]; # JD1 (PMOD 1) +set_property -dict { PACKAGE_PIN Y30 IOSTANDARD LVCMOS33 PULLTYPE PULLUP } [get_ports { jtag_tms }]; # JD2 (PMOD 2) +set_property -dict { PACKAGE_PIN V24 IOSTANDARD LVCMOS33 PULLTYPE PULLUP } [get_ports { jtag_tdi }]; # JD3 (PMOD 3) +set_property -dict { PACKAGE_PIN W22 IOSTANDARD LVCMOS33 PULLTYPE PULLUP } [get_ports { jtag_trst_n }]; # JD4 (PMOD 4) +set_property -dict { PACKAGE_PIN U24 IOSTANDARD LVCMOS33 } [get_ports { jtag_tdo }]; # JD7 (PMOD 7) diff --git a/hw/top_chip/data/timing_genesys2.xdc b/hw/top_chip/data/timing_genesys2.xdc index 13a3ced4a..06c730812 100644 --- a/hw/top_chip/data/timing_genesys2.xdc +++ b/hw/top_chip/data/timing_genesys2.xdc @@ -26,3 +26,15 @@ set_clock_groups -asynchronous -group [get_clocks eth_rxck_pin -include_generate ## set_false_path -hold \ ## -through [get_pins -hierarchical -filter async] \ ## -through [get_pins -hierarchical -filter async] + +## Debug JTAG Clock (Max 30 MHz) +create_clock -period 33.333 -waveform {0 16.667} -name jtag_tck_pin [get_ports jtag_tck]; + +## Debug JTAG Clock Asynchronous with All Other Clocks +set_clock_groups -asynchronous -group [get_clocks jtag_tck_pin]; + +## JTAG to Mocha CDC Bus Skew Constraints +## min(33.333ns, 20ns) = 20ns +set_max_delay -datapath_only 20 \ + -from [get_pins -hierarchical -regexp .*/i_dmi_cdc/.*/data_wr_q_reg.*/C] \ + -to [get_pins -hierarchical -regexp .*/i_dmi_cdc/.*/data_rd_q_reg.*/D] diff --git a/hw/top_chip/rtl/chip_mocha_genesys2.sv b/hw/top_chip/rtl/chip_mocha_genesys2.sv index 93c4722b0..541ae3106 100644 --- a/hw/top_chip/rtl/chip_mocha_genesys2.sv +++ b/hw/top_chip/rtl/chip_mocha_genesys2.sv @@ -72,7 +72,14 @@ module chip_mocha_genesys2 #( output logic eth_tx_en, output logic [3:0] eth_tx_d, output logic eth_mdc, - inout logic eth_mdio + inout logic eth_mdio, + + // Debug JTAG + input logic jtag_tck, + input logic jtag_tms, + input logic jtag_tdi, + output logic jtag_tdo, + input logic jtag_trst_n ); // Local parameters localparam int unsigned InitialResetCycles = 4; @@ -306,11 +313,11 @@ module chip_mocha_genesys2 #( .ethernet_irq_i (ethernet_irq), // Debug module JTAG tie-off - .dm_jtag_tck (1'b0), - .dm_jtag_tms (1'b0), - .dm_jtag_tdi (1'b0), - .dm_jtag_tdo ( ), - .dm_jtag_trst_n (1'b0) + .dm_jtag_tck (jtag_tck), + .dm_jtag_tms (jtag_tms), + .dm_jtag_tdi (jtag_tdi), + .dm_jtag_tdo (jtag_tdo), + .dm_jtag_trst_n (jtag_trst_n & rst_n_sync_assert_50m) ); // GPIO tri-state output drivers diff --git a/util/debug_test_fpga.sh b/util/debug_test_fpga.sh new file mode 100755 index 000000000..470943ada --- /dev/null +++ b/util/debug_test_fpga.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env -S bash -eux +# Copyright lowRISC contributors (COSMIC project). +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +util/fpga_runner.py run -e build/sw/device/examples/infinite_loop +sleep 5 +openocd -f util/genesys2-openocd-cfg.tcl & +sleep 5 +expect util/gdb_response.exp + +kill -SIGTERM $(jobs -p) diff --git a/util/debug_test.sh b/util/debug_test_verilator.sh similarity index 100% rename from util/debug_test.sh rename to util/debug_test_verilator.sh diff --git a/util/gdb_response.exp b/util/gdb_response.exp index f6b62155b..5d4ed38bc 100755 --- a/util/gdb_response.exp +++ b/util/gdb_response.exp @@ -6,9 +6,9 @@ # On timeout just wait indefinitely. set timeout 20 spawn gdb build/sw/device/examples/infinite_loop -expect_before -i $spawn_id { - timeout { send_error "Error: GDB didn't print the expected response within teh timeout\n"; exit 2 } - eof { send_error "Error: GDB unexpectedly terminated\n"; exit 1} +expect_before { + timeout { send_error "Error: GDB didn't print the expected response within the timeout\n"; exit 2 } + eof { send_error "Error: GDB unexpectedly terminated\n"; exit 1 } } expect "build/sw/device/examples/infinite_loop" # Connect to OpenOCD. diff --git a/util/genesys2-openocd-cfg.tcl b/util/genesys2-openocd-cfg.tcl index 3c2e1efa9..e2f6e7fc6 100644 --- a/util/genesys2-openocd-cfg.tcl +++ b/util/genesys2-openocd-cfg.tcl @@ -3,110 +3,15 @@ # SPDX-License-Identifier: Apache-2.0 # Used to connect OpenOCD to Mocha running on the Genesys2 board. -# To use this configuration you must first disconnect the SPI device and connect up the JTAG pins so this does not work out of the box in Mocha. -# An example diff below: -################################################# -#diff --git a/hw/top_chip/data/pins_genesys2.xdc b/hw/top_chip/data/pins_genesys2.xdc -#index ca742777..aa405125 100644 -#--- a/hw/top_chip/data/pins_genesys2.xdc -#+++ b/hw/top_chip/data/pins_genesys2.xdc -#@@ -49,11 +49,11 @@ set_property -dict { PACKAGE_PIN T26 IOSTANDARD LVCMOS33 PULLTYPE PULLUP } [ge -# set_property -dict { PACKAGE_PIN T27 IOSTANDARD LVCMOS33 PULLTYPE PULLUP } [get_ports { i2c_sda_io }]; -# -# ## SPI Device (PMOD Header JD) -#-set_property -dict { PACKAGE_PIN W28 IOSTANDARD LVCMOS33 PULLTYPE PULLDOWN } [get_ports { spi_device_sd_o }]; -#-set_property -dict { PACKAGE_PIN W27 IOSTANDARD LVCMOS33 PULLTYPE PULLDOWN } [get_ports { spi_device_sd_i }]; -#-set_property -dict { PACKAGE_PIN W29 IOSTANDARD LVCMOS33 PULLTYPE PULLUP } [get_ports { spi_device_csb_i }]; -#-set_property -dict { PACKAGE_PIN AD27 IOSTANDARD LVCMOS33 PULLTYPE PULLDOWN } [get_ports { spi_device_sck_i }]; -#-set_property -dict { PACKAGE_PIN AD29 IOSTANDARD LVCMOS33 } [get_ports { spien }]; -#+set_property -dict { PACKAGE_PIN W28 IOSTANDARD LVCMOS33 } [get_ports { jtag_tdo }]; -#+set_property -dict { PACKAGE_PIN W27 IOSTANDARD LVCMOS33 } [get_ports { jtag_tdi }]; -#+set_property -dict { PACKAGE_PIN W29 IOSTANDARD LVCMOS33 } [get_ports { jtag_tms }]; -#+set_property -dict { PACKAGE_PIN AD27 IOSTANDARD LVCMOS33 } [get_ports { jtag_tck }]; -#+#set_property -dict { PACKAGE_PIN AD29 IOSTANDARD LVCMOS33 } [get_ports { spien }]; -# -# ## Ethernet RGMII -# set_property -dict { PACKAGE_PIN AH24 IOSTANDARD LVCMOS33 } [get_ports { eth_phyrst_n }]; -#diff --git a/hw/top_chip/rtl/chip_mocha_genesys2.sv b/hw/top_chip/rtl/chip_mocha_genesys2.sv -#index 4341266f..101c0b15 100644 -#--- a/hw/top_chip/rtl/chip_mocha_genesys2.sv -#+++ b/hw/top_chip/rtl/chip_mocha_genesys2.sv -#@@ -27,11 +27,11 @@ module chip_mocha_genesys2 #( -# inout logic i2c_sda_io, -# -# // SPI Device -#- input logic spi_device_sck_i, -#- input logic spi_device_csb_i, -#- input logic spi_device_sd_i, -#- output logic spi_device_sd_o, -#- output logic spien, -#+ //input logic spi_device_sck_i, -#+ //input logic spi_device_csb_i, -#+ //input logic spi_device_sd_i, -#+ //output logic spi_device_sd_o, -#+ //output logic spien, -# -# // SPI Host -# output logic spi_host_sck_o, -#@@ -72,7 +72,13 @@ module chip_mocha_genesys2 #( -# output logic eth_tx_en, -# output logic [3:0] eth_tx_d, -# output logic eth_mdc, -#- inout logic eth_mdio -#+ inout logic eth_mdio, -#+ -#+ input logic jtag_tck, -#+ input logic jtag_tms, -#+ input logic jtag_tdi, -#+ output logic jtag_tdo, -#+ input logic jtag_trst -# ); -# // Local parameters -# localparam int unsigned InitialResetCycles = 4; -#@@ -259,11 +265,11 @@ module chip_mocha_genesys2 #( -# .mailbox_ext_irq_o ( ), -# -# // SPI device -#- .spi_device_sck_i (spi_device_sck_i), -#- .spi_device_csb_i (spi_device_csb_i), -#- .spi_device_sd_o (qspi_device_sdo), -#- .spi_device_sd_en_o (qspi_device_sdo_en), -#- .spi_device_sd_i ({3'h0, spi_device_sd_i}), // SPI COPI = QSPI DQ0 -#+ .spi_device_sck_i ('0), -#+ .spi_device_csb_i ('0), -#+ .spi_device_sd_o ( ), -#+ .spi_device_sd_en_o ( ), -#+ .spi_device_sd_i ('0), // SPI COPI = QSPI DQ0 -# .spi_device_tpm_csb_i ('0), -# -# // SPI host -#@@ -291,12 +297,12 @@ module chip_mocha_genesys2 #( -# // Ethernet IRQ -# .ethernet_irq_i (ethernet_irq), -# -#- // Debug module JTAG tie-off -#- .dm_jtag_tck (1'b0), -#- .dm_jtag_tms (1'b0), -#- .dm_jtag_tdi (1'b0), -#- .dm_jtag_tdo ( ), -#- .dm_jtag_trst_n (1'b0) -#+ // Debug module JTAG -#+ .dm_jtag_tck (jtag_tck), -#+ .dm_jtag_tms (jtag_tms), -#+ .dm_jtag_tdi (jtag_tdi), -#+ .dm_jtag_tdo (jtag_tdo), -#+ .dm_jtag_trst_n (rst_n_sync_50m) -# ); -# -# // GPIO tri-state output drivers -################################################# +# This configuration assumes the Olimex ARM-USB-TINY-H adapter is used. adapter driver ftdi transport select jtag -ftdi vid_pid 0x0403 0x6010 +ftdi vid_pid 0x15ba 0x002a ftdi channel 0 ftdi layout_init 0x0018 0x001b +ftdi tdo_sample_edge falling reset_config none