RISC-V External Debug


Hi, all
I want to accessing registers using abstract command,

1.According to the part Debugger Implementation of RISC-V External Debug Support Version 0.13,but I don’t understand what do “S0” and “matatus” mean? They are just register’s name?

2.And I also want to know how can I write a specified value into a specified physical address such as 0x8000_0000, But I look at the “S0” use the GPRs whose value is 0x1008,and the “mstatus” is 0x300? Why mstatus ‘s GPRs is 0x300, It already exceed the GPRs’ range.

3.And I also have a question that why the bit of write is 0 when read “S0” using abstract command, it means that Copy data from the register specied by regno into the arg0 region of data, if write is clearand transfer is set. What dose “arg0 region of data” means? How can I read a specifed address such as 0x8000_0004 by using Abstract command by JTAG simulation. What should I pass the address such as 0x8000_0004 into DM?

That’s all .Sincerely waiting for your reply.

(Megan A. Wachs) #2
  1. s0 and mstatus are RISC-V Registers. s0 is a GPR and mstatus is a CSR. You can find out more about them by reading the RISC-V ISA Specifications (https://riscv.org/specifications/)

  2. mstatus is not a GPR, it is a CSR. See Table 3.3 “Abstract Register Numbers”. 0x300 is in the range for CSRs.

  3. To understand “arg0 region of data”, please see Table 3.2, “Use of Data Registers”.

It is not possible to read/write arbitrary memory locations with Abstract Commands only. You must use the Program Buffer or the System Bus Access block.

(Megan A. Wachs) #3

Also, since your question was specifically about the E31 Coreplex, a few things to note for that specific implementation of the spec:

  • Only GPR Abstract Commands are supported. To access a CSR, you need to use Program Buffer
  • There is no System Bus Access Block, so you must use the Progam Buffer to access memory.


1.Thanks, but I don’t understand what does "lw s1, 0(s0)" mean ? Is it not a value? what is the value in JTAG Debug Module Interface Accessing? why is it a Assembler command? And I also want to know what does “ebreak” mean?

2.And I also have a question that why don’t leave “write progbuf0" and "write progbuf1 ebreak " behind? What operations does it actually represent? I think that they should place in the end.

3.why is "sw 0(s0) ,s1" in “write a word to memory using program buffer”,but ""sw s1,0(s0)" in “write block of memory using program buffer”, Are there some error?

(Megan A. Wachs) #5
  1. lw s1 0(s0) is a RISC-V assembly instruction. You can understand what it means and its exact value by reading about the lw instruction in the RISC-V ISA Manual. ebreak instruction is also a RISC-V instruction. You can determine the actual numerical value that is written by understanding RISC-V opcode encoding. It will be very difficult to understand the Debug Spec if you do not first read and understand the RISC-V ISA manuals.

  2. I don’t really understand your second question. What is written to the program buffer is like a little mini program. ebreak marks the end of the program. You could write data0 before writing to progbuf, it does not matter, all those values can be written in any order as long as the are written before command.

  3. To write a block of memory, the mini program is different. It is optimized to increment the address and work every time data0 register is written. So the registers are used differently. Probably it is fine to swap them around as well, as long as the appropriate command is written.


Thank you very much!But in the question three.I just want ask the sequence of “0(s0)” and “s1”. Is “s0” a sources?Is “s1” destination?why “s0” has a offset “0” .

(Megan A. Wachs) #7

Oh, I see. Yes, the first example sw 0(s0), s1 is written in a non-standard way for RISC-V. We will correct it, thanks for pointing it out.


And I want to know how many bits the “abits” of the address of Debug Module Interface Accessing.Are there 7 bits of address ?abits+data+op=41bits?


I am simulating the Debug Module of E31 Coreplex by using JTAG.According to your suggestion,then I use the “program buffer” to try to write and read a value into arbitrarily address of the memory. First,I sent the JTAG instruction “0x11” for access DMI.Then I select the DR-scan,set “address+value+op(41bits?)” and shift it ,and then it execute the commands in the following order

But I can’t read the value what I have writen. I read the RISC-V ISA manuals find that “sw s0 0(s1)” 's value for 32 bits is as follow

On my opinion ,
“imm[11:5] and imm[4:0]” is 0
"funct3" is “010”,
“opcode” is “0100011”,
“rs2” is “s0” and the value of “s0” is “01000”.Is it right?
“rs1” is “s1” and the value of “s1” is “01001”.is it right?
if not ,and I really don’t know what the value is.
But if I use gcc to disassembly “sw s0 0(s1)”, I can recieve a value 0xc080 which are 16bits.why? I have known that RISC-V support the variable instruction. but JTAG needs 32 bits value as follow

That’s all .Sincerely waiting for your reply.

(Drew) #10

I placed the opcodes here:

When compiling it is always good practice to explicitly set the -march and -mabi fields explicitly. It looks like you were disassembling the Compressed instruction which doesn’t seem to be what you are after. This can be avoided by explicitly setting -march=rv32i.