ESP32 Vector Registers Debugging Issue
Posted: Thu Apr 10, 2025 10:58 pm
Hi ESP team,
I have been trying to develop some DSP code on an ESP32S3 device, using the TIE vector extensions.
While developing the code I am using the built in USB-JTAG device on the device, in combination with OpenOCD and GDB from the IDF framework. Mostly, this works well--I can run and step through code, and inspect the contents of registers.
However, the issue I am facing is that I cannot seem to inspect the vector registers, q0-q7 from the debugger. They always appear to contain 0, even when I know I have data loaded into them.
To demonstrate this I have attached a simple example project that contains a single assembly function, test_tie. This contains three assembly instructions:
The first clears the ACCX accumulator. This is not really necessary to show the issue, but it does trigger the lazy context saving interrupt before the instructions that do show the issue, so single stepping works afterwards.
The second loads 128 bits of data into q0, from a buffer that has been initialised with known values. The third saves the 128 bits of q0 back to a different buffer in memory.
After the second instruction has executed, I would expect to be able to inspect the contents of q0 using the GDB command:
But this always prints the value 0.
To demonstrate this, start OpenOCD:
and the debugger, using the supplied debugging script:
Breakpoints have already been placed at the second and third assembly instructions.
Run the code, this will stop before the second assembly instruction (just before the 128 bits are loaded into q0).
At this point it is possible to inspect the memory pointed to by a2 (the pointer to the initialised input buffer) and a3 (the pointer to the empty output buffer). q0 also shows as containing 0 at this point, as expected:

The next instruction is:
I expect this to load 128 bits from the memory pointed to by a2 (i.e. the start of the input buffer) into q0, then increment a2 by 16.
Stepping this instruction, and then examining the contents of q0 suggests that q0 still contains zero:

This is unexpected. I expected each lane of the q0 vector register to contain one of the 16 bit values from the input buffer.
The next instruction writes the vector register back to memory in the first 128 bits of the output buffer:
Stepping this instruction and examining the output buffer shows that indeed the expected data is written to the output buffer:

This tells me that the code and hardware are working as expected: 128 bits of data are copied from the input buffer, through q0 and out to the output buffer. However, it does tell me that the debugger is not correctly reading the contents of the vector registers.
Interestingly, q0 and q1 are always reported as containing 0 by the debugger, but q2-q7 are always reported as containing the same fixed 128-bit string:

Also interestingly, asking GDB to show the registers with
does not show the q0-q7 registers at all.
Looking at shows that the q0-q7 registers are listed in the debugger definition file.
Is there something missing or not implemented with the TIE instruction set and the debugger?
I'm trying to write some DSP code with the ESP32-S3 and it is going to be extremely difficult to do so if I can't inspect the contents of the registers.
For reference, I am using IDF v5.4.
Thank you.
I have been trying to develop some DSP code on an ESP32S3 device, using the TIE vector extensions.
While developing the code I am using the built in USB-JTAG device on the device, in combination with OpenOCD and GDB from the IDF framework. Mostly, this works well--I can run and step through code, and inspect the contents of registers.
However, the issue I am facing is that I cannot seem to inspect the vector registers, q0-q7 from the debugger. They always appear to contain 0, even when I know I have data loaded into them.
To demonstrate this I have attached a simple example project that contains a single assembly function, test_tie. This contains three assembly instructions:
Code: Select all
// Clear accumulator. Not really used in this example but it is the first
// TIE instruction that is used in this application so it triggers the
// lazy context switch early so single-stepping instructions afterwards is
// easier
ee.zero.accx
// Should load 128 bits -> Q0 from pIn, then increments pIn
ee.vld.128.ip q0, a2, 16
// Should write 128 bits -> pOut from Q0, then increment pOut
ee.vst.128.ip q0, a3, 16
The second loads 128 bits of data into q0, from a buffer that has been initialised with known values. The third saves the 128 bits of q0 back to a different buffer in memory.
After the second instruction has executed, I would expect to be able to inspect the contents of q0 using the GDB command:
Code: Select all
(gdb) p $q0
$1 = 0
To demonstrate this, start OpenOCD:
Code: Select all
. $HOME/esp/esp-idf/export.sh
openocd -f board/esp32s3-builtin.cfg
Code: Select all
. $HOME/esp/esp-idf/export.sh
xtensa-esp32s3-elf-gdb -x debug.gdb
Run the code, this will stop before the second assembly instruction (just before the 128 bits are loaded into q0).
At this point it is possible to inspect the memory pointed to by a2 (the pointer to the initialised input buffer) and a3 (the pointer to the empty output buffer). q0 also shows as containing 0 at this point, as expected:

The next instruction is:
Code: Select all
ee.vld.128.ip q0, a2, 16
Stepping this instruction, and then examining the contents of q0 suggests that q0 still contains zero:

This is unexpected. I expected each lane of the q0 vector register to contain one of the 16 bit values from the input buffer.
The next instruction writes the vector register back to memory in the first 128 bits of the output buffer:
Code: Select all
ee.vst.128.ip q0, a3, 16

This tells me that the code and hardware are working as expected: 128 bits of data are copied from the input buffer, through q0 and out to the output buffer. However, it does tell me that the debugger is not correctly reading the contents of the vector registers.
Interestingly, q0 and q1 are always reported as containing 0 by the debugger, but q2-q7 are always reported as containing the same fixed 128-bit string:

Also interestingly, asking GDB to show the registers with
Code: Select all
(gdb) info registers
Looking at
Code: Select all
~/.espressif/tools/openocd-esp32/v0.12.0-esp32-20241016/openocd-esp32/share/openocd/scripts/target/xtensa-core-esp32s3.cfgIs there something missing or not implemented with the TIE instruction set and the debugger?
I'm trying to write some DSP code with the ESP32-S3 and it is going to be extremely difficult to do so if I can't inspect the contents of the registers.
For reference, I am using IDF v5.4.
Thank you.