Writing and building software for ACC
The ACC (Asymmetric Cryptography Coprocessor) reference manual describes the hardware and associated ISA.
Since ACC is designed for cryptographic offload, not general computation, it has no C compiler. However, it does have the usual binutils programs: an assembler, linker and disassembler. The core of ACC’s instruction set is based on RV32I, the RISC-V base integer instruction set. As such, we implement the toolchain as a thin wrapper around RISC-V binutils.
Assembly format and examples
The ACC ISA and programmer model are described in the ACC reference manual.
In particular, note that the register x1 has special stack-like behaviour.
There are some example programs at sw/acc/code-snippets.
These range from simple examples of how to use pseudo-operations up to example cryptographic primitives.
For specific formatting and secure coding guidelines, see the ACC style guide.
The tools
Assembler
The ACC assembler is called acc_as.py.
This has the same command line interface as riscv32-unknown-elf-as (indeed, it’s a wrapper around that program).
The only difference in default flags is that acc_as.py passes -mno-relax, telling the assembler not to request linker relaxation.
This is needed because one of these relaxations generates GP-relative loads, which assume x3 is treated as a global pointer (not true for ACC code).
To assemble some code in foo.s to an ELF object called foo.o, run:
hw/ip/acc/util/acc_as.py -o foo.o foo.s
Linker
The ACC linker is called acc_ld.py.
This is a thin wrapper around riscv32-unknown-elf-ld, but supplies a default linker script that matches the ACC memory layout.
This linker script creates .start, .text and .data output sections.
The .start and .text sections go to IMEM, with .start coming first.
The .data section goes to DMEM.
Since ACC has a strict Harvard architecture with IMEM and DMEM both starting at address zero, the .start and the .data sections will both start at VMA zero.
The instruction and data segments have distinct LMAs (for addresses, see the IMEM and DMEM windows at hw/ip/acc/data/acc.hjson).
Since the entry point for ACC is always address zero, the entry vector should be the one and only thing in the .start section.
To achieve that, put your entry point (and nothing else) in the .text.start input section like this:
.section .text.start
jal x0, main
.text
...
This ensures that, even if there are multiple objects being linked together, the intended entry point will appear in the right place.
To link ELF object files to an ACC ELF binary, run
hw/ip/acc/util/acc_ld.py -o foo foo0.o foo1.o foo2.o
Objdump
To disassemble ACC code, use acc_objdump.py.
This wraps riscv32-unknown-elf-objdump, but correctly disassembles ACC instructions when run with the -d flag.
To disassemble the ELF binary linked in the previous section, run
hw/ip/acc/util/acc_objdump.py -d foo