From 284ddbff6260c2d9f34a8f05b593774ea1665c8b Mon Sep 17 00:00:00 2001 From: Ryad Benadjila Date: Wed, 26 Jun 2024 09:41:24 +0200 Subject: [PATCH 1/5] Add picolibc (packaged e.g. under Debian distros with the RISC-V toolchain) compatibility in the compilation toolchain. The commit also adds "printf" possible usage using picolibc. --- Makefile | 10 +++++++++- README.md | 8 +++++--- drv/main.c | 35 +++++++++++++++++++++++++++++++++++ flow/picolibc.ld | 6 ++++++ 4 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 flow/picolibc.ld diff --git a/Makefile b/Makefile index 9ca8675..366ce9d 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,15 @@ CCONF_H ?= config.h XCHAIN ?= riscv64-unknown-elf- CFLAGS = -O2 -Wall -g -mabi=ilp32 -march=rv32imc CFLAGS += -include $(CCONF_H) -DNDEBUG -LDFLAGS = -Wl,-Bstatic,-T,flow/riscv.ld,--no-relax +# If we use picolibc, adapt the flags. +# NOTE: the local ld script mostly provides flash and RAM layout +# (in our case flash starts at 0 and is in fact part of RAM) +ifeq ($(USE_PICOLIBC),1) + CFLAGS += -specs=picolibc.specs + LDFLAGS = -Wl,-Bstatic,-T,flow/picolibc.ld,--no-relax +else + LDFLAGS = -Wl,-Bstatic,-T,flow/riscv.ld,--no-relax +endif KATNUM ?= 10 CFLAGS += -DKATNUM=$(KATNUM) diff --git a/README.md b/README.md index 7890ea6..7099913 100644 --- a/README.md +++ b/README.md @@ -53,11 +53,13 @@ See [slh/README.md](slh/README.md) for more information. As a prerequisite for simulation, you'll need: -* [Verilator](https://github.com/verilator/verilator) verilog simulator. +* [Verilator](https://github.com/verilator/verilator) verilog simulator. This might be packaged on some Linux distros. * A RISC-V cross-compiler that supports bare-metal targets. You can build a suitable [riscv-gnu-toolchain](https://github.com/riscv/riscv-gnu-toolchain) -with `./configure --enable-multilib` and `make newlib`. +with `./configure --enable-multilib` and `make newlib`. Under some Linux based distros (such as Debian), it is possible to use the packaged +`gcc-riscv64-unknown-elf` along with the packaged `picolibc-riscv64-unknown-elf`: note that in this case, you will have to export the `USE_PICOLIBC=1` environment +variable when compiling: `USE_PICOLIBC=1 make veri` (this is due to some divergence between `newlib` and `picolibc` C standard libraries linking scripts). -Both of these may be available as packages for Linux operating systems. The name of your toolchain is set in `XCHAIN` variable in the [Makefile](Makefile). +The name of your toolchain is set in `XCHAIN` variable in the [Makefile](Makefile). To build and run a quick end-to-end test, try: ``` diff --git a/drv/main.c b/drv/main.c index 02c8bfd..f529f09 100644 --- a/drv/main.c +++ b/drv/main.c @@ -18,6 +18,36 @@ int test_sloth(); // test_sloth.c int test_bench(); // test_bench.c int test_leak(); // test_leak.c +#ifdef _PICOLIBC__ +// XXX In case of Picolibc, redirect stdio related stuff to uart +// (see https://github.com/picolibc/picolibc/blob/main/doc/os.md) +// This allows to use printf family of functions +#include +#include +static int sample_putc(char c, FILE *file) +{ + (void) file; /* Not used in this function */ + sio_putc(c); /* Defined by underlying system */ + return c; +} + +static int sample_getc(FILE *file) +{ + unsigned char c; + (void) file; /* Not used in this function */ + c = sio_getc(); /* Defined by underlying system */ + return c; +} + +FILE __stdio = FDEV_SETUP_STREAM(sample_putc, + sample_getc, + NULL, + _FDEV_SETUP_RW); + +FILE *const stdin = &__stdio; __strong_reference(stdin, stdout); __strong_reference(stdin, stderr); +#endif + + int main() { int fail = 0; @@ -68,6 +98,11 @@ int main() sio_putc(4); // translated to EOF sio_putc(0); +#ifdef _PICOLIBC__ + // XXX: in case of picolibc, explicitly exit as + // this is not performed at the return of main + exit(0); +#endif return 0; } diff --git a/flow/picolibc.ld b/flow/picolibc.ld new file mode 100644 index 0000000..937c4c6 --- /dev/null +++ b/flow/picolibc.ld @@ -0,0 +1,6 @@ +# XXX: sizes to be fixed according to the (hardware) allocated RAM size of SLotH +__flash = 0x00000000; +__flash_size = 64k; +__ram = __flash + __flash_size; +__ram_size = 64k; +__stack_size = 8k; From 28b73746befbaccfcd9b7000fc05259d3dcff301 Mon Sep 17 00:00:00 2001 From: Ryad Benadjila Date: Wed, 26 Jun 2024 10:26:52 +0200 Subject: [PATCH 2/5] Fix profiling script for usage with toolchains with non-present source files. --- flow/eprof.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/flow/eprof.py b/flow/eprof.py index e4de51e..1a35386 100755 --- a/flow/eprof.py +++ b/flow/eprof.py @@ -56,7 +56,12 @@ def cnt_str(cnt): pfl=len(os.path.commonprefix([os.getcwd(), rfn])) wfn = rfn[pfl:].replace("/","_"); print("writing:", wfn) - fr = open(rfn, "r") + try: + # Try to open the source file, if not possible skip it + fr = open(rfn, "r") + except: + print("[-] Skipping %s (not found)" % wfn) + continue fw = open(wfn, "w") ln = 0 for sf in fr: From 1dfc4928530438e78f0d3145042b9cc649bcc58b Mon Sep 17 00:00:00 2001 From: Ryad Benadjila Date: Wed, 26 Jun 2024 10:42:51 +0200 Subject: [PATCH 3/5] Small fix in profiling script. --- flow/eprof.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flow/eprof.py b/flow/eprof.py index 1a35386..1d17933 100755 --- a/flow/eprof.py +++ b/flow/eprof.py @@ -55,13 +55,13 @@ def cnt_str(cnt): for rfn in lsc: pfl=len(os.path.commonprefix([os.getcwd(), rfn])) wfn = rfn[pfl:].replace("/","_"); - print("writing:", wfn) try: # Try to open the source file, if not possible skip it fr = open(rfn, "r") except: - print("[-] Skipping %s (not found)" % wfn) + print("[-] Skipping %s (not found)" % rfn) continue + print("writing:", wfn) fw = open(wfn, "w") ln = 0 for sf in fr: From 36b4c963cc57868572e233470371647d0f3ea46a Mon Sep 17 00:00:00 2001 From: Ryad Benadjila Date: Wed, 26 Jun 2024 12:01:03 +0200 Subject: [PATCH 4/5] Add autonomous Dockerfile based on Ubuntu for simulation and profiling. To launch: $ make -f Makefile.docker --- Docker/Dockerfile | 22 ++++++++++++++++++++++ Makefile | 1 + Makefile.docker | 19 +++++++++++++++++++ 3 files changed, 42 insertions(+) create mode 100644 Docker/Dockerfile create mode 100644 Makefile.docker diff --git a/Docker/Dockerfile b/Docker/Dockerfile new file mode 100644 index 0000000..e243249 --- /dev/null +++ b/Docker/Dockerfile @@ -0,0 +1,22 @@ +FROM ubuntu:noble AS builder + +# Install Make, g++, verilator, the RISC-V toolchain and the picolibc library +RUN apt-get update + +RUN apt-get install -qy --no-install-recommends make g++ bsdmainutils verilator gcc-riscv64-unknown-elf picolibc-riscv64-unknown-elf + + +# NOTE: the random forces a Docker cache miss to force +# the execution of the script +ADD "https://www.random.org/cgi-bin/randbyte?nbytes=10&format=h" skipcache + +# Now compile and simulate +WORKDIR /build +COPY ./ /build + +RUN USE_PICOLIBC=1 make prof 2>&1 | tee -a sloth_build.log +RUN tar -czvf docker_build.tar.gz sloth_build.log core_pc.log firmware.pmap firmware.bin firmware.elf firmware.hex _prof _build drv slh --transform 's,^,docker_build/,' + +# Copy the produced artifacts to the host +FROM scratch AS artifacts +COPY --from=builder /build/docker_build.tar.gz ./docker_build.tar.gz diff --git a/Makefile b/Makefile index 366ce9d..671b920 100644 --- a/Makefile +++ b/Makefile @@ -144,6 +144,7 @@ clean: $(RM) -f $(FW).* $(CCONF_H) $(OBJS) $(VVP) $(RM) -rf $(PROF) $(BUILD) $(RM) -f *.jou *.log *.bit + $(MAKE) -f Makefile.docker clean cd slh && $(MAKE) clean cd flow/yosys-syn && $(MAKE) clean diff --git a/Makefile.docker b/Makefile.docker new file mode 100644 index 0000000..33d8791 --- /dev/null +++ b/Makefile.docker @@ -0,0 +1,19 @@ +ifeq ($(DOCKER_FORCE_REBUILD),1) +NOCACHE=--no-cache +RECREATE=--force-recreate +else +NOCACHE= +RECREATE= +endif +ifeq ($(DOCKER_VERBOSE),1) +BUILDKIT_PROGRESS=plain +endif + +DOCKER_PLATFORM=--platform linux/amd64 + +all: + DOCKER_BUILDKIT=1 BUILDKIT_PROGRESS=$(BUILDKIT_PROGRESS) docker build --build-arg PLATFORMS="$(PLATFORMS)" --file Docker/Dockerfile -o type=local,dest=Docker/ . + +clean: + # Remove build artifacts + @rm -f Docker/docker_build.tar.gz From 8e1a1aebcedf98f4dd0f96af8b6035ef0a559a73 Mon Sep 17 00:00:00 2001 From: Ryad Benadjila Date: Wed, 26 Jun 2024 12:09:44 +0200 Subject: [PATCH 5/5] Update README with Docker help. --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 7099913..7473c4c 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,16 @@ exit() ``` The readout from this particular execution of SLH-DSA-SHAKE-128f is that KeyGen was 204310 cycles, signing was 4943111 cycles, and verification was 434660 cycles. Furthermore, the self-tests were a PASS; the output matched the Known Answer Tests. Modify the end of `test_bench.c` to have broader test behavior. +## Using Docker + +Alternatively, it is possible to use an Ubuntu based Docker container for the simulation (with preinstalled verilator and toolchain). Having Docker installed, simply execute: + + +``` +DOCKER_VERBOSE=1 make -f Makefile.docker +``` + +This will put the compilation and profiling artifacts in the compressed `Docker/docker_build.tar.gz` file. ## Some other targets