Which toolchain

There is a toolchain in riscv.org Git release. Freedom SDK includes another toolchain.

Which one should be used for E3000 platform?



For developing against the E300 platform, you should always use the version included in the Freedom E SDK.


Does it support RISC-V compressed extension, RVC?


I just ordered the Hifive, and started to play with the software. A little experimentation shows that you can add…


… to the CFLAGS in your Makefile.

Some output:

demo_gpio.o:     file format elf32-littleriscv

Disassembly of section .text:

00000000 <no_interrupt_handler>:
   0:   1141                    addi    sp,sp,-16
   2:   c622                    sw      s0,12(sp)
   4:   0800                    addi    s0,sp,16

00000006 <.LM2>:
   6:   0001                    nop
   8:   4432                    lw      s0,12(sp)
   a:   0141                    addi    sp,sp,16
   c:   8082                    ret

0000000e <handle_m_ext_interrupt>:
   e:   1101                    addi    sp,sp,-32
  10:   ce06                    sw      ra,28(sp)
  12:   cc22                    sw      s0,24(sp)
  14:   1000                    addi    s0,sp,32

00000016 <.LM4>:
  16:   000007b7                lui     a5,0x0
  1a:   00078513                mv      a0,a5
  1e:   00000317                auipc   t1,0x0
  22:   000300e7                jalr    t1
  26:   fea42623                sw      a0,-20(s0)

0000002a <.LM5>:
  2a:   fec42783                lw      a5,-20(s0)
  2e:   cb9d                    beqz    a5,64 <.L3>

00000030 <.LM6>:
  30:   fec42703                lw      a4,-20(s0)
  34:   47a1                    li      a5,8
  36:   02e7e763                bltu    a5,a4,64 <.L3>

0000003a <.LM7>:
  3a:   000007b7                lui     a5,0x0
  3e:   fec42703                lw      a4,-20(s0)
  42:   070a                    slli    a4,a4,0x2
  44:   00078793                mv      a5,a5
  48:   97ba                    add     a5,a5,a4
  4a:   439c                    lw      a5,0(a5)
  4c:   9782                    jalr    a5

Nice. Will try it later.


Yes, the FE310 supports the C extension.

Just be aware that GDB doesn’t yet support misaligned breakpoints. So if you’re trying to debug your ‘C’ code, you may have to get creative on where you place them :slight_smile:

I notice that in .o files from gcc -march=RV32IC there are many longer than necessary instructions, such as branches, and even completely unnecessary instructions such as auipc with #0. Looking at the final executable, many of those have been cleaned up, but not all.

Presumably the linker has done this?

for example, in .o

00000000 <fib>:
   0:	4785                	li	a5,1
   2:	02a7d863          	ble	a0,a5,32 <.L8>
   6:	1141                	addi	sp,sp,-16
   8:	c606                	sw	ra,12(sp)
   a:	c422                	sw	s0,8(sp)
   c:	c226                	sw	s1,4(sp)
   e:	842a                	mv	s0,a0
  10:	1579                	addi	a0,a0,-2
  12:	00000317          	auipc	t1,0x0
  16:	000300e7          	jalr	t1
  1a:	84aa                	mv	s1,a0
  1c:	fff40513          	addi	a0,s0,-1
  20:	00000317          	auipc	t1,0x0
  24:	000300e7          	jalr	t1
  28:	9526                	add	a0,a0,s1
  2a:	40b2                	lw	ra,12(sp)
  2c:	4422                	lw	s0,8(sp)
  2e:	4492                	lw	s1,4(sp)
  30:	0141                	addi	sp,sp,16

00000032 <.L8>:
  32:	8082                	ret

And then in executable:

00010164 <fib>:
   10164:       4785                    li      a5,1
   10166:       02a7d263                ble     a0,a5,1018a <fib+0x26>
   1016a:       1141                    addi    sp,sp,-16
   1016c:       c606                    sw      ra,12(sp)
   1016e:       c422                    sw      s0,8(sp)
   10170:       c226                    sw      s1,4(sp)
   10172:       842a                    mv      s0,a0
   10174:       1579                    addi    a0,a0,-2
   10176:       37fd                    jal     10164 <fib>
   10178:       84aa                    mv      s1,a0
   1017a:       fff40513                addi    a0,s0,-1
   1017e:       37dd                    jal     10164 <fib>
   10180:       9526                    add     a0,a0,s1
   10182:       40b2                    lw      ra,12(sp)
   10184:       4422                    lw      s0,8(sp)
   10186:       4492                    lw      s1,4(sp)
   10188:       0141                    addi    sp,sp,16
   1018a:       8082                    ret

Also, the documentation (User-Level ISA specification) says that millicode routines are used for saving and restoring registers when -Os is used with the standard toolchain, but I haven’t been able to trigger this.

Also, a complete example without any handwaving of how to build and run (on an emulator) HelloWorld would be useful.

Is there no install package for a Debian/Ubuntu x86-64 qemu-riscv (-user) somewhere? Everyone having to build their own seems a bit daft. I tried the docker image sorear/fedora-riscv-wip but when I copy a binary into it (which took some googling to find out how to do that – EXPLICIT INSTRUCTIONS PLEASE) I get

[root@84eef74525b3 ~]# qemu-riscv64 fib_rv
fib_rv: Invalid ELF image for this architecture

$ file fib_rv
fib_rv: ELF 32-bit LSB executable, UCB RISC-V, version 1 (SYSV), statically linked, not stripped

Does qemu-riscv64 only execute 64 bit binaries? But 32 bit is a strict subset…

Soooo confused.

One last question for now: if I hand write some assembler, is there a syntax to specify that I want a compressed instruction, or it’s just automatic when it’s possible?

You can write RVC code directly if you want, but the assembler always compresses instructions when possible, so usually there’s little point in doing so.

Branches aren’t relaxed until link time, which is why they show up as 4 bytes long in the .o files.

So I’ve just found a show-stopper, at least until my hardware (HiFive1, not the FPGA board) arrives: qemu doesn’t support RVC! That explains why I was having trouble running it.

Looking at the code, it’s probably no more than a couple of day’s work to implement RVC crudely by:

  1. stop branches checking for 4 byte alignment

  2. making sure unaligned reads of 4 bytes to fetch instructions work

  3. if the bottom two bits of the just fetched 4 byte instruction are not 11
    then back up the PC by 2 bytes before the next fetch.

  4. decode the 2 byte instruction to the equivalent 4 byte one, and substitute it for the four bytes you read from memory.

  5. generate host code as normal

It won’t be all that fast, but as it’s a JIT I don’t think it would be critical. The only problem I see is if there is a 16 bit instruction in the last two bytes of a memory page and the next page is not readable. I don’t know if real hardware allows that situation.

However, I don’t have that couple of days right now…

Thanks for creating the associated issue on the riscv-qemu repository.

Part 3 of that proposal seems like a potential pitfall. If the RVC instruction generates an exception, will EPC be set correctly? I’d look into how qemu’s Thumb2 (or even x86) port handles variable-length instructions, and follow their lead. Hopefully, the riscv-qemu maintainers can assist with this process.

In the mean time, Spike can interpret RVC code.

Yeah, I have no idea at all how the internals of qemu work to map generated x86 code back to the corresponding emulated opcode, or if explicit code is generated to check for exceptions, or what. I’ve never looked into the qemu code.

Where do you find spike?

$ find . -name \*spike\*
$ cat riscv-gnu-toolchain/scripts/spike.exp 
load_generic_config "sim"
set_board_info sim "spike pk"
set_board_info compiler "[find_gcc]"
set_board_info ldflags "-static -pthread"
set_board_info gdb,nosignals 1
set_board_info is_simulator 1

That doesn’t seem terribly helpful.

Spike isn’t part of the riscv-gnu-toolchain. You can get it by installing the full riscv-tools suite: https://github.com/riscv/riscv-tools

It’s the riscv-isa-sim submodule, but you need several other things so you may want to install the full suite.