GNU tools for ARC-V¶
The GNU toolchain for ARC-V processors is a pre-built and verified distribution of a GCC-based set of tools for building applications targeting supported ARC-V processors.
This toolchain is built on the pillars of proven and widely used open-source components such as GCC, Binutils, GDB, and Newlib. While many pre-built GCC-based toolchains are available around the Internet, and it is reasonably easy to build your own, the ARC GNU toolchain is prepared specifically to produce the best possible results for ARC processors. It also makes sure the results produced are reliable in all supported environments.
GNU Toolchain for ARC-V Processors v2023.12¶
This is the 2023.12 version of the GNU Toolchain for Synopsys ARC-V Processor IP. This release introduces support for the ARC-V RMX and RHX processors series based on the RISC-V instruction-set architecture.
More information about these processors can be found on Synopsys website:
Note
This release of the ARC GNU tools doesn’t include prebuilt toolchains for ARC Classic processor families. Users of ARC 600, ARC 700, ARC EM, ARCv2 HS (HS3x and HS4x) and ARCv3 HS (HS5x and HS6x) should keep using ARC GNU Tools 2023.09 (latest version).
New Features and Enhancements¶
Support for RISC-V based ARC-V RMX and RHX Processors¶
In this release the following RISC-V extensions are supported:
Zba
,Zbb
,Zbs
,Zdinx
,Zfinx
,Zicbom
,Zicbop
, andZicboz
.Support for ARC-V RMX and RHX processors:
Instruction scheduling tuning for ARC-V RMX-100 (
-mtune=rmx100
) and RMX-500 (-mtune=rmx500
)Instruction fusion for the ARC-V RHX series (
-mtune=rhx
)Implementation of the code-size reduction extensions
Zcb
andZcmp
As this is the first release of prebuilt GNU tools with ARC-V support, some functionality might have issues, some processor features might not yet be fully supported, and performance might be lower than expected performance of the final product.
Binary Distribution¶
Supported host operating systems: Windows 10/11 64-bit, Ubuntu 18.04.x, 20.04.x, CentOS/RHEL 7.x
Prebuilt bare-metal toolchains for 64-bit Windows & Linux hosts; see table with references and list of artifacts.
Toolchain Components¶
GCC 13.2 with ARC patches
Uses upstream 13.2 release; see GCC release announcement and complete list of changes.
Added support for ARC-V RMX-100, RMX-500, and RHX processors.
Added code size reduction
Zcb
andZcmp
extensions.
Binutils pre-2.41 with ARC patches
Upstream sources of pre-v2.41; see Binutils release announcement.
Added code size reduction
Zcb
andZcmp
extensions.
GDB 12.1 with ARC patches
Upstream sources of v12.1; see GDB release announcement.
Newlib 4.3.0 with ARC patches
Updated sources of 4.3.0 release; see Newlib release announcement.
Improved start-up code to initialize GP (global pointer), SP (stack pointer), clear
.bss
section, and similar enhancements.Provided custom linker command file for use with fast on-chip memories (DCCM and ICCM).
Known Issues¶
There are no known issues for this release so far.
Getting Help¶
A Getting Started manual covering all aspects of the ARC-V family of processors is available here: https://foss-for-synopsys-dwc-arc-processors.github.io/arc-v-getting-started.
Also visit the GitHub discussions link for a community forum tailored to ARC-V processors. To report issues and enhancement requests, use GitHub issues (if you are not sure, start with discussions, since a discussion can always be converted into an issue).
Prebuilt Toolchains Available for Download¶
Archive SHA-256 checksums are:
4e555c1b214eb97fd3bf9e1ffa43d69a0d274deb295fec66bdfdebef714b7bf7 arc_gnu_2023.12_prebuilt_riscv64_elf_le_win_install.tar.bz2
9dedb6e496e52a45ce536c9a1970a44401319c42ea17b7b8f6655b6204b9b444 arc_gnu_2023.12_prebuilt_riscv64_elf_le_linux_install.tar.bz2
Command-Line Reference¶
Because the ARC-V GNU toolchain is built on top of standard components such as GCC, Binutils, and GDB, all functionality of these tools stays in place and can be studied in detail in the corresponding manuals:
GCC documentation: https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gcc/
GNU LD documentation: https://sourceware.org/binutils/docs/ld/
GDB documentation: https://www.sourceware.org/gdb/documentation/
On top of the functionality that comes with the standard releases of these tools, the ARC GNU toolchain adds some ARC-V specific options:
The ARC-V GNU compiler has support for the ARC-V RMX-100, RMX-500, and RHX CPU families.
To enable compiler optimizations for those CPU families you must use certain
-mtune
options. The valid -mtune
options are:
rmx100
for the ARC-V RMX-100 familyrmx500
for the ARC-V RMX-500 familyrhx
for the ARC-V RHX family
The architecture options used by the ARC-V RMX-100, RMX-500 and RHX families are -march=rv32im_zba_zbb_zbs_zicsr_zca_zcb_zcmp -mabi=ilp32
.
ARC-V .specs File¶
The new arcv.specs
file uses a custom starting routine based on the original crt0.S
with a special linker command file.
The latter is highly configurable, introducing four new linker defines:
txtmem_addr
if defined sets the ICCM start address; otherwise the ICCM start address is set to0x0
txtmem_len
if defined sets the ICCM length; otherwise the length is set to128K
datamem_addr
if defined sets the DCCM start address; otherwise the DCCM start address is set to0x8000_0000
datamem_len
if defined sets the DCCM length, otherwise the length is set to128K
Where:
ICCM is usually flash memory or ROM.
DCCM is usually SRAM.
You can set a linker define as follows (using the GCC driver): For example:
-Wl,-defsym=datamem_addr=0x10000
This spec file can be used with other spec files too.
For example, using semihosting: --specs=semihost.specs --specs=arcv.specs
.
The First Sample Application¶
Consider the following sample application:
#include <stdio.h>
extern void init_semihosting ();
int main(void) {
init_semihosting();
printf("Hello world!\n");
return 0;
}
Build and Run a Simple Application for Synopsys nSIM¶
The following commands can be used for compiling the sample for later execution in the nSIM simulator:
For an ARC-V RMX-100 processor:
$ riscv64-elf-gcc --specs=semihost.specs --specs=arcv.specs -mabi=ilp32 \ -mtune=rmx100 -march=rv32im_zba_zbb_zbs_zca_zcb_zcmp_zicsr \ -T arcv.ld test.c -o a.out
For an ARC-V RMX-500 processor:
$ riscv64-elf-gcc --specs=semihost.specs --specs=arcv.specs -mabi=ilp32 \ -mtune=rmx500 -march=rv32im_zba_zbb_zbs_zca_zcb_zcmp_zicsr \ -T arcv.ld test.c -o a.out
For an ARC-V RHX processors:
$ riscv64-elf-gcc --specs=semihost.specs --specs=arcv.specs -mabi=ilp32 \ -mtune=rhx -march=rv32im_zba_zbb_zbs_zca_zcb_zcmp_zicsr \ -T arcv.ld test.c -o a.out
After building, use the following command line to run the sample in nSIM:
$ nsimdrv -prop=nsim_isa_family=rv32 \
-prop=nsim_isa_ext=-all.i.zicsr.zifencei.zihintpause.b.zca.zcb.zcmp.zcmt.a.m.zbb \
-prop=nsim_semihosting=1 -off=enable_exceptions a.out
Hello world!
For more details on use of the Synopsys nSIM simulator, see the section dedicated to it here: nSIM and NCAM.
Build and Run a Simple Application for QEMU¶
It is best to use the latest official QEMU version for the following exercises. As of today, it’s v8.2; see release notes here https://wiki.qemu.org/ChangeLog/8.2. The sources are on GitLab (https://gitlab.com/qemu-project/qemu) or in the official GitHub mirror (https://github.com/qemu/qemu).
Note
To get the latest version of QEMU on your system it might be much easier to build it from sources rather than trying to find a pre-built version which suits your host type and operating system.
Instructions for building on Linux are on QEMU’s Wiki: https://github.com/qemu/qemu
First you need to install required additional packages, which depend on the Linux distribution used on the host. For example for Ubuntu 20.04 the following needs to be done:
$ apt-get install build-essential git libglib2.0-dev libfdt-dev \
libpixman-1-dev zlib1g-dev ninja-build python3-venv
After installation of prerequisites you can download sources, configure, and build in the following way:
# Clone v8.2.0 from GitHub repository
$ git clone --depth 1 --branch v8.2.0 git@github.com:qemu/qemu.git
# Configure project for build selecting only RISCV32 full system emulation,
$ ./configure --target-list=riscv32-softmmu
# Build QEMU
$ make
After the build is complete qemu-system-riscv32
is placed in the build
folder,
which you can add to the PATH
environment variable for convenience, and use the short binary name
instead of the full path.
The following commands can be used for compiling the sample for later execution in QEMU.
Basically the same compiler options are used, except that you need to make sure
DDR memory is used and the .text
section starts in the DDR beginning at 0x8000_0000, where
the board jumps on start automatically. For that, you need to override two linker symbols otherwise defined in
ARC-V’s default linker script arcv.ld
: txtmem_addr
and datamem_addr
.
Then the command lines look like this:
For an ARC-V RMX-100 processor:
$ riscv64-elf-gcc --specs=semihost.specs --specs=arcv.specs -mabi=ilp32 \ -mtune=rmx100 -march=rv32im_zba_zbb_zbs_zca_zcb_zcmp_zicsr \ -Wl,-defsym=txtmem_addr=0x80000000 -Wl,-defsym=datamem_addr=0x80100000 \ -T arcv.ld test.c -o a.out
For an ARC-V RMX-500 processor:
$ riscv64-elf-gcc --specs=semihost.specs --specs=arcv.specs -mabi=ilp32 \ -mtune=rmx500 -march=rv32im_zba_zbb_zbs_zca_zcb_zcmp_zicsr \ -Wl,-defsym=txtmem_addr=0x80000000 -Wl,-defsym=datamem_addr=0x80100000 \ -T arcv.ld test.c -o a.out
For an ARC-V RHX processor:
$ riscv64-elf-gcc --specs=semihost.specs --specs=arcv.specs -mabi=ilp32 \ -mtune=rhx -march=rv32im_zba_zbb_zbs_zca_zcb_zcmp_zicsr \ -Wl,-defsym=txtmem_addr=0x80000000 -Wl,-defsym=datamem_addr=0x80100000 \ -T arcv.ld test.c -o a.out
After building, use the following command line to run the sample in QEMU:
$ qemu-system-riscv32 -semihosting -nographic -machine virt -cpu rv32 -bios none -kernel a.out
Hello world!
For more details on use of the QEMU simulator, see the official documentation here: https://www.qemu.org/docs/master/.
Debugging a Simple Application¶
With the Synopsys LLDB Debugger and Visual Studio Code IDE¶
For detailed information on how to debug an application with the Synopsys LLDB Debugger and Visual Studio Code IDE, see the following section: The MetaWare Development Toolkit.
With QEMU and GDB¶
You can debug an application that is being run on QEMU with help of the built-in GDB server of QEMU. On the QEMU side, you need to enable the GDB sever and optionally instruct the QEMU not to start the application execution automatically, but instead wait for user input. For that you need to pass -s -S
commands to qemu-system-riscv32 so that the full command-line looks like this:
$ qemu-system-riscv32 -semihosting -nographic -machine virt -cpu rv32 -bios none -kernel a.out -s -S
Then you can attach the GDB client and start debugging. Do the following in a separate console:
$ riscv64-elf-gdb a.out
(gdb) target remote :1234
Remote debugging using :1234
0x00001000 in ?? ()
(gdb) b main
Breakpoint 1 at 0x800000b4: file ~/test.c, line 10.
(gdb) continue
Continuing.
Breakpoint 1, main () at ~/test.c:10
10 init_semihosting();
(gdb) c
Continuing.
[Inferior 1 (process 1) exited normally]
Note that the first location where the CPU is waiting for commands is 0x0000_1000. It’s a virt board reset vector location; see https://elixir.bootlin.com/qemu/v8.2.0/source/hw/riscv/boot.c#L396. It is not possible to suppress execution of that reset vector code as it’s an essential part of the QEMU board (think of it as a boot-ROM). You can only bypass it if you load the target executable from the GDB client with the load
command. Then execution starts from the loaded application entry point.
Testing Specific RISC-V Extensions¶
One of the benefits of RISC-V ISA is its extensibility. As a matter of fact, only a handful of instructions form the minimally required base. But the most interesting part is in utilizing application-specific extensions, which let you achieve benefits in certain situations.
In embedded and especially deeply embedded applications, one of the key objectives is to keep the memory footprint of the target application as tiny as possible. And the RISC-V Zc* extensions help to achieve exactly that. This section demonstrates a couple of those extensions in action. See also the documentation and related information on each extension on the corresponding GitHub resource here: https://github.com/riscv/riscv-code-size-reduction.
Zcmp Extension¶
Consider the following code snippet:
$ cat t01.c
void test (void) {
asm volatile (""
:
:
: "s0", "s1", "s2", "s3",
"s4", "s5", "s6", "s7",
"s8", "s9", "s10", "s11");
}
Here is a generated assembly listing targeting the Zcmp extension:
$ riscv64-unknown-elf-gcc -march=rv32im_zcmp -mabi=ilp32 t01.c -S -O1 -o -
.file "t01.c"
.option nopic
.attribute arch, "rv32i2p1_m2p0_zca1p0_zcmp1p0"
.attribute unaligned_access, 0
.attribute stack_align, 16
.text
.align 1
.globl test
.type test, @function
test:
cm.push {ra, s0-s11}, -64
cm.popret {ra, s0-s11}, 64
.size test, .-test
.ident "GCC: (RISC-V elf toolchain - build 6278) 13.2.0"
Note the generated cm.push
and cm.popret
instructions, which confirm that the compiler is capable of using the extension.
Zcb Extension¶
Another RISC-V extension that is easy to see in action also comes from the code-size-reduction group: Zcb. Consider the following C function:
$ cat t03.c
int test (int a, int b) {
return a + b;
}
Now compile and disassemble it:
$ riscv64-elf-gcc -march=rv32im_zca_zcb -mabi=ilp32 t03.c -c -O1
$ riscv64-unknown-elf-objdump -d t03.o
t03.o: file format elf32-littleriscv
Disassembly of section .text:
00000000 <test>:
0: 952e add a0,a0,a1
2: 8082 ret
Note the short 16-bit encoding of the add
instruction. Without use of Zc extensions, compiler generates a full 32-bit encoding as in the example below.
$ riscv64-elf-gcc -march=rv32im -mabi=ilp32 t03.c -c -O1
$ riscv64-unknown-elf-objdump -d t03.o
t03.o: file format elf32-littleriscv
Disassembly of section .text:
00000000 <test>:
0: 00b50533 add a0,a0,a1
4: 00008067 ret