├── sim ├── .gitignore └── Makefile ├── tests ├── .gitignore ├── spectre-tests │ ├── .gitignore │ ├── Makefile │ ├── secret-after-branch.s │ ├── secret-before-branch.s │ └── eval.py ├── synthetic-benchmark │ ├── .gitignore │ ├── include │ │ ├── kremlib │ │ │ ├── Makefile.include │ │ │ ├── libkremlib.def │ │ │ ├── LowStar_Endianness.h │ │ │ ├── Makefile.basic │ │ │ ├── fstar_uint128_struct_endianness.h │ │ │ └── FStar_UInt128.h │ │ ├── kremlin │ │ │ ├── internal │ │ │ │ ├── wasmsupport.h │ │ │ │ ├── builtin.h │ │ │ │ ├── compat.h │ │ │ │ ├── callconv.h │ │ │ │ └── debug.h │ │ │ ├── c_endianness.h │ │ │ └── fstar_int.h │ │ └── kremlib.h │ ├── Makefile │ ├── Hacl_Chacha20.h │ └── eval.py ├── crypto │ ├── curve25519 │ │ ├── .gitignore │ │ ├── Curve25519-donna.h │ │ ├── Makefile │ │ ├── clear.S │ │ ├── curve25519.c │ │ └── curve25519.S │ ├── hacl-star-sha2 │ │ ├── .gitignore │ │ ├── include │ │ │ ├── kremlib │ │ │ │ ├── Makefile.include │ │ │ │ ├── libkremlib.def │ │ │ │ ├── LowStar_Endianness.h │ │ │ │ ├── Makefile.basic │ │ │ │ ├── fstar_uint128_struct_endianness.h │ │ │ │ └── FStar_UInt128.h │ │ │ ├── kremlin │ │ │ │ ├── internal │ │ │ │ │ ├── wasmsupport.h │ │ │ │ │ ├── builtin.h │ │ │ │ │ ├── compat.h │ │ │ │ │ ├── callconv.h │ │ │ │ │ └── debug.h │ │ │ │ ├── c_endianness.h │ │ │ │ └── fstar_int.h │ │ │ └── kremlib.h │ │ ├── Makefile │ │ ├── clear.S │ │ ├── sha2.c │ │ ├── README.md │ │ ├── Hacl_Hash_SHA2.h │ │ └── sha2.S │ ├── hacl-star-chacha20 │ │ ├── .gitignore │ │ ├── include │ │ │ ├── kremlib │ │ │ │ ├── Makefile.include │ │ │ │ ├── libkremlib.def │ │ │ │ ├── LowStar_Endianness.h │ │ │ │ ├── Makefile.basic │ │ │ │ ├── fstar_uint128_struct_endianness.h │ │ │ │ └── FStar_UInt128.h │ │ │ ├── kremlin │ │ │ │ ├── internal │ │ │ │ │ ├── wasmsupport.h │ │ │ │ │ ├── builtin.h │ │ │ │ │ ├── compat.h │ │ │ │ │ ├── callconv.h │ │ │ │ │ └── debug.h │ │ │ │ ├── c_endianness.h │ │ │ │ └── fstar_int.h │ │ │ └── kremlib.h │ │ ├── Makefile │ │ ├── clear.S │ │ ├── chacha20.c │ │ ├── Hacl_Chacha20.h │ │ ├── chacha20.S │ │ └── README.md │ ├── djbsort-20190516 │ │ ├── .gitignore │ │ ├── uint32 │ │ │ ├── portable3 │ │ │ │ └── sort.c │ │ │ └── portable4 │ │ │ │ └── sort.c │ │ ├── include │ │ │ ├── int32_minmax.c │ │ │ ├── int32_sort.h │ │ │ └── uint32_sort.h │ │ ├── int32 │ │ │ ├── portable3 │ │ │ │ └── sort.c │ │ │ └── portable4 │ │ │ │ └── sort.c │ │ ├── sort_portable3_int32.c │ │ ├── clear.S │ │ └── Makefile │ └── README.md ├── tests.ld ├── Makefile └── riscv_test.h ├── project └── plugins.sbt ├── synthesis ├── Constraints.xdc └── Top.v ├── .scalafmt.conf ├── src └── main │ └── scala │ └── riscv │ ├── plugins │ ├── cheri │ │ ├── tests │ │ │ ├── Makefile.include │ │ │ ├── CGetSealed.S │ │ │ ├── CClearTag.S │ │ │ ├── Traps.S │ │ │ ├── CIncOffsetImm.S │ │ │ ├── CIncOffset.S │ │ │ ├── CInvoke.S │ │ │ ├── CSetOffset.S │ │ │ ├── CSetBoundsImm.S │ │ │ ├── CAndPerm.S │ │ │ ├── CSetBounds.S │ │ │ ├── Scr.S │ │ │ ├── CSetAddr.S │ │ │ ├── InitialState.S │ │ │ ├── Sealing.S │ │ │ ├── cheri.h │ │ │ ├── RiscvLsu.S │ │ │ ├── Pcc.S │ │ │ └── LsuCap.S │ │ ├── Context.scala │ │ ├── GlobalPipelineData.scala │ │ ├── CapBus.scala │ │ ├── MachineMode.scala │ │ ├── Ccsr.scala │ │ ├── CapIdx.scala │ │ ├── ExceptionHandler.scala │ │ ├── Services.scala │ │ └── RegisterFile.scala │ ├── scheduling │ │ ├── static │ │ │ ├── NoPipeliningScheduler.scala │ │ │ └── Scheduler.scala │ │ └── dynamic │ │ │ ├── Dispatcher.scala │ │ │ ├── DynamicDataBuses.scala │ │ │ └── PcManager.scala │ ├── NoPredictionPredictor.scala │ ├── Fetcher.scala │ ├── Timers.scala │ ├── RegisterFileAccessor.scala │ ├── Shifter.scala │ ├── BranchTargetPredictor.scala │ └── StaticMemoryBackbone.scala │ ├── soc │ └── devices │ │ ├── Apb3CharDev.scala │ │ ├── Apb3TestDev.scala │ │ ├── Apb3MachineTimers.scala │ │ └── Apb3ByteDev.scala │ ├── sim │ └── StdioByteDev.scala │ ├── Config.scala │ ├── Plugin.scala │ ├── PipelineData.scala │ ├── PipelineRegs.scala │ ├── Pipeline.scala │ ├── RegisterFile.scala │ └── Utils.scala ├── .gitignore ├── formal ├── checks.cfg ├── Makefile └── disasm.py ├── .gitmodules ├── sim.gtkw ├── res └── disas.py ├── LICENSE ├── .gitlab-ci.yml ├── .github └── workflows │ └── ci.yml └── Dockerfile /sim/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | -------------------------------------------------------------------------------- /tests/spectre-tests/.gitignore: -------------------------------------------------------------------------------- 1 | *.bin 2 | *.elf 3 | *_stripped.s 4 | -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.6") 2 | -------------------------------------------------------------------------------- /synthesis/Constraints.xdc: -------------------------------------------------------------------------------- 1 | create_clock -period 31.000 -name sysClk [get_ports sysClk] 2 | -------------------------------------------------------------------------------- /tests/synthetic-benchmark/.gitignore: -------------------------------------------------------------------------------- 1 | *.bin 2 | *.elf 3 | *_stripped.s 4 | *.ihex 5 | *.o 6 | -------------------------------------------------------------------------------- /tests/crypto/curve25519/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.elf 3 | *.bin 4 | *.ihex 5 | *.vcd 6 | *.objdump 7 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-sha2/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.elf 3 | *.bin 4 | *.ihex 5 | *.vcd 6 | *.objdump 7 | -------------------------------------------------------------------------------- /.scalafmt.conf: -------------------------------------------------------------------------------- 1 | version = 3.5.8 2 | runner.dialect = scala212 3 | maxColumn = 100 4 | align.preset = none 5 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-chacha20/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.elf 3 | *.bin 4 | *.ihex 5 | *.vcd 6 | *.objdump 7 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/cheri/tests/Makefile.include: -------------------------------------------------------------------------------- 1 | CORE = riscv.plugins.cheri.CoreExtMem 2 | CC = clang 3 | CFLAGS = -target riscv32 -march=rv32imxcheri -Dmbadaddr=mtval -Dsptbr=satp 4 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-sha2/include/kremlib/Makefile.include: -------------------------------------------------------------------------------- 1 | USER_TARGET=libkremlib.a 2 | USER_CFLAGS= 3 | USER_C_FILES=fstar_uint128.c 4 | ALL_C_FILES= 5 | ALL_H_FILES=FStar_UInt_8_16_32_64.h FStar_UInt128.h LowStar_Endianness.h 6 | -------------------------------------------------------------------------------- /tests/synthetic-benchmark/include/kremlib/Makefile.include: -------------------------------------------------------------------------------- 1 | USER_TARGET=libkremlib.a 2 | USER_CFLAGS= 3 | USER_C_FILES=fstar_uint128.c 4 | ALL_C_FILES= 5 | ALL_H_FILES=FStar_UInt_8_16_32_64.h FStar_UInt128.h LowStar_Endianness.h 6 | -------------------------------------------------------------------------------- /tests/crypto/djbsort-20190516/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.elf 3 | *.bin 4 | *.ihex 5 | *.binsec 6 | *.objdump 7 | *.dba 8 | 9 | # Not ready yet 10 | sort_portable3_uint32.c 11 | sort_portable4_int32.c 12 | sort_portable4_uint32.c 13 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-chacha20/include/kremlib/Makefile.include: -------------------------------------------------------------------------------- 1 | USER_TARGET=libkremlib.a 2 | USER_CFLAGS= 3 | USER_C_FILES=fstar_uint128.c 4 | ALL_C_FILES= 5 | ALL_H_FILES=FStar_UInt_8_16_32_64.h FStar_UInt128.h LowStar_Endianness.h 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vscode/ 3 | /*.v 4 | /*.bin 5 | /project/* 6 | !/project/plugins.sbt 7 | /simWorkspace/ 8 | /target/ 9 | /tmp/ 10 | /tools/ 11 | /verbose.log 12 | *~ 13 | *.swp 14 | *.vcd 15 | .kdev4/ 16 | *.kdev4 17 | .bsp 18 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-sha2/include/kremlin/internal/wasmsupport.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) INRIA and Microsoft Corporation. All rights reserved. 2 | Licensed under the Apache 2.0 License. */ 3 | 4 | /* This file is automatically included when compiling with -wasm -d force-c */ 5 | #define WasmSupport_check_buffer_size(X) 6 | -------------------------------------------------------------------------------- /tests/synthetic-benchmark/include/kremlin/internal/wasmsupport.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) INRIA and Microsoft Corporation. All rights reserved. 2 | Licensed under the Apache 2.0 License. */ 3 | 4 | /* This file is automatically included when compiling with -wasm -d force-c */ 5 | #define WasmSupport_check_buffer_size(X) 6 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-chacha20/include/kremlin/internal/wasmsupport.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) INRIA and Microsoft Corporation. All rights reserved. 2 | Licensed under the Apache 2.0 License. */ 3 | 4 | /* This file is automatically included when compiling with -wasm -d force-c */ 5 | #define WasmSupport_check_buffer_size(X) 6 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-sha2/include/kremlib/libkremlib.def: -------------------------------------------------------------------------------- 1 | LIBRARY libkremlib 2 | 3 | EXPORTS 4 | FStar_UInt64_eq_mask 5 | FStar_UInt64_gte_mask 6 | FStar_UInt32_eq_mask 7 | FStar_UInt32_gte_mask 8 | FStar_UInt16_eq_mask 9 | FStar_UInt16_gte_mask 10 | FStar_UInt8_eq_mask 11 | FStar_UInt8_gte_mask 12 | -------------------------------------------------------------------------------- /tests/synthetic-benchmark/include/kremlib/libkremlib.def: -------------------------------------------------------------------------------- 1 | LIBRARY libkremlib 2 | 3 | EXPORTS 4 | FStar_UInt64_eq_mask 5 | FStar_UInt64_gte_mask 6 | FStar_UInt32_eq_mask 7 | FStar_UInt32_gte_mask 8 | FStar_UInt16_eq_mask 9 | FStar_UInt16_gte_mask 10 | FStar_UInt8_eq_mask 11 | FStar_UInt8_gte_mask 12 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-chacha20/include/kremlib/libkremlib.def: -------------------------------------------------------------------------------- 1 | LIBRARY libkremlib 2 | 3 | EXPORTS 4 | FStar_UInt64_eq_mask 5 | FStar_UInt64_gte_mask 6 | FStar_UInt32_eq_mask 7 | FStar_UInt32_gte_mask 8 | FStar_UInt16_eq_mask 9 | FStar_UInt16_gte_mask 10 | FStar_UInt8_eq_mask 11 | FStar_UInt8_gte_mask 12 | -------------------------------------------------------------------------------- /tests/tests.ld: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | RAM : ORIGIN = 0x80000000, LENGTH = 0x00a00000 4 | } 5 | 6 | SECTIONS 7 | { 8 | .text : { 9 | . = ALIGN(4); 10 | *(.text) 11 | } > RAM 12 | 13 | .data : { 14 | . = ALIGN(4); 15 | *(.data); 16 | . = ALIGN(4); 17 | } > RAM 18 | } 19 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/cheri/Context.scala: -------------------------------------------------------------------------------- 1 | package riscv.plugins.cheri 2 | 3 | import riscv._ 4 | 5 | case class Context(pipeline: Pipeline)(implicit val config: Config) { 6 | val clen = 4 * config.xlen 7 | val otypeLen = 12 8 | val maxOtype = (1 << otypeLen) - 17 9 | val data = new GlobalPipelineData(pipeline)(this) 10 | } 11 | -------------------------------------------------------------------------------- /tests/crypto/curve25519/Curve25519-donna.h: -------------------------------------------------------------------------------- 1 | #ifndef CURVE25519_DONNA_H_ 2 | #define CURVE25519_DONNA_H_ 3 | #include 4 | #include 5 | 6 | typedef uint8_t u8; 7 | typedef int32_t s32; 8 | typedef int64_t limb; 9 | 10 | int curve25519_donna(u8 *mypublic, const u8 *secret, const u8 *basepoint); 11 | 12 | #endif // CURVE25519-DONNA_H_ 13 | -------------------------------------------------------------------------------- /tests/spectre-tests/Makefile: -------------------------------------------------------------------------------- 1 | %.elf: %.s 2 | riscv32-unknown-elf-gcc -mabi=ilp32 -march=rv32im_zicsr -c -o $@ $< 3 | riscv32-unknown-elf-gcc -mabi=ilp32 -march=rv32im_zicsr -ffreestanding -nostdlib -T ../tests.ld -o $@ $< 4 | 5 | %.ihex: %.elf 6 | riscv32-unknown-elf-objcopy -O ihex $< $@ 7 | 8 | %.bin: %.elf 9 | riscv32-unknown-elf-objcopy -O binary $< $@ 10 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/cheri/GlobalPipelineData.scala: -------------------------------------------------------------------------------- 1 | package riscv.plugins.cheri 2 | 3 | import riscv._ 4 | 5 | import spinal.core._ 6 | 7 | class GlobalPipelineData(pipeline: Pipeline)(implicit context: Context) { 8 | object CS1_DATA extends PipelineData(RegCapability()) 9 | object CS2_DATA extends PipelineData(RegCapability()) 10 | object CD_DATA extends PipelineData(RegCapability()) 11 | } 12 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-sha2/include/kremlin/c_endianness.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) INRIA and Microsoft Corporation. All rights reserved. 2 | Licensed under the Apache 2.0 License. */ 3 | 4 | #ifndef __KREMLIN_ENDIAN_H 5 | #define __KREMLIN_ENDIAN_H 6 | 7 | #ifdef __GNUC__ 8 | #warning "c_endianness.h is deprecated, include lowstar_endianness.h instead" 9 | #endif 10 | 11 | #include "lowstar_endianness.h" 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /tests/synthetic-benchmark/include/kremlin/c_endianness.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) INRIA and Microsoft Corporation. All rights reserved. 2 | Licensed under the Apache 2.0 License. */ 3 | 4 | #ifndef __KREMLIN_ENDIAN_H 5 | #define __KREMLIN_ENDIAN_H 6 | 7 | #ifdef __GNUC__ 8 | #warning "c_endianness.h is deprecated, include lowstar_endianness.h instead" 9 | #endif 10 | 11 | #include "lowstar_endianness.h" 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-chacha20/include/kremlin/c_endianness.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) INRIA and Microsoft Corporation. All rights reserved. 2 | Licensed under the Apache 2.0 License. */ 3 | 4 | #ifndef __KREMLIN_ENDIAN_H 5 | #define __KREMLIN_ENDIAN_H 6 | 7 | #ifdef __GNUC__ 8 | #warning "c_endianness.h is deprecated, include lowstar_endianness.h instead" 9 | #endif 10 | 11 | #include "lowstar_endianness.h" 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /tests/crypto/djbsort-20190516/uint32/portable3/sort.c: -------------------------------------------------------------------------------- 1 | #include "int32_sort.h" 2 | #include "uint32_sort.h" 3 | 4 | /* can save time by vectorizing xor loops */ 5 | /* can save time by integrating xor loops with int32_sort */ 6 | 7 | void uint32_sort(uint32_t *x,long long n) 8 | { 9 | long long j; 10 | for (j = 0;j < n;++j) x[j] ^= 0x80000000; 11 | int32_sort((int32_t *) x,n); 12 | for (j = 0;j < n;++j) x[j] ^= 0x80000000; 13 | } 14 | -------------------------------------------------------------------------------- /tests/crypto/djbsort-20190516/uint32/portable4/sort.c: -------------------------------------------------------------------------------- 1 | #include "int32_sort.h" 2 | #include "uint32_sort.h" 3 | 4 | /* can save time by vectorizing xor loops */ 5 | /* can save time by integrating xor loops with int32_sort */ 6 | 7 | void uint32_sort(uint32_t *x,long long n) 8 | { 9 | long long j; 10 | for (j = 0;j < n;++j) x[j] ^= 0x80000000; 11 | int32_sort((int32_t *) x,n); 12 | for (j = 0;j < n;++j) x[j] ^= 0x80000000; 13 | } 14 | -------------------------------------------------------------------------------- /formal/checks.cfg: -------------------------------------------------------------------------------- 1 | 2 | [options] 3 | isa rv32i 4 | 5 | [depth] 6 | insn 20 7 | reg 15 30 8 | pc_fwd 10 30 9 | pc_bwd 10 30 10 | liveness 1 10 70 11 | unique 1 10 30 12 | causal 10 30 13 | 14 | [defines] 15 | `define RISCV_FORMAL_ALIGNED_MEM 16 | `define RISCV_FORMAL_ALTOPS 17 | `define DEBUGNETS 18 | 19 | [script-sources] 20 | read_verilog -sv @basedir@/cores/@core@/wrapper.sv 21 | read_verilog @basedir@/cores/@core@/@core@.v 22 | 23 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/scheduling/static/NoPipeliningScheduler.scala: -------------------------------------------------------------------------------- 1 | package riscv.plugins.scheduling.static 2 | 3 | import riscv._ 4 | 5 | import spinal.core._ 6 | import spinal.lib._ 7 | 8 | class NoPipeliningScheduler extends Scheduler { 9 | override def build(): Unit = { 10 | super.build() 11 | 12 | pipeline plug new Area { 13 | val stages = pipeline.stages 14 | stages.head.arbitration.isValid := !stages.tail.map(_.arbitration.isValid).orR 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "formal/riscv-formal"] 2 | path = formal/riscv-formal 3 | url = https://github.com/SymbioticEDA/riscv-formal.git 4 | ignore = untracked 5 | [submodule "tests/riscv-tests"] 6 | path = tests/riscv-tests 7 | url = https://github.com/riscv/riscv-tests.git 8 | [submodule "tests/riscv-test-env"] 9 | path = tests/riscv-test-env 10 | url = https://github.com/riscv/riscv-test-env.git 11 | [submodule "tests/newlib"] 12 | path = tests/newlib 13 | url = https://github.com/proteus-core/newlib.git 14 | -------------------------------------------------------------------------------- /src/main/scala/riscv/soc/devices/Apb3CharDev.scala: -------------------------------------------------------------------------------- 1 | package riscv.soc.devices 2 | 3 | import riscv._ 4 | 5 | import spinal.core._ 6 | import spinal.lib._ 7 | import spinal.lib.bus.amba3.apb._ 8 | 9 | class Apb3CharDev(implicit config: Config) extends Component { 10 | val io = new Bundle { 11 | val char = master(Flow(UInt(8 bits))) 12 | val apb = slave(Apb3(Apb3Config(addressWidth = 4, dataWidth = config.xlen))) 13 | } 14 | 15 | val busCtrl = Apb3SlaveFactory(io.apb) 16 | 17 | busCtrl.driveFlow(io.char, 0) 18 | } 19 | -------------------------------------------------------------------------------- /tests/synthetic-benchmark/Makefile: -------------------------------------------------------------------------------- 1 | KERNEL_DIR = ../newlib 2 | KREMLIB_INCLUDE_DIR = ./include/kremlib 3 | KREMLIN_INCLUDE_DIR = ./include 4 | 5 | EXTRA_CFLAGS = -I$(KREMLIN_INCLUDE_DIR) -I$(KREMLIB_INCLUDE_DIR) 6 | 7 | TARGET ?= specBench 8 | 9 | 10 | all: $(TARGET).bin $(TARGET).ihex $(TARGET).objdump 11 | 12 | $(TARGET).elf: Hacl_Chacha20.o 13 | 14 | include $(KERNEL_DIR)/Makefile.include 15 | 16 | $(TARGET).objdump: $(TARGET).elf 17 | $(OBJDUMP) -d $^ > $@ 18 | 19 | clean: 20 | make -C $(KERNEL_DIR) clean 21 | rm -f *.elf *.bin *.ihex *.o 22 | -------------------------------------------------------------------------------- /src/main/scala/riscv/soc/devices/Apb3TestDev.scala: -------------------------------------------------------------------------------- 1 | package riscv.soc.devices 2 | 3 | import riscv._ 4 | import riscv.soc._ 5 | 6 | import spinal.core._ 7 | import spinal.lib._ 8 | import spinal.lib.bus.amba3.apb._ 9 | 10 | class Apb3TestDev(implicit config: Config) extends Component { 11 | val io = new Bundle { 12 | val test = master(Flow(UInt(config.xlen bits))) 13 | val apb = slave(Apb3(Apb3Config(addressWidth = 4, dataWidth = config.xlen))) 14 | } 15 | 16 | val busCtrl = Apb3SlaveFactory(io.apb) 17 | 18 | busCtrl.driveFlow(io.test, 0) 19 | } 20 | -------------------------------------------------------------------------------- /tests/synthetic-benchmark/include/kremlin/internal/builtin.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) INRIA and Microsoft Corporation. All rights reserved. 2 | Licensed under the Apache 2.0 License. */ 3 | 4 | #ifndef __KREMLIN_BUILTIN_H 5 | #define __KREMLIN_BUILTIN_H 6 | 7 | /* For alloca, when using KreMLin's -falloca */ 8 | #if (defined(_WIN32) || defined(_WIN64)) 9 | # include 10 | #endif 11 | 12 | /* If some globals need to be initialized before the main, then kremlin will 13 | * generate and try to link last a function with this type: */ 14 | void kremlinit_globals(void); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-chacha20/include/kremlin/internal/builtin.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) INRIA and Microsoft Corporation. All rights reserved. 2 | Licensed under the Apache 2.0 License. */ 3 | 4 | #ifndef __KREMLIN_BUILTIN_H 5 | #define __KREMLIN_BUILTIN_H 6 | 7 | /* For alloca, when using KreMLin's -falloca */ 8 | #if (defined(_WIN32) || defined(_WIN64)) 9 | # include 10 | #endif 11 | 12 | /* If some globals need to be initialized before the main, then kremlin will 13 | * generate and try to link last a function with this type: */ 14 | void kremlinit_globals(void); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-sha2/include/kremlin/internal/builtin.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) INRIA and Microsoft Corporation. All rights reserved. 2 | Licensed under the Apache 2.0 License. */ 3 | 4 | #ifndef __KREMLIN_BUILTIN_H 5 | #define __KREMLIN_BUILTIN_H 6 | 7 | /* For alloca, when using KreMLin's -falloca */ 8 | #if (defined(_WIN32) || defined(_WIN64)) 9 | # include 10 | #endif 11 | 12 | /* If some globals need to be initialized before the main, then kremlin will 13 | * generate and try to link last a function with this type: */ 14 | void kremlinit_globals(void); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/cheri/tests/CGetSealed.S: -------------------------------------------------------------------------------- 1 | #include "riscv_test.h" 2 | 3 | #include "test_macros_cap.h" 4 | #include "cheri.h" 5 | 6 | RVTEST_RV32U 7 | RVTEST_CODE_BEGIN 8 | 9 | INIT_ROOT_CAP 10 | 11 | TEST_CASE_START(1) 12 | CGetSealed t0, ROOT 13 | bne t0, zero, fail 14 | 15 | TEST_CASE_START(2) 16 | SEAL(c1, ROOT, 123) 17 | CGetSealed t0, c1 18 | li t1, 1 19 | bne t0, t1, fail 20 | 21 | TEST_PASSFAIL 22 | 23 | RVTEST_CODE_END 24 | 25 | .data 26 | RVTEST_DATA_BEGIN 27 | 28 | TEST_DATA 29 | 30 | RVTEST_DATA_END 31 | -------------------------------------------------------------------------------- /tests/crypto/djbsort-20190516/include/int32_minmax.c: -------------------------------------------------------------------------------- 1 | #define int32_MINMAX(a,b) \ 2 | do { \ 3 | __attribute__((section(".secret"))) static int32 ab; \ 4 | ab = b ^ a; \ 5 | __attribute__((section(".secret"))) static int32 c; \ 6 | c = b - a; \ 7 | c ^= ab & (c ^ b); \ 8 | c >>= 31; \ 9 | c &= ab; \ 10 | a ^= c; \ 11 | b ^= c; \ 12 | } while(0) 13 | -------------------------------------------------------------------------------- /sim.gtkw: -------------------------------------------------------------------------------- 1 | [*] 2 | [*] GTKWave Analyzer v3.3.103 (w)1999-2019 BSI 3 | [*] Tue Jan 3 13:34:44 2023 4 | [*] 5 | [dumpfile] "~/proteus/sim.vcd" 6 | [dumpfile_size] 9795828 7 | [savefile] "~/proteus/sim.gtkw" 8 | [timestart] 0 9 | [size] 1920 1043 10 | [pos] -1 -1 11 | *-5.000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 12 | [treeopen] TOP. 13 | [treeopen] TOP.Core. 14 | [treeopen] TOP.Core.pipeline. 15 | [sst_width] 487 16 | [signals_width] 174 17 | [sst_expanded] 1 18 | [sst_vpaned_height] 298 19 | @28 20 | TOP.Core.pipeline.clk 21 | @4023 22 | ^>1 ~/proteus/res/disas.py 23 | TOP.Core.pipeline.fetch_out_IR[31:0] 24 | [pattern_trace] 1 25 | [pattern_trace] 0 26 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/cheri/CapBus.scala: -------------------------------------------------------------------------------- 1 | package riscv.plugins.cheri 2 | 3 | import spinal.core._ 4 | import spinal.lib._ 5 | 6 | case class CapBusCmd(implicit context: Context) extends Bundle { 7 | val address = UInt(context.config.xlen bits) 8 | val write = Bool() 9 | val wdata = MemCapability() 10 | } 11 | 12 | case class CapBusRsp(implicit context: Context) extends Bundle { 13 | val rdata = MemCapability() 14 | } 15 | 16 | case class CapBus(implicit context: Context) extends Bundle with IMasterSlave { 17 | val cmd = Stream(CapBusCmd()) 18 | val rsp = Stream(CapBusRsp()) 19 | 20 | override def asMaster(): Unit = { 21 | master(cmd) 22 | slave(rsp) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/cheri/tests/CClearTag.S: -------------------------------------------------------------------------------- 1 | #include "riscv_test.h" 2 | 3 | #include "test_macros_cap.h" 4 | #include "cheri.h" 5 | 6 | RVTEST_RV32U 7 | RVTEST_CODE_BEGIN 8 | 9 | # c1 contains a root capability during this whole test 10 | CSpecialR c1, ddc; 11 | 12 | TEST_CASE_FREE(1) 13 | CClearTag c2, c1 14 | CHECK_TAG(c2, 0) 15 | CHECK_BOUNDS_EQ(c1, c2) 16 | CHECK_OFFSET_EQ(c1, c2) 17 | CHECK_PERMS_EQ(c1, c2) 18 | 19 | TEST_CASE_FREE(2) 20 | CClearTag c2, c1 21 | CClearTag c3, c2 22 | CHECK_CAP_EQ(c2, c3) 23 | 24 | TEST_PASSFAIL 25 | 26 | RVTEST_CODE_END 27 | 28 | .data 29 | RVTEST_DATA_BEGIN 30 | 31 | TEST_DATA 32 | 33 | RVTEST_DATA_END 34 | -------------------------------------------------------------------------------- /tests/crypto/djbsort-20190516/int32/portable3/sort.c: -------------------------------------------------------------------------------- 1 | #include "int32_sort.h" 2 | #define int32 int32_t 3 | 4 | #include "int32_minmax.c" 5 | 6 | void int32_sort(int32 *x,long long n) 7 | { 8 | long long top,p,q,r,i; 9 | 10 | if (n < 2) return; 11 | top = 1; 12 | while (top < n - top) top += top; 13 | 14 | for (p = top;p > 0;p >>= 1) { 15 | for (i = 0;i < n - p;++i) 16 | if (!(i & p)) 17 | int32_MINMAX(x[i],x[i+p]); 18 | i = 0; 19 | for (q = top;q > p;q >>= 1) { 20 | for (;i < n - q;++i) { 21 | if (!(i & p)) { 22 | int32 a = x[i + p]; 23 | for (r = q;r > p;r >>= 1) 24 | int32_MINMAX(a,x[i+r]); 25 | x[i + p] = a; 26 | } 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /formal/Makefile: -------------------------------------------------------------------------------- 1 | BASE_DIR = $(shell pwd) 2 | RISCV_DIR = $(BASE_DIR)/.. 3 | RISCV_FORMAL_DIR = $(BASE_DIR)/riscv-formal 4 | CORE_DIR = $(RISCV_FORMAL_DIR)/cores/riscv 5 | CORE ?= riscv.CoreFormal 6 | 7 | all: formal 8 | 9 | $(RISCV_DIR)/Core.v: FORCE 10 | cd $(RISCV_DIR); sbt "runMain $(CORE)" 11 | 12 | setup: $(RISCV_DIR)/Core.v 13 | mkdir -p $(CORE_DIR) 14 | cp $< $(CORE_DIR)/riscv.v 15 | cp checks.cfg wrapper.sv disasm.py $(CORE_DIR) 16 | cd $(CORE_DIR); python3 $(RISCV_FORMAL_DIR)/checks/genchecks.py 17 | 18 | formal: setup 19 | $(MAKE) -C $(CORE_DIR)/checks 20 | @echo "Failed tests:" 21 | find $(CORE_DIR)/checks -name trace.vcd 22 | 23 | formal-%: setup 24 | $(MAKE) -C $(CORE_DIR)/checks $(subst formal-,,$@)_ch0 25 | 26 | .PHONY: FORCE 27 | 28 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/cheri/tests/Traps.S: -------------------------------------------------------------------------------- 1 | #include "riscv_test.h" 2 | 3 | #include "test_macros_cap.h" 4 | #include "cheri.h" 5 | 6 | 7 | RVTEST_RV32U 8 | RVTEST_CODE_BEGIN 9 | 10 | TEST_CASE_START(1) 11 | CSpecialR c1, pcc 12 | la t0, trap_vec 13 | CSetOffset c1, c1, t0 14 | CSetBoundsImm c1, c1, 4 * 4 15 | CSpecialW mtcc, c1 16 | 17 | ecall 18 | j fail 19 | j test_end 20 | 21 | trap_vec: 22 | CSpecialR c2, mepcc 23 | CIncOffsetImm c2, c2, 8 24 | CSpecialW mepcc, c2 25 | mret 26 | test_end: 27 | 28 | 29 | TEST_PASSFAIL 30 | 31 | RVTEST_CODE_END 32 | 33 | .data 34 | RVTEST_DATA_BEGIN 35 | 36 | TEST_DATA 37 | 38 | RVTEST_DATA_END 39 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/cheri/MachineMode.scala: -------------------------------------------------------------------------------- 1 | package riscv.plugins.cheri 2 | 3 | import riscv._ 4 | 5 | import spinal.core._ 6 | 7 | private class RegScr(implicit context: Context) extends Area with Scr { 8 | val reg = Reg(PackedCapability()).init(PackedCapability.Null) 9 | 10 | override val needAsr: Boolean = true 11 | override def read(): Capability = reg 12 | override def write(value: Capability): Unit = reg.assignFrom(value) 13 | } 14 | 15 | class MachineMode(implicit context: Context) extends Plugin[Pipeline] { 16 | override def setup(): Unit = { 17 | val scrService = pipeline.service[ScrService] 18 | 19 | scrService.registerScr(ScrIndex.MTDC, new RegScr) 20 | scrService.registerScr(ScrIndex.MScratchC, new RegScr) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/cheri/Ccsr.scala: -------------------------------------------------------------------------------- 1 | package riscv.plugins.cheri 2 | 3 | import riscv._ 4 | 5 | import spinal.core._ 6 | 7 | class Ccsr extends Plugin[Pipeline] { 8 | 9 | override def setup(): Unit = { 10 | val csrFile = pipeline.service[CsrService] 11 | 12 | csrFile.registerCsr( 13 | 0xbc0, 14 | new Csr { 15 | val cause = Reg(UInt(5 bits)).init(0) 16 | val capIdx = Reg(UInt(6 bits)).init(0) 17 | 18 | override def read(): UInt = { 19 | (capIdx ## cause ## B"000" ## B"11").asUInt.resize(config.xlen bits) 20 | } 21 | 22 | override def write(value: UInt): Unit = { 23 | cause := value(9 downto 5) 24 | capIdx := value(15 downto 10) 25 | } 26 | } 27 | ) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/cheri/tests/CIncOffsetImm.S: -------------------------------------------------------------------------------- 1 | #include "riscv_test.h" 2 | 3 | #include "test_macros_cap.h" 4 | #include "cheri.h" 5 | 6 | #define TEST_CIncOffsetImm(testnum, cs, inc, result) \ 7 | TEST_CASE_FREE(testnum) \ 8 | CIncOffset c30, cs, inc; \ 9 | CHECK_OFFSET(c30, result); \ 10 | CHECK_TAG_EQ(cs, c30); \ 11 | CHECK_BOUNDS_EQ(cs, c30); \ 12 | CHECK_PERMS_EQ(cs, c30) 13 | 14 | RVTEST_RV32U 15 | RVTEST_CODE_BEGIN 16 | 17 | # c1 contains a root capability during this whole test 18 | CSpecialR c1, ddc; 19 | 20 | TEST_CIncOffsetImm(1, c1, 7, 7) 21 | TEST_CIncOffsetImm(2, c1, -1, 0xffffffff) 22 | 23 | TEST_PASSFAIL 24 | 25 | RVTEST_CODE_END 26 | 27 | .data 28 | RVTEST_DATA_BEGIN 29 | 30 | TEST_DATA 31 | 32 | RVTEST_DATA_END 33 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/cheri/tests/CIncOffset.S: -------------------------------------------------------------------------------- 1 | #include "riscv_test.h" 2 | 3 | #include "test_macros_cap.h" 4 | #include "cheri.h" 5 | 6 | #define TEST_CIncOffset(testnum, cs, inc, result) \ 7 | TEST_CASE_FREE(testnum) \ 8 | li t0, inc; \ 9 | CIncOffset c30, cs, t0; \ 10 | CHECK_OFFSET(c30, result); \ 11 | CHECK_TAG_EQ(cs, c30); \ 12 | CHECK_BOUNDS_EQ(cs, c30); \ 13 | CHECK_PERMS_EQ(cs, c30) 14 | 15 | RVTEST_RV32U 16 | RVTEST_CODE_BEGIN 17 | 18 | # c1 contains a root capability during this whole test 19 | CSpecialR c1, ddc; 20 | 21 | TEST_CIncOffset(1, c1, 7, 7) 22 | TEST_CIncOffset(2, c1, -1, 0xffffffff) 23 | 24 | TEST_PASSFAIL 25 | 26 | RVTEST_CODE_END 27 | 28 | .data 29 | RVTEST_DATA_BEGIN 30 | 31 | TEST_DATA 32 | 33 | RVTEST_DATA_END 34 | -------------------------------------------------------------------------------- /tests/crypto/djbsort-20190516/include/int32_sort.h: -------------------------------------------------------------------------------- 1 | #ifndef int32_sort_H 2 | #define int32_sort_H 3 | 4 | #include 5 | 6 | #define int32_sort djbsort_int32 7 | #define int32_sort_implementation djbsort_int32_implementation 8 | #define int32_sort_version djbsort_int32_version 9 | #define int32_sort_compiler djbsort_int32_compiler 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | extern void int32_sort(int32_t *,long long) __attribute__((visibility("default"))); 16 | 17 | extern const char int32_sort_implementation[] __attribute__((visibility("default"))); 18 | extern const char int32_sort_version[] __attribute__((visibility("default"))); 19 | extern const char int32_sort_compiler[] __attribute__((visibility("default"))); 20 | 21 | #ifdef __cplusplus 22 | } 23 | #endif 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-sha2/Makefile: -------------------------------------------------------------------------------- 1 | KERNEL_DIR = ../kernel 2 | HACL_STAR_DIR = ./hacl-star 3 | HACL_STAR_SRC_DIR = $(HACL_STAR_DIR)/dist/portable-gcc-compatible 4 | KREMLIN_INCLUDE_DIR = ./include 5 | KREMLIB_INCLUDE_DIR = ./include/kremlib 6 | 7 | EXTRA_CFLAGS = -I$(KREMLIN_INCLUDE_DIR) -I$(KREMLIB_INCLUDE_DIR) 8 | 9 | TARGET = sha2 10 | 11 | all: $(TARGET).bin $(TARGET).ihex $(TARGET).objdump 12 | 13 | include $(KERNEL_DIR)/Makefile.include 14 | 15 | %.S: %.c 16 | $(CC) $(CFLAGS) -o $@ -S $^ 17 | 18 | $(TARGET).elf: $(TARGET).S Hacl_Hash_SHA2.S clear.S $(EXTRA_OBJECTS) $(KERNEL_LIB) 19 | $(CC) $(CFLAGS) -T $(KERNEL_DIR)/link.ld -o $@ $^ 20 | 21 | $(TARGET).objdump: $(TARGET).elf 22 | $(OBJDUMP) -d $^ > $@ 23 | 24 | clean: 25 | rm -f *.elf *.bin *.ihex *.o *.objdump 26 | 27 | clean-all: clean 28 | rm -f *.S 29 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/cheri/tests/CInvoke.S: -------------------------------------------------------------------------------- 1 | #include "riscv_test.h" 2 | 3 | #include "test_macros_cap.h" 4 | #include "cheri.h" 5 | 6 | RVTEST_RV32U 7 | RVTEST_CODE_BEGIN 8 | 9 | INIT_ROOT_CAP 10 | 11 | TEST_CASE_START(1) 12 | la t0, test_func 13 | CSetOffset c1, ROOT, t0 14 | SEAL(c2, c1, 456) 15 | li t0, 0x100 16 | CSetOffset c3, ROOT, t0 17 | li t0, ~(1 << PERM_PERMIT_EXECUTE) 18 | CAndPerm c3, c3, t0 19 | SEAL(c4, c3, 456) 20 | CInvoke c2, c4 21 | j fail 22 | 23 | test_func: 24 | CSpecialR c5, pcc 25 | CHECK_CAP_EQ(c5, c1) 26 | CHECK_CAP_EQ(c31, c3) 27 | 28 | TEST_PASSFAIL 29 | 30 | RVTEST_CODE_END 31 | 32 | .data 33 | RVTEST_DATA_BEGIN 34 | 35 | TEST_DATA 36 | 37 | RVTEST_DATA_END 38 | -------------------------------------------------------------------------------- /tests/crypto/djbsort-20190516/include/uint32_sort.h: -------------------------------------------------------------------------------- 1 | #ifndef uint32_sort_H 2 | #define uint32_sort_H 3 | 4 | #include 5 | 6 | #define uint32_sort djbsort_uint32 7 | #define uint32_sort_implementation djbsort_uint32_implementation 8 | #define uint32_sort_version djbsort_uint32_version 9 | #define uint32_sort_compiler djbsort_uint32_compiler 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | extern void uint32_sort(uint32_t *,long long) __attribute__((visibility("default"))); 16 | 17 | extern const char uint32_sort_implementation[] __attribute__((visibility("default"))); 18 | extern const char uint32_sort_version[] __attribute__((visibility("default"))); 19 | extern const char uint32_sort_compiler[] __attribute__((visibility("default"))); 20 | 21 | #ifdef __cplusplus 22 | } 23 | #endif 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /tests/crypto/djbsort-20190516/sort_portable3_int32.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "include/int32_sort.h" 4 | #include "sort_portable.h" 5 | 6 | #define SIZE 100 // up to 1024 7 | 8 | int32_t *secret = data_int32; // Actual symbol to protect is data_int32 9 | __attribute__((section(".declassified"))) static volatile int32_t declassified[SIZE]; 10 | 11 | void declassify_secret() { 12 | long long i; 13 | for (i = 0; i < SIZE; ++i) { 14 | declassified[i] = secret[i]; 15 | } 16 | } 17 | 18 | int main() { 19 | long long i; 20 | 21 | // Sort secret array 22 | int32_sort(secret,SIZE); 23 | 24 | // Declassify secret array 25 | declassify_secret(); 26 | 27 | // Print declassified array 28 | for (i = 0; i < SIZE; ++i) { 29 | printf("%ld, ", declassified[i]); 30 | } 31 | printf("\n"); 32 | } 33 | -------------------------------------------------------------------------------- /tests/crypto/README.md: -------------------------------------------------------------------------------- 1 | **Warning:** These benchmark were compiled for a former version of the processor, where secret boundaries were hardcoded directly in the processor. Therefore, while secrets are placed in a dedicated `.secret` section, the boundaries of this region are not loaded in CSRs. Please look at the [synthetic_benchmark](../synthetic_benchmark) for an example of how to load the boundaries of the secret region in the CSRs. 2 | 3 | If you decide to recompile these benchmarks, please note that the assembly code was manually patched to clear secret values from registers after declassification (see [`clear.S`](./curve25519/clear.S) files). You'll likely have to do this too if you want to declassify secrets. 4 | 5 | If you want to experiment with these programs on Proteus, you'll need to fix this compatibility issue. If you do so, we'll be happy to take a pull request. 6 | -------------------------------------------------------------------------------- /tests/crypto/curve25519/Makefile: -------------------------------------------------------------------------------- 1 | KERNEL_DIR = ../kernel 2 | HACL_STAR_DIR = ./hacl-star 3 | HACL_STAR_SRC_DIR = $(HACL_STAR_DIR)/dist/portable-gcc-compatible 4 | KREMLIN_INCLUDE_DIR = ./include 5 | KREMLIB_INCLUDE_DIR = ./include/kremlib 6 | 7 | EXTRA_CFLAGS = -I$(KREMLIN_INCLUDE_DIR) -I$(KREMLIB_INCLUDE_DIR) 8 | 9 | TARGET = curve25519 10 | DEPS = Curve25519-donna 11 | # DEPS = Hacl_Curve25519_51 12 | 13 | all: $(TARGET).bin $(TARGET).ihex $(TARGET).objdump 14 | 15 | include $(KERNEL_DIR)/Makefile.include 16 | 17 | %.S: %.c 18 | $(CC) $(CFLAGS) -o $@ -S $^ 19 | 20 | $(TARGET).elf: $(TARGET).S $(DEPS).S clear.S $(EXTRA_OBJECTS) $(KERNEL_LIB) 21 | $(CC) $(CFLAGS) -T $(KERNEL_DIR)/link.ld -o $@ $^ 22 | 23 | $(TARGET).objdump: $(TARGET).elf 24 | $(OBJDUMP) -d $^ > $@ 25 | 26 | clean: 27 | rm -f *.elf *.bin *.ihex *.o *.objdump 28 | 29 | clean-all: clean 30 | rm -f $(TARGET).S $(DEPS).S 31 | -------------------------------------------------------------------------------- /tests/synthetic-benchmark/include/kremlib/LowStar_Endianness.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) INRIA and Microsoft Corporation. All rights reserved. 3 | Licensed under the Apache 2.0 License. 4 | */ 5 | 6 | 7 | #ifndef __LowStar_Endianness_H 8 | #define __LowStar_Endianness_H 9 | #include 10 | #include 11 | #include "kremlin/internal/compat.h" 12 | #include "kremlin/lowstar_endianness.h" 13 | #include "kremlin/internal/types.h" 14 | #include "kremlin/internal/target.h" 15 | 16 | 17 | #include "FStar_UInt128.h" 18 | 19 | static inline void store128_le(uint8_t *x0, FStar_UInt128_uint128 x1); 20 | 21 | static inline FStar_UInt128_uint128 load128_le(uint8_t *x0); 22 | 23 | static inline void store128_be(uint8_t *x0, FStar_UInt128_uint128 x1); 24 | 25 | static inline FStar_UInt128_uint128 load128_be(uint8_t *x0); 26 | 27 | 28 | #define __LowStar_Endianness_H_DEFINED 29 | #endif 30 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-chacha20/include/kremlib/LowStar_Endianness.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) INRIA and Microsoft Corporation. All rights reserved. 3 | Licensed under the Apache 2.0 License. 4 | */ 5 | 6 | 7 | #ifndef __LowStar_Endianness_H 8 | #define __LowStar_Endianness_H 9 | #include 10 | #include 11 | #include "kremlin/internal/compat.h" 12 | #include "kremlin/lowstar_endianness.h" 13 | #include "kremlin/internal/types.h" 14 | #include "kremlin/internal/target.h" 15 | 16 | 17 | #include "FStar_UInt128.h" 18 | 19 | static inline void store128_le(uint8_t *x0, FStar_UInt128_uint128 x1); 20 | 21 | static inline FStar_UInt128_uint128 load128_le(uint8_t *x0); 22 | 23 | static inline void store128_be(uint8_t *x0, FStar_UInt128_uint128 x1); 24 | 25 | static inline FStar_UInt128_uint128 load128_be(uint8_t *x0); 26 | 27 | 28 | #define __LowStar_Endianness_H_DEFINED 29 | #endif 30 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-sha2/include/kremlib/LowStar_Endianness.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) INRIA and Microsoft Corporation. All rights reserved. 3 | Licensed under the Apache 2.0 License. 4 | */ 5 | 6 | 7 | #ifndef __LowStar_Endianness_H 8 | #define __LowStar_Endianness_H 9 | #include 10 | #include 11 | #include "kremlin/internal/compat.h" 12 | #include "kremlin/lowstar_endianness.h" 13 | #include "kremlin/internal/types.h" 14 | #include "kremlin/internal/target.h" 15 | 16 | 17 | #include "FStar_UInt128.h" 18 | 19 | static inline void store128_le(uint8_t *x0, FStar_UInt128_uint128 x1); 20 | 21 | static inline FStar_UInt128_uint128 load128_le(uint8_t *x0); 22 | 23 | static inline void store128_be(uint8_t *x0, FStar_UInt128_uint128 x1); 24 | 25 | static inline FStar_UInt128_uint128 load128_be(uint8_t *x0); 26 | 27 | 28 | #define __LowStar_Endianness_H_DEFINED 29 | #endif 30 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/cheri/CapIdx.scala: -------------------------------------------------------------------------------- 1 | package riscv.plugins.cheri 2 | 3 | import spinal.core._ 4 | 5 | class CapIdx extends Bundle { 6 | private val idx = Bits(6 bits) 7 | 8 | def assignFromScr(scr: UInt): Unit = { 9 | idx.msb := True 10 | idx(4 downto 0) := scr.asBits 11 | } 12 | 13 | def assignFromGpcr(cr: UInt): Unit = { 14 | assert(cr.getBitsWidth <= 5) 15 | idx := cr.asBits.resize(getBitsWidth bits) 16 | } 17 | 18 | def asUInt: UInt = idx.asUInt 19 | } 20 | 21 | object CapIdx { 22 | def apply(): CapIdx = new CapIdx 23 | 24 | def scr(scr: UInt): CapIdx = { 25 | val idx = new CapIdx() 26 | idx.assignFromScr(scr) 27 | idx 28 | } 29 | 30 | def scr(scr: Int): CapIdx = { 31 | this.scr(U(scr, 5 bits)) 32 | } 33 | 34 | def gpcr(cr: UInt): CapIdx = { 35 | val idx = new CapIdx() 36 | idx.assignFromGpcr(cr) 37 | idx 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/cheri/tests/CSetOffset.S: -------------------------------------------------------------------------------- 1 | #include "riscv_test.h" 2 | 3 | #include "test_macros_cap.h" 4 | #include "cheri.h" 5 | 6 | RVTEST_RV32U 7 | RVTEST_CODE_BEGIN 8 | 9 | # c1 contains a root capability during this whole test 10 | CSpecialR c1, ddc; 11 | 12 | TEST_CASE_FREE(1) 13 | li t0, 7 14 | CSetOffset c2, c1, t0 15 | CHECK_OFFSET(c2, 7) 16 | CHECK_TAG_EQ(c1, c2) 17 | CHECK_BOUNDS_EQ(c1, c2) 18 | CHECK_PERMS_EQ(c1, c2) 19 | 20 | TEST_CASE_FREE(2) 21 | CSetBounds c2, c1, zero 22 | li t0, 7 23 | CSetOffset c3, c2, t0 24 | CHECK_OFFSET(c3, 7) 25 | CHECK_TAG_EQ(c2, c3) 26 | CHECK_BOUNDS_EQ(c2, c3) 27 | CHECK_PERMS_EQ(c2, c3) 28 | 29 | TEST_PASSFAIL 30 | 31 | RVTEST_CODE_END 32 | 33 | .data 34 | RVTEST_DATA_BEGIN 35 | 36 | TEST_DATA 37 | 38 | RVTEST_DATA_END 39 | -------------------------------------------------------------------------------- /sim/Makefile: -------------------------------------------------------------------------------- 1 | CORE ?= riscv.CoreExtMem 2 | 3 | BASE_DIR = .. 4 | BUILD_DIR = build 5 | TOPLEVEL_MODULE = Core 6 | VERILOG_FILE_NAME = $(TOPLEVEL_MODULE).v 7 | VERILOG_INPUT = $(BUILD_DIR)/$(VERILOG_FILE_NAME) 8 | VERILATOR_NAME = V$(TOPLEVEL_MODULE) 9 | EXE_NAME = sim 10 | EXE_FILE = $(BUILD_DIR)/$(EXE_NAME) 11 | 12 | all: $(EXE_FILE) 13 | 14 | $(EXE_FILE): $(BUILD_DIR)/$(VERILATOR_NAME).mk main.cpp 15 | make -C $(BUILD_DIR) -f $(VERILATOR_NAME).mk $(EXE_NAME) 16 | 17 | $(BUILD_DIR)/$(VERILATOR_NAME).mk: $(VERILOG_INPUT) 18 | verilator --cc --exe --trace -O3 -CFLAGS "-O3 -std=c++11" -Wno-WIDTH -Wno-UNOPTFLAT -Wno-CMPCONST -Wno-UNSIGNED -Mdir $(BUILD_DIR) $(VERILOG_INPUT) main.cpp -o $(EXE_NAME) 19 | 20 | $(VERILOG_INPUT): $(BASE_DIR)/$(VERILOG_FILE_NAME) 21 | mkdir -p $(@D) 22 | cp $< $@ 23 | 24 | $(BASE_DIR)/$(VERILOG_FILE_NAME): FORCE 25 | cd $(BASE_DIR); sbt "runMain $(CORE)" 26 | 27 | FORCE: 28 | 29 | clean: 30 | rm -rf $(BUILD_DIR) 31 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/cheri/tests/CSetBoundsImm.S: -------------------------------------------------------------------------------- 1 | #include "riscv_test.h" 2 | 3 | #include "test_macros_cap.h" 4 | 5 | #define SET_BOUNDS(cs, imm) \ 6 | CSetBoundsImm c31, cs, imm; \ 7 | 8 | #define TEST_CSetBoundsImm_NO_CHANGE(testnum, cs, imm) \ 9 | TEST_CASE_CAP_EQ(testnum, c31, cs, SET_BOUNDS(cs, imm)) 10 | 11 | #define TEST_CSetBoundsImm_NEW_BOUNDS_OFFSET(testnum, cs, imm, base, len, offset) \ 12 | TEST_CASE_CAP_NEW_BOUNDS_OFFSET(testnum, c31, cs, base, len, offset, SET_BOUNDS(cs, imm)) 13 | 14 | RVTEST_RV32U 15 | RVTEST_CODE_BEGIN 16 | 17 | # c1 contains a root capability during this whole test 18 | CSpecialR c1, ddc; 19 | 20 | TEST_CSetBoundsImm_NEW_BOUNDS_OFFSET(1, c1, 0x4, 0, 0x4, 0) 21 | TEST_CSetBoundsImm_NEW_BOUNDS_OFFSET(2, c1, 0xfff, 0, 0xfff, 0) 22 | 23 | TEST_PASSFAIL 24 | 25 | RVTEST_CODE_END 26 | 27 | .data 28 | RVTEST_DATA_BEGIN 29 | 30 | TEST_DATA 31 | 32 | RVTEST_DATA_END 33 | -------------------------------------------------------------------------------- /tests/spectre-tests/secret-after-branch.s: -------------------------------------------------------------------------------- 1 | .globl _start 2 | .data 3 | public_value: .word 0 4 | public_address: .word 0 5 | secret: .word 0xDEAD0 6 | 7 | .text 8 | _start: 9 | 10 | setup: 11 | # public_address = &public_value; 12 | 13 | la t0, public_value 14 | la t1, public_address 15 | sw t0, (t1) 16 | 17 | # lower_boundary = &secret 18 | # upper_boundary = &secret + 4 19 | 20 | la t0, secret 21 | csrrw zero, 0x707, t0 22 | addi t0, t0, 4 23 | csrrw zero, 0x708, t0 24 | 25 | condition: 26 | # t0 = *public_address 27 | # t0 = *t0 28 | # if (t0 == 0) { goto finish; } 29 | 30 | la t0, public_address 31 | lw t0, (t0) 32 | lw t0, (t0) 33 | beqz t0, finish 34 | 35 | # ----- BEGIN TRANSIENT BLOCK ----- 36 | 37 | # t6 = *secret; 38 | # leak(t6); 39 | 40 | la t6, secret 41 | lw t6, (t6) 42 | lw zero, (t6) 43 | 44 | # ----- END TRANSIENT BLOCK ----- 45 | 46 | finish: 47 | lui ra,0x10000 48 | li sp,4 49 | sb sp,0(ra) 50 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-chacha20/Makefile: -------------------------------------------------------------------------------- 1 | KERNEL_DIR = ../kernel 2 | HACL_STAR_DIR = ./hacl-star 3 | KREMLIN_INCLUDE_DIR = ./include 4 | KREMLIB_INCLUDE_DIR = ./include/kremlib 5 | 6 | # VPATH = $(HACL_STAR_SRC_DIR) 7 | EXTRA_CFLAGS = -I$(KREMLIN_INCLUDE_DIR) -I$(KREMLIB_INCLUDE_DIR) 8 | 9 | TARGET = chacha20 10 | DEP = Hacl_Chacha20 11 | 12 | all: $(TARGET).bin $(TARGET).ihex $(TARGET).objdump 13 | 14 | include $(KERNEL_DIR)/Makefile.include 15 | 16 | %.S: %.c 17 | $(CC) $(CFLAGS) -o $@ -S $^ 18 | 19 | # $(TARGET).elf: $(TARGET).o $(DEP).o $(EXTRA_OBJECTS) $(KERNEL_LIB) 20 | # $(CC) $(CFLAGS) -T $(KERNEL_DIR)/link.ld -o $@ $^ 21 | 22 | $(TARGET).elf: $(TARGET).S $(DEP).S clear.S $(EXTRA_OBJECTS) $(KERNEL_LIB) 23 | $(CC) $(CFLAGS) -T $(KERNEL_DIR)/link.ld -o $@ $^ 24 | 25 | $(TARGET).objdump: $(TARGET).elf 26 | $(OBJDUMP) -d $^ > $@ 27 | 28 | clean: 29 | rm -f *.elf *.bin *.ihex *.o *.objdump 30 | 31 | clean-all: clean 32 | rm -f $(TARGET).S $(DEP).S 33 | -------------------------------------------------------------------------------- /tests/spectre-tests/secret-before-branch.s: -------------------------------------------------------------------------------- 1 | .globl _start 2 | .data 3 | public_value: .word 0 4 | public_address: .word 0 5 | secret: .word 0xDEAD0 6 | 7 | .text 8 | _start: 9 | 10 | setup: 11 | # public_address = &public_value; 12 | 13 | la t0, public_value 14 | la t1, public_address 15 | sw t0, (t1) 16 | 17 | # lower_boundary = &secret 18 | # upper_boundary = &secret + 4 19 | 20 | la t0, secret 21 | csrrw zero, 0x707, t0 22 | addi t0, t0, 4 23 | csrrw zero, 0x708, t0 24 | 25 | nop 26 | nop 27 | 28 | # s0 = *secret // load secret architecturally 29 | lw s0, secret 30 | 31 | condition: 32 | # t0 = *public_address 33 | # t0 = *t0 34 | # if (t0 == 0) { goto finish; } 35 | 36 | la t0, public_address 37 | lw t0, (t0) 38 | lw t0, (t0) 39 | beqz t0, finish 40 | 41 | # ----- BEGIN TRANSIENT BLOCK ----- 42 | 43 | # leak(s0);. 44 | 45 | lw zero, (s0) 46 | 47 | # ----- END TRANSIENT BLOCK ----- 48 | 49 | finish: 50 | lui ra,0x10000 51 | li sp,4 52 | sb sp,0(ra) 53 | 54 | -------------------------------------------------------------------------------- /src/main/scala/riscv/sim/StdioByteDev.scala: -------------------------------------------------------------------------------- 1 | package riscv.sim 2 | 3 | import riscv.soc.devices._ 4 | 5 | import spinal.core.sim._ 6 | 7 | class StdioByteDev(io: ByteDevIo) { 8 | private var currentStdinByte: Option[Byte] = None 9 | 10 | private def rdataTrigger: Seq[Any] = { 11 | Seq(currentStdinByte, io.rdata.ready.toBoolean) 12 | } 13 | 14 | io.rdata.valid #= false 15 | 16 | forkSensitive(rdataTrigger) { 17 | currentStdinByte.foreach { byte => 18 | io.rdata.valid #= true 19 | io.rdata.payload #= byte 20 | 21 | if (io.rdata.ready.toBoolean) { 22 | currentStdinByte = None 23 | } 24 | } 25 | } 26 | 27 | def eval(): Unit = { 28 | io.rdata.valid #= false 29 | 30 | if (io.wdata.valid.toBoolean) { 31 | val byte = io.wdata.payload.toInt.toByte 32 | System.out.write(byte) 33 | } 34 | 35 | if (currentStdinByte.isEmpty && System.in.available() > 0) { 36 | currentStdinByte = Some(System.in.read().toByte) 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/cheri/tests/CAndPerm.S: -------------------------------------------------------------------------------- 1 | #include "riscv_test.h" 2 | 3 | #include "test_macros_cap.h" 4 | #include "cheri.h" 5 | 6 | #define CHECK_CAP_MASKED_PERM(cd, cs, perm_mask) \ 7 | CHECK_TAG_EQ(cd, cs); \ 8 | CHECK_BOUNDS_EQ(cd, cs); \ 9 | CHECK_OFFSET_EQ(cd, cs); \ 10 | CGetPerm t0, cs; \ 11 | li t1, perm_mask; \ 12 | and t0, t0, t1; \ 13 | CGetPerm t1, cd; \ 14 | bne t0, t1, fail; 15 | 16 | #define TEST_AND_PERM(testnum, cs, mask) \ 17 | TEST_CASE_FREE(testnum) \ 18 | li t0, mask; \ 19 | CAndPerm c31, cs, t0; \ 20 | CHECK_CAP_MASKED_PERM(c31, cs, mask) 21 | 22 | RVTEST_RV32U 23 | RVTEST_CODE_BEGIN 24 | 25 | # c1 contains a root capability during this whole test 26 | CSpecialR c1, ddc; 27 | 28 | TEST_AND_PERM(1, c1, 0x0); 29 | TEST_AND_PERM(2, c1, 0xffffffff); 30 | TEST_AND_PERM(3, c1, (1 << PERM_PERMIT_LOAD)); 31 | 32 | TEST_PASSFAIL 33 | 34 | RVTEST_CODE_END 35 | 36 | .data 37 | RVTEST_DATA_BEGIN 38 | 39 | TEST_DATA 40 | 41 | RVTEST_DATA_END 42 | -------------------------------------------------------------------------------- /tests/crypto/curve25519/clear.S: -------------------------------------------------------------------------------- 1 | .option nopic 2 | .attribute arch, "rv32i2p0_m2p0" 3 | .attribute unaligned_access, 0 4 | .attribute stack_align, 16 5 | .text 6 | .align 2 7 | .globl clear_t_regs 8 | .type clear_t_regs, @function 9 | clear_t_regs: 10 | li t0,0 11 | li t1,0 12 | li t2,0 13 | li t3,0 14 | li t4,0 15 | li t5,0 16 | li t6,0 17 | li a0,0 18 | li a1,0 19 | li a2,0 20 | li a3,0 21 | li a4,0 22 | li a5,0 23 | li a6,0 24 | li a7,0 25 | ret 26 | 27 | .globl clear_s_regs 28 | .type clear_s_regs, @function 29 | clear_s_regs: 30 | li s0,0 31 | li s1,0 32 | li s2,0 33 | li s3,0 34 | li s4,0 35 | li s5,0 36 | li s6,0 37 | li s7,0 38 | li s8,0 39 | li s9,0 40 | li s10,0 41 | li s11,0 42 | ret 43 | 44 | .globl clear_all_regs 45 | .type clear_all_regs, @function 46 | clear_all_regs: 47 | addi sp,sp,-4 48 | sw ra,0(sp) 49 | jal clear_t_regs 50 | jal clear_s_regs 51 | lw ra,0(sp) 52 | addi sp,sp,4 53 | -------------------------------------------------------------------------------- /tests/crypto/djbsort-20190516/clear.S: -------------------------------------------------------------------------------- 1 | .option nopic 2 | .attribute arch, "rv32i2p0_m2p0" 3 | .attribute unaligned_access, 0 4 | .attribute stack_align, 16 5 | .text 6 | .align 2 7 | .globl clear_t_regs 8 | .type clear_t_regs, @function 9 | clear_t_regs: 10 | li t0,0 11 | li t1,0 12 | li t2,0 13 | li t3,0 14 | li t4,0 15 | li t5,0 16 | li t6,0 17 | li a0,0 18 | li a1,0 19 | li a2,0 20 | li a3,0 21 | li a4,0 22 | li a5,0 23 | li a6,0 24 | li a7,0 25 | ret 26 | 27 | .globl clear_s_regs 28 | .type clear_s_regs, @function 29 | clear_s_regs: 30 | li s0,0 31 | li s1,0 32 | li s2,0 33 | li s3,0 34 | li s4,0 35 | li s5,0 36 | li s6,0 37 | li s7,0 38 | li s8,0 39 | li s9,0 40 | li s10,0 41 | li s11,0 42 | ret 43 | 44 | .globl clear_all_regs 45 | .type clear_all_regs, @function 46 | clear_all_regs: 47 | addi sp,sp,-4 48 | sw ra,0(sp) 49 | jal clear_t_regs 50 | jal clear_s_regs 51 | lw ra,0(sp) 52 | addi sp,sp,4 53 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-sha2/clear.S: -------------------------------------------------------------------------------- 1 | .option nopic 2 | .attribute arch, "rv32i2p0_m2p0" 3 | .attribute unaligned_access, 0 4 | .attribute stack_align, 16 5 | .text 6 | .align 2 7 | .globl clear_t_regs 8 | .type clear_t_regs, @function 9 | clear_t_regs: 10 | li t0,0 11 | li t1,0 12 | li t2,0 13 | li t3,0 14 | li t4,0 15 | li t5,0 16 | li t6,0 17 | li a0,0 18 | li a1,0 19 | li a2,0 20 | li a3,0 21 | li a4,0 22 | li a5,0 23 | li a6,0 24 | li a7,0 25 | ret 26 | 27 | .globl clear_s_regs 28 | .type clear_s_regs, @function 29 | clear_s_regs: 30 | li s0,0 31 | li s1,0 32 | li s2,0 33 | li s3,0 34 | li s4,0 35 | li s5,0 36 | li s6,0 37 | li s7,0 38 | li s8,0 39 | li s9,0 40 | li s10,0 41 | li s11,0 42 | ret 43 | 44 | .globl clear_all_regs 45 | .type clear_all_regs, @function 46 | clear_all_regs: 47 | addi sp,sp,-4 48 | sw ra,0(sp) 49 | jal clear_t_regs 50 | jal clear_s_regs 51 | lw ra,0(sp) 52 | addi sp,sp,4 53 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-chacha20/clear.S: -------------------------------------------------------------------------------- 1 | .option nopic 2 | .attribute arch, "rv32i2p0_m2p0" 3 | .attribute unaligned_access, 0 4 | .attribute stack_align, 16 5 | .text 6 | .align 2 7 | .globl clear_t_regs 8 | .type clear_t_regs, @function 9 | clear_t_regs: 10 | li t0,0 11 | li t1,0 12 | li t2,0 13 | li t3,0 14 | li t4,0 15 | li t5,0 16 | li t6,0 17 | li a0,0 18 | li a1,0 19 | li a2,0 20 | li a3,0 21 | li a4,0 22 | li a5,0 23 | li a6,0 24 | li a7,0 25 | ret 26 | 27 | .globl clear_s_regs 28 | .type clear_s_regs, @function 29 | clear_s_regs: 30 | li s0,0 31 | li s1,0 32 | li s2,0 33 | li s3,0 34 | li s4,0 35 | li s5,0 36 | li s6,0 37 | li s7,0 38 | li s8,0 39 | li s9,0 40 | li s10,0 41 | li s11,0 42 | ret 43 | 44 | .globl clear_all_regs 45 | .type clear_all_regs, @function 46 | clear_all_regs: 47 | addi sp,sp,-4 48 | sw ra,0(sp) 49 | jal clear_t_regs 50 | jal clear_s_regs 51 | lw ra,0(sp) 52 | addi sp,sp,4 53 | -------------------------------------------------------------------------------- /src/main/scala/riscv/Config.scala: -------------------------------------------------------------------------------- 1 | package riscv 2 | 3 | sealed trait BaseIsa { 4 | val xlen: Int 5 | val numRegs: Int 6 | } 7 | 8 | object BaseIsa { 9 | case object RV32I extends BaseIsa { 10 | override val xlen = 32 11 | override val numRegs = 32 12 | } 13 | case object RV32E extends BaseIsa { 14 | override val xlen = 32 15 | override val numRegs = 16 16 | } 17 | case object RV64I extends BaseIsa { 18 | override val xlen = 64 19 | override val numRegs = 32 20 | } 21 | } 22 | 23 | class Config(val baseIsa: BaseIsa, val debug: Boolean = true) { 24 | def xlen = baseIsa.xlen 25 | def numRegs = baseIsa.xlen 26 | 27 | def ibusConfig = MemBusConfig( 28 | addressWidth = baseIsa.xlen, 29 | dataWidth = baseIsa.xlen, 30 | readWrite = false 31 | ) 32 | def readDbusConfig = MemBusConfig( 33 | addressWidth = baseIsa.xlen, 34 | dataWidth = baseIsa.xlen, 35 | readWrite = false 36 | ) 37 | def dbusConfig = MemBusConfig( 38 | addressWidth = baseIsa.xlen, 39 | dataWidth = baseIsa.xlen 40 | ) 41 | } 42 | -------------------------------------------------------------------------------- /res/disas.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import subprocess 5 | import tempfile 6 | 7 | 8 | objdump = 'riscv32-unknown-elf-objdump' 9 | 10 | def output(line): 11 | print(line, flush=True) 12 | 13 | for line in sys.stdin: 14 | hexstring = line.strip() 15 | instruction = bytes(reversed(bytes.fromhex(hexstring))) 16 | assert len(instruction) == 4 17 | 18 | with tempfile.NamedTemporaryFile() as f: 19 | f.write(instruction) 20 | f.flush() 21 | proc = subprocess.run([objdump, '-b', 'binary', '-m', 'riscv', '-D', '-M', 'no-aliases', f.name], 22 | stdout=subprocess.PIPE, stderr=subprocess.PIPE, 23 | universal_newlines=True) 24 | 25 | if proc.returncode != 0: 26 | output('???') 27 | else: 28 | for line in proc.stdout.split('\n'): 29 | parts = line.split() 30 | 31 | if len(parts) >= 3 and parts[0] == '0:': 32 | output(' '.join(parts[2:])) 33 | break 34 | else: 35 | output('???') 36 | 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Proteus developers 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/main/scala/riscv/Plugin.scala: -------------------------------------------------------------------------------- 1 | package riscv 2 | 3 | import spinal.core._ 4 | 5 | abstract class Plugin[-PipelineT <: Pipeline] { 6 | protected[this] var pipeline: PipelineT = _ 7 | implicit def config = pipeline.config 8 | 9 | def setPipeline(pipeline: PipelineT): Unit = { 10 | assert(this.pipeline == null) 11 | this.pipeline = pipeline 12 | } 13 | 14 | def getName = getClass.getSimpleName.replace("$", "") 15 | def setup(): Unit = () 16 | def build(): Unit = () 17 | def finish(): Unit = () 18 | 19 | implicit class PlugComponent(component: Component) { 20 | def plug[T](logic: => T): T = component.rework { 21 | val result = logic 22 | 23 | result match { 24 | case component: Component => component.setName(getName) 25 | case area: Area => area.setName(getName).reflectNames() 26 | case _ => 27 | } 28 | 29 | result 30 | } 31 | } 32 | 33 | implicit class PlugPipeline(pipeline: Pipeline) { 34 | def plug[T](logic: => T): T = pipeline.pipelineComponent plug logic 35 | } 36 | 37 | def getImplementedExtensions: Seq[Extension] = Seq() 38 | implicit def charToExtension(char: Char) = Extension(char) 39 | } 40 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/cheri/tests/CSetBounds.S: -------------------------------------------------------------------------------- 1 | #include "riscv_test.h" 2 | 3 | #include "test_macros_cap.h" 4 | #include "cheri.h" 5 | 6 | #define SET_BOUNDS(cs, rs_val) \ 7 | li x1, rs_val; \ 8 | CSetBounds c31, cs, x1; \ 9 | 10 | #define TEST_CSetBounds_NO_CHANGE(testnum, cs, rs_val) \ 11 | TEST_CASE_CAP_EQ(testnum, c31, cs, SET_BOUNDS(cs, rs_val)) 12 | 13 | #define TEST_CSetBounds_NEW_BOUNDS_OFFSET(testnum, cs, rs_val, base, len, offset) \ 14 | TEST_CASE_CAP_NEW_BOUNDS_OFFSET(testnum, c31, cs, base, len, offset, SET_BOUNDS(cs, rs_val)) 15 | 16 | RVTEST_RV32U 17 | RVTEST_CODE_BEGIN 18 | 19 | # c1 contains a root capability during this whole test 20 | CSpecialR c1, ddc; 21 | 22 | TEST_CSetBounds_NO_CHANGE(1, c1, -1) 23 | TEST_CSetBounds_NEW_BOUNDS_OFFSET(2, c1, 4, 0, 4, 0) 24 | 25 | TEST_EXPECT_EXCEPTION(3, CAUSE_TAG_VIOLATION, 0, CSetBounds c0, c0, zero) 26 | 27 | TEST_CASE_FREE(4) 28 | CSetBounds c2, c1, zero 29 | EXPECT_EXCEPTION(CAUSE_LENGTH_VIOLATION, 2, CSetBounds c0, c2, 1) 30 | 31 | TEST_PASSFAIL 32 | 33 | RVTEST_CODE_END 34 | 35 | .data 36 | RVTEST_DATA_BEGIN 37 | 38 | TEST_DATA 39 | 40 | RVTEST_DATA_END 41 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-sha2/include/kremlib.h: -------------------------------------------------------------------------------- 1 | #ifndef __KREMLIB_H 2 | #define __KREMLIB_H 3 | 4 | /******************************************************************************/ 5 | /* The all-in-one kremlib.h header */ 6 | /******************************************************************************/ 7 | 8 | /* This is a meta-header that is included by default in KreMLin generated 9 | * programs. If you wish to have a more lightweight set of headers, or are 10 | * targeting an environment where controlling these macros yourself is 11 | * important, consider using: 12 | * 13 | * krml -minimal 14 | * 15 | * to disable the inclusion of this file (note: this also disables the default 16 | * argument "-bundle FStar.*"). You can then include the headers of your choice 17 | * one by one, using -add-early-include. */ 18 | 19 | #include "kremlin/internal/target.h" 20 | #include "kremlin/internal/callconv.h" 21 | #include "kremlin/internal/builtin.h" 22 | #include "kremlin/internal/debug.h" 23 | #include "kremlin/internal/types.h" 24 | 25 | #include "kremlin/lowstar_endianness.h" 26 | #include "kremlin/fstar_int.h" 27 | 28 | #endif /* __KREMLIB_H */ 29 | -------------------------------------------------------------------------------- /tests/synthetic-benchmark/include/kremlib.h: -------------------------------------------------------------------------------- 1 | #ifndef __KREMLIB_H 2 | #define __KREMLIB_H 3 | 4 | /******************************************************************************/ 5 | /* The all-in-one kremlib.h header */ 6 | /******************************************************************************/ 7 | 8 | /* This is a meta-header that is included by default in KreMLin generated 9 | * programs. If you wish to have a more lightweight set of headers, or are 10 | * targeting an environment where controlling these macros yourself is 11 | * important, consider using: 12 | * 13 | * krml -minimal 14 | * 15 | * to disable the inclusion of this file (note: this also disables the default 16 | * argument "-bundle FStar.*"). You can then include the headers of your choice 17 | * one by one, using -add-early-include. */ 18 | 19 | #include "kremlin/internal/target.h" 20 | #include "kremlin/internal/callconv.h" 21 | #include "kremlin/internal/builtin.h" 22 | #include "kremlin/internal/debug.h" 23 | #include "kremlin/internal/types.h" 24 | 25 | #include "kremlin/lowstar_endianness.h" 26 | #include "kremlin/fstar_int.h" 27 | 28 | #endif /* __KREMLIB_H */ 29 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-chacha20/include/kremlib.h: -------------------------------------------------------------------------------- 1 | #ifndef __KREMLIB_H 2 | #define __KREMLIB_H 3 | 4 | /******************************************************************************/ 5 | /* The all-in-one kremlib.h header */ 6 | /******************************************************************************/ 7 | 8 | /* This is a meta-header that is included by default in KreMLin generated 9 | * programs. If you wish to have a more lightweight set of headers, or are 10 | * targeting an environment where controlling these macros yourself is 11 | * important, consider using: 12 | * 13 | * krml -minimal 14 | * 15 | * to disable the inclusion of this file (note: this also disables the default 16 | * argument "-bundle FStar.*"). You can then include the headers of your choice 17 | * one by one, using -add-early-include. */ 18 | 19 | #include "kremlin/internal/target.h" 20 | #include "kremlin/internal/callconv.h" 21 | #include "kremlin/internal/builtin.h" 22 | #include "kremlin/internal/debug.h" 23 | #include "kremlin/internal/types.h" 24 | 25 | #include "kremlin/lowstar_endianness.h" 26 | #include "kremlin/fstar_int.h" 27 | 28 | #endif /* __KREMLIB_H */ 29 | -------------------------------------------------------------------------------- /src/main/scala/riscv/PipelineData.scala: -------------------------------------------------------------------------------- 1 | package riscv 2 | 3 | import spinal.core._ 4 | 5 | class PipelineData[T <: Data](val dataType: HardType[T]) { 6 | def name: String = getClass.getSimpleName.takeWhile(_ != '$') 7 | 8 | override def toString: String = name 9 | } 10 | 11 | class StandardPipelineData(config: Config) { 12 | private val xlen = config.xlen 13 | 14 | object PC extends PipelineData(UInt(xlen bits)) 15 | object NEXT_PC extends PipelineData(UInt(xlen bits)) 16 | object IR extends PipelineData(UInt(32 bits)) 17 | object RS1 extends PipelineData(UInt(5 bits)) 18 | object RS1_DATA extends PipelineData(UInt(xlen bits)) 19 | object RS1_TYPE extends PipelineData(RegisterType()) 20 | object RS2 extends PipelineData(UInt(5 bits)) 21 | object RS2_DATA extends PipelineData(UInt(xlen bits)) 22 | object RS2_TYPE extends PipelineData(RegisterType()) 23 | object RD extends PipelineData(UInt(5 bits)) 24 | object RD_DATA extends PipelineData(UInt(xlen bits)) 25 | object RD_TYPE extends PipelineData(RegisterType()) 26 | object RD_DATA_VALID extends PipelineData(Bool()) 27 | object IMM extends PipelineData(UInt(32 bits)) 28 | object IMM_USED extends PipelineData(Bool()) 29 | } 30 | -------------------------------------------------------------------------------- /tests/crypto/djbsort-20190516/Makefile: -------------------------------------------------------------------------------- 1 | KERNEL_DIR = ../kernel 2 | EXTRA_CFLAGS = -I./include 3 | 4 | all: sort_portable3_int32.bin sort_portable3_int32.ihex sort_portable3_int32.objdump 5 | 6 | # all: sort_portable3_int32.bin sort_portable3_int32.ihex\ 7 | # sort_portable3_uint32.bin sort_portable3_uint32.ihex\ 8 | # sort_portable4_int32.bin sort_portable4_int32.ihex\ 9 | # sort_portable4_uint32.bin sort_portable4_uint32.ihex 10 | 11 | include $(KERNEL_DIR)/Makefile.include 12 | 13 | %.elf: %.S clear.S $(EXTRA_OBJECTS) $(KERNEL_LIB) 14 | $(CC) $(CFLAGS) -T $(KERNEL_DIR)/link.ld -o $@ $^ 15 | 16 | sort_portable3_int32.elf: int32/portable3/sort.S 17 | 18 | # sort_portable3_int32.elf: sort_portable3_int32.S int32/portable3/sort.S clear.S $(EXTRA_OBJECTS) $(KERNEL_LIB) 19 | # $(CC) $(CFLAGS) -T $(KERNEL_DIR)/link.ld -o $@ $^ 20 | sort_portable3_uint32.elf: uint32/portable3/sort.S int32/portable3/sort.S 21 | sort_portable4_int32.elf: int32/portable4/sort.S 22 | sort_portable4_uint32.elf: uint32/portable4/sort.S int32/portable4/sort.S 23 | 24 | %.S: %.c 25 | $(CC) $(CFLAGS) -o $@ -S $^ 26 | 27 | %.objdump: %.elf 28 | $(OBJDUMP) $^ -d > $@ 29 | 30 | clean: 31 | rm -f *.elf *.bin *.ihex *.o *.objdump *.binsec 32 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/cheri/tests/Scr.S: -------------------------------------------------------------------------------- 1 | #include "riscv_test.h" 2 | 3 | #include "test_macros_cap.h" 4 | #include "cheri.h" 5 | 6 | RVTEST_RV32U 7 | RVTEST_CODE_BEGIN 8 | 9 | # c1 contains a root capability during this whole test 10 | CSpecialR c1, ddc; 11 | 12 | TEST_CASE_CAP_EQ(1, c1, c2, 13 | CSpecialW mtdc, c1; 14 | CSpecialR c2, mtdc; 15 | ) 16 | 17 | TEST_CASE_CAP_EQ(2, c1, c2, 18 | CSpecialW mscratchc, c1; 19 | CSpecialR c2, mscratchc; 20 | ) 21 | 22 | # test exception when PERM_ACCESS_SYSTEM_REGISTERS is not set 23 | TEST_CASE_START(3) 24 | # to unset PERM_ACCESS_SYSTEM_REGISTERS on PCC, we have to create the 25 | # new capability and jump to it. 26 | CSpecialR c2, pcc 27 | li t0, ~(1 << PERM_ACCESS_SYSTEM_REGISTERS) 28 | CAndPerm c2, c2, t0 29 | la t0, 1f 30 | CSetOffset c2, c2, t0 31 | CJALR c2 32 | 1: 33 | EXPECT_EXCEPTION(CAUSE_ACCESS_SYSTEM_REGISTERS_VIOLATION, CAP_IDX_MTDC, 34 | CSpecialR c3, mtdc 35 | ) 36 | 37 | TEST_PASSFAIL 38 | 39 | RVTEST_CODE_END 40 | 41 | .data 42 | RVTEST_DATA_BEGIN 43 | 44 | TEST_DATA 45 | 46 | RVTEST_DATA_END 47 | -------------------------------------------------------------------------------- /src/main/scala/riscv/soc/devices/Apb3MachineTimers.scala: -------------------------------------------------------------------------------- 1 | package riscv.soc.devices 2 | 3 | import riscv._ 4 | 5 | import spinal.core._ 6 | import spinal.lib._ 7 | import spinal.lib.bus.amba3.apb._ 8 | 9 | class Apb3MachineTimers(pipeline: Pipeline)(implicit config: Config) extends Component { 10 | val io = new Bundle { 11 | val mtimer = master(new IrqIo) 12 | val apb = slave(Apb3(Apb3Config(addressWidth = 4, dataWidth = config.xlen))) 13 | } 14 | 15 | io.mtimer.init() 16 | 17 | private val mtime = Reg(UInt(64 bits)).init(0) 18 | mtime := mtime + 1 19 | 20 | private val mtimecmp = Reg(UInt(64 bits)).init(0) 21 | 22 | parent rework { 23 | pipeline.serviceOption[InterruptService] foreach { interruptService => 24 | interruptService.getMachineTimerIrqIo <> io.mtimer 25 | } 26 | } 27 | 28 | // It is important that this comes before the call to build() to ensure that 29 | // the clearing of the mtip bit on a write has precedence over setting it. 30 | when(mtime >= mtimecmp) { 31 | io.mtimer.postInterrupt() 32 | } 33 | 34 | private val busCtrl = Apb3SlaveFactory(io.apb) 35 | 36 | busCtrl.readAndWriteMultiWord(mtime, 0) 37 | busCtrl.readAndWriteMultiWord(mtimecmp, 8) 38 | 39 | busCtrl.onWrite(8) { 40 | io.mtimer.clearInterrupt() 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | image: ubuntu:jammy 2 | 3 | before_script: 4 | - apt-get update -yqq 5 | # Prevent interactive prompt when installing tzdata 6 | - DEBIAN_FRONTEND=noninteractive apt-get install tzdata -yqq 7 | # Install build dependencies 8 | - apt-get install build-essential verilator gcc-riscv64-unknown-elf openjdk-11-jdk -yqq 9 | # Install dependencies needed for adding the sbt repo 10 | - apt-get install apt-transport-https gnupg curl -yqq 11 | # Add keyserver for SBT 12 | - echo "deb https://repo.scala-sbt.org/scalasbt/debian all main" | tee /etc/apt/sources.list.d/sbt.list 13 | - apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 2EE0EA64E40A89B84B2DF73499E82A75642AC823 14 | # Install SBT 15 | - apt-get update -yqq 16 | - apt-get install sbt -yqq 17 | # Log the dependency versions 18 | - verilator --version 19 | - sbt sbtVersion 20 | # Update all submodules (e.g., riscv-tests) 21 | - git submodule update --init 22 | 23 | scalafmt: 24 | script: 25 | - sbt scalafmtCheck 26 | 27 | test: 28 | script: 29 | # Execute base RV32IM tests on the static pipeline 30 | - make ARCHFLAGS="-march=rv32im -mabi=ilp32" -C tests 31 | # Execute base RV32IM tests on the dynamic pipeline 32 | - make CORE=riscv.CoreDynamicExtMem ARCHFLAGS="-march=rv32im -mabi=ilp32" -C tests 33 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/cheri/tests/CSetAddr.S: -------------------------------------------------------------------------------- 1 | #include "riscv_test.h" 2 | 3 | #include "test_macros_cap.h" 4 | #include "cheri.h" 5 | 6 | RVTEST_RV32U 7 | RVTEST_CODE_BEGIN 8 | 9 | INIT_ROOT_CAP 10 | 11 | # Normal case 12 | TEST_CASE_FREE(1) 13 | li t0, 7 14 | CSetAddr c2, ROOT, t0 15 | CHECK_ADDR(c2, 7) 16 | CHECK_TAG_EQ(ROOT, c2) 17 | CHECK_PERMS_EQ(ROOT, c2) 18 | 19 | # Address below base 20 | TEST_CASE_FREE(2) 21 | li t0, 32 22 | CSetOffset c2, ROOT, t0 23 | CSetBounds c2, c2, t0 24 | li t0, 7 25 | CSetAddr c3, c2, t0 26 | CHECK_ADDR(c3, 7) 27 | CHECK_TAG(c3, 0) 28 | CHECK_PERMS_EQ(c2, c3) 29 | 30 | # Address above top 31 | TEST_CASE_FREE(3) 32 | li t0, 32 33 | CSetBounds c2, ROOT, t0 34 | li t0, 64 35 | CSetAddr c3, c2, t0 36 | CHECK_ADDR(c3, 64) 37 | CHECK_TAG(c3, 0) 38 | CHECK_PERMS_EQ(c2, c3) 39 | 40 | # Sealed source 41 | TEST_CASE_FREE(4) 42 | CSeal c2, ROOT, ROOT 43 | li t0, 64 44 | EXPECT_EXCEPTION(CAUSE_SEAL_VIOLATION, 2, CSetAddr c3, c2, t0) 45 | 46 | TEST_PASSFAIL 47 | 48 | RVTEST_CODE_END 49 | 50 | .data 51 | RVTEST_DATA_BEGIN 52 | 53 | TEST_DATA 54 | 55 | RVTEST_DATA_END 56 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI checks 2 | on: push 3 | 4 | jobs: 5 | build: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - name: Check out repository 9 | uses: actions/checkout@v3 10 | with: 11 | submodules: 'recursive' 12 | 13 | - name: Install native dependencies 14 | run: | 15 | sudo apt-get update 16 | sudo apt-get -yqq install git lsb-release sudo vim gnupg openjdk-17-jdk verilator gcc-riscv64-unknown-elf curl make gcc g++ 17 | - name: Install sbt 18 | run: | 19 | echo "deb https://repo.scala-sbt.org/scalasbt/debian all main" | sudo tee /etc/apt/sources.list.d/sbt.list 20 | echo "deb https://repo.scala-sbt.org/scalasbt/debian /" | sudo tee /etc/apt/sources.list.d/sbt_old.list 21 | curl -sL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x2EE0EA64E40A89B84B2DF73499E82A75642AC823" | sudo apt-key add 22 | sudo apt-get update 23 | sudo apt-get -yqq install sbt 24 | - name: Run Scalafmt 25 | run: sbt scalafmtCheck 26 | - name: Static pipeline riscv-tests 27 | run: make ARCHFLAGS="-march=rv32im -mabi=ilp32" -C tests 28 | - name: Dynamic pipeline riscv-tests 29 | run: make CORE=riscv.CoreDynamicExtMem ARCHFLAGS="-march=rv32im -mabi=ilp32" -C tests 30 | -------------------------------------------------------------------------------- /src/main/scala/riscv/PipelineRegs.scala: -------------------------------------------------------------------------------- 1 | package riscv 2 | 3 | import spinal.core._ 4 | 5 | import scala.collection.mutable 6 | 7 | class PipelineRegs(stage: Stage) extends Component { 8 | private case class RegInfo[T <: Data](reg: T, input: T, output: T, shift: Bool) 9 | private val regs = mutable.Map[PipelineData[Data], RegInfo[Data]]() 10 | 11 | definitionName = s"PipelineRegs_${stage.stageName}" 12 | val shift = in Bool () 13 | 14 | def addReg[T <: Data](data: PipelineData[T]): (T, T) = rework { 15 | val input = in(data.dataType()) 16 | val output = out(data.dataType()) 17 | val regShift = in(Bool()) 18 | parent.rework { regShift := False } 19 | val reg = RegNextWhen(input, shift || regShift).init(input.getZero) 20 | output := reg 21 | 22 | input.setName(s"in_${data.name}") 23 | output.setName(s"out_${data.name}") 24 | reg.setName(s"reg_${data.name}") 25 | regShift.setName(s"shift_${data.name}") 26 | 27 | regs(data.asInstanceOf[PipelineData[Data]]) = RegInfo(reg, input, output, regShift) 28 | 29 | (input, output) 30 | } 31 | 32 | def setReg[T <: Data](data: PipelineData[T], value: T): Unit = { 33 | val regInfo = 34 | regs(data.asInstanceOf[PipelineData[Data]]).asInstanceOf[RegInfo[T]] 35 | 36 | regInfo.input := value 37 | regInfo.shift := True 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/cheri/ExceptionHandler.scala: -------------------------------------------------------------------------------- 1 | package riscv.plugins.cheri 2 | 3 | import riscv._ 4 | 5 | import spinal.core._ 6 | import spinal.lib._ 7 | 8 | class ExceptionHandler extends Plugin[Pipeline] with ExceptionService { 9 | object Data { 10 | object CEXC_CAUSE extends PipelineData(UInt(5 bits)) 11 | object CEXC_CAP_IDX extends PipelineData(CapIdx()) 12 | } 13 | 14 | override def handleException(stage: Stage, cause: UInt, capIdx: CapIdx): Unit = { 15 | assert(cause.getBitsWidth <= 5) 16 | 17 | val trapHandler = pipeline.service[TrapService] 18 | trapHandler.trap(stage, TrapCause.CheriException) 19 | stage.output(Data.CEXC_CAUSE) := cause.resized 20 | stage.output(Data.CEXC_CAP_IDX) := capIdx 21 | } 22 | 23 | override def setup(): Unit = { 24 | val trapHandler = pipeline.service[TrapService] 25 | val csrFile = pipeline.service[CsrService] 26 | 27 | trapHandler.onTrapCommit { (stage, isInterrupt, cause) => 28 | val ccsr = slave(new CsrIo) 29 | 30 | pipeline plug { 31 | ccsr <> csrFile.getCsr(0xbc0) 32 | } 33 | 34 | when(!isInterrupt && cause === TrapCause.CheriException.code) { 35 | val newCcsr = UInt(config.xlen bits) 36 | newCcsr := ccsr.read() 37 | newCcsr(9 downto 5) := stage.value(Data.CEXC_CAUSE) 38 | newCcsr(15 downto 10) := stage.value(Data.CEXC_CAP_IDX).asUInt 39 | ccsr.write(newCcsr) 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/NoPredictionPredictor.scala: -------------------------------------------------------------------------------- 1 | package riscv.plugins 2 | 3 | import riscv._ 4 | import spinal.core._ 5 | 6 | class NoPredictionPredictor(fetchStage: Stage, executeStage: Stage) 7 | extends Plugin[Pipeline] 8 | with BranchTargetPredictorService { 9 | private object Data { 10 | object PREDICTED_PC extends PipelineData(UInt(config.xlen bits)) 11 | } 12 | 13 | override def build(): Unit = { 14 | fetchStage plug new Area { 15 | fetchStage.output(Data.PREDICTED_PC) := fetchStage.value(pipeline.data.NEXT_PC) 16 | } 17 | 18 | executeStage plug new Area { 19 | executeStage.output(Data.PREDICTED_PC) 20 | } 21 | } 22 | 23 | override def predictedPc(stage: Stage): UInt = { 24 | stage.output(Data.PREDICTED_PC) 25 | } 26 | 27 | override def setPredictedPc(stage: Stage, pc: UInt): Unit = { 28 | stage.input(Data.PREDICTED_PC) := pc 29 | } 30 | 31 | override def predictionForAddress(address: UInt): UInt = { 32 | address + 4 33 | } 34 | 35 | override def addPredictedPcToBundle(bundle: DynBundle[PipelineData[Data]]): Unit = { 36 | bundle.addElement( 37 | Data.PREDICTED_PC.asInstanceOf[PipelineData[Data]], 38 | Data.PREDICTED_PC.dataType 39 | ) 40 | } 41 | 42 | override def predictedPcOfBundle( 43 | bundle: Bundle with DynBundleAccess[PipelineData[Data]] 44 | ): UInt = { 45 | bundle.elementAs[UInt](Data.PREDICTED_PC.asInstanceOf[PipelineData[Data]]) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /formal/disasm.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from Verilog_VCD.Verilog_VCD import parse_vcd 4 | from os import system 5 | from sys import argv 6 | 7 | rvfi_valid = None 8 | rvfi_order = None 9 | rvfi_insn = None 10 | 11 | for netinfo in parse_vcd(argv[1]).values(): 12 | for net in netinfo['nets']: 13 | # print(net["hier"], net["name"]) 14 | if net["hier"] == "rvfi_testbench.wrapper" and net["name"] == "rvfi_valid": 15 | rvfi_valid = netinfo['tv'] 16 | if net["hier"] == "rvfi_testbench.wrapper" and net["name"] == "rvfi_order": 17 | rvfi_order = netinfo['tv'] 18 | if net["hier"] == "rvfi_testbench.wrapper" and net["name"] == "rvfi_insn": 19 | rvfi_insn = netinfo['tv'] 20 | 21 | assert len(rvfi_valid) == len(rvfi_order) 22 | assert len(rvfi_valid) == len(rvfi_insn) 23 | 24 | prog = list() 25 | 26 | for tv_valid, tv_order, tv_insn in zip(rvfi_valid, rvfi_order, rvfi_insn): 27 | if tv_valid[1] == '1': 28 | prog.append((int(tv_order[1], 2), int(tv_insn[1], 2))) 29 | 30 | with open("disasm.s", "w") as f: 31 | for tv_order, tv_insn in sorted(prog): 32 | if tv_insn & 3 != 3 and tv_insn & 0xffff0000 == 0: 33 | print(".hword 0x%04x # %d" % (tv_insn, tv_order), file=f) 34 | else: 35 | print(".word 0x%08x # %d" % (tv_insn, tv_order), file=f) 36 | 37 | system("riscv32-unknown-elf-gcc -c disasm.s") 38 | system("riscv32-unknown-elf-objdump -d -M numeric,no-aliases disasm.o") 39 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-sha2/include/kremlin/internal/compat.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) INRIA and Microsoft Corporation. All rights reserved. 2 | Licensed under the Apache 2.0 License. */ 3 | 4 | #ifndef KRML_COMPAT_H 5 | #define KRML_COMPAT_H 6 | 7 | #include 8 | 9 | /* A series of macros that define C implementations of types that are not Low*, 10 | * to facilitate porting programs to Low*. */ 11 | 12 | typedef struct { 13 | uint32_t length; 14 | const char *data; 15 | } FStar_Bytes_bytes; 16 | 17 | typedef int32_t Prims_pos, Prims_nat, Prims_nonzero, Prims_int, 18 | krml_checked_int_t; 19 | 20 | #define RETURN_OR(x) \ 21 | do { \ 22 | int64_t __ret = x; \ 23 | if (__ret < INT32_MIN || INT32_MAX < __ret) { \ 24 | KRML_HOST_PRINTF( \ 25 | "Prims.{int,nat,pos} integer overflow at %s:%d\n", __FILE__, \ 26 | __LINE__); \ 27 | KRML_HOST_EXIT(252); \ 28 | } \ 29 | return (int32_t)__ret; \ 30 | } while (0) 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /tests/synthetic-benchmark/include/kremlin/internal/compat.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) INRIA and Microsoft Corporation. All rights reserved. 2 | Licensed under the Apache 2.0 License. */ 3 | 4 | #ifndef KRML_COMPAT_H 5 | #define KRML_COMPAT_H 6 | 7 | #include 8 | 9 | /* A series of macros that define C implementations of types that are not Low*, 10 | * to facilitate porting programs to Low*. */ 11 | 12 | typedef struct { 13 | uint32_t length; 14 | const char *data; 15 | } FStar_Bytes_bytes; 16 | 17 | typedef int32_t Prims_pos, Prims_nat, Prims_nonzero, Prims_int, 18 | krml_checked_int_t; 19 | 20 | #define RETURN_OR(x) \ 21 | do { \ 22 | int64_t __ret = x; \ 23 | if (__ret < INT32_MIN || INT32_MAX < __ret) { \ 24 | KRML_HOST_PRINTF( \ 25 | "Prims.{int,nat,pos} integer overflow at %s:%d\n", __FILE__, \ 26 | __LINE__); \ 27 | KRML_HOST_EXIT(252); \ 28 | } \ 29 | return (int32_t)__ret; \ 30 | } while (0) 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-chacha20/include/kremlin/internal/compat.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) INRIA and Microsoft Corporation. All rights reserved. 2 | Licensed under the Apache 2.0 License. */ 3 | 4 | #ifndef KRML_COMPAT_H 5 | #define KRML_COMPAT_H 6 | 7 | #include 8 | 9 | /* A series of macros that define C implementations of types that are not Low*, 10 | * to facilitate porting programs to Low*. */ 11 | 12 | typedef struct { 13 | uint32_t length; 14 | const char *data; 15 | } FStar_Bytes_bytes; 16 | 17 | typedef int32_t Prims_pos, Prims_nat, Prims_nonzero, Prims_int, 18 | krml_checked_int_t; 19 | 20 | #define RETURN_OR(x) \ 21 | do { \ 22 | int64_t __ret = x; \ 23 | if (__ret < INT32_MIN || INT32_MAX < __ret) { \ 24 | KRML_HOST_PRINTF( \ 25 | "Prims.{int,nat,pos} integer overflow at %s:%d\n", __FILE__, \ 26 | __LINE__); \ 27 | KRML_HOST_EXIT(252); \ 28 | } \ 29 | return (int32_t)__ret; \ 30 | } while (0) 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /src/main/scala/riscv/soc/devices/Apb3ByteDev.scala: -------------------------------------------------------------------------------- 1 | package riscv.soc.devices 2 | 3 | import riscv._ 4 | 5 | import spinal.core._ 6 | import spinal.lib._ 7 | import spinal.lib.bus.amba3.apb._ 8 | 9 | class ByteDevIo(implicit config: Config) extends Bundle with IMasterSlave { 10 | val wdata = Flow(UInt(8 bits)) 11 | val rdata = Stream(UInt(8 bits)) 12 | 13 | override def asMaster(): Unit = { 14 | master(wdata) 15 | slave(rdata) 16 | } 17 | } 18 | 19 | class Apb3ByteDev(implicit config: Config) extends Component { 20 | val io = new Bundle { 21 | val bytes = master(new ByteDevIo) 22 | val irq = master(new IrqIo) 23 | val apb = slave(Apb3(Apb3Config(addressWidth = 4, dataWidth = config.xlen))) 24 | } 25 | 26 | io.irq.init() 27 | 28 | private val rbuf = Reg(UInt(8 bits)).init(0) 29 | private val rbufFull = Reg(Bool()).init(False) 30 | 31 | io.bytes.rdata.ready := !rbufFull 32 | 33 | when(io.bytes.rdata.valid && !rbufFull) { 34 | rbuf := io.bytes.rdata.payload 35 | rbufFull := True 36 | io.irq.postInterrupt() 37 | } 38 | 39 | private val busCtrl = Apb3SlaveFactory(io.apb) 40 | busCtrl.driveFlow(io.bytes.wdata, 0) 41 | 42 | private val rdata = U(0, 8 bits) 43 | 44 | when(rbufFull) { 45 | rdata := rbuf 46 | } elsewhen (io.bytes.rdata.valid) { 47 | rdata := io.bytes.rdata.payload 48 | } 49 | 50 | busCtrl.read(rdata, 0) 51 | 52 | busCtrl.onRead(0) { 53 | rbufFull := False 54 | io.irq.clearInterrupt() 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /tests/crypto/curve25519/curve25519.c: -------------------------------------------------------------------------------- 1 | #include "Curve25519-donna.h" 2 | /* #include "Hacl_Curve25519_51.h" */ 3 | 4 | #include 5 | #include 6 | 7 | __attribute__((section(".secret"))) uint8_t out[32] = { 8 | 0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d, 0x3b, 0x16, 0x15, 0x4b, 0x82, 0x46, 0x5e, 0xdd, 9 | 0x62, 0x14, 0x4c, 0x0a, 0xc1, 0xfc, 0x5a, 0x18, 0x50, 0x6a, 0x22, 0x44, 0xba, 0x44, 0x9a, 0xc4 10 | }; 11 | __attribute__((section(".secret"))) uint8_t public[32] = { 12 | 0xe6, 0xdb, 0x68, 0x67, 0x58, 0x30, 0x30, 0xdb, 0x35, 0x94, 0xc1, 0xa4, 0x24, 0xb1, 0x5f, 0x7c, 13 | 0x72, 0x66, 0x24, 0xec, 0x26, 0xb3, 0x35, 0x3b, 0x10, 0xa9, 0x03, 0xa6, 0xd0, 0xab, 0x1c, 0x4c 14 | }; 15 | __attribute__((section(".secret"))) uint8_t private[32] = { 16 | 0xc3, 0xda, 0x55, 0x37, 0x9d, 0xe9, 0xc6, 0x90, 0x8e, 0x94, 0xea, 0x4d, 0xf2, 0x8d, 0x08, 0x4f, 17 | 0x32, 0xec, 0xcf, 0x03, 0x49, 0x1c, 0x71, 0xf7, 0x54, 0xb4, 0x07, 0x55, 0x77, 0xa2, 0x85, 0x52 18 | }; 19 | 20 | __attribute__((section(".declassified"))) volatile uint8_t declassified[32]; 21 | 22 | int main() { 23 | 24 | /* curve25519_donna(private, public, out); */ 25 | curve25519_donna(private, public, out); 26 | /* Hacl_Curve25519_51_ecdh(out, private, public); */ 27 | 28 | for (size_t i = 0; i < sizeof(out); ++i) { 29 | declassified[i] = out[i]; 30 | } 31 | 32 | for (size_t i = 0; i < sizeof(declassified); ++i) { 33 | printf("%02x", declassified[i]); 34 | } 35 | 36 | printf("\n"); 37 | } 38 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/Fetcher.scala: -------------------------------------------------------------------------------- 1 | package riscv.plugins 2 | 3 | import riscv._ 4 | 5 | import spinal.core._ 6 | import spinal.lib._ 7 | 8 | class Fetcher(fetchStage: Stage, ibusLatency: Int = 2) extends Plugin[Pipeline] with FetchService { 9 | private var addressTranslator = new FetchAddressTranslator { 10 | override def translate(stage: Stage, address: UInt): UInt = { 11 | address 12 | } 13 | } 14 | 15 | private var addressTranslatorChanged = false 16 | 17 | override def build(): Unit = { 18 | fetchStage plug new Area { 19 | import fetchStage._ 20 | 21 | val ibus = pipeline.service[MemoryService].createInternalIBus(fetchStage) 22 | val ibusCtrl = new IBusControl(ibus, ibusLatency) 23 | 24 | arbitration.isReady := False 25 | 26 | val pc = input(pipeline.data.PC) 27 | val nextPc = pc + 4 28 | 29 | when(arbitration.isRunning) { 30 | val fetchAddress = addressTranslator.translate(fetchStage, pc) 31 | val (valid, rdata) = ibusCtrl.read(fetchAddress) 32 | 33 | when(valid) { 34 | arbitration.isReady := True 35 | 36 | output(pipeline.data.NEXT_PC) := nextPc 37 | output(pipeline.data.IR) := rdata 38 | } 39 | } 40 | } 41 | } 42 | 43 | override def setAddressTranslator(translator: FetchAddressTranslator): Unit = { 44 | assert(!addressTranslatorChanged, "FetchAddressTranslator can only be set once") 45 | 46 | addressTranslator = translator 47 | addressTranslatorChanged = true 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /tests/crypto/djbsort-20190516/int32/portable4/sort.c: -------------------------------------------------------------------------------- 1 | #include "int32_sort.h" 2 | #define int32 int32_t 3 | 4 | #include "int32_minmax.c" 5 | 6 | void int32_sort(int32 *x,long long n) 7 | { 8 | long long top,p,q,r,i,j; 9 | 10 | if (n < 2) return; 11 | top = 1; 12 | while (top < n - top) top += top; 13 | 14 | for (p = top;p >= 1;p >>= 1) { 15 | i = 0; 16 | while (i + 2 * p <= n) { 17 | for (j = i;j < i + p;++j) 18 | int32_MINMAX(x[j],x[j+p]); 19 | i += 2 * p; 20 | } 21 | for (j = i;j < n - p;++j) 22 | int32_MINMAX(x[j],x[j+p]); 23 | 24 | i = 0; 25 | j = 0; 26 | for (q = top;q > p;q >>= 1) { 27 | if (j != i) for (;;) { 28 | if (j == n - q) goto done; 29 | int32 a = x[j + p]; 30 | for (r = q;r > p;r >>= 1) 31 | int32_MINMAX(a,x[j + r]); 32 | x[j + p] = a; 33 | ++j; 34 | if (j == i + p) { 35 | i += 2 * p; 36 | break; 37 | } 38 | } 39 | while (i + p <= n - q) { 40 | for (j = i;j < i + p;++j) { 41 | int32 a = x[j + p]; 42 | for (r = q;r > p;r >>= 1) 43 | int32_MINMAX(a,x[j+r]); 44 | x[j + p] = a; 45 | } 46 | i += 2 * p; 47 | } 48 | /* now i + p > n - q */ 49 | j = i; 50 | while (j < n - q) { 51 | int32 a = x[j + p]; 52 | for (r = q;r > p;r >>= 1) 53 | int32_MINMAX(a,x[j+r]); 54 | x[j + p] = a; 55 | ++j; 56 | } 57 | 58 | done: ; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/cheri/tests/InitialState.S: -------------------------------------------------------------------------------- 1 | #include "riscv_test.h" 2 | 3 | #include "test_macros_cap.h" 4 | 5 | RVTEST_RV32U 6 | RVTEST_CODE_BEGIN 7 | 8 | TEST_CASE_NULL_CAP(1, c0) 9 | TEST_CASE_NULL_CAP(2, c1) 10 | TEST_CASE_NULL_CAP(3, c2) 11 | TEST_CASE_NULL_CAP(4, c3) 12 | TEST_CASE_NULL_CAP(5, c4) 13 | TEST_CASE_NULL_CAP(6, c5) 14 | TEST_CASE_NULL_CAP(7, c6) 15 | TEST_CASE_NULL_CAP(8, c7) 16 | TEST_CASE_NULL_CAP(9, c8) 17 | TEST_CASE_NULL_CAP(10, c9) 18 | TEST_CASE_NULL_CAP(11, c10) 19 | TEST_CASE_NULL_CAP(12, c11) 20 | TEST_CASE_NULL_CAP(13, c12) 21 | TEST_CASE_NULL_CAP(14, c13) 22 | TEST_CASE_NULL_CAP(15, c14) 23 | TEST_CASE_NULL_CAP(16, c15) 24 | TEST_CASE_NULL_CAP(17, c16) 25 | TEST_CASE_NULL_CAP(18, c17) 26 | TEST_CASE_NULL_CAP(19, c18) 27 | TEST_CASE_NULL_CAP(20, c19) 28 | TEST_CASE_NULL_CAP(21, c20) 29 | TEST_CASE_NULL_CAP(22, c21) 30 | TEST_CASE_NULL_CAP(23, c22) 31 | TEST_CASE_NULL_CAP(24, c23) 32 | TEST_CASE_NULL_CAP(25, c24) 33 | TEST_CASE_NULL_CAP(26, c25) 34 | TEST_CASE_NULL_CAP(27, c26) 35 | TEST_CASE_NULL_CAP(28, c27) 36 | TEST_CASE_NULL_CAP(29, c28) 37 | TEST_CASE_NULL_CAP(30, c29) 38 | TEST_CASE_NULL_CAP(31, c30) 39 | TEST_CASE_NULL_CAP(32, c31) 40 | 41 | TEST_CASE_ROOT_CAP(33, c1, CSpecialR c1, ddc) 42 | TEST_CASE_ROOT_CAP_NO_OFFSET(34, c1, CSpecialR c1, pcc) 43 | 44 | 45 | TEST_PASSFAIL 46 | 47 | RVTEST_CODE_END 48 | 49 | .data 50 | RVTEST_DATA_BEGIN 51 | 52 | TEST_DATA 53 | 54 | RVTEST_DATA_END 55 | -------------------------------------------------------------------------------- /tests/Makefile: -------------------------------------------------------------------------------- 1 | TESTS_DIR = $(abspath .) 2 | BASE_DIR = $(abspath $(TESTS_DIR)/..) 3 | RISCV_TESTS_DIR = $(TESTS_DIR)/riscv-tests 4 | ISA_TESTS_DIR = $(RISCV_TESTS_DIR)/isa 5 | BUILD_DIR = $(TESTS_DIR)/build 6 | SIM_DIR = $(BASE_DIR)/sim 7 | SIM_EXE = $(SIM_DIR)/build/sim 8 | CORE ?= riscv.CoreExtMem 9 | BUILD_CORE ?= 1 10 | 11 | RISCV_PREFIX ?= riscv64-unknown-elf 12 | CC = $(RISCV_PREFIX)-gcc 13 | LD = $(RISCV_PREFIX)-gcc 14 | OBJCOPY = $(RISCV_PREFIX)-objcopy 15 | ARCHFLAGS ?= -march=rv32imzicsr -mabi=ilp32 16 | CFLAGS = $(ARCHFLAGS) 17 | 18 | ifeq ($(BUILD_CORE),1) 19 | FORCE = FORCE 20 | else 21 | FORCE = 22 | endif 23 | 24 | -include $(CUSTOM_TESTS_DIR)/Makefile.include 25 | 26 | TEST_DIRS ?= $(ISA_TESTS_DIR)/rv32ui $(ISA_TESTS_DIR)/rv32mi $(ISA_TESTS_DIR)/rv32um $(CUSTOM_TESTS_DIR) 27 | ALL_ISA_TESTS = $(shell find $(TEST_DIRS) -name '*.S') 28 | UNSUPPORTED_TESTS = %fence_i.S %breakpoint.S 29 | ALL_TESTS = $(filter-out $(UNSUPPORTED_TESTS),$(ALL_ISA_TESTS)) 30 | ALL_TARGETS = $(addsuffix .pass,$(basename $(addprefix $(BUILD_DIR)/,$(notdir $(ALL_TESTS))))) 31 | 32 | all: $(ALL_TARGETS) 33 | 34 | .SECONDARY: 35 | 36 | VPATH = $(TEST_DIRS) 37 | 38 | $(BUILD_DIR)/%.o: %.S 39 | mkdir -p $(@D) 40 | $(CC) $(CFLAGS) -I$(TESTS_DIR) -I$(ISA_TESTS_DIR)/macros/scalar -c -o $@ $^ 41 | 42 | %.elf: %.o 43 | $(LD) $(ARCHFLAGS) -ffreestanding -nostdlib -T tests.ld -o $@ $^ 44 | 45 | %.bin: %.elf 46 | $(OBJCOPY) -O binary $^ $@ 47 | 48 | $(SIM_EXE): $(FORCE) 49 | make -C $(SIM_DIR) CORE=$(CORE) 50 | 51 | .PHONY: FORCE 52 | 53 | %.pass: %.bin $(SIM_EXE) 54 | cd $(BASE_DIR); $(SIM_EXE) $< 55 | touch $@ 56 | -------------------------------------------------------------------------------- /tests/synthetic-benchmark/include/kremlin/internal/callconv.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) INRIA and Microsoft Corporation. All rights reserved. 2 | Licensed under the Apache 2.0 License. */ 3 | 4 | #ifndef __KREMLIN_CALLCONV_H 5 | #define __KREMLIN_CALLCONV_H 6 | 7 | /******************************************************************************/ 8 | /* Some macros to ease compatibility */ 9 | /******************************************************************************/ 10 | 11 | /* We want to generate __cdecl safely without worrying about it being undefined. 12 | * When using MSVC, these are always defined. When using MinGW, these are 13 | * defined too. They have no meaning for other platforms, so we define them to 14 | * be empty macros in other situations. */ 15 | #ifndef _MSC_VER 16 | #ifndef __cdecl 17 | #define __cdecl 18 | #endif 19 | #ifndef __stdcall 20 | #define __stdcall 21 | #endif 22 | #ifndef __fastcall 23 | #define __fastcall 24 | #endif 25 | #endif 26 | 27 | /* Since KreMLin emits the inline keyword unconditionally, we follow the 28 | * guidelines at https://gcc.gnu.org/onlinedocs/gcc/Inline.html and make this 29 | * __inline__ to ensure the code compiles with -std=c90 and earlier. */ 30 | #ifdef __GNUC__ 31 | # define inline __inline__ 32 | #endif 33 | 34 | /* GCC-specific attribute syntax; everyone else gets the standard C inline 35 | * attribute. */ 36 | #ifdef __GNU_C__ 37 | # ifndef __clang__ 38 | # define force_inline inline __attribute__((always_inline)) 39 | # else 40 | # define force_inline inline 41 | # endif 42 | #else 43 | # define force_inline inline 44 | #endif 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-sha2/include/kremlin/internal/callconv.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) INRIA and Microsoft Corporation. All rights reserved. 2 | Licensed under the Apache 2.0 License. */ 3 | 4 | #ifndef __KREMLIN_CALLCONV_H 5 | #define __KREMLIN_CALLCONV_H 6 | 7 | /******************************************************************************/ 8 | /* Some macros to ease compatibility */ 9 | /******************************************************************************/ 10 | 11 | /* We want to generate __cdecl safely without worrying about it being undefined. 12 | * When using MSVC, these are always defined. When using MinGW, these are 13 | * defined too. They have no meaning for other platforms, so we define them to 14 | * be empty macros in other situations. */ 15 | #ifndef _MSC_VER 16 | #ifndef __cdecl 17 | #define __cdecl 18 | #endif 19 | #ifndef __stdcall 20 | #define __stdcall 21 | #endif 22 | #ifndef __fastcall 23 | #define __fastcall 24 | #endif 25 | #endif 26 | 27 | /* Since KreMLin emits the inline keyword unconditionally, we follow the 28 | * guidelines at https://gcc.gnu.org/onlinedocs/gcc/Inline.html and make this 29 | * __inline__ to ensure the code compiles with -std=c90 and earlier. */ 30 | #ifdef __GNUC__ 31 | # define inline __inline__ 32 | #endif 33 | 34 | /* GCC-specific attribute syntax; everyone else gets the standard C inline 35 | * attribute. */ 36 | #ifdef __GNU_C__ 37 | # ifndef __clang__ 38 | # define force_inline inline __attribute__((always_inline)) 39 | # else 40 | # define force_inline inline 41 | # endif 42 | #else 43 | # define force_inline inline 44 | #endif 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-chacha20/include/kremlin/internal/callconv.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) INRIA and Microsoft Corporation. All rights reserved. 2 | Licensed under the Apache 2.0 License. */ 3 | 4 | #ifndef __KREMLIN_CALLCONV_H 5 | #define __KREMLIN_CALLCONV_H 6 | 7 | /******************************************************************************/ 8 | /* Some macros to ease compatibility */ 9 | /******************************************************************************/ 10 | 11 | /* We want to generate __cdecl safely without worrying about it being undefined. 12 | * When using MSVC, these are always defined. When using MinGW, these are 13 | * defined too. They have no meaning for other platforms, so we define them to 14 | * be empty macros in other situations. */ 15 | #ifndef _MSC_VER 16 | #ifndef __cdecl 17 | #define __cdecl 18 | #endif 19 | #ifndef __stdcall 20 | #define __stdcall 21 | #endif 22 | #ifndef __fastcall 23 | #define __fastcall 24 | #endif 25 | #endif 26 | 27 | /* Since KreMLin emits the inline keyword unconditionally, we follow the 28 | * guidelines at https://gcc.gnu.org/onlinedocs/gcc/Inline.html and make this 29 | * __inline__ to ensure the code compiles with -std=c90 and earlier. */ 30 | #ifdef __GNUC__ 31 | # define inline __inline__ 32 | #endif 33 | 34 | /* GCC-specific attribute syntax; everyone else gets the standard C inline 35 | * attribute. */ 36 | #ifdef __GNU_C__ 37 | # ifndef __clang__ 38 | # define force_inline inline __attribute__((always_inline)) 39 | # else 40 | # define force_inline inline 41 | # endif 42 | #else 43 | # define force_inline inline 44 | #endif 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/cheri/tests/Sealing.S: -------------------------------------------------------------------------------- 1 | #include "riscv_test.h" 2 | 3 | #include "test_macros_cap.h" 4 | #include "cheri.h" 5 | 6 | RVTEST_RV32U 7 | RVTEST_CODE_BEGIN 8 | 9 | INIT_ROOT_CAP 10 | 11 | # Check otype is correctly set when sealing 12 | TEST_CASE_START(1) 13 | SEAL_ROOT(c1, 100) 14 | CHECK_CAP_NEW_TYPE(c1, ROOT, 100) 15 | 16 | # Check unsealing a capability results in original capability 17 | TEST_CASE_START(2) 18 | SEAL_ROOT(c1, 1234) 19 | li t0, 1234 20 | CSetOffset c2, ROOT, t0 21 | CUnseal c3, c1, c2 22 | CHECK_CAP_EQ(c3, ROOT) 23 | 24 | # Sealing without permission 25 | TEST_CASE_START(3) 26 | li t0, ~(1 << PERM_PERMIT_SEAL) 27 | CAndPerm c1, ROOT, t0 28 | EXPECT_EXCEPTION(CAUSE_PERMIT_SEAL_VIOLATION, 1, CSeal c2, ROOT, c1) 29 | 30 | # Unsealing without permission 31 | TEST_CASE_START(4) 32 | SEAL_ROOT(c1, 1234) 33 | li t0, 1234 34 | CSetOffset c2, ROOT, t0 35 | li t0, ~(1 << PERM_PERMIT_UNSEAL) 36 | CAndPerm c2, c2, t0 37 | EXPECT_EXCEPTION(CAUSE_PERMIT_UNSEAL_VIOLATION, 2, CUnseal c3, c1, c2) 38 | 39 | # Unsealing using wrong otype 40 | TEST_CASE_START(5) 41 | SEAL_ROOT(c1, 1234) 42 | li t0, 5678 43 | CSetOffset c2, ROOT, t0 44 | EXPECT_EXCEPTION(CAUSE_TYPE_VIOLATION, 2, CUnseal c3, c1, c2) 45 | 46 | # Unsealing unsealed capability 47 | TEST_CASE_START(6) 48 | CMove c1, ROOT 49 | EXPECT_EXCEPTION(CAUSE_SEAL_VIOLATION, 1, CUnseal c2, c1, ROOT) 50 | 51 | TEST_PASSFAIL 52 | 53 | RVTEST_CODE_END 54 | 55 | .data 56 | RVTEST_DATA_BEGIN 57 | 58 | TEST_DATA 59 | 60 | RVTEST_DATA_END 61 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/cheri/tests/cheri.h: -------------------------------------------------------------------------------- 1 | #ifndef CHERI_H 2 | #define CHERI_H 3 | 4 | #define CAUSE_NONE 0x0 5 | #define CAUSE_LENGTH_VIOLATION 0x1 6 | #define CAUSE_TAG_VIOLATION 0x2 7 | #define CAUSE_SEAL_VIOLATION 0x3 8 | #define CAUSE_TYPE_VIOLATION 0x4 9 | #define CAUSE_CALL_TRAP 0x5 10 | #define CAUSE_RETURN_TRAP 0x6 11 | #define CAUSE_TRUSTED_SYSTEM_STACK_OVERFLOW 0x7 12 | #define CAUSE_SOFTWARE_DEFINED_PERMISSION_VIOLATION 0x8 13 | #define CAUSE_MMU_PROHIBITS_STORE_CAPABILITY 0x9 14 | #define CAUSE_BOUNDS_CANNOT_BE_REPRESENTED_EXACTLY 0xa 15 | #define CAUSE_GLOBAL_VIOLATION 0x10 16 | #define CAUSE_PERMIT_EXECUTE_VIOLATION 0x11 17 | #define CAUSE_PERMIT_LOAD_VIOLATION 0x12 18 | #define CAUSE_PERMIT_STORE_VIOLATION 0x13 19 | #define CAUSE_PERMIT_LOAD_CAPABILITY_VIOLATION 0x14 20 | #define CAUSE_PERMIT_STORE_CAPABILITY_VIOLATION 0x15 21 | #define CAUSE_PERMIT_STORE_LOCAL_CAPABILITY_VIOLATION 0x16 22 | #define CAUSE_PERMIT_SEAL_VIOLATION 0x17 23 | #define CAUSE_ACCESS_SYSTEM_REGISTERS_VIOLATION 0x18 24 | #define CAUSE_PERMIT_CCALL_VIOLATION 0x19 25 | #define CAUSE_ACCESS_CCALL_IDC_VIOLATION 0x1a 26 | #define CAUSE_PERMIT_UNSEAL_VIOLATION 0x1b 27 | #define CAUSE_PERMIT_SET_CID_VIOLATION 0x1c 28 | 29 | #define CAP_IDX_PCC 0x20 30 | #define CAP_IDX_DDC 0x21 31 | #define CAP_IDX_MTDC 0x3d 32 | 33 | #define PERM_GLOBAL 0 34 | #define PERM_PERMIT_EXECUTE 1 35 | #define PERM_PERMIT_LOAD 2 36 | #define PERM_PERMIT_STORE 3 37 | #define PERM_PERMIT_LOAD_CAPABILITY 4 38 | #define PERM_PERMIT_STORE_CAPABILITY 5 39 | #define PERM_PERMIT_STORE_LOCAL_CAPABILITY 6 40 | #define PERM_PERMIT_SEAL 7 41 | #define PERM_PERMIT_CCALL 8 42 | #define PERM_PERMIT_UNSEAL 9 43 | #define PERM_ACCESS_SYSTEM_REGISTERS 10 44 | #define PERM_PERMIT_SET_CID 11 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-sha2/include/kremlib/Makefile.basic: -------------------------------------------------------------------------------- 1 | # A basic Makefile that KreMLin copies in the output directory; this is not 2 | # guaranteed to work and will only work well for very simple projects. This 3 | # Makefile uses: 4 | # - the custom C files passed to your krml invocation 5 | # - the custom C flags passed to your krml invocation 6 | # - the -o option passed to your krml invocation 7 | 8 | include Makefile.include 9 | 10 | ifeq (,$(KREMLIN_HOME)) 11 | $(error please define KREMLIN_HOME to point to the root of your KReMLin git checkout) 12 | endif 13 | 14 | CFLAGS += -I. -I $(KREMLIN_HOME)/include -I $(KREMLIN_HOME)/kremlib/dist/minimal 15 | CFLAGS += -Wall -Wextra -Werror -std=c11 -Wno-unused-variable \ 16 | -Wno-unknown-warning-option -Wno-unused-but-set-variable \ 17 | -Wno-unused-parameter -Wno-infinite-recursion \ 18 | -g -fwrapv -D_BSD_SOURCE -D_DEFAULT_SOURCE 19 | ifeq ($(OS),Windows_NT) 20 | CFLAGS += -D__USE_MINGW_ANSI_STDIO 21 | else 22 | CFLAGS += -fPIC 23 | endif 24 | CFLAGS += $(USER_CFLAGS) 25 | 26 | SOURCES += $(ALL_C_FILES) $(USER_C_FILES) 27 | ifneq (,$(BLACKLIST)) 28 | SOURCES := $(filter-out $(BLACKLIST),$(SOURCES)) 29 | endif 30 | OBJS += $(patsubst %.c,%.o,$(SOURCES)) 31 | 32 | all: $(USER_TARGET) 33 | 34 | $(USER_TARGET): $(OBJS) 35 | 36 | AR ?= ar 37 | 38 | %.a: 39 | $(AR) cr $@ $^ 40 | 41 | %.exe: 42 | $(CC) $(CFLAGS) -o $@ $^ $(KREMLIN_HOME)/kremlib/dist/generic/libkremlib.a 43 | 44 | %.so: 45 | $(CC) $(CFLAGS) -shared -o $@ $^ 46 | 47 | %.d: %.c 48 | @set -e; rm -f $@; \ 49 | $(CC) -MM $(CFLAGS) $< > $@.$$$$; \ 50 | sed 's,\($(notdir $*)\)\.o[ :]*,$(dir $@)\1.o $@ : ,g' < $@.$$$$ > $@; \ 51 | rm -f $@.$$$$ 52 | 53 | include $(patsubst %.c,%.d,$(SOURCES)) 54 | 55 | clean: 56 | rm -rf *.o *.d $(USER_TARGET) 57 | -------------------------------------------------------------------------------- /tests/synthetic-benchmark/include/kremlib/Makefile.basic: -------------------------------------------------------------------------------- 1 | # A basic Makefile that KreMLin copies in the output directory; this is not 2 | # guaranteed to work and will only work well for very simple projects. This 3 | # Makefile uses: 4 | # - the custom C files passed to your krml invocation 5 | # - the custom C flags passed to your krml invocation 6 | # - the -o option passed to your krml invocation 7 | 8 | include Makefile.include 9 | 10 | ifeq (,$(KREMLIN_HOME)) 11 | $(error please define KREMLIN_HOME to point to the root of your KReMLin git checkout) 12 | endif 13 | 14 | CFLAGS += -I. -I $(KREMLIN_HOME)/include -I $(KREMLIN_HOME)/kremlib/dist/minimal 15 | CFLAGS += -Wall -Wextra -Werror -std=c11 -Wno-unused-variable \ 16 | -Wno-unknown-warning-option -Wno-unused-but-set-variable \ 17 | -Wno-unused-parameter -Wno-infinite-recursion \ 18 | -g -fwrapv -D_BSD_SOURCE -D_DEFAULT_SOURCE 19 | ifeq ($(OS),Windows_NT) 20 | CFLAGS += -D__USE_MINGW_ANSI_STDIO 21 | else 22 | CFLAGS += -fPIC 23 | endif 24 | CFLAGS += $(USER_CFLAGS) 25 | 26 | SOURCES += $(ALL_C_FILES) $(USER_C_FILES) 27 | ifneq (,$(BLACKLIST)) 28 | SOURCES := $(filter-out $(BLACKLIST),$(SOURCES)) 29 | endif 30 | OBJS += $(patsubst %.c,%.o,$(SOURCES)) 31 | 32 | all: $(USER_TARGET) 33 | 34 | $(USER_TARGET): $(OBJS) 35 | 36 | AR ?= ar 37 | 38 | %.a: 39 | $(AR) cr $@ $^ 40 | 41 | %.exe: 42 | $(CC) $(CFLAGS) -o $@ $^ $(KREMLIN_HOME)/kremlib/dist/generic/libkremlib.a 43 | 44 | %.so: 45 | $(CC) $(CFLAGS) -shared -o $@ $^ 46 | 47 | %.d: %.c 48 | @set -e; rm -f $@; \ 49 | $(CC) -MM $(CFLAGS) $< > $@.$$$$; \ 50 | sed 's,\($(notdir $*)\)\.o[ :]*,$(dir $@)\1.o $@ : ,g' < $@.$$$$ > $@; \ 51 | rm -f $@.$$$$ 52 | 53 | include $(patsubst %.c,%.d,$(SOURCES)) 54 | 55 | clean: 56 | rm -rf *.o *.d $(USER_TARGET) 57 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-chacha20/include/kremlib/Makefile.basic: -------------------------------------------------------------------------------- 1 | # A basic Makefile that KreMLin copies in the output directory; this is not 2 | # guaranteed to work and will only work well for very simple projects. This 3 | # Makefile uses: 4 | # - the custom C files passed to your krml invocation 5 | # - the custom C flags passed to your krml invocation 6 | # - the -o option passed to your krml invocation 7 | 8 | include Makefile.include 9 | 10 | ifeq (,$(KREMLIN_HOME)) 11 | $(error please define KREMLIN_HOME to point to the root of your KReMLin git checkout) 12 | endif 13 | 14 | CFLAGS += -I. -I $(KREMLIN_HOME)/include -I $(KREMLIN_HOME)/kremlib/dist/minimal 15 | CFLAGS += -Wall -Wextra -Werror -std=c11 -Wno-unused-variable \ 16 | -Wno-unknown-warning-option -Wno-unused-but-set-variable \ 17 | -Wno-unused-parameter -Wno-infinite-recursion \ 18 | -g -fwrapv -D_BSD_SOURCE -D_DEFAULT_SOURCE 19 | ifeq ($(OS),Windows_NT) 20 | CFLAGS += -D__USE_MINGW_ANSI_STDIO 21 | else 22 | CFLAGS += -fPIC 23 | endif 24 | CFLAGS += $(USER_CFLAGS) 25 | 26 | SOURCES += $(ALL_C_FILES) $(USER_C_FILES) 27 | ifneq (,$(BLACKLIST)) 28 | SOURCES := $(filter-out $(BLACKLIST),$(SOURCES)) 29 | endif 30 | OBJS += $(patsubst %.c,%.o,$(SOURCES)) 31 | 32 | all: $(USER_TARGET) 33 | 34 | $(USER_TARGET): $(OBJS) 35 | 36 | AR ?= ar 37 | 38 | %.a: 39 | $(AR) cr $@ $^ 40 | 41 | %.exe: 42 | $(CC) $(CFLAGS) -o $@ $^ $(KREMLIN_HOME)/kremlib/dist/generic/libkremlib.a 43 | 44 | %.so: 45 | $(CC) $(CFLAGS) -shared -o $@ $^ 46 | 47 | %.d: %.c 48 | @set -e; rm -f $@; \ 49 | $(CC) -MM $(CFLAGS) $< > $@.$$$$; \ 50 | sed 's,\($(notdir $*)\)\.o[ :]*,$(dir $@)\1.o $@ : ,g' < $@.$$$$ > $@; \ 51 | rm -f $@.$$$$ 52 | 53 | include $(patsubst %.c,%.d,$(SOURCES)) 54 | 55 | clean: 56 | rm -rf *.o *.d $(USER_TARGET) 57 | -------------------------------------------------------------------------------- /tests/spectre-tests/eval.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import vcdvcd 4 | import subprocess 5 | import sys 6 | 7 | 8 | def evaluate(): 9 | vcd = vcdvcd.VCDVCD("sim.vcd", []) 10 | addresses = vcd["TOP.Core.pipeline.dbus_cmd_payload_address[31:0]"] 11 | 12 | violation = False 13 | 14 | for (_, val) in addresses.tv: 15 | addr = int(val, 2) 16 | if str(hex(addr)) == "0xdead0": 17 | violation = True 18 | 19 | return violation 20 | 21 | 22 | base_proteus = sys.argv[1] 23 | secure_proteus = sys.argv[2] 24 | 25 | test_cases = [ 26 | "secret-before-branch", 27 | "secret-after-branch", 28 | ] 29 | 30 | for case in test_cases: 31 | print(f"TEST {case}:") 32 | # run test case with secure variant 33 | subprocess.call( 34 | ["make", f"{case}.bin"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) 35 | subprocess.call([f"{secure_proteus}", f"{case}.bin"]) 36 | print("SECURE VARIANT: ", end='\t') 37 | print("🗲 Secret leaked!" if evaluate() else "✔ Secret did not leak!") 38 | 39 | # run test case with insecure variant: 40 | # 1. remove csrrw instructions from code 41 | with open(f"{case}.s") as source: 42 | lines = source.readlines() 43 | stripped = [ 44 | line for line in lines if not line.strip().startswith("csr")] 45 | with open(f"{case}_stripped.s", 'w') as stripped_file: 46 | stripped_file.writelines(stripped) 47 | 48 | subprocess.call(["make", f"{case}_stripped.bin"], 49 | stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) 50 | subprocess.call([f"{secure_proteus}", f"{case}_stripped.bin"]) 51 | print("INSECURE VARIANT:", end='\t') 52 | print("🗲 Secret leaked!" if evaluate() else "✔ Secret did not leak!") 53 | print() 54 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/Timers.scala: -------------------------------------------------------------------------------- 1 | package riscv.plugins 2 | 3 | import riscv._ 4 | 5 | import spinal.core._ 6 | 7 | class Timers extends Plugin[Pipeline] { 8 | override def setup(): Unit = { 9 | val csr = pipeline.service[CsrService] 10 | 11 | val cycleCsr = csr.registerCsr( 12 | 0xc00, 13 | new Csr { 14 | val cycle = Reg(UInt(64 bits)).init(0) 15 | cycle := cycle + 1 16 | 17 | override def read(): UInt = { 18 | if (config.xlen == 32) { 19 | cycle(31 downto 0) 20 | } else { 21 | cycle 22 | } 23 | } 24 | } 25 | ) 26 | 27 | // For now, just alias time[h] to cycle[h] 28 | csr.registerCsr(0xc01, cycleCsr) 29 | 30 | val instretCsr = csr.registerCsr( 31 | 0xc02, 32 | new Csr { 33 | val incInstret = in Bool () 34 | val instret = Reg(UInt(64 bits)).init(0) 35 | 36 | when(incInstret) { 37 | instret := instret + 1 38 | } 39 | 40 | override def read(): UInt = { 41 | if (config.xlen == 32) { 42 | instret(31 downto 0) 43 | } else { 44 | instret 45 | } 46 | } 47 | } 48 | ) 49 | 50 | pipeline plug new Area { 51 | instretCsr.incInstret := pipeline.retirementStage.arbitration.isDone 52 | } 53 | 54 | if (config.xlen == 32) { 55 | val cyclehCsr = csr.registerCsr( 56 | 0xc80, 57 | new Csr { 58 | override def read(): UInt = cycleCsr.cycle(63 downto 32) 59 | } 60 | ) 61 | 62 | csr.registerCsr(0xc81, cyclehCsr) 63 | 64 | csr.registerCsr( 65 | 0xc82, 66 | new Csr { 67 | override def read(): UInt = instretCsr.instret(63 downto 32) 68 | } 69 | ) 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/cheri/tests/RiscvLsu.S: -------------------------------------------------------------------------------- 1 | #include "riscv_test.h" 2 | 3 | #include "test_macros_cap.h" 4 | #include "cheri.h" 5 | 6 | RVTEST_RV32U 7 | RVTEST_CODE_BEGIN 8 | 9 | INIT_ROOT_CAP 10 | 11 | TEST_CASE_DCC_BOUNDS_EXCEPTION(1, 0, CAUSE_LENGTH_VIOLATION, sb zero, (zero)) 12 | TEST_CASE_DCC_BOUNDS_EXCEPTION(2, 1, CAUSE_LENGTH_VIOLATION, sh zero, (zero)) 13 | TEST_CASE_DCC_BOUNDS_EXCEPTION(3, 3, CAUSE_LENGTH_VIOLATION, sw zero, (zero)) 14 | TEST_CASE_DCC_BOUNDS_EXCEPTION(4, 0, CAUSE_LENGTH_VIOLATION, lb zero, (zero)) 15 | TEST_CASE_DCC_BOUNDS_EXCEPTION(5, 1, CAUSE_LENGTH_VIOLATION, lh zero, (zero)) 16 | TEST_CASE_DCC_BOUNDS_EXCEPTION(6, 3, CAUSE_LENGTH_VIOLATION, lw zero, (zero)) 17 | 18 | TEST_CASE_DCC_BOUNDS_NO_EXCEPTION(7, 1, sb zero, (zero)) 19 | TEST_CASE_DCC_BOUNDS_NO_EXCEPTION(8, 2, sh zero, (zero)) 20 | TEST_CASE_DCC_BOUNDS_NO_EXCEPTION(9, 4, sw zero, (zero)) 21 | TEST_CASE_DCC_BOUNDS_NO_EXCEPTION(10, 1, lb zero, (zero)) 22 | TEST_CASE_DCC_BOUNDS_NO_EXCEPTION(11, 2, lh zero, (zero)) 23 | TEST_CASE_DCC_BOUNDS_NO_EXCEPTION(12, 4, lw zero, (zero)) 24 | 25 | TEST_CASE_DCC_AND_PERM_EXCEPTION(13, ~(1 << PERM_PERMIT_STORE), CAUSE_PERMIT_STORE_VIOLATION, sb zero, (zero)) 26 | TEST_CASE_DCC_AND_PERM_EXCEPTION(14, ~(1 << PERM_PERMIT_LOAD), CAUSE_PERMIT_LOAD_VIOLATION, lb zero, (zero)) 27 | 28 | TEST_CASE_DCC_AND_PERM_NO_EXCEPTION(15, ~(1 << PERM_PERMIT_STORE), lb zero, (zero)) 29 | TEST_CASE_DCC_AND_PERM_NO_EXCEPTION(16, ~(1 << PERM_PERMIT_LOAD), sb zero, (zero)) 30 | 31 | TEST_CASE_FREE(17) 32 | SET_BOUNDS_DCC(512) 33 | SEAL_DDC(123) 34 | EXPECT_EXCEPTION(CAUSE_SEAL_VIOLATION, CAP_IDX_DDC, sb zero, (zero)) 35 | 36 | TEST_PASSFAIL 37 | 38 | RVTEST_CODE_END 39 | 40 | .data 41 | RVTEST_DATA_BEGIN 42 | 43 | TEST_DATA 44 | 45 | RVTEST_DATA_END 46 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/RegisterFileAccessor.scala: -------------------------------------------------------------------------------- 1 | package riscv.plugins 2 | 3 | import riscv._ 4 | import spinal.core._ 5 | import spinal.lib._ 6 | 7 | class RegisterFileAccessor(readStage: Stage, writeStage: Stage) extends Plugin[Pipeline] { 8 | 9 | override def setup(): Unit = { 10 | pipeline.serviceOption[DataHazardService] foreach { dataHazardService => 11 | val hazardInfo = DataHazardInfo( 12 | RegisterType.GPR, 13 | pipeline.data.RS1_DATA, 14 | pipeline.data.RS2_DATA, 15 | pipeline.data.RD_DATA 16 | ) 17 | 18 | dataHazardService.addHazard(hazardInfo) 19 | } 20 | } 21 | 22 | override def build(): Unit = { 23 | val regFile = pipeline plug new RegisterFile() 24 | 25 | val readArea = readStage plug new Area { 26 | import readStage._ 27 | 28 | val regFileIo = slave(RegisterFileReadIo()) 29 | 30 | regFileIo.rs1 := value(pipeline.data.RS1) 31 | regFileIo.rs2 := value(pipeline.data.RS2) 32 | output(pipeline.data.RS1_DATA) := regFileIo.rs1Data 33 | output(pipeline.data.RS2_DATA) := regFileIo.rs2Data 34 | } 35 | 36 | val writeArea = writeStage plug new Area { 37 | import writeStage._ 38 | 39 | val regFileIo = slave(RegisterFileWriteIo()) 40 | 41 | regFileIo.rd := value(pipeline.data.RD) 42 | regFileIo.data := value(pipeline.data.RD_DATA) 43 | 44 | val hasTrapped = pipeline.serviceOption[TrapService] match { 45 | case Some(trapService) => trapService.hasTrapped(writeStage) 46 | case None => False 47 | } 48 | 49 | regFileIo.write := 50 | value(pipeline.data.RD_TYPE) === RegisterType.GPR && 51 | arbitration.isDone && 52 | !hasTrapped 53 | } 54 | 55 | pipeline plug new Area { 56 | regFile.readIo <> readArea.regFileIo 57 | regFile.writeIo <> writeArea.regFileIo 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /synthesis/Top.v: -------------------------------------------------------------------------------- 1 | module Top( 2 | input sysClk, 3 | input reset, 4 | input mtimer_update, 5 | input mtimer_interruptPending, 6 | input external_update, 7 | input external_interruptPending, 8 | output ibus_cmd_valid, 9 | input ibus_cmd_ready, 10 | output [31:0] ibus_cmd_payload_address, 11 | input ibus_rsp_valid, 12 | output ibus_rsp_ready, 13 | input [31:0] ibus_rsp_payload_rdata, 14 | output dbus_cmd_valid, 15 | input dbus_cmd_ready, 16 | output [31:0] dbus_cmd_payload_address, 17 | output dbus_cmd_payload_write, 18 | output [31:0] dbus_cmd_payload_wdata, 19 | output [3:0] dbus_cmd_payload_wmask, 20 | input dbus_rsp_valid, 21 | output dbus_rsp_ready, 22 | input [31:0] dbus_rsp_payload_rdata 23 | ); 24 | 25 | Pipeline pipeline( 26 | .clk (sysClk), 27 | .reset (reset), 28 | .external_update(external_update), 29 | .external_interruptPending(external_interruptPending), 30 | .ibus_cmd_valid(ibus_cmd_valid), 31 | .ibus_cmd_ready(ibus_cmd_ready), 32 | .ibus_cmd_payload_address(ibus_cmd_payload_address), 33 | .ibus_rsp_valid(ibus_rsp_valid), 34 | .ibus_rsp_ready(ibus_rsp_ready), 35 | .ibus_rsp_payload_rdata(ibus_rsp_payload_rdata), 36 | .dbus_cmd_valid(dbus_cmd_valid), 37 | .dbus_cmd_ready(dbus_cmd_ready), 38 | .dbus_cmd_payload_address(dbus_cmd_payload_address), 39 | .dbus_cmd_payload_write(dbus_cmd_payload_write), 40 | .dbus_cmd_payload_wdata(dbus_cmd_payload_wdata), 41 | .dbus_cmd_payload_wmask(dbus_cmd_payload_wmask), 42 | .dbus_rsp_valid(dbus_rsp_valid), 43 | .dbus_rsp_ready(dbus_rsp_ready), 44 | .dbus_rsp_payload_rdata(dbus_rsp_payload_rdata) 45 | ); 46 | 47 | endmodule 48 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-sha2/include/kremlib/fstar_uint128_struct_endianness.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) INRIA and Microsoft Corporation. All rights reserved. 2 | Licensed under the Apache 2.0 License. */ 3 | 4 | #ifndef FSTAR_UINT128_STRUCT_ENDIANNESS_H 5 | #define FSTAR_UINT128_STRUCT_ENDIANNESS_H 6 | 7 | /* Hand-written implementation of endianness-related uint128 functions 8 | * for the extracted uint128 implementation */ 9 | 10 | /* Access 64-bit fields within the int128. */ 11 | #define HIGH64_OF(x) ((x)->high) 12 | #define LOW64_OF(x) ((x)->low) 13 | 14 | /* A series of definitions written using pointers. */ 15 | 16 | inline static void load128_le_(uint8_t *b, uint128_t *r) { 17 | LOW64_OF(r) = load64_le(b); 18 | HIGH64_OF(r) = load64_le(b + 8); 19 | } 20 | 21 | inline static void store128_le_(uint8_t *b, uint128_t *n) { 22 | store64_le(b, LOW64_OF(n)); 23 | store64_le(b + 8, HIGH64_OF(n)); 24 | } 25 | 26 | inline static void load128_be_(uint8_t *b, uint128_t *r) { 27 | HIGH64_OF(r) = load64_be(b); 28 | LOW64_OF(r) = load64_be(b + 8); 29 | } 30 | 31 | inline static void store128_be_(uint8_t *b, uint128_t *n) { 32 | store64_be(b, HIGH64_OF(n)); 33 | store64_be(b + 8, LOW64_OF(n)); 34 | } 35 | 36 | #ifndef KRML_NOSTRUCT_PASSING 37 | 38 | inline static uint128_t load128_le(uint8_t *b) { 39 | uint128_t r; 40 | load128_le_(b, &r); 41 | return r; 42 | } 43 | 44 | inline static void store128_le(uint8_t *b, uint128_t n) { 45 | store128_le_(b, &n); 46 | } 47 | 48 | inline static uint128_t load128_be(uint8_t *b) { 49 | uint128_t r; 50 | load128_be_(b, &r); 51 | return r; 52 | } 53 | 54 | inline static void store128_be(uint8_t *b, uint128_t n) { 55 | store128_be_(b, &n); 56 | } 57 | 58 | #else /* !defined(KRML_STRUCT_PASSING) */ 59 | 60 | # define print128 print128_ 61 | # define load128_le load128_le_ 62 | # define store128_le store128_le_ 63 | # define load128_be load128_be_ 64 | # define store128_be store128_be_ 65 | 66 | #endif /* KRML_STRUCT_PASSING */ 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /tests/synthetic-benchmark/include/kremlib/fstar_uint128_struct_endianness.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) INRIA and Microsoft Corporation. All rights reserved. 2 | Licensed under the Apache 2.0 License. */ 3 | 4 | #ifndef FSTAR_UINT128_STRUCT_ENDIANNESS_H 5 | #define FSTAR_UINT128_STRUCT_ENDIANNESS_H 6 | 7 | /* Hand-written implementation of endianness-related uint128 functions 8 | * for the extracted uint128 implementation */ 9 | 10 | /* Access 64-bit fields within the int128. */ 11 | #define HIGH64_OF(x) ((x)->high) 12 | #define LOW64_OF(x) ((x)->low) 13 | 14 | /* A series of definitions written using pointers. */ 15 | 16 | inline static void load128_le_(uint8_t *b, uint128_t *r) { 17 | LOW64_OF(r) = load64_le(b); 18 | HIGH64_OF(r) = load64_le(b + 8); 19 | } 20 | 21 | inline static void store128_le_(uint8_t *b, uint128_t *n) { 22 | store64_le(b, LOW64_OF(n)); 23 | store64_le(b + 8, HIGH64_OF(n)); 24 | } 25 | 26 | inline static void load128_be_(uint8_t *b, uint128_t *r) { 27 | HIGH64_OF(r) = load64_be(b); 28 | LOW64_OF(r) = load64_be(b + 8); 29 | } 30 | 31 | inline static void store128_be_(uint8_t *b, uint128_t *n) { 32 | store64_be(b, HIGH64_OF(n)); 33 | store64_be(b + 8, LOW64_OF(n)); 34 | } 35 | 36 | #ifndef KRML_NOSTRUCT_PASSING 37 | 38 | inline static uint128_t load128_le(uint8_t *b) { 39 | uint128_t r; 40 | load128_le_(b, &r); 41 | return r; 42 | } 43 | 44 | inline static void store128_le(uint8_t *b, uint128_t n) { 45 | store128_le_(b, &n); 46 | } 47 | 48 | inline static uint128_t load128_be(uint8_t *b) { 49 | uint128_t r; 50 | load128_be_(b, &r); 51 | return r; 52 | } 53 | 54 | inline static void store128_be(uint8_t *b, uint128_t n) { 55 | store128_be_(b, &n); 56 | } 57 | 58 | #else /* !defined(KRML_STRUCT_PASSING) */ 59 | 60 | # define print128 print128_ 61 | # define load128_le load128_le_ 62 | # define store128_le store128_le_ 63 | # define load128_be load128_be_ 64 | # define store128_be store128_be_ 65 | 66 | #endif /* KRML_STRUCT_PASSING */ 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-chacha20/include/kremlib/fstar_uint128_struct_endianness.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) INRIA and Microsoft Corporation. All rights reserved. 2 | Licensed under the Apache 2.0 License. */ 3 | 4 | #ifndef FSTAR_UINT128_STRUCT_ENDIANNESS_H 5 | #define FSTAR_UINT128_STRUCT_ENDIANNESS_H 6 | 7 | /* Hand-written implementation of endianness-related uint128 functions 8 | * for the extracted uint128 implementation */ 9 | 10 | /* Access 64-bit fields within the int128. */ 11 | #define HIGH64_OF(x) ((x)->high) 12 | #define LOW64_OF(x) ((x)->low) 13 | 14 | /* A series of definitions written using pointers. */ 15 | 16 | inline static void load128_le_(uint8_t *b, uint128_t *r) { 17 | LOW64_OF(r) = load64_le(b); 18 | HIGH64_OF(r) = load64_le(b + 8); 19 | } 20 | 21 | inline static void store128_le_(uint8_t *b, uint128_t *n) { 22 | store64_le(b, LOW64_OF(n)); 23 | store64_le(b + 8, HIGH64_OF(n)); 24 | } 25 | 26 | inline static void load128_be_(uint8_t *b, uint128_t *r) { 27 | HIGH64_OF(r) = load64_be(b); 28 | LOW64_OF(r) = load64_be(b + 8); 29 | } 30 | 31 | inline static void store128_be_(uint8_t *b, uint128_t *n) { 32 | store64_be(b, HIGH64_OF(n)); 33 | store64_be(b + 8, LOW64_OF(n)); 34 | } 35 | 36 | #ifndef KRML_NOSTRUCT_PASSING 37 | 38 | inline static uint128_t load128_le(uint8_t *b) { 39 | uint128_t r; 40 | load128_le_(b, &r); 41 | return r; 42 | } 43 | 44 | inline static void store128_le(uint8_t *b, uint128_t n) { 45 | store128_le_(b, &n); 46 | } 47 | 48 | inline static uint128_t load128_be(uint8_t *b) { 49 | uint128_t r; 50 | load128_be_(b, &r); 51 | return r; 52 | } 53 | 54 | inline static void store128_be(uint8_t *b, uint128_t n) { 55 | store128_be_(b, &n); 56 | } 57 | 58 | #else /* !defined(KRML_STRUCT_PASSING) */ 59 | 60 | # define print128 print128_ 61 | # define load128_le load128_le_ 62 | # define store128_le store128_le_ 63 | # define load128_be load128_be_ 64 | # define store128_be store128_be_ 65 | 66 | #endif /* KRML_STRUCT_PASSING */ 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-chacha20/chacha20.c: -------------------------------------------------------------------------------- 1 | #include "Hacl_Chacha20.h" 2 | 3 | #include 4 | #include 5 | 6 | #define MESSAGE_LEN 72 7 | #define MACBYTES 16 8 | #define NONCEBYTES 12 9 | #define KEYBYTES 32 10 | #define CIPHERTEXT_LEN (MESSAGE_LEN) 11 | 12 | __attribute__((section(".secret"))) static uint8_t message[MESSAGE_LEN] = { 13 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 14 | 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 15 | 0x16, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23, 16 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 17 | 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 18 | 0x16, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23, 19 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 20 | 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 21 | 0x16, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23 22 | }; 23 | 24 | __attribute__((section(".public"))) static uint8_t nonce[NONCEBYTES] = { 25 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 26 | 0x06, 0x07, 0x08, 0x09, 0x10, 0x11 27 | }; 28 | 29 | __attribute__((section(".secret"))) static uint8_t key[KEYBYTES] = { 30 | 0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33, 31 | 0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8, 32 | 0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd, 33 | 0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b 34 | }; 35 | 36 | __attribute__((section(".secret"))) static uint8_t ciphertext[CIPHERTEXT_LEN]; 37 | __attribute__((section(".declassify"))) static volatile uint8_t declassified[CIPHERTEXT_LEN]; 38 | 39 | int main() { 40 | Hacl_Chacha20_chacha20_encrypt((uint32_t)MESSAGE_LEN, ciphertext, message, 41 | key, nonce, (uint32_t)0U); 42 | 43 | for (size_t i = 0; i < CIPHERTEXT_LEN; ++i) { 44 | declassified[i] = ciphertext[i]; 45 | } 46 | 47 | for (size_t i = 0; i < CIPHERTEXT_LEN; ++i) { 48 | printf("%02x", declassified[i]); 49 | } 50 | printf("\n"); 51 | // e5ec977d11d43aebe63af666bb5f4c3d2ae84bc2170803de67f1e76fd9130c83e0d443ffab602770576a3fd61c2d7ff3cd2c9bee595c82f6426d3e05d0232d4eb5f275c2927f4097 52 | } 53 | -------------------------------------------------------------------------------- /src/main/scala/riscv/Pipeline.scala: -------------------------------------------------------------------------------- 1 | package riscv 2 | 3 | import spinal.core._ 4 | 5 | import scala.collection.mutable 6 | import scala.reflect.ClassTag 7 | 8 | trait Pipeline { 9 | private val plugins = mutable.ArrayBuffer[Plugin[this.type]]() 10 | 11 | def config: Config 12 | def data: StandardPipelineData 13 | 14 | // NOTE This is deliberately not just called "component" because that causes a 15 | // (silent) name-clash with one of the traits implemented by Component. 16 | def pipelineComponent: Component 17 | 18 | def stages: Seq[Stage] 19 | def fetchStage: Stage 20 | def passThroughStage: Stage // TODO: this only makes sense for the dynamic pipeline? 21 | def retirementStage: Stage 22 | 23 | def addPlugin(plugin: Plugin[this.type]): Unit = { 24 | plugins += plugin 25 | } 26 | 27 | def addPlugins(plugins: Seq[Plugin[this.type]]): Unit = { 28 | this.plugins ++= plugins 29 | } 30 | 31 | final def initBuild(): Unit = { 32 | pipelineComponent.rework { 33 | init() 34 | } 35 | 36 | plugins.foreach(_.setPipeline(this)) 37 | } 38 | 39 | final def setupPlugins(): Unit = { 40 | plugins.foreach(_.setup()) 41 | } 42 | 43 | final def buildPlugins(): Unit = { 44 | plugins.foreach(_.build()) 45 | } 46 | 47 | final def finishBuild(): Unit = { 48 | pipelineComponent.rework { 49 | connectStages() 50 | } 51 | 52 | plugins.foreach(_.finish()) 53 | } 54 | 55 | def build(): Unit = { 56 | initBuild() 57 | setupPlugins() 58 | buildPlugins() 59 | finishBuild() 60 | } 61 | 62 | protected def init(): Unit 63 | protected def connectStages(): Unit 64 | 65 | def serviceOption[T](implicit tag: ClassTag[T]): Option[T] = { 66 | val services = plugins.filter(_ match { 67 | case _: T => true 68 | case _ => false 69 | }) 70 | 71 | assert(services.length <= 1) 72 | services.headOption.map(_.asInstanceOf[T]) 73 | } 74 | 75 | def service[T](implicit tag: ClassTag[T]): T = { 76 | serviceOption[T].get 77 | } 78 | 79 | def hasService[T](implicit tag: ClassTag[T]): Boolean = { 80 | serviceOption[T].isDefined 81 | } 82 | 83 | def getImplementedExtensions: Seq[Extension] = { 84 | Extension(config.baseIsa) +: plugins.flatMap(_.getImplementedExtensions) 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /tests/crypto/curve25519/curve25519.S: -------------------------------------------------------------------------------- 1 | .file "curve25519.c" 2 | .option nopic 3 | .attribute arch, "rv32i2p0_m2p0" 4 | .attribute unaligned_access, 0 5 | .attribute stack_align, 16 6 | .text 7 | .section .rodata.str1.4,"aMS",@progbits,1 8 | .align 2 9 | .LC0: 10 | .string "%02x" 11 | .section .text.startup,"ax",@progbits 12 | .align 2 13 | .globl main 14 | .type main, @function 15 | main: 16 | addi sp,sp,-32 17 | sw s0,24(sp) 18 | lui s0,%hi(.LANCHOR0) 19 | addi a0,s0,%lo(.LANCHOR0) 20 | addi a1,a0,32 21 | addi a2,s0,%lo(.LANCHOR0) 22 | addi a0,a0,64 23 | sw s1,20(sp) 24 | sw ra,28(sp) 25 | sw s2,16(sp) 26 | sw s3,12(sp) 27 | lui s1,%hi(.LANCHOR1) 28 | call curve25519_donna 29 | addi a4,s0,%lo(.LANCHOR0) 30 | li a5,0 31 | addi s1,s1,%lo(.LANCHOR1) 32 | li a1,32 33 | .L2: 34 | lbu a2,0(a4) 35 | add a3,s1,a5 36 | addi a5,a5,1 37 | sb a2,0(a3) 38 | addi a4,a4,1 39 | bne a5,a1,.L2 40 | # Begin: Extra code to clear secrets from registers 41 | addi sp,sp,-4 42 | sw s1,0(sp) 43 | call clear_s_regs 44 | call clear_t_regs 45 | lw s1,0(sp) 46 | addi sp,sp,4 47 | # End 48 | li s0,0 49 | lui s3,%hi(.LC0) 50 | li s2,32 51 | .L3: 52 | add a5,s1,s0 53 | lbu a1,0(a5) 54 | addi s0,s0,1 55 | addi a0,s3,%lo(.LC0) 56 | call printf 57 | bne s0,s2,.L3 58 | li a0,10 59 | call putchar 60 | lw ra,28(sp) 61 | lw s0,24(sp) 62 | lw s1,20(sp) 63 | lw s2,16(sp) 64 | lw s3,12(sp) 65 | li a0,0 66 | addi sp,sp,32 67 | jr ra 68 | .size main, .-main 69 | .globl declassified 70 | .globl private 71 | .globl public 72 | .globl out 73 | .section .declassified,"aw" 74 | .align 2 75 | .set .LANCHOR1,. + 0 76 | .type declassified, @object 77 | .size declassified, 32 78 | declassified: 79 | .zero 32 80 | .section .secret,"aw" 81 | .align 2 82 | .set .LANCHOR0,. + 0 83 | .type out, @object 84 | .size out, 32 85 | out: 86 | .ascii "\245F\343k\360R|\235;\026\025K\202F^\335b\024L\n\301\374Z\030" 87 | .ascii "Pj\"D\272D\232\304" 88 | .type public, @object 89 | .size public, 32 90 | public: 91 | .ascii "\346\333hgX00\3335\224\301\244$\261_|rf$\354&\2635;\020\251\003" 92 | .ascii "\246\320\253\034L" 93 | .type private, @object 94 | .size private, 32 95 | private: 96 | .ascii "\303\332U7\235\351\306\220\216\224\352M\362\215\bO2\354\317\003" 97 | .ascii "I\034q\367T\264\007Uw\242\205R" 98 | .ident "GCC: (GNU) 11.1.0" 99 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/cheri/Services.scala: -------------------------------------------------------------------------------- 1 | package riscv.plugins.cheri 2 | 3 | import riscv._ 4 | 5 | import spinal.core._ 6 | import spinal.lib._ 7 | 8 | trait PccService { 9 | def getPcc(stage: Stage): Capability 10 | def jump(stage: Stage, pcc: Capability, capIdx: CapIdx): Unit 11 | } 12 | 13 | trait Scr { 14 | val needAsr: Boolean 15 | 16 | def read(): Capability 17 | def write(value: Capability) 18 | } 19 | 20 | case class ScrIo(implicit context: Context) extends Bundle with IMasterSlave { 21 | val valid = Bool() 22 | val id = UInt(5 bits) 23 | val write = Bool() 24 | val wdata = PackedCapability() 25 | val rdata = PackedCapability() 26 | val unknownId = Bool() 27 | val hasAsr = Bool() 28 | val needAsr = Bool() 29 | 30 | override def asMaster(): Unit = { 31 | in(valid, id, write, wdata, hasAsr) 32 | out(rdata, unknownId, needAsr) 33 | } 34 | } 35 | 36 | trait ScrService { 37 | 38 | /** Get an IO port for accessing the SCR file. 39 | * 40 | * This has to be called during the setup phase. 41 | * 42 | * Note that when multiple stages create IO ports, it's undefined which one "wins" when more than 43 | * one tries to access it. Therefore, plugins using this method should somehow ensure that they 44 | * have exclusive access, e.g., by using [[ScheduleService.claimPipeline()]]. 45 | */ 46 | def getIo(stage: Stage): ScrIo 47 | def getPcc(stage: Stage): Capability 48 | def getDdc(stage: Stage): Capability 49 | 50 | def registerScr[T <: Scr](id: Int, scr: => T): T 51 | 52 | /** Register a new SCR that extends the given CSR. Extending a CSR means that reads and write of 53 | * the CSR will refer to this SCR's offset. 54 | */ 55 | def registerScr[T <: Scr](id: Int, offsetCsr: Int, scr: => T): T 56 | def getScr(stage: Stage, id: Int): Scr 57 | def getRegisteredScrs: Seq[Int] 58 | } 59 | 60 | trait ExceptionService { 61 | protected def handleException(stage: Stage, cause: UInt, capIdx: CapIdx): Unit 62 | 63 | def except(stage: Stage, cause: UInt, capIdx: CapIdx): Unit = { 64 | handleException(stage, cause, capIdx) 65 | } 66 | 67 | def except(stage: Stage, cause: ExceptionCause, capIdx: CapIdx): Unit = { 68 | handleException(stage, U(cause.code), capIdx) 69 | } 70 | } 71 | 72 | trait TaggedMemoryService { 73 | def createCapBus(stage: Stage): CapBus 74 | } 75 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/scheduling/dynamic/Dispatcher.scala: -------------------------------------------------------------------------------- 1 | package riscv.plugins.scheduling.dynamic 2 | 3 | import riscv._ 4 | import spinal.core._ 5 | import spinal.lib.Stream 6 | 7 | class Dispatcher( 8 | pipeline: DynamicPipeline, 9 | rob: ReorderBuffer, 10 | loadManagers: Seq[LoadManager], 11 | retirementRegisters: DynBundle[PipelineData[Data]] 12 | ) extends Area 13 | with Resettable { 14 | val rdbStream: Stream[RdbMessage] = Stream( 15 | HardType(RdbMessage(retirementRegisters, rob.indexBits)) 16 | ) 17 | val storedMessage: RdbMessage = RegInit(RdbMessage(retirementRegisters, rob.indexBits).getZero) 18 | 19 | private object State extends SpinalEnum { 20 | val IDLE, BROADCASTING_RESULT = newElement() 21 | } 22 | 23 | private val stateNext = State() 24 | private val state = RegNext(stateNext).init(State.IDLE) 25 | 26 | private val activeFlush = Bool() 27 | 28 | def processMessage(rdbMessage: RdbMessage): Bool = { 29 | val ret = Bool() 30 | ret := False 31 | 32 | val lsu = pipeline.service[LsuService] 33 | 34 | when(lsu.operationOfBundle(rdbMessage.registerMap) === LsuOperationType.LOAD) { 35 | var context = when(False) {} 36 | for (lm <- loadManagers) { 37 | context = context.elsewhen(lm.isAvailable) { 38 | ret := lm.receiveMessage(rdbMessage) 39 | } 40 | } 41 | context.otherwise { 42 | ret := False 43 | } 44 | } elsewhen (!activeFlush) { 45 | when(state === State.BROADCASTING_RESULT) { 46 | ret := False 47 | } otherwise { 48 | storedMessage := rdbMessage 49 | rdbStream.payload := rdbMessage 50 | rdbStream.valid := True 51 | when(!rdbStream.ready) { 52 | stateNext := State.BROADCASTING_RESULT 53 | } 54 | ret := True 55 | } 56 | } otherwise { 57 | ret := False 58 | } 59 | ret 60 | } 61 | 62 | def build(): Unit = { 63 | rdbStream.payload := storedMessage 64 | rdbStream.valid := False 65 | 66 | stateNext := state 67 | 68 | activeFlush := False 69 | 70 | when(activeFlush) { 71 | stateNext := State.IDLE 72 | } 73 | 74 | when(state === State.BROADCASTING_RESULT && !activeFlush) { 75 | rdbStream.valid := True 76 | when(rdbStream.ready) { 77 | stateNext := State.IDLE 78 | } 79 | } 80 | } 81 | 82 | override def pipelineReset(): Unit = { 83 | activeFlush := True 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/scala/riscv/RegisterFile.scala: -------------------------------------------------------------------------------- 1 | package riscv 2 | 3 | import riscv._ 4 | import spinal.core._ 5 | import spinal.lib._ 6 | 7 | case class RegisterFileReadIo()(implicit config: Config) extends Bundle with IMasterSlave { 8 | val rs1 = UInt(5 bits) 9 | val rs2 = UInt(5 bits) 10 | val rs1Data = UInt(config.xlen bits) 11 | val rs2Data = UInt(config.xlen bits) 12 | 13 | override def asMaster(): Unit = { 14 | in(rs1, rs2) 15 | out(rs1Data, rs2Data) 16 | } 17 | } 18 | 19 | case class RegisterFileWriteIo()(implicit config: Config) extends Bundle with IMasterSlave { 20 | val rd = UInt(5 bits) 21 | val data = UInt(config.xlen bits) 22 | val write = Bool() 23 | 24 | override def asMaster(): Unit = { 25 | in(rd, data, write) 26 | } 27 | } 28 | 29 | class RegisterFile()(implicit config: Config) extends Component { 30 | 31 | private val registerNames = Seq( 32 | "zero", 33 | "ra", 34 | "sp", 35 | "gp", 36 | "tp", 37 | "t0", 38 | "t1", 39 | "t2", 40 | "s0_fp", 41 | "s1", 42 | "a0", 43 | "a1", 44 | "a2", 45 | "a3", 46 | "a4", 47 | "a5", 48 | "a6", 49 | "a7", 50 | "s2", 51 | "s3", 52 | "s4", 53 | "s5", 54 | "s6", 55 | "s7", 56 | "s8", 57 | "s9", 58 | "s10", 59 | "s11", 60 | "t3", 61 | "t4", 62 | "t5", 63 | "t6" 64 | ) 65 | 66 | val readIo = master(RegisterFileReadIo()) 67 | val writeIo = master(RegisterFileWriteIo()) 68 | val regs = Mem(UInt(config.xlen bits), config.numRegs) 69 | 70 | // Add a wire for each register with a readable name. This is to easily 71 | // view register values in a wave dump. 72 | for (i <- 0 until config.numRegs) { 73 | val regWire = UInt(config.xlen bits) 74 | val regName = registerNames(i) 75 | regWire.setName(s"x${i}_${regName}") 76 | regWire := regs.readAsync(U(i).resized, writeFirst) 77 | } 78 | 79 | // We explicitly check if x0 is read and return 0 in that case. Another 80 | // option would be to initialize regs(0) to zero at boot. However, this 81 | // slows-down riscv-formal runs significantly for some reason... 82 | def readReg(addr: UInt) = { 83 | addr.mux( 84 | 0 -> U(0, config.xlen bits), 85 | default -> regs.readAsync(addr, writeFirst) 86 | ) 87 | } 88 | 89 | readIo.rs1Data := readReg(readIo.rs1) 90 | readIo.rs2Data := readReg(readIo.rs2) 91 | 92 | when(writeIo.write && writeIo.rd =/= 0) { 93 | regs(writeIo.rd) := writeIo.data 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/Shifter.scala: -------------------------------------------------------------------------------- 1 | package riscv.plugins 2 | 3 | import riscv._ 4 | 5 | import spinal.core._ 6 | 7 | class Shifter(exeStages: Set[Stage]) extends Plugin[Pipeline] { 8 | object ShiftOp extends SpinalEnum { 9 | val NONE, SLL, SRL, SRA = newElement() 10 | } 11 | 12 | object Data { 13 | object SHIFT_OP extends PipelineData(ShiftOp()) 14 | } 15 | 16 | override def setup(): Unit = { 17 | val issuer = pipeline.service[IssueService] 18 | 19 | pipeline.service[DecoderService].configure { config => 20 | config.addDefault( 21 | Map( 22 | Data.SHIFT_OP -> ShiftOp.NONE 23 | ) 24 | ) 25 | 26 | val ops = Seq( 27 | (Opcodes.SLLI, ShiftOp.SLL, InstructionType.I), 28 | (Opcodes.SRLI, ShiftOp.SRL, InstructionType.I), 29 | (Opcodes.SRAI, ShiftOp.SRA, InstructionType.I), 30 | (Opcodes.SLL, ShiftOp.SLL, InstructionType.R), 31 | (Opcodes.SRL, ShiftOp.SRL, InstructionType.R), 32 | (Opcodes.SRA, ShiftOp.SRA, InstructionType.R) 33 | ) 34 | 35 | for ((opcode, op, itype) <- ops) { 36 | config.addDecoding( 37 | opcode, 38 | itype, 39 | Map( 40 | Data.SHIFT_OP -> op 41 | ) 42 | ) 43 | issuer.setDestinations(opcode, exeStages) 44 | } 45 | } 46 | } 47 | 48 | override def build(): Unit = { 49 | for (exeStage <- exeStages) { 50 | exeStage plug new Area { 51 | import exeStage._ 52 | 53 | val src = UInt(config.xlen bits) 54 | src := value(pipeline.data.RS1_DATA) 55 | val shamt = UInt(5 bits) 56 | val useImm = value(pipeline.data.IMM_USED) 57 | 58 | when(useImm) { 59 | shamt := value(pipeline.data.IMM)(4 downto 0) 60 | } otherwise { 61 | shamt := value(pipeline.data.RS2_DATA)(4 downto 0) 62 | } 63 | 64 | val op = value(Data.SHIFT_OP) 65 | 66 | val result = op.mux( 67 | ShiftOp.NONE -> U(0), 68 | ShiftOp.SLL -> (src |<< shamt), 69 | ShiftOp.SRL -> (src |>> shamt), 70 | ShiftOp.SRA -> (src.asSInt >> shamt).asUInt 71 | ) 72 | 73 | when(arbitration.isValid && op =/= ShiftOp.NONE) { 74 | arbitration.rs1Needed := True 75 | arbitration.rs2Needed := !useImm 76 | output(pipeline.data.RD_DATA) := result 77 | output(pipeline.data.RD_DATA_VALID) := True 78 | } 79 | } 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-sha2/sha2.c: -------------------------------------------------------------------------------- 1 | #include "Hacl_Hash_SHA2.h" 2 | 3 | #include 4 | #include 5 | 6 | // for i in {1..300}; do N=$(od -A n -tx1 -N 1 /dev/urandom | cut -d ' ' -f2); echo -n "0x$N, "; done 7 | __attribute__((section(".secret"))) uint8_t secret[] = { 0x51, 0xeb, 0xd8, 0xbb, 0x95, 0x5f, 0xa2, 0x91, 0x6f, 0x87, 0x27, 0xb6, 0x7b, 0x3c, 0xd3, 0xe0, 0x15, 0xc0, 0x71, 0x54, 0x19, 0x40, 0xb9, 0x32, 0x5b, 0x14, 0x41, 0xbf, 0x53, 0xbe, 0x6a, 0xc4, 0xe0, 0xaa, 0xcf, 0x92, 0xa4, 0xac, 0x5d, 0x45, 0x9b, 0x72, 0x49, 0x0d, 0xb9, 0x91, 0x54, 0x97, 0x4e, 0xe2, 0xa6, 0xd9, 0xa9, 0xda, 0x01, 0x05, 0x3a, 0xd5, 0x62, 0x65, 0x4a, 0x3c, 0xdd, 0xaf, 0x31, 0x07, 0x16, 0xcc, 0x18, 0x5a, 0x99, 0xdb, 0x50, 0x89, 0x34, 0x32, 0x2f, 0x37, 0x1c, 0xb3, 0x41, 0x02, 0x22, 0xb3, 0x5d, 0x7b, 0x32, 0xf0, 0x91, 0x77, 0xf3, 0x4c, 0x39, 0xa5, 0xa7, 0xf9, 0xc2, 0x73, 0x81, 0xb1, 0x9a, 0x50, 0x71, 0x39, 0xc6, 0xb3, 0xe5, 0x12, 0xed, 0x3e, 0x87, 0xcb, 0xc5, 0x46, 0x1c, 0x7c, 0x88, 0x49, 0x51, 0x7d, 0x8c, 0x54, 0xa4, 0xda, 0x58, 0x78, 0x87, 0xe0, 0x6f, 0x1a, 0x2b, 0xd2, 0x40, 0x0b, 0x47, 0x72, 0x76, 0x5b, 0x07, 0xbb, 0x3b, 0xd6, 0xe5, 0x38, 0x5c, 0x46, 0x7c, 0x60, 0xd0, 0x03, 0xc7, 0xe5, 0x97, 0x16, 0x7c, 0x23, 0x45, 0x26, 0x29, 0xbc, 0x41, 0x11, 0x17, 0x88, 0x78, 0xe4, 0xce, 0x32, 0x2d, 0xa3, 0x97, 0x34, 0x73, 0x3a, 0xb9, 0x26, 0x5b, 0xdd, 0xd2, 0x0e, 0xa8, 0xbd, 0xd4, 0xa8, 0x71, 0xae, 0x98, 0x69, 0x40, 0x25, 0x93, 0xe8, 0x89, 0x81, 0xc5, 0x11, 0xe3, 0x98, 0x5b, 0xca, 0xdc, 0xb8, 0x8b, 0x7f, 0x92, 0xc8, 0xd2, 0xbe, 0xed, 0xc4, 0x85, 0x86, 0x0f, 0x3a, 0x29, 0x1c, 0x09, 0x08, 0xfc, 0x4c, 0xe2, 0x8b, 0x6a, 0x80, 0x9d, 0xbc, 0xa4, 0xb2, 0x5a, 0xfc, 0x66, 0x2b, 0xc4, 0x35, 0x26, 0xaf, 0x69, 0xf3, 0xb4, 0xff, 0xe2, 0x0e, 0x65, 0x58, 0x2a, 0x69, 0x77, 0xb7, 0x6c, 0xda, 0x47, 0x8a, 0x78, 0xce, 0x81, 0x9e, 0x34, 0xfb, 0x28, 0x96, 0x82, 0xda, 0xc6, 0x6e, 0x70, 0xa0, 0x46, 0xa9, 0x7c, 0x1d, 0xa8, 0x8a, 0x94, 0x66, 0x46, 0x3e, 0xa0, 0x74, 0x0e, 0x0e, 0x16, 0x25, 0xc7, 0xaf, 0x73, 0xfa, 0xab, 0x1e, 0x52, 0x2c, 0x74, 0xbd, 0x11, 0x29, 0xe9, 0x1a, 0x98, 0x93, 0x5b, 0x3a }; 8 | __attribute__((section(".secret"))) uint8_t hash[32]; 9 | __attribute__((section(".declassified"))) volatile uint8_t public[32]; 10 | 11 | int main() { 12 | 13 | Hacl_Hash_SHA2_hash_256(secret, sizeof(secret), hash); 14 | 15 | for (size_t i = 0; i < sizeof(hash); ++i) { 16 | public[i] = hash[i]; 17 | } 18 | 19 | for (size_t i = 0; i < sizeof(public); ++i) { 20 | printf("%02x", public[i]); 21 | } // 44b302f763d628b29928366a0ea744edc74786ad03bf95cb35774cd29eafbaaf 22 | 23 | printf("\n"); 24 | } 25 | -------------------------------------------------------------------------------- /tests/synthetic-benchmark/Hacl_Chacha20.h: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | * 3 | * Copyright (c) 2016-2020 INRIA, CMU and Microsoft Corporation 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in all 13 | * copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | 25 | #ifndef __Hacl_Chacha20_H 26 | #define __Hacl_Chacha20_H 27 | 28 | #if defined(__cplusplus) 29 | extern "C" { 30 | #endif 31 | 32 | /* #include "evercrypt_targetconfig.h" */ 33 | /* #include "libintvector.h" */ 34 | #include "kremlin/internal/types.h" 35 | /* #include "kremlin/lowstar_endianness.h" */ 36 | /* #include */ 37 | /* #include "kremlin/internal/target.h" */ 38 | 39 | 40 | /* #include "Hacl_Kremlib.h" */ 41 | 42 | extern const uint32_t Hacl_Impl_Chacha20_Vec_chacha20_constants[4U]; 43 | 44 | void Hacl_Impl_Chacha20_chacha20_init(uint32_t *ctx, uint8_t *k, uint8_t *n, uint32_t ctr); 45 | 46 | void 47 | Hacl_Impl_Chacha20_chacha20_encrypt_block( 48 | uint32_t *ctx, 49 | uint8_t *out, 50 | uint32_t incr, 51 | uint8_t *text 52 | ); 53 | 54 | void 55 | Hacl_Impl_Chacha20_chacha20_update(uint32_t *ctx, uint32_t len, uint8_t *out, uint8_t *text); 56 | 57 | void 58 | Hacl_Chacha20_chacha20_encrypt( 59 | uint32_t len, 60 | uint8_t *out, 61 | uint8_t *text, 62 | uint8_t *key, 63 | uint8_t *n, 64 | uint32_t ctr 65 | ); 66 | 67 | void 68 | Hacl_Chacha20_chacha20_decrypt( 69 | uint32_t len, 70 | uint8_t *out, 71 | uint8_t *cipher, 72 | uint8_t *key, 73 | uint8_t *n, 74 | uint32_t ctr 75 | ); 76 | 77 | #if defined(__cplusplus) 78 | } 79 | #endif 80 | 81 | #define __Hacl_Chacha20_H_DEFINED 82 | #endif 83 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-chacha20/Hacl_Chacha20.h: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | * 3 | * Copyright (c) 2016-2020 INRIA, CMU and Microsoft Corporation 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in all 13 | * copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | 25 | #ifndef __Hacl_Chacha20_H 26 | #define __Hacl_Chacha20_H 27 | 28 | #if defined(__cplusplus) 29 | extern "C" { 30 | #endif 31 | 32 | /* #include "evercrypt_targetconfig.h" */ 33 | /* #include "libintvector.h" */ 34 | #include "kremlin/internal/types.h" 35 | /* #include "kremlin/lowstar_endianness.h" */ 36 | /* #include */ 37 | /* #include "kremlin/internal/target.h" */ 38 | 39 | 40 | /* #include "Hacl_Kremlib.h" */ 41 | 42 | extern const uint32_t Hacl_Impl_Chacha20_Vec_chacha20_constants[4U]; 43 | 44 | void Hacl_Impl_Chacha20_chacha20_init(uint32_t *ctx, uint8_t *k, uint8_t *n, uint32_t ctr); 45 | 46 | void 47 | Hacl_Impl_Chacha20_chacha20_encrypt_block( 48 | uint32_t *ctx, 49 | uint8_t *out, 50 | uint32_t incr, 51 | uint8_t *text 52 | ); 53 | 54 | void 55 | Hacl_Impl_Chacha20_chacha20_update(uint32_t *ctx, uint32_t len, uint8_t *out, uint8_t *text); 56 | 57 | void 58 | Hacl_Chacha20_chacha20_encrypt( 59 | uint32_t len, 60 | uint8_t *out, 61 | uint8_t *text, 62 | uint8_t *key, 63 | uint8_t *n, 64 | uint32_t ctr 65 | ); 66 | 67 | void 68 | Hacl_Chacha20_chacha20_decrypt( 69 | uint32_t len, 70 | uint8_t *out, 71 | uint8_t *cipher, 72 | uint8_t *key, 73 | uint8_t *n, 74 | uint32_t ctr 75 | ); 76 | 77 | #if defined(__cplusplus) 78 | } 79 | #endif 80 | 81 | #define __Hacl_Chacha20_H_DEFINED 82 | #endif 83 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/cheri/tests/Pcc.S: -------------------------------------------------------------------------------- 1 | #include "riscv_test.h" 2 | 3 | #include "test_macros_cap.h" 4 | #include "cheri.h" 5 | 6 | #define SET_DUMMY_TARGET(cap) \ 7 | la t0, dummy_jump_target; \ 8 | CSetOffset cap, ROOT, t0; \ 9 | CSetBoundsImm cap, cap, 4 10 | 11 | 12 | RVTEST_RV32U 13 | RVTEST_CODE_BEGIN 14 | 15 | INIT_ROOT_CAP 16 | 17 | # Jump to non-executable capability 18 | TEST_CASE_START(1) 19 | SET_DUMMY_TARGET(c1) 20 | li t0, ~(1 << PERM_PERMIT_EXECUTE) 21 | CAndPerm c1, c1, t0 22 | EXPECT_EXCEPTION(CAUSE_PERMIT_EXECUTE_VIOLATION, 1, CJALR c1) 23 | 24 | # Jump to capability with length 0 25 | TEST_CASE_START(2) 26 | SET_DUMMY_TARGET(c1) 27 | CSetBoundsImm c1, c1, 0 28 | EXPECT_EXCEPTION(CAUSE_LENGTH_VIOLATION, 1, CJALR c1) 29 | 30 | # Jump to capability with length 3 31 | TEST_CASE_START(3) 32 | SET_DUMMY_TARGET(c1) 33 | CSetBoundsImm c1, c1, 3 34 | EXPECT_EXCEPTION(CAUSE_LENGTH_VIOLATION, 1, CJALR c1) 35 | 36 | # Jump to capability with unset tag 37 | TEST_CASE_START(4) 38 | SET_DUMMY_TARGET(c1) 39 | CClearTag c1, c1 40 | EXPECT_EXCEPTION(CAUSE_TAG_VIOLATION, 1, CJALR c1) 41 | 42 | # Overflow execution out of capabiliy range (4 bytes) 43 | TEST_CASE_START(5) 44 | la t0, 1f 45 | CSetBounds c1, ROOT, t0 46 | la t0, 2f 47 | CSetOffset c1, c1, t0 48 | CJALR c1 49 | 2: 50 | EXPECT_EXCEPTION(CAUSE_LENGTH_VIOLATION, CAP_IDX_PCC, 1: j fail) 51 | 52 | # Overflow execution out of capabiliy range (1 byte) 53 | TEST_CASE_START(6) 54 | la t0, 1f 55 | addi t0, t0, 3 56 | CSetBounds c1, ROOT, t0 57 | la t0, 2f 58 | CSetOffset c1, c1, t0 59 | CJALR c1 60 | 2: 61 | EXPECT_EXCEPTION(CAUSE_LENGTH_VIOLATION, CAP_IDX_PCC, 1: j fail) 62 | 63 | # mret while mepcc has invalid capability 64 | TEST_CASE_START(7) 65 | la t0, 1f 66 | CSetOffset c1, ROOT, t0 67 | CClearTag c1, c1 68 | CSpecialW mepcc, c1 69 | 70 | la t0, 2f 71 | CSetOffset c2, ROOT, t0 72 | CSpecialW mtcc, c2 73 | 74 | mret 75 | 1: 76 | j fail 77 | 2: 78 | 79 | # Jump to sealed capability 80 | TEST_CASE_START(8) 81 | SET_DUMMY_TARGET(c1) 82 | SEAL(c1, c1, 456) 83 | EXPECT_EXCEPTION(CAUSE_SEAL_VIOLATION, 1, CJALR c1) 84 | 85 | TEST_PASSFAIL 86 | 87 | dummy_jump_target: 88 | CRET 89 | 90 | RVTEST_CODE_END 91 | 92 | .data 93 | RVTEST_DATA_BEGIN 94 | 95 | TEST_DATA 96 | 97 | RVTEST_DATA_END 98 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-sha2/include/kremlin/fstar_int.h: -------------------------------------------------------------------------------- 1 | #ifndef __FSTAR_INT_H 2 | #define __FSTAR_INT_H 3 | 4 | #include "internal/types.h" 5 | 6 | /* 7 | * Arithmetic Shift Right operator 8 | * 9 | * In all C standards, a >> b is implementation-defined when a has a signed 10 | * type and a negative value. See e.g. 6.5.7 in 11 | * http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2310.pdf 12 | * 13 | * GCC, MSVC, and Clang implement a >> b as an arithmetic shift. 14 | * 15 | * GCC: https://gcc.gnu.org/onlinedocs/gcc-9.1.0/gcc/Integers-implementation.html#Integers-implementation 16 | * MSVC: https://docs.microsoft.com/en-us/cpp/cpp/left-shift-and-right-shift-operators-input-and-output?view=vs-2019#right-shifts 17 | * Clang: tested that Clang 7, 8 and 9 compile this to an arithmetic shift 18 | * 19 | * We implement arithmetic shift right simply as >> in these compilers 20 | * and bail out in others. 21 | */ 22 | 23 | #if !(defined(_MSC_VER) || defined(__GNUC__) || (defined(__clang__) && (__clang_major__ >= 7))) 24 | 25 | static inline 26 | int8_t FStar_Int8_shift_arithmetic_right(int8_t a, uint32_t b) { 27 | do { 28 | KRML_HOST_EPRINTF("Could not identify compiler so could not provide an implementation of signed arithmetic shift right.\n"); 29 | KRML_HOST_EXIT(255); 30 | } while (0); 31 | } 32 | 33 | static inline 34 | int16_t FStar_Int16_shift_arithmetic_right(int16_t a, uint32_t b) { 35 | do { 36 | KRML_HOST_EPRINTF("Could not identify compiler so could not provide an implementation of signed arithmetic shift right.\n"); 37 | KRML_HOST_EXIT(255); 38 | } while (0); 39 | } 40 | 41 | static inline 42 | int32_t FStar_Int32_shift_arithmetic_right(int32_t a, uint32_t b) { 43 | do { 44 | KRML_HOST_EPRINTF("Could not identify compiler so could not provide an implementation of signed arithmetic shift right.\n"); 45 | KRML_HOST_EXIT(255); 46 | } while (0); 47 | } 48 | 49 | static inline 50 | int64_t FStar_Int64_shift_arithmetic_right(int64_t a, uint32_t b) { 51 | do { 52 | KRML_HOST_EPRINTF("Could not identify compiler so could not provide an implementation of signed arithmetic shift right.\n"); 53 | KRML_HOST_EXIT(255); 54 | } while (0); 55 | } 56 | 57 | #else 58 | 59 | static inline 60 | int8_t FStar_Int8_shift_arithmetic_right(int8_t a, uint32_t b) { 61 | return (a >> b); 62 | } 63 | 64 | static inline 65 | int16_t FStar_Int16_shift_arithmetic_right(int16_t a, uint32_t b) { 66 | return (a >> b); 67 | } 68 | 69 | static inline 70 | int32_t FStar_Int32_shift_arithmetic_right(int32_t a, uint32_t b) { 71 | return (a >> b); 72 | } 73 | 74 | static inline 75 | int64_t FStar_Int64_shift_arithmetic_right(int64_t a, uint32_t b) { 76 | return (a >> b); 77 | } 78 | 79 | #endif /* !(defined(_MSC_VER) ... ) */ 80 | 81 | #endif /* __FSTAR_INT_H */ 82 | -------------------------------------------------------------------------------- /tests/synthetic-benchmark/include/kremlin/fstar_int.h: -------------------------------------------------------------------------------- 1 | #ifndef __FSTAR_INT_H 2 | #define __FSTAR_INT_H 3 | 4 | #include "internal/types.h" 5 | 6 | /* 7 | * Arithmetic Shift Right operator 8 | * 9 | * In all C standards, a >> b is implementation-defined when a has a signed 10 | * type and a negative value. See e.g. 6.5.7 in 11 | * http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2310.pdf 12 | * 13 | * GCC, MSVC, and Clang implement a >> b as an arithmetic shift. 14 | * 15 | * GCC: https://gcc.gnu.org/onlinedocs/gcc-9.1.0/gcc/Integers-implementation.html#Integers-implementation 16 | * MSVC: https://docs.microsoft.com/en-us/cpp/cpp/left-shift-and-right-shift-operators-input-and-output?view=vs-2019#right-shifts 17 | * Clang: tested that Clang 7, 8 and 9 compile this to an arithmetic shift 18 | * 19 | * We implement arithmetic shift right simply as >> in these compilers 20 | * and bail out in others. 21 | */ 22 | 23 | #if !(defined(_MSC_VER) || defined(__GNUC__) || (defined(__clang__) && (__clang_major__ >= 7))) 24 | 25 | static inline 26 | int8_t FStar_Int8_shift_arithmetic_right(int8_t a, uint32_t b) { 27 | do { 28 | KRML_HOST_EPRINTF("Could not identify compiler so could not provide an implementation of signed arithmetic shift right.\n"); 29 | KRML_HOST_EXIT(255); 30 | } while (0); 31 | } 32 | 33 | static inline 34 | int16_t FStar_Int16_shift_arithmetic_right(int16_t a, uint32_t b) { 35 | do { 36 | KRML_HOST_EPRINTF("Could not identify compiler so could not provide an implementation of signed arithmetic shift right.\n"); 37 | KRML_HOST_EXIT(255); 38 | } while (0); 39 | } 40 | 41 | static inline 42 | int32_t FStar_Int32_shift_arithmetic_right(int32_t a, uint32_t b) { 43 | do { 44 | KRML_HOST_EPRINTF("Could not identify compiler so could not provide an implementation of signed arithmetic shift right.\n"); 45 | KRML_HOST_EXIT(255); 46 | } while (0); 47 | } 48 | 49 | static inline 50 | int64_t FStar_Int64_shift_arithmetic_right(int64_t a, uint32_t b) { 51 | do { 52 | KRML_HOST_EPRINTF("Could not identify compiler so could not provide an implementation of signed arithmetic shift right.\n"); 53 | KRML_HOST_EXIT(255); 54 | } while (0); 55 | } 56 | 57 | #else 58 | 59 | static inline 60 | int8_t FStar_Int8_shift_arithmetic_right(int8_t a, uint32_t b) { 61 | return (a >> b); 62 | } 63 | 64 | static inline 65 | int16_t FStar_Int16_shift_arithmetic_right(int16_t a, uint32_t b) { 66 | return (a >> b); 67 | } 68 | 69 | static inline 70 | int32_t FStar_Int32_shift_arithmetic_right(int32_t a, uint32_t b) { 71 | return (a >> b); 72 | } 73 | 74 | static inline 75 | int64_t FStar_Int64_shift_arithmetic_right(int64_t a, uint32_t b) { 76 | return (a >> b); 77 | } 78 | 79 | #endif /* !(defined(_MSC_VER) ... ) */ 80 | 81 | #endif /* __FSTAR_INT_H */ 82 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-chacha20/chacha20.S: -------------------------------------------------------------------------------- 1 | .file "chacha20.c" 2 | .option nopic 3 | .attribute arch, "rv32i2p0_m2p0" 4 | .attribute unaligned_access, 0 5 | .attribute stack_align, 16 6 | .text 7 | .section .rodata.str1.4,"aMS",@progbits,1 8 | .align 2 9 | .LC0: 10 | .string "%02x" 11 | .section .text.startup,"ax",@progbits 12 | .align 2 13 | .globl main 14 | .type main, @function 15 | main: 16 | lui a3,%hi(.LANCHOR1) 17 | addi sp,sp,-32 18 | addi a2,a3,%lo(.LANCHOR1) 19 | sw s0,24(sp) 20 | lui a4,%hi(.LANCHOR0) 21 | addi s0,a2,104 22 | li a5,0 23 | addi a2,a2,32 24 | mv a1,s0 25 | addi a4,a4,%lo(.LANCHOR0) 26 | addi a3,a3,%lo(.LANCHOR1) 27 | li a0,72 28 | sw s1,20(sp) 29 | sw ra,28(sp) 30 | sw s2,16(sp) 31 | sw s3,12(sp) 32 | lui s1,%hi(.LANCHOR2) 33 | call Hacl_Chacha20_chacha20_encrypt 34 | mv a1,s0 35 | li a5,0 36 | addi s1,s1,%lo(.LANCHOR2) 37 | li a2,72 38 | .L2: 39 | lbu a3,0(a1) 40 | add a4,s1,a5 41 | addi a5,a5,1 42 | sb a3,0(a4) 43 | addi a1,a1,1 44 | bne a5,a2,.L2 45 | # Begin: Extra code to clear secrets from registers 46 | addi sp,sp,-4 47 | sw s1,0(sp) 48 | call clear_s_regs 49 | call clear_t_regs 50 | lw s1,0(sp) 51 | addi sp,sp,4 52 | # End 53 | li s0,0 54 | lui s3,%hi(.LC0) 55 | li s2,72 56 | .L3: 57 | add a5,s1,s0 58 | lbu a1,0(a5) 59 | addi s0,s0,1 60 | addi a0,s3,%lo(.LC0) 61 | call printf 62 | bne s0,s2,.L3 63 | li a0,10 64 | call putchar 65 | lw ra,28(sp) 66 | lw s0,24(sp) 67 | lw s1,20(sp) 68 | lw s2,16(sp) 69 | lw s3,12(sp) 70 | li a0,0 71 | addi sp,sp,32 72 | jr ra 73 | .size main, .-main 74 | .section .declassify,"aw" 75 | .align 2 76 | .set .LANCHOR2,. + 0 77 | .type declassified, @object 78 | .size declassified, 72 79 | declassified: 80 | .zero 72 81 | .section .public,"aw" 82 | .align 2 83 | .set .LANCHOR0,. + 0 84 | .type nonce, @object 85 | .size nonce, 12 86 | nonce: 87 | .string "" 88 | .ascii "\001\002\003\004\005\006\007\b\t\020\021" 89 | .section .secret,"aw" 90 | .align 2 91 | .set .LANCHOR1,. + 0 92 | .type key, @object 93 | .size key, 32 94 | key: 95 | .ascii "\205\326\276xWUm3\177DR\376B\325\006\250\001\003\200\212\373" 96 | .ascii "\r\262\375J\277\366\257AI\365\033" 97 | .type message, @object 98 | .size message, 72 99 | message: 100 | .string "" 101 | .string "\001\002\003\004\005\006\007\b\t\020\021\022\023\024\025\026\027\030\031 !\"#" 102 | .string "\001\002\003\004\005\006\007\b\t\020\021\022\023\024\025\026\027\030\031 !\"#" 103 | .ascii "\001\002\003\004\005\006\007\b\t\020\021\022\023\024\025\026" 104 | .ascii "\027\030\031 !\"#" 105 | .type ciphertext, @object 106 | .size ciphertext, 72 107 | ciphertext: 108 | .zero 72 109 | .ident "GCC: (GNU) 11.1.0" 110 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-chacha20/include/kremlin/fstar_int.h: -------------------------------------------------------------------------------- 1 | #ifndef __FSTAR_INT_H 2 | #define __FSTAR_INT_H 3 | 4 | #include "internal/types.h" 5 | 6 | /* 7 | * Arithmetic Shift Right operator 8 | * 9 | * In all C standards, a >> b is implementation-defined when a has a signed 10 | * type and a negative value. See e.g. 6.5.7 in 11 | * http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2310.pdf 12 | * 13 | * GCC, MSVC, and Clang implement a >> b as an arithmetic shift. 14 | * 15 | * GCC: https://gcc.gnu.org/onlinedocs/gcc-9.1.0/gcc/Integers-implementation.html#Integers-implementation 16 | * MSVC: https://docs.microsoft.com/en-us/cpp/cpp/left-shift-and-right-shift-operators-input-and-output?view=vs-2019#right-shifts 17 | * Clang: tested that Clang 7, 8 and 9 compile this to an arithmetic shift 18 | * 19 | * We implement arithmetic shift right simply as >> in these compilers 20 | * and bail out in others. 21 | */ 22 | 23 | #if !(defined(_MSC_VER) || defined(__GNUC__) || (defined(__clang__) && (__clang_major__ >= 7))) 24 | 25 | static inline 26 | int8_t FStar_Int8_shift_arithmetic_right(int8_t a, uint32_t b) { 27 | do { 28 | KRML_HOST_EPRINTF("Could not identify compiler so could not provide an implementation of signed arithmetic shift right.\n"); 29 | KRML_HOST_EXIT(255); 30 | } while (0); 31 | } 32 | 33 | static inline 34 | int16_t FStar_Int16_shift_arithmetic_right(int16_t a, uint32_t b) { 35 | do { 36 | KRML_HOST_EPRINTF("Could not identify compiler so could not provide an implementation of signed arithmetic shift right.\n"); 37 | KRML_HOST_EXIT(255); 38 | } while (0); 39 | } 40 | 41 | static inline 42 | int32_t FStar_Int32_shift_arithmetic_right(int32_t a, uint32_t b) { 43 | do { 44 | KRML_HOST_EPRINTF("Could not identify compiler so could not provide an implementation of signed arithmetic shift right.\n"); 45 | KRML_HOST_EXIT(255); 46 | } while (0); 47 | } 48 | 49 | static inline 50 | int64_t FStar_Int64_shift_arithmetic_right(int64_t a, uint32_t b) { 51 | do { 52 | KRML_HOST_EPRINTF("Could not identify compiler so could not provide an implementation of signed arithmetic shift right.\n"); 53 | KRML_HOST_EXIT(255); 54 | } while (0); 55 | } 56 | 57 | #else 58 | 59 | static inline 60 | int8_t FStar_Int8_shift_arithmetic_right(int8_t a, uint32_t b) { 61 | return (a >> b); 62 | } 63 | 64 | static inline 65 | int16_t FStar_Int16_shift_arithmetic_right(int16_t a, uint32_t b) { 66 | return (a >> b); 67 | } 68 | 69 | static inline 70 | int32_t FStar_Int32_shift_arithmetic_right(int32_t a, uint32_t b) { 71 | return (a >> b); 72 | } 73 | 74 | static inline 75 | int64_t FStar_Int64_shift_arithmetic_right(int64_t a, uint32_t b) { 76 | return (a >> b); 77 | } 78 | 79 | #endif /* !(defined(_MSC_VER) ... ) */ 80 | 81 | #endif /* __FSTAR_INT_H */ 82 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/cheri/tests/LsuCap.S: -------------------------------------------------------------------------------- 1 | #include "riscv_test.h" 2 | 3 | #include "test_macros_cap.h" 4 | #include "cheri.h" 5 | 6 | RVTEST_RV32U 7 | RVTEST_CODE_BEGIN 8 | 9 | INIT_ROOT_CAP 10 | SET_BOUNDS_DCC(512) 11 | 12 | TEST_CASE_FREE(1) 13 | LC c1, (zero) 14 | CHECK_TAG(c1, 0) 15 | 16 | TEST_CASE_FREE(2) 17 | SC ROOT, (zero) 18 | LC c1, (zero) 19 | CHECK_CAP_EQ(c1, ROOT) 20 | 21 | TEST_CASE_FREE(3) 22 | SC ROOT, (zero) 23 | sb zero, 1(zero) 24 | LC c1, (zero) 25 | CHECK_TAG(c1, 0) 26 | 27 | TEST_CASE_DCC_BOUNDS_EXCEPTION(4, 7, CAUSE_LENGTH_VIOLATION, SC ROOT, (zero)) 28 | 29 | TEST_CASE_DCC_AND_PERM_EXCEPTION(5, ~(1 << PERM_PERMIT_STORE), CAUSE_PERMIT_STORE_VIOLATION, SC ROOT, (zero)) 30 | TEST_CASE_DCC_AND_PERM_EXCEPTION(6, ~(1 << PERM_PERMIT_LOAD), CAUSE_PERMIT_LOAD_VIOLATION, LC c1, (zero)) 31 | 32 | TEST_CASE_DCC_AND_PERM_NO_EXCEPTION(7, ~(1 << PERM_PERMIT_STORE), LC c1, (zero)) 33 | TEST_CASE_DCC_AND_PERM_NO_EXCEPTION(8, ~(1 << PERM_PERMIT_LOAD), SC ROOT, (zero)) 34 | 35 | TEST_CASE_FREE(9) 36 | SET_BOUNDS_DCC(512) 37 | SEAL_DDC(123) 38 | EXPECT_EXCEPTION(CAUSE_SEAL_VIOLATION, CAP_IDX_DDC, SC ROOT, (zero)) 39 | 40 | TEST_CASE_FREE(10) 41 | la t0, scratch 42 | CSetAddr c1, ROOT, t0 43 | SC.cap ROOT, (c1) 44 | LC.cap c2, (c1) 45 | CHECK_CAP_EQ(c2, ROOT) 46 | 47 | TEST_CASE_FREE(11) 48 | la t0, scratch 49 | CSetAddr c1, ROOT, t0 50 | CSetBoundsImm c1, c1, 3 51 | EXPECT_EXCEPTION(CAUSE_LENGTH_VIOLATION, 1, SC.cap ROOT, (c1)) 52 | 53 | TEST_CASE_FREE(12) 54 | la t0, scratch 55 | CSetAddr c1, ROOT, t0 56 | CSetBoundsImm c1, c1, 3 57 | EXPECT_EXCEPTION(CAUSE_LENGTH_VIOLATION, 1, LC.cap ROOT, (c1)) 58 | 59 | TEST_CASE_FREE(13) 60 | la t0, scratch 61 | CSetAddr c1, ROOT, t0 62 | li t0, ~(1 << PERM_PERMIT_STORE) 63 | CAndPerm c1, c1, t0 64 | EXPECT_EXCEPTION(CAUSE_PERMIT_STORE_VIOLATION, 1, SC.cap ROOT, (c1)) 65 | 66 | TEST_CASE_FREE(14) 67 | la t0, scratch 68 | CSetAddr c1, ROOT, t0 69 | li t0, ~(1 << PERM_PERMIT_LOAD) 70 | CAndPerm c1, c1, t0 71 | EXPECT_EXCEPTION(CAUSE_PERMIT_LOAD_VIOLATION, 1, LC.cap ROOT, (c1)) 72 | 73 | TEST_CASE_FREE(15) 74 | la t0, scratch 75 | CSetAddr c1, ROOT, t0 76 | SEAL(c1, c1, 123) 77 | EXPECT_EXCEPTION(CAUSE_SEAL_VIOLATION, 1, LC.cap ROOT, (c1)) 78 | EXPECT_EXCEPTION(CAUSE_SEAL_VIOLATION, 1, SC.cap ROOT, (c1)) 79 | 80 | 81 | TEST_PASSFAIL 82 | 83 | RVTEST_CODE_END 84 | 85 | RVTEST_DATA_BEGIN 86 | 87 | .align 8 88 | scratch: 89 | .fill 8, 1, 0 90 | 91 | TEST_DATA 92 | 93 | RVTEST_DATA_END 94 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/scheduling/static/Scheduler.scala: -------------------------------------------------------------------------------- 1 | package riscv.plugins.scheduling.static 2 | 3 | import riscv._ 4 | 5 | import spinal.core._ 6 | import spinal.lib._ 7 | 8 | import collection.mutable 9 | 10 | class Scheduler(canStallExternally: Boolean = false) 11 | extends Plugin[StaticPipeline] 12 | with ScheduleService 13 | with IssueService { 14 | private class ClaimPipelineArea extends Area { 15 | val claimPipeline = out(Bool()) 16 | val pipelineFlushed = in(Bool()) 17 | claimPipeline := False 18 | } 19 | 20 | private val claimPipelineAreas = mutable.Map[Stage, ClaimPipelineArea]() 21 | 22 | override def build(): Unit = { 23 | pipeline plug new Area { 24 | val stages = pipeline.stages 25 | stages.head.arbitration.isValid := !ClockDomain.current.readResetWire 26 | stages.head.arbitration.isValid.allowOverride 27 | 28 | for ((stage, nextStage) <- stages.zip(stages.tail)) { 29 | stage.arbitration.isStalled := 30 | nextStage.arbitration.isStalled || 31 | (nextStage.arbitration.isValid && !nextStage.arbitration.isReady) 32 | } 33 | 34 | if (!canStallExternally) { 35 | stages.last.arbitration.isStalled := False 36 | } 37 | 38 | for ((prevStage, stage) <- stages.zip(stages.tail)) { 39 | val isValidReg = Reg(Bool()).init(False) 40 | stage.arbitration.isValid := isValidReg 41 | 42 | when(stage.arbitration.isDone || !stage.arbitration.isValid) { 43 | isValidReg := prevStage.arbitration.isDone 44 | } 45 | } 46 | 47 | for ((stage, regs) <- pipeline.pipelineRegs) { 48 | regs.shift := stage.arbitration.isDone 49 | } 50 | } 51 | } 52 | 53 | override def claimPipeline(stage: Stage): Bool = { 54 | val area = claimPipelineAreas.getOrElseUpdate( 55 | stage, { 56 | val stageArea = stage plug new ClaimPipelineArea 57 | 58 | pipeline plug new Area { 59 | val laterStagesEmpty = if (stage == pipeline.retirementStage) { 60 | True 61 | } else { 62 | val laterStages = pipeline.stages.dropWhile(_ != stage).tail 63 | !laterStages.map(_.arbitration.isValid).orR 64 | } 65 | 66 | stageArea.pipelineFlushed := laterStagesEmpty 67 | 68 | when(stageArea.claimPipeline) { 69 | for (prevStage <- pipeline.stages.takeWhile(_ != stage)) { 70 | prevStage.arbitration.isValid := False 71 | } 72 | 73 | pipeline.service[JumpService].setFetchPc(stage.input(pipeline.data.NEXT_PC)) 74 | } 75 | } 76 | 77 | stageArea 78 | } 79 | ) 80 | 81 | area.claimPipeline := True 82 | area.pipelineFlushed 83 | } 84 | 85 | override def setDestinations(opcode: MaskedLiteral, stages: Set[Stage]): Unit = { 86 | // Dummy implementation of IssueService 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/BranchTargetPredictor.scala: -------------------------------------------------------------------------------- 1 | package riscv.plugins 2 | 3 | import riscv._ 4 | import spinal.core._ 5 | import spinal.lib._ 6 | 7 | class BranchTargetPredictor( 8 | fetchStage: Stage, 9 | jumpStage: Stage, 10 | numEntries: Int = 8, 11 | storedPcBitLength: Int = 32 12 | ) extends BranchTargetPredictorBase(fetchStage, jumpStage) { 13 | override var predictorComponent: PredictorComponent = null 14 | 15 | case class PredictionEntry() extends Bundle { 16 | val pc: UInt = UInt(storedPcBitLength bits) 17 | val target: UInt = UInt(config.xlen bits) 18 | } 19 | 20 | override def build(): Unit = { 21 | super.build() 22 | 23 | predictorComponent = pipeline plug new PredictorComponent { 24 | private val entries = Vec.fill(numEntries)(RegInit(PredictionEntry().getZero)) 25 | private val counter = Counter(numEntries) 26 | 27 | def recordJump(pc: UInt, target: UInt): Unit = { 28 | val result = findEntryIndex(pc) 29 | when(result.valid) { 30 | entries(result.payload).target := target 31 | } otherwise { 32 | val index = counter.value 33 | entries(index).pc := pc(storedPcBitLength - 1 downto 0) 34 | entries(index).target := target 35 | counter.increment() 36 | } 37 | } 38 | 39 | def findEntryIndex(pc: UInt): Flow[UInt] = { 40 | val result = Flow(UInt(log2Up(numEntries) bits)) 41 | result.valid := False 42 | result.payload.assignDontCare() 43 | 44 | for (i <- 0 until numEntries) { 45 | when(entries(i).pc === pc(storedPcBitLength - 1 downto 0)) { 46 | result.push(i) 47 | } 48 | } 49 | result 50 | } 51 | 52 | def findEntry(pc: UInt): Flow[UInt] = { 53 | val index = findEntryIndex(pc) 54 | val result = Flow(UInt(config.xlen bits)) 55 | result.valid := False 56 | result.payload.assignDontCare() 57 | 58 | when(index.valid) { 59 | result.push(entries(index.payload).target) 60 | } 61 | result 62 | } 63 | 64 | when(jumpIo.mispredicted) { 65 | recordJump(jumpIo.currentPc, jumpIo.target) 66 | } 67 | 68 | predictIo.predictedAddress.payload.assignDontCare() 69 | predictIo.predictedAddress.valid := False 70 | 71 | val result = findEntryIndex(predictIo.currentPc) 72 | when(result.valid) { 73 | predictIo.predictedAddress.payload := entries(result.payload).target 74 | predictIo.predictedAddress.valid := True 75 | } 76 | } 77 | } 78 | 79 | override def predictionForAddress(address: UInt): UInt = { 80 | val entry = predictorComponent.findEntry(address) 81 | val result = UInt(config.xlen bits) 82 | when(entry.valid) { 83 | result := entry.payload 84 | } otherwise { 85 | result := address + 4 86 | } 87 | result 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /tests/riscv_test.h: -------------------------------------------------------------------------------- 1 | #ifndef RISCV_TEST_H 2 | #define RISCV_TEST_H 3 | 4 | #include "riscv-test-env/encoding.h" 5 | 6 | #define RVTEST_RV64U \ 7 | .macro init; \ 8 | .endm 9 | 10 | #define RVTEST_RV64M \ 11 | .macro init; \ 12 | .endm 13 | 14 | #define RVTEST_RV32U \ 15 | .macro init; \ 16 | .endm 17 | 18 | #define RVTEST_RV32M \ 19 | .macro init; \ 20 | .endm 21 | 22 | #define RVTEST_CODE_BEGIN \ 23 | .text; \ 24 | .weak fail; \ 25 | .globl _start; \ 26 | _start: \ 27 | la tp, trap_vector; \ 28 | csrw mtvec, tp; \ 29 | j start_tests; \ 30 | trap_vector: \ 31 | la tp, mtvec_handler; \ 32 | beqz tp, 1f; \ 33 | jr tp; \ 34 | 1: la tp, fail; \ 35 | beqz tp, 1f; \ 36 | jr tp; \ 37 | 1: mret; \ 38 | start_tests: 39 | 40 | // HACK LLVM started erring when weak symbols are redefined as global. However, 41 | // globals being redefined as weak only causes a warning. 42 | // https://reviews.llvm.org/D90108 43 | #define RVTEST_CODE_END \ 44 | .weak mtvec_handler; 45 | 46 | #define RVTEST_DATA_BEGIN \ 47 | .data; 48 | 49 | #define RVTEST_DATA_END 50 | 51 | #define TESTNUM gp 52 | 53 | #define TESTDEV 0x30000000 54 | 55 | #define RVTEST_FAIL \ 56 | li tp, TESTDEV; \ 57 | sw TESTNUM, 0(tp); 58 | 59 | #define RVTEST_PASS \ 60 | li tp, TESTDEV; \ 61 | sw zero, 0(tp); 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-sha2/README.md: -------------------------------------------------------------------------------- 1 | # Running HACL*/SHA2 on Proteus/Prospect 2 | 3 | ## Files 4 | 5 | - `sha2.c`: computes the hash of a 300 bytes array and prints the result 6 | - `sha2.S`: assembly code of `sha2.c`, modified to clear secrets from register 7 | after the execution of the cryptographic primitive (so they are not written to 8 | public memory locations, e.g. on the stack, afterwards). Note that if you 9 | modify `sha2.c` you'll have to remove `sha2.S` before recompiling with the 10 | Makefile. 11 | - `Hacl_Hash_SHA2.c`: implementation of the `Hacl_Hash_SHA2_hash_256` primitive. 12 | 13 | Secrets local variables have been annotated using: 14 | ``` c 15 | __attribute__((section(".secret"))) static 16 | ``` 17 | 18 | `sha2.c`, `Hacl_Hash_SHA2.c` and `include/kremlin/lowstar_endianness.h` have 19 | been modified to annotate secrets. In total, `34` annotations were added to mark 20 | all secret variables. 21 | 22 | 23 | ## Building & running 24 | ### Prerequisites 25 | - [riscv-gnu-toolchain](https://github.com/riscv-collab/riscv-gnu-toolchain) configured like this: 26 | ``` 27 | ./configure --prefix=... --with-arch=rv32im --with-abi=ilp32 28 | ``` 29 | 30 | ### Building 31 | Build with `make`. 32 | 33 | This creates `sha2.bin` and `sha2.ihex` which can be simulated on Proteus. 34 | 35 | ### Running 36 | Secret initialization in Proteus/Prospect: 37 | ``` scala 38 | // Sha 39 | def isSecret(address: UInt): Bool = { 40 | val beg = U"32'h80016a08" 41 | val size = U"h310" 42 | (beg <= address) && (address < (beg + size)) 43 | } 44 | ``` 45 | 46 | Expected output: 47 | ``` 48 | 44b302f763d628b29928366a0ea744edc74786ad03bf95cb35774cd29eafbaaf 49 | ``` 50 | 51 | ## Track secret spilling to the stack 52 | It is important to make sure that secrets are not written to non secret memory 53 | locations. Typically this can happen when secrets are copied to local variables 54 | on the stack, registers are saved on the stack to respect calling conventions, 55 | or registers are spilled on the stack by the compiler when all data do not fit 56 | in registers. 57 | 58 | We make sure that this does not happen in this program. We use Proteus/Prospect 59 | secret tracking to flag secrets that are written to public locations. 60 | 61 | After the execution of the hash function, the result is declassified. Memory 62 | used for declassification is marked in Proteus/Prospect using the following 63 | code: 64 | 65 | ``` scala 66 | def isDeclassified(address: UInt): Bool = { 67 | val beg = U"32'h800169e8" 68 | val size = U"h20" 69 | (beg <= address) && (address < (beg + size)) 70 | } 71 | ``` 72 | 73 | In addition, after declassification we add a few lines of assembly code to `sha2.S` to clear registers: 74 | ``` 75 | # Begin: Extra code to clear secrets from registers 76 | addi sp,sp,-4 77 | sw s1,0(sp) 78 | call clear_s_regs 79 | call clear_t_regs 80 | lw s1,0(sp) 81 | addi sp,sp,4 82 | # End 83 | ``` 84 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-sha2/Hacl_Hash_SHA2.h: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | * 3 | * Copyright (c) 2016-2020 INRIA, CMU and Microsoft Corporation 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in all 13 | * copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | 25 | #ifndef __Hacl_Hash_SHA2_H 26 | #define __Hacl_Hash_SHA2_H 27 | 28 | /* #if defined(__cplusplus) */ 29 | /* extern "C" { */ 30 | /* #endif */ 31 | 32 | /* #include "evercrypt_targetconfig.h" */ 33 | /* #include "libintvector.h" */ 34 | #include "kremlin/internal/types.h" 35 | #include "kremlin/lowstar_endianness.h" 36 | #include 37 | #include "kremlin/internal/target.h" 38 | 39 | 40 | /* #include "Hacl_Kremlib.h" */ 41 | 42 | /* SNIPPET_START: Hacl_Hash_Core_SHA2_init_256 */ 43 | 44 | void Hacl_Hash_Core_SHA2_init_256(uint32_t *s); 45 | 46 | /* SNIPPET_END: Hacl_Hash_Core_SHA2_init_256 */ 47 | 48 | /* SNIPPET_START: Hacl_Hash_Core_SHA2_pad_256 */ 49 | 50 | void Hacl_Hash_Core_SHA2_pad_256(uint64_t len, uint8_t *dst); 51 | 52 | /* SNIPPET_END: Hacl_Hash_Core_SHA2_pad_256 */ 53 | 54 | /* SNIPPET_START: Hacl_Hash_Core_SHA2_finish_256 */ 55 | 56 | void Hacl_Hash_Core_SHA2_finish_256(uint32_t *s, uint8_t *dst); 57 | 58 | /* SNIPPET_END: Hacl_Hash_Core_SHA2_finish_256 */ 59 | 60 | /* SNIPPET_START: Hacl_Hash_SHA2_update_multi_256 */ 61 | 62 | void Hacl_Hash_SHA2_update_multi_256(uint32_t *s, uint8_t *blocks, uint32_t n_blocks); 63 | 64 | /* SNIPPET_END: Hacl_Hash_SHA2_update_multi_256 */ 65 | 66 | /* SNIPPET_START: Hacl_Hash_SHA2_update_last_256 */ 67 | 68 | void 69 | Hacl_Hash_SHA2_update_last_256( 70 | uint32_t *s, 71 | uint64_t prev_len, 72 | uint8_t *input, 73 | uint32_t input_len 74 | ); 75 | 76 | /* SNIPPET_END: Hacl_Hash_SHA2_update_last_256 */ 77 | 78 | /* SNIPPET_START: Hacl_Hash_SHA2_hash_256 */ 79 | 80 | void Hacl_Hash_SHA2_hash_256(uint8_t *input, uint32_t input_len, uint8_t *dst); 81 | 82 | /* SNIPPET_END: Hacl_Hash_SHA2_hash_256 */ 83 | 84 | #define __Hacl_Hash_SHA2_H_DEFINED 85 | #endif 86 | -------------------------------------------------------------------------------- /tests/synthetic-benchmark/include/kremlib/FStar_UInt128.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) INRIA and Microsoft Corporation. All rights reserved. 3 | Licensed under the Apache 2.0 License. 4 | */ 5 | 6 | 7 | #ifndef __FStar_UInt128_H 8 | #define __FStar_UInt128_H 9 | #include 10 | #include 11 | #include "kremlin/internal/compat.h" 12 | #include "kremlin/lowstar_endianness.h" 13 | #include "kremlin/internal/types.h" 14 | #include "kremlin/internal/target.h" 15 | 16 | 17 | 18 | 19 | static inline FStar_UInt128_uint128 20 | FStar_UInt128_add(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 21 | 22 | static inline FStar_UInt128_uint128 23 | FStar_UInt128_add_underspec(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 24 | 25 | static inline FStar_UInt128_uint128 26 | FStar_UInt128_add_mod(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 27 | 28 | static inline FStar_UInt128_uint128 29 | FStar_UInt128_sub(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 30 | 31 | static inline FStar_UInt128_uint128 32 | FStar_UInt128_sub_underspec(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 33 | 34 | static inline FStar_UInt128_uint128 35 | FStar_UInt128_sub_mod(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 36 | 37 | static inline FStar_UInt128_uint128 38 | FStar_UInt128_logand(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 39 | 40 | static inline FStar_UInt128_uint128 41 | FStar_UInt128_logxor(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 42 | 43 | static inline FStar_UInt128_uint128 44 | FStar_UInt128_logor(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 45 | 46 | static inline FStar_UInt128_uint128 FStar_UInt128_lognot(FStar_UInt128_uint128 a); 47 | 48 | static inline FStar_UInt128_uint128 49 | FStar_UInt128_shift_left(FStar_UInt128_uint128 a, uint32_t s); 50 | 51 | static inline FStar_UInt128_uint128 52 | FStar_UInt128_shift_right(FStar_UInt128_uint128 a, uint32_t s); 53 | 54 | static inline bool FStar_UInt128_eq(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 55 | 56 | static inline bool FStar_UInt128_gt(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 57 | 58 | static inline bool FStar_UInt128_lt(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 59 | 60 | static inline bool FStar_UInt128_gte(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 61 | 62 | static inline bool FStar_UInt128_lte(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 63 | 64 | static inline FStar_UInt128_uint128 65 | FStar_UInt128_eq_mask(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 66 | 67 | static inline FStar_UInt128_uint128 68 | FStar_UInt128_gte_mask(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 69 | 70 | static inline FStar_UInt128_uint128 FStar_UInt128_uint64_to_uint128(uint64_t a); 71 | 72 | static inline uint64_t FStar_UInt128_uint128_to_uint64(FStar_UInt128_uint128 a); 73 | 74 | static inline FStar_UInt128_uint128 FStar_UInt128_mul32(uint64_t x, uint32_t y); 75 | 76 | static inline FStar_UInt128_uint128 FStar_UInt128_mul_wide(uint64_t x, uint64_t y); 77 | 78 | 79 | #define __FStar_UInt128_H_DEFINED 80 | #endif 81 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-chacha20/include/kremlib/FStar_UInt128.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) INRIA and Microsoft Corporation. All rights reserved. 3 | Licensed under the Apache 2.0 License. 4 | */ 5 | 6 | 7 | #ifndef __FStar_UInt128_H 8 | #define __FStar_UInt128_H 9 | #include 10 | #include 11 | #include "kremlin/internal/compat.h" 12 | #include "kremlin/lowstar_endianness.h" 13 | #include "kremlin/internal/types.h" 14 | #include "kremlin/internal/target.h" 15 | 16 | 17 | 18 | 19 | static inline FStar_UInt128_uint128 20 | FStar_UInt128_add(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 21 | 22 | static inline FStar_UInt128_uint128 23 | FStar_UInt128_add_underspec(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 24 | 25 | static inline FStar_UInt128_uint128 26 | FStar_UInt128_add_mod(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 27 | 28 | static inline FStar_UInt128_uint128 29 | FStar_UInt128_sub(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 30 | 31 | static inline FStar_UInt128_uint128 32 | FStar_UInt128_sub_underspec(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 33 | 34 | static inline FStar_UInt128_uint128 35 | FStar_UInt128_sub_mod(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 36 | 37 | static inline FStar_UInt128_uint128 38 | FStar_UInt128_logand(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 39 | 40 | static inline FStar_UInt128_uint128 41 | FStar_UInt128_logxor(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 42 | 43 | static inline FStar_UInt128_uint128 44 | FStar_UInt128_logor(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 45 | 46 | static inline FStar_UInt128_uint128 FStar_UInt128_lognot(FStar_UInt128_uint128 a); 47 | 48 | static inline FStar_UInt128_uint128 49 | FStar_UInt128_shift_left(FStar_UInt128_uint128 a, uint32_t s); 50 | 51 | static inline FStar_UInt128_uint128 52 | FStar_UInt128_shift_right(FStar_UInt128_uint128 a, uint32_t s); 53 | 54 | static inline bool FStar_UInt128_eq(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 55 | 56 | static inline bool FStar_UInt128_gt(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 57 | 58 | static inline bool FStar_UInt128_lt(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 59 | 60 | static inline bool FStar_UInt128_gte(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 61 | 62 | static inline bool FStar_UInt128_lte(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 63 | 64 | static inline FStar_UInt128_uint128 65 | FStar_UInt128_eq_mask(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 66 | 67 | static inline FStar_UInt128_uint128 68 | FStar_UInt128_gte_mask(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 69 | 70 | static inline FStar_UInt128_uint128 FStar_UInt128_uint64_to_uint128(uint64_t a); 71 | 72 | static inline uint64_t FStar_UInt128_uint128_to_uint64(FStar_UInt128_uint128 a); 73 | 74 | static inline FStar_UInt128_uint128 FStar_UInt128_mul32(uint64_t x, uint32_t y); 75 | 76 | static inline FStar_UInt128_uint128 FStar_UInt128_mul_wide(uint64_t x, uint64_t y); 77 | 78 | 79 | #define __FStar_UInt128_H_DEFINED 80 | #endif 81 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-sha2/include/kremlib/FStar_UInt128.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) INRIA and Microsoft Corporation. All rights reserved. 3 | Licensed under the Apache 2.0 License. 4 | */ 5 | 6 | 7 | #ifndef __FStar_UInt128_H 8 | #define __FStar_UInt128_H 9 | #include 10 | #include 11 | #include "kremlin/internal/compat.h" 12 | #include "kremlin/lowstar_endianness.h" 13 | #include "kremlin/internal/types.h" 14 | #include "kremlin/internal/target.h" 15 | 16 | 17 | 18 | 19 | static inline FStar_UInt128_uint128 20 | FStar_UInt128_add(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 21 | 22 | static inline FStar_UInt128_uint128 23 | FStar_UInt128_add_underspec(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 24 | 25 | static inline FStar_UInt128_uint128 26 | FStar_UInt128_add_mod(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 27 | 28 | static inline FStar_UInt128_uint128 29 | FStar_UInt128_sub(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 30 | 31 | static inline FStar_UInt128_uint128 32 | FStar_UInt128_sub_underspec(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 33 | 34 | static inline FStar_UInt128_uint128 35 | FStar_UInt128_sub_mod(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 36 | 37 | static inline FStar_UInt128_uint128 38 | FStar_UInt128_logand(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 39 | 40 | static inline FStar_UInt128_uint128 41 | FStar_UInt128_logxor(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 42 | 43 | static inline FStar_UInt128_uint128 44 | FStar_UInt128_logor(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 45 | 46 | static inline FStar_UInt128_uint128 FStar_UInt128_lognot(FStar_UInt128_uint128 a); 47 | 48 | static inline FStar_UInt128_uint128 49 | FStar_UInt128_shift_left(FStar_UInt128_uint128 a, uint32_t s); 50 | 51 | static inline FStar_UInt128_uint128 52 | FStar_UInt128_shift_right(FStar_UInt128_uint128 a, uint32_t s); 53 | 54 | static inline bool FStar_UInt128_eq(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 55 | 56 | static inline bool FStar_UInt128_gt(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 57 | 58 | static inline bool FStar_UInt128_lt(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 59 | 60 | static inline bool FStar_UInt128_gte(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 61 | 62 | static inline bool FStar_UInt128_lte(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 63 | 64 | static inline FStar_UInt128_uint128 65 | FStar_UInt128_eq_mask(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 66 | 67 | static inline FStar_UInt128_uint128 68 | FStar_UInt128_gte_mask(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); 69 | 70 | static inline FStar_UInt128_uint128 FStar_UInt128_uint64_to_uint128(uint64_t a); 71 | 72 | static inline uint64_t FStar_UInt128_uint128_to_uint64(FStar_UInt128_uint128 a); 73 | 74 | static inline FStar_UInt128_uint128 FStar_UInt128_mul32(uint64_t x, uint32_t y); 75 | 76 | static inline FStar_UInt128_uint128 FStar_UInt128_mul_wide(uint64_t x, uint64_t y); 77 | 78 | 79 | #define __FStar_UInt128_H_DEFINED 80 | #endif 81 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-sha2/sha2.S: -------------------------------------------------------------------------------- 1 | .file "sha2.c" 2 | .option nopic 3 | .attribute arch, "rv32i2p0_m2p0" 4 | .attribute unaligned_access, 0 5 | .attribute stack_align, 16 6 | .text 7 | .section .rodata.str1.4,"aMS",@progbits,1 8 | .align 2 9 | .LC0: 10 | .string "%02x" 11 | .section .text.startup,"ax",@progbits 12 | .align 2 13 | .globl main 14 | .type main, @function 15 | main: 16 | addi sp,sp,-32 17 | sw s0,24(sp) 18 | lui s0,%hi(.LANCHOR0) 19 | addi a0,s0,%lo(.LANCHOR0) 20 | li a1,300 21 | addi a2,s0,%lo(.LANCHOR0) 22 | addi a0,a0,32 23 | sw s1,20(sp) 24 | sw ra,28(sp) 25 | sw s2,16(sp) 26 | sw s3,12(sp) 27 | lui s1,%hi(.LANCHOR1) 28 | call Hacl_Hash_SHA2_hash_256 29 | addi a4,s0,%lo(.LANCHOR0) 30 | li a5,0 31 | addi s1,s1,%lo(.LANCHOR1) 32 | li a1,32 33 | .L2: 34 | lbu a2,0(a4) 35 | add a3,s1,a5 36 | addi a5,a5,1 37 | sb a2,0(a3) 38 | addi a4,a4,1 39 | bne a5,a1,.L2 40 | # Begin: Extra code to clear secrets from registers 41 | addi sp,sp,-4 42 | sw s1,0(sp) 43 | call clear_s_regs 44 | call clear_t_regs 45 | lw s1,0(sp) 46 | addi sp,sp,4 47 | # End 48 | li s0,0 49 | lui s3,%hi(.LC0) 50 | li s2,32 51 | .L3: 52 | add a5,s1,s0 53 | lbu a1,0(a5) 54 | addi s0,s0,1 55 | addi a0,s3,%lo(.LC0) 56 | call printf 57 | bne s0,s2,.L3 58 | li a0,10 59 | call putchar 60 | lw ra,28(sp) 61 | lw s0,24(sp) 62 | lw s1,20(sp) 63 | lw s2,16(sp) 64 | lw s3,12(sp) 65 | li a0,0 66 | addi sp,sp,32 67 | jr ra 68 | .size main, .-main 69 | .globl public 70 | .globl hash 71 | .globl secret 72 | .section .declassified,"aw" 73 | .align 2 74 | .set .LANCHOR1,. + 0 75 | .type public, @object 76 | .size public, 32 77 | public: 78 | .zero 32 79 | .section .secret,"aw" 80 | .align 2 81 | .set .LANCHOR0,. + 0 82 | .type hash, @object 83 | .size hash, 32 84 | hash: 85 | .zero 32 86 | .type secret, @object 87 | .size secret, 300 88 | secret: 89 | .ascii "Q\353\330\273\225_\242\221o\207'\266{<\323\340\025\300qT\031" 90 | .ascii "@\2712[\024A\277S\276j\304\340\252\317\222\244\254]E\233rI\r" 91 | .ascii "\271\221T\227N\342\246\331\251\332\001\005:\325beJ<\335\2571" 92 | .ascii "\007\026\314\030Z\231\333P\21142/7\034\263A\002\"\263]{2\360" 93 | .ascii "\221w\363L9\245\247\371\302s\201\261\232Pq9\306\263\345\022\355" 94 | .ascii ">\207\313\305F\034|\210IQ}\214T\244\332Xx\207\340o\032+\322@" 95 | .ascii "\013Grv[\007\273;\326\3458\\F|`\320\003\307\345\227\026|#E&)" 96 | .ascii "\274A\021\027\210x\344\3162-\243\2274s:\271&[\335\322\016\250" 97 | .ascii "\275\324\250q\256\230i@%\223\350\211\201\305\021\343\230[\312" 98 | .ascii "\334\270\213\177\222\310\322\276\355\304\205\206\017:)\034\t" 99 | .ascii "\b\374L\342\213j\200\235\274\244\262Z\374f+\3045&\257i\363\264" 100 | .ascii "\377\342\016eX*iw\267l\332G\212x\316\201\2364\373(\226\202\332" 101 | .ascii "\306np\240F\251|\035\250\212\224fF>\240t\016\016\026%\307\257" 102 | .ascii "s\372\253\036R,t\275\021)\351\032\230\223[:" 103 | .ident "GCC: (GNU) 11.1.0" 104 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-chacha20/README.md: -------------------------------------------------------------------------------- 1 | # Running HACL*/Chacha20 on Proteus/Prospect 2 | 3 | ## Files 4 | 5 | - `chacha20.c`: encrypts a 72 bytes array and prints the result 6 | - `chacha20.S`: assembly code of `chacha20.c`, modified to clear secrets from 7 | register after the execution of the cryptographic primitive (so they are not 8 | written to public memory locations, e.g. on the stack, afterwards). Note that 9 | if you modify `chacha20.c` you'll have to remove `chacha20.S` before recompiling 10 | with the Makefile. 11 | - `Hacl_Hash_Chacha20.c`: implementation of the `Hacl_Chacha20_chacha20_encrypt` primitive. 12 | 13 | Secrets local variables have been annotated using: 14 | ``` c 15 | __attribute__((section(".secret"))) static 16 | ``` 17 | 18 | `chacha20.c`, `Hacl_Hash_CHACHA20.c` and `include/kremlin/lowstar_endianness.h` 19 | have been modified to annotate secrets. In total, `51` annotations were added to 20 | mark all secret variables. 21 | 22 | Approximate time to place all annotation and make sure that no secrets are 23 | written to public location: 1h 24 | 25 | ## Building & running 26 | ### Prerequisites 27 | - [riscv-gnu-toolchain](https://github.com/riscv-collab/riscv-gnu-toolchain) configured like this: 28 | ``` 29 | ./configure --prefix=... --with-arch=rv32im --with-abi=ilp32 30 | ``` 31 | 32 | ### Building 33 | Build with `make`. 34 | 35 | This creates `chacha20.bin` and `chacha20.ihex` which can be simulated on Proteus. 36 | 37 | ### Running 38 | Secret initialization in Proteus/Prospect: 39 | ``` scala 40 | def isSecret(address: UInt): Bool = { 41 | val beg = U"32'h80016a3c" 42 | val size = U"h1f4" 43 | (beg <= address) && (address < (beg + size)) 44 | } 45 | ``` 46 | 47 | Expected output: 48 | ``` 49 | 44b302f763d628b29928366a0ea744edc74786ad03bf95cb35774cd29eafbaaf 50 | ``` 51 | 52 | ## Track secret spilling to the stack 53 | It is important to make sure that secrets are not written to non secret memory 54 | locations. Typically this can happen when secrets are copied to local variables 55 | on the stack, registers are saved on the stack to respect calling conventions, 56 | or registers are spilled on the stack by the compiler when all data do not fit 57 | in registers. 58 | 59 | We make sure that this does not happen in this program. We use Proteus/Prospect 60 | secret tracking to flag secrets that are written to public locations. 61 | 62 | After the execution of the hash function, the result is declassified. Memory 63 | used for declassification is marked in Proteus/Prospect using the following 64 | code: 65 | 66 | ``` scala 67 | def isDeclassified(address: UInt): Bool = { 68 | val beg = U"32'h800169e8" 69 | val size = U"h48" 70 | (beg <= address) && (address < (beg + size)) 71 | } 72 | ``` 73 | 74 | 75 | In addition, after declassification we add a few lines of assembly code to `chacha20.S` to clear registers: 76 | ``` 77 | # Begin: Extra code to clear secrets from registers 78 | addi sp,sp,-4 79 | sw s1,0(sp) 80 | call clear_s_regs 81 | call clear_t_regs 82 | lw s1,0(sp) 83 | addi sp,sp,4 84 | # End 85 | ``` 86 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/StaticMemoryBackbone.scala: -------------------------------------------------------------------------------- 1 | package riscv.plugins 2 | 3 | import riscv._ 4 | import spinal.core._ 5 | import spinal.lib._ 6 | 7 | import scala.collection.mutable 8 | 9 | class StaticMemoryBackbone(implicit config: Config) extends Plugin with MemoryService { 10 | private var externalIBus: MemBus = null 11 | private var internalIBus: MemBus = null 12 | private var externalDBus: MemBus = null 13 | private var internalDBus: MemBus = null 14 | private var internalDBusStage: Stage = null 15 | private var dbusFilter: Option[MemBusFilter] = None 16 | private val dbusObservers = mutable.ArrayBuffer[MemBusObserver]() 17 | 18 | override def finish(): Unit = { 19 | def dummyConnect(bus: MemBus) = { 20 | bus.cmd.valid := False 21 | bus.cmd.payload.assignDontCare() 22 | bus.rsp.ready := False 23 | } 24 | 25 | // IBUS 26 | pipeline plug new Area { 27 | externalIBus = master(new MemBus(config.ibusConfig, 0 bits)).setName("ibus") 28 | 29 | if (internalIBus != null) { 30 | externalIBus <> internalIBus 31 | } else { 32 | internalIBus = externalIBus 33 | dummyConnect(internalIBus) 34 | } 35 | } 36 | 37 | // DBUS 38 | if (dbusFilter.isEmpty) { 39 | dbusFilter = Some((_, idbus, edbus) => { 40 | idbus <> edbus 41 | }) 42 | } 43 | 44 | pipeline plug new Area { 45 | externalDBus = master(new MemBus(config.dbusConfig, 0 bits)).setName("dbus") 46 | dbusFilter.foreach(_(internalDBusStage, internalDBus, externalDBus)) 47 | dbusObservers.foreach(_(internalDBusStage, internalDBus)) 48 | } 49 | } 50 | 51 | override def getExternalIBus: MemBus = { 52 | assert(externalIBus != null) 53 | externalIBus 54 | } 55 | 56 | override def getExternalDBus: MemBus = { 57 | assert(externalDBus != null) 58 | externalDBus 59 | } 60 | 61 | override def createInternalIBus(stage: Stage): MemBus = { 62 | assert(internalIBus == null) 63 | 64 | stage plug new Area { 65 | internalIBus = master(new MemBus(config.ibusConfig, 0 bits)) 66 | internalIBus.cmd.id.assignDontCare() 67 | } 68 | 69 | internalIBus 70 | } 71 | 72 | override def createInternalDBus( 73 | readStages: Seq[Stage], 74 | writeStage: Stage 75 | ): (Seq[MemBus], MemBus) = { 76 | assert(readStages.size == 1) 77 | assert(readStages.head == writeStage) 78 | 79 | internalDBusStage = readStages.head 80 | 81 | internalDBusStage plug new Area { 82 | val dbus = master(new MemBus(config.dbusConfig, 0 bits)) 83 | internalDBus = dbus 84 | } 85 | 86 | (Seq(internalDBus), internalDBus) 87 | } 88 | 89 | override def getDBusStages: Seq[Stage] = { 90 | Seq(internalDBusStage).filter(_ != null).distinct // TODO: not sure what this does 91 | } 92 | 93 | override def filterDBus(filter: MemBusFilter): Unit = { 94 | assert(dbusFilter.isEmpty) 95 | dbusFilter = Some(filter) 96 | } 97 | 98 | override def observeDBus(observer: MemBusObserver): Unit = { 99 | dbusObservers += observer 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/main/scala/riscv/Utils.scala: -------------------------------------------------------------------------------- 1 | package riscv 2 | 3 | import spinal.core._ 4 | import spinal.lib._ 5 | 6 | import scala.collection.mutable 7 | import scala.collection.mutable.ArrayBuffer 8 | 9 | object Utils { 10 | def signExtend[T <: BitVector](data: T, width: Int): T = { 11 | val dataWidth = data.getBitsWidth 12 | assert(dataWidth <= width && dataWidth > 0) 13 | 14 | (B((width - 1 - dataWidth downto 0) -> data(dataWidth - 1)) ## data) 15 | .as(data.clone().setWidth(width)) 16 | } 17 | 18 | def zeroExtend[T <: BitVector](data: T, width: Int): T = { 19 | val dataWidth = data.getBitsWidth 20 | assert(dataWidth <= width && dataWidth > 0) 21 | 22 | (B((width - 1 - dataWidth downto 0) -> False) ## data).as(data.clone().setWidth(width)) 23 | } 24 | 25 | def twosComplement(data: UInt): UInt = ~data + 1 26 | 27 | def delay(cycles: Int)(logic: => Unit) = { 28 | assert(cycles >= 0) 29 | 30 | val delayCounter = Counter(cycles + 1) 31 | 32 | when(delayCounter.willOverflowIfInc) { 33 | logic 34 | } 35 | 36 | delayCounter.increment() 37 | } 38 | 39 | def outsideConditionScope[T](rtl: => T): T = { 40 | val body = Component.current.dslBody 41 | val ctx = body.push() 42 | val swapContext = body.swap() 43 | val ret = rtl 44 | ctx.restore() 45 | swapContext.appendBack() 46 | ret 47 | } 48 | 49 | implicit class StreamExtensions[T <: Data](stream: Stream[T]) { 50 | def stage(stagesCount: Int): Stream[T] = { 51 | stagesCount match { 52 | case 0 => stream 53 | case _ => stream.stage().stage(stagesCount - 1) 54 | } 55 | } 56 | } 57 | } 58 | 59 | trait DynBundleAccess[KeyType] { 60 | def element(key: KeyType): Data 61 | 62 | def elementAs[T <: Data](key: KeyType): T = { 63 | element(key).asInstanceOf[T] 64 | } 65 | } 66 | 67 | class DynBundle[KeyType] { 68 | private val elementsMap = mutable.Map[KeyType, Data]() 69 | 70 | val keys: Iterable[KeyType] = elementsMap.keys 71 | 72 | def addElement[T <: Data](key: KeyType, hardType: HardType[T]) = { 73 | val data = hardType() 74 | elementsMap(key) = data 75 | } 76 | 77 | def createBundle: Bundle with DynBundleAccess[KeyType] = { 78 | class NewBundle extends Bundle with DynBundleAccess[KeyType] { 79 | private val elementsMap = DynBundle.this.elementsMap.map { case (key, data) => 80 | val clonedData = cloneOf(data) 81 | clonedData.parent = this 82 | 83 | if (OwnableRef.proposal(clonedData, this)) { 84 | clonedData.setPartialName(key.toString, Nameable.DATAMODEL_WEAK) 85 | } 86 | 87 | (key, clonedData) 88 | } 89 | 90 | override val elements: ArrayBuffer[(String, Data)] = elementsMap 91 | .map { case (key, data) => 92 | (key.toString, data) 93 | } 94 | .toSeq 95 | .to[mutable.ArrayBuffer] 96 | 97 | override def element(key: KeyType): Data = { 98 | elementsMap(key) 99 | } 100 | 101 | override def clone(): Bundle = { 102 | new NewBundle 103 | } 104 | } 105 | 106 | new NewBundle 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /tests/synthetic-benchmark/eval.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import sys 5 | import subprocess 6 | import re 7 | 8 | 9 | def filename(mode, config): 10 | return f"specBench_{mode}_{config}" 11 | 12 | 13 | def create_simulation(mode, config): 14 | print(f"creating with mode {mode} and config {config}") 15 | os.system( 16 | f"sed \"s/#define mode.*/#define mode {mode}/g\" specBench.c > {filename(mode, config)}.c") 17 | os.system( 18 | f"sed \"s/#define input.*/#define input \\\"{config}\\\"/g\" -i {filename(mode, config)}.c") 19 | os.system( 20 | f"make {filename(mode, config)}.bin TARGET={filename(mode, config)}") 21 | 22 | 23 | def run_simulation(binary, mode, config): 24 | return { 25 | 'process': subprocess.Popen(['stdbuf', '-o0'] + [binary, f"{filename(mode, config)}.bin"], bufsize=1, stdout=subprocess.PIPE, encoding="utf8"), 26 | 'mode': mode, 27 | 'config': config, 28 | } 29 | 30 | 31 | base_proteus = sys.argv[1] 32 | secure_proteus = sys.argv[2] 33 | 34 | 35 | MODES = [ 36 | ("0", base_proteus, "baseline"), # baseline 37 | ("1", secure_proteus, " p(key)"), # precise boundaries 38 | ("2", secure_proteus, " p(all)"), # all secrets 39 | ] 40 | 41 | results = { 42 | '0': { 43 | '75': 0, 44 | '50': 0, 45 | '25': 0, 46 | '10': 0, 47 | }, 48 | '1': { 49 | '75': 0, 50 | '50': 0, 51 | '25': 0, 52 | '10': 0, 53 | }, 54 | '2': { 55 | '75': 0, 56 | '50': 0, 57 | '25': 0, 58 | '10': 0, 59 | }, 60 | } 61 | 62 | CONFIGS = [ 63 | "75", 64 | "50", 65 | "25", 66 | "10", 67 | ] 68 | 69 | for mode in MODES: 70 | for config in CONFIGS: 71 | create_simulation(mode[0], config) 72 | 73 | processes = [] 74 | 75 | for mode in MODES: 76 | for config in CONFIGS: 77 | processes.append(run_simulation(mode[1], mode[0], config)) 78 | 79 | i = len(MODES) * len(CONFIGS) 80 | 81 | with open("benchmark_logs.txt", 'w') as logfile: 82 | for proc in processes: 83 | print(f"Waiting for {i} process(es)...", flush=True) 84 | i -= 1 85 | # proc['process'].wait() 86 | logfile.write( 87 | f"Benchmark with mode = {proc['mode']} and config = {proc['config']}:\n") 88 | logfile.write(f"{'-' * 80}\n") 89 | for line in iter(proc['process'].stdout.readline, ''): 90 | logfile.write(line) 91 | match = re.match(r"total time\s*:\[(\d+)\]", line) 92 | if match: 93 | results[proc['mode']][proc['config']] = int(match.group(1)) 94 | else: 95 | dmatch = re.match(r"^(\d+)$", line) 96 | if dmatch: 97 | perc = int(dmatch.group(1)) 98 | if perc % 10 == 0: 99 | print(f"{perc}%", flush=True) 100 | 101 | print("\t\t", "\t ".join(CONFIGS)) 102 | 103 | for mode in MODES: 104 | print(mode[2] + '\t', end='') 105 | for config in CONFIGS: 106 | print(str(round(results[mode[0]][config] / 107 | results['0'][config] * 100)) + '%\t', end='') 108 | print() 109 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-sha2/include/kremlin/internal/debug.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) INRIA and Microsoft Corporation. All rights reserved. 2 | Licensed under the Apache 2.0 License. */ 3 | 4 | #ifndef __KREMLIN_DEBUG_H 5 | #define __KREMLIN_DEBUG_H 6 | 7 | #include 8 | 9 | #include "kremlin/internal/target.h" 10 | 11 | /******************************************************************************/ 12 | /* Debugging helpers - intended only for KreMLin developers */ 13 | /******************************************************************************/ 14 | 15 | /* In support of "-wasm -d force-c": we might need this function to be 16 | * forward-declared, because the dependency on WasmSupport appears very late, 17 | * after SimplifyWasm, and sadly, after the topological order has been done. */ 18 | void WasmSupport_check_buffer_size(uint32_t s); 19 | 20 | /* A series of GCC atrocities to trace function calls (kremlin's [-d c-calls] 21 | * option). Useful when trying to debug, say, Wasm, to compare traces. */ 22 | /* clang-format off */ 23 | #ifdef __GNUC__ 24 | #define KRML_FORMAT(X) _Generic((X), \ 25 | uint8_t : "0x%08" PRIx8, \ 26 | uint16_t: "0x%08" PRIx16, \ 27 | uint32_t: "0x%08" PRIx32, \ 28 | uint64_t: "0x%08" PRIx64, \ 29 | int8_t : "0x%08" PRIx8, \ 30 | int16_t : "0x%08" PRIx16, \ 31 | int32_t : "0x%08" PRIx32, \ 32 | int64_t : "0x%08" PRIx64, \ 33 | default : "%s") 34 | 35 | #define KRML_FORMAT_ARG(X) _Generic((X), \ 36 | uint8_t : X, \ 37 | uint16_t: X, \ 38 | uint32_t: X, \ 39 | uint64_t: X, \ 40 | int8_t : X, \ 41 | int16_t : X, \ 42 | int32_t : X, \ 43 | int64_t : X, \ 44 | default : "unknown") 45 | /* clang-format on */ 46 | 47 | # define KRML_DEBUG_RETURN(X) \ 48 | ({ \ 49 | __auto_type _ret = (X); \ 50 | KRML_HOST_PRINTF("returning: "); \ 51 | KRML_HOST_PRINTF(KRML_FORMAT(_ret), KRML_FORMAT_ARG(_ret)); \ 52 | KRML_HOST_PRINTF(" \n"); \ 53 | _ret; \ 54 | }) 55 | #endif 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /tests/synthetic-benchmark/include/kremlin/internal/debug.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) INRIA and Microsoft Corporation. All rights reserved. 2 | Licensed under the Apache 2.0 License. */ 3 | 4 | #ifndef __KREMLIN_DEBUG_H 5 | #define __KREMLIN_DEBUG_H 6 | 7 | #include 8 | 9 | #include "kremlin/internal/target.h" 10 | 11 | /******************************************************************************/ 12 | /* Debugging helpers - intended only for KreMLin developers */ 13 | /******************************************************************************/ 14 | 15 | /* In support of "-wasm -d force-c": we might need this function to be 16 | * forward-declared, because the dependency on WasmSupport appears very late, 17 | * after SimplifyWasm, and sadly, after the topological order has been done. */ 18 | void WasmSupport_check_buffer_size(uint32_t s); 19 | 20 | /* A series of GCC atrocities to trace function calls (kremlin's [-d c-calls] 21 | * option). Useful when trying to debug, say, Wasm, to compare traces. */ 22 | /* clang-format off */ 23 | #ifdef __GNUC__ 24 | #define KRML_FORMAT(X) _Generic((X), \ 25 | uint8_t : "0x%08" PRIx8, \ 26 | uint16_t: "0x%08" PRIx16, \ 27 | uint32_t: "0x%08" PRIx32, \ 28 | uint64_t: "0x%08" PRIx64, \ 29 | int8_t : "0x%08" PRIx8, \ 30 | int16_t : "0x%08" PRIx16, \ 31 | int32_t : "0x%08" PRIx32, \ 32 | int64_t : "0x%08" PRIx64, \ 33 | default : "%s") 34 | 35 | #define KRML_FORMAT_ARG(X) _Generic((X), \ 36 | uint8_t : X, \ 37 | uint16_t: X, \ 38 | uint32_t: X, \ 39 | uint64_t: X, \ 40 | int8_t : X, \ 41 | int16_t : X, \ 42 | int32_t : X, \ 43 | int64_t : X, \ 44 | default : "unknown") 45 | /* clang-format on */ 46 | 47 | # define KRML_DEBUG_RETURN(X) \ 48 | ({ \ 49 | __auto_type _ret = (X); \ 50 | KRML_HOST_PRINTF("returning: "); \ 51 | KRML_HOST_PRINTF(KRML_FORMAT(_ret), KRML_FORMAT_ARG(_ret)); \ 52 | KRML_HOST_PRINTF(" \n"); \ 53 | _ret; \ 54 | }) 55 | #endif 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /tests/crypto/hacl-star-chacha20/include/kremlin/internal/debug.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) INRIA and Microsoft Corporation. All rights reserved. 2 | Licensed under the Apache 2.0 License. */ 3 | 4 | #ifndef __KREMLIN_DEBUG_H 5 | #define __KREMLIN_DEBUG_H 6 | 7 | #include 8 | 9 | #include "kremlin/internal/target.h" 10 | 11 | /******************************************************************************/ 12 | /* Debugging helpers - intended only for KreMLin developers */ 13 | /******************************************************************************/ 14 | 15 | /* In support of "-wasm -d force-c": we might need this function to be 16 | * forward-declared, because the dependency on WasmSupport appears very late, 17 | * after SimplifyWasm, and sadly, after the topological order has been done. */ 18 | void WasmSupport_check_buffer_size(uint32_t s); 19 | 20 | /* A series of GCC atrocities to trace function calls (kremlin's [-d c-calls] 21 | * option). Useful when trying to debug, say, Wasm, to compare traces. */ 22 | /* clang-format off */ 23 | #ifdef __GNUC__ 24 | #define KRML_FORMAT(X) _Generic((X), \ 25 | uint8_t : "0x%08" PRIx8, \ 26 | uint16_t: "0x%08" PRIx16, \ 27 | uint32_t: "0x%08" PRIx32, \ 28 | uint64_t: "0x%08" PRIx64, \ 29 | int8_t : "0x%08" PRIx8, \ 30 | int16_t : "0x%08" PRIx16, \ 31 | int32_t : "0x%08" PRIx32, \ 32 | int64_t : "0x%08" PRIx64, \ 33 | default : "%s") 34 | 35 | #define KRML_FORMAT_ARG(X) _Generic((X), \ 36 | uint8_t : X, \ 37 | uint16_t: X, \ 38 | uint32_t: X, \ 39 | uint64_t: X, \ 40 | int8_t : X, \ 41 | int16_t : X, \ 42 | int32_t : X, \ 43 | int64_t : X, \ 44 | default : "unknown") 45 | /* clang-format on */ 46 | 47 | # define KRML_DEBUG_RETURN(X) \ 48 | ({ \ 49 | __auto_type _ret = (X); \ 50 | KRML_HOST_PRINTF("returning: "); \ 51 | KRML_HOST_PRINTF(KRML_FORMAT(_ret), KRML_FORMAT_ARG(_ret)); \ 52 | KRML_HOST_PRINTF(" \n"); \ 53 | _ret; \ 54 | }) 55 | #endif 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/scheduling/dynamic/DynamicDataBuses.scala: -------------------------------------------------------------------------------- 1 | package riscv.plugins.scheduling.dynamic 2 | 3 | import riscv._ 4 | import spinal.core._ 5 | import spinal.lib._ 6 | 7 | case class CdbMessage(metaRegisters: DynBundle[PipelineData[Data]], robIndexBits: BitCount)(implicit 8 | config: Config 9 | ) extends Bundle { 10 | val robIndex: UInt = UInt(robIndexBits) 11 | val writeValue: UInt = UInt(config.xlen bits) 12 | val metadata: Bundle with DynBundleAccess[PipelineData[Data]] = metaRegisters.createBundle 13 | 14 | override def clone(): CdbMessage = { 15 | CdbMessage(metaRegisters, robIndexBits) 16 | } 17 | } 18 | 19 | case class RdbMessage(retirementRegisters: DynBundle[PipelineData[Data]], robIndexBits: BitCount) 20 | extends Bundle { 21 | val robIndex = UInt(robIndexBits) 22 | val registerMap: Bundle with DynBundleAccess[PipelineData[Data]] = 23 | retirementRegisters.createBundle 24 | } 25 | 26 | trait CdbListener { 27 | def onCdbMessage(cdbMessage: CdbMessage) 28 | } 29 | 30 | class CommonDataBus( 31 | reservationStations: Seq[ReservationStation], 32 | rob: ReorderBuffer, 33 | metaRegisters: DynBundle[PipelineData[Data]], 34 | loadManagerCount: Int 35 | )(implicit config: Config) 36 | extends Area { 37 | val inputs: Vec[Stream[CdbMessage]] = 38 | Vec( 39 | Stream(HardType(CdbMessage(metaRegisters, rob.indexBits))), 40 | reservationStations.size + loadManagerCount 41 | ) 42 | 43 | private val arbitratedInputs = StreamArbiterFactory.roundRobin.noLock.on(inputs) 44 | 45 | def build(): Unit = { 46 | when(arbitratedInputs.valid) { 47 | arbitratedInputs.ready := True 48 | val listeners = reservationStations :+ rob 49 | for (listener <- listeners) { 50 | listener.onCdbMessage(arbitratedInputs.payload) 51 | } 52 | } otherwise { 53 | arbitratedInputs.ready := False 54 | } 55 | } 56 | } 57 | 58 | class DispatchBus( 59 | reservationStations: Seq[ReservationStation], 60 | rob: ReorderBuffer, 61 | dispatcher: Dispatcher, 62 | retirementRegisters: DynBundle[PipelineData[Data]] 63 | ) extends Area { 64 | val inputs: Vec[Stream[RdbMessage]] = 65 | Vec(Stream(HardType(RdbMessage(retirementRegisters, rob.indexBits))), reservationStations.size) 66 | private val arbitratedInputs = StreamArbiterFactory.roundRobin.noLock.on(inputs) 67 | 68 | def build(): Unit = { 69 | when(arbitratedInputs.valid) { 70 | arbitratedInputs.ready := dispatcher.processMessage(arbitratedInputs.payload) 71 | } otherwise { 72 | arbitratedInputs.ready := False 73 | } 74 | } 75 | } 76 | 77 | class RobDataBus( 78 | rob: ReorderBuffer, 79 | retirementRegisters: DynBundle[PipelineData[Data]], 80 | loadManagerCount: Int 81 | ) extends Area { 82 | val inputs: Vec[Stream[RdbMessage]] = Vec( 83 | Stream(HardType(RdbMessage(retirementRegisters, rob.indexBits))), 84 | loadManagerCount + 1 85 | ) // +1 for dispatcher 86 | private val arbitratedInputs = StreamArbiterFactory.roundRobin.noLock.on(inputs) 87 | 88 | def build(): Unit = { 89 | when(arbitratedInputs.valid) { 90 | arbitratedInputs.ready := True 91 | rob.onRdbMessage(arbitratedInputs.payload) 92 | } otherwise { 93 | arbitratedInputs.ready := False 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 2 | 3 | # Set to noninteractive mode 4 | ARG DEBIAN_FRONTEND=noninteractive 5 | 6 | ARG BENCHMARKS 7 | RUN echo "Running benchmarks: ${BENCHMARKS}" 8 | 9 | RUN apt-get update 10 | RUN apt-get -yqq install git openjdk-17-jdk verilator curl build-essential python3-pip libz-dev 11 | 12 | # Install sbt - https://www.scala-sbt.org/ 13 | RUN echo "deb https://repo.scala-sbt.org/scalasbt/debian all main" | tee /etc/apt/sources.list.d/sbt.list 14 | RUN echo "deb https://repo.scala-sbt.org/scalasbt/debian /" | tee /etc/apt/sources.list.d/sbt_old.list 15 | RUN curl -sL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x2EE0EA64E40A89B84B2DF73499E82A75642AC823" | apt-key add 16 | RUN apt-get update 17 | RUN apt-get -yqq install sbt 18 | 19 | # install vcdvcd (for eval) 20 | WORKDIR /vcdvcd 21 | 22 | RUN git clone --depth=1 --branch v2.3.6 https://github.com/cirosantilli/vcdvcd . 23 | RUN python3 -m pip install --user /vcdvcd 24 | 25 | # install gnu toolchain 26 | WORKDIR /toolchain 27 | RUN git clone --depth=1 --branch 2023.07.07 https://github.com/riscv/riscv-gnu-toolchain . 28 | RUN apt-get -yqq install autoconf automake autotools-dev curl python3 libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev ninja-build 29 | RUN ./configure --prefix=/opt/riscv --with-arch=rv32im_zicsr --with-abi=ilp32 && \ 30 | make -j"$(nproc)" && \ 31 | make clean 32 | 33 | ENV PATH="${PATH}:/opt/riscv/bin" 34 | 35 | # Install baseline version of Proteus 36 | WORKDIR /proteus-base 37 | RUN git clone --recurse-submodules --depth=1 --branch v23.02 https://github.com/proteus-core/proteus.git . 38 | # update SpinalHDL version 39 | RUN sed -e 's/val spinalVersion = "1.7.3"/val spinalVersion = "1.9.3"/g' -i build.sbt 40 | # create simulator binary and run riscv-tests 41 | RUN make -C tests CORE=riscv.CoreDynamicExtMem RISCV_PREFIX=riscv32-unknown-elf 42 | RUN mv sim/build/sim sim/build/base 43 | # comment out waveform dumping to save disk space 44 | RUN sed -e '/tracer->dump(mainTime);/s/^/\/\//g' -i sim/main.cpp 45 | # create simulator binary and run riscv-tests 46 | RUN make -C tests CORE=riscv.CoreDynamicExtMem RISCV_PREFIX=riscv32-unknown-elf 47 | RUN mv sim/build/sim sim/build/base_nodump 48 | 49 | # Install Proteus extended with ProSpeCT 50 | WORKDIR /prospect 51 | RUN git clone --recurse-submodules --depth=1 --branch usenix_artifact https://github.com/proteus-core/prospect.git . 52 | # update SpinalHDL version 53 | RUN sed -e 's/val spinalVersion = "1.7.3"/val spinalVersion = "1.9.3"/g' -i build.sbt 54 | # create simulator binary and run riscv-tests 55 | RUN make -C tests CORE=riscv.CoreDynamicExtMem RISCV_PREFIX=riscv32-unknown-elf 56 | RUN mv sim/build/sim sim/build/prospect 57 | # comment out waveform dumping to save disk space 58 | RUN sed -e '/tracer->dump(mainTime);/s/^/\/\//g' -i sim/main.cpp 59 | # create simulator binary and run riscv-tests 60 | RUN make -C tests CORE=riscv.CoreDynamicExtMem RISCV_PREFIX=riscv32-unknown-elf 61 | RUN mv sim/build/sim sim/build/prospect_nodump 62 | 63 | WORKDIR /prospect/tests/spectre-tests 64 | RUN ./eval.py /proteus-base/sim/build/base /prospect/sim/build/prospect 65 | 66 | WORKDIR /prospect/tests/synthetic-benchmark 67 | RUN if [ "${BENCHMARKS}" = "true" ] ; then ./eval.py /proteus-base/sim/build/base_nodump /prospect/sim/build/prospect_nodump ; else echo Skipping benchmarks... ; fi 68 | 69 | CMD /bin/bash 70 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/cheri/RegisterFile.scala: -------------------------------------------------------------------------------- 1 | package riscv.plugins.cheri 2 | 3 | import riscv._ 4 | import spinal.core._ 5 | import spinal.lib._ 6 | 7 | class RegisterFile(readStage: Stage, writeStage: Stage)(implicit context: Context) 8 | extends Plugin[Pipeline] { 9 | override def setup(): Unit = { 10 | val decoder = pipeline.service[DecoderService] 11 | 12 | decoder.configure { config => 13 | config.addDefault(context.data.CD_DATA, RegCapability.Null) 14 | } 15 | 16 | val hazardInfo = DataHazardInfo( 17 | RegisterType.CAP, 18 | context.data.CS1_DATA, 19 | context.data.CS2_DATA, 20 | context.data.CD_DATA 21 | ) 22 | 23 | pipeline.service[DataHazardService].addHazard(hazardInfo) 24 | } 25 | 26 | override def build(): Unit = { 27 | case class ReadIo() extends Bundle with IMasterSlave { 28 | val cs1 = UInt(5 bits) 29 | val cs2 = UInt(5 bits) 30 | val cs1Data = RegCapability() 31 | val cs2Data = RegCapability() 32 | 33 | override def asMaster(): Unit = { 34 | in(cs1, cs2) 35 | out(cs1Data, cs2Data) 36 | } 37 | } 38 | 39 | case class WriteIo() extends Bundle with IMasterSlave { 40 | val cd = UInt(5 bits) 41 | val data = RegCapability() 42 | val write = Bool() 43 | 44 | override def asMaster(): Unit = { 45 | in(cd, data, write) 46 | } 47 | } 48 | 49 | val regFile = pipeline plug new Component { 50 | setDefinitionName("CapabilityRegisterFile") 51 | 52 | val readIo = master(ReadIo()) 53 | val writeIo = master(WriteIo()) 54 | val regs = Mem(RegCapability(), Seq.fill(config.numRegs) { RegCapability.Null }) 55 | 56 | // Add a wire for each register with a readable name. This is to easily 57 | // view register values in a wave dump. 58 | for (i <- 0 until config.numRegs) { 59 | val regWire = RegCapability() 60 | regWire.setName(s"c$i") 61 | regWire := regs.readAsync(U(i).resized, writeFirst) 62 | } 63 | 64 | def readReg(addr: UInt) = regs.readAsync(addr, writeFirst) 65 | readIo.cs1Data := readReg(readIo.cs1) 66 | readIo.cs2Data := readReg(readIo.cs2) 67 | 68 | when(writeIo.write && writeIo.cd =/= 0) { 69 | regs.write(writeIo.cd, writeIo.data) 70 | } 71 | } 72 | 73 | val readArea = readStage plug new Area { 74 | import readStage._ 75 | 76 | val regFileIo = slave(ReadIo()) 77 | 78 | regFileIo.cs1 := value(pipeline.data.RS1) 79 | regFileIo.cs2 := value(pipeline.data.RS2) 80 | output(context.data.CS1_DATA) := regFileIo.cs1Data 81 | output(context.data.CS2_DATA) := regFileIo.cs2Data 82 | } 83 | 84 | val writeArea = writeStage plug new Area { 85 | import writeStage._ 86 | 87 | val regFileIo = slave(WriteIo()) 88 | 89 | regFileIo.cd := value(pipeline.data.RD) 90 | regFileIo.data := value(context.data.CD_DATA) 91 | 92 | val trapHandler = pipeline.service[TrapService] 93 | val hasTrapped = trapHandler.hasTrapped(writeStage) 94 | regFileIo.write := 95 | (value(pipeline.data.RD_TYPE) === RegisterType.CAP) && 96 | arbitration.isDone && 97 | !hasTrapped 98 | } 99 | 100 | pipeline plug new Area { 101 | regFile.readIo <> readArea.regFileIo 102 | regFile.writeIo <> writeArea.regFileIo 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/scala/riscv/plugins/scheduling/dynamic/PcManager.scala: -------------------------------------------------------------------------------- 1 | package riscv.plugins.scheduling.dynamic 2 | 3 | import riscv._ 4 | import spinal.core._ 5 | 6 | import scala.collection.mutable 7 | 8 | class PcManager() extends Plugin[DynamicPipeline] with JumpService { 9 | private object PrivateRegisters { 10 | object JUMP_REQUESTED extends PipelineData(Bool()) 11 | } 12 | 13 | private val jumpObservers = mutable.Buffer[JumpObserver]() 14 | 15 | override def jump( 16 | stage: Stage, 17 | target: UInt, 18 | jumpType: JumpType, 19 | checkAlignment: Boolean 20 | ): Unit = { 21 | def doJump() = { 22 | stage.output(pipeline.data.NEXT_PC) := target 23 | stage.output(PrivateRegisters.JUMP_REQUESTED) := True 24 | 25 | jumpObservers.foreach(_(stage, stage.value(pipeline.data.PC), target, jumpType)) 26 | } 27 | 28 | if (!checkAlignment) { 29 | doJump() 30 | } else { 31 | when(target(1 downto 0) =/= 0) { 32 | val trapHandler = pipeline.service[TrapService] 33 | trapHandler.trap(stage, TrapCause.InstructionAddressMisaligned(target)) 34 | }.otherwise { 35 | doJump() 36 | } 37 | } 38 | } 39 | 40 | // TODO: should the following functions have a body? would it maybe make sense to inherit 41 | // from PcManager and use those? decent amount of duplication already 42 | override def addPcPayload[T <: Data](pcPayload: PcPayload[T]): Unit = ??? 43 | 44 | override def onPcUpdate(observer: PcUpdateObserver): Unit = ??? 45 | 46 | override def onJump(observer: JumpObserver): Unit = { 47 | jumpObservers += observer 48 | } 49 | 50 | override def jump(target: UInt): Unit = ??? // TODO: can we remove this? 51 | 52 | override def jumpRequested(stage: Stage): Bool = { 53 | stage.output(PrivateRegisters.JUMP_REQUESTED) 54 | } 55 | 56 | override def setFetchPc(pc: UInt): Unit = { 57 | val staticPcManager = pipeline.issuePipeline.service[JumpService] 58 | staticPcManager.setFetchPc(pc) 59 | } 60 | 61 | override def setup(): Unit = { 62 | pipeline.service[DecoderService].configure { config => 63 | config.addDefault(PrivateRegisters.JUMP_REQUESTED, False) 64 | } 65 | 66 | // Make sure the needed pipeline registers are correctly propagated. Needed because we use 67 | // them during the finish phase. 68 | pipeline.retirementStage.output(PrivateRegisters.JUMP_REQUESTED) 69 | pipeline.retirementStage.output(pipeline.data.NEXT_PC) 70 | } 71 | 72 | override def finish(): Unit = { 73 | pipeline plug new Area { 74 | val jumpStage = pipeline.retirementStage 75 | 76 | when(jumpStage.arbitration.isDone && jumpRequested(jumpStage)) { 77 | val staticPcManager = pipeline.issuePipeline.service[JumpService] 78 | staticPcManager.jump(jumpStage.output(pipeline.data.NEXT_PC)) 79 | 80 | pipeline.rob.reset() 81 | 82 | for (component <- pipeline.components) { 83 | component.pipelineReset() 84 | } 85 | } 86 | } 87 | } 88 | 89 | override def disableJump(stage: Stage): Unit = { 90 | val staticPcManager = pipeline.issuePipeline.service[JumpService] 91 | staticPcManager.disableJump(stage) 92 | stage.output(PrivateRegisters.JUMP_REQUESTED) := False 93 | } 94 | 95 | override def jumpOfBundle(bundle: Bundle with DynBundleAccess[PipelineData[Data]]): Bool = { 96 | bundle.elementAs[Bool](PrivateRegisters.JUMP_REQUESTED.asInstanceOf[PipelineData[Data]]) 97 | } 98 | 99 | override def flushPipeline(stage: Stage): Unit = { 100 | stage.input(PrivateRegisters.JUMP_REQUESTED) := True 101 | } 102 | } 103 | --------------------------------------------------------------------------------