[Open SoC Debug] CDM-OR1K implementation

Stafford Horne shorne at gmail.com
Wed May 23 23:11:15 CEST 2018


On Wed, May 23, 2018 at 02:06:57PM +0530, SHIVAM AGGARWAL wrote:
> Hi all,
> 
> I spend last two days reading about GDB and its architecture.
> 
> As a program that works directly with the instructions of the target CPU,
> GDB needs in-depth knowledge about the details of the CPU core. GDB needs
> information of all registers (SPRs and GPRs) within the target system CPU;

GDB Only really needs information about the GPRs:
  See: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=blob;f=gdb/features/or1k-core.xml;h=6fe9765150575464bf11a9752e3c3276ff4ab8fa;hb=HEAD

This is the base register map that GCC needs.

For openOCD there are more provided which we can see here:
  http://repo.or.cz/openocd.git/blob/HEAD:/src/target/openrisc/or1k.c#l53

The register maps are transferred from the debug server to GDB via an xml file.

> this allows it to read or write CPU registers by address. It also needs to
> know about all the the sizes of the different kinds of data, the size and
> shape of the address space, how the calling convention works, what
> instruction will cause a trap exception, and so on.

Yes, GDB has that all defined within it.  It doesnt need to be provided by OSD.

> To sum up, CDM-OR1K must provides access to each register in the CPU core
> as a OSD specific register.
> 
> All SPRs in mor1kx are listed in this verilog code:
> https://github.com/openrisc/mor1kx/blob/master/rtl/verilog/mor1kx-sprs.v
> 
> 
>    1.
> 
>    *Register map for SPRs and GPRs in CDM-OR1K*:
> 
> We can easily map 32-bit wide 32 GPRs as two 16-bit OSD specific registers
> in the module. We already have access to the debug unit for setting
> watchpoints/breakpoints.

*We already have access to the debug unit for reading/setting all registers.

> In GDB, there are commands like ‘info spr’ used to show the value of a SPR
> or group of SPRs and ‘spr’ to set the value of an individual SPR. There are
> about 12 groups (permitted upto 32) with some groups (1, 2 and 3) having
> 1000+ SPRs.

That list is provided by OpenOCD, or the features XML of the target server not
by the debug hardware. See my links above.

*Option 1*
> We can assign address spaces 0x0200-0xffff (about 65023 registers) as
> module specific registers in CDM-OR1K. The space is enough to map each or1k
> register into OSD address space.

Any mapping makes it specific to a processor this is not needed.

*Option 2*
> *Alternate solution*: Can we have certain dedicated read/write registers in
> the module?
> 
> i.e instead of mapping each and every register, each time GDB asks for a
> specific SPR read/write, we can store its address in one of OSD register
> and data in two other registers. This information can be translated over
> system interface signals to the CPU core. But, for commands like ‘info
> spr’, we might need to store such information for all the SPRs.

This sounds better.  Have you seen how it is done in Adv_debug_if?

  - OpenOCD driver:
    http://repo.or.cz/openocd.git/blob/HEAD:/src/target/openrisc/or1k_du_adv.c#l498
    Burst read/write for registers is always 4 bytes.

  - Adv Debug IF:
    https://github.com/freecores/adv_debug_sys/blob/master/Hardware/adv_dbg_if/doc/AdvancedDebugInterface.pdf
    RTL: https://github.com/freecores/adv_debug_sys/blob/master/Hardware/adv_dbg_if/rtl/verilog/adbg_or1k_module.v
    (I think I asked you to look at this before)

    Commands
      0x0 - NOP
      0x3 - cpu register burst setup write
      0x7 - cpu register burst setup read
      0x9 - module internal register write
      0xd - module internal register select

    cpu register burst read/write
      [ 0 |  Opcode (0x3/0x7) | Address  | Count ]

      Here Address is the CPU Register Address

    Read/Write are then not send with opcodes, just data
      Burst write
      [ match | crc | status | Data | Start ]

      Burst read
      [ CRC  |  Data | Status ]

     Here Data is the register data

    Status register Select (There is only a single 2-bit internal register)
      [ 0    |  Opcode (0xd) | Index 0 ]

      Status Register Read
      (Send nop command)

      Status Register Write
      [ 0 | Opcode (0x9) | Index (0x0) | Data (2-bits) ]

      Status Register contents 2 bits.
      [ Reset | Stall ]

So in summary, there are 2 parts here
  - Reading/Writing registers looks exactly like memory.  All registers are all
    in the same address space. (Actually in OpenRISC the GPRS can also be
    accessed via SPR space, that is what is done here)
  - Reading/Writing the status bit to Stall or Reset the processor or just get
    the stall status.

Note adv_debug_if support burst mode to get around having to send an address and
data command for each read/write.  We could think about a burst interface, but
currently the software side (OpenOCD) does not use that.

Also Note, the interface has nothing OpenRISC specific.  It doesnt really even
mention OpenRISC in the spec. It says:

  "
  The CPU interface is designed to connect to an OR1200 processor, or any
  other CPU which uses the same debug ports.
  "

Next Steps
 - Read OpenOCD code
 - Read openrisc target code for GDB (optional)
 - Adapt the ideas in the adv debug interface to the OSD CDM spec.

-Stafford


More information about the OpenSoCDebug mailing list